Skip to content

Commit b77732f

Browse files
committed
gtp: add helper function to build GTP packets from an IPv4 packet
Add routine to attach an IPv4 route for the encapsulated packet, deal with Path MTU and push GTP header. This helper function will be used to deal with IPv6-in-IPv4-GTP. Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 559101a commit b77732f

File tree

1 file changed

+42
-27
lines changed

1 file changed

+42
-27
lines changed

drivers/net/gtp.c

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -983,33 +983,16 @@ static void gtp_set_pktinfo_ipv6(struct gtp_pktinfo *pktinfo,
983983
pktinfo->dev = dev;
984984
}
985985

986-
static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
987-
struct gtp_pktinfo *pktinfo)
986+
static int gtp_build_skb_outer_ip4(struct sk_buff *skb, struct net_device *dev,
987+
struct gtp_pktinfo *pktinfo,
988+
struct pdp_ctx *pctx, __u8 tos,
989+
__be16 frag_off)
988990
{
989-
struct gtp_dev *gtp = netdev_priv(dev);
990-
struct pdp_ctx *pctx;
991991
struct rtable *rt;
992992
struct flowi4 fl4;
993-
struct iphdr *iph;
994993
__be16 df;
995994
int mtu;
996995

997-
/* Read the IP destination address and resolve the PDP context.
998-
* Prepend PDP header with TEI/TID from PDP ctx.
999-
*/
1000-
iph = ip_hdr(skb);
1001-
if (gtp->role == GTP_ROLE_SGSN)
1002-
pctx = ipv4_pdp_find(gtp, iph->saddr);
1003-
else
1004-
pctx = ipv4_pdp_find(gtp, iph->daddr);
1005-
1006-
if (!pctx) {
1007-
netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n",
1008-
&iph->daddr);
1009-
return -ENOENT;
1010-
}
1011-
netdev_dbg(dev, "found PDP context %p\n", pctx);
1012-
1013996
rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->peer.addr.s_addr,
1014997
inet_sk(pctx->sk)->inet_saddr);
1015998
if (IS_ERR(rt)) {
@@ -1027,7 +1010,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
10271010
}
10281011

10291012
/* This is similar to tnl_update_pmtu(). */
1030-
df = iph->frag_off;
1013+
df = frag_off;
10311014
if (df) {
10321015
mtu = dst_mtu(&rt->dst) - dev->hard_header_len -
10331016
sizeof(struct iphdr) - sizeof(struct udphdr);
@@ -1045,7 +1028,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
10451028

10461029
skb_dst_update_pmtu_no_confirm(skb, mtu);
10471030

1048-
if (iph->frag_off & htons(IP_DF) &&
1031+
if (frag_off & htons(IP_DF) &&
10491032
((!skb_is_gso(skb) && skb->len > mtu) ||
10501033
(skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu)))) {
10511034
netdev_dbg(dev, "packet too big, fragmentation needed\n");
@@ -1054,19 +1037,51 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
10541037
goto err_rt;
10551038
}
10561039

1057-
gtp_set_pktinfo_ipv4(pktinfo, pctx->sk, iph->tos, pctx, rt, &fl4, dev);
1040+
gtp_set_pktinfo_ipv4(pktinfo, pctx->sk, tos, pctx, rt, &fl4, dev);
10581041
gtp_push_header(skb, pktinfo);
10591042

1060-
netdev_dbg(dev, "gtp -> IP src: %pI4 dst: %pI4\n",
1061-
&iph->saddr, &iph->daddr);
1062-
10631043
return 0;
10641044
err_rt:
10651045
ip_rt_put(rt);
10661046
err:
10671047
return -EBADMSG;
10681048
}
10691049

1050+
static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
1051+
struct gtp_pktinfo *pktinfo)
1052+
{
1053+
struct gtp_dev *gtp = netdev_priv(dev);
1054+
struct pdp_ctx *pctx;
1055+
struct iphdr *iph;
1056+
int ret;
1057+
1058+
/* Read the IP destination address and resolve the PDP context.
1059+
* Prepend PDP header with TEI/TID from PDP ctx.
1060+
*/
1061+
iph = ip_hdr(skb);
1062+
if (gtp->role == GTP_ROLE_SGSN)
1063+
pctx = ipv4_pdp_find(gtp, iph->saddr);
1064+
else
1065+
pctx = ipv4_pdp_find(gtp, iph->daddr);
1066+
1067+
if (!pctx) {
1068+
netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n",
1069+
&iph->daddr);
1070+
return -ENOENT;
1071+
}
1072+
netdev_dbg(dev, "found PDP context %p\n", pctx);
1073+
1074+
ret = gtp_build_skb_outer_ip4(skb, dev, pktinfo, pctx,
1075+
iph->tos, iph->frag_off);
1076+
if (ret < 0)
1077+
return ret;
1078+
1079+
netdev_dbg(dev, "gtp -> IP src: %pI4 dst: %pI4\n",
1080+
&iph->saddr, &iph->daddr);
1081+
1082+
return 0;
1083+
}
1084+
10701085
static int gtp_build_skb_ip6(struct sk_buff *skb, struct net_device *dev,
10711086
struct gtp_pktinfo *pktinfo)
10721087
{

0 commit comments

Comments
 (0)