aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bonding/bond_netlink.c32
-rw-r--r--drivers/net/bonding/bond_options.c42
-rw-r--r--drivers/net/bonding/bond_sysfs.c53
-rw-r--r--drivers/net/bonding/bonding.h1
-rw-r--r--include/uapi/linux/if_link.h1
5 files changed, 80 insertions, 49 deletions
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index 40e7b1cb4aea..28a88beb749b 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * drivers/net/bond/bond_netlink.c - Netlink interface for bonding 2 * drivers/net/bond/bond_netlink.c - Netlink interface for bonding
3 * Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us> 3 * Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us>
4 * Copyright (c) 2013 Scott Feldman <sfeldma@cumulusnetworks.com>
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -23,6 +24,7 @@
23static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { 24static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
24 [IFLA_BOND_MODE] = { .type = NLA_U8 }, 25 [IFLA_BOND_MODE] = { .type = NLA_U8 },
25 [IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 }, 26 [IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 },
27 [IFLA_BOND_MIIMON] = { .type = NLA_U32 },
26}; 28};
27 29
28static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) 30static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -42,14 +44,17 @@ static int bond_changelink(struct net_device *bond_dev,
42 struct bonding *bond = netdev_priv(bond_dev); 44 struct bonding *bond = netdev_priv(bond_dev);
43 int err; 45 int err;
44 46
45 if (data && data[IFLA_BOND_MODE]) { 47 if (!data)
48 return 0;
49
50 if (data[IFLA_BOND_MODE]) {
46 int mode = nla_get_u8(data[IFLA_BOND_MODE]); 51 int mode = nla_get_u8(data[IFLA_BOND_MODE]);
47 52
48 err = bond_option_mode_set(bond, mode); 53 err = bond_option_mode_set(bond, mode);
49 if (err) 54 if (err)
50 return err; 55 return err;
51 } 56 }
52 if (data && data[IFLA_BOND_ACTIVE_SLAVE]) { 57 if (data[IFLA_BOND_ACTIVE_SLAVE]) {
53 int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]); 58 int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]);
54 struct net_device *slave_dev; 59 struct net_device *slave_dev;
55 60
@@ -65,6 +70,13 @@ static int bond_changelink(struct net_device *bond_dev,
65 if (err) 70 if (err)
66 return err; 71 return err;
67 } 72 }
73 if (data[IFLA_BOND_MIIMON]) {
74 int miimon = nla_get_u32(data[IFLA_BOND_MIIMON]);
75
76 err = bond_option_miimon_set(bond, miimon);
77 if (err)
78 return err;
79 }
68 return 0; 80 return 0;
69} 81}
70 82
@@ -83,7 +95,9 @@ static int bond_newlink(struct net *src_net, struct net_device *bond_dev,
83static size_t bond_get_size(const struct net_device *bond_dev) 95static size_t bond_get_size(const struct net_device *bond_dev)
84{ 96{
85 return nla_total_size(sizeof(u8)) + /* IFLA_BOND_MODE */ 97 return nla_total_size(sizeof(u8)) + /* IFLA_BOND_MODE */
86 nla_total_size(sizeof(u32)); /* IFLA_BOND_ACTIVE_SLAVE */ 98 nla_total_size(sizeof(u32)) + /* IFLA_BOND_ACTIVE_SLAVE */
99 nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIIMON */
100 0;
87} 101}
88 102
89static int bond_fill_info(struct sk_buff *skb, 103static int bond_fill_info(struct sk_buff *skb,
@@ -92,10 +106,16 @@ static int bond_fill_info(struct sk_buff *skb,
92 struct bonding *bond = netdev_priv(bond_dev); 106 struct bonding *bond = netdev_priv(bond_dev);
93 struct net_device *slave_dev = bond_option_active_slave_get(bond); 107 struct net_device *slave_dev = bond_option_active_slave_get(bond);
94 108
95 if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode) || 109 if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode))
96 (slave_dev &&
97 nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex)))
98 goto nla_put_failure; 110 goto nla_put_failure;
111
112 if (slave_dev &&
113 nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex))
114 goto nla_put_failure;
115
116 if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon))
117 goto nla_put_failure;
118
99 return 0; 119 return 0;
100 120
101nla_put_failure: 121nla_put_failure:
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index ea6f640782b7..8ae42d36f11f 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * drivers/net/bond/bond_options.c - bonding options 2 * drivers/net/bond/bond_options.c - bonding options
3 * Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us> 3 * Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us>
4 * Copyright (c) 2013 Scott Feldman <sfeldma@cumulusnetworks.com>
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -145,3 +146,44 @@ int bond_option_active_slave_set(struct bonding *bond,
145 unblock_netpoll_tx(); 146 unblock_netpoll_tx();
146 return ret; 147 return ret;
147} 148}
149
150int bond_option_miimon_set(struct bonding *bond, int miimon)
151{
152 if (miimon < 0) {
153 pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n",
154 bond->dev->name, miimon, 0, INT_MAX);
155 return -EINVAL;
156 }
157 pr_info("%s: Setting MII monitoring interval to %d.\n",
158 bond->dev->name, miimon);
159 bond->params.miimon = miimon;
160 if (bond->params.updelay)
161 pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
162 bond->dev->name,
163 bond->params.updelay * bond->params.miimon);
164 if (bond->params.downdelay)
165 pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
166 bond->dev->name,
167 bond->params.downdelay * bond->params.miimon);
168 if (miimon && bond->params.arp_interval) {
169 pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
170 bond->dev->name);
171 bond->params.arp_interval = 0;
172 if (bond->params.arp_validate)
173 bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
174 }
175 if (bond->dev->flags & IFF_UP) {
176 /* If the interface is up, we may need to fire off
177 * the MII timer. If the interface is down, the
178 * timer will get fired off when the open function
179 * is called.
180 */
181 if (!miimon) {
182 cancel_delayed_work_sync(&bond->mii_work);
183 } else {
184 cancel_delayed_work_sync(&bond->arp_work);
185 queue_delayed_work(bond->wq, &bond->mii_work, 0);
186 }
187 }
188 return 0;
189}
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index e46467683e82..d6d6fc7812d5 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -970,55 +970,22 @@ static ssize_t bonding_store_miimon(struct device *d,
970 struct device_attribute *attr, 970 struct device_attribute *attr,
971 const char *buf, size_t count) 971 const char *buf, size_t count)
972{ 972{
973 int new_value, ret = count; 973 int new_value, ret;
974 struct bonding *bond = to_bond(d); 974 struct bonding *bond = to_bond(d);
975 975
976 if (!rtnl_trylock())
977 return restart_syscall();
978 if (sscanf(buf, "%d", &new_value) != 1) { 976 if (sscanf(buf, "%d", &new_value) != 1) {
979 pr_err("%s: no miimon value specified.\n", 977 pr_err("%s: no miimon value specified.\n",
980 bond->dev->name); 978 bond->dev->name);
981 ret = -EINVAL; 979 return -EINVAL;
982 goto out;
983 }
984 if (new_value < 0) {
985 pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n",
986 bond->dev->name, new_value, 0, INT_MAX);
987 ret = -EINVAL;
988 goto out;
989 }
990 pr_info("%s: Setting MII monitoring interval to %d.\n",
991 bond->dev->name, new_value);
992 bond->params.miimon = new_value;
993 if (bond->params.updelay)
994 pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
995 bond->dev->name,
996 bond->params.updelay * bond->params.miimon);
997 if (bond->params.downdelay)
998 pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
999 bond->dev->name,
1000 bond->params.downdelay * bond->params.miimon);
1001 if (new_value && bond->params.arp_interval) {
1002 pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
1003 bond->dev->name);
1004 bond->params.arp_interval = 0;
1005 if (bond->params.arp_validate)
1006 bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
1007 }
1008 if (bond->dev->flags & IFF_UP) {
1009 /* If the interface is up, we may need to fire off
1010 * the MII timer. If the interface is down, the
1011 * timer will get fired off when the open function
1012 * is called.
1013 */
1014 if (!new_value) {
1015 cancel_delayed_work_sync(&bond->mii_work);
1016 } else {
1017 cancel_delayed_work_sync(&bond->arp_work);
1018 queue_delayed_work(bond->wq, &bond->mii_work, 0);
1019 }
1020 } 980 }
1021out: 981
982 if (!rtnl_trylock())
983 return restart_syscall();
984
985 ret = bond_option_miimon_set(bond, new_value);
986 if (!ret)
987 ret = count;
988
1022 rtnl_unlock(); 989 rtnl_unlock();
1023 return ret; 990 return ret;
1024} 991}
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index a74c92c83ead..b146479d5859 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -439,6 +439,7 @@ int bond_netlink_init(void);
439void bond_netlink_fini(void); 439void bond_netlink_fini(void);
440int bond_option_mode_set(struct bonding *bond, int mode); 440int bond_option_mode_set(struct bonding *bond, int mode);
441int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev); 441int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev);
442int bond_option_miimon_set(struct bonding *bond, int miimon);
442struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); 443struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
443struct net_device *bond_option_active_slave_get(struct bonding *bond); 444struct net_device *bond_option_active_slave_get(struct bonding *bond);
444 445
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 6db460121f84..739b2db3f035 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -331,6 +331,7 @@ enum {
331 IFLA_BOND_UNSPEC, 331 IFLA_BOND_UNSPEC,
332 IFLA_BOND_MODE, 332 IFLA_BOND_MODE,
333 IFLA_BOND_ACTIVE_SLAVE, 333 IFLA_BOND_ACTIVE_SLAVE,
334 IFLA_BOND_MIIMON,
334 __IFLA_BOND_MAX, 335 __IFLA_BOND_MAX,
335}; 336};
336 337