aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_netlink.c78
-rw-r--r--drivers/net/bonding/bond_options.c80
-rw-r--r--drivers/net/bonding/bond_sysfs.c116
-rw-r--r--drivers/net/bonding/bonding.h7
4 files changed, 220 insertions, 61 deletions
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index e161c9cbd91e..84acd144d075 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -19,6 +19,7 @@
19#include <linux/if_ether.h> 19#include <linux/if_ether.h>
20#include <net/netlink.h> 20#include <net/netlink.h>
21#include <net/rtnetlink.h> 21#include <net/rtnetlink.h>
22#include <linux/reciprocal_div.h>
22#include "bonding.h" 23#include "bonding.h"
23 24
24static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { 25static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
@@ -37,6 +38,11 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
37 [IFLA_BOND_FAIL_OVER_MAC] = { .type = NLA_U8 }, 38 [IFLA_BOND_FAIL_OVER_MAC] = { .type = NLA_U8 },
38 [IFLA_BOND_XMIT_HASH_POLICY] = { .type = NLA_U8 }, 39 [IFLA_BOND_XMIT_HASH_POLICY] = { .type = NLA_U8 },
39 [IFLA_BOND_RESEND_IGMP] = { .type = NLA_U32 }, 40 [IFLA_BOND_RESEND_IGMP] = { .type = NLA_U32 },
41 [IFLA_BOND_NUM_PEER_NOTIF] = { .type = NLA_U8 },
42 [IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NLA_U8 },
43 [IFLA_BOND_MIN_LINKS] = { .type = NLA_U32 },
44 [IFLA_BOND_LP_INTERVAL] = { .type = NLA_U32 },
45 [IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NLA_U32 },
40}; 46};
41 47
42static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) 48static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -204,6 +210,48 @@ static int bond_changelink(struct net_device *bond_dev,
204 if (err) 210 if (err)
205 return err; 211 return err;
206 } 212 }
213 if (data[IFLA_BOND_NUM_PEER_NOTIF]) {
214 int num_peer_notif =
215 nla_get_u8(data[IFLA_BOND_NUM_PEER_NOTIF]);
216
217 err = bond_option_num_peer_notif_set(bond, num_peer_notif);
218 if (err)
219 return err;
220 }
221 if (data[IFLA_BOND_ALL_SLAVES_ACTIVE]) {
222 int all_slaves_active =
223 nla_get_u8(data[IFLA_BOND_ALL_SLAVES_ACTIVE]);
224
225 err = bond_option_all_slaves_active_set(bond,
226 all_slaves_active);
227 if (err)
228 return err;
229 }
230 if (data[IFLA_BOND_MIN_LINKS]) {
231 int min_links =
232 nla_get_u32(data[IFLA_BOND_MIN_LINKS]);
233
234 err = bond_option_min_links_set(bond, min_links);
235 if (err)
236 return err;
237 }
238 if (data[IFLA_BOND_LP_INTERVAL]) {
239 int lp_interval =
240 nla_get_u32(data[IFLA_BOND_LP_INTERVAL]);
241
242 err = bond_option_lp_interval_set(bond, lp_interval);
243 if (err)
244 return err;
245 }
246 if (data[IFLA_BOND_PACKETS_PER_SLAVE]) {
247 int packets_per_slave =
248 nla_get_u32(data[IFLA_BOND_PACKETS_PER_SLAVE]);
249
250 err = bond_option_packets_per_slave_set(bond,
251 packets_per_slave);
252 if (err)
253 return err;
254 }
207 return 0; 255 return 0;
208} 256}
209 257
@@ -237,6 +285,11 @@ static size_t bond_get_size(const struct net_device *bond_dev)
237 nla_total_size(sizeof(u8)) + /* IFLA_BOND_FAIL_OVER_MAC */ 285 nla_total_size(sizeof(u8)) + /* IFLA_BOND_FAIL_OVER_MAC */
238 nla_total_size(sizeof(u8)) + /* IFLA_BOND_XMIT_HASH_POLICY */ 286 nla_total_size(sizeof(u8)) + /* IFLA_BOND_XMIT_HASH_POLICY */
239 nla_total_size(sizeof(u32)) + /* IFLA_BOND_RESEND_IGMP */ 287 nla_total_size(sizeof(u32)) + /* IFLA_BOND_RESEND_IGMP */
288 nla_total_size(sizeof(u8)) + /* IFLA_BOND_NUM_PEER_NOTIF */
289 nla_total_size(sizeof(u8)) + /* IFLA_BOND_ALL_SLAVES_ACTIVE */
290 nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIN_LINKS */
291 nla_total_size(sizeof(u32)) + /* IFLA_BOND_LP_INTERVAL */
292 nla_total_size(sizeof(u32)) + /* IFLA_BOND_PACKETS_PER_SLAVE */
240 0; 293 0;
241} 294}
242 295
@@ -246,6 +299,7 @@ static int bond_fill_info(struct sk_buff *skb,
246 struct bonding *bond = netdev_priv(bond_dev); 299 struct bonding *bond = netdev_priv(bond_dev);
247 struct net_device *slave_dev = bond_option_active_slave_get(bond); 300 struct net_device *slave_dev = bond_option_active_slave_get(bond);
248 struct nlattr *targets; 301 struct nlattr *targets;
302 unsigned int packets_per_slave;
249 int i, targets_added; 303 int i, targets_added;
250 304
251 if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode)) 305 if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode))
@@ -317,6 +371,30 @@ static int bond_fill_info(struct sk_buff *skb,
317 bond->params.resend_igmp)) 371 bond->params.resend_igmp))
318 goto nla_put_failure; 372 goto nla_put_failure;
319 373
374 if (nla_put_u8(skb, IFLA_BOND_NUM_PEER_NOTIF,
375 bond->params.num_peer_notif))
376 goto nla_put_failure;
377
378 if (nla_put_u8(skb, IFLA_BOND_ALL_SLAVES_ACTIVE,
379 bond->params.all_slaves_active))
380 goto nla_put_failure;
381
382 if (nla_put_u32(skb, IFLA_BOND_MIN_LINKS,
383 bond->params.min_links))
384 goto nla_put_failure;
385
386 if (nla_put_u32(skb, IFLA_BOND_LP_INTERVAL,
387 bond->params.lp_interval))
388 goto nla_put_failure;
389
390 packets_per_slave = bond->params.packets_per_slave;
391 if (packets_per_slave > 1)
392 packets_per_slave = reciprocal_value(packets_per_slave);
393
394 if (nla_put_u32(skb, IFLA_BOND_PACKETS_PER_SLAVE,
395 packets_per_slave))
396 goto nla_put_failure;
397
320 return 0; 398 return 0;
321 399
322nla_put_failure: 400nla_put_failure:
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 1ed7dff9a679..f8a2cd8c7b57 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -16,6 +16,7 @@
16#include <linux/netdevice.h> 16#include <linux/netdevice.h>
17#include <linux/rwlock.h> 17#include <linux/rwlock.h>
18#include <linux/rcupdate.h> 18#include <linux/rcupdate.h>
19#include <linux/reciprocal_div.h>
19#include "bonding.h" 20#include "bonding.h"
20 21
21static bool bond_mode_is_valid(int mode) 22static bool bond_mode_is_valid(int mode)
@@ -576,3 +577,82 @@ int bond_option_resend_igmp_set(struct bonding *bond, int resend_igmp)
576 577
577 return 0; 578 return 0;
578} 579}
580
581int bond_option_num_peer_notif_set(struct bonding *bond, int num_peer_notif)
582{
583 bond->params.num_peer_notif = num_peer_notif;
584 return 0;
585}
586
587int bond_option_all_slaves_active_set(struct bonding *bond,
588 int all_slaves_active)
589{
590 struct list_head *iter;
591 struct slave *slave;
592
593 if (all_slaves_active == bond->params.all_slaves_active)
594 return 0;
595
596 if ((all_slaves_active == 0) || (all_slaves_active == 1)) {
597 bond->params.all_slaves_active = all_slaves_active;
598 } else {
599 pr_info("%s: Ignoring invalid all_slaves_active value %d.\n",
600 bond->dev->name, all_slaves_active);
601 return -EINVAL;
602 }
603
604 bond_for_each_slave(bond, slave, iter) {
605 if (!bond_is_active_slave(slave)) {
606 if (all_slaves_active)
607 slave->inactive = 0;
608 else
609 slave->inactive = 1;
610 }
611 }
612
613 return 0;
614}
615
616int bond_option_min_links_set(struct bonding *bond, int min_links)
617{
618 pr_info("%s: Setting min links value to %u\n",
619 bond->dev->name, min_links);
620 bond->params.min_links = min_links;
621
622 return 0;
623}
624
625int bond_option_lp_interval_set(struct bonding *bond, int lp_interval)
626{
627 if (lp_interval <= 0) {
628 pr_err("%s: lp_interval must be between 1 and %d\n",
629 bond->dev->name, INT_MAX);
630 return -EINVAL;
631 }
632
633 bond->params.lp_interval = lp_interval;
634
635 return 0;
636}
637
638int bond_option_packets_per_slave_set(struct bonding *bond,
639 int packets_per_slave)
640{
641 if (packets_per_slave < 0 || packets_per_slave > USHRT_MAX) {
642 pr_err("%s: packets_per_slave must be between 0 and %u\n",
643 bond->dev->name, USHRT_MAX);
644 return -EINVAL;
645 }
646
647 if (bond->params.mode != BOND_MODE_ROUNDROBIN)
648 pr_warn("%s: Warning: packets_per_slave has effect only in balance-rr mode\n",
649 bond->dev->name);
650
651 if (packets_per_slave > 1)
652 bond->params.packets_per_slave =
653 reciprocal_value(packets_per_slave);
654 else
655 bond->params.packets_per_slave = packets_per_slave;
656
657 return 0;
658}
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index f5c1a54095b9..a0a3476fadba 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -722,10 +722,15 @@ static ssize_t bonding_store_min_links(struct device *d,
722 return ret; 722 return ret;
723 } 723 }
724 724
725 pr_info("%s: Setting min links value to %u\n", 725 if (!rtnl_trylock())
726 bond->dev->name, new_value); 726 return restart_syscall();
727 bond->params.min_links = new_value; 727
728 return count; 728 ret = bond_option_min_links_set(bond, new_value);
729 if (!ret)
730 ret = count;
731
732 rtnl_unlock();
733 return ret;
729} 734}
730static DEVICE_ATTR(min_links, S_IRUGO | S_IWUSR, 735static DEVICE_ATTR(min_links, S_IRUGO | S_IWUSR,
731 bonding_show_min_links, bonding_store_min_links); 736 bonding_show_min_links, bonding_store_min_links);
@@ -790,8 +795,25 @@ static ssize_t bonding_store_num_peer_notif(struct device *d,
790 const char *buf, size_t count) 795 const char *buf, size_t count)
791{ 796{
792 struct bonding *bond = to_bond(d); 797 struct bonding *bond = to_bond(d);
793 int err = kstrtou8(buf, 10, &bond->params.num_peer_notif); 798 u8 new_value;
794 return err ? err : count; 799 int ret;
800
801 ret = kstrtou8(buf, 10, &new_value);
802 if (!ret) {
803 pr_err("%s: invalid value %s specified.\n",
804 bond->dev->name, buf);
805 return ret;
806 }
807
808 if (!rtnl_trylock())
809 return restart_syscall();
810
811 ret = bond_option_num_peer_notif_set(bond, new_value);
812 if (!ret)
813 ret = count;
814
815 rtnl_unlock();
816 return ret;
795} 817}
796static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, 818static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR,
797 bonding_show_num_peer_notif, bonding_store_num_peer_notif); 819 bonding_show_num_peer_notif, bonding_store_num_peer_notif);
@@ -1273,41 +1295,21 @@ static ssize_t bonding_store_slaves_active(struct device *d,
1273 const char *buf, size_t count) 1295 const char *buf, size_t count)
1274{ 1296{
1275 struct bonding *bond = to_bond(d); 1297 struct bonding *bond = to_bond(d);
1276 int new_value, ret = count; 1298 int new_value, ret;
1277 struct list_head *iter;
1278 struct slave *slave;
1279
1280 if (!rtnl_trylock())
1281 return restart_syscall();
1282 1299
1283 if (sscanf(buf, "%d", &new_value) != 1) { 1300 if (sscanf(buf, "%d", &new_value) != 1) {
1284 pr_err("%s: no all_slaves_active value specified.\n", 1301 pr_err("%s: no all_slaves_active value specified.\n",
1285 bond->dev->name); 1302 bond->dev->name);
1286 ret = -EINVAL; 1303 return -EINVAL;
1287 goto out;
1288 } 1304 }
1289 1305
1290 if (new_value == bond->params.all_slaves_active) 1306 if (!rtnl_trylock())
1291 goto out; 1307 return restart_syscall();
1292 1308
1293 if ((new_value == 0) || (new_value == 1)) { 1309 ret = bond_option_all_slaves_active_set(bond, new_value);
1294 bond->params.all_slaves_active = new_value; 1310 if (!ret)
1295 } else { 1311 ret = count;
1296 pr_info("%s: Ignoring invalid all_slaves_active value %d.\n",
1297 bond->dev->name, new_value);
1298 ret = -EINVAL;
1299 goto out;
1300 }
1301 1312
1302 bond_for_each_slave(bond, slave, iter) {
1303 if (!bond_is_active_slave(slave)) {
1304 if (new_value)
1305 slave->inactive = 0;
1306 else
1307 slave->inactive = 1;
1308 }
1309 }
1310out:
1311 rtnl_unlock(); 1313 rtnl_unlock();
1312 return ret; 1314 return ret;
1313} 1315}
@@ -1367,24 +1369,22 @@ static ssize_t bonding_store_lp_interval(struct device *d,
1367 const char *buf, size_t count) 1369 const char *buf, size_t count)
1368{ 1370{
1369 struct bonding *bond = to_bond(d); 1371 struct bonding *bond = to_bond(d);
1370 int new_value, ret = count; 1372 int new_value, ret;
1371 1373
1372 if (sscanf(buf, "%d", &new_value) != 1) { 1374 if (sscanf(buf, "%d", &new_value) != 1) {
1373 pr_err("%s: no lp interval value specified.\n", 1375 pr_err("%s: no lp interval value specified.\n",
1374 bond->dev->name); 1376 bond->dev->name);
1375 ret = -EINVAL; 1377 return -EINVAL;
1376 goto out;
1377 } 1378 }
1378 1379
1379 if (new_value <= 0) { 1380 if (!rtnl_trylock())
1380 pr_err ("%s: lp_interval must be between 1 and %d\n", 1381 return restart_syscall();
1381 bond->dev->name, INT_MAX);
1382 ret = -EINVAL;
1383 goto out;
1384 }
1385 1382
1386 bond->params.lp_interval = new_value; 1383 ret = bond_option_lp_interval_set(bond, new_value);
1387out: 1384 if (!ret)
1385 ret = count;
1386
1387 rtnl_unlock();
1388 return ret; 1388 return ret;
1389} 1389}
1390 1390
@@ -1409,28 +1409,22 @@ static ssize_t bonding_store_packets_per_slave(struct device *d,
1409 const char *buf, size_t count) 1409 const char *buf, size_t count)
1410{ 1410{
1411 struct bonding *bond = to_bond(d); 1411 struct bonding *bond = to_bond(d);
1412 int new_value, ret = count; 1412 int new_value, ret;
1413 1413
1414 if (sscanf(buf, "%d", &new_value) != 1) { 1414 if (sscanf(buf, "%d", &new_value) != 1) {
1415 pr_err("%s: no packets_per_slave value specified.\n", 1415 pr_err("%s: no packets_per_slave value specified.\n",
1416 bond->dev->name); 1416 bond->dev->name);
1417 ret = -EINVAL; 1417 return -EINVAL;
1418 goto out;
1419 }
1420 if (new_value < 0 || new_value > USHRT_MAX) {
1421 pr_err("%s: packets_per_slave must be between 0 and %u\n",
1422 bond->dev->name, USHRT_MAX);
1423 ret = -EINVAL;
1424 goto out;
1425 } 1418 }
1426 if (bond->params.mode != BOND_MODE_ROUNDROBIN) 1419
1427 pr_warn("%s: Warning: packets_per_slave has effect only in balance-rr mode\n", 1420 if (!rtnl_trylock())
1428 bond->dev->name); 1421 return restart_syscall();
1429 if (new_value > 1) 1422
1430 bond->params.packets_per_slave = reciprocal_value(new_value); 1423 ret = bond_option_packets_per_slave_set(bond, new_value);
1431 else 1424 if (!ret)
1432 bond->params.packets_per_slave = new_value; 1425 ret = count;
1433out: 1426
1427 rtnl_unlock();
1434 return ret; 1428 return ret;
1435} 1429}
1436 1430
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index c70ad9f02b1e..5886f07dc1f3 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -461,6 +461,13 @@ int bond_option_fail_over_mac_set(struct bonding *bond, int fail_over_mac);
461int bond_option_xmit_hash_policy_set(struct bonding *bond, 461int bond_option_xmit_hash_policy_set(struct bonding *bond,
462 int xmit_hash_policy); 462 int xmit_hash_policy);
463int bond_option_resend_igmp_set(struct bonding *bond, int resend_igmp); 463int bond_option_resend_igmp_set(struct bonding *bond, int resend_igmp);
464int bond_option_num_peer_notif_set(struct bonding *bond, int num_peer_notif);
465int bond_option_all_slaves_active_set(struct bonding *bond,
466 int all_slaves_active);
467int bond_option_min_links_set(struct bonding *bond, int min_links);
468int bond_option_lp_interval_set(struct bonding *bond, int min_links);
469int bond_option_packets_per_slave_set(struct bonding *bond,
470 int packets_per_slave);
464struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); 471struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
465struct net_device *bond_option_active_slave_get(struct bonding *bond); 472struct net_device *bond_option_active_slave_get(struct bonding *bond);
466 473