From 183cfdf31a8f608b17175bdbdd55b759473316d3 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 5 May 2009 11:47:36 -0700 Subject: [PATCH] vswitch: Restore MAC learning for broadcast ARP replies on bonds. 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 | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index bba96492..410d28f3 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -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; } -- 2.30.2