Python policy – Diameter API

The alc.diameter Python module provides an API for Diameter message manipulation.

Terminology used in the API description:

Table: Diameter message header alc.diameter attributes displays attributes available in alc.diameter module providing access to the Diameter message header:

Table: Diameter message header alc.diameter attributes
Attribute Description Type Access

application_id

Diameter message header field

string

Read/Write

code

Diameter message header field

string

Read/Write

end_to_end_id

Diameter message header field

string

Read/Write

flags

Diameter message header field

string

Read/Write

hop_by_hop_id

Diameter message header field

string

Read/Write

msg_length

Diameter message header field. The value is the message length of the original diameter message.

string

Read

version

Diameter message header field

string

Read/Write

Table: Message and AVP manipulation functionality alc.diameter methods displays methods available in alc.diameter module providing message and AVP manipulation functionality:

Table: Message and AVP manipulation functionality alc.diameter methods
Method Description

clear_avps(AVP code, vendor id)

AVP code, vendor id = top-level-AVP

Remove all instances of the specified AVP from the message. Applies to top-level-AVP’s only. If the specified AVP is not present, no python error is generated. Vendor ID value zero matches top-level-AVP’s without vendor ID field.

Return value: None

For example:

diameter.clear_avps(256, 12645)

drop()

Drop the Diameter message. Packet is consumed at TCP level (ack send). A drop triggers retransmits on Diameter level.

Return value: None

For example:

diameter.drop()

get_avps(AVP code, vendor id)

AVP code, vendor id = top-level-AVP

Returns a list of AVP-value-tuples. Each AVP-value-tuple represents an instance of the specified AVP in the message. Applies to top-level-AVP’s only. The position in the list corresponds with the position of the AVP instance in the message at that stage in the script. When executed before any clear or set AVP method, the list order corresponds with the AVP order in the received message. If the specified AVP is a grouped AVP, then the data contains all the embedded-AVP’s. An empty list is returned if the specified AVP is not present. Vendor ID value zero matches top-level-AVP’s without vendor ID field.

For example:

diameter.get_avps(263, 0)

[('@', 'bng.nokia.com;1398156449;28')]

get_avps_list()

Returns a list of AVP-tuples. Each AVP-tuple represents an instance of an AVP in the message. Applies to top-level-AVP’s only. The position in the list corresponds with the position of the AVP in the message at that stage in the script. When executed before any clear or set AVP method, the list order corresponds with the AVP order in the received message. When multiple instances of an AVP are present in the message, then there are multiple instances in the list. The vendor ID has value zero when not present. Grouped AVPs cannot be distinguished from other AVPs in the list.

For example:

diameter.get_avps_list()

[(263, 0, '@'), (264, 0, '@'), (296, 0, '@'), (258, 0, '@'), (416, 0, '@'), (415, 0, '@'), (268, 0, '@'), (55, 0, '@'), (456, 0, '@'), (456, 0, '@'), (456, 0, '@'), (293, 0, '@'), (256, 12645, '\x80')]

get_grouped_avps(AVP code, vendor id, grouped-AVP-decode-tuple)

AVP code, vendor id = top-level-AVP

Returns a list of grouped-AVP-value-tuples with each grouped-AVP-dictionary entry representing an embedded AVP. Each grouped-AVP-value-tuple represents an instance of the specified AVP in the message. Applies to top-level-AVPs of type grouped only. The position in the list corresponds with the position of the grouped AVP instance in the message at that stage in the script. When executed before any clear or set AVP method, the list order corresponds with the AVP order in the received message.

If the grouped-AVP-decode-tuple is empty, only the specified top-level-AVP is expanded in a grouped-AVP-value-tuple, with each grouped-AVP-dictionary entry representing an embedded AVP and all dictionary values of type ‟list of AVP-value-tuples”

To expand nested AVPs (grouped AVPs embedded in a grouped AVP), the grouped top-level-AVP and grouped embedded-AVP to expand must be added to the grouped-AVP-decode-tuple. All grouped AVPs in the grouped-AVP-decode-tuple are expanded in a list of grouped-AVP-value-tuples provided that their embedding AVP is also in the list.

The position of the embedded AVPs in the grouped-AVP-dictionary does not correspond with the position in the grouped AVP.

If the specified top-level-AVP is not a grouped AVP, then a Python error is generated: ‟ValueError: malformed diameter message”.

For example:

To expand the Multiple Services Credit Control (456) grouped top level AVP:

diameter.get_grouped_avps(456,0,())

[('@', {(432, 0): [('@', '\x00\x00\x00\x01')], (431, 0): [('@', '\x00\x00\x01\xa4@\x00\x00\x0c\x00\x00\x00d')], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]}), ('@', {(432, 0): [('@', '\x00\x00\x00\x02')], (431, 0): [('@', '\x00\x00\x01\xa4@\x00\x00\x0c\x00\x00\x03\x84')], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]}), ('@', {(432, 0): [('@', '\x00\x00\x00\x03')], (431, 0): [('@', '\x00\x00\x01\xa4@\x00\x00\x0c\x00\x00\x00<')], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]})]

