From f52b9c10d4ca93d78a1c170b16fa4eebf54ef1c6 Mon Sep 17 00:00:00 2001 From: brianchennn Date: Wed, 29 Nov 2023 06:42:22 +0000 Subject: [PATCH 1/4] fix: flow description should accept token "assigned" --- internal/forwarder/flowdesc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/forwarder/flowdesc.go b/internal/forwarder/flowdesc.go index 52603f2..e048646 100644 --- a/internal/forwarder/flowdesc.go +++ b/internal/forwarder/flowdesc.go @@ -129,7 +129,7 @@ func ParseFlowDesc(s string) (*FlowDesc, error) { } func ParseFlowDescIPNet(s string) (*net.IPNet, error) { - if s == "any" { + if s == "any" || s == "assigned" { return &net.IPNet{ IP: net.IPv6zero, Mask: net.CIDRMask(0, 128), From 838afdf967359e50a547499389c8126216c511c8 Mon Sep 17 00:00:00 2001 From: brianchennn Date: Thu, 30 Nov 2023 08:28:31 +0000 Subject: [PATCH 2/4] fix: swap srt, dst IP/Port in when newPdi --- go.mod | 2 +- go.sum | 4 ++-- internal/forwarder/flowdesc.go | 9 ++++++++- internal/forwarder/gtp5g.go | 29 ++++++++++++++++++++--------- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index ba33b99..4d083f5 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/davecgh/go-spew v1.1.1 github.com/free5gc/go-gtp5gnl v1.4.6-0.20230629034810-9a49c0a5ee2f - github.com/free5gc/util v1.0.5-0.20230823103219-e511c4fd20ef + github.com/free5gc/util v1.0.5-0.20231012123940-85f4557167be github.com/hashicorp/go-version v1.6.0 github.com/khirono/go-genl v1.0.1 github.com/khirono/go-nl v1.0.5 diff --git a/go.sum b/go.sum index 733b4b0..f79f2b3 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/free5gc/go-gtp5gnl v1.4.6-0.20230629034810-9a49c0a5ee2f h1:+D0L2ixhbg6Iy/oQEAJQLmOU/w1mmndqVF78GdjX1yo= github.com/free5gc/go-gtp5gnl v1.4.6-0.20230629034810-9a49c0a5ee2f/go.mod h1:TT5aXB90NuSPMehuIK9lV2yJFnq6Qjw37ZqNB1QAKh0= -github.com/free5gc/util v1.0.5-0.20230823103219-e511c4fd20ef h1:ne0EMnst7wbLoaY2Uvn/2Kvp/KkXKMQJcaIJQKFe+a4= -github.com/free5gc/util v1.0.5-0.20230823103219-e511c4fd20ef/go.mod h1:l2Jrml4vojDomW5jdDJhIS60KdbrE9uPYhyAq/7OnF4= +github.com/free5gc/util v1.0.5-0.20231012123940-85f4557167be h1:SglM1KIL+bR50hPzbvxVwNW44+yHR2tq9nTpLra75UE= +github.com/free5gc/util v1.0.5-0.20231012123940-85f4557167be/go.mod h1:d+79g84a3YHhzvjJ2IhurrBOavOA8xWIQ/GCywPXqQk= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= diff --git a/internal/forwarder/flowdesc.go b/internal/forwarder/flowdesc.go index e048646..624a7b3 100644 --- a/internal/forwarder/flowdesc.go +++ b/internal/forwarder/flowdesc.go @@ -5,6 +5,8 @@ import ( "net" "strconv" "strings" + + "github.com/wmnsk/go-pfcp/ie" ) // IPFilterRule <- action s dir s proto s 'from' s src 'to' s dst @@ -31,7 +33,7 @@ type FlowDesc struct { DstPorts [][]uint16 } -func ParseFlowDesc(s string) (*FlowDesc, error) { +func ParseFlowDesc(s string, sourceInterface uint8) (*FlowDesc, error) { fd := new(FlowDesc) token := strings.Fields(s) pos := 0 @@ -125,6 +127,11 @@ func ParseFlowDesc(s string) (*FlowDesc, error) { } } + if sourceInterface == ie.SrcInterfaceAccess { // TS 29.244 5.2.1A.2A + fd.Dst, fd.Src = fd.Src, fd.Dst + fd.DstPorts, fd.SrcPorts = fd.SrcPorts, fd.DstPorts + } + return fd, nil } diff --git a/internal/forwarder/gtp5g.go b/internal/forwarder/gtp5g.go index d82b752..5f94831 100644 --- a/internal/forwarder/gtp5g.go +++ b/internal/forwarder/gtp5g.go @@ -173,9 +173,9 @@ func (g *Gtp5g) Link() *Gtp5gLink { return g.link } -func (g *Gtp5g) newFlowDesc(s string) (nl.AttrList, error) { +func (g *Gtp5g) newFlowDesc(s string, sourceInterface uint8) (nl.AttrList, error) { var attrs nl.AttrList - fd, err := ParseFlowDesc(s) + fd, err := ParseFlowDesc(s, sourceInterface) if err != nil { return nil, err } @@ -249,7 +249,7 @@ func convertSlice(ports [][]uint16) []byte { return b } -func (g *Gtp5g) newSdfFilter(i *ie.IE) (nl.AttrList, error) { +func (g *Gtp5g) newSdfFilter(i *ie.IE, sourceInterface uint8) (nl.AttrList, error) { var attrs nl.AttrList v, err := i.SDFFilter() @@ -258,7 +258,7 @@ func (g *Gtp5g) newSdfFilter(i *ie.IE) (nl.AttrList, error) { } if v.HasFD() { - fd, err := g.newFlowDesc(v.FlowDescription) + fd, err := g.newFlowDesc(v.FlowDescription, sourceInterface) if err != nil { return nil, err } @@ -311,9 +311,17 @@ func (g *Gtp5g) newPdi(i *ie.IE) (nl.AttrList, error) { if err != nil { return nil, err } + + var sourceInterface uint8 + var sdfFilterIE *ie.IE for _, x := range ies { switch x.Type { case ie.SourceInterface: + var err1 error + sourceInterface, err1 = x.SourceInterface() + if err1 != nil { + break + } case ie.FTEID: v, err := x.FTEID() if err != nil { @@ -343,15 +351,18 @@ func (g *Gtp5g) newPdi(i *ie.IE) (nl.AttrList, error) { Value: nl.AttrBytes(v.IPv4Address), }) case ie.SDFFilter: - v, err := g.newSdfFilter(x) - if err != nil { - break - } + sdfFilterIE = x + case ie.ApplicationID: + } + } + + if sdfFilterIE != nil { + v, err := g.newSdfFilter(sdfFilterIE, sourceInterface) + if err == nil { attrs = append(attrs, nl.Attr{ Type: gtp5gnl.PDI_SDF_FILTER, Value: v, }) - case ie.ApplicationID: } } From 2fde71f59841f4342a60654dba8cea6a9d8a1e11 Mon Sep 17 00:00:00 2001 From: brianchennn Date: Fri, 1 Dec 2023 15:09:52 +0000 Subject: [PATCH 3/4] swapSrcDst() in newSdfFilter() --- internal/forwarder/flowdesc.go | 9 +------ internal/forwarder/gtp5g.go | 43 +++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/internal/forwarder/flowdesc.go b/internal/forwarder/flowdesc.go index 624a7b3..e048646 100644 --- a/internal/forwarder/flowdesc.go +++ b/internal/forwarder/flowdesc.go @@ -5,8 +5,6 @@ import ( "net" "strconv" "strings" - - "github.com/wmnsk/go-pfcp/ie" ) // IPFilterRule <- action s dir s proto s 'from' s src 'to' s dst @@ -33,7 +31,7 @@ type FlowDesc struct { DstPorts [][]uint16 } -func ParseFlowDesc(s string, sourceInterface uint8) (*FlowDesc, error) { +func ParseFlowDesc(s string) (*FlowDesc, error) { fd := new(FlowDesc) token := strings.Fields(s) pos := 0 @@ -127,11 +125,6 @@ func ParseFlowDesc(s string, sourceInterface uint8) (*FlowDesc, error) { } } - if sourceInterface == ie.SrcInterfaceAccess { // TS 29.244 5.2.1A.2A - fd.Dst, fd.Src = fd.Src, fd.Dst - fd.DstPorts, fd.SrcPorts = fd.SrcPorts, fd.DstPorts - } - return fd, nil } diff --git a/internal/forwarder/gtp5g.go b/internal/forwarder/gtp5g.go index 5f94831..c8a6564 100644 --- a/internal/forwarder/gtp5g.go +++ b/internal/forwarder/gtp5g.go @@ -3,6 +3,7 @@ package forwarder import ( "fmt" "net" + "strings" "sync" "syscall" "time" @@ -173,9 +174,9 @@ func (g *Gtp5g) Link() *Gtp5gLink { return g.link } -func (g *Gtp5g) newFlowDesc(s string, sourceInterface uint8) (nl.AttrList, error) { +func (g *Gtp5g) newFlowDesc(s string) (nl.AttrList, error) { var attrs nl.AttrList - fd, err := ParseFlowDesc(s, sourceInterface) + fd, err := ParseFlowDesc(s) if err != nil { return nil, err } @@ -249,6 +250,21 @@ func convertSlice(ports [][]uint16) []byte { return b } +func swapSrcDst(fdStr string) (string, error) { + strs1 := strings.Split(fdStr, "from") + if len(strs1) != 2 { + return "", fmt.Errorf("invalid flow description format") + } + + strs2 := strings.Split(strs1[1], "to") + if len(strs2) != 2 { + return "", fmt.Errorf("invalid flow description format") + } + + ret := strs1[0] + "from" + strs2[1] + " to" + strs2[0] + return ret, nil +} + func (g *Gtp5g) newSdfFilter(i *ie.IE, sourceInterface uint8) (nl.AttrList, error) { var attrs nl.AttrList @@ -258,7 +274,15 @@ func (g *Gtp5g) newSdfFilter(i *ie.IE, sourceInterface uint8) (nl.AttrList, erro } if v.HasFD() { - fd, err := g.newFlowDesc(v.FlowDescription, sourceInterface) + fdStr := v.FlowDescription + if sourceInterface == ie.SrcInterfaceAccess { + fdStr, err = swapSrcDst(fdStr) + if err != nil { + return nil, err + } + } + + fd, err := g.newFlowDesc(fdStr) if err != nil { return nil, err } @@ -314,18 +338,19 @@ func (g *Gtp5g) newPdi(i *ie.IE) (nl.AttrList, error) { var sourceInterface uint8 var sdfFilterIE *ie.IE + +L: for _, x := range ies { switch x.Type { case ie.SourceInterface: - var err1 error - sourceInterface, err1 = x.SourceInterface() - if err1 != nil { - break + sourceInterface, err = x.SourceInterface() + if err != nil { + break L } case ie.FTEID: v, err := x.FTEID() if err != nil { - break + break L } attrs = append(attrs, nl.Attr{ Type: gtp5gnl.PDI_F_TEID, @@ -344,7 +369,7 @@ func (g *Gtp5g) newPdi(i *ie.IE) (nl.AttrList, error) { case ie.UEIPAddress: v, err := x.UEIPAddress() if err != nil { - break + break L } attrs = append(attrs, nl.Attr{ Type: gtp5gnl.PDI_UE_ADDR_IPV4, From f3df8bed79fd57c845739776f27a9d69b1f9f6cc Mon Sep 17 00:00:00 2001 From: Tim Liu Date: Fri, 16 Feb 2024 10:44:11 +0000 Subject: [PATCH 4/4] fix to handle multi sdfIE and refactor --- internal/forwarder/gtp5g.go | 55 ++++++++++++------------------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/internal/forwarder/gtp5g.go b/internal/forwarder/gtp5g.go index c8a6564..e9ed74f 100644 --- a/internal/forwarder/gtp5g.go +++ b/internal/forwarder/gtp5g.go @@ -3,7 +3,6 @@ package forwarder import ( "fmt" "net" - "strings" "sync" "syscall" "time" @@ -174,12 +173,15 @@ func (g *Gtp5g) Link() *Gtp5gLink { return g.link } -func (g *Gtp5g) newFlowDesc(s string) (nl.AttrList, error) { +func (g *Gtp5g) newFlowDesc(s string, swapSrcDst bool) (nl.AttrList, error) { var attrs nl.AttrList fd, err := ParseFlowDesc(s) if err != nil { return nil, err } + if swapSrcDst { + fd.Src, fd.Dst = fd.Dst, fd.Src + } switch fd.Action { case "permit": attrs = append(attrs, nl.Attr{ @@ -250,22 +252,7 @@ func convertSlice(ports [][]uint16) []byte { return b } -func swapSrcDst(fdStr string) (string, error) { - strs1 := strings.Split(fdStr, "from") - if len(strs1) != 2 { - return "", fmt.Errorf("invalid flow description format") - } - - strs2 := strings.Split(strs1[1], "to") - if len(strs2) != 2 { - return "", fmt.Errorf("invalid flow description format") - } - - ret := strs1[0] + "from" + strs2[1] + " to" + strs2[0] - return ret, nil -} - -func (g *Gtp5g) newSdfFilter(i *ie.IE, sourceInterface uint8) (nl.AttrList, error) { +func (g *Gtp5g) newSdfFilter(i *ie.IE, srcIf uint8) (nl.AttrList, error) { var attrs nl.AttrList v, err := i.SDFFilter() @@ -274,15 +261,8 @@ func (g *Gtp5g) newSdfFilter(i *ie.IE, sourceInterface uint8) (nl.AttrList, erro } if v.HasFD() { - fdStr := v.FlowDescription - if sourceInterface == ie.SrcInterfaceAccess { - fdStr, err = swapSrcDst(fdStr) - if err != nil { - return nil, err - } - } - - fd, err := g.newFlowDesc(fdStr) + swapSrcDst := (srcIf == ie.SrcInterfaceAccess) + fd, err := g.newFlowDesc(v.FlowDescription, swapSrcDst) if err != nil { return nil, err } @@ -336,21 +316,20 @@ func (g *Gtp5g) newPdi(i *ie.IE) (nl.AttrList, error) { return nil, err } - var sourceInterface uint8 - var sdfFilterIE *ie.IE - -L: + var srcIf uint8 + var sdfIEs []*ie.IE for _, x := range ies { switch x.Type { case ie.SourceInterface: - sourceInterface, err = x.SourceInterface() + v, err := x.SourceInterface() if err != nil { - break L + break } + srcIf = v case ie.FTEID: v, err := x.FTEID() if err != nil { - break L + break } attrs = append(attrs, nl.Attr{ Type: gtp5gnl.PDI_F_TEID, @@ -369,20 +348,20 @@ L: case ie.UEIPAddress: v, err := x.UEIPAddress() if err != nil { - break L + break } attrs = append(attrs, nl.Attr{ Type: gtp5gnl.PDI_UE_ADDR_IPV4, Value: nl.AttrBytes(v.IPv4Address), }) case ie.SDFFilter: - sdfFilterIE = x + sdfIEs = append(sdfIEs, x) case ie.ApplicationID: } } - if sdfFilterIE != nil { - v, err := g.newSdfFilter(sdfFilterIE, sourceInterface) + for _, x := range sdfIEs { + v, err := g.newSdfFilter(x, srcIf) if err == nil { attrs = append(attrs, nl.Attr{ Type: gtp5gnl.PDI_SDF_FILTER,