]> git.proxmox.com Git - mirror_ovs.git/commitdiff
netdev-offload-dpdk: Add IPv6 pattern matching.
authorEli Britstein <elibr@mellanox.com>
Wed, 8 Jul 2020 06:38:26 +0000 (06:38 +0000)
committerIlya Maximets <i.maximets@ovn.org>
Wed, 8 Jul 2020 15:51:33 +0000 (17:51 +0200)
Add support for IPv6 pattern matching for offloading flows.

Signed-off-by: Eli Britstein <elibr@mellanox.com>
Reviewed-by: Roni Bar Yanai <roniba@mellanox.com>
Acked-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Documentation/howto/dpdk.rst
NEWS
lib/netdev-offload-dpdk.c

index c40fcafcb43f6b9a1f3063a1da7c8f4214a8079b..ebde9aeb988c60f1d93694b0694ccc1e097e234c 100644 (file)
@@ -385,7 +385,7 @@ The validated NICs are:
 Supported protocols for hardware offload matches are:
 
 - L2: Ethernet, VLAN
-- L3: IPv4
+- L3: IPv4, IPv6
 - L4: TCP, UDP, SCTP, ICMP
 
 Supported actions for hardware offload are:
diff --git a/NEWS b/NEWS
index ac992d17feab16fd6786b0ce99ebac8c1423206a..4dddbb23b9fb200ffd9826edcfff6fd46ca2441d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ Post-v2.13.0
      * Deprecated DPDK pdump packet capture support removed.
      * Deprecated DPDK ring ports (dpdkr) are no longer supported.
      * Add hardware offload support for VLAN Push/Pop actions (experimental).
+     * Add hardware offload support for matching IPv6 protocol (experimental).
    - Linux datapath:
      * Support for kernel versions up to 5.5.x.
    - AF_XDP:
index 426b8414f4c0bc005acc13db038c0701406c78c3..110f6e8292a6ebfec5638cc255df4c2dc8404019 100644 (file)
@@ -16,6 +16,8 @@
  */
 #include <config.h>
 
+#include <sys/types.h>
+#include <netinet/ip6.h>
 #include <rte_flow.h>
 
 #include "cmap.h"
@@ -294,6 +296,41 @@ dump_flow_pattern(struct ds *s, const struct rte_flow_item *item)
                               tcp_mask->hdr.tcp_flags);
         }
         ds_put_cstr(s, "/ ");
+    } else if (item->type == RTE_FLOW_ITEM_TYPE_IPV6) {
+        const struct rte_flow_item_ipv6 *ipv6_spec = item->spec;
+        const struct rte_flow_item_ipv6 *ipv6_mask = item->mask;
+
+        char addr_str[INET6_ADDRSTRLEN];
+        char mask_str[INET6_ADDRSTRLEN];
+        struct in6_addr addr, mask;
+
+        ds_put_cstr(s, "ipv6 ");
+        if (ipv6_spec) {
+            if (!ipv6_mask) {
+                ipv6_mask = &rte_flow_item_ipv6_mask;
+            }
+            memcpy(&addr, ipv6_spec->hdr.src_addr, sizeof addr);
+            memcpy(&mask, ipv6_mask->hdr.src_addr, sizeof mask);
+            ipv6_string_mapped(addr_str, &addr);
+            ipv6_string_mapped(mask_str, &mask);
+            DUMP_PATTERN_ITEM(mask, "src", "%s", addr_str, mask_str);
+
+            memcpy(&addr, ipv6_spec->hdr.dst_addr, sizeof addr);
+            memcpy(&mask, ipv6_mask->hdr.dst_addr, sizeof mask);
+            ipv6_string_mapped(addr_str, &addr);
+            ipv6_string_mapped(mask_str, &mask);
+            DUMP_PATTERN_ITEM(mask, "dst", "%s", addr_str, mask_str);
+
+            DUMP_PATTERN_ITEM(ipv6_mask->hdr.proto, "proto", "%"PRIu8,
+                              ipv6_spec->hdr.proto, ipv6_mask->hdr.proto);
+            DUMP_PATTERN_ITEM(ipv6_mask->hdr.vtc_flow, "tc", "0x%"PRIx32,
+                              ntohl(ipv6_spec->hdr.vtc_flow),
+                              ntohl(ipv6_mask->hdr.vtc_flow));
+            DUMP_PATTERN_ITEM(ipv6_mask->hdr.hop_limits, "hop", "%"PRIu8,
+                              ipv6_spec->hdr.hop_limits,
+                              ipv6_mask->hdr.hop_limits);
+        }
+        ds_put_cstr(s, "/ ");
     } else {
         ds_put_format(s, "unknown rte flow pattern (%d)\n", item->type);
     }
@@ -644,6 +681,44 @@ parse_flow_match(struct flow_patterns *patterns,
     }
     consumed_masks->nw_frag = 0;
 
+    /* IP v6 */
+    if (match->flow.dl_type == htons(ETH_TYPE_IPV6)) {
+        struct rte_flow_item_ipv6 *spec, *mask;
+
+        spec = xzalloc(sizeof *spec);
+        mask = xzalloc(sizeof *mask);
+
+        spec->hdr.proto = match->flow.nw_proto;
+        spec->hdr.hop_limits = match->flow.nw_ttl;
+        spec->hdr.vtc_flow =
+            htonl((uint32_t) match->flow.nw_tos << RTE_IPV6_HDR_TC_SHIFT);
+        memcpy(spec->hdr.src_addr, &match->flow.ipv6_src,
+               sizeof spec->hdr.src_addr);
+        memcpy(spec->hdr.dst_addr, &match->flow.ipv6_dst,
+               sizeof spec->hdr.dst_addr);
+
+        mask->hdr.proto = match->wc.masks.nw_proto;
+        mask->hdr.hop_limits = match->wc.masks.nw_ttl;
+        mask->hdr.vtc_flow =
+            htonl((uint32_t) match->wc.masks.nw_tos << RTE_IPV6_HDR_TC_SHIFT);
+        memcpy(mask->hdr.src_addr, &match->wc.masks.ipv6_src,
+               sizeof mask->hdr.src_addr);
+        memcpy(mask->hdr.dst_addr, &match->wc.masks.ipv6_dst,
+               sizeof mask->hdr.dst_addr);
+
+        consumed_masks->nw_proto = 0;
+        consumed_masks->nw_ttl = 0;
+        consumed_masks->nw_tos = 0;
+        memset(&consumed_masks->ipv6_src, 0, sizeof consumed_masks->ipv6_src);
+        memset(&consumed_masks->ipv6_dst, 0, sizeof consumed_masks->ipv6_dst);
+
+        add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_IPV6, spec, mask);
+
+        /* Save proto for L4 protocol setup. */
+        proto = spec->hdr.proto & mask->hdr.proto;
+        next_proto_mask = &mask->hdr.proto;
+    }
+
     if (proto != IPPROTO_ICMP && proto != IPPROTO_UDP  &&
         proto != IPPROTO_SCTP && proto != IPPROTO_TCP  &&
         (match->wc.masks.tp_src ||