Skip to content

Commit

Permalink
feat: request UPF to allocate F-TEID (#334)
Browse files Browse the repository at this point in the history
* feat: request upf to allocate f-teid

Signed-off-by: Guillaume Belanger <[email protected]>

* fix: also implement for downlink pdr

Signed-off-by: Guillaume Belanger <[email protected]>

* fix: set fteid with downlink tunnel

Signed-off-by: Guillaume Belanger <[email protected]>

* fix: write f-teid to proper variable

Signed-off-by: Guillaume Belanger <[email protected]>

* chore: add unit tests

Signed-off-by: Guillaume Belanger <[email protected]>

* chore: add copyright info

Signed-off-by: Guillaume Belanger <[email protected]>

* chore: bump version

Signed-off-by: Guillaume Belanger <[email protected]>

* chore: use different ports to avoid conflicts

Signed-off-by: Guillaume Belanger <[email protected]>

* chore: re-add newline to version file

Signed-off-by: Guillaume Belanger <[email protected]>

* feat: store upf generated f-teid when using pfcp adapter

Signed-off-by: Guillaume Belanger <[email protected]>

* chore: bump go version to v1.23

Signed-off-by: Guillaume Belanger <[email protected]>

* chore: add missing lock statement

Signed-off-by: Guillaume Belanger <[email protected]>

* chore: defer mutex unlock right away

Signed-off-by: Guillaume Belanger <[email protected]>

---------

Signed-off-by: Guillaume Belanger <[email protected]>
  • Loading branch information
gruyaume authored Nov 28, 2024
1 parent 7cc3adb commit ec30f3e
Show file tree
Hide file tree
Showing 10 changed files with 356 additions and 552 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.7.1-dev
2.0.0
8 changes: 0 additions & 8 deletions context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ const (
var smfContext SMFContext

type DrsmCtxts struct {
TeidPool drsm.DrsmInterface
SeidPool drsm.DrsmInterface
UeIpPool drsm.DrsmInterface
}
Expand Down Expand Up @@ -436,13 +435,6 @@ func (smfCtxt *SMFContext) InitDrsm() error {
return err
}

// for local FTEID
if drsmCtxt, err := drsm.InitDRSM("fteid", podId, db, opt); err == nil {
smfCtxt.DrsmCtxts.TeidPool = drsmCtxt
} else {
return err
}

// for IP-Addr
// TODO, use UPF based allocation for now

Expand Down
111 changes: 10 additions & 101 deletions context/datapath.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"strconv"

"github.com/omec-project/openapi/models"
"github.com/omec-project/smf/factory"
"github.com/omec-project/smf/logger"
"github.com/omec-project/smf/qos"
"github.com/omec-project/smf/util"
Expand Down Expand Up @@ -154,23 +153,6 @@ func (node *DataPathNode) ActivateUpLinkTunnel(smContext *SMContext) error {
return err
}

var teid uint32
var teidErr error

if factory.SmfConfig.Configuration.EnableDbStore {
var tmp int32
tmp, teidErr = smfContext.DrsmCtxts.TeidPool.AllocateInt32ID()
teid = uint32(tmp)
} else {
teid, teidErr = destUPF.GenerateTEID()
}
if teidErr != nil {
logger.CtxLog.Errorf("generate uplink TEID fail: %s", teidErr)
return teidErr
} else {
node.UpLinkTunnel.TEID = teid
}

return nil
}

Expand Down Expand Up @@ -213,24 +195,6 @@ func (node *DataPathNode) ActivateDownLinkTunnel(smContext *SMContext) error {
return err
}

// Generate TEID for Tunnel
var teid uint32
var teidErr error

if factory.SmfConfig.Configuration.EnableDbStore {
var tmp int32
tmp, teidErr = smfContext.DrsmCtxts.TeidPool.AllocateInt32ID()
teid = uint32(tmp)
} else {
teid, teidErr = destUPF.GenerateTEID()
}
if teidErr != nil {
logger.CtxLog.Errorf("generate downlink TEID fail: %s", teidErr)
return teidErr
} else {
node.DownLinkTunnel.TEID = teid
}

return nil
}

Expand Down Expand Up @@ -274,17 +238,6 @@ func (node *DataPathNode) DeactivateUpLinkTunnel(smContext *SMContext) {
}
}
}

teid := node.DownLinkTunnel.TEID
var err error
if factory.SmfConfig.Configuration.EnableDbStore {
err = smfContext.DrsmCtxts.TeidPool.ReleaseInt32ID(int32(teid))
} else {
node.UPF.teidGenerator.FreeID(int64(teid))
}
if err != nil {
logger.CtxLog.Errorln("deactivated UpLinkTunnel", err)
}
node.DownLinkTunnel = &GTPTunnel{}
}

