vswitchd: Eliminate "can't forward to bad port" when interfaces disappear.
authorBen Pfaff <blp@nicira.com>
Fri, 9 Jan 2009 20:51:19 +0000 (12:51 -0800)
committerBen Pfaff <blp@nicira.com>
Fri, 9 Jan 2009 20:51:19 +0000 (12:51 -0800)
When an interface was deleted from a datapath by a process other than
vswitchd (which is not supposed to happen), vswitchd would not realize it
and would continue to set up flows for that interface (and leave in place
existing flows).  This caused the kernel to complain "can't forward to bad
port" for each packet on these flows.

Xen triggered this by destroying vifs that were on vswitchd-controlled
datapaths (which removes them from any datapath that they are on).

This fixes the problem, by making vswitchd notice when interfaces
disappear and fixing up the flow table.

vswitchd/bridge.c

index 37cc964e7f293101de772719afc511096392201d..f7a4672f3b68f01c2f7f770d76cdee0076d5be6e 100644 (file)
@@ -1896,14 +1896,23 @@ phy_port_changed(struct bridge *br, enum ofp_port_reason reason,
     if (!iface) {
         return;
     }
-
     port = iface->port;
-    if (port && port->n_ifaces > 1) {
-        bond_link_status_update(iface,
-                                (reason != OFPPR_DELETE
-                                 && !(opp->state & htonl(OFPPS_LINK_DOWN))));
-    }
-    if (reason != OFPPR_DELETE) {
+
+    if (reason == OFPPR_DELETE) {
+        VLOG_WARN("bridge %s: interface %s deleted unexpectedly",
+                  br->name, iface->name);
+        iface_destroy(iface);
+        if (!port->n_ifaces) {
+            VLOG_WARN("bridge %s: port %s has no interfaces, deleting",
+                      br->name, port->name);
+            port_destroy(port);
+        }
+        bridge_flush(br);
+    } else {
+        if (port->n_ifaces > 1) {
+            bool up = !(opp->state & htonl(OFPPS_LINK_DOWN));
+            bond_link_status_update(iface, up);
+        }
         memcpy(iface->mac, opp->hw_addr, ETH_ADDR_LEN);
     }
 }