Skip to content
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

Source GTP4 for downlink #113

Merged
merged 1 commit into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/lib/pq v1.10.9
github.com/nextmn/gopacket-gtp v0.0.8
github.com/nextmn/gopacket-srv6 v0.0.8
github.com/nextmn/json-api v0.0.16
github.com/nextmn/json-api v0.0.17
github.com/nextmn/logrus-formatter v0.0.1
github.com/nextmn/rfc9433 v0.0.2
github.com/sirupsen/logrus v1.9.3
Expand All @@ -21,14 +21,14 @@ require (

require (
github.com/bytedance/sonic v1.12.7 // indirect
github.com/bytedance/sonic/loader v0.2.2 // indirect
github.com/bytedance/sonic/loader v0.2.3 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/gin-contrib/sse v1.0.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.23.0 // indirect
github.com/go-playground/validator/v10 v10.24.0 // indirect
github.com/goccy/go-json v0.10.4 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
Expand All @@ -46,5 +46,5 @@ require (
golang.org/x/net v0.34.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.21.0 // indirect
google.golang.org/protobuf v1.36.2 // indirect
google.golang.org/protobuf v1.36.3 // indirect
)
16 changes: 8 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ
github.com/bytedance/sonic v1.12.7 h1:CQU8pxOy9HToxhndH0Kx/S1qU/CuS9GnKYrGioDcU1Q=
github.com/bytedance/sonic v1.12.7/go.mod h1:tnbal4mxOMju17EGfknm2XyYcpyCnIROYOEYuemj13I=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.2 h1:jxAJuN9fOot/cyz5Q6dUuMJF5OqQ6+5GfA8FjjQ0R4o=
github.com/bytedance/sonic/loader v0.2.2/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/bytedance/sonic/loader v0.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0=
github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
Expand All @@ -25,8 +25,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg=
github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
Expand Down Expand Up @@ -57,8 +57,8 @@ github.com/nextmn/gopacket-gtp v0.0.8 h1:NF3GRPSdDjmoTeyN584NwbJJJ3tHwPZysZE2ma/
github.com/nextmn/gopacket-gtp v0.0.8/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.16 h1:RU5eTVvnwrYK0Zmh/EhdO7Q3A+hUWjavg9ytJknaYTU=
github.com/nextmn/json-api v0.0.16/go.mod h1:CQXeNPj9MDGsEExtnqJFIGjLgZAKsmOoO2fy+mep7Ak=
github.com/nextmn/json-api v0.0.17 h1:u8Q32fxy7xh1XCGG/QrtZIN/8NVDU6Q9W8CnaMZdZq0=
github.com/nextmn/json-api v0.0.17/go.mod h1:CQXeNPj9MDGsEExtnqJFIGjLgZAKsmOoO2fy+mep7Ak=
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=
Expand Down Expand Up @@ -117,8 +117,8 @@ golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
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.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
google.golang.org/protobuf v1.36.3/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=
Expand Down
65 changes: 56 additions & 9 deletions internal/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,14 @@ func (db *Database) InsertRule(ctx context.Context, r n4tosrv6.Rule) (*uuid.UUID
} else {
dst = r.Match.Payload.Dst.String() + "/32"
}
err := stmt.QueryRowContext(ctx, r.Enabled, dst, pq.Array(srh)).Scan(&id)
src_ipv6 := "::"
if r.Action.SourceGtp4 != nil {
src_ipv6 = r.Action.SourceGtp4.String()
} else {
return nil, fmt.Errorf("Empty SourceGtp4 for downlink Action")
}

err := stmt.QueryRowContext(ctx, r.Enabled, dst, pq.Array(srh), src_ipv6).Scan(&id)
return &id, err
} else {
return nil, fmt.Errorf("Procedure not registered")
Expand All @@ -139,13 +146,14 @@ func (db *Database) GetRule(ctx context.Context, uuid uuid.UUID) (n4tosrv6.Rule,
var type_uplink bool
var enabled bool
var action_srh []string
var action_source_gtp4 *string
var match_ue_ip string
var match_gnb_ip []string
var match_service_ip *string
var match_uplink_teid *uint32
var match_uplink_upf *string
if stmt, ok := db.stmt["get_rule"]; ok {
err := stmt.QueryRowContext(ctx, uuid.String()).Scan(&type_uplink, &enabled, pq.Array(&action_srh), &match_ue_ip, pq.Array(&match_gnb_ip), &match_uplink_teid, &match_uplink_upf, &match_service_ip)
err := stmt.QueryRowContext(ctx, uuid.String()).Scan(&type_uplink, &enabled, pq.Array(&action_srh), &action_source_gtp4, &match_ue_ip, pq.Array(&match_gnb_ip), &match_uplink_teid, &match_uplink_upf, &match_service_ip)
if err != nil {
return n4tosrv6.Rule{}, err
}
Expand Down Expand Up @@ -202,8 +210,18 @@ func (db *Database) GetRule(ctx context.Context, uuid uuid.UUID) (n4tosrv6.Rule,
return n4tosrv6.Rule{}, err
}

if action_source_gtp4 == nil {
return n4tosrv6.Rule{}, fmt.Errorf("Empty SourceGtp4 for downlink rule")
}

source_gtp4, err := netip.ParseAddr(*action_source_gtp4)
if err != nil {
return n4tosrv6.Rule{}, err
}

rule.Action = n4tosrv6.Action{
SRH: *srh,
SRH: *srh,
SourceGtp4: &source_gtp4,
}

return rule, err
Expand All @@ -217,6 +235,7 @@ func (db *Database) GetRules(ctx context.Context) (n4tosrv6.RuleMap, error) {
var type_uplink bool
var enabled bool
var action_srh []string
var action_source_gtp4 *string
var match_ue_ip string
var match_gnb_ip []string
var match_uplink_teid *uint32
Expand All @@ -234,7 +253,7 @@ func (db *Database) GetRules(ctx context.Context) (n4tosrv6.RuleMap, error) {
// avoid looping if no longer necessary
return n4tosrv6.RuleMap{}, ctx.Err()
default:
err := rows.Scan(&uuid, &type_uplink, &enabled, pq.Array(&action_srh), &match_ue_ip, pq.Array(&match_gnb_ip), &match_uplink_teid, &match_uplink_upf, &match_service_ip)
err := rows.Scan(&uuid, &type_uplink, &enabled, pq.Array(&action_srh), &action_source_gtp4, &match_ue_ip, pq.Array(&match_gnb_ip), &match_uplink_teid, &match_uplink_upf, &match_service_ip)
if err != nil {
return m, err
}
Expand Down Expand Up @@ -285,14 +304,23 @@ func (db *Database) GetRules(ctx context.Context) (n4tosrv6.RuleMap, error) {
}
}
}
if action_source_gtp4 == nil {
return n4tosrv6.RuleMap{}, fmt.Errorf("Empty SourceGtp4 for downlink rule")
}

source_gtp4, err := netip.ParseAddr(*action_source_gtp4)
if err != nil {
return n4tosrv6.RuleMap{}, err
}

srh, err := n4tosrv6.NewSRH(action_srh)
if err != nil {
return n4tosrv6.RuleMap{}, err
}

rule.Action = n4tosrv6.Action{
SRH: *srh,
SRH: *srh,
SourceGtp4: &source_gtp4,
}
m[uuid] = rule
}
Expand Down Expand Up @@ -351,36 +379,55 @@ func (db *Database) GetUplinkAction(ctx context.Context, uplinkFTeid jsonapi.Fte
if err != nil {
return n4tosrv6.Action{}, err
}
return n4tosrv6.Action{SRH: *srh}, err
return n4tosrv6.Action{
SRH: *srh,
}, err
} else {
return n4tosrv6.Action{}, fmt.Errorf("Procedure not registered")
}
}

func (db *Database) GetDownlinkAction(ctx context.Context, ueIp netip.Addr) (n4tosrv6.Action, error) {
var action_srh []string
var action_source_gtp4 *string
if stmt, ok := db.stmt["get_downlink_action"]; ok {
err := stmt.QueryRowContext(ctx, ueIp.String()).Scan(pq.Array(&action_srh))
err := stmt.QueryRowContext(ctx, ueIp.String()).Scan(pq.Array(&action_srh), &action_source_gtp4)
if err != nil {
return n4tosrv6.Action{}, err
}
srh, err := n4tosrv6.NewSRH(action_srh)
if err != nil {
return n4tosrv6.Action{}, err
}
return n4tosrv6.Action{SRH: *srh}, err
if action_source_gtp4 == nil {
return n4tosrv6.Action{}, fmt.Errorf("Empty SourceGtp4 for downlink rule")
}
source_gtp4, err := netip.ParseAddr(*action_source_gtp4)
if err != nil {
return n4tosrv6.Action{}, err
}
return n4tosrv6.Action{
SRH: *srh,
SourceGtp4: &source_gtp4,
}, err
} else {
return n4tosrv6.Action{}, fmt.Errorf("Procedure not registered")
}
}

func (db *Database) UpdateAction(ctx context.Context, uuidRule uuid.UUID, action n4tosrv6.Action) error {
srh := []string{}
source_gtp4 := "::"
if action.SourceGtp4 != nil {
source_gtp4 = action.SourceGtp4.String()
} else {
return fmt.Errorf("Empty SourceGtp4 for downlink rule")
}
for _, ip := range action.SRH {
srh = append(srh, ip.String())
}
if stmt, ok := db.stmt["update_action"]; ok {
_, err := stmt.ExecContext(ctx, uuidRule.String(), pq.Array(srh))
_, err := stmt.ExecContext(ctx, uuidRule.String(), pq.Array(srh), source_gtp4)
return err
} else {
return fmt.Errorf("Procedure not registered")
Expand Down
23 changes: 16 additions & 7 deletions internal/database/database.sql
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ CREATE TABLE IF NOT EXISTS rule (
type_uplink BOOL NOT NULL,
enabled BOOL NOT NULL,
action_srh INET ARRAY NOT NULL,
action_source_gtp4 INET,
match_ue_ip CIDR NOT NULL,
match_gnb_ip CIDR ARRAY,
match_service_ip CIDR,
Expand All @@ -33,12 +34,13 @@ END;$$;
CREATE OR REPLACE PROCEDURE insert_downlink_rule(
IN in_enabled BOOL, IN in_ue_ip CIDR,
IN in_srh INET ARRAY,
IN in_source_gtp4 INET,
OUT out_uuid UUID
)
LANGUAGE plpgsql AS $$
BEGIN
INSERT INTO rule(type_uplink, enabled, match_ue_ip, action_srh)
VALUES(FALSE, in_enabled, in_ue_ip, in_srh) RETURNING rule.uuid INTO out_uuid;
INSERT INTO rule(type_uplink, enabled, match_ue_ip, action_srh, action_source_gtp4)
VALUES(FALSE, in_enabled, in_ue_ip, in_srh, in_source_gtp4) RETURNING rule.uuid INTO out_uuid;
END;$$;


Expand Down Expand Up @@ -78,11 +80,13 @@ END;$$;

CREATE OR REPLACE PROCEDURE update_action(
IN in_uuid UUID,
IN in_srh INET ARRAY
IN in_srh INET ARRAY,
IN in_source_gtp4 INET
)
LANGUAGE plpgsql AS $$
BEGIN
UPDATE rule SET action_srh = in_srh WHERE rule.uuid = in_uuid;
UPDATE rule SET action_source_gtp4 = in_source_gtp4 WHERE rule.uuid = in_uuid;
END;$$;

CREATE OR REPLACE FUNCTION get_uplink_action(
Expand Down Expand Up @@ -111,11 +115,12 @@ CREATE OR REPLACE FUNCTION get_downlink_action(
IN in_ue_ip_address INET
)
RETURNS TABLE (
t_action_srh INET ARRAY
t_action_srh INET ARRAY,
t_action_source_gtp4 INET
)
AS $$
BEGIN
RETURN QUERY SELECT rule.action_srh AS "t_action_srh"
RETURN QUERY SELECT rule.action_srh AS "t_action_srh", rule.action_source_gtp4 AS "t_action_source_gtp4"
FROM rule
WHERE (rule.type_uplink = FALSE AND rule.enabled = TRUE
AND match_ue_ip && in_ue_ip_address);
Expand All @@ -128,6 +133,7 @@ RETURNS TABLE (
t_type_uplink BOOL,
t_enabled BOOL,
t_action_srh INET ARRAY,
t_action_source_gtp4 INET,
t_match_ue_ip CIDR,
t_match_gnb_ip CIDR ARRAY,
t_match_uplink_teid BIGINT,
Expand All @@ -137,7 +143,8 @@ RETURNS TABLE (
AS $$
BEGIN
RETURN QUERY SELECT type_uplink AS "t_type_uplink", enabled AS "t_enabled",
action_srh AS "t_action_srh", match_ue_ip AS "t_match_ue_ip", match_gnb_ip AS "t_match_gnb_ip",
action_srh AS "t_action_srh", action_source_gtp4 AS "t_action_source_gtp4",
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_uplink_upf AS "t_match_uplink_upf",
match_service_ip AS "t_match_service_ip"
FROM rule
Expand All @@ -150,6 +157,7 @@ RETURNS TABLE (
t_type_uplink BOOL,
t_enabled BOOL,
t_action_srh INET ARRAY,
t_action_source_gtp4 INET,
t_match_ue_ip CIDR,
t_match_gnb_ip CIDR ARRAY,
t_match_uplink_teid BIGINT,
Expand All @@ -160,7 +168,8 @@ AS $$
BEGIN
RETURN QUERY SELECT uuid AS "t_uuid", type_uplink AS "t_type_uplink",
enabled AS "t_enabled",
action_srh AS "t_action_srh", match_ue_ip AS "t_match_ue_ip", match_gnb_ip AS "t_match_gnb_ip",
action_srh AS "t_action_srh", action_source_gtp4 AS "t_action_source_gtp4",
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_uplink_upf AS "t_match_uplink_upf",
match_service_ip AS "t_match_service_ip"
FROM rule;
Expand Down
4 changes: 2 additions & 2 deletions internal/database/database_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion internal/netfunc/headend-encaps-ctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ func (h HeadendEncapsWithCtrl) Handle(ctx context.Context, packet []byte) ([]byt
if err != nil {
return nil, err
}
srgw_gtp_ip := netip.MustParseAddr("10.3.0.1") // FIXME: dont hardcode
if action.SourceGtp4 == nil {
return nil, fmt.Errorf("Empty SourceGtp4 for downlink Action")
}
srgw_gtp_ip := *action.SourceGtp4
ipv6Src := encoding.NewMGTP4IPv6Src(h.srcPrefix, srgw_gtp_ip.As4(), 2152) // FIXME:dont hardcode udp port number to 2152
src, err := ipv6Src.Marshal()
if err != nil {
Expand Down
Loading