To expand the nested Granted-Service-Unit AVP (code 431) in the grouped Multiple Services Credit Control top level AVP (code 456):

diameter.get_grouped_avps(456,0,((456,0),(431,0)))

[('@', {(432, 0): [('@', '\x00\x00\x00\x01')], (431, 0): [('@', {(420, 0): [('@', '\x00\x00\x00d')]})], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]}), ('@', {(432, 0): [('@', '\x00\x00\x00\x02')], (431, 0): [('@', {(420, 0): [('@', '\x00\x00\x03\x84')]})], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]}), ('@', {(432, 0): [('@', '\x00\x00\x00\x03')], (431, 0): [('@', {(420, 0): [('@', '\x00\x00\x00<')]})], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]})]

set_avps(AVP code, vendor id, list of AVP-value-tuples)

AVP code, vendor id = top-level-AVP

Remove all instances of the specified top-level-AVP from the message. For each entry in the AVP-value-tuple list, a top-level-AVP instance is inserted.

If the specified vendor ID value is zero, then no vendor ID field is inserted and setting the Vendor-Specific bit in the flags field of the AVP value tuple results in a Python error: ‟ValueError: no vendor ID but vendor flag set”.

If the specified vendor ID value is non-zero, then a vendor ID field is inserted and not setting the Vendor-Specific bit in the flags field of the AVP value tuple results in a Python error: ‟ValueError: vendor ID but vendor flag not set”.

Padding between AVPs, AVP length and Diameter message length are adapted accordingly by the system.

Return value is None.

For example:

diameter.set_avps(461,0,[('\x40', 'Pytho.n-1'), ('\x40', 'Python-2')])

set_fixed_position_avps(AVP-order-tuple)

Put the specified top-level-AVPs at the beginning of the message in the order as specified in the AVP-order-tuple.

This method overrides the order of the top-level-AVPs in the resulting Diameter message. If for example the session-id AVP must appear as first in the message, then the corresponding AVP-key-tuple must be included in the first position of the AVP-order-tuple.

AVPs not present in the message but specified in the AVP-order-tuple are ignored.

AVPs present in the message and not specified in the AVP-order-tuple are included in the final message after the AVPs listed in the AVP-order-tuple. The order is deterministic but implementation specific.

This method can appear at any point in the script. The last call overrides the previous one.

From a black box viewpoint, this method is executed at the end of the script: the result of the call is not reflected in the list returned by a subsequent get_avp_list() call.

Return value: None

For example:

diameter.set_fixed_position_avps(((263,0), (264,0), (296,0), (268,0)

set_grouped_avps(AVP code, vendor id, list of grouped-AVP-value-tuples)

AVP code, vendor id = top-level-AVP

Remove all instances of the specified grouped top-level-AVP from the message. For each entry in the grouped-AVP-value-tuples list, a grouped top-level-AVP instance is inserted.

The order of the embedded-AVPs in the grouped AVP cannot be specified. If the specified vendor ID value is zero, then no vendor ID field is inserted and setting the Vendor-Specific bit in the flags field of the AVP value tuple will then result in a Python error: ‟ValueError: no vendor ID but vendor flag set”.

If the specified vendor ID value is non-zero, then a vendor ID field is inserted and not setting the Vendor-Specific bit in the flags field of the AVP value tuple will result in a Python error: ‟ValueError: vendor ID but vendor flag not set”.

Padding between AVPs, AVP length and Diameter message length are adapted accordingly.

Return value is None.

For example:

diameter.set_grouped_avps(456,0,[('@', {(432, 0): [('@', '\x00\x00\x00\x01')], (431, 0): [('@', {(420, 0): [('@', '\x00\x00\x00\x2b')]})], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]}), ('@', {(432, 0): [('@', '\x00\x00\x00\x03')], (431, 0): [('@', {(420, 0): [('@', '\x00\x00\x00\x53')]})], (448, 0): [('@', '\x00\x00\x04\xb0')], (268, 0): [('@', '\x00\x00\x07\xd1')]})])

To enable Diameter message manipulation using Python, a Python policy must be configured in the diameter-peer-policy. For example:

The Python policy specifies the Python script to use for each Diameter message type received or transmitted on a Diameter peer. In the ingress direction, the Python script is executed when the corresponding packet type is received on the Diameter peer but before further processing in the system. In the egress direction, the Python script is executed prior to sending the corresponding packet type on the Diameter peer. For example:

The Python script specifies the location of the script and optional protection mechanism. For example:

configure
    python
        python-script "diameter-1" create
            primary-url "ftp://usr:pwd@192.0.2.1/./py/diam-1.py"
            no shutdown
        exit
    exit

As an example, the diam-1.py script, clears the M-bit from the Event-Timestamp AVP (code 55):

    from alc import diameter
    avp55=diameter.get_avps(55,0)
    diameter.set_avps(55,0,[('\x00',avp55[0][1])])