12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
20a2a78c4SJiri Pirko /*
30a2a78c4SJiri Pirko * drivers/net/bond/bond_netlink.c - Netlink interface for bonding
40a2a78c4SJiri Pirko * Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us>
5eecdaa6eSsfeldma@cumulusnetworks.com * Copyright (c) 2013 Scott Feldman <sfeldma@cumulusnetworks.com>
60a2a78c4SJiri Pirko */
70a2a78c4SJiri Pirko
80a2a78c4SJiri Pirko #include <linux/module.h>
90a2a78c4SJiri Pirko #include <linux/errno.h>
100a2a78c4SJiri Pirko #include <linux/netdevice.h>
110a2a78c4SJiri Pirko #include <linux/etherdevice.h>
120a2a78c4SJiri Pirko #include <linux/if_link.h>
130a2a78c4SJiri Pirko #include <linux/if_ether.h>
140a2a78c4SJiri Pirko #include <net/netlink.h>
150a2a78c4SJiri Pirko #include <net/rtnetlink.h>
161ef8019bSDavid S. Miller #include <net/bonding.h>
17129e3c1bSHangbin Liu #include <net/ipv6.h>
180a2a78c4SJiri Pirko
bond_get_slave_size(const struct net_device * bond_dev,const struct net_device * slave_dev)193bad540eSJiri Pirko static size_t bond_get_slave_size(const struct net_device *bond_dev,
203bad540eSJiri Pirko const struct net_device *slave_dev)
213bad540eSJiri Pirko {
223bad540eSJiri Pirko return nla_total_size(sizeof(u8)) + /* IFLA_BOND_SLAVE_STATE */
233bad540eSJiri Pirko nla_total_size(sizeof(u8)) + /* IFLA_BOND_SLAVE_MII_STATUS */
243bad540eSJiri Pirko nla_total_size(sizeof(u32)) + /* IFLA_BOND_SLAVE_LINK_FAILURE_COUNT */
253bad540eSJiri Pirko nla_total_size(MAX_ADDR_LEN) + /* IFLA_BOND_SLAVE_PERM_HWADDR */
263bad540eSJiri Pirko nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_QUEUE_ID */
273bad540eSJiri Pirko nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_AD_AGGREGATOR_ID */
28254cb6dbSNikolay Aleksandrov nla_total_size(sizeof(u8)) + /* IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE */
2946ea297eSNikolay Aleksandrov nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE */
300a2ff7ccSHangbin Liu nla_total_size(sizeof(s32)) + /* IFLA_BOND_SLAVE_PRIO */
313bad540eSJiri Pirko 0;
323bad540eSJiri Pirko }
333bad540eSJiri Pirko
bond_fill_slave_info(struct sk_buff * skb,const struct net_device * bond_dev,const struct net_device * slave_dev)343bad540eSJiri Pirko static int bond_fill_slave_info(struct sk_buff *skb,
353bad540eSJiri Pirko const struct net_device *bond_dev,
363bad540eSJiri Pirko const struct net_device *slave_dev)
371d3ee88aSsfeldma@cumulusnetworks.com {
381d3ee88aSsfeldma@cumulusnetworks.com struct slave *slave = bond_slave_get_rtnl(slave_dev);
391d3ee88aSsfeldma@cumulusnetworks.com
40df7dbcbbSJiri Pirko if (nla_put_u8(skb, IFLA_BOND_SLAVE_STATE, bond_slave_state(slave)))
411d3ee88aSsfeldma@cumulusnetworks.com goto nla_put_failure;
421d3ee88aSsfeldma@cumulusnetworks.com
43df7dbcbbSJiri Pirko if (nla_put_u8(skb, IFLA_BOND_SLAVE_MII_STATUS, slave->link))
441d3ee88aSsfeldma@cumulusnetworks.com goto nla_put_failure;
451d3ee88aSsfeldma@cumulusnetworks.com
46df7dbcbbSJiri Pirko if (nla_put_u32(skb, IFLA_BOND_SLAVE_LINK_FAILURE_COUNT,
471d3ee88aSsfeldma@cumulusnetworks.com slave->link_failure_count))
481d3ee88aSsfeldma@cumulusnetworks.com goto nla_put_failure;
491d3ee88aSsfeldma@cumulusnetworks.com
50df7dbcbbSJiri Pirko if (nla_put(skb, IFLA_BOND_SLAVE_PERM_HWADDR,
511d3ee88aSsfeldma@cumulusnetworks.com slave_dev->addr_len, slave->perm_hwaddr))
521d3ee88aSsfeldma@cumulusnetworks.com goto nla_put_failure;
531d3ee88aSsfeldma@cumulusnetworks.com
54df7dbcbbSJiri Pirko if (nla_put_u16(skb, IFLA_BOND_SLAVE_QUEUE_ID, slave->queue_id))
551d3ee88aSsfeldma@cumulusnetworks.com goto nla_put_failure;
561d3ee88aSsfeldma@cumulusnetworks.com
570a2ff7ccSHangbin Liu if (nla_put_s32(skb, IFLA_BOND_SLAVE_PRIO, slave->prio))
580a2ff7ccSHangbin Liu goto nla_put_failure;
590a2ff7ccSHangbin Liu
6001844098SVeaceslav Falico if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) {
613bad540eSJiri Pirko const struct aggregator *agg;
62254cb6dbSNikolay Aleksandrov const struct port *ad_port;
633bad540eSJiri Pirko
64254cb6dbSNikolay Aleksandrov ad_port = &SLAVE_AD_INFO(slave)->port;
653fdddd85Sdingtianhong agg = SLAVE_AD_INFO(slave)->port.aggregator;
66254cb6dbSNikolay Aleksandrov if (agg) {
67df7dbcbbSJiri Pirko if (nla_put_u16(skb, IFLA_BOND_SLAVE_AD_AGGREGATOR_ID,
681d3ee88aSsfeldma@cumulusnetworks.com agg->aggregator_identifier))
691d3ee88aSsfeldma@cumulusnetworks.com goto nla_put_failure;
70254cb6dbSNikolay Aleksandrov if (nla_put_u8(skb,
71254cb6dbSNikolay Aleksandrov IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
72254cb6dbSNikolay Aleksandrov ad_port->actor_oper_port_state))
73254cb6dbSNikolay Aleksandrov goto nla_put_failure;
7446ea297eSNikolay Aleksandrov if (nla_put_u16(skb,
7546ea297eSNikolay Aleksandrov IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
7646ea297eSNikolay Aleksandrov ad_port->partner_oper.port_state))
7746ea297eSNikolay Aleksandrov goto nla_put_failure;
78254cb6dbSNikolay Aleksandrov }
791d3ee88aSsfeldma@cumulusnetworks.com }
801d3ee88aSsfeldma@cumulusnetworks.com
811d3ee88aSsfeldma@cumulusnetworks.com return 0;
821d3ee88aSsfeldma@cumulusnetworks.com
831d3ee88aSsfeldma@cumulusnetworks.com nla_put_failure:
841d3ee88aSsfeldma@cumulusnetworks.com return -EMSGSIZE;
851d3ee88aSsfeldma@cumulusnetworks.com }
861d3ee88aSsfeldma@cumulusnetworks.com
87*9949e2efSHangbin Liu /* Limit the max delay range to 300s */
88*9949e2efSHangbin Liu static struct netlink_range_validation delay_range = {
89*9949e2efSHangbin Liu .max = 300000,
90*9949e2efSHangbin Liu };
91*9949e2efSHangbin Liu
9290af2311SJiri Pirko static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
9390af2311SJiri Pirko [IFLA_BOND_MODE] = { .type = NLA_U8 },
94ec76aa49SJiri Pirko [IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 },
95eecdaa6eSsfeldma@cumulusnetworks.com [IFLA_BOND_MIIMON] = { .type = NLA_U32 },
9625852e29Ssfeldma@cumulusnetworks.com [IFLA_BOND_UPDELAY] = { .type = NLA_U32 },
97c7461f9bSsfeldma@cumulusnetworks.com [IFLA_BOND_DOWNDELAY] = { .type = NLA_U32 },
989f53e14eSsfeldma@cumulusnetworks.com [IFLA_BOND_USE_CARRIER] = { .type = NLA_U8 },
9906151dbcSsfeldma@cumulusnetworks.com [IFLA_BOND_ARP_INTERVAL] = { .type = NLA_U32 },
1007f28fa10Ssfeldma@cumulusnetworks.com [IFLA_BOND_ARP_IP_TARGET] = { .type = NLA_NESTED },
10129c49482Ssfeldma@cumulusnetworks.com [IFLA_BOND_ARP_VALIDATE] = { .type = NLA_U32 },
102d5c84254Ssfeldma@cumulusnetworks.com [IFLA_BOND_ARP_ALL_TARGETS] = { .type = NLA_U32 },
1030a98a0d1Ssfeldma@cumulusnetworks.com [IFLA_BOND_PRIMARY] = { .type = NLA_U32 },
1048a41ae44Ssfeldma@cumulusnetworks.com [IFLA_BOND_PRIMARY_RESELECT] = { .type = NLA_U8 },
10589901972Ssfeldma@cumulusnetworks.com [IFLA_BOND_FAIL_OVER_MAC] = { .type = NLA_U8 },
106f70161c6Ssfeldma@cumulusnetworks.com [IFLA_BOND_XMIT_HASH_POLICY] = { .type = NLA_U8 },
107d8838de7Ssfeldma@cumulusnetworks.com [IFLA_BOND_RESEND_IGMP] = { .type = NLA_U32 },
1082c9839c1Ssfeldma@cumulusnetworks.com [IFLA_BOND_NUM_PEER_NOTIF] = { .type = NLA_U8 },
1091cc0b1e3Ssfeldma@cumulusnetworks.com [IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NLA_U8 },
1107d101008Ssfeldma@cumulusnetworks.com [IFLA_BOND_MIN_LINKS] = { .type = NLA_U32 },
1118d836d09Ssfeldma@cumulusnetworks.com [IFLA_BOND_LP_INTERVAL] = { .type = NLA_U32 },
112c13ab3ffSsfeldma@cumulusnetworks.com [IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NLA_U32 },
1133a755cd8SHangbin Liu [IFLA_BOND_AD_LACP_ACTIVE] = { .type = NLA_U8 },
114998e40bbSsfeldma@cumulusnetworks.com [IFLA_BOND_AD_LACP_RATE] = { .type = NLA_U8 },
115ec029facSsfeldma@cumulusnetworks.com [IFLA_BOND_AD_SELECT] = { .type = NLA_U8 },
1164ee7ac75Ssfeldma@cumulusnetworks.com [IFLA_BOND_AD_INFO] = { .type = NLA_NESTED },
117171a42c3SAndy Gospodarek [IFLA_BOND_AD_ACTOR_SYS_PRIO] = { .type = NLA_U16 },
118171a42c3SAndy Gospodarek [IFLA_BOND_AD_USER_PORT_KEY] = { .type = NLA_U16 },
119171a42c3SAndy Gospodarek [IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NLA_BINARY,
120171a42c3SAndy Gospodarek .len = ETH_ALEN },
1210f7bffd9SNikolay Aleksandrov [IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NLA_U8 },
122*9949e2efSHangbin Liu [IFLA_BOND_PEER_NOTIF_DELAY] = NLA_POLICY_FULL_RANGE(NLA_U32, &delay_range),
1235944b5abSHangbin Liu [IFLA_BOND_MISSED_MAX] = { .type = NLA_U8 },
124129e3c1bSHangbin Liu [IFLA_BOND_NS_IP6_TARGET] = { .type = NLA_NESTED },
12590af2311SJiri Pirko };
12690af2311SJiri Pirko
127cea6aeb6SJiri Pirko static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
128cea6aeb6SJiri Pirko [IFLA_BOND_SLAVE_QUEUE_ID] = { .type = NLA_U16 },
1290a2ff7ccSHangbin Liu [IFLA_BOND_SLAVE_PRIO] = { .type = NLA_S32 },
130cea6aeb6SJiri Pirko };
131cea6aeb6SJiri Pirko
bond_validate(struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)132a8b8a889SMatthias Schiffer static int bond_validate(struct nlattr *tb[], struct nlattr *data[],
133a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack)
1340a2a78c4SJiri Pirko {
1350a2a78c4SJiri Pirko if (tb[IFLA_ADDRESS]) {
1360a2a78c4SJiri Pirko if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1370a2a78c4SJiri Pirko return -EINVAL;
1380a2a78c4SJiri Pirko if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1390a2a78c4SJiri Pirko return -EADDRNOTAVAIL;
1400a2a78c4SJiri Pirko }
1410a2a78c4SJiri Pirko return 0;
1420a2a78c4SJiri Pirko }
1430a2a78c4SJiri Pirko
bond_slave_changelink(struct net_device * bond_dev,struct net_device * slave_dev,struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)1440f23124aSNikolay Aleksandrov static int bond_slave_changelink(struct net_device *bond_dev,
1450f23124aSNikolay Aleksandrov struct net_device *slave_dev,
14617dd0ec4SMatthias Schiffer struct nlattr *tb[], struct nlattr *data[],
14717dd0ec4SMatthias Schiffer struct netlink_ext_ack *extack)
1480f23124aSNikolay Aleksandrov {
1490f23124aSNikolay Aleksandrov struct bonding *bond = netdev_priv(bond_dev);
1500f23124aSNikolay Aleksandrov struct bond_opt_value newval;
1510f23124aSNikolay Aleksandrov int err;
1520f23124aSNikolay Aleksandrov
1530f23124aSNikolay Aleksandrov if (!data)
1540f23124aSNikolay Aleksandrov return 0;
1550f23124aSNikolay Aleksandrov
1560f23124aSNikolay Aleksandrov if (data[IFLA_BOND_SLAVE_QUEUE_ID]) {
1570f23124aSNikolay Aleksandrov u16 queue_id = nla_get_u16(data[IFLA_BOND_SLAVE_QUEUE_ID]);
1580f23124aSNikolay Aleksandrov char queue_id_str[IFNAMSIZ + 7];
1590f23124aSNikolay Aleksandrov
1600f23124aSNikolay Aleksandrov /* queue_id option setting expects slave_name:queue_id */
1610f23124aSNikolay Aleksandrov snprintf(queue_id_str, sizeof(queue_id_str), "%s:%u\n",
1620f23124aSNikolay Aleksandrov slave_dev->name, queue_id);
1630f23124aSNikolay Aleksandrov bond_opt_initstr(&newval, queue_id_str);
1642bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_QUEUE_ID, &newval,
1652bff369bSJonathan Toppins data[IFLA_BOND_SLAVE_QUEUE_ID], extack);
1660f23124aSNikolay Aleksandrov if (err)
1670f23124aSNikolay Aleksandrov return err;
1680f23124aSNikolay Aleksandrov }
1690f23124aSNikolay Aleksandrov
1700a2ff7ccSHangbin Liu if (data[IFLA_BOND_SLAVE_PRIO]) {
1710a2ff7ccSHangbin Liu int prio = nla_get_s32(data[IFLA_BOND_SLAVE_PRIO]);
1720a2ff7ccSHangbin Liu
1730a2ff7ccSHangbin Liu bond_opt_slave_initval(&newval, &slave_dev, prio);
1740a2ff7ccSHangbin Liu err = __bond_opt_set(bond, BOND_OPT_PRIO, &newval,
1750a2ff7ccSHangbin Liu data[IFLA_BOND_SLAVE_PRIO], extack);
1760a2ff7ccSHangbin Liu if (err)
1770a2ff7ccSHangbin Liu return err;
1780a2ff7ccSHangbin Liu }
1790a2ff7ccSHangbin Liu
1800f23124aSNikolay Aleksandrov return 0;
1810f23124aSNikolay Aleksandrov }
1820f23124aSNikolay Aleksandrov
bond_changelink(struct net_device * bond_dev,struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)183ad744b22SMatthias Schiffer static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
184ad744b22SMatthias Schiffer struct nlattr *data[],
185ad744b22SMatthias Schiffer struct netlink_ext_ack *extack)
18690af2311SJiri Pirko {
18790af2311SJiri Pirko struct bonding *bond = netdev_priv(bond_dev);
1882b3798d5SNikolay Aleksandrov struct bond_opt_value newval;
18906151dbcSsfeldma@cumulusnetworks.com int miimon = 0;
19090af2311SJiri Pirko int err;
19190af2311SJiri Pirko
192eecdaa6eSsfeldma@cumulusnetworks.com if (!data)
193eecdaa6eSsfeldma@cumulusnetworks.com return 0;
194eecdaa6eSsfeldma@cumulusnetworks.com
195eecdaa6eSsfeldma@cumulusnetworks.com if (data[IFLA_BOND_MODE]) {
19690af2311SJiri Pirko int mode = nla_get_u8(data[IFLA_BOND_MODE]);
19790af2311SJiri Pirko
1982b3798d5SNikolay Aleksandrov bond_opt_initval(&newval, mode);
1992bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_MODE, &newval,
2002bff369bSJonathan Toppins data[IFLA_BOND_MODE], extack);
20190af2311SJiri Pirko if (err)
20290af2311SJiri Pirko return err;
20390af2311SJiri Pirko }
204eecdaa6eSsfeldma@cumulusnetworks.com if (data[IFLA_BOND_ACTIVE_SLAVE]) {
205ec76aa49SJiri Pirko int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]);
206ec76aa49SJiri Pirko struct net_device *slave_dev;
207d1fbd3edSNikolay Aleksandrov char *active_slave = "";
208ec76aa49SJiri Pirko
209d1fbd3edSNikolay Aleksandrov if (ifindex != 0) {
210ec76aa49SJiri Pirko slave_dev = __dev_get_by_index(dev_net(bond_dev),
211ec76aa49SJiri Pirko ifindex);
212ec76aa49SJiri Pirko if (!slave_dev)
213ec76aa49SJiri Pirko return -ENODEV;
214d1fbd3edSNikolay Aleksandrov active_slave = slave_dev->name;
215ec76aa49SJiri Pirko }
216d1fbd3edSNikolay Aleksandrov bond_opt_initstr(&newval, active_slave);
2172bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval,
2182bff369bSJonathan Toppins data[IFLA_BOND_ACTIVE_SLAVE], extack);
219ec76aa49SJiri Pirko if (err)
220ec76aa49SJiri Pirko return err;
221ec76aa49SJiri Pirko }
222eecdaa6eSsfeldma@cumulusnetworks.com if (data[IFLA_BOND_MIIMON]) {
22306151dbcSsfeldma@cumulusnetworks.com miimon = nla_get_u32(data[IFLA_BOND_MIIMON]);
224eecdaa6eSsfeldma@cumulusnetworks.com
225b98d9c66SNikolay Aleksandrov bond_opt_initval(&newval, miimon);
2262bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_MIIMON, &newval,
2272bff369bSJonathan Toppins data[IFLA_BOND_MIIMON], extack);
228eecdaa6eSsfeldma@cumulusnetworks.com if (err)
229eecdaa6eSsfeldma@cumulusnetworks.com return err;
230eecdaa6eSsfeldma@cumulusnetworks.com }
23125852e29Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_UPDELAY]) {
23225852e29Ssfeldma@cumulusnetworks.com int updelay = nla_get_u32(data[IFLA_BOND_UPDELAY]);
23325852e29Ssfeldma@cumulusnetworks.com
234e4994612SNikolay Aleksandrov bond_opt_initval(&newval, updelay);
2352bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_UPDELAY, &newval,
2362bff369bSJonathan Toppins data[IFLA_BOND_UPDELAY], extack);
23725852e29Ssfeldma@cumulusnetworks.com if (err)
23825852e29Ssfeldma@cumulusnetworks.com return err;
23925852e29Ssfeldma@cumulusnetworks.com }
240c7461f9bSsfeldma@cumulusnetworks.com if (data[IFLA_BOND_DOWNDELAY]) {
241c7461f9bSsfeldma@cumulusnetworks.com int downdelay = nla_get_u32(data[IFLA_BOND_DOWNDELAY]);
242c7461f9bSsfeldma@cumulusnetworks.com
24325a9b54aSNikolay Aleksandrov bond_opt_initval(&newval, downdelay);
2442bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_DOWNDELAY, &newval,
2452bff369bSJonathan Toppins data[IFLA_BOND_DOWNDELAY], extack);
246c7461f9bSsfeldma@cumulusnetworks.com if (err)
247c7461f9bSsfeldma@cumulusnetworks.com return err;
248c7461f9bSsfeldma@cumulusnetworks.com }
24907a4ddecSVincent Bernat if (data[IFLA_BOND_PEER_NOTIF_DELAY]) {
25007a4ddecSVincent Bernat int delay = nla_get_u32(data[IFLA_BOND_PEER_NOTIF_DELAY]);
25107a4ddecSVincent Bernat
25207a4ddecSVincent Bernat bond_opt_initval(&newval, delay);
2532bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_PEER_NOTIF_DELAY, &newval,
2542bff369bSJonathan Toppins data[IFLA_BOND_PEER_NOTIF_DELAY], extack);
25507a4ddecSVincent Bernat if (err)
25607a4ddecSVincent Bernat return err;
25707a4ddecSVincent Bernat }
2589f53e14eSsfeldma@cumulusnetworks.com if (data[IFLA_BOND_USE_CARRIER]) {
2599f53e14eSsfeldma@cumulusnetworks.com int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]);
2609f53e14eSsfeldma@cumulusnetworks.com
2610fff0608SNikolay Aleksandrov bond_opt_initval(&newval, use_carrier);
2622bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_USE_CARRIER, &newval,
2632bff369bSJonathan Toppins data[IFLA_BOND_USE_CARRIER], extack);
2649f53e14eSsfeldma@cumulusnetworks.com if (err)
2659f53e14eSsfeldma@cumulusnetworks.com return err;
2669f53e14eSsfeldma@cumulusnetworks.com }
26706151dbcSsfeldma@cumulusnetworks.com if (data[IFLA_BOND_ARP_INTERVAL]) {
26806151dbcSsfeldma@cumulusnetworks.com int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]);
26906151dbcSsfeldma@cumulusnetworks.com
27006151dbcSsfeldma@cumulusnetworks.com if (arp_interval && miimon) {
2712bff369bSJonathan Toppins NL_SET_ERR_MSG_ATTR(extack, data[IFLA_BOND_ARP_INTERVAL],
2722bff369bSJonathan Toppins "ARP monitoring cannot be used with MII monitoring");
27306151dbcSsfeldma@cumulusnetworks.com return -EINVAL;
27406151dbcSsfeldma@cumulusnetworks.com }
27506151dbcSsfeldma@cumulusnetworks.com
2767bdb04edSNikolay Aleksandrov bond_opt_initval(&newval, arp_interval);
2772bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_ARP_INTERVAL, &newval,
2782bff369bSJonathan Toppins data[IFLA_BOND_ARP_INTERVAL], extack);
27906151dbcSsfeldma@cumulusnetworks.com if (err)
28006151dbcSsfeldma@cumulusnetworks.com return err;
28106151dbcSsfeldma@cumulusnetworks.com }
2827f28fa10Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_ARP_IP_TARGET]) {
2837f28fa10Ssfeldma@cumulusnetworks.com struct nlattr *attr;
2847f28fa10Ssfeldma@cumulusnetworks.com int i = 0, rem;
2857f28fa10Ssfeldma@cumulusnetworks.com
2864fb0ef58SNikolay Aleksandrov bond_option_arp_ip_targets_clear(bond);
2877f28fa10Ssfeldma@cumulusnetworks.com nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
288f6c6fda4SThomas Graf __be32 target;
289f6c6fda4SThomas Graf
290f6c6fda4SThomas Graf if (nla_len(attr) < sizeof(target))
291f6c6fda4SThomas Graf return -EINVAL;
292f6c6fda4SThomas Graf
293f6c6fda4SThomas Graf target = nla_get_be32(attr);
2947f28fa10Ssfeldma@cumulusnetworks.com
295a19a7ec8Sstephen hemminger bond_opt_initval(&newval, (__force u64)target);
2964fb0ef58SNikolay Aleksandrov err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
2972bff369bSJonathan Toppins &newval,
2982bff369bSJonathan Toppins data[IFLA_BOND_ARP_IP_TARGET],
2992bff369bSJonathan Toppins extack);
3004fb0ef58SNikolay Aleksandrov if (err)
3014fb0ef58SNikolay Aleksandrov break;
3024fb0ef58SNikolay Aleksandrov i++;
3034fb0ef58SNikolay Aleksandrov }
3044fb0ef58SNikolay Aleksandrov if (i == 0 && bond->params.arp_interval)
305a5f24542SVeaceslav Falico netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n");
3067f28fa10Ssfeldma@cumulusnetworks.com if (err)
3077f28fa10Ssfeldma@cumulusnetworks.com return err;
3087f28fa10Ssfeldma@cumulusnetworks.com }
309129e3c1bSHangbin Liu #if IS_ENABLED(CONFIG_IPV6)
310129e3c1bSHangbin Liu if (data[IFLA_BOND_NS_IP6_TARGET]) {
311129e3c1bSHangbin Liu struct nlattr *attr;
312129e3c1bSHangbin Liu int i = 0, rem;
313129e3c1bSHangbin Liu
314129e3c1bSHangbin Liu bond_option_ns_ip6_targets_clear(bond);
315129e3c1bSHangbin Liu nla_for_each_nested(attr, data[IFLA_BOND_NS_IP6_TARGET], rem) {
316129e3c1bSHangbin Liu struct in6_addr addr6;
317129e3c1bSHangbin Liu
318129e3c1bSHangbin Liu if (nla_len(attr) < sizeof(addr6)) {
319129e3c1bSHangbin Liu NL_SET_ERR_MSG(extack, "Invalid IPv6 address");
320129e3c1bSHangbin Liu return -EINVAL;
321129e3c1bSHangbin Liu }
322129e3c1bSHangbin Liu
323129e3c1bSHangbin Liu addr6 = nla_get_in6_addr(attr);
324129e3c1bSHangbin Liu
325129e3c1bSHangbin Liu bond_opt_initextra(&newval, &addr6, sizeof(addr6));
326129e3c1bSHangbin Liu err = __bond_opt_set(bond, BOND_OPT_NS_TARGETS,
3272bff369bSJonathan Toppins &newval,
3282bff369bSJonathan Toppins data[IFLA_BOND_NS_IP6_TARGET],
3292bff369bSJonathan Toppins extack);
330129e3c1bSHangbin Liu if (err)
331129e3c1bSHangbin Liu break;
332129e3c1bSHangbin Liu i++;
333129e3c1bSHangbin Liu }
334129e3c1bSHangbin Liu if (i == 0 && bond->params.arp_interval)
335129e3c1bSHangbin Liu netdev_warn(bond->dev, "Removing last ns target with arp_interval on\n");
336129e3c1bSHangbin Liu if (err)
337129e3c1bSHangbin Liu return err;
338129e3c1bSHangbin Liu }
339129e3c1bSHangbin Liu #endif
34029c49482Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_ARP_VALIDATE]) {
34129c49482Ssfeldma@cumulusnetworks.com int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]);
34229c49482Ssfeldma@cumulusnetworks.com
34329c49482Ssfeldma@cumulusnetworks.com if (arp_validate && miimon) {
3442bff369bSJonathan Toppins NL_SET_ERR_MSG_ATTR(extack, data[IFLA_BOND_ARP_INTERVAL],
3452bff369bSJonathan Toppins "ARP validating cannot be used with MII monitoring");
34629c49482Ssfeldma@cumulusnetworks.com return -EINVAL;
34729c49482Ssfeldma@cumulusnetworks.com }
34829c49482Ssfeldma@cumulusnetworks.com
34916228881SNikolay Aleksandrov bond_opt_initval(&newval, arp_validate);
3502bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_ARP_VALIDATE, &newval,
3512bff369bSJonathan Toppins data[IFLA_BOND_ARP_VALIDATE], extack);
35229c49482Ssfeldma@cumulusnetworks.com if (err)
35329c49482Ssfeldma@cumulusnetworks.com return err;
35429c49482Ssfeldma@cumulusnetworks.com }
355d5c84254Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_ARP_ALL_TARGETS]) {
356d5c84254Ssfeldma@cumulusnetworks.com int arp_all_targets =
357d5c84254Ssfeldma@cumulusnetworks.com nla_get_u32(data[IFLA_BOND_ARP_ALL_TARGETS]);
358d5c84254Ssfeldma@cumulusnetworks.com
359edf36b24SNikolay Aleksandrov bond_opt_initval(&newval, arp_all_targets);
3602bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_ARP_ALL_TARGETS, &newval,
3612bff369bSJonathan Toppins data[IFLA_BOND_ARP_ALL_TARGETS], extack);
362d5c84254Ssfeldma@cumulusnetworks.com if (err)
363d5c84254Ssfeldma@cumulusnetworks.com return err;
364d5c84254Ssfeldma@cumulusnetworks.com }
3650a98a0d1Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_PRIMARY]) {
3660a98a0d1Ssfeldma@cumulusnetworks.com int ifindex = nla_get_u32(data[IFLA_BOND_PRIMARY]);
3670a98a0d1Ssfeldma@cumulusnetworks.com struct net_device *dev;
3680a98a0d1Ssfeldma@cumulusnetworks.com char *primary = "";
3690a98a0d1Ssfeldma@cumulusnetworks.com
3700a98a0d1Ssfeldma@cumulusnetworks.com dev = __dev_get_by_index(dev_net(bond_dev), ifindex);
3710a98a0d1Ssfeldma@cumulusnetworks.com if (dev)
3720a98a0d1Ssfeldma@cumulusnetworks.com primary = dev->name;
3730a98a0d1Ssfeldma@cumulusnetworks.com
374180222f0SNikolay Aleksandrov bond_opt_initstr(&newval, primary);
3752bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_PRIMARY, &newval,
3762bff369bSJonathan Toppins data[IFLA_BOND_PRIMARY], extack);
3770a98a0d1Ssfeldma@cumulusnetworks.com if (err)
3780a98a0d1Ssfeldma@cumulusnetworks.com return err;
3790a98a0d1Ssfeldma@cumulusnetworks.com }
3808a41ae44Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_PRIMARY_RESELECT]) {
3818a41ae44Ssfeldma@cumulusnetworks.com int primary_reselect =
3828a41ae44Ssfeldma@cumulusnetworks.com nla_get_u8(data[IFLA_BOND_PRIMARY_RESELECT]);
3838a41ae44Ssfeldma@cumulusnetworks.com
384388d3a6dSNikolay Aleksandrov bond_opt_initval(&newval, primary_reselect);
3852bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_PRIMARY_RESELECT, &newval,
3862bff369bSJonathan Toppins data[IFLA_BOND_PRIMARY_RESELECT], extack);
3878a41ae44Ssfeldma@cumulusnetworks.com if (err)
3888a41ae44Ssfeldma@cumulusnetworks.com return err;
3898a41ae44Ssfeldma@cumulusnetworks.com }
39089901972Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_FAIL_OVER_MAC]) {
39189901972Ssfeldma@cumulusnetworks.com int fail_over_mac =
39289901972Ssfeldma@cumulusnetworks.com nla_get_u8(data[IFLA_BOND_FAIL_OVER_MAC]);
39389901972Ssfeldma@cumulusnetworks.com
3941df6b6aaSNikolay Aleksandrov bond_opt_initval(&newval, fail_over_mac);
3952bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_FAIL_OVER_MAC, &newval,
3962bff369bSJonathan Toppins data[IFLA_BOND_FAIL_OVER_MAC], extack);
39789901972Ssfeldma@cumulusnetworks.com if (err)
39889901972Ssfeldma@cumulusnetworks.com return err;
39989901972Ssfeldma@cumulusnetworks.com }
400f70161c6Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_XMIT_HASH_POLICY]) {
401f70161c6Ssfeldma@cumulusnetworks.com int xmit_hash_policy =
402f70161c6Ssfeldma@cumulusnetworks.com nla_get_u8(data[IFLA_BOND_XMIT_HASH_POLICY]);
403f70161c6Ssfeldma@cumulusnetworks.com
404a4b32ce7SNikolay Aleksandrov bond_opt_initval(&newval, xmit_hash_policy);
4052bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_XMIT_HASH, &newval,
4062bff369bSJonathan Toppins data[IFLA_BOND_XMIT_HASH_POLICY], extack);
407f70161c6Ssfeldma@cumulusnetworks.com if (err)
408f70161c6Ssfeldma@cumulusnetworks.com return err;
409f70161c6Ssfeldma@cumulusnetworks.com }
410d8838de7Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_RESEND_IGMP]) {
411d8838de7Ssfeldma@cumulusnetworks.com int resend_igmp =
412d8838de7Ssfeldma@cumulusnetworks.com nla_get_u32(data[IFLA_BOND_RESEND_IGMP]);
413d8838de7Ssfeldma@cumulusnetworks.com
414105c8fb6SNikolay Aleksandrov bond_opt_initval(&newval, resend_igmp);
4152bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_RESEND_IGMP, &newval,
4162bff369bSJonathan Toppins data[IFLA_BOND_RESEND_IGMP], extack);
417d8838de7Ssfeldma@cumulusnetworks.com if (err)
418d8838de7Ssfeldma@cumulusnetworks.com return err;
419d8838de7Ssfeldma@cumulusnetworks.com }
4202c9839c1Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_NUM_PEER_NOTIF]) {
4212c9839c1Ssfeldma@cumulusnetworks.com int num_peer_notif =
4222c9839c1Ssfeldma@cumulusnetworks.com nla_get_u8(data[IFLA_BOND_NUM_PEER_NOTIF]);
4232c9839c1Ssfeldma@cumulusnetworks.com
424ef56becbSNikolay Aleksandrov bond_opt_initval(&newval, num_peer_notif);
4252bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_NUM_PEER_NOTIF, &newval,
4262bff369bSJonathan Toppins data[IFLA_BOND_NUM_PEER_NOTIF], extack);
4272c9839c1Ssfeldma@cumulusnetworks.com if (err)
4282c9839c1Ssfeldma@cumulusnetworks.com return err;
4292c9839c1Ssfeldma@cumulusnetworks.com }
4301cc0b1e3Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_ALL_SLAVES_ACTIVE]) {
4311cc0b1e3Ssfeldma@cumulusnetworks.com int all_slaves_active =
4321cc0b1e3Ssfeldma@cumulusnetworks.com nla_get_u8(data[IFLA_BOND_ALL_SLAVES_ACTIVE]);
4331cc0b1e3Ssfeldma@cumulusnetworks.com
4343df01162SNikolay Aleksandrov bond_opt_initval(&newval, all_slaves_active);
4352bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_ALL_SLAVES_ACTIVE, &newval,
4362bff369bSJonathan Toppins data[IFLA_BOND_ALL_SLAVES_ACTIVE], extack);
4371cc0b1e3Ssfeldma@cumulusnetworks.com if (err)
4381cc0b1e3Ssfeldma@cumulusnetworks.com return err;
4391cc0b1e3Ssfeldma@cumulusnetworks.com }
4407d101008Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_MIN_LINKS]) {
4417d101008Ssfeldma@cumulusnetworks.com int min_links =
4427d101008Ssfeldma@cumulusnetworks.com nla_get_u32(data[IFLA_BOND_MIN_LINKS]);
4437d101008Ssfeldma@cumulusnetworks.com
444633ddc9eSNikolay Aleksandrov bond_opt_initval(&newval, min_links);
4452bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_MINLINKS, &newval,
4462bff369bSJonathan Toppins data[IFLA_BOND_MIN_LINKS], extack);
4477d101008Ssfeldma@cumulusnetworks.com if (err)
4487d101008Ssfeldma@cumulusnetworks.com return err;
4497d101008Ssfeldma@cumulusnetworks.com }
4508d836d09Ssfeldma@cumulusnetworks.com if (data[IFLA_BOND_LP_INTERVAL]) {
4518d836d09Ssfeldma@cumulusnetworks.com int lp_interval =
4528d836d09Ssfeldma@cumulusnetworks.com nla_get_u32(data[IFLA_BOND_LP_INTERVAL]);
4538d836d09Ssfeldma@cumulusnetworks.com
4544325b374SNikolay Aleksandrov bond_opt_initval(&newval, lp_interval);
4552bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_LP_INTERVAL, &newval,
4562bff369bSJonathan Toppins data[IFLA_BOND_LP_INTERVAL], extack);
4578d836d09Ssfeldma@cumulusnetworks.com if (err)
4588d836d09Ssfeldma@cumulusnetworks.com return err;
4598d836d09Ssfeldma@cumulusnetworks.com }
460c13ab3ffSsfeldma@cumulusnetworks.com if (data[IFLA_BOND_PACKETS_PER_SLAVE]) {
461c13ab3ffSsfeldma@cumulusnetworks.com int packets_per_slave =
462c13ab3ffSsfeldma@cumulusnetworks.com nla_get_u32(data[IFLA_BOND_PACKETS_PER_SLAVE]);
463c13ab3ffSsfeldma@cumulusnetworks.com
464aa59d851SNikolay Aleksandrov bond_opt_initval(&newval, packets_per_slave);
4652bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_PACKETS_PER_SLAVE, &newval,
4662bff369bSJonathan Toppins data[IFLA_BOND_PACKETS_PER_SLAVE], extack);
467c13ab3ffSsfeldma@cumulusnetworks.com if (err)
468c13ab3ffSsfeldma@cumulusnetworks.com return err;
469c13ab3ffSsfeldma@cumulusnetworks.com }
4703a755cd8SHangbin Liu
4713a755cd8SHangbin Liu if (data[IFLA_BOND_AD_LACP_ACTIVE]) {
4723a755cd8SHangbin Liu int lacp_active = nla_get_u8(data[IFLA_BOND_AD_LACP_ACTIVE]);
4733a755cd8SHangbin Liu
4743a755cd8SHangbin Liu bond_opt_initval(&newval, lacp_active);
4752bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_LACP_ACTIVE, &newval,
4762bff369bSJonathan Toppins data[IFLA_BOND_AD_LACP_ACTIVE], extack);
4773a755cd8SHangbin Liu if (err)
4783a755cd8SHangbin Liu return err;
4793a755cd8SHangbin Liu }
4803a755cd8SHangbin Liu
481998e40bbSsfeldma@cumulusnetworks.com if (data[IFLA_BOND_AD_LACP_RATE]) {
482998e40bbSsfeldma@cumulusnetworks.com int lacp_rate =
483998e40bbSsfeldma@cumulusnetworks.com nla_get_u8(data[IFLA_BOND_AD_LACP_RATE]);
484998e40bbSsfeldma@cumulusnetworks.com
485d3131de7SNikolay Aleksandrov bond_opt_initval(&newval, lacp_rate);
4862bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_LACP_RATE, &newval,
4872bff369bSJonathan Toppins data[IFLA_BOND_AD_LACP_RATE], extack);
488998e40bbSsfeldma@cumulusnetworks.com if (err)
489998e40bbSsfeldma@cumulusnetworks.com return err;
490998e40bbSsfeldma@cumulusnetworks.com }
491ec029facSsfeldma@cumulusnetworks.com if (data[IFLA_BOND_AD_SELECT]) {
492ec029facSsfeldma@cumulusnetworks.com int ad_select =
493ec029facSsfeldma@cumulusnetworks.com nla_get_u8(data[IFLA_BOND_AD_SELECT]);
494ec029facSsfeldma@cumulusnetworks.com
4959e5f5eebSNikolay Aleksandrov bond_opt_initval(&newval, ad_select);
4962bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_AD_SELECT, &newval,
4972bff369bSJonathan Toppins data[IFLA_BOND_AD_SELECT], extack);
498ec029facSsfeldma@cumulusnetworks.com if (err)
499ec029facSsfeldma@cumulusnetworks.com return err;
500ec029facSsfeldma@cumulusnetworks.com }
501171a42c3SAndy Gospodarek if (data[IFLA_BOND_AD_ACTOR_SYS_PRIO]) {
502171a42c3SAndy Gospodarek int actor_sys_prio =
503171a42c3SAndy Gospodarek nla_get_u16(data[IFLA_BOND_AD_ACTOR_SYS_PRIO]);
504171a42c3SAndy Gospodarek
505171a42c3SAndy Gospodarek bond_opt_initval(&newval, actor_sys_prio);
5062bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYS_PRIO, &newval,
5072bff369bSJonathan Toppins data[IFLA_BOND_AD_ACTOR_SYS_PRIO], extack);
508171a42c3SAndy Gospodarek if (err)
509171a42c3SAndy Gospodarek return err;
510171a42c3SAndy Gospodarek }
511171a42c3SAndy Gospodarek if (data[IFLA_BOND_AD_USER_PORT_KEY]) {
512171a42c3SAndy Gospodarek int port_key =
513171a42c3SAndy Gospodarek nla_get_u16(data[IFLA_BOND_AD_USER_PORT_KEY]);
514171a42c3SAndy Gospodarek
515171a42c3SAndy Gospodarek bond_opt_initval(&newval, port_key);
5162bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_AD_USER_PORT_KEY, &newval,
5172bff369bSJonathan Toppins data[IFLA_BOND_AD_USER_PORT_KEY], extack);
518171a42c3SAndy Gospodarek if (err)
519171a42c3SAndy Gospodarek return err;
520171a42c3SAndy Gospodarek }
521171a42c3SAndy Gospodarek if (data[IFLA_BOND_AD_ACTOR_SYSTEM]) {
522171a42c3SAndy Gospodarek if (nla_len(data[IFLA_BOND_AD_ACTOR_SYSTEM]) != ETH_ALEN)
523171a42c3SAndy Gospodarek return -EINVAL;
524171a42c3SAndy Gospodarek
525171a42c3SAndy Gospodarek bond_opt_initval(&newval,
5265eb3d22aSXin Long nla_get_u64(data[IFLA_BOND_AD_ACTOR_SYSTEM]));
5272bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYSTEM, &newval,
5282bff369bSJonathan Toppins data[IFLA_BOND_AD_ACTOR_SYSTEM], extack);
529171a42c3SAndy Gospodarek if (err)
530171a42c3SAndy Gospodarek return err;
531171a42c3SAndy Gospodarek }
5320f7bffd9SNikolay Aleksandrov if (data[IFLA_BOND_TLB_DYNAMIC_LB]) {
5330f7bffd9SNikolay Aleksandrov int dynamic_lb = nla_get_u8(data[IFLA_BOND_TLB_DYNAMIC_LB]);
5340f7bffd9SNikolay Aleksandrov
5350f7bffd9SNikolay Aleksandrov bond_opt_initval(&newval, dynamic_lb);
5362bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_TLB_DYNAMIC_LB, &newval,
5372bff369bSJonathan Toppins data[IFLA_BOND_TLB_DYNAMIC_LB], extack);
5380f7bffd9SNikolay Aleksandrov if (err)
5390f7bffd9SNikolay Aleksandrov return err;
5400f7bffd9SNikolay Aleksandrov }
5410f7bffd9SNikolay Aleksandrov
5425944b5abSHangbin Liu if (data[IFLA_BOND_MISSED_MAX]) {
5435944b5abSHangbin Liu int missed_max = nla_get_u8(data[IFLA_BOND_MISSED_MAX]);
5445944b5abSHangbin Liu
5455944b5abSHangbin Liu bond_opt_initval(&newval, missed_max);
5462bff369bSJonathan Toppins err = __bond_opt_set(bond, BOND_OPT_MISSED_MAX, &newval,
5472bff369bSJonathan Toppins data[IFLA_BOND_MISSED_MAX], extack);
5485944b5abSHangbin Liu if (err)
5495944b5abSHangbin Liu return err;
5505944b5abSHangbin Liu }
5515944b5abSHangbin Liu
55290af2311SJiri Pirko return 0;
55390af2311SJiri Pirko }
55490af2311SJiri Pirko
bond_newlink(struct net * src_net,struct net_device * bond_dev,struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)55590af2311SJiri Pirko static int bond_newlink(struct net *src_net, struct net_device *bond_dev,
5567a3f4a18SMatthias Schiffer struct nlattr *tb[], struct nlattr *data[],
5577a3f4a18SMatthias Schiffer struct netlink_ext_ack *extack)
55890af2311SJiri Pirko {
55990af2311SJiri Pirko int err;
56090af2311SJiri Pirko
561ad744b22SMatthias Schiffer err = bond_changelink(bond_dev, tb, data, extack);
56290af2311SJiri Pirko if (err < 0)
56390af2311SJiri Pirko return err;
56490af2311SJiri Pirko
565005db31dSBeniamino Galvani err = register_netdevice(bond_dev);
566ea8ffc08SMahesh Bandewar if (!err) {
567ea8ffc08SMahesh Bandewar struct bonding *bond = netdev_priv(bond_dev);
568ea8ffc08SMahesh Bandewar
569c75d1d52SCong Wang netif_carrier_off(bond_dev);
570ea8ffc08SMahesh Bandewar bond_work_init_all(bond);
571ea8ffc08SMahesh Bandewar }
572005db31dSBeniamino Galvani
573005db31dSBeniamino Galvani return err;
57490af2311SJiri Pirko }
57590af2311SJiri Pirko
bond_get_size(const struct net_device * bond_dev)57690af2311SJiri Pirko static size_t bond_get_size(const struct net_device *bond_dev)
57790af2311SJiri Pirko {
578e139862eSDan Carpenter return nla_total_size(sizeof(u8)) + /* IFLA_BOND_MODE */
579eecdaa6eSsfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_ACTIVE_SLAVE */
580eecdaa6eSsfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIIMON */
58125852e29Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_UPDELAY */
582c7461f9bSsfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_DOWNDELAY */
5839f53e14eSsfeldma@cumulusnetworks.com nla_total_size(sizeof(u8)) + /* IFLA_BOND_USE_CARRIER */
58406151dbcSsfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_INTERVAL */
5857f28fa10Ssfeldma@cumulusnetworks.com /* IFLA_BOND_ARP_IP_TARGET */
586288db0aaSsfeldma@cumulusnetworks.com nla_total_size(sizeof(struct nlattr)) +
5877f28fa10Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) * BOND_MAX_ARP_TARGETS +
58829c49482Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_VALIDATE */
589d5c84254Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_ALL_TARGETS */
5900a98a0d1Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_PRIMARY */
5918a41ae44Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u8)) + /* IFLA_BOND_PRIMARY_RESELECT */
59289901972Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u8)) + /* IFLA_BOND_FAIL_OVER_MAC */
593f70161c6Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u8)) + /* IFLA_BOND_XMIT_HASH_POLICY */
594d8838de7Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_RESEND_IGMP */
5952c9839c1Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u8)) + /* IFLA_BOND_NUM_PEER_NOTIF */
5961cc0b1e3Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u8)) + /* IFLA_BOND_ALL_SLAVES_ACTIVE */
5977d101008Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIN_LINKS */
5988d836d09Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_LP_INTERVAL */
599c13ab3ffSsfeldma@cumulusnetworks.com nla_total_size(sizeof(u32)) + /* IFLA_BOND_PACKETS_PER_SLAVE */
6003a755cd8SHangbin Liu nla_total_size(sizeof(u8)) + /* IFLA_BOND_AD_LACP_ACTIVE */
601998e40bbSsfeldma@cumulusnetworks.com nla_total_size(sizeof(u8)) + /* IFLA_BOND_AD_LACP_RATE */
602ec029facSsfeldma@cumulusnetworks.com nla_total_size(sizeof(u8)) + /* IFLA_BOND_AD_SELECT */
6034ee7ac75Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(struct nlattr)) + /* IFLA_BOND_AD_INFO */
6044ee7ac75Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_AGGREGATOR */
6054ee7ac75Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_NUM_PORTS */
6064ee7ac75Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_ACTOR_KEY */
6074ee7ac75Ssfeldma@cumulusnetworks.com nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_INFO_PARTNER_KEY*/
6084ee7ac75Ssfeldma@cumulusnetworks.com nla_total_size(ETH_ALEN) + /* IFLA_BOND_AD_INFO_PARTNER_MAC*/
609171a42c3SAndy Gospodarek nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_ACTOR_SYS_PRIO */
610171a42c3SAndy Gospodarek nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_USER_PORT_KEY */
611171a42c3SAndy Gospodarek nla_total_size(ETH_ALEN) + /* IFLA_BOND_AD_ACTOR_SYSTEM */
6120f7bffd9SNikolay Aleksandrov nla_total_size(sizeof(u8)) + /* IFLA_BOND_TLB_DYNAMIC_LB */
61307a4ddecSVincent Bernat nla_total_size(sizeof(u32)) + /* IFLA_BOND_PEER_NOTIF_DELAY */
6145944b5abSHangbin Liu nla_total_size(sizeof(u8)) + /* IFLA_BOND_MISSED_MAX */
615129e3c1bSHangbin Liu /* IFLA_BOND_NS_IP6_TARGET */
616129e3c1bSHangbin Liu nla_total_size(sizeof(struct nlattr)) +
617129e3c1bSHangbin Liu nla_total_size(sizeof(struct in6_addr)) * BOND_MAX_NS_TARGETS +
618eecdaa6eSsfeldma@cumulusnetworks.com 0;
61990af2311SJiri Pirko }
62090af2311SJiri Pirko
bond_option_active_slave_get_ifindex(struct bonding * bond)621e965f804SEric Dumazet static int bond_option_active_slave_get_ifindex(struct bonding *bond)
622e965f804SEric Dumazet {
623e965f804SEric Dumazet const struct net_device *slave;
624e965f804SEric Dumazet int ifindex;
625e965f804SEric Dumazet
626e965f804SEric Dumazet rcu_read_lock();
627e965f804SEric Dumazet slave = bond_option_active_slave_get_rcu(bond);
628e965f804SEric Dumazet ifindex = slave ? slave->ifindex : 0;
629e965f804SEric Dumazet rcu_read_unlock();
630e965f804SEric Dumazet return ifindex;
631e965f804SEric Dumazet }
632e965f804SEric Dumazet
bond_fill_info(struct sk_buff * skb,const struct net_device * bond_dev)63390af2311SJiri Pirko static int bond_fill_info(struct sk_buff *skb,
63490af2311SJiri Pirko const struct net_device *bond_dev)
63590af2311SJiri Pirko {
63690af2311SJiri Pirko struct bonding *bond = netdev_priv(bond_dev);
637c13ab3ffSsfeldma@cumulusnetworks.com unsigned int packets_per_slave;
638e965f804SEric Dumazet int ifindex, i, targets_added;
639e965f804SEric Dumazet struct nlattr *targets;
640059b47e8SNikolay Aleksandrov struct slave *primary;
64190af2311SJiri Pirko
64201844098SVeaceslav Falico if (nla_put_u8(skb, IFLA_BOND_MODE, BOND_MODE(bond)))
64390af2311SJiri Pirko goto nla_put_failure;
644eecdaa6eSsfeldma@cumulusnetworks.com
645e965f804SEric Dumazet ifindex = bond_option_active_slave_get_ifindex(bond);
646e965f804SEric Dumazet if (ifindex && nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, ifindex))
647eecdaa6eSsfeldma@cumulusnetworks.com goto nla_put_failure;
648eecdaa6eSsfeldma@cumulusnetworks.com
649eecdaa6eSsfeldma@cumulusnetworks.com if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon))
650eecdaa6eSsfeldma@cumulusnetworks.com goto nla_put_failure;
651eecdaa6eSsfeldma@cumulusnetworks.com
65225852e29Ssfeldma@cumulusnetworks.com if (nla_put_u32(skb, IFLA_BOND_UPDELAY,
65325852e29Ssfeldma@cumulusnetworks.com bond->params.updelay * bond->params.miimon))
65425852e29Ssfeldma@cumulusnetworks.com goto nla_put_failure;
65525852e29Ssfeldma@cumulusnetworks.com
656c7461f9bSsfeldma@cumulusnetworks.com if (nla_put_u32(skb, IFLA_BOND_DOWNDELAY,
657c7461f9bSsfeldma@cumulusnetworks.com bond->params.downdelay * bond->params.miimon))
658c7461f9bSsfeldma@cumulusnetworks.com goto nla_put_failure;
659c7461f9bSsfeldma@cumulusnetworks.com
66007a4ddecSVincent Bernat if (nla_put_u32(skb, IFLA_BOND_PEER_NOTIF_DELAY,
661ee4f56f4SVincent Bernat bond->params.peer_notif_delay * bond->params.miimon))
66207a4ddecSVincent Bernat goto nla_put_failure;
66307a4ddecSVincent Bernat
6649f53e14eSsfeldma@cumulusnetworks.com if (nla_put_u8(skb, IFLA_BOND_USE_CARRIER, bond->params.use_carrier))
6659f53e14eSsfeldma@cumulusnetworks.com goto nla_put_failure;
6669f53e14eSsfeldma@cumulusnetworks.com
66706151dbcSsfeldma@cumulusnetworks.com if (nla_put_u32(skb, IFLA_BOND_ARP_INTERVAL, bond->params.arp_interval))
66806151dbcSsfeldma@cumulusnetworks.com goto nla_put_failure;
66906151dbcSsfeldma@cumulusnetworks.com
670ae0be8deSMichal Kubecek targets = nla_nest_start_noflag(skb, IFLA_BOND_ARP_IP_TARGET);
6717f28fa10Ssfeldma@cumulusnetworks.com if (!targets)
6727f28fa10Ssfeldma@cumulusnetworks.com goto nla_put_failure;
6737f28fa10Ssfeldma@cumulusnetworks.com
6747f28fa10Ssfeldma@cumulusnetworks.com targets_added = 0;
6757f28fa10Ssfeldma@cumulusnetworks.com for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
6767f28fa10Ssfeldma@cumulusnetworks.com if (bond->params.arp_targets[i]) {
677d62844a8SHangbin Liu if (nla_put_be32(skb, i, bond->params.arp_targets[i]))
678d62844a8SHangbin Liu goto nla_put_failure;
6797f28fa10Ssfeldma@cumulusnetworks.com targets_added = 1;
6807f28fa10Ssfeldma@cumulusnetworks.com }
6817f28fa10Ssfeldma@cumulusnetworks.com }
6827f28fa10Ssfeldma@cumulusnetworks.com
6837f28fa10Ssfeldma@cumulusnetworks.com if (targets_added)
6847f28fa10Ssfeldma@cumulusnetworks.com nla_nest_end(skb, targets);
6857f28fa10Ssfeldma@cumulusnetworks.com else
6867f28fa10Ssfeldma@cumulusnetworks.com nla_nest_cancel(skb, targets);
6877f28fa10Ssfeldma@cumulusnetworks.com
68829c49482Ssfeldma@cumulusnetworks.com if (nla_put_u32(skb, IFLA_BOND_ARP_VALIDATE, bond->params.arp_validate))
68929c49482Ssfeldma@cumulusnetworks.com goto nla_put_failure;
69029c49482Ssfeldma@cumulusnetworks.com
691d5c84254Ssfeldma@cumulusnetworks.com if (nla_put_u32(skb, IFLA_BOND_ARP_ALL_TARGETS,
692d5c84254Ssfeldma@cumulusnetworks.com bond->params.arp_all_targets))
693d5c84254Ssfeldma@cumulusnetworks.com goto nla_put_failure;
694d5c84254Ssfeldma@cumulusnetworks.com
695129e3c1bSHangbin Liu #if IS_ENABLED(CONFIG_IPV6)
696129e3c1bSHangbin Liu targets = nla_nest_start(skb, IFLA_BOND_NS_IP6_TARGET);
697129e3c1bSHangbin Liu if (!targets)
698129e3c1bSHangbin Liu goto nla_put_failure;
699129e3c1bSHangbin Liu
700129e3c1bSHangbin Liu targets_added = 0;
701129e3c1bSHangbin Liu for (i = 0; i < BOND_MAX_NS_TARGETS; i++) {
702129e3c1bSHangbin Liu if (!ipv6_addr_any(&bond->params.ns_targets[i])) {
703129e3c1bSHangbin Liu if (nla_put_in6_addr(skb, i, &bond->params.ns_targets[i]))
704129e3c1bSHangbin Liu goto nla_put_failure;
705129e3c1bSHangbin Liu targets_added = 1;
706129e3c1bSHangbin Liu }
707129e3c1bSHangbin Liu }
708129e3c1bSHangbin Liu
709129e3c1bSHangbin Liu if (targets_added)
710129e3c1bSHangbin Liu nla_nest_end(skb, targets);
711129e3c1bSHangbin Liu else
712129e3c1bSHangbin Liu nla_nest_cancel(skb, targets);
713129e3c1bSHangbin Liu #endif
714129e3c1bSHangbin Liu
715059b47e8SNikolay Aleksandrov primary = rtnl_dereference(bond->primary_slave);
716059b47e8SNikolay Aleksandrov if (primary &&
717059b47e8SNikolay Aleksandrov nla_put_u32(skb, IFLA_BOND_PRIMARY, primary->dev->ifindex))
7180a98a0d1Ssfeldma@cumulusnetworks.com goto nla_put_failure;
7190a98a0d1Ssfeldma@cumulusnetworks.com
7208a41ae44Ssfeldma@cumulusnetworks.com if (nla_put_u8(skb, IFLA_BOND_PRIMARY_RESELECT,
7218a41ae44Ssfeldma@cumulusnetworks.com bond->params.primary_reselect))
7228a41ae44Ssfeldma@cumulusnetworks.com goto nla_put_failure;
7238a41ae44Ssfeldma@cumulusnetworks.com
72489901972Ssfeldma@cumulusnetworks.com if (nla_put_u8(skb, IFLA_BOND_FAIL_OVER_MAC,
72589901972Ssfeldma@cumulusnetworks.com bond->params.fail_over_mac))
72689901972Ssfeldma@cumulusnetworks.com goto nla_put_failure;
72789901972Ssfeldma@cumulusnetworks.com
728f70161c6Ssfeldma@cumulusnetworks.com if (nla_put_u8(skb, IFLA_BOND_XMIT_HASH_POLICY,
729f70161c6Ssfeldma@cumulusnetworks.com bond->params.xmit_policy))
730f70161c6Ssfeldma@cumulusnetworks.com goto nla_put_failure;
731f70161c6Ssfeldma@cumulusnetworks.com
732d8838de7Ssfeldma@cumulusnetworks.com if (nla_put_u32(skb, IFLA_BOND_RESEND_IGMP,
733d8838de7Ssfeldma@cumulusnetworks.com bond->params.resend_igmp))
734d8838de7Ssfeldma@cumulusnetworks.com goto nla_put_failure;
735d8838de7Ssfeldma@cumulusnetworks.com
7362c9839c1Ssfeldma@cumulusnetworks.com if (nla_put_u8(skb, IFLA_BOND_NUM_PEER_NOTIF,
7372c9839c1Ssfeldma@cumulusnetworks.com bond->params.num_peer_notif))
7382c9839c1Ssfeldma@cumulusnetworks.com goto nla_put_failure;
7392c9839c1Ssfeldma@cumulusnetworks.com
7401cc0b1e3Ssfeldma@cumulusnetworks.com if (nla_put_u8(skb, IFLA_BOND_ALL_SLAVES_ACTIVE,
7411cc0b1e3Ssfeldma@cumulusnetworks.com bond->params.all_slaves_active))
7421cc0b1e3Ssfeldma@cumulusnetworks.com goto nla_put_failure;
7431cc0b1e3Ssfeldma@cumulusnetworks.com
7447d101008Ssfeldma@cumulusnetworks.com if (nla_put_u32(skb, IFLA_BOND_MIN_LINKS,
7457d101008Ssfeldma@cumulusnetworks.com bond->params.min_links))
7467d101008Ssfeldma@cumulusnetworks.com goto nla_put_failure;
7477d101008Ssfeldma@cumulusnetworks.com
7488d836d09Ssfeldma@cumulusnetworks.com if (nla_put_u32(skb, IFLA_BOND_LP_INTERVAL,
7498d836d09Ssfeldma@cumulusnetworks.com bond->params.lp_interval))
7508d836d09Ssfeldma@cumulusnetworks.com goto nla_put_failure;
7518d836d09Ssfeldma@cumulusnetworks.com
752c13ab3ffSsfeldma@cumulusnetworks.com packets_per_slave = bond->params.packets_per_slave;
753c13ab3ffSsfeldma@cumulusnetworks.com if (nla_put_u32(skb, IFLA_BOND_PACKETS_PER_SLAVE,
754c13ab3ffSsfeldma@cumulusnetworks.com packets_per_slave))
755c13ab3ffSsfeldma@cumulusnetworks.com goto nla_put_failure;
756c13ab3ffSsfeldma@cumulusnetworks.com
7573a755cd8SHangbin Liu if (nla_put_u8(skb, IFLA_BOND_AD_LACP_ACTIVE,
7583a755cd8SHangbin Liu bond->params.lacp_active))
7593a755cd8SHangbin Liu goto nla_put_failure;
7603a755cd8SHangbin Liu
761998e40bbSsfeldma@cumulusnetworks.com if (nla_put_u8(skb, IFLA_BOND_AD_LACP_RATE,
762998e40bbSsfeldma@cumulusnetworks.com bond->params.lacp_fast))
763998e40bbSsfeldma@cumulusnetworks.com goto nla_put_failure;
764998e40bbSsfeldma@cumulusnetworks.com
765ec029facSsfeldma@cumulusnetworks.com if (nla_put_u8(skb, IFLA_BOND_AD_SELECT,
766ec029facSsfeldma@cumulusnetworks.com bond->params.ad_select))
767ec029facSsfeldma@cumulusnetworks.com goto nla_put_failure;
768ec029facSsfeldma@cumulusnetworks.com
7690f7bffd9SNikolay Aleksandrov if (nla_put_u8(skb, IFLA_BOND_TLB_DYNAMIC_LB,
7700f7bffd9SNikolay Aleksandrov bond->params.tlb_dynamic_lb))
7710f7bffd9SNikolay Aleksandrov goto nla_put_failure;
7720f7bffd9SNikolay Aleksandrov
7735944b5abSHangbin Liu if (nla_put_u8(skb, IFLA_BOND_MISSED_MAX,
7745944b5abSHangbin Liu bond->params.missed_max))
7755944b5abSHangbin Liu goto nla_put_failure;
7765944b5abSHangbin Liu
77701844098SVeaceslav Falico if (BOND_MODE(bond) == BOND_MODE_8023AD) {
7784ee7ac75Ssfeldma@cumulusnetworks.com struct ad_info info;
7794ee7ac75Ssfeldma@cumulusnetworks.com
7804cd6b475SMahesh Bandewar if (capable(CAP_NET_ADMIN)) {
781171a42c3SAndy Gospodarek if (nla_put_u16(skb, IFLA_BOND_AD_ACTOR_SYS_PRIO,
782171a42c3SAndy Gospodarek bond->params.ad_actor_sys_prio))
783171a42c3SAndy Gospodarek goto nla_put_failure;
784171a42c3SAndy Gospodarek
785171a42c3SAndy Gospodarek if (nla_put_u16(skb, IFLA_BOND_AD_USER_PORT_KEY,
786171a42c3SAndy Gospodarek bond->params.ad_user_port_key))
787171a42c3SAndy Gospodarek goto nla_put_failure;
788171a42c3SAndy Gospodarek
789171a42c3SAndy Gospodarek if (nla_put(skb, IFLA_BOND_AD_ACTOR_SYSTEM,
790414dd6fbSTobias Jungel ETH_ALEN, &bond->params.ad_actor_system))
791171a42c3SAndy Gospodarek goto nla_put_failure;
7924cd6b475SMahesh Bandewar }
7934ee7ac75Ssfeldma@cumulusnetworks.com if (!bond_3ad_get_active_agg_info(bond, &info)) {
7944ee7ac75Ssfeldma@cumulusnetworks.com struct nlattr *nest;
7954ee7ac75Ssfeldma@cumulusnetworks.com
796ae0be8deSMichal Kubecek nest = nla_nest_start_noflag(skb, IFLA_BOND_AD_INFO);
7974ee7ac75Ssfeldma@cumulusnetworks.com if (!nest)
7984ee7ac75Ssfeldma@cumulusnetworks.com goto nla_put_failure;
7994ee7ac75Ssfeldma@cumulusnetworks.com
8004ee7ac75Ssfeldma@cumulusnetworks.com if (nla_put_u16(skb, IFLA_BOND_AD_INFO_AGGREGATOR,
8014ee7ac75Ssfeldma@cumulusnetworks.com info.aggregator_id))
8024ee7ac75Ssfeldma@cumulusnetworks.com goto nla_put_failure;
8034ee7ac75Ssfeldma@cumulusnetworks.com if (nla_put_u16(skb, IFLA_BOND_AD_INFO_NUM_PORTS,
8044ee7ac75Ssfeldma@cumulusnetworks.com info.ports))
8054ee7ac75Ssfeldma@cumulusnetworks.com goto nla_put_failure;
8064ee7ac75Ssfeldma@cumulusnetworks.com if (nla_put_u16(skb, IFLA_BOND_AD_INFO_ACTOR_KEY,
8074ee7ac75Ssfeldma@cumulusnetworks.com info.actor_key))
8084ee7ac75Ssfeldma@cumulusnetworks.com goto nla_put_failure;
8094ee7ac75Ssfeldma@cumulusnetworks.com if (nla_put_u16(skb, IFLA_BOND_AD_INFO_PARTNER_KEY,
8104ee7ac75Ssfeldma@cumulusnetworks.com info.partner_key))
8114ee7ac75Ssfeldma@cumulusnetworks.com goto nla_put_failure;
8124ee7ac75Ssfeldma@cumulusnetworks.com if (nla_put(skb, IFLA_BOND_AD_INFO_PARTNER_MAC,
8134ee7ac75Ssfeldma@cumulusnetworks.com sizeof(info.partner_system),
8144ee7ac75Ssfeldma@cumulusnetworks.com &info.partner_system))
8154ee7ac75Ssfeldma@cumulusnetworks.com goto nla_put_failure;
8164ee7ac75Ssfeldma@cumulusnetworks.com
8174ee7ac75Ssfeldma@cumulusnetworks.com nla_nest_end(skb, nest);
8184ee7ac75Ssfeldma@cumulusnetworks.com }
8194ee7ac75Ssfeldma@cumulusnetworks.com }
8204ee7ac75Ssfeldma@cumulusnetworks.com
82190af2311SJiri Pirko return 0;
82290af2311SJiri Pirko
82390af2311SJiri Pirko nla_put_failure:
82490af2311SJiri Pirko return -EMSGSIZE;
82590af2311SJiri Pirko }
82690af2311SJiri Pirko
bond_get_linkxstats_size(const struct net_device * dev,int attr)827a258aeacSNikolay Aleksandrov static size_t bond_get_linkxstats_size(const struct net_device *dev, int attr)
828a258aeacSNikolay Aleksandrov {
829a258aeacSNikolay Aleksandrov switch (attr) {
830a258aeacSNikolay Aleksandrov case IFLA_STATS_LINK_XSTATS:
831a258aeacSNikolay Aleksandrov case IFLA_STATS_LINK_XSTATS_SLAVE:
832a258aeacSNikolay Aleksandrov break;
833a258aeacSNikolay Aleksandrov default:
834a258aeacSNikolay Aleksandrov return 0;
835a258aeacSNikolay Aleksandrov }
836a258aeacSNikolay Aleksandrov
837a258aeacSNikolay Aleksandrov return bond_3ad_stats_size() + nla_total_size(0);
838a258aeacSNikolay Aleksandrov }
839a258aeacSNikolay Aleksandrov
bond_fill_linkxstats(struct sk_buff * skb,const struct net_device * dev,int * prividx,int attr)840a258aeacSNikolay Aleksandrov static int bond_fill_linkxstats(struct sk_buff *skb,
841a258aeacSNikolay Aleksandrov const struct net_device *dev,
842a258aeacSNikolay Aleksandrov int *prividx, int attr)
843a258aeacSNikolay Aleksandrov {
844a258aeacSNikolay Aleksandrov struct nlattr *nla __maybe_unused;
845a258aeacSNikolay Aleksandrov struct slave *slave = NULL;
846a258aeacSNikolay Aleksandrov struct nlattr *nest, *nest2;
847a258aeacSNikolay Aleksandrov struct bonding *bond;
848a258aeacSNikolay Aleksandrov
849a258aeacSNikolay Aleksandrov switch (attr) {
850a258aeacSNikolay Aleksandrov case IFLA_STATS_LINK_XSTATS:
851a258aeacSNikolay Aleksandrov bond = netdev_priv(dev);
852a258aeacSNikolay Aleksandrov break;
853a258aeacSNikolay Aleksandrov case IFLA_STATS_LINK_XSTATS_SLAVE:
854a258aeacSNikolay Aleksandrov slave = bond_slave_get_rtnl(dev);
855a258aeacSNikolay Aleksandrov if (!slave)
856a258aeacSNikolay Aleksandrov return 0;
857a258aeacSNikolay Aleksandrov bond = slave->bond;
858a258aeacSNikolay Aleksandrov break;
859a258aeacSNikolay Aleksandrov default:
860a258aeacSNikolay Aleksandrov return -EINVAL;
861a258aeacSNikolay Aleksandrov }
862a258aeacSNikolay Aleksandrov
863ae0be8deSMichal Kubecek nest = nla_nest_start_noflag(skb, LINK_XSTATS_TYPE_BOND);
864a258aeacSNikolay Aleksandrov if (!nest)
865a258aeacSNikolay Aleksandrov return -EMSGSIZE;
866a258aeacSNikolay Aleksandrov if (BOND_MODE(bond) == BOND_MODE_8023AD) {
867949e7ceaSNikolay Aleksandrov struct bond_3ad_stats *stats;
868a258aeacSNikolay Aleksandrov
869949e7ceaSNikolay Aleksandrov if (slave)
870949e7ceaSNikolay Aleksandrov stats = &SLAVE_AD_INFO(slave)->stats;
871949e7ceaSNikolay Aleksandrov else
872949e7ceaSNikolay Aleksandrov stats = &BOND_AD_INFO(bond).stats;
873a258aeacSNikolay Aleksandrov
874ae0be8deSMichal Kubecek nest2 = nla_nest_start_noflag(skb, BOND_XSTATS_3AD);
875a258aeacSNikolay Aleksandrov if (!nest2) {
876a258aeacSNikolay Aleksandrov nla_nest_end(skb, nest);
877a258aeacSNikolay Aleksandrov return -EMSGSIZE;
878a258aeacSNikolay Aleksandrov }
879a258aeacSNikolay Aleksandrov
880949e7ceaSNikolay Aleksandrov if (bond_3ad_stats_fill(skb, stats)) {
881a258aeacSNikolay Aleksandrov nla_nest_cancel(skb, nest2);
882a258aeacSNikolay Aleksandrov nla_nest_end(skb, nest);
883a258aeacSNikolay Aleksandrov return -EMSGSIZE;
884a258aeacSNikolay Aleksandrov }
885a258aeacSNikolay Aleksandrov nla_nest_end(skb, nest2);
886a258aeacSNikolay Aleksandrov }
887a258aeacSNikolay Aleksandrov nla_nest_end(skb, nest);
888a258aeacSNikolay Aleksandrov
889a258aeacSNikolay Aleksandrov return 0;
890a258aeacSNikolay Aleksandrov }
891a258aeacSNikolay Aleksandrov
8920a2a78c4SJiri Pirko struct rtnl_link_ops bond_link_ops __read_mostly = {
8930a2a78c4SJiri Pirko .kind = "bond",
8940a2a78c4SJiri Pirko .priv_size = sizeof(struct bonding),
8950a2a78c4SJiri Pirko .setup = bond_setup,
89690af2311SJiri Pirko .maxtype = IFLA_BOND_MAX,
89790af2311SJiri Pirko .policy = bond_policy,
8980a2a78c4SJiri Pirko .validate = bond_validate,
89990af2311SJiri Pirko .newlink = bond_newlink,
90090af2311SJiri Pirko .changelink = bond_changelink,
90190af2311SJiri Pirko .get_size = bond_get_size,
90290af2311SJiri Pirko .fill_info = bond_fill_info,
9030a2a78c4SJiri Pirko .get_num_tx_queues = bond_get_num_tx_queues,
9040a2a78c4SJiri Pirko .get_num_rx_queues = bond_get_num_tx_queues, /* Use the same number
9050a2a78c4SJiri Pirko as for TX queues */
906a258aeacSNikolay Aleksandrov .fill_linkxstats = bond_fill_linkxstats,
907a258aeacSNikolay Aleksandrov .get_linkxstats_size = bond_get_linkxstats_size,
908cea6aeb6SJiri Pirko .slave_maxtype = IFLA_BOND_SLAVE_MAX,
909cea6aeb6SJiri Pirko .slave_policy = bond_slave_policy,
910cea6aeb6SJiri Pirko .slave_changelink = bond_slave_changelink,
9113bad540eSJiri Pirko .get_slave_size = bond_get_slave_size,
9123bad540eSJiri Pirko .fill_slave_info = bond_fill_slave_info,
9130a2a78c4SJiri Pirko };
9140a2a78c4SJiri Pirko
bond_netlink_init(void)9150a2a78c4SJiri Pirko int __init bond_netlink_init(void)
9160a2a78c4SJiri Pirko {
9170a2a78c4SJiri Pirko return rtnl_link_register(&bond_link_ops);
9180a2a78c4SJiri Pirko }
9190a2a78c4SJiri Pirko
bond_netlink_fini(void)920a729e83aSDavid S. Miller void bond_netlink_fini(void)
9210a2a78c4SJiri Pirko {
9220a2a78c4SJiri Pirko rtnl_link_unregister(&bond_link_ops);
9230a2a78c4SJiri Pirko }
9240a2a78c4SJiri Pirko
9250a2a78c4SJiri Pirko MODULE_ALIAS_RTNL_LINK("bond");
926