Home

Awesome

go-pfcp

A comprehensive PFCP implementation in the Go programming language.

CI status GoDoc License

What is PFCP?

PFCP (Packet Forwarding Control Protocol) is a signaling protocol used in mobile core network, such as EPC and 5GC, to implement the CUPS architecture (Control and User Plane Separation, not a printing system). The architecture and the protocol detail is defined in 3GPP TS 29.244.

Are you also searching for a GTP implementation in Go? If so, go-gtp is the perfect choice for you! :p

Project Status

This project is EXPERIMENTAL.
Implementation of most of the messages and IEs defined in TS 29.244 V16.7.0 (2021-04) has been done, but the exported APIs may still be updated in the future (we add a new tag in that case).

This library does not include the networking functionalities such as association setup, message delivery, and session management. We noticed that there are many ways to implement those functionalities depending on the use cases, so we decided to leave them to the users. louisroyer/go-pfcp-networking is a good example of how to implement those functionalities.

Getting Started

Installation

go-pfcp supports Go Modules. Run go mod tidy in your project's directory to collect the required packages automatically. See Features for how to handle messages and IEs, and what is supported.

Running examples

Exchanging Heartbeat

Small heartbeat client and server examples are available under examples/heartheat. The client sends a Heartbeat Request, and the server responds to it with a Heartbeat Response.

<details> <summary>Click here to see details</summary>
  1. Run the server

By default, the server listens on loopback. The address/port can be specified explicitly by the -s flag.

go-pfcp/examples/heartbeat/hb-server$ go run main.go
2019/12/22 20:03:31 waiting for messages to come on: 127.0.0.2:8805
  1. Run the client

By default, the client sends a Heartbeat to loopback. The address/port can be specified explicitly by the -s flag. It exits after printing the timestamp in the received Heartbeat Response.

The output should look like below on the client side:

go-pfcp/examples/heartbeat/hb-client$ go run main.go
2019/12/22 20:03:36 sent Heartbeat Request to: 127.0.0.2:8805
2019/12/22 20:03:36 got Heartbeat Response with TS: 2019-12-22 20:03:36 +0900 JST, from: 127.0.0.2:8805
go-pfcp/examples/heartbeat/hb-client$
go-pfcp/examples/heartbeat/hb-client$ go run main.go
2019/12/22 20:03:40 sent Heartbeat Request to: 127.0.0.2:8805
2019/12/22 20:03:40 got Heartbeat Response with TS: 2019-12-22 20:03:40 +0900 JST, from: 127.0.0.2:8805

On the server side, the output should look like below:

go-pfcp/examples/heartbeat/hb-server$ go run main.go
2019/12/22 20:03:31 waiting for messages to come on: 127.0.0.2:8805
2019/12/22 20:03:36 got Heartbeat Request with TS: 2019-12-22 20:03:36 +0900 JST, from: 127.0.0.1:47305
2019/12/22 20:03:36 sent Heartbeat Response to: 127.0.0.1:47305
2019/12/22 20:03:36 waiting for messages to come on: 127.0.0.2:8805
2019/12/22 20:03:40 got Heartbeat Request with TS: 2019-12-22 20:03:40 +0900 JST, from: 127.0.0.1:55395
2019/12/22 20:03:40 sent Heartbeat Response to: 127.0.0.1:55395
2019/12/22 20:03:40 waiting for messages to come on: 127.0.0.2:8805
^Csignal: interrupt

The server continues to listen on the same port until it is terminated (by Ctrl-C or something).

</details>

Features

Messages

All the messages implements the same interface: message.Message, and have their own structs named <MessageName>.

Creating a message and encoding it

To create a message and encode it into binary, use New<MessageName>() function, which returns a *<MessageName> struct. The parameters for each constructor varies depending on the message type, but in general the first parameter is the sequence number, the second parameter is a SEID the message is session-related one, and the rest are the IEs contained in the message. See the godoc for the details.

Handling of IEs is described in the Information Elements section.

