diff options
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r-- | drivers/net/bonding/bond_3ad.c | 62 | ||||
-rw-r--r-- | drivers/net/bonding/bond_alb.c | 153 | ||||
-rw-r--r-- | drivers/net/bonding/bond_alb.h | 1 | ||||
-rw-r--r-- | drivers/net/bonding/bond_debugfs.c | 2 | ||||
-rw-r--r-- | drivers/net/bonding/bond_main.c | 218 | ||||
-rw-r--r-- | drivers/net/bonding/bond_netlink.c | 8 | ||||
-rw-r--r-- | drivers/net/bonding/bond_options.c | 66 | ||||
-rw-r--r-- | drivers/net/bonding/bond_options.h | 2 | ||||
-rw-r--r-- | drivers/net/bonding/bond_procfs.c | 16 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 567 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs_slave.c | 4 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 143 |
12 files changed, 512 insertions, 730 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index b667a51ed215..0dfeaf5da3f2 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -157,7 +157,7 @@ static inline struct aggregator *__get_first_agg(struct port *port) rcu_read_lock(); first_slave = bond_first_slave_rcu(bond); - agg = first_slave ? &(SLAVE_AD_INFO(first_slave).aggregator) : NULL; + agg = first_slave ? &(SLAVE_AD_INFO(first_slave)->aggregator) : NULL; rcu_read_unlock(); return agg; @@ -192,7 +192,7 @@ static inline void __enable_port(struct port *port) { struct slave *slave = port->slave; - if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) + if ((slave->link == BOND_LINK_UP) && bond_slave_is_up(slave)) bond_set_slave_active_flags(slave, BOND_SLAVE_NOTIFY_LATER); } @@ -241,7 +241,7 @@ static inline int __check_agg_selection_timer(struct port *port) */ static inline void __get_state_machine_lock(struct port *port) { - spin_lock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); + spin_lock_bh(&(SLAVE_AD_INFO(port->slave)->state_machine_lock)); } /** @@ -250,7 +250,7 @@ static inline void __get_state_machine_lock(struct port *port) */ static inline void __release_state_machine_lock(struct port *port) { - spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); + spin_unlock_bh(&(SLAVE_AD_INFO(port->slave)->state_machine_lock)); } /** @@ -350,7 +350,7 @@ static u8 __get_duplex(struct port *port) static inline void __initialize_port_locks(struct slave *slave) { /* make sure it isn't called twice */ - spin_lock_init(&(SLAVE_AD_INFO(slave).state_machine_lock)); + spin_lock_init(&(SLAVE_AD_INFO(slave)->state_machine_lock)); } /* Conversions */ @@ -688,8 +688,8 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator) struct slave *slave; bond_for_each_slave_rcu(bond, slave, iter) - if (SLAVE_AD_INFO(slave).aggregator.is_active) - return &(SLAVE_AD_INFO(slave).aggregator); + if (SLAVE_AD_INFO(slave)->aggregator.is_active) + return &(SLAVE_AD_INFO(slave)->aggregator); return NULL; } @@ -1293,7 +1293,7 @@ static void ad_port_selection_logic(struct port *port) } /* search on all aggregators for a suitable aggregator for this port */ bond_for_each_slave(bond, slave, iter) { - aggregator = &(SLAVE_AD_INFO(slave).aggregator); + aggregator = &(SLAVE_AD_INFO(slave)->aggregator); /* keep a free aggregator for later use(if needed) */ if (!aggregator->lag_ports) { @@ -1504,7 +1504,7 @@ static void ad_agg_selection_logic(struct aggregator *agg) best = (active && agg_device_up(active)) ? active : NULL; bond_for_each_slave_rcu(bond, slave, iter) { - agg = &(SLAVE_AD_INFO(slave).aggregator); + agg = &(SLAVE_AD_INFO(slave)->aggregator); agg->is_active = 0; @@ -1549,7 +1549,7 @@ static void ad_agg_selection_logic(struct aggregator *agg) best->slave ? best->slave->dev->name : "NULL"); bond_for_each_slave_rcu(bond, slave, iter) { - agg = &(SLAVE_AD_INFO(slave).aggregator); + agg = &(SLAVE_AD_INFO(slave)->aggregator); pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", agg->aggregator_identifier, agg->num_of_ports, @@ -1840,16 +1840,16 @@ void bond_3ad_bind_slave(struct slave *slave) struct aggregator *aggregator; /* check that the slave has not been initialized yet. */ - if (SLAVE_AD_INFO(slave).port.slave != slave) { + if (SLAVE_AD_INFO(slave)->port.slave != slave) { /* port initialization */ - port = &(SLAVE_AD_INFO(slave).port); + port = &(SLAVE_AD_INFO(slave)->port); ad_initialize_port(port, bond->params.lacp_fast); __initialize_port_locks(slave); port->slave = slave; - port->actor_port_number = SLAVE_AD_INFO(slave).id; + port->actor_port_number = SLAVE_AD_INFO(slave)->id; /* key is determined according to the link speed, duplex and user key(which * is yet not supported) */ @@ -1874,7 +1874,7 @@ void bond_3ad_bind_slave(struct slave *slave) __disable_port(port); /* aggregator initialization */ - aggregator = &(SLAVE_AD_INFO(slave).aggregator); + aggregator = &(SLAVE_AD_INFO(slave)->aggregator); ad_initialize_agg(aggregator); @@ -1903,8 +1903,8 @@ void bond_3ad_unbind_slave(struct slave *slave) struct slave *slave_iter; struct list_head *iter; - aggregator = &(SLAVE_AD_INFO(slave).aggregator); - port = &(SLAVE_AD_INFO(slave).port); + aggregator = &(SLAVE_AD_INFO(slave)->aggregator); + port = &(SLAVE_AD_INFO(slave)->port); /* if slave is null, the whole port is not initialized */ if (!port->slave) { @@ -1932,7 +1932,7 @@ void bond_3ad_unbind_slave(struct slave *slave) (aggregator->lag_ports->next_port_in_aggregator)) { /* find new aggregator for the related port(s) */ bond_for_each_slave(bond, slave_iter, iter) { - new_aggregator = &(SLAVE_AD_INFO(slave_iter).aggregator); + new_aggregator = &(SLAVE_AD_INFO(slave_iter)->aggregator); /* if the new aggregator is empty, or it is * connected to our port only */ @@ -2010,7 +2010,7 @@ void bond_3ad_unbind_slave(struct slave *slave) /* find the aggregator that this port is connected to */ bond_for_each_slave(bond, slave_iter, iter) { - temp_aggregator = &(SLAVE_AD_INFO(slave_iter).aggregator); + temp_aggregator = &(SLAVE_AD_INFO(slave_iter)->aggregator); prev_port = NULL; /* search the port in the aggregator's related ports */ for (temp_port = temp_aggregator->lag_ports; temp_port; @@ -2076,7 +2076,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) if (BOND_AD_INFO(bond).agg_select_timer && !(--BOND_AD_INFO(bond).agg_select_timer)) { slave = bond_first_slave_rcu(bond); - port = slave ? &(SLAVE_AD_INFO(slave).port) : NULL; + port = slave ? &(SLAVE_AD_INFO(slave)->port) : NULL; /* select the active aggregator for the bond */ if (port) { @@ -2094,7 +2094,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) /* for each port run the state machines */ bond_for_each_slave_rcu(bond, slave, iter) { - port = &(SLAVE_AD_INFO(slave).port); + port = &(SLAVE_AD_INFO(slave)->port); if (!port->slave) { pr_warn_ratelimited("%s: Warning: Found an uninitialized port\n", bond->dev->name); @@ -2155,7 +2155,7 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, if (length >= sizeof(struct lacpdu)) { - port = &(SLAVE_AD_INFO(slave).port); + port = &(SLAVE_AD_INFO(slave)->port); if (!port->slave) { pr_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n", @@ -2212,7 +2212,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave) { struct port *port; - port = &(SLAVE_AD_INFO(slave).port); + port = &(SLAVE_AD_INFO(slave)->port); /* if slave is null, the whole port is not initialized */ if (!port->slave) { @@ -2245,7 +2245,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) { struct port *port; - port = &(SLAVE_AD_INFO(slave).port); + port = &(SLAVE_AD_INFO(slave)->port); /* if slave is null, the whole port is not initialized */ if (!port->slave) { @@ -2279,7 +2279,7 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) { struct port *port; - port = &(SLAVE_AD_INFO(slave).port); + port = &(SLAVE_AD_INFO(slave)->port); /* if slave is null, the whole port is not initialized */ if (!port->slave) { @@ -2347,7 +2347,7 @@ int bond_3ad_set_carrier(struct bonding *bond) ret = 0; goto out; } - active = __get_active_agg(&(SLAVE_AD_INFO(first_slave).aggregator)); + active = __get_active_agg(&(SLAVE_AD_INFO(first_slave)->aggregator)); if (active) { /* are enough slaves available to consider link up? */ if (active->num_of_ports < bond->params.min_links) { @@ -2384,7 +2384,7 @@ int __bond_3ad_get_active_agg_info(struct bonding *bond, struct port *port; bond_for_each_slave_rcu(bond, slave, iter) { - port = &(SLAVE_AD_INFO(slave).port); + port = &(SLAVE_AD_INFO(slave)->port); if (port->aggregator && port->aggregator->is_active) { aggregator = port->aggregator; break; @@ -2440,22 +2440,22 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) goto err_free; } - slave_agg_no = bond_xmit_hash(bond, skb, slaves_in_agg); + slave_agg_no = bond_xmit_hash(bond, skb) % slaves_in_agg; first_ok_slave = NULL; bond_for_each_slave_rcu(bond, slave, iter) { - agg = SLAVE_AD_INFO(slave).port.aggregator; + agg = SLAVE_AD_INFO(slave)->port.aggregator; if (!agg || agg->aggregator_identifier != agg_id) continue; if (slave_agg_no >= 0) { - if (!first_ok_slave && SLAVE_IS_OK(slave)) + if (!first_ok_slave && bond_slave_can_tx(slave)) first_ok_slave = slave; slave_agg_no--; continue; } - if (SLAVE_IS_OK(slave)) { + if (bond_slave_can_tx(slave)) { bond_dev_queue_xmit(bond, skb, slave->dev); goto out; } @@ -2522,7 +2522,7 @@ void bond_3ad_update_lacp_rate(struct bonding *bond) lacp_fast = bond->params.lacp_fast; bond_for_each_slave(bond, slave, iter) { - port = &(SLAVE_AD_INFO(slave).port); + port = &(SLAVE_AD_INFO(slave)->port); __get_state_machine_lock(port); if (lacp_fast) port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT; diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 93580a47cc54..76c0dade233f 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -229,7 +229,7 @@ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond) /* Find the slave with the largest gap */ bond_for_each_slave_rcu(bond, slave, iter) { - if (SLAVE_IS_OK(slave)) { + if (bond_slave_can_tx(slave)) { long long gap = compute_gap(slave); if (max_gap < gap) { @@ -384,7 +384,7 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond) bool found = false; bond_for_each_slave(bond, slave, iter) { - if (!SLAVE_IS_OK(slave)) + if (!bond_slave_can_tx(slave)) continue; if (!found) { if (!before || before->speed < slave->speed) @@ -417,7 +417,7 @@ static struct slave *__rlb_next_rx_slave(struct bonding *bond) bool found = false; bond_for_each_slave_rcu(bond, slave, iter) { - if (!SLAVE_IS_OK(slave)) + if (!bond_slave_can_tx(slave)) continue; if (!found) { if (!before || before->speed < slave->speed) @@ -755,7 +755,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) /* Don't modify or load balance ARPs that do not originate locally * (e.g.,arrive via a bridge). */ - if (!bond_slave_has_mac_rcu(bond, arp->mac_src)) + if (!bond_slave_has_mac_rx(bond, arp->mac_src)) return NULL; if (arp->op_code == htons(ARPOP_REPLY)) { @@ -1039,11 +1039,14 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], struct bonding *bond = bond_get_bond_by_slave(slave); struct net_device *upper; struct list_head *iter; + struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP]; /* send untagged */ alb_send_lp_vid(slave, mac_addr, 0, 0); - /* loop through vlans and send one packet for each */ + /* loop through all devices and see if we need to send a packet + * for that device. + */ rcu_read_lock(); netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { 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[], vlan_dev_vlan_id(upper)); } } + + /* If this is a macvlan device, then only send updates + * when strict_match is turned off. + */ + if (netif_is_macvlan(upper) && !strict_match) { + memset(tags, 0, sizeof(tags)); + bond_verify_device_path(bond->dev, upper, tags); + alb_send_lp_vid(slave, upper->dev_addr, + tags[0].vlan_proto, tags[0].vlan_id); + } } rcu_read_unlock(); } @@ -1068,7 +1081,7 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[]) struct net_device *dev = slave->dev; struct sockaddr s_addr; - if (slave->bond->params.mode == BOND_MODE_TLB) { + if (BOND_MODE(slave->bond) == BOND_MODE_TLB) { memcpy(dev->dev_addr, addr, dev->addr_len); return 0; } @@ -1111,13 +1124,13 @@ static void alb_swap_mac_addr(struct slave *slave1, struct slave *slave2) static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1, struct slave *slave2) { - int slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2)); + int slaves_state_differ = (bond_slave_can_tx(slave1) != bond_slave_can_tx(slave2)); struct slave *disabled_slave = NULL; ASSERT_RTNL(); /* fasten the change in the switch */ - if (SLAVE_IS_OK(slave1)) { + if (bond_slave_can_tx(slave1)) { alb_send_learning_packets(slave1, slave1->dev->dev_addr, false); if (bond->alb_info.rlb_enabled) { /* inform the clients that the mac address @@ -1129,7 +1142,7 @@ static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1, disabled_slave = slave1; } - if (SLAVE_IS_OK(slave2)) { + if (bond_slave_can_tx(slave2)) { alb_send_learning_packets(slave2, slave2->dev->dev_addr, false); if (bond->alb_info.rlb_enabled) { /* inform the clients that the mac address @@ -1358,6 +1371,77 @@ void bond_alb_deinitialize(struct bonding *bond) rlb_deinitialize(bond); } +static int bond_do_alb_xmit(struct sk_buff *skb, struct bonding *bond, + struct slave *tx_slave) +{ + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); + struct ethhdr *eth_data = eth_hdr(skb); + + if (!tx_slave) { + /* unbalanced or unassigned, send through primary */ + tx_slave = rcu_dereference(bond->curr_active_slave); + if (bond->params.tlb_dynamic_lb) + bond_info->unbalanced_load += skb->len; + } + + if (tx_slave && bond_slave_can_tx(tx_slave)) { + if (tx_slave != rcu_dereference(bond->curr_active_slave)) { + ether_addr_copy(eth_data->h_source, + tx_slave->dev->dev_addr); + } + + bond_dev_queue_xmit(bond, skb, tx_slave->dev); + goto out; + } + + if (tx_slave && bond->params.tlb_dynamic_lb) { + _lock_tx_hashtbl(bond); + __tlb_clear_slave(bond, tx_slave, 0); + _unlock_tx_hashtbl(bond); + } + + /* no suitable interface, frame not sent */ + dev_kfree_skb_any(skb); +out: + return NETDEV_TX_OK; +} + +int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev) +{ + struct bonding *bond = netdev_priv(bond_dev); + struct ethhdr *eth_data; + struct slave *tx_slave = NULL; + u32 hash_index; + + skb_reset_mac_header(skb); + eth_data = eth_hdr(skb); + + /* Do not TX balance any multicast or broadcast */ + if (!is_multicast_ether_addr(eth_data->h_dest)) { + switch (skb->protocol) { + case htons(ETH_P_IP): + case htons(ETH_P_IPX): + /* In case of IPX, it will falback to L2 hash */ + case htons(ETH_P_IPV6): + hash_index = bond_xmit_hash(bond, skb); + if (bond->params.tlb_dynamic_lb) { + tx_slave = tlb_choose_channel(bond, + hash_index & 0xFF, + skb->len); + } else { + struct list_head *iter; + int idx = hash_index % bond->slave_cnt; + + bond_for_each_slave_rcu(bond, tx_slave, iter) + if (--idx < 0) + break; + } + break; + } + } + return bond_do_alb_xmit(skb, bond, tx_slave); +} + int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); @@ -1366,7 +1450,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) struct slave *tx_slave = NULL; static const __be32 ip_bcast = htonl(0xffffffff); int hash_size = 0; - int do_tx_balance = 1; + bool do_tx_balance = true; u32 hash_index = 0; const u8 *hash_start = NULL; struct ipv6hdr *ip6hdr; @@ -1381,7 +1465,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) if (ether_addr_equal_64bits(eth_data->h_dest, mac_bcast) || (iph->daddr == ip_bcast) || (iph->protocol == IPPROTO_IGMP)) { - do_tx_balance = 0; + do_tx_balance = false; break; } hash_start = (char *)&(iph->daddr); @@ -1393,7 +1477,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) * that here just in case. */ if (ether_addr_equal_64bits(eth_data->h_dest, mac_bcast)) { - do_tx_balance = 0; + do_tx_balance = false; break; } @@ -1401,7 +1485,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) * broadcasts in IPv4. */ if (ether_addr_equal_64bits(eth_data->h_dest, mac_v6_allmcast)) { - do_tx_balance = 0; + do_tx_balance = false; break; } @@ -1411,7 +1495,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) */ ip6hdr = ipv6_hdr(skb); if (ipv6_addr_any(&ip6hdr->saddr)) { - do_tx_balance = 0; + do_tx_balance = false; break; } @@ -1421,7 +1505,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) case ETH_P_IPX: if (ipx_hdr(skb)->ipx_checksum != IPX_NO_CHECKSUM) { /* something is wrong with this packet */ - do_tx_balance = 0; + do_tx_balance = false; break; } @@ -1430,7 +1514,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) * this family since it has an "ARP" like * mechanism */ - do_tx_balance = 0; + do_tx_balance = false; break; } @@ -1438,12 +1522,12 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) hash_size = ETH_ALEN; break; case ETH_P_ARP: - do_tx_balance = 0; + do_tx_balance = false; if (bond_info->rlb_enabled) tx_slave = rlb_arp_xmit(skb, bond); break; default: - do_tx_balance = 0; + do_tx_balance = false; break; } @@ -1452,32 +1536,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) tx_slave = tlb_choose_channel(bond, hash_index, skb->len); } - if (!tx_slave) { - /* unbalanced or unassigned, send through primary */ - tx_slave = rcu_dereference(bond->curr_active_slave); - bond_info->unbalanced_load += skb->len; - } - - if (tx_slave && SLAVE_IS_OK(tx_slave)) { - if (tx_slave != rcu_dereference(bond->curr_active_slave)) { - ether_addr_copy(eth_data->h_source, - tx_slave->dev->dev_addr); - } - - bond_dev_queue_xmit(bond, skb, tx_slave->dev); - goto out; - } - - if (tx_slave) { - _lock_tx_hashtbl(bond); - __tlb_clear_slave(bond, tx_slave, 0); - _unlock_tx_hashtbl(bond); - } - - /* no suitable interface, frame not sent */ - dev_kfree_skb_any(skb); -out: - return NETDEV_TX_OK; + return bond_do_alb_xmit(skb, bond, tx_slave); } void bond_alb_monitor(struct work_struct *work) @@ -1514,8 +1573,10 @@ void bond_alb_monitor(struct work_struct *work) /* If updating current_active, use all currently * user mac addreses (!strict_match). Otherwise, only * use mac of the slave device. + * In RLB mode, we always use strict matches. */ - strict_match = (slave != bond->curr_active_slave); + strict_match = (slave != bond->curr_active_slave || + bond_info->rlb_enabled); alb_send_learning_packets(slave, slave->dev->dev_addr, strict_match); } @@ -1719,7 +1780,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave /* in TLB mode, the slave might flip down/up with the old dev_addr, * and thus filter bond->dev_addr's packets, so force bond's mac */ - if (bond->params.mode == BOND_MODE_TLB) { + if (BOND_MODE(bond) == BOND_MODE_TLB) { struct sockaddr sa; u8 tmp_addr[ETH_ALEN]; diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h index e09dd4bfafff..5fc76c01636c 100644 --- a/drivers/net/bonding/bond_alb.h +++ b/drivers/net/bonding/bond_alb.h @@ -175,6 +175,7 @@ void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave); void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link); void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave); int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev); +int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev); void bond_alb_monitor(struct work_struct *); int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr); void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id); diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c index 2d3f7fa541ff..658e761c4568 100644 --- a/drivers/net/bonding/bond_debugfs.c +++ b/drivers/net/bonding/bond_debugfs.c @@ -23,7 +23,7 @@ static int bond_debug_rlb_hash_show(struct seq_file *m, void *v) struct rlb_client_info *client_info; u32 hash_index; - if (bond->params.mode != BOND_MODE_ALB) + if (BOND_MODE(bond) != BOND_MODE_ALB) return 0; seq_printf(m, "SourceIP DestinationIP " diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d3a67896d435..04f35f960cb8 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -343,7 +343,7 @@ static int bond_set_carrier(struct bonding *bond) if (!bond_has_slaves(bond)) goto down; - if (bond->params.mode == BOND_MODE_8023AD) + if (BOND_MODE(bond) == BOND_MODE_8023AD) return bond_3ad_set_carrier(bond); bond_for_each_slave(bond, slave, iter) { @@ -497,7 +497,7 @@ static int bond_set_promiscuity(struct bonding *bond, int inc) struct list_head *iter; int err = 0; - if (USES_PRIMARY(bond->params.mode)) { + if (bond_uses_primary(bond)) { /* write lock already acquired */ if (bond->curr_active_slave) { err = dev_set_promiscuity(bond->curr_active_slave->dev, @@ -523,7 +523,7 @@ static int bond_set_allmulti(struct bonding *bond, int inc) struct list_head *iter; int err = 0; - if (USES_PRIMARY(bond->params.mode)) { + if (bond_uses_primary(bond)) { /* write lock already acquired */ if (bond->curr_active_slave) { err = dev_set_allmulti(bond->curr_active_slave->dev, @@ -574,7 +574,7 @@ static void bond_hw_addr_flush(struct net_device *bond_dev, dev_uc_unsync(slave_dev, bond_dev); dev_mc_unsync(slave_dev, bond_dev); - if (bond->params.mode == BOND_MODE_8023AD) { + if (BOND_MODE(bond) == BOND_MODE_8023AD) { /* del lacpdu mc addr from mc list */ u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; @@ -585,8 +585,8 @@ static void bond_hw_addr_flush(struct net_device *bond_dev, /*--------------------------- Active slave change ---------------------------*/ /* Update the hardware address list and promisc/allmulti for the new and - * old active slaves (if any). Modes that are !USES_PRIMARY keep all - * slaves up date at all times; only the USES_PRIMARY modes need to call + * old active slaves (if any). Modes that are not using primary keep all + * slaves up date at all times; only the modes that use primary need to call * this function to swap these settings during a failover. */ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active, @@ -747,7 +747,7 @@ static struct slave *bond_find_best_slave(struct bonding *bond) bond_for_each_slave(bond, slave, iter) { if (slave->link == BOND_LINK_UP) return slave; - if (slave->link == BOND_LINK_BACK && IS_UP(slave->dev) && + if (slave->link == BOND_LINK_BACK && bond_slave_is_up(slave) && slave->delay < mintime) { mintime = slave->delay; bestslave = slave; @@ -801,7 +801,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) new_active->last_link_up = jiffies; if (new_active->link == BOND_LINK_BACK) { - if (USES_PRIMARY(bond->params.mode)) { + if (bond_uses_primary(bond)) { pr_info("%s: making interface %s the new active one %d ms earlier\n", bond->dev->name, new_active->dev->name, (bond->params.updelay - new_active->delay) * bond->params.miimon); @@ -810,20 +810,20 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) new_active->delay = 0; new_active->link = BOND_LINK_UP; - if (bond->params.mode == BOND_MODE_8023AD) + if (BOND_MODE(bond) == BOND_MODE_8023AD) bond_3ad_handle_link_change(new_active, BOND_LINK_UP); if (bond_is_lb(bond)) bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP); } else { - if (USES_PRIMARY(bond->params.mode)) { + if (bond_uses_primary(bond)) { pr_info("%s: making interface %s the new active one\n", bond->dev->name, new_active->dev->name); } } } - if (USES_PRIMARY(bond->params.mode)) + if (bond_uses_primary(bond)) bond_hw_addr_swap(bond, new_active, old_active); if (bond_is_lb(bond)) { @@ -838,7 +838,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) rcu_assign_pointer(bond->curr_active_slave, new_active); } - if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { + if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) { if (old_active) bond_set_slave_inactive_flags(old_active, BOND_SLAVE_NOTIFY_NOW); @@ -876,8 +876,8 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) * resend only if bond is brought up with the affected * bonding modes and the retransmission is enabled */ if (netif_running(bond->dev) && (bond->params.resend_igmp > 0) && - ((USES_PRIMARY(bond->params.mode) && new_active) || - bond->params.mode == BOND_MODE_ROUNDROBIN)) { + ((bond_uses_primary(bond) && new_active) || + BOND_MODE(bond) == BOND_MODE_ROUNDROBIN)) { bond->igmp_retrans = bond->params.resend_igmp; queue_delayed_work(bond->wq, &bond->mcast_work, 1); } @@ -958,7 +958,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev) struct slave *slave; bond_for_each_slave(bond, slave, iter) - if (IS_UP(slave->dev)) + if (bond_slave_is_up(slave)) slave_disable_netpoll(slave); } @@ -1038,6 +1038,7 @@ static void bond_compute_features(struct bonding *bond) if (!bond_has_slaves(bond)) goto done; + vlan_features &= NETIF_F_ALL_FOR_ALL; bond_for_each_slave(bond, slave, iter) { vlan_features = netdev_increment_features(vlan_features, @@ -1084,7 +1085,7 @@ static bool bond_should_deliver_exact_match(struct sk_buff *skb, struct bonding *bond) { if (bond_is_slave_inactive(slave)) { - if (bond->params.mode == BOND_MODE_ALB && + if (BOND_MODE(bond) == BOND_MODE_ALB && skb->pkt_type != PACKET_BROADCAST && skb->pkt_type != PACKET_MULTICAST) return false; @@ -1126,7 +1127,7 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) skb->dev = bond->dev; - if (bond->params.mode == BOND_MODE_ALB && + if (BOND_MODE(bond) == BOND_MODE_ALB && bond->dev->priv_flags & IFF_BRIDGE_PORT && skb->pkt_type == PACKET_HOST) { @@ -1163,6 +1164,35 @@ static void bond_upper_dev_unlink(struct net_device *bond_dev, rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE, GFP_KERNEL); } +static struct slave *bond_alloc_slave(struct bonding *bond) +{ + struct slave *slave = NULL; + + slave = kzalloc(sizeof(struct slave), GFP_KERNEL); + if (!slave) + return NULL; + + if (BOND_MODE(bond) == BOND_MODE_8023AD) { + SLAVE_AD_INFO(slave) = kzalloc(sizeof(struct ad_slave_info), + GFP_KERNEL); + if (!SLAVE_AD_INFO(slave)) { + kfree(slave); + return NULL; + } + } + return slave; +} + +static void bond_free_slave(struct slave *slave) +{ + struct bonding *bond = bond_get_bond_by_slave(slave); + + if (BOND_MODE(bond) == BOND_MODE_8023AD) + kfree(SLAVE_AD_INFO(slave)); + + kfree(slave); +} + /* enslave device <slave> to bond device <master> */ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) { @@ -1269,7 +1299,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (!bond_has_slaves(bond)) { pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address\n", bond_dev->name); - if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { + if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) { bond->params.fail_over_mac = BOND_FOM_ACTIVE; pr_warn("%s: Setting fail_over_mac to active for active-backup mode\n", bond_dev->name); @@ -1290,11 +1320,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond->dev->addr_assign_type == NET_ADDR_RANDOM) bond_set_dev_addr(bond->dev, slave_dev); - new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); + new_slave = bond_alloc_slave(bond); if (!new_slave) { res = -ENOMEM; goto err_undo_flags; } + + new_slave->bond = bond; + new_slave->dev = slave_dev; /* * Set the new_slave's queue_id to be zero. Queue ID mapping * is set via sysfs or module option if desired. @@ -1317,7 +1350,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ether_addr_copy(new_slave->perm_hwaddr, slave_dev->dev_addr); if (!bond->params.fail_over_mac || - bond->params.mode != BOND_MODE_ACTIVEBACKUP) { + BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) { /* * Set slave to master's mac address. The application already * set the master's mac address to that of the first slave @@ -1338,8 +1371,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_restore_mac; } - new_slave->bond = bond; - new_slave->dev = slave_dev; slave_dev->priv_flags |= IFF_BONDING; if (bond_is_lb(bond)) { @@ -1351,10 +1382,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_close; } - /* If the mode USES_PRIMARY, then the following is handled by + /* If the mode uses primary, then the following is handled by * bond_change_active_slave(). */ - if (!USES_PRIMARY(bond->params.mode)) { + if (!bond_uses_primary(bond)) { /* set promiscuity level to new slave */ if (bond_dev->flags & IFF_PROMISC) { res = dev_set_promiscuity(slave_dev, 1); @@ -1377,7 +1408,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) netif_addr_unlock_bh(bond_dev); } - if (bond->params.mode == BOND_MODE_8023AD) { + if (BOND_MODE(bond) == BOND_MODE_8023AD) { /* add lacpdu mc addr to mc list */ u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; @@ -1450,7 +1481,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) new_slave->link == BOND_LINK_DOWN ? "DOWN" : (new_slave->link == BOND_LINK_UP ? "UP" : "BACK")); - if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { + if (bond_uses_primary(bond) && bond->params.primary[0]) { /* if there is a primary slave, remember it */ if (strcmp(bond->params.primary, new_slave->dev->name) == 0) { bond->primary_slave = new_slave; @@ -1458,7 +1489,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) } } - switch (bond->params.mode) { + switch (BOND_MODE(bond)) { case BOND_MODE_ACTIVEBACKUP: bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); @@ -1471,14 +1502,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); /* if this is the first slave */ if (!prev_slave) { - SLAVE_AD_INFO(new_slave).id = 1; + SLAVE_AD_INFO(new_slave)->id = 1; /* Initialize AD with the number of times that the AD timer is called in 1 second * can be called only after the mac address of the bond is set */ bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL); } else { - SLAVE_AD_INFO(new_slave).id = - SLAVE_AD_INFO(prev_slave).id + 1; + SLAVE_AD_INFO(new_slave)->id = + SLAVE_AD_INFO(prev_slave)->id + 1; } bond_3ad_bind_slave(new_slave); @@ -1539,7 +1570,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_compute_features(bond); bond_set_carrier(bond); - if (USES_PRIMARY(bond->params.mode)) { + if (bond_uses_primary(bond)) { block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); @@ -1563,7 +1594,7 @@ err_unregister: netdev_rx_handler_unregister(slave_dev); err_detach: - if (!USES_PRIMARY(bond->params.mode)) + if (!bond_uses_primary(bond)) bond_hw_addr_flush(bond_dev, slave_dev); vlan_vids_del_by_dev(slave_dev, bond_dev); @@ -1585,7 +1616,7 @@ err_close: err_restore_mac: if (!bond->params.fail_over_mac || - bond->params.mode != BOND_MODE_ACTIVEBACKUP) { + BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) { /* XXX TODO - fom follow mode needs to change master's * MAC if this slave's MAC is in use by the bond, or at * least print a warning. @@ -1599,7 +1630,7 @@ err_restore_mtu: dev_set_mtu(slave_dev, new_slave->original_mtu); err_free: - kfree(new_slave); + bond_free_slave(new_slave); err_undo_flags: |