History

bonding: add arp_ip_target netlink support

Add IFLA_BOND_ARP_IP_TARGET to allow get/set of bonding parameter arp_ip_target via netlink.

sfeldma@cumulusnetworks.com committed 12 years ago

Commit 7f28fa11 parent 06151db5 files · +187 −68Browse files

Unified · Split

5 files
  1. drivers/net/bonding/bond_netlink.c +36 −0
  2. drivers/net/bonding/bond_options.c +130 −0
  3. drivers/net/bonding/bond_sysfs.c +16 −68
  4. drivers/net/bonding/bonding.h +4 −0
  5. include/uapi/linux/if_link.h +1 −0
drivers/net/bonding/bond_netlink.c+36−0
@@ -29,6 +29,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { · 28 unmodified lines
2929 [IFLA_BOND_DOWNDELAY] = { .type = NLA_U32 },
3030 [IFLA_BOND_USE_CARRIER] = { .type = NLA_U8 },
3131 [IFLA_BOND_ARP_INTERVAL] = { .type = NLA_U32 },
32+ [IFLA_BOND_ARP_IP_TARGET] = { .type = NLA_NESTED },
3233 };
3334
3435 static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -116,6 +117,20 @@ static int bond_changelink(struct net_device *bond_dev, · 81 unmodified lines
116117 if (err)
117118 return err;
118119 }
120+ if (data[IFLA_BOND_ARP_IP_TARGET]) {
121+ __be32 targets[BOND_MAX_ARP_TARGETS] = { 0, };
122+ struct nlattr *attr;
123+ int i = 0, rem;
124+
125+ nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
126+ __be32 target = nla_get_u32(attr);
127+ targets[i++] = target;
128+ }
129+
130+ err = bond_option_arp_ip_targets_set(bond, targets, i);
131+ if (err)
132+ return err;
133+ }
119134 return 0;
120135 }
121136
@@ -140,6 +155,8 @@ static size_t bond_get_size(const struct net_device *bond_dev) · 18 unmodified lines
140155 nla_total_size(sizeof(u32)) + /* IFLA_BOND_DOWNDELAY */
141156 nla_total_size(sizeof(u8)) + /* IFLA_BOND_USE_CARRIER */
142157 nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_INTERVAL */
158+ /* IFLA_BOND_ARP_IP_TARGET */
159+ nla_total_size(sizeof(u32)) * BOND_MAX_ARP_TARGETS +
143160 0;
144161 }
145162
@@ -148,6 +165,8 @@ static int bond_fill_info(struct sk_buff *skb, · 2 unmodified lines
148165 {
149166 struct bonding *bond = netdev_priv(bond_dev);
150167 struct net_device *slave_dev = bond_option_active_slave_get(bond);
168+ struct nlattr *targets;
169+ int i, targets_added;
151170
152171 if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode))
153172 goto nla_put_failure;
@@ -173,6 +192,23 @@ static int bond_fill_info(struct sk_buff *skb, · 19 unmodified lines
173192 if (nla_put_u32(skb, IFLA_BOND_ARP_INTERVAL, bond->params.arp_interval))
174193 goto nla_put_failure;
175194
195+ targets = nla_nest_start(skb, IFLA_BOND_ARP_IP_TARGET);
196+ if (!targets)
197+ goto nla_put_failure;
198+
199+ targets_added = 0;
200+ for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
201+ if (bond->params.arp_targets[i]) {
202+ nla_put_u32(skb, i, bond->params.arp_targets[i]);
203+ targets_added = 1;
204+ }
205+ }
206+
207+ if (targets_added)
208+ nla_nest_end(skb, targets);
209+ else
210+ nla_nest_cancel(skb, targets);
211+
176212 return 0;
177213
178214 nla_put_failure:
drivers/net/bonding/bond_options.c+130−0
@@ -306,3 +306,133 @@ int bond_option_arp_interval_set(struct bonding *bond, int arp_interval) · 305 unmodified lines
306306
307307 return 0;
308308 }
309+
310+static void _bond_options_arp_ip_target_set(struct bonding *bond, int slot,
311+ __be32 target,
312+ unsigned long last_rx)
313+{
314+ __be32 *targets = bond->params.arp_targets;
315+ struct list_head *iter;
316+ struct slave *slave;
317+
318+ if (slot >= 0 && slot < BOND_MAX_ARP_TARGETS) {
319+ bond_for_each_slave(bond, slave, iter)
320+ slave->target_last_arp_rx[slot] = last_rx;
321+ targets[slot] = target;
322+ }
323+}
324+
325+static int _bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
326+{
327+ __be32 *targets = bond->params.arp_targets;
328+ int ind;
329+
330+ if (IS_IP_TARGET_UNUSABLE_ADDRESS(target)) {
331+ pr_err("%s: invalid ARP target %pI4 specified for addition\n",
332+ bond->dev->name, &target);
333+ return -EINVAL;
334+ }
335+
336+ if (bond_get_targets_ip(targets, target) != -1) { /* dup */
337+ pr_err("%s: ARP target %pI4 is already present\n",
338+ bond->dev->name, &target);
339+ return -EINVAL;
340+ }
341+
342+ ind = bond_get_targets_ip(targets, 0); /* first free slot */
343+ if (ind == -1) {
344+ pr_err("%s: ARP target table is full!\n",
345+ bond->dev->name);
346+ return -EINVAL;
347+ }
348+
349+ pr_info("%s: adding ARP target %pI4.\n", bond->dev->name, &target);
350+
351+ _bond_options_arp_ip_target_set(bond, ind, target, jiffies);
352+
353+ return 0;
354+}
355+
356+int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
357+{
358+ int ret;
359+
360+ /* not to race with bond_arp_rcv */
361+ write_lock_bh(&bond->lock);
362+ ret = _bond_option_arp_ip_target_add(bond, target);
363+ write_unlock_bh(&bond->lock);
364+
365+ return ret;
366+}
367+
368+int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
369+{
370+ __be32 *targets = bond->params.arp_targets;
371+ struct list_head *iter;
372+ struct slave *slave;
373+ unsigned long *targets_rx;
374+ int ind, i;
375+
376+ if (IS_IP_TARGET_UNUSABLE_ADDRESS(target)) {
377+ pr_err("%s: invalid ARP target %pI4 specified for removal\n",
378+ bond->dev->name, &target);
379+ return -EINVAL;
380+ }
381+
382+ ind = bond_get_targets_ip(targets, target);
383+ if (ind == -1) {
384+ pr_err("%s: unable to remove nonexistent ARP target %pI4.\n",
385+ bond->dev->name, &target);
386+ return -EINVAL;
387+ }
388+
389+ if (ind == 0 && !targets[1] && bond->params.arp_interval)
390+ pr_warn("%s: removing last arp target with arp_interval on\n",
391+ bond->dev->name);
392+
393+ pr_info("%s: removing ARP target %pI4.\n", bond->dev->name,
394+ &target);
395+
396+ /* not to race with bond_arp_rcv */
397+ write_lock_bh(&bond->lock);
398+
399+ bond_for_each_slave(bond, slave, iter) {
400+ targets_rx = slave->target_last_arp_rx;
401+ for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++)
402+ targets_rx[i] = targets_rx[i+1];
403+ targets_rx[i] = 0;
404+ }
405+ for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++)
406+ targets[i] = targets[i+1];
407+ targets[i] = 0;
408+
409+ write_unlock_bh(&bond->lock);
410+
411+ return 0;
412+}
413+
414+int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets,
415+ int count)
416+{
417+ int i, ret = 0;
418+
419+ /* not to race with bond_arp_rcv */
420+ write_lock_bh(&bond->lock);
421+
422+ /* clear table */
423+ for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
424+ _bond_options_arp_ip_target_set(bond, i, 0, 0);
425+
426+ if (count == 0 && bond->params.arp_interval)
427+ pr_warn("%s: removing last arp target with arp_interval on\n",
428+ bond->dev->name);
429+
430+ for (i = 0; i < count; i++) {
431+ ret = _bond_option_arp_ip_target_add(bond, targets[i]);
432+ if (ret)
433+ break;
434+ }
435+
436+ write_unlock_bh(&bond->lock);
437+ return ret;
438+}
drivers/net/bonding/bond_sysfs.c+16−68
@@ -552,81 +552,29 @@ static ssize_t bonding_store_arp_targets(struct device *d, · 551 unmodified lines
552552 const char *buf, size_t count)
553553 {
554554 struct bonding *bond = to_bond(d);
555− struct list_head *iter;
556− struct slave *slave;
557− __be32 newtarget, *targets;
558− unsigned long *targets_rx;
559− int ind, i, j, ret = -EINVAL;
555+ __be32 target;
556+ int ret = -EPERM;
560557
561− if (!rtnl_trylock())
562− return restart_syscall();
563−
564− targets = bond->params.arp_targets;
565− if (!in4_pton(buf + 1, -1, (u8 *)&newtarget, -1, NULL) ||
566− IS_IP_TARGET_UNUSABLE_ADDRESS(newtarget)) {
567− pr_err("%s: invalid ARP target %pI4 specified for addition\n",
568− bond->dev->name, &newtarget);
569− goto out;
558+ if (!in4_pton(buf + 1, -1, (u8 *)&target, -1, NULL)) {
559+ pr_err("%s: invalid ARP target %pI4 specified\n",
560+ bond->dev->name, &target);
561+ return -EPERM;
570562 }
571− /* look for adds */
572− if (buf[0] == '+') {
573− if (bond_get_targets_ip(targets, newtarget) != -1) { /* dup */
574− pr_err("%s: ARP target %pI4 is already present\n",
575− bond->dev->name, &newtarget);
576− goto out;
577− }
578−
579− ind = bond_get_targets_ip(targets, 0); /* first free slot */
580− if (ind == -1) {
581− pr_err("%s: ARP target table is full!\n",
582− bond->dev->name);
583− goto out;
584− }
585−
586− pr_info("%s: adding ARP target %pI4.\n", bond->dev->name,
587− &newtarget);
588− /* not to race with bond_arp_rcv */
589− write_lock_bh(&bond->lock);
590− bond_for_each_slave(bond, slave, iter)
591− slave->target_last_arp_rx[ind] = jiffies;
592− targets[ind] = newtarget;
593− write_unlock_bh(&bond->lock);
594− } else if (buf[0] == '-') {
595− ind = bond_get_targets_ip(targets, newtarget);
596− if (ind == -1) {
597− pr_err("%s: unable to remove nonexistent ARP target %pI4.\n",
598− bond->dev->name, &newtarget);
599− goto out;
600− }
601563
602− if (ind == 0 && !targets[1] && bond->params.arp_interval)
603− pr_warn("%s: removing last arp target with arp_interval on\n",
604− bond->dev->name);
605−
606− pr_info("%s: removing ARP target %pI4.\n", bond->dev->name,
607− &newtarget);
564+ if (!rtnl_trylock())
565+ return restart_syscall();
608566
609− write_lock_bh(&bond->lock);
610− bond_for_each_slave(bond, slave, iter) {
611− targets_rx = slave->target_last_arp_rx;
612− j = ind;
613− for (; (j < BOND_MAX_ARP_TARGETS-1) && targets[j+1]; j++)
614− targets_rx[j] = targets_rx[j+1];
615− targets_rx[j] = 0;
616− }
617− for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++)
618− targets[i] = targets[i+1];
619− targets[i] = 0;
620− write_unlock_bh(&bond->lock);
621− } else {
567+ if (buf[0] == '+')
568+ ret = bond_option_arp_ip_target_add(bond, target);
569+ else if (buf[0] == '-')
570+ ret = bond_option_arp_ip_target_rem(bond, target);
571+ else
622572 pr_err("no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
623573 bond->dev->name);
624− ret = -EPERM;
625− goto out;
626− }
627574
628− ret = count;
629−out:
575+ if (!ret)
576+ ret = count;
577+
630578 rtnl_unlock();
631579 return ret;
632580 }
drivers/net/bonding/bonding.h+4−0
@@ -444,6 +444,10 @@ int bond_option_updelay_set(struct bonding *bond, int updelay); · 443 unmodified lines
444444 int bond_option_downdelay_set(struct bonding *bond, int downdelay);
445445 int bond_option_use_carrier_set(struct bonding *bond, int use_carrier);
446446 int bond_option_arp_interval_set(struct bonding *bond, int arp_interval);
447+int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets,
448+ int count);
449+int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target);
450+int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target);
447451 struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
448452 struct net_device *bond_option_active_slave_get(struct bonding *bond);
449453
include/uapi/linux/if_link.h+1−0
@@ -336,6 +336,7 @@ enum { · 335 unmodified lines
336336 IFLA_BOND_DOWNDELAY,
337337 IFLA_BOND_USE_CARRIER,
338338 IFLA_BOND_ARP_INTERVAL,
339+ IFLA_BOND_ARP_IP_TARGET,
339340 __IFLA_BOND_MAX,
340341 };
341342