Skip to content

Commit

Permalink
Fix multi ifaces (for real this time); fix iface types; add logs; add…
Browse files Browse the repository at this point in the history
… Free5GC interop.
  • Loading branch information
louisroyer committed Dec 14, 2024
1 parent 48f3783 commit 72fd067
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 21 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.22.7
require (
github.com/adrg/xdg v0.5.3
github.com/gin-gonic/gin v1.10.0
github.com/nextmn/go-pfcp-networking v0.0.41-0.20241213191334-2767b639c015
github.com/nextmn/go-pfcp-networking v0.0.41
github.com/nextmn/json-api v0.0.14
github.com/nextmn/logrus-formatter v0.0.1
github.com/sirupsen/logrus v1.9.3
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nextmn/go-pfcp-networking v0.0.41-0.20241212103129-24fe84808302 h1:NlmeMncMd72Qf0jTnXLPxHnXVB07tGycVn7Nrvx4YXw=
github.com/nextmn/go-pfcp-networking v0.0.41-0.20241212103129-24fe84808302/go.mod h1:KYoKLiltDmHL2YMU5mz2k/E1xMoz4TpmzTz6Nr5u5gA=
github.com/nextmn/go-pfcp-networking v0.0.41-0.20241213191334-2767b639c015 h1:0ICHKYmbOXM2QB5D34rL1kfkAyMdqJZ3E8zZPx02bCg=
github.com/nextmn/go-pfcp-networking v0.0.41-0.20241213191334-2767b639c015/go.mod h1:KYoKLiltDmHL2YMU5mz2k/E1xMoz4TpmzTz6Nr5u5gA=
github.com/nextmn/go-pfcp-networking v0.0.41 h1:vA8TfjlxZMxZIZiJ3eEdllwYjmBurvZvD9J4xcCPheo=
github.com/nextmn/go-pfcp-networking v0.0.41/go.mod h1:KYoKLiltDmHL2YMU5mz2k/E1xMoz4TpmzTz6Nr5u5gA=
github.com/nextmn/json-api v0.0.14 h1:m4uHOVcXsxkXoxbrhqemLTRG4T86eYkejjirew1nDUU=
github.com/nextmn/json-api v0.0.14/go.mod h1:CQXeNPj9MDGsEExtnqJFIGjLgZAKsmOoO2fy+mep7Ak=
github.com/nextmn/logrus-formatter v0.0.1 h1:Bsf78jjiEESc+rV8xE6IyKj4frDPGMwXFNrLQzm6A1E=
Expand Down
46 changes: 37 additions & 9 deletions internal/smf/smf.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func (smf *Smf) CreateSessionDownlink(ctx context.Context, ueCtrl jsonapi.Contro
if i == 0 {
upf_iface, err = upf.GetN3()
} else if i != len(slice.Upfs)-1 {
upf_iface, err = upf.GetN6()
upf_iface, err = upf.GetN9()
}
if err != nil {
return nil, err
Expand Down Expand Up @@ -158,11 +158,24 @@ func (smf *Smf) CreateSessionUplink(ctx context.Context, ueCtrl jsonapi.ControlU
var upfa_iface netip.Addr
if len(slice.Upfs) == 1 {
upfa_iface, err = upfa.GetN3()
if err != nil {
logrus.WithError(err).WithFields(logrus.Fields{
"upf": upfa_ctrl,
"iface": "n3",
"type": "anchor",
}).Error("Could not prepare session uplink path")
return nil, err
}
} else {
upfa_iface, err = upfa.GetN6()
}
if err != nil {
return nil, err
upfa_iface, err = upfa.GetN9()
if err != nil {
logrus.WithError(err).WithFields(logrus.Fields{
"upf": upfa_ctrl,
"iface": "n9",
"type": "anchor",
}).Error("Could not prepare session uplink path")
return nil, err
}
}
last_fteid, err := upfa.CreateUplinkAnchor(ctx, ueIpAddr, dnn, upfa_iface)
if err != nil {
Expand All @@ -183,17 +196,32 @@ func (smf *Smf) CreateSessionUplink(ctx context.Context, ueCtrl jsonapi.ControlU
var upf_iface netip.Addr
if i == 0 {
upf_iface, err = upf.GetN3()
if err != nil {
logrus.WithError(err).WithFields(logrus.Fields{
"upf": upf_ctrl,
"iface": "n3",
"type": "inter",
}).Error("Could not prepare session uplink path")
return nil, err
}
} else {
upf_iface, err = upf.GetN6()
}
if err != nil {
return nil, err
upf_iface, err = upf.GetN9()
if err != nil {
logrus.WithError(err).WithFields(logrus.Fields{
"upf": upf_ctrl,
"iface": "n9",
"type": "inter",
}).Error("Could not prepare session uplink path")
return nil, err
}
}
last_fteid, err = upf.CreateUplinkIntermediate(ctx, ueIpAddr, dnn, upf_iface, last_fteid)
if err != nil {
logrus.WithError(err).Error("Could not create uplink intermediate")
return nil, err
}
if err := upf.CreateSession(ueIpAddr); err != nil {
logrus.WithError(err).Error("Could not create session uplink")
return nil, err
}
}
Expand Down
22 changes: 19 additions & 3 deletions internal/smf/upf.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ func (upf *Upf) GetN3() (netip.Addr, error) {
return netip.Addr{}, ErrInterfaceNotFound
}

func (upf *Upf) GetN6() (netip.Addr, error) {
func (upf *Upf) GetN9() (netip.Addr, error) {
for addr, iface := range upf.interfaces {
if iface.IsN6() {
if iface.IsN9() {
return addr, nil
}
}
Expand Down Expand Up @@ -135,6 +135,7 @@ func (upf *Upf) CreateUplinkIntermediateWithFteid(ueIp netip.Addr, dnn string, l
),
),
))
// TODO: QER, to avoid wrong gtp size set by F5GC's UPF
}

func (upf *Upf) CreateUplinkAnchor(ctx context.Context, ueIp netip.Addr, dnn string, listenInterface netip.Addr) (*Fteid, error) {
Expand Down Expand Up @@ -200,6 +201,7 @@ func (upf *Upf) UpdateDownlinkAnchor(ueIp netip.Addr, dnn string, forwardFteid *
),
),
))
// TODO: QER, to avoid wrong gtp size set by F5GC's UPF
}

func (upf *Upf) UpdateDownlinkIntermediate(ctx context.Context, ueIp netip.Addr, dnn string, listenInterface netip.Addr, forwardFteid *Fteid) (*Fteid, error) {
Expand All @@ -223,7 +225,20 @@ func (upf *Upf) UpdateDownlinkIntermediateWithFteid(ueIp netip.Addr, dnn string,
ie.NewSourceInterface(ie.SrcInterfaceCore),
ie.NewFTEID(FteidTypeIPv4, listenFteid.Teid, listenFteid.Addr.AsSlice(), nil, 0),
ie.NewNetworkInstance(dnn),
ie.NewUEIPAddress(UEIpAddrTypeIPv4, ueIp.String(), "", 0, 0),
// Free5GC's UPF seems to drop GTP packets, when UE IP Address is present
// and for downlink only
// According to TS 129.244 version 17.4.0, section 7.5.2.2, table 7.5.2.2-2, p. 159:
// "If present, this IE shall identify the UE IP address as
// the source or destination IP address to match for the incoming packet"
// Here, it seems that when the packet is GTP encapsulated, only the source address is checked.
// This is a bug.
// As a workaround, we don't add the UE IP Address in this case.
// Free5GC's SMF implementation has a similar workaround:
// https://github.com/free5gc/smf/blob/62925c4a5840f118b42f245b5fef492898f9f0bd/internal/context/datapath.go#L636-L640
// and the bug seems to be referenced as "FR5GC-1029" (but I have no link to the details of the issue)
// XXX: the following line may be uncommented if the bug is fixed:

// ie.NewUEIPAddress(UEIpAddrTypeIPv4, ueIp.String(), "", 0, 0),
),
ie.NewOuterHeaderRemoval(OuterHeaderRemoveGtpuUdpIpv4, 0),
ie.NewFARID(r.currentfarid),
Expand All @@ -242,6 +257,7 @@ func (upf *Upf) UpdateDownlinkIntermediateWithFteid(ueIp netip.Addr, dnn string,
),
),
))
// TODO: QER, to avoid wrong gtp size set by F5GC's UPF
}

func (upf *Upf) CreateSession(ue netip.Addr) error {
Expand Down
9 changes: 5 additions & 4 deletions internal/smf/upf_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ func NewUpfInterfaceMap(ifaces []config.Interface) map[netip.Addr]*UpfInterface
r := make(map[netip.Addr]*UpfInterface)
for _, v := range ifaces {
if i, ok := r[v.Addr]; ok {
i.Types = append(i.Types, v.Type)
r[v.Addr].Types = append(i.Types, v.Type)
} else {
r[v.Addr] = NewUpfInterface(v.Type)
}
r[v.Addr] = NewUpfInterface(v.Type)
}
return r
}
Expand All @@ -43,9 +44,9 @@ func (iface *UpfInterface) IsN3() bool {
return false
}

func (iface *UpfInterface) IsN6() bool {
func (iface *UpfInterface) IsN9() bool {
for _, t := range iface.Types {
if strings.ToLower(t) == "n6" {
if strings.ToLower(t) == "n9" {
return true
}
}
Expand Down

0 comments on commit 72fd067

Please sign in to comment.