PFCP

The system provides a python object alc.pfcp, an instance of class alc.Pfcp, to inspect and modify the PFCP packets.

Note

For PFCP message, only the pre-provided alc.pfcp object should be used in script, the class alc.Pfcp should not be used directly.

The alc.Pfcp class

Instance Attributes

The PFCP header fields are exposed as instance attributes on the object.

Attributes of alc.pfcp

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

drop()

Drops the packet.

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

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

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

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

clear(type, /)

Removes all IEs with the specified type.

Parameters

type (int) – IE-type to clear

Constants

The alc.pfcp object provides a list of following constants.

Message type constants defined on alc.pfcp

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))