Skip to contentSkip to conversation

net: openvswitch: IPv6: Add IPv6 extension header support

PATCH Superseded Toms Atteka 3 participants 4 messages Oct 14, 2021 – Oct 19, 2021

Subsystems (3)

v7 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

PATCH v7 1/1 net: openvswitch: IPv6: Add IPv6 extension header support

This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and packets can be filtered using ipv6_ext flag.

---
 include/uapi/linux/openvswitch.h |  16 +++-
 net/openvswitch/flow.c           | 140 +++++++++++++++++++++++++++++++
 net/openvswitch/flow.h           |  14 ++++
 net/openvswitch/flow_netlink.c   |  24 +++++-
 4 files changed, 192 insertions(+), 2 deletions(-)
include/uapi/linux/openvswitch.h +15 -1
index a87b44cd5590..763adf3dce23 100644
@@ -344,8 +344,17 @@ enum ovs_key_attr {
 	OVS_KEY_ATTR_NSH,       /* Nested set of ovs_nsh_key_* */
 
 #ifdef __KERNEL__
-	OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
+	OVS_KEY_ATTR_TUNNEL_INFO,/* struct ip_tunnel_info */
+	__OVS_KEY_ATTR_PADDING_1,/* Padding to match field count with ovs */
 #endif
+
+#ifndef __KERNEL__
+	__OVS_KEY_ATTR_PADDING_2,/* Padding to match field count with ovs */
+	__OVS_KEY_ATTR_PADDING_3,/* Padding to match field count with ovs */
+#endif
+
+	OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
+
 	__OVS_KEY_ATTR_MAX
 };
 
@@ -421,6 +430,11 @@ struct ovs_key_ipv6 {
 	__u8   ipv6_frag;	/* One of OVS_FRAG_TYPE_*. */
 };
 
+/* separate structure to support backward compatibility with older user space */
+struct ovs_key_ipv6_exthdrs {
+	__u16  hdrs;
+};
+
 struct ovs_key_tcp {
 	__be16 tcp_src;
 	__be16 tcp_dst;
net/openvswitch/flow.c +140 -0

152 lines not on this page · raw message

net/openvswitch/flow.h +14 -0
index 758a8c77f736..073ab73ffeaa 100644
@@ -32,6 +32,19 @@ enum sw_flow_mac_proto {
 #define SW_FLOW_KEY_INVALID	0x80
 #define MPLS_LABEL_DEPTH       3
 
+/* Bit definitions for IPv6 Extension Header pseudo-field. */
+enum ofp12_ipv6exthdr_flags {
+	OFPIEH12_NONEXT = 1 << 0,   /* "No next header" encountered. */
+	OFPIEH12_ESP    = 1 << 1,   /* Encrypted Sec Payload header present. */
+	OFPIEH12_AUTH   = 1 << 2,   /* Authentication header present. */
+	OFPIEH12_DEST   = 1 << 3,   /* 1 or 2 dest headers present. */
+	OFPIEH12_FRAG   = 1 << 4,   /* Fragment header present. */
+	OFPIEH12_ROUTER = 1 << 5,   /* Router header present. */
+	OFPIEH12_HOP    = 1 << 6,   /* Hop-by-hop header present. */
+	OFPIEH12_UNREP  = 1 << 7,   /* Unexpected repeats encountered. */
+	OFPIEH12_UNSEQ  = 1 << 8    /* Unexpected sequencing encountered. */
+};
+
 /* Store options at the end of the array if they are less than the
  * maximum size. This allows us to get the benefits of variable length
  * matching for small options.
@@ -121,6 +134,7 @@ struct sw_flow_key {
 				struct in6_addr dst;	/* IPv6 destination address. */
 			} addr;
 			__be32 label;			/* IPv6 flow label. */
+			u16 exthdrs;	/* IPv6 extension header flags */
 			union {
 				struct {
 					struct in6_addr src;
net/openvswitch/flow_netlink.c +23 -1
index 65c2e3458ff5..2fbf324fcfff 100644
@@ -367,7 +367,8 @@ size_t ovs_key_attr_size(void)
 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
 		+ nla_total_size(40)  /* OVS_KEY_ATTR_IPV6 */
 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ICMPV6 */
-		+ nla_total_size(28); /* OVS_KEY_ATTR_ND */
+		+ nla_total_size(28)  /* OVS_KEY_ATTR_ND */
+		+ nla_total_size(2);  /* OVS_KEY_ATTR_IPV6_EXTHDRS */
 }
 
 static const struct ovs_len_tbl ovs_vxlan_ext_key_lens[OVS_VXLAN_EXT_MAX + 1] = {
@@ -435,6 +436,8 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
 		.len = sizeof(struct ovs_key_ct_tuple_ipv6) },
 	[OVS_KEY_ATTR_NSH]       = { .len = OVS_ATTR_NESTED,
 				     .next = ovs_nsh_key_attr_lens, },
+	[OVS_KEY_ATTR_IPV6_EXTHDRS] = {
+		.len = sizeof(struct ovs_key_ipv6_exthdrs) },
 };
 
 static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
@@ -1595,6 +1598,17 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
 		attrs &= ~(1 << OVS_KEY_ATTR_IPV6);
 	}
 
