Skip to content

Commit

Permalink
feat: report URR on deleting of PDR (#571)
Browse files Browse the repository at this point in the history
Co-authored-by: pirog-spb <[email protected]>
  • Loading branch information
pirog-spb and pirog-spb authored Sep 22, 2024
1 parent 19593cf commit 649c5d1
Show file tree
Hide file tree
Showing 12 changed files with 240 additions and 33 deletions.
4 changes: 4 additions & 0 deletions cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type UpfConfig struct {
GtpEchoInterval uint32 `mapstructure:"gtp_echo_interval" validate:"min=1" json:"gtp_echo_interval"`
QerMapSize uint32 `mapstructure:"qer_map_size" validate:"min=1" json:"qer_map_size"`
FarMapSize uint32 `mapstructure:"far_map_size" validate:"min=1" json:"far_map_size"`
UrrMapSize uint32 `mapstructure:"urr_map_size" validate:"min=1" json:"urr_map_size"`
PdrMapSize uint32 `mapstructure:"pdr_map_size" validate:"min=1" json:"pdr_map_size"`
EbpfMapResize bool `mapstructure:"resize_ebpf_maps" json:"resize_ebpf_maps"`
HeartbeatRetries uint32 `mapstructure:"heartbeat_retries" json:"heartbeat_retries"`
Expand All @@ -50,6 +51,7 @@ func init() {
pflag.Uint32("echo", 10, "Interval of sending echo requests in seconds")
pflag.Uint32("qersize", 1024, "Size of the QER ebpf map")
pflag.Uint32("farsize", 1024, "Size of the FAR ebpf map")
pflag.Uint32("urrsize", 1024, "Size of the URR ebpf map")
pflag.Uint32("pdrsize", 1024, "Size of the PDR ebpf map")
pflag.Bool("mapresize", false, "Enable or disable ebpf map resizing")
pflag.Uint32("hbretries", 3, "Number of heartbeat retries")
Expand Down Expand Up @@ -78,6 +80,7 @@ func init() {
_ = v.BindPFlag("gtp_echo_interval", pflag.Lookup("echo"))
_ = v.BindPFlag("qer_map_size", pflag.Lookup("qersize"))
_ = v.BindPFlag("far_map_size", pflag.Lookup("farsize"))
_ = v.BindPFlag("urr_map_size", pflag.Lookup("urrsize"))
_ = v.BindPFlag("pdr_map_size", pflag.Lookup("pdrsize"))
_ = v.BindPFlag("resize_ebpf_maps", pflag.Lookup("mapresize"))
_ = v.BindPFlag("heartbeat_retries", pflag.Lookup("hbretries"))
Expand All @@ -100,6 +103,7 @@ func init() {
v.SetDefault("gtp_echo_interval", 10)
v.SetDefault("qer_map_size", 1024)
v.SetDefault("far_map_size", 1024)
v.SetDefault("urr_map_size", 1024)
v.SetDefault("pdr_map_size", 1024)
v.SetDefault("resize_ebpf_maps", false)
v.SetDefault("heartbeat_retries", 3)
Expand Down
5 changes: 3 additions & 2 deletions cmd/core/ie_overwrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
)

type MapOperationsMock struct {
urr ebpf.UrrInfo
}

func (mapOps *MapOperationsMock) PutPdrUplink(teid uint32, pdrInfo ebpf.PdrInfo) error {
Expand Down Expand Up @@ -68,8 +69,8 @@ func (mapOps *MapOperationsMock) UpdateUrr(internalId uint32, urrInfo ebpf.UrrIn
return nil
}

func (mapOps *MapOperationsMock) DeleteUrr(internalId uint32) error {
return nil
func (mapOps *MapOperationsMock) DeleteUrr(internalId uint32) (error, ebpf.UrrInfo) {
return nil, mapOps.urr
}

func TestSessionOverwrite(t *testing.T) {
Expand Down
51 changes: 51 additions & 0 deletions cmd/core/pdr_creation_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,43 @@ func NewPDRCreationContext(session *Session, resourceManager *service.ResourceMa
}
}

func GetURRIDs(i *ie.IE) ([]uint32, error) {

var urrs []uint32

switch i.Type {
case ie.CreatePDR:
ies, err := i.CreatePDR()
if err != nil {
return urrs, err
}
for _, x := range ies {
if x.Type == ie.URRID {
if value, err := x.URRID(); err == nil {
urrs = append(urrs, value)
}
}
}
return urrs, nil

case ie.UpdatePDR:
ies, err := i.UpdatePDR()
if err != nil {
return urrs, err
}
for _, x := range ies {
if x.Type == ie.URRID {
if value, err := x.URRID(); err == nil {
urrs = append(urrs, value)
}
}
}
return urrs, nil
default:
return urrs, &ie.InvalidTypeError{Type: i.Type}
}
}

func (pdrContext *PDRCreationContext) extractPDR(pdr *ie.IE, spdrInfo *SPDRInfo) error {
if outerHeaderRemoval, err := pdr.OuterHeaderRemovalDescription(); err == nil {
spdrInfo.PdrInfo.OuterHeaderRemoval = outerHeaderRemoval
Expand All @@ -37,6 +74,16 @@ func (pdrContext *PDRCreationContext) extractPDR(pdr *ie.IE, spdrInfo *SPDRInfo)
spdrInfo.PdrInfo.QerId = pdrContext.getQERID(qerid)
}

if urrs, err := GetURRIDs(pdr); err == nil {
if len(urrs) > 0 {
spdrInfo.PdrInfo.Urr1Id = pdrContext.getURRID(urrs[0])
}

if len(urrs) > 1 {
spdrInfo.PdrInfo.Urr2Id = pdrContext.getURRID(urrs[1])
}
}

pdi, err := pdr.PDI()
if err != nil {
return fmt.Errorf("PDI IE is missing")
Expand Down Expand Up @@ -137,6 +184,10 @@ func (pdrContext *PDRCreationContext) getQERID(qerid uint32) uint32 {
return pdrContext.Session.GetQer(qerid).GlobalId
}

func (pdrContext *PDRCreationContext) getURRID(urrid uint32) uint32 {
return pdrContext.Session.GetUrr(urrid).GlobalId
}

func (pdrContext *PDRCreationContext) getFTEID(seID uint64, pdrID uint32) (uint32, error) {
if pdrContext.ResourceManager == nil || pdrContext.ResourceManager.FTEIDM == nil {
return 0, errors.New("FTEID manager is nil")
Expand Down
42 changes: 30 additions & 12 deletions cmd/core/pfcp_session_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/binary"
"fmt"
"net"
"time"

"github.com/edgecomllc/eupf/cmd/ebpf"

Expand Down Expand Up @@ -178,15 +179,20 @@ func HandlePfcpSessionDeletionRequest(conn *PfcpConnection, msg message.Message,
return message.NewSessionDeletionResponse(0, 0, 0, req.Sequence(), 0, newIeNodeID(conn.nodeId), ie.NewCause(ie.CauseRuleCreationModificationFailure)), err
}
}
for id := range session.URRs {
for id, urr := range session.URRs {
err, urrInfo := mapOperations.DeleteUrr(id)
if err != nil {
log.Info().Msgf("WARN: mapOperations failed to delete URR: %d, %s", id, err.Error())
continue
}
urr.ReportSeqNumber = urr.ReportSeqNumber + 1
deletedURRs = append(deletedURRs, ie.NewUsageReportWithinSessionDeletionResponse(
ie.NewURRID(id),
// TODO: add getting actual values from ebpf.UrrInfo
ie.NewVolumeMeasurement(0x3f, 1, 0, 0, 0, 0, 0),
ie.NewURSEQN(urr.ReportSeqNumber),
ie.NewUsageReportTrigger([]uint8{0, 1 << 3, 0}...),
ie.NewEndTime(time.Now()),
ie.NewVolumeMeasurement(0x7, urrInfo.UplinkVolume+urrInfo.DownlinkVolume, urrInfo.UplinkVolume, urrInfo.DownlinkVolume, 0, 0, 0),
))
if err := mapOperations.DeleteUrr(id); err != nil {
log.Info().Msgf("WARN: mapOperations failed to delete URR: %d, %s", id, err.Error())
}
}

additionalIEs := []*ie.IE{
Expand Down Expand Up @@ -375,15 +381,21 @@ func HandlePfcpSessionModificationRequest(conn *PfcpConnection, msg message.Mess
}
log.Info().Msgf("Removing URR ID: %d", urrId)
sUrrInfo := session.RemoveUrr(urrId)

err, urrInfo := mapOperations.DeleteUrr(sUrrInfo.GlobalId)
if err != nil {
log.Warn().Msgf("Can't remove URR: %s", err.Error())
continue
}

sUrrInfo.ReportSeqNumber = sUrrInfo.ReportSeqNumber + 1
removedURRs = append(removedURRs, ie.NewUsageReportWithinSessionModificationResponse(
ie.NewURRID(urrId),
// TODO: add getting actual values from ebpf.UrrInfo
ie.NewVolumeMeasurement(0x3f, 1, 0, 0, 0, 0, 0),
ie.NewURSEQN(sUrrInfo.ReportSeqNumber),
ie.NewUsageReportTrigger([]uint8{0, 1 << 3, 0}...),
ie.NewEndTime(time.Now()),
ie.NewVolumeMeasurement(0x7, urrInfo.UplinkVolume+urrInfo.DownlinkVolume, urrInfo.UplinkVolume, urrInfo.DownlinkVolume, 0, 0, 0),
))
if err := mapOperations.DeleteUrr(sUrrInfo.GlobalId); err != nil {
log.Info().Msgf("Can't remove URR: %s", err.Error())
return err
}
}

for _, pdr := range req.CreatePDR {
Expand Down Expand Up @@ -616,4 +628,10 @@ func GetTransportLevelMarking(far *ie.IE) (uint16, error) {

// TODO: add making or updating UrrInfo
func updateUrr(urrInfo *ebpf.UrrInfo, urr *ie.IE) {

// if urr.HasVOLUM() {
// }

// if volumeThreshold, err := urr.VolumeThreshold(); err == nil {
// }
}
69 changes: 61 additions & 8 deletions cmd/core/pfcp_session_handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/edgecomllc/eupf/cmd/config"
"github.com/edgecomllc/eupf/cmd/core/service"
"github.com/edgecomllc/eupf/cmd/ebpf"
"github.com/rs/zerolog/log"

"github.com/wmnsk/go-pfcp/ie"
Expand Down Expand Up @@ -73,7 +74,10 @@ func TestAssociationSetup(t *testing.T) {
}

func PreparePfcpConnection(t *testing.T) (PfcpConnection, string) {
mapOps := MapOperationsMock{}
return PreparePfcpConnectionWithMock(t, &MapOperationsMock{})
}

func PreparePfcpConnectionWithMock(t *testing.T, ebpfMock ebpf.ForwardingPlaneController) (PfcpConnection, string) {

var pfcpHandlers = PfcpHandlerMap{
message.MsgTypeHeartbeatRequest: HandlePfcpHeartbeatRequest,
Expand All @@ -91,7 +95,7 @@ func PreparePfcpConnection(t *testing.T) (PfcpConnection, string) {
pfcpConn := PfcpConnection{
NodeAssociations: make(map[string]*NodeAssociation),
nodeId: "test-node",
mapOperations: &mapOps,
mapOperations: ebpfMock,
pfcpHandlerMap: pfcpHandlers,
n3Address: net.ParseIP("1.2.3.4"),
associationMutex: &sync.Mutex{},
Expand Down Expand Up @@ -570,7 +574,8 @@ func TestHandlePfcpSessionEstablishmentRequestWithURR(t *testing.T) {
}

func TestHandlePfcpSessionModificationRequestWithURR(t *testing.T) {
pfcpConn, smfIP := PreparePfcpConnection(t)
ebpfMock := &MapOperationsMock{}
pfcpConn, smfIP := PreparePfcpConnectionWithMock(t, ebpfMock)

estReq := message.NewSessionEstablishmentRequest(0, 0, 2, 1, 0,
ie.NewNodeID("", "", "test"),
Expand Down Expand Up @@ -618,6 +623,9 @@ func TestHandlePfcpSessionModificationRequestWithURR(t *testing.T) {
ie.NewURRID(0xf),
),
)

ebpfMock.urr.UplinkVolume = 1234
ebpfMock.urr.DownlinkVolume = 5678
msg, err := HandlePfcpSessionModificationRequest(&pfcpConn, modReq, smfIP)
if err != nil {
t.Errorf("Error handling session modification request: %s", err)
Expand All @@ -635,8 +643,28 @@ func TestHandlePfcpSessionModificationRequestWithURR(t *testing.T) {
}

vol, _ := ur.VolumeMeasurement()
if vol.TotalVolume == 0 {
t.Errorf("TotalVolume equal 0")
if !vol.HasTOVOL() {
t.Errorf("No TotalVolume")
}

if !vol.HasULVOL() {
t.Errorf("No UplinkVolume")
}

if !vol.HasDLVOL() {
t.Errorf("No DownlinkVolume")
}

if vol.UplinkVolume != ebpfMock.urr.UplinkVolume {
t.Errorf("TotalVolume equals %d", vol.UplinkVolume)
}

if vol.DownlinkVolume != ebpfMock.urr.DownlinkVolume {
t.Errorf("TotalVolume equals %d", vol.DownlinkVolume)
}

if vol.TotalVolume != ebpfMock.urr.UplinkVolume+ebpfMock.urr.DownlinkVolume {
t.Errorf("TotalVolume equals %d", vol.TotalVolume)
}

if _, exists := pfcpConn.NodeAssociations[smfIP].Sessions[2].URRs[0xf]; exists {
Expand All @@ -645,7 +673,9 @@ func TestHandlePfcpSessionModificationRequestWithURR(t *testing.T) {
}

func TestHandlePfcpSessionDeletionRequestWithURR(t *testing.T) {
pfcpConn, smfIP := PreparePfcpConnection(t)

ebpfMock := &MapOperationsMock{}
pfcpConn, smfIP := PreparePfcpConnectionWithMock(t, ebpfMock)

estReq := message.NewSessionEstablishmentRequest(0, 0, 2, 1, 0,
ie.NewNodeID("", "", "test"),
Expand All @@ -662,6 +692,8 @@ func TestHandlePfcpSessionDeletionRequestWithURR(t *testing.T) {
t.Errorf("Error handling session establishment request: %s", err)
}

ebpfMock.urr.UplinkVolume = 100
ebpfMock.urr.DownlinkVolume = 200
delReq := message.NewSessionDeletionRequest(0, 0, 2, 1, 0)
msg, err := HandlePfcpSessionDeletionRequest(&pfcpConn, delReq, smfIP)
if err != nil {
Expand All @@ -680,7 +712,28 @@ func TestHandlePfcpSessionDeletionRequestWithURR(t *testing.T) {
}

vol, _ := ur.VolumeMeasurement()
if vol.TotalVolume == 0 {
t.Errorf("TotalVolume equal 0")

if !vol.HasTOVOL() {
t.Errorf("No TotalVolume")
}

if !vol.HasULVOL() {
t.Errorf("No UplinkVolume")
}

if !vol.HasDLVOL() {
t.Errorf("No DownlinkVolume")
}

if vol.UplinkVolume != ebpfMock.urr.UplinkVolume {
t.Errorf("TotalVolume equals %d", vol.UplinkVolume)
}

if vol.DownlinkVolume != ebpfMock.urr.DownlinkVolume {
t.Errorf("TotalVolume equals %d", vol.DownlinkVolume)
}

if vol.TotalVolume != ebpfMock.urr.UplinkVolume+ebpfMock.urr.DownlinkVolume {
t.Errorf("TotalVolume equals %d", vol.TotalVolume)
}
}
5 changes: 3 additions & 2 deletions cmd/core/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ type SQerInfo struct {
}

type SUrrInfo struct {
UrrInfo ebpf.UrrInfo
GlobalId uint32
UrrInfo ebpf.UrrInfo
GlobalId uint32
ReportSeqNumber uint32
}

func (s *Session) NewFar(id uint32, internalId uint32, farInfo ebpf.FarInfo) {
Expand Down
2 changes: 2 additions & 0 deletions cmd/ebpf/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ type BpfObjects struct {

FarIdTracker *IdTracker
QerIdTracker *IdTracker
UrrIdTracker *IdTracker
}

func NewBpfObjects() *BpfObjects {
return &BpfObjects{
FarIdTracker: NewIdTracker(config.Conf.FarMapSize),
QerIdTracker: NewIdTracker(config.Conf.QerMapSize),
UrrIdTracker: NewIdTracker(config.Conf.UrrMapSize),
}
}

Expand Down
Loading

0 comments on commit 649c5d1

Please sign in to comment.