ofproto-dpif-upcall: Fix a memory leak.
authorJarno Rajahalme <jrajahalme@nicira.com>
Mon, 23 Sep 2013 17:57:22 +0000 (10:57 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 24 Sep 2013 23:20:35 +0000 (16:20 -0700)
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 <jrajahalme@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
ofproto/ofproto-dpif-upcall.c
ofproto/ofproto-dpif-upcall.h

index 16c53e5..180b87e 100644 (file)
@@ -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);
index 9bd19ad..cd97e79 100644 (file)
@@ -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 *);