dpif-linux: Clean up vports that are no longer in config.
authorJesse Gross <jesse@nicira.com>
Sat, 10 Apr 2010 05:19:29 +0000 (01:19 -0400)
committerJesse Gross <jesse@nicira.com>
Mon, 19 Apr 2010 13:11:57 +0000 (09:11 -0400)
If the config changes while ovs-vswitchd is not running it is possible
that there could be some vports which are no longer needed but won't
be destroyed when closed because they aren't open.  This deletes
unneeded vports at the same time that we clean up unneeded datapaths.

lib/dpif-linux.c

index 593127f41b5a6ee06a251e2e8d43c06d687c3cbb..87c9f327c79bf95b5357d64e3cd923c78df5bcd0 100644 (file)
@@ -31,6 +31,7 @@
 #include <unistd.h>
 
 #include "dpif-provider.h"
+#include "netdev.h"
 #include "ofpbuf.h"
 #include "poll-loop.h"
 #include "rtnetlink.h"
@@ -190,6 +191,28 @@ dpif_linux_get_all_names(const struct dpif *dpif_, struct svec *all_names)
 static int
 dpif_linux_destroy(struct dpif *dpif_)
 {
+    struct odp_port *ports;
+    size_t n_ports;
+    int err;
+    int i;
+
+    err = dpif_port_list(dpif_, &ports, &n_ports);
+    if (err) {
+        return err;
+    }
+
+    for (i = 0; i < n_ports; i++) {
+        if (ports[i].port != ODPP_LOCAL) {
+            err = do_ioctl(dpif_, ODP_VPORT_DEL, ports[i].devname);
+            if (err) {
+                VLOG_WARN_RL(&error_rl, "%s: error deleting port %s (%s)",
+                             dpif_name(dpif_), ports[i].devname, strerror(err));
+            }
+        }
+    }
+
+    free(ports);
+
     return do_ioctl(dpif_, ODP_DP_DESTROY, NULL);
 }
 
@@ -241,7 +264,27 @@ static int
 dpif_linux_port_del(struct dpif *dpif_, uint16_t port_no)
 {
     int tmp = port_no;
-    return do_ioctl(dpif_, ODP_PORT_DETACH, &tmp);
+    int err;
+    struct odp_port port;
+
+    err = dpif_port_query_by_number(dpif_, port_no, &port);
+    if (err) {
+        return err;
+    }
+
+    err = do_ioctl(dpif_, ODP_PORT_DETACH, &tmp);
+    if (err) {
+        return err;
+    }
+
+    if (!netdev_is_open(port.devname)) {
+        /* Try deleting the port if no one has it open.  This shouldn't
+         * actually be necessary unless the config changed while we weren't
+         * running but it won't hurt anything if the port is already gone. */
+        do_ioctl(dpif_, ODP_VPORT_DEL, port.devname);
+    }
+
+    return 0;
 }
 
 static int