[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240823201557.1794985-13-tom@herbertland.com>
Date: Fri, 23 Aug 2024 13:15:56 -0700
From: Tom Herbert <tom@...bertland.com>
To: davem@...emloft.net,
kuba@...nel.org,
edumazet@...gle.com,
netdev@...r.kernel.org,
felipe@...anda.io,
willemdebruijn.kernel@...il.com,
pablo@...filter.org,
laforge@...monks.org,
xeb@...l.ru
Cc: Tom Herbert <tom@...bertland.com>
Subject: [PATCH net-next v4 12/13] flow_dissector: Parse gtp in UDP
Parse both version 0 and 1. Call __skb_direct_ip_dissect to determine
IP version of the encapsulated packet
Signed-off-by: Tom Herbert <tom@...bertland.com>
---
net/core/flow_dissector.c | 97 +++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index b59a9e896a31..ae56de7d420a 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -9,6 +9,7 @@
#include <net/dsa.h>
#include <net/dst_metadata.h>
#include <net/fou.h>
+#include <net/gtp.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/geneve.h>
@@ -35,6 +36,7 @@
#include <net/pkt_cls.h>
#include <scsi/fc/fc_fcoe.h>
#include <uapi/linux/batadv_packet.h>
+#include <uapi/linux/gtp.h>
#include <linux/bpf.h>
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
#include <net/netfilter/nf_conntrack_core.h>
@@ -876,6 +878,91 @@ __skb_flow_dissect_gue(const struct sk_buff *skb,
return FLOW_DISSECT_RET_IPPROTO_AGAIN;
}
+static enum flow_dissect_ret
+__skb_flow_dissect_gtp0(const struct sk_buff *skb,
+ struct flow_dissector *flow_dissector,
+ void *target_container, const void *data,
+ __u8 *p_ip_proto, int *p_nhoff, int hlen,
+ unsigned int flags)
+{
+ __u8 *ip_version, _ip_version, proto;
+ struct gtp0_header *hdr, _hdr;
+
+ hdr = __skb_header_pointer(skb, *p_nhoff, sizeof(_hdr), data, hlen,
+ &_hdr);
+ if (!hdr)
+ return FLOW_DISSECT_RET_OUT_BAD;
+
+ if ((hdr->flags >> 5) != GTP_V0)
+ return FLOW_DISSECT_RET_OUT_GOOD;
+
+ ip_version = skb_header_pointer(skb, *p_nhoff + sizeof(_hdr),
+ sizeof(*ip_version),
+ &_ip_version);
+ if (!ip_version)
+ return FLOW_DISSECT_RET_OUT_BAD;
+
+ proto = __skb_direct_ip_dissect(ip_version);
+ if (!proto)
+ return FLOW_DISSECT_RET_OUT_GOOD;
+
+ *p_ip_proto = proto;
+ *p_nhoff += sizeof(struct gtp0_header);
+
+ return FLOW_DISSECT_RET_IPPROTO_AGAIN;
+}
+
+static enum flow_dissect_ret
+__skb_flow_dissect_gtp1u(const struct sk_buff *skb,
+ struct flow_dissector *flow_dissector,
+ void *target_container, const void *data,
+ __u8 *p_ip_proto, int *p_nhoff, int hlen,
+ unsigned int flags)
+{
+ __u8 *ip_version, _ip_version, proto;
+ struct gtp1_header *hdr, _hdr;
+ int hdrlen = sizeof(_hdr);
+
+ hdr = __skb_header_pointer(skb, *p_nhoff, sizeof(_hdr), data, hlen,
+ &_hdr);
+ if (!hdr)
+ return FLOW_DISSECT_RET_OUT_BAD;
+
+ if ((hdr->flags >> 5) != GTP_V1)
+ return FLOW_DISSECT_RET_OUT_GOOD;
+
+ if (hdr->type != GTP_TPDU)
+ return FLOW_DISSECT_RET_OUT_GOOD;
+
+ if (hdr->flags & GTP1_F_MASK)
+ hdrlen += 4;
+
+ /* Skip over GTP extension headers if they are present */
+ if (hdr->flags & GTP1_F_EXTHDR &&
+ gtp_parse_exthdrs(skb, &hdrlen) < 0)
+ return FLOW_DISSECT_RET_OUT_BAD;
+
+ /* Exit if either NPDU or SEQ glags are set */
+ if (hdr->flags & GTP1_F_NPDU ||
+ hdr->flags & GTP1_F_SEQ)
+ return FLOW_DISSECT_RET_OUT_GOOD;
+
+ ip_version = skb_header_pointer(skb, *p_nhoff + hdrlen,
+ sizeof(*ip_version),
+ &_ip_version);
+ if (!ip_version)
+ return FLOW_DISSECT_RET_OUT_GOOD;
+
+ proto = __skb_direct_ip_dissect(ip_version);
+ if (!proto)
+ return FLOW_DISSECT_RET_OUT_GOOD;
+
+ *p_ip_proto = proto;
+ *p_nhoff += hdrlen;
+
+ return FLOW_DISSECT_RET_IPPROTO_AGAIN;
+}
+
/**
* __skb_flow_dissect_batadv() - dissect batman-adv header
* @skb: sk_buff to with the batman-adv header
@@ -1053,6 +1140,16 @@ __skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
*p_ip_proto = IPPROTO_L2TP;
ret = FLOW_DISSECT_RET_IPPROTO_AGAIN;
break;
+ case UDP_ENCAP_GTP0:
+ ret = __skb_flow_dissect_gtp0(skb, flow_dissector,
+ target_container, data,
+ p_ip_proto, &nhoff, hlen, flags);
+ break;
+ case UDP_ENCAP_GTP1U:
+ ret = __skb_flow_dissect_gtp1u(skb, flow_dissector,
+ target_container, data,
+ p_ip_proto, &nhoff, hlen, flags);
+ break;
case UDP_ENCAP_FOU:
*p_ip_proto = fou_protocol;
ret = FLOW_DISSECT_RET_IPPROTO_AGAIN;
--
2.34.1
Powered by blists - more mailing lists