diff mbox series

[ovs-dev,3/3] netdev-offload-dpdk: Add geneve header pattern match

Message ID 20211229083519.554-4-elibr@nvidia.com
State Superseded
Headers show
Series Support geneve offloads | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed

Commit Message

Eli Britstein Dec. 29, 2021, 8:35 a.m. UTC
Add support for matching on geneve header.

Signed-off-by: Eli Britstein <elibr@nvidia.com>
Reviewed-by: Nir Anteby <nanteby@nvidia.com>
---
 NEWS                      |  2 ++
 lib/netdev-offload-dpdk.c | 58 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index bc4a1cfac..18f15b61f 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,8 @@  Post-v2.16.0
      * Add hardware offload support for GRE flows (experimental).
        Available only if DPDK experimantal APIs enabled during the build.
      * Add support for DPDK 21.11.
+     * Add hardware offload support for GENEVE flows (experimental).
+       Available only if DPDK experimantal APIs enabled during the build.
    - Python:
      * For SSL support, the use of the pyOpenSSL library has been replaced
        with the native 'ssl' module.
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index 50650bd07..36b780be6 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -491,6 +491,24 @@  dump_flow_pattern(struct ds *s,
                               ntohl(*key_spec), ntohl(*key_mask), 0);
         }
         ds_put_cstr(s, "/ ");
+    } else if (item->type == RTE_FLOW_ITEM_TYPE_GENEVE) {
+        const struct rte_flow_item_geneve *geneve_spec = item->spec;
+        const struct rte_flow_item_geneve *geneve_mask = item->mask;
+        ovs_be32 spec_vni, mask_vni;
+
+        ds_put_cstr(s, "geneve ");
+        if (geneve_spec) {
+            if (!geneve_mask) {
+                geneve_mask = &rte_flow_item_geneve_mask;
+            }
+            spec_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
+                                                       geneve_spec->vni));
+            mask_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
+                                                       geneve_mask->vni));
+            DUMP_PATTERN_ITEM(geneve_mask->vni, false, "vni", "%"PRIu32,
+                              ntohl(spec_vni) >> 8, ntohl(mask_vni) >> 8, 0);
+        }
+        ds_put_cstr(s, "/ ");
     } else {
         ds_put_format(s, "unknown rte flow pattern (%d)\n", item->type);
     }
@@ -1197,6 +1215,44 @@  parse_gre_match(struct flow_patterns *patterns,
     return 0;
 }
 
+static int
+parse_geneve_match(struct flow_patterns *patterns,
+                   struct match *match)
+{
+    struct rte_flow_item_geneve *geneve_spec, *geneve_mask;
+    struct flow *consumed_masks;
+    int ret;
+
+    ret = parse_tnl_ip_match(patterns, match, IPPROTO_UDP);
+    if (ret) {
+        return -1;
+    }
+    parse_tnl_udp_match(patterns, match);
+
+    consumed_masks = &match->wc.masks;
+    /* GENEVE */
+    geneve_spec = xzalloc(sizeof *geneve_spec);
+    geneve_mask = xzalloc(sizeof *geneve_mask);
+
+    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_spec->vni),
+                       htonl(ntohll(match->flow.tunnel.tun_id) << 8));
+    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_mask->vni),
+                       htonl(ntohll(match->wc.masks.tunnel.tun_id) << 8));
+
+    consumed_masks->tunnel.tun_id = 0;
+    consumed_masks->tunnel.flags = 0;
+    /* tunnel.metadata.present.len value indicates the number of
+     * options, it's mask does not indicate any match on the packet,
+     * thus masked.
+     */
+    memset(&consumed_masks->tunnel.metadata.present, 0,
+           sizeof consumed_masks->tunnel.metadata.present);
+
+    add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_GENEVE, geneve_spec,
+                     geneve_mask, NULL);
+    return 0;
+}
+
 static int OVS_UNUSED
 parse_flow_tnl_match(struct netdev *tnldev,
                      struct flow_patterns *patterns,
@@ -1212,6 +1268,8 @@  parse_flow_tnl_match(struct netdev *tnldev,
 
     if (!strcmp(netdev_get_type(tnldev), "vxlan")) {
         ret = parse_vxlan_match(patterns, match);
+    } else if (!strcmp(netdev_get_type(tnldev), "geneve")) {
+        ret = parse_geneve_match(patterns, match);
     }
     else if (!strcmp(netdev_get_type(tnldev), "gre")) {
         ret = parse_gre_match(patterns, match);