Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'bonding-macvlan'

Vlad Yasevich says:

====================
Fix support for macvlan devices on top bonding

Currently, macvlan devices do not work well over bond interfaces.
Everything works well, untill a failover is triggered in the bond
device and then macvlan becomes unreachble untill arp entries
are flushed. This series adds needed functionality to
handle correct notifications and update switches with mac addresses
assigned to macvlans.

The first patch simply addes IFF_UNICAST_FLT flag to bonds since they
already correctly manage the unicast filter list of the slaves, so
we might as well prevent the bond from needlessly going into promiscuous
mode.

The second patch adds notifier handler to macvlan to trigger correct
ARP notifications.

The third patch adds handling for TLB and RLB modes that use special
ETH_P_LOOPBACK type packets to teach switch about mac addresses.
It also allow ARPs for the macvlan mac addresses to be handled by
RLB mode.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+53 -7
+18 -3
drivers/net/bonding/bond_alb.c
··· 755 755 /* Don't modify or load balance ARPs that do not originate locally 756 756 * (e.g.,arrive via a bridge). 757 757 */ 758 - if (!bond_slave_has_mac_rcu(bond, arp->mac_src)) 758 + if (!bond_slave_has_mac_rx(bond, arp->mac_src)) 759 759 return NULL; 760 760 761 761 if (arp->op_code == htons(ARPOP_REPLY)) { ··· 1039 1039 struct bonding *bond = bond_get_bond_by_slave(slave); 1040 1040 struct net_device *upper; 1041 1041 struct list_head *iter; 1042 + struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP]; 1042 1043 1043 1044 /* send untagged */ 1044 1045 alb_send_lp_vid(slave, mac_addr, 0, 0); 1045 1046 1046 - /* loop through vlans and send one packet for each */ 1047 + /* loop through all devices and see if we need to send a packet 1048 + * for that device. 1049 + */ 1047 1050 rcu_read_lock(); 1048 1051 netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { 1049 1052 if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) { ··· 1061 1058 vlan_dev_vlan_proto(upper), 1062 1059 vlan_dev_vlan_id(upper)); 1063 1060 } 1061 + } 1062 + 1063 + /* If this is a macvlan device, then only send updates 1064 + * when strict_match is turned off. 1065 + */ 1066 + if (netif_is_macvlan(upper) && !strict_match) { 1067 + memset(tags, 0, sizeof(tags)); 1068 + bond_verify_device_path(bond->dev, upper, tags); 1069 + alb_send_lp_vid(slave, upper->dev_addr, 1070 + tags[0].vlan_proto, tags[0].vlan_id); 1064 1071 } 1065 1072 } 1066 1073 rcu_read_unlock(); ··· 1573 1560 /* If updating current_active, use all currently 1574 1561 * user mac addreses (!strict_match). Otherwise, only 1575 1562 * use mac of the slave device. 1563 + * In RLB mode, we always use strict matches. 1576 1564 */ 1577 - strict_match = (slave != bond->curr_active_slave); 1565 + strict_match = (slave != bond->curr_active_slave || 1566 + bond_info->rlb_enabled); 1578 1567 alb_send_learning_packets(slave, slave->dev->dev_addr, 1579 1568 strict_match); 1580 1569 }
+4 -4
drivers/net/bonding/bond_main.c
··· 2206 2206 * When the path is validated, collect any vlan information in the 2207 2207 * path. 2208 2208 */ 2209 - static bool bond_verify_device_path(struct net_device *start_dev, 2210 - struct net_device *end_dev, 2211 - struct bond_vlan_tag *tags) 2209 + bool bond_verify_device_path(struct net_device *start_dev, 2210 + struct net_device *end_dev, 2211 + struct bond_vlan_tag *tags) 2212 2212 { 2213 2213 struct net_device *upper; 2214 2214 struct list_head *iter; ··· 3945 3945 /* Initialize the device options */ 3946 3946 bond_dev->tx_queue_len = 0; 3947 3947 bond_dev->flags |= IFF_MASTER|IFF_MULTICAST; 3948 - bond_dev->priv_flags |= IFF_BONDING; 3948 + bond_dev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT; 3949 3949 bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); 3950 3950 3951 3951 /* At first, we block adding VLANs. That's the only way to
+24
drivers/net/bonding/bonding.h
··· 516 516 struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); 517 517 struct net_device *bond_option_active_slave_get(struct bonding *bond); 518 518 const char *bond_slave_link_status(s8 link); 519 + bool bond_verify_device_path(struct net_device *start_dev, 520 + struct net_device *end_dev, 521 + struct bond_vlan_tag *tags); 519 522 520 523 #ifdef CONFIG_PROC_FS 521 524 void bond_create_proc_entry(struct bonding *bond); ··· 568 565 return tmp; 569 566 570 567 return NULL; 568 + } 569 + 570 + /* Caller must hold rcu_read_lock() for read */ 571 + static inline bool bond_slave_has_mac_rx(struct bonding *bond, const u8 *mac) 572 + { 573 + struct list_head *iter; 574 + struct slave *tmp; 575 + struct netdev_hw_addr *ha; 576 + 577 + bond_for_each_slave_rcu(bond, tmp, iter) 578 + if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr)) 579 + return true; 580 + 581 + if (netdev_uc_empty(bond->dev)) 582 + return false; 583 + 584 + netdev_for_each_uc_addr(ha, bond->dev) 585 + if (ether_addr_equal_64bits(mac, ha->addr)) 586 + return true; 587 + 588 + return false; 571 589 } 572 590 573 591 /* Check if the ip is present in arp ip list, or first free slot if ip == 0
+7
drivers/net/macvlan.c
··· 1209 1209 case NETDEV_PRE_TYPE_CHANGE: 1210 1210 /* Forbid underlaying device to change its type. */ 1211 1211 return NOTIFY_BAD; 1212 + 1213 + case NETDEV_NOTIFY_PEERS: 1214 + case NETDEV_BONDING_FAILOVER: 1215 + case NETDEV_RESEND_IGMP: 1216 + /* Propagate to all vlans */ 1217 + list_for_each_entry(vlan, &port->vlans, list) 1218 + call_netdevice_notifiers(event, vlan->dev); 1212 1219 } 1213 1220 return NOTIFY_DONE; 1214 1221 }