diff options
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r-- | drivers/net/bonding/bond_3ad.c | 185 | ||||
-rw-r--r-- | drivers/net/bonding/bond_alb.c | 146 | ||||
-rw-r--r-- | drivers/net/bonding/bond_alb.h | 8 | ||||
-rw-r--r-- | drivers/net/bonding/bond_debugfs.c | 6 | ||||
-rw-r--r-- | drivers/net/bonding/bond_main.c | 535 | ||||
-rw-r--r-- | drivers/net/bonding/bond_netlink.c | 32 | ||||
-rw-r--r-- | drivers/net/bonding/bond_options.c | 228 | ||||
-rw-r--r-- | drivers/net/bonding/bond_procfs.c | 4 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 3 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs_slave.c | 4 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 22 |
11 files changed, 600 insertions, 573 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 0dfeaf5..ee2c73a 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -20,8 +20,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/skbuff.h> #include <linux/if_ether.h> #include <linux/netdevice.h> @@ -301,8 +299,8 @@ static u16 __get_link_speed(struct port *port) } } - pr_debug("Port %d Received link speed %d update from adapter\n", - port->actor_port_number, speed); + netdev_dbg(slave->bond->dev, "Port %d Received link speed %d update from adapter\n", + port->actor_port_number, speed); return speed; } @@ -329,14 +327,14 @@ static u8 __get_duplex(struct port *port) switch (slave->duplex) { case DUPLEX_FULL: retval = 0x1; - pr_debug("Port %d Received status full duplex update from adapter\n", - port->actor_port_number); + netdev_dbg(slave->bond->dev, "Port %d Received status full duplex update from adapter\n", + port->actor_port_number); break; case DUPLEX_HALF: default: retval = 0x0; - pr_debug("Port %d Received status NOT full duplex update from adapter\n", - port->actor_port_number); + netdev_dbg(slave->bond->dev, "Port %d Received status NOT full duplex update from adapter\n", + port->actor_port_number); break; } } @@ -1079,9 +1077,8 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) /* detect loopback situation */ if (MAC_ADDRESS_EQUAL(&(lacpdu->actor_system), &(port->actor_system))) { - pr_err("%s: An illegal loopback occurred on adapter (%s)\n" + netdev_err(port->slave->bond->dev, "An illegal loopback occurred on adapter (%s)\n" "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", - port->slave->bond->dev->name, port->slave->dev->name); return; } @@ -1269,9 +1266,9 @@ static void ad_port_selection_logic(struct port *port) port->next_port_in_aggregator = NULL; port->actor_port_aggregator_identifier = 0; - pr_debug("Port %d left LAG %d\n", - port->actor_port_number, - temp_aggregator->aggregator_identifier); + netdev_dbg(bond->dev, "Port %d left LAG %d\n", + port->actor_port_number, + temp_aggregator->aggregator_identifier); /* if the aggregator is empty, clear its * parameters, and set it ready to be attached */ @@ -1284,11 +1281,11 @@ static void ad_port_selection_logic(struct port *port) /* meaning: the port was related to an aggregator * but was not on the aggregator port list */ - pr_warn_ratelimited("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n", - port->slave->bond->dev->name, - port->actor_port_number, - port->slave->dev->name, - port->aggregator->aggregator_identifier); + net_warn_ratelimited("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n", + port->slave->bond->dev->name, + port->actor_port_number, + port->slave->dev->name, + port->aggregator->aggregator_identifier); } } /* search on all aggregators for a suitable aggregator for this port */ @@ -1318,9 +1315,9 @@ static void ad_port_selection_logic(struct port *port) port->next_port_in_aggregator = aggregator->lag_ports; port->aggregator->num_of_ports++; aggregator->lag_ports = port; - pr_debug("Port %d joined LAG %d(existing LAG)\n", - port->actor_port_number, - port->aggregator->aggregator_identifier); + netdev_dbg(bond->dev, "Port %d joined LAG %d(existing LAG)\n", + port->actor_port_number, + port->aggregator->aggregator_identifier); /* mark this port as selected */ port->sm_vars |= AD_PORT_SELECTED; @@ -1363,12 +1360,11 @@ static void ad_port_selection_logic(struct port *port) /* mark this port as selected */ port->sm_vars |= AD_PORT_SELECTED; - pr_debug("Port %d joined LAG %d(new LAG)\n", - port->actor_port_number, - port->aggregator->aggregator_identifier); + netdev_dbg(bond->dev, "Port %d joined LAG %d(new LAG)\n", + port->actor_port_number, + port->aggregator->aggregator_identifier); } else { - pr_err("%s: Port %d (on %s) did not find a suitable aggregator\n", - port->slave->bond->dev->name, + netdev_err(bond->dev, "Port %d (on %s) did not find a suitable aggregator\n", port->actor_port_number, port->slave->dev->name); } } @@ -1445,9 +1441,9 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best, break; default: - pr_warn_ratelimited("%s: Impossible agg select mode %d\n", - curr->slave->bond->dev->name, - __get_agg_selection_mode(curr->lag_ports)); + net_warn_ratelimited("%s: Impossible agg select mode %d\n", + curr->slave->bond->dev->name, + __get_agg_selection_mode(curr->lag_ports)); break; } @@ -1539,40 +1535,40 @@ static void ad_agg_selection_logic(struct aggregator *agg) /* if there is new best aggregator, activate it */ if (best) { - pr_debug("best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", - best->aggregator_identifier, best->num_of_ports, - best->actor_oper_aggregator_key, - best->partner_oper_aggregator_key, - best->is_individual, best->is_active); - pr_debug("best ports %p slave %p %s\n", - best->lag_ports, best->slave, - best->slave ? best->slave->dev->name : "NULL"); + netdev_dbg(bond->dev, "best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", + best->aggregator_identifier, best->num_of_ports, + best->actor_oper_aggregator_key, + best->partner_oper_aggregator_key, + best->is_individual, best->is_active); + netdev_dbg(bond->dev, "best ports %p slave %p %s\n", + best->lag_ports, best->slave, + best->slave ? best->slave->dev->name : "NULL"); bond_for_each_slave_rcu(bond, slave, iter) { 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, - agg->actor_oper_aggregator_key, - agg->partner_oper_aggregator_key, - agg->is_individual, agg->is_active); + netdev_dbg(bond->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", + agg->aggregator_identifier, agg->num_of_ports, + agg->actor_oper_aggregator_key, + agg->partner_oper_aggregator_key, + agg->is_individual, agg->is_active); } /* check if any partner replys */ if (best->is_individual) { - pr_warn_ratelimited("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n", - best->slave ? - best->slave->bond->dev->name : "NULL"); + net_warn_ratelimited("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n", + best->slave ? + best->slave->bond->dev->name : "NULL"); } best->is_active = 1; - pr_debug("LAG %d chosen as the active LAG\n", - best->aggregator_identifier); - pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", - best->aggregator_identifier, best->num_of_ports, - best->actor_oper_aggregator_key, - best->partner_oper_aggregator_key, - best->is_individual, best->is_active); + netdev_dbg(bond->dev, "LAG %d chosen as the active LAG\n", + best->aggregator_identifier); + netdev_dbg(bond->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", + best->aggregator_identifier, best->num_of_ports, + best->actor_oper_aggregator_key, + best->partner_oper_aggregator_key, + best->is_individual, best->is_active); /* disable the ports that were related to the former * active_aggregator @@ -1908,13 +1904,13 @@ void bond_3ad_unbind_slave(struct slave *slave) /* if slave is null, the whole port is not initialized */ if (!port->slave) { - pr_warn("Warning: %s: Trying to unbind an uninitialized port on %s\n", - slave->bond->dev->name, slave->dev->name); + netdev_warn(bond->dev, "Trying to unbind an uninitialized port on %s\n", + slave->dev->name); return; } - pr_debug("Unbinding Link Aggregation Group %d\n", - aggregator->aggregator_identifier); + netdev_dbg(bond->dev, "Unbinding Link Aggregation Group %d\n", + aggregator->aggregator_identifier); /* Tell the partner that this port is not suitable for aggregation */ port->actor_oper_port_state &= ~AD_STATE_AGGREGATION; @@ -1949,14 +1945,13 @@ void bond_3ad_unbind_slave(struct slave *slave) * new aggregator */ if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) { - pr_debug("Some port(s) related to LAG %d - replacing with LAG %d\n", - aggregator->aggregator_identifier, - new_aggregator->aggregator_identifier); + netdev_dbg(bond->dev, "Some port(s) related to LAG %d - replacing with LAG %d\n", + aggregator->aggregator_identifier, + new_aggregator->aggregator_identifier); if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) { - pr_info("%s: Removing an active aggregator\n", - aggregator->slave->bond->dev->name); + netdev_info(bond->dev, "Removing an active aggregator\n"); select_new_active_agg = 1; } @@ -1986,8 +1981,7 @@ void bond_3ad_unbind_slave(struct slave *slave) if (select_new_active_agg) ad_agg_selection_logic(__get_first_agg(port)); } else { - pr_warn("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n", - slave->bond->dev->name); + netdev_warn(bond->dev, "unbinding aggregator, and could not find a new aggregator for its ports\n"); } } else { /* in case that the only port related to this @@ -1996,8 +1990,7 @@ void bond_3ad_unbind_slave(struct slave *slave) select_new_active_agg = aggregator->is_active; ad_clear_agg(aggregator); if (select_new_active_agg) { - pr_info("%s: Removing an active aggregator\n", - slave->bond->dev->name); + netdev_info(bond->dev, "Removing an active aggregator\n"); /* select new active aggregator */ temp_aggregator = __get_first_agg(port); if (temp_aggregator) @@ -2006,7 +1999,7 @@ void bond_3ad_unbind_slave(struct slave *slave) } } - pr_debug("Unbinding port %d\n", port->actor_port_number); + netdev_dbg(bond->dev, "Unbinding port %d\n", port->actor_port_number); /* find the aggregator that this port is connected to */ bond_for_each_slave(bond, slave_iter, iter) { @@ -2029,8 +2022,7 @@ void bond_3ad_unbind_slave(struct slave *slave) select_new_active_agg = temp_aggregator->is_active; ad_clear_agg(temp_aggregator); if (select_new_active_agg) { - pr_info("%s: Removing an active aggregator\n", - slave->bond->dev->name); + netdev_info(bond->dev, "Removing an active aggregator\n"); /* select new active aggregator */ ad_agg_selection_logic(__get_first_agg(port)); } @@ -2081,8 +2073,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work) /* select the active aggregator for the bond */ if (port) { if (!port->slave) { - pr_warn_ratelimited("%s: Warning: bond's first port is uninitialized\n", - bond->dev->name); + net_warn_ratelimited("%s: Warning: bond's first port is uninitialized\n", + bond->dev->name); goto re_arm; } @@ -2096,7 +2088,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) bond_for_each_slave_rcu(bond, slave, iter) { port = &(SLAVE_AD_INFO(slave)->port); if (!port->slave) { - pr_warn_ratelimited("%s: Warning: Found an uninitialized port\n", + net_warn_ratelimited("%s: Warning: Found an uninitialized port\n", bond->dev->name); goto re_arm; } @@ -2158,16 +2150,16 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, port = &(SLAVE_AD_INFO(slave)->port); if (!port->slave) { - pr_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n", - slave->dev->name, slave->bond->dev->name); + net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n", + slave->dev->name, slave->bond->dev->name); return ret; } switch (lacpdu->subtype) { case AD_TYPE_LACPDU: ret = RX_HANDLER_CONSUMED; - pr_debug("Received LACPDU on port %d\n", - port->actor_port_number); + netdev_dbg(slave->bond->dev, "Received LACPDU on port %d\n", + port->actor_port_number); /* Protect against concurrent state machines */ __get_state_machine_lock(port); ad_rx_machine(lacpdu, port); @@ -2182,20 +2174,20 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, switch (((struct bond_marker *)lacpdu)->tlv_type) { case AD_MARKER_INFORMATION_SUBTYPE: - pr_debug("Received Marker Information on port %d\n", - port->actor_port_number); + netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n", + port->actor_port_number); ad_marker_info_received((struct bond_marker *)lacpdu, port); break; case AD_MARKER_RESPONSE_SUBTYPE: - pr_debug("Received Marker Response on port %d\n", - port->actor_port_number); + netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n", + port->actor_port_number); ad_marker_response_received((struct bond_marker *)lacpdu, port); break; default: - pr_debug("Received an unknown Marker subtype on slot %d\n", - port->actor_port_number); + netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n", + port->actor_port_number); } } } @@ -2216,8 +2208,8 @@ void bond_3ad_adapter_speed_changed(struct slave *slave) /* if slave is null, the whole port is not initialized */ if (!port->slave) { - pr_warn("Warning: %s: speed changed for uninitialized port on %s\n", - slave->bond->dev->name, slave->dev->name); + netdev_warn(slave->bond->dev, "speed changed for uninitialized port on %s\n", + slave->dev->name); return; } @@ -2226,7 +2218,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave) port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS; port->actor_oper_port_key = port->actor_admin_port_key |= (__get_link_speed(port) << 1); - pr_debug("Port %d changed speed\n", port->actor_port_number); + netdev_dbg(slave->bond->dev, "Port %d changed speed\n", port->actor_port_number); /* there is no need to reselect a new aggregator, just signal the * state machines to reinitialize */ @@ -2249,8 +2241,8 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) /* if slave is null, the whole port is not initialized */ if (!port->slave) { - pr_warn("%s: Warning: duplex changed for uninitialized port on %s\n", - slave->bond->dev->name, slave->dev->name); + netdev_warn(slave->bond->dev, "duplex changed for uninitialized port on %s\n", + slave->dev->name); return; } @@ -2259,7 +2251,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; port->actor_oper_port_key = port->actor_admin_port_key |= __get_duplex(port); - pr_debug("Port %d changed duplex\n", port->actor_port_number); + netdev_dbg(slave->bond->dev, "Port %d changed duplex\n", port->actor_port_number); /* there is no need to reselect a new aggregator, just signal the * state machines to reinitialize */ @@ -2283,8 +2275,8 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) /* if slave is null, the whole port is not initialized */ if (!port->slave) { - pr_warn("Warning: %s: link status changed for uninitialized port on %s\n", - slave->bond->dev->name, slave->dev->name); + netdev_warn(slave->bond->dev, "link status changed for uninitialized port on %s\n", + slave->dev->name); return; } @@ -2311,9 +2303,9 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) port->actor_oper_port_key = (port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS); } - pr_debug("Port %d changed link status to %s\n", - port->actor_port_number, - link == BOND_LINK_UP ? "UP" : "DOWN"); + netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n", + port->actor_port_number, + link == BOND_LINK_UP ? "UP" : "DOWN"); /* there is no need to reselect a new aggregator, just signal the * state machines to reinitialize */ @@ -2427,8 +2419,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) int agg_id; if (__bond_3ad_get_active_agg_info(bond, &ad_info)) { - pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n", - dev->name); + netdev_dbg(dev, "__bond_3ad_get_active_agg_info failed\n"); goto err_free; } @@ -2436,7 +2427,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) agg_id = ad_info.aggregator_id; if (slaves_in_agg == 0) { - pr_debug("%s: Error: active aggregator is empty\n", dev->name); + netdev_dbg(dev, "active aggregator is empty\n"); goto err_free; } @@ -2462,8 +2453,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) } if (slave_agg_no >= 0) { - pr_err("%s: Error: Couldn't find a slave to tx on for aggregator ID %d\n", - dev->name, agg_id); + netdev_err(dev, "Couldn't find a slave to tx on for aggregator ID %d\n", + agg_id); goto err_free; } diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 76c0dad..95dd1f5 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -19,8 +19,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/skbuff.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -202,6 +200,7 @@ static int tlb_initialize(struct bonding *bond) static void tlb_deinitialize(struct bonding *bond) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); + struct tlb_up_slave *arr; _lock_tx_hashtbl_bh(bond); @@ -209,6 +208,10 @@ static void tlb_deinitialize(struct bonding *bond) bond_info->tx_hashtbl = NULL; _unlock_tx_hashtbl_bh(bond); + + arr = rtnl_dereference(bond_info->slave_arr); + if (arr) + kfree_rcu(arr, rcu); } static long long compute_gap(struct slave *slave) @@ -369,7 +372,7 @@ static int rlb_arp_recv(const struct sk_buff *skb, struct bonding *bond, if (arp->op_code == htons(ARPOP_REPLY)) { /* update rx hash table for this ARP */ rlb_update_entry_from_arp(bond, arp); - pr_debug("Server received an ARP Reply from client\n"); + netdev_dbg(bond->dev, "Server received an ARP Reply from client\n"); } out: return RX_HANDLER_ANOTHER; @@ -448,11 +451,13 @@ static struct slave *__rlb_next_rx_slave(struct bonding *bond) */ static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[]) { - if (!bond->curr_active_slave) + struct slave *curr_active = bond_deref_active_protected(bond); + + if (!curr_active) return; if (!bond->alb_info.primary_is_promisc) { - if (!dev_set_promiscuity(bond->curr_active_slave->dev, 1)) + if (!dev_set_promiscuity(curr_active->dev, 1)) bond->alb_info.primary_is_promisc = 1; else bond->alb_info.primary_is_promisc = 0; @@ -460,7 +465,7 @@ static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[]) bond->alb_info.rlb_promisc_timeout_counter = 0; - alb_send_learning_packets(bond->curr_active_slave, addr, true); + alb_send_learning_packets(curr_active, addr, true); } /* slave being removed should not be active at this point @@ -509,7 +514,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave) write_lock_bh(&bond->curr_slave_lock); - if (slave != bond->curr_active_slave) + if (slave != bond_deref_active_protected(bond)) rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr); write_unlock_bh(&bond->curr_slave_lock); @@ -533,8 +538,8 @@ static void rlb_update_client(struct rlb_client_info *client_info) client_info->slave->dev->dev_addr, client_info->mac_dst); if (!skb) { - pr_err("%s: Error: failed to create an ARP packet\n", - client_info->slave->bond->dev->name); + netdev_err(client_info->slave->bond->dev, + "failed to create an ARP packet\n"); continue; } @@ -543,8 +548,8 @@ static void rlb_update_client(struct rlb_client_info *client_info) if (client_info->vlan_id) { skb = vlan_put_tag(skb, htons(ETH_P_8021Q), client_info->vlan_id); if (!skb) { - pr_err("%s: Error: failed to insert VLAN tag\n", - client_info->slave->bond->dev->name); + netdev_err(client_info->slave->bond->dev, + "failed to insert VLAN tag\n"); continue; } } @@ -628,8 +633,7 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip) client_info = &(bond_info->rx_hashtbl[hash_index]); if (!client_info->slave) { - pr_err("%s: Error: found a client with no channel in the client's hash table\n", - bond->dev->name); + netdev_err(bond->dev, "found a client with no channel in the client's hash table\n"); continue; } /*update all clients using this src_ip, that are not assigned @@ -684,7 +688,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon * move the old client to primary (curr_active_slave) so * that the new client can be assigned to this entry. */ - if (bond->curr_active_slave && + if (curr_active_slave && client_info->slave != curr_active_slave) { client_info->slave = curr_active_slave; rlb_update_client(client_info); @@ -765,7 +769,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) tx_slave = rlb_choose_channel(skb, bond); if (tx_slave) ether_addr_copy(arp->mac_src, tx_slave->dev->dev_addr); - pr_debug("Server sent ARP Reply packet\n"); + netdev_dbg(bond->dev, "Server sent ARP Reply packet\n"); } else if (arp->op_code == htons(ARPOP_REQUEST)) { /* Create an entry in the rx_hashtbl for this client as a * place holder. @@ -785,7 +789,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) * updated with their assigned mac. */ rlb_req_update_subnet_clients(bond, arp->ip_src); - pr_debug("Server sent ARP Request packet\n"); + netdev_dbg(bond->dev, "Server sent ARP Request packet\n"); } return tx_slave; @@ -1024,8 +1028,7 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[], if (vid) { skb = vlan_put_tag(skb, vlan_proto, vid); if (!skb) { - pr_err("%s: Error: failed to insert VLAN tag\n", - slave->bond->dev->name); + netdev_err(slave->bond->dev, "failed to insert VLAN tag\n"); return; } } @@ -1039,7 +1042,7 @@ 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]; + struct bond_vlan_tag *tags; /* send untagged */ alb_send_lp_vid(slave, mac_addr, 0, 0); @@ -1067,10 +1070,12 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], * 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); + tags = bond_verify_device_path(bond->dev, upper, 0); + if (IS_ERR_OR_NULL(tags)) + BUG(); alb_send_lp_vid(slave, upper->dev_addr, tags[0].vlan_proto, tags[0].vlan_id); + kfree(tags); } } rcu_read_unlock(); @@ -1091,9 +1096,8 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[]) memcpy(s_addr.sa_data, addr, dev->addr_len); s_addr.sa_family = dev->type; if (dev_set_mac_address(dev, &s_addr)) { - pr_err("%s: Error: dev_set_mac_address of dev %s failed!\n" - "ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n", - slave->bond->dev->name, dev->name); + netdev_err(slave->bond->dev, "dev_set_mac_address of dev %s failed! ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n", + dev->name); return -EOPNOTSUPP; } return 0; @@ -1221,7 +1225,7 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla */ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave) { - struct slave *has_bond_addr = bond->curr_active_slave; + struct slave *has_bond_addr = rcu_access_pointer(bond->curr_active_slave); struct slave *tmp_slave1, *free_mac_slave = NULL; struct list_head *iter; @@ -1267,13 +1271,12 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav if (free_mac_slave) { alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr); - pr_warn("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n", - bond->dev->name, slave->dev->name, - free_mac_slave->dev->name); + netdev_warn(bond->dev, "the hw address of slave %s is in use by the bond; giving it the hw address of %s\n", + slave->dev->name, free_mac_slave->dev->name); } else if (has_bond_addr) { - pr_err("%s: Error: the hw address of slave %s is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened)\n", - bond->dev->name, slave->dev->name); + netdev_err(bond->dev, "the hw address of slave %s is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened)\n", + slave->dev->name); return -EFAULT; } @@ -1406,9 +1409,39 @@ out: return NETDEV_TX_OK; } +static int bond_tlb_update_slave_arr(struct bonding *bond, + struct slave *skipslave) +{ + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); + struct slave *tx_slave; + struct list_head *iter; + struct tlb_up_slave *new_arr, *old_arr; + + new_arr = kzalloc(offsetof(struct tlb_up_slave, arr[bond->slave_cnt]), + GFP_ATOMIC); + if (!new_arr) + return -ENOMEM; + + bond_for_each_slave(bond, tx_slave, iter) { + if (!bond_slave_can_tx(tx_slave)) + continue; + if (skipslave == tx_slave) + continue; + new_arr->arr[new_arr->count++] = tx_slave; + } + + old_arr = rtnl_dereference(bond_info->slave_arr); + rcu_assign_pointer(bond_info->slave_arr, new_arr); + if (old_arr) + kfree_rcu(old_arr, rcu); + + return 0; +} + int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); struct ethhdr *eth_data; struct slave *tx_slave = NULL; u32 hash_index; @@ -1429,12 +1462,12 @@ int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev) hash_index & 0xFF, skb->len); } else { - struct list_head *iter; - int idx = hash_index % bond->slave_cnt; + struct tlb_up_slave *slaves; - bond_for_each_slave_rcu(bond, tx_slave, iter) - if (--idx < 0) - break; + slaves = rcu_dereference(bond_info->slave_arr); + if (slaves && slaves->count) + tx_slave = slaves->arr[hash_index % + slaves->count]; } break; } @@ -1575,7 +1608,7 @@ void bond_alb_monitor(struct work_struct *work) * use mac of the slave device. * In RLB mode, we always use strict matches. */ - strict_match = (slave != bond->curr_active_slave || + strict_match = (slave != rcu_access_pointer(bond->curr_active_slave) || bond_info->rlb_enabled); alb_send_learning_packets(slave, slave->dev->dev_addr, strict_match); @@ -1593,7 +1626,7 @@ void bond_alb_monitor(struct work_struct *work) bond_for_each_slave_rcu(bond, slave, iter) { tlb_clear_slave(bond, slave, 1); - if (slave == bond->curr_active_slave) { + if (slave == rcu_access_pointer(bond->curr_active_slave)) { SLAVE_TLB_INFO(slave).load = bond_info->unbalanced_load / BOND_TLB_REBALANCE_INTERVAL; @@ -1625,7 +1658,8 @@ void bond_alb_monitor(struct work_struct *work) * because a slave was disabled then * it can now leave promiscuous mode. */ - dev_set_promiscuity(bond->curr_active_slave->dev, -1); + dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev, + -1); bond_info->primary_is_promisc = 0; rtnl_unlock(); @@ -1698,6 +1732,11 @@ void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave) bond->alb_info.rx_slave = NULL; rlb_clear_slave(bond, slave); } + + if (bond_is_nondyn_tlb(bond)) + if (bond_tlb_update_slave_arr(bond, slave)) + pr_err("Failed to build slave-array for TLB mode.\n"); + } /* Caller must hold bond lock for read */ @@ -1721,6 +1760,11 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char */ } } + + if (bond_is_nondyn_tlb(bond)) { + if (bond_tlb_update_slave_arr(bond, NULL)) + pr_err("Failed to build slave-array for TLB mode.\n"); + } } /** @@ -1742,17 +1786,21 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave __acquires(&bond->curr_slave_lock) { struct slave *swap_slave; + struct slave *curr_active; - if (bond->curr_active_slave == new_slave) + curr_active = rcu_dereference_protected(bond->curr_active_slave, + !new_slave || + lockdep_is_held(&bond->curr_slave_lock)); + if (curr_active == new_slave) return; - if (bond->curr_active_slave && bond->alb_info.primary_is_promisc) { - dev_set_promiscuity(bond->curr_active_slave->dev, -1); + if (curr_active && bond->alb_info.primary_is_promisc) { + dev_set_promiscuity(curr_active->dev, -1); bond->alb_info.primary_is_promisc = 0; bond->alb_info.rlb_promisc_timeout_counter = 0; } - swap_slave = bond->curr_active_slave; + swap_slave = curr_active; rcu_assign_pointer(bond->curr_active_slave, new_slave); if (!new_slave || !bond_has_slaves(bond)) @@ -1818,6 +1866,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) { struct bonding *bond = netdev_priv(bond_dev); struct sockaddr *sa = addr; + struct slave *curr_active; struct slave *swap_slave; int res; @@ -1834,23 +1883,24 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) * Otherwise we'll need to pass the new address to it and handle * duplications. */ - if (!bond->curr_active_slave) + curr_active = rtnl_dereference(bond->curr_active_slave); + if (!curr_active) return 0; swap_slave = bond_slave_has_mac(bond, bond_dev->dev_addr); if (swap_slave) { - alb_swap_mac_addr(swap_slave, bond->curr_active_slave); - alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave); + alb_swap_mac_addr(swap_slave, curr_active); + alb_fasten_mac_swap(bond, swap_slave, curr_active); } else { - alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr); + alb_set_slave_mac_addr(curr_active, bond_dev->dev_addr); read_lock(&bond->lock); - alb_send_learning_packets(bond->curr_active_slave, + alb_send_learning_packets(curr_active, bond_dev->dev_addr, false); if (bond->alb_info.rlb_enabled) { /* inform clients mac address has changed */ - rlb_req_update_slave_clients(bond, bond->curr_active_slave); + rlb_req_update_slave_clients(bond, curr_active); } read_unlock(&bond->lock); } diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h index 5fc76c0..aaeac61 100644 --- a/drivers/net/bonding/bond_alb.h +++ b/drivers/net/bonding/bond_alb.h @@ -139,12 +139,20 @@ struct tlb_slave_info { */ }; +struct tlb_up_slave { + unsigned int count; + struct rcu_head rcu; + struct slave *arr[0]; +}; + struct alb_bond_info { struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */ spinlock_t tx_hashtbl_lock; u32 unbalanced_load; int tx_rebalance_counter; int lp_counter; + /* -------- non-dynamic tlb mode only ---------*/ + struct tlb_up_slave __rcu *slave_arr; /* Up slaves */ /* -------- rlb parameters -------- */ int rlb_enabled; struct rlb_client_info *rx_hashtbl; /* Receive hash table */ diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c index 658e761..280971b 100644 --- a/drivers/net/bonding/bond_debugfs.c +++ b/drivers/net/bonding/bond_debugfs.c @@ -69,8 +69,7 @@ void bond_debug_register(struct bonding *bond) debugfs_create_dir(bond->dev->name, bonding_debug_root); if (!bond->debug_dir) { - pr_warn("%s: Warning: failed to register to debugfs\n", - bond->dev->name); + netdev_warn(bond->dev, "failed to register to debugfs\n"); return; } @@ -98,8 +97,7 @@ void bond_debug_reregister(struct bonding *bond) if (d) { bond->debug_dir = d; } else { - pr_warn("%s: Warning: failed to reregister, so just unregister old one\n", - bond->dev->name); + netdev_warn(bond->dev, "failed to reregister, so just unregister old one\n"); bond_debug_unregister(bond); } } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 701f86c..f0f5eab 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -31,8 +31,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/kernel.h> #include <linux/module.h> #include <linux/types.h> @@ -498,11 +496,10 @@ static int bond_set_promiscuity(struct bonding *bond, int inc) int err = 0; if (bond_uses_primary(bond)) { - /* write lock already acquired */ - if (bond->curr_active_slave) { - err = dev_set_promiscuity(bond->curr_active_slave->dev, - inc); - } + struct slave *curr_active = rtnl_dereference(bond->curr_active_slave); + + if (curr_active) + err = dev_set_promiscuity(curr_active->dev, inc); } else { struct slave *slave; @@ -524,11 +521,10 @@ static int bond_set_allmulti(struct bonding *bond, int inc) int err = 0; if (bond_uses_primary(bond)) { - /* write lock already acquired */ - if (bond->curr_active_slave) { - err = dev_set_allmulti(bond->curr_active_slave->dev, - inc); - } + struct slave *curr_active = rtnl_dereference(bond->curr_active_slave); + + if (curr_active) + err = dev_set_allmulti(curr_active->dev, inc); } else { struct slave *slave; @@ -629,8 +625,8 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active, static void bond_set_dev_addr(struct net_device *bond_dev, struct net_device *slave_dev) { - pr_debug("bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n", - bond_dev, slave_dev, slave_dev->addr_len); + netdev_dbg(bond_dev, "bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n", + bond_dev, slave_dev, slave_dev->addr_len); memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len); bond_dev->addr_assign_type = NET_ADDR_STOLEN; call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); @@ -684,8 +680,8 @@ static void bond_do_fail_over_mac(struct bonding *bond, rv = dev_set_mac_address(new_active->dev, &saddr); if (rv) { - pr_err("%s: Error %d setting MAC of slave %s\n", - bond->dev->name, -rv, new_active->dev->name); + netdev_err(bond->dev, "Error %d setting MAC of slave %s\n", + -rv, new_active->dev->name); goto out; } @@ -697,14 +693,14 @@ static void bond_do_fail_over_mac(struct bonding *bond, rv = dev_set_mac_address(old_active->dev, &saddr); if (rv) - pr_err("%s: Error %d setting MAC of slave %s\n", - bond->dev->name, -rv, new_active->dev->name); + netdev_err(bond->dev, "Error %d setting MAC of slave %s\n", + -rv, new_active->dev->name); out: write_lock_bh(&bond->curr_slave_lock); break; default: - pr_err("%s: bond_do_fail_over_mac impossible: bad policy %d\n", - bond->dev->name, bond->params.fail_over_mac); + netdev_err(bond->dev, "bond_do_fail_over_mac impossible: bad policy %d\n", + bond->params.fail_over_mac); break; } @@ -713,7 +709,7 @@ out: static bool bond_should_change_active(struct bonding *bond) { struct slave *prim = bond->primary_slave; - struct slave *curr = bond->curr_active_slave; + struct slave *curr = bond_deref_active_protected(bond); if (!prim || !curr || curr->link != BOND_LINK_UP) return true; @@ -765,8 +761,8 @@ static bool bond_should_notify_peers(struct bonding *bond) slave = rcu_dereference(bond->curr_active_slave); rcu_read_unlock(); - pr_debug("bond_should_notify_peers: bond %s slave %s\n", - bond->dev->name, slave ? slave->dev->name : "NULL"); + netdev_dbg(bond->dev, "bond_should_notify_peers: slave %s\n", + slave ? slave->dev->name : "NULL"); if (!slave || !bond->send_peer_notif || test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state)) @@ -792,7 +788,11 @@ static bool bond_should_notify_peers(struct bonding *bond) */ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) { - struct slave *old_active = bond->curr_active_slave; + struct slave *old_active; + + old_active = rcu_dereference_protected(bond->curr_active_slave, + !new_active || + lockdep_is_held(&bond->curr_slave_lock)); if (old_active == new_active) return; @@ -802,9 +802,9 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) if (new_active->link == BOND_LINK_BACK) { 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); + netdev_info(bond->dev, "making interface %s the new active one %d ms earlier\n", + new_active->dev->name, + (bond->params.updelay - new_active->delay) * bond->params.miimon); } new_active->delay = 0; @@ -817,8 +817,8 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP); } else { if (bond_uses_primary(bond)) { - pr_info("%s: making interface %s the new active one\n", - bond->dev->name, new_active->dev->name); + netdev_info(bond->dev, "making interface %s the new active one\n", + new_active->dev->name); } } } @@ -900,18 +900,16 @@ void bond_select_active_slave(struct bonding *bond) int rv; best_slave = bond_find_best_slave(bond); - if (best_slave != bond->curr_active_slave) { + if (best_slave != bond_deref_active_protected(bond)) { bond_change_active_slave(bond, best_slave); rv = bond_set_carrier(bond); if (!rv) return; if (netif_carrier_ok(bond->dev)) { - pr_info("%s: first active interface up!\n", - bond->dev->name); + netdev_info(bond->dev, "first active interface up!\n"); } else { - pr_info("%s: now running without any active interface!\n", - bond->dev->name); + netdev_info(bond->dev, "now running without any active interface!\n"); } } } @@ -1001,12 +999,6 @@ static netdev_features_t bond_fix_features(struct net_device *dev, netdev_features_t mask; struct slave *slave; - if (!bond_has_slaves(bond)) { - /* Disable adding VLANs to empty bond. But why? --mq */ - features |= NETIF_F_VLAN_CHALLENGED; - return features; - } - mask = features; features &= ~NETIF_F_ONE_FOR_ALL; features |= NETIF_F_ALL_FOR_ALL; @@ -1214,36 +1206,38 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (!bond->params.use_carrier && slave_dev->ethtool_ops->get_link == NULL && slave_ops->ndo_do_ioctl == NULL) { - pr_warn("%s: Warning: no link monitoring support for %s\n", - bond_dev->name, slave_dev->name); + netdev_warn(bond_dev, "no link monitoring support for %s\n", + slave_dev->name); } /* already enslaved */ if (slave_dev->flags & IFF_SLAVE) { - pr_debug("Error: Device was already enslaved\n"); + netdev_dbg(bond_dev, "Error: Device was already enslaved\n"); return -EBUSY; } if (bond_dev == slave_dev) { - pr_err("%s: cannot enslave bond to itself.\n", bond_dev->name); + netdev_err(bond_dev, "cannot enslave bond to itself.\n"); return -EPERM; } /* vlan challenged mutual exclusion */ /* no need to lock since we're protected by rtnl_lock */ if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { - pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); + netdev_dbg(bond_dev, "%s is NETIF_F_VLAN_CHALLENGED\n", + slave_dev->name); if (vlan_uses_dev(bond_dev)) { - pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n", - bond_dev->name, slave_dev->name, bond_dev->name); + netdev_err(bond_dev, "Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n", + slave_dev->name, bond_dev->name); return -EPERM; } else { - pr_warn("%s: Warning: enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n", - bond_dev->name, slave_dev->name, - slave_dev->name, bond_dev->name); + netdev_warn(bond_dev, "enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n", + slave_dev->name, slave_dev->name, + bond_dev->name); } } else { - pr_debug("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); + netdev_dbg(bond_dev, "%s is !NETIF_F_VLAN_CHALLENGED\n", + slave_dev->name); } /* @@ -1253,8 +1247,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) * enslaving it; the old ifenslave will not. */ if ((slave_dev->flags & IFF_UP)) { - pr_err("%s is up - this may be due to an out of date ifenslave\n", - slave_dev->name); + netdev_err(bond_dev, "%s is up - this may be due to an out of date ifenslave\n", + slave_dev->name); res = -EPERM; goto err_undo_flags; } @@ -1268,16 +1262,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) */ if (!bond_has_slaves(bond)) { if (bond_dev->type != slave_dev->type) { - pr_debug("%s: change device type from %d to %d\n", - bond_dev->name, - bond_dev->type, slave_dev->type); + netdev_dbg(bond_dev, "change device type from %d to %d\n", + bond_dev->type, slave_dev->type); res = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, bond_dev); res = notifier_to_errno(res); if (res) { - pr_err("%s: refused to change device type\n", - bond_dev->name); + netdev_err(bond_dev, "refused to change device type\n"); res = -EBUSY; goto err_undo_flags; } @@ -1297,26 +1289,24 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_dev); } } else if (bond_dev->type != slave_dev->type) { - pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it\n", - slave_dev->name, slave_dev->type, bond_dev->type); + netdev_err(bond_dev, "%s ether type (%d) is different from other slaves (%d), can not enslave it\n", + slave_dev->name, slave_dev->type, bond_dev->type); res = -EINVAL; goto err_undo_flags; } if (slave_ops->ndo_set_mac_address == NULL) { - 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_MODE(bond) == BOND_MODE_ACTIVEBACKUP) { + netdev_warn(bond_dev, "The slave device specified does not support setting the MAC address\n"); + if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP && + bond->params.fail_over_mac != BOND_FOM_ACTIVE) { + if (!bond_has_slaves(bond)) { 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); + netdev_warn(bond_dev, "Setting fail_over_mac to active for active-backup mode\n"); + } else { + netdev_err(bond_dev, "The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n"); + res = -EOPNOTSUPP; + goto err_undo_flags; } - } else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) { - pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n", - bond_dev->name); - res = -EOPNOTSUPP; - goto err_undo_flags; } } @@ -1346,7 +1336,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) new_slave->original_mtu = slave_dev->mtu; res = dev_set_mtu(slave_dev, bond->dev->mtu); if (res) { - pr_debug("Error %d calling dev_set_mtu\n", res); + netdev_dbg(bond_dev, "Error %d calling dev_set_mtu\n", res); goto err_free; } @@ -1367,7 +1357,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) addr.sa_family = slave_dev->type; res = dev_set_mac_address(slave_dev, &addr); if (res) { - pr_debug("Error %d calling set_mac_address\n", res); + netdev_dbg(bond_dev, "Error %d calling set_mac_address\n", res); goto err_restore_mtu; } } @@ -1375,7 +1365,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* open the slave since the application closed it */ res = dev_open(slave_dev); if (res) { - pr_debug("Opening slave %s failed\n", slave_dev->name); + netdev_dbg(bond_dev, "Opening slave %s failed\n", slave_dev->name); goto err_restore_mac; } @@ -1425,8 +1415,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) res = vlan_vids_add_by_dev(slave_dev, bond_dev); if (res) { - pr_err("%s: Error: Couldn't add bond vlan ids to %s\n", - bond_dev->name, slave_dev->name); + netdev_err(bond_dev, "Couldn't add bond vlan ids to %s\n", + slave_dev->name); goto err_close; } @@ -1455,12 +1445,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) * supported); thus, we don't need to change * the messages for netif_carrier. */ - pr_warn("%s: Warning: MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details\n", - bond_dev->name, slave_dev->name); + netdev_warn(bond_dev, "MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details\n", + slave_dev->name); } else if (link_reporting == -1) { /* unable get link status using mii/ethtool */ - pr_warn("%s: Warning: can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface\n", - bond_dev->name, slave_dev->name); + netdev_warn(bond_dev, "can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface\n", + slave_dev->name); } } @@ -1485,9 +1475,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (new_slave->link != BOND_LINK_DOWN) new_slave->last_link_up = jiffies; - pr_debug("Initial state of slave_dev is BOND_LINK_%s\n", - new_slave->link == BOND_LINK_DOWN ? "DOWN" : - (new_slave->link == BOND_LINK_UP ? "UP" : "BACK")); + netdev_dbg(bond_dev, "Initial state of slave_dev is BOND_LINK_%s\n", + new_slave->link == BOND_LINK_DOWN ? "DOWN" : + (new_slave->link == BOND_LINK_UP ? "UP" : "BACK")); if (bond_uses_primary(bond) && bond->params.primary[0]) { /* if there is a primary slave, remember it */ @@ -1528,7 +1518,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); break; default: - pr_debug("This slave is always active in trunk mode\n"); + netdev_dbg(bond_dev, "This slave is always active in trunk mode\n"); /* always active in trunk mode */ bond_set_active_slave(new_slave); @@ -1537,7 +1527,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) * anyway (it holds no special properties of the bond device), * so we can change it without calling change_active_interface() */ - if (!bond->curr_active_slave && new_slave->link == BOND_LINK_UP) + if (!rcu_access_pointer(bond->curr_active_slave) && + new_slave->link == BOND_LINK_UP) rcu_assign_pointer(bond->curr_active_slave, new_slave); break; @@ -1547,8 +1538,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) slave_dev->npinfo = bond->dev->npinfo; if (slave_dev->npinfo) { if (slave_enable_netpoll(new_slave)) { - pr_info("Error, %s: master_dev is using netpoll, but new slave device does not support netpoll\n", - bond_dev->name); + netdev_info(bond_dev, "master_dev is using netpoll, but new slave device does not support netpoll\n"); res = -EBUSY; goto err_detach; } @@ -1558,19 +1548,19 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) res = netdev_rx_handler_register(slave_dev, bond_handle_frame, new_slave); if (res) { - pr_debug("Error %d calling netdev_rx_handler_register\n", res); + netdev_dbg(bond_dev, "Error %d calling netdev_rx_handler_register\n", res); goto err_detach; } res = bond_master_upper_dev_link(bond_dev, slave_dev, new_slave); if (res) { - pr_debug("Error %d calling bond_master_upper_dev_link\n", res); + netdev_dbg(bond_dev, "Error %d calling bond_master_upper_dev_link\n", res); goto err_unregister; } res = bond_sysfs_slave_add(new_slave); if (res) { - pr_debug("Error %d calling bond_sysfs_slave_add\n", res); + netdev_dbg(bond_dev, "Error %d calling bond_sysfs_slave_add\n", res); goto err_upper_unlink; } @@ -1586,10 +1576,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) unblock_netpoll_tx(); } - pr_info("%s: Enslaving %s as %s interface with %s link\n", - bond_dev->name, slave_dev->name, - bond_is_active_slave(new_slave) ? "an active" : "a backup", - new_slave->link != BOND_LINK_DOWN ? "an up" : "a down"); + netdev_info(bond_dev, "Enslaving %s as %s interface with %s link\n", + slave_dev->name, + bond_is_active_slave(new_slave) ? "an active" : "a backup", + new_slave->link != BOND_LINK_DOWN ? "an up" : "a down"); /* enslave is successful */ return 0; @@ -1608,7 +1598,7 @@ err_detach: vlan_vids_del_by_dev(slave_dev, bond_dev); if (bond->primary_slave == new_slave) bond->primary_slave = NULL; - if (bond->curr_active_slave == new_slave) { + if (rcu_access_pointer(bond->curr_active_slave) == new_slave) { block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_change_active_slave(bond, NULL); @@ -1674,8 +1664,8 @@ static int __bond_release_one(struct net_device *bond_dev, /* slave is not a slave or master is not master of this slave */ if (!(slave_dev->flags & IFF_SLAVE) || !netdev_has_upper_dev(slave_dev, bond_dev)) { - pr_err("%s: Error: cannot release %s\n", - bond_dev->name, slave_dev->name); + netdev_err(bond_dev, "cannot release %s\n", + slave_dev->name); return -EINVAL; } @@ -1684,8 +1674,8 @@ static int __bond_release_one(struct net_device *bond_dev, slave = bond_get_slave_by_dev(bond, slave_dev); if (!slave) { /* not a slave of this bond */ - pr_info("%s: %s not enslaved\n", - bond_dev->name, slave_dev->name); + netdev_info(bond_dev, "%s not enslaved\n", + slave_dev->name); unblock_netpoll_tx(); return -EINVAL; } @@ -1705,23 +1695,21 @@ static int __bond_release_one(struct net_device *bond_dev, write_unlock_bh(&bond->lock); - pr_info("%s: Releasing %s interface %s\n", - bond_dev->name, - bond_is_active_slave(slave) ? "active" : "backup", - slave_dev->name); + netdev_info(bond_dev, "Releasing %s interface %s\n", + bond_is_active_slave(slave) ? "active" : "backup", + slave_dev->name); - oldcurrent = bond->curr_active_slave; + oldcurrent = rcu_access_pointer(bond->curr_active_slave); - bond->current_arp_slave = NULL; + RCU_INIT_POINTER(bond->current_arp_slave, NULL); if (!all && (!bond->params.fail_over_mac || BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)) { if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) && bond_has_slaves(bond)) - pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s - set the HWaddr of %s to a different address to avoid conflicts\n", - bond_dev->name, slave_dev->name, - slave->perm_hwaddr, - bond_dev->name, slave_dev->name); + netdev_warn(bond_dev, "the permanent HWaddr of %s - %pM - is still in use by %s - set the HWaddr of %s to a different address to avoid conflicts\n", + slave_dev->name, slave->perm_hwaddr, + bond_dev->name, slave_dev->name); } if (bond->primary_slave == slave) @@ -1760,13 +1748,6 @@ static int __bond_release_one(struct net_device *bond_dev, if (!bond_has_slaves(bond)) { bond_set_carrier(bond); eth_hw_addr_random(bond_dev); - - if (vlan_uses_dev(bond_dev)) { - pr_warn("%s: Warning: clearing HW address of %s while it still has VLANs\n", - bond_dev->name, bond_dev->name); - pr_warn("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs\n", - bond_dev->name); - } } unblock_netpoll_tx(); @@ -1781,8 +1762,8 @@ static int __bond_release_one(struct net_device *bond_dev, bond_compute_features(bond); if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) && (old_features & NETIF_F_VLAN_CHALLENGED)) - pr_info("%s: last VLAN challenged slave %s left bond %s - VLAN blocking is removed\n", - bond_dev->name, slave_dev->name, bond_dev->name); + netdev_info(bond_dev, "last VLAN challenged slave %s left bond %s - VLAN blocking is removed\n", + slave_dev->name, bond_dev->name); /* must do this from outside any spinlocks */ vlan_vids_del_by_dev(slave_dev, bond_dev); @@ -1849,8 +1830,8 @@ static int bond_release_and_destroy(struct net_device *bond_dev, ret = bond_release(bond_dev, slave_dev); if (ret == 0 && !bond_has_slaves(bond)) { bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; - pr_info("%s: Destroying bond %s\n", - bond_dev->name, bond_dev->name); + netdev_info(bond_dev, "Destroying bond %s\n", + bond_dev->name); unregister_netdevice(bond_dev); } return ret; @@ -1891,7 +1872,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in /*-------------------------------- Monitoring -------------------------------*/ - +/* called with rcu_read_lock() */ static int bond_miimon_inspect(struct bonding *bond) { int link_state, commit = 0; @@ -1899,7 +1880,7 @@ static int bond_miimon_inspect(struct bonding *bond) struct slave *slave; bool ignore_updelay; - ignore_updelay = !bond->curr_active_slave ? true : false; + ignore_updelay = !rcu_dereference(bond->curr_active_slave); bond_for_each_slave_rcu(bond, slave, iter) { slave->new_link = BOND_LINK_NOCHANGE; @@ -1914,14 +1895,13 @@ static int bond_miimon_inspect(struct bonding *bond) slave->link = BOND_LINK_FAIL; slave->delay = bond->params.downdelay; if (slave->delay) { - pr_info("%s: link status down for %sinterface %s, disabling it in %d ms\n", - bond->dev->name, - (BOND_MODE(bond) == - BOND_MODE_ACTIVEBACKUP) ? - (bond_is_active_slave(slave) ? - "active " : "backup ") : "", - slave->dev->name, - bond->params.downdelay * bond->params.miimon); + netdev_info(bond->dev, "link status down for %sinterface %s, disabling it in %d ms\n", + (BOND_MODE(bond) == + BOND_MODE_ACTIVEBACKUP) ? + (bond_is_active_slave(slave) ? + "active " : "backup ") : "", + slave->dev->name, + bond->params.downdelay * bond->params.miimon); } /*FALLTHRU*/ case BOND_LINK_FAIL: @@ -1931,11 +1911,10 @@ static int bond_miimon_inspect(struct bonding *bond) */ slave->link = BOND_LINK_UP; slave->last_link_up = jiffies; - pr_info("%s: link status up again after %d ms for interface %s\n", - bond->dev->name, - (bond->params.downdelay - slave->delay) * - bond->params.miimon, - slave->dev->name); + netdev_info(bond->dev, "link status up again after %d ms for interface %s\n", + (bond->params.downdelay - slave->delay) * + bond->params.miimon, + slave->dev->name); continue; } @@ -1956,21 +1935,20 @@ static int bond_miimon_inspect(struct bonding *bond) slave->delay = bond->params.updelay; if (slave->delay) { - pr_info("%s: link status up for interface %s, enabling it in %d ms\n", - bond->dev->name, slave->dev->name, - ignore_updelay ? 0 : - bond->params.updelay * - bond->params.miimon); + netdev_info(bond->dev, "link status up for interface %s, enabling it in %d ms\n", + slave->dev->name, + ignore_updelay ? 0 : + bond->params.updelay * + bond->params.miimon); } /*FALLTHRU*/ case BOND_LINK_BACK: if (!link_state) { slave->link = BOND_LINK_DOWN; - pr_info("%s: link status down again after %d ms for interface %s\n", - bond->dev->name, - (bond->params.updelay - slave->delay) * - bond->params.miimon, - slave->dev->name); + netdev_info(bond->dev, "link status down again after %d ms for interface %s\n", + (bond->params.updelay - slave->delay) * + bond->params.miimon, + slave->dev->name); continue; } @@ -2018,10 +1996,10 @@ static void bond_miimon_commit(struct bonding *bond) bond_set_backup_slave(slave); } - pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex\n", - bond->dev->name, slave->dev->name, - slave->speed == SPEED_UNKNOWN ? 0 : slave->speed, - slave->duplex ? "full" : "half"); + netdev_info(bond->dev, "link status definitely up for interface %s, %u Mbps %s duplex\n", + slave->dev->name, + slave->speed == SPEED_UNKNOWN ? 0 : slave->speed, + slave->duplex ? "full" : "half"); /* notify ad that the link status has changed */ if (BOND_MODE(bond) == BOND_MODE_8023AD) @@ -2048,8 +2026,8 @@ static void bond_miimon_commit(struct bonding *bond) bond_set_slave_inactive_flags(slave, BOND_SLAVE_NOTIFY_NOW); - pr_info("%s: link status definitely down for interface %s, disabling it\n", - bond->dev->name, slave->dev->name); + netdev_info(bond->dev, "link status definitely down for interface %s, disabling it\n", + slave->dev->name); if (BOND_MODE(bond) == BOND_MODE_8023AD) bond_3ad_handle_link_change(slave, @@ -2059,15 +2037,14 @@ static void bond_miimon_commit(struct bonding *bond) bond_alb_handle_link_change(bond, slave, BOND_LINK_DOWN); - if (slave == bond->curr_active_slave) + if (slave == rcu_access_pointer(bond->curr_active_slave)) goto do_failover; continue; default: - pr_err("%s: invalid new link %d on slave %s\n", - bond->dev->name, slave->new_link, - slave->dev->name); + netdev_err(bond->dev, "invalid new link %d on slave %s\n", + slave->new_link, slave->dev->name); slave->new_link = BOND_LINK_NOCHANGE; continue; @@ -2168,10 +2145,10 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, struct bond_vlan_tag *tags) { struct sk_buff *skb; - int i; + struct bond_vlan_tag *outer_tag = tags; - pr_debug("arp %d on slave %s: dst %pI4 src %pI4\n", - arp_op, slave_dev->name, &dest_ip, &src_ip); + netdev_dbg(slave_dev, "arp %d on slave %s: dst %pI4 src %pI4\n", + arp_op, slave_dev->name, &dest_ip, &src_ip); skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip, NULL, slave_dev->dev_addr, NULL); @@ -2181,30 +2158,42 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, return; } + if (!tags || tags->vlan_proto == VLAN_N_VID) + goto xmit; + + tags++; + /* Go through all the tags backwards and add them to the packet */ - for (i = BOND_MAX_VLAN_ENCAP - 1; i > 0; i--) { - if (!tags[i].vlan_id) + while (tags->vlan_proto != VLAN_N_VID) { + if (!tags->vlan_id) { + tags++; continue; + } - pr_debug("inner tag: proto %X vid %X\n", - ntohs(tags[i].vlan_proto), tags[i].vlan_id); - skb = __vlan_put_tag(skb, tags[i].vlan_proto, - tags[i].vlan_id); + netdev_dbg(slave_dev, "inner tag: proto %X vid %X\n", + ntohs(outer_tag->vlan_proto), tags->vlan_id); + skb = __vlan_put_tag(skb, tags->vlan_proto, + tags->vlan_id); if (!skb) { net_err_ratelimited("failed to insert inner VLAN tag\n"); return; } + + tags++; } /* Set the outer tag */ - if (tags[0].vlan_id) { - pr_debug("outer tag: proto %X vid %X\n", - ntohs(tags[0].vlan_proto), tags[0].vlan_id); - skb = vlan_put_tag(skb, tags[0].vlan_proto, tags[0].vlan_id); + if (outer_tag->vlan_id) { + netdev_dbg(slave_dev, "outer tag: proto %X vid %X\n", + ntohs(outer_tag->vlan_proto), outer_tag->vlan_id); + skb = vlan_put_tag(skb, outer_tag->vlan_proto, + outer_tag->vlan_id); if (!skb) { net_err_ratelimited("failed to insert outer VLAN tag\n"); return; } } + +xmit: arp_xmit(skb); } @@ -2214,46 +2203,50 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, * When the path is validated, collect any vlan information in the * path. */ -bool bond_verify_device_path(struct net_device *start_dev, - struct net_device *end_dev, - struct bond_vlan_tag *tags) +struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev, + struct net_device *end_dev, + int level) { + struct bond_vlan_tag *tags; struct net_device *upper; struct list_head *iter; - int idx; - if (start_dev == end_dev) - return true; + if (start_dev == end_dev) { + tags = kzalloc(sizeof(*tags) * (level + 1), GFP_ATOMIC); + if (!tags) + return ERR_PTR(-ENOMEM); + tags[level].vlan_proto = VLAN_N_VID; + return tags; + } netdev_for_each_upper_dev_rcu(start_dev, upper, iter) { - if (bond_verify_device_path(upper, end_dev, tags)) { - if (is_vlan_dev(upper)) { - idx = vlan_get_encap_level(upper); - if (idx >= BOND_MAX_VLAN_ENCAP) - return false; - - tags[idx].vlan_proto = - vlan_dev_vlan_proto(upper); - tags[idx].vlan_id = vlan_dev_vlan_id(upper); - } - return true; + tags = bond_verify_device_path(upper, end_dev, level + 1); + if (IS_ERR_OR_NULL(tags)) { + if (IS_ERR(tags)) + return tags; + continue; } + if (is_vlan_dev(upper)) { + tags[level].vlan_proto = vlan_dev_vlan_proto(upper); + tags[level].vlan_id = vlan_dev_vlan_id(upper); + } + + return tags; } - return false; + return NULL; } static void bond_arp_send_all(struct bonding *bond, struct slave *slave) { struct rtable *rt; - struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP]; + struct bond_vlan_tag *tags; __be32 *targets = bond->params.arp_targets, addr; int i; - bool ret; for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) { - pr_debug("basa: target %pI4\n", &targets[i]); - memset(tags, 0, sizeof(tags)); + netdev_dbg(bond->dev, "basa: target %pI4\n", &targets[i]); + tags = NULL; /* Find out through which dev should the packet go */ rt = ip_route_output(dev_net(bond->dev), targets[i], 0, @@ -2276,16 +2269,15 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) goto found; rcu_read_lock(); - ret = bond_verify_device_path(bond->dev, rt->dst.dev, tags); + tags = bond_verify_device_path(bond->dev, rt->dst.dev, 0); rcu_read_unlock(); - if (ret) + if (!IS_ERR_OR_NULL(tags)) goto found; /* Not our device - skip */ - pr_debug("%s: no path to arp_ip_target %pI4 via rt.dev %s\n", - bond->dev->name, &targets[i], - rt->dst.dev ? rt->dst.dev->name : "NULL"); + netdev_dbg(bond->dev, "no path to arp_ip_target %pI4 via rt.dev %s\n", + &targets[i], rt->dst.dev ? rt->dst.dev->name : "NULL"); ip_rt_put(rt); continue; @@ -2295,6 +2287,7 @@ found: ip_rt_put(rt); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], addr, tags); + kfree(tags); } } @@ -2303,13 +2296,15 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 int i; if (!sip || !bond_has_this_ip(bond, tip)) { - pr_debug("bva: sip %pI4 tip %pI4 not found\n", &sip, &tip); + netdev_dbg(bond->dev, "bva: sip %pI4 tip %pI4 not found\n", + &sip, &tip); return; } i = bond_get_targets_ip(bond->params.arp_targets, sip); if (i == -1) { - pr_debug("bva: sip %pI4 not found in targets\n", &sip); + netdev_dbg(bond->dev, "bva: sip %pI4 not found in targets\n", + &sip); return; } slave->last_rx = jiffies; @@ -2336,8 +2331,8 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, alen = arp_hdr_len(bond->dev); - pr_debug("bond_arp_rcv: bond %s skb->dev %s\n", - bond->dev->name, skb->dev->name); + netdev_dbg(bond->dev, "bond_arp_rcv: skb->dev %s\n", + skb->dev->name); if (alen > skb_headlen(skb)) { arp = kmalloc(alen, GFP_ATOMIC); @@ -2361,10 +2356,10 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, arp_ptr += 4 + bond->dev->addr_len; memcpy(&tip, arp_ptr, 4); - pr_debug("bond_arp_rcv: %s %s/%d av %d sv %d sip %pI4 tip %pI4\n", - bond->dev->name, slave->dev->name, bond_slave_state(slave), - bond->params.arp_validate, slave_do_arp_validate(bond, slave), - &sip, &tip); + netdev_dbg(bond->dev, "bond_arp_rcv: %s/%d av %d sv %d sip %pI4 tip %pI4\n", + slave->dev->name, bond_slave_state(slave), + bond->params.arp_validate, slave_do_arp_validate(bond, slave), + &sip, &tip); curr_active_slave = rcu_dereference(bond->curr_active_slave); @@ -2429,7 +2424,7 @@ static void bond_loadbalance_arp_mon(struct work_struct *work) rcu_read_lock(); - oldcurrent = ACCESS_ONCE(bond->curr_active_slave); + oldcurrent = rcu_dereference(bond->curr_active_slave); /* see if any of the previous devices are up now (i.e. they have * xmt and rcv traffic). the curr_active_slave does not come into * the picture unless it is null. also, slave->last_link_up is not @@ -2454,14 +2449,12 @@ static void bond_loadbalance_arp_mon(struct work_struct *work) * is closed. */ if (!oldcurrent) { - pr_info("%s: link status definitely up for interface %s\n", - bond->dev->name, - slave->dev->name); + netdev_info(bond->dev, "link status definitely up for interface %s\n", + slave->dev->name); do_failover = 1; } else { - pr_info("%s: interface %s is now up\n", - bond->dev->name, - slave->dev->name); + netdev_info(bond->dev, "interface %s is now up\n", + slave->dev->name); } } } else { @@ -2480,8 +2473,8 @@ static void bond_loadbalance_arp_mon(struct work_struct *work) if (slave->link_failure_count < UINT_MAX) slave->link_failure_count++; - pr_info("%s: interface %s is now down\n", - bond->dev->name, slave->dev->name); + netdev_info(bond->dev, "interface %s is now down\n", + slave->dev->name); if (slave == oldcurrent) do_failover = 1; @@ -2577,7 +2570,7 @@ static int bond_ab_arp_inspect(struct bonding *bond) * before being taken out */ if (!bond_is_active_slave(slave) && - !bond->current_arp_slave && + !rcu_access_pointer(bond->current_arp_slave) && !bond_time_in_interval(bond, last_rx, 3)) { slave->new_link = BOND_LINK_DOWN; commit++; @@ -2620,21 +2613,24 @@ static void bond_ab_arp_commit(struct bonding *bond) case BOND_LINK_UP: trans_start = dev_trans_start(slave->dev); - if (bond->curr_active_slave != slave || - (!bond->curr_active_slave && + if (rtnl_dereference(bond->curr_active_slave) != slave || + (!rtnl_dereference(bond->curr_active_slave) && bond_time_in_interval(bond, trans_start, 1))) { + struct slave *current_arp_slave; + + current_arp_slave = rtnl_dereference(bond->current_arp_slave); slave->link = BOND_LINK_UP; - if (bond->current_arp_slave) { + if (current_arp_slave) { bond_set_slave_inactive_flags( - bond->current_arp_slave, + current_arp_slave, BOND_SLAVE_NOTIFY_NOW); - bond->current_arp_slave = NULL; + RCU_INIT_POINTER(bond->current_arp_slave, NULL); } - pr_info("%s: link status definitely up for interface %s\n", - bond->dev->name, slave->dev->name); + netdev_info(bond->dev, "link status definitely up for interface %s\n", + slave->dev->name); - if (!bond->curr_active_slave || + if (!rtnl_dereference(bond->curr_active_slave) || (slave == bond->primary_slave)) goto do_failover; @@ -2650,20 +2646,19 @@ static void bond_ab_arp_commit(struct bonding *bond) bond_set_slave_inactive_flags(slave, BOND_SLAVE_NOTIFY_NOW); - pr_info("%s: link status definitely down for interface %s, disabling it\n", - bond->dev->name, slave->dev->name); + netdev_info(bond->dev, "link status definitely down for interface %s, disabling it\n", + slave->dev->name); - if (slave == bond->curr_active_slave) { - bond->current_arp_slave = NULL; + if (slave == rtnl_dereference(bond->curr_active_slave)) { + RCU_INIT_POINTER(bond->current_arp_slave, NULL); goto do_failover; } continue; default: - pr_err("%s: impossible: new_link %d on slave %s\n", - bond->dev->name, slave->new_link, - slave->dev->name); + netdev_err(bond->dev, "impossible: new_link %d on slave %s\n", + slave->new_link, slave->dev->name); continue; } @@ -2694,9 +2689,9 @@ static bool bond_ab_arp_probe(struct bonding *bond) bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER; if (curr_arp_slave && curr_active_slave) - pr_info("PROBE: c_arp %s && cas %s BAD\n", - curr_arp_slave->dev->name, - curr_active_slave->dev->name); + netdev_info(bond->dev, "PROBE: c_arp %s && cas %s BAD\n", + curr_arp_slave->dev->name, + curr_active_slave->dev->name); if (curr_active_slave) { bond_arp_send_all(bond, curr_active_slave); @@ -2737,8 +2732,8 @@ static bool bond_ab_arp_probe(struct bonding *bond) bond_set_slave_inactive_flags(slave, BOND_SLAVE_NOTIFY_LATER); - pr_info("%s: backup interface %s is now down\n", - bond->dev->name, slave->dev->name); + netdev_info(bond->dev, "backup interface %s is now down\n", + slave->dev->name); } if (slave == curr_arp_slave) found = true; @@ -2934,9 +2929,8 @@ static int bond_slave_netdev_event(unsigned long event, break; } - pr_info("%s: Primary slave changed to %s, reselecting active slave\n", - bond->dev->name, - bond->primary_slave ? slave_dev->name : "none"); + netdev_info(bond->dev, "Primary slave changed to %s, reselecting active slave\n", + bond->primary_slave ? slave_dev->name : "none"); block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); @@ -2971,19 +2965,18 @@ static int bond_netdev_event(struct notifier_block *this, { struct net_device *event_dev = netdev_notifier_info_to_dev(ptr); - pr_debug("event_dev: %s, event: %lx\n", - event_dev ? event_dev->name : "None", event); + netdev_dbg(event_dev, "event: %lx\n", event); if (!(event_dev->priv_flags & IFF_BONDING)) return NOTIFY_DONE; if (event_dev->flags & IFF_MASTER) { - pr_debug("IFF_MASTER\n"); + netdev_dbg(event_dev, "IFF_MASTER\n"); return bond_master_netdev_event(event, event_dev); } if (event_dev->flags & IFF_SLAVE) { - pr_debug("IFF_SLAVE\n"); + netdev_dbg(event_dev, "IFF_SLAVE\n"); return bond_slave_netdev_event(event, event_dev); } @@ -2999,11 +2992,11 @@ static struct notifier_block bond_netdev_notifier = { /* L2 hash helper */ static inline u32 bond_eth_hash(struct sk_buff *skb) { - struct ethhdr *data = (struct ethhdr *)skb->data; - - if (skb_headlen(skb) >= offsetof(struct ethhdr, h_proto)) - return data->h_dest[5] ^ data->h_source[5]; + struct ethhdr *ep, hdr_tmp; + ep = skb_header_pointer(skb, 0, sizeof(hdr_tmp), &hdr_tmp); + if (ep) + return ep->h_dest[5] ^ ep->h_source[5] ^ ep->h_proto; return 0; } @@ -3110,8 +3103,8 @@ static int bond_open(struct net_device *bond_dev) if (bond_has_slaves(bond)) { read_lock(&bond->curr_slave_lock); bond_for_each_slave(bond, slave, iter) { - if (bond_uses_primary(bond) - && (slave != bond->curr_active_slave)) { + if (bond_uses_primary(bond) && + slave != rcu_access_pointer(bond->curr_active_slave)) { bond_set_slave_inactive_flags(slave, BOND_SLAVE_NOTIFY_NOW); } else { @@ -3225,7 +3218,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd struct net *net; int res = 0; - pr_debug("bond_ioctl: master=%s, cmd=%d\n", bond_dev->name, cmd); + netdev_dbg(bond_dev, "bond_ioctl: cmd=%d\n", cmd); switch (cmd) { case SIOCGMIIPHY: @@ -3295,12 +3288,12 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd slave_dev = __dev_get_by_name(net, ifr->ifr_slave); - pr_debug("slave_dev=%p:\n", slave_dev); + netdev_dbg(bond_dev, "slave_dev=%p:\n", slave_dev); if (!slave_dev) return -ENODEV; - pr_debug("slave_dev->name=%s:\n", slave_dev->name); + netdev_dbg(bond_dev, "slave_dev->name=%s:\n", slave_dev->name); switch (cmd) { case BOND_ENSLAVE_OLD: case SIOCBONDENSLAVE: @@ -3427,8 +3420,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu) struct list_head *iter; int res = 0; - pr_debug("bond=%p, name=%s, new_mtu=%d\n", - bond, bond_dev ? bond_dev->name : "None", new_mtu); + netdev_dbg(bond_dev, "bond=%p, new_mtu=%d\n", bond, new_mtu); /* Can't hold bond->lock with bh disabled here since * some base drivers panic. On the other hand we can't @@ -3446,8 +3438,8 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu) */ bond_for_each_slave(bond, slave, iter) { - pr_debug("s %p c_m %p\n", - slave, slave->dev->netdev_ops->ndo_change_mtu); + netdev_dbg(bond_dev, "s %p c_m %p\n", + slave, slave->dev->netdev_ops->ndo_change_mtu); res = dev_set_mtu(slave->dev, new_mtu); @@ -3460,7 +3452,8 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu) * means changing their mtu from timer context, which * is probably not a good idea. */ - pr_debug("err %d %s\n", res, slave->dev->name); + netdev_dbg(bond_dev, "err %d %s\n", res, + slave->dev->name); goto unwind; } } @@ -3479,8 +3472,8 @@ unwind: tmp_res = dev_set_mtu(rollback_slave->dev, bond_dev->mtu); if (tmp_res) { - pr_debug("unwind err %d dev %s\n", - tmp_res, rollback_slave->dev->name); + netdev_dbg(bond_dev, "unwind err %d dev %s\n", + tmp_res, rollback_slave->dev->name); } } @@ -3506,8 +3499,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) return bond_alb_set_mac_address(bond_dev, addr); - pr_debug("bond=%p, name=%s\n", - bond, bond_dev ? bond_dev->name : "None"); + netdev_dbg(bond_dev, "bond=%p\n", bond); /* If fail_over_mac is enabled, do nothing and return success. * Returning an error causes ifenslave to fail. @@ -3535,7 +3527,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) */ bond_for_each_slave(bond, slave, iter) { - pr_debug("slave %p %s\n", slave, slave->dev->name); + netdev_dbg(bond_dev, "slave %p %s\n", slave, slave->dev->name); res = dev_set_mac_address(slave->dev, addr); if (res) { /* TODO: consider downing the slave @@ -3544,7 +3536,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) * breakage anyway until ARP finish * updating, so... */ - pr_debug("err %d %s\n", res, slave->dev->name); + netdev_dbg(bond_dev, "err %d %s\n", res, slave->dev->name); goto unwind; } } @@ -3566,8 +3558,8 @@ unwind: tmp_res = dev_set_mac_address(rollback_slave->dev, &tmp_sa); if (tmp_res) { - pr_debug("unwind err %d dev %s\n", - tmp_res, rollback_slave->dev->name); + netdev_dbg(bond_dev, "unwind err %d dev %s\n", + tmp_res, rollback_slave->dev->name); } } @@ -3814,8 +3806,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev return bond_tlb_xmit(skb, dev); default: /* Should never happen, mode already checked */ - pr_err("%s: Error: Unknown bonding mode %d\n", - dev->name, BOND_MODE(bond)); + netdev_err(dev, "Unknown bonding mode %d\n", BOND_MODE(bond)); WARN_ON_ONCE(1); dev_kfree_skb_any(skb); return NETDEV_TX_OK; @@ -3956,13 +3947,6 @@ void bond_setup(struct net_device *bond_dev) bond_dev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT; bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); - /* At first, we block adding VLANs. That's the only way to - * prevent problems that occur when adding VLANs over an - * empty bond. The block will be removed once non-challenged - * slaves are enslaved. - */ - bond_dev->features |= NETIF_F_VLAN_CHALLENGED; - /* don't acquire bond device's netif_tx_lock when * transmitting */ bond_dev->features |= NETIF_F_LLTX; @@ -4002,7 +3986,7 @@ static void bond_uninit(struct net_device *bond_dev) /* Release the bonded slaves */ bond_for_each_slave(bond, slave, iter) __bond_release_one(bond_dev, slave->dev, true); - pr_info("%s: Released all slaves\n", bond_dev->name); + netdev_info(bond_dev, "Released all slaves\n"); list_del(&bond->bond_list); @@ -4391,7 +4375,7 @@ static int bond_init(struct net_device *bond_dev) struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id); struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); - pr_debug("Begin bond_init for %s\n", bond_dev->name); + netdev_dbg(bond_dev, "Begin bond_init\n"); /* * Initialize locks that may be required during @@ -4440,7 +4424,7 @@ int bond_create(struct net *net, const char *name) rtnl_lock(); bond_dev = alloc_netdev_mq(sizeof(struct bonding), - name ? name : "bond%d", + name ? name : "bond%d", NET_NAME_UNKNOWN, bond_setup, tx_queues); if (!bond_dev) { pr_err("%s: eek! can't alloc netdev!\n", name); @@ -4481,7 +4465,6 @@ static void __net_exit bond_net_exit(struct net *net) LIST_HEAD(list); bond_destroy_sysfs(bn); - bond_destroy_proc_dir(bn); /* Kill off any bonds created after unregistering bond rtnl ops */ rtnl_lock(); @@ -4489,6 +4472,8 @@ static void __net_exit bond_net_exit(struct net *net) unregister_netdevice_queue(bond->dev, &list); unregister_netdevice_many(&list); rtnl_unlock(); + + bond_destroy_proc_dir(bn); } static struct pernet_operations bond_net_ops = { diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 5ab3c18..d163e11 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -9,8 +9,6 @@ * (at your option) any later version. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/module.h> #include <linux/errno.h> #include <linux/netdevice.h> @@ -181,8 +179,7 @@ static int bond_changelink(struct net_device *bond_dev, int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]); if (arp_interval && miimon) { - pr_err("%s: ARP monitoring cannot be used with MII monitoring\n", - bond->dev->name); + netdev_err(bond->dev, "ARP monitoring cannot be used with MII monitoring\n"); return -EINVAL; } @@ -207,8 +204,7 @@ static int bond_changelink(struct net_device *bond_dev, i++; } if (i == 0 && bond->params.arp_interval) - pr_warn("%s: Removing last arp target with arp_interval on\n", - bond->dev->name); + netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n"); if (err) return err; } @@ -216,8 +212,7 @@ static int bond_changelink(struct net_device *bond_dev, int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]); if (arp_validate && miimon) { - pr_err("%s: ARP validating cannot be used with MII monitoring\n", - bond->dev->name); + netdev_err(bond->dev, "ARP validating cannot be used with MII monitoring\n"); return -EINVAL; } @@ -398,20 +393,31 @@ static size_t bond_get_size(const struct net_device *bond_dev) 0; } +static int bond_option_active_slave_get_ifindex(struct bonding *bond) +{ + const struct net_device *slave; + int ifindex; + + rcu_read_lock(); + slave = bond_option_active_slave_get_rcu(bond); + ifindex = slave ? slave->ifindex : 0; + rcu_read_unlock(); + return ifindex; +} + static int bond_fill_info(struct sk_buff *skb, const struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); - struct net_device *slave_dev = bond_option_active_slave_get(bond); - struct nlattr *targets; unsigned int packets_per_slave; - int i, targets_added; + int ifindex, i, targets_added; + struct nlattr *targets; if (nla_put_u8(skb, IFLA_BOND_MODE, BOND_MODE(bond))) goto nla_put_failure; - if (slave_dev && - nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex)) + ifindex = bond_option_active_slave_get_ifindex(bond); + if (ifindex && nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, ifindex)) goto nla_put_failure; if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon)) diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 540e016..dc73463 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -9,8 +9,6 @@ * (at your option) any later version. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/errno.h> #include <linux/if.h> #include <linux/netdevice.h> @@ -544,9 +542,8 @@ static void bond_opt_dep_print(struct bonding *bond, params = &bond->params; modeval = bond_opt_get_val(BOND_OPT_MODE, params->mode); if (test_bit(params->mode, &opt->unsuppmodes)) - pr_err("%s: option %s: mode dependency failed, not supported in mode %s(%llu)\n", - bond->dev->name, opt->name, - modeval->string, modeval->value); + netdev_err(bond->dev, "option %s: mode dependency failed, not supported in mode %s(%llu)\n", + opt->name, modeval->string, modeval->value); } static void bond_opt_error_interpret(struct bonding *bond, @@ -564,31 +561,30 @@ static void bond_opt_error_interpret(struct bonding *bond, p = strchr(val->string, '\n'); if (p) *p = '\0'; - pr_err("%s: option %s: invalid value (%s)\n", - bond->dev->name, opt->name, val->string); + netdev_err(bond->dev, "option %s: invalid value (%s)\n", + opt->name, val->string); } else { - pr_err("%s: option %s: invalid value (%llu)\n", - bond->dev->name, opt->name, val->value); + netdev_err(bond->dev, "option %s: invalid value (%llu)\n", + opt->name, val->value); } } minval = bond_opt_get_flags(opt, BOND_VALFLAG_MIN); maxval = bond_opt_get_flags(opt, BOND_VALFLAG_MAX); if (!maxval) break; - pr_err("%s: option %s: allowed values %llu - %llu\n", - bond->dev->name, opt->name, minval ? minval->value : 0, - maxval->value); + netdev_err(bond->dev, "option %s: allowed values %llu - %llu\n", + opt->name, minval ? minval->value : 0, maxval->value); break; case -EACCES: bond_opt_dep_print(bond, opt); break; case -ENOTEMPTY: - pr_err("%s: option %s: unable to set because the bond device has slaves\n", - bond->dev->name, opt->name); + netdev_err(bond->dev, "option %s: unable to set because the bond device has slaves\n", + opt->name); break; case -EBUSY: - pr_err("%s: option %s: unable to set because the bond device is up\n", - bond->dev->name, opt->name); + netdev_err(bond->dev, "option %s: unable to set because the bond device is up\n", + opt->name); break; default: break; @@ -671,17 +667,18 @@ const struct bond_option *bond_opt_get(unsigned int option) return &bond_opts[option]; } -int bond_option_mode_set(struct bonding *bond, const struct bond_opt_value *newval) +static int bond_option_mode_set(struct bonding *bond, + const struct bond_opt_value *newval) { if (!bond_mode_uses_arp(newval->value) && bond->params.arp_interval) { - pr_info("%s: %s mode is incompatible with arp monitoring, start mii monitoring\n", - bond->dev->name, newval->string); + netdev_info(bond->dev, "%s mode is incompatible with arp monitoring, start mii monitoring\n", + newval->string); /* disable arp monitoring */ bond->params.arp_interval = 0; /* set miimon to default value */ bond->params.miimon = BOND_DEFAULT_MIIMON; - pr_info("%s: Setting MII monitoring interval to %d\n", - bond->dev->name, bond->params.miimon); + netdev_info(bond->dev, "Setting MII monitoring interval to %d\n", + bond->params.miimon); } /* don't cache arp_validate between modes */ @@ -704,11 +701,6 @@ struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond) return __bond_option_active_slave_get(bond, slave); } -struct net_device *bond_option_active_slave_get(struct bonding *bond) -{ - return __bond_option_active_slave_get(bond, bond->curr_active_slave); -} - static int bond_option_active_slave_set(struct bonding *bond, const struct bond_opt_value *newval) { @@ -727,14 +719,14 @@ static int bond_option_active_slave_set(struct bonding *bond, if (slave_dev) { if (!netif_is_bond_slave(slave_dev)) { - pr_err("Device %s is not bonding slave\n", - slave_dev->name); + netdev_err(bond->dev, "Device %s is not bonding slave\n", + slave_dev->name); return -EINVAL; } if (bond->dev != netdev_master_upper_dev_get(slave_dev)) { - pr_err("%s: Device %s is not our slave\n", - bond->dev->name, slave_dev->name); + netdev_err(bond->dev, "Device %s is not our slave\n", + slave_dev->name); return -EINVAL; } } @@ -744,29 +736,29 @@ static int bond_option_active_slave_set(struct bonding *bond, /* check to see if we are clearing active */ if (!slave_dev) { - pr_info("%s: Clearing current active slave\n", bond->dev->name); + netdev_info(bond->dev, "Clearing current active slave\n"); RCU_INIT_POINTER(bond->curr_active_slave, NULL); bond_select_active_slave(bond); } else { - struct slave *old_active = bond->curr_active_slave; + struct slave *old_active = bond_deref_active_protected(bond); struct slave *new_active = bond_slave_get_rtnl(slave_dev); BUG_ON(!new_active); if (new_active == old_active) { /* do nothing */ - pr_info("%s: %s is already the current active slave\n", - bond->dev->name, new_active->dev->name); + netdev_info(bond->dev, "%s is already the current active slave\n", + new_active->dev->name); } else { if (old_active && (new_active->link == BOND_LINK_UP) && bond_slave_is_up(new_active)) { - pr_info("%s: Setting %s as active slave\n", - bond->dev->name, new_active->dev->name); + netdev_info(bond->dev, "Setting %s as active slave\n", + new_active->dev->name); bond_change_active_slave(bond, new_active); } else { - pr_err("%s: Could not set %s as active slave; either %s is down or the link is down\n", - bond->dev->name, new_active->dev->name, - new_active->dev->name); + netdev_err(bond->dev, "Could not set %s as active slave; either %s is down or the link is down\n", + new_active->dev->name, + new_active->dev->name); ret = -EINVAL; } } @@ -785,20 +777,17 @@ static int bond_option_active_slave_set(struct bonding *bond, static int bond_option_miimon_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting MII monitoring interval to %llu\n", - bond->dev->name, newval->value); + netdev_info(bond->dev, "Setting MII monitoring interval to %llu\n", + newval->value); bond->params.miimon = newval->value; if (bond->params.updelay) - pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value\n", - bond->dev->name, + netdev_info(bond->dev, "Note: Updating updelay (to %d) since it is a multiple of the miimon value\n", bond->params.updelay * bond->params.miimon); if (bond->params.downdelay) - pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n", - bond->dev->name, - bond->params.downdelay * bond->params.miimon); + netdev_info(bond->dev, "Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n", + bond->params.downdelay * bond->params.miimon); if (newval->value && bond->params.arp_interval) { - pr_info("%s: MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n", - bond->dev->name); + netdev_info(bond->dev, "MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n"); bond->params.arp_interval = 0; if (bond->params.arp_validate) bond->params.arp_validate = BOND_ARP_VALIDATE_NONE; @@ -830,20 +819,18 @@ static int bond_option_updelay_set(struct bonding *bond, int value = newval->value; if (!bond->params.miimon) { - pr_err("%s: Unable to set up delay as MII monitoring is disabled\n", - bond->dev->name); + netdev_err(bond->dev, "Unable to set up delay as MII monitoring is disabled\n"); return -EPERM; } if ((value % bond->params.miimon) != 0) { - pr_warn("%s: Warning: up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n", - bond->dev->name, value, - bond->params.miimon, - (value / bond->params.miimon) * - bond->params.miimon); + netdev_warn(bond->dev, "up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n", + value, bond->params.miimon, + (value / bond->params.miimon) * + bond->params.miimon); } bond->params.updelay = value / bond->params.miimon; - pr_info("%s: Setting up delay to %d\n", - bond->dev->name, bond->params.updelay * bond->params.miimon); + netdev_info(bond->dev, "Setting up delay to %d\n", + bond->params.updelay * bond->params.miimon); return 0; } @@ -854,20 +841,18 @@ static int bond_option_downdelay_set(struct bonding *bond, int value = newval->value; if (!bond->params.miimon) { - pr_err("%s: Unable to set down delay as MII monitoring is disabled\n", - bond->dev->name); + netdev_err(bond->dev, "Unable to set down delay as MII monitoring is disabled\n"); return -EPERM; } if ((value % bond->params.miimon) != 0) { - pr_warn("%s: Warning: down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n", - bond->dev->name, value, - bond->params.miimon, - (value / bond->params.miimon) * - bond->params.miimon); + netdev_warn(bond->dev, "down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n", + value, bond->params.miimon, + (value / bond->params.miimon) * + bond->params.miimon); } bond->params.downdelay = value / bond->params.miimon; - pr_info("%s: Setting down delay to %d\n", - bond->dev->name, bond->params.downdelay * bond->params.miimon); + netdev_info(bond->dev, "Setting down delay to %d\n", + bond->params.downdelay * bond->params.miimon); return 0; } @@ -875,8 +860,8 @@ static int bond_option_downdelay_set(struct bonding *bond, static int bond_option_use_carrier_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting use_carrier to %llu\n", - bond->dev->name, newval->value); + netdev_info(bond->dev, "Setting use_carrier to %llu\n", + newval->value); bond->params.use_carrier = newval->value; return 0; @@ -889,18 +874,16 @@ static int bond_option_use_carrier_set(struct bonding *bond, static int bond_option_arp_interval_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting ARP monitoring interval to %llu\n", - bond->dev->name, newval->value); + netdev_info(bond->dev, "Setting ARP monitoring interval to %llu\n", + newval->value); bond->params.arp_interval = newval->value; if (newval->value) { if (bond->params.miimon) { - pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring\n", - bond->dev->name, bond->dev->name); + netdev_info(bond->dev, "ARP monitoring cannot be used with MII monitoring. Disabling MII monitoring\n"); bond->params.miimon = 0; } if (!bond->params.arp_targets[0]) - pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified\n", - bond->dev->name); + netdev_info(bond->dev, "ARP monitoring has been set up, but no ARP targets have been specified\n"); } if (bond->dev->flags & IFF_UP) { /* If the interface is up, we may need to fire off @@ -944,24 +927,24 @@ static int _bond_option_arp_ip_target_add(struct bonding *bond, __be32 target) int ind; if (!bond_is_ip_target_ok(target)) { - pr_err("%s: invalid ARP target %pI4 specified for addition\n", - bond->dev->name, &target); + netdev_err(bond->dev, "invalid ARP target %pI4 specified for addition\n", + &target); return -EINVAL; } if (bond_get_targets_ip(targets, target) != -1) { /* dup */ - pr_err("%s: ARP target %pI4 is already present\n", - bond->dev->name, &target); + netdev_err(bond->dev, "ARP target %pI4 is already present\n", + &target); return -EINVAL; } ind = bond_get_targets_ip(targets, 0); /* first free slot */ if (ind == -1) { - pr_err("%s: ARP target table is full!\n", bond->dev->name); + netdev_err(bond->dev, "ARP target table is full!\n"); return -EINVAL; } - pr_info("%s: Adding ARP target %pI4\n", bond->dev->name, &target); + netdev_info(bond->dev, "Adding ARP target %pI4\n", &target); _bond_options_arp_ip_target_set(bond, ind, target, jiffies); @@ -989,23 +972,22 @@ static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target) int ind, i; if (!bond_is_ip_target_ok(target)) { - pr_err("%s: invalid ARP target %pI4 specified for removal\n", - bond->dev->name, &target); + netdev_err(bond->dev, "invalid ARP target %pI4 specified for removal\n", + &target); return -EINVAL; } ind = bond_get_targets_ip(targets, target); if (ind == -1) { - pr_err("%s: unable to remove nonexistent ARP target %pI4\n", - bond->dev->name, &target); + netdev_err(bond->dev, "unable to remove nonexistent ARP target %pI4\n", + &target); return -EINVAL; } if (ind == 0 && !targets[1] && bond->params.arp_interval) - pr_warn("%s: Removing last arp target with arp_interval on\n", - bond->dev->name); + netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n"); - pr_info("%s: Removing ARP target %pI4\n", bond->dev->name, &target); + netdev_info(bond->dev, "Removing ARP target %pI4\n", &target); /* not to race with bond_arp_rcv */ write_lock_bh(&bond->lock); @@ -1044,8 +1026,8 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond, if (newval->string) { if (!in4_pton(newval->string+1, -1, (u8 *)&target, -1, NULL)) { - pr_err("%s: invalid ARP target %pI4 specified\n", - bond->dev->name, &target); + netdev_err(bond->dev, "invalid ARP target %pI4 specified\n", + &target); return ret; } if (newval->string[0] == '+') @@ -1053,8 +1035,7 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond, else if (newval->string[0] == '-') ret = bond_option_arp_ip_target_rem(bond, target); else - pr_err("no command found in arp_ip_targets file for bond %s - use +<addr> or -<addr>\n", - bond->dev->name); + netdev_err(bond->dev, "no command found in arp_ip_targets file - use +<addr> or -<addr>\n"); } else { target = newval->value; ret = bond_option_arp_ip_target_add(bond, target); @@ -1066,8 +1047,8 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond, static int bond_option_arp_validate_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting arp_validate to %s (%llu)\n", - bond->dev->name, newval->string, newval->value); + netdev_info(bond->dev, "Setting arp_validate to %s (%llu)\n", + newval->string, newval->value); if (bond->dev->flags & IFF_UP) { if (!newval->value) @@ -1083,8 +1064,8 @@ static int bond_option_arp_validate_set(struct bonding *bond, static int bond_option_arp_all_targets_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting arp_all_targets to %s (%llu)\n", - bond->dev->name, newval->string, newval->value); + netdev_info(bond->dev, "Setting arp_all_targets to %s (%llu)\n", + newval->string, newval->value); bond->params.arp_all_targets = newval->value; return 0; @@ -1106,7 +1087,7 @@ static int bond_option_primary_set(struct bonding *bond, *p = '\0'; /* check to see if we are clearing primary */ if (!strlen(primary)) { - pr_info("%s: Setting primary slave to None\n", bond->dev->name); + netdev_info(bond->dev, "Setting primary slave to None\n"); bond->primary_slave = NULL; memset(bond->params.primary, 0, sizeof(bond->params.primary)); bond_select_active_slave(bond); @@ -1115,8 +1096,8 @@ static int bond_option_primary_set(struct bonding *bond, bond_for_each_slave(bond, slave, iter) { if (strncmp(slave->dev->name, primary, IFNAMSIZ) == 0) { - pr_info("%s: Setting %s as primary slave\n", - bond->dev->name, slave->dev->name); + netdev_info(bond->dev, "Setting %s as primary slave\n", + slave->dev->name); bond->primary_slave = slave; strcpy(bond->params.primary, slave->dev->name); bond_select_active_slave(bond); @@ -1125,15 +1106,15 @@ static int bond_option_primary_set(struct bonding *bond, } if (bond->primary_slave) { - pr_info("%s: Setting primary slave to None\n", bond->dev->name); + netdev_info(bond->dev, "Setting primary slave to None\n"); bond->primary_slave = NULL; bond_select_active_slave(bond); } strncpy(bond->params.primary, primary, IFNAMSIZ); bond->params.primary[IFNAMSIZ - 1] = 0; - pr_info("%s: Recording %s as primary, but it has not been enslaved to %s yet\n", - bond->dev->name, primary, bond->dev->name); + netdev_info(bond->dev, "Recording %s as primary, but it has not been enslaved to %s yet\n", + primary, bond->dev->name); out: write_unlock_bh(&bond->curr_slave_lock); @@ -1146,8 +1127,8 @@ out: static int bond_option_primary_reselect_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting primary_reselect to %s (%llu)\n", - bond->dev->name, newval->string, newval->value); + netdev_info(bond->dev, "Setting primary_reselect to %s (%llu)\n", + newval->string, newval->value); bond->params.primary_reselect = newval->value; block_netpoll_tx(); @@ -1162,8 +1143,8 @@ static int bond_option_primary_reselect_set(struct bonding *bond, static int bond_option_fail_over_mac_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting fail_over_mac to %s (%llu)\n", - bond->dev->name, newval->string, newval->value); + netdev_info(bond->dev, "Setting fail_over_mac to %s (%llu)\n", + newval->string, newval->value); bond->params.fail_over_mac = newval->value; return 0; @@ -1172,8 +1153,8 @@ static int bond_option_fail_over_mac_set(struct bonding *bond, static int bond_option_xmit_hash_policy_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting xmit hash policy to %s (%llu)\n", - bond->dev->name, newval->string, newval->value); + netdev_info(bond->dev, "Setting xmit hash policy to %s (%llu)\n", + newval->string, newval->value); bond->params.xmit_policy = newval->value; return 0; @@ -1182,8 +1163,8 @@ static int bond_option_xmit_hash_policy_set(struct bonding *bond, static int bond_option_resend_igmp_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting resend_igmp to %llu\n", - bond->dev->name, newval->value); + netdev_info(bond->dev, "Setting resend_igmp to %llu\n", + newval->value); bond->params.resend_igmp = newval->value; return 0; @@ -1221,8 +1202,8 @@ static int bond_option_all_slaves_active_set(struct bonding *bond, static int bond_option_min_links_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting min links value to %llu\n", - bond->dev->name, newval->value); + netdev_info(bond->dev, "Setting min links value to %llu\n", + newval->value); bond->params.min_links = newval->value; return 0; @@ -1257,8 +1238,8 @@ static int bond_option_pps_set(struct bonding *bond, static int bond_option_lacp_rate_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting LACP rate to %s (%llu)\n", - bond->dev->name, newval->string, newval->value); + netdev_info(bond->dev, "Setting LACP rate to %s (%llu)\n", + newval->string, newval->value); bond->params.lacp_fast = newval->value; bond_3ad_update_lacp_rate(bond); @@ -1268,8 +1249,8 @@ static int bond_option_lacp_rate_set(struct bonding *bond, static int bond_option_ad_select_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting ad_select to %s (%llu)\n", - bond->dev->name, newval->string, newval->value); + netdev_info(bond->dev, "Setting ad_select to %s (%llu)\n", + newval->string, newval->value); bond->params.ad_select = newval->value; return 0; @@ -1330,7 +1311,7 @@ out: return ret; err_no_cmd: - pr_info("invalid input for queue_id set for %s\n", bond->dev->name); + netdev_info(bond->dev, "invalid input for queue_id set\n"); ret = -EPERM; goto out; @@ -1352,20 +1333,20 @@ static int bond_option_slaves_set(struct bonding *bond, dev = __dev_get_by_name(dev_net(bond->dev), ifname); if (!dev) { - pr_info("%s: interface %s does not exist!\n", - bond->dev->name, ifname); + netdev_info(bond->dev, "interface %s does not exist!\n", + ifname); ret = -ENODEV; goto out; } switch (command[0]) { case '+': - pr_info("%s: Adding slave %s\n", bond->dev->name, dev->name); + netdev_info(bond->dev, "Adding slave %s\n", dev->name); ret = bond_enslave(bond->dev, dev); break; case '-': - pr_info("%s: Removing slave %s\n", bond->dev->name, dev->name); + netdev_info(bond->dev, "Removing slave %s\n", dev->name); ret = bond_release(bond->dev, dev); break; @@ -1377,8 +1358,7 @@ out: return ret; err_no_cmd: - pr_err("no command found in slaves file for bond %s - use +ifname or -ifname\n", - bond->dev->name); + netdev_err(bond->dev, "no command found in slaves file - use +ifname or -ifname\n"); ret = -EPERM; goto out; } @@ -1386,8 +1366,8 @@ err_no_cmd: static int bond_option_tlb_dynamic_lb_set(struct bonding *bond, const struct bond_opt_value *newval) { - pr_info("%s: Setting dynamic-lb to %s (%llu)\n", - bond->dev->name, newval->string, newval->value); + netdev_info(bond->dev, "Setting dynamic-lb to %s (%llu)\n", + newval->string, newval->value); bond->params.tlb_dynamic_lb = newval->value; return 0; diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c index b215b47..de62c03 100644 --- a/drivers/net/bonding/bond_procfs.c +++ b/drivers/net/bonding/bond_procfs.c @@ -252,8 +252,8 @@ void bond_create_proc_entry(struct bonding *bond) S_IRUGO, bn->proc_dir, &bond_info_fops, bond); if (bond->proc_entry == NULL) - pr_warn("Warning: Cannot create /proc/net/%s/%s\n", - DRV_NAME, bond_dev->name); + netdev_warn(bond_dev, "Cannot create /proc/net/%s/%s\n", + DRV_NAME, bond_dev->name); else memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ); } diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index daed52f..98db8ed 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -492,8 +492,9 @@ static ssize_t bonding_show_mii_status(struct device *d, char *buf) { struct bonding *bond = to_bond(d); + bool active = !!rcu_access_pointer(bond->curr_active_slave); - return sprintf(buf, "%s\n", bond->curr_active_slave ? "up" : "down"); + return sprintf(buf, "%s\n", active ? "up" : "down"); } static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL); diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c index 198677f..5cd532c 100644 --- a/drivers/net/bonding/bond_sysfs_slave.c +++ b/drivers/net/bonding/bond_sysfs_slave.c @@ -125,7 +125,7 @@ int bond_sysfs_slave_add(struct slave *slave) for (a = slave_attrs; *a; ++a) { err = sysfs_create_file(&slave->kobj, &((*a)->attr)); if (err) { - kobject_del(&slave->kobj); + kobject_put(&slave->kobj); return err; } } @@ -140,5 +140,5 @@ void bond_sysfs_slave_del(struct slave *slave) for (a = slave_attrs; *a; ++a) sysfs_remove_file(&slave->kobj, &((*a)->attr)); - kobject_del(&slave->kobj); + kobject_put(&slave->kobj); } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 0b4d9cd..aace510 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -36,7 +36,6 @@ #define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n" -#define BOND_MAX_VLAN_ENCAP 2 #define BOND_MAX_ARP_TARGETS 16 #define BOND_DEFAULT_MIIMON 100 @@ -194,8 +193,8 @@ struct slave { */ struct bonding { struct net_device *dev; /* first - useful for panic debug */ - struct slave *curr_active_slave; - struct slave *current_arp_slave; + struct slave __rcu *curr_active_slave; + struct slave __rcu *current_arp_slave; struct slave *primary_slave; bool force_primary; s32 slave_cnt; /* never change this value outside the attach/detach wrappers */ @@ -232,6 +231,10 @@ struct bonding { #define bond_slave_get_rtnl(dev) \ ((struct slave *) rtnl_dereference(dev->rx_handler_data)) +#define bond_deref_active_protected(bond) \ + rcu_dereference_protected(bond->curr_active_slave, \ + lockdep_is_held(&bond->curr_slave_lock)) + struct bond_vlan_tag { __be16 vlan_proto; unsigned short vlan_id; @@ -265,6 +268,12 @@ static inline bool bond_is_lb(const struct bonding *bond) BOND_MODE(bond) == BOND_MODE_ALB; } +static inline bool bond_is_nondyn_tlb(const struct bonding *bond) +{ + return (BOND_MODE(bond) == BOND_MODE_TLB) && + (bond->params.tlb_dynamic_lb == 0); +} + static inline bool bond_mode_uses_arp(int mode) { return mode != BOND_MODE_8023AD && mode != BOND_MODE_TLB && @@ -514,11 +523,10 @@ unsigned int bond_get_num_tx_queues(void); int bond_netlink_init(void); void bond_netlink_fini(void); struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); -struct net_device *bond_option_active_slave_get(struct bonding *bond); const char *bond_slave_link_status(s8 link); -bool bond_verify_device_path(struct net_device *start_dev, - struct net_device *end_dev, - struct bond_vlan_tag *tags); +struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev, + struct net_device *end_dev, + int level); #ifdef CONFIG_PROC_FS void bond_create_proc_entry(struct bonding *bond); |