From 06cc7c7c2d91006aba7c5f8b95b59f3e6eaadddf Mon Sep 17 00:00:00 2001 From: Louis Royer Date: Thu, 17 Oct 2024 19:09:20 +0200 Subject: [PATCH] Update api --- go.mod | 18 ++-- go.sum | 36 +++---- internal/database/api/uplink.go | 2 +- internal/database/database.go | 142 +++++++++++++++++--------- internal/database/database.sql | 52 ++++++---- internal/database/database_gen.go | 4 +- internal/netfunc/headend-gtp4-ctrl.go | 14 ++- 7 files changed, 169 insertions(+), 99 deletions(-) diff --git a/go.mod b/go.mod index 9e1c8cd..61380df 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,14 @@ module github.com/nextmn/srv6 go 1.22.7 require ( - github.com/adrg/xdg v0.5.0 + github.com/adrg/xdg v0.5.1 github.com/gin-gonic/gin v1.10.0 github.com/gofrs/uuid v4.4.0+incompatible github.com/google/gopacket v1.1.19 github.com/lib/pq v1.10.9 github.com/nextmn/gopacket-gtp v0.0.7 github.com/nextmn/gopacket-srv6 v0.0.8 - github.com/nextmn/json-api v0.0.7 + github.com/nextmn/json-api v0.0.10 github.com/nextmn/logrus-formatter v0.0.1 github.com/nextmn/rfc9433 v0.0.2 github.com/sirupsen/logrus v1.9.3 @@ -25,7 +25,7 @@ require ( github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect - github.com/gabriel-vasile/mimetype v1.4.5 // indirect + github.com/gabriel-vasile/mimetype v1.4.6 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect @@ -42,10 +42,10 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect - golang.org/x/arch v0.10.0 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/net v0.29.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + golang.org/x/arch v0.11.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect + google.golang.org/protobuf v1.35.1 // indirect ) diff --git a/go.sum b/go.sum index 09d2dd7..7a996bc 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY= -github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4= +github.com/adrg/xdg v0.5.1 h1:Im8iDbEFARltY09yOJlSGu4Asjk2vF85+3Dyru8uJ0U= +github.com/adrg/xdg v0.5.1/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= @@ -14,8 +14,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= -github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4= +github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= +github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= @@ -58,8 +58,8 @@ github.com/nextmn/gopacket-gtp v0.0.7 h1:O2cuShLTlpVBEXyHn9OIi1Nd+j4QCB66RAwzKBe github.com/nextmn/gopacket-gtp v0.0.7/go.mod h1:94jLjLU04IOVTKBXUP09MXZCgmlizqmflU2ion1ht6E= github.com/nextmn/gopacket-srv6 v0.0.8 h1:oP4wuJ7dOiV/gWmX3zoFcdp2dKdSWLUaxH2fJ3TYAwA= github.com/nextmn/gopacket-srv6 v0.0.8/go.mod h1:2Tyuo9zsG0bP2IhC4tVRgPRuyUqOgrvEEH9seJSZTlU= -github.com/nextmn/json-api v0.0.7 h1:cM1DJhOTleeESDQIGn8Ahuo3szCW9YEiymbsng+aFws= -github.com/nextmn/json-api v0.0.7/go.mod h1:0py63IYCOBp1ZtLkMjNCNnOwbwhOmkh+ymJ0/OrxYx8= +github.com/nextmn/json-api v0.0.10 h1:/7WCtGaLEKFKGstOrssac6QgPL0MeGqpkRWU3hepS1A= +github.com/nextmn/json-api v0.0.10/go.mod h1:0py63IYCOBp1ZtLkMjNCNnOwbwhOmkh+ymJ0/OrxYx8= github.com/nextmn/logrus-formatter v0.0.1 h1:Bsf78jjiEESc+rV8xE6IyKj4frDPGMwXFNrLQzm6A1E= github.com/nextmn/logrus-formatter v0.0.1/go.mod h1:vdSZ+sIcSna8vjbXkSFxsnsKHqRwaUEed4JCPcXoGyM= github.com/nextmn/rfc9433 v0.0.2 h1:6FjMY+Qy8MNXQ0PPxezUsyXDxJiCbTp5j3OcXQgIQh8= @@ -92,33 +92,33 @@ github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8= -golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4= +golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/database/api/uplink.go b/internal/database/api/uplink.go index cedfaa0..f124d7e 100644 --- a/internal/database/api/uplink.go +++ b/internal/database/api/uplink.go @@ -12,5 +12,5 @@ import ( ) type Uplink interface { - GetUplinkAction(ctx context.Context, UplinkTeid uint32, GnbIp netip.Addr) (jsonapi.Action, error) + GetUplinkAction(ctx context.Context, UplinkTeid uint32, GnbIp netip.Addr, UeIp netip.Addr, ServiceIp netip.Addr) (jsonapi.Action, error) } diff --git a/internal/database/database.go b/internal/database/database.go index 3f56e4a..0ff6ce9 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -89,9 +89,24 @@ func (db *Database) InsertRule(ctx context.Context, r jsonapi.Rule) (*uuid.UUID, } switch r.Type { case "uplink": + var inneripsrc string + var inneripdst string + var outeripsrc string + if r.Match.Header.InnerIpSrc == nil { + inneripsrc = "0.0.0.0/0" + } else { + inneripsrc = r.Match.Header.InnerIpSrc.String() + "/32" + } + if r.Match.Payload == nil { + inneripdst = "0.0.0.0/0" + } else { + inneripdst = r.Match.Payload.Dst.String() + "/32" + } + outeripsrc = r.Match.Header.OuterIpSrc.String() + "/32" + if stmt, ok := db.stmt["insert_uplink_rule"]; ok { var id uuid.UUID - err := stmt.QueryRowContext(ctx, r.Enabled, r.Match.UEIpPrefix.String(), r.Match.GNBIpPrefix.String(), r.Match.Teid, r.Action.NextHop.String(), pq.Array(srh)).Scan(&id) + err := stmt.QueryRowContext(ctx, r.Enabled, inneripsrc, outeripsrc, r.Match.Header.Teid, inneripdst, r.Action.NextHop.String(), pq.Array(srh)).Scan(&id) return &id, err } else { return nil, fmt.Errorf("Procedure not registered") @@ -99,7 +114,13 @@ func (db *Database) InsertRule(ctx context.Context, r jsonapi.Rule) (*uuid.UUID, case "downlink": if stmt, ok := db.stmt["insert_downlink_rule"]; ok { var id uuid.UUID - err := stmt.QueryRowContext(ctx, r.Enabled, r.Match.UEIpPrefix.String(), r.Action.NextHop.String(), pq.Array(srh)).Scan(&id) + var dst string + if r.Match.Payload == nil { + dst = "0.0.0.0/0" + } else { + dst = r.Match.Payload.Dst.String() + "/32" + } + err := stmt.QueryRowContext(ctx, r.Enabled, dst, r.Action.NextHop.String(), pq.Array(srh)).Scan(&id) return &id, err } else { return nil, fmt.Errorf("Procedure not registered") @@ -114,37 +135,53 @@ func (db *Database) GetRule(ctx context.Context, uuid uuid.UUID) (jsonapi.Rule, var enabled bool var action_next_hop string var action_srh []string - var match_ue_ip_prefix string - var match_gnb_ip_prefix string + var match_ue_ip string + var match_gnb_ip *string + var match_service_ip *string + var match_uplink_teid *uint32 if stmt, ok := db.stmt["get_rule"]; ok { - err := stmt.QueryRowContext(ctx, uuid.String()).Scan(&type_uplink, &enabled, &action_next_hop, pq.Array(&action_srh), &match_ue_ip_prefix, &match_gnb_ip_prefix) + err := stmt.QueryRowContext(ctx, uuid.String()).Scan(&type_uplink, &enabled, &action_next_hop, pq.Array(&action_srh), &match_ue_ip, &match_gnb_ip, &match_uplink_teid, &match_service_ip) if err != nil { return jsonapi.Rule{}, err } - var t string - if type_uplink { - t = "uplink" - } else { - t = "downlink" - } rule := jsonapi.Rule{ Enabled: enabled, - Type: t, + Match: jsonapi.Match{}, } - rule.Match = jsonapi.Match{} - if match_ue_ip_prefix != "" { - p, err := netip.ParsePrefix(match_ue_ip_prefix) - if err == nil { - rule.Match.UEIpPrefix = p + if type_uplink { + rule.Type = "uplink" + rule.Match.Header = &jsonapi.GtpHeader{} + if match_gnb_ip != nil { + p, err := netip.ParsePrefix(*match_gnb_ip) + if err == nil && p.Bits() == 32 { + rule.Match.Header.OuterIpSrc = p.Addr() + } + } + if match_uplink_teid != nil { + rule.Match.Header.Teid = *match_uplink_teid } + if match_service_ip != nil { + p, err := netip.ParsePrefix(*match_service_ip) + if err == nil && p.Bits() == 32 { + rule.Match.Payload = &jsonapi.Payload{ + Dst: p.Addr(), + } + } + } + } else { + rule.Type = "downlink" } - if match_gnb_ip_prefix != "" { - p, err := netip.ParsePrefix(match_gnb_ip_prefix) - if err == nil { - rule.Match.GNBIpPrefix = p + p, err := netip.ParsePrefix(match_ue_ip) + if err == nil && p.Bits() == 32 { + if type_uplink { + a := p.Addr() + rule.Match.Header.InnerIpSrc = &a + } else { + rule.Match.Payload = &jsonapi.Payload{ + Dst: p.Addr(), + } } } - srh, err := jsonapi.NewSRH(action_srh) if err != nil { return jsonapi.Rule{}, err @@ -171,9 +208,10 @@ func (db *Database) GetRules(ctx context.Context) (jsonapi.RuleMap, error) { var enabled bool var action_next_hop string var action_srh []string - var match_ue_ip_prefix string - var match_gnb_ip_prefix *string + var match_ue_ip string + var match_gnb_ip *string var match_uplink_teid *uint32 + var match_service_ip *string m := jsonapi.RuleMap{} if stmt, ok := db.stmt["get_all_rules"]; ok { rows, err := stmt.QueryContext(ctx) @@ -186,35 +224,47 @@ func (db *Database) GetRules(ctx context.Context) (jsonapi.RuleMap, error) { // avoid looping if no longer necessary return jsonapi.RuleMap{}, ctx.Err() default: - err := rows.Scan(&uuid, &type_uplink, &enabled, &action_next_hop, pq.Array(&action_srh), &match_ue_ip_prefix, &match_gnb_ip_prefix, &match_uplink_teid) + err := rows.Scan(&uuid, &type_uplink, &enabled, &action_next_hop, pq.Array(&action_srh), &match_ue_ip, &match_gnb_ip, &match_uplink_teid, &match_service_ip) if err != nil { return m, err } - var t string - if type_uplink { - t = "uplink" - } else { - t = "downlink" - } rule := jsonapi.Rule{ Enabled: enabled, - Type: t, + Match: jsonapi.Match{}, } - rule.Match = jsonapi.Match{} - if match_ue_ip_prefix != "" { - p, err := netip.ParsePrefix(match_ue_ip_prefix) - if err == nil { - rule.Match.UEIpPrefix = p + if type_uplink { + rule.Type = "uplink" + rule.Match.Header = &jsonapi.GtpHeader{} + if match_gnb_ip != nil { + p, err := netip.ParsePrefix(*match_gnb_ip) + if err == nil && p.Bits() == 32 { + rule.Match.Header.OuterIpSrc = p.Addr() + } } - } - if match_gnb_ip_prefix != nil { - p, err := netip.ParsePrefix(*match_gnb_ip_prefix) - if err == nil { - rule.Match.GNBIpPrefix = p + if match_uplink_teid != nil { + rule.Match.Header.Teid = *match_uplink_teid } + if match_service_ip != nil { + p, err := netip.ParsePrefix(*match_service_ip) + if err == nil && p.Bits() == 32 { + rule.Match.Payload = &jsonapi.Payload{ + Dst: p.Addr(), + } + } + } + } else { + rule.Type = "downlink" } - if match_uplink_teid != nil { - rule.Match.Teid = *match_uplink_teid + p, err := netip.ParsePrefix(match_ue_ip) + if err == nil && p.Bits() == 32 { + if type_uplink { + a := p.Addr() + rule.Match.Header.InnerIpSrc = &a + } else { + rule.Match.Payload = &jsonapi.Payload{ + Dst: p.Addr(), + } + } } srh, err := jsonapi.NewSRH(action_srh) @@ -276,11 +326,11 @@ func (db *Database) DeleteRule(ctx context.Context, uuid uuid.UUID) error { } } -func (db *Database) GetUplinkAction(ctx context.Context, uplinkTeid uint32, gnbIp netip.Addr) (jsonapi.Action, error) { +func (db *Database) GetUplinkAction(ctx context.Context, uplinkTeid uint32, gnbIp netip.Addr, ueIp netip.Addr, serviceIp netip.Addr) (jsonapi.Action, error) { var action_next_hop string var action_srh []string if stmt, ok := db.stmt["get_uplink_action"]; ok { - err := stmt.QueryRowContext(ctx, uplinkTeid, gnbIp.String()).Scan(&action_next_hop, pq.Array(&action_srh)) + err := stmt.QueryRowContext(ctx, uplinkTeid, gnbIp.String(), ueIp.String(), serviceIp.String()).Scan(&action_next_hop, pq.Array(&action_srh)) if err != nil { return jsonapi.Action{}, err } diff --git a/internal/database/database.sql b/internal/database/database.sql index be6bb0a..830251e 100644 --- a/internal/database/database.sql +++ b/internal/database/database.sql @@ -9,33 +9,35 @@ CREATE TABLE IF NOT EXISTS rule ( enabled BOOL NOT NULL, action_next_hop INET NOT NULL, action_srh INET ARRAY NOT NULL, - match_ue_ip_prefix CIDR NOT NULL, - match_gnb_ip_prefix CIDR, + match_ue_ip CIDR NOT NULL, + match_gnb_ip CIDR, + match_service_ip CIDR, match_uplink_teid INTEGER ); CREATE OR REPLACE PROCEDURE insert_uplink_rule( - IN in_enabled BOOL, IN in_ue_ip_prefix CIDR, - IN in_gnb_ip_prefix CIDR, IN in_uplink_teid INTEGER, + IN in_enabled BOOL, IN in_ue_ip CIDR, + IN in_gnb_ip CIDR, IN in_uplink_teid INTEGER, + IN in_service_ip CIDR, IN in_next_hop INET, IN in_srh INET ARRAY, OUT out_uuid UUID ) LANGUAGE plpgsql AS $$ BEGIN - INSERT INTO rule(type_uplink, enabled, match_ue_ip_prefix, match_gnb_ip_prefix, match_uplink_teid, action_next_hop, action_srh) - VALUES(TRUE, in_enabled, in_ue_ip_prefix, in_gnb_ip_prefix, in_uplink_teid, in_next_hop, in_srh) RETURNING rule.uuid INTO out_uuid; + INSERT INTO rule(type_uplink, enabled, match_ue_ip, match_gnb_ip, match_uplink_teid, match_service_ip, action_next_hop, action_srh) + VALUES(TRUE, in_enabled, in_ue_ip, in_gnb_ip, in_uplink_teid, in_service_ip, in_next_hop, in_srh) RETURNING rule.uuid INTO out_uuid; END;$$; CREATE OR REPLACE PROCEDURE insert_downlink_rule( - IN in_enabled BOOL, IN in_ue_ip_prefix CIDR, + IN in_enabled BOOL, IN in_ue_ip CIDR, IN in_next_hop INET, IN in_srh INET ARRAY, OUT out_uuid UUID ) LANGUAGE plpgsql AS $$ BEGIN - INSERT INTO rule(type_uplink, enabled, match_ue_ip_prefix, action_next_hop, action_srh) - VALUES(FALSE, in_enabled, in_ue_ip_prefix, in_next_hop, in_srh) RETURNING rule.uuid INTO out_uuid; + INSERT INTO rule(type_uplink, enabled, match_ue_ip, action_next_hop, action_srh) + VALUES(FALSE, in_enabled, in_ue_ip, in_next_hop, in_srh) RETURNING rule.uuid INTO out_uuid; END;$$; @@ -74,7 +76,8 @@ BEGIN END;$$; CREATE OR REPLACE FUNCTION get_uplink_action( - IN in_uplink_teid INTEGER, IN in_gnb_ip INET + IN in_uplink_teid INTEGER, IN in_gnb_ip INET, + IN in_ue_ip INET, IN in_service_ip INET ) RETURNS TABLE ( t_action_next_hop INET, @@ -85,7 +88,10 @@ BEGIN RETURN QUERY SELECT rule.action_next_hop AS "t_action_next_hop", rule.action_srh AS "t_action_srh" FROM rule WHERE (rule.match_uplink_teid = in_uplink_teid - AND rule.match_gnb_ip_prefix && in_gnb_ip); + AND rule.match_gnb_ip && in_gnb_ip + AND (rule.match_ue_ip && in_ue_ip) + AND (rule.match_service_ip && in_service_ip) + ); END;$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION get_downlink_action( @@ -100,7 +106,7 @@ BEGIN RETURN QUERY SELECT rule.action_next_hop AS "t_action_next_hop", rule.action_srh AS "t_action_srh" FROM rule WHERE (rule.type_uplink = FALSE AND rule.enabled = TRUE - AND match_ue_ip_prefix && in_ue_ip_address); + AND match_ue_ip && in_ue_ip_address); END;$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION get_rule( @@ -111,15 +117,16 @@ RETURNS TABLE ( t_enabled BOOL, t_action_next_hop INET, t_action_srh INET ARRAY, - t_match_ue_ip_prefix CIDR, - t_match_gnb_ip_prefix CIDR, - t_match_uplink_teid INTEGER + t_match_ue_ip CIDR, + t_match_gnb_ip CIDR, + t_match_uplink_teid INTEGER, + t_match_service_ip CIDR ) AS $$ BEGIN RETURN QUERY SELECT type_uplink AS "t_type_uplink", enabled AS "t_enabled", action_next_hop AS "t_action_next_hop", - action_srh AS "t_action_srh", match_ue_ip_prefix AS "t_match_ue_ip_prefix", match_gnb_ip_prefix AS "t_match_gnb_ip_prefix", - match_uplink_teid AS "t_match_uplink_teid" + action_srh AS "t_action_srh", match_ue_ip AS "t_match_ue_ip", match_gnb_ip AS "t_match_gnb_ip", + match_uplink_teid AS "t_match_uplink_teid", match_service_ip AS "t_match_service_ip" FROM rule WHERE (rule.uuid = in_uuid); END;$$ LANGUAGE plpgsql; @@ -131,15 +138,16 @@ RETURNS TABLE ( t_enabled BOOL, t_action_next_hop INET, t_action_srh INET ARRAY, - t_match_ue_ip_prefix CIDR, - t_match_gnb_ip_prefix CIDR, - t_match_uplink_teid INTEGER + t_match_ue_ip CIDR, + t_match_gnb_ip CIDR, + t_match_uplink_teid INTEGER, + t_match_service_ip CIDR ) AS $$ BEGIN RETURN QUERY SELECT uuid AS "t_uuid", type_uplink AS "t_type_uplink", enabled AS "t_enabled", action_next_hop AS "t_action_next_hop", - action_srh AS "t_action_srh", match_ue_ip_prefix AS "t_match_ue_ip_prefix", match_gnb_ip_prefix AS "t_match_gnb_ip_prefix", - match_uplink_teid AS "t_match_uplink_teid" + action_srh AS "t_action_srh", match_ue_ip AS "t_match_ue_ip", match_gnb_ip AS "t_match_gnb_ip", + match_uplink_teid AS "t_match_uplink_teid", match_service_ip AS "t_match_service_ip" FROM rule; END;$$ LANGUAGE plpgsql; diff --git a/internal/database/database_gen.go b/internal/database/database_gen.go index 751d279..2261708 100644 --- a/internal/database/database_gen.go +++ b/internal/database/database_gen.go @@ -13,13 +13,13 @@ type procedureOrFunction struct { } var procedures = map[string]procedureOrFunction{ - "insert_uplink_rule": {is_procedure: true, num_in: 6, num_out: 1}, + "insert_uplink_rule": {is_procedure: true, num_in: 7, num_out: 1}, "insert_downlink_rule": {is_procedure: true, num_in: 4, num_out: 1}, "enable_rule": {is_procedure: true, num_in: 1, num_out: 0}, "disable_rule": {is_procedure: true, num_in: 1, num_out: 0}, "switch_rule": {is_procedure: true, num_in: 2, num_out: 0}, "delete_rule": {is_procedure: true, num_in: 1, num_out: 0}, - "get_uplink_action": {is_procedure: false, num_in: 2, num_out: 0}, + "get_uplink_action": {is_procedure: false, num_in: 4, num_out: 0}, "get_downlink_action": {is_procedure: false, num_in: 1, num_out: 0}, "get_rule": {is_procedure: false, num_in: 1, num_out: 0}, "get_all_rules": {is_procedure: false, num_in: 0, num_out: 0}, diff --git a/internal/netfunc/headend-gtp4-ctrl.go b/internal/netfunc/headend-gtp4-ctrl.go index cd1bb54..b39a0ee 100644 --- a/internal/netfunc/headend-gtp4-ctrl.go +++ b/internal/netfunc/headend-gtp4-ctrl.go @@ -63,7 +63,19 @@ func (h HeadendGTP4WithCtrl) Handle(ctx context.Context, packet []byte) ([]byte, gtpu := layerGTPU.(*layers.GTPv1U) teid := gtpu.TEID - action, err := h.db.GetUplinkAction(ctx, teid, gnb_ip) + // Check payload is IPv4 + inner, ok := payload.(*layers.IPv4) + if !ok { + return nil, fmt.Errorf("Payload is not IPv4") + } + if inner.Version != 4 { + return nil, fmt.Errorf("Payload is IPv%d instead of IPv4", inner.Version) + } + // Get Inner IPv4 Header Addresses + innerHeaderSrcIPv4 := netip.AddrFrom4([4]byte{inner.SrcIP[0], inner.SrcIP[1], inner.SrcIP[2], inner.SrcIP[3]}) + innerHeaderDstIPv4 := netip.AddrFrom4([4]byte{inner.DstIP[0], inner.DstIP[1], inner.DstIP[2], inner.DstIP[3]}) + + action, err := h.db.GetUplinkAction(ctx, teid, gnb_ip, innerHeaderSrcIPv4, innerHeaderDstIPv4) if err != nil { return nil, err }