assocSetupReq := message.NewAssociationSetupRequest(
	sequenceNumber,
	ie.NewNodeID("", "", "go-pfcp.epc.3gppnetwork.org"),
	ie.NewRecoveryTimeStamp(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)),
	ie.NewUPFunctionFeatures(0x01, 0x02),
	ie.NewCPFunctionFeatures(0x3f),
	ie.NewAlternativeSMFIPAddress(net.ParseIP("127.0.0.1"), net.ParseIP("2001::1")),
	ie.NewSMFSetID("go-pfcp.epc.3gppnetwork.org"),
	ie.NewPFCPSessionRetentionInformation(
		ie.NewCPPFCPEntityIPAddress(net.ParseIP("127.0.0.1"), nil),
	),
	ie.NewUEIPAddressPoolInformation(
		ie.NewUEIPAddressPoolIdentity("go-pfcp"),
		ie.NewNetworkInstance("some.instance.example"),
	),
	ie.NewGTPUPathQoSControlInformation(
		ie.NewRemoteGTPUPeer(0x0e, "127.0.0.1", "", ie.DstInterfaceAccess, "some.instance.example"),
		ie.NewGTPUPathInterfaceType(1, 1),
		ie.NewQoSReportTrigger(1, 1, 1),
		ie.NewTransportLevelMarking(0x1111),
		ie.NewMeasurementMethod(1, 1, 1),
		ie.NewAveragePacketDelay(10*time.Second),
		ie.NewMinimumPacketDelay(10*time.Second),
		ie.NewMaximumPacketDelay(10*time.Second),
		ie.NewTimer(20*time.Hour),
	),
	ie.NewClockDriftControlInformation(
		ie.NewRequestedClockDriftInformation(1, 1),
		ie.NewTSNTimeDomainNumber(255),
		ie.NewTimeOffsetThreshold(10*time.Second),
		ie.NewCumulativeRateRatioThreshold(0xffffffff),
	),
	ie.NewNFInstanceID([]byte{0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33, 0x33, 0x44, 0x44, 0x44, 0x44}),
)

This will create a *AssociationSetupRequest struct with the given sequence number and IEs. The fields of the struct vary depending on the message type, but in general it has a common *Header at the top, and the list of IEs that have no explicit field at the bottom. This means that you can add any type of IEs to any type of messages, even if it is not supported in this library.

type AssociationSetupRequest struct {
	*Header
	NodeID                          *ie.IE
	RecoveryTimeStamp               *ie.IE
	UPFunctionFeatures              *ie.IE
	CPFunctionFeatures              *ie.IE
	UserPlaneIPResourceInformation  []*ie.IE
	AlternativeSMFIPAddress         []*ie.IE
	SMFSetID                        *ie.IE
	PFCPSessionRetentionInformation *ie.IE
	UEIPAddressPoolInformation      []*ie.IE
	GTPUPathQoSControlInformation   []*ie.IE
	ClockDriftControlInformation    []*ie.IE
	UPFInstanceID                   *ie.IE
	PFCPASReqFlags                  *ie.IE
	IEs                             []*ie.IE
}

All the <MessageName> struct, or the message.Message interface, has the Marshal() method which returns the binary in []byte. This can be used to send the message to the peer on top of any transport protocol (typically UDP) using the Go's standard net library.

// serialize the message
b, err := assocSetupReq.Marshal()
if err != nil {
	// handle error
}

// send `b` to "127.0.0.1:8805"
raddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8805")
if err != nil {
	// handle error
}

conn, err := net.DialUDP("udp", nil, raddr)
if err != nil {
	// handle error
}

if _, err := conn.Write(b); err != nil {
	// handle error
}

log.Printf("sent %s to %s", assocSetupReq.MessageTypeName(), raddr)

Is the message type you want to create not supported in this library? No problem. You can still create a message of any type by using NewGeneric() function. This function takes the message type as the first parameter, and the rest are the same as the New<MessageName>() function.

// create a message of type 0x64
yourMessage := message.NewGeneric(
	0x64,
	sequenceNumber,
	seid,
	ie.NewNodeID("", "", "go-pfcp.epc.3gppnetwork.org"),
	ie.NewRecoveryTimeStamp(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)),
	// ...
)

The created yourMessage is of type *message.Generic, which is a struct that implements the message.Message interface and has the common *Header and the list of IEs. You can still call the Marshal() method on this struct to get the binary.

Decoding a received message

To decode a received message, use message.Parse() function. This returns a message in the message.Message interface and an error.

// receive a message on a UDP connection
b := make([]byte, 1500)
n, raddr, err := conn.ReadFromUDP(b)
if err != nil {
	// handle error
}

// decode the message
// NOTE: when you do this in another goroutine, copy the `b` to another slice
// as the `b` will be overwritten by the next `ReadFromUDP()` call.
msg, err := message.Parse(b[:n])
if err != nil {
	// handle error
}

