netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols
@ 2024-08-15 21:45 Tom Herbert
  2024-08-15 21:45 ` [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE Tom Herbert
                   ` (12 more replies)
  0 siblings, 13 replies; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

Add support in flow_dissector for dissecting into UDP
encapsulations like VXLAN. __skb_flow_dissect_udp is called for
IPPROTO_UDP. The flag FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS enables parsing
of UDP encapsulations. If the flag is set when parsing a UDP packet then
a socket lookup is performed. The offset of the base network header,
either an IPv4 or IPv6 header, is tracked and passed to
__skb_flow_dissect_udp so that it can perform the socket lookup.
If a socket is found and it's for a UDP encapsulation (encap_type is
set in the UDP socket) then a switch is performed on the encap_type
value (cases are UDP_ENCAP_* values)

Changes in the patch set:

- Unconstantify struct net argument in flowdis functions so we can call
  UDP socket lookup functions
- Dissect ETH_P_TEB in main flow dissector loop, move ETH_P_TEB check
  out of __skb_flow_dissect_gre and process it in main loop
- Add UDP_ENCAP constants for tipc, fou, gue, sctp, rxe, pfcp,
  wireguard, bareudp, vxlan, vxlan_gpe, geneve, and amt
- For the various UDP encapsulation protocols, Instead of just setting
  UDP tunnel encap type to 1, set it to the corresponding UDP_ENCAP
  constant. This allows identify the encapsulation protocol for a
  UDP socket by the encap_type
- Add function __skb_flow_dissect_udp in flow_dissector and call it for
  UDP packets. If a UDP encapsulation is present then the function
  returns either FLOW_DISSECT_RET_PROTO_AGAIN or
  FLOW_DISSECT_RET_IPPROTO_AGAIN
- Add flag FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS that indicates UDP
  encapsulations should be dissected
- Add __skb_flow_dissect_vxlan which is called when encap_type is
  UDP_ENCAP_VXLAN or UDP_ENCAP_VXLAN_GPE. Dissect VXLAN and return
  a next protocol and offset
- Add __skb_flow_dissect_fou which is called when encap_type is
  UDP_ENCAP_FOU. Dissect FOU and return a next protocol and offset
- Add support for ESP, L2TP, and SCTP in UDP in __skb_flow_dissect_udp.
  All we need to do is return FLOW_DISSECT_RET_IPPROTO_AGAIN and the
  corresponding IP protocol number
- Add __skb_flow_dissect_geneve which is called when encap_type is
  UDP_ENCAP_GENEVE. Dissect geneve and return a next protocol and offset
- Add __skb_flow_dissect_gue which is called when encap_type is
  UDP_ENCAP_GUE. Dissect gue and return a next protocol and offset
- Add __skb_flow_dissect_gtp which is called when encap_type is
  UDP_ENCAP_GTP. Dissect gtp and return a next protocol and offset

Tested: Verified fou, gue, vxlan, and geneve are properly dissected for
IPv4 and IPv6 cases. This includes testing ETH_P_TEB case

v2:
- Add #if IS_ENABLED(CONFIG_IPV6) around IPv6 cases when dissecting UDP.
  Also, c all ipv6_bpf_stub->udp6_lib_lookup instead of udp6_lib_lookup
  directly since udp6_lib_lookup in the IPv6 module
- Drop patch to unconstantify struct net argument in flowdis functions,
  edumazet added const to ne argument in UDP socket lookup functions
- As support in flowdis ipproto switch for no-next-hdr. Just exit
  flowdis on good result when this is seen
- Merge patches that move TEB processing out of GRE and moved into
  main protocol switch
- Rename bpoff in UDP flow dissector functions to be base_nhoff for
  clarity
- Parse GTPv1 extension headers (part of this is moving
  gtp_parse_exthdrs to a header file
- Exit flowdis on good result if NPDU or SEQ GTPv1 flags are set


Tom Herbert (12):
  flow_dissector: Parse ETH_P_TEB and move out of GRE
  udp_encaps: Add new UDP_ENCAP constants
  udp_encaps: Set proper UDP_ENCAP types in tunnel setup
  flow_dissector: UDP encap infrastructure
  flow_dissector: Parse vxlan in UDP
  flow_dissector: Parse foo-over-udp (FOU)
  flow_dissector: Parse ESP, L2TP, and SCTP in UDP
  flow_dissector: Parse Geneve in UDP
  flow_dissector: Parse GUE in UDP
  gtp: Move gtp_parse_exthdrs into net/gtp.h
  flow_dissector: Parse gtp in UDP
  flow_dissector: Add case in ipproto switch for NEXTHDR_NONE

 drivers/infiniband/sw/rxe/rxe_net.c |   2 +-
 drivers/net/amt.c                   |   2 +-
 drivers/net/bareudp.c               |   2 +-
 drivers/net/geneve.c                |   2 +-
 drivers/net/gtp.c                   |  37 ---
 drivers/net/pfcp.c                  |   2 +-
 drivers/net/vxlan/vxlan_core.c      |   3 +-
 drivers/net/wireguard/socket.c      |   2 +-
 include/net/flow_dissector.h        |   1 +
 include/net/fou.h                   |  16 +
 include/net/gtp.h                   |  38 +++
 include/uapi/linux/udp.h            |  13 +
 net/core/flow_dissector.c           | 448 ++++++++++++++++++++++++++--
 net/ipv4/fou_core.c                 |  19 +-
 net/sctp/protocol.c                 |   2 +-
 net/tipc/udp_media.c                |   2 +-
 16 files changed, 502 insertions(+), 89 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-16 18:54   ` Willem de Bruijn
  2024-08-15 21:45 ` [PATCH net-next v2 02/12] udp_encaps: Add new UDP_ENCAP constants Tom Herbert
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

ETH_P_TEB (Trans Ether Bridging) is the EtherType to carry
a plain Etherent frame. Add case in skb_flow_dissect to parse
packets of this type

If the GRE protocol is ETH_P_TEB then just process that as any
another EtherType since it's now supported in the main loop

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/core/flow_dissector.c | 57 +++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 26 deletions(-)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 0e638a37aa09..4b116119086a 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -654,7 +654,7 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
 		       struct flow_dissector_key_control *key_control,
 		       struct flow_dissector *flow_dissector,
 		       void *target_container, const void *data,
-		       __be16 *p_proto, int *p_nhoff, int *p_hlen,
+		       __be16 *p_proto, int *p_nhoff, int hlen,
 		       unsigned int flags)
 {
 	struct flow_dissector_key_keyid *key_keyid;
@@ -663,7 +663,7 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
 	u16 gre_ver;
 
 	hdr = __skb_header_pointer(skb, *p_nhoff, sizeof(_hdr),
-				   data, *p_hlen, &_hdr);
+				   data, hlen, &_hdr);
 	if (!hdr)
 		return FLOW_DISSECT_RET_OUT_BAD;
 
@@ -695,7 +695,7 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
 
 		keyid = __skb_header_pointer(skb, *p_nhoff + offset,
 					     sizeof(_keyid),
-					     data, *p_hlen, &_keyid);
+					     data, hlen, &_keyid);
 		if (!keyid)
 			return FLOW_DISSECT_RET_OUT_BAD;
 
@@ -715,27 +715,11 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
 	if (hdr->flags & GRE_SEQ)
 		offset += sizeof_field(struct pptp_gre_header, seq);
 
-	if (gre_ver == 0) {
-		if (*p_proto == htons(ETH_P_TEB)) {
-			const struct ethhdr *eth;
-			struct ethhdr _eth;
-
-			eth = __skb_header_pointer(skb, *p_nhoff + offset,
-						   sizeof(_eth),
-						   data, *p_hlen, &_eth);
-			if (!eth)
-				return FLOW_DISSECT_RET_OUT_BAD;
-			*p_proto = eth->h_proto;
-			offset += sizeof(*eth);
-
-			/* Cap headers that we access via pointers at the
-			 * end of the Ethernet header as our maximum alignment
-			 * at that point is only 2 bytes.
-			 */
-			if (NET_IP_ALIGN)
-				*p_hlen = *p_nhoff + offset;
-		}
-	} else { /* version 1, must be PPTP */
+	/* For GRE version 0 p_proto is already correctly set (including if
+	 * it is ETH_P_TEB)
+	 */
+
+	if (gre_ver == 1) { /* Version 1 is PPP */
 		u8 _ppp_hdr[PPP_HDRLEN];
 		u8 *ppp_hdr;
 
@@ -744,7 +728,7 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
 
 		ppp_hdr = __skb_header_pointer(skb, *p_nhoff + offset,
 					       sizeof(_ppp_hdr),
-					       data, *p_hlen, _ppp_hdr);
+					       data, hlen, _ppp_hdr);
 		if (!ppp_hdr)
 			return FLOW_DISSECT_RET_OUT_BAD;
 
@@ -1284,6 +1268,27 @@ bool __skb_flow_dissect(const struct net *net,
 
 		break;
 	}
+	case htons(ETH_P_TEB): {
+		const struct ethhdr *eth;
+		struct ethhdr _eth;
+
+		eth = __skb_header_pointer(skb, nhoff, sizeof(_eth),
+					   data, hlen, &_eth);
+		if (!eth)
+			goto out_bad;
+
+		proto = eth->h_proto;
+		nhoff += sizeof(*eth);
+
+		/* Cap headers that we access via pointers at the
+		 * end of the Ethernet header as our maximum alignment
+		 * at that point is only 2 bytes.
+		 */
+		if (NET_IP_ALIGN)
+			hlen = nhoff;
+
+		goto proto_again;
+	}
 	case htons(ETH_P_8021AD):
 	case htons(ETH_P_8021Q): {
 		const struct vlan_hdr *vlan = NULL;
@@ -1531,7 +1536,7 @@ bool __skb_flow_dissect(const struct net *net,
 
 		fdret = __skb_flow_dissect_gre(skb, key_control, flow_dissector,
 					       target_container, data,
-					       &proto, &nhoff, &hlen, flags);
+					       &proto, &nhoff, hlen, flags);
 		break;
 
 	case NEXTHDR_HOP:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 02/12] udp_encaps: Add new UDP_ENCAP constants
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
  2024-08-15 21:45 ` [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-16 18:56   ` Willem de Bruijn
  2024-08-15 21:45 ` [PATCH net-next v2 03/12] udp_encaps: Set proper UDP_ENCAP types in tunnel setup Tom Herbert
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

Add constants for various UDP encapsulations that are supported

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 include/uapi/linux/udp.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/include/uapi/linux/udp.h b/include/uapi/linux/udp.h
index 1a0fe8b151fb..0432a9a6536d 100644
--- a/include/uapi/linux/udp.h
+++ b/include/uapi/linux/udp.h
@@ -36,6 +36,7 @@ struct udphdr {
 #define UDP_GRO		104	/* This socket can receive UDP GRO packets */
 
 /* UDP encapsulation types */
+#define UDP_ENCAP_NONE		0
 #define UDP_ENCAP_ESPINUDP_NON_IKE	1 /* unused  draft-ietf-ipsec-nat-t-ike-00/01 */
 #define UDP_ENCAP_ESPINUDP	2 /* draft-ietf-ipsec-udp-encaps-06 */
 #define UDP_ENCAP_L2TPINUDP	3 /* rfc2661 */
@@ -43,5 +44,17 @@ struct udphdr {
 #define UDP_ENCAP_GTP1U		5 /* 3GPP TS 29.060 */
 #define UDP_ENCAP_RXRPC		6
 #define TCP_ENCAP_ESPINTCP	7 /* Yikes, this is really xfrm encap types. */
+#define UDP_ENCAP_TIPC		8
+#define UDP_ENCAP_FOU		9
+#define UDP_ENCAP_GUE		10
+#define UDP_ENCAP_SCTP		11
+#define UDP_ENCAP_RXE		12
+#define UDP_ENCAP_PFCP		13
+#define UDP_ENCAP_WIREGUARD	14
+#define UDP_ENCAP_BAREUDP	15
+#define UDP_ENCAP_VXLAN		16
+#define UDP_ENCAP_VXLAN_GPE	17
+#define UDP_ENCAP_GENEVE	18
+#define UDP_ENCAP_AMT		19
 
 #endif /* _UAPI_LINUX_UDP_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 03/12] udp_encaps: Set proper UDP_ENCAP types in tunnel setup
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
  2024-08-15 21:45 ` [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE Tom Herbert
  2024-08-15 21:45 ` [PATCH net-next v2 02/12] udp_encaps: Add new UDP_ENCAP constants Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-15 21:45 ` [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure Tom Herbert
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel
  Cc: Tom Herbert, Willem de Bruijn

Instead of just setting UDP tunnel config encap_type to 1,
use the appropriate constat for the tunnel type. This value
can be used to determine the encapsulated protocol in UDP
by looking at the socket

Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 drivers/infiniband/sw/rxe/rxe_net.c | 2 +-
 drivers/net/amt.c                   | 2 +-
 drivers/net/bareudp.c               | 2 +-
 drivers/net/geneve.c                | 2 +-
 drivers/net/pfcp.c                  | 2 +-
 drivers/net/vxlan/vxlan_core.c      | 3 ++-
 drivers/net/wireguard/socket.c      | 2 +-
 net/ipv4/fou_core.c                 | 3 ++-
 net/sctp/protocol.c                 | 2 +-
 net/tipc/udp_media.c                | 2 +-
 10 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 75d1407db52d..1c2bb88132c5 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -193,7 +193,7 @@ static struct socket *rxe_setup_udp_tunnel(struct net *net, __be16 port,
 	if (err < 0)
 		return ERR_PTR(err);
 
-	tnl_cfg.encap_type = 1;
+	tnl_cfg.encap_type = UDP_ENCAP_RXE;
 	tnl_cfg.encap_rcv = rxe_udp_encap_recv;
 
 	/* Setup UDP tunnel */
diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index 6d15ab3bfbbc..fc421cf2c032 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -2970,7 +2970,7 @@ static int amt_socket_create(struct amt_dev *amt)
 	/* Mark socket as an encapsulation socket */
 	memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));
 	tunnel_cfg.sk_user_data = amt;
-	tunnel_cfg.encap_type = 1;
+	tunnel_cfg.encap_type = UDP_ENCAP_AMT;
 	tunnel_cfg.encap_rcv = amt_rcv;
 	tunnel_cfg.encap_err_lookup = amt_err_lookup;
 	tunnel_cfg.encap_destroy = NULL;
diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c
index d5c56ca91b77..007fb8c5168b 100644
--- a/drivers/net/bareudp.c
+++ b/drivers/net/bareudp.c
@@ -248,7 +248,7 @@ static int bareudp_socket_create(struct bareudp_dev *bareudp, __be16 port)
 	/* Mark socket as an encapsulation socket */
 	memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));
 	tunnel_cfg.sk_user_data = bareudp;
