[ovs-dev] [PATCH v5 18/27] dpif-netdev: Introduce tagged union of offload requests

Gaetan Rivet grive at u256.net
Wed Sep 8 09:47:42 UTC 2021


Offload requests are currently only supporting flow offloads.
As a pre-step before supporting an offload flush request,
modify the layout of an offload request item, to become a tagged union.

Future offload types won't be forced to re-use the full flow offload
structure, which consumes a lot of memory.

Signed-off-by: Gaetan Rivet <grive at u256.net>
Reviewed-by: Maxime Coquelin <maxime.coquelin at redhat.com>
---
 lib/dpif-netdev.c | 137 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 96 insertions(+), 41 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 24ecaa0a8..e0052a65b 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -333,13 +333,17 @@ enum rxq_cycles_counter_type {
     RXQ_N_CYCLES
 };
 
+enum dp_offload_type {
+    DP_OFFLOAD_FLOW,
+};
+
 enum {
     DP_NETDEV_FLOW_OFFLOAD_OP_ADD,
     DP_NETDEV_FLOW_OFFLOAD_OP_MOD,
     DP_NETDEV_FLOW_OFFLOAD_OP_DEL,
 };
 
-struct dp_offload_thread_item {
+struct dp_offload_flow_item {
     struct dp_netdev_pmd_thread *pmd;
     struct dp_netdev_flow *flow;
     int op;
@@ -347,9 +351,17 @@ struct dp_offload_thread_item {
     struct nlattr *actions;
     size_t actions_len;
     odp_port_t orig_in_port; /* Originating in_port for tnl flows. */
-    long long int timestamp;
+};
+
+union dp_offload_thread_data {
+    struct dp_offload_flow_item flow;
+};
 
+struct dp_offload_thread_item {
     struct ovs_list node;
+    enum dp_offload_type type;
+    long long int timestamp;
+    union dp_offload_thread_data data[0];
 };
 
 struct dp_offload_thread {
@@ -2538,34 +2550,55 @@ dp_netdev_alloc_flow_offload(struct dp_netdev_pmd_thread *pmd,
                              struct dp_netdev_flow *flow,
                              int op)
 {
-    struct dp_offload_thread_item *offload;
+    struct dp_offload_thread_item *item;
+    struct dp_offload_flow_item *flow_offload;
+
+    item = xzalloc(sizeof *item + sizeof *flow_offload);
+    flow_offload = &item->data->flow;
+
+    item->type = DP_OFFLOAD_FLOW;
 
-    offload = xzalloc(sizeof(*offload));
-    offload->pmd = pmd;
-    offload->flow = flow;
-    offload->op = op;
+    flow_offload->pmd = pmd;
+    flow_offload->flow = flow;
+    flow_offload->op = op;
 
     dp_netdev_flow_ref(flow);
     dp_netdev_pmd_try_ref(pmd);
 
-    return offload;
+    return item;
 }
 
 static void
 dp_netdev_free_flow_offload__(struct dp_offload_thread_item *offload)
 {
-    free(offload->actions);
+    struct dp_offload_flow_item *flow_offload = &offload->data->flow;
+
+    free(flow_offload->actions);
     free(offload);
 }
 
 static void
 dp_netdev_free_flow_offload(struct dp_offload_thread_item *offload)
 {
-    dp_netdev_pmd_unref(offload->pmd);
-    dp_netdev_flow_unref(offload->flow);
+    struct dp_offload_flow_item *flow_offload = &offload->data->flow;
+
+    dp_netdev_pmd_unref(flow_offload->pmd);
+    dp_netdev_flow_unref(flow_offload->flow);
     ovsrcu_postpone(dp_netdev_free_flow_offload__, offload);
 }
 
+static void
+dp_netdev_free_offload(struct dp_offload_thread_item *offload)
+{
+    switch (offload->type) {
+    case DP_OFFLOAD_FLOW:
+        dp_netdev_free_flow_offload(offload);
+        break;
+    default:
+        OVS_NOT_REACHED();
+    };
+}
+
 static void
 dp_netdev_append_flow_offload(struct dp_offload_thread_item *offload)
 {
@@ -2577,7 +2610,7 @@ dp_netdev_append_flow_offload(struct dp_offload_thread_item *offload)
 }
 
 static int
-dp_netdev_flow_offload_del(struct dp_offload_thread_item *offload)
+dp_netdev_flow_offload_del(struct dp_offload_flow_item *offload)
 {
     return mark_to_flow_disassociate(offload->pmd, offload->flow);
 }
@@ -2594,7 +2627,7 @@ dp_netdev_flow_offload_del(struct dp_offload_thread_item *offload)
  * valid, thus only item 2 needed.
  */
 static int
-dp_netdev_flow_offload_put(struct dp_offload_thread_item *offload)
+dp_netdev_flow_offload_put(struct dp_offload_flow_item *offload)
 {
     struct dp_netdev_pmd_thread *pmd = offload->pmd;
     struct dp_netdev_flow *flow = offload->flow;
@@ -2672,6 +2705,35 @@ err_free:
     return -1;
 }
 
+static void
+dp_offload_flow(struct dp_offload_thread_item *item)
+{
+    struct dp_offload_flow_item *flow_offload = &item->data->flow;
+    const char *op;
+    int ret;
+
+    switch (flow_offload->op) {
+    case DP_NETDEV_FLOW_OFFLOAD_OP_ADD:
+        op = "add";
+        ret = dp_netdev_flow_offload_put(flow_offload);
+        break;
+    case DP_NETDEV_FLOW_OFFLOAD_OP_MOD:
+        op = "modify";
+        ret = dp_netdev_flow_offload_put(flow_offload);
+        break;
+    case DP_NETDEV_FLOW_OFFLOAD_OP_DEL:
+        op = "delete";
+        ret = dp_netdev_flow_offload_del(flow_offload);
+        break;
+    default:
+        OVS_NOT_REACHED();
+    }
+
+    VLOG_DBG("%s to %s netdev flow "UUID_FMT,
+             ret == 0 ? "succeed" : "failed", op,
+             UUID_ARGS((struct uuid *) &flow_offload->flow->mega_ufid));
+}
+
 #define DP_NETDEV_OFFLOAD_QUIESCE_INTERVAL_US (10 * 1000) /* 10 ms */
 
 static void *
@@ -2682,8 +2744,6 @@ dp_netdev_flow_offload_main(void *data OVS_UNUSED)
     long long int latency_us;
     long long int next_rcu;
     long long int now;
-    const char *op;
-    int ret;
 
     next_rcu = time_usec() + DP_NETDEV_OFFLOAD_QUIESCE_INTERVAL_US;
     for (;;) {
@@ -2700,18 +2760,9 @@ dp_netdev_flow_offload_main(void *data OVS_UNUSED)
         offload = CONTAINER_OF(list, struct dp_offload_thread_item, node);
         ovs_mutex_unlock(&dp_offload_thread.mutex);
 
-        switch (offload->op) {
-        case DP_NETDEV_FLOW_OFFLOAD_OP_ADD:
-            op = "add";
-            ret = dp_netdev_flow_offload_put(offload);
-            break;
-        case DP_NETDEV_FLOW_OFFLOAD_OP_MOD:
-            op = "modify";
-            ret = dp_netdev_flow_offload_put(offload);
-            break;
-        case DP_NETDEV_FLOW_OFFLOAD_OP_DEL:
-            op = "delete";
-            ret = dp_netdev_flow_offload_del(offload);
+        switch (offload->type) {
+        case DP_OFFLOAD_FLOW:
+            dp_offload_flow(offload);
             break;
         default:
             OVS_NOT_REACHED();
@@ -2723,10 +2774,7 @@ dp_netdev_flow_offload_main(void *data OVS_UNUSED)
         mov_avg_cma_update(&dp_offload_thread.cma, latency_us);
         mov_avg_ema_update(&dp_offload_thread.ema, latency_us);
 
-        VLOG_DBG("%s to %s netdev flow "UUID_FMT,
-                 ret == 0 ? "succeed" : "failed", op,
-                 UUID_ARGS((struct uuid *) &offload->flow->mega_ufid));
-        dp_netdev_free_flow_offload(offload);
+        dp_netdev_free_offload(offload);
 
         /* Do RCU synchronization at fixed interval. */
         if (now > next_rcu) {
@@ -2827,7 +2875,8 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
                       const struct nlattr *actions, size_t actions_len,
                       odp_port_t orig_in_port, int op)
 {
-    struct dp_offload_thread_item *offload;
+    struct dp_offload_thread_item *item;
+    struct dp_offload_flow_item *flow_offload;
 
     if (!netdev_is_flow_api_enabled()) {
         return;
@@ -2839,15 +2888,21 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
         ovsthread_once_done(&offload_thread_once);
     }
 
-    offload = dp_netdev_alloc_flow_offload(pmd, flow, op);
-    offload->match = *match;
-    offload->actions = xmalloc(actions_len);
-    memcpy(offload->actions, actions, actions_len);
-    offload->actions_len = actions_len;
-    offload->orig_in_port = orig_in_port;
-
-    offload->timestamp = pmd->ctx.now;
-    dp_netdev_append_flow_offload(offload);
+    if (flow->mark != INVALID_FLOW_MARK) {
+        op = DP_NETDEV_FLOW_OFFLOAD_OP_MOD;
+    } else {
+        op = DP_NETDEV_FLOW_OFFLOAD_OP_ADD;
+    }
+    item = dp_netdev_alloc_flow_offload(pmd, flow, op);
+    flow_offload = &item->data->flow;
+    flow_offload->match = *match;
+    flow_offload->actions = xmalloc(actions_len);
+    memcpy(flow_offload->actions, actions, actions_len);
+    flow_offload->actions_len = actions_len;
+    flow_offload->orig_in_port = orig_in_port;
+
+    item->timestamp = pmd->ctx.now;
+    dp_netdev_append_flow_offload(item);
 }
 
 static void
-- 
2.31.1



More information about the dev mailing list