log.Printf("got %s from %s", msg.MessageTypeName(), raddr)

To access the fields of the message, you need to assert the type of the message to the corresponding struct. For example, to access IEs in the AssociationSetupResponse message, you need to assert the type of the message to *AssociationSetupResponse first.

// assert the type of the message
assocSetupRes, ok := msg.(*message.AssociationSetupResponse)
if !ok {
	// handle error
}

// get the value of NodeID IE
// see the Information Elements section for what `NodeID()` method does
nodeID, err := assocSetupRes.NodeID.NodeID()
if err != nil {
	// handle error
}

If the message type is not supported in this library, it can still be asserted to *Generic whose header and IEs are accessible through the Header and IEs fields.

// assert the type of the message
unknownMsg, ok := msg.(*message.Generic)
if !ok {
	// handle error
}

// iterate over the IEs to get the value of NodeID IE
for _, i := range unknownMsg.IEs {
	switch i.Type {
	case ie.NodeID:
		nodeID, err := i.NodeID()
		if err != nil {
			// handle error
		}
	case ie.SomeOtherIE:
		// ...
	}
}

So, what you will be likely to do is to check the type of the message and handle it accordingly using the switch statement.

switch m := msg.(type) {
case *message.AssociationSetupRequest:
	// handle AssociationSetupRequest
case *message.AssociationSetupResponse:
	// handle AssociationSetupResponse
case *message.SomeOtherMessage:
	// ...
}

// alternatively, you can use the `MessageType()` method
switch msg.MessageType() {
case message.MsgTypeAssociationSetupRequest:
	// handle AssociationSetupRequest
case message.MsgTypeAssociationSetupResponse:
	// handle AssociationSetupResponse
case message.MsgTypeSomeOtherMessage:
	// ...
}

// using a map containing the handlers for each message type may also be a good idea
// NOTE: use with care, as there may be a race condition when accessing the map
handlers := map[uint8]func(message.Message) error{
	message.MsgTypeAssociationSetupRequest: func(m message.Message) error {
		assocSetupReq := m.(*message.AssociationSetupRequest)
		// handle AssociationSetupRequest
	},
	message.MsgTypeAssociationSetupResponse: func(m message.Message) error {
		assocSetupRes := m.(*message.AssociationSetupResponse)
		// handle AssociationSetupResponse
	},
	// ...
}

handle, ok := handlers[msg.MessageType()]
if !ok {
	// handle unsupported message type
} else {
	if err := handle(msg); err != nil {
		// handle error
	}
}

List of supported messages

Messages are implemented in conformance with TS 29.244 V16.7.0 (2021-04). The word "supported" in the table below means that the struct and the constructor for the message are implemented in this library. As described in the previous section, you can still create a message of any type eve if it is not supported or missing in the table.

PFCP Node related messages
Message TypeMessageSxaSxbSxcN4Supported?
1Heartbeat RequestXXXXYes
2Heartbeat ResponseXXXXYes
3PFD Management Request-XXXYes
4PFD Management Response-XXXYes
5Association Setup RequestXXXXYes
6Association Setup ResponseXXXXYes
7Association Update RequestXXXXYes
8Association Update ResponseXXXXYes
9Association Release RequestXXXXYes
10Association Release ResponseXXXXYes
11Version Not Supported ResponseXXXXYes
12Node Report RequestXXXXYes
13Node Report ResponseXXXXYes
14Session Set Deletion RequestXX-Yes
15Session Set Deletion ResponseXX-Yes
16 to 49(For future use)-
PFCP Session related messages
Message TypeMessageSxaSxbSxcN4Supported?
50Session Establishment RequestXXXXYes
51Session Establishment ResponseXXXXYes
52Session Modification RequestXXXXYes
53Session Modification ResponseXXXXYes
54Session Deletion RequestXXXXYes
55Session Deletion ResponseXXXXYes
56Session Report RequestXXXXYes
57Session Report ResponseXXXXYes
58 to 99(For future use)-

Information Elements

All the IEs are of the same type: ie.IE.

Creating IEs

Constructors are available for every type of supported IEs (see Supported IEs for which are supported).
To create a CreatePDR IE, use NewCreatePDR(). Parameters for those "named" constructors are implemented as friendly as possible for the built-in Go types.

