diff options
| -rw-r--r-- | drivers/net/bonding/bond_netlink.c | 32 | ||||
| -rw-r--r-- | drivers/net/bonding/bond_options.c | 42 | ||||
| -rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 53 | ||||
| -rw-r--r-- | drivers/net/bonding/bonding.h | 1 | ||||
| -rw-r--r-- | include/uapi/linux/if_link.h | 1 |
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 @@ | |||
| 23 | static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { | 24 | static 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 | ||
| 28 | static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) | 30 | static 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, | |||
| 83 | static size_t bond_get_size(const struct net_device *bond_dev) | 95 | static 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 | ||
| 89 | static int bond_fill_info(struct sk_buff *skb, | 103 | static 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 | ||
| 101 | nla_put_failure: | 121 | nla_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 | |||
| 150 | int 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 | } |
| 1021 | out: | 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); | |||
| 439 | void bond_netlink_fini(void); | 439 | void bond_netlink_fini(void); |
| 440 | int bond_option_mode_set(struct bonding *bond, int mode); | 440 | int bond_option_mode_set(struct bonding *bond, int mode); |
| 441 | int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev); | 441 | int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev); |
| 442 | int bond_option_miimon_set(struct bonding *bond, int miimon); | ||
| 442 | struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); | 443 | struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); |
| 443 | struct net_device *bond_option_active_slave_get(struct bonding *bond); | 444 | struct 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 | ||
