Thread (8 messages) flat view 8 messages, 3 authors, 2022-02-10

Re: [PATCH net-next v8] net: openvswitch: IPv6: Add IPv6 extension header support

From: Pravin Shelar <hidden>
Date: 2021-12-03 05:28:51
Also in: lkml

On Thu, Dec 2, 2021 at 12:20 PM Cpp Code [off-list ref] wrote:
On Wed, Dec 1, 2021 at 11:34 PM Pravin Shelar [off-list ref] wrote:
quoted
On Wed, Nov 24, 2021 at 11:33 AM Toms Atteka [off-list ref] wrote:
quoted
This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
packets can be filtered using ipv6_ext flag.

Signed-off-by: Toms Atteka <redacted>
---
 include/uapi/linux/openvswitch.h |   6 ++
 net/openvswitch/flow.c           | 140 +++++++++++++++++++++++++++++++
 net/openvswitch/flow.h           |  14 ++++
 net/openvswitch/flow_netlink.c   |  26 +++++-
 4 files changed, 184 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index a87b44cd5590..43790f07e4a2 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -342,6 +342,7 @@ enum ovs_key_attr {
        OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,   /* struct ovs_key_ct_tuple_ipv4 */
        OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,   /* struct ovs_key_ct_tuple_ipv6 */
        OVS_KEY_ATTR_NSH,       /* Nested set of ovs_nsh_key_* */
+       OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */

 #ifdef __KERNEL__
        OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
@@ -421,6 +422,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;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 9d375e74b607..28acb40437ca 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -239,6 +239,144 @@ static bool icmphdr_ok(struct sk_buff *skb)
                                  sizeof(struct icmphdr));
 }

+/**
+ * get_ipv6_ext_hdrs() - Parses packet and sets IPv6 extension header flags.
+ *
+ * @skb: buffer where extension header data starts in packet
+ * @nh: ipv6 header
+ * @ext_hdrs: flags are stored here
+ *
+ * OFPIEH12_UNREP is set if more than one of a given IPv6 extension header
+ * is unexpectedly encountered. (Two destination options headers may be
+ * expected and would not cause this bit to be set.)
+ *
+ * OFPIEH12_UNSEQ is set if IPv6 extension headers were not in the order
+ * preferred (but not required) by RFC 2460:
+ *
+ * When more than one extension header is used in the same packet, it is
+ * recommended that those headers appear in the following order:
+ *      IPv6 header
+ *      Hop-by-Hop Options header
+ *      Destination Options header
+ *      Routing header
+ *      Fragment header
+ *      Authentication header
+ *      Encapsulating Security Payload header
+ *      Destination Options header
+ *      upper-layer header
+ */
+static void get_ipv6_ext_hdrs(struct sk_buff *skb, struct ipv6hdr *nh,
+                             u16 *ext_hdrs)
+{
+       u8 next_type = nh->nexthdr;
+       unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
+       int dest_options_header_count = 0;
+
+       *ext_hdrs = 0;
+
+       while (ipv6_ext_hdr(next_type)) {
+               struct ipv6_opt_hdr _hdr, *hp;
+
+               switch (next_type) {
+               case IPPROTO_NONE:
+                       *ext_hdrs |= OFPIEH12_NONEXT;
+                       /* stop parsing */
+                       return;
+
+               case IPPROTO_ESP:
+                       if (*ext_hdrs & OFPIEH12_ESP)
+                               *ext_hdrs |= OFPIEH12_UNREP;
+                       if ((*ext_hdrs & ~(OFPIEH12_HOP | OFPIEH12_DEST |
+                                          OFPIEH12_ROUTER | IPPROTO_FRAGMENT |
+                                          OFPIEH12_AUTH | OFPIEH12_UNREP)) ||
+                           dest_options_header_count >= 2) {
+                               *ext_hdrs |= OFPIEH12_UNSEQ;
+                       }
+                       *ext_hdrs |= OFPIEH12_ESP;
+                       break;
you need to check_header() before looking into each extension header.
Could you elaborate why I need to add check_header(),
skb_header_pointer() is doing sanitization.
I mean check_header() would allow you to read the header without
copying the bits, it is used in ovs flow extraction so its usual
check.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help