Skip to content

Commit

Permalink
Merge branch 'bonding_netlink'
Browse files Browse the repository at this point in the history
Scott Feldman says:

====================
bonding: add more netlink attributes

v2:

Addressed v1 review comments.  In particular, Jay's concern about
current sysfs ordering limitations carrying over to iproute.  Netlink
attributes are processed in a priority order in
bond_netlink.c:bond_changelink().  Lower priority attributes can't undo
higher priority attributes when attempting to set both with iproute
command.  For example, this command will fail:

  ip link add bond1 type bond mode active-backup miimon 10 arp_interval 10

Because we're trying to create a new bond to use incompatible miimon
and ARP interval attributes.  However, if attributes are applied
one-at-a-time, previously applied attributes can be overridden:

  ip link add bond1 type bond mode active-backup miimon 10
  ip link set dev bond1 type bond arp_interval 10

These two commands succeed.  The bond is first created to use miimon.
Next, the bond is converted to use ARP interval, which undoes miimon.

v1:

Following Jiri Pirko's lead, add more bonding netlink attributes.  Sending
matching iproute2 patch separately.  sysfs access to attributes is
retained.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Dec 14, 2013
2 parents 1cbac01 + d5c8425 commit 0aac68f
Show file tree
Hide file tree
Showing 5 changed files with 578 additions and 271 deletions.
157 changes: 151 additions & 6 deletions drivers/net/bonding/bond_netlink.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* drivers/net/bond/bond_netlink.c - Netlink interface for bonding
* Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us>
* Copyright (c) 2013 Scott Feldman <sfeldma@cumulusnetworks.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -23,6 +24,14 @@
static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
[IFLA_BOND_MODE] = { .type = NLA_U8 },
[IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 },
[IFLA_BOND_MIIMON] = { .type = NLA_U32 },
[IFLA_BOND_UPDELAY] = { .type = NLA_U32 },
[IFLA_BOND_DOWNDELAY] = { .type = NLA_U32 },
[IFLA_BOND_USE_CARRIER] = { .type = NLA_U8 },
[IFLA_BOND_ARP_INTERVAL] = { .type = NLA_U32 },
[IFLA_BOND_ARP_IP_TARGET] = { .type = NLA_NESTED },
[IFLA_BOND_ARP_VALIDATE] = { .type = NLA_U32 },
[IFLA_BOND_ARP_ALL_TARGETS] = { .type = NLA_U32 },
};

static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
Expand All @@ -40,16 +49,20 @@ static int bond_changelink(struct net_device *bond_dev,
struct nlattr *tb[], struct nlattr *data[])
{
struct bonding *bond = netdev_priv(bond_dev);
int miimon = 0;
int err;

if (data && data[IFLA_BOND_MODE]) {
if (!data)
return 0;

if (data[IFLA_BOND_MODE]) {
int mode = nla_get_u8(data[IFLA_BOND_MODE]);

err = bond_option_mode_set(bond, mode);
if (err)
return err;
}
if (data && data[IFLA_BOND_ACTIVE_SLAVE]) {
if (data[IFLA_BOND_ACTIVE_SLAVE]) {
int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]);
struct net_device *slave_dev;

Expand All @@ -65,6 +78,82 @@ static int bond_changelink(struct net_device *bond_dev,
if (err)
return err;
}
if (data[IFLA_BOND_MIIMON]) {
miimon = nla_get_u32(data[IFLA_BOND_MIIMON]);

err = bond_option_miimon_set(bond, miimon);
if (err)
return err;
}
if (data[IFLA_BOND_UPDELAY]) {
int updelay = nla_get_u32(data[IFLA_BOND_UPDELAY]);

err = bond_option_updelay_set(bond, updelay);
if (err)
return err;
}
if (data[IFLA_BOND_DOWNDELAY]) {
int downdelay = nla_get_u32(data[IFLA_BOND_DOWNDELAY]);

err = bond_option_downdelay_set(bond, downdelay);
if (err)
return err;
}
if (data[IFLA_BOND_USE_CARRIER]) {
int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]);

err = bond_option_use_carrier_set(bond, use_carrier);
if (err)
return err;
}
if (data[IFLA_BOND_ARP_INTERVAL]) {
int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]);