// returned type and parameters in NewCreatePDR() are all *ie.IE.
createPDR := ie.NewCreatePDR(
	ie.NewPDRID(0xffff),
	ie.NewPrecedence(0x11111111),
	ie.NewPDI(
		ie.NewSourceInterface(ie.SrcInterfaceAccess),
		ie.NewFTEID(0x01, 0x11111111, net.ParseIP("127.0.0.1"), nil, 0),
		ie.NewNetworkInstance("some.instance.example"),
		ie.NewRedundantTransmissionParametersInPDI(
			ie.NewFTEID(0x01, 0x11111111, net.ParseIP("127.0.0.1"), nil, 0),
			ie.NewNetworkInstance("some.instance.example"),
		),
		ie.NewUEIPAddress(0x02, "127.0.0.1", "", 0),
		ie.NewTrafficEndpointID(0x01),
		ie.NewSDFFilter("aaaaaaaa", "bb", "cccc", "ddd", 0xffffffff),
		ie.NewApplicationID("https://github.com/wmnsk/go-pfcp/"),
		ie.NewEthernetPDUSessionInformation(0x01),
		ie.NewEthernetPacketFilter(
			ie.NewEthernetFilterID(0xffffffff),
			ie.NewEthernetFilterProperties(0x01),
			ie.NewMACAddress(mac1, mac2, mac3, mac4),
			ie.NewEthertype(0xffff),
			ie.NewCTAG(0x07, 1, 1, 4095),
			ie.NewSTAG(0x07, 1, 1, 4095),
			ie.NewSDFFilter("aaaaaaaa", "bb", "cccc", "ddd", 0xffffffff),
		),
	),
	ie.NewOuterHeaderRemoval(0x01, 0x02),
	ie.NewFARID(0xffffffff),
	ie.NewURRID(0xffffffff),
	ie.NewQERID(0xffffffff),
	ie.NewActivatePredefinedRules("go-pfcp"),
	ie.NewActivationTime(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)),
	ie.NewDeactivationTime(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)),
	ie.NewMARID(0x1111),
	ie.NewPacketReplicationAndDetectionCarryOnInformation(0x0f),
	ie.NewIPMulticastAddressingInfo(
		ie.NewIPMulticastAddress(net.ParseIP("127.0.0.1"), nil, net.ParseIP("127.0.0.1"), nil),
		ie.NewSourceIPAddress(net.ParseIP("127.0.0.1"), nil, 24),
	),
	ie.NewUEIPAddressPoolIdentity("go-pfcp"),
)

Instead of using the named constructors, you can also create an arbitrary IE of any type with the SomeType value where SomeType is any of the Uint8, Uint16, Uint32, Uint64, String, or FQDN. This is useful when you don't want to use the named constructors which require the specific type of parameters, or when you want to create an IE that is not supported in this library.

For example, the following two codes will create the same *ie.IE instance.

qvTime := ie.NewQuotaValidityTime(10 * time.Second)
qvTime := ie.NewUint32(ie.QuotaValidityTime, 0x0000000a)

Sometimes you may have a value that is already in uint32 format. In that case, the latter way of creating an IE is preferable, as converting the uint32 value to time.Duration is not very efficient (compiler optimization possibly helps in the former case? I don't know, but it doesn't look good for humans anyway).

Alternatively, you may want to create an IE with the undecoded or already encoded binary (in []byte), which can be done using ie.New().

qvTime := ie.New(ie.QuotaValidityTime, []byte{0x00, 0x00, 0x00, 0x0a})

When you want to create an unsupported IE whose IE type is 999 and the value is of uint16 type, you can do like below. If it is vendor-specific, you can also specify the enterprise ID.

ie999 := ie.NewUint16(999, 0x0102)
ie999.EnterpriseID = 0x1234

This can instead be done using ie.NewUint16VendorSpecific(). There are no type-specific constructors for vendor-specific IEs.

ie999 := ie.NewVendorSpecificIE(999, 0x1234, []byte{0x01, 0x02})

Retrieving values from IEs

To retrieve values from an IE, you can call helper methods that have the same name as the IE itself on an *ie.IE. For example, you can get the value of a NetworkInstance IE by calling the NetworkInstance() method.

ni := ie.NewNetworkInstance("some.instance.example")
v, err := ni.NetworkInstance()

In the example above, calling the NetworkInstance() method returns "some.instance.example", nil. However, if ni is not of type ie.NetworkInstance or the payload is not in right format, it returns "", SomeError. It's important to always check the returned error, as the value may be empty as expected.

