Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

Commit

Permalink
feat: moves pfcp server to main process (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
gruyaume authored Jan 7, 2024
1 parent a002887 commit 807650a
Show file tree
Hide file tree
Showing 23 changed files with 321 additions and 211 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import (
func main() {
pfcpServer := server.New("localhost:8805")
pfcpServer.HeartbeatRequest(HandleHeartbeatRequest)
pfcpServer.Run()
go pfcpServer.Run()
}

func HandleHeartbeatRequest(sequenceNumber uint32, msg messages.HeartbeatRequest) {
Expand Down
173 changes: 33 additions & 140 deletions client/client.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package client

import (
"fmt"
"log"

"github.com/dot-5g/pfcp/ie"
"github.com/dot-5g/pfcp/messages"
"github.com/dot-5g/pfcp/network"
)
Expand All @@ -17,199 +15,94 @@ type Pfcp struct {
func New(ServerAddress string) *Pfcp {
udpClient, err := network.NewUdp(ServerAddress)
if err != nil {
log.Printf("Failed to initialize UDP client: %v\n", err)
log.Printf("Failed to initialize PFCP client: %v\n", err)
return nil
}
return &Pfcp{ServerAddress: ServerAddress, Udp: udpClient}
}

func (pfcp *Pfcp) sendPfcpMessage(header messages.PFCPHeader, elements []ie.InformationElement) error {
var payload []byte
for _, element := range elements {
payload = append(payload, element.Serialize()...)
}
message := serializeMessage(header, payload)
if err := pfcp.Udp.Send(message); err != nil {
func (pfcp *Pfcp) sendNodePfcpMessage(message messages.PFCPMessage, sequenceNumber uint32) error {
messageType := message.GetMessageType()
header := messages.NewNodePFCPHeader(messageType, sequenceNumber)
return pfcp.sendPfcpMessage(message, header)
}

func (pfcp *Pfcp) sendSessionPfcpMessage(message messages.PFCPMessage, seid uint64, sequenceNumber uint32) error {
messageType := message.GetMessageType()
header := messages.NewSessionPFCPHeader(messageType, seid, sequenceNumber)
return pfcp.sendPfcpMessage(message, header)
}

func (pfcp *Pfcp) sendPfcpMessage(message messages.PFCPMessage, header messages.PFCPHeader) error {
payload := messages.Serialize(message, header)
if err := pfcp.Udp.Send(payload); err != nil {
log.Printf("Failed to send PFCP: %v\n", err)
return err
}
log.Printf("PFCP sent successfully to %s.\n", pfcp.ServerAddress)
log.Printf("PFCP message sent successfully to %s.\n", pfcp.ServerAddress)
return nil
}

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 := messages.NewNodePFCPHeader(messages.HeartbeatRequestMessageType, sequenceNumber)

ies := []ie.InformationElement{msg.RecoveryTimeStamp}

if !msg.SourceIPAddress.IsZeroValue() {
ies = append(ies, msg.SourceIPAddress)
}

err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Heartbeat Request: %w", err)
}
return nil
return pfcp.sendNodePfcpMessage(msg, sequenceNumber)
}

func (pfcp *Pfcp) SendHeartbeatResponse(msg messages.HeartbeatResponse, sequenceNumber uint32) error {
header := messages.NewNodePFCPHeader(messages.HeartbeatResponseMessageType, sequenceNumber)
ies := []ie.InformationElement{msg.RecoveryTimeStamp}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Heartbeat Response: %w", err)
}
return nil
return pfcp.sendNodePfcpMessage(msg, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPAssociationSetupRequest(msg messages.PFCPAssociationSetupRequest, sequenceNumber uint32) error {
header := messages.NewNodePFCPHeader(messages.PFCPAssociationSetupRequestMessageType, sequenceNumber)
ies := []ie.InformationElement{msg.NodeID, msg.RecoveryTimeStamp}

if !msg.UPFunctionFeatures.IsZeroValue() {
ies = append(ies, msg.UPFunctionFeatures)
}

err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Association Setup Request: %w", err)
}
return nil
return pfcp.sendNodePfcpMessage(msg, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPAssociationSetupResponse(msg messages.PFCPAssociationSetupResponse, sequenceNumber uint32) error {
header := messages.NewNodePFCPHeader(messages.PFCPAssociationSetupResponseMessageType, sequenceNumber)
ies := []ie.InformationElement{msg.NodeID, msg.Cause, msg.RecoveryTimeStamp}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Association Setup Response: %w", err)
}
return nil
return pfcp.sendNodePfcpMessage(msg, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPAssociationUpdateRequest(msg messages.PFCPAssociationUpdateRequest, sequenceNumber uint32) error {
header := messages.NewNodePFCPHeader(messages.PFCPAssociationUpdateRequestMessageType, sequenceNumber)
ies := []ie.InformationElement{msg.NodeID}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Association Update Request: %w", err)
}
return nil
return pfcp.sendNodePfcpMessage(msg, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPAssociationUpdateResponse(msg messages.PFCPAssociationUpdateResponse, sequenceNumber uint32) error {
header := messages.NewNodePFCPHeader(messages.PFCPAssociationUpdateResponseMessageType, sequenceNumber)
ies := []ie.InformationElement{msg.NodeID, msg.Cause}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Association Update Response: %w", err)
}
return nil
return pfcp.sendNodePfcpMessage(msg, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPAssociationReleaseRequest(msg messages.PFCPAssociationReleaseRequest, sequenceNumber uint32) error {
header := messages.NewNodePFCPHeader(messages.PFCPAssociationReleaseRequestMessageType, sequenceNumber)
ies := []ie.InformationElement{msg.NodeID}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Association Release Request: %w", err)
}
return nil
return pfcp.sendNodePfcpMessage(msg, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPAssociationReleaseResponse(msg messages.PFCPAssociationReleaseResponse, sequenceNumber uint32) error {
header := messages.NewNodePFCPHeader(messages.PFCPAssociationReleaseResponseMessageType, sequenceNumber)
ies := []ie.InformationElement{msg.NodeID, msg.Cause}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Association Release Response: %w", err)
}
return nil
return pfcp.sendNodePfcpMessage(msg, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPNodeReportRequest(msg messages.PFCPNodeReportRequest, sequenceNumber uint32) error {
header := messages.NewNodePFCPHeader(messages.PFCPNodeReportRequestMessageType, sequenceNumber)
ies := []ie.InformationElement{msg.NodeID, msg.NodeReportType}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Node Report Request: %w", err)
}
return nil
return pfcp.sendNodePfcpMessage(msg, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPNodeReportResponse(msg messages.PFCPNodeReportResponse, sequenceNumber uint32) error {
header := messages.NewNodePFCPHeader(messages.PFCPNodeReportResponseMessageType, sequenceNumber)
ies := []ie.InformationElement{msg.NodeID, msg.Cause}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Node Report Response: %w", err)
}
return nil
return pfcp.sendNodePfcpMessage(msg, 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 {
return fmt.Errorf("error sending PFCP Session Establishment Request: %w", err)
}
return nil
return pfcp.sendSessionPfcpMessage(msg, seid, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPSessionEstablishmentResponse(msg messages.PFCPSessionEstablishmentResponse, seid uint64, sequenceNumber uint32) error {
header := messages.NewSessionPFCPHeader(messages.PFCPSessionEstablishmentResponseMessageType, seid, sequenceNumber)
ies := []ie.InformationElement{msg.NodeID, msg.Cause}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Session Establishment Response: %w", err)
}
return nil
return pfcp.sendSessionPfcpMessage(msg, seid, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPSessionDeletionRequest(msg messages.PFCPSessionDeletionRequest, seid uint64, sequenceNumber uint32) error {
header := messages.NewSessionPFCPHeader(messages.PFCPSessionDeletionRequestMessageType, seid, sequenceNumber)
ies := []ie.InformationElement{}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Session Deletion Request: %w", err)
}
return nil
return pfcp.sendSessionPfcpMessage(msg, seid, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPSessionDeletionResponse(msg messages.PFCPSessionDeletionResponse, seid uint64, sequenceNumber uint32) error {
header := messages.NewSessionPFCPHeader(messages.PFCPSessionDeletionResponseMessageType, seid, sequenceNumber)
ies := []ie.InformationElement{msg.Cause}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Session Deletion Response: %w", err)
}
return nil
return pfcp.sendSessionPfcpMessage(msg, seid, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPSessionReportRequest(msg messages.PFCPSessionReportRequest, seid uint64, sequenceNumber uint32) error {
header := messages.NewSessionPFCPHeader(messages.PFCPSessionReportRequestMessageType, seid, sequenceNumber)
ies := []ie.InformationElement{msg.ReportType}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Session Report Request: %w", err)
}
return nil
return pfcp.sendSessionPfcpMessage(msg, seid, sequenceNumber)
}

func (pfcp *Pfcp) SendPFCPSessionReportResponse(msg messages.PFCPSessionReportResponse, seid uint64, sequenceNumber uint32) error {
header := messages.NewSessionPFCPHeader(messages.PFCPSessionReportResponseMessageType, seid, sequenceNumber)
ies := []ie.InformationElement{msg.Cause}
err := pfcp.sendPfcpMessage(header, ies)
if err != nil {
return fmt.Errorf("error sending PFCP Session Report Response: %w", err)
}
return nil
return pfcp.sendSessionPfcpMessage(msg, seid, sequenceNumber)
}
18 changes: 18 additions & 0 deletions ie/ie.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ie

import (
"bytes"
"encoding/binary"
"fmt"
)
Expand Down Expand Up @@ -28,6 +29,23 @@ const (
SourceIPAddressIEType IEType = 192
)

type IEHeader struct {
Type IEType
Length uint16
}

func (ieHeader *IEHeader) Serialize() []byte {
buf := new(bytes.Buffer)

// Octets 1 to 2: Type
binary.Write(buf, binary.BigEndian, uint16(ieHeader.Type))

// Octets 3 to 4: Length
binary.Write(buf, binary.BigEndian, uint16(ieHeader.Length))

return buf.Bytes()
}

type InformationElement interface {
Serialize() []byte
IsZeroValue() bool
Expand Down
23 changes: 2 additions & 21 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,20 @@ package main

import (
"fmt"
"log"
"time"

"github.com/dot-5g/pfcp/client"
"github.com/dot-5g/pfcp/ie"
"github.com/dot-5g/pfcp/messages"
"github.com/dot-5g/pfcp/server"
)

func main() {
pfcpClient := client.New("1.2.3.4:8805")
recoveryTimeStamp, err := ie.NewRecoveryTimeStamp(time.Now())

if err != nil {
log.Fatalf("Error creating Recovery TimeStamp: %v", err)
}

sequenceNumber := uint32(21)
heartbeatRequestMsg := messages.HeartbeatRequest{
RecoveryTimeStamp: recoveryTimeStamp,
}

err = pfcpClient.SendHeartbeatRequest(heartbeatRequestMsg, sequenceNumber)
if err != nil {
log.Fatalf("SendHeartbeatRequest failed: %v", err)
}
RunServer()
}

func RunServer() {
pfcpServer := server.New("localhost:8805")
pfcpServer.HeartbeatRequest(HandleHeartbeatRequest)
pfcpServer.HeartbeatResponse(HandleHeartbeatResponse)
pfcpServer.Run()
go pfcpServer.Run()
}

func HandleHeartbeatRequest(sequenceNumber uint32, msg messages.HeartbeatRequest) {
Expand Down
28 changes: 28 additions & 0 deletions messages/heartbeat.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,34 @@ type HeartbeatResponse struct {
RecoveryTimeStamp ie.RecoveryTimeStamp // Mandatory
}

func (msg HeartbeatRequest) GetIEs() []ie.InformationElement {
ies := []ie.InformationElement{msg.RecoveryTimeStamp}
if !msg.SourceIPAddress.IsZeroValue() {
ies = append(ies, msg.SourceIPAddress)
}
return ies
}

func (msg HeartbeatResponse) GetIEs() []ie.InformationElement {
return []ie.InformationElement{msg.RecoveryTimeStamp}
}

func (msg HeartbeatRequest) GetMessageType() MessageType {
return HeartbeatRequestMessageType
}

func (msg HeartbeatResponse) GetMessageType() MessageType {
return HeartbeatResponseMessageType
}

func (msg HeartbeatRequest) GetMessageTypeString() string {
return "Heartbeat Request"
}

func (msg HeartbeatResponse) GetMessageTypeString() string {
return "Heartbeat Response"
}

func DeserializeHeartbeatRequest(data []byte) (PFCPMessage, error) {
ies, err := ie.ParseInformationElements(data)
var recoveryTimeStamp ie.RecoveryTimeStamp
Expand Down
Loading

0 comments on commit 807650a

Please sign in to comment.