PFCP
The system provides a python object alc.pfcp to inspect and modify the PFCP packets.
The alc.pfcp object
Attributes
The object exposes the header fields as attributes on the object.
| Attribute | Description | Access | Type | 
|---|---|---|---|
| flags | Complete flags field as an 8-bit integer | ro | int | 
| version | PFCP version | ro | int | 
| fo_flag | FO flag (follow on) marking another PFCP message follows in the same UDP frame | ro | bool | 
| mp_flag | Flag marking if there is a msg_priority field | ro | bool | 
| s_flag | Flag marking if there is a SEID field | ro | bool | 
| msg_type | Message type | ro | int | 
| msg_len | Message length | ro | int | 
| seid | Session Endpoint Identifier; None if the header field is not present | ro | int|None | 
| seq_number | Sequence number | ro | int | 
| msg_priority | Message priority; None if the header field is not present | ro | int|None | 
Methods
- alc.Pfcp.drop()
- Drops the packet. 
- alc.Pfcp.get_ie_list()
- Returns a list of IE-types that are present in the packet. - The order of the elements is the same as they appear in the packet. 
- If there are multiple instances of the same IE, the IE-type appears multiple times in the tuple. 
 - Return type
- list 
 
- alc.Pfcp.has(type, /)
- Returns if an IE of the specified type is present at the top-level. - Parameters
- type (int) – IE-type to find 
- Return type
- bool 
 
- alc.Pfcp.get(type, /)
- Returns all values of the IEs with the specified type. The values are returned as the exact bytestrings as they appear in the packet. - If the specified type does not exist, the result is an empty tuple: () 
- If a specific instance has zero length or no values, the corresponding bytestring is an empty bytestring: b”” 
 - Parameters
- type (int) – IE-type to fetch 
- Return type
- tuple of bytestrings 
 
- alc.Pfcp.set(type, value, /)
- Replaces the currently present IEs of the specific type with new ones. Multiple values can be specified in a tuple in which case one IE with the specified type is added for each item in the tuple. - Parameters
- type (int) – IE-type to set 
- value (bytes|tuple(bytes)) – value of the IE; length is computed from this value 
 
 
- alc.Pfcp.clear(type, /)
- Removes all IEs with the specified type. - Parameters
- type (int) – IE-type to clear 
 
Constants
| Name | Value | 
|---|---|
| MSG_TYPE_HEARTBEAT_REQ | 1 | 
| MSG_TYPE_HEARTBEAT_RESP | 2 | 
| MSG_TYPE_PFD_MGMT_REQ | 3 | 
| MSG_TYPE_PFD_MGMT_RESP | 4 | 
| MSG_TYPE_ASSOC_SETUP_REQ | 5 | 
| MSG_TYPE_ASSOC_SETUP_RESP | 6 | 
| MSG_TYPE_ASSOC_UPDATE_REQ | 7 | 
| MSG_TYPE_ASSOC_UPDATE_RESP | 8 | 
| MSG_TYPE_ASSOC_RELEASE_REQ | 9 | 
| MSG_TYPE_ASSOC_RELEASE_RESP | 10 | 
| MSG_TYPE_VERSION_NOT_SUP_RESP | 11 | 
| MSG_TYPE_NODE_REPORT_REQ | 12 | 
| MSG_TYPE_NODE_REPORT_RESP | 13 | 
| MSG_TYPE_SESSION_SET_DEL_REQ | 14 | 
| MSG_TYPE_SESSION_SET_DEL_RESP | 15 | 
| MSG_TYPE_SESSION_EST_REQ | 50 | 
| MSG_TYPE_SESSION_EST_RESP | 51 | 
| MSG_TYPE_SESSION_MOD_REQ | 52 | 
| MSG_TYPE_SESSION_MOD_RESP | 53 | 
| MSG_TYPE_SESSION_DEL_REQ | 54 | 
| MSG_TYPE_SESSION_DEL_RESP | 55 | 
| MSG_TYPE_SESSION_REPORT_REQ | 56 | 
| MSG_TYPE_SESSION_REPORT_RESP | 57 | 
The alc.pfcp_utils module
Decoded IE classes
The module comes with a list of pre-defined classes which represent a decoded IE. These classes known how to convert between a bytes-representation of a specific IE and a Python-object of that class that allows direct interaction with its value.
- AbstractIE
- BasicIE
- IntegerIE
- StringIE
- GroupedIE
Other decoders can be created by subclassing the AbstractIE class, providing a sensible __init__ function and overriding the following two methods:
- AbstractIE.encode()
- AbstractIE.from_bytes()
Decoding
The module provides a function to decode a bytes representation of the value of an IE.
This function can be passed in the result of a call to alc.pfcp.get() as the value for the iter_of_bytes argument.
Examples
Example 1: Adding and removing IEs
from alc import pfcp
from pfcp_utils import IntegerIE, GroupedIE, BasicIE, StringIE
# remove some IEs from the packet
pfcp.clear(17)
pfcp.clear(2)
# create new IEs and insert them
new_ies = [
    IntegerIE(109, 4, 1),
    BasicIE(25, b'\x00'),
    GroupedIE(7, [qerid_ie, corrid_ie, gatestatus_ie])
]
for ie in new_ies:
    pfcp.set(ie.type, ie.encode())
# add multiple IEs of the same type
pfcp.set(22, (StringIE(22, "ISP1").encode(), StringIE(22, "ISP2").encode()))
Example 2: Fetching and decoding IEs
from alc import pfcp
from pfcp_utils import IntegerIE, decode_ies
# fetch some IEs
# result will be a tuple of bytestrings
raw_qer_ies = pfcp.get(109)
# decode them using an IntegerIE decoder
qer_ies = decode_ies(109, raw_qer_ies, IntegerIE)
Example 3: Working with grouped IEs
from alc import pfcp
from pfcp_utils import IntegerIE, GroupedIE, BasicIE, StringIE, decode_ies
# Fetch a grouped IE and iterate its sub-IEs
create_pdrs = decode_ies(1, pfcp.get(1), GroupedIE)
for pdr in create_pdrs:
  for ie in pdr.sub_ies:
    print(ie)
# You can pass in extra info about sub-IEs that you want to be decoded automatically
# Notice that you can specify sub-IEs to be GroupedIE as well, which will cause the
# decoding to recurse even further.
sub_decoders = {2: GroupedIE, 20: IntegerIE}
create_pdrs = decode_ies(1, pfcp.get(1), GroupedIE, sub_decoders = sub_decoders)
# Find a specific sub-ie
for pdr in create_pdrs:
    for pdi_ie in pdr.sub_ies_of_type(2):
        print(ie)
# Find and modify specific sub-sub-ie:
for pdr in create_pdrs:
    for pdi_ie in pdr.sub_ies_of_type(2):
        for src_iface_ie in pdi_ie.sub_ies_of_type(20):
            src_iface = src_iface_ie.value & 0x0f
            if src_iface == 1:
                src_iface = 2
# create a groupedIE
qerid_ie      = IntegerIE(109, 4, 1)
corrid_ie     = IntegerIE(28, 4, corrid)
gatestatus_ie = BasicIE(25, b'\x00')
qer_ie        = GroupedIE(7, [qerid_ie, corrid_ie, gatestatus_ie])
# Add a sub-IE to an existing grouped IE:
for pdr in create_pdrs:
    pdr.sub_ies.append(qerid_ie)
# In order to propagate these changes into the pfcp-packet, the outer
# GroupedIE needs to be encoded again and the resulting bytes has to be
# set on the packet.
alc.pfcp.set(1, tuple(ie.encode() for ie in create_pdrs))