Skip to content

Commit

Permalink
Update to use uplink TEID from controller; close #80
Browse files Browse the repository at this point in the history
  • Loading branch information
louisroyer committed Sep 24, 2024
1 parent aaab854 commit 2ce29cf
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 90 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
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.6
github.com/nextmn/json-api v0.0.7
github.com/sirupsen/logrus v1.9.3
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
github.com/urfave/cli/v2 v2.27.4
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ github.com/nextmn/gopacket-srv6 v0.0.8 h1:oP4wuJ7dOiV/gWmX3zoFcdp2dKdSWLUaxH2fJ3
github.com/nextmn/gopacket-srv6 v0.0.8/go.mod h1:2Tyuo9zsG0bP2IhC4tVRgPRuyUqOgrvEEH9seJSZTlU=
github.com/nextmn/json-api v0.0.6 h1:YvYWarvCSX9pHyexy9uOR2IK8xpnsKkIqAALG3k+XMg=
github.com/nextmn/json-api v0.0.6/go.mod h1:gi9IhsD+FFg7iEnJaZtEaY1WlZkQ75KBBk0z5FmSJBU=
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/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
3 changes: 1 addition & 2 deletions internal/database/api/uplink.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ import (
)

type Uplink interface {
GetUplinkAction(ctx context.Context, UplinkTeid uint32, SrgwIp netip.Addr, GnbIp netip.Addr) (jsonapi.Action, error)
SetUplinkAction(ctx context.Context, UplinkTeid uint32, SrgwIp netip.Addr, GnbIp netip.Addr, UeIpAddress netip.Addr) (jsonapi.Action, error)
GetUplinkAction(ctx context.Context, UplinkTeid uint32, GnbIp netip.Addr) (jsonapi.Action, error)
}
34 changes: 8 additions & 26 deletions internal/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func (db *Database) InsertRule(ctx context.Context, r jsonapi.Rule) (*uuid.UUID,
case "uplink":
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.Action.NextHop.String(), pq.Array(srh)).Scan(&id)
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)
return &id, err
} else {
return nil, fmt.Errorf("Procedure not registered")
Expand Down Expand Up @@ -173,6 +173,7 @@ func (db *Database) GetRules(ctx context.Context) (jsonapi.RuleMap, error) {
var action_srh []string
var match_ue_ip_prefix string
var match_gnb_ip_prefix *string
var match_uplink_teid *uint32
m := jsonapi.RuleMap{}
if stmt, ok := db.stmt["get_all_rules"]; ok {
rows, err := stmt.QueryContext(ctx)
Expand All @@ -185,7 +186,7 @@ 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)
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)
if err != nil {
return m, err
}
Expand All @@ -212,6 +213,9 @@ func (db *Database) GetRules(ctx context.Context) (jsonapi.RuleMap, error) {
rule.Match.GNBIpPrefix = p
}
}
if match_uplink_teid != nil {
rule.Match.Teid = *match_uplink_teid
}

srh, err := jsonapi.NewSRH(action_srh)
if err != nil {
Expand Down Expand Up @@ -263,11 +267,11 @@ func (db *Database) DeleteRule(ctx context.Context, uuid uuid.UUID) error {
}
}

func (db *Database) GetUplinkAction(ctx context.Context, uplinkTeid uint32, srgwIp netip.Addr, gnbIp netip.Addr) (jsonapi.Action, error) {
func (db *Database) GetUplinkAction(ctx context.Context, uplinkTeid uint32, gnbIp 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, srgwIp.String(), gnbIp.String()).Scan(&action_next_hop, pq.Array(&action_srh))
err := stmt.QueryRowContext(ctx, uplinkTeid, gnbIp.String()).Scan(&action_next_hop, pq.Array(&action_srh))
if err != nil {
return jsonapi.Action{}, err
}
Expand Down Expand Up @@ -306,25 +310,3 @@ func (db *Database) GetDownlinkAction(ctx context.Context, ueIp netip.Addr) (jso
return jsonapi.Action{}, fmt.Errorf("Procedure not registered")
}
}

func (db *Database) SetUplinkAction(ctx context.Context, uplinkTeid uint32, srgwIp netip.Addr, gnbIp netip.Addr, ueIp netip.Addr) (jsonapi.Action, error) {
var action_next_hop string
var action_srh []string
if stmt, ok := db.stmt["set_uplink_action"]; ok {
err := stmt.QueryRowContext(ctx, uplinkTeid, srgwIp.String(), gnbIp.String(), ueIp.String()).Scan(&action_next_hop, pq.Array(&action_srh))
if err != nil {
return jsonapi.Action{}, err
}
srh, err := jsonapi.NewSRH(action_srh)
if err != nil {
return jsonapi.Action{}, err
}
nh, err := jsonapi.NewNextHop(action_next_hop)
if err != nil {
return jsonapi.Action{}, err
}
return jsonapi.Action{NextHop: *nh, SRH: *srh}, err
} else {
return jsonapi.Action{}, fmt.Errorf("Procedure not registered")
}
}
60 changes: 18 additions & 42 deletions internal/database/database.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,21 @@ CREATE TABLE IF NOT EXISTS rule (
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_gnb_ip_prefix CIDR,
match_uplink_teid INTEGER
);

CREATE TABLE IF NOT EXISTS uplink_gtp4 (
uplink_teid INTEGER,
srgw_ip INET,
gnb_ip INET,
action_uuid UUID REFERENCES rule (uuid) ON DELETE CASCADE,
PRIMARY KEY (uplink_teid, srgw_ip, gnb_ip)
);

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_next_hop INET, IN in_srh INET ARRAY,
IN in_gnb_ip_prefix CIDR, IN in_uplink_teid INTEGER,
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, action_next_hop, action_srh)
VALUES(TRUE, in_enabled, in_ue_ip_prefix, in_gnb_ip_prefix, in_next_hop, in_srh) RETURNING rule.uuid INTO out_uuid;
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;
END;$$;

