From 47c861b948fa574043c2470d515978d4b0bfac18 Mon Sep 17 00:00:00 2001 From: Guillaume Belanger Date: Sat, 6 Jan 2024 12:50:21 -0500 Subject: [PATCH] Adds pfcp session header --- client/client.go | 33 ++-- headers/header.go | 67 ------- ie/fseid.go | 7 - messages/heartbeat.go | 4 +- messages/messages.go | 179 ++++++++++++++++++ .../messages_test.go | 8 +- messages/pfcp_association_release.go | 4 +- messages/pfcp_association_setup.go | 4 +- messages/pfcp_association_update.go | 4 +- messages/pfcp_node_report.go | 4 +- messages/pfcp_session_establishment.go | 2 +- server/server.go | 78 ++++---- tests/pfcp_node_report_test.go | 5 + tests/pfcp_session_establishment_test.go | 14 +- 14 files changed, 265 insertions(+), 148 deletions(-) delete mode 100644 headers/header.go rename headers/header_test.go => messages/messages_test.go (87%) diff --git a/client/client.go b/client/client.go index f173f77..41a09f0 100644 --- a/client/client.go +++ b/client/client.go @@ -4,7 +4,6 @@ import ( "fmt" "log" - "github.com/dot-5g/pfcp/headers" "github.com/dot-5g/pfcp/ie" "github.com/dot-5g/pfcp/messages" "github.com/dot-5g/pfcp/network" @@ -24,7 +23,7 @@ func New(ServerAddress string) *Pfcp { return &Pfcp{ServerAddress: ServerAddress, Udp: udpClient} } -func (pfcp *Pfcp) sendPfcpMessage(header headers.PFCPHeader, elements []ie.InformationElement) error { +func (pfcp *Pfcp) sendPfcpMessage(header messages.PFCPHeader, elements []ie.InformationElement) error { var payload []byte for _, element := range elements { payload = append(payload, element.Serialize()...) @@ -38,14 +37,14 @@ func (pfcp *Pfcp) sendPfcpMessage(header headers.PFCPHeader, elements []ie.Infor return nil } -func serializeMessage(header headers.PFCPHeader, payload []byte) []byte { - header.MessageLength = uint16(4 + len(payload)) - headerBytes := headers.SerializePFCPHeader(header) +func serializeMessage(header messages.PFCPHeader, payload []byte) []byte { + header.MessageLength = uint16(len(payload)) + headerBytes := header.Serialize() return append(headerBytes, payload...) } func (pfcp *Pfcp) SendHeartbeatRequest(msg messages.HeartbeatRequest, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.HeartbeatRequestMessageType, sequenceNumber) + header := messages.NewNodePFCPHeader(messages.HeartbeatRequestMessageType, sequenceNumber) ies := []ie.InformationElement{msg.RecoveryTimeStamp} @@ -61,7 +60,7 @@ func (pfcp *Pfcp) SendHeartbeatRequest(msg messages.HeartbeatRequest, sequenceNu } func (pfcp *Pfcp) SendHeartbeatResponse(msg messages.HeartbeatResponse, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.HeartbeatResponseMessageType, sequenceNumber) + header := messages.NewNodePFCPHeader(messages.HeartbeatResponseMessageType, sequenceNumber) ies := []ie.InformationElement{msg.RecoveryTimeStamp} err := pfcp.sendPfcpMessage(header, ies) if err != nil { @@ -71,7 +70,7 @@ func (pfcp *Pfcp) SendHeartbeatResponse(msg messages.HeartbeatResponse, sequence } func (pfcp *Pfcp) SendPFCPAssociationSetupRequest(msg messages.PFCPAssociationSetupRequest, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.PFCPAssociationSetupRequestMessageType, sequenceNumber) + header := messages.NewNodePFCPHeader(messages.PFCPAssociationSetupRequestMessageType, sequenceNumber) ies := []ie.InformationElement{msg.NodeID, msg.RecoveryTimeStamp} if !msg.UPFunctionFeatures.IsZeroValue() { @@ -86,7 +85,7 @@ func (pfcp *Pfcp) SendPFCPAssociationSetupRequest(msg messages.PFCPAssociationSe } func (pfcp *Pfcp) SendPFCPAssociationSetupResponse(msg messages.PFCPAssociationSetupResponse, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.PFCPAssociationSetupResponseMessageType, sequenceNumber) + header := messages.NewNodePFCPHeader(messages.PFCPAssociationSetupResponseMessageType, sequenceNumber) ies := []ie.InformationElement{msg.NodeID, msg.Cause, msg.RecoveryTimeStamp} err := pfcp.sendPfcpMessage(header, ies) if err != nil { @@ -96,7 +95,7 @@ func (pfcp *Pfcp) SendPFCPAssociationSetupResponse(msg messages.PFCPAssociationS } func (pfcp *Pfcp) SendPFCPAssociationUpdateRequest(msg messages.PFCPAssociationUpdateRequest, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.PFCPAssociationUpdateRequestMessageType, sequenceNumber) + header := messages.NewNodePFCPHeader(messages.PFCPAssociationUpdateRequestMessageType, sequenceNumber) ies := []ie.InformationElement{msg.NodeID} err := pfcp.sendPfcpMessage(header, ies) if err != nil { @@ -106,7 +105,7 @@ func (pfcp *Pfcp) SendPFCPAssociationUpdateRequest(msg messages.PFCPAssociationU } func (pfcp *Pfcp) SendPFCPAssociationUpdateResponse(msg messages.PFCPAssociationUpdateResponse, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.PFCPAssociationUpdateResponseMessageType, sequenceNumber) + header := messages.NewNodePFCPHeader(messages.PFCPAssociationUpdateResponseMessageType, sequenceNumber) ies := []ie.InformationElement{msg.NodeID, msg.Cause} err := pfcp.sendPfcpMessage(header, ies) if err != nil { @@ -116,7 +115,7 @@ func (pfcp *Pfcp) SendPFCPAssociationUpdateResponse(msg messages.PFCPAssociation } func (pfcp *Pfcp) SendPFCPAssociationReleaseRequest(msg messages.PFCPAssociationReleaseRequest, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.PFCPAssociationReleaseRequestMessageType, sequenceNumber) + header := messages.NewNodePFCPHeader(messages.PFCPAssociationReleaseRequestMessageType, sequenceNumber) ies := []ie.InformationElement{msg.NodeID} err := pfcp.sendPfcpMessage(header, ies) if err != nil { @@ -126,7 +125,7 @@ func (pfcp *Pfcp) SendPFCPAssociationReleaseRequest(msg messages.PFCPAssociation } func (pfcp *Pfcp) SendPFCPAssociationReleaseResponse(msg messages.PFCPAssociationReleaseResponse, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.PFCPAssociationReleaseResponseMessageType, sequenceNumber) + header := messages.NewNodePFCPHeader(messages.PFCPAssociationReleaseResponseMessageType, sequenceNumber) ies := []ie.InformationElement{msg.NodeID, msg.Cause} err := pfcp.sendPfcpMessage(header, ies) if err != nil { @@ -136,7 +135,7 @@ func (pfcp *Pfcp) SendPFCPAssociationReleaseResponse(msg messages.PFCPAssociatio } func (pfcp *Pfcp) SendPFCPNodeReportRequest(msg messages.PFCPNodeReportRequest, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.PFCPNodeReportRequestMessageType, sequenceNumber) + header := messages.NewNodePFCPHeader(messages.PFCPNodeReportRequestMessageType, sequenceNumber) ies := []ie.InformationElement{msg.NodeID, msg.NodeReportType} err := pfcp.sendPfcpMessage(header, ies) if err != nil { @@ -146,7 +145,7 @@ func (pfcp *Pfcp) SendPFCPNodeReportRequest(msg messages.PFCPNodeReportRequest, } func (pfcp *Pfcp) SendPFCPNodeReportResponse(msg messages.PFCPNodeReportResponse, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.PFCPNodeReportResponseMessageType, sequenceNumber) + header := messages.NewNodePFCPHeader(messages.PFCPNodeReportResponseMessageType, sequenceNumber) ies := []ie.InformationElement{msg.NodeID, msg.Cause} err := pfcp.sendPfcpMessage(header, ies) if err != nil { @@ -155,8 +154,8 @@ func (pfcp *Pfcp) SendPFCPNodeReportResponse(msg messages.PFCPNodeReportResponse return nil } -func (pfcp *Pfcp) SendPFCPSessionEstablishmentRequest(msg messages.PFCPSessionEstablishmentRequest, sequenceNumber uint32) error { - header := headers.NewPFCPHeader(messages.PFCPSessionEstablishmentRequestMessageType, sequenceNumber) +func (pfcp *Pfcp) SendPFCPSessionEstablishmentRequest(msg messages.PFCPSessionEstablishmentRequest, seid uint64, sequenceNumber uint32) error { + header := messages.NewSessionPFCPHeader(messages.PFCPSessionEstablishmentRequestMessageType, seid, sequenceNumber) ies := []ie.InformationElement{msg.NodeID, msg.CPFSEID, msg.CreatePDR, msg.CreateFAR} err := pfcp.sendPfcpMessage(header, ies) if err != nil { diff --git a/headers/header.go b/headers/header.go deleted file mode 100644 index 0f56c64..0000000 --- a/headers/header.go +++ /dev/null @@ -1,67 +0,0 @@ -package headers - -import ( - "bytes" - "encoding/binary" - "fmt" - - "github.com/dot-5g/pfcp/messages" -) - -const HeaderSize = 8 - -type PFCPHeader struct { - Version byte - MessageType messages.MessageType - MessageLength uint16 - SequenceNumber uint32 -} - -func SerializePFCPHeader(header PFCPHeader) []byte { - buf := new(bytes.Buffer) - - // Octet 1: Version (3 bits), Spare (2 bits), FO (1 bit set to 0), MP (1 bit set to 0), S (1 bit set to 0) - firstOctet := (header.Version << 5) - buf.WriteByte(firstOctet) - - // Octet 2: Message Type (1 byte) - buf.WriteByte(byte(header.MessageType)) - - // Octets 3 and 4: Message Length (2 bytes) - binary.Write(buf, binary.BigEndian, header.MessageLength) - - // Octets 5, 6, and 7: Sequence Number (3 bytes) - seqNumBytes := make([]byte, 4) - binary.BigEndian.PutUint32(seqNumBytes, header.SequenceNumber) - buf.Write(seqNumBytes[1:]) - - // Octet 8: Spare (1 byte set to 0) - buf.WriteByte(0) - - return buf.Bytes() -} - -func NewPFCPHeader(messageType messages.MessageType, sequenceNumber uint32) PFCPHeader { - return PFCPHeader{ - Version: 1, - MessageType: messageType, - MessageLength: 0, // To be set later - SequenceNumber: sequenceNumber, - } -} - -func ParsePFCPHeader(data []byte) (PFCPHeader, error) { - if len(data) != HeaderSize { - return PFCPHeader{}, fmt.Errorf("expected %d bytes, got %d", HeaderSize, len(data)) - } - - header := PFCPHeader{} - header.Version = data[0] >> 5 - header.MessageType = messages.MessageType(data[1]) - header.MessageLength = binary.BigEndian.Uint16(data[2:4]) - - seqNumBytes := []byte{0, data[4], data[5], data[6]} - header.SequenceNumber = binary.BigEndian.Uint32(seqNumBytes) - - return header, nil -} diff --git a/ie/fseid.go b/ie/fseid.go index 604c0b1..31cdc44 100644 --- a/ie/fseid.go +++ b/ie/fseid.go @@ -3,7 +3,6 @@ package ie import ( "bytes" "encoding/binary" - "fmt" "net" ) @@ -29,9 +28,6 @@ func NewFSEID(seid uint64, ipv4Address string, ipv6Address string) (FSEID, error fseid.IPv4 = ipv4.To4() fseid.IPv6 = ipv6.To16() - fmt.Print("IPv4: ", fseid.IPv4, "\n") - fmt.Print("IPv6: ", fseid.IPv6, "\n") - if fseid.IPv4 != nil { fseid.V4 = true length += 4 @@ -80,9 +76,6 @@ func (fseid FSEID) Serialize() []byte { } func DeserializeFSEID(ieType uint16, ieLength uint16, ieValue []byte) (FSEID, error) { - fmt.Printf("ieType: %v\n", ieType) - - fmt.Printf("ieValue: %v\n", ieValue) v4 := ieValue[0]&0x02 > 0 v6 := ieValue[0]&0x01 > 0 seid := binary.BigEndian.Uint64(ieValue[1:9]) diff --git a/messages/heartbeat.go b/messages/heartbeat.go index 1b0845d..3966dee 100644 --- a/messages/heartbeat.go +++ b/messages/heartbeat.go @@ -13,7 +13,7 @@ type HeartbeatResponse struct { RecoveryTimeStamp ie.RecoveryTimeStamp // Mandatory } -func ParseHeartbeatRequest(data []byte) (HeartbeatRequest, error) { +func DeserializeHeartbeatRequest(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var recoveryTimeStamp ie.RecoveryTimeStamp var sourceIPAddress ie.SourceIPAddress @@ -34,7 +34,7 @@ func ParseHeartbeatRequest(data []byte) (HeartbeatRequest, error) { }, err } -func ParseHeartbeatResponse(data []byte) (HeartbeatResponse, error) { +func DeserializeHeartbeatResponse(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var recoveryTimeStamp ie.RecoveryTimeStamp for _, elem := range ies { diff --git a/messages/messages.go b/messages/messages.go index b749ed3..742e853 100644 --- a/messages/messages.go +++ b/messages/messages.go @@ -1,5 +1,11 @@ package messages +import ( + "bytes" + "encoding/binary" + "fmt" +) + type MessageType byte const ( @@ -15,3 +21,176 @@ const ( PFCPNodeReportResponseMessageType MessageType = 13 PFCPSessionEstablishmentRequestMessageType MessageType = 50 ) + +type PFCPMessage interface { +} + +type DeserializerFunc func([]byte) (PFCPMessage, error) + +var messageTypeDeserializers = map[MessageType]DeserializerFunc{ + HeartbeatRequestMessageType: DeserializeHeartbeatRequest, + HeartbeatResponseMessageType: DeserializeHeartbeatResponse, + PFCPAssociationSetupRequestMessageType: DeserializePFCPAssociationSetupRequest, + PFCPAssociationSetupResponseMessageType: DeserializePFCPAssociationSetupResponse, + PFCPAssociationUpdateRequestMessageType: DeserializePFCPAssociationUpdateRequest, + PFCPAssociationUpdateResponseMessageType: DeserializePFCPAssociationUpdateResponse, + PFCPAssociationReleaseRequestMessageType: DeserializePFCPAssociationReleaseRequest, + PFCPAssociationReleaseResponseMessageType: DeserializePFCPAssociationReleaseResponse, + PFCPNodeReportRequestMessageType: DeserializePFCPNodeReportRequest, + PFCPNodeReportResponseMessageType: DeserializePFCPNodeReportResponse, + PFCPSessionEstablishmentRequestMessageType: DeserializePFCPSessionEstablishmentRequest, +} + +type PFCPHeader struct { + Version byte + FO bool + MP bool + S bool + MessageType MessageType + MessageLength uint16 + SEID uint64 + SequenceNumber uint32 +} + +func NewNodePFCPHeader(messageType MessageType, sequenceNumber uint32) PFCPHeader { + var version byte = 1 + var fo bool = false + var mp bool = false + var s bool = false + var messageLength uint16 = 0 // To be set later + + return PFCPHeader{ + Version: version, + FO: fo, + MP: mp, + S: s, + MessageType: messageType, + MessageLength: messageLength, + SequenceNumber: sequenceNumber, + } +} + +func NewSessionPFCPHeader(messageType MessageType, seid uint64, sequenceNumber uint32) PFCPHeader { + var version byte = 1 + var fo bool = false + var mp bool = false + var s bool = true + var messageLength uint16 = 0 // To be set later + + return PFCPHeader{ + Version: version, + FO: fo, + MP: mp, + S: s, + MessageType: messageType, + MessageLength: messageLength, + SEID: seid, + SequenceNumber: sequenceNumber, + } +} + +func (header PFCPHeader) Serialize() []byte { + // if S = 0, SEID field is not present, k = 0, m = 0 and n = 5; + // if S = 1, SEID field is present, k = 1, m = 5 and n = 13. + buf := new(bytes.Buffer) + + // Octet 1: Version (3 bits), Spare (2 bits), FO (1 bit), MP (1 bit), S (1 bit) + firstOctet := (header.Version << 5) + if header.FO { + firstOctet |= 1 << 2 // Set the FO bit + } + if header.MP { + firstOctet |= 1 << 1 // Set the MP bit + } + if header.S { + firstOctet |= 1 // Set the S bit + } + buf.WriteByte(firstOctet) + + // Octet 2: Message Type (1 byte) + buf.WriteByte(byte(header.MessageType)) + + // Octets 3 to 4: Message Length (2 bytes) + binary.Write(buf, binary.BigEndian, header.MessageLength) + + // Octets m to k(m+7): SEID (8 bytes) + if header.S { + binary.Write(buf, binary.BigEndian, header.SEID) + } + + // Octets n to (n+2): Sequence Number (4 bytes) + seqNumBytes := make([]byte, 4) + binary.BigEndian.PutUint32(seqNumBytes, header.SequenceNumber) + buf.Write(seqNumBytes[1:]) + + // Octet 8: Spare (1 byte set to 0) + buf.WriteByte(0) + + return buf.Bytes() +} + +func DeserializePFCPHeader(data []byte) (PFCPHeader, error) { + const baseHeaderSize = 8 // Base size for node-related messages + const seidSize = 8 // Size of SEID field + const sessionHeaderSize = baseHeaderSize + seidSize // Total size for session-related messages + + if len(data) < baseHeaderSize { + return PFCPHeader{}, fmt.Errorf("expected at least %d bytes, got %d", baseHeaderSize, len(data)) + } + + header := PFCPHeader{} + header.Version = data[0] >> 5 + header.FO = (data[0] & 0x04) != 0 // Extract the FO bit + header.MP = (data[0] & 0x02) != 0 // Extract the MP bit + header.S = (data[0] & 0x01) != 0 // Extract the S bit + header.MessageType = MessageType(data[1]) + header.MessageLength = binary.BigEndian.Uint16(data[2:4]) + + // For node-related messages, sequence number starts at offset 4 + // For session-related messages, SEID is between offsets 4-11, and sequence number starts at offset 12 + var seqNumOffset int + if header.S { + if len(data) < sessionHeaderSize { + return PFCPHeader{}, fmt.Errorf("expected %d bytes for session message, got %d", sessionHeaderSize, len(data)) + } + header.SEID = binary.BigEndian.Uint64(data[4:12]) + seqNumOffset = 12 + } else { + seqNumOffset = 4 + } + + // Extract the sequence number + if len(data) < seqNumOffset+3 { + return PFCPHeader{}, fmt.Errorf("insufficient data for sequence number") + } + seqNumBytes := []byte{0, data[seqNumOffset], data[seqNumOffset+1], data[seqNumOffset+2]} + header.SequenceNumber = binary.BigEndian.Uint32(seqNumBytes) + + return header, nil +} + +func DeserializePFCPMessage(payload []byte) (PFCPHeader, PFCPMessage, error) { + header, err := DeserializePFCPHeader(payload) + if err != nil { + return header, nil, err + } + + payloadOffset := 8 + if header.S { + payloadOffset = 16 + } + + if len(payload) < payloadOffset { + return header, nil, fmt.Errorf("insufficient data for payload message") + } + payloadMessage := payload[payloadOffset:] + if deserializer, exists := messageTypeDeserializers[header.MessageType]; exists { + msg, err := deserializer(payloadMessage) + if err != nil { + return header, nil, fmt.Errorf("error deserializing payload message: %v", err) + } + return header, msg, nil + } + + return header, nil, fmt.Errorf("unsupported message type: %d", header.MessageType) +} diff --git a/headers/header_test.go b/messages/messages_test.go similarity index 87% rename from headers/header_test.go rename to messages/messages_test.go index aeb2de9..6116a1e 100644 --- a/headers/header_test.go +++ b/messages/messages_test.go @@ -1,22 +1,22 @@ -package headers_test +package messages_test import ( "bytes" "encoding/binary" "testing" - "github.com/dot-5g/pfcp/headers" + "github.com/dot-5g/pfcp/messages" ) func TestGivenPfcpHeaderWhenSerializePFCPHeaderThenSerializedCorrectly(t *testing.T) { - pfcpHeader := headers.PFCPHeader{ + pfcpHeader := messages.PFCPHeader{ Version: 1, MessageType: 2, MessageLength: 3, SequenceNumber: 4, } - headerBytes := headers.SerializePFCPHeader(pfcpHeader) + headerBytes := pfcpHeader.Serialize() if len(headerBytes) != 8 { t.Errorf("Expected 8 bytes, got %d", len(headerBytes)) diff --git a/messages/pfcp_association_release.go b/messages/pfcp_association_release.go index cef98c0..f9c96d2 100644 --- a/messages/pfcp_association_release.go +++ b/messages/pfcp_association_release.go @@ -11,7 +11,7 @@ type PFCPAssociationReleaseResponse struct { Cause ie.Cause // Mandatory } -func ParsePFCPAssociationReleaseRequest(data []byte) (PFCPAssociationReleaseRequest, error) { +func DeserializePFCPAssociationReleaseRequest(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var nodeID ie.NodeID for _, elem := range ies { @@ -26,7 +26,7 @@ func ParsePFCPAssociationReleaseRequest(data []byte) (PFCPAssociationReleaseRequ }, err } -func ParsePFCPAssociationReleaseResponse(data []byte) (PFCPAssociationReleaseResponse, error) { +func DeserializePFCPAssociationReleaseResponse(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var nodeID ie.NodeID var cause ie.Cause diff --git a/messages/pfcp_association_setup.go b/messages/pfcp_association_setup.go index b1daf02..8fc9988 100644 --- a/messages/pfcp_association_setup.go +++ b/messages/pfcp_association_setup.go @@ -16,7 +16,7 @@ type PFCPAssociationSetupResponse struct { RecoveryTimeStamp ie.RecoveryTimeStamp // Mandatory } -func ParsePFCPAssociationSetupRequest(data []byte) (PFCPAssociationSetupRequest, error) { +func DeserializePFCPAssociationSetupRequest(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var nodeID ie.NodeID var recoveryTimeStamp ie.RecoveryTimeStamp @@ -43,7 +43,7 @@ func ParsePFCPAssociationSetupRequest(data []byte) (PFCPAssociationSetupRequest, }, err } -func ParsePFCPAssociationSetupResponse(data []byte) (PFCPAssociationSetupResponse, error) { +func DeserializePFCPAssociationSetupResponse(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var nodeID ie.NodeID var cause ie.Cause diff --git a/messages/pfcp_association_update.go b/messages/pfcp_association_update.go index 7b12249..426e922 100644 --- a/messages/pfcp_association_update.go +++ b/messages/pfcp_association_update.go @@ -11,7 +11,7 @@ type PFCPAssociationUpdateResponse struct { Cause ie.Cause // Mandatory } -func ParsePFCPAssociationUpdateRequest(data []byte) (PFCPAssociationUpdateRequest, error) { +func DeserializePFCPAssociationUpdateRequest(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var nodeID ie.NodeID for _, elem := range ies { @@ -26,7 +26,7 @@ func ParsePFCPAssociationUpdateRequest(data []byte) (PFCPAssociationUpdateReques }, err } -func ParsePFCPAssociationUpdateResponse(data []byte) (PFCPAssociationUpdateResponse, error) { +func DeserializePFCPAssociationUpdateResponse(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var nodeID ie.NodeID var cause ie.Cause diff --git a/messages/pfcp_node_report.go b/messages/pfcp_node_report.go index 83bc3f9..0a833ee 100644 --- a/messages/pfcp_node_report.go +++ b/messages/pfcp_node_report.go @@ -14,7 +14,7 @@ type PFCPNodeReportResponse struct { Cause ie.Cause // Mandatory } -func ParsePFCPNodeReportRequest(data []byte) (PFCPNodeReportRequest, error) { +func DeserializePFCPNodeReportRequest(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var nodeID ie.NodeID var nodeReportType ie.NodeReportType @@ -35,7 +35,7 @@ func ParsePFCPNodeReportRequest(data []byte) (PFCPNodeReportRequest, error) { }, err } -func ParsePFCPNodeReportResponse(data []byte) (PFCPNodeReportResponse, error) { +func DeserializePFCPNodeReportResponse(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var nodeID ie.NodeID var cause ie.Cause diff --git a/messages/pfcp_session_establishment.go b/messages/pfcp_session_establishment.go index 68b3a20..5bede7f 100644 --- a/messages/pfcp_session_establishment.go +++ b/messages/pfcp_session_establishment.go @@ -9,7 +9,7 @@ type PFCPSessionEstablishmentRequest struct { CreateFAR ie.CreateFAR // Mandatory } -func ParsePFCPSessionEstablishmentRequest(data []byte) (PFCPSessionEstablishmentRequest, error) { +func DeserializePFCPSessionEstablishmentRequest(data []byte) (PFCPMessage, error) { ies, err := ie.ParseInformationElements(data) var nodeID ie.NodeID var controlPlaneFSEID ie.FSEID diff --git a/server/server.go b/server/server.go index 95db466..c3178d0 100644 --- a/server/server.go +++ b/server/server.go @@ -3,7 +3,6 @@ package server import ( "log" - "github.com/dot-5g/pfcp/headers" "github.com/dot-5g/pfcp/messages" "github.com/dot-5g/pfcp/network" ) @@ -18,7 +17,7 @@ type HandlePFCPAssociationReleaseRequest func(sequenceNumber uint32, msg message type HandlePFCPAssociationReleaseResponse func(sequenceNumber uint32, msg messages.PFCPAssociationReleaseResponse) type HandlePFCPNodeReportRequest func(sequenceNumber uint32, msg messages.PFCPNodeReportRequest) type HandlePFCPNodeReportResponse func(sequenceNumber uint32, msg messages.PFCPNodeReportResponse) -type HandlePFCPSessionEstablishmentRequest func(sequenceNumber uint32, msg messages.PFCPSessionEstablishmentRequest) +type HandlePFCPSessionEstablishmentRequest func(sequenceNumber uint32, seid uint64, msg messages.PFCPSessionEstablishmentRequest) type Server struct { address string @@ -99,10 +98,11 @@ func (server *Server) PFCPSessionEstablishmentRequest(handler HandlePFCPSessionE server.pfcpSessionEstablishmentRequestHandler = handler } -func (server *Server) handleUDPMessage(data []byte) { - header, err := headers.ParsePFCPHeader(data[:headers.HeaderSize]) +func (server *Server) handleUDPMessage(payload []byte) { + header, genericMessage, err := messages.DeserializePFCPMessage(payload) + if err != nil { - log.Printf("Error parsing PFCP header: %v", err) + log.Printf("Error deserializing PFCP message: %v", err) return } @@ -112,9 +112,9 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for Heartbeat Request") return } - msg, err := messages.ParseHeartbeatRequest(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing Heartbeat Request: %v", err) + msg, ok := genericMessage.(messages.HeartbeatRequest) + if !ok { + log.Printf("Error asserting Heartbeat Request type") return } server.heartbeatRequestHandler(header.SequenceNumber, msg) @@ -123,9 +123,9 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for Heartbeat Response") return } - msg, err := messages.ParseHeartbeatResponse(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing Heartbeat Response: %v", err) + msg, ok := genericMessage.(messages.HeartbeatResponse) + if !ok { + log.Printf("Error asserting Heartbeat Response type") return } server.heartbeatResponseHandler(header.SequenceNumber, msg) @@ -134,9 +134,9 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for PFCP Association Setup Request") return } - msg, err := messages.ParsePFCPAssociationSetupRequest(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing PFCP Association Setup Request: %v", err) + msg, ok := genericMessage.(messages.PFCPAssociationSetupRequest) + if !ok { + log.Printf("Error asserting PFCP Association Setup Request type") return } server.pfcpAssociationSetupRequestHandler(header.SequenceNumber, msg) @@ -145,9 +145,9 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for PFCP Association Setup Response") return } - msg, err := messages.ParsePFCPAssociationSetupResponse(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing PFCP Association Setup Response: %v", err) + msg, ok := genericMessage.(messages.PFCPAssociationSetupResponse) + if !ok { + log.Printf("Error asserting PFCP Association Setup Response type") return } server.pfcpAssociationSetupResponseHandler(header.SequenceNumber, msg) @@ -156,9 +156,9 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for PFCP Association Update Request") return } - msg, err := messages.ParsePFCPAssociationUpdateRequest(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing PFCP Association Update Request: %v", err) + msg, ok := genericMessage.(messages.PFCPAssociationUpdateRequest) + if !ok { + log.Printf("Error asserting PFCP Association Update Request type") return } server.pfcpAssociationUpdateRequestHandler(header.SequenceNumber, msg) @@ -167,9 +167,9 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for PFCP Association Update Response") return } - msg, err := messages.ParsePFCPAssociationUpdateResponse(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing PFCP Association Update Response: %v", err) + msg, ok := genericMessage.(messages.PFCPAssociationUpdateResponse) + if !ok { + log.Printf("Error asserting PFCP Association Update Response type") return } server.pfcpAssociationUpdateResponseHandler(header.SequenceNumber, msg) @@ -178,9 +178,9 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for PFCP Association Release Request") return } - msg, err := messages.ParsePFCPAssociationReleaseRequest(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing PFCP Association Release Request: %v", err) + msg, ok := genericMessage.(messages.PFCPAssociationReleaseRequest) + if !ok { + log.Printf("Error asserting PFCP Association Release Request type") return } server.pfcpAssociationReleaseRequestHandler(header.SequenceNumber, msg) @@ -189,9 +189,9 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for PFCP Association Release Response") return } - msg, err := messages.ParsePFCPAssociationReleaseResponse(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing PFCP Association Release Response: %v", err) + msg, ok := genericMessage.(messages.PFCPAssociationReleaseResponse) + if !ok { + log.Printf("Error asserting PFCP Association Release Response type") return } server.pfcpAssociationReleaseResponseHandler(header.SequenceNumber, msg) @@ -200,9 +200,9 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for PFCP Node Report Request") return } - msg, err := messages.ParsePFCPNodeReportRequest(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing PFCP Node Report Request: %v", err) + msg, ok := genericMessage.(messages.PFCPNodeReportRequest) + if !ok { + log.Printf("Error asserting PFCP Node Report Request type") return } server.pfcpNodeReportRequestHandler(header.SequenceNumber, msg) @@ -211,9 +211,9 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for PFCP Node Report Response") return } - msg, err := messages.ParsePFCPNodeReportResponse(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing PFCP Node Report Response: %v", err) + msg, ok := genericMessage.(messages.PFCPNodeReportResponse) + if !ok { + log.Printf("Error asserting PFCP Node Report Response type") return } server.pfcpNodeReportResponseHandler(header.SequenceNumber, msg) @@ -222,12 +222,12 @@ func (server *Server) handleUDPMessage(data []byte) { log.Printf("No handler for PFCP Session Establishment Request") return } - msg, err := messages.ParsePFCPSessionEstablishmentRequest(data[headers.HeaderSize:]) - if err != nil { - log.Printf("Error parsing PFCP Session Establishment Request: %v", err) + msg, ok := genericMessage.(messages.PFCPSessionEstablishmentRequest) + if !ok { + log.Printf("Error asserting PFCP Session Establishment Request type") return } - server.pfcpSessionEstablishmentRequestHandler(header.SequenceNumber, msg) + server.pfcpSessionEstablishmentRequestHandler(header.SequenceNumber, header.SEID, msg) default: log.Printf("Unknown PFCP message type: %v", header.MessageType) } diff --git a/tests/pfcp_node_report_test.go b/tests/pfcp_node_report_test.go index d7b639c..c59de4e 100644 --- a/tests/pfcp_node_report_test.go +++ b/tests/pfcp_node_report_test.go @@ -72,6 +72,11 @@ func PFCPNodeReportRequest(t *testing.T) { upfr := false nodeReportType, err := ie.NewNodeReportType(gpqr, ckdr, uprr, upfr) + + if err != nil { + t.Fatalf("Error creating NodeReportType: %v", err) + } + sequenceNumber := uint32(32) PFCPNodeReportRequestMsg := messages.PFCPNodeReportRequest{ NodeID: nodeID, diff --git a/tests/pfcp_session_establishment_test.go b/tests/pfcp_session_establishment_test.go index bab37e4..a9a2eac 100644 --- a/tests/pfcp_session_establishment_test.go +++ b/tests/pfcp_session_establishment_test.go @@ -15,17 +15,19 @@ var ( pfcpSessionEstablishmentRequestMu sync.Mutex pfcpSessionEstablishmentRequesthandlerCalled bool pfcpSessionEstablishmentRequestReceivedSequenceNumber uint32 + pfcpSessionEstablishmentRequestReceivedSEID uint64 pfcpSessionEstablishmentRequestReceivedNodeID ie.NodeID pfcpSessionEstablishmentRequestReceivedCPFSEID ie.FSEID pfcpSessionEstablishmentRequestReceivedCreatePDR ie.CreatePDR pfcpSessionEstablishmentRequestReceivedCreateFAR ie.CreateFAR ) -func HandlePFCPSessionEstablishmentRequest(sequenceNumber uint32, msg messages.PFCPSessionEstablishmentRequest) { +func HandlePFCPSessionEstablishmentRequest(sequenceNumber uint32, seid uint64, msg messages.PFCPSessionEstablishmentRequest) { pfcpSessionEstablishmentRequestMu.Lock() defer pfcpSessionEstablishmentRequestMu.Unlock() pfcpSessionEstablishmentRequesthandlerCalled = true pfcpSessionEstablishmentRequestReceivedSequenceNumber = sequenceNumber + pfcpSessionEstablishmentRequestReceivedSEID = seid pfcpSessionEstablishmentRequestReceivedNodeID = msg.NodeID pfcpSessionEstablishmentRequestReceivedCPFSEID = msg.CPFSEID pfcpSessionEstablishmentRequestReceivedCreatePDR = msg.CreatePDR @@ -53,7 +55,9 @@ func PFCPSessionEstablishmentRequest(t *testing.T) { t.Fatalf("Error creating Node ID: %v", err) } - fseid, err := ie.NewFSEID(uint64(1234567890), "1.2.3.4", "") + seid := uint64(1234567890) + + fseid, err := ie.NewFSEID(seid, "1.2.3.4", "") if err != nil { t.Fatalf("Error creating FSEID: %v", err) } @@ -110,7 +114,7 @@ func PFCPSessionEstablishmentRequest(t *testing.T) { } sequenceNumber := uint32(32) - pfcpClient.SendPFCPSessionEstablishmentRequest(PFCPSessionEstablishmentRequestMsg, sequenceNumber) + pfcpClient.SendPFCPSessionEstablishmentRequest(PFCPSessionEstablishmentRequestMsg, seid, sequenceNumber) time.Sleep(time.Second) @@ -123,6 +127,10 @@ func PFCPSessionEstablishmentRequest(t *testing.T) { t.Errorf("PFCP Session Establishment Request handler was called with wrong sequence number.\n- Sent sequence number: %v\n- Received sequence number %v\n", sequenceNumber, pfcpSessionEstablishmentRequestReceivedSequenceNumber) } + if pfcpSessionEstablishmentRequestReceivedSEID != seid { + t.Errorf("PFCP Session Establishment Request handler was called with wrong SEID.\n- Sent SEID: %v\n- Received SEID %v\n", seid, pfcpSessionEstablishmentRequestReceivedSEID) + } + if pfcpSessionEstablishmentRequestReceivedNodeID.Length != nodeID.Length { t.Errorf("PFCP Session Establishment Request handler was called with wrong node ID length.\n- Sent node ID length: %v\n- Received node ID length %v\n", nodeID.Length, pfcpSessionEstablishmentRequestReceivedNodeID.Length) }