[ovs-dev] [PATCH 02/11] netdev-offload-dpdk: Add IPv6 pattern matching
Eli Britstein
elibr at mellanox.com
Mon May 18 15:40:17 UTC 2020
Add support for IPv6 pattern matching for offloading flows.
Signed-off-by: Eli Britstein <elibr at mellanox.com>
Reviewed-by: Roni Bar Yanai <roniba at mellanox.com>
---
Documentation/howto/dpdk.rst | 2 +-
NEWS | 1 +
lib/netdev-offload-dpdk.c | 76 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 78 insertions(+), 1 deletion(-)
diff --git a/Documentation/howto/dpdk.rst b/Documentation/howto/dpdk.rst
index be950d7ce..8a0eee80c 100644
--- a/Documentation/howto/dpdk.rst
+++ b/Documentation/howto/dpdk.rst
@@ -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 3dbd8ec0e..91d3d05b7 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ Post-v2.13.0
- DPDK:
* Deprecated DPDK pdump packet capture support removed.
* Deprecated DPDK ring ports (dpdkr) are no longer supported.
+ * Add hardware offload support for matching IPv6 protocol.
- Linux datapath:
* Support for kernel versions up to 5.5.x.
- AF_XDP:
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index 84bbe29e7..9964ba69e 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -16,6 +16,8 @@
*/
#include <config.h>
+#include <sys/types.h>
+#include <netinet/ip6.h>
#include <rte_flow.h>
#include "cmap.h"
@@ -321,6 +323,42 @@ dump_flow_pattern(struct ds *s, const struct rte_flow_item *item)
} else {
ds_put_cstr(s, " Mask = null\n");
}
+ } 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 src_addr_str[INET6_ADDRSTRLEN];
+ char dst_addr_str[INET6_ADDRSTRLEN];
+
+ ds_put_cstr(s, "rte flow ipv6 pattern:\n");
+ if (ipv6_spec) {
+ ipv6_string_mapped(src_addr_str,
+ (struct in6_addr *)&ipv6_spec->hdr.src_addr);
+ ipv6_string_mapped(dst_addr_str,
+ (struct in6_addr *)&ipv6_spec->hdr.dst_addr);
+
+ ds_put_format(s, " Spec: vtc_flow=%#"PRIx32", proto=%"PRIu8","
+ " hlim=%"PRIu8", src=%s, dst=%s\n",
+ ntohl(ipv6_spec->hdr.vtc_flow), ipv6_spec->hdr.proto,
+ ipv6_spec->hdr.hop_limits, src_addr_str,
+ dst_addr_str);
+ } else {
+ ds_put_cstr(s, " Spec = null\n");
+ }
+ if (ipv6_mask) {
+ ipv6_string_mapped(src_addr_str,
+ (struct in6_addr *)&ipv6_mask->hdr.src_addr);
+ ipv6_string_mapped(dst_addr_str,
+ (struct in6_addr *)&ipv6_mask->hdr.dst_addr);
+
+ ds_put_format(s, " Mask: vtc_flow=%#"PRIx32", proto=%#"PRIx8","
+ " hlim=%#"PRIx8", src=%s, dst=%s\n",
+ ntohl(ipv6_mask->hdr.vtc_flow), ipv6_mask->hdr.proto,
+ ipv6_mask->hdr.hop_limits, src_addr_str,
+ dst_addr_str);
+ } else {
+ ds_put_cstr(s, " Mask = null\n");
+ }
} else {
ds_put_format(s, "unknown rte flow pattern (%d)\n", item->type);
}
@@ -660,6 +698,44 @@ parse_flow_match(struct flow_patterns *patterns,
/* ignore mask match for now */
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 ||
--
2.14.5
More information about the dev
mailing list