
In the previous iteration, OpenSIPS 3.2 introduced a first version of the support for Diameter protocol peering by leveraging the freeDiameter project and its excellent C libraries. Building on top of this, OpenSIPS 3.3 now offers a way of building and sending arbitrary Diameter protocol requests, from the opensips.cfg script.
This brief post will teach you everything about the new client-side Diameter support.
Configuration
Say we want to send User-Data-Request (306) Diameter messages, as part of the “3GPP Sh Application” (16777217). Before actually working on the opensips.cfg logic, we must configure the freeDiameter client library with any custom application IDs, message IDs and AVP templates.
To achieve this, we have extended the syntax of the dictionary.opensips RADIUS/Diameter configuration file. Here is how we would configure all of the above:
ATTRIBUTE DRMP 301 integer ... ATTRIBUTE Wildcarded-Public-Identity 634 string ATTRIBUTE DSAI-Tag 711 string ... ATTRIBUTE UDR-Flags 719 unsigned32 ... ATTRIBUTE Supported-Features 628 grouped { Vendor-Id | REQUIRED | 1 Feature-List-ID | REQUIRED | 1 Feature-List | REQUIRED | 1 } APPLICATION 16777217 3GPP Sh Application REQUEST 306 User-Data-Request { Session-Id | FIXED_HEAD | 1 Origin-Host | REQUIRED | 1 Origin-Realm | REQUIRED | 1 DRMP | OPTIONAL | 1 Wildcarded-Public-Identity | OPTIONAL | 1 Data-Reference | REQUIRED | 1 Supported-Features | OPTIONAL | 1 ... } ANSWER 306 User-Data-Answer { Session-Id | FIXED_HEAD | 1 DRMP | OPTIONAL | 1 Result-Code | OPTIONAL | 1 Origin-Host | REQUIRED | 1 Origin-Realm | REQUIRED | 1 .... }
Notice the sections of this file:
- any freeDiameter-unknown AVPs must be explicitly defined
- any freeDiameter-unknown Applications must be explicitly defined
- any freeDiameter-unknown Requests and their Answers must be explicitly defined
Regarding the Request/Answer format, notice how an AVP may be of three types: FIXED_HEAD (it must be the top-most AVP), REQUIRED or OPTIONAL. The final integer suggests the “max occurrences” allowed for that AVP, in that respective message type.
Sending a Request
Once you’ve “trained” freeDiameter to properly recognize your intended Diameter AVP and request formats, it’s time to move over to the opensips.cfg file and script the request sending part. Here is an example request taken from the docs:
# Building an sending a My-Custom-Request (92001) for the # My Diameter Application (42) $var(payload) = "[ { \"Origin-Host\": \"client.diameter.test\" }, { \"Origin-Realm\": \"diameter.test\" }, { \"Destination-Realm\": \"diameter.test\" }, { \"Sip-From-Tag\": \"" + $ft + "\" }, { \"Sip-To-Tag\": \"" + $tt + "\" }, { \"Acct-Session-Id\": \"a59c-dff0d9efd167\" }, { \"Sip-Call-Duration\": " + $var(call_dur) + " }, { \"Sip-Call-Setuptime\": " + $var(setuptime) + " }, { \"Sip-Call-Created\": 1652372541 }, { \"Sip-Call-MSDuration\": " + $avp(ms_duration) + " }, { \"out_gw\": \"GW-774\" }, { \"Cost-Information\": [ {\"Unit-Value\": [{\"Value-Digits\": 1000}]}, {\"Currency-Code\": 35} ]} ]"; $var(rc) = dm_send_request(42, 92001, $var(payload), $var(rpl_avps)); xlog("rc: $var(rc), AVPs: $var(rpl_avps)\n");
Since the AVPs are well-known, we only have to specify their string name and the library will take care of looking them up and plugging in the appropriate code in the Diameter packet. The complete list of AVP codes and their values will effectively form the entire payload of the Diameter message: easy stuff! To avoid introducing too much complexity, we decided to require you to pass this information as a JSON Array string – the module will take care of interpreting the content, as long as it’s properly formatted.
Once we have the payload, we just send it out to the configured peer of the aaa_diameter module, using the dm_send_request() function.
PS: regarding pre-configuration, do make sure to check out the freediameter-extensions package, as it contains a lot of pre-defined Diameter applications, AVPs, requests and answers, possibly even the 3GPP ones discussed above.
Processing an Answer
Diameter replies will often contain several important pieces of data (AVPs), so OpenSIPS provides all AVPs of the Diameter Answer as a JSON Array (similar to the request JSON!), stored in an output variable (in our case: the $var(rpl_avps) variable). Once we have it, we use the json module in order to parse and iterate it:
$json(avps) := $var(rpl_avps); for ($var(avp) in $(json(avps)[*])) { xlog("we have reply AVP: $var(avp)\n"); ... }
Further Improvements
There are several features from which the aaa_diameter module could further benefit. Support for dynamic peering (would having a short-lived Diameter exchange with an arbitrary peer be useful?), grouped AVPs, customizable AVP vendor IDs to name a few which I see as being useful.
But what is your favourite part of the Diameter support? Can you build your desired Diameter components and message exchanges with the current set of features? And, most importantly, will you be at OpenSIPS Summit 2022 in Athens to talk more about it?
Hi Liviuchircu,
Thank you for helping me last time.
Now am facing another issue. If i follow the same procedure as mentioned above and when sending Diameter message, then there is no Vendor-Id and vendor bit is set for few AVP’s. So after searching i found out that and Extention File need to be configured in freeDiameter.config file. After adding am getting error -22 while bringing up the opensips binary.
805:48:28 DBG Generating fresh Diffie-Hellman parameters of size 1024 (this takes some time)…
05:48:28 DBG Loading PS : /usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx
05:48:28 DBG Loading #####PS : /usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx
05:48:28 FATAL! PS Loading of extension /usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx failed: /usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx: undefined symbol: fd_g_config
05:48:28 ERROR ERROR: in ‘((fd_ext_load()))’ : Invalid argument
Nov 11 05:48:28 [5396] ERROR:aaa_diameter:freeDiameter_init: error in ((fd_core_parseconf(dm_conf_filename))): -22
Nov 11 05:48:28 [5396] ERROR:aaa_diameter:diameter_peer_loop: failed to init freeDiameter library
Can you please help me to overcome this error.
Thank you so much
Pavan
LikeLike
Make sure you are using freeDiameter v1.2.1 packages, as well as version 1.2.1 for the source code. If the issues persist, please post the issue to users@lists.opensips.org mailing list (you can google it), so we can discuss it in-depth.
LikeLike
Hi Liviuchircu,
Can you please post a sample example of encoding JSON array string with variables. It will be really helpful.
Thank you and have a nice day.
Pavan
LikeLike
Sure thing, pspavan56! In opensips.cfg, when assigning strings to variables, you cannot use string interpolation, unfortunately. So you will have to do something like: a = string1 + variable1 + string2 + variable2 + string3. I will update the example so it includes a few variables too. Thank you for the suggestion!
LikeLike
Thank You so much Liviuchircu. Looking forward the example.
Regards,
Pavan
LikeLike
Hi,
Just took the latest Opensips-3.4-Dev source and same issue observed.
root@ec-192-168-107-18-Ubuntu-18-04-dc:/home/ecadmin/opensips# opensips -V
version: opensips 3.4.0-dev (x86_64/linux)
flags: STATS: On, DISABLE_NAGLE, USE_MCAST, SHM_MMAP, PKG_MALLOC, Q_MALLOC, F_MALLOC, HP_MALLOC, DBG_MALLOC, CC_O0, FAST_LOCK-ADAPTIVE_WAIT
ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144, MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 65535
poll method support: poll, epoll, sigio_rt, select.
git revision: 6e735356e
main.c compiled on 04:03:59 Jul 11 2022 with gcc 7
Required Diameter libs are properly initialized,
04:07:40 NOTI libfdproto ‘1.5.0-1562+(6219359a36a9+)’ initialized.
04:07:40 NOTI libfdcore ‘1.5.0-1562+(6219359a36a9+)’ initialized.
At the start of Opensips CCR and CCA diameter messages are properly exchanged between Opensips and HSS.
Below is the error am getting,
Jul 11 04:08:57 [17650] rc: [
{ “Origin-Host”: “client.diameter.test” },
{ “Origin-Realm”: “diameter.test” },
{ “Destination-Realm”: “hss.ims.mnc001.mcc001.3gppnetwork.org” },
{ “Sip-From-Tag”: “dc93-4fba-91db” },
{ “Sip-To-Tag”: “ae12-47d6-816a” },
{ “Acct-Session-Id”: “a59c-dff0d9efd167” },
{ “Sip-Call-Duration”: 6 },
{ “Sip-Call-Setuptime”: 1 },
{ “Sip-Call-Created”: 1652372541 },
{ “Sip-Call-MSDuration”: 5850 }
]
Jul 11 04:08:57 [17650] ERROR:aaa_diameter:dm_send_request: unrecognized Request command code: 92001
Jul 11 04:08:57 [17650] ERROR:aaa_diameter:dm_send_request: to fix this, you can define the Request/Answer format in the ‘extra-avps-file’ config file
Jul 11 04:08:57 [17650] rc: -1, AVPs:
Please Suggest.
Thank You,
Pavan
LikeLike
Hi, did you set the “extra-avps-file” modparam value? Follow this example:
modparam(“acc”, “aaa_url”, “diameter:freeDiameter-client.conf;
extra-avps-file: /var/tmp/acc-avps.conf”)
LikeLike
Hi Liviuchircu,
Thank you so much for the response.
Before i didn’t add ‘extra-avps-file’ modparam values. I have updated accordingly,
loadmodule “acc.so”
modparam(“acc”, “aaa_url”, “diameter:freeDiameter.conf;
extra-avps-file: /var/tmp/dictionary.opensips”)
But still am facing the problem. Below is the error message from logs,
Jul 12 13:53:40 [28977] DBG:core:init_mod: initializing module aaa_diameter
Jul 12 13:53:40 [28977] DBG:aaa_diameter:mod_init: initializing module…
Jul 12 13:53:40 [28977] INFO:aaa_diameter:dm_init_minimal: initializing the Diameter object dictionary…
Jul 12 13:53:40 [28977] DBG:core:init_mod: register MI for aaa_diameter
Jul 12 13:53:40 [28977] DBG:core:init_mod: initializing module acc
Jul 12 13:53:40 [28977] INFO:acc:mod_init: initializing…
Jul 12 13:53:40 [28977] DBG:core:find_mod_cmd_export_t: found in module tm [/usr/local/lib64/opensips/modules/]
Jul 12 13:53:40 [28977] DBG:core:find_mod_export: found in module aaa_diameter [/usr/local/lib64/opensips/modules/]
Jul 12 13:53:40 [28977] DBG:core:aaa_prot_bind: using aaa bind api for aaa_diameter
Jul 12 13:53:40 [28977] DBG:aaa_diameter:parse_config_string: freeDiameter cfg file: ‘freeDiameter.conf’
Jul 12 13:53:40 [28977] DBG:aaa_diameter:parse_config_string: freeDiameter extra-avps-file: ‘/var/tmp/dictionary.opensips’
Jul 12 13:53:40 [28977] DBG:aaa_diameter:parse_attr_def: registered custom AVP (Sip-Method, code 204, type integer32, sub-avps: 0)
13:53:40 ERROR error in ((fd_dict_new(fd_g_config->cnf_dict, (DICT_AVP), (&data), (parent), (pref)))): -17
Jul 12 13:53:40 [28977] ERROR:aaa_diameter:dm_init_prot: failed to load the ‘extra-avps-file’
Jul 12 13:53:40 [28977] ERROR:acc:init_acc_aaa: AAA protocol initialization failure
Jul 12 13:53:40 [28977] ERROR:acc:mod_init: failed to init radius
Jul 12 13:53:40 [28977] ERROR:core:init_mod: failed to initialize module acc
Jul 12 13:53:40 [28977] ERROR:core:main: error while initializing modules
Jul 12 13:53:40 [28977] INFO:core:cleanup: cleanup
Please suggest what to do next. It will be really great helpful.
Thank You,
Pavan
LikeLike
Can you post your dictionary.opensips content? Error -17 means: “EEXIST”, so the freeDiameter library is most likely complaining that you are trying to re-define a well-known AVP (which is already present in its internal lookup tables) 😉
LikeLike
Hi Liviuchiru,
I have tried sending diameter message as said above but am getting error as,
Jul 8 07:56:17 [27884] ERROR:aaa_diameter:dm_send_request: to fix this, you can define the Request/Answer format in the ‘extra-avps-file’ config file
Jul 8 07:56:17 [27884] rc: -1, AVPs:
I followed the same procedure as said in this post.
Can you please suggest how to processed.
I am using Opensips-3.3 Version and Freediameter- 1.5 Version
Thank You,
Pavan
LikeLike
Hello! Both the blog post and the aaa_diameter module docs have been updated to include examples of the recently finalized **Grouped AVP support**! And since it’s a critical feature, the Grouped AVP support has been backported to the 3.3 branch as well.
Enjoy!
LikeLike