diff mbox series

[ovs-dev,v2,4/6] netdev-offload-dpdk: Support multiple local destinations

Message ID 20210823160140.12788-5-salems@nvidia.com
State Deferred
Headers show
Series Adding support for multiple destinations | 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

Salem Sol Aug. 23, 2021, 4:01 p.m. UTC
From: Noa Levy <noae@nvidia.com>

Add support for offloading multiple local destinations using
rte_flow_action_sample with ratio 1.

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                      |  1 +
 lib/netdev-offload-dpdk.c | 77 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 76 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index 1f2adf718..793e1adc5 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,7 @@  Post-v2.16.0
        by default.  'other_config:dpdk-socket-limit' can be set equal to
        the 'other_config:dpdk-socket-mem' to preserve the legacy memory
        limiting behavior.
+     * Add support for offloading multiple local destinations actions.
 
 
 v2.16.0 - 16 Aug 2021
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index cd63d3ae1..efd7c844d 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -627,6 +627,29 @@  dump_flow_action(struct ds *s, struct ds *s_extra,
             ds_put_format(s, "group %"PRIu32" ", jump->group);
         }
         ds_put_cstr(s, "/ ");
+    } else if (actions->type == RTE_FLOW_ACTION_TYPE_SAMPLE) {
+        const struct rte_flow_action_sample *sample = actions->conf;
+
+        if (sample) {
+            const struct rte_flow_action *rte_actions;
+
+            rte_actions = sample->actions;
+            ds_put_format(s_extra, "set sample_actions %d ", act_index);
+
+            while (rte_actions &&
+                   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 {
+                    ds_put_format(s, "unknown rte flow action (%d)\n",
+                                  rte_actions->type);
+                }
+                rte_actions++;
+            }
+            ds_put_cstr(s_extra, "end; ");
+            ds_put_format(s, "sample ratio %d index %d / ", sample->ratio,
+                          act_index);
+        }
     } else {
         ds_put_format(s, "unknown rte flow action (%d)\n", actions->type);
     }
@@ -1722,6 +1745,47 @@  parse_clone_actions(struct netdev *netdev,
     return 0;
 }
 
+/* Maximum number of actions in multiple local destinations.
+ * PORT_ID / END
+ */
+#define SAMPLE_EMBEDDED_ACTIONS_NUM 2
+
+static int
+add_sample_embedded_output_action(struct netdev *netdev,
+                                  struct flow_actions *actions,
+                                  const struct nlattr *nla)
+{
+    struct netdev *outdev;
+    struct sample_conf {
+        struct rte_flow_action_sample sample;
+        struct rte_flow_action_port_id port_id;
+        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;
+    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;
+    /* Initialize sample struct */
+    sample_conf->sample.ratio = 1;
+    sample_conf->sample.actions = sample_conf->sample_actions;
+    sample_conf->port_id.id = port_id;
+
+    sample_itr->conf = &sample_conf->port_id;
+    sample_itr->type = RTE_FLOW_ACTION_TYPE_PORT_ID;
+    sample_itr++;
+    sample_itr->type = RTE_FLOW_ACTION_TYPE_END;
+
+    add_flow_action(actions, RTE_FLOW_ACTION_TYPE_SAMPLE, sample_conf);
+    return 0;
+}
+
 static void
 add_jump_action(struct flow_actions *actions, uint32_t group)
 {
@@ -1787,8 +1851,17 @@  parse_flow_actions(struct netdev *netdev,
     add_count_action(actions);
     NL_ATTR_FOR_EACH_UNSAFE (nla, left, nl_actions, nl_actions_len) {
         if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) {
-            if (add_output_action(netdev, actions, nla)) {
-                return -1;
+            /* The last output should use port-id action, while previous
+             * outputs should embed the port-id action inside a sample action.
+             */
+            if (left <= NLA_ALIGN(nla->nla_len)) {
+                if (add_output_action(netdev, actions, nla)) {
+                   return -1;
+                }
+            } else {
+                if (add_sample_embedded_output_action(netdev, actions, nla)) {
+                    return -1;
+                }
             }
         } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_DROP) {
             add_flow_action(actions, RTE_FLOW_ACTION_TYPE_DROP, NULL);