[ovs-dev] [PATCH] dpif-netdev: Fix (packet) memory leaks in the slow path.
Daniele Di Proietto
ddiproietto at vmware.com
Fri Sep 19 20:28:47 UTC 2014
If a packet didn't match a rule in the fast path classifier its memory was
never freed. The issue was particularly clear with DPDK devices because it was
not possible to process more than ~250000 DPDK mbufs in the slow path.
This commit fixes the problem by:
* calling dpif_packet_delete() if the upcalls are disabled
* passing may_steal==true to dp_netdev_execute_actions() during normal upcall
processing
Signed-off-by: Daniele Di Proietto <ddiproietto at vmware.com>
---
lib/dpif-netdev.c | 47 ++++++++++++++++++++++++++++++++---------------
1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 7e27acf..8df3b81 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -2576,7 +2576,7 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
/* We can't allow the packet batching in the next loop to execute
* the actions. Otherwise, if there are any slow path actions,
* we'll send the packet up twice. */
- dp_netdev_execute_actions(pmd, &packets[i], 1, false, md,
+ dp_netdev_execute_actions(pmd, &packets[i], 1, true, md,
ofpbuf_data(&actions),
ofpbuf_size(&actions));
@@ -2602,6 +2602,17 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
ofpbuf_uninit(&actions);
ofpbuf_uninit(&put_actions);
fat_rwlock_unlock(&dp->upcall_rwlock);
+ } else if (OVS_UNLIKELY(any_miss)) {
+ int dropped_cnt = 0;
+
+ for (i = 0; i < cnt; i++) {
+ if (OVS_UNLIKELY(!rules[i] && mfs[i])) {
+ dpif_packet_delete(packets[i]);
+ dropped_cnt++;
+ }
+ }
+
+ dp_netdev_count_packet(dp, DP_STAT_LOST, dropped_cnt);
}
n_batches = 0;
@@ -2658,6 +2669,18 @@ dpif_netdev_register_upcall_cb(struct dpif *dpif, upcall_callback *cb,
}
static void
+dp_netdev_drop_packets(struct dpif_packet ** packets, int cnt, bool may_steal)
+{
+ int i;
+
+ if (may_steal) {
+ for (i = 0; i < cnt; i++) {
+ dpif_packet_delete(packets[i]);
+ }
+ }
+}
+
+static void
dp_execute_cb(void *aux_, struct dpif_packet **packets, int cnt,
struct pkt_metadata *md,
const struct nlattr *a, bool may_steal)
@@ -2676,10 +2699,8 @@ dp_execute_cb(void *aux_, struct dpif_packet **packets, int cnt,
p = dp_netdev_lookup_port(dp, u32_to_odp(nl_attr_get_u32(a)));
if (OVS_LIKELY(p)) {
netdev_send(p->netdev, pmd->core_id, packets, cnt, may_steal);
- } else if (may_steal) {
- for (i = 0; i < cnt; i++) {
- dpif_packet_delete(packets[i]);
- }
+ } else {
+ dp_netdev_drop_packets(packets, cnt, may_steal);
}
break;
@@ -2702,17 +2723,17 @@ dp_execute_cb(void *aux_, struct dpif_packet **packets, int cnt,
DPIF_UC_ACTION, userdata, &actions,
NULL);
if (!error || error == ENOSPC) {
- dp_netdev_execute_actions(pmd, &packets[i], 1, false, md,
- ofpbuf_data(&actions),
+ dp_netdev_execute_actions(pmd, &packets[i], 1, may_steal,
+ md, ofpbuf_data(&actions),
ofpbuf_size(&actions));
- }
-
- if (may_steal) {
+ } else if (may_steal) {
dpif_packet_delete(packets[i]);
}
}
ofpbuf_uninit(&actions);
fat_rwlock_unlock(&dp->upcall_rwlock);
+ } else {
+ dp_netdev_drop_packets(packets, cnt, may_steal);
}
break;
@@ -2772,11 +2793,7 @@ dp_execute_cb(void *aux_, struct dpif_packet **packets, int cnt,
break;
} else {
VLOG_WARN("Packet dropped. Max recirculation depth exceeded.");
- if (may_steal) {
- for (i = 0; i < cnt; i++) {
- dpif_packet_delete(packets[i]);
- }
- }
+ dp_netdev_drop_packets(packets, cnt, may_steal);
}
break;
--
2.1.0.rc1
More information about the dev
mailing list