Skip to content

Commit

Permalink
ethface+ndndpdk-upf: separate ulQFI and dlQFI
Browse files Browse the repository at this point in the history
  • Loading branch information
yoursunny committed Jun 21, 2024
1 parent b35ada0 commit 269f611
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ build/bpf.done: build/build.ninja bpf/**/*.c csrc/strategyapi/* csrc/fib/enum.h
touch $@

.PHONY: cmds
cmds: build/share/bash_autocomplete build/bin/ndndpdk-ctrl build/bin/ndndpdk-godemo build/bin/ndndpdk-hrlog2histogram build/bin/ndndpdk-jrproxy build/bin/ndndpdk-svc
cmds: build/share/bash_autocomplete build/bin/ndndpdk-ctrl build/bin/ndndpdk-godemo build/bin/ndndpdk-hrlog2histogram build/bin/ndndpdk-jrproxy build/bin/ndndpdk-svc build/bin/ndndpdk-upf

build/bin/%: cmd/%/* godeps
GOBIN=$$(realpath build/bin) mk/go.sh install ./cmd/$*
Expand Down
65 changes: 53 additions & 12 deletions cmd/ndndpdk-upf/sess.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,34 @@ import (
"go.uber.org/zap"
)

const (
sessHaveUlTEID = 1 << iota
sessHaveDlTEID
sessHaveUlQFI
sessHaveDlQFI
sessHaveDlQERID
sessHavePeer
sessHaveUeIP
sessHaveAll = 0b1111111
)

var pfcpSessTable = make(map[uint64]*pfcpSess)

type pfcpSess struct {
cpSEID, upSEID uint64
ulTEID, dlTEID uint32
qfi uint8
ulQFI, dlQFI uint8
dlQERID uint32
peer, ueIP netip.Addr
have uint8
have uint32
FaceID string
}

func (sess pfcpSess) decorateLogEntry(logger *zap.Logger) *zap.Logger {
return logger.With(zap.Uint64("cp-seid", sess.cpSEID), zap.Uint64("up-seid", sess.upSEID))
}

func (sess *pfcpSess) HandleCreate(ctx context.Context, logEntry *zap.Logger, pdrs, fars []*ie.IE) {
func (sess *pfcpSess) HandleCreate(ctx context.Context, logEntry *zap.Logger, pdrs, fars, qers []*ie.IE) {
logEntry = sess.decorateLogEntry(logEntry)

for i, pdr := range pdrs {
Expand All @@ -40,12 +52,17 @@ func (sess *pfcpSess) HandleCreate(ctx context.Context, logEntry *zap.Logger, pd
logEntry.Info("createFAR error", zap.Int("index", i), zap.Error(e))
}
}
if sess.have != 0b111 {
logEntry.Debug("waiting for more updates", zap.Uint8("have", sess.have))
for i, qer := range qers {
if e := sess.createQER(qer); e != nil {
logEntry.Info("createQER error", zap.Int("index", i), zap.Error(e))
}
}
if sess.have != sessHaveAll {
logEntry.Debug("waiting for more updates", zap.Uint32("have", sess.have))
return
}

loc, e := upfCfg.MakeLocator(sess.ulTEID, sess.dlTEID, sess.qfi, sess.peer, sess.ueIP)
loc, e := upfCfg.MakeLocator(sess.ulTEID, sess.ulQFI, sess.dlTEID, sess.dlQFI, sess.peer, sess.ueIP)
if e != nil {
logEntry.Warn("cannot construct locator", zap.Error(e))
return
Expand Down Expand Up @@ -97,8 +114,8 @@ func (sess *pfcpSess) createPDRAccess(pdr *ie.IE) error {
return fmt.Errorf("QFI: %w", e)
}

sess.ulTEID, sess.qfi = fTEID.TEID, qfi
sess.have |= 0b001
sess.ulTEID, sess.ulQFI = fTEID.TEID, qfi
sess.have |= sessHaveUlTEID | sessHaveUlQFI
return nil
}

Expand All @@ -114,7 +131,14 @@ func (sess *pfcpSess) createPDRCore(pdr *ie.IE) error {
}

sess.ueIP = ip
sess.have |= 0b010
sess.have |= sessHaveUeIP

sess.dlQERID, e = pdr.QERID()
if e != nil {
return fmt.Errorf("QERID: %w", e)
}
sess.have |= sessHaveDlQERID

return nil
}

Expand Down Expand Up @@ -149,7 +173,24 @@ func (sess *pfcpSess) createFARAccess(far *ie.IE) error {

sess.dlTEID = ohc.TEID
sess.peer, _ = netip.AddrFromSlice(ohc.IPv4Address)
sess.have |= 0b100
sess.have |= sessHaveDlTEID | sessHavePeer
return nil
}

func (sess *pfcpSess) createQER(qer *ie.IE) error {
qerID, e := qer.QERID()
if e != nil {
return fmt.Errorf("QERID: %w", e)
}
if sess.have&sessHaveDlQERID == 0 || qerID != sess.dlQERID {
return nil
}

sess.dlQFI, e = qer.QFI()
if e != nil {
return fmt.Errorf("QFI: %w", e)
}
sess.have |= sessHaveDlQFI
return nil
}

Expand Down Expand Up @@ -182,7 +223,7 @@ func handleSessEstab(ctx context.Context, logEntry *zap.Logger, req *message.Ses
}
pfcpSessTable[sess.upSEID] = sess

sess.HandleCreate(ctx, logEntry, req.CreatePDR, req.CreateFAR)
sess.HandleCreate(ctx, logEntry, req.CreatePDR, req.CreateFAR, req.CreateQER)
return message.NewSessionEstablishmentResponse(
0, 0, sess.cpSEID, req.SequenceNumber, 0,
upfCfg.UpfNodeID,
Expand All @@ -200,7 +241,7 @@ func handleSessMod(ctx context.Context, logEntry *zap.Logger, req *message.Sessi
), nil
}

sess.HandleCreate(ctx, logEntry, req.CreatePDR, req.CreateFAR)
sess.HandleCreate(ctx, logEntry, req.CreatePDR, req.CreateFAR, req.CreateQER)
return message.NewSessionModificationResponse(
0, 0, sess.cpSEID, req.SequenceNumber, 0,
ie.NewCause(ie.CauseRequestAccepted),
Expand Down
5 changes: 3 additions & 2 deletions cmd/ndndpdk-upf/upfconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,15 @@ func (cfg *UpfConfig) ProcessFlags(c *cli.Context) error {
return nil
}

func (cfg UpfConfig) MakeLocator(ulTEID, dlTEID uint32, qfi uint8, peer, ueIP netip.Addr) (loc map[string]any, e error) {
func (cfg UpfConfig) MakeLocator(ulTEID uint32, ulQFI uint8, dlTEID uint32, dlQFI uint8, peer, ueIP netip.Addr) (loc map[string]any, e error) {
loc = map[string]any{
"scheme": "gtp",
"local": cfg.upfMAC,
"localIP": cfg.upfIP,
"ulTEID": ulTEID,
"ulQFI": ulQFI,
"dlTEID": dlTEID,
"qfi": qfi,
"dlQFI": dlQFI,
"innerLocalIP": cfg.dnIP,
"innerRemoteIP": ueIP,
}
Expand Down
6 changes: 3 additions & 3 deletions csrc/ethface/locator.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ EthRxMatch_Prepare(EthRxMatch* match, const EthLocator* loc) {
break;
}
case 'G': {
match->len += PutGtpHdr(BUF_TAIL, true, loc->ulTEID, loc->qfi);
match->len += PutGtpHdr(BUF_TAIL, true, loc->ulTEID, loc->ulQFI);
match->len += PutIpv4Hdr(BUF_TAIL, loc->innerLocalIP, loc->innerRemoteIP);
match->len += PutUdpHdr(BUF_TAIL, UDPPortNDN, UDPPortNDN);
match->f = MatchGtp;
Expand Down Expand Up @@ -326,7 +326,7 @@ EthXdpLocator_Prepare(EthXdpLocator* xl, const EthLocator* loc) {
}
case 'G': {
xl->teid = rte_cpu_to_be_32(loc->ulTEID);
xl->qfi = loc->qfi;
xl->qfi = loc->ulQFI;
break;
}
}
Expand Down Expand Up @@ -548,7 +548,7 @@ EthTxHdr_Prepare(EthTxHdr* hdr, const EthLocator* loc, bool hasChecksumOffloads)
break;
}
case 'G': {
hdr->len += PutGtpHdr(BUF_TAIL, false, loc->dlTEID, loc->qfi);
hdr->len += PutGtpHdr(BUF_TAIL, false, loc->dlTEID, loc->dlQFI);
hdr->len += PutIpv4Hdr(BUF_TAIL, loc->innerLocalIP, loc->innerRemoteIP);
hdr->len += PutUdpHdr(BUF_TAIL, UDPPortNDN, UDPPortNDN);
break;
Expand Down
3 changes: 2 additions & 1 deletion csrc/ethface/locator.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ typedef struct EthLocator {
uint32_t dlTEID;
uint8_t innerLocalIP[16];
uint8_t innerRemoteIP[16];
uint8_t qfi;
uint8_t ulQFI;
uint8_t dlQFI;
bool isGtp;
} EthLocator;

Expand Down
15 changes: 11 additions & 4 deletions iface/ethface/gtp.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ type GtpLocator struct {
// This must fit in 32 bits.
UlTEID int `json:"ulTEID"`

// UlQFI is the uplink/incoming QoS flow identifier.
// This must fit in 6 bits.
UlQFI int `json:"ulQFI"`

// DlTEID is the downlink/outgoing tunnel endpoint identifier.
// This must fit in 32 bits.
DlTEID int `json:"dlTEID"`

// QFI is the QoS flow identifier.
// DlQFI is the downlink/outgoing QoS flow identifier.
// This must fit in 6 bits.
QFI int `json:"qfi"`
DlQFI int `json:"dlQFI"`

// InnerLocalIP is the inner local IPv4 address.
InnerLocalIP netip.Addr `json:"innerLocalIP"`
Expand All @@ -55,9 +59,11 @@ func (loc GtpLocator) Validate() error {
switch {
case loc.UlTEID < 0, loc.UlTEID > math.MaxUint32:
return ErrTEID
case loc.UlQFI < 0, loc.UlQFI > 0b111111:
return ErrQFI
case loc.DlTEID < 0, loc.DlTEID > math.MaxUint32:
return ErrTEID
case loc.QFI < 0, loc.QFI > 0b111111:
case loc.DlQFI < 0, loc.DlQFI > 0b111111:
return ErrQFI
case !local.Is4(), local.IsMulticast(), !remote.Is4(), remote.IsMulticast():
return ErrUnicastIP
Expand All @@ -73,8 +79,9 @@ func (loc GtpLocator) EthLocatorC() (locC ethport.LocatorC) {
locC.RemoteUDP = ethport.UDPPortGTP
locC.IsGtp = true
locC.UlTEID = uint32(loc.UlTEID)
locC.UlQFI = uint8(loc.UlQFI)
locC.DlTEID = uint32(loc.DlTEID)
locC.Qfi = uint8(loc.QFI)
locC.DlQFI = uint8(loc.DlQFI)
locC.InnerLocalIP = loc.InnerLocalIP.As16()
locC.InnerRemoteIP = loc.InnerRemoteIP.As16()
return
Expand Down
24 changes: 13 additions & 11 deletions iface/ethface/locator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,16 @@ func TestLocatorCoexist(t *testing.T) {

const innerIP = `,"innerLocalIP":"192.168.60.3","innerRemoteIP":"192.168.60.4"`
conflict( // same ulTEID
`{"scheme":"gtp","ulTEID":268435464,"dlTEID":536870920,"qfi":1`+innerIP+ipA+etherA,
`{"scheme":"gtp","ulTEID":268435464,"dlTEID":536870921,"qfi":2`+innerIP+ipA+etherA,
`{"scheme":"gtp","ulTEID":268435464,"ulQFI":1,"dlTEID":536870920,"dlQFI":1`+innerIP+ipA+etherA,
`{"scheme":"gtp","ulTEID":268435464,"ulQFI":2,"dlTEID":536870921,"dlQFI":2`+innerIP+ipA+etherA,
)
conflict( // same dlTEID
`{"scheme":"gtp","ulTEID":268435464,"dlTEID":536870920,"qfi":1`+innerIP+ipA+etherA,
`{"scheme":"gtp","ulTEID":268435465,"dlTEID":536870920,"qfi":2`+innerIP+ipA+etherA,
`{"scheme":"gtp","ulTEID":268435464,"ulQFI":1,"dlTEID":536870920,"dlQFI":1`+innerIP+ipA+etherA,
`{"scheme":"gtp","ulTEID":268435465,"ulQFI":2,"dlTEID":536870920,"dlQFI":2`+innerIP+ipA+etherA,
)
coexist( // different ulTEID and dlTEID
`{"scheme":"gtp","ulTEID":268435464,"dlTEID":536870920,"qfi":1`+innerIP+ipA+etherA,
`{"scheme":"gtp","ulTEID":268435465,"dlTEID":536870921,"qfi":1`+innerIP+ipA+etherA,
`{"scheme":"gtp","ulTEID":268435464,"ulQFI":1,"dlTEID":536870920,"dlQFI":1`+innerIP+ipA+etherA,
`{"scheme":"gtp","ulTEID":268435465,"ulQFI":1,"dlTEID":536870921,"dlQFI":1`+innerIP+ipA+etherA,
)

// mixed schemes
Expand All @@ -130,7 +130,7 @@ func TestLocatorCoexist(t *testing.T) {
`{"scheme":"vxlan","vxlan":1`+innerA+ipA+etherA)
conflict( // "udpe" with "gtp", same localUDP and remoteUDP
`{"scheme":"udpe","localUDP":2152,"remoteUDP":2152`+ipA+etherA,
`{"scheme":"gtp","ulTEID":268435464,"dlTEID": 536870920,"qfi":1`+innerIP+ipA+etherA)
`{"scheme":"gtp","ulTEID":268435464,"ulQFI":1,"dlTEID": 536870920,"dlQFI":1`+innerIP+ipA+etherA)
}

func TestLocatorRxMatch(t *testing.T) {
Expand Down Expand Up @@ -207,8 +207,9 @@ func TestLocatorRxMatch(t *testing.T) {
"localIP": "192.168.37.1",
"remoteIP": "192.168.37.2",
"ulTEID": 268435464,
"ulQFI": 1,
"dlTEID": 536870920,
"qfi": 1,
"dlQFI": 11,
"innerLocalIP": "192.168.60.3",
"innerRemoteIP": "192.168.60.4"
}`)
Expand Down Expand Up @@ -388,7 +389,7 @@ func TestLocatorRxMatch(t *testing.T) {
&layers.Ethernet{SrcMAC: mac2, DstMAC: mac1, EthernetType: layers.EthernetTypeIPv4},
&layers.IPv4{Version: 4, TTL: 64, Protocol: layers.IPProtocolUDP, SrcIP: ip42, DstIP: ip41},
&layers.UDP{SrcPort: 2152, DstPort: 2152},
&GTPv1UTPDU{TEID: 0x10000008, PDUType: 1, QFI: 2},
&GTPv1UTPDU{TEID: 0x10000008, PDUType: 1, QFI: 11},
&layers.IPv4{Version: 4, TTL: 64, Protocol: layers.IPProtocolUDP, SrcIP: ip44, DstIP: ip43},
&layers.UDP{SrcPort: 6363, DstPort: 6363},
)
Expand Down Expand Up @@ -496,8 +497,9 @@ func TestLocatorTxHdr(t *testing.T) {
"localIP": "192.168.37.1",
"remoteIP": "192.168.37.2",
"ulTEID": 268435464,
"ulQFI": 1,
"dlTEID": 536870920,
"qfi": 1,
"dlQFI": 11,
"innerLocalIP": "192.168.60.3",
"innerRemoteIP": "192.168.60.4"
}`, layers.LayerTypeEthernet, layers.LayerTypeIPv4, layers.LayerTypeUDP, layers.LayerTypeGTPv1U, layers.LayerTypeIPv4, layers.LayerTypeUDP)
Expand All @@ -509,6 +511,6 @@ func TestLocatorTxHdr(t *testing.T) {
if assert.Len(gtpGTP.GTPExtensionHeaders, 1) {
gtpPSC := gtpGTP.GTPExtensionHeaders[0]
assert.EqualValues(0x85, gtpPSC.Type)
assert.Equal([]byte{0x00, 0x01}, gtpPSC.Content)
assert.Equal([]byte{0x00, 0x0B}, gtpPSC.Content)
}
}
6 changes: 3 additions & 3 deletions iface/ethface/tap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func testPortTAP(t testing.TB, makeNetifConfig func(ifname string) ethnetif.Conf
locGTP8.IPLocator = locUDP4.IPLocator
locGTP8.VLAN = 0
locGTP8.UlTEID, locGTP8.DlTEID = 0x10000008, 0x20000008
locGTP8.QFI = 2
locGTP8.UlQFI, locGTP8.DlQFI = 2, 12
locGTP8.InnerLocalIP = netip.MustParseAddr("192.168.60.3")
locGTP8.InnerRemoteIP = netip.MustParseAddr("192.168.60.4")
faceGTP8 := addFace(locGTP8)
Expand Down Expand Up @@ -208,7 +208,7 @@ func testPortTAP(t testing.TB, makeNetifConfig func(ifname string) ethnetif.Conf
&layers.Ethernet{SrcMAC: locGTP8.Remote.HardwareAddr, DstMAC: locGTP8.Local.HardwareAddr, EthernetType: layers.EthernetTypeIPv4},
&layers.IPv4{Version: 4, TTL: 64, Protocol: layers.IPProtocolUDP, SrcIP: net.IP(locGTP8.RemoteIP.AsSlice()), DstIP: net.IP(locGTP8.LocalIP.AsSlice())},
&layers.UDP{SrcPort: 2152, DstPort: 2152},
&GTPv1UTPDU{TEID: uint32(locGTP8.UlTEID), PDUType: 1, QFI: uint8(locGTP8.QFI)},
&GTPv1UTPDU{TEID: uint32(locGTP8.UlTEID), PDUType: 1, QFI: uint8(locGTP8.UlQFI)},
&layers.IPv4{Version: 4, TTL: 64, Protocol: layers.IPProtocolUDP, SrcIP: net.IP(locGTP8.InnerRemoteIP.AsSlice()), DstIP: net.IP(locGTP8.InnerLocalIP.AsSlice())},
&layers.UDP{SrcPort: 6363, DstPort: 6363},
makeRxFrame("GTP8", i),
Expand All @@ -220,7 +220,7 @@ func testPortTAP(t testing.TB, makeNetifConfig func(ifname string) ethnetif.Conf
&layers.Ethernet{SrcMAC: locGTP9.Remote.HardwareAddr, DstMAC: locGTP9.Local.HardwareAddr, EthernetType: layers.EthernetTypeIPv4},
&layers.IPv4{Version: 4, TTL: 64, Protocol: layers.IPProtocolUDP, SrcIP: net.IP(locGTP9.RemoteIP.AsSlice()), DstIP: net.IP(locGTP9.LocalIP.AsSlice())},
&layers.UDP{SrcPort: 2152, DstPort: 2152},
&GTPv1UTPDU{TEID: uint32(locGTP9.UlTEID), PDUType: 1, QFI: uint8(locGTP9.QFI)},
&GTPv1UTPDU{TEID: uint32(locGTP9.UlTEID), PDUType: 1, QFI: uint8(locGTP9.UlQFI)},
&layers.IPv4{Version: 4, TTL: 64, Protocol: layers.IPProtocolUDP, SrcIP: net.IP(locGTP9.InnerRemoteIP.AsSlice()), DstIP: net.IP(locGTP9.InnerLocalIP.AsSlice())},
&layers.UDP{SrcPort: 6363, DstPort: 6363},
makeRxFrame("GTP9", i),
Expand Down

0 comments on commit 269f611

Please sign in to comment.