The type of returned values are determined as friendly as possible for the built-in Go types. For example, QuotaValidityTime() returns the value as time.Duration. In the cases that this is undesirable, such as when you need to pass the raw value to another node, you can use ValueAsUint32() method instead, which returns the value as uint32. This could also be useful for handling vendor-specific IEs whose value retrieval methods are not available in this library. Available ValueAs-methods are ValueAsUin8(), ValueAsUint16(), ValueAsUint32(), ValueAsUint64(), ValueAsString(), and ValueAsFQDN().

qvTime := ie.NewQuotaValidityTime(10 * time.Second)

vDuration, err := qvTime.QuotaValidityTime()
vUint32, err := qvTime.ValueAsUint32()

For IEs with more complex payloads, such as F-TEID, calling the <IE-name> method returns a <IE-name>Fields struct containing the values in its fields.

fteid := ie.NewFTEID(0x01, 0x11111111, net.ParseIP("127.0.0.1"), nil, nil)
fteidFields, err := fteid.FTEID() // `FTEIDFields` struct

teid := fteidFields.TEID      // TEID as uint32
v4 := fteidFields.IPv4Address // IPv4 address as net.IP

For grouped IEs, accesing the ChildIEs field is the best way to retrieve the list of IEs contained. If you are not sure that the IE is already parsed, you can use ValueAsGrouped() method instead, which parses the payload into []*IE and returns it if the ChildIEs field is empty.

cpdrIE := ie.NewCreatePDR(
	ie.NewPDRID(0xffff),
	// ...
)

// most efficient way
cpdrChildren := cpdrIE.ChildIEs
// or use this if you are not sure that the IE is already parsed
cpdrChildren, err := cpdrIE.ValueAsGrouped()

NOTE: if you have called ie.Parse, the child IEs are already parsed.

To determine if an IE is grouped or not, this library uses the defaultGroupedIEMap in ie_grouped.go, which contains the list of grouped IEs. You can add your own IE type to this map using ie.AddGroupedIEType() function, or you can change the entire logic to determine if an IE is grouped or not by setting your own function to ie.SetIsGroupedFun function.

<IE-name> method is also available for consistency with non-grouped IEs, but it is not recommended to use it as it always parses the payload into []*IE and returns it though the ChildIEs field is already populated. In the rare case that the payload can be modified after the IE is created or parsed, this method could be useful.

cpdrChildren, err := cpdrIE.CreatePDR()

For convenience, helper methods of the child IEs can be called directly on the grouped IE, or you can call FindByType() method to get the child IE of the specified type.

pdrID, err := cpdrIE.PDRID()

// or
pdrID, err := cpdrIE.FindByType(ie.PDRID)

This is useful when you only need a small number of IEs within a grouped IE. Since it iterates over all child IEs internally, retrieving everything using these method is very inefficient. When you need to retrieve the value of multiple IEs, it is recommended to iterate over the list of child IEs in your own code.

var (
	pdrID uint16
	farID uint32
	// ...
)

for _, i := range cpdrIE.ChildIEs {
	switch i.Type {
	case ie.PDRID:
		v, err = i.PDRID()
		if err != nil {
			// handle error
		}
		pdrID = v
	case ie.FARID:
		v, err = i.FARID()
		if err != nil {
			// handle error
		}
		farID = v
	case ie.SomeOtherIE:
		// ...
	}
}

List of supported IEs

IEs are implemented in conformance with TS 29.244 V16.7.0 (2021-04). The word "supported" in the table below means that the constructor and helper method for the IE are implemented in this library. As described in the previous section, you can still create an IE of any type even if it is not supported or missing in the table.

