vswitch: Restore MAC learning for broadcast ARP replies on bonds.
authorBen Pfaff <blp@nicira.com>
Tue, 5 May 2009 18:47:36 +0000 (11:47 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 5 May 2009 18:47:36 +0000 (11:47 -0700)
Bonding has a special exception for MAC learning: don't learn from packets
on bonded ports if we already have learned it on another port.  This is
because packets sent out one port can be received on the other, which would
cause us to learn incorrect locations.

But we need to make an exception for broadcast ARP replies, which indicate
that the MAC in question has moved to another switch.  Before commit
76fdb7e57 "Implement OFPP_NORMAL action in secchan and hook into vswitchd"
we did so, and this commit restores that behavior.

vswitchd/bridge.c

index bba96492a50447d330cfa36088f784adc0e93367..410d28f390ef66cbb771eb657cdb2849751c2fd9 100644 (file)
@@ -1559,6 +1559,16 @@ compose_actions(struct bridge *br, const flow_t *flow, uint16_t vlan,
     }
 }
 
+static bool
+is_bcast_arp_reply(const flow_t *flow, const struct ofpbuf *packet)
+{
+    struct arp_eth_header *arp = (struct arp_eth_header *) packet->data;
+    return (flow->dl_type == htons(ETH_TYPE_ARP)
+            && eth_addr_is_broadcast(flow->dl_dst)
+            && packet->size >= sizeof(struct arp_eth_header)
+            && arp->ar_op == ARP_OP_REQUEST);
+}
+
 /* If the composed actions may be applied to any packet in the given 'flow',
  * returns true.  Otherwise, the actions should only be applied to 'packet', or
  * not at all, if 'packet' was NULL. */
@@ -1678,13 +1688,12 @@ process_flow(struct bridge *br, const flow_t *flow,
             /* If the packet arrived on a bonded port, don't learn from it
              * unless we haven't learned any port at all for that address
              * (because we probably sent the packet on one bonded interface and
-             * got it back on the other). */
-            /* XXX invalidation? */
+             * got it back on the other).  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);
-            may_learn = src_idx < 0 || src_idx == in_port->port_idx;
-
-            /* XXX Need to make an exception for broadcast ARP replies here:
-             * the host has moved to another switch. */
+            may_learn = (src_idx < 0
+                         || src_idx == in_port->port_idx
+                         || is_bcast_arp_reply(flow, packet));
         } else {
             may_learn = true;
         }