-	tunnel_cfg.encap_type = 1;
+	tunnel_cfg.encap_type = UDP_ENCAP_BAREUDP;
 	tunnel_cfg.encap_rcv = bareudp_udp_encap_recv;
 	tunnel_cfg.encap_err_lookup = bareudp_err_lookup;
 	tunnel_cfg.encap_destroy = NULL;
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 838e85ddec67..923c573b6e5c 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -611,7 +611,7 @@ static struct geneve_sock *geneve_socket_create(struct net *net, __be16 port,
 	/* Mark socket as an encapsulation socket */
 	memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));
 	tunnel_cfg.sk_user_data = gs;
-	tunnel_cfg.encap_type = 1;
+	tunnel_cfg.encap_type = UDP_ENCAP_GENEVE;
 	tunnel_cfg.gro_receive = geneve_gro_receive;
 	tunnel_cfg.gro_complete = geneve_gro_complete;
 	tunnel_cfg.encap_rcv = geneve_udp_encap_recv;
diff --git a/drivers/net/pfcp.c b/drivers/net/pfcp.c
index 69434fd13f96..c7e4fa606b16 100644
--- a/drivers/net/pfcp.c
+++ b/drivers/net/pfcp.c
@@ -170,7 +170,7 @@ static struct socket *pfcp_create_sock(struct pfcp_dev *pfcp)
 
 	tuncfg.sk_user_data = pfcp;
 	tuncfg.encap_rcv = pfcp_encap_recv;
-	tuncfg.encap_type = 1;
+	tuncfg.encap_type = UDP_ENCAP_PFCP;
 
 	setup_udp_tunnel_sock(net, sock, &tuncfg);
 
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 8983e75e9881..e02cbc018b8c 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3572,7 +3572,8 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
 	/* Mark socket as an encapsulation socket. */
 	memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));
 	tunnel_cfg.sk_user_data = vs;
-	tunnel_cfg.encap_type = 1;
+	tunnel_cfg.encap_type = vs->flags & VXLAN_F_GPE ?
+			UDP_ENCAP_VXLAN_GPE : UDP_ENCAP_VXLAN;
 	tunnel_cfg.encap_rcv = vxlan_rcv;
 	tunnel_cfg.encap_err_lookup = vxlan_err_lookup;
 	tunnel_cfg.encap_destroy = NULL;
diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c
index 0414d7a6ce74..f4b5bd14fd56 100644
--- a/drivers/net/wireguard/socket.c
+++ b/drivers/net/wireguard/socket.c
@@ -352,7 +352,7 @@ int wg_socket_init(struct wg_device *wg, u16 port)
 	int ret;
 	struct udp_tunnel_sock_cfg cfg = {
 		.sk_user_data = wg,
-		.encap_type = 1,
+		.encap_type = UDP_ENCAP_WIREGUARD,
 		.encap_rcv = wg_receive
 	};
 	struct socket *new4 = NULL, *new6 = NULL;
diff --git a/net/ipv4/fou_core.c b/net/ipv4/fou_core.c
index 0abbc413e0fe..8241f762e45b 100644
--- a/net/ipv4/fou_core.c
+++ b/net/ipv4/fou_core.c
@@ -578,19 +578,20 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
 	fou->sock = sock;
 
 	memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));
-	tunnel_cfg.encap_type = 1;
 	tunnel_cfg.sk_user_data = fou;
 	tunnel_cfg.encap_destroy = NULL;
 
 	/* Initial for fou type */
 	switch (cfg->type) {
 	case FOU_ENCAP_DIRECT:
+		tunnel_cfg.encap_type = UDP_ENCAP_FOU;
 		tunnel_cfg.encap_rcv = fou_udp_recv;
 		tunnel_cfg.gro_receive = fou_gro_receive;
 		tunnel_cfg.gro_complete = fou_gro_complete;
 		fou->protocol = cfg->protocol;
 		break;
 	case FOU_ENCAP_GUE:
+		tunnel_cfg.encap_type = UDP_ENCAP_GUE;
 		tunnel_cfg.encap_rcv = gue_udp_recv;
 		tunnel_cfg.gro_receive = gue_gro_receive;
 		tunnel_cfg.gro_complete = gue_gro_complete;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 5a7436a13b74..290ebcf17a48 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -876,7 +876,7 @@ int sctp_udp_sock_start(struct net *net)
 		return err;
 	}
 
-	tuncfg.encap_type = 1;
+	tuncfg.encap_type = UDP_ENCAP_SCTP;
 	tuncfg.encap_rcv = sctp_udp_rcv;
 	tuncfg.encap_err_lookup = sctp_udp_v4_err;
 	setup_udp_tunnel_sock(net, sock, &tuncfg);
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index 439f75539977..3c081b7b9d67 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -771,7 +771,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
 	if (err)
 		goto err;
 	tuncfg.sk_user_data = ub;
-	tuncfg.encap_type = 1;
+	tuncfg.encap_type = UDP_ENCAP_TIPC;
 	tuncfg.encap_rcv = tipc_udp_recv;
 	tuncfg.encap_destroy = NULL;
 	setup_udp_tunnel_sock(net, ub->ubsock, &tuncfg);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
                   ` (2 preceding siblings ...)
  2024-08-15 21:45 ` [PATCH net-next v2 03/12] udp_encaps: Set proper UDP_ENCAP types in tunnel setup Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-16 19:09   ` Willem de Bruijn
                     ` (2 more replies)
  2024-08-15 21:45 ` [PATCH net-next v2 05/12] flow_dissector: Parse vxlan in UDP Tom Herbert
                   ` (8 subsequent siblings)
  12 siblings, 3 replies; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

Add infrastructure for parsing into UDP encapsulations

Add function __skb_flow_dissect_udp that is called for IPPROTO_UDP.
The flag FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS enables parsing of UDP
encapsulations. If the flag is set when parsing a UDP packet then
a socket lookup is performed. The offset of the base network header,
either an IPv4 or IPv6 header, is tracked and passed to
__skb_flow_dissect_udp so that it can perform the socket lookup

If a socket is found and it's for a UDP encapsulation (encap_type is
set in the UDP socket) then a switch is performed on the encap_type
value (cases are UDP_ENCAP_* values)

An encapsulated packet in UDP can either be indicated by an
EtherType or IP protocol. The processing for dissecting a UDP encap
protocol returns a flow dissector return code. If
FLOW_DISSECT_RET_PROTO_AGAIN or FLOW_DISSECT_RET_IPPROTO_AGAIN is
returned then the corresponding  encapsulated protocol is dissected.
The nhoff is set to point to the header to process.  In the case
FLOW_DISSECT_RET_PROTO_AGAIN the EtherType protocol is returned and
the IP protocol is set to zero. In the case of
FLOW_DISSECT_RET_IPPROTO_AGAIN, the IP protocol is returned and
the EtherType protocol is returned unchanged

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 include/net/flow_dissector.h |   1 +
 net/core/flow_dissector.c    | 121 +++++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+)

diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index ced79dc8e856..8a868a88a6f1 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -384,6 +384,7 @@ enum flow_dissector_key_id {
 #define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL	BIT(1)
 #define FLOW_DISSECTOR_F_STOP_AT_ENCAP		BIT(2)
 #define FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP	BIT(3)
+#define FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS	BIT(4)
 
 struct flow_dissector_key {
 	enum flow_dissector_key_id key_id;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 4b116119086a..160801b83d54 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -13,6 +13,7 @@
 #include <net/gre.h>
 #include <net/pptp.h>
 #include <net/tipc.h>
+#include <net/udp.h>
 #include <linux/igmp.h>
 #include <linux/icmp.h>
 #include <linux/sctp.h>
@@ -806,6 +807,117 @@ __skb_flow_dissect_batadv(const struct sk_buff *skb,
 	return FLOW_DISSECT_RET_PROTO_AGAIN;
 }
 
+static enum flow_dissect_ret
+__skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
+		       struct flow_dissector *flow_dissector,
+		       void *target_container, const void *data,
+		       int *p_nhoff, int hlen, __be16 *p_proto,
+		       u8 *p_ip_proto, int base_nhoff, unsigned int flags)
+{
+	enum flow_dissect_ret ret;
+	const struct udphdr *udph;
+	struct udphdr _udph;
+	struct sock *sk;
+	__u8 encap_type;
+	int nhoff;
+
+	if (!(flags & FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS))
+		return FLOW_DISSECT_RET_OUT_GOOD;
+
+	switch (*p_proto) {
+	case htons(ETH_P_IP): {
+		const struct iphdr *iph;
+		struct iphdr _iph;
+
+		iph = __skb_header_pointer(skb, base_nhoff, sizeof(_iph), data,
+					   hlen, &_iph);
+		if (!iph)
+			return FLOW_DISSECT_RET_OUT_BAD;
+
+		udph = __skb_header_pointer(skb, *p_nhoff, sizeof(_udph), data,
+					    hlen, &_udph);
+		if (!udph)
+			return FLOW_DISSECT_RET_OUT_BAD;
+
+		rcu_read_lock();
+		/* Look up the UDPv4 socket and get the encap_type */
+		sk = __udp4_lib_lookup(net, iph->saddr, udph->source,
+				       iph->daddr, udph->dest,
+				       inet_iif(skb), inet_sdif(skb),
+				       net->ipv4.udp_table, NULL);
+		if (!sk || !udp_sk(sk)->encap_type) {
+			rcu_read_unlock();
+			return FLOW_DISSECT_RET_OUT_GOOD;
+		}
+
+		encap_type = udp_sk(sk)->encap_type;
+		rcu_read_unlock();
+
+		break;
+	}
+#if IS_ENABLED(CONFIG_IPV6)
+	case htons(ETH_P_IPV6): {
+		const struct ipv6hdr *iph;
+		struct ipv6hdr _iph;
+
+		if (!likely(ipv6_bpf_stub))
+			return FLOW_DISSECT_RET_OUT_GOOD;
+
+		iph = __skb_header_pointer(skb, base_nhoff, sizeof(_iph), data,
+					   hlen, &_iph);
+		if (!iph)
+			return FLOW_DISSECT_RET_OUT_BAD;
+
+		udph = __skb_header_pointer(skb, *p_nhoff, sizeof(_udph), data,
+					    hlen, &_udph);
+		if (!udph)
+			return FLOW_DISSECT_RET_OUT_BAD;
+
+		rcu_read_lock();
+		/* Look up the UDPv6 socket and get the encap_type */
+		sk = ipv6_bpf_stub->udp6_lib_lookup(net,
+				&iph->saddr, udph->source,
+				&iph->daddr, udph->dest,
+				inet_iif(skb), inet_sdif(skb),
+				net->ipv4.udp_table, NULL);
+
+		if (!sk || !udp_sk(sk)->encap_type) {
+			rcu_read_unlock();
+			return FLOW_DISSECT_RET_OUT_GOOD;
+		}
+
+		encap_type = udp_sk(sk)->encap_type;
+		rcu_read_unlock();
+
+		break;
+	}
+#endif /* CONFIG_IPV6 */
+	default:
+		return FLOW_DISSECT_RET_OUT_GOOD;
+	}
+
+	nhoff = *p_nhoff + sizeof(struct udphdr);
+	ret = FLOW_DISSECT_RET_OUT_GOOD;
+
+	switch (encap_type) {
+	default:
+		break;
+	}
+
+	switch (ret) {
+	case FLOW_DISSECT_RET_PROTO_AGAIN:
+		*p_ip_proto = 0;
+		fallthrough;
+	case FLOW_DISSECT_RET_IPPROTO_AGAIN:
+		*p_nhoff = nhoff;
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
 static void
 __skb_flow_dissect_tcp(const struct sk_buff *skb,
 		       struct flow_dissector *flow_dissector,
@@ -1046,6 +1158,7 @@ bool __skb_flow_dissect(const struct net *net,
 	int mpls_lse = 0;
 	int num_hdrs = 0;
 	u8 ip_proto = 0;
+	int base_nhoff;
 	bool ret;
 
 	if (!data) {
@@ -1168,6 +1281,7 @@ bool __skb_flow_dissect(const struct net *net,
 
 proto_again:
 	fdret = FLOW_DISSECT_RET_CONTINUE;
+	base_nhoff = nhoff;
 
 	switch (proto) {
 	case htons(ETH_P_IP): {
@@ -1635,6 +1749,13 @@ bool __skb_flow_dissect(const struct net *net,
 				       data, nhoff, hlen);
 		break;
 
+	case IPPROTO_UDP:
+		fdret = __skb_flow_dissect_udp(skb, net, flow_dissector,
+					       target_container, data, &nhoff,
+					       hlen, &proto, &ip_proto,
+					       base_nhoff, flags);
+		break;
+
 	case IPPROTO_ICMP:
 	case IPPROTO_ICMPV6:
 		__skb_flow_dissect_icmp(skb, flow_dissector, target_container,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 05/12] flow_dissector: Parse vxlan in UDP
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
                   ` (3 preceding siblings ...)
  2024-08-15 21:45 ` [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-16 19:19   ` Willem de Bruijn
  2024-08-17  1:09   ` Jakub Kicinski
  2024-08-15 21:45 ` [PATCH net-next v2 06/12] flow_dissector: Parse foo-over-udp (FOU) Tom Herbert
                   ` (7 subsequent siblings)
  12 siblings, 2 replies; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

Parse vxlan in a UDP encapsulation

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/core/flow_dissector.c | 57 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 160801b83d54..57cfae4b5d2f 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -13,7 +13,9 @@
 #include <net/gre.h>
 #include <net/pptp.h>
 #include <net/tipc.h>
+#include <net/tun_proto.h>
 #include <net/udp.h>
+#include <net/vxlan.h>
 #include <linux/igmp.h>
 #include <linux/icmp.h>
 #include <linux/sctp.h>
@@ -756,6 +758,55 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
 	return FLOW_DISSECT_RET_PROTO_AGAIN;
 }
 
+static enum flow_dissect_ret
+__skb_flow_dissect_vxlan(const struct sk_buff *skb,
+			 struct flow_dissector *flow_dissector,
+			 void *target_container, const void *data,
+			 __be16 *p_proto, int *p_nhoff, int hlen,
+			 unsigned int flags)
+{
+	struct vxlanhdr *hdr, _hdr;
+	__be16 protocol;
+
+	hdr = __skb_header_pointer(skb, *p_nhoff, sizeof(_hdr), data, hlen,
+				   &_hdr);
+	if (!hdr)
+		return FLOW_DISSECT_RET_OUT_BAD;
+
+	/* VNI flag always required to be set */
+	if (!(hdr->vx_flags & VXLAN_HF_VNI))
+		return FLOW_DISSECT_RET_OUT_BAD;
+
+	if (hdr->vx_flags & VXLAN_F_GPE) {
+		struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)hdr;
+
+		/* Need to have Next Protocol set for interfaces in GPE mode. */
+		if (!gpe->np_applied)
+			return FLOW_DISSECT_RET_OUT_BAD;
+
+		/* The initial version is 0 */
+		if (gpe->version != 0)
+			return FLOW_DISSECT_RET_OUT_GOOD;
+
+		/* "When the O bit is set to 1, the packet is an OAM packet and
+		 * OAM so ignore
+		 */
+		if (gpe->oam_flag)
+			return FLOW_DISSECT_RET_OUT_GOOD;
+
+		protocol = tun_p_to_eth_p(gpe->next_protocol);
+		if (!protocol)
+			return FLOW_DISSECT_RET_OUT_GOOD;
+	} else {
+		protocol = htons(ETH_P_TEB);
+	}
+
+	*p_nhoff += sizeof(struct vxlanhdr);
+	*p_proto = protocol;
+
+	return FLOW_DISSECT_RET_PROTO_AGAIN;
+}
+
 /**
  * __skb_flow_dissect_batadv() - dissect batman-adv header
  * @skb: sk_buff to with the batman-adv header
@@ -900,6 +951,12 @@ __skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
 	ret = FLOW_DISSECT_RET_OUT_GOOD;
 
 	switch (encap_type) {
+	case UDP_ENCAP_VXLAN:
+	case UDP_ENCAP_VXLAN_GPE:
+		ret = __skb_flow_dissect_vxlan(skb, flow_dissector,
+					       target_container, data,
+					       p_proto, &nhoff, hlen, flags);
+		break;
 	default:
 		break;
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 06/12] flow_dissector: Parse foo-over-udp (FOU)
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
                   ` (4 preceding siblings ...)
  2024-08-15 21:45 ` [PATCH net-next v2 05/12] flow_dissector: Parse vxlan in UDP Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-15 21:45 ` [PATCH net-next v2 07/12] flow_dissector: Parse ESP, L2TP, and SCTP in UDP Tom Herbert
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel
  Cc: Tom Herbert, Willem de Bruijn

Parse FOU by getting the FOU protocol from the matching socket.
This includes moving "struct fou" and "fou_from_sock" to fou.h

Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 include/net/fou.h         | 16 ++++++++++++++++
 net/core/flow_dissector.c | 13 ++++++++++++-
 net/ipv4/fou_core.c       | 16 ----------------
 3 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/include/net/fou.h b/include/net/fou.h
index 824eb4b231fd..8574767b91b6 100644
--- a/include/net/fou.h
+++ b/include/net/fou.h
@@ -17,6 +17,22 @@ int __fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 int __gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 		       u8 *protocol, __be16 *sport, int type);
 
+struct fou {
+	struct socket *sock;
+	u8 protocol;
+	u8 flags;
+	__be16 port;
+	u8 family;
+	u16 type;
+	struct list_head list;
+	struct rcu_head rcu;
+};
+
+static inline struct fou *fou_from_sock(struct sock *sk)
+{
+	return sk->sk_user_data;
+}
+
 int register_fou_bpf(void);
 
 #endif
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 57cfae4b5d2f..ce7119dbf1ab 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -8,6 +8,7 @@
 #include <linux/filter.h>
 #include <net/dsa.h>
 #include <net/dst_metadata.h>
+#include <net/fou.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/gre.h>
@@ -865,11 +866,11 @@ __skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
 		       int *p_nhoff, int hlen, __be16 *p_proto,
 		       u8 *p_ip_proto, int base_nhoff, unsigned int flags)
 {
+	__u8 encap_type, fou_protocol;
 	enum flow_dissect_ret ret;
 	const struct udphdr *udph;
 	struct udphdr _udph;
 	struct sock *sk;
-	__u8 encap_type;
 	int nhoff;
 
 	if (!(flags & FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS))
@@ -902,6 +903,9 @@ __skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
 		}
 
 		encap_type = udp_sk(sk)->encap_type;
+		if (encap_type == UDP_ENCAP_FOU)
+			fou_protocol = fou_from_sock(sk)->protocol;
+
 		rcu_read_unlock();
 
 		break;
@@ -938,6 +942,9 @@ __skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
 		}
 
 		encap_type = udp_sk(sk)->encap_type;
+		if (encap_type == UDP_ENCAP_FOU)
+			fou_protocol = fou_from_sock(sk)->protocol;
+
 		rcu_read_unlock();
 
 		break;
@@ -951,6 +958,10 @@ __skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
 	ret = FLOW_DISSECT_RET_OUT_GOOD;
 
 	switch (encap_type) {
+	case UDP_ENCAP_FOU:
+		*p_ip_proto = fou_protocol;
+		ret = FLOW_DISSECT_RET_IPPROTO_AGAIN;
+		break;
 	case UDP_ENCAP_VXLAN:
 	case UDP_ENCAP_VXLAN_GPE:
 		ret = __skb_flow_dissect_vxlan(skb, flow_dissector,
diff --git a/net/ipv4/fou_core.c b/net/ipv4/fou_core.c
index 8241f762e45b..137eb80c56a2 100644
--- a/net/ipv4/fou_core.c
+++ b/net/ipv4/fou_core.c
@@ -21,17 +21,6 @@
 
 #include "fou_nl.h"
 
-struct fou {
-	struct socket *sock;
-	u8 protocol;
-	u8 flags;
-	__be16 port;
-	u8 family;
-	u16 type;
-	struct list_head list;
-	struct rcu_head rcu;
-};
-
 #define FOU_F_REMCSUM_NOPARTIAL BIT(0)
 
 struct fou_cfg {
@@ -48,11 +37,6 @@ struct fou_net {
 	struct mutex fou_lock;
 };
 
-static inline struct fou *fou_from_sock(struct sock *sk)
-{
-	return sk->sk_user_data;
-}
-
 static int fou_recv_pull(struct sk_buff *skb, struct fou *fou, size_t len)
 {
 	/* Remove 'len' bytes from the packet (UDP header and
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 07/12] flow_dissector: Parse ESP, L2TP, and SCTP in UDP
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
                   ` (5 preceding siblings ...)
  2024-08-15 21:45 ` [PATCH net-next v2 06/12] flow_dissector: Parse foo-over-udp (FOU) Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-16 19:20   ` Willem de Bruijn
  2024-08-15 21:45 ` [PATCH net-next v2 08/12] flow_dissector: Parse Geneve " Tom Herbert
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

These don't have an encapsulation header so it's fairly easy to
support them

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/core/flow_dissector.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index ce7119dbf1ab..5878955c01a5 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -958,10 +958,23 @@ __skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
 	ret = FLOW_DISSECT_RET_OUT_GOOD;
 
 	switch (encap_type) {
+	case UDP_ENCAP_ESPINUDP_NON_IKE:
+	case UDP_ENCAP_ESPINUDP:
+		*p_ip_proto = IPPROTO_ESP;
+		ret = FLOW_DISSECT_RET_IPPROTO_AGAIN;
+		break;
+	case UDP_ENCAP_L2TPINUDP:
+		*p_ip_proto = IPPROTO_L2TP;
+		ret = FLOW_DISSECT_RET_IPPROTO_AGAIN;
+		break;
 	case UDP_ENCAP_FOU:
 		*p_ip_proto = fou_protocol;
 		ret = FLOW_DISSECT_RET_IPPROTO_AGAIN;
 		break;
+	case UDP_ENCAP_SCTP:
+		*p_ip_proto = IPPROTO_SCTP;
+		ret = FLOW_DISSECT_RET_IPPROTO_AGAIN;
+		break;
 	case UDP_ENCAP_VXLAN:
 	case UDP_ENCAP_VXLAN_GPE:
 		ret = __skb_flow_dissect_vxlan(skb, flow_dissector,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 08/12] flow_dissector: Parse Geneve in UDP
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
                   ` (6 preceding siblings ...)
  2024-08-15 21:45 ` [PATCH net-next v2 07/12] flow_dissector: Parse ESP, L2TP, and SCTP in UDP Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-16 19:21   ` Willem de Bruijn
  2024-08-15 21:45 ` [PATCH net-next v2 09/12] flow_dissector: Parse GUE " Tom Herbert
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

Parse Geneve in a UDP encapsulation

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/core/flow_dissector.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 5878955c01a5..e2a0d67b2753 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -11,6 +11,7 @@
 #include <net/fou.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
+#include <net/geneve.h>
 #include <net/gre.h>
 #include <net/pptp.h>
 #include <net/tipc.h>
@@ -808,6 +809,29 @@ __skb_flow_dissect_vxlan(const struct sk_buff *skb,
 	return FLOW_DISSECT_RET_PROTO_AGAIN;
 }
 
+static enum flow_dissect_ret
+__skb_flow_dissect_geneve(const struct sk_buff *skb,
+			  struct flow_dissector *flow_dissector,
+			  void *target_container, const void *data,
+			  __be16 *p_proto, int *p_nhoff, int hlen,
+			  unsigned int flags)
+{
+	struct genevehdr *hdr, _hdr;
+
+	hdr = __skb_header_pointer(skb, *p_nhoff, sizeof(_hdr), data, hlen,
+				   &_hdr);
+	if (!hdr)
+		return FLOW_DISSECT_RET_OUT_BAD;
+
+	if (hdr->ver != 0)
+		return FLOW_DISSECT_RET_OUT_GOOD;
+
+	*p_proto = hdr->proto_type;
+	*p_nhoff += sizeof(struct genevehdr) + (hdr->opt_len * 4);
+
+	return FLOW_DISSECT_RET_PROTO_AGAIN;
+}
+
 /**
  * __skb_flow_dissect_batadv() - dissect batman-adv header
  * @skb: sk_buff to with the batman-adv header
@@ -981,6 +1005,11 @@ __skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
 					       target_container, data,
 					       p_proto, &nhoff, hlen, flags);
 		break;
+	case UDP_ENCAP_GENEVE:
+		ret = __skb_flow_dissect_geneve(skb, flow_dissector,
+						target_container, data,
+						p_proto, &nhoff, hlen, flags);
+		break;
 	default:
 		break;
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 09/12] flow_dissector: Parse GUE in UDP
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
                   ` (7 preceding siblings ...)
  2024-08-15 21:45 ` [PATCH net-next v2 08/12] flow_dissector: Parse Geneve " Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-16 19:25   ` Willem de Bruijn
  2024-08-15 21:45 ` [PATCH net-next v2 10/12] gtp: Move gtp_parse_exthdrs into net/gtp.h Tom Herbert
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

Parse both version 0 and 1 of GUE encapsulated in UDP. Add helper
function __skb_direct_ip_dissect to convert an IP header to
IPPROTO_IPIP or IPPROTO_IPV6 (by looking just at the version
number)

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/core/flow_dissector.c | 60 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index e2a0d67b2753..fb8c0d97384e 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -832,6 +832,61 @@ __skb_flow_dissect_geneve(const struct sk_buff *skb,
 	return FLOW_DISSECT_RET_PROTO_AGAIN;
 }
 
+static __u8
+__skb_direct_ip_dissect(void *hdr)
+{
+	/* Direct encapsulation of IPv4 or IPv6 */
+
+	switch (((struct iphdr *)hdr)->version) {
+	case 4:
+		return IPPROTO_IPIP;
+	case 6:
+		return IPPROTO_IPV6;
+	default:
+		return 0;
+	}
+}
+
+static enum flow_dissect_ret
+__skb_flow_dissect_gue(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)
+{
+	struct guehdr *hdr, _hdr;
+	__u8 proto;
+
+	hdr = __skb_header_pointer(skb, *p_nhoff, sizeof(_hdr), data, hlen,
+				   &_hdr);
+	if (!hdr)
+		return FLOW_DISSECT_RET_OUT_BAD;
+
+	switch (hdr->version) {
+	case 0:
+		if (unlikely(hdr->control))
+			return FLOW_DISSECT_RET_OUT_GOOD;
+
+		*p_nhoff += sizeof(struct guehdr) + (hdr->hlen << 2);
+		*p_ip_proto = hdr->proto_ctype;
+
+		break;
+	case 1:
+		/* Direct encapsulation of IPv4 or IPv6 */
+
+		proto = __skb_direct_ip_dissect(hdr);
+		if (proto) {
+			*p_ip_proto = proto;
+			break;
+		}
+		fallthrough;
+	default:
+		return FLOW_DISSECT_RET_OUT_GOOD;
+	}
+
+	return FLOW_DISSECT_RET_IPPROTO_AGAIN;
+}
+
 /**
  * __skb_flow_dissect_batadv() - dissect batman-adv header
  * @skb: sk_buff to with the batman-adv header
@@ -995,6 +1050,11 @@ __skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
 		*p_ip_proto = fou_protocol;
 		ret = FLOW_DISSECT_RET_IPPROTO_AGAIN;
 		break;
+	case UDP_ENCAP_GUE:
+		ret = __skb_flow_dissect_gue(skb, flow_dissector,
+					     target_container, data,
+					     p_ip_proto, p_nhoff, hlen, flags);
+		break;
 	case UDP_ENCAP_SCTP:
 		*p_ip_proto = IPPROTO_SCTP;
 		ret = FLOW_DISSECT_RET_IPPROTO_AGAIN;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 10/12] gtp: Move gtp_parse_exthdrs into net/gtp.h
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
                   ` (8 preceding siblings ...)
  2024-08-15 21:45 ` [PATCH net-next v2 09/12] flow_dissector: Parse GUE " Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-16 19:27   ` Willem de Bruijn
  2024-08-15 21:45 ` [PATCH net-next v2 11/12] flow_dissector: Parse gtp in UDP Tom Herbert
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

gtp_parse_exthdrs is a generic function, move into a header file
so we can call it outside of the GTP driver (specifically, we can
call it from flow dissector)

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 drivers/net/gtp.c | 37 -------------------------------------
 include/net/gtp.h | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 427b91aca50d..61d5dfd48c88 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -742,43 +742,6 @@ static int gtp1u_handle_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb)
 				       msg, 0, GTP_GENL_MCGRP, GFP_ATOMIC);
 }
 
-static int gtp_parse_exthdrs(struct sk_buff *skb, unsigned int *hdrlen)
-{
-	struct gtp_ext_hdr *gtp_exthdr, _gtp_exthdr;
-	unsigned int offset = *hdrlen;
-	__u8 *next_type, _next_type;
-
-	/* From 29.060: "The Extension Header Length field specifies the length
-	 * of the particular Extension header in 4 octets units."
-	 *
-	 * This length field includes length field size itself (1 byte),
-	 * payload (variable length) and next type (1 byte). The extension
-	 * header is aligned to to 4 bytes.
-	 */
-
-	do {
-		gtp_exthdr = skb_header_pointer(skb, offset, sizeof(*gtp_exthdr),
-						&_gtp_exthdr);
-		if (!gtp_exthdr || !gtp_exthdr->len)
-			return -1;
-
-		offset += gtp_exthdr->len * 4;
-
-		/* From 29.060: "If no such Header follows, then the value of
-		 * the Next Extension Header Type shall be 0."
-		 */
-		next_type = skb_header_pointer(skb, offset - 1,
-					       sizeof(_next_type), &_next_type);
-		if (!next_type)
-			return -1;
-
-	} while (*next_type != 0);
-
-	*hdrlen = offset;
-
-	return 0;
-}
-
 static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 {
 	unsigned int hdrlen = sizeof(struct udphdr) +
diff --git a/include/net/gtp.h b/include/net/gtp.h
index c0253c8702d0..a513aa1c7394 100644
--- a/include/net/gtp.h
+++ b/include/net/gtp.h
@@ -83,4 +83,42 @@ struct gtp_ext_hdr {
 	__u8	data[];
 };
 
+static inline int gtp_parse_exthdrs(const struct sk_buff *skb,
+				    unsigned int *hdrlen)
+{
+	struct gtp_ext_hdr *gtp_exthdr, _gtp_exthdr;
+	unsigned int offset = *hdrlen;
+	__u8 *next_type, _next_type;
+
+	/* From 29.060: "The Extension Header Length field specifies the length
+	 * of the particular Extension header in 4 octets units."
+	 *
+	 * This length field includes length field size itself (1 byte),
+	 * payload (variable length) and next type (1 byte). The extension
+	 * header is aligned to 4 bytes.
+	 */
+
+	do {
+		gtp_exthdr = skb_header_pointer(skb, offset, sizeof(*gtp_exthdr),
+						&_gtp_exthdr);
+		if (!gtp_exthdr || !gtp_exthdr->len)
+			return -1;
+
+		offset += gtp_exthdr->len * 4;
+
+		/* From 29.060: "If no such Header follows, then the value of
+		 * the Next Extension Header Type shall be 0."
+		 */
+		next_type = skb_header_pointer(skb, offset - 1,
+					       sizeof(_next_type), &_next_type);
+		if (!next_type)
+			return -1;
+
+	} while (*next_type != 0);
+
+	*hdrlen = offset;
+
+	return 0;
+}
+
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 11/12] flow_dissector: Parse gtp in UDP
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
                   ` (9 preceding siblings ...)
  2024-08-15 21:45 ` [PATCH net-next v2 10/12] gtp: Move gtp_parse_exthdrs into net/gtp.h Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-15 21:45 ` [PATCH net-next v2 12/12] flow_dissector: Add case in ipproto switch for NEXTHDR_NONE Tom Herbert
  2024-08-16 20:19 ` [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Willem de Bruijn
  12 siblings, 0 replies; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

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@herbertland.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 fb8c0d97384e..b2abccf8aac2 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>
@@ -887,6 +889,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
@@ -1046,6 +1133,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


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next v2 12/12] flow_dissector: Add case in ipproto switch for NEXTHDR_NONE
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
                   ` (10 preceding siblings ...)
  2024-08-15 21:45 ` [PATCH net-next v2 11/12] flow_dissector: Parse gtp in UDP Tom Herbert
@ 2024-08-15 21:45 ` Tom Herbert
  2024-08-16 19:28   ` Willem de Bruijn
  2024-08-16 20:19 ` [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Willem de Bruijn
  12 siblings, 1 reply; 33+ messages in thread
From: Tom Herbert @ 2024-08-15 21:45 UTC (permalink / raw)
  To: davem, kuba, edumazet, netdev, felipe, willemdebruijn.kernel; +Cc: Tom Herbert

Protocol number 59 (no-next-header) means nothing follows the
IP header, break out of the flow dissector loop on
FLOW_DISSECT_RET_OUT_GOOD when encountered in a packet

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/core/flow_dissector.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index b2abccf8aac2..fb1ca7d024de 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -1971,6 +1971,9 @@ bool __skb_flow_dissect(const struct net *net,
 		fdret = FLOW_DISSECT_RET_OUT_GOOD;
 		break;
 	}
+	case NEXTHDR_NONE:
+		fdret = FLOW_DISSECT_RET_OUT_GOOD;
+		break;
 	case IPPROTO_IPIP:
 		if (flags & FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP) {
 			fdret = FLOW_DISSECT_RET_OUT_GOOD;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE
  2024-08-15 21:45 ` [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE Tom Herbert
@ 2024-08-16 18:54   ` Willem de Bruijn
  2024-08-20 16:21     ` Tom Herbert
  0 siblings, 1 reply; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-16 18:54 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: Tom Herbert

Tom Herbert wrote:
> ETH_P_TEB (Trans Ether Bridging) is the EtherType to carry
> a plain Etherent frame. Add case in skb_flow_dissect to parse
> packets of this type
> 
> If the GRE protocol is ETH_P_TEB then just process that as any
> another EtherType since it's now supported in the main loop
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>

Reviewed-by: Willem de Bruijn <willemb@google.com>

> -	if (gre_ver == 0) {
> -		if (*p_proto == htons(ETH_P_TEB)) {
> -			const struct ethhdr *eth;
> -			struct ethhdr _eth;
> -
> -			eth = __skb_header_pointer(skb, *p_nhoff + offset,
> -						   sizeof(_eth),
> -						   data, *p_hlen, &_eth);
> -			if (!eth)
> -				return FLOW_DISSECT_RET_OUT_BAD;
> -			*p_proto = eth->h_proto;
> -			offset += sizeof(*eth);
> -
> -			/* Cap headers that we access via pointers at the
> -			 * end of the Ethernet header as our maximum alignment
> -			 * at that point is only 2 bytes.
> -			 */
> -			if (NET_IP_ALIGN)
> -				*p_hlen = *p_nhoff + offset;
> -		}
> -	} else { /* version 1, must be PPTP */

> @@ -1284,6 +1268,27 @@ bool __skb_flow_dissect(const struct net *net,
>  
>  		break;
>  	}
> +	case htons(ETH_P_TEB): {
> +		const struct ethhdr *eth;
> +		struct ethhdr _eth;
> +
> +		eth = __skb_header_pointer(skb, nhoff, sizeof(_eth),
> +					   data, hlen, &_eth);
> +		if (!eth)
> +			goto out_bad;
> +
> +		proto = eth->h_proto;
> +		nhoff += sizeof(*eth);
> +
> +		/* Cap headers that we access via pointers at the
> +		 * end of the Ethernet header as our maximum alignment
> +		 * at that point is only 2 bytes.
> +		 */
> +		if (NET_IP_ALIGN)
> +			hlen = nhoff;

I wonder why this exists. But besides the point of this move.

> +
> +		goto proto_again;
> +	}


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 02/12] udp_encaps: Add new UDP_ENCAP constants
  2024-08-15 21:45 ` [PATCH net-next v2 02/12] udp_encaps: Add new UDP_ENCAP constants Tom Herbert
@ 2024-08-16 18:56   ` Willem de Bruijn
  0 siblings, 0 replies; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-16 18:56 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: Tom Herbert

Tom Herbert wrote:
> Add constants for various UDP encapsulations that are supported
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>

Reviewed-by: Willem de Bruijn <willemb@google.com>

If a v3 is needed, maybe add to the comment your response on why we
think this is UAPI to begin with: for BPF.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure
  2024-08-15 21:45 ` [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure Tom Herbert
@ 2024-08-16 19:09   ` Willem de Bruijn
  2024-08-17 14:01   ` kernel test robot
  2024-08-20 18:52   ` Eric Dumazet
  2 siblings, 0 replies; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-16 19:09 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: Tom Herbert

Tom Herbert wrote:
> Add infrastructure for parsing into UDP encapsulations
> 
> Add function __skb_flow_dissect_udp that is called for IPPROTO_UDP.
> The flag FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS enables parsing of UDP
> encapsulations. If the flag is set when parsing a UDP packet then
> a socket lookup is performed. The offset of the base network header,
> either an IPv4 or IPv6 header, is tracked and passed to
> __skb_flow_dissect_udp so that it can perform the socket lookup
> 
> If a socket is found and it's for a UDP encapsulation (encap_type is
> set in the UDP socket) then a switch is performed on the encap_type
> value (cases are UDP_ENCAP_* values)
> 
> An encapsulated packet in UDP can either be indicated by an
> EtherType or IP protocol. The processing for dissecting a UDP encap
> protocol returns a flow dissector return code. If
> FLOW_DISSECT_RET_PROTO_AGAIN or FLOW_DISSECT_RET_IPPROTO_AGAIN is
> returned then the corresponding  encapsulated protocol is dissected.
> The nhoff is set to point to the header to process.  In the case
> FLOW_DISSECT_RET_PROTO_AGAIN the EtherType protocol is returned and
> the IP protocol is set to zero. In the case of
> FLOW_DISSECT_RET_IPPROTO_AGAIN, the IP protocol is returned and
> the EtherType protocol is returned unchanged
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>
> ---
>  include/net/flow_dissector.h |   1 +
>  net/core/flow_dissector.c    | 121 +++++++++++++++++++++++++++++++++++
>  2 files changed, 122 insertions(+)
> 
> diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
> index ced79dc8e856..8a868a88a6f1 100644
> --- a/include/net/flow_dissector.h
> +++ b/include/net/flow_dissector.h
> @@ -384,6 +384,7 @@ enum flow_dissector_key_id {
>  #define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL	BIT(1)
>  #define FLOW_DISSECTOR_F_STOP_AT_ENCAP		BIT(2)
>  #define FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP	BIT(3)
> +#define FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS	BIT(4)
>  
>  struct flow_dissector_key {
>  	enum flow_dissector_key_id key_id;
> diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
> index 4b116119086a..160801b83d54 100644
> --- a/net/core/flow_dissector.c
> +++ b/net/core/flow_dissector.c
> @@ -13,6 +13,7 @@
>  #include <net/gre.h>
>  #include <net/pptp.h>
>  #include <net/tipc.h>
> +#include <net/udp.h>
>  #include <linux/igmp.h>
>  #include <linux/icmp.h>
>  #include <linux/sctp.h>
> @@ -806,6 +807,117 @@ __skb_flow_dissect_batadv(const struct sk_buff *skb,
>  	return FLOW_DISSECT_RET_PROTO_AGAIN;
>  }
>  
> +static enum flow_dissect_ret
> +__skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
> +		       struct flow_dissector *flow_dissector,
> +		       void *target_container, const void *data,
> +		       int *p_nhoff, int hlen, __be16 *p_proto,
> +		       u8 *p_ip_proto, int base_nhoff, unsigned int flags)
> +{
> +	enum flow_dissect_ret ret;
> +	const struct udphdr *udph;
> +	struct udphdr _udph;
> +	struct sock *sk;
> +	__u8 encap_type;
> +	int nhoff;
> +
> +	if (!(flags & FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS))
> +		return FLOW_DISSECT_RET_OUT_GOOD;
> +
> +	switch (*p_proto) {
> +	case htons(ETH_P_IP): {
> +		const struct iphdr *iph;
> +		struct iphdr _iph;
> +
> +		iph = __skb_header_pointer(skb, base_nhoff, sizeof(_iph), data,
> +					   hlen, &_iph);
> +		if (!iph)
> +			return FLOW_DISSECT_RET_OUT_BAD;
> +
> +		udph = __skb_header_pointer(skb, *p_nhoff, sizeof(_udph), data,
> +					    hlen, &_udph);
> +		if (!udph)
> +			return FLOW_DISSECT_RET_OUT_BAD;
> +
> +		rcu_read_lock();
> +		/* Look up the UDPv4 socket and get the encap_type */
> +		sk = __udp4_lib_lookup(net, iph->saddr, udph->source,
> +				       iph->daddr, udph->dest,
> +				       inet_iif(skb), inet_sdif(skb),
> +				       net->ipv4.udp_table, NULL);
> +		if (!sk || !udp_sk(sk)->encap_type) {
> +			rcu_read_unlock();
> +			return FLOW_DISSECT_RET_OUT_GOOD;
> +		}
> +
> +		encap_type = udp_sk(sk)->encap_type;
> +		rcu_read_unlock();
> +
> +		break;
> +	}
> +#if IS_ENABLED(CONFIG_IPV6)
> +	case htons(ETH_P_IPV6): {
> +		const struct ipv6hdr *iph;
> +		struct ipv6hdr _iph;
> +
> +		if (!likely(ipv6_bpf_stub))
> +			return FLOW_DISSECT_RET_OUT_GOOD;
> +
> +		iph = __skb_header_pointer(skb, base_nhoff, sizeof(_iph), data,
> +					   hlen, &_iph);
> +		if (!iph)
> +			return FLOW_DISSECT_RET_OUT_BAD;
> +
> +		udph = __skb_header_pointer(skb, *p_nhoff, sizeof(_udph), data,
> +					    hlen, &_udph);
> +		if (!udph)
> +			return FLOW_DISSECT_RET_OUT_BAD;
> +
> +		rcu_read_lock();
> +		/* Look up the UDPv6 socket and get the encap_type */
> +		sk = ipv6_bpf_stub->udp6_lib_lookup(net,

Should this use ipv6_stub?
> +				&iph->saddr, udph->source,
> +				&iph->daddr, udph->dest,
> +				inet_iif(skb), inet_sdif(skb),
> +				net->ipv4.udp_table, NULL);
> +
> +		if (!sk || !udp_sk(sk)->encap_type) {
> +			rcu_read_unlock();
> +			return FLOW_DISSECT_RET_OUT_GOOD;
> +		}
> +
> +		encap_type = udp_sk(sk)->encap_type;
> +		rcu_read_unlock();
> +
> +		break;
> +	}
> +#endif /* CONFIG_IPV6 */
> +	default:
> +		return FLOW_DISSECT_RET_OUT_GOOD;
> +	}
> +
> +	nhoff = *p_nhoff + sizeof(struct udphdr);

maybe sizeof(_udph) for consistency

> +	ret = FLOW_DISSECT_RET_OUT_GOOD;
> +
> +	switch (encap_type) {
> +	default:
> +		break;
> +	}
> +
> +	switch (ret) {
> +	case FLOW_DISSECT_RET_PROTO_AGAIN:
> +		*p_ip_proto = 0;
> +		fallthrough;
> +	case FLOW_DISSECT_RET_IPPROTO_AGAIN:
> +		*p_nhoff = nhoff;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return ret;
> +}
> +

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 05/12] flow_dissector: Parse vxlan in UDP
  2024-08-15 21:45 ` [PATCH net-next v2 05/12] flow_dissector: Parse vxlan in UDP Tom Herbert
@ 2024-08-16 19:19   ` Willem de Bruijn
  2024-08-17  1:09   ` Jakub Kicinski
  1 sibling, 0 replies; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-16 19:19 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: Tom Herbert

Tom Herbert wrote:
> Parse vxlan in a UDP encapsulation
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>

Reviewed-by: Willem de Bruijn <willemb@google.com>

(not very familiar with VXLAN)

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 07/12] flow_dissector: Parse ESP, L2TP, and SCTP in UDP
  2024-08-15 21:45 ` [PATCH net-next v2 07/12] flow_dissector: Parse ESP, L2TP, and SCTP in UDP Tom Herbert
@ 2024-08-16 19:20   ` Willem de Bruijn
  0 siblings, 0 replies; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-16 19:20 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: Tom Herbert

Tom Herbert wrote:
> These don't have an encapsulation header so it's fairly easy to
> support them
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>

Reviewed-by: Willem de Bruijn <willemb@google.com>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 08/12] flow_dissector: Parse Geneve in UDP
  2024-08-15 21:45 ` [PATCH net-next v2 08/12] flow_dissector: Parse Geneve " Tom Herbert
@ 2024-08-16 19:21   ` Willem de Bruijn
  0 siblings, 0 replies; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-16 19:21 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: Tom Herbert

Tom Herbert wrote:
> Parse Geneve in a UDP encapsulation
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>

Reviewed-by: Willem de Bruijn <willemb@google.com>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 09/12] flow_dissector: Parse GUE in UDP
  2024-08-15 21:45 ` [PATCH net-next v2 09/12] flow_dissector: Parse GUE " Tom Herbert
@ 2024-08-16 19:25   ` Willem de Bruijn
  0 siblings, 0 replies; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-16 19:25 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: Tom Herbert

Tom Herbert wrote:
> Parse both version 0 and 1 of GUE encapsulated in UDP. Add helper
> function __skb_direct_ip_dissect to convert an IP header to
> IPPROTO_IPIP or IPPROTO_IPV6 (by looking just at the version
> number)
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>

Reviewed-by: Willem de Bruijn <willemb@google.com>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 10/12] gtp: Move gtp_parse_exthdrs into net/gtp.h
  2024-08-15 21:45 ` [PATCH net-next v2 10/12] gtp: Move gtp_parse_exthdrs into net/gtp.h Tom Herbert
@ 2024-08-16 19:27   ` Willem de Bruijn
  0 siblings, 0 replies; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-16 19:27 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: Tom Herbert

Tom Herbert wrote:
> gtp_parse_exthdrs is a generic function, move into a header file
> so we can call it outside of the GTP driver (specifically, we can
> call it from flow dissector)
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>

For this and next patch probably directly Cc: the GTP maintainers.

That said,

Reviewed-by: Willem de Bruijn <willemb@google.com>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 12/12] flow_dissector: Add case in ipproto switch for NEXTHDR_NONE
  2024-08-15 21:45 ` [PATCH net-next v2 12/12] flow_dissector: Add case in ipproto switch for NEXTHDR_NONE Tom Herbert
@ 2024-08-16 19:28   ` Willem de Bruijn
  0 siblings, 0 replies; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-16 19:28 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: Tom Herbert

Tom Herbert wrote:
> Protocol number 59 (no-next-header) means nothing follows the
> IP header, break out of the flow dissector loop on
> FLOW_DISSECT_RET_OUT_GOOD when encountered in a packet
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>

Reviewed-by: Willem de Bruijn <willemb@google.com>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols
  2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
                   ` (11 preceding siblings ...)
  2024-08-15 21:45 ` [PATCH net-next v2 12/12] flow_dissector: Add case in ipproto switch for NEXTHDR_NONE Tom Herbert
@ 2024-08-16 20:19 ` Willem de Bruijn
  2024-08-20 18:28   ` Tom Herbert
  12 siblings, 1 reply; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-16 20:19 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: Tom Herbert

Tom Herbert wrote:
> Add support in flow_dissector for dissecting into UDP
> encapsulations like VXLAN. __skb_flow_dissect_udp is called for
> IPPROTO_UDP. The flag FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS enables parsing
> of UDP encapsulations. If the flag is set when parsing a UDP packet then
> a socket lookup is performed. The offset of the base network header,
> either an IPv4 or IPv6 header, is tracked and passed to
> __skb_flow_dissect_udp so that it can perform the socket lookup.
> If a socket is found and it's for a UDP encapsulation (encap_type is
> set in the UDP socket) then a switch is performed on the encap_type
> value (cases are UDP_ENCAP_* values)
> 
> Changes in the patch set:
> 
> - Unconstantify struct net argument in flowdis functions so we can call
>   UDP socket lookup functions
> - Dissect ETH_P_TEB in main flow dissector loop, move ETH_P_TEB check
>   out of __skb_flow_dissect_gre and process it in main loop
> - Add UDP_ENCAP constants for tipc, fou, gue, sctp, rxe, pfcp,
>   wireguard, bareudp, vxlan, vxlan_gpe, geneve, and amt
> - For the various UDP encapsulation protocols, Instead of just setting
>   UDP tunnel encap type to 1, set it to the corresponding UDP_ENCAP
>   constant. This allows identify the encapsulation protocol for a
>   UDP socket by the encap_type
> - Add function __skb_flow_dissect_udp in flow_dissector and call it for
>   UDP packets. If a UDP encapsulation is present then the function
>   returns either FLOW_DISSECT_RET_PROTO_AGAIN or
>   FLOW_DISSECT_RET_IPPROTO_AGAIN
> - Add flag FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS that indicates UDP
>   encapsulations should be dissected
> - Add __skb_flow_dissect_vxlan which is called when encap_type is
>   UDP_ENCAP_VXLAN or UDP_ENCAP_VXLAN_GPE. Dissect VXLAN and return
>   a next protocol and offset
> - Add __skb_flow_dissect_fou which is called when encap_type is
>   UDP_ENCAP_FOU. Dissect FOU and return a next protocol and offset
> - Add support for ESP, L2TP, and SCTP in UDP in __skb_flow_dissect_udp.
>   All we need to do is return FLOW_DISSECT_RET_IPPROTO_AGAIN and the
>   corresponding IP protocol number
> - Add __skb_flow_dissect_geneve which is called when encap_type is
>   UDP_ENCAP_GENEVE. Dissect geneve and return a next protocol and offset
> - Add __skb_flow_dissect_gue which is called when encap_type is
>   UDP_ENCAP_GUE. Dissect gue and return a next protocol and offset
> - Add __skb_flow_dissect_gtp which is called when encap_type is
>   UDP_ENCAP_GTP. Dissect gtp and return a next protocol and offset
> 
> Tested: Verified fou, gue, vxlan, and geneve are properly dissected for
> IPv4 and IPv6 cases. This includes testing ETH_P_TEB case

On our conversation in v1 that this is manual:

Would be really nice to have some test coverage for flow dissection.
We only have this for BPF flow dissection. This seems like a suitable
candidate for KUNIT. Like gso_test_func. Don't mean to put you on the
spot per se to add this coverage.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 05/12] flow_dissector: Parse vxlan in UDP
  2024-08-15 21:45 ` [PATCH net-next v2 05/12] flow_dissector: Parse vxlan in UDP Tom Herbert
  2024-08-16 19:19   ` Willem de Bruijn
@ 2024-08-17  1:09   ` Jakub Kicinski
  2024-08-20 18:15     ` Tom Herbert
  1 sibling, 1 reply; 33+ messages in thread
From: Jakub Kicinski @ 2024-08-17  1:09 UTC (permalink / raw)
  To: Tom Herbert; +Cc: davem, edumazet, netdev, felipe, willemdebruijn.kernel

On Thu, 15 Aug 2024 14:45:20 -0700 Tom Herbert wrote:
> +	if (hdr->vx_flags & VXLAN_F_GPE) {

sparse points out that VXLAN_F_GPE needs to be byte swapped

not 100% sure I'm following the scheme but it appears _F_ flags are in
CPU byte order, and _HF_ flags are in network
-- 
pw-bot: cr

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure
  2024-08-15 21:45 ` [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure Tom Herbert
  2024-08-16 19:09   ` Willem de Bruijn
@ 2024-08-17 14:01   ` kernel test robot
  2024-08-20 18:52   ` Eric Dumazet
  2 siblings, 0 replies; 33+ messages in thread
From: kernel test robot @ 2024-08-17 14:01 UTC (permalink / raw)
  To: Tom Herbert, davem, kuba, edumazet, netdev, felipe,
	willemdebruijn.kernel
  Cc: oe-kbuild-all, Tom Herbert

Hi Tom,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Tom-Herbert/flow_dissector-Parse-ETH_P_TEB-and-move-out-of-GRE/20240816-102659
base:   net-next/main
patch link:    https://lore.kernel.org/r/20240815214527.2100137-5-tom%40herbertland.com
patch subject: [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure
config: loongarch-randconfig-002-20240817 (https://download.01.org/0day-ci/archive/20240817/202408172101.UDWfVPns-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 14.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240817/202408172101.UDWfVPns-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202408172101.UDWfVPns-lkp@intel.com/

All errors (new ones prefixed by >>):

   loongarch64-linux-ld: net/core/flow_dissector.o: in function `__skb_flow_dissect_udp':
>> net/core/flow_dissector.c:844:(.text+0x13e8): undefined reference to `__udp4_lib_lookup'


vim +844 net/core/flow_dissector.c

   809	
   810	static enum flow_dissect_ret
   811	__skb_flow_dissect_udp(const struct sk_buff *skb, const struct net *net,
   812			       struct flow_dissector *flow_dissector,
   813			       void *target_container, const void *data,
   814			       int *p_nhoff, int hlen, __be16 *p_proto,
   815			       u8 *p_ip_proto, int base_nhoff, unsigned int flags)
   816	{
   817		enum flow_dissect_ret ret;
   818		const struct udphdr *udph;
   819		struct udphdr _udph;
   820		struct sock *sk;
   821		__u8 encap_type;
   822		int nhoff;
   823	
   824		if (!(flags & FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS))
   825			return FLOW_DISSECT_RET_OUT_GOOD;
   826	
   827		switch (*p_proto) {
   828		case htons(ETH_P_IP): {
   829			const struct iphdr *iph;
   830			struct iphdr _iph;
   831	
   832			iph = __skb_header_pointer(skb, base_nhoff, sizeof(_iph), data,
   833						   hlen, &_iph);
   834			if (!iph)
   835				return FLOW_DISSECT_RET_OUT_BAD;
   836	
   837			udph = __skb_header_pointer(skb, *p_nhoff, sizeof(_udph), data,
   838						    hlen, &_udph);
   839			if (!udph)
   840				return FLOW_DISSECT_RET_OUT_BAD;
   841	
   842			rcu_read_lock();
   843			/* Look up the UDPv4 socket and get the encap_type */
 > 844			sk = __udp4_lib_lookup(net, iph->saddr, udph->source,
   845					       iph->daddr, udph->dest,
   846					       inet_iif(skb), inet_sdif(skb),
   847					       net->ipv4.udp_table, NULL);
   848			if (!sk || !udp_sk(sk)->encap_type) {
   849				rcu_read_unlock();
   850				return FLOW_DISSECT_RET_OUT_GOOD;
   851			}
   852	
   853			encap_type = udp_sk(sk)->encap_type;
   854			rcu_read_unlock();
   855	
   856			break;
   857		}
   858	#if IS_ENABLED(CONFIG_IPV6)
   859		case htons(ETH_P_IPV6): {
   860			const struct ipv6hdr *iph;
   861			struct ipv6hdr _iph;
   862	
   863			if (!likely(ipv6_bpf_stub))
   864				return FLOW_DISSECT_RET_OUT_GOOD;
   865	
   866			iph = __skb_header_pointer(skb, base_nhoff, sizeof(_iph), data,
   867						   hlen, &_iph);
   868			if (!iph)
   869				return FLOW_DISSECT_RET_OUT_BAD;
   870	
   871			udph = __skb_header_pointer(skb, *p_nhoff, sizeof(_udph), data,
   872						    hlen, &_udph);
   873			if (!udph)
   874				return FLOW_DISSECT_RET_OUT_BAD;
   875	
   876			rcu_read_lock();
   877			/* Look up the UDPv6 socket and get the encap_type */
   878			sk = ipv6_bpf_stub->udp6_lib_lookup(net,
   879					&iph->saddr, udph->source,
   880					&iph->daddr, udph->dest,
   881					inet_iif(skb), inet_sdif(skb),
   882					net->ipv4.udp_table, NULL);
   883	
   884			if (!sk || !udp_sk(sk)->encap_type) {
   885				rcu_read_unlock();
   886				return FLOW_DISSECT_RET_OUT_GOOD;
   887			}
   888	
   889			encap_type = udp_sk(sk)->encap_type;
   890			rcu_read_unlock();
   891	
   892			break;
   893		}
   894	#endif /* CONFIG_IPV6 */
   895		default:
   896			return FLOW_DISSECT_RET_OUT_GOOD;
   897		}
   898	
   899		nhoff = *p_nhoff + sizeof(struct udphdr);
   900		ret = FLOW_DISSECT_RET_OUT_GOOD;
   901	
   902		switch (encap_type) {
   903		default:
   904			break;
   905		}
   906	
   907		switch (ret) {
   908		case FLOW_DISSECT_RET_PROTO_AGAIN:
   909			*p_ip_proto = 0;
   910			fallthrough;
   911		case FLOW_DISSECT_RET_IPPROTO_AGAIN:
   912			*p_nhoff = nhoff;
   913			break;
   914		default:
   915			break;
   916		}
   917	
   918		return ret;
   919	}
   920	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE
  2024-08-16 18:54   ` Willem de Bruijn
@ 2024-08-20 16:21     ` Tom Herbert
  2024-08-20 16:30       ` Willem de Bruijn
  0 siblings, 1 reply; 33+ messages in thread
From: Tom Herbert @ 2024-08-20 16:21 UTC (permalink / raw)
  To: Willem de Bruijn; +Cc: davem, kuba, edumazet, netdev, felipe

On Fri, Aug 16, 2024 at 11:54 AM Willem de Bruijn
<willemdebruijn.kernel@gmail.com> wrote:
>
> Tom Herbert wrote:
> > ETH_P_TEB (Trans Ether Bridging) is the EtherType to carry
> > a plain Etherent frame. Add case in skb_flow_dissect to parse
> > packets of this type
> >
> > If the GRE protocol is ETH_P_TEB then just process that as any
> > another EtherType since it's now supported in the main loop
> >
> > Signed-off-by: Tom Herbert <tom@herbertland.com>
>
> Reviewed-by: Willem de Bruijn <willemb@google.com>
>
> > -     if (gre_ver == 0) {
> > -             if (*p_proto == htons(ETH_P_TEB)) {
> > -                     const struct ethhdr *eth;
> > -                     struct ethhdr _eth;
> > -
> > -                     eth = __skb_header_pointer(skb, *p_nhoff + offset,
> > -                                                sizeof(_eth),
> > -                                                data, *p_hlen, &_eth);
> > -                     if (!eth)
> > -                             return FLOW_DISSECT_RET_OUT_BAD;
> > -                     *p_proto = eth->h_proto;
> > -                     offset += sizeof(*eth);
> > -
> > -                     /* Cap headers that we access via pointers at the
> > -                      * end of the Ethernet header as our maximum alignment
> > -                      * at that point is only 2 bytes.
> > -                      */
> > -                     if (NET_IP_ALIGN)
> > -                             *p_hlen = *p_nhoff + offset;
> > -             }
> > -     } else { /* version 1, must be PPTP */
>
> > @@ -1284,6 +1268,27 @@ bool __skb_flow_dissect(const struct net *net,
> >
> >               break;
> >       }
> > +     case htons(ETH_P_TEB): {
> > +             const struct ethhdr *eth;
> > +             struct ethhdr _eth;
> > +
> > +             eth = __skb_header_pointer(skb, nhoff, sizeof(_eth),
> > +                                        data, hlen, &_eth);
> > +             if (!eth)
> > +                     goto out_bad;
> > +
> > +             proto = eth->h_proto;
> > +             nhoff += sizeof(*eth);
> > +
> > +             /* Cap headers that we access via pointers at the
> > +              * end of the Ethernet header as our maximum alignment
> > +              * at that point is only 2 bytes.
> > +              */
> > +             if (NET_IP_ALIGN)
> > +                     hlen = nhoff;
>
> I wonder why this exists. But besides the point of this move.

Willem,

Ethernet header breaks 4-byte alignment of encapsulated protocols
since it's 14 bytes, so the NET_IP_ALIGN can be used on architectures
that don't like unaligned loads.

Tom

>
> > +
> > +             goto proto_again;
> > +     }
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE
  2024-08-20 16:21     ` Tom Herbert
@ 2024-08-20 16:30       ` Willem de Bruijn
  2024-08-20 16:42         ` Tom Herbert
  0 siblings, 1 reply; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-20 16:30 UTC (permalink / raw)
  To: Tom Herbert, Willem de Bruijn; +Cc: davem, kuba, edumazet, netdev, felipe

Tom Herbert wrote:
> On Fri, Aug 16, 2024 at 11:54 AM Willem de Bruijn
> <willemdebruijn.kernel@gmail.com> wrote:
> >
> > Tom Herbert wrote:
> > > ETH_P_TEB (Trans Ether Bridging) is the EtherType to carry
> > > a plain Etherent frame. Add case in skb_flow_dissect to parse
> > > packets of this type
> > >
> > > If the GRE protocol is ETH_P_TEB then just process that as any
> > > another EtherType since it's now supported in the main loop
> > >
> > > Signed-off-by: Tom Herbert <tom@herbertland.com>
> >
> > Reviewed-by: Willem de Bruijn <willemb@google.com>
> >
> > > -     if (gre_ver == 0) {
> > > -             if (*p_proto == htons(ETH_P_TEB)) {
> > > -                     const struct ethhdr *eth;
> > > -                     struct ethhdr _eth;
> > > -
> > > -                     eth = __skb_header_pointer(skb, *p_nhoff + offset,
> > > -                                                sizeof(_eth),
> > > -                                                data, *p_hlen, &_eth);
> > > -                     if (!eth)
> > > -                             return FLOW_DISSECT_RET_OUT_BAD;
> > > -                     *p_proto = eth->h_proto;
> > > -                     offset += sizeof(*eth);
> > > -
> > > -                     /* Cap headers that we access via pointers at the
> > > -                      * end of the Ethernet header as our maximum alignment
> > > -                      * at that point is only 2 bytes.
> > > -                      */
> > > -                     if (NET_IP_ALIGN)
> > > -                             *p_hlen = *p_nhoff + offset;
> > > -             }
> > > -     } else { /* version 1, must be PPTP */
> >
> > > @@ -1284,6 +1268,27 @@ bool __skb_flow_dissect(const struct net *net,
> > >
> > >               break;
> > >       }
> > > +     case htons(ETH_P_TEB): {
> > > +             const struct ethhdr *eth;
> > > +             struct ethhdr _eth;
> > > +
> > > +             eth = __skb_header_pointer(skb, nhoff, sizeof(_eth),
> > > +                                        data, hlen, &_eth);
> > > +             if (!eth)
> > > +                     goto out_bad;
> > > +
> > > +             proto = eth->h_proto;
> > > +             nhoff += sizeof(*eth);
> > > +
> > > +             /* Cap headers that we access via pointers at the
> > > +              * end of the Ethernet header as our maximum alignment
> > > +              * at that point is only 2 bytes.
> > > +              */
> > > +             if (NET_IP_ALIGN)
> > > +                     hlen = nhoff;
> >
> > I wonder why this exists. But besides the point of this move.
> 
> Willem,
> 
> Ethernet header breaks 4-byte alignment of encapsulated protocols
> since it's 14 bytes, so the NET_IP_ALIGN can be used on architectures
> that don't like unaligned loads.

I understand how NET_IP_ALIGN is used by drivers.

I don't understand its use here in the flow dissector. Why is hlen
capped if it is set?

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE
  2024-08-20 16:30       ` Willem de Bruijn
@ 2024-08-20 16:42         ` Tom Herbert
  2024-08-20 17:43           ` Willem de Bruijn
  0 siblings, 1 reply; 33+ messages in thread
From: Tom Herbert @ 2024-08-20 16:42 UTC (permalink / raw)
  To: Willem de Bruijn; +Cc: davem, kuba, edumazet, netdev, felipe

On Tue, Aug 20, 2024 at 9:30 AM Willem de Bruijn
<willemdebruijn.kernel@gmail.com> wrote:
>
> Tom Herbert wrote:
> > On Fri, Aug 16, 2024 at 11:54 AM Willem de Bruijn
> > <willemdebruijn.kernel@gmail.com> wrote:
> > >
> > > Tom Herbert wrote:
> > > > ETH_P_TEB (Trans Ether Bridging) is the EtherType to carry
> > > > a plain Etherent frame. Add case in skb_flow_dissect to parse
> > > > packets of this type
> > > >
> > > > If the GRE protocol is ETH_P_TEB then just process that as any
> > > > another EtherType since it's now supported in the main loop
> > > >
> > > > Signed-off-by: Tom Herbert <tom@herbertland.com>
> > >
> > > Reviewed-by: Willem de Bruijn <willemb@google.com>
> > >
> > > > -     if (gre_ver == 0) {
> > > > -             if (*p_proto == htons(ETH_P_TEB)) {
> > > > -                     const struct ethhdr *eth;
> > > > -                     struct ethhdr _eth;
> > > > -
> > > > -                     eth = __skb_header_pointer(skb, *p_nhoff + offset,
> > > > -                                                sizeof(_eth),
> > > > -                                                data, *p_hlen, &_eth);
> > > > -                     if (!eth)
> > > > -                             return FLOW_DISSECT_RET_OUT_BAD;
> > > > -                     *p_proto = eth->h_proto;
> > > > -                     offset += sizeof(*eth);
> > > > -
> > > > -                     /* Cap headers that we access via pointers at the
> > > > -                      * end of the Ethernet header as our maximum alignment
> > > > -                      * at that point is only 2 bytes.
> > > > -                      */
> > > > -                     if (NET_IP_ALIGN)
> > > > -                             *p_hlen = *p_nhoff + offset;
> > > > -             }
> > > > -     } else { /* version 1, must be PPTP */
> > >
> > > > @@ -1284,6 +1268,27 @@ bool __skb_flow_dissect(const struct net *net,
> > > >
> > > >               break;
> > > >       }
> > > > +     case htons(ETH_P_TEB): {
> > > > +             const struct ethhdr *eth;
> > > > +             struct ethhdr _eth;
> > > > +
> > > > +             eth = __skb_header_pointer(skb, nhoff, sizeof(_eth),
> > > > +                                        data, hlen, &_eth);
> > > > +             if (!eth)
> > > > +                     goto out_bad;
> > > > +
> > > > +             proto = eth->h_proto;
> > > > +             nhoff += sizeof(*eth);
> > > > +
> > > > +             /* Cap headers that we access via pointers at the
> > > > +              * end of the Ethernet header as our maximum alignment
> > > > +              * at that point is only 2 bytes.
> > > > +              */
> > > > +             if (NET_IP_ALIGN)
> > > > +                     hlen = nhoff;
> > >
> > > I wonder why this exists. But besides the point of this move.
> >
> > Willem,
> >
> > Ethernet header breaks 4-byte alignment of encapsulated protocols
> > since it's 14 bytes, so the NET_IP_ALIGN can be used on architectures
> > that don't like unaligned loads.
>
> I understand how NET_IP_ALIGN is used by drivers.
>
> I don't understand its use here in the flow dissector. Why is hlen
> capped if it is set?

Willem,

For the real Ethernet header the receive skbuf is offset by two so
that device places the packet such that the Ethernet payload, i.e. IP
header, is aligned to four bytes (14+2=16 which will be offset of IP
header). When a packets contains an encapsulated Ethernet header, the
offset of the header is aligned to four bytes which means the payload
of that Ethernet header, i.e. an encapsulated IP header, is not four
byte aligned and neither are any subsequent headers (TCP, UDP, etc.).
On some architectures, performing unaligned loads is expensive
compared to aligned loads, so hlen is being capped here to avoid
having flow dissector do that on unaligned headers after the Ethernet
header. It's a tradeoff between performance and deeper flow
dissection.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE
  2024-08-20 16:42         ` Tom Herbert
@ 2024-08-20 17:43           ` Willem de Bruijn
  0 siblings, 0 replies; 33+ messages in thread
From: Willem de Bruijn @ 2024-08-20 17:43 UTC (permalink / raw)
  To: Tom Herbert, Willem de Bruijn; +Cc: davem, kuba, edumazet, netdev, felipe

> > > > > +             /* Cap headers that we access via pointers at the
> > > > > +              * end of the Ethernet header as our maximum alignment
> > > > > +              * at that point is only 2 bytes.
> > > > > +              */
> > > > > +             if (NET_IP_ALIGN)
> > > > > +                     hlen = nhoff;
> > > >
> > > > I wonder why this exists. But besides the point of this move.
> > >
> > > Willem,
> > >
> > > Ethernet header breaks 4-byte alignment of encapsulated protocols
> > > since it's 14 bytes, so the NET_IP_ALIGN can be used on architectures
> > > that don't like unaligned loads.
> >
> > I understand how NET_IP_ALIGN is used by drivers.
> >
> > I don't understand its use here in the flow dissector. Why is hlen
> > capped if it is set?
> 
> Willem,
> 
> For the real Ethernet header the receive skbuf is offset by two so
> that device places the packet such that the Ethernet payload, i.e. IP
> header, is aligned to four bytes (14+2=16 which will be offset of IP
> header). When a packets contains an encapsulated Ethernet header, the
> offset of the header is aligned to four bytes which means the payload
> of that Ethernet header, i.e. an encapsulated IP header, is not four
> byte aligned and neither are any subsequent headers (TCP, UDP, etc.).

> On some architectures, performing unaligned loads is expensive
> compared to aligned loads, so hlen is being capped here to avoid
> having flow dissector do that on unaligned headers after the Ethernet
> header. It's a tradeoff between performance and deeper flow
> dissection.

Thanks Tom. That explains.

So flow dissector behavior differs in this subtle way depending on
platform.

Maybe this is a good opportunity to add a comment. This thread alone
also already documents it to some extent.


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 05/12] flow_dissector: Parse vxlan in UDP
  2024-08-17  1:09   ` Jakub Kicinski
@ 2024-08-20 18:15     ` Tom Herbert
  0 siblings, 0 replies; 33+ messages in thread
From: Tom Herbert @ 2024-08-20 18:15 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: davem, edumazet, netdev, felipe, willemdebruijn.kernel

On Fri, Aug 16, 2024 at 6:09 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Thu, 15 Aug 2024 14:45:20 -0700 Tom Herbert wrote:
> > +     if (hdr->vx_flags & VXLAN_F_GPE) {
>
> sparse points out that VXLAN_F_GPE needs to be byte swapped
>
> not 100% sure I'm following the scheme but it appears _F_ flags are in
> CPU byte order, and _HF_ flags are in network

Hmmm, VXLAN does seem to be a bit squirrely :-) AFAICT, a VXLAN-GPE
packet isn't self identifying but requires a VNI lookup which is what
the vxlan driver. We don't have access to that table in flow
dissector, but I think we can safely infer a VXLAN-GPE packet if the
next proto-applied flag bit is set (it's always set for VXLAN-GPE,
never for VXLAN).

Tom



> --
> pw-bot: cr

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols
  2024-08-16 20:19 ` [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Willem de Bruijn
@ 2024-08-20 18:28   ` Tom Herbert
  0 siblings, 0 replies; 33+ messages in thread
From: Tom Herbert @ 2024-08-20 18:28 UTC (permalink / raw)
  To: Willem de Bruijn; +Cc: davem, kuba, edumazet, netdev, felipe

On Fri, Aug 16, 2024 at 1:19 PM Willem de Bruijn
<willemdebruijn.kernel@gmail.com> wrote:
>
> Tom Herbert wrote:
> > Add support in flow_dissector for dissecting into UDP
> > encapsulations like VXLAN. __skb_flow_dissect_udp is called for
> > IPPROTO_UDP. The flag FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS enables parsing
> > of UDP encapsulations. If the flag is set when parsing a UDP packet then
> > a socket lookup is performed. The offset of the base network header,
> > either an IPv4 or IPv6 header, is tracked and passed to
> > __skb_flow_dissect_udp so that it can perform the socket lookup.
> > If a socket is found and it's for a UDP encapsulation (encap_type is
> > set in the UDP socket) then a switch is performed on the encap_type
> > value (cases are UDP_ENCAP_* values)
> >
> > Changes in the patch set:
> >
> > - Unconstantify struct net argument in flowdis functions so we can call
> >   UDP socket lookup functions
> > - Dissect ETH_P_TEB in main flow dissector loop, move ETH_P_TEB check
> >   out of __skb_flow_dissect_gre and process it in main loop
> > - Add UDP_ENCAP constants for tipc, fou, gue, sctp, rxe, pfcp,
> >   wireguard, bareudp, vxlan, vxlan_gpe, geneve, and amt
> > - For the various UDP encapsulation protocols, Instead of just setting
> >   UDP tunnel encap type to 1, set it to the corresponding UDP_ENCAP
> >   constant. This allows identify the encapsulation protocol for a
> >   UDP socket by the encap_type
> > - Add function __skb_flow_dissect_udp in flow_dissector and call it for
> >   UDP packets. If a UDP encapsulation is present then the function
> >   returns either FLOW_DISSECT_RET_PROTO_AGAIN or
> >   FLOW_DISSECT_RET_IPPROTO_AGAIN
> > - Add flag FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS that indicates UDP
> >   encapsulations should be dissected
> > - Add __skb_flow_dissect_vxlan which is called when encap_type is
> >   UDP_ENCAP_VXLAN or UDP_ENCAP_VXLAN_GPE. Dissect VXLAN and return
> >   a next protocol and offset
> > - Add __skb_flow_dissect_fou which is called when encap_type is
> >   UDP_ENCAP_FOU. Dissect FOU and return a next protocol and offset
> > - Add support for ESP, L2TP, and SCTP in UDP in __skb_flow_dissect_udp.
> >   All we need to do is return FLOW_DISSECT_RET_IPPROTO_AGAIN and the
> >   corresponding IP protocol number
> > - Add __skb_flow_dissect_geneve which is called when encap_type is
> >   UDP_ENCAP_GENEVE. Dissect geneve and return a next protocol and offset
> > - Add __skb_flow_dissect_gue which is called when encap_type is
> >   UDP_ENCAP_GUE. Dissect gue and return a next protocol and offset
> > - Add __skb_flow_dissect_gtp which is called when encap_type is
> >   UDP_ENCAP_GTP. Dissect gtp and return a next protocol and offset
> >
> > Tested: Verified fou, gue, vxlan, and geneve are properly dissected for
> > IPv4 and IPv6 cases. This includes testing ETH_P_TEB case
>
> On our conversation in v1 that this is manual:
>
> Would be really nice to have some test coverage for flow dissection.
> We only have this for BPF flow dissection. This seems like a suitable
> candidate for KUNIT. Like gso_test_func. Don't mean to put you on the
> spot per se to add this coverage.

Sure. We'll add a KUNIT test for flow dissector (it sorely needs that!)

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure
  2024-08-15 21:45 ` [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure Tom Herbert
  2024-08-16 19:09   ` Willem de Bruijn
  2024-08-17 14:01   ` kernel test robot
@ 2024-08-20 18:52   ` Eric Dumazet
  2024-08-20 19:00     ` Tom Herbert
  2 siblings, 1 reply; 33+ messages in thread
From: Eric Dumazet @ 2024-08-20 18:52 UTC (permalink / raw)
  To: Tom Herbert; +Cc: davem, kuba, netdev, felipe, willemdebruijn.kernel

On Thu, Aug 15, 2024 at 11:46 PM Tom Herbert <tom@herbertland.com> wrote:
>
> Add infrastructure for parsing into UDP encapsulations
>
> Add function __skb_flow_dissect_udp that is called for IPPROTO_UDP.
> The flag FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS enables parsing of UDP
> encapsulations. If the flag is set when parsing a UDP packet then
> a socket lookup is performed. The offset of the base network header,
> either an IPv4 or IPv6 header, is tracked and passed to
> __skb_flow_dissect_udp so that it can perform the socket lookup
>
> If a socket is found and it's for a UDP encapsulation (encap_type is
> set in the UDP socket) then a switch is performed on the encap_type
> value (cases are UDP_ENCAP_* values)
>
> An encapsulated packet in UDP can either be indicated by an
> EtherType or IP protocol. The processing for dissecting a UDP encap
> protocol returns a flow dissector return code. If
> FLOW_DISSECT_RET_PROTO_AGAIN or FLOW_DISSECT_RET_IPPROTO_AGAIN is
> returned then the corresponding  encapsulated protocol is dissected.
> The nhoff is set to point to the header to process.  In the case
> FLOW_DISSECT_RET_PROTO_AGAIN the EtherType protocol is returned and
> the IP protocol is set to zero. In the case of
> FLOW_DISSECT_RET_IPPROTO_AGAIN, the IP protocol is returned and
> the EtherType protocol is returned unchanged
>
> Signed-off-by: Tom Herbert <tom@herbertland.com>

I am a bit confused.

How is this series netns ready ?

tunnel decap devices can be in different netns from the lower device.

socket lookups need the correct net pointer.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure
  2024-08-20 18:52   ` Eric Dumazet
@ 2024-08-20 19:00     ` Tom Herbert
  0 siblings, 0 replies; 33+ messages in thread
From: Tom Herbert @ 2024-08-20 19:00 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: davem, kuba, netdev, felipe, willemdebruijn.kernel

On Tue, Aug 20, 2024 at 11:52 AM Eric Dumazet <edumazet@google.com> wrote:
>
> On Thu, Aug 15, 2024 at 11:46 PM Tom Herbert <tom@herbertland.com> wrote:
> >
> > Add infrastructure for parsing into UDP encapsulations
> >
> > Add function __skb_flow_dissect_udp that is called for IPPROTO_UDP.
> > The flag FLOW_DISSECTOR_F_PARSE_UDP_ENCAPS enables parsing of UDP
> > encapsulations. If the flag is set when parsing a UDP packet then
> > a socket lookup is performed. The offset of the base network header,
> > either an IPv4 or IPv6 header, is tracked and passed to
> > __skb_flow_dissect_udp so that it can perform the socket lookup
> >
> > If a socket is found and it's for a UDP encapsulation (encap_type is
> > set in the UDP socket) then a switch is performed on the encap_type
> > value (cases are UDP_ENCAP_* values)
> >
> > An encapsulated packet in UDP can either be indicated by an
> > EtherType or IP protocol. The processing for dissecting a UDP encap
> > protocol returns a flow dissector return code. If
> > FLOW_DISSECT_RET_PROTO_AGAIN or FLOW_DISSECT_RET_IPPROTO_AGAIN is
> > returned then the corresponding  encapsulated protocol is dissected.
> > The nhoff is set to point to the header to process.  In the case
> > FLOW_DISSECT_RET_PROTO_AGAIN the EtherType protocol is returned and
> > the IP protocol is set to zero. In the case of
> > FLOW_DISSECT_RET_IPPROTO_AGAIN, the IP protocol is returned and
> > the EtherType protocol is returned unchanged
> >
> > Signed-off-by: Tom Herbert <tom@herbertland.com>
>
> I am a bit confused.
>
> How is this series netns ready ?
>
> tunnel decap devices can be in different netns from the lower device.
>
> socket lookups need the correct net pointer.

Hi Eric,

How would we know what the correct net pointer is? Seems like there
could be multiple choices if netns were nested. Maybe best effort is
sufficient here?

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2024-08-20 19:00 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-15 21:45 [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Tom Herbert
2024-08-15 21:45 ` [PATCH net-next v2 01/12] flow_dissector: Parse ETH_P_TEB and move out of GRE Tom Herbert
2024-08-16 18:54   ` Willem de Bruijn
2024-08-20 16:21     ` Tom Herbert
2024-08-20 16:30       ` Willem de Bruijn
2024-08-20 16:42         ` Tom Herbert
2024-08-20 17:43           ` Willem de Bruijn
2024-08-15 21:45 ` [PATCH net-next v2 02/12] udp_encaps: Add new UDP_ENCAP constants Tom Herbert
2024-08-16 18:56   ` Willem de Bruijn
2024-08-15 21:45 ` [PATCH net-next v2 03/12] udp_encaps: Set proper UDP_ENCAP types in tunnel setup Tom Herbert
2024-08-15 21:45 ` [PATCH net-next v2 04/12] flow_dissector: UDP encap infrastructure Tom Herbert
2024-08-16 19:09   ` Willem de Bruijn
2024-08-17 14:01   ` kernel test robot
2024-08-20 18:52   ` Eric Dumazet
2024-08-20 19:00     ` Tom Herbert
2024-08-15 21:45 ` [PATCH net-next v2 05/12] flow_dissector: Parse vxlan in UDP Tom Herbert
2024-08-16 19:19   ` Willem de Bruijn
2024-08-17  1:09   ` Jakub Kicinski
2024-08-20 18:15     ` Tom Herbert
2024-08-15 21:45 ` [PATCH net-next v2 06/12] flow_dissector: Parse foo-over-udp (FOU) Tom Herbert
2024-08-15 21:45 ` [PATCH net-next v2 07/12] flow_dissector: Parse ESP, L2TP, and SCTP in UDP Tom Herbert
2024-08-16 19:20   ` Willem de Bruijn
2024-08-15 21:45 ` [PATCH net-next v2 08/12] flow_dissector: Parse Geneve " Tom Herbert
2024-08-16 19:21   ` Willem de Bruijn
2024-08-15 21:45 ` [PATCH net-next v2 09/12] flow_dissector: Parse GUE " Tom Herbert
2024-08-16 19:25   ` Willem de Bruijn
2024-08-15 21:45 ` [PATCH net-next v2 10/12] gtp: Move gtp_parse_exthdrs into net/gtp.h Tom Herbert
2024-08-16 19:27   ` Willem de Bruijn
2024-08-15 21:45 ` [PATCH net-next v2 11/12] flow_dissector: Parse gtp in UDP Tom Herbert
2024-08-15 21:45 ` [PATCH net-next v2 12/12] flow_dissector: Add case in ipproto switch for NEXTHDR_NONE Tom Herbert
2024-08-16 19:28   ` Willem de Bruijn
2024-08-16 20:19 ` [PATCH net-next v2 00/12] flow_dissector: Dissect UDP encapsulation protocols Willem de Bruijn
2024-08-20 18:28   ` Tom Herbert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).