IE TypeInformation elementsSupported?
0(Reserved)-
1Create PDRYes
2PDIYes
3Create FARYes
4Forwarding ParametersYes
5Duplicating ParametersYes
6Create URRYes
7Create QERYes
8Created PDRYes
9Update PDRYes
10Update FARYes
11Update Forwarding ParametersYes
12Update BAR (PFCP Session Report Response)Yes
13Update URRYes
14Update QERYes
15Remove PDRYes
16Remove FARYes
17Remove URRYes
18Remove QERYes
19CauseYes
20Source InterfaceYes
21F-TEIDYes
22Network InstanceYes
23SDF FilterYes
24Application IDYes
25Gate StatusYes
26MBRYes
27GBRYes
28QER Correlation IDYes
29PrecedenceYes
30Transport Level MarkingYes
31Volume ThresholdYes
32Time ThresholdYes
33Monitoring TimeYes
34Subsequent Volume ThresholdYes
35Subsequent Time ThresholdYes
36Inactivity Detection TimeYes
37Reporting TriggersYes
38Redirect InformationYes
39Report TypeYes
40Offending IEYes
41Forwarding PolicyYes
42Destination InterfaceYes
43UP Function FeaturesYes
44Apply ActionYes
45Downlink Data Service InformationYes
46Downlink Data Notification DelayYes
47DL Buffering DurationYes
48DL Buffering Suggested Packet CountYes
49PFCPSMReq-FlagsYes
50PFCPSRRsp-FlagsYes
51Load Control InformationYes
52Sequence NumberYes
53MetricYes
54Overload Control InformationYes
55TimerYes
56Packet Detection Rule IDYes
57F-SEIDYes
58Application ID's PFDsYes
59PFD contextYes
60Node IDYes
61PFD contentsYes
62Measurement MethodYes
63Usage Report TriggerYes
64Measurement PeriodYes
65FQ-CSIDYes
66Volume MeasurementYes
67Duration MeasurementYes
68Application Detection InformationYes
69Time of First PacketYes
70Time of Last PacketYes
71Quota Holding TimeYes
72Dropped DL Traffic ThresholdYes
73Volume QuotaYes
74Time QuotaYes
75Start TimeYes
76End TimeYes
77Query URRYes
78Usage Report (Session Modification Response)Yes
79Usage Report (Session Deletion Response)Yes
80Usage Report (Session Report Request)Yes
81URR IDYes
82Linked URR IDYes
83Downlink Data ReportYes
84Outer Header CreationYes
85Create BARYes
86Update BAR (Session Modification Request)Yes
87Remove BARYes
88BAR IDYes
89CP Function FeaturesYes
90Usage InformationYes
91Application Instance IDYes
92Flow InformationYes
93UE IP AddressYes
94Packet RateYes
95Outer Header RemovalYes
96Recovery Time StampYes
97DL Flow Level MarkingYes
98Header EnrichmentYes
99Error Indication ReportYes
100Measurement InformationYes
101Node Report TypeYes
102User Plane Path Failure ReportYes
103Remote GTP-U PeerYes
104UR-SEQNYes
105Update Duplicating ParametersYes
106Activate Predefined RulesYes
107Deactivate Predefined RulesYes
108FAR IDYes
109QER IDYes
110OCI FlagsYes
111PFCP Association Release RequestYes
112Graceful Release PeriodYes
113PDN TypeYes
114Failed Rule IDYes
115Time Quota MechanismYes
116User Plane IP Resource InformationYes
117User Plane Inactivity TimerYes
118Aggregated URRsYes
119MultiplierYes
120Aggregated URR IDYes
121Subsequent Volume QuotaYes
122Subsequent Time QuotaYes
123RQIYes
124QFIYes
125Query URR ReferenceYes
126Additional Usage Reports InformationYes
127Create Traffic EndpointYes
128Created Traffic EndpointYes
129Update Traffic EndpointYes
130Remove Traffic EndpointYes
131Traffic Endpoint IDYes
132Ethernet Packet FilterYes
133MAC addressYes
134C-TAGYes
135S-TAGYes
136EthertypeYes
137ProxyingYes
138Ethernet Filter IDYes
139Ethernet Filter PropertiesYes
140Suggested Buffering Packets CountYes
141User IDYes
142Ethernet PDU Session InformationYes
143Ethernet Traffic InformationYes
144MAC Addresses DetectedYes
145MAC Addresses RemovedYes
146Ethernet Inactivity TimerYes
147Additional Monitoring TimeYes
148Event QuotaYes
149Event ThresholdYes
150Subsequent Event QuotaYes
151Subsequent Event ThresholdYes
152Trace InformationYes
153Framed-RouteYes
154Framed-RoutingYes
155Framed-IPv6-RouteYes
156Event Time StampYes
157Averaging WindowYes
158Paging Policy IndicatorYes
159APN/DNNYes
1603GPP Interface TypeYes
161PFCPSRReq-FlagsYes
162PFCPAUReq-FlagsYes
163Activation TimeYes
164Deactivation TimeYes
165Create MARYes
1663GPP Access Forwarding Action InformationYes
167Non-3GPP Access Forwarding Action InformationYes
168Remove MARYes
169Update MARYes
170MAR IDYes
171Steering FunctionalityYes
172Steering ModeYes
173WeightYes
174PriorityYes
175Update 3GPP Access Forwarding Action InformationYes
176Update Non 3GPP Access Forwarding Action InformationYes
177UE IP address Pool IdentityYes
178Alternative SMF IP AddressYes
179Packet Replication and Detection Carry-On InformationYes
180SMF Set IDYes
181Quota Validity TimeYes
182Number of ReportsYes
183PFCP Session Retention Information (within PFCP Association Setup Request)Yes
184PFCPASRsp-FlagsYes
185CP PFCP Entity IP AddressYes
186PFCPSEReq-FlagsYes
187User Plane Path Recovery ReportYes
188IP Multicast Addressing Info within PFCP Session Establishment RequestYes
189Join IP Multicast Information IE within Usage ReportYes
190Leave IP Multicast Information IE within Usage ReportYes
191IP Multicast AddressYes
192Source IP AddressYes
193Packet Rate StatusYes
194Create Bridge Info for TSCYes
195Created Bridge Info for TSCYes
196DS-TT Port NumberYes
197NW-TT Port NumberYes
198TSN Bridge IDYes
199TSC Management Information IE within PFCP Session Modification RequestYes
200TSC Management Information IE within PFCP Session Modification ResponseYes
201TSC Management Information IE within PFCP Session Report RequestYes
202Port Management Information ContainerYes
203Clock Drift Control InformationYes
204Requested Clock Drift InformationYes
205Clock Drift ReportYes
206TSN Time Domain NumberYes
207Time Offset ThresholdYes
208Cumulative rateRatio ThresholdYes
209Time Offset MeasurementYes
210Cumulative rateRatio MeasurementYes
211Remove SRRYes
212Create SRRYes
213Update SRRYes
214Session ReportYes
215SRR IDYes
216Access Availability Control InformationYes
217Requested Access Availability InformationYes
218Access Availability ReportYes
219Access Availability InformationYes
220Provide ATSSS Control InformationYes
221ATSSS Control ParametersYes
222MPTCP Control InformationYes
223ATSSS-LL Control InformationYes
224PMF Control InformationYes
225MPTCP ParametersYes
226ATSSS-LL ParametersYes
227PMF ParametersYes
228MPTCP Address InformationYes
229UE Link-Specific IP AddressYes
230PMF Address InformationYes
231ATSSS-LL InformationYes
232Data Network Access IdentifierYes
233UE IP address Pool InformationYes
234Average Packet DelayYes
235Minimum Packet DelayYes
236Maximum Packet DelayYes
237QoS Report TriggerYes
238GTP-U Path QoS Control InformationYes
239GTP-U Path QoS Report (PFCP Node Report Request)Yes
240QoS Information in GTP-U Path QoS ReportYes
241GTP-U Path Interface TypeYes
242QoS Monitoring per QoS flow Control InformationYes
243Requested QoS MonitoringYes
244Reporting FrequencyYes
245Packet Delay ThresholdsYes
246Minimum Wait TimeYes
247QoS Monitoring ReportYes
248QoS Monitoring MeasurementYes
249MT-EDT Control InformationYes
250DL Data Packets SizeYes
251QER Control IndicationsYes
252Packet Rate Status ReportYes
253NF Instance IDYes
254Ethernet Context InformationYes
255Redundant Transmission ParametersYes
256Updated PDRYes
257S-NSSAIYes
258IP versionYes
259PFCPASReq-FlagsYes
260Data StatusYes
261Provide RDS configuration informationYes
262RDS configuration informationYes
263Query Packet Rate Status IE within PFCP Session Modification RequestYes
264Packet Rate Status Report IE within PFCP Session Modification ResponseYes
265MPTCP Applicable IndicationYes
266Bridge Management Information ContainerYes
267UE IP Address Usage InformationYes
268Number of UE IP AddressesYes
269Validity TimerYes
270Redundant Transmission Forwarding ParametersYes
271Transport Delay ReportingYes
272 to 32767(For future use)-
32768 to 65535Reserved for vendor specific IEs-

Author(s)

Yoshiyuki Kurauchi and contributors.

I'm always open to welcome co-authors! Please feel free to talk to me.

LICENSE

MIT