-
Notifications
You must be signed in to change notification settings - Fork 106
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: add F-TEID allocation support #840
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -123,6 +123,7 @@ sudo | |
tc | ||
TCP | ||
tcpdump | ||
TEID | ||
TRex | ||
UDP | ||
UE | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
1.5.1-dev | ||
2.0.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
module github.com/omec-project/upf-epc | ||
|
||
go 1.21 | ||
go 1.23 | ||
|
||
require ( | ||
github.com/Showmax/go-fqdn v1.0.0 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2024 Canonical Ltd. | ||
|
||
package pfcpiface | ||
|
||
import ( | ||
"errors" | ||
"math" | ||
"sync" | ||
) | ||
|
||
const ( | ||
minValue = 1 | ||
maxValue = math.MaxUint32 | ||
) | ||
|
||
type FTEIDGenerator struct { | ||
lock sync.Mutex | ||
offset uint32 | ||
usedMap map[uint32]bool | ||
} | ||
|
||
func NewFTEIDGenerator() *FTEIDGenerator { | ||
return &FTEIDGenerator{ | ||
offset: 0, | ||
usedMap: make(map[uint32]bool), | ||
} | ||
} | ||
|
||
// Allocate and return an id in range [minValue, maxValue] | ||
func (idGenerator *FTEIDGenerator) Allocate() (uint32, error) { | ||
idGenerator.lock.Lock() | ||
defer idGenerator.lock.Unlock() | ||
|
||
offsetBegin := idGenerator.offset | ||
for { | ||
if _, ok := idGenerator.usedMap[idGenerator.offset]; ok { | ||
idGenerator.updateOffset() | ||
|
||
if idGenerator.offset == offsetBegin { | ||
return 0, errors.New("no available value range to allocate id") | ||
} | ||
} else { | ||
break | ||
} | ||
} | ||
idGenerator.usedMap[idGenerator.offset] = true | ||
id := idGenerator.offset + minValue | ||
idGenerator.updateOffset() | ||
return id, nil | ||
} | ||
|
||
func (idGenerator *FTEIDGenerator) FreeID(id uint32) { | ||
if id < minValue { | ||
return | ||
} | ||
idGenerator.lock.Lock() | ||
defer idGenerator.lock.Unlock() | ||
delete(idGenerator.usedMap, id-minValue) | ||
} | ||
|
||
func (idGenerator *FTEIDGenerator) IsAllocated(id uint32) bool { | ||
if id < minValue { | ||
return false | ||
} | ||
idGenerator.lock.Lock() | ||
defer idGenerator.lock.Unlock() | ||
_, ok := idGenerator.usedMap[id-minValue] | ||
return ok | ||
} | ||
|
||
func (idGenerator *FTEIDGenerator) updateOffset() { | ||
idGenerator.offset++ | ||
idGenerator.offset = idGenerator.offset % maxValue | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2024 Canonical Ltd. | ||
|
||
package pfcpiface_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/omec-project/upf-epc/pfcpiface" | ||
) | ||
|
||
func TestFTEIDAllocate(t *testing.T) { | ||
fteidGenerator := pfcpiface.NewFTEIDGenerator() | ||
|
||
fteid, err := fteidGenerator.Allocate() | ||
if err != nil { | ||
t.Errorf("FTEID allocation failed: %v", err) | ||
} | ||
if fteid < 1 { | ||
t.Errorf("FTEID allocation failed, value is too small: %v", fteid) | ||
} | ||
if !fteidGenerator.IsAllocated(fteid) { | ||
t.Errorf("FTEID was not allocated") | ||
} | ||
} | ||
|
||
func TestFTEIDFree(t *testing.T) { | ||
fteidGenerator := pfcpiface.NewFTEIDGenerator() | ||
fteid, err := fteidGenerator.Allocate() | ||
if err != nil { | ||
t.Errorf("FTEID allocation failed: %v", err) | ||
} | ||
|
||
fteidGenerator.FreeID(fteid) | ||
|
||
if fteidGenerator.IsAllocated(fteid) { | ||
t.Errorf("FTEID was not freed") | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -269,10 +269,11 @@ type applicationFilter struct { | |
} | ||
|
||
type pdr struct { | ||
srcIface uint8 | ||
tunnelIP4Dst uint32 | ||
tunnelTEID uint32 | ||
ueAddress uint32 | ||
UPAllocateFteid bool | ||
srcIface uint8 | ||
tunnelIP4Dst uint32 | ||
tunnelTEID uint32 | ||
ueAddress uint32 | ||
|
||
srcIfaceMask uint8 | ||
tunnelIP4DstMask uint32 | ||
|
@@ -390,13 +391,14 @@ func (p *pdr) parseFTEID(teidIE *ie.IE) error { | |
} | ||
|
||
teid := fteid.TEID | ||
tunnelIPv4Address := fteid.IPv4Address | ||
|
||
if teid != 0 { | ||
if fteid.HasCh() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you pls help with this. What does this do? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the SMF wants the UPF to allocate the F-TEID, which is the case in 3GPP release 16, the SMF sets the CHOOSE flag in the Local F-TEID of its PFCP association setup request. Here, the UPF checks if this flag is set. If it is, it sets UPAllocateFteid to True which will result in the UPF allocating an F-TEID. From the 3GPP spec:
|
||
p.UPAllocateFteid = true | ||
} else if teid != 0 { | ||
p.tunnelTEID = teid | ||
p.tunnelTEIDMask = 0xFFFFFFFF | ||
p.tunnelIP4Dst = ip2int(tunnelIPv4Address) | ||
p.tunnelIP4Dst = ip2int(fteid.IPv4Address) | ||
p.tunnelIP4DstMask = 0xFFFFFFFF | ||
|
||
} | ||
|
||
return nil | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not efficient.. In case we establish few hundred or thousand tunnels then this will become slow. Anything better we can do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is using the exact same algorithm as was used in the SMF. While we may want to change it for something efficient, I would decouple this performance improvement from this change here which is focused on moving f-teid allocation from the SMF to the UPF.
Reference: