diff mbox series

[ovs-dev,6/6] netdev-offload-dpdk: Support multiple remote destinations

Message ID 20210531064613.30636-7-noae@nvidia.com
State New
Headers show
Series Multiple destinations | expand

Commit Message

Noa Levy May 31, 2021, 6:46 a.m. UTC
Add support for offloading multiple remote destinations by parsing the
actions and adding remote destinations actions.
Update dump_flow_action in order to support tunnel actions.

Co-authored-by: Salem Sol <salems@nvidia.com>
Signed-off-by: Noa Levy <noae@nvidia.com>
Signed-off-by: Salem Sol <salems@nvidia.com>
---
 NEWS                      |  3 +-
 lib/netdev-offload-dpdk.c | 69 ++++++++++++++++++++++++++++++---------
 2 files changed, 55 insertions(+), 17 deletions(-)
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index 066f90437..d2f0b8812 100644
--- a/NEWS
+++ b/NEWS
@@ -12,7 +12,8 @@  Post-v2.15.0
    - DPDK:
      * OVS validated with DPDK 20.11.1. It is recommended to use this version
        until further releases.
-     * Add support for offloading multiple local destinations actions.
+     * Add support for offloading multiple local and remote destinations
+       actions.
 
 v2.15.0 - 15 Feb 2021
 ---------------------
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index eb798a69b..ab30fbbeb 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -630,6 +630,13 @@  dump_flow_action(struct ds *s, struct ds *s_extra,
                    rte_actions->type != RTE_FLOW_ACTION_TYPE_END) {
                 if (rte_actions->type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
                     dump_port_id(s_extra, rte_actions->conf);
+                } else if (rte_actions->type ==
+                           RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+                    const struct rte_flow_action_raw_encap *raw_encap =
+                        rte_actions->conf;
+
+                    dump_raw_encap(s, s_extra, raw_encap);
+                    ds_put_format(s_extra, "raw_encap index 0 / ");
                 } else {
                     ds_put_format(s, "unknown rte flow action (%d)\n",
                                   rte_actions->type);
@@ -1744,37 +1751,53 @@  parse_clone_actions(struct netdev *netdev,
 }
 
 /* Maximum number of actions in multiple local destinations.
- * PORT_ID / END
+ * RAW_ENCAP / PORT_ID / END
  */
-#define SAMPLE_EMBEDDED_ACTIONS_NUM 2
+#define SAMPLE_EMBEDDED_ACTIONS_NUM 3
 
 static int
 add_sample_embedded_output_action(struct netdev *netdev,
                                   struct flow_actions *actions,
-                                  const struct nlattr *nla)
+                                  const struct nlattr *nla,
+                                  const size_t clone_actions_len)
 {
     struct netdev *outdev;
     struct sample_conf {
         struct rte_flow_action_sample sample;
         struct rte_flow_action_port_id port_id;
+        struct rte_flow_action_raw_encap raw_encap;
         struct rte_flow_action sample_actions[SAMPLE_EMBEDDED_ACTIONS_NUM];
     } *sample_conf;
     BUILD_ASSERT_DECL(offsetof(struct sample_conf, sample) == 0);
     struct rte_flow_action *sample_itr;
+    bool is_raw;
     int port_id;
 
-    if (get_netdev_by_port(netdev, nla, &port_id, &outdev)) {
-        return -1;
-    }
-    netdev_close(outdev);
-
     sample_conf = xzalloc(sizeof *sample_conf);
     sample_itr = sample_conf->sample_actions;
+    is_raw = false;
+    if (!clone_actions_len) {
+        if (get_netdev_by_port(netdev, nla, &port_id, &outdev)) {
+            goto err;
+        }
+        netdev_close(outdev);
+    } else {
+        if (parse_clone_actions(netdev, NULL, nla,
+                                clone_actions_len, &port_id,
+                                &sample_conf->raw_encap)) {
+            goto err;
+        }
+        is_raw = sample_conf->raw_encap.size > 0;
+    }
     /* Initialize sample struct */
     sample_conf->sample.ratio = 1;
     sample_conf->sample.actions = sample_conf->sample_actions;
     sample_conf->port_id.id = port_id;
-
+    if (is_raw) {
+        sample_itr->conf = &sample_conf->raw_encap;
+        sample_itr->type = RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
+        sample_itr++;
+    }
     sample_itr->conf = &sample_conf->port_id;
     sample_itr->type = RTE_FLOW_ACTION_TYPE_PORT_ID;
     sample_itr++;
@@ -1782,6 +1805,9 @@  add_sample_embedded_output_action(struct netdev *netdev,
 
     add_flow_action(actions, RTE_FLOW_ACTION_TYPE_SAMPLE, sample_conf);
     return 0;
+err:
+    free(sample_conf);
+    return -1;
 }
 
 static void
@@ -1857,7 +1883,8 @@  parse_flow_actions(struct netdev *netdev,
                    return -1;
                 }
             } else {
-                if (add_sample_embedded_output_action(netdev, actions, nla)) {
+                if (add_sample_embedded_output_action(netdev, actions, nla,
+                                                      0)) {
                     return -1;
                 }
             }
@@ -1881,14 +1908,24 @@  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)) {
+        } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CLONE) {
             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, NULL, NULL)) {
-                return -1;
+             /* The last cloned action is parsed and actions are applied
+              * natively, while previous ones are parsed and the actions are
+              * applied embedded in a sample action.
+              */
+            if (left <= NLA_ALIGN(nla->nla_len)) {
+                if (parse_clone_actions(netdev, actions, clone_actions,
+                                        clone_actions_len, NULL, NULL)) {
+                    return -1;
+                }
+            } else {
+                if (add_sample_embedded_output_action(netdev, actions,
+                                                      clone_actions,
+                                                      clone_actions_len)) {
+                    return -1;
+                }
             }
         } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_TUNNEL_POP) {
             if (add_tnl_pop_action(netdev, actions, nla)) {