Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: request UPF to allocate F-TEID #334

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const (
var smfContext SMFContext

type DrsmCtxts struct {
TeidPool drsm.DrsmInterface
SeidPool drsm.DrsmInterface
UeIpPool drsm.DrsmInterface
}
Expand Down Expand Up @@ -439,13 +438,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
112 changes: 11 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,22 @@ 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
DLPDR.PDI.UEIPAddress = &ueIpAddr

DLFAR := DLPDR.FAR

logger.PduSessLog.Debugln("current DP Node IP:", dpNode.UPF.NodeID.ResolveNodeIdToIp().String())
Expand Down
58 changes: 0 additions & 58 deletions context/upf.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"fmt"
"math"
"net"
"os"
"reflect"
"strconv"
"sync"
Expand All @@ -23,7 +22,6 @@ import (
"github.com/omec-project/smf/factory"
"github.com/omec-project/smf/logger"
"github.com/omec-project/util/idgenerator"
"github.com/omec-project/util/util_3gpp"
)

var upfPool sync.Map
Expand Down Expand Up @@ -62,19 +60,6 @@ type RecoveryTimeStamp struct {
RecoveryTimeStamp time.Time
}

type UserPlaneIPResourceInformation struct {
Ipv4Address net.IP
Ipv6Address net.IP
NetworkInstance util_3gpp.Dnn
Assosi bool
Assoni bool
V6 bool
V4 bool
TeidRange uint8
Teidri uint8 // 0x00011100
SourceInterface uint8 // 0x00001111
}

type UPF struct {
SNssaiInfos []SnssaiUPFInfo
N3Interfaces []UPFInterfaceInfo
Expand All @@ -91,11 +76,9 @@ type UPF struct {
barIDGenerator *idgenerator.IDGenerator
urrIDGenerator *idgenerator.IDGenerator
qerIDGenerator *idgenerator.IDGenerator
teidGenerator *idgenerator.IDGenerator

RecoveryTimeStamp RecoveryTimeStamp
NodeID NodeID
UPIPInfo UserPlaneIPResourceInformation
UPFStatus UPFStatus
uuid uuid.UUID
Port uint16
Expand Down Expand Up @@ -241,7 +224,6 @@ func NewUPF(nodeID *NodeID, ifaces []factory.InterfaceUpfInfoItem) (upf *UPF) {
upf.barIDGenerator = idgenerator.NewGenerator(1, math.MaxUint8)
upf.qerIDGenerator = idgenerator.NewGenerator(1, math.MaxUint32)
upf.urrIDGenerator = idgenerator.NewGenerator(1, math.MaxUint32)
upf.teidGenerator = idgenerator.NewGenerator(1, math.MaxUint32)

upf.N3Interfaces = make([]UPFInterfaceInfo, 0)
upf.N9Interfaces = make([]UPFInterfaceInfo, 0)
Expand Down Expand Up @@ -280,33 +262,6 @@ func (upf *UPF) GetInterface(interfaceType models.UpInterfaceType, dnn string) *
return nil
}

func (upf *UPF) GenerateTEID() (uint32, error) {
if upf.UPFStatus != AssociatedSetUpSuccess {
err := fmt.Errorf("this upf not associate with smf")
return 0, err
}

var id uint32
if tmpID, err := upf.teidGenerator.Allocate(); err != nil {
return 0, err
} else {
id = uint32(tmpID)
}

// Assuming one SMF host 5000 UEs, this code gets offset = smfCount * 5000 and generate unique TEID

smfCountStr := os.Getenv("SMF_COUNT")
smfCount, err := strconv.Atoi(smfCountStr)
if err != nil {
logger.CtxLog.Errorf("failed to convert SMF_COUNT to int: %v", err)
}

offset := (smfCount - 1) * 5000
uniqueId := id + uint32(offset)
// return id, nil
return uniqueId, nil
}

func (upf *UPF) PFCPAddr() *net.UDPAddr {
return &net.UDPAddr{
IP: upf.NodeID.ResolveNodeIdToIp(),
Expand Down Expand Up @@ -366,19 +321,6 @@ func RemoveUPFNodeByNodeID(nodeID NodeID) bool {
return false
}

func SelectUPFByDnn(Dnn string) *UPF {
var upf *UPF
upfPool.Range(func(key, value interface{}) bool {
upf = value.(*UPF)
if upf.UPIPInfo.Assoni && string(upf.UPIPInfo.NetworkInstance) == Dnn {
return false
}
upf = nil
return true
})
return upf
}

func (upf *UPF) GetUPFIP() string {
upfIP := upf.NodeID.ResolveNodeIdToIp().String()
return upfIP
Expand Down
45 changes: 0 additions & 45 deletions pfcp/adapter/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
package adapter

import (
"net"
"sync"

"github.com/omec-project/smf/context"
"github.com/omec-project/smf/logger"
"github.com/omec-project/smf/pfcp/ies"
"github.com/omec-project/smf/pfcp/udp"
"github.com/wmnsk/go-pfcp/ie"
"github.com/wmnsk/go-pfcp/message"
Expand Down Expand Up @@ -100,15 +98,6 @@ func HandlePfcpAssociationSetupResponse(msg *udp.Message) {
return
}

var userPlaneIPResourceInformation *context.UserPlaneIPResourceInformation
if len(rsp.UserPlaneIPResourceInformation) != 0 {
userPlaneIPResourceInformation, err = ies.UnmarshalUEIPInformationBinary(rsp.UserPlaneIPResourceInformation[0].Payload)
if err != nil {
logger.PfcpLog.Errorf("failed to get UserPlaneIPResourceInformation: %+v", err)
return
}
}

if causeValue == ie.CauseRequestAccepted {
logger.PfcpLog.Infof("handle PFCP Association Setup Response with NodeID[%s]", nodeID.ResolveNodeIdToIp().String())

Expand All @@ -118,15 +107,6 @@ func HandlePfcpAssociationSetupResponse(msg *udp.Message) {
return
}

// validate if DNNs served by UPF matches with the one provided by UPF
if userPlaneIPResourceInformation != nil {
upfProvidedDnn := string(userPlaneIPResourceInformation.NetworkInstance)
if !upf.IsDnnConfigured(upfProvidedDnn) {
logger.PfcpLog.Errorf("handle PFCP Association Setup Response, DNN mismatch, [%v] is not configured", upfProvidedDnn)
return
}
}

upf.UPFStatus = context.AssociatedSetUpSuccess
if rsp.RecoveryTimeStamp == nil {
logger.PfcpLog.Errorln("pfcp association setup response has no RecoveryTimeStamp")
Expand All @@ -141,31 +121,6 @@ func HandlePfcpAssociationSetupResponse(msg *udp.Message) {
RecoveryTimeStamp: recoveryTimestamp,
}
upf.NHeartBeat = 0 // reset Heartbeat attempt to 0

if rsp.UserPlaneIPResourceInformation != nil {
upf.UPIPInfo = *userPlaneIPResourceInformation

if upf.UPIPInfo.Assosi && upf.UPIPInfo.Assoni && upf.UPIPInfo.SourceInterface == ie.SrcInterfaceAccess &&
upf.UPIPInfo.V4 && !upf.UPIPInfo.Ipv4Address.Equal(net.IPv4zero) {
logger.PfcpLog.Infof("UPF[%s] received N3 interface IP[%v], network instance[%v] and TEID[%v]",
upf.NodeID.ResolveNodeIdToIp().String(), upf.UPIPInfo.Ipv4Address,
string(upf.UPIPInfo.NetworkInstance), upf.UPIPInfo.TeidRange)

// reset the N3 interface of UPF
upf.N3Interfaces = make([]context.UPFInterfaceInfo, 0)

// Insert N3 interface info from UPF
n3Interface := context.UPFInterfaceInfo{}
n3Interface.NetworkInstance = string(upf.UPIPInfo.NetworkInstance)
n3Interface.IPv4EndPointAddresses = append(n3Interface.IPv4EndPointAddresses, upf.UPIPInfo.Ipv4Address)
upf.N3Interfaces = append(upf.N3Interfaces, n3Interface)
}

logger.PfcpLog.Infof("UPF(%s)[%s] setup association",
upf.NodeID.ResolveNodeIdToIp().String(), upf.UPIPInfo.NetworkInstance)
} else {
logger.PfcpLog.Errorln("pfcp association setup response has no UserPlane IP Resource Information")
}
}
}

Expand Down
Loading