diff options
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 70 | ||||
-rw-r--r-- | drivers/net/bonding/bond_procfs.c | 13 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 7 |
3 files changed, 36 insertions, 54 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index c34cc1e7c6f..7f8756825b8 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -550,7 +550,7 @@ down: | |||
550 | /* | 550 | /* |
551 | * Get link speed and duplex from the slave's base driver | 551 | * Get link speed and duplex from the slave's base driver |
552 | * using ethtool. If for some reason the call fails or the | 552 | * using ethtool. If for some reason the call fails or the |
553 | * values are invalid, fake speed and duplex to 100/Full | 553 | * values are invalid, set speed and duplex to -1, |
554 | * and return error. | 554 | * and return error. |
555 | */ | 555 | */ |
556 | static int bond_update_speed_duplex(struct slave *slave) | 556 | static int bond_update_speed_duplex(struct slave *slave) |
@@ -560,9 +560,8 @@ static int bond_update_speed_duplex(struct slave *slave) | |||
560 | u32 slave_speed; | 560 | u32 slave_speed; |
561 | int res; | 561 | int res; |
562 | 562 | ||
563 | /* Fake speed and duplex */ | 563 | slave->speed = SPEED_UNKNOWN; |
564 | slave->speed = SPEED_100; | 564 | slave->duplex = DUPLEX_UNKNOWN; |
565 | slave->duplex = DUPLEX_FULL; | ||
566 | 565 | ||
567 | res = __ethtool_get_settings(slave_dev, &ecmd); | 566 | res = __ethtool_get_settings(slave_dev, &ecmd); |
568 | if (res < 0) | 567 | if (res < 0) |
@@ -1751,16 +1750,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1751 | new_slave->link = BOND_LINK_DOWN; | 1750 | new_slave->link = BOND_LINK_DOWN; |
1752 | } | 1751 | } |
1753 | 1752 | ||
1754 | if (bond_update_speed_duplex(new_slave) && | 1753 | bond_update_speed_duplex(new_slave); |
1755 | (new_slave->link != BOND_LINK_DOWN)) { | ||
1756 | pr_warning("%s: Warning: failed to get speed and duplex from %s, assumed to be 100Mb/sec and Full.\n", | ||
1757 | bond_dev->name, new_slave->dev->name); | ||
1758 | |||
1759 | if (bond->params.mode == BOND_MODE_8023AD) { | ||
1760 | pr_warning("%s: Warning: Operation of 802.3ad mode requires ETHTOOL support in base driver for proper aggregator selection.\n", | ||
1761 | bond_dev->name); | ||
1762 | } | ||
1763 | } | ||
1764 | 1754 | ||
1765 | if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { | 1755 | if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { |
1766 | /* if there is a primary slave, remember it */ | 1756 | /* if there is a primary slave, remember it */ |
@@ -2563,30 +2553,6 @@ re_arm: | |||
2563 | } | 2553 | } |
2564 | } | 2554 | } |
2565 | 2555 | ||
2566 | static __be32 bond_glean_dev_ip(struct net_device *dev) | ||
2567 | { | ||
2568 | struct in_device *idev; | ||
2569 | struct in_ifaddr *ifa; | ||
2570 | __be32 addr = 0; | ||
2571 | |||
2572 | if (!dev) | ||
2573 | return 0; | ||
2574 | |||
2575 | rcu_read_lock(); | ||
2576 | idev = __in_dev_get_rcu(dev); | ||
2577 | if (!idev) | ||
2578 | goto out; | ||
2579 | |||
2580 | ifa = idev->ifa_list; | ||
2581 | if (!ifa) | ||
2582 | goto out; | ||
2583 | |||
2584 | addr = ifa->ifa_local; | ||
2585 | out: | ||
2586 | rcu_read_unlock(); | ||
2587 | return addr; | ||
2588 | } | ||
2589 | |||
2590 | static int bond_has_this_ip(struct bonding *bond, __be32 ip) | 2556 | static int bond_has_this_ip(struct bonding *bond, __be32 ip) |
2591 | { | 2557 | { |
2592 | struct vlan_entry *vlan; | 2558 | struct vlan_entry *vlan; |
@@ -3220,6 +3186,7 @@ static int bond_slave_netdev_event(unsigned long event, | |||
3220 | { | 3186 | { |
3221 | struct net_device *bond_dev = slave_dev->master; | 3187 | struct net_device *bond_dev = slave_dev->master; |
3222 | struct bonding *bond = netdev_priv(bond_dev); | 3188 | struct bonding *bond = netdev_priv(bond_dev); |
3189 | struct slave *slave = NULL; | ||
3223 | 3190 | ||
3224 | switch (event) { | 3191 | switch (event) { |
3225 | case NETDEV_UNREGISTER: | 3192 | case NETDEV_UNREGISTER: |
@@ -3230,20 +3197,16 @@ static int bond_slave_netdev_event(unsigned long event, | |||
3230 | bond_release(bond_dev, slave_dev); | 3197 | bond_release(bond_dev, slave_dev); |
3231 | } | 3198 | } |
3232 | break; | 3199 | break; |
3200 | case NETDEV_UP: | ||
3233 | case NETDEV_CHANGE: | 3201 | case NETDEV_CHANGE: |
3234 | if (bond->params.mode == BOND_MODE_8023AD || bond_is_lb(bond)) { | 3202 | slave = bond_get_slave_by_dev(bond, slave_dev); |
3235 | struct slave *slave; | 3203 | if (slave) { |
3204 | u32 old_speed = slave->speed; | ||
3205 | u8 old_duplex = slave->duplex; | ||
3236 | 3206 | ||
3237 | slave = bond_get_slave_by_dev(bond, slave_dev); | 3207 | bond_update_speed_duplex(slave); |
3238 | if (slave) { | ||
3239 | u32 old_speed = slave->speed; | ||
3240 | u8 old_duplex = slave->duplex; | ||
3241 | |||
3242 | bond_update_speed_duplex(slave); | ||
3243 | |||
3244 | if (bond_is_lb(bond)) | ||
3245 | break; | ||
3246 | 3208 | ||
3209 | if (bond->params.mode == BOND_MODE_8023AD) { | ||
3247 | if (old_speed != slave->speed) | 3210 | if (old_speed != slave->speed) |
3248 | bond_3ad_adapter_speed_changed(slave); | 3211 | bond_3ad_adapter_speed_changed(slave); |
3249 | if (old_duplex != slave->duplex) | 3212 | if (old_duplex != slave->duplex) |
@@ -3335,6 +3298,10 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
3335 | struct bonding *bond; | 3298 | struct bonding *bond; |
3336 | struct vlan_entry *vlan; | 3299 | struct vlan_entry *vlan; |
3337 | 3300 | ||
3301 | /* we only care about primary address */ | ||
3302 | if(ifa->ifa_flags & IFA_F_SECONDARY) | ||
3303 | return NOTIFY_DONE; | ||
3304 | |||
3338 | list_for_each_entry(bond, &bn->dev_list, bond_list) { | 3305 | list_for_each_entry(bond, &bn->dev_list, bond_list) { |
3339 | if (bond->dev == event_dev) { | 3306 | if (bond->dev == event_dev) { |
3340 | switch (event) { | 3307 | switch (event) { |
@@ -3342,7 +3309,7 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
3342 | bond->master_ip = ifa->ifa_local; | 3309 | bond->master_ip = ifa->ifa_local; |
3343 | return NOTIFY_OK; | 3310 | return NOTIFY_OK; |
3344 | case NETDEV_DOWN: | 3311 | case NETDEV_DOWN: |
3345 | bond->master_ip = bond_glean_dev_ip(bond->dev); | 3312 | bond->master_ip = 0; |
3346 | return NOTIFY_OK; | 3313 | return NOTIFY_OK; |
3347 | default: | 3314 | default: |
3348 | return NOTIFY_DONE; | 3315 | return NOTIFY_DONE; |
@@ -3358,8 +3325,7 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
3358 | vlan->vlan_ip = ifa->ifa_local; | 3325 | vlan->vlan_ip = ifa->ifa_local; |
3359 | return NOTIFY_OK; | 3326 | return NOTIFY_OK; |
3360 | case NETDEV_DOWN: | 3327 | case NETDEV_DOWN: |
3361 | vlan->vlan_ip = | 3328 | vlan->vlan_ip = 0; |
3362 | bond_glean_dev_ip(vlan_dev); | ||
3363 | return NOTIFY_OK; | 3329 | return NOTIFY_OK; |
3364 | default: | 3330 | default: |
3365 | return NOTIFY_DONE; | 3331 | return NOTIFY_DONE; |
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c index 95de93b9038..ad284baafe8 100644 --- a/drivers/net/bonding/bond_procfs.c +++ b/drivers/net/bonding/bond_procfs.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <linux/proc_fs.h> | 1 | #include <linux/proc_fs.h> |
2 | #include <linux/export.h> | ||
2 | #include <net/net_namespace.h> | 3 | #include <net/net_namespace.h> |
3 | #include <net/netns/generic.h> | 4 | #include <net/netns/generic.h> |
4 | #include "bonding.h" | 5 | #include "bonding.h" |
@@ -157,8 +158,16 @@ static void bond_info_show_slave(struct seq_file *seq, | |||
157 | seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name); | 158 | seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name); |
158 | seq_printf(seq, "MII Status: %s\n", | 159 | seq_printf(seq, "MII Status: %s\n", |
159 | (slave->link == BOND_LINK_UP) ? "up" : "down"); | 160 | (slave->link == BOND_LINK_UP) ? "up" : "down"); |
160 | seq_printf(seq, "Speed: %d Mbps\n", slave->speed); | 161 | if (slave->speed == SPEED_UNKNOWN) |
161 | seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half"); | 162 | seq_printf(seq, "Speed: %s\n", "Unknown"); |
163 | else | ||
164 | seq_printf(seq, "Speed: %d Mbps\n", slave->speed); | ||
165 | |||
166 | if (slave->duplex == DUPLEX_UNKNOWN) | ||
167 | seq_printf(seq, "Duplex: %s\n", "Unknown"); | ||
168 | else | ||
169 | seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half"); | ||
170 | |||
162 | seq_printf(seq, "Link Failure Count: %u\n", | 171 | seq_printf(seq, "Link Failure Count: %u\n", |
163 | slave->link_failure_count); | 172 | slave->link_failure_count); |
164 | 173 | ||
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 5a20804fdec..4ef7e2fd9fe 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -319,6 +319,13 @@ static ssize_t bonding_store_mode(struct device *d, | |||
319 | goto out; | 319 | goto out; |
320 | } | 320 | } |
321 | 321 | ||
322 | if (bond->slave_cnt > 0) { | ||
323 | pr_err("unable to update mode of %s because it has slaves.\n", | ||
324 | bond->dev->name); | ||
325 | ret = -EPERM; | ||
326 | goto out; | ||
327 | } | ||
328 | |||
322 | new_value = bond_parse_parm(buf, bond_mode_tbl); | 329 | new_value = bond_parse_parm(buf, bond_mode_tbl); |
323 | if (new_value < 0) { | 330 | if (new_value < 0) { |
324 | pr_err("%s: Ignoring invalid mode value %.*s.\n", | 331 | pr_err("%s: Ignoring invalid mode value %.*s.\n", |