2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-04 16:25:17 +00:00

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>
This commit is contained in:
Gaetan Rivet
2021-09-08 11:47:42 +02:00
committed by Ilya Maximets
parent 73ecf098d2
commit d68d2ed466

View File

@@ -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,34 +2586,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;
offload = xzalloc(sizeof(*offload));
offload->pmd = pmd;
offload->flow = flow;
offload->op = op;
item = xzalloc(sizeof *item + sizeof *flow_offload);
flow_offload = &item->data->flow;
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)
{
@@ -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