summaryrefslogtreecommitdiff
path: root/lib/dpif-netdev.c
diff options
context:
space:
mode:
authorGaetan Rivet <grive@u256.net>2021-09-08 11:47:42 +0200
committerIlya Maximets <i.maximets@ovn.org>2022-01-19 01:35:19 +0100
commitd68d2ed466d48abc1120feb6e636b932f52b666b (patch)
treec5e8eab515edb23605d6a1fb48aade16fdfb8ad6 /lib/dpif-netdev.c
parent73ecf098d2d221df5b9ecbaa00480fc87053a3f4 (diff)
downloadopenvswitch-d68d2ed466d48abc1120feb6e636b932f52b666b.tar.gz
dpif-netdev: Introduce tagged union of offload requests.
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@u256.net> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'lib/dpif-netdev.c')
-rw-r--r--lib/dpif-netdev.c130
1 files changed, 90 insertions, 40 deletions
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 7038fa132..14c8d61ec 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -335,13 +335,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;
@@ -349,9 +353,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 {
@@ -2574,35 +2586,56 @@ 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;
- offload = xzalloc(sizeof(*offload));
- offload->pmd = pmd;
- offload->flow = flow;
- offload->op = op;
+ item->type = DP_OFFLOAD_FLOW;
+
+ 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)
{
ovs_mutex_lock(&dp_offload_thread.mutex);
@@ -2613,7 +2646,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);
}
@@ -2630,7 +2663,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;
@@ -2708,6 +2741,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 *
@@ -2718,8 +2780,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 (;;) {
@@ -2736,18 +2796,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();
@@ -2759,10 +2810,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) {
@@ -2863,7 +2911,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;
@@ -2875,15 +2924,16 @@ 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;
+ 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;
- offload->timestamp = pmd->ctx.now;
- dp_netdev_append_flow_offload(offload);
+ item->timestamp = pmd->ctx.now;
+ dp_netdev_append_flow_offload(item);
}
static void