The following commit has been merged in the master branch: commit 1e8d6421cff2c24fe0b345711e7a21af02e8bcf5 Merge: f7b12606b5de323a2bb5ca1696558efde8f25441 960dfc4eb23a28495276b02604d7458e0e1a1ed8 Author: David S. Miller davem@davemloft.net Date: Wed Feb 19 01:24:22 2014 -0500
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/bonding/bond_3ad.h drivers/net/bonding/bond_main.c
Two minor conflicts in bonding, both of which were overlapping changes.
Signed-off-by: David S. Miller davem@davemloft.net
diff --combined MAINTAINERS index 5a7b3ec,0dba50b..db8bb0d --- a/MAINTAINERS +++ b/MAINTAINERS @@@ -1845,12 -1845,6 +1845,12 @@@ L: netdev@vger.kernel.or S: Supported F: drivers/net/ethernet/broadcom/b44.*
+BROADCOM GENET ETHERNET DRIVER +M: Florian Fainelli f.fainelli@gmail.com +L: netdev@vger.kernel.org +S: Supported +F: drivers/net/ethernet/broadcom/genet/ + BROADCOM BNX2 GIGABIT ETHERNET DRIVER M: Michael Chan mchan@broadcom.com L: netdev@vger.kernel.org @@@ -2373,7 -2367,7 +2373,7 @@@ F: include/linux/cpufreq.
CPU FREQUENCY DRIVERS - ARM BIG LITTLE M: Viresh Kumar viresh.kumar@linaro.org - M: Sudeep KarkadaNagesha sudeep.karkadanagesha@arm.com + M: Sudeep Holla sudeep.holla@arm.com L: cpufreq@vger.kernel.org L: linux-pm@vger.kernel.org W: http://www.arm.com/products/processors/technologies/biglittleprocessing.php @@@ -2863,7 -2857,7 +2863,7 @@@ M: Jani Nikula <jani.nikula@linux.intel L: intel-gfx@lists.freedesktop.org L: dri-devel@lists.freedesktop.org Q: http://patchwork.freedesktop.org/project/intel-gfx/ - T: git git://people.freedesktop.org/~danvet/drm-intel + T: git git://anongit.freedesktop.org/drm-intel S: Supported F: drivers/gpu/drm/i915/ F: include/drm/i915* @@@ -3330,6 -3324,17 +3330,17 @@@ S: Maintaine F: include/linux/netfilter_bridge/ F: net/bridge/
+ ETHERNET PHY LIBRARY + M: Florian Fainelli f.fainelli@gmail.com + L: netdev@vger.kernel.org + S: Maintained + F: include/linux/phy.h + F: include/linux/phy_fixed.h + F: drivers/net/phy/ + F: Documentation/networking/phy.txt + F: drivers/of/of_mdio.c + F: drivers/of/of_net.c + EXT2 FILE SYSTEM M: Jan Kara jack@suse.cz L: linux-ext4@vger.kernel.org diff --combined drivers/net/bonding/bond_3ad.c index e9edd84,6d20fbd..e362ff7 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@@ -768,11 -768,11 +768,11 @@@ static int ad_lacpdu_send(struct port *
lacpdu_header = (struct lacpdu_header *)skb_put(skb, length);
- memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN); + ether_addr_copy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr); /* Note: source address is set to be the member's PERMANENT address, * because we use it to identify loopback lacpdus in receive. */ - memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN); + ether_addr_copy(lacpdu_header->hdr.h_source, slave->perm_hwaddr); lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU;
lacpdu_header->lacpdu = port->lacpdu; @@@ -810,11 -810,11 +810,11 @@@ static int ad_marker_send(struct port *
marker_header = (struct bond_marker_header *)skb_put(skb, length);
- memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN); + ether_addr_copy(marker_header->hdr.h_dest, lacpdu_mcast_addr); /* Note: source address is set to be the member's PERMANENT address, * because we use it to identify loopback MARKERs in receive. */ - memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN); + ether_addr_copy(marker_header->hdr.h_source, slave->perm_hwaddr); marker_header->hdr.h_proto = PKT_TYPE_LACPDU;
marker_header->marker = *marker; @@@ -1079,8 -1079,7 +1079,8 @@@ static void ad_rx_machine(struct lacpd /* detect loopback situation */ if (MAC_ADDRESS_EQUAL(&(lacpdu->actor_system), &(port->actor_system))) { - pr_err("%s: An illegal loopback occurred on adapter (%s).\nCheck the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", + pr_err("%s: 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; @@@ -1797,8 -1796,6 +1797,6 @@@ void bond_3ad_initiate_agg_selection(st BOND_AD_INFO(bond).agg_select_timer = timeout; }
- static u16 aggregator_identifier; - /** * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures * @bond: bonding struct to work on @@@ -1812,7 -1809,7 +1810,7 @@@ void bond_3ad_initialize(struct bondin if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr), bond->dev->dev_addr)) {
- aggregator_identifier = 0; + BOND_AD_INFO(bond).aggregator_identifier = 0;
BOND_AD_INFO(bond).system.sys_priority = 0xFFFF; BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr); @@@ -1881,7 -1878,7 +1879,7 @@@ void bond_3ad_bind_slave(struct slave * ad_initialize_agg(aggregator);
aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr); - aggregator->aggregator_identifier = (++aggregator_identifier); + aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier; aggregator->slave = slave; aggregator->is_active = 0; aggregator->num_of_ports = 0; @@@ -1951,7 -1948,7 +1949,7 @@@ void bond_3ad_unbind_slave(struct slav * 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 - replaceing with LAG %d\n", + pr_debug("Some port(s) related to LAG %d - replacing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
@@@ -2301,9 -2298,9 +2299,9 @@@ void bond_3ad_handle_link_change(struc port->actor_oper_port_key = (port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS); } - pr_debug("Port %d changed link status to %s", - port->actor_port_number, - (link == BOND_LINK_UP) ? "UP" : "DOWN"); + pr_debug("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 */ diff --combined drivers/net/bonding/bond_3ad.h index 3b97fe48,f4dd959..bb03b1d --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@@ -28,7 -28,7 +28,7 @@@ #include <linux/netdevice.h> #include <linux/if_ether.h>
-// General definitions +/* General definitions */ #define PKT_TYPE_LACPDU cpu_to_be16(ETH_P_SLOW) #define AD_TIMER_INTERVAL 100 /*msec*/
@@@ -47,54 -47,54 +47,54 @@@ enum BOND_AD_COUNT = 2, };
-// rx machine states(43.4.11 in the 802.3ad standard) +/* rx machine states(43.4.11 in the 802.3ad standard) */ typedef enum { AD_RX_DUMMY, - AD_RX_INITIALIZE, // rx Machine - AD_RX_PORT_DISABLED, // rx Machine - AD_RX_LACP_DISABLED, // rx Machine - AD_RX_EXPIRED, // rx Machine - AD_RX_DEFAULTED, // rx Machine - AD_RX_CURRENT // rx Machine + AD_RX_INITIALIZE, /* rx Machine */ + AD_RX_PORT_DISABLED, /* rx Machine */ + AD_RX_LACP_DISABLED, /* rx Machine */ + AD_RX_EXPIRED, /* rx Machine */ + AD_RX_DEFAULTED, /* rx Machine */ + AD_RX_CURRENT /* rx Machine */ } rx_states_t;
-// periodic machine states(43.4.12 in the 802.3ad standard) +/* periodic machine states(43.4.12 in the 802.3ad standard) */ typedef enum { AD_PERIODIC_DUMMY, - AD_NO_PERIODIC, // periodic machine - AD_FAST_PERIODIC, // periodic machine - AD_SLOW_PERIODIC, // periodic machine - AD_PERIODIC_TX // periodic machine + AD_NO_PERIODIC, /* periodic machine */ + AD_FAST_PERIODIC, /* periodic machine */ + AD_SLOW_PERIODIC, /* periodic machine */ + AD_PERIODIC_TX /* periodic machine */ } periodic_states_t;
-// mux machine states(43.4.13 in the 802.3ad standard) +/* mux machine states(43.4.13 in the 802.3ad standard) */ typedef enum { AD_MUX_DUMMY, - AD_MUX_DETACHED, // mux machine - AD_MUX_WAITING, // mux machine - AD_MUX_ATTACHED, // mux machine - AD_MUX_COLLECTING_DISTRIBUTING // mux machine + AD_MUX_DETACHED, /* mux machine */ + AD_MUX_WAITING, /* mux machine */ + AD_MUX_ATTACHED, /* mux machine */ + AD_MUX_COLLECTING_DISTRIBUTING /* mux machine */ } mux_states_t;
-// tx machine states(43.4.15 in the 802.3ad standard) +/* tx machine states(43.4.15 in the 802.3ad standard) */ typedef enum { AD_TX_DUMMY, - AD_TRANSMIT // tx Machine + AD_TRANSMIT /* tx Machine */ } tx_states_t;
-// rx indication types +/* rx indication types */ typedef enum { - AD_TYPE_LACPDU = 1, // type lacpdu - AD_TYPE_MARKER // type marker + AD_TYPE_LACPDU = 1, /* type lacpdu */ + AD_TYPE_MARKER /* type marker */ } pdu_type_t;
-// rx marker indication types +/* rx marker indication types */ typedef enum { - AD_MARKER_INFORMATION_SUBTYPE = 1, // marker imformation subtype - AD_MARKER_RESPONSE_SUBTYPE // marker response subtype + AD_MARKER_INFORMATION_SUBTYPE = 1, /* marker imformation subtype */ + AD_MARKER_RESPONSE_SUBTYPE /* marker response subtype */ } bond_marker_subtype_t;
-// timers types(43.4.9 in the 802.3ad standard) +/* timers types(43.4.9 in the 802.3ad standard) */ typedef enum { AD_CURRENT_WHILE_TIMER, AD_ACTOR_CHURN_TIMER, @@@ -105,35 -105,35 +105,35 @@@
#pragma pack(1)
-// Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard) +/* Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard) */ typedef struct lacpdu { - u8 subtype; // = LACP(= 0x01) + u8 subtype; /* = LACP(= 0x01) */ u8 version_number; - u8 tlv_type_actor_info; // = actor information(type/length/value) - u8 actor_information_length; // = 20 + u8 tlv_type_actor_info; /* = actor information(type/length/value) */ + u8 actor_information_length; /* = 20 */ __be16 actor_system_priority; struct mac_addr actor_system; __be16 actor_key; __be16 actor_port_priority; __be16 actor_port; u8 actor_state; - u8 reserved_3_1[3]; // = 0 - u8 tlv_type_partner_info; // = partner information - u8 partner_information_length; // = 20 + u8 reserved_3_1[3]; /* = 0 */ + u8 tlv_type_partner_info; /* = partner information */ + u8 partner_information_length; /* = 20 */ __be16 partner_system_priority; struct mac_addr partner_system; __be16 partner_key; __be16 partner_port_priority; __be16 partner_port; u8 partner_state; - u8 reserved_3_2[3]; // = 0 - u8 tlv_type_collector_info; // = collector information - u8 collector_information_length; // = 16 + u8 reserved_3_2[3]; /* = 0 */ + u8 tlv_type_collector_info; /* = collector information */ + u8 collector_information_length;/* = 16 */ __be16 collector_max_delay; u8 reserved_12[12]; - u8 tlv_type_terminator; // = terminator - u8 terminator_length; // = 0 - u8 reserved_50[50]; // = 0 + u8 tlv_type_terminator; /* = terminator */ + u8 terminator_length; /* = 0 */ + u8 reserved_50[50]; /* = 0 */ } __packed lacpdu_t;
typedef struct lacpdu_header { @@@ -141,20 -141,20 +141,20 @@@ struct lacpdu lacpdu; } __packed lacpdu_header_t;
-// Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard) +/* Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard) */ typedef struct bond_marker { - u8 subtype; // = 0x02 (marker PDU) - u8 version_number; // = 0x01 - u8 tlv_type; // = 0x01 (marker information) - // = 0x02 (marker response information) - u8 marker_length; // = 0x16 - u16 requester_port; // The number assigned to the port by the requester - struct mac_addr requester_system; // The requester's system id - u32 requester_transaction_id; // The transaction id allocated by the requester, - u16 pad; // = 0 - u8 tlv_type_terminator; // = 0x00 - u8 terminator_length; // = 0x00 - u8 reserved_90[90]; // = 0 + u8 subtype; /* = 0x02 (marker PDU) */ + u8 version_number; /* = 0x01 */ + u8 tlv_type; /* = 0x01 (marker information) */ + /* = 0x02 (marker response information) */ + u8 marker_length; /* = 0x16 */ + u16 requester_port; /* The number assigned to the port by the requester */ + struct mac_addr requester_system; /* The requester's system id */ + u32 requester_transaction_id; /* The transaction id allocated by the requester, */ + u16 pad; /* = 0 */ + u8 tlv_type_terminator; /* = 0x00 */ + u8 terminator_length; /* = 0x00 */ + u8 reserved_90[90]; /* = 0 */ } __packed bond_marker_t;
typedef struct bond_marker_header { @@@ -173,7 -173,7 +173,7 @@@ struct port #pragma pack(8) #endif
-// aggregator structure(43.4.5 in the 802.3ad standard) +/* aggregator structure(43.4.5 in the 802.3ad standard) */ typedef struct aggregator { struct mac_addr aggregator_mac_address; u16 aggregator_identifier; @@@ -183,12 -183,12 +183,12 @@@ struct mac_addr partner_system; u16 partner_system_priority; u16 partner_oper_aggregator_key; - u16 receive_state; // BOOLEAN - u16 transmit_state; // BOOLEAN + u16 receive_state; /* BOOLEAN */ + u16 transmit_state; /* BOOLEAN */ struct port *lag_ports; - // ****** PRIVATE PARAMETERS ****** - struct slave *slave; // pointer to the bond slave that this aggregator belongs to - u16 is_active; // BOOLEAN. Indicates if this aggregator is active + /* ****** PRIVATE PARAMETERS ****** */ + struct slave *slave; /* pointer to the bond slave that this aggregator belongs to */ + u16 is_active; /* BOOLEAN. Indicates if this aggregator is active */ u16 num_of_ports; } aggregator_t;
@@@ -201,12 -201,12 +201,12 @@@ struct port_params u16 port_state; };
-// port structure(43.4.6 in the 802.3ad standard) +/* port structure(43.4.6 in the 802.3ad standard) */ typedef struct port { u16 actor_port_number; u16 actor_port_priority; - struct mac_addr actor_system; // This parameter is added here although it is not specified in the standard, just for simplification - u16 actor_system_priority; // This parameter is added here although it is not specified in the standard, just for simplification + struct mac_addr actor_system; /* This parameter is added here although it is not specified in the standard, just for simplification */ + u16 actor_system_priority; /* This parameter is added here although it is not specified in the standard, just for simplification */ u16 actor_port_aggregator_identifier; bool ntt; u16 actor_admin_port_key; @@@ -219,24 -219,24 +219,24 @@@
bool is_enabled;
- // ****** PRIVATE PARAMETERS ****** - u16 sm_vars; // all state machines variables for this port - rx_states_t sm_rx_state; // state machine rx state - u16 sm_rx_timer_counter; // state machine rx timer counter - periodic_states_t sm_periodic_state;// state machine periodic state - u16 sm_periodic_timer_counter; // state machine periodic timer counter - mux_states_t sm_mux_state; // state machine mux state - u16 sm_mux_timer_counter; // state machine mux timer counter - tx_states_t sm_tx_state; // state machine tx state - u16 sm_tx_timer_counter; // state machine tx timer counter(allways on - enter to transmit state 3 time per second) - struct slave *slave; // pointer to the bond slave that this port belongs to - struct aggregator *aggregator; // pointer to an aggregator that this port related to - struct port *next_port_in_aggregator; // Next port on the linked list of the parent aggregator - u32 transaction_id; // continuous number for identification of Marker PDU's; - struct lacpdu lacpdu; // the lacpdu that will be sent for this port + /* ****** PRIVATE PARAMETERS ****** */ + u16 sm_vars; /* all state machines variables for this port */ + rx_states_t sm_rx_state; /* state machine rx state */ + u16 sm_rx_timer_counter; /* state machine rx timer counter */ + periodic_states_t sm_periodic_state; /* state machine periodic state */ + u16 sm_periodic_timer_counter; /* state machine periodic timer counter */ + mux_states_t sm_mux_state; /* state machine mux state */ + u16 sm_mux_timer_counter; /* state machine mux timer counter */ + tx_states_t sm_tx_state; /* state machine tx state */ + u16 sm_tx_timer_counter; /* state machine tx timer counter(allways on - enter to transmit state 3 time per second) */ + struct slave *slave; /* pointer to the bond slave that this port belongs to */ + struct aggregator *aggregator; /* pointer to an aggregator that this port related to */ + struct port *next_port_in_aggregator; /* Next port on the linked list of the parent aggregator */ + u32 transaction_id; /* continuous number for identification of Marker PDU's; */ + struct lacpdu lacpdu; /* the lacpdu that will be sent for this port */ } port_t;
-// system structure +/* system structure */ struct ad_system { u16 sys_priority; struct mac_addr sys_mac_addr; @@@ -246,25 -246,27 +246,26 @@@ #pragma pack() #endif
-// ================= AD Exported structures to the main bonding code ================== +/* ========== AD Exported structures to the main bonding code ========== */ #define BOND_AD_INFO(bond) ((bond)->ad_info) #define SLAVE_AD_INFO(slave) ((slave)->ad_info)
struct ad_bond_info { - struct ad_system system; /* 802.3ad system structure */ - u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes + struct ad_system system; /* 802.3ad system structure */ + u32 agg_select_timer; /* Timer to select aggregator after all adapter's hand shakes */ + u16 aggregator_identifier; };
struct ad_slave_info { - struct aggregator aggregator; // 802.3ad aggregator structure - struct port port; // 802.3ad port structure - spinlock_t state_machine_lock; /* mutex state machines vs. - incoming LACPDU */ + struct aggregator aggregator; /* 802.3ad aggregator structure */ + struct port port; /* 802.3ad port structure */ + spinlock_t state_machine_lock; /* mutex state machines vs. incoming LACPDU */ u16 id; };
-// ================= AD Exported functions to the main bonding code ================== +/* ========== AD Exported functions to the main bonding code ========== */ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution); -void bond_3ad_bind_slave(struct slave *slave); +void bond_3ad_bind_slave(struct slave *slave); void bond_3ad_unbind_slave(struct slave *slave); void bond_3ad_state_machine_handler(struct work_struct *); void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout); @@@ -279,5 -281,5 +280,5 @@@ int bond_3ad_lacpdu_recv(const struct s struct slave *slave); int bond_3ad_set_carrier(struct bonding *bond); void bond_3ad_update_lacp_rate(struct bonding *bond); -#endif //__BOND_3AD_H__ +#endif /* __BOND_3AD_H__ */
diff --combined drivers/net/bonding/bond_main.c index ac4a1b8,1c6104d..afae7ca --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@@ -673,12 -673,12 +673,12 @@@ static void bond_do_fail_over_mac(struc write_unlock_bh(&bond->curr_slave_lock);
if (old_active) { - memcpy(tmp_mac, new_active->dev->dev_addr, ETH_ALEN); + ether_addr_copy(tmp_mac, new_active->dev->dev_addr); memcpy(saddr.sa_data, old_active->dev->dev_addr, ETH_ALEN); saddr.sa_family = new_active->dev->type; } else { - memcpy(saddr.sa_data, bond->dev->dev_addr, ETH_ALEN); + ether_addr_copy(saddr.sa_data, bond->dev->dev_addr); saddr.sa_family = bond->dev->type; }
@@@ -692,7 -692,7 +692,7 @@@ if (!old_active) goto out;
- memcpy(saddr.sa_data, tmp_mac, ETH_ALEN); + ether_addr_copy(saddr.sa_data, tmp_mac); saddr.sa_family = old_active->dev->type;
rv = dev_set_mac_address(old_active->dev, &saddr); @@@ -798,11 -798,11 +798,11 @@@ void bond_change_active_slave(struct bo return;
if (new_active) { - new_active->jiffies = jiffies; + new_active->last_link_up = jiffies;
if (new_active->link == BOND_LINK_BACK) { if (USES_PRIMARY(bond->params.mode)) { - pr_info("%s: making interface %s the new active one %d ms earlier.\n", + 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); } @@@ -817,7 -817,7 +817,7 @@@ bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP); } else { if (USES_PRIMARY(bond->params.mode)) { - pr_info("%s: making interface %s the new active one.\n", + pr_info("%s: making interface %s the new active one\n", bond->dev->name, new_active->dev->name); } } @@@ -906,7 -906,7 +906,7 @@@ void bond_select_active_slave(struct bo pr_info("%s: first active interface up!\n", bond->dev->name); } else { - pr_info("%s: now running without any active interface !\n", + pr_info("%s: now running without any active interface!\n", bond->dev->name); } } @@@ -1115,6 -1115,9 +1115,6 @@@ static rx_handler_result_t bond_handle_ slave = bond_slave_get_rcu(skb->dev); bond = slave->bond;
- if (bond->params.arp_interval) - slave->dev->last_rx = jiffies; - recv_probe = ACCESS_ONCE(bond->recv_probe); if (recv_probe) { ret = recv_probe(skb, bond, slave); @@@ -1180,13 -1183,13 +1180,13 @@@ int bond_enslave(struct net_device *bon if (!bond->params.use_carrier && slave_dev->ethtool_ops->get_link == NULL && slave_ops->ndo_do_ioctl == NULL) { - pr_warning("%s: Warning: no link monitoring support for %s\n", - bond_dev->name, slave_dev->name); + pr_warn("%s: Warning: no link monitoring support for %s\n", + bond_dev->name, slave_dev->name); }
/* already enslaved */ if (slave_dev->flags & IFF_SLAVE) { - pr_debug("Error, Device was already enslaved\n"); + pr_debug("Error: Device was already enslaved\n"); return -EBUSY; }
@@@ -1199,9 -1202,9 +1199,9 @@@ bond_dev->name, slave_dev->name, bond_dev->name); return -EPERM; } else { - pr_warning("%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); + 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); } } else { pr_debug("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); @@@ -1214,7 -1217,7 +1214,7 @@@ * 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", + pr_err("%s is up - this may be due to an out of date ifenslave\n", slave_dev->name); res = -EPERM; goto err_undo_flags; @@@ -1258,23 -1261,24 +1258,23 @@@ 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); + 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); 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", + pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address\n", bond_dev->name); if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { bond->params.fail_over_mac = BOND_FOM_ACTIVE; - pr_warn("%s: Setting fail_over_mac to active for active-backup mode.\n", + pr_warn("%s: Setting fail_over_mac to active for active-backup mode\n", bond_dev->name); } } 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", + 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; @@@ -1313,7 -1317,7 +1313,7 @@@ * that need it, and for restoring it upon release, and then * set it to the master's address */ - memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); + ether_addr_copy(new_slave->perm_hwaddr, slave_dev->dev_addr);
if (!bond->params.fail_over_mac || bond->params.mode != BOND_MODE_ACTIVEBACKUP) { @@@ -1397,10 -1401,10 +1397,10 @@@
bond_update_speed_duplex(new_slave);
- new_slave->last_arp_rx = jiffies - + new_slave->last_rx = jiffies - (msecs_to_jiffies(bond->params.arp_interval) + 1); for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) - new_slave->target_last_arp_rx[i] = new_slave->last_arp_rx; + new_slave->target_last_arp_rx[i] = new_slave->last_rx;
if (bond->params.miimon && !bond->params.use_carrier) { link_reporting = bond_check_dev_link(bond, slave_dev, 1); @@@ -1415,12 -1419,12 +1415,12 @@@ * supported); thus, we don't need to change * the messages for netif_carrier. */ - pr_warning("%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); + 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); } else if (link_reporting == -1) { /* unable get link status using mii/ethtool */ - pr_warning("%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); + 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); } }
@@@ -1444,10 -1448,10 +1444,10 @@@ }
if (new_slave->link != BOND_LINK_DOWN) - new_slave->jiffies = jiffies; + 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")); + new_slave->link == BOND_LINK_DOWN ? "DOWN" : + (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { /* if there is a primary slave, remember it */ @@@ -1506,8 -1510,9 +1506,8 @@@ 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); + pr_info("Error, %s: master_dev is using netpoll, but new slave device does not support netpoll\n", + bond_dev->name); res = -EBUSY; goto err_detach; } @@@ -1538,15 -1543,17 +1538,17 @@@ bond_set_carrier(bond);
if (USES_PRIMARY(bond->params.mode)) { + block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); + unblock_netpoll_tx(); }
- pr_info("%s: enslaving %s as a%s interface with a%s link.\n", + pr_info("%s: Enslaving %s as %s interface with %s link\n", bond_dev->name, slave_dev->name, - bond_is_active_slave(new_slave) ? "n active" : " backup", - new_slave->link != BOND_LINK_DOWN ? "n up" : " down"); + 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; @@@ -1566,10 -1573,12 +1568,12 @@@ err_detach if (bond->primary_slave == new_slave) bond->primary_slave = NULL; if (bond->curr_active_slave == new_slave) { + block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_change_active_slave(bond, NULL); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); + unblock_netpoll_tx(); } slave_disable_netpoll(new_slave);
@@@ -1584,7 -1593,7 +1588,7 @@@ err_restore_mac * MAC if this slave's MAC is in use by the bond, or at * least print a warning. */ - memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN); + ether_addr_copy(addr.sa_data, new_slave->perm_hwaddr); addr.sa_family = slave_dev->type; dev_set_mac_address(slave_dev, &addr); } @@@ -1629,7 -1638,7 +1633,7 @@@ static int __bond_release_one(struct ne /* 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", + pr_err("%s: Error: cannot release %s\n", bond_dev->name, slave_dev->name); return -EINVAL; } @@@ -1663,7 -1672,7 +1667,7 @@@
write_unlock_bh(&bond->lock);
- pr_info("%s: releasing %s interface %s\n", + pr_info("%s: Releasing %s interface %s\n", bond_dev->name, bond_is_active_slave(slave) ? "active" : "backup", slave_dev->name); @@@ -1676,10 -1685,10 +1680,10 @@@ bond->params.mode != 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); + 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); }
if (bond->primary_slave == slave) @@@ -1720,10 -1729,10 +1724,10 @@@ eth_hw_addr_random(bond_dev);
if (vlan_uses_dev(bond_dev)) { - pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n", - bond_dev->name, bond_dev->name); - pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n", - bond_dev->name); + 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); } }
@@@ -1738,7 -1747,7 +1742,7 @@@ 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", + 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);
/* must do this from outside any spinlocks */ @@@ -1773,7 -1782,7 +1777,7 @@@ if (bond->params.fail_over_mac != BOND_FOM_ACTIVE || bond->params.mode != BOND_MODE_ACTIVEBACKUP) { /* restore original ("permanent") mac address */ - memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); + ether_addr_copy(addr.sa_data, slave->perm_hwaddr); addr.sa_family = slave_dev->type; dev_set_mac_address(slave_dev, &addr); } @@@ -1806,7 -1815,7 +1810,7 @@@ static int bond_release_and_destroy(st 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", + pr_info("%s: Destroying bond %s\n", bond_dev->name, bond_dev->name); unregister_netdevice(bond_dev); } @@@ -1875,7 -1884,7 +1879,7 @@@ static int bond_miimon_inspect(struct b 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", + pr_info("%s: link status down for %sinterface %s, disabling it in %d ms\n", bond->dev->name, (bond->params.mode == BOND_MODE_ACTIVEBACKUP) ? @@@ -1891,8 -1900,8 +1895,8 @@@ * recovered before downdelay expired */ slave->link = BOND_LINK_UP; - slave->jiffies = jiffies; - pr_info("%s: link status up again after %d ms for interface %s.\n", + 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, @@@ -1917,7 -1926,7 +1921,7 @@@ slave->delay = bond->params.updelay;
if (slave->delay) { - pr_info("%s: link status up for interface %s, enabling it in %d ms.\n", + 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 * @@@ -1927,7 -1936,7 +1931,7 @@@ 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", + 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, @@@ -1966,7 -1975,7 +1970,7 @@@ static void bond_miimon_commit(struct b
case BOND_LINK_UP: slave->link = BOND_LINK_UP; - slave->jiffies = jiffies; + slave->last_link_up = jiffies;
if (bond->params.mode == BOND_MODE_8023AD) { /* prevent it from being the active one */ @@@ -1979,7 -1988,7 +1983,7 @@@ bond_set_backup_slave(slave); }
- pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n", + 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"); @@@ -2127,8 -2136,8 +2131,8 @@@ static void bond_arp_send(struct net_de { struct sk_buff *skb;
- pr_debug("arp %d on slave %s: dst %pI4 src %pI4 vid %d\n", arp_op, - slave_dev->name, &dest_ip, &src_ip, vlan_id); + pr_debug("arp %d on slave %s: dst %pI4 src %pI4 vid %d\n", + arp_op, slave_dev->name, &dest_ip, &src_ip, vlan_id);
skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip, NULL, slave_dev->dev_addr, NULL); @@@ -2242,7 -2251,7 +2246,7 @@@ static void bond_validate_arp(struct bo pr_debug("bva: sip %pI4 not found in targets\n", &sip); return; } - slave->last_arp_rx = jiffies; + slave->last_rx = jiffies; slave->target_last_arp_rx[i] = jiffies; }
@@@ -2252,16 -2261,15 +2256,16 @@@ int bond_arp_rcv(const struct sk_buff * struct arphdr *arp = (struct arphdr *)skb->data; unsigned char *arp_ptr; __be32 sip, tip; - int alen; + int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
- if (skb->protocol != __cpu_to_be16(ETH_P_ARP)) + if (!slave_do_arp_validate(bond, slave)) { + if ((slave_do_arp_validate_only(bond, slave) && is_arp) || + !slave_do_arp_validate_only(bond, slave)) + slave->last_rx = jiffies; return RX_HANDLER_ANOTHER; - - read_lock(&bond->lock); - - if (!slave_do_arp_validate(bond, slave)) - goto out_unlock; + } else if (!is_arp) { + return RX_HANDLER_ANOTHER; + }
alen = arp_hdr_len(bond->dev);
@@@ -2312,10 -2320,11 +2316,10 @@@ bond_validate_arp(bond, slave, sip, tip); else if (bond->curr_active_slave && time_after(slave_last_rx(bond, bond->curr_active_slave), - bond->curr_active_slave->jiffies)) + bond->curr_active_slave->last_link_up)) bond_validate_arp(bond, slave, tip, sip);
out_unlock: - read_unlock(&bond->lock); if (arp != (struct arphdr *)skb->data) kfree(arp); return RX_HANDLER_ANOTHER; @@@ -2358,9 -2367,9 +2362,9 @@@ static void bond_loadbalance_arp_mon(st oldcurrent = ACCESS_ONCE(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->jiffies is not needed - * here because we send an arp on each slave and give a slave as - * long as it needs to get the tx/rx within the delta. + * the picture unless it is null. also, slave->last_link_up is not + * needed here because we send an arp on each slave and give a slave + * as long as it needs to get the tx/rx within the delta. * TODO: what about up/down delay in arp mode? it wasn't here before * so it can wait */ @@@ -2369,7 -2378,7 +2373,7 @@@
if (slave->link != BOND_LINK_UP) { if (bond_time_in_interval(bond, trans_start, 1) && - bond_time_in_interval(bond, slave->dev->last_rx, 1)) { + bond_time_in_interval(bond, slave->last_rx, 1)) {
slave->link = BOND_LINK_UP; slave_state_changed = 1; @@@ -2380,7 -2389,7 +2384,7 @@@ * is closed. */ if (!oldcurrent) { - pr_info("%s: link status definitely up for interface %s, ", + pr_info("%s: link status definitely up for interface %s\n", bond->dev->name, slave->dev->name); do_failover = 1; @@@ -2398,7 -2407,7 +2402,7 @@@ * if we don't know our ip yet */ if (!bond_time_in_interval(bond, trans_start, 2) || - !bond_time_in_interval(bond, slave->dev->last_rx, 2)) { + !bond_time_in_interval(bond, slave->last_rx, 2)) {
slave->link = BOND_LINK_DOWN; slave_state_changed = 1; @@@ -2406,8 -2415,9 +2410,8 @@@ 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); + pr_info("%s: interface %s is now down\n", + bond->dev->name, slave->dev->name);
if (slave == oldcurrent) do_failover = 1; @@@ -2486,7 -2496,7 +2490,7 @@@ static int bond_ab_arp_inspect(struct b * active. This avoids bouncing, as the last receive * times need a full ARP monitor cycle to be updated. */ - if (bond_time_in_interval(bond, slave->jiffies, 2)) + if (bond_time_in_interval(bond, slave->last_link_up, 2)) continue;
/* @@@ -2556,7 -2566,7 +2560,7 @@@ static void bond_ab_arp_commit(struct b bond->current_arp_slave = NULL; }
- pr_info("%s: link status definitely up for interface %s.\n", + pr_info("%s: link status definitely up for interface %s\n", bond->dev->name, slave->dev->name);
if (!bond->curr_active_slave || @@@ -2669,7 -2679,7 +2673,7 @@@ static bool bond_ab_arp_probe(struct bo
bond_set_slave_inactive_flags(slave);
- pr_info("%s: backup interface %s is now down.\n", + pr_info("%s: backup interface %s is now down\n", bond->dev->name, slave->dev->name); } if (slave == curr_arp_slave) @@@ -2687,7 -2697,7 +2691,7 @@@ new_slave->link = BOND_LINK_BACK; bond_set_slave_active_flags(new_slave); bond_arp_send_all(bond, new_slave); - new_slave->jiffies = jiffies; + new_slave->last_link_up = jiffies; rcu_assign_pointer(bond->current_arp_slave, new_slave); rtnl_unlock();
@@@ -2855,12 -2865,15 +2859,15 @@@ static int bond_slave_netdev_event(unsi break; }
- pr_info("%s: Primary slave changed to %s, reselecting active slave.\n", - bond->dev->name, bond->primary_slave ? slave_dev->name : - "none"); + pr_info("%s: Primary slave changed to %s, reselecting active slave\n", + bond->dev->name, + bond->primary_slave ? slave_dev->name : "none"); + + block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); + unblock_netpoll_tx(); break; case NETDEV_FEAT_CHANGE: bond_compute_features(bond); @@@ -2890,7 -2903,8 +2897,7 @@@ static int bond_netdev_event(struct not 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); + event_dev ? event_dev->name : "None", event);
if (!(event_dev->priv_flags & IFF_BONDING)) return NOTIFY_DONE; @@@ -3057,7 -3071,8 +3064,7 @@@ static int bond_open(struct net_device
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */ queue_delayed_work(bond->wq, &bond->arp_work, 0); - if (bond->params.arp_validate) - bond->recv_probe = bond_arp_rcv; + bond->recv_probe = bond_arp_rcv; }
if (bond->params.mode == BOND_MODE_8023AD) { @@@ -3344,8 -3359,8 +3351,8 @@@ static int bond_change_mtu(struct net_d 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); + pr_debug("bond=%p, name=%s, new_mtu=%d\n", + bond, bond_dev ? bond_dev->name : "None", new_mtu);
/* Can't hold bond->lock with bh disabled here since * some base drivers panic. On the other hand we can't @@@ -3364,7 -3379,8 +3371,7 @@@
bond_for_each_slave(bond, slave, iter) { pr_debug("s %p c_m %p\n", - slave, - slave->dev->netdev_ops->ndo_change_mtu); + slave, slave->dev->netdev_ops->ndo_change_mtu);
res = dev_set_mtu(slave->dev, new_mtu);
@@@ -3452,7 -3468,15 +3459,7 @@@ static int bond_set_mac_address(struct */
bond_for_each_slave(bond, slave, iter) { - const struct net_device_ops *slave_ops = slave->dev->netdev_ops; pr_debug("slave %p %s\n", slave, slave->dev->name); - - if (slave_ops->ndo_set_mac_address == NULL) { - res = -EOPNOTSUPP; - pr_debug("EOPNOTSUPP %s\n", slave->dev->name); - goto unwind; - } - res = dev_set_mac_address(slave->dev, addr); if (res) { /* TODO: consider downing the slave @@@ -3683,7 -3707,7 +3690,7 @@@ static inline int bond_slave_override(s
static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { /* * This helper function exists to help dev_pick_tx get the correct @@@ -3918,7 -3942,7 +3925,7 @@@ static void bond_uninit(struct net_devi /* 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); + pr_info("%s: Released all slaves\n", bond_dev->name);
list_del(&bond->bond_list);
@@@ -3996,7 -4020,7 +4003,7 @@@ static int bond_check_params(struct bon if ((bond_mode != BOND_MODE_XOR) && (bond_mode != BOND_MODE_8023AD)) { pr_info("xmit_hash_policy param is irrelevant in mode %s\n", - bond_mode_name(bond_mode)); + bond_mode_name(bond_mode)); } else { bond_opt_initstr(&newval, xmit_hash_policy); valptr = bond_opt_parse(bond_opt_get(BOND_OPT_XMIT_HASH), @@@ -4037,71 -4061,74 +4044,71 @@@ } params->ad_select = valptr->value; if (bond_mode != BOND_MODE_8023AD) - pr_warning("ad_select param only affects 802.3ad mode\n"); + pr_warn("ad_select param only affects 802.3ad mode\n"); } else { params->ad_select = BOND_AD_STABLE; }
if (max_bonds < 0) { - pr_warning("Warning: max_bonds (%d) not in range %d-%d, so it was reset to BOND_DEFAULT_MAX_BONDS (%d)\n", - max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS); + pr_warn("Warning: max_bonds (%d) not in range %d-%d, so it was reset to BOND_DEFAULT_MAX_BONDS (%d)\n", + max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS); max_bonds = BOND_DEFAULT_MAX_BONDS; }
if (miimon < 0) { - pr_warning("Warning: miimon module parameter (%d), not in range 0-%d, so it was reset to 0\n", - miimon, INT_MAX); + pr_warn("Warning: miimon module parameter (%d), not in range 0-%d, so it was reset to 0\n", + miimon, INT_MAX); miimon = 0; }
if (updelay < 0) { - pr_warning("Warning: updelay module parameter (%d), not in range 0-%d, so it was reset to 0\n", - updelay, INT_MAX); + pr_warn("Warning: updelay module parameter (%d), not in range 0-%d, so it was reset to 0\n", + updelay, INT_MAX); updelay = 0; }
if (downdelay < 0) { - pr_warning("Warning: downdelay module parameter (%d), not in range 0-%d, so it was reset to 0\n", - downdelay, INT_MAX); + pr_warn("Warning: downdelay module parameter (%d), not in range 0-%d, so it was reset to 0\n", + downdelay, INT_MAX); downdelay = 0; }
if ((use_carrier != 0) && (use_carrier != 1)) { - pr_warning("Warning: use_carrier module parameter (%d), not of valid value (0/1), so it was set to 1\n", - use_carrier); + pr_warn("Warning: use_carrier module parameter (%d), not of valid value (0/1), so it was set to 1\n", + use_carrier); use_carrier = 1; }
if (num_peer_notif < 0 || num_peer_notif > 255) { - pr_warning("Warning: num_grat_arp/num_unsol_na (%d) not in range 0-255 so it was reset to 1\n", - num_peer_notif); + pr_warn("Warning: num_grat_arp/num_unsol_na (%d) not in range 0-255 so it was reset to 1\n", + num_peer_notif); num_peer_notif = 1; }
/* reset values for 802.3ad/TLB/ALB */ if (BOND_NO_USES_ARP(bond_mode)) { if (!miimon) { - pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n"); - pr_warning("Forcing miimon to 100msec\n"); + pr_warn("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n"); + pr_warn("Forcing miimon to 100msec\n"); miimon = BOND_DEFAULT_MIIMON; } }
if (tx_queues < 1 || tx_queues > 255) { - pr_warning("Warning: tx_queues (%d) should be between " - "1 and 255, resetting to %d\n", - tx_queues, BOND_DEFAULT_TX_QUEUES); + pr_warn("Warning: tx_queues (%d) should be between 1 and 255, resetting to %d\n", + tx_queues, BOND_DEFAULT_TX_QUEUES); tx_queues = BOND_DEFAULT_TX_QUEUES; }
if ((all_slaves_active != 0) && (all_slaves_active != 1)) { - pr_warning("Warning: all_slaves_active module parameter (%d), " - "not of valid value (0/1), so it was set to " - "0\n", all_slaves_active); + pr_warn("Warning: all_slaves_active module parameter (%d), not of valid value (0/1), so it was set to 0\n", + all_slaves_active); all_slaves_active = 0; }
if (resend_igmp < 0 || resend_igmp > 255) { - pr_warning("Warning: resend_igmp (%d) should be between " - "0 and 255, resetting to %d\n", - resend_igmp, BOND_DEFAULT_RESEND_IGMP); + pr_warn("Warning: resend_igmp (%d) should be between 0 and 255, resetting to %d\n", + resend_igmp, BOND_DEFAULT_RESEND_IGMP); resend_igmp = BOND_DEFAULT_RESEND_IGMP; }
@@@ -4122,36 -4149,37 +4129,36 @@@ /* just warn the user the up/down delay will have * no effect since miimon is zero... */ - pr_warning("Warning: miimon module parameter not set and updelay (%d) or downdelay (%d) module parameter is set; updelay and downdelay have no effect unless miimon is set\n", - updelay, downdelay); + pr_warn("Warning: miimon module parameter not set and updelay (%d) or downdelay (%d) module parameter is set; updelay and downdelay have no effect unless miimon is set\n", + updelay, downdelay); } } else { /* don't allow arp monitoring */ if (arp_interval) { - pr_warning("Warning: miimon (%d) and arp_interval (%d) can't be used simultaneously, disabling ARP monitoring\n", - miimon, arp_interval); + pr_warn("Warning: miimon (%d) and arp_interval (%d) can't be used simultaneously, disabling ARP monitoring\n", + miimon, arp_interval); arp_interval = 0; }
if ((updelay % miimon) != 0) { - pr_warning("Warning: updelay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n", - updelay, miimon, - (updelay / miimon) * miimon); + pr_warn("Warning: updelay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n", + updelay, miimon, (updelay / miimon) * miimon); }
updelay /= miimon;
if ((downdelay % miimon) != 0) { - pr_warning("Warning: downdelay (%d) is not a multiple of miimon (%d), downdelay rounded to %d ms\n", - downdelay, miimon, - (downdelay / miimon) * miimon); + pr_warn("Warning: downdelay (%d) is not a multiple of miimon (%d), downdelay rounded to %d ms\n", + downdelay, miimon, + (downdelay / miimon) * miimon); }
downdelay /= miimon; }
if (arp_interval < 0) { - pr_warning("Warning: arp_interval module parameter (%d) , not in range 0-%d, so it was reset to 0\n", - arp_interval, INT_MAX); + pr_warn("Warning: arp_interval module parameter (%d), not in range 0-%d, so it was reset to 0\n", + arp_interval, INT_MAX); arp_interval = 0; }
@@@ -4162,26 -4190,30 +4169,26 @@@ __be32 ip; if (!in4_pton(arp_ip_target[i], -1, (u8 *)&ip, -1, NULL) || IS_IP_TARGET_UNUSABLE_ADDRESS(ip)) { - pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n", - arp_ip_target[i]); + pr_warn("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n", + arp_ip_target[i]); arp_interval = 0; } else { if (bond_get_targets_ip(arp_target, ip) == -1) arp_target[arp_ip_count++] = ip; else - pr_warning("Warning: duplicate address %pI4 in arp_ip_target, skipping\n", - &ip); + pr_warn("Warning: duplicate address %pI4 in arp_ip_target, skipping\n", + &ip); } }
if (arp_interval && !arp_ip_count) { /* don't allow arping if no arp_ip_target given... */ - pr_warning("Warning: arp_interval module parameter (%d) specified without providing an arp_ip_target parameter, arp_interval was reset to 0\n", - arp_interval); + pr_warn("Warning: arp_interval module parameter (%d) specified without providing an arp_ip_target parameter, arp_interval was reset to 0\n", + arp_interval); arp_interval = 0; }
if (arp_validate) { - if (bond_mode != BOND_MODE_ACTIVEBACKUP) { - pr_err("arp_validate only supported in active-backup mode\n"); - return -EINVAL; - } if (!arp_interval) { pr_err("arp_validate requires arp_interval\n"); return -EINVAL; @@@ -4223,23 -4255,23 +4230,23 @@@ arp_interval, valptr->string, arp_ip_count);
for (i = 0; i < arp_ip_count; i++) - pr_info(" %s", arp_ip_target[i]); + pr_cont(" %s", arp_ip_target[i]);
- pr_info("\n"); + pr_cont("\n");
} else if (max_bonds) { /* miimon and arp_interval not set, we need one so things * work as expected, see bonding.txt for details */ - pr_debug("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n"); + pr_debug("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details\n"); }
if (primary && !USES_PRIMARY(bond_mode)) { /* currently, using a primary only makes sense * in active backup, TLB or ALB modes */ - pr_warning("Warning: %s primary device specified but has no effect in %s mode\n", - primary, bond_mode_name(bond_mode)); + pr_warn("Warning: %s primary device specified but has no effect in %s mode\n", + primary, bond_mode_name(bond_mode)); primary = NULL; }
@@@ -4268,14 -4300,14 +4275,14 @@@ } fail_over_mac_value = valptr->value; if (bond_mode != BOND_MODE_ACTIVEBACKUP) - pr_warning("Warning: fail_over_mac only affects active-backup mode.\n"); + pr_warn("Warning: fail_over_mac only affects active-backup mode\n"); } else { fail_over_mac_value = BOND_FOM_NONE; }
if (lp_interval == 0) { - pr_warning("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n", - INT_MAX, BOND_ALB_DEFAULT_LP_INTERVAL); + pr_warn("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n", + INT_MAX, BOND_ALB_DEFAULT_LP_INTERVAL); lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL; }
diff --combined drivers/net/bonding/bond_options.c index 5f997b9,c378784..23f3655 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@@ -14,7 -14,7 +14,7 @@@ #include <linux/errno.h> #include <linux/if.h> #include <linux/netdevice.h> - #include <linux/rwlock.h> + #include <linux/spinlock.h> #include <linux/rcupdate.h> #include <linux/ctype.h> #include <linux/inet.h> @@@ -47,14 -47,11 +47,14 @@@ static struct bond_opt_value bond_xmit_ };
static struct bond_opt_value bond_arp_validate_tbl[] = { - { "none", BOND_ARP_VALIDATE_NONE, BOND_VALFLAG_DEFAULT}, - { "active", BOND_ARP_VALIDATE_ACTIVE, 0}, - { "backup", BOND_ARP_VALIDATE_BACKUP, 0}, - { "all", BOND_ARP_VALIDATE_ALL, 0}, - { NULL, -1, 0}, + { "none", BOND_ARP_VALIDATE_NONE, BOND_VALFLAG_DEFAULT}, + { "active", BOND_ARP_VALIDATE_ACTIVE, 0}, + { "backup", BOND_ARP_VALIDATE_BACKUP, 0}, + { "all", BOND_ARP_VALIDATE_ALL, 0}, + { "filter", BOND_ARP_FILTER, 0}, + { "filter_active", BOND_ARP_FILTER_ACTIVE, 0}, + { "filter_backup", BOND_ARP_FILTER_BACKUP, 0}, + { NULL, -1, 0}, };
static struct bond_opt_value bond_arp_all_targets_tbl[] = { @@@ -154,8 -151,7 +154,8 @@@ static struct bond_option bond_opts[] .id = BOND_OPT_ARP_VALIDATE, .name = "arp_validate", .desc = "validate src/dst of ARP probes", - .unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_ACTIVEBACKUP)), + .unsuppmodes = BIT(BOND_MODE_8023AD) | BIT(BOND_MODE_TLB) | + BIT(BOND_MODE_ALB), .values = bond_arp_validate_tbl, .set = bond_option_arp_validate_set }, @@@ -477,10 -473,10 +477,10 @@@ static void bond_opt_error_interpret(st p = strchr(val->string, '\n'); if (p) *p = '\0'; - pr_err("%s: option %s: invalid value (%s).\n", + pr_err("%s: option %s: invalid value (%s)\n", bond->dev->name, opt->name, val->string); } else { - pr_err("%s: option %s: invalid value (%llu).\n", + pr_err("%s: option %s: invalid value (%llu)\n", bond->dev->name, opt->name, val->value); } } @@@ -488,7 -484,7 +488,7 @@@ maxval = bond_opt_get_flags(opt, BOND_VALFLAG_MAX); if (!maxval) break; - pr_err("%s: option %s: allowed values %llu - %llu.\n", + pr_err("%s: option %s: allowed values %llu - %llu\n", bond->dev->name, opt->name, minval ? minval->value : 0, maxval->value); break; @@@ -496,11 -492,11 +496,11 @@@ bond_opt_dep_print(bond, opt); break; case -ENOTEMPTY: - pr_err("%s: option %s: unable to set because the bond device has slaves.\n", + pr_err("%s: option %s: unable to set because the bond device has slaves\n", bond->dev->name, opt->name); break; case -EBUSY: - pr_err("%s: option %s: unable to set because the bond device is up.\n", + pr_err("%s: option %s: unable to set because the bond device is up\n", bond->dev->name, opt->name); break; default: @@@ -593,7 -589,7 +593,7 @@@ int bond_option_mode_set(struct bondin 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", + pr_info("%s: Setting MII monitoring interval to %d\n", bond->dev->name, bond->params.miimon); }
@@@ -640,13 -636,13 +640,13 @@@ int bond_option_active_slave_set(struc
if (slave_dev) { if (!netif_is_bond_slave(slave_dev)) { - pr_err("Device %s is not bonding slave.\n", + pr_err("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", + pr_err("%s: Device %s is not our slave\n", bond->dev->name, slave_dev->name); return -EINVAL; } @@@ -657,7 -653,8 +657,7 @@@
/* check to see if we are clearing active */ if (!slave_dev) { - pr_info("%s: Clearing current active slave.\n", - bond->dev->name); + pr_info("%s: Clearing current active slave\n", bond->dev->name); rcu_assign_pointer(bond->curr_active_slave, NULL); bond_select_active_slave(bond); } else { @@@ -668,16 -665,16 +668,16 @@@
if (new_active == old_active) { /* do nothing */ - pr_info("%s: %s is already the current active slave.\n", + pr_info("%s: %s is already the current active slave\n", bond->dev->name, new_active->dev->name); } else { if (old_active && (new_active->link == BOND_LINK_UP) && IS_UP(new_active->dev)) { - pr_info("%s: Setting %s as active slave.\n", + pr_info("%s: Setting %s as active slave\n", bond->dev->name, 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", + 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); ret = -EINVAL; @@@ -693,19 -690,19 +693,19 @@@
int bond_option_miimon_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: Setting MII monitoring interval to %llu.\n", + pr_info("%s: Setting MII monitoring interval to %llu\n", bond->dev->name, 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", + pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value\n", bond->dev->name, 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", + 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); if (newval->value && bond->params.arp_interval) { - pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n", + pr_info("%s: MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n", bond->dev->name); bond->params.arp_interval = 0; if (bond->params.arp_validate) @@@ -745,8 -742,9 +745,8 @@@ int bond_option_updelay_set(struct bond 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); + pr_info("%s: Setting up delay to %d\n", + bond->dev->name, bond->params.updelay * bond->params.miimon);
return 0; } @@@ -769,8 -767,9 +769,8 @@@ int bond_option_downdelay_set(struct bo 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); + pr_info("%s: Setting down delay to %d\n", + bond->dev->name, bond->params.downdelay * bond->params.miimon);
return 0; } @@@ -778,7 -777,7 +778,7 @@@ int bond_option_use_carrier_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: Setting use_carrier to %llu.\n", + pr_info("%s: Setting use_carrier to %llu\n", bond->dev->name, newval->value); bond->params.use_carrier = newval->value;
@@@ -788,17 -787,17 +788,17 @@@ int bond_option_arp_interval_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: Setting ARP monitoring interval to %llu.\n", + pr_info("%s: Setting ARP monitoring interval to %llu\n", bond->dev->name, 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", + pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring\n", bond->dev->name, bond->dev->name); 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", + pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified\n", bond->dev->name); } if (bond->dev->flags & IFF_UP) { @@@ -813,7 -812,8 +813,7 @@@ cancel_delayed_work_sync(&bond->arp_work); } else { /* arp_validate can be set only in active-backup mode */ - if (bond->params.arp_validate) - bond->recv_probe = bond_arp_rcv; + bond->recv_probe = bond_arp_rcv; cancel_delayed_work_sync(&bond->mii_work); queue_delayed_work(bond->wq, &bond->arp_work, 0); } @@@ -856,11 -856,12 +856,11 @@@ static int _bond_option_arp_ip_target_a
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); + pr_err("%s: ARP target table is full!\n", bond->dev->name); return -EINVAL; }
- pr_info("%s: adding ARP target %pI4.\n", bond->dev->name, &target); + pr_info("%s: Adding ARP target %pI4\n", bond->dev->name, &target);
_bond_options_arp_ip_target_set(bond, ind, target, jiffies);
@@@ -895,16 -896,17 +895,16 @@@ int bond_option_arp_ip_target_rem(struc
ind = bond_get_targets_ip(targets, target); if (ind == -1) { - pr_err("%s: unable to remove nonexistent ARP target %pI4.\n", + pr_err("%s: unable to remove nonexistent ARP target %pI4\n", bond->dev->name, &target); return -EINVAL; }
if (ind == 0 && !targets[1] && bond->params.arp_interval) - pr_warn("%s: removing last arp target with arp_interval on\n", + pr_warn("%s: Removing last arp target with arp_interval on\n", bond->dev->name);
- pr_info("%s: removing ARP target %pI4.\n", bond->dev->name, - &target); + pr_info("%s: Removing ARP target %pI4\n", bond->dev->name, &target);
/* not to race with bond_arp_rcv */ write_lock_bh(&bond->lock); @@@ -952,7 -954,7 +952,7 @@@ int bond_option_arp_ip_targets_set(stru 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", + pr_err("no command found in arp_ip_targets file for bond %s - use +<addr> or -<addr>\n", bond->dev->name); } else { target = newval->value; @@@ -965,7 -967,7 +965,7 @@@ int bond_option_arp_validate_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: setting arp_validate to %s (%llu).\n", + pr_info("%s: Setting arp_validate to %s (%llu)\n", bond->dev->name, newval->string, newval->value);
if (bond->dev->flags & IFF_UP) { @@@ -982,7 -984,7 +982,7 @@@ int bond_option_arp_all_targets_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: setting arp_all_targets to %s (%llu).\n", + pr_info("%s: Setting arp_all_targets to %s (%llu)\n", bond->dev->name, newval->string, newval->value); bond->params.arp_all_targets = newval->value;
@@@ -1004,7 -1006,8 +1004,7 @@@ int bond_option_primary_set(struct 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); + pr_info("%s: Setting primary slave to None\n", bond->dev->name); bond->primary_slave = NULL; memset(bond->params.primary, 0, sizeof(bond->params.primary)); bond_select_active_slave(bond); @@@ -1013,7 -1016,7 +1013,7 @@@
bond_for_each_slave(bond, slave, iter) { if (strncmp(slave->dev->name, primary, IFNAMSIZ) == 0) { - pr_info("%s: Setting %s as primary slave.\n", + pr_info("%s: Setting %s as primary slave\n", bond->dev->name, slave->dev->name); bond->primary_slave = slave; strcpy(bond->params.primary, slave->dev->name); @@@ -1023,14 -1026,15 +1023,14 @@@ }
if (bond->primary_slave) { - pr_info("%s: Setting primary slave to None.\n", - bond->dev->name); + pr_info("%s: Setting primary slave to None\n", bond->dev->name); 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", + pr_info("%s: Recording %s as primary, but it has not been enslaved to %s yet\n", bond->dev->name, primary, bond->dev->name);
out: @@@ -1044,7 -1048,7 +1044,7 @@@ int bond_option_primary_reselect_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: setting primary_reselect to %s (%llu).\n", + pr_info("%s: Setting primary_reselect to %s (%llu)\n", bond->dev->name, newval->string, newval->value); bond->params.primary_reselect = newval->value;
@@@ -1060,7 -1064,7 +1060,7 @@@ int bond_option_fail_over_mac_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: Setting fail_over_mac to %s (%llu).\n", + pr_info("%s: Setting fail_over_mac to %s (%llu)\n", bond->dev->name, newval->string, newval->value); bond->params.fail_over_mac = newval->value;
@@@ -1070,7 -1074,7 +1070,7 @@@ int bond_option_xmit_hash_policy_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: setting xmit hash policy to %s (%llu).\n", + pr_info("%s: Setting xmit hash policy to %s (%llu)\n", bond->dev->name, newval->string, newval->value); bond->params.xmit_policy = newval->value;
@@@ -1080,7 -1084,7 +1080,7 @@@ int bond_option_resend_igmp_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: Setting resend_igmp to %llu.\n", + pr_info("%s: Setting resend_igmp to %llu\n", bond->dev->name, newval->value); bond->params.resend_igmp = newval->value;
@@@ -1154,7 -1158,7 +1154,7 @@@ int bond_option_pps_set(struct bonding int bond_option_lacp_rate_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: Setting LACP rate to %s (%llu).\n", + pr_info("%s: Setting LACP rate to %s (%llu)\n", bond->dev->name, newval->string, newval->value); bond->params.lacp_fast = newval->value; bond_3ad_update_lacp_rate(bond); @@@ -1165,7 -1169,7 +1165,7 @@@ int bond_option_ad_select_set(struct bonding *bond, struct bond_opt_value *newval) { - pr_info("%s: Setting ad_select to %s (%llu).\n", + pr_info("%s: Setting ad_select to %s (%llu)\n", bond->dev->name, newval->string, newval->value); bond->params.ad_select = newval->value;
@@@ -1195,7 -1199,8 +1195,7 @@@ int bond_option_queue_id_set(struct bon goto err_no_cmd;
/* Check buffer length, valid ifname and queue id */ - if (strlen(newval->string) > IFNAMSIZ || - !dev_valid_name(newval->string) || + if (!dev_valid_name(newval->string) || qid > bond->dev->real_num_tx_queues) goto err_no_cmd;
@@@ -1227,7 -1232,8 +1227,7 @@@ out return ret;
err_no_cmd: - pr_info("invalid input for queue_id set for %s.\n", - bond->dev->name); + pr_info("invalid input for queue_id set for %s\n", bond->dev->name); ret = -EPERM; goto out;
@@@ -1248,7 -1254,7 +1248,7 @@@ int bond_option_slaves_set(struct bondi
dev = __dev_get_by_name(dev_net(bond->dev), ifname); if (!dev) { - pr_info("%s: Interface %s does not exist!\n", + pr_info("%s: interface %s does not exist!\n", bond->dev->name, ifname); ret = -ENODEV; goto out; @@@ -1256,12 -1262,12 +1256,12 @@@
switch (command[0]) { case '+': - pr_info("%s: Adding slave %s.\n", bond->dev->name, dev->name); + pr_info("%s: Adding slave %s\n", bond->dev->name, dev->name); ret = bond_enslave(bond->dev, dev); break;
case '-': - pr_info("%s: Removing slave %s.\n", bond->dev->name, dev->name); + pr_info("%s: Removing slave %s\n", bond->dev->name, dev->name); ret = bond_release(bond->dev, dev); break;
@@@ -1273,7 -1279,7 +1273,7 @@@ out return ret;
err_no_cmd: - pr_err("no command found in slaves file for bond %s. Use +ifname or -ifname.\n", + pr_err("no command found in slaves file for bond %s - use +ifname or -ifname\n", bond->dev->name); ret = -EPERM; goto out; diff --combined drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 8363b9d,66c0df7..5ee13af --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@@ -1638,16 -1638,36 +1638,16 @@@ int bnx2x_enable_msix(struct bnx2x *bp DP(BNX2X_MSG_SP, "about to request enable msix with %d vectors\n", msix_vec);
- rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], msix_vec); - + rc = pci_enable_msix_range(bp->pdev, &bp->msix_table[0], + BNX2X_MIN_MSIX_VEC_CNT(bp), msix_vec); /* * reconfigure number of tx/rx queues according to available * MSI-X vectors */ - if (rc >= BNX2X_MIN_MSIX_VEC_CNT(bp)) { - /* how less vectors we will have? */ - int diff = msix_vec - rc; - - BNX2X_DEV_INFO("Trying to use less MSI-X vectors: %d\n", rc); - - rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], rc); - - if (rc) { - BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc); - goto no_msix; - } - /* - * decrease number of queues by number of unallocated entries - */ - bp->num_ethernet_queues -= diff; - bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues; - - BNX2X_DEV_INFO("New queue configuration set: %d\n", - bp->num_queues); - } else if (rc > 0) { + if (rc == -ENOSPC) { /* Get by with single vector */ - rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], 1); - if (rc) { + rc = pci_enable_msix_range(bp->pdev, &bp->msix_table[0], 1, 1); + if (rc < 0) { BNX2X_DEV_INFO("Single MSI-X is not attainable rc %d\n", rc); goto no_msix; @@@ -1660,22 -1680,8 +1660,22 @@@ bp->num_ethernet_queues = 1; bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues; } else if (rc < 0) { - BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc); + BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc); goto no_msix; + } else if (rc < msix_vec) { + /* how less vectors we will have? */ + int diff = msix_vec - rc; + + BNX2X_DEV_INFO("Trying to use less MSI-X vectors: %d\n", rc); + + /* + * decrease number of queues by number of unallocated entries + */ + bp->num_ethernet_queues -= diff; + bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues; + + BNX2X_DEV_INFO("New queue configuration set: %d\n", + bp->num_queues); }
bp->flags |= USING_MSIX_FLAG; @@@ -1867,7 -1873,7 +1867,7 @@@ void bnx2x_netif_stop(struct bnx2x *bp }
u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct bnx2x *bp = netdev_priv(dev);
@@@ -1889,7 -1895,7 +1889,7 @@@ }
/* select a non-FCoE queue */ - return __netdev_pick_tx(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); + return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); }
void bnx2x_set_num_queues(struct bnx2x *bp) @@@ -4767,8 -4773,12 +4767,8 @@@ void bnx2x_tx_timeout(struct net_devic bnx2x_panic(); #endif
- smp_mb__before_clear_bit(); - set_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state); - smp_mb__after_clear_bit(); - /* This allows the netif to be shutdown gracefully before resetting */ - schedule_delayed_work(&bp->sp_rtnl_task, 0); + bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_TX_TIMEOUT, 0); }
int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state) @@@ -4896,15 -4906,3 +4896,15 @@@ void bnx2x_update_coalesce_sb_index(str disable = disable ? 1 : (usec ? 0 : 1); storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable); } + +void bnx2x_schedule_sp_rtnl(struct bnx2x *bp, enum sp_rtnl_flag flag, + u32 verbose) +{ + smp_mb__before_clear_bit(); + set_bit(flag, &bp->sp_rtnl_state); + smp_mb__after_clear_bit(); + DP((BNX2X_MSG_SP | verbose), "Scheduling sp_rtnl task [Flag: %d]\n", + flag); + schedule_delayed_work(&bp->sp_rtnl_task, 0); +} +EXPORT_SYMBOL(bnx2x_schedule_sp_rtnl); diff --combined drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 5135cc7,a89a40f..ec02b15 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@@ -496,7 -496,7 +496,7 @@@ int bnx2x_set_vf_vlan(struct net_devic
/* select_queue callback */ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv); + void *accel_priv, select_queue_fallback_t fallback);
static inline void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp, @@@ -1324,7 -1324,4 +1324,7 @@@ void bnx2x_fill_fw_str(struct bnx2x *bp int bnx2x_drain_tx_queues(struct bnx2x *bp); void bnx2x_squeeze_objects(struct bnx2x *bp);
+void bnx2x_schedule_sp_rtnl(struct bnx2x*, enum sp_rtnl_flag, + u32 verbose); + #endif /* BNX2X_CMN_H */ diff --combined drivers/net/ethernet/ti/cpsw.c index 39d1253,651087b..0b6a280 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@@ -554,7 -554,7 +554,7 @@@ static void cpsw_set_promiscious(struc * common for both the interface as the interface shares * the same hardware resource. */ - for (i = 0; i <= priv->data.slaves; i++) + for (i = 0; i < priv->data.slaves; i++) if (priv->slaves[i].ndev->flags & IFF_PROMISC) flag = true;
@@@ -578,7 -578,7 +578,7 @@@ unsigned long timeout = jiffies + HZ;
/* Disable Learn for all ports */ - for (i = 0; i <= priv->data.slaves; i++) { + for (i = 0; i < priv->data.slaves; i++) { cpsw_ale_control_set(ale, i, ALE_PORT_NOLEARN, 1); cpsw_ale_control_set(ale, i, @@@ -606,7 -606,7 +606,7 @@@ cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 0);
/* Enable Learn for all ports */ - for (i = 0; i <= priv->data.slaves; i++) { + for (i = 0; i < priv->data.slaves; i++) { cpsw_ale_control_set(ale, i, ALE_PORT_NOLEARN, 0); cpsw_ale_control_set(ale, i, @@@ -1471,6 -1471,7 +1471,6 @@@ static int cpsw_hwtstamp_get(struct net static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { struct cpsw_priv *priv = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(req); int slave_no = cpsw_slave_index(priv);
if (!netif_running(dev)) @@@ -1483,11 -1484,14 +1483,11 @@@ case SIOCGHWTSTAMP: return cpsw_hwtstamp_get(dev, req); #endif - case SIOCGMIIPHY: - data->phy_id = priv->slaves[slave_no].phy->addr; - break; - default: - return -ENOTSUPP; }
- return 0; + if (!priv->slaves[slave_no].phy) + return -EOPNOTSUPP; + return phy_mii_ioctl(priv->slaves[slave_no].phy, req, cmd); }
static void cpsw_ndo_tx_timeout(struct net_device *ndev) @@@ -1892,6 -1896,11 +1892,11 @@@ static int cpsw_probe_dt(struct cpsw_pl memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
slave_data->phy_if = of_get_phy_mode(slave_node); + if (slave_data->phy_if < 0) { + pr_err("Missing or malformed slave[%d] phy-mode property\n", + i); + return slave_data->phy_if; + }
if (data->dual_emac) { if (of_property_read_u32(slave_node, "dual_emac_res_vlan", diff --combined drivers/net/hyperv/netvsc_drv.c index 1eadc13,7141a19..bcd2df2 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@@ -88,8 -88,12 +88,12 @@@ static int netvsc_open(struct net_devic { struct net_device_context *net_device_ctx = netdev_priv(net); struct hv_device *device_obj = net_device_ctx->device_ctx; + struct netvsc_device *nvdev; + struct rndis_device *rdev; int ret = 0;
+ netif_carrier_off(net); + /* Open up the device */ ret = rndis_filter_open(device_obj); if (ret != 0) { @@@ -99,6 -103,11 +103,11 @@@
netif_start_queue(net);
+ nvdev = hv_get_drvdata(device_obj); + rdev = nvdev->extension; + if (!rdev->link_state) + netif_carrier_on(net); + return ret; }
@@@ -146,7 -155,7 +155,7 @@@ static int netvsc_start_xmit(struct sk_ /* Allocate a netvsc packet based on # of frags. */ packet = kzalloc(sizeof(struct hv_netvsc_packet) + (num_pages * sizeof(struct hv_page_buffer)) + - sizeof(struct rndis_filter_packet) + + sizeof(struct rndis_message) + NDIS_VLAN_PPI_SIZE, GFP_ATOMIC); if (!packet) { /* out of memory, drop packet */ @@@ -229,23 -238,24 +238,24 @@@ void netvsc_linkstatus_callback(struct struct net_device *net; struct net_device_context *ndev_ctx; struct netvsc_device *net_device; + struct rndis_device *rdev;
net_device = hv_get_drvdata(device_obj); + rdev = net_device->extension; + + rdev->link_state = status != 1; + net = net_device->ndev;
- if (!net) { - netdev_err(net, "got link status but net device " - "not initialized yet\n"); + if (!net || net->reg_state != NETREG_REGISTERED) return; - }
+ ndev_ctx = netdev_priv(net); if (status == 1) { schedule_delayed_work(&ndev_ctx->dwork, 0); schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20)); } else { - netif_carrier_off(net); + schedule_delayed_work(&ndev_ctx->dwork, 0); } }
@@@ -388,17 -398,35 +398,35 @@@ static const struct net_device_ops devi * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add * another netif_notify_peers() into a delayed work, otherwise GARP packet * will not be sent after quick migration, and cause network disconnection. + * Also, we update the carrier status here. */ - static void netvsc_send_garp(struct work_struct *w) + static void netvsc_link_change(struct work_struct *w) { struct net_device_context *ndev_ctx; struct net_device *net; struct netvsc_device *net_device; + struct rndis_device *rdev; + bool notify; + + rtnl_lock();
ndev_ctx = container_of(w, struct net_device_context, dwork.work); net_device = hv_get_drvdata(ndev_ctx->device_ctx); + rdev = net_device->extension; net = net_device->ndev; - netdev_notify_peers(net); + + if (rdev->link_state) { + netif_carrier_off(net); + notify = false; + } else { + netif_carrier_on(net); + notify = true; + } + + rtnl_unlock(); + + if (notify) + netdev_notify_peers(net); }
@@@ -414,13 -442,10 +442,10 @@@ static int netvsc_probe(struct hv_devic if (!net) return -ENOMEM;
net_device_ctx = netdev_priv(net); net_device_ctx->device_ctx = dev; hv_set_drvdata(dev, net); - INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); + INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change); INIT_WORK(&net_device_ctx->work, do_set_multicast);
net->netdev_ops = &device_ops; @@@ -443,8 -468,6 +468,6 @@@ } memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
- netif_carrier_on(net); - ret = register_netdev(net); if (ret != 0) { pr_err("Unable to register netdev.\n"); diff --combined drivers/net/macvlan.c index 25685e3,a5d2189..44227c2 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@@ -534,6 -534,7 +534,6 @@@ static int macvlan_init(struct net_devi { struct macvlan_dev *vlan = netdev_priv(dev); const struct net_device *lowerdev = vlan->lowerdev; - int i;
dev->state = (dev->state & ~MACVLAN_STATE_MASK) | (lowerdev->state & MACVLAN_STATE_MASK); @@@ -545,10 -546,16 +545,10 @@@
macvlan_set_lockdep_class(dev);
- vlan->pcpu_stats = alloc_percpu(struct vlan_pcpu_stats); + vlan->pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); if (!vlan->pcpu_stats) return -ENOMEM;
- for_each_possible_cpu(i) { - struct vlan_pcpu_stats *mvlstats; - mvlstats = per_cpu_ptr(vlan->pcpu_stats, i); - u64_stats_init(&mvlstats->syncp); - } - return 0; }
@@@ -872,14 -879,15 +872,15 @@@ int macvlan_common_newlink(struct net * dev->priv_flags |= IFF_MACVLAN; err = netdev_upper_dev_link(lowerdev, dev); if (err) - goto destroy_port; - + goto unregister_netdev;
list_add_tail_rcu(&vlan->list, &port->vlans); netif_stacked_transfer_operstate(lowerdev, dev);
return 0;
+ unregister_netdev: + unregister_netdevice(dev); destroy_port: port->count -= 1; if (!port->count) diff --combined drivers/net/team/team.c index adb46de,c8624a8..aea92f0 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@@ -1540,10 -1540,16 +1540,10 @@@ static int team_init(struct net_device mutex_init(&team->lock); team_set_no_mode(team);
- team->pcpu_stats = alloc_percpu(struct team_pcpu_stats); + team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats); if (!team->pcpu_stats) return -ENOMEM;
- for_each_possible_cpu(i) { - struct team_pcpu_stats *team_stats; - team_stats = per_cpu_ptr(team->pcpu_stats, i); - u64_stats_init(&team_stats->syncp); - } - for (i = 0; i < TEAM_PORT_HASHENTRIES; i++) INIT_HLIST_HEAD(&team->en_port_hlist[i]); INIT_LIST_HEAD(&team->port_list); @@@ -1642,7 -1648,7 +1642,7 @@@ static netdev_tx_t team_xmit(struct sk_ }
static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { /* * This helper function exists to help dev_pick_tx get the correct diff --combined include/linux/netdevice.h index 891432a,e8eeebd..5e47565 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@@ -752,6 -752,9 +752,9 @@@ struct netdev_phys_port_id unsigned char id_len; };
+ typedef u16 (*select_queue_fallback_t)(struct net_device *dev, + struct sk_buff *skb); + /* * This structure defines the management hooks for network devices. * The following hooks can be defined; unless noted otherwise, they are @@@ -783,7 -786,7 +786,7 @@@ * Required can not be NULL. * * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb, - * void *accel_priv); + * void *accel_priv, select_queue_fallback_t fallback); * Called to decide which queue to when device supports multiple * transmit queues. * @@@ -1005,7 -1008,8 +1008,8 @@@ struct net_device_ops struct net_device *dev); u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb, - void *accel_priv); + void *accel_priv, + select_queue_fallback_t fallback); void (*ndo_change_rx_flags)(struct net_device *dev, int flags); void (*ndo_set_rx_mode)(struct net_device *dev); @@@ -1312,7 -1316,13 +1316,7 @@@ struct net_device /* * Cache lines mostly used on receive path (including eth_type_trans()) */ - unsigned long last_rx; /* Time of last Rx - * This should not be set in - * drivers, unless really needed, - * because network stack (bonding) - * use it if/when necessary, to - * avoid dirtying this cache line. - */ + unsigned long last_rx; /* Time of last Rx */
/* Interface address info used in eth_type_trans() */ unsigned char *dev_addr; /* hw address, (before bcast @@@ -1545,7 -1555,6 +1549,6 @@@ static inline void netdev_for_each_tx_q struct netdev_queue *netdev_pick_tx(struct net_device *dev, struct sk_buff *skb, void *accel_priv); - u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb);
/* * Net namespace inlines @@@ -1720,20 -1729,6 +1723,20 @@@ struct pcpu_sw_netstats struct u64_stats_sync syncp; };
+#define netdev_alloc_pcpu_stats(type) \ +({ \ + typeof(type) *pcpu_stats = alloc_percpu(type); \ + if (pcpu_stats) { \ + int i; \ + for_each_possible_cpu(i) { \ + typeof(type) *stat; \ + stat = per_cpu_ptr(pcpu_stats, i); \ + u64_stats_init(&stat->syncp); \ + } \ + } \ + pcpu_stats; \ +}) + #include <linux/notifier.h>
/* netdevice notifier chain. Please remember to update the rtnetlink @@@ -2284,6 -2279,26 +2287,26 @@@ static inline void netdev_reset_queue(s }
/** + * netdev_cap_txqueue - check if selected tx queue exceeds device queues + * @dev: network device + * @queue_index: given tx queue index + * + * Returns 0 if given tx queue index >= number of device tx queues, + * otherwise returns the originally passed tx queue index. + */ + static inline u16 netdev_cap_txqueue(struct net_device *dev, u16 queue_index) + { + if (unlikely(queue_index >= dev->real_num_tx_queues)) { + net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n", + dev->name, queue_index, + dev->real_num_tx_queues); + return 0; + } + + return queue_index; + } + + /** * netif_running - test if up * @dev: network device * @@@ -3076,7 -3091,12 +3099,12 @@@ void netdev_change_features(struct net_ void netif_stacked_transfer_operstate(const struct net_device *rootdev, struct net_device *dev);
- netdev_features_t netif_skb_features(struct sk_buff *skb); + netdev_features_t netif_skb_dev_features(struct sk_buff *skb, + const struct net_device *dev); + static inline netdev_features_t netif_skb_features(struct sk_buff *skb) + { + return netif_skb_dev_features(skb, skb->dev); + }
static inline bool net_gso_ok(netdev_features_t features, int gso_type) { diff --combined net/core/rtnetlink.c index 7b2ad56,1a0dac2..fc122fd --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@@ -1121,7 -1121,56 +1121,7 @@@ nla_put_failure return -EMSGSIZE; }
-static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) -{ - struct net *net = sock_net(skb->sk); - int h, s_h; - int idx = 0, s_idx; - struct net_device *dev; - struct hlist_head *head; - struct nlattr *tb[IFLA_MAX+1]; - u32 ext_filter_mask = 0; - - s_h = cb->args[0]; - s_idx = cb->args[1]; - - rcu_read_lock(); - cb->seq = net->dev_base_seq; - - if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, - ifla_policy) >= 0) { - - if (tb[IFLA_EXT_MASK]) - ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); - } - - for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { - idx = 0; - head = &net->dev_index_head[h]; - hlist_for_each_entry_rcu(dev, head, index_hlist) { - if (idx < s_idx) - goto cont; - if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, - NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, 0, - NLM_F_MULTI, - ext_filter_mask) <= 0) - goto out; - - nl_dump_check_consistent(cb, nlmsg_hdr(skb)); -cont: - idx++; - } - } -out: - rcu_read_unlock(); - cb->args[1] = idx; - cb->args[0] = h; - - return skb->len; -} - -const struct nla_policy ifla_policy[IFLA_MAX+1] = { +static const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, @@@ -1148,6 -1197,7 +1148,6 @@@ [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, }; -EXPORT_SYMBOL(ifla_policy);
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { [IFLA_INFO_KIND] = { .type = NLA_STRING }, @@@ -1185,61 -1235,6 +1185,61 @@@ static const struct nla_policy ifla_por [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, };
+static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct net *net = sock_net(skb->sk); + int h, s_h; + int idx = 0, s_idx; + struct net_device *dev; + struct hlist_head *head; + struct nlattr *tb[IFLA_MAX+1]; + u32 ext_filter_mask = 0; + + s_h = cb->args[0]; + s_idx = cb->args[1]; + + rcu_read_lock(); + cb->seq = net->dev_base_seq; + + if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, + ifla_policy) >= 0) { + + if (tb[IFLA_EXT_MASK]) + ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); + } + + for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { + idx = 0; + head = &net->dev_index_head[h]; + hlist_for_each_entry_rcu(dev, head, index_hlist) { + if (idx < s_idx) + goto cont; + if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, 0, + NLM_F_MULTI, + ext_filter_mask) <= 0) + goto out; + + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +cont: + idx++; + } + } +out: + rcu_read_unlock(); + cb->args[1] = idx; + cb->args[0] = h; + + return skb->len; +} + +int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len) +{ + return nla_parse(tb, IFLA_MAX, head, len, ifla_policy); +} +EXPORT_SYMBOL(rtnl_nla_parse_ifla); + struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) { struct net *net; @@@ -1968,16 -1963,21 +1968,21 @@@ replay
dev->ifindex = ifm->ifi_index;
- if (ops->newlink) + if (ops->newlink) { err = ops->newlink(net, dev, tb, data); - else + /* Drivers should call free_netdev() in ->destructor + * and unregister it on failure so that device could be + * finally freed in rtnl_unlock. + */ + if (err < 0) + goto out; + } else { err = register_netdevice(dev); - - if (err < 0) { - free_netdev(dev); - goto out; + if (err < 0) { + free_netdev(dev); + goto out; + } } - err = rtnl_configure_link(dev, ifm); if (err < 0) unregister_netdevice(dev); diff --combined net/ipv4/ip_forward.c index d9d9290,f3869c1..be8abe7 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@@ -39,6 -39,71 +39,71 @@@ #include <net/route.h> #include <net/xfrm.h>
+ static bool ip_may_fragment(const struct sk_buff *skb) + { + return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) || + !skb->local_df; + } + + static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) + { + if (skb->len <= mtu || skb->local_df) + return false; + + if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) + return false; + + return true; + } + + static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb) + { + unsigned int mtu; + + if (skb->local_df || !skb_is_gso(skb)) + return false; + + mtu = ip_dst_mtu_maybe_forward(skb_dst(skb), true); + + /* if seglen > mtu, do software segmentation for IP fragmentation on + * output. DF bit cannot be set since ip_forward would have sent + * icmp error. + */ + return skb_gso_network_seglen(skb) > mtu; + } + + /* called if GSO skb needs to be fragmented on forward */ + static int ip_forward_finish_gso(struct sk_buff *skb) + { + struct dst_entry *dst = skb_dst(skb); + netdev_features_t features; + struct sk_buff *segs; + int ret = 0; + + features = netif_skb_dev_features(skb, dst->dev); + segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); + if (IS_ERR(segs)) { + kfree_skb(skb); + return -ENOMEM; + } + + consume_skb(skb); + + do { + struct sk_buff *nskb = segs->next; + int err; + + segs->next = NULL; + err = dst_output(segs); + + if (err && ret == 0) + ret = err; + segs = nskb; + } while (segs); + + return ret; + } + static int ip_forward_finish(struct sk_buff *skb) { struct ip_options *opt = &(IPCB(skb)->opt); @@@ -49,6 -114,9 +114,9 @@@ if (unlikely(opt->optlen)) ip_forward_options(skb);
+ if (ip_gso_exceeds_dst_mtu(skb)) + return ip_forward_finish_gso(skb); + return dst_output(skb); }
@@@ -59,10 -127,6 +127,10 @@@ int ip_forward(struct sk_buff *skb struct rtable *rt; /* Route we use */ struct ip_options *opt = &(IPCB(skb)->opt);
+ /* that should never happen */ + if (skb->pkt_type != PACKET_HOST) + goto drop; + if (skb_warn_if_lro(skb)) goto drop;
@@@ -72,6 -136,9 +140,6 @@@ if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb)) return NET_RX_SUCCESS;
- if (skb->pkt_type != PACKET_HOST) - goto drop; - skb_forward_csum(skb);
/* @@@ -92,8 -159,7 +160,7 @@@
IPCB(skb)->flags |= IPSKB_FORWARDED; mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); - if (unlikely(skb->len > mtu && !skb_is_gso(skb) && - (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) { + if (!ip_may_fragment(skb) && ip_exceeds_mtu(skb, mtu)) { IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); diff --combined net/ipv4/route.c index 271554c,4c011ec..11e4384 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@@ -697,6 -697,7 +697,6 @@@ static void update_or_create_fnhe(struc
out_unlock: spin_unlock_bh(&fnhe_lock); - return; }
static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4, @@@ -1596,6 -1597,7 +1596,7 @@@ static int __mkroute_input(struct sk_bu rth->rt_gateway = 0; rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); + RT_CACHE_STAT_INC(in_slow_tot);
rth->dst.input = ip_forward; rth->dst.output = ip_output; @@@ -1694,10 -1696,11 +1695,11 @@@ static int ip_route_input_slow(struct s fl4.daddr = daddr; fl4.saddr = saddr; err = fib_lookup(net, &fl4, &res); - if (err != 0) + if (err != 0) { + if (!IN_DEV_FORWARD(in_dev)) + err = -EHOSTUNREACH; goto no_route; - - RT_CACHE_STAT_INC(in_slow_tot); + }
if (res.type == RTN_BROADCAST) goto brd_input; @@@ -1711,8 -1714,10 +1713,10 @@@ goto local_input; }
- if (!IN_DEV_FORWARD(in_dev)) + if (!IN_DEV_FORWARD(in_dev)) { + err = -EHOSTUNREACH; goto no_route; + } if (res.type != RTN_UNICAST) goto martian_destination;
@@@ -1767,6 -1772,7 +1771,7 @@@ local_input rth->rt_gateway = 0; rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); + RT_CACHE_STAT_INC(in_slow_tot); if (res.type == RTN_UNREACHABLE) { rth->dst.input= ip_error; rth->dst.error= -err; diff --combined net/tipc/link.c index e4f233d,da6018b..284d638 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@@ -77,19 -77,19 +77,19 @@@ static const char *link_unk_evt = "Unkn
static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, struct sk_buff *buf); -static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf); -static int tipc_link_tunnel_rcv(struct tipc_link **l_ptr, +static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf); +static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr, struct sk_buff **buf); static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance); -static int link_send_sections_long(struct tipc_port *sender, - struct iovec const *msg_sect, - unsigned int len, u32 destnode); +static int tipc_link_iovec_long_xmit(struct tipc_port *sender, + struct iovec const *msg_sect, + unsigned int len, u32 destnode); static void link_state_event(struct tipc_link *l_ptr, u32 event); static void link_reset_statistics(struct tipc_link *l_ptr); static void link_print(struct tipc_link *l_ptr, const char *str); -static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf); -static void tipc_link_send_sync(struct tipc_link *l); -static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf); +static int tipc_link_frag_xmit(struct tipc_link *l_ptr, struct sk_buff *buf); +static void tipc_link_sync_xmit(struct tipc_link *l); +static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf);
/* * Simple link routines @@@ -147,6 -147,11 +147,6 @@@ int tipc_link_is_active(struct tipc_lin /** * link_timeout - handle expiration of link timer * @l_ptr: pointer to link - * - * This routine must not grab "tipc_net_lock" to avoid a potential deadlock conflict - * with tipc_link_delete(). (There is no risk that the node will be deleted by - * another thread because tipc_link_delete() always cancels the link timer before - * tipc_node_delete() is called.) */ static void link_timeout(struct tipc_link *l_ptr) { @@@ -208,8 -213,8 +208,8 @@@ static void link_set_timer(struct tipc_ * Returns pointer to link. */ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, - struct tipc_bearer *b_ptr, - const struct tipc_media_addr *media_addr) + struct tipc_bearer *b_ptr, + const struct tipc_media_addr *media_addr) { struct tipc_link *l_ptr; struct tipc_msg *msg; @@@ -274,43 -279,41 +274,43 @@@
k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr); - list_add_tail(&l_ptr->link_list, &b_ptr->links);
link_state_event(l_ptr, STARTING_EVT);
return l_ptr; }
-/** - * tipc_link_delete - delete a link - * @l_ptr: pointer to link - * - * Note: 'tipc_net_lock' is write_locked, bearer is locked. - * This routine must not grab the node lock until after link timer cancellation - * to avoid a potential deadlock situation. - */ -void tipc_link_delete(struct tipc_link *l_ptr) -{ - if (!l_ptr) { - pr_err("Attempt to delete non-existent link\n"); - return; - }
- k_cancel_timer(&l_ptr->timer); +void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down) +{ + struct tipc_link *l_ptr; + struct tipc_node *n_ptr;
- tipc_node_lock(l_ptr->owner); - tipc_link_reset(l_ptr); - tipc_node_detach_link(l_ptr->owner, l_ptr); - tipc_link_purge_queues(l_ptr); - list_del_init(&l_ptr->link_list); - tipc_node_unlock(l_ptr->owner); - k_term_timer(&l_ptr->timer); - kfree(l_ptr); + list_for_each_entry(n_ptr, &tipc_node_list, list) { + spin_lock_bh(&n_ptr->lock); + l_ptr = n_ptr->links[bearer_id]; + if (l_ptr) { + tipc_link_reset(l_ptr); + if (shutting_down || !tipc_node_is_up(n_ptr)) { + tipc_node_detach_link(l_ptr->owner, l_ptr); + tipc_link_reset_fragments(l_ptr); + spin_unlock_bh(&n_ptr->lock); + + /* Nobody else can access this link now: */ + del_timer_sync(&l_ptr->timer); + kfree(l_ptr); + } else { + /* Detach/delete when failover is finished: */ + l_ptr->flags |= LINK_STOPPED; + spin_unlock_bh(&n_ptr->lock); + del_timer_sync(&l_ptr->timer); + } + continue; + } + spin_unlock_bh(&n_ptr->lock); + } }
- /** * link_schedule_port - schedule port for deferred sending * @l_ptr: pointer to link @@@ -458,19 -461,6 +458,19 @@@ void tipc_link_reset(struct tipc_link * link_reset_statistics(l_ptr); }
+void tipc_link_reset_list(unsigned int bearer_id) +{ + struct tipc_link *l_ptr; + struct tipc_node *n_ptr; + + list_for_each_entry(n_ptr, &tipc_node_list, list) { + spin_lock_bh(&n_ptr->lock); + l_ptr = n_ptr->links[bearer_id]; + if (l_ptr) + tipc_link_reset(l_ptr); + spin_unlock_bh(&n_ptr->lock); + } +}
static void link_activate(struct tipc_link *l_ptr) { @@@ -489,10 -479,7 +489,10 @@@ static void link_state_event(struct tip struct tipc_link *other; u32 cont_intv = l_ptr->continuity_interval;
- if (!l_ptr->started && (event != STARTING_EVT)) + if (l_ptr->flags & LINK_STOPPED) + return; + + if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT)) return; /* Not yet. */
/* Check whether changeover is going on */ @@@ -512,12 -499,12 +512,12 @@@ if (l_ptr->next_in_no != l_ptr->checkpoint) { l_ptr->checkpoint = l_ptr->next_in_no; if (tipc_bclink_acks_missing(l_ptr->owner)) { - tipc_link_send_proto_msg(l_ptr, STATE_MSG, - 0, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, STATE_MSG, + 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; } else if (l_ptr->max_pkt < l_ptr->max_pkt_target) { - tipc_link_send_proto_msg(l_ptr, STATE_MSG, - 1, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, STATE_MSG, + 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; } link_set_timer(l_ptr, cont_intv); @@@ -525,7 -512,7 +525,7 @@@ } l_ptr->state = WORKING_UNKNOWN; l_ptr->fsm_msg_cnt = 0; - tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv / 4); break; @@@ -535,8 -522,7 +535,8 @@@ tipc_link_reset(l_ptr); l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; - tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, + 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; @@@ -558,8 -544,7 +558,8 @@@ tipc_link_reset(l_ptr); l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; - tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, + 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; @@@ -569,14 -554,14 +569,14 @@@ l_ptr->fsm_msg_cnt = 0; l_ptr->checkpoint = l_ptr->next_in_no; if (tipc_bclink_acks_missing(l_ptr->owner)) { - tipc_link_send_proto_msg(l_ptr, STATE_MSG, - 0, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, STATE_MSG, + 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; } link_set_timer(l_ptr, cont_intv); } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) { - tipc_link_send_proto_msg(l_ptr, STATE_MSG, - 1, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, STATE_MSG, + 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv / 4); } else { /* Link has failed */ @@@ -585,8 -570,8 +585,8 @@@ tipc_link_reset(l_ptr); l_ptr->state = RESET_UNKNOWN; l_ptr->fsm_msg_cnt = 0; - tipc_link_send_proto_msg(l_ptr, RESET_MSG, - 0, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, RESET_MSG, + 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); } @@@ -606,25 -591,24 +606,25 @@@ l_ptr->state = WORKING_WORKING; l_ptr->fsm_msg_cnt = 0; link_activate(l_ptr); - tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; if (l_ptr->owner->working_links == 1) - tipc_link_send_sync(l_ptr); + tipc_link_sync_xmit(l_ptr); link_set_timer(l_ptr, cont_intv); break; case RESET_MSG: l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; - tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, + 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; case STARTING_EVT: - l_ptr->started = 1; + l_ptr->flags |= LINK_STARTED; /* fall through */ case TIMEOUT_EVT: - tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; @@@ -642,17 -626,16 +642,17 @@@ l_ptr->state = WORKING_WORKING; l_ptr->fsm_msg_cnt = 0; link_activate(l_ptr); - tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; if (l_ptr->owner->working_links == 1) - tipc_link_send_sync(l_ptr); + tipc_link_sync_xmit(l_ptr); link_set_timer(l_ptr, cont_intv); break; case RESET_MSG: break; case TIMEOUT_EVT: - tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, + 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; @@@ -738,11 -721,11 +738,11 @@@ static void link_add_chain_to_outqueue( }
/* - * tipc_link_send_buf() is the 'full path' for messages, called from - * inside TIPC when the 'fast path' in tipc_send_buf + * tipc_link_xmit() is the 'full path' for messages, called from + * inside TIPC when the 'fast path' in tipc_send_xmit * has failed, and from link_send() */ -int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf) +int __tipc_link_xmit(struct tipc_link *l_ptr, struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); u32 size = msg_size(msg); @@@ -770,7 -753,7 +770,7 @@@
/* Fragmentation needed ? */ if (size > max_packet) - return link_send_long_buf(l_ptr, buf); + return tipc_link_frag_xmit(l_ptr, buf);
/* Packet can be queued or sent. */ if (likely(!link_congested(l_ptr))) { @@@ -814,11 -797,11 +814,11 @@@ }
/* - * tipc_link_send(): same as tipc_link_send_buf(), but the link to use has - * not been selected yet, and the the owner node is not locked + * tipc_link_xmit(): same as __tipc_link_xmit(), but the link to use + * has not been selected yet, and the the owner node is not locked * Called by TIPC internal users, e.g. the name distributor */ -int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) +int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector) { struct tipc_link *l_ptr; struct tipc_node *n_ptr; @@@ -830,7 -813,7 +830,7 @@@ tipc_node_lock(n_ptr); l_ptr = n_ptr->active_links[selector & 1]; if (l_ptr) - res = tipc_link_send_buf(l_ptr, buf); + res = __tipc_link_xmit(l_ptr, buf); else kfree_skb(buf); tipc_node_unlock(n_ptr); @@@ -842,14 -825,14 +842,14 @@@ }
/* - * tipc_link_send_sync - synchronize broadcast link endpoints. + * tipc_link_sync_xmit - synchronize broadcast link endpoints. * * Give a newly added peer node the sequence number where it should * start receiving and acking broadcast packets. * * Called with node locked */ -static void tipc_link_send_sync(struct tipc_link *l) +static void tipc_link_sync_xmit(struct tipc_link *l) { struct sk_buff *buf; struct tipc_msg *msg; @@@ -866,14 -849,14 +866,14 @@@ }
/* - * tipc_link_recv_sync - synchronize broadcast link endpoints. + * tipc_link_sync_rcv - synchronize broadcast link endpoints. * Receive the sequence number where we should start receiving and * acking broadcast packets from a newly added peer node, and open * up for reception of such packets. * * Called with node locked */ -static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf) +static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf);
@@@ -883,7 -866,7 +883,7 @@@ }
/* - * tipc_link_send_names - send name table entries to new neighbor + * tipc_link_names_xmit - send name table entries to new neighbor * * Send routine for bulk delivery of name table messages when contact * with a new neighbor occurs. No link congestion checking is performed @@@ -891,7 -874,7 +891,7 @@@ * small enough not to require fragmentation. * Called without any locks held. */ -void tipc_link_send_names(struct list_head *message_list, u32 dest) +void tipc_link_names_xmit(struct list_head *message_list, u32 dest) { struct tipc_node *n_ptr; struct tipc_link *l_ptr; @@@ -926,13 -909,13 +926,13 @@@ }
/* - * link_send_buf_fast: Entry for data messages where the + * tipc_link_xmit_fast: Entry for data messages where the * destination link is known and the header is complete, * inclusive total message length. Very time critical. * Link is locked. Returns user data length. */ -static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf, - u32 *used_max_pkt) +static int tipc_link_xmit_fast(struct tipc_link *l_ptr, struct sk_buff *buf, + u32 *used_max_pkt) { struct tipc_msg *msg = buf_msg(buf); int res = msg_data_sz(msg); @@@ -948,18 -931,18 +948,18 @@@ else *used_max_pkt = l_ptr->max_pkt; } - return tipc_link_send_buf(l_ptr, buf); /* All other cases */ + return __tipc_link_xmit(l_ptr, buf); /* All other cases */ }
/* - * tipc_link_send_sections_fast: Entry for messages where the + * tipc_link_iovec_xmit_fast: Entry for messages where the * destination processor is known and the header is complete, * except for total message length. * Returns user data length or errno. */ -int tipc_link_send_sections_fast(struct tipc_port *sender, - struct iovec const *msg_sect, - unsigned int len, u32 destaddr) +int tipc_link_iovec_xmit_fast(struct tipc_port *sender, + struct iovec const *msg_sect, + unsigned int len, u32 destaddr) { struct tipc_msg *hdr = &sender->phdr; struct tipc_link *l_ptr; @@@ -985,8 -968,8 +985,8 @@@ again l_ptr = node->active_links[selector]; if (likely(l_ptr)) { if (likely(buf)) { - res = link_send_buf_fast(l_ptr, buf, - &sender->max_pkt); + res = tipc_link_xmit_fast(l_ptr, buf, + &sender->max_pkt); exit: tipc_node_unlock(node); read_unlock_bh(&tipc_net_lock); @@@ -1012,8 -995,8 +1012,8 @@@ if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) goto again;
- return link_send_sections_long(sender, msg_sect, len, - destaddr); + return tipc_link_iovec_long_xmit(sender, msg_sect, + len, destaddr); } tipc_node_unlock(node); } @@@ -1023,13 -1006,13 +1023,13 @@@ if (buf) return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); if (res >= 0) - return tipc_port_reject_sections(sender, hdr, msg_sect, - len, TIPC_ERR_NO_NODE); + return tipc_port_iovec_reject(sender, hdr, msg_sect, len, + TIPC_ERR_NO_NODE); return res; }
/* - * link_send_sections_long(): Entry for long messages where the + * tipc_link_iovec_long_xmit(): Entry for long messages where the * destination node is known and the header is complete, * inclusive total message length. * Link and bearer congestion status have been checked to be ok, @@@ -1042,9 -1025,9 +1042,9 @@@ * * Returns user data length or errno. */ -static int link_send_sections_long(struct tipc_port *sender, - struct iovec const *msg_sect, - unsigned int len, u32 destaddr) +static int tipc_link_iovec_long_xmit(struct tipc_port *sender, + struct iovec const *msg_sect, + unsigned int len, u32 destaddr) { struct tipc_link *l_ptr; struct tipc_node *node; @@@ -1163,8 -1146,8 +1163,8 @@@ error } else { reject: kfree_skb_list(buf_chain); - return tipc_port_reject_sections(sender, hdr, msg_sect, - len, TIPC_ERR_NO_NODE); + return tipc_port_iovec_reject(sender, hdr, msg_sect, + len, TIPC_ERR_NO_NODE); }
/* Append chain of fragments to send queue & send them */ @@@ -1408,6 -1391,12 +1408,12 @@@ static int link_recv_buf_validate(struc u32 hdr_size; u32 min_hdr_size;
+ /* If this packet comes from the defer queue, the skb has already + * been validated + */ + if (unlikely(TIPC_SKB_CB(buf)->deferred)) + return 1; + if (unlikely(buf->len < MIN_H_SIZE)) return 0;
@@@ -1452,6 -1441,7 +1458,6 @@@ void tipc_rcv(struct sk_buff *head, str u32 seq_no; u32 ackd; u32 released = 0; - int type;
head = head->next; buf->next = NULL; @@@ -1473,9 -1463,9 +1479,9 @@@
if (unlikely(msg_non_seq(msg))) { if (msg_user(msg) == LINK_CONFIG) - tipc_disc_recv_msg(buf, b_ptr); + tipc_disc_rcv(buf, b_ptr); else - tipc_bclink_recv_pkt(buf); + tipc_bclink_rcv(buf); continue; }
@@@ -1499,7 -1489,7 +1505,7 @@@ if ((n_ptr->block_setup & WAIT_PEER_DOWN) && msg_user(msg) == LINK_PROTOCOL && (msg_type(msg) == RESET_MSG || - msg_type(msg) == ACTIVATE_MSG) && + msg_type(msg) == ACTIVATE_MSG) && !msg_redundant_link(msg)) n_ptr->block_setup &= ~WAIT_PEER_DOWN;
@@@ -1518,6 -1508,7 +1524,6 @@@ while ((crs != l_ptr->next_out) && less_eq(buf_seqno(crs), ackd)) { struct sk_buff *next = crs->next; - kfree_skb(crs); crs = next; released++; @@@ -1530,19 -1521,18 +1536,19 @@@ /* Try sending any messages link endpoint has pending */ if (unlikely(l_ptr->next_out)) tipc_link_push_queue(l_ptr); + if (unlikely(!list_empty(&l_ptr->waiting_ports))) tipc_link_wakeup_ports(l_ptr, 0); + if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) { l_ptr->stats.sent_acks++; - tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); }
- /* Now (finally!) process the incoming message */ -protocol_check: + /* Process the incoming packet */ if (unlikely(!link_working_working(l_ptr))) { if (msg_user(msg) == LINK_PROTOCOL) { - link_recv_proto_msg(l_ptr, buf); + tipc_link_proto_rcv(l_ptr, buf); head = link_insert_deferred_queue(l_ptr, head); tipc_node_unlock(n_ptr); continue; @@@ -1571,65 -1561,67 +1577,65 @@@ l_ptr->next_in_no++; if (unlikely(l_ptr->oldest_deferred_in)) head = link_insert_deferred_queue(l_ptr, head); -deliver: - if (likely(msg_isdata(msg))) { - tipc_node_unlock(n_ptr); - tipc_port_recv_msg(buf); - continue; + + /* Deliver packet/message to correct user: */ + if (unlikely(msg_user(msg) == CHANGEOVER_PROTOCOL)) { + if (!tipc_link_tunnel_rcv(n_ptr, &buf)) { + tipc_node_unlock(n_ptr); + continue; + } + msg = buf_msg(buf); + } else if (msg_user(msg) == MSG_FRAGMENTER) { + int rc; + + l_ptr->stats.recv_fragments++; + rc = tipc_link_frag_rcv(&l_ptr->reasm_head, + &l_ptr->reasm_tail, + &buf); + if (rc == LINK_REASM_COMPLETE) { + l_ptr->stats.recv_fragmented++; + msg = buf_msg(buf); + } else { + if (rc == LINK_REASM_ERROR) + tipc_link_reset(l_ptr); + tipc_node_unlock(n_ptr); + continue; + } } + switch (msg_user(msg)) { - int ret; + case TIPC_LOW_IMPORTANCE: + case TIPC_MEDIUM_IMPORTANCE: + case TIPC_HIGH_IMPORTANCE: + case TIPC_CRITICAL_IMPORTANCE: + tipc_node_unlock(n_ptr); + tipc_port_rcv(buf); + continue; case MSG_BUNDLER: l_ptr->stats.recv_bundles++; l_ptr->stats.recv_bundled += msg_msgcnt(msg); tipc_node_unlock(n_ptr); - tipc_link_recv_bundle(buf); + tipc_link_bundle_rcv(buf); continue; case NAME_DISTRIBUTOR: n_ptr->bclink.recv_permitted = true; tipc_node_unlock(n_ptr); - tipc_named_recv(buf); - continue; - case BCAST_PROTOCOL: - tipc_link_recv_sync(n_ptr, buf); - tipc_node_unlock(n_ptr); + tipc_named_rcv(buf); continue; case CONN_MANAGER: tipc_node_unlock(n_ptr); - tipc_port_recv_proto_msg(buf); + tipc_port_proto_rcv(buf); continue; - case MSG_FRAGMENTER: - l_ptr->stats.recv_fragments++; - ret = tipc_link_recv_fragment(&l_ptr->reasm_head, - &l_ptr->reasm_tail, - &buf); - if (ret == LINK_REASM_COMPLETE) { - l_ptr->stats.recv_fragmented++; - msg = buf_msg(buf); - goto deliver; - } - if (ret == LINK_REASM_ERROR) - tipc_link_reset(l_ptr); - tipc_node_unlock(n_ptr); - continue; - case CHANGEOVER_PROTOCOL: - type = msg_type(msg); - if (tipc_link_tunnel_rcv(&l_ptr, &buf)) { - msg = buf_msg(buf); - seq_no = msg_seqno(msg); - if (type == ORIGINAL_MSG) - goto deliver; - goto protocol_check; - } + case BCAST_PROTOCOL: + tipc_link_sync_rcv(n_ptr, buf); break; default: kfree_skb(buf); break; } tipc_node_unlock(n_ptr); - tipc_net_route_msg(buf); continue; unlock_discard: - tipc_node_unlock(n_ptr); discard: kfree_skb(buf); @@@ -1696,7 -1688,7 +1702,7 @@@ static void link_handle_out_of_seq_msg( u32 seq_no = buf_seqno(buf);
if (likely(msg_user(buf_msg(buf)) == LINK_PROTOCOL)) { - link_recv_proto_msg(l_ptr, buf); + tipc_link_proto_rcv(l_ptr, buf); return; }
@@@ -1717,8 -1709,9 +1723,9 @@@ &l_ptr->newest_deferred_in, buf)) { l_ptr->deferred_inqueue_sz++; l_ptr->stats.deferred_recv++; + TIPC_SKB_CB(buf)->deferred = true; if ((l_ptr->deferred_inqueue_sz % 16) == 1) - tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); + tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); } else l_ptr->stats.duplicates++; } @@@ -1726,8 -1719,9 +1733,8 @@@ /* * Send protocol message to the other endpoint. */ -void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, - int probe_msg, u32 gap, u32 tolerance, - u32 priority, u32 ack_mtu) +void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, + u32 gap, u32 tolerance, u32 priority, u32 ack_mtu) { struct sk_buff *buf = NULL; struct tipc_msg *msg = l_ptr->pmsg; @@@ -1826,7 -1820,7 +1833,7 @@@ * Note that network plane id propagates through the network, and may * change at any time. The node with lowest address rules */ -static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf) +static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf) { u32 rec_gap = 0; u32 max_pkt_info; @@@ -1945,8 -1939,8 +1952,8 @@@ msg_last_bcast(msg));
if (rec_gap || (msg_probe(msg))) { - tipc_link_send_proto_msg(l_ptr, STATE_MSG, - 0, rec_gap, 0, 0, max_pkt_ack); + tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, rec_gap, 0, + 0, max_pkt_ack); } if (msg_seq_gap(msg)) { l_ptr->stats.recv_nacks++; @@@ -1985,7 -1979,7 +1992,7 @@@ static void tipc_link_tunnel_xmit(struc } skb_copy_to_linear_data(buf, tunnel_hdr, INT_H_SIZE); skb_copy_to_linear_data_offset(buf, INT_H_SIZE, msg, length); - tipc_link_send_buf(tunnel, buf); + __tipc_link_xmit(tunnel, buf); }
@@@ -2018,7 -2012,7 +2025,7 @@@ void tipc_link_failover_send_queue(stru if (buf) { skb_copy_to_linear_data(buf, &tunnel_hdr, INT_H_SIZE); msg_set_size(&tunnel_hdr, INT_H_SIZE); - tipc_link_send_buf(tunnel, buf); + __tipc_link_xmit(tunnel, buf); } else { pr_warn("%sunable to send changeover msg\n", link_co_err); @@@ -2052,7 -2046,7 +2059,7 @@@ } }
-/* tipc_link_dup_send_queue(): A second link has become active. Tunnel a +/* tipc_link_dup_queue_xmit(): A second link has become active. Tunnel a * duplicate of the first link's send queue via the new link. This way, we * are guaranteed that currently queued packets from a socket are delivered * before future traffic from the same socket, even if this is using the @@@ -2061,7 -2055,7 +2068,7 @@@ * and sequence order is preserved per sender/receiver socket pair. * Owner node is locked. */ -void tipc_link_dup_send_queue(struct tipc_link *l_ptr, +void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr, struct tipc_link *tunnel) { struct sk_buff *iter; @@@ -2091,7 -2085,7 +2098,7 @@@ skb_copy_to_linear_data(outbuf, &tunnel_hdr, INT_H_SIZE); skb_copy_to_linear_data_offset(outbuf, INT_H_SIZE, iter->data, length); - tipc_link_send_buf(tunnel, outbuf); + __tipc_link_xmit(tunnel, outbuf); if (!tipc_link_is_up(l_ptr)) return; iter = iter->next; @@@ -2118,114 -2112,89 +2125,114 @@@ static struct sk_buff *buf_extract(stru return eb; }
-/* tipc_link_tunnel_rcv(): Receive a tunneled packet, sent - * via other link as result of a failover (ORIGINAL_MSG) or - * a new active link (DUPLICATE_MSG). Failover packets are - * returned to the active link for delivery upwards. + + +/* tipc_link_dup_rcv(): Receive a tunnelled DUPLICATE_MSG packet. + * Owner node is locked. + */ +static void tipc_link_dup_rcv(struct tipc_link *l_ptr, + struct sk_buff *t_buf) +{ + struct sk_buff *buf; + + if (!tipc_link_is_up(l_ptr)) + return; + + buf = buf_extract(t_buf, INT_H_SIZE); + if (buf == NULL) { + pr_warn("%sfailed to extract inner dup pkt\n", link_co_err); + return; + } + + /* Add buffer to deferred queue, if applicable: */ + link_handle_out_of_seq_msg(l_ptr, buf); +} + +/* tipc_link_failover_rcv(): Receive a tunnelled ORIGINAL_MSG packet * Owner node is locked. */ -static int tipc_link_tunnel_rcv(struct tipc_link **l_ptr, - struct sk_buff **buf) +static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr, + struct sk_buff *t_buf) { - struct sk_buff *tunnel_buf = *buf; - struct tipc_link *dest_link; + struct tipc_msg *t_msg = buf_msg(t_buf); + struct sk_buff *buf = NULL; struct tipc_msg *msg; - struct tipc_msg *tunnel_msg = buf_msg(tunnel_buf); - u32 msg_typ = msg_type(tunnel_msg); - u32 msg_count = msg_msgcnt(tunnel_msg); - u32 bearer_id = msg_bearer_id(tunnel_msg);
- if (bearer_id >= MAX_BEARERS) - goto exit; - dest_link = (*l_ptr)->owner->links[bearer_id]; - if (!dest_link) - goto exit; - if (dest_link == *l_ptr) { - pr_err("Unexpected changeover message on link <%s>\n", - (*l_ptr)->name); - goto exit; - } - *l_ptr = dest_link; - msg = msg_get_wrapped(tunnel_msg); + if (tipc_link_is_up(l_ptr)) + tipc_link_reset(l_ptr);
- if (msg_typ == DUPLICATE_MSG) { - if (less(msg_seqno(msg), mod(dest_link->next_in_no))) - goto exit; - *buf = buf_extract(tunnel_buf, INT_H_SIZE); - if (*buf == NULL) { - pr_warn("%sduplicate msg dropped\n", link_co_err); + /* First failover packet? */ + if (l_ptr->exp_msg_count == START_CHANGEOVER) + l_ptr->exp_msg_count = msg_msgcnt(t_msg); + + /* Should there be an inner packet? */ + if (l_ptr->exp_msg_count) { + l_ptr->exp_msg_count--; + buf = buf_extract(t_buf, INT_H_SIZE); + if (buf == NULL) { + pr_warn("%sno inner failover pkt\n", link_co_err); goto exit; } - kfree_skb(tunnel_buf); - return 1; - } + msg = buf_msg(buf);
- /* First original message ?: */ - if (tipc_link_is_up(dest_link)) { - pr_info("%s<%s>, changeover initiated by peer\n", link_rst_msg, - dest_link->name); - tipc_link_reset(dest_link); - dest_link->exp_msg_count = msg_count; - if (!msg_count) - goto exit; - } else if (dest_link->exp_msg_count == START_CHANGEOVER) { - dest_link->exp_msg_count = msg_count; - if (!msg_count) + if (less(msg_seqno(msg), l_ptr->reset_checkpoint)) { + kfree_skb(buf); + buf = NULL; goto exit; + } + if (msg_user(msg) == MSG_FRAGMENTER) { + l_ptr->stats.recv_fragments++; + tipc_link_frag_rcv(&l_ptr->reasm_head, + &l_ptr->reasm_tail, + &buf); + } } +exit: + if ((l_ptr->exp_msg_count == 0) && (l_ptr->flags & LINK_STOPPED)) { + tipc_node_detach_link(l_ptr->owner, l_ptr); + kfree(l_ptr); + } + return buf; +} + +/* tipc_link_tunnel_rcv(): Receive a tunnelled packet, sent + * via other link as result of a failover (ORIGINAL_MSG) or + * a new active link (DUPLICATE_MSG). Failover packets are + * returned to the active link for delivery upwards. + * Owner node is locked. + */ +static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr, + struct sk_buff **buf) +{ + struct sk_buff *t_buf = *buf; + struct tipc_link *l_ptr; + struct tipc_msg *t_msg = buf_msg(t_buf); + u32 bearer_id = msg_bearer_id(t_msg);
- /* Receive original message */ - if (dest_link->exp_msg_count == 0) { - pr_warn("%sgot too many tunnelled messages\n", link_co_err); + *buf = NULL; + + if (bearer_id >= MAX_BEARERS) goto exit; - } - dest_link->exp_msg_count--; - if (less(msg_seqno(msg), dest_link->reset_checkpoint)) { + + l_ptr = n_ptr->links[bearer_id]; + if (!l_ptr) goto exit; - } else { - *buf = buf_extract(tunnel_buf, INT_H_SIZE); - if (*buf != NULL) { - kfree_skb(tunnel_buf); - return 1; - } else { - pr_warn("%soriginal msg dropped\n", link_co_err); - } - } + + if (msg_type(t_msg) == DUPLICATE_MSG) + tipc_link_dup_rcv(l_ptr, t_buf); + else if (msg_type(t_msg) == ORIGINAL_MSG) + *buf = tipc_link_failover_rcv(l_ptr, t_buf); + else + pr_warn("%sunknown tunnel pkt received\n", link_co_err); exit: - *buf = NULL; - kfree_skb(tunnel_buf); - return 0; + kfree_skb(t_buf); + return *buf != NULL; }
/* * Bundler functionality: */ -void tipc_link_recv_bundle(struct sk_buff *buf) +void tipc_link_bundle_rcv(struct sk_buff *buf) { u32 msgcount = msg_msgcnt(buf_msg(buf)); u32 pos = INT_H_SIZE; @@@ -2248,11 -2217,11 +2255,11 @@@ */
/* - * link_send_long_buf: Entry for buffers needing fragmentation. + * tipc_link_frag_xmit: Entry for buffers needing fragmentation. * The buffer is complete, inclusive total message length. * Returns user data length. */ -static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf) +static int tipc_link_frag_xmit(struct tipc_link *l_ptr, struct sk_buff *buf) { struct sk_buff *buf_chain = NULL; struct sk_buff *buf_chain_tail = (struct sk_buff *)&buf_chain; @@@ -2315,11 -2284,12 +2322,11 @@@ return dsz; }
-/* - * tipc_link_recv_fragment(): Called with node lock on. Returns +/* tipc_link_frag_rcv(): Called with node lock on. Returns * the reassembled buffer if message is complete. */ -int tipc_link_recv_fragment(struct sk_buff **head, struct sk_buff **tail, - struct sk_buff **fbuf) +int tipc_link_frag_rcv(struct sk_buff **head, struct sk_buff **tail, + struct sk_buff **fbuf) { struct sk_buff *frag = *fbuf; struct tipc_msg *msg = buf_msg(frag); @@@ -2333,7 -2303,6 +2340,7 @@@ goto out_free; *head = frag; skb_frag_list_init(*head); + *fbuf = NULL; return 0; } else if (*head && skb_try_coalesce(*head, frag, &headstolen, &delta)) { @@@ -2353,12 -2322,10 +2360,12 @@@ *tail = *head = NULL; return LINK_REASM_COMPLETE; } + *fbuf = NULL; return 0; out_free: pr_warn_ratelimited("Link unable to reassemble fragmented message\n"); kfree_skb(*fbuf); + *fbuf = NULL; return LINK_REASM_ERROR; }
@@@ -2392,40 -2359,35 +2399,40 @@@ void tipc_link_set_queue_limits(struct l_ptr->queue_limit[MSG_FRAGMENTER] = 4000; }
-/** - * link_find_link - locate link by name - * @name: ptr to link name string - * @node: ptr to area to be filled with ptr to associated node - * +/* tipc_link_find_owner - locate owner node of link by link's name + * @name: pointer to link name string + * @bearer_id: pointer to index in 'node->links' array where the link was found. * Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted; * this also prevents link deletion. * - * Returns pointer to link (or 0 if invalid link name). + * Returns pointer to node owning the link, or 0 if no matching link is found. */ -static struct tipc_link *link_find_link(const char *name, - struct tipc_node **node) +static struct tipc_node *tipc_link_find_owner(const char *link_name, + unsigned int *bearer_id) { struct tipc_link *l_ptr; struct tipc_node *n_ptr; + struct tipc_node *tmp_n_ptr; + struct tipc_node *found_node = 0; + int i;
- list_for_each_entry(n_ptr, &tipc_node_list, list) { + *bearer_id = 0; + list_for_each_entry_safe(n_ptr, tmp_n_ptr, &tipc_node_list, list) { + tipc_node_lock(n_ptr); for (i = 0; i < MAX_BEARERS; i++) { l_ptr = n_ptr->links[i]; - if (l_ptr && !strcmp(l_ptr->name, name)) - goto found; + if (l_ptr && !strcmp(l_ptr->name, link_name)) { + *bearer_id = i; + found_node = n_ptr; + break; + } } + tipc_node_unlock(n_ptr); + if (found_node) + break; } - l_ptr = NULL; - n_ptr = NULL; -found: - *node = n_ptr; - return l_ptr; + return found_node; }
/** @@@ -2467,33 -2429,32 +2474,33 @@@ static int link_cmd_set_value(const cha struct tipc_link *l_ptr; struct tipc_bearer *b_ptr; struct tipc_media *m_ptr; + int bearer_id; int res = 0;
- l_ptr = link_find_link(name, &node); - if (l_ptr) { - /* - * acquire node lock for tipc_link_send_proto_msg(). - * see "TIPC locking policy" in net.c. - */ + node = tipc_link_find_owner(name, &bearer_id); + if (node) { tipc_node_lock(node); - switch (cmd) { - case TIPC_CMD_SET_LINK_TOL: - link_set_supervision_props(l_ptr, new_value); - tipc_link_send_proto_msg(l_ptr, - STATE_MSG, 0, 0, new_value, 0, 0); - break; - case TIPC_CMD_SET_LINK_PRI: - l_ptr->priority = new_value; - tipc_link_send_proto_msg(l_ptr, - STATE_MSG, 0, 0, 0, new_value, 0); - break; - case TIPC_CMD_SET_LINK_WINDOW: - tipc_link_set_queue_limits(l_ptr, new_value); - break; - default: - res = -EINVAL; - break; + l_ptr = node->links[bearer_id]; + + if (l_ptr) { + switch (cmd) { + case TIPC_CMD_SET_LINK_TOL: + link_set_supervision_props(l_ptr, new_value); + tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, + new_value, 0, 0); + break; + case TIPC_CMD_SET_LINK_PRI: + l_ptr->priority = new_value; + tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, + 0, new_value, 0); + break; + case TIPC_CMD_SET_LINK_WINDOW: + tipc_link_set_queue_limits(l_ptr, new_value); + break; + default: + res = -EINVAL; + break; + } } tipc_node_unlock(node); return res; @@@ -2588,7 -2549,6 +2595,7 @@@ struct sk_buff *tipc_link_cmd_reset_sta char *link_name; struct tipc_link *l_ptr; struct tipc_node *node; + unsigned int bearer_id;
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); @@@ -2599,19 -2559,15 +2606,19 @@@ return tipc_cfg_reply_error_string("link not found"); return tipc_cfg_reply_none(); } - read_lock_bh(&tipc_net_lock); - l_ptr = link_find_link(link_name, &node); - if (!l_ptr) { + node = tipc_link_find_owner(link_name, &bearer_id); + if (!node) { read_unlock_bh(&tipc_net_lock); return tipc_cfg_reply_error_string("link not found"); } - tipc_node_lock(node); + l_ptr = node->links[bearer_id]; + if (!l_ptr) { + tipc_node_unlock(node); + read_unlock_bh(&tipc_net_lock); + return tipc_cfg_reply_error_string("link not found"); + } link_reset_statistics(l_ptr); tipc_node_unlock(node); read_unlock_bh(&tipc_net_lock); @@@ -2641,27 -2597,18 +2648,27 @@@ static int tipc_link_stats(const char * struct tipc_node *node; char *status; u32 profile_total = 0; + unsigned int bearer_id; int ret;
if (!strcmp(name, tipc_bclink_name)) return tipc_bclink_stats(buf, buf_size);
read_lock_bh(&tipc_net_lock); - l = link_find_link(name, &node); - if (!l) { + node = tipc_link_find_owner(name, &bearer_id); + if (!node) { read_unlock_bh(&tipc_net_lock); return 0; } tipc_node_lock(node); + + l = node->links[bearer_id]; + if (!l) { + tipc_node_unlock(node); + read_unlock_bh(&tipc_net_lock); + return 0; + } + s = &l->stats;
if (tipc_link_is_active(l))
linux-merge@lists.open-mesh.org