From ddeca9a44933e1f96938cca0dd2ab77b92dd2101 Mon Sep 17 00:00:00 2001 From: Jarno Rajahalme Date: Mon, 23 Sep 2013 10:57:22 -0700 Subject: [PATCH] ofproto-dpif-upcall: Fix a memory leak. The "key" member in struct flow_miss refers to memory held by the "struct upcall", hence the upcalls should be freed only after the flow misses are processed by the main thread. Signed-off-by: Jarno Rajahalme Signed-off-by: Ben Pfaff --- ofproto/ofproto-dpif-upcall.c | 17 +++++++++++++---- ofproto/ofproto-dpif-upcall.h | 5 +++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 16c53e5cd..180b87e2c 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -309,6 +309,7 @@ void flow_miss_batch_destroy(struct flow_miss_batch *fmb) { struct flow_miss *miss, *next; + struct upcall *upcall, *next_upcall; if (!fmb) { return; @@ -319,6 +320,11 @@ flow_miss_batch_destroy(struct flow_miss_batch *fmb) miss_destroy(miss); } + LIST_FOR_EACH_SAFE (upcall, next_upcall, list_node, &fmb->upcalls) { + list_remove(&upcall->list_node); + upcall_destroy(upcall); + } + hmap_destroy(&fmb->misses); free(fmb); } @@ -599,7 +605,7 @@ handle_miss_upcalls(struct udpif *udpif, struct list *upcalls) struct dpif_op ops[FLOW_MISS_MAX_BATCH]; struct upcall *upcall, *next; struct flow_miss_batch *fmb; - size_t n_upcalls, n_ops, i; + size_t n_misses, n_ops, i; struct flow_miss *miss; unsigned int reval_seq; bool fail_open; @@ -626,11 +632,12 @@ handle_miss_upcalls(struct udpif *udpif, struct list *upcalls) fmb = xmalloc(sizeof *fmb); atomic_read(&udpif->reval_seq, &fmb->reval_seq); hmap_init(&fmb->misses); - n_upcalls = 0; + list_init(&fmb->upcalls); + n_misses = 0; LIST_FOR_EACH_SAFE (upcall, next, list_node, upcalls) { struct dpif_upcall *dupcall = &upcall->dpif_upcall; struct ofpbuf *packet = dupcall->packet; - struct flow_miss *miss = &fmb->miss_buf[n_upcalls]; + struct flow_miss *miss = &fmb->miss_buf[n_misses]; struct flow_miss *existing_miss; struct ofproto_dpif *ofproto; odp_port_t odp_in_port; @@ -661,7 +668,7 @@ handle_miss_upcalls(struct udpif *udpif, struct list *upcalls) miss->stats.used = time_msec(); miss->stats.tcp_flags = 0; - n_upcalls++; + n_misses++; } else { miss = existing_miss; } @@ -814,6 +821,8 @@ handle_miss_upcalls(struct udpif *udpif, struct list *upcalls) } } + list_move(&fmb->upcalls, upcalls); + atomic_read(&udpif->reval_seq, &reval_seq); if (reval_seq != fmb->reval_seq) { COVERAGE_INC(fmb_queue_revalidated); diff --git a/ofproto/ofproto-dpif-upcall.h b/ofproto/ofproto-dpif-upcall.h index 9bd19ad52..cd97e79db 100644 --- a/ofproto/ofproto-dpif-upcall.h +++ b/ofproto/ofproto-dpif-upcall.h @@ -104,6 +104,11 @@ struct flow_miss_batch { struct hmap misses; unsigned int reval_seq; + + /* Flow misses refer to the memory held by "struct upcall"s, + * so we need to keep track of the upcalls to be able to + * free them when done. */ + struct list upcalls; /* Contains "struct upcall"s. */ }; struct flow_miss_batch *flow_miss_batch_next(struct udpif *); -- 2.20.1