CREATE OR REPLACE PROCEDURE insert_downlink_rule(
Expand Down Expand Up @@ -58,7 +53,6 @@ CREATE OR REPLACE PROCEDURE disable_rule(
LANGUAGE plpgsql AS $$
BEGIN
UPDATE rule SET enabled = false WHERE rule.uuid = in_uuid;
DELETE FROM uplink_gtp4 WHERE uplink_gtp4.action_uuid = in_uuid;
END;$$;

CREATE OR REPLACE PROCEDURE delete_rule(
Expand All @@ -70,7 +64,7 @@ BEGIN
END;$$;

CREATE OR REPLACE FUNCTION get_uplink_action(
IN in_uplink_teid INTEGER, IN in_srgw_ip INET, IN in_gnb_ip INET
IN in_uplink_teid INTEGER, IN in_gnb_ip INET
)
RETURNS TABLE (
t_action_next_hop INET,
Expand All @@ -79,33 +73,11 @@ RETURNS TABLE (
AS $$
BEGIN
RETURN QUERY SELECT rule.action_next_hop AS "t_action_next_hop", rule.action_srh AS "t_action_srh"
FROM uplink_gtp4, rule
WHERE (uplink_gtp4.uplink_teid = in_uplink_teid
AND uplink_gtp4.srgw_ip = in_srgw_ip
AND uplink_gtp4.gnb_ip = in_gnb_ip
AND rule.uuid = uplink_gtp4.action_uuid);
FROM rule
WHERE (rule.match_uplink_teid = in_uplink_teid
AND rule.match_gnb_ip_prefix && in_gnb_ip);
END;$$ LANGUAGE plpgsql;

CREATE OR REPLACE PROCEDURE set_uplink_action(
IN in_uplink_teid INTEGER, IN in_srgw_ip INET, IN in_gnb_ip INET, IN in_ue_ip_address INET,
OUT out_action_next_hop INET, OUT out_action_srh INET ARRAY
)
LANGUAGE plpgsql AS $$
DECLARE
var_uuid UUID;
BEGIN
SELECT uuid, action_next_hop, action_srh FROM rule
WHERE (rule.type_uplink = TRUE AND rule.enabled = TRUE
AND rule.match_gnb_ip_prefix && in_gnb_ip AND rule.match_ue_ip_prefix && in_ue_ip_address)
INTO var_uuid, out_action_next_hop, out_action_srh
LIMIT 1;
IF not FOUND THEN
RAISE EXCEPTION 'No enabled rule could be found for this set of (srgw, gnb, ue)';
END IF;
INSERT INTO uplink_gtp4(uplink_teid, srgw_ip, gnb_ip, action_uuid)
VALUES(in_uplink_teid, in_srgw_ip, in_gnb_ip, var_uuid);
END;$$;

CREATE OR REPLACE FUNCTION get_downlink_action(
IN in_ue_ip_address INET
)
Expand All @@ -130,12 +102,14 @@ RETURNS TABLE (
t_action_next_hop INET,
t_action_srh INET ARRAY,
t_match_ue_ip_prefix CIDR,
t_match_gnb_ip_prefix CIDR
t_match_gnb_ip_prefix CIDR,
t_match_uplink_teid INTEGER
)
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"
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"
FROM rule
WHERE (rule.uuid = in_uuid);
END;$$ LANGUAGE plpgsql;
Expand All @@ -148,12 +122,14 @@ RETURNS TABLE (
t_action_next_hop INET,
t_action_srh INET ARRAY,
t_match_ue_ip_prefix CIDR,
t_match_gnb_ip_prefix CIDR
t_match_gnb_ip_prefix CIDR,
t_match_uplink_teid INTEGER
)
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"
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"
FROM rule;
END;$$ LANGUAGE plpgsql;
5 changes: 2 additions & 3 deletions internal/database/database_gen.go

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

19 changes: 3 additions & 16 deletions internal/netfunc/headend-gtp4-ctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (h HeadendGTP4WithCtrl) Handle(ctx context.Context, packet []byte) ([]byte,
if err != nil {
return nil, err
}
srgw_ip, err := h.CheckDAInPrefixRange(pqt)
_, err = h.CheckDAInPrefixRange(pqt)
if err != nil {
return nil, err
}
Expand All @@ -60,22 +60,9 @@ func (h HeadendGTP4WithCtrl) Handle(ctx context.Context, packet []byte) ([]byte,
gtpu := layerGTPU.(*layers.GTPv1U)
teid := gtpu.TEID

action, err := h.db.GetUplinkAction(ctx, teid, srgw_ip, gnb_ip)
action, err := h.db.GetUplinkAction(ctx, teid, gnb_ip)
if err != nil {
ue_ip_address, ok := netip.AddrFromSlice(gopacket.NewPacket(payload.LayerContents(), layers.LayerTypeIPv4, gopacket.Default).NetworkLayer().NetworkFlow().Src().Raw())
if !ok {
return nil, fmt.Errorf("Could not extract ue ip address (not IPv4 in payload?)")
}
select {
case <-ctx.Done(): // TODO: check if err is no row instead of checking ctx
return nil, ctx.Err()
default:
action, err = h.db.SetUplinkAction(ctx, teid, srgw_ip, gnb_ip, ue_ip_address)
if err != nil {
return nil, err
}
}

return nil, err
}
// S04. Copy IPv4 SA to form IPv6 SA B'
ipv4SA := pqt.NetworkLayer().NetworkFlow().Src().Raw()
Expand Down

0 comments on commit 2ce29cf

Please sign in to comment.