Expand Down Expand Up @@ -328,17 +281,6 @@ func (node *DataPathNode) DeactivateDownLinkTunnel(smContext *SMContext) {
}
}
}

teid := node.DownLinkTunnel.TEID
var err error
if factory.SmfConfig.Configuration.EnableDbStore {
err = smfContext.DrsmCtxts.TeidPool.ReleaseInt32ID(int32(teid))
} else {
node.UPF.teidGenerator.FreeID(int64(teid))
}
if err != nil {
logger.CtxLog.Errorln("deactivated DownLinkTunnel", err)
}
node.DownLinkTunnel = &GTPTunnel{}
}

Expand Down Expand Up @@ -534,37 +476,19 @@ func (dpNode *DataPathNode) ActivateUpLinkPdr(smContext *SMContext, defQER *QER,

curULTunnel := dpNode.UpLinkTunnel
for name, ULPDR := range curULTunnel.PDR {
ULDestUPF := curULTunnel.DestEndPoint.UPF
ULPDR.QER = append(ULPDR.QER, defQER)

// Set Default precedence
if ULPDR.Precedence == 0 {
ULPDR.Precedence = defPrecedence
}

var iface *UPFInterfaceInfo
if dpNode.IsANUPF() {
iface = ULDestUPF.GetInterface(models.UpInterfaceType_N3, smContext.Dnn)
} else {
iface = ULDestUPF.GetInterface(models.UpInterfaceType_N9, smContext.Dnn)
ULPDR.PDI.SourceInterface = SourceInterface{InterfaceValue: SourceInterfaceAccess}
ULPDR.PDI.LocalFTeid = &FTEID{
Ch: true,
}

if upIP, err := iface.IP(smContext.SelectedPDUSessionType); err != nil {
logger.CtxLog.Errorf("activate UpLink PDR[%v] failed %v", name, err)
return err
} else {
ULPDR.PDI.SourceInterface = SourceInterface{InterfaceValue: SourceInterfaceAccess}
ULPDR.PDI.LocalFTeid = &FTEID{
V4: true,
Ipv4Address: upIP,
Teid: curULTunnel.TEID,
}

ULPDR.PDI.UEIPAddress = &ueIpAddr

ULPDR.PDI.NetworkInstance = util_3gpp.Dnn(smContext.Dnn)
}

ULPDR.PDI.UEIPAddress = &ueIpAddr
ULPDR.PDI.NetworkInstance = util_3gpp.Dnn(smContext.Dnn)
ULPDR.OuterHeaderRemoval = &OuterHeaderRemoval{
OuterHeaderRemovalDescription: OuterHeaderRemovalGtpUUdpIpv4,
}
Expand All @@ -591,7 +515,7 @@ func (dpNode *DataPathNode) ActivateUpLinkPdr(smContext *SMContext, defQER *QER,

if nextULDest := dpNode.Next(); nextULDest != nil {
nextULTunnel := nextULDest.UpLinkTunnel
iface = nextULTunnel.DestEndPoint.UPF.GetInterface(models.UpInterfaceType_N9, smContext.Dnn)
iface := nextULTunnel.DestEndPoint.UPF.GetInterface(models.UpInterfaceType_N9, smContext.Dnn)

if upIP, err := iface.IP(smContext.SelectedPDUSessionType); err != nil {
logger.CtxLog.Errorf("activate UpLink PDR[%v] failed %v", name, err)
Expand Down Expand Up @@ -624,36 +548,21 @@ func (dpNode *DataPathNode) ActivateDlLinkPdr(smContext *SMContext, defQER *QER,

for name, DLPDR := range curDLTunnel.PDR {
logger.CtxLog.Infof("activate Downlink PDR[%v]:[%v]", name, DLPDR)
DLDestUPF := curDLTunnel.DestEndPoint.UPF
DLPDR.QER = append(DLPDR.QER, defQER)

if DLPDR.Precedence == 0 {
DLPDR.Precedence = defPrecedence
}

if dpNode.IsAnchorUPF() {
DLPDR.PDI.UEIPAddress = &ueIpAddr
} else {
if !dpNode.IsAnchorUPF() {
DLPDR.OuterHeaderRemoval = &OuterHeaderRemoval{
OuterHeaderRemovalDescription: OuterHeaderRemovalGtpUUdpIpv4,
}

iface = DLDestUPF.GetInterface(models.UpInterfaceType_N9, smContext.Dnn)
if upIP, err := iface.IP(smContext.SelectedPDUSessionType); err != nil {
logger.CtxLog.Errorf("activate Downlink PDR[%v] failed %v", name, err)
return err
} else {
DLPDR.PDI.SourceInterface = SourceInterface{InterfaceValue: SourceInterfaceCore}
DLPDR.PDI.LocalFTeid = &FTEID{
V4: true,
Ipv4Address: upIP,
Teid: curDLTunnel.TEID,
}

DLPDR.PDI.UEIPAddress = &ueIpAddr
}
}

DLPDR.PDI.SourceInterface = SourceInterface{InterfaceValue: SourceInterfaceCore}
DLPDR.PDI.UEIPAddress = &ueIpAddr

DLFAR := DLPDR.FAR

logger.PduSessLog.Debugln("current DP Node IP:", dpNode.UPF.NodeID.ResolveNodeIdToIp().String())
Expand Down
126 changes: 126 additions & 0 deletions context/datapath_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright 2024 Canonical Ltd.
//
// SPDX-License-Identifier: Apache-2.0

package context_test

import (
"net"
"testing"

"github.com/omec-project/smf/context"
)

func TestActivateUpLinkPdr(t *testing.T) {
smContext := &context.SMContext{
PDUAddress: &context.UeIpAddr{
Ip: net.IPv4(192, 168, 1, 1),
},
Dnn: "internet",
}

defQER := &context.QER{}

dpNode := &context.DataPathNode{
UPF: &context.UPF{},
UpLinkTunnel: &context.GTPTunnel{
PDR: map[string]*context.PDR{
"default": {
Precedence: 0,
FAR: &context.FAR{},
},
},
},
}

err := dpNode.ActivateUpLinkPdr(smContext, defQER, 10)
if err != nil {
t.Errorf("expected no error, got %v", err)
}

pdr := dpNode.UpLinkTunnel.PDR["default"]
if pdr == nil {
t.Fatalf("expected pdr to be not nil")
}

if pdr.PDI.SourceInterface.InterfaceValue != context.SourceInterfaceAccess {
t.Errorf("expected SourceInterface to be %v, got %v", context.SourceInterfaceAccess, pdr.PDI.SourceInterface.InterfaceValue)
}
if pdr.PDI.LocalFTeid == nil {
t.Errorf("expected pdr.PDI.LocalFTeid to be not nil")
}
if !pdr.PDI.LocalFTeid.Ch {
t.Errorf("expected pdr.PDI.LocalFTeid.Ch to be true")
}
if pdr.PDI.UEIPAddress == nil {
t.Errorf("expected pdr.PDI.UEIPAddress to be not nil")
}
if !pdr.PDI.UEIPAddress.V4 {
t.Errorf("expected pdr.PDI.UEIPAddress.V4 to be true")
}
if !pdr.PDI.UEIPAddress.Ipv4Address.Equal(net.IP{192, 168, 1, 1}) {
t.Errorf("expected pdr.PDI.UEIPAddress.Ipv4Address to be %v, got %v", net.IP{192, 168, 1, 1}, pdr.PDI.UEIPAddress.Ipv4Address)
}
if string(pdr.PDI.NetworkInstance) != "internet" {
t.Errorf("expected pdr.PDI.NetworkInstance to be 'internet', got %v", string(pdr.PDI.NetworkInstance))
}
}

func TestActivateDlLinkPdr(t *testing.T) {
smContext := &context.SMContext{
PDUAddress: &context.UeIpAddr{
Ip: net.IP{192, 168, 1, 1},
},
Dnn: "internet",
Tunnel: &context.UPTunnel{
ANInformation: struct {
IPAddress net.IP
TEID uint32
}{
IPAddress: net.IP{10, 0, 0, 1},
TEID: 12345,
},
},
}

defQER := &context.QER{}

dpNode := &context.DataPathNode{
UPF: &context.UPF{},
DownLinkTunnel: &context.GTPTunnel{
PDR: map[string]*context.PDR{
"default": {
Precedence: 0,
FAR: &context.FAR{},
},
},
},
}

dataPath := &context.DataPath{
FirstDPNode: dpNode,
}

err := dpNode.ActivateDlLinkPdr(smContext, defQER, 10, dataPath)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}

pdr := dpNode.DownLinkTunnel.PDR["default"]
if pdr == nil {
t.Fatalf("expected pdr to be not nil")
}

if pdr.PDI.SourceInterface.InterfaceValue != context.SourceInterfaceCore {
t.Errorf("expected SourceInterface to be %v, got %v", context.SourceInterfaceCore, pdr.PDI.SourceInterface.InterfaceValue)
}
if pdr.PDI.UEIPAddress == nil {
t.Errorf("expected pdr.PDI.UEIPAddress to be not nil")
}
if !pdr.PDI.UEIPAddress.V4 {
t.Errorf("expected pdr.PDI.UEIPAddress.V4 to be true")
}
if !pdr.PDI.UEIPAddress.Ipv4Address.Equal(net.IP{192, 168, 1, 1}) {
t.Errorf("expected pdr.PDI.UEIPAddress.Ipv4Address to be %v, got %v", net.IP{192, 168, 1, 1}, pdr.PDI.UEIPAddress.Ipv4Address)
}
}
Loading

0 comments on commit ec30f3e

Please sign in to comment.