+	if (attrs & (1ULL << OVS_KEY_ATTR_IPV6_EXTHDRS)) {
+		const struct ovs_key_ipv6_exthdrs *ipv6_exthdrs_key;
+
+		ipv6_exthdrs_key = nla_data(a[OVS_KEY_ATTR_IPV6_EXTHDRS]);
+
+		SW_FLOW_KEY_PUT(match, ipv6.exthdrs,
+				ipv6_exthdrs_key->hdrs, is_mask);
+
+		attrs &= ~(1ULL << OVS_KEY_ATTR_IPV6_EXTHDRS);
+	}
+
 	if (attrs & (1 << OVS_KEY_ATTR_ARP)) {
 		const struct ovs_key_arp *arp_key;
 
@@ -2097,6 +2111,7 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
 		ipv4_key->ipv4_frag = output->ip.frag;
 	} else if (swkey->eth.type == htons(ETH_P_IPV6)) {
 		struct ovs_key_ipv6 *ipv6_key;
+		struct ovs_key_ipv6_exthdrs *ipv6_exthdrs_key;
 
 		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV6, sizeof(*ipv6_key));
 		if (!nla)
@@ -2111,6 +2126,13 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
 		ipv6_key->ipv6_tclass = output->ip.tos;
 		ipv6_key->ipv6_hlimit = output->ip.ttl;
 		ipv6_key->ipv6_frag = output->ip.frag;
+
+		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV6_EXTHDRS,
+				  sizeof(*ipv6_exthdrs_key));
+		if (!nla)
+			goto nla_put_failure;
+		ipv6_exthdrs_key = nla_data(nla);
+		ipv6_exthdrs_key->hdrs = output->ipv6.exthdrs;
 	} else if (swkey->eth.type == htons(ETH_P_NSH)) {
 		if (nsh_key_to_nlattr(&output->nsh, is_mask, skb))
 			goto nla_put_failure;
Signature · 1 line
2.25.1
maintainer
#1 lore raw
Quoted 23 lines · Toms Atteka

This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and packets can be filtered using ipv6_ext flag.

---
 include/uapi/linux/openvswitch.h |  16 +++-
 net/openvswitch/flow.c           | 140 +++++++++++++++++++++++++++++++
 net/openvswitch/flow.h           |  14 ++++
 net/openvswitch/flow_netlink.c   |  24 +++++-
 4 files changed, 192 insertions(+), 2 deletions(-)
include/uapi/linux/openvswitch.h +2 -1
index a87b44cd5590..763adf3dce23 100644
@@ -344,8 +344,17 @@ enum ovs_key_attr {
 	OVS_KEY_ATTR_NSH,       /* Nested set of ovs_nsh_key_* */
 
 #ifdef __KERNEL__
-	OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
+	OVS_KEY_ATTR_TUNNEL_INFO,/* struct ip_tunnel_info */
+	__OVS_KEY_ATTR_PADDING_1,/* Padding to match field count with ovs */
 #endif

include/uapi/linux/openvswitch.h enum ovs_key_attr { · line 359

Quoted 10 lines
include/uapi/linux/openvswitch.h +8 -0
+
+#ifndef __KERNEL__
+	__OVS_KEY_ATTR_PADDING_2,/* Padding to match field count with ovs */
+	__OVS_KEY_ATTR_PADDING_3,/* Padding to match field count with ovs */
+#endif
+
+	OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
+
 	__OVS_KEY_ATTR_MAX
 };

Not a full review, but, I think, that we should not add paddings, and define OVS_KEY_ATTR_IPV6_EXTHDRS before the OVS_KEY_ATTR_TUNNEL_INFO instead. See my comments for v6:
https://lore.kernel.org/netdev/[email protected]/T/#u

Best regards, Ilya Maximets.

#2 lore raw

Le 15/10/2021 à 15:56, Ilya Maximets a écrit :
[snip]

Quoted 3 lines

Not a full review, but, I think, that we should not add paddings, and define OVS_KEY_ATTR_IPV6_EXTHDRS before the OVS_KEY_ATTR_TUNNEL_INFO instead. See my comments for v6:

+1

author
#3 lore raw
In reply to Ilya Maximets
Quoted 41 lines · Ilya Maximets
Quoted 23 lines · Toms Atteka

This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and packets can be filtered using ipv6_ext flag.

---
 include/uapi/linux/openvswitch.h |  16 +++-
 net/openvswitch/flow.c           | 140 +++++++++++++++++++++++++++++++
 net/openvswitch/flow.h           |  14 ++++
 net/openvswitch/flow_netlink.c   |  24 +++++-
 4 files changed, 192 insertions(+), 2 deletions(-)
include/uapi/linux/openvswitch.h +2 -1
index a87b44cd5590..763adf3dce23 100644
@@ -344,8 +344,17 @@ enum ovs_key_attr {
      OVS_KEY_ATTR_NSH,       /* Nested set of ovs_nsh_key_* */
 
 #ifdef __KERNEL__
-     OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
+     OVS_KEY_ATTR_TUNNEL_INFO,/* struct ip_tunnel_info */
+     __OVS_KEY_ATTR_PADDING_1,/* Padding to match field count with ovs */
 #endif

include/uapi/linux/openvswitch.h enum ovs_key_attr { · line 359

Quoted 10 lines
include/uapi/linux/openvswitch.h +8 -0
+
+#ifndef __KERNEL__
+     __OVS_KEY_ATTR_PADDING_2,/* Padding to match field count with ovs */
+     __OVS_KEY_ATTR_PADDING_3,/* Padding to match field count with ovs */
+#endif
+
+     OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
+
      __OVS_KEY_ATTR_MAX
 };

Not a full review, but, I think, that we should not add paddings, and define OVS_KEY_ATTR_IPV6_EXTHDRS before the OVS_KEY_ATTR_TUNNEL_INFO instead. See my comments for v6:
https://lore.kernel.org/netdev/[email protected]/T/#u

Quoted 1 line

Best regards, Ilya Maximets.

Maybe I am still missing the idea, but I think it's not possible.

If we consider userspace code:
OVS_KEY_ATTR_NSH, /* Nested set of ovs_nsh_key_* */

#ifdef __KERNEL__
/* Only used within kernel data path. */ OVS_KEY_ATTR_TUNNEL_INFO, /* struct ovs_tunnel_info */ #endif

#ifndef __KERNEL__
/* Only used within userspace data path. */ OVS_KEY_ATTR_PACKET_TYPE, /* be32 packet type */ OVS_KEY_ATTR_ND_EXTENSIONS, /* struct ovs_key_nd_extensions */ #endif

__OVS_KEY_ATTR_MAX
};

adding OVS_KEY_ATTR_IPV6_EXTHDRS before OVS_KEY_ATTR_PACKET_TYPE will conflict on kernel update.

And we will see following warning:
00001|odp_util(handler1)|WARN|attribute packet_type has length 2 but should have length 4

Best,
Tom