aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevic@redhat.com>2014-06-04 16:23:38 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-04 18:13:54 -0400
commit14af9963ba1e5e8400c9de9267bdcab895109f6a (patch)
tree55e2be9506708df787f2158e11454b8ac2b7c36a /drivers/net/bonding
parent4c9912556867bf89e7bb6946fd218a40b1d12139 (diff)
bonding: Support macvlans on top of tlb/rlb mode bonds
To make TLB mode work, the patch allows learning packets to be sent using mac addresses assigned to macvlan devices, also taking into an account vlans that may be between the bond and macvlan device. To make RLB work, all we have to do is accept ARP packets for addresses added to the bond dev->uc list. Since RLB mode will take care to update the peers directly with correct mac addresses, learning packets for these addresses do not have be send to switch. Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_alb.c21
-rw-r--r--drivers/net/bonding/bond_main.c6
-rw-r--r--drivers/net/bonding/bonding.h24
3 files changed, 45 insertions, 6 deletions
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 7bbbf1ca0887..76c0dade233f 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -755,7 +755,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
755 /* Don't modify or load balance ARPs that do not originate locally 755 /* Don't modify or load balance ARPs that do not originate locally
756 * (e.g.,arrive via a bridge). 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 return NULL; 759 return NULL;
760 760
761 if (arp->op_code == htons(ARPOP_REPLY)) { 761 if (arp->op_code == htons(ARPOP_REPLY)) {
@@ -1039,11 +1039,14 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
1039 struct bonding *bond = bond_get_bond_by_slave(slave); 1039 struct bonding *bond = bond_get_bond_by_slave(slave);
1040 struct net_device *upper; 1040 struct net_device *upper;
1041 struct list_head *iter; 1041 struct list_head *iter;
1042 struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP];
1042 1043
1043 /* send untagged */ 1044 /* send untagged */
1044 alb_send_lp_vid(slave, mac_addr, 0, 0); 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 rcu_read_lock(); 1050 rcu_read_lock();
1048 netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { 1051 netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
1049 if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) { 1052 if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
@@ -1059,6 +1062,16 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
1059 vlan_dev_vlan_id(upper)); 1062 vlan_dev_vlan_id(upper));
1060 } 1063 }
1061 } 1064 }
1065
1066 /* If this is a macvlan device, then only send updates
1067 * when strict_match is turned off.
1068 */
1069 if (netif_is_macvlan(upper) && !strict_match) {
1070 memset(tags, 0, sizeof(tags));
1071 bond_verify_device_path(bond->dev, upper, tags);
1072 alb_send_lp_vid(slave, upper->dev_addr,
1073 tags[0].vlan_proto, tags[0].vlan_id);
1074 }
1062 } 1075 }
1063 rcu_read_unlock(); 1076 rcu_read_unlock();
1064} 1077}
@@ -1560,8 +1573,10 @@ void bond_alb_monitor(struct work_struct *work)
1560 /* If updating current_active, use all currently 1573 /* If updating current_active, use all currently
1561 * user mac addreses (!strict_match). Otherwise, only 1574 * user mac addreses (!strict_match). Otherwise, only
1562 * use mac of the slave device. 1575 * use mac of the slave device.
1576 * In RLB mode, we always use strict matches.
1563 */ 1577 */
1564 strict_match = (slave != bond->curr_active_slave); 1578 strict_match = (slave != bond->curr_active_slave ||
1579 bond_info->rlb_enabled);
1565 alb_send_learning_packets(slave, slave->dev->dev_addr, 1580 alb_send_learning_packets(slave, slave->dev->dev_addr,
1566 strict_match); 1581 strict_match);
1567 } 1582 }
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a89bf18caa79..04f35f960cb8 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2206,9 +2206,9 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,
2206 * When the path is validated, collect any vlan information in the 2206 * When the path is validated, collect any vlan information in the
2207 * path. 2207 * path.
2208 */ 2208 */
2209static bool bond_verify_device_path(struct net_device *start_dev, 2209bool bond_verify_device_path(struct net_device *start_dev,
2210 struct net_device *end_dev, 2210 struct net_device *end_dev,
2211 struct bond_vlan_tag *tags) 2211 struct bond_vlan_tag *tags)
2212{ 2212{
2213 struct net_device *upper; 2213 struct net_device *upper;
2214 struct list_head *iter; 2214 struct list_head *iter;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ea64aa2f8b95..0b4d9cde0b05 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -516,6 +516,9 @@ void bond_netlink_fini(void);
516struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); 516struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
517struct net_device *bond_option_active_slave_get(struct bonding *bond); 517struct net_device *bond_option_active_slave_get(struct bonding *bond);
518const char *bond_slave_link_status(s8 link); 518const char *bond_slave_link_status(s8 link);
519bool bond_verify_device_path(struct net_device *start_dev,
520 struct net_device *end_dev,
521 struct bond_vlan_tag *tags);
519 522
520#ifdef CONFIG_PROC_FS 523#ifdef CONFIG_PROC_FS
521void bond_create_proc_entry(struct bonding *bond); 524void bond_create_proc_entry(struct bonding *bond);
@@ -567,6 +570,27 @@ static inline struct slave *bond_slave_has_mac_rcu(struct bonding *bond,
567 return NULL; 570 return NULL;
568} 571}
569 572
573/* Caller must hold rcu_read_lock() for read */
574static inline bool bond_slave_has_mac_rx(struct bonding *bond, const u8 *mac)
575{
576 struct list_head *iter;
577 struct slave *tmp;
578 struct netdev_hw_addr *ha;
579
580 bond_for_each_slave_rcu(bond, tmp, iter)
581 if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
582 return true;
583
584 if (netdev_uc_empty(bond->dev))
585 return false;
586
587 netdev_for_each_uc_addr(ha, bond->dev)
588 if (ether_addr_equal_64bits(mac, ha->addr))
589 return true;
590
591 return false;
592}
593
570/* Check if the ip is present in arp ip list, or first free slot if ip == 0 594/* Check if the ip is present in arp ip list, or first free slot if ip == 0
571 * Returns -1 if not found, index if found 595 * Returns -1 if not found, index if found
572 */ 596 */