2019-05-27 08:55:01 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2013-10-18 17:43:33 +02:00
|
|
|
/*
|
|
|
|
* drivers/net/bond/bond_netlink.c - Netlink interface for bonding
|
|
|
|
* Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us>
|
2013-12-12 14:09:55 -08:00
|
|
|
* Copyright (c) 2013 Scott Feldman <sfeldma@cumulusnetworks.com>
|
2013-10-18 17:43:33 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/netdevice.h>
|
|
|
|
#include <linux/etherdevice.h>
|
|
|
|
#include <linux/if_link.h>
|
|
|
|
#include <linux/if_ether.h>
|
|
|
|
#include <net/netlink.h>
|
|
|
|
#include <net/rtnetlink.h>
|
2014-11-10 13:27:49 -05:00
|
|
|
#include <net/bonding.h>
|
2022-02-21 13:54:57 +08:00
|
|
|
#include <net/ipv6.h>
|
2013-10-18 17:43:33 +02:00
|
|
|
|
2014-01-22 09:05:56 +01:00
|
|
|
static size_t bond_get_slave_size(const struct net_device *bond_dev,
|
|
|
|
const struct net_device *slave_dev)
|
|
|
|
{
|
|
|
|
return nla_total_size(sizeof(u8)) + /* IFLA_BOND_SLAVE_STATE */
|
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_SLAVE_MII_STATUS */
|
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_SLAVE_LINK_FAILURE_COUNT */
|
|
|
|
nla_total_size(MAX_ADDR_LEN) + /* IFLA_BOND_SLAVE_PERM_HWADDR */
|
|
|
|
nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_QUEUE_ID */
|
|
|
|
nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_AD_AGGREGATOR_ID */
|
2015-06-14 16:36:34 +03:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE */
|
2015-06-14 16:36:35 +03:00
|
|
|
nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE */
|
2022-06-21 15:49:19 +08:00
|
|
|
nla_total_size(sizeof(s32)) + /* IFLA_BOND_SLAVE_PRIO */
|
2014-01-22 09:05:56 +01:00
|
|
|
0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int bond_fill_slave_info(struct sk_buff *skb,
|
|
|
|
const struct net_device *bond_dev,
|
|
|
|
const struct net_device *slave_dev)
|
2014-01-16 22:57:56 -08:00
|
|
|
{
|
|
|
|
struct slave *slave = bond_slave_get_rtnl(slave_dev);
|
|
|
|
|
2014-01-22 09:05:54 +01:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_SLAVE_STATE, bond_slave_state(slave)))
|
2014-01-16 22:57:56 -08:00
|
|
|
goto nla_put_failure;
|
|
|
|
|
2014-01-22 09:05:54 +01:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_SLAVE_MII_STATUS, slave->link))
|
2014-01-16 22:57:56 -08:00
|
|
|
goto nla_put_failure;
|
|
|
|
|
2014-01-22 09:05:54 +01:00
|
|
|
if (nla_put_u32(skb, IFLA_BOND_SLAVE_LINK_FAILURE_COUNT,
|
2014-01-16 22:57:56 -08:00
|
|
|
slave->link_failure_count))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2014-01-22 09:05:54 +01:00
|
|
|
if (nla_put(skb, IFLA_BOND_SLAVE_PERM_HWADDR,
|
2014-01-16 22:57:56 -08:00
|
|
|
slave_dev->addr_len, slave->perm_hwaddr))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2024-04-08 19:04:37 +00:00
|
|
|
if (nla_put_u16(skb, IFLA_BOND_SLAVE_QUEUE_ID,
|
|
|
|
READ_ONCE(slave->queue_id)))
|
2014-01-16 22:57:56 -08:00
|
|
|
goto nla_put_failure;
|
|
|
|
|
2022-06-21 15:49:19 +08:00
|
|
|
if (nla_put_s32(skb, IFLA_BOND_SLAVE_PRIO, slave->prio))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2014-05-15 21:39:55 +02:00
|
|
|
if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) {
|
2014-01-22 09:05:56 +01:00
|
|
|
const struct aggregator *agg;
|
2015-06-14 16:36:34 +03:00
|
|
|
const struct port *ad_port;
|
2014-01-22 09:05:56 +01:00
|
|
|
|
2015-06-14 16:36:34 +03:00
|
|
|
ad_port = &SLAVE_AD_INFO(slave)->port;
|
2014-05-12 15:08:43 +08:00
|
|
|
agg = SLAVE_AD_INFO(slave)->port.aggregator;
|
2015-06-14 16:36:34 +03:00
|
|
|
if (agg) {
|
2014-01-22 09:05:54 +01:00
|
|
|
if (nla_put_u16(skb, IFLA_BOND_SLAVE_AD_AGGREGATOR_ID,
|
2014-01-16 22:57:56 -08:00
|
|
|
agg->aggregator_identifier))
|
|
|
|
goto nla_put_failure;
|
2015-06-14 16:36:34 +03:00
|
|
|
if (nla_put_u8(skb,
|
|
|
|
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
|
|
|
|
ad_port->actor_oper_port_state))
|
|
|
|
goto nla_put_failure;
|
2015-06-14 16:36:35 +03:00
|
|
|
if (nla_put_u16(skb,
|
|
|
|
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
|
|
|
|
ad_port->partner_oper.port_state))
|
|
|
|
goto nla_put_failure;
|
2015-06-14 16:36:34 +03:00
|
|
|
}
|
2014-01-16 22:57:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
nla_put_failure:
|
|
|
|
return -EMSGSIZE;
|
|
|
|
}
|
|
|
|
|
2023-05-09 11:11:57 +08:00
|
|
|
/* Limit the max delay range to 300s */
|
2023-10-25 09:22:04 -07:00
|
|
|
static const struct netlink_range_validation delay_range = {
|
2023-05-09 11:11:57 +08:00
|
|
|
.max = 300000,
|
|
|
|
};
|
|
|
|
|
2013-10-18 17:43:38 +02:00
|
|
|
static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
|
|
|
|
[IFLA_BOND_MODE] = { .type = NLA_U8 },
|
2013-10-18 17:43:39 +02:00
|
|
|
[IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 },
|
2013-12-12 14:09:55 -08:00
|
|
|
[IFLA_BOND_MIIMON] = { .type = NLA_U32 },
|
2013-12-12 14:10:02 -08:00
|
|
|
[IFLA_BOND_UPDELAY] = { .type = NLA_U32 },
|
2013-12-12 14:10:09 -08:00
|
|
|
[IFLA_BOND_DOWNDELAY] = { .type = NLA_U32 },
|
2013-12-12 14:10:16 -08:00
|
|
|
[IFLA_BOND_USE_CARRIER] = { .type = NLA_U8 },
|
2013-12-12 14:10:24 -08:00
|
|
|
[IFLA_BOND_ARP_INTERVAL] = { .type = NLA_U32 },
|
2013-12-12 14:10:31 -08:00
|
|
|
[IFLA_BOND_ARP_IP_TARGET] = { .type = NLA_NESTED },
|
2013-12-12 14:10:38 -08:00
|
|
|
[IFLA_BOND_ARP_VALIDATE] = { .type = NLA_U32 },
|
2013-12-12 14:10:45 -08:00
|
|
|
[IFLA_BOND_ARP_ALL_TARGETS] = { .type = NLA_U32 },
|
2013-12-15 16:41:51 -08:00
|
|
|
[IFLA_BOND_PRIMARY] = { .type = NLA_U32 },
|
2013-12-15 16:41:58 -08:00
|
|
|
[IFLA_BOND_PRIMARY_RESELECT] = { .type = NLA_U8 },
|
2013-12-15 16:42:05 -08:00
|
|
|
[IFLA_BOND_FAIL_OVER_MAC] = { .type = NLA_U8 },
|
2013-12-15 16:42:12 -08:00
|
|
|
[IFLA_BOND_XMIT_HASH_POLICY] = { .type = NLA_U8 },
|
2013-12-15 16:42:19 -08:00
|
|
|
[IFLA_BOND_RESEND_IGMP] = { .type = NLA_U32 },
|
2013-12-17 21:30:09 -08:00
|
|
|
[IFLA_BOND_NUM_PEER_NOTIF] = { .type = NLA_U8 },
|
2013-12-17 21:30:16 -08:00
|
|
|
[IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NLA_U8 },
|
2013-12-17 21:30:23 -08:00
|
|
|
[IFLA_BOND_MIN_LINKS] = { .type = NLA_U32 },
|
2013-12-17 21:30:30 -08:00
|
|
|
[IFLA_BOND_LP_INTERVAL] = { .type = NLA_U32 },
|
2013-12-17 21:30:37 -08:00
|
|
|
[IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NLA_U32 },
|
2021-08-02 11:02:19 +08:00
|
|
|
[IFLA_BOND_AD_LACP_ACTIVE] = { .type = NLA_U8 },
|
2014-01-03 14:18:41 -08:00
|
|
|
[IFLA_BOND_AD_LACP_RATE] = { .type = NLA_U8 },
|
2014-01-03 14:18:49 -08:00
|
|
|
[IFLA_BOND_AD_SELECT] = { .type = NLA_U8 },
|
2014-01-03 14:18:56 -08:00
|
|
|
[IFLA_BOND_AD_INFO] = { .type = NLA_NESTED },
|
2015-05-09 00:01:58 -07:00
|
|
|
[IFLA_BOND_AD_ACTOR_SYS_PRIO] = { .type = NLA_U16 },
|
|
|
|
[IFLA_BOND_AD_USER_PORT_KEY] = { .type = NLA_U16 },
|
|
|
|
[IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NLA_BINARY,
|
|
|
|
.len = ETH_ALEN },
|
2015-07-31 16:49:43 +02:00
|
|
|
[IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NLA_U8 },
|
2023-05-09 11:11:57 +08:00
|
|
|
[IFLA_BOND_PEER_NOTIF_DELAY] = NLA_POLICY_FULL_RANGE(NLA_U32, &delay_range),
|
2021-11-30 12:29:47 +08:00
|
|
|
[IFLA_BOND_MISSED_MAX] = { .type = NLA_U8 },
|
2022-02-21 13:54:57 +08:00
|
|
|
[IFLA_BOND_NS_IP6_TARGET] = { .type = NLA_NESTED },
|
2024-02-02 17:58:58 +00:00
|
|
|
[IFLA_BOND_COUPLED_CONTROL] = { .type = NLA_U8 },
|
2025-06-27 21:49:29 +08:00
|
|
|
[IFLA_BOND_BROADCAST_NEIGH] = { .type = NLA_U8 },
|
2013-10-18 17:43:38 +02:00
|
|
|
};
|
|
|
|
|
2014-09-05 11:36:34 +02:00
|
|
|
static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
|
|
|
|
[IFLA_BOND_SLAVE_QUEUE_ID] = { .type = NLA_U16 },
|
2022-06-21 15:49:19 +08:00
|
|
|
[IFLA_BOND_SLAVE_PRIO] = { .type = NLA_S32 },
|
2014-09-05 11:36:34 +02:00
|
|
|
};
|
|
|
|
|
2017-06-25 23:56:01 +02:00
|
|
|
static int bond_validate(struct nlattr *tb[], struct nlattr *data[],
|
|
|
|
struct netlink_ext_ack *extack)
|
2013-10-18 17:43:33 +02:00
|
|
|
{
|
|
|
|
if (tb[IFLA_ADDRESS]) {
|
|
|
|
if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
|
|
|
|
return -EINVAL;
|
|
|
|
if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
|
|
|
|
return -EADDRNOTAVAIL;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-27 16:06:46 +02:00
|
|
|
static int bond_slave_changelink(struct net_device *bond_dev,
|
|
|
|
struct net_device *slave_dev,
|
2017-06-25 23:56:02 +02:00
|
|
|
struct nlattr *tb[], struct nlattr *data[],
|
|
|
|
struct netlink_ext_ack *extack)
|
2014-08-27 16:06:46 +02:00
|
|
|
{
|
|
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
|
|
|
struct bond_opt_value newval;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!data)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (data[IFLA_BOND_SLAVE_QUEUE_ID]) {
|
|
|
|
u16 queue_id = nla_get_u16(data[IFLA_BOND_SLAVE_QUEUE_ID]);
|
|
|
|
char queue_id_str[IFNAMSIZ + 7];
|
|
|
|
|
|
|
|
/* queue_id option setting expects slave_name:queue_id */
|
|
|
|
snprintf(queue_id_str, sizeof(queue_id_str), "%s:%u\n",
|
|
|
|
slave_dev->name, queue_id);
|
|
|
|
bond_opt_initstr(&newval, queue_id_str);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_QUEUE_ID, &newval,
|
|
|
|
data[IFLA_BOND_SLAVE_QUEUE_ID], extack);
|
2014-08-27 16:06:46 +02:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2022-06-21 15:49:19 +08:00
|
|
|
if (data[IFLA_BOND_SLAVE_PRIO]) {
|
|
|
|
int prio = nla_get_s32(data[IFLA_BOND_SLAVE_PRIO]);
|
|
|
|
|
|
|
|
bond_opt_slave_initval(&newval, &slave_dev, prio);
|
|
|
|
err = __bond_opt_set(bond, BOND_OPT_PRIO, &newval,
|
|
|
|
data[IFLA_BOND_SLAVE_PRIO], extack);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2014-08-27 16:06:46 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-06-25 23:56:00 +02:00
|
|
|
static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
|
|
|
|
struct nlattr *data[],
|
|
|
|
struct netlink_ext_ack *extack)
|
2013-10-18 17:43:38 +02:00
|
|
|
{
|
|
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
2014-01-22 14:53:17 +01:00
|
|
|
struct bond_opt_value newval;
|
2013-12-12 14:10:24 -08:00
|
|
|
int miimon = 0;
|
2013-10-18 17:43:38 +02:00
|
|
|
int err;
|
|
|
|
|
2013-12-12 14:09:55 -08:00
|
|
|
if (!data)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (data[IFLA_BOND_MODE]) {
|
2013-10-18 17:43:38 +02:00
|
|
|
int mode = nla_get_u8(data[IFLA_BOND_MODE]);
|
|
|
|
|
2014-01-22 14:53:17 +01:00
|
|
|
bond_opt_initval(&newval, mode);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_MODE, &newval,
|
|
|
|
data[IFLA_BOND_MODE], extack);
|
2013-10-18 17:43:38 +02:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-12 14:09:55 -08:00
|
|
|
if (data[IFLA_BOND_ACTIVE_SLAVE]) {
|
2013-10-18 17:43:39 +02:00
|
|
|
int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]);
|
|
|
|
struct net_device *slave_dev;
|
2014-01-22 14:53:35 +01:00
|
|
|
char *active_slave = "";
|
2013-10-18 17:43:39 +02:00
|
|
|
|
2014-01-22 14:53:35 +01:00
|
|
|
if (ifindex != 0) {
|
2013-10-18 17:43:39 +02:00
|
|
|
slave_dev = __dev_get_by_index(dev_net(bond_dev),
|
|
|
|
ifindex);
|
|
|
|
if (!slave_dev)
|
|
|
|
return -ENODEV;
|
2014-01-22 14:53:35 +01:00
|
|
|
active_slave = slave_dev->name;
|
2013-10-18 17:43:39 +02:00
|
|
|
}
|
2014-01-22 14:53:35 +01:00
|
|
|
bond_opt_initstr(&newval, active_slave);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval,
|
|
|
|
data[IFLA_BOND_ACTIVE_SLAVE], extack);
|
2013-10-18 17:43:39 +02:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-12 14:09:55 -08:00
|
|
|
if (data[IFLA_BOND_MIIMON]) {
|
2013-12-12 14:10:24 -08:00
|
|
|
miimon = nla_get_u32(data[IFLA_BOND_MIIMON]);
|
2013-12-12 14:09:55 -08:00
|
|
|
|
2014-01-22 14:53:31 +01:00
|
|
|
bond_opt_initval(&newval, miimon);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_MIIMON, &newval,
|
|
|
|
data[IFLA_BOND_MIIMON], extack);
|
2013-12-12 14:09:55 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-12 14:10:02 -08:00
|
|
|
if (data[IFLA_BOND_UPDELAY]) {
|
|
|
|
int updelay = nla_get_u32(data[IFLA_BOND_UPDELAY]);
|
|
|
|
|
2014-01-22 14:53:26 +01:00
|
|
|
bond_opt_initval(&newval, updelay);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_UPDELAY, &newval,
|
|
|
|
data[IFLA_BOND_UPDELAY], extack);
|
2013-12-12 14:10:02 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-12 14:10:09 -08:00
|
|
|
if (data[IFLA_BOND_DOWNDELAY]) {
|
|
|
|
int downdelay = nla_get_u32(data[IFLA_BOND_DOWNDELAY]);
|
|
|
|
|
2014-01-22 14:53:25 +01:00
|
|
|
bond_opt_initval(&newval, downdelay);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_DOWNDELAY, &newval,
|
|
|
|
data[IFLA_BOND_DOWNDELAY], extack);
|
2013-12-12 14:10:09 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
bonding: add an option to specify a delay between peer notifications
Currently, gratuitous ARP/ND packets are sent every `miimon'
milliseconds. This commit allows a user to specify a custom delay
through a new option, `peer_notif_delay'.
Like for `updelay' and `downdelay', this delay should be a multiple of
`miimon' to avoid managing an additional work queue. The configuration
logic is copied from `updelay' and `downdelay'. However, the default
value cannot be set using a module parameter: Netlink or sysfs should
be used to configure this feature.
When setting `miimon' to 100 and `peer_notif_delay' to 500, we can
observe the 500 ms delay is respected:
20:30:19.354693 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:19.874892 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.394919 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.914963 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
In bond_mii_monitor(), I have tried to keep the lock logic readable.
The change is due to the fact we cannot rely on a notification to
lower the value of `bond->send_peer_notif' as `NETDEV_NOTIFY_PEERS' is
only triggered once every N times, while we need to decrement the
counter each time.
iproute2 also needs to be updated to be able to specify this new
attribute through `ip link'.
Signed-off-by: Vincent Bernat <vincent@bernat.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-07-02 19:43:54 +02:00
|
|
|
if (data[IFLA_BOND_PEER_NOTIF_DELAY]) {
|
|
|
|
int delay = nla_get_u32(data[IFLA_BOND_PEER_NOTIF_DELAY]);
|
|
|
|
|
|
|
|
bond_opt_initval(&newval, delay);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_PEER_NOTIF_DELAY, &newval,
|
|
|
|
data[IFLA_BOND_PEER_NOTIF_DELAY], extack);
|
bonding: add an option to specify a delay between peer notifications
Currently, gratuitous ARP/ND packets are sent every `miimon'
milliseconds. This commit allows a user to specify a custom delay
through a new option, `peer_notif_delay'.
Like for `updelay' and `downdelay', this delay should be a multiple of
`miimon' to avoid managing an additional work queue. The configuration
logic is copied from `updelay' and `downdelay'. However, the default
value cannot be set using a module parameter: Netlink or sysfs should
be used to configure this feature.
When setting `miimon' to 100 and `peer_notif_delay' to 500, we can
observe the 500 ms delay is respected:
20:30:19.354693 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:19.874892 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.394919 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.914963 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
In bond_mii_monitor(), I have tried to keep the lock logic readable.
The change is due to the fact we cannot rely on a notification to
lower the value of `bond->send_peer_notif' as `NETDEV_NOTIFY_PEERS' is
only triggered once every N times, while we need to decrement the
counter each time.
iproute2 also needs to be updated to be able to specify this new
attribute through `ip link'.
Signed-off-by: Vincent Bernat <vincent@bernat.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-07-02 19:43:54 +02:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-12 14:10:16 -08:00
|
|
|
if (data[IFLA_BOND_USE_CARRIER]) {
|
|
|
|
int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]);
|
|
|
|
|
2014-01-22 14:53:34 +01:00
|
|
|
bond_opt_initval(&newval, use_carrier);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_USE_CARRIER, &newval,
|
|
|
|
data[IFLA_BOND_USE_CARRIER], extack);
|
2013-12-12 14:10:16 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-12 14:10:24 -08:00
|
|
|
if (data[IFLA_BOND_ARP_INTERVAL]) {
|
|
|
|
int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]);
|
|
|
|
|
|
|
|
if (arp_interval && miimon) {
|
2022-06-08 14:14:56 -04:00
|
|
|
NL_SET_ERR_MSG_ATTR(extack, data[IFLA_BOND_ARP_INTERVAL],
|
|
|
|
"ARP monitoring cannot be used with MII monitoring");
|
2013-12-12 14:10:24 -08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2014-01-22 14:53:23 +01:00
|
|
|
bond_opt_initval(&newval, arp_interval);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_ARP_INTERVAL, &newval,
|
|
|
|
data[IFLA_BOND_ARP_INTERVAL], extack);
|
2013-12-12 14:10:24 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-12 14:10:31 -08:00
|
|
|
if (data[IFLA_BOND_ARP_IP_TARGET]) {
|
|
|
|
struct nlattr *attr;
|
|
|
|
int i = 0, rem;
|
|
|
|
|
2014-01-22 14:53:24 +01:00
|
|
|
bond_option_arp_ip_targets_clear(bond);
|
2013-12-12 14:10:31 -08:00
|
|
|
nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
|
2014-11-27 00:22:33 +01:00
|
|
|
__be32 target;
|
|
|
|
|
|
|
|
if (nla_len(attr) < sizeof(target))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
target = nla_get_be32(attr);
|
2013-12-12 14:10:31 -08:00
|
|
|
|
2014-03-10 09:48:38 -07:00
|
|
|
bond_opt_initval(&newval, (__force u64)target);
|
2014-01-22 14:53:24 +01:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
|
2022-06-08 14:14:56 -04:00
|
|
|
&newval,
|
|
|
|
data[IFLA_BOND_ARP_IP_TARGET],
|
|
|
|
extack);
|
2014-01-22 14:53:24 +01:00
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (i == 0 && bond->params.arp_interval)
|
2014-07-15 19:36:05 +02:00
|
|
|
netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n");
|
2013-12-12 14:10:31 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2022-02-21 13:54:57 +08:00
|
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
|
|
if (data[IFLA_BOND_NS_IP6_TARGET]) {
|
|
|
|
struct nlattr *attr;
|
|
|
|
int i = 0, rem;
|
|
|
|
|
|
|
|
bond_option_ns_ip6_targets_clear(bond);
|
|
|
|
nla_for_each_nested(attr, data[IFLA_BOND_NS_IP6_TARGET], rem) {
|
|
|
|
struct in6_addr addr6;
|
|
|
|
|
|
|
|
if (nla_len(attr) < sizeof(addr6)) {
|
|
|
|
NL_SET_ERR_MSG(extack, "Invalid IPv6 address");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr6 = nla_get_in6_addr(attr);
|
|
|
|
|
|
|
|
bond_opt_initextra(&newval, &addr6, sizeof(addr6));
|
|
|
|
err = __bond_opt_set(bond, BOND_OPT_NS_TARGETS,
|
2022-06-08 14:14:56 -04:00
|
|
|
&newval,
|
|
|
|
data[IFLA_BOND_NS_IP6_TARGET],
|
|
|
|
extack);
|
2022-02-21 13:54:57 +08:00
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (i == 0 && bond->params.arp_interval)
|
|
|
|
netdev_warn(bond->dev, "Removing last ns target with arp_interval on\n");
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#endif
|
2013-12-12 14:10:38 -08:00
|
|
|
if (data[IFLA_BOND_ARP_VALIDATE]) {
|
|
|
|
int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]);
|
|
|
|
|
|
|
|
if (arp_validate && miimon) {
|
2022-06-08 14:14:56 -04:00
|
|
|
NL_SET_ERR_MSG_ATTR(extack, data[IFLA_BOND_ARP_INTERVAL],
|
|
|
|
"ARP validating cannot be used with MII monitoring");
|
2013-12-12 14:10:38 -08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2014-01-22 14:53:20 +01:00
|
|
|
bond_opt_initval(&newval, arp_validate);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_ARP_VALIDATE, &newval,
|
|
|
|
data[IFLA_BOND_ARP_VALIDATE], extack);
|
2013-12-12 14:10:38 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-12 14:10:45 -08:00
|
|
|
if (data[IFLA_BOND_ARP_ALL_TARGETS]) {
|
|
|
|
int arp_all_targets =
|
|
|
|
nla_get_u32(data[IFLA_BOND_ARP_ALL_TARGETS]);
|
|
|
|
|
2014-01-22 14:53:21 +01:00
|
|
|
bond_opt_initval(&newval, arp_all_targets);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_ARP_ALL_TARGETS, &newval,
|
|
|
|
data[IFLA_BOND_ARP_ALL_TARGETS], extack);
|
2013-12-12 14:10:45 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-15 16:41:51 -08:00
|
|
|
if (data[IFLA_BOND_PRIMARY]) {
|
|
|
|
int ifindex = nla_get_u32(data[IFLA_BOND_PRIMARY]);
|
|
|
|
struct net_device *dev;
|
|
|
|
char *primary = "";
|
|
|
|
|
|
|
|
dev = __dev_get_by_index(dev_net(bond_dev), ifindex);
|
|
|
|
if (dev)
|
|
|
|
primary = dev->name;
|
|
|
|
|
2014-01-22 14:53:32 +01:00
|
|
|
bond_opt_initstr(&newval, primary);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_PRIMARY, &newval,
|
|
|
|
data[IFLA_BOND_PRIMARY], extack);
|
2013-12-15 16:41:51 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-15 16:41:58 -08:00
|
|
|
if (data[IFLA_BOND_PRIMARY_RESELECT]) {
|
|
|
|
int primary_reselect =
|
|
|
|
nla_get_u8(data[IFLA_BOND_PRIMARY_RESELECT]);
|
|
|
|
|
2014-01-22 14:53:33 +01:00
|
|
|
bond_opt_initval(&newval, primary_reselect);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_PRIMARY_RESELECT, &newval,
|
|
|
|
data[IFLA_BOND_PRIMARY_RESELECT], extack);
|
2013-12-15 16:41:58 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-15 16:42:05 -08:00
|
|
|
if (data[IFLA_BOND_FAIL_OVER_MAC]) {
|
|
|
|
int fail_over_mac =
|
|
|
|
nla_get_u8(data[IFLA_BOND_FAIL_OVER_MAC]);
|
|
|
|
|
2014-01-22 14:53:22 +01:00
|
|
|
bond_opt_initval(&newval, fail_over_mac);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_FAIL_OVER_MAC, &newval,
|
|
|
|
data[IFLA_BOND_FAIL_OVER_MAC], extack);
|
2013-12-15 16:42:05 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-15 16:42:12 -08:00
|
|
|
if (data[IFLA_BOND_XMIT_HASH_POLICY]) {
|
|
|
|
int xmit_hash_policy =
|
|
|
|
nla_get_u8(data[IFLA_BOND_XMIT_HASH_POLICY]);
|
|
|
|
|
2014-01-22 14:53:19 +01:00
|
|
|
bond_opt_initval(&newval, xmit_hash_policy);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_XMIT_HASH, &newval,
|
|
|
|
data[IFLA_BOND_XMIT_HASH_POLICY], extack);
|
2013-12-15 16:42:12 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-15 16:42:19 -08:00
|
|
|
if (data[IFLA_BOND_RESEND_IGMP]) {
|
|
|
|
int resend_igmp =
|
|
|
|
nla_get_u32(data[IFLA_BOND_RESEND_IGMP]);
|
|
|
|
|
2014-01-22 14:53:38 +01:00
|
|
|
bond_opt_initval(&newval, resend_igmp);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_RESEND_IGMP, &newval,
|
|
|
|
data[IFLA_BOND_RESEND_IGMP], extack);
|
2013-12-15 16:42:19 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-17 21:30:09 -08:00
|
|
|
if (data[IFLA_BOND_NUM_PEER_NOTIF]) {
|
|
|
|
int num_peer_notif =
|
|
|
|
nla_get_u8(data[IFLA_BOND_NUM_PEER_NOTIF]);
|
|
|
|
|
2014-01-22 14:53:30 +01:00
|
|
|
bond_opt_initval(&newval, num_peer_notif);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_NUM_PEER_NOTIF, &newval,
|
|
|
|
data[IFLA_BOND_NUM_PEER_NOTIF], extack);
|
2013-12-17 21:30:09 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-17 21:30:16 -08:00
|
|
|
if (data[IFLA_BOND_ALL_SLAVES_ACTIVE]) {
|
|
|
|
int all_slaves_active =
|
|
|
|
nla_get_u8(data[IFLA_BOND_ALL_SLAVES_ACTIVE]);
|
|
|
|
|
2014-01-22 14:53:37 +01:00
|
|
|
bond_opt_initval(&newval, all_slaves_active);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_ALL_SLAVES_ACTIVE, &newval,
|
|
|
|
data[IFLA_BOND_ALL_SLAVES_ACTIVE], extack);
|
2013-12-17 21:30:16 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-17 21:30:23 -08:00
|
|
|
if (data[IFLA_BOND_MIN_LINKS]) {
|
|
|
|
int min_links =
|
|
|
|
nla_get_u32(data[IFLA_BOND_MIN_LINKS]);
|
|
|
|
|
2014-01-22 14:53:28 +01:00
|
|
|
bond_opt_initval(&newval, min_links);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_MINLINKS, &newval,
|
|
|
|
data[IFLA_BOND_MIN_LINKS], extack);
|
2013-12-17 21:30:23 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-17 21:30:30 -08:00
|
|
|
if (data[IFLA_BOND_LP_INTERVAL]) {
|
|
|
|
int lp_interval =
|
|
|
|
nla_get_u32(data[IFLA_BOND_LP_INTERVAL]);
|
|
|
|
|
2014-01-22 14:53:39 +01:00
|
|
|
bond_opt_initval(&newval, lp_interval);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_LP_INTERVAL, &newval,
|
|
|
|
data[IFLA_BOND_LP_INTERVAL], extack);
|
2013-12-17 21:30:30 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2013-12-17 21:30:37 -08:00
|
|
|
if (data[IFLA_BOND_PACKETS_PER_SLAVE]) {
|
|
|
|
int packets_per_slave =
|
|
|
|
nla_get_u32(data[IFLA_BOND_PACKETS_PER_SLAVE]);
|
|
|
|
|
2014-01-22 14:53:18 +01:00
|
|
|
bond_opt_initval(&newval, packets_per_slave);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_PACKETS_PER_SLAVE, &newval,
|
|
|
|
data[IFLA_BOND_PACKETS_PER_SLAVE], extack);
|
2013-12-17 21:30:37 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2021-08-02 11:02:19 +08:00
|
|
|
|
|
|
|
if (data[IFLA_BOND_AD_LACP_ACTIVE]) {
|
|
|
|
int lacp_active = nla_get_u8(data[IFLA_BOND_AD_LACP_ACTIVE]);
|
|
|
|
|
|
|
|
bond_opt_initval(&newval, lacp_active);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_LACP_ACTIVE, &newval,
|
|
|
|
data[IFLA_BOND_AD_LACP_ACTIVE], extack);
|
2021-08-02 11:02:19 +08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2014-01-03 14:18:41 -08:00
|
|
|
if (data[IFLA_BOND_AD_LACP_RATE]) {
|
|
|
|
int lacp_rate =
|
|
|
|
nla_get_u8(data[IFLA_BOND_AD_LACP_RATE]);
|
|
|
|
|
2014-01-22 14:53:27 +01:00
|
|
|
bond_opt_initval(&newval, lacp_rate);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_LACP_RATE, &newval,
|
|
|
|
data[IFLA_BOND_AD_LACP_RATE], extack);
|
2014-01-03 14:18:41 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2014-01-03 14:18:49 -08:00
|
|
|
if (data[IFLA_BOND_AD_SELECT]) {
|
|
|
|
int ad_select =
|
|
|
|
nla_get_u8(data[IFLA_BOND_AD_SELECT]);
|
|
|
|
|
2014-01-22 14:53:29 +01:00
|
|
|
bond_opt_initval(&newval, ad_select);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_AD_SELECT, &newval,
|
|
|
|
data[IFLA_BOND_AD_SELECT], extack);
|
2014-01-03 14:18:49 -08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2015-05-09 00:01:58 -07:00
|
|
|
if (data[IFLA_BOND_AD_ACTOR_SYS_PRIO]) {
|
|
|
|
int actor_sys_prio =
|
|
|
|
nla_get_u16(data[IFLA_BOND_AD_ACTOR_SYS_PRIO]);
|
|
|
|
|
|
|
|
bond_opt_initval(&newval, actor_sys_prio);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYS_PRIO, &newval,
|
|
|
|
data[IFLA_BOND_AD_ACTOR_SYS_PRIO], extack);
|
2015-05-09 00:01:58 -07:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
if (data[IFLA_BOND_AD_USER_PORT_KEY]) {
|
|
|
|
int port_key =
|
|
|
|
nla_get_u16(data[IFLA_BOND_AD_USER_PORT_KEY]);
|
|
|
|
|
|
|
|
bond_opt_initval(&newval, port_key);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_AD_USER_PORT_KEY, &newval,
|
|
|
|
data[IFLA_BOND_AD_USER_PORT_KEY], extack);
|
2015-05-09 00:01:58 -07:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
if (data[IFLA_BOND_AD_ACTOR_SYSTEM]) {
|
|
|
|
if (nla_len(data[IFLA_BOND_AD_ACTOR_SYSTEM]) != ETH_ALEN)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
bond_opt_initval(&newval,
|
2017-11-26 21:12:09 +08:00
|
|
|
nla_get_u64(data[IFLA_BOND_AD_ACTOR_SYSTEM]));
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYSTEM, &newval,
|
|
|
|
data[IFLA_BOND_AD_ACTOR_SYSTEM], extack);
|
2015-05-09 00:01:58 -07:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
2015-07-31 16:49:43 +02:00
|
|
|
if (data[IFLA_BOND_TLB_DYNAMIC_LB]) {
|
|
|
|
int dynamic_lb = nla_get_u8(data[IFLA_BOND_TLB_DYNAMIC_LB]);
|
|
|
|
|
|
|
|
bond_opt_initval(&newval, dynamic_lb);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_TLB_DYNAMIC_LB, &newval,
|
|
|
|
data[IFLA_BOND_TLB_DYNAMIC_LB], extack);
|
2015-07-31 16:49:43 +02:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-11-30 12:29:47 +08:00
|
|
|
if (data[IFLA_BOND_MISSED_MAX]) {
|
|
|
|
int missed_max = nla_get_u8(data[IFLA_BOND_MISSED_MAX]);
|
|
|
|
|
|
|
|
bond_opt_initval(&newval, missed_max);
|
2022-06-08 14:14:56 -04:00
|
|
|
err = __bond_opt_set(bond, BOND_OPT_MISSED_MAX, &newval,
|
|
|
|
data[IFLA_BOND_MISSED_MAX], extack);
|
2021-11-30 12:29:47 +08:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2024-02-02 17:58:58 +00:00
|
|
|
if (data[IFLA_BOND_COUPLED_CONTROL]) {
|
|
|
|
int coupled_control = nla_get_u8(data[IFLA_BOND_COUPLED_CONTROL]);
|
|
|
|
|
|
|
|
bond_opt_initval(&newval, coupled_control);
|
|
|
|
err = __bond_opt_set(bond, BOND_OPT_COUPLED_CONTROL, &newval,
|
|
|
|
data[IFLA_BOND_COUPLED_CONTROL], extack);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2025-06-27 21:49:29 +08:00
|
|
|
if (data[IFLA_BOND_BROADCAST_NEIGH]) {
|
|
|
|
int broadcast_neigh = nla_get_u8(data[IFLA_BOND_BROADCAST_NEIGH]);
|
|
|
|
|
|
|
|
bond_opt_initval(&newval, broadcast_neigh);
|
|
|
|
err = __bond_opt_set(bond, BOND_OPT_BROADCAST_NEIGH, &newval,
|
|
|
|
data[IFLA_BOND_BROADCAST_NEIGH], extack);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2013-10-18 17:43:38 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
rtnetlink: Pack newlink() params into struct
There are 4 net namespaces involved when creating links:
- source netns - where the netlink socket resides,
- target netns - where to put the device being created,
- link netns - netns associated with the device (backend),
- peer netns - netns of peer device.
Currently, two nets are passed to newlink() callback - "src_net"
parameter and "dev_net" (implicitly in net_device). They are set as
follows, depending on netlink attributes in the request.
+------------+-------------------+---------+---------+
| peer netns | IFLA_LINK_NETNSID | src_net | dev_net |
+------------+-------------------+---------+---------+
| | absent | source | target |
| absent +-------------------+---------+---------+
| | present | link | link |
+------------+-------------------+---------+---------+
| | absent | peer | target |
| present +-------------------+---------+---------+
| | present | peer | link |
+------------+-------------------+---------+---------+
When IFLA_LINK_NETNSID is present, the device is created in link netns
first and then moved to target netns. This has some side effects,
including extra ifindex allocation, ifname validation and link events.
These could be avoided if we create it in target netns from
the beginning.
On the other hand, the meaning of src_net parameter is ambiguous. It
varies depending on how parameters are passed. It is the effective
link (or peer netns) by design, but some drivers ignore it and use
dev_net instead.
To provide more netns context for drivers, this patch packs existing
newlink() parameters, along with the source netns, link netns and peer
netns, into a struct. The old "src_net" is renamed to "net" to avoid
confusion with real source netns, and will be deprecated later. The use
of src_net are converted to params->net trivially.
Signed-off-by: Xiao Liang <shaw.leon@gmail.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250219125039.18024-3-shaw.leon@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-02-19 20:50:28 +08:00
|
|
|
static int bond_newlink(struct net_device *bond_dev,
|
|
|
|
struct rtnl_newlink_params *params,
|
2017-06-25 23:55:59 +02:00
|
|
|
struct netlink_ext_ack *extack)
|
2013-10-18 17:43:38 +02:00
|
|
|
{
|
rtnetlink: Pack newlink() params into struct
There are 4 net namespaces involved when creating links:
- source netns - where the netlink socket resides,
- target netns - where to put the device being created,
- link netns - netns associated with the device (backend),
- peer netns - netns of peer device.
Currently, two nets are passed to newlink() callback - "src_net"
parameter and "dev_net" (implicitly in net_device). They are set as
follows, depending on netlink attributes in the request.
+------------+-------------------+---------+---------+
| peer netns | IFLA_LINK_NETNSID | src_net | dev_net |
+------------+-------------------+---------+---------+
| | absent | source | target |
| absent +-------------------+---------+---------+
| | present | link | link |
+------------+-------------------+---------+---------+
| | absent | peer | target |
| present +-------------------+---------+---------+
| | present | peer | link |
+------------+-------------------+---------+---------+
When IFLA_LINK_NETNSID is present, the device is created in link netns
first and then moved to target netns. This has some side effects,
including extra ifindex allocation, ifname validation and link events.
These could be avoided if we create it in target netns from
the beginning.
On the other hand, the meaning of src_net parameter is ambiguous. It
varies depending on how parameters are passed. It is the effective
link (or peer netns) by design, but some drivers ignore it and use
dev_net instead.
To provide more netns context for drivers, this patch packs existing
newlink() parameters, along with the source netns, link netns and peer
netns, into a struct. The old "src_net" is renamed to "net" to avoid
confusion with real source netns, and will be deprecated later. The use
of src_net are converted to params->net trivially.
Signed-off-by: Xiao Liang <shaw.leon@gmail.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250219125039.18024-3-shaw.leon@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-02-19 20:50:28 +08:00
|
|
|
struct nlattr **data = params->data;
|
|
|
|
struct nlattr **tb = params->tb;
|
2013-10-18 17:43:38 +02:00
|
|
|
int err;
|
|
|
|
|
2017-06-25 23:56:00 +02:00
|
|
|
err = bond_changelink(bond_dev, tb, data, extack);
|
2013-10-18 17:43:38 +02:00
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
2016-07-13 18:25:08 +02:00
|
|
|
err = register_netdevice(bond_dev);
|
2017-04-20 12:49:24 -07:00
|
|
|
if (!err) {
|
|
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
|
|
|
|
2020-07-22 16:31:54 -07:00
|
|
|
netif_carrier_off(bond_dev);
|
2017-04-20 12:49:24 -07:00
|
|
|
bond_work_init_all(bond);
|
|
|
|
}
|
2016-07-13 18:25:08 +02:00
|
|
|
|
|
|
|
return err;
|
2013-10-18 17:43:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static size_t bond_get_size(const struct net_device *bond_dev)
|
|
|
|
{
|
2013-11-01 13:18:44 +03:00
|
|
|
return nla_total_size(sizeof(u8)) + /* IFLA_BOND_MODE */
|
2013-12-12 14:09:55 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_ACTIVE_SLAVE */
|
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIIMON */
|
2013-12-12 14:10:02 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_UPDELAY */
|
2013-12-12 14:10:09 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_DOWNDELAY */
|
2013-12-12 14:10:16 -08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_USE_CARRIER */
|
2013-12-12 14:10:24 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_INTERVAL */
|
2013-12-12 14:10:31 -08:00
|
|
|
/* IFLA_BOND_ARP_IP_TARGET */
|
2014-01-03 14:28:11 -08:00
|
|
|
nla_total_size(sizeof(struct nlattr)) +
|
2013-12-12 14:10:31 -08:00
|
|
|
nla_total_size(sizeof(u32)) * BOND_MAX_ARP_TARGETS +
|
2013-12-12 14:10:38 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_VALIDATE */
|
2013-12-12 14:10:45 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_ALL_TARGETS */
|
2013-12-15 16:41:51 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_PRIMARY */
|
2013-12-15 16:41:58 -08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_PRIMARY_RESELECT */
|
2013-12-15 16:42:05 -08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_FAIL_OVER_MAC */
|
2013-12-15 16:42:12 -08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_XMIT_HASH_POLICY */
|
2013-12-15 16:42:19 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_RESEND_IGMP */
|
2013-12-17 21:30:09 -08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_NUM_PEER_NOTIF */
|
2013-12-17 21:30:16 -08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_ALL_SLAVES_ACTIVE */
|
2013-12-17 21:30:23 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIN_LINKS */
|
2013-12-17 21:30:30 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_LP_INTERVAL */
|
2013-12-17 21:30:37 -08:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_PACKETS_PER_SLAVE */
|
2021-08-02 11:02:19 +08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_AD_LACP_ACTIVE */
|
2014-01-03 14:18:41 -08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_AD_LACP_RATE */
|
2014-01-03 14:18:49 -08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_AD_SELECT */
|
2014-01-03 14:18:56 -08:00
|
|
|
nla_total_size(sizeof(struct nlattr)) + /* IFLA_BOND_AD_INFO */
|
|
|
|
nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_AGGREGATOR */
|
|
|
|
nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_NUM_PORTS */
|
|
|
|
nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_ACTOR_KEY */
|
|
|
|
nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_PARTNER_KEY*/
|
|
|
|
nla_total_size(ETH_ALEN) + /* IFLA_BOND_AD_INFO_PARTNER_MAC*/
|
2015-05-09 00:01:58 -07:00
|
|
|
nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_ACTOR_SYS_PRIO */
|
|
|
|
nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_USER_PORT_KEY */
|
|
|
|
nla_total_size(ETH_ALEN) + /* IFLA_BOND_AD_ACTOR_SYSTEM */
|
2015-07-31 16:49:43 +02:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_TLB_DYNAMIC_LB */
|
bonding: add an option to specify a delay between peer notifications
Currently, gratuitous ARP/ND packets are sent every `miimon'
milliseconds. This commit allows a user to specify a custom delay
through a new option, `peer_notif_delay'.
Like for `updelay' and `downdelay', this delay should be a multiple of
`miimon' to avoid managing an additional work queue. The configuration
logic is copied from `updelay' and `downdelay'. However, the default
value cannot be set using a module parameter: Netlink or sysfs should
be used to configure this feature.
When setting `miimon' to 100 and `peer_notif_delay' to 500, we can
observe the 500 ms delay is respected:
20:30:19.354693 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:19.874892 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.394919 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.914963 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
In bond_mii_monitor(), I have tried to keep the lock logic readable.
The change is due to the fact we cannot rely on a notification to
lower the value of `bond->send_peer_notif' as `NETDEV_NOTIFY_PEERS' is
only triggered once every N times, while we need to decrement the
counter each time.
iproute2 also needs to be updated to be able to specify this new
attribute through `ip link'.
Signed-off-by: Vincent Bernat <vincent@bernat.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-07-02 19:43:54 +02:00
|
|
|
nla_total_size(sizeof(u32)) + /* IFLA_BOND_PEER_NOTIF_DELAY */
|
2021-11-30 12:29:47 +08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_MISSED_MAX */
|
2022-02-21 13:54:57 +08:00
|
|
|
/* IFLA_BOND_NS_IP6_TARGET */
|
|
|
|
nla_total_size(sizeof(struct nlattr)) +
|
|
|
|
nla_total_size(sizeof(struct in6_addr)) * BOND_MAX_NS_TARGETS +
|
2024-02-02 17:58:58 +00:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_COUPLED_CONTROL */
|
2025-06-27 21:49:29 +08:00
|
|
|
nla_total_size(sizeof(u8)) + /* IFLA_BOND_BROADCAST_NEIGH */
|
2013-12-12 14:09:55 -08:00
|
|
|
0;
|
2013-10-18 17:43:38 +02:00
|
|
|
}
|
|
|
|
|
2014-07-15 06:56:53 -07:00
|
|
|
static int bond_option_active_slave_get_ifindex(struct bonding *bond)
|
|
|
|
{
|
|
|
|
const struct net_device *slave;
|
|
|
|
int ifindex;
|
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
slave = bond_option_active_slave_get_rcu(bond);
|
|
|
|
ifindex = slave ? slave->ifindex : 0;
|
|
|
|
rcu_read_unlock();
|
|
|
|
return ifindex;
|
|
|
|
}
|
|
|
|
|
2013-10-18 17:43:38 +02:00
|
|
|
static int bond_fill_info(struct sk_buff *skb,
|
|
|
|
const struct net_device *bond_dev)
|
|
|
|
{
|
|
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
2013-12-17 21:30:37 -08:00
|
|
|
unsigned int packets_per_slave;
|
2014-07-15 06:56:53 -07:00
|
|
|
int ifindex, i, targets_added;
|
|
|
|
struct nlattr *targets;
|
2014-09-09 23:17:00 +02:00
|
|
|
struct slave *primary;
|
2013-10-18 17:43:38 +02:00
|
|
|
|
2014-05-15 21:39:55 +02:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_MODE, BOND_MODE(bond)))
|
2013-10-18 17:43:38 +02:00
|
|
|
goto nla_put_failure;
|
2013-12-12 14:09:55 -08:00
|
|
|
|
2014-07-15 06:56:53 -07:00
|
|
|
ifindex = bond_option_active_slave_get_ifindex(bond);
|
|
|
|
if (ifindex && nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, ifindex))
|
2013-12-12 14:09:55 -08:00
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-12 14:10:02 -08:00
|
|
|
if (nla_put_u32(skb, IFLA_BOND_UPDELAY,
|
|
|
|
bond->params.updelay * bond->params.miimon))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-12 14:10:09 -08:00
|
|
|
if (nla_put_u32(skb, IFLA_BOND_DOWNDELAY,
|
|
|
|
bond->params.downdelay * bond->params.miimon))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
bonding: add an option to specify a delay between peer notifications
Currently, gratuitous ARP/ND packets are sent every `miimon'
milliseconds. This commit allows a user to specify a custom delay
through a new option, `peer_notif_delay'.
Like for `updelay' and `downdelay', this delay should be a multiple of
`miimon' to avoid managing an additional work queue. The configuration
logic is copied from `updelay' and `downdelay'. However, the default
value cannot be set using a module parameter: Netlink or sysfs should
be used to configure this feature.
When setting `miimon' to 100 and `peer_notif_delay' to 500, we can
observe the 500 ms delay is respected:
20:30:19.354693 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:19.874892 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.394919 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.914963 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
In bond_mii_monitor(), I have tried to keep the lock logic readable.
The change is due to the fact we cannot rely on a notification to
lower the value of `bond->send_peer_notif' as `NETDEV_NOTIFY_PEERS' is
only triggered once every N times, while we need to decrement the
counter each time.
iproute2 also needs to be updated to be able to specify this new
attribute through `ip link'.
Signed-off-by: Vincent Bernat <vincent@bernat.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-07-02 19:43:54 +02:00
|
|
|
if (nla_put_u32(skb, IFLA_BOND_PEER_NOTIF_DELAY,
|
2019-07-06 23:01:08 +02:00
|
|
|
bond->params.peer_notif_delay * bond->params.miimon))
|
bonding: add an option to specify a delay between peer notifications
Currently, gratuitous ARP/ND packets are sent every `miimon'
milliseconds. This commit allows a user to specify a custom delay
through a new option, `peer_notif_delay'.
Like for `updelay' and `downdelay', this delay should be a multiple of
`miimon' to avoid managing an additional work queue. The configuration
logic is copied from `updelay' and `downdelay'. However, the default
value cannot be set using a module parameter: Netlink or sysfs should
be used to configure this feature.
When setting `miimon' to 100 and `peer_notif_delay' to 500, we can
observe the 500 ms delay is respected:
20:30:19.354693 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:19.874892 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.394919 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.914963 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
In bond_mii_monitor(), I have tried to keep the lock logic readable.
The change is due to the fact we cannot rely on a notification to
lower the value of `bond->send_peer_notif' as `NETDEV_NOTIFY_PEERS' is
only triggered once every N times, while we need to decrement the
counter each time.
iproute2 also needs to be updated to be able to specify this new
attribute through `ip link'.
Signed-off-by: Vincent Bernat <vincent@bernat.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-07-02 19:43:54 +02:00
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-12 14:10:16 -08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_USE_CARRIER, bond->params.use_carrier))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-12 14:10:24 -08:00
|
|
|
if (nla_put_u32(skb, IFLA_BOND_ARP_INTERVAL, bond->params.arp_interval))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2019-04-26 11:13:06 +02:00
|
|
|
targets = nla_nest_start_noflag(skb, IFLA_BOND_ARP_IP_TARGET);
|
2013-12-12 14:10:31 -08:00
|
|
|
if (!targets)
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
targets_added = 0;
|
|
|
|
for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
|
|
|
|
if (bond->params.arp_targets[i]) {
|
2017-05-06 11:17:06 +08:00
|
|
|
if (nla_put_be32(skb, i, bond->params.arp_targets[i]))
|
|
|
|
goto nla_put_failure;
|
2013-12-12 14:10:31 -08:00
|
|
|
targets_added = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (targets_added)
|
|
|
|
nla_nest_end(skb, targets);
|
|
|
|
else
|
|
|
|
nla_nest_cancel(skb, targets);
|
|
|
|
|
2013-12-12 14:10:38 -08:00
|
|
|
if (nla_put_u32(skb, IFLA_BOND_ARP_VALIDATE, bond->params.arp_validate))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-12 14:10:45 -08:00
|
|
|
if (nla_put_u32(skb, IFLA_BOND_ARP_ALL_TARGETS,
|
|
|
|
bond->params.arp_all_targets))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2022-02-21 13:54:57 +08:00
|
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
|
|
targets = nla_nest_start(skb, IFLA_BOND_NS_IP6_TARGET);
|
|
|
|
if (!targets)
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
targets_added = 0;
|
|
|
|
for (i = 0; i < BOND_MAX_NS_TARGETS; i++) {
|
|
|
|
if (!ipv6_addr_any(&bond->params.ns_targets[i])) {
|
|
|
|
if (nla_put_in6_addr(skb, i, &bond->params.ns_targets[i]))
|
|
|
|
goto nla_put_failure;
|
|
|
|
targets_added = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (targets_added)
|
|
|
|
nla_nest_end(skb, targets);
|
|
|
|
else
|
|
|
|
nla_nest_cancel(skb, targets);
|
|
|
|
#endif
|
|
|
|
|
2014-09-09 23:17:00 +02:00
|
|
|
primary = rtnl_dereference(bond->primary_slave);
|
|
|
|
if (primary &&
|
|
|
|
nla_put_u32(skb, IFLA_BOND_PRIMARY, primary->dev->ifindex))
|
2013-12-15 16:41:51 -08:00
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-15 16:41:58 -08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_PRIMARY_RESELECT,
|
|
|
|
bond->params.primary_reselect))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-15 16:42:05 -08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_FAIL_OVER_MAC,
|
|
|
|
bond->params.fail_over_mac))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-15 16:42:12 -08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_XMIT_HASH_POLICY,
|
|
|
|
bond->params.xmit_policy))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-15 16:42:19 -08:00
|
|
|
if (nla_put_u32(skb, IFLA_BOND_RESEND_IGMP,
|
2021-05-20 14:18:35 +08:00
|
|
|
bond->params.resend_igmp))
|
2013-12-15 16:42:19 -08:00
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-17 21:30:09 -08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_NUM_PEER_NOTIF,
|
|
|
|
bond->params.num_peer_notif))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-17 21:30:16 -08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_ALL_SLAVES_ACTIVE,
|
|
|
|
bond->params.all_slaves_active))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-17 21:30:23 -08:00
|
|
|
if (nla_put_u32(skb, IFLA_BOND_MIN_LINKS,
|
|
|
|
bond->params.min_links))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-17 21:30:30 -08:00
|
|
|
if (nla_put_u32(skb, IFLA_BOND_LP_INTERVAL,
|
|
|
|
bond->params.lp_interval))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2013-12-17 21:30:37 -08:00
|
|
|
packets_per_slave = bond->params.packets_per_slave;
|
|
|
|
if (nla_put_u32(skb, IFLA_BOND_PACKETS_PER_SLAVE,
|
|
|
|
packets_per_slave))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2021-08-02 11:02:19 +08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_AD_LACP_ACTIVE,
|
|
|
|
bond->params.lacp_active))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2014-01-03 14:18:41 -08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_AD_LACP_RATE,
|
|
|
|
bond->params.lacp_fast))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2014-01-03 14:18:49 -08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_AD_SELECT,
|
|
|
|
bond->params.ad_select))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2015-07-31 16:49:43 +02:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_TLB_DYNAMIC_LB,
|
|
|
|
bond->params.tlb_dynamic_lb))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2021-11-30 12:29:47 +08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_MISSED_MAX,
|
|
|
|
bond->params.missed_max))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2024-02-02 17:58:58 +00:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_COUPLED_CONTROL,
|
|
|
|
bond->params.coupled_control))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2025-06-27 21:49:29 +08:00
|
|
|
if (nla_put_u8(skb, IFLA_BOND_BROADCAST_NEIGH,
|
|
|
|
bond->params.broadcast_neighbor))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2014-05-15 21:39:55 +02:00
|
|
|
if (BOND_MODE(bond) == BOND_MODE_8023AD) {
|
2014-01-03 14:18:56 -08:00
|
|
|
struct ad_info info;
|
|
|
|
|
2015-06-18 11:30:54 -07:00
|
|
|
if (capable(CAP_NET_ADMIN)) {
|
|
|
|
if (nla_put_u16(skb, IFLA_BOND_AD_ACTOR_SYS_PRIO,
|
|
|
|
bond->params.ad_actor_sys_prio))
|
|
|
|
goto nla_put_failure;
|
2015-05-09 00:01:58 -07:00
|
|
|
|
2015-06-18 11:30:54 -07:00
|
|
|
if (nla_put_u16(skb, IFLA_BOND_AD_USER_PORT_KEY,
|
|
|
|
bond->params.ad_user_port_key))
|
|
|
|
goto nla_put_failure;
|
2015-05-09 00:01:58 -07:00
|
|
|
|
2015-06-18 11:30:54 -07:00
|
|
|
if (nla_put(skb, IFLA_BOND_AD_ACTOR_SYSTEM,
|
2018-10-28 12:54:10 +01:00
|
|
|
ETH_ALEN, &bond->params.ad_actor_system))
|
2015-06-18 11:30:54 -07:00
|
|
|
goto nla_put_failure;
|
|
|
|
}
|
2014-01-03 14:18:56 -08:00
|
|
|
if (!bond_3ad_get_active_agg_info(bond, &info)) {
|
|
|
|
struct nlattr *nest;
|
|
|
|
|
2019-04-26 11:13:06 +02:00
|
|
|
nest = nla_nest_start_noflag(skb, IFLA_BOND_AD_INFO);
|
2014-01-03 14:18:56 -08:00
|
|
|
if (!nest)
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
if (nla_put_u16(skb, IFLA_BOND_AD_INFO_AGGREGATOR,
|
|
|
|
info.aggregator_id))
|
|
|
|
goto nla_put_failure;
|
|
|
|
if (nla_put_u16(skb, IFLA_BOND_AD_INFO_NUM_PORTS,
|
|
|
|
info.ports))
|
|
|
|
goto nla_put_failure;
|
|
|
|
if (nla_put_u16(skb, IFLA_BOND_AD_INFO_ACTOR_KEY,
|
|
|
|
info.actor_key))
|
|
|
|
goto nla_put_failure;
|
|
|
|
if (nla_put_u16(skb, IFLA_BOND_AD_INFO_PARTNER_KEY,
|
|
|
|
info.partner_key))
|
|
|
|
goto nla_put_failure;
|
|
|
|
if (nla_put(skb, IFLA_BOND_AD_INFO_PARTNER_MAC,
|
|
|
|
sizeof(info.partner_system),
|
|
|
|
&info.partner_system))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
nla_nest_end(skb, nest);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-18 17:43:38 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
nla_put_failure:
|
|
|
|
return -EMSGSIZE;
|
|
|
|
}
|
|
|
|
|
2019-01-18 14:30:23 +02:00
|
|
|
static size_t bond_get_linkxstats_size(const struct net_device *dev, int attr)
|
|
|
|
{
|
|
|
|
switch (attr) {
|
|
|
|
case IFLA_STATS_LINK_XSTATS:
|
|
|
|
case IFLA_STATS_LINK_XSTATS_SLAVE:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bond_3ad_stats_size() + nla_total_size(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int bond_fill_linkxstats(struct sk_buff *skb,
|
|
|
|
const struct net_device *dev,
|
|
|
|
int *prividx, int attr)
|
|
|
|
{
|
|
|
|
struct nlattr *nla __maybe_unused;
|
|
|
|
struct slave *slave = NULL;
|
|
|
|
struct nlattr *nest, *nest2;
|
|
|
|
struct bonding *bond;
|
|
|
|
|
|
|
|
switch (attr) {
|
|
|
|
case IFLA_STATS_LINK_XSTATS:
|
|
|
|
bond = netdev_priv(dev);
|
|
|
|
break;
|
|
|
|
case IFLA_STATS_LINK_XSTATS_SLAVE:
|
|
|
|
slave = bond_slave_get_rtnl(dev);
|
|
|
|
if (!slave)
|
|
|
|
return 0;
|
|
|
|
bond = slave->bond;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2019-04-26 11:13:06 +02:00
|
|
|
nest = nla_nest_start_noflag(skb, LINK_XSTATS_TYPE_BOND);
|
2019-01-18 14:30:23 +02:00
|
|
|
if (!nest)
|
|
|
|
return -EMSGSIZE;
|
|
|
|
if (BOND_MODE(bond) == BOND_MODE_8023AD) {
|
2019-01-23 19:14:50 +02:00
|
|
|
struct bond_3ad_stats *stats;
|
|
|
|
|
|
|
|
if (slave)
|
|
|
|
stats = &SLAVE_AD_INFO(slave)->stats;
|
|
|
|
else
|
|
|
|
stats = &BOND_AD_INFO(bond).stats;
|
2019-01-18 14:30:23 +02:00
|
|
|
|
2019-04-26 11:13:06 +02:00
|
|
|
nest2 = nla_nest_start_noflag(skb, BOND_XSTATS_3AD);
|
2019-01-18 14:30:23 +02:00
|
|
|
if (!nest2) {
|
|
|
|
nla_nest_end(skb, nest);
|
|
|
|
return -EMSGSIZE;
|
|
|
|
}
|
|
|
|
|
2019-01-23 19:14:50 +02:00
|
|
|
if (bond_3ad_stats_fill(skb, stats)) {
|
2019-01-18 14:30:23 +02:00
|
|
|
nla_nest_cancel(skb, nest2);
|
|
|
|
nla_nest_end(skb, nest);
|
|
|
|
return -EMSGSIZE;
|
|
|
|
}
|
|
|
|
nla_nest_end(skb, nest2);
|
|
|
|
}
|
|
|
|
nla_nest_end(skb, nest);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-10-18 17:43:33 +02:00
|
|
|
struct rtnl_link_ops bond_link_ops __read_mostly = {
|
|
|
|
.kind = "bond",
|
|
|
|
.priv_size = sizeof(struct bonding),
|
|
|
|
.setup = bond_setup,
|
2013-10-18 17:43:38 +02:00
|
|
|
.maxtype = IFLA_BOND_MAX,
|
|
|
|
.policy = bond_policy,
|
2013-10-18 17:43:33 +02:00
|
|
|
.validate = bond_validate,
|
2013-10-18 17:43:38 +02:00
|
|
|
.newlink = bond_newlink,
|
|
|
|
.changelink = bond_changelink,
|
|
|
|
.get_size = bond_get_size,
|
|
|
|
.fill_info = bond_fill_info,
|
2013-10-18 17:43:33 +02:00
|
|
|
.get_num_tx_queues = bond_get_num_tx_queues,
|
|
|
|
.get_num_rx_queues = bond_get_num_tx_queues, /* Use the same number
|
|
|
|
as for TX queues */
|
2019-01-18 14:30:23 +02:00
|
|
|
.fill_linkxstats = bond_fill_linkxstats,
|
|
|
|
.get_linkxstats_size = bond_get_linkxstats_size,
|
2014-09-05 11:36:34 +02:00
|
|
|
.slave_maxtype = IFLA_BOND_SLAVE_MAX,
|
|
|
|
.slave_policy = bond_slave_policy,
|
|
|
|
.slave_changelink = bond_slave_changelink,
|
2014-01-22 09:05:56 +01:00
|
|
|
.get_slave_size = bond_get_slave_size,
|
|
|
|
.fill_slave_info = bond_fill_slave_info,
|
2013-10-18 17:43:33 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
int __init bond_netlink_init(void)
|
|
|
|
{
|
|
|
|
return rtnl_link_register(&bond_link_ops);
|
|
|
|
}
|
|
|
|
|
2013-10-19 19:09:18 -04:00
|
|
|
void bond_netlink_fini(void)
|
2013-10-18 17:43:33 +02:00
|
|
|
{
|
|
|
|
rtnl_link_unregister(&bond_link_ops);
|
|
|
|
}
|
|
|
|
|
|
|
|
MODULE_ALIAS_RTNL_LINK("bond");
|