gtp: set flow ID for PDP context created throught GTPv0
This field is very important, downlink and uplink packet shall use the same flow ID.
This commit is contained in:
parent
9b649117b6
commit
a03b3754d6
29
gtp.c
29
gtp.c
|
@ -430,7 +430,7 @@ gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx, int payload_len)
|
||||||
gtp0->type = GTP_TPDU;
|
gtp0->type = GTP_TPDU;
|
||||||
gtp0->length = htons(payload_len);
|
gtp0->length = htons(payload_len);
|
||||||
gtp0->seq = htons((atomic_inc_return(&pctx->tx_seq)-1) % 0xffff);
|
gtp0->seq = htons((atomic_inc_return(&pctx->tx_seq)-1) % 0xffff);
|
||||||
gtp0->flow = htonl(pctx->flow);
|
gtp0->flow = htons(pctx->flow);
|
||||||
gtp0->number = 0xFF;
|
gtp0->number = 0xFF;
|
||||||
gtp0->spare[0] = gtp0->spare[1] = gtp0->spare[2] = 0xFF;
|
gtp0->spare[0] = gtp0->spare[1] = gtp0->spare[2] = 0xFF;
|
||||||
gtp0->tid = cpu_to_be64(pctx->tid);
|
gtp0->tid = cpu_to_be64(pctx->tid);
|
||||||
|
@ -952,10 +952,9 @@ static struct net_device *gtp_find_dev(int ifindex)
|
||||||
static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info)
|
static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct gtp_instance *gti = netdev_priv(dev);
|
struct gtp_instance *gti = netdev_priv(dev);
|
||||||
u32 hash_ms;
|
|
||||||
u32 hash_tid;
|
|
||||||
struct pdp_ctx *pctx;
|
struct pdp_ctx *pctx;
|
||||||
u32 gtp_version, link, sgsn_addr, ms_addr;
|
u16 flow = 0;
|
||||||
|
u32 gtp_version, link, sgsn_addr, ms_addr, hash_ms, hash_tid;
|
||||||
u64 tid;
|
u64 tid;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
|
@ -973,6 +972,17 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info)
|
||||||
if (gtp_version == GTP_V1 && tid > UINT_MAX)
|
if (gtp_version == GTP_V1 && tid > UINT_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* According to TS 09.60, sections 7.5.1 and 7.5.2, the flow label
|
||||||
|
* needs to be the same for uplink and downlink packets, so let's
|
||||||
|
* annotate this.
|
||||||
|
*/
|
||||||
|
if (gtp_version == GTP_V0) {
|
||||||
|
if (!info->attrs[GTPA_FLOW])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
flow = nla_get_u16(info->attrs[GTPA_FLOW]);
|
||||||
|
}
|
||||||
|
|
||||||
link = nla_get_u32(info->attrs[GTPA_LINK]);
|
link = nla_get_u32(info->attrs[GTPA_LINK]);
|
||||||
sgsn_addr = nla_get_u32(info->attrs[GTPA_SGSN_ADDRESS]);
|
sgsn_addr = nla_get_u32(info->attrs[GTPA_SGSN_ADDRESS]);
|
||||||
ms_addr = nla_get_u32(info->attrs[GTPA_MS_ADDRESS]);
|
ms_addr = nla_get_u32(info->attrs[GTPA_MS_ADDRESS]);
|
||||||
|
@ -1013,10 +1023,16 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info)
|
||||||
pctx->tid = tid;
|
pctx->tid = tid;
|
||||||
pctx->sgsn_addr.ip4.s_addr = sgsn_addr;
|
pctx->sgsn_addr.ip4.s_addr = sgsn_addr;
|
||||||
pctx->ms_addr.ip4.s_addr = ms_addr;
|
pctx->ms_addr.ip4.s_addr = ms_addr;
|
||||||
|
pctx->flow = flow;
|
||||||
atomic_set(&pctx->tx_seq, 0);
|
atomic_set(&pctx->tx_seq, 0);
|
||||||
|
|
||||||
switch (gtp_version) {
|
switch (gtp_version) {
|
||||||
case GTP_V0:
|
case GTP_V0:
|
||||||
|
/* TS 09.60: "The flow label identifies unambiguously a GTP
|
||||||
|
* flow.". We use the tid for this instead, I cannot find a
|
||||||
|
* situation in which this doesn't unambiguosly identify the
|
||||||
|
* PDP context.
|
||||||
|
*/
|
||||||
hash_tid = gtp0_hashfn(tid) % gti->hash_size;
|
hash_tid = gtp0_hashfn(tid) % gti->hash_size;
|
||||||
break;
|
break;
|
||||||
case GTP_V1:
|
case GTP_V1:
|
||||||
|
@ -1131,7 +1147,9 @@ gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
|
||||||
if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) ||
|
if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) ||
|
||||||
nla_put_u32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr.ip4.s_addr) ||
|
nla_put_u32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr.ip4.s_addr) ||
|
||||||
nla_put_u32(skb, GTPA_MS_ADDRESS, pctx->ms_addr.ip4.s_addr) ||
|
nla_put_u32(skb, GTPA_MS_ADDRESS, pctx->ms_addr.ip4.s_addr) ||
|
||||||
nla_put_u64(skb, GTPA_TID, pctx->tid))
|
nla_put_u64(skb, GTPA_TID, pctx->tid) ||
|
||||||
|
(pctx->gtp_version == GTP_V0 &&
|
||||||
|
nla_put_u16(skb, GTPA_FLOW, pctx->flow)))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
return genlmsg_end(skb, genlh);
|
return genlmsg_end(skb, genlh);
|
||||||
|
@ -1269,6 +1287,7 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = {
|
||||||
[GTPA_TID] = { .type = NLA_U64, },
|
[GTPA_TID] = { .type = NLA_U64, },
|
||||||
[GTPA_SGSN_ADDRESS] = { .type = NLA_NESTED, },
|
[GTPA_SGSN_ADDRESS] = { .type = NLA_NESTED, },
|
||||||
[GTPA_MS_ADDRESS] = { .type = NLA_NESTED, },
|
[GTPA_MS_ADDRESS] = { .type = NLA_NESTED, },
|
||||||
|
[GTPA_FLOW] = { .type = NLA_U16, },
|
||||||
};
|
};
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
|
||||||
|
|
1
gtp_nl.h
1
gtp_nl.h
|
@ -39,6 +39,7 @@ enum gtp_attrs {
|
||||||
GTPA_TID, /* 64 bits for GTPv1 */
|
GTPA_TID, /* 64 bits for GTPv1 */
|
||||||
GTPA_SGSN_ADDRESS,
|
GTPA_SGSN_ADDRESS,
|
||||||
GTPA_MS_ADDRESS,
|
GTPA_MS_ADDRESS,
|
||||||
|
GTPA_FLOW,
|
||||||
__GTPA_MAX,
|
__GTPA_MAX,
|
||||||
};
|
};
|
||||||
#define GTPA_MAX (__GTPA_MAX + 1)
|
#define GTPA_MAX (__GTPA_MAX + 1)
|
||||||
|
|
Loading…
Reference in New Issue