if (arp_interval && miimon) {
pr_err("%s: ARP monitoring cannot be used with MII monitoring.\n",
bond->dev->name);
return -EINVAL;
}

err = bond_option_arp_interval_set(bond, arp_interval);
if (err)
return err;
}
if (data[IFLA_BOND_ARP_IP_TARGET]) {
__be32 targets[BOND_MAX_ARP_TARGETS] = { 0, };
struct nlattr *attr;
int i = 0, rem;

nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
__be32 target = nla_get_u32(attr);
targets[i++] = target;
}

err = bond_option_arp_ip_targets_set(bond, targets, i);
if (err)
return err;
}
if (data[IFLA_BOND_ARP_VALIDATE]) {
int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]);

if (arp_validate && miimon) {
pr_err("%s: ARP validating cannot be used with MII monitoring.\n",
bond->dev->name);
return -EINVAL;
}

err = bond_option_arp_validate_set(bond, arp_validate);
if (err)
return err;
}
if (data[IFLA_BOND_ARP_ALL_TARGETS]) {
int arp_all_targets =
nla_get_u32(data[IFLA_BOND_ARP_ALL_TARGETS]);

err = bond_option_arp_all_targets_set(bond, arp_all_targets);
if (err)
return err;
}
return 0;
}

Expand All @@ -83,19 +172,75 @@ static int bond_newlink(struct net *src_net, struct net_device *bond_dev,
static size_t bond_get_size(const struct net_device *bond_dev)
{
return nla_total_size(sizeof(u8)) + /* IFLA_BOND_MODE */
nla_total_size(sizeof(u32)); /* IFLA_BOND_ACTIVE_SLAVE */
nla_total_size(sizeof(u32)) + /* IFLA_BOND_ACTIVE_SLAVE */
nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIIMON */
nla_total_size(sizeof(u32)) + /* IFLA_BOND_UPDELAY */
nla_total_size(sizeof(u32)) + /* IFLA_BOND_DOWNDELAY */
nla_total_size(sizeof(u8)) + /* IFLA_BOND_USE_CARRIER */
nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_INTERVAL */
/* IFLA_BOND_ARP_IP_TARGET */
nla_total_size(sizeof(u32)) * BOND_MAX_ARP_TARGETS +
nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_VALIDATE */
nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_ALL_TARGETS */
0;
}

static int bond_fill_info(struct sk_buff *skb,
const struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct net_device *slave_dev = bond_option_active_slave_get(bond);
struct nlattr *targets;
int i, targets_added;

if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode))
goto nla_put_failure;

if (slave_dev &&
nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex))
goto nla_put_failure;

if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon))
goto nla_put_failure;

if (nla_put_u32(skb, IFLA_BOND_UPDELAY,
bond->params.updelay * bond->params.miimon))
goto nla_put_failure;

if (nla_put_u32(skb, IFLA_BOND_DOWNDELAY,
bond->params.downdelay * bond->params.miimon))
goto nla_put_failure;

if (nla_put_u8(skb, IFLA_BOND_USE_CARRIER, bond->params.use_carrier))
goto nla_put_failure;

if (nla_put_u32(skb, IFLA_BOND_ARP_INTERVAL, bond->params.arp_interval))
goto nla_put_failure;

targets = nla_nest_start(skb, IFLA_BOND_ARP_IP_TARGET);
if (!targets)
goto nla_put_failure;

targets_added = 0;
for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
if (bond->params.arp_targets[i]) {
nla_put_u32(skb, i, bond->params.arp_targets[i]);
targets_added = 1;
}
}

if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode) ||
(slave_dev &&
nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex)))
if (targets_added)
nla_nest_end(skb, targets);
else
nla_nest_cancel(skb, targets);

if (nla_put_u32(skb, IFLA_BOND_ARP_VALIDATE, bond->params.arp_validate))
goto nla_put_failure;

if (nla_put_u32(skb, IFLA_BOND_ARP_ALL_TARGETS,
bond->params.arp_all_targets))
goto nla_put_failure;

return 0;

nla_put_failure:
Expand Down
Loading

0 comments on commit 0aac68f

Please sign in to comment.