bonding: Drop unicast packets which have a different learned port.
authorJesse Gross <jesse@nicira.com>
Mon, 12 Oct 2009 20:09:51 +0000 (13:09 -0700)
committerJesse Gross <jesse@nicira.com>
Tue, 20 Oct 2009 17:52:31 +0000 (10:52 -0700)
Drop packets received on a bond port if we have learned a different
source port for that MAC.  We were already doing this for multicast
packets but extend the logic to unicast packets as well since the
same situation can occur if the connected switch has not learned the
MAC address and is flooding.  Otherwise vSwitch will learn the bond
port as the source of that MAC.

Bug #2167

vswitchd/INTERNALS
vswitchd/bridge.c

index 49a4158..5873dc1 100644 (file)
@@ -83,12 +83,12 @@ received on other slaves are dropped.  Otherwise, every multicast
 packet would be duplicated, once for every bond slave, because the
 physical switch attached to the bond will flood those packets.
 
-Bonding also drops some multicast packets received on the active
-slave: those for the vswitch has learned that the packet's MAC is on a
-port other than the bond port itself.  This is because it is likely
-that the vswitch itself sent the multicast packet out the bond port,
-on a slave other than the active slave, and is now receiving the
-packet back on the active slave.  However, the vswitch makes an
+Bonding also drops received packets when the vswitch has learned that
+the packet's MAC is on a port other than the bond port itself.  This is
+because it is likely that the vswitch itself sent the packet out the
+bond port on a different slave and is now receiving the packet back.
+This occurs when the packet is multicast or the physical switch has not
+yet learned the MAC and is flooding it.  However, the vswitch makes an
 exception to this rule for broadcast ARP replies, which indicate that
 the MAC has moved to another switch, probably due to VM migration.
 (ARP replies are normally unicast, so this exception does not match
index 3ee964d..7ce1f25 100644 (file)
@@ -1897,33 +1897,27 @@ process_flow(struct bridge *br, const flow_t *flow,
         goto done;
     }
 
-    /* Multicast (and broadcast) packets on bonds need special attention, to
-     * avoid receiving duplicates. */
-    if (in_port->n_ifaces > 1 && eth_addr_is_multicast(flow->dl_dst)) {
-        *tags |= in_port->active_iface_tag;
-        if (in_port->active_iface != in_iface->port_ifidx) {
-            /* Drop all multicast packets on inactive slaves. */
-            goto done;
-        } else {
-            /* Drop all multicast packets for which we have learned a different
-             * input port, because we probably sent the packet on one slave
-             * and got it back on the active slave.  Broadcast ARP replies are
-             * an exception to this rule: the host has moved to another
-             * switch. */
-            int src_idx = mac_learning_lookup(br->ml, flow->dl_src, vlan);
-            if (src_idx != -1 && src_idx != in_port->port_idx) {
-                if (packet) {
-                    if (!is_bcast_arp_reply(flow, packet)) {
-                        goto done;
-                    }
-                } else {
-                    /* No way to know whether it's an ARP reply, because the
-                     * flow entry doesn't include enough information and we
-                     * don't have a packet.  Punt. */
-                    return false;
-                }
+    /* Packets received on bonds need special attention to avoid duplicates. */
+    if (in_port->n_ifaces > 1) {
+        int src_idx;
+
+        if (eth_addr_is_multicast(flow->dl_dst)) {
+            *tags |= in_port->active_iface_tag;
+            if (in_port->active_iface != in_iface->port_ifidx) {
+                /* Drop all multicast packets on inactive slaves. */
+                goto done;
             }
         }
+
+        /* Drop all packets for which we have learned a different input
+         * port, because we probably sent the packet on one slave and got
+         * it back on the other.  Broadcast ARP replies are an exception
+         * to this rule: the host has moved to another switch. */
+        src_idx = mac_learning_lookup(br->ml, flow->dl_src, vlan);
+        if (src_idx != -1 && src_idx != in_port->port_idx &&
+            (!packet || !is_bcast_arp_reply(flow, packet))) {
+                goto done;
+        }
     }
 
     /* MAC learning. */