diff mbox series

[ovs-dev,V4,11/12] netdev-offload-dpdk: Support offload of clone tnl_push/output actions

Message ID 20200701053501.27081-12-elibr@mellanox.com
State Changes Requested
Headers show
Series netdev datapath offload: Support IPv6 and VXLAN encap | expand

Commit Message

Eli Britstein July 1, 2020, 5:35 a.m. UTC
Tunnel encapsulation is done by tnl_push and output actions nested in a
clone action. Support offloading of such flows with
RTE_FLOW_ACTION_TYPE_RAW_ENCAP attribute.

Signed-off-by: Eli Britstein <elibr@mellanox.com>
Reviewed-by: Oz Shlomo <ozsh@mellanox.com>
Acked-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
---
 Documentation/howto/dpdk.rst |  1 +
 NEWS                         |  2 +-
 lib/netdev-offload-dpdk.c    | 60 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/Documentation/howto/dpdk.rst b/Documentation/howto/dpdk.rst
index fb9bd2d10..f0d45e47b 100644
--- a/Documentation/howto/dpdk.rst
+++ b/Documentation/howto/dpdk.rst
@@ -397,6 +397,7 @@  Supported actions for hardware offload are:
 - Modification of TCP/UDP (mod_tp_src/mod_tp_dst).
 - VLAN Push/Pop (push_vlan/pop_vlan).
 - Modification of IPv6 (set_field:<ADDR>->ipv6_src/ipv6_dst/mod_nw_ttl).
+- Clone/output (tnl_push and output) for encapsulating over a tunnel.
 
 Further Reading
 ---------------
diff --git a/NEWS b/NEWS
index c9ad3fd1d..95e1431d2 100644
--- a/NEWS
+++ b/NEWS
@@ -12,7 +12,7 @@  Post-v2.13.0
      * Add hardware offload support for VLAN Push/Pop actions (experimental).
      * Add hardware offload support for matching IPv6 protocol (experimental).
      * Add hardware offload support for set of IPv6 TCP/UDP ports
-       actions (experimental).
+       and tunnel push-output actions (experimental).
    - 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 607833d4d..ba6d4eb32 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -451,6 +451,20 @@  dump_flow_action(struct ds *s, const struct rte_flow_action *actions)
             ds_put_cstr(s, " ");
         }
         ds_put_cstr(s, "/ ");
+    } else if (actions->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+        const struct rte_flow_action_raw_encap *raw_encap = actions->conf;
+
+        ds_put_cstr(s, "raw_encap index 0 / ");
+        if (raw_encap) {
+            struct ds s1;
+
+            ds_init(&s1);
+            ds_put_hex_dump(&s1, raw_encap->data, raw_encap->size, 0, false);
+            VLOG_DBG_RL(&rl, "testpmd Raw-encap size=%ld set raw_encap 0 raw "
+                        "pattern is\n"
+                        "%s / end_set\n", raw_encap->size, ds_cstr(&s1));
+            ds_destroy(&s1);
+        }
     } else {
         ds_put_format(s, "unknown rte flow action (%d)\n", actions->type);
     }
@@ -1121,6 +1135,43 @@  parse_vlan_push_action(struct flow_actions *actions,
     return 0;
 }
 
+static int
+parse_clone_actions(struct netdev *netdev,
+                    struct flow_actions *actions,
+                    const struct nlattr *clone_actions,
+                    const size_t clone_actions_len)
+{
+    const struct nlattr *ca;
+    unsigned int cleft;
+
+    NL_ATTR_FOR_EACH_UNSAFE (ca, cleft, clone_actions, clone_actions_len) {
+        int clone_type = nl_attr_type(ca);
+
+        if (clone_type == OVS_ACTION_ATTR_TUNNEL_PUSH) {
+            const struct ovs_action_push_tnl *tnl_push = nl_attr_get(ca);
+            struct rte_flow_action_raw_encap *raw_encap =
+                xzalloc(sizeof *raw_encap);
+
+            raw_encap->data = (uint8_t *)tnl_push->header;
+            raw_encap->preserve = NULL;
+            raw_encap->size = tnl_push->header_len;
+
+            add_flow_action(actions, RTE_FLOW_ACTION_TYPE_RAW_ENCAP,
+                            raw_encap);
+        } else if (clone_type == OVS_ACTION_ATTR_OUTPUT) {
+            if (add_output_action(netdev, actions, ca)) {
+                return -1;
+            }
+        } else {
+            VLOG_DBG_RL(&rl,
+                        "Unsupported nested action inside clone(), "
+                        "action type: %d", clone_type);
+            return -1;
+        }
+    }
+    return 0;
+}
+
 static int
 parse_flow_actions(struct netdev *netdev,
                    struct flow_actions *actions,
@@ -1156,6 +1207,15 @@  parse_flow_actions(struct netdev *netdev,
             }
         } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_POP_VLAN) {
             add_flow_action(actions, RTE_FLOW_ACTION_TYPE_OF_POP_VLAN, NULL);
+        } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CLONE &&
+                   left <= NLA_ALIGN(nla->nla_len)) {
+            const struct nlattr *clone_actions = nl_attr_get(nla);
+            size_t clone_actions_len = nl_attr_get_size(nla);
+
+            if (parse_clone_actions(netdev, actions, clone_actions,
+                                    clone_actions_len)) {
+                return -1;
+            }
         } else {
             VLOG_DBG_RL(&rl, "Unsupported action type %d", nl_attr_type(nla));
             return -1;