bonding: convert arp_ip_target to use the new option API
authorNikolay Aleksandrov <nikolay@redhat.com>
Wed, 22 Jan 2014 13:53:24 +0000 (14:53 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 22 Jan 2014 23:38:42 +0000 (15:38 -0800)
This patch adds the necessary changes so arp_ip_target would use
the new bonding option API. This option is an exception because of
the way it's currently implemented that's why its netlink code is
a bit different from the other options to keep the functionality as
before and at the same time to have a single set function.

This patch also fixes a few stylistic errors.

Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/bonding/bond_netlink.c
drivers/net/bonding/bond_options.c
drivers/net/bonding/bond_options.h
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h

index 74463f3db8b6ed731abe327624575be5795e89b3..9164a5a8e44f4d7ee5a0aff98be66b5b15e7315b 100644 (file)
@@ -172,16 +172,23 @@ static int bond_changelink(struct net_device *bond_dev,
                        return err;
        }
        if (data[IFLA_BOND_ARP_IP_TARGET]) {
-               __be32 targets[BOND_MAX_ARP_TARGETS] = { 0, };
                struct nlattr *attr;
                int i = 0, rem;
 
+               bond_option_arp_ip_targets_clear(bond);
                nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
                        __be32 target = nla_get_be32(attr);
-                       targets[i++] = target;
-               }
 
-               err = bond_option_arp_ip_targets_set(bond, targets, i);
+                       bond_opt_initval(&newval, target);
+                       err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
+                                            &newval);
+                       if (err)
+                               break;
+                       i++;
+               }
+               if (i == 0 && bond->params.arp_interval)
+                       pr_warn("%s: removing last arp target with arp_interval on\n",
+                               bond->dev->name);
                if (err)
                        return err;
        }
index df693afbb1a55ba330c70866cc1d5081a1bad8e0..df5f007ddaa56dfd7a5a5ffd6f03cd583f6076dd 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/rwlock.h>
 #include <linux/rcupdate.h>
 #include <linux/ctype.h>
+#include <linux/inet.h>
 #include "bonding.h"
 
 static struct bond_opt_value bond_mode_tbl[] = {
@@ -127,6 +128,13 @@ static struct bond_option bond_opts[] = {
                .values = bond_intmax_tbl,
                .set = bond_option_arp_interval_set
        },
+       [BOND_OPT_ARP_TARGETS] = {
+               .id = BOND_OPT_ARP_TARGETS,
+               .name = "arp_ip_target",
+               .desc = "arp targets in n.n.n.n form",
+               .flags = BOND_OPTFLAG_RAWVAL,
+               .set = bond_option_arp_ip_targets_set
+       },
        { }
 };
 
@@ -757,29 +765,41 @@ int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
        return 0;
 }
 
-int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets,
-                                  int count)
+void bond_option_arp_ip_targets_clear(struct bonding *bond)
 {
-       int i, ret = 0;
+       int i;
 
        /* not to race with bond_arp_rcv */
        write_lock_bh(&bond->lock);
-
-       /* clear table */
        for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
                _bond_options_arp_ip_target_set(bond, i, 0, 0);
+       write_unlock_bh(&bond->lock);
+}
 
-       if (count == 0 && bond->params.arp_interval)
-               pr_warn("%s: removing last arp target with arp_interval on\n",
-                       bond->dev->name);
-
-       for (i = 0; i < count; i++) {
-               ret = _bond_option_arp_ip_target_add(bond, targets[i]);
-               if (ret)
-                       break;
+int bond_option_arp_ip_targets_set(struct bonding *bond,
+                                  struct bond_opt_value *newval)
+{
+       int ret = -EPERM;
+       __be32 target;
+
+       if (newval->string) {
+               if (!in4_pton(newval->string+1, -1, (u8 *)&target, -1, NULL)) {
+                       pr_err("%s: invalid ARP target %pI4 specified\n",
+                              bond->dev->name, &target);
+                       return ret;
+               }
+               if (newval->string[0] == '+')
+                       ret = bond_option_arp_ip_target_add(bond, target);
+               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",
+                              bond->dev->name);
+       } else {
+               target = newval->value;
+               ret = bond_option_arp_ip_target_add(bond, target);
        }
 
-       write_unlock_bh(&bond->lock);
        return ret;
 }
 
index f02b8573116e21406e500ded3868d23ea4e5c94c..da351489a583d34cf8bad123b6f1d7e91ef0d73d 100644 (file)
@@ -45,6 +45,7 @@ enum {
        BOND_OPT_ARP_ALL_TARGETS,
        BOND_OPT_FAIL_OVER_MAC,
        BOND_OPT_ARP_INTERVAL,
+       BOND_OPT_ARP_TARGETS,
        BOND_OPT_LAST
 };
 
@@ -117,4 +118,7 @@ int bond_option_fail_over_mac_set(struct bonding *bond,
                                  struct bond_opt_value *newval);
 int bond_option_arp_interval_set(struct bonding *bond,
                                 struct bond_opt_value *newval);
+int bond_option_arp_ip_targets_set(struct bonding *bond,
+                                  struct bond_opt_value *newval);
+void bond_option_arp_ip_targets_clear(struct bonding *bond);
 #endif /* _BOND_OPTIONS_H */
index 585c38c5562c63fa511c0dbc787f32e2ab09f1b1..5eeb3a2add02c0f78450abf0e44af2a264792f55 100644 (file)
@@ -454,8 +454,8 @@ static ssize_t bonding_show_arp_targets(struct device *d,
                                        struct device_attribute *attr,
                                        char *buf)
 {
-       int i, res = 0;
        struct bonding *bond = to_bond(d);
+       int i, res = 0;
 
        for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
                if (bond->params.arp_targets[i])
@@ -464,6 +464,7 @@ static ssize_t bonding_show_arp_targets(struct device *d,
        }
        if (res)
                buf[res-1] = '\n'; /* eat the leftover space */
+
        return res;
 }
 
@@ -472,30 +473,12 @@ static ssize_t bonding_store_arp_targets(struct device *d,
                                         const char *buf, size_t count)
 {
        struct bonding *bond = to_bond(d);
-       __be32 target;
-       int ret = -EPERM;
-
-       if (!in4_pton(buf + 1, -1, (u8 *)&target, -1, NULL)) {
-               pr_err("%s: invalid ARP target %pI4 specified\n",
-                      bond->dev->name, &target);
-               return -EPERM;
-       }
-
-       if (!rtnl_trylock())
-               return restart_syscall();
-
-       if (buf[0] == '+')
-               ret = bond_option_arp_ip_target_add(bond, target);
-       else if (buf[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",
-                      bond->dev->name);
+       int ret;
 
+       ret = bond_opt_tryset_rtnl(bond, BOND_OPT_ARP_TARGETS, (char *)buf);
        if (!ret)
                ret = count;
 
-       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
index 7d39588b17db9e876096bf980d4faca2c6033938..5a63c0e777e79bed0347d90b78350372936142c7 100644 (file)
@@ -457,8 +457,6 @@ int bond_option_miimon_set(struct bonding *bond, int miimon);
 int bond_option_updelay_set(struct bonding *bond, int updelay);
 int bond_option_downdelay_set(struct bonding *bond, int downdelay);
 int bond_option_use_carrier_set(struct bonding *bond, int use_carrier);
-int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets,
-                                  int count);
 int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target);
 int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target);
 int bond_option_primary_set(struct bonding *bond, const char *primary);