@@ -2621,13 +2621,19 @@ dp_netdev_alloc_flow_offload(struct dp_netdev_pmd_thread *pmd,
}
static void
-dp_netdev_free_flow_offload(struct dp_offload_thread_item *offload)
+dp_netdev_flow_offload_free(struct dp_offload_thread_item *offload)
+{
+ free(offload->actions);
+ free(offload);
+}
+
+static void
+dp_netdev_flow_offload_unref(struct dp_offload_thread_item *offload)
{
dp_netdev_pmd_unref(offload->pmd);
dp_netdev_flow_unref(offload->flow);
- free(offload->actions);
- free(offload);
+ ovsrcu_postpone(dp_netdev_flow_offload_free, offload);
}
static void
@@ -2788,7 +2794,8 @@ dp_netdev_flow_offload_main(void *data OVS_UNUSED)
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_flow_offload_unref(offload);
/* Do RCU synchronization at fixed interval. */
if (now > next_rcu) {
Profiling the HW offload thread, the flow offload freeing takes approximatively 25% of the time. Most of this time is spent waiting on the futex used by the libc free(), as it triggers a syscall and reschedule the thread. Avoid the syscall and its expensive context switch. Batch the offload messages freeing using the RCU. Signed-off-by: Gaetan Rivet <grive@u256.net> --- lib/dpif-netdev.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)