dpif-netdev: Fix memory leak.
[sliver-openvswitch.git] / lib / dpif-netdev.c
index a907722..3d01b17 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -165,6 +165,17 @@ get_dp_netdev(const struct dpif *dpif)
     return dpif_netdev_cast(dpif)->dp;
 }
 
+static int
+dpif_netdev_enumerate(struct sset *all_dps)
+{
+    struct shash_node *node;
+
+    SHASH_FOR_EACH(node, &dp_netdevs) {
+        sset_add(all_dps, node->name);
+    }
+    return 0;
+}
+
 static struct dpif *
 create_dpif_netdev(struct dp_netdev *dp)
 {
@@ -396,7 +407,16 @@ dpif_netdev_port_add(struct dpif *dpif, struct netdev *netdev,
     struct dp_netdev *dp = get_dp_netdev(dpif);
     int port_no;
 
-    port_no = choose_port(dpif, netdev);
+    if (*port_nop != UINT16_MAX) {
+        if (*port_nop >= MAX_PORTS) {
+            return EFBIG;
+        } else if (dp->ports[*port_nop]) {
+            return EBUSY;
+        }
+        port_no = *port_nop;
+    } else {
+        port_no = choose_port(dpif, netdev);
+    }
     if (port_no >= 0) {
         *port_nop = port_no;
         return do_add_port(dp, netdev_get_name(netdev),
@@ -702,10 +722,9 @@ set_flow_actions(struct dp_netdev_flow *flow,
 }
 
 static int
-add_flow(struct dpif *dpif, const struct flow *key,
-         const struct nlattr *actions, size_t actions_len)
+dp_netdev_flow_add(struct dp_netdev *dp, const struct flow *key,
+                   const struct nlattr *actions, size_t actions_len)
 {
-    struct dp_netdev *dp = get_dp_netdev(dpif);
     struct dp_netdev_flow *flow;
     int error;
 
@@ -751,7 +770,8 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
                 if (put->stats) {
                     memset(put->stats, 0, sizeof *put->stats);
                 }
-                return add_flow(dpif, &key, put->actions, put->actions_len);
+                return dp_netdev_flow_add(dp, &key, put->actions,
+                                          put->actions_len);
             } else {
                 return EFBIG;
             }
@@ -935,7 +955,8 @@ find_nonempty_queue(struct dpif *dpif)
 }
 
 static int
-dpif_netdev_recv(struct dpif *dpif, struct dpif_upcall *upcall)
+dpif_netdev_recv(struct dpif *dpif, struct dpif_upcall *upcall,
+                 struct ofpbuf *buf)
 {
     struct dp_netdev_queue *q = find_nonempty_queue(dpif);
     if (q) {
@@ -943,6 +964,10 @@ dpif_netdev_recv(struct dpif *dpif, struct dpif_upcall *upcall)
         *upcall = *u;
         free(u);
 
+        ofpbuf_uninit(buf);
+        *buf = *upcall->packet;
+        free(upcall->packet);
+
         return 0;
     } else {
         return EAGAIN;
@@ -987,7 +1012,7 @@ dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port,
     if (packet->size < ETH_HEADER_LEN) {
         return;
     }
-    flow_extract(packet, 0, 0, port->port_no, &key);
+    flow_extract(packet, 0, 0, odp_port_to_ofp_port(port->port_no), &key);
     flow = dp_netdev_lookup_flow(dp, &key);
     if (flow) {
         dp_netdev_flow_used(flow, &key, packet);
@@ -1237,7 +1262,7 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
 
 const struct dpif_class dpif_netdev_class = {
     "netdev",
-    NULL,                       /* enumerate */
+    dpif_netdev_enumerate,
     dpif_netdev_open,
     dpif_netdev_close,
     dpif_netdev_destroy,