Using the Diameter Client Capability of OpenSIPS 3.3

Network Points Technology - Free image on Pixabay

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\": \"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 },
	{ \"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?

One thought on “Using the Diameter Client Capability of OpenSIPS 3.3

  1. 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!

    Like

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s