gtp: add flags to gtp_tunnel object
Flags tells us what fields have been set in this object.
This is required by
./gtp-tunnel del
otherwise, build helper function adds the MS/UE address and kernel reports
ENOENT, and tunnel identifier is ignored.
Update gtp-tunnel tool to set flowid to zero in the GTP version 0 case,
otherwise kernel reports EINVAL since now this flag is not ever set.
Change-Id: I66677ab2d4de2c459ed9987c465fce6f059d6d93
diff --git a/src/gtp-genl.c b/src/gtp-genl.c
index 447e1ea..3b7c3ef 100644
--- a/src/gtp-genl.c
+++ b/src/gtp-genl.c
@@ -44,42 +44,55 @@
static void gtp_build_payload(struct nlmsghdr *nlh, struct gtp_tunnel *t)
{
- mnl_attr_put_u8(nlh, GTPA_FAMILY, t->ms_addr.family);
- mnl_attr_put_u32(nlh, GTPA_VERSION, t->gtp_version);
- if (t->ifns >= 0)
+ if (t->flags & GTP_TUN_FAMILY)
+ mnl_attr_put_u8(nlh, GTPA_FAMILY, t->ms_addr.family);
+ if (t->flags & GTP_TUN_VERSION)
+ mnl_attr_put_u32(nlh, GTPA_VERSION, t->gtp_version);
+ if (t->flags & GTP_TUN_IFNS)
mnl_attr_put_u32(nlh, GTPA_NET_NS_FD, t->ifns);
- mnl_attr_put_u32(nlh, GTPA_LINK, t->ifidx);
+ if (t->flags & GTP_TUN_IFIDX)
+ mnl_attr_put_u32(nlh, GTPA_LINK, t->ifidx);
- switch (t->ms_addr.family) {
- case AF_INET:
- mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, t->ms_addr.ip4.s_addr);
- break;
- case AF_INET6:
- mnl_attr_put(nlh, GTPA_MS_ADDR6, sizeof(t->ms_addr.ip6), &t->ms_addr.ip6);
- break;
- default:
- /* No addr is set when deleting a tunnel */
- break;
+ if (t->flags & GTP_TUN_MS_ADDR) {
+ switch (t->ms_addr.family) {
+ case AF_INET:
+ mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, t->ms_addr.ip4.s_addr);
+ break;
+ case AF_INET6:
+ mnl_attr_put(nlh, GTPA_MS_ADDR6, sizeof(t->ms_addr.ip6), &t->ms_addr.ip6);
+ break;
+ default:
+ /* No addr is set when deleting a tunnel */
+ break;
+ }
}
- switch (t->sgsn_addr.family) {
- case AF_INET:
- mnl_attr_put_u32(nlh, GTPA_PEER_ADDRESS, t->sgsn_addr.ip4.s_addr);
- break;
- case AF_INET6:
- mnl_attr_put(nlh, GTPA_PEER_ADDR6, sizeof(t->sgsn_addr.ip6), &t->sgsn_addr.ip6);
- break;
- default:
- /* No addr is set when deleting a tunnel */
- break;
+ if (t->flags & GTP_TUN_SGSN_ADDR) {
+ switch (t->sgsn_addr.family) {
+ case AF_INET:
+ mnl_attr_put_u32(nlh, GTPA_PEER_ADDRESS, t->sgsn_addr.ip4.s_addr);
+ break;
+ case AF_INET6:
+ mnl_attr_put(nlh, GTPA_PEER_ADDR6, sizeof(t->sgsn_addr.ip6), &t->sgsn_addr.ip6);
+ break;
+ default:
+ /* No addr is set when deleting a tunnel */
+ break;
+ }
}
- if (t->gtp_version == GTP_V0) {
- mnl_attr_put_u64(nlh, GTPA_TID, t->u.v0.tid);
- mnl_attr_put_u16(nlh, GTPA_FLOW, t->u.v0.flowid);
- } else if (t->gtp_version == GTP_V1) {
- mnl_attr_put_u32(nlh, GTPA_I_TEI, t->u.v1.i_tei);
- mnl_attr_put_u32(nlh, GTPA_O_TEI, t->u.v1.o_tei);
+ if (t->flags & GTP_TUN_VERSION) {
+ if (t->gtp_version == GTP_V0) {
+ if (t->flags & GTP_TUN_V0_TID)
+ mnl_attr_put_u64(nlh, GTPA_TID, t->u.v0.tid);
+ if (t->flags & GTP_TUN_V0_FLOWID)
+ mnl_attr_put_u16(nlh, GTPA_FLOW, t->u.v0.flowid);
+ } else if (t->gtp_version == GTP_V1) {
+ if (t->flags & GTP_TUN_V1_I_TEI)
+ mnl_attr_put_u32(nlh, GTPA_I_TEI, t->u.v1.i_tei);
+ if (t->flags & GTP_TUN_V1_O_TEI)
+ mnl_attr_put_u32(nlh, GTPA_O_TEI, t->u.v1.o_tei);
+ }
}
}
diff --git a/src/gtp.c b/src/gtp.c
index 0c378c4..af216f7 100644
--- a/src/gtp.c
+++ b/src/gtp.c
@@ -49,18 +49,21 @@
void gtp_tunnel_set_ifns(struct gtp_tunnel *t, int ifns)
{
t->ifns = ifns;
+ t->flags |= GTP_TUN_IFNS;
}
EXPORT_SYMBOL(gtp_tunnel_set_ifns);
void gtp_tunnel_set_ifidx(struct gtp_tunnel *t, uint32_t ifidx)
{
t->ifidx = ifidx;
+ t->flags |= GTP_TUN_IFIDX;
}
EXPORT_SYMBOL(gtp_tunnel_set_ifidx);
void gtp_tunnel_set_family(struct gtp_tunnel *t, uint16_t family)
{
t->ms_addr.family = family;
+ t->flags |= GTP_TUN_FAMILY;
}
EXPORT_SYMBOL(gtp_tunnel_set_family);
@@ -68,6 +71,7 @@
{
t->ms_addr.family = AF_INET;
t->ms_addr.ip4 = *ms_addr;
+ t->flags |= GTP_TUN_FAMILY | GTP_TUN_MS_ADDR;
}
EXPORT_SYMBOL(gtp_tunnel_set_ms_ip4);
@@ -75,6 +79,7 @@
{
t->sgsn_addr.family = AF_INET;
t->sgsn_addr.ip4 = *sgsn_addr;
+ t->flags |= GTP_TUN_SGSN_ADDR;
}
EXPORT_SYMBOL(gtp_tunnel_set_sgsn_ip4);
@@ -82,6 +87,7 @@
{
t->ms_addr.family = AF_INET6;
t->ms_addr.ip6 = *ms_addr;
+ t->flags |= GTP_TUN_FAMILY | GTP_TUN_MS_ADDR;
}
EXPORT_SYMBOL(gtp_tunnel_set_ms_ip6);
@@ -89,36 +95,42 @@
{
t->sgsn_addr.family = AF_INET6;
t->sgsn_addr.ip6 = *sgsn_addr;
+ t->flags |= GTP_TUN_SGSN_ADDR;
}
EXPORT_SYMBOL(gtp_tunnel_set_sgsn_ip6);
void gtp_tunnel_set_version(struct gtp_tunnel *t, uint32_t version)
{
t->gtp_version = version;
+ t->flags |= GTP_TUN_VERSION;
}
EXPORT_SYMBOL(gtp_tunnel_set_version);
void gtp_tunnel_set_tid(struct gtp_tunnel *t, uint64_t tid)
{
t->u.v0.tid = tid;
+ t->flags |= GTP_TUN_V0_TID;
}
EXPORT_SYMBOL(gtp_tunnel_set_tid);
void gtp_tunnel_set_flowid(struct gtp_tunnel *t, uint16_t flowid)
{
t->u.v0.flowid = flowid;
+ t->flags |= GTP_TUN_V0_FLOWID;
}
EXPORT_SYMBOL(gtp_tunnel_set_flowid);
void gtp_tunnel_set_i_tei(struct gtp_tunnel *t, uint32_t i_tei)
{
t->u.v1.i_tei = i_tei;
+ t->flags |= GTP_TUN_V1_I_TEI;
}
EXPORT_SYMBOL(gtp_tunnel_set_i_tei);
void gtp_tunnel_set_o_tei(struct gtp_tunnel *t, uint32_t o_tei)
{
t->u.v1.o_tei = o_tei;
+ t->flags |= GTP_TUN_V1_O_TEI;
}
EXPORT_SYMBOL(gtp_tunnel_set_o_tei);
diff --git a/src/internal.h b/src/internal.h
index ce8a683..1433621 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -20,6 +20,19 @@
};
};
+enum {
+ GTP_TUN_IFNS = (1 << 0),
+ GTP_TUN_IFIDX = (1 << 1),
+ GTP_TUN_FAMILY = (1 << 2),
+ GTP_TUN_MS_ADDR = (1 << 3),
+ GTP_TUN_SGSN_ADDR = (1 << 4),
+ GTP_TUN_VERSION = (1 << 5),
+ GTP_TUN_V0_TID = (1 << 6),
+ GTP_TUN_V0_FLOWID = (1 << 7),
+ GTP_TUN_V1_I_TEI = (1 << 8),
+ GTP_TUN_V1_O_TEI = (1 << 9),
+};
+
struct gtp_tunnel {
int ifns;
uint32_t ifidx;
@@ -36,6 +49,7 @@
uint32_t o_tei;
} v1;
} u;
+ uint32_t flags;
};
#endif
diff --git a/tools/gtp-tunnel.c b/tools/gtp-tunnel.c
index 1b8a7a0..8c8f95f 100644
--- a/tools/gtp-tunnel.c
+++ b/tools/gtp-tunnel.c
@@ -109,9 +109,10 @@
optidx++;
- if (gtp_version == GTP_V0)
+ if (gtp_version == GTP_V0) {
gtp_tunnel_set_tid(t, atoi(argv[optidx++]));
- else if (gtp_version == GTP_V1) {
+ gtp_tunnel_set_flowid(t, 0);
+ } else if (gtp_version == GTP_V1) {
gtp_tunnel_set_i_tei(t, atoi(argv[optidx++]));
gtp_tunnel_set_o_tei(t, atoi(argv[optidx++]));
}