2013-10-18 19:43:33 +04:00
/*
* drivers / net / bond / bond_netlink . c - Netlink interface for bonding
* Copyright ( c ) 2013 Jiri Pirko < jiri @ resnulli . us >
2013-12-13 02:09:55 +04:00
* Copyright ( c ) 2013 Scott Feldman < sfeldma @ cumulusnetworks . com >
2013-10-18 19:43:33 +04:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# 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 21:27:49 +03:00
# include <net/bonding.h>
2013-10-18 19:43:33 +04:00
2014-01-22 12:05:56 +04: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 */
2014-01-22 12:05:56 +04: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-17 10:57:56 +04:00
{
struct slave * slave = bond_slave_get_rtnl ( slave_dev ) ;
2014-01-22 12:05:54 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_SLAVE_STATE , bond_slave_state ( slave ) ) )
2014-01-17 10:57:56 +04:00
goto nla_put_failure ;
2014-01-22 12:05:54 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_SLAVE_MII_STATUS , slave - > link ) )
2014-01-17 10:57:56 +04:00
goto nla_put_failure ;
2014-01-22 12:05:54 +04:00
if ( nla_put_u32 ( skb , IFLA_BOND_SLAVE_LINK_FAILURE_COUNT ,
2014-01-17 10:57:56 +04:00
slave - > link_failure_count ) )
goto nla_put_failure ;
2014-01-22 12:05:54 +04:00
if ( nla_put ( skb , IFLA_BOND_SLAVE_PERM_HWADDR ,
2014-01-17 10:57:56 +04:00
slave_dev - > addr_len , slave - > perm_hwaddr ) )
goto nla_put_failure ;
2014-01-22 12:05:54 +04:00
if ( nla_put_u16 ( skb , IFLA_BOND_SLAVE_QUEUE_ID , slave - > queue_id ) )
2014-01-17 10:57:56 +04:00
goto nla_put_failure ;
2014-05-15 23:39:55 +04:00
if ( BOND_MODE ( slave - > bond ) = = BOND_MODE_8023AD ) {
2014-01-22 12:05:56 +04:00
const struct aggregator * agg ;
2015-06-14 16:36:34 +03:00
const struct port * ad_port ;
2014-01-22 12:05:56 +04:00
2015-06-14 16:36:34 +03:00
ad_port = & SLAVE_AD_INFO ( slave ) - > port ;
2014-05-12 11:08:43 +04:00
agg = SLAVE_AD_INFO ( slave ) - > port . aggregator ;
2015-06-14 16:36:34 +03:00
if ( agg ) {
2014-01-22 12:05:54 +04:00
if ( nla_put_u16 ( skb , IFLA_BOND_SLAVE_AD_AGGREGATOR_ID ,
2014-01-17 10:57:56 +04: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-17 10:57:56 +04:00
}
return 0 ;
nla_put_failure :
return - EMSGSIZE ;
}
2013-10-18 19:43:38 +04:00
static const struct nla_policy bond_policy [ IFLA_BOND_MAX + 1 ] = {
[ IFLA_BOND_MODE ] = { . type = NLA_U8 } ,
2013-10-18 19:43:39 +04:00
[ IFLA_BOND_ACTIVE_SLAVE ] = { . type = NLA_U32 } ,
2013-12-13 02:09:55 +04:00
[ IFLA_BOND_MIIMON ] = { . type = NLA_U32 } ,
2013-12-13 02:10:02 +04:00
[ IFLA_BOND_UPDELAY ] = { . type = NLA_U32 } ,
2013-12-13 02:10:09 +04:00
[ IFLA_BOND_DOWNDELAY ] = { . type = NLA_U32 } ,
2013-12-13 02:10:16 +04:00
[ IFLA_BOND_USE_CARRIER ] = { . type = NLA_U8 } ,
2013-12-13 02:10:24 +04:00
[ IFLA_BOND_ARP_INTERVAL ] = { . type = NLA_U32 } ,
2013-12-13 02:10:31 +04:00
[ IFLA_BOND_ARP_IP_TARGET ] = { . type = NLA_NESTED } ,
2013-12-13 02:10:38 +04:00
[ IFLA_BOND_ARP_VALIDATE ] = { . type = NLA_U32 } ,
2013-12-13 02:10:45 +04:00
[ IFLA_BOND_ARP_ALL_TARGETS ] = { . type = NLA_U32 } ,
2013-12-16 04:41:51 +04:00
[ IFLA_BOND_PRIMARY ] = { . type = NLA_U32 } ,
2013-12-16 04:41:58 +04:00
[ IFLA_BOND_PRIMARY_RESELECT ] = { . type = NLA_U8 } ,
2013-12-16 04:42:05 +04:00
[ IFLA_BOND_FAIL_OVER_MAC ] = { . type = NLA_U8 } ,
2013-12-16 04:42:12 +04:00
[ IFLA_BOND_XMIT_HASH_POLICY ] = { . type = NLA_U8 } ,
2013-12-16 04:42:19 +04:00
[ IFLA_BOND_RESEND_IGMP ] = { . type = NLA_U32 } ,
2013-12-18 09:30:09 +04:00
[ IFLA_BOND_NUM_PEER_NOTIF ] = { . type = NLA_U8 } ,
2013-12-18 09:30:16 +04:00
[ IFLA_BOND_ALL_SLAVES_ACTIVE ] = { . type = NLA_U8 } ,
2013-12-18 09:30:23 +04:00
[ IFLA_BOND_MIN_LINKS ] = { . type = NLA_U32 } ,
2013-12-18 09:30:30 +04:00
[ IFLA_BOND_LP_INTERVAL ] = { . type = NLA_U32 } ,
2013-12-18 09:30:37 +04:00
[ IFLA_BOND_PACKETS_PER_SLAVE ] = { . type = NLA_U32 } ,
2014-01-04 02:18:41 +04:00
[ IFLA_BOND_AD_LACP_RATE ] = { . type = NLA_U8 } ,
2014-01-04 02:18:49 +04:00
[ IFLA_BOND_AD_SELECT ] = { . type = NLA_U8 } ,
2014-01-04 02:18:56 +04:00
[ IFLA_BOND_AD_INFO ] = { . type = NLA_NESTED } ,
2015-05-09 10:01:58 +03: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 17:49:43 +03:00
[ IFLA_BOND_TLB_DYNAMIC_LB ] = { . type = NLA_U8 } ,
2013-10-18 19:43:38 +04:00
} ;
2014-09-05 13:36:34 +04:00
static const struct nla_policy bond_slave_policy [ IFLA_BOND_SLAVE_MAX + 1 ] = {
[ IFLA_BOND_SLAVE_QUEUE_ID ] = { . type = NLA_U16 } ,
} ;
2017-06-26 00:56:01 +03:00
static int bond_validate ( struct nlattr * tb [ ] , struct nlattr * data [ ] ,
struct netlink_ext_ack * extack )
2013-10-18 19:43:33 +04: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 18:06:46 +04:00
static int bond_slave_changelink ( struct net_device * bond_dev ,
struct net_device * slave_dev ,
2017-06-26 00:56:02 +03:00
struct nlattr * tb [ ] , struct nlattr * data [ ] ,
struct netlink_ext_ack * extack )
2014-08-27 18:06:46 +04: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 ) ;
err = __bond_opt_set ( bond , BOND_OPT_QUEUE_ID , & newval ) ;
if ( err )
return err ;
}
return 0 ;
}
2017-06-26 00:56:00 +03:00
static int bond_changelink ( struct net_device * bond_dev , struct nlattr * tb [ ] ,
struct nlattr * data [ ] ,
struct netlink_ext_ack * extack )
2013-10-18 19:43:38 +04:00
{
struct bonding * bond = netdev_priv ( bond_dev ) ;
2014-01-22 17:53:17 +04:00
struct bond_opt_value newval ;
2013-12-13 02:10:24 +04:00
int miimon = 0 ;
2013-10-18 19:43:38 +04:00
int err ;
2013-12-13 02:09:55 +04:00
if ( ! data )
return 0 ;
if ( data [ IFLA_BOND_MODE ] ) {
2013-10-18 19:43:38 +04:00
int mode = nla_get_u8 ( data [ IFLA_BOND_MODE ] ) ;
2014-01-22 17:53:17 +04:00
bond_opt_initval ( & newval , mode ) ;
err = __bond_opt_set ( bond , BOND_OPT_MODE , & newval ) ;
2013-10-18 19:43:38 +04:00
if ( err )
return err ;
}
2013-12-13 02:09:55 +04:00
if ( data [ IFLA_BOND_ACTIVE_SLAVE ] ) {
2013-10-18 19:43:39 +04:00
int ifindex = nla_get_u32 ( data [ IFLA_BOND_ACTIVE_SLAVE ] ) ;
struct net_device * slave_dev ;
2014-01-22 17:53:35 +04:00
char * active_slave = " " ;
2013-10-18 19:43:39 +04:00
2014-01-22 17:53:35 +04:00
if ( ifindex ! = 0 ) {
2013-10-18 19:43:39 +04:00
slave_dev = __dev_get_by_index ( dev_net ( bond_dev ) ,
ifindex ) ;
if ( ! slave_dev )
return - ENODEV ;
2014-01-22 17:53:35 +04:00
active_slave = slave_dev - > name ;
2013-10-18 19:43:39 +04:00
}
2014-01-22 17:53:35 +04:00
bond_opt_initstr ( & newval , active_slave ) ;
err = __bond_opt_set ( bond , BOND_OPT_ACTIVE_SLAVE , & newval ) ;
2013-10-18 19:43:39 +04:00
if ( err )
return err ;
}
2013-12-13 02:09:55 +04:00
if ( data [ IFLA_BOND_MIIMON ] ) {
2013-12-13 02:10:24 +04:00
miimon = nla_get_u32 ( data [ IFLA_BOND_MIIMON ] ) ;
2013-12-13 02:09:55 +04:00
2014-01-22 17:53:31 +04:00
bond_opt_initval ( & newval , miimon ) ;
err = __bond_opt_set ( bond , BOND_OPT_MIIMON , & newval ) ;
2013-12-13 02:09:55 +04:00
if ( err )
return err ;
}
2013-12-13 02:10:02 +04:00
if ( data [ IFLA_BOND_UPDELAY ] ) {
int updelay = nla_get_u32 ( data [ IFLA_BOND_UPDELAY ] ) ;
2014-01-22 17:53:26 +04:00
bond_opt_initval ( & newval , updelay ) ;
err = __bond_opt_set ( bond , BOND_OPT_UPDELAY , & newval ) ;
2013-12-13 02:10:02 +04:00
if ( err )
return err ;
}
2013-12-13 02:10:09 +04:00
if ( data [ IFLA_BOND_DOWNDELAY ] ) {
int downdelay = nla_get_u32 ( data [ IFLA_BOND_DOWNDELAY ] ) ;
2014-01-22 17:53:25 +04:00
bond_opt_initval ( & newval , downdelay ) ;
err = __bond_opt_set ( bond , BOND_OPT_DOWNDELAY , & newval ) ;
2013-12-13 02:10:09 +04:00
if ( err )
return err ;
}
2013-12-13 02:10:16 +04:00
if ( data [ IFLA_BOND_USE_CARRIER ] ) {
int use_carrier = nla_get_u8 ( data [ IFLA_BOND_USE_CARRIER ] ) ;
2014-01-22 17:53:34 +04:00
bond_opt_initval ( & newval , use_carrier ) ;
err = __bond_opt_set ( bond , BOND_OPT_USE_CARRIER , & newval ) ;
2013-12-13 02:10:16 +04:00
if ( err )
return err ;
}
2013-12-13 02:10:24 +04:00
if ( data [ IFLA_BOND_ARP_INTERVAL ] ) {
int arp_interval = nla_get_u32 ( data [ IFLA_BOND_ARP_INTERVAL ] ) ;
if ( arp_interval & & miimon ) {
2014-07-15 21:36:05 +04:00
netdev_err ( bond - > dev , " ARP monitoring cannot be used with MII monitoring \n " ) ;
2013-12-13 02:10:24 +04:00
return - EINVAL ;
}
2014-01-22 17:53:23 +04:00
bond_opt_initval ( & newval , arp_interval ) ;
err = __bond_opt_set ( bond , BOND_OPT_ARP_INTERVAL , & newval ) ;
2013-12-13 02:10:24 +04:00
if ( err )
return err ;
}
2013-12-13 02:10:31 +04:00
if ( data [ IFLA_BOND_ARP_IP_TARGET ] ) {
struct nlattr * attr ;
int i = 0 , rem ;
2014-01-22 17:53:24 +04:00
bond_option_arp_ip_targets_clear ( bond ) ;
2013-12-13 02:10:31 +04:00
nla_for_each_nested ( attr , data [ IFLA_BOND_ARP_IP_TARGET ] , rem ) {
2014-11-27 02:22:33 +03:00
__be32 target ;
if ( nla_len ( attr ) < sizeof ( target ) )
return - EINVAL ;
target = nla_get_be32 ( attr ) ;
2013-12-13 02:10:31 +04:00
2014-03-10 20:48:38 +04:00
bond_opt_initval ( & newval , ( __force u64 ) target ) ;
2014-01-22 17:53:24 +04:00
err = __bond_opt_set ( bond , BOND_OPT_ARP_TARGETS ,
& newval ) ;
if ( err )
break ;
i + + ;
}
if ( i = = 0 & & bond - > params . arp_interval )
2014-07-15 21:36:05 +04:00
netdev_warn ( bond - > dev , " Removing last arp target with arp_interval on \n " ) ;
2013-12-13 02:10:31 +04:00
if ( err )
return err ;
}
2013-12-13 02:10:38 +04:00
if ( data [ IFLA_BOND_ARP_VALIDATE ] ) {
int arp_validate = nla_get_u32 ( data [ IFLA_BOND_ARP_VALIDATE ] ) ;
if ( arp_validate & & miimon ) {
2014-07-15 21:36:05 +04:00
netdev_err ( bond - > dev , " ARP validating cannot be used with MII monitoring \n " ) ;
2013-12-13 02:10:38 +04:00
return - EINVAL ;
}
2014-01-22 17:53:20 +04:00
bond_opt_initval ( & newval , arp_validate ) ;
err = __bond_opt_set ( bond , BOND_OPT_ARP_VALIDATE , & newval ) ;
2013-12-13 02:10:38 +04:00
if ( err )
return err ;
}
2013-12-13 02:10:45 +04:00
if ( data [ IFLA_BOND_ARP_ALL_TARGETS ] ) {
int arp_all_targets =
nla_get_u32 ( data [ IFLA_BOND_ARP_ALL_TARGETS ] ) ;
2014-01-22 17:53:21 +04:00
bond_opt_initval ( & newval , arp_all_targets ) ;
err = __bond_opt_set ( bond , BOND_OPT_ARP_ALL_TARGETS , & newval ) ;
2013-12-13 02:10:45 +04:00
if ( err )
return err ;
}
2013-12-16 04:41:51 +04: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 17:53:32 +04:00
bond_opt_initstr ( & newval , primary ) ;
err = __bond_opt_set ( bond , BOND_OPT_PRIMARY , & newval ) ;
2013-12-16 04:41:51 +04:00
if ( err )
return err ;
}
2013-12-16 04:41:58 +04:00
if ( data [ IFLA_BOND_PRIMARY_RESELECT ] ) {
int primary_reselect =
nla_get_u8 ( data [ IFLA_BOND_PRIMARY_RESELECT ] ) ;
2014-01-22 17:53:33 +04:00
bond_opt_initval ( & newval , primary_reselect ) ;
err = __bond_opt_set ( bond , BOND_OPT_PRIMARY_RESELECT , & newval ) ;
2013-12-16 04:41:58 +04:00
if ( err )
return err ;
}
2013-12-16 04:42:05 +04:00
if ( data [ IFLA_BOND_FAIL_OVER_MAC ] ) {
int fail_over_mac =
nla_get_u8 ( data [ IFLA_BOND_FAIL_OVER_MAC ] ) ;
2014-01-22 17:53:22 +04:00
bond_opt_initval ( & newval , fail_over_mac ) ;
err = __bond_opt_set ( bond , BOND_OPT_FAIL_OVER_MAC , & newval ) ;
2013-12-16 04:42:05 +04:00
if ( err )
return err ;
}
2013-12-16 04:42:12 +04:00
if ( data [ IFLA_BOND_XMIT_HASH_POLICY ] ) {
int xmit_hash_policy =
nla_get_u8 ( data [ IFLA_BOND_XMIT_HASH_POLICY ] ) ;
2014-01-22 17:53:19 +04:00
bond_opt_initval ( & newval , xmit_hash_policy ) ;
err = __bond_opt_set ( bond , BOND_OPT_XMIT_HASH , & newval ) ;
2013-12-16 04:42:12 +04:00
if ( err )
return err ;
}
2013-12-16 04:42:19 +04:00
if ( data [ IFLA_BOND_RESEND_IGMP ] ) {
int resend_igmp =
nla_get_u32 ( data [ IFLA_BOND_RESEND_IGMP ] ) ;
2014-01-22 17:53:38 +04:00
bond_opt_initval ( & newval , resend_igmp ) ;
err = __bond_opt_set ( bond , BOND_OPT_RESEND_IGMP , & newval ) ;
2013-12-16 04:42:19 +04:00
if ( err )
return err ;
}
2013-12-18 09:30:09 +04:00
if ( data [ IFLA_BOND_NUM_PEER_NOTIF ] ) {
int num_peer_notif =
nla_get_u8 ( data [ IFLA_BOND_NUM_PEER_NOTIF ] ) ;
2014-01-22 17:53:30 +04:00
bond_opt_initval ( & newval , num_peer_notif ) ;
err = __bond_opt_set ( bond , BOND_OPT_NUM_PEER_NOTIF , & newval ) ;
2013-12-18 09:30:09 +04:00
if ( err )
return err ;
}
2013-12-18 09:30:16 +04:00
if ( data [ IFLA_BOND_ALL_SLAVES_ACTIVE ] ) {
int all_slaves_active =
nla_get_u8 ( data [ IFLA_BOND_ALL_SLAVES_ACTIVE ] ) ;
2014-01-22 17:53:37 +04:00
bond_opt_initval ( & newval , all_slaves_active ) ;
err = __bond_opt_set ( bond , BOND_OPT_ALL_SLAVES_ACTIVE , & newval ) ;
2013-12-18 09:30:16 +04:00
if ( err )
return err ;
}
2013-12-18 09:30:23 +04:00
if ( data [ IFLA_BOND_MIN_LINKS ] ) {
int min_links =
nla_get_u32 ( data [ IFLA_BOND_MIN_LINKS ] ) ;
2014-01-22 17:53:28 +04:00
bond_opt_initval ( & newval , min_links ) ;
err = __bond_opt_set ( bond , BOND_OPT_MINLINKS , & newval ) ;
2013-12-18 09:30:23 +04:00
if ( err )
return err ;
}
2013-12-18 09:30:30 +04:00
if ( data [ IFLA_BOND_LP_INTERVAL ] ) {
int lp_interval =
nla_get_u32 ( data [ IFLA_BOND_LP_INTERVAL ] ) ;
2014-01-22 17:53:39 +04:00
bond_opt_initval ( & newval , lp_interval ) ;
err = __bond_opt_set ( bond , BOND_OPT_LP_INTERVAL , & newval ) ;
2013-12-18 09:30:30 +04:00
if ( err )
return err ;
}
2013-12-18 09:30:37 +04:00
if ( data [ IFLA_BOND_PACKETS_PER_SLAVE ] ) {
int packets_per_slave =
nla_get_u32 ( data [ IFLA_BOND_PACKETS_PER_SLAVE ] ) ;
2014-01-22 17:53:18 +04:00
bond_opt_initval ( & newval , packets_per_slave ) ;
err = __bond_opt_set ( bond , BOND_OPT_PACKETS_PER_SLAVE , & newval ) ;
2013-12-18 09:30:37 +04:00
if ( err )
return err ;
}
2014-01-04 02:18:41 +04:00
if ( data [ IFLA_BOND_AD_LACP_RATE ] ) {
int lacp_rate =
nla_get_u8 ( data [ IFLA_BOND_AD_LACP_RATE ] ) ;
2014-01-22 17:53:27 +04:00
bond_opt_initval ( & newval , lacp_rate ) ;
err = __bond_opt_set ( bond , BOND_OPT_LACP_RATE , & newval ) ;
2014-01-04 02:18:41 +04:00
if ( err )
return err ;
}
2014-01-04 02:18:49 +04:00
if ( data [ IFLA_BOND_AD_SELECT ] ) {
int ad_select =
nla_get_u8 ( data [ IFLA_BOND_AD_SELECT ] ) ;
2014-01-22 17:53:29 +04:00
bond_opt_initval ( & newval , ad_select ) ;
err = __bond_opt_set ( bond , BOND_OPT_AD_SELECT , & newval ) ;
2014-01-04 02:18:49 +04:00
if ( err )
return err ;
}
2015-05-09 10:01:58 +03: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 ) ;
err = __bond_opt_set ( bond , BOND_OPT_AD_ACTOR_SYS_PRIO , & newval ) ;
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 ) ;
err = __bond_opt_set ( bond , BOND_OPT_AD_USER_PORT_KEY , & newval ) ;
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 ,
nla_get_be64 ( data [ IFLA_BOND_AD_ACTOR_SYSTEM ] ) ) ;
err = __bond_opt_set ( bond , BOND_OPT_AD_ACTOR_SYSTEM , & newval ) ;
if ( err )
return err ;
}
2015-07-31 17:49:43 +03: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 ) ;
err = __bond_opt_set ( bond , BOND_OPT_TLB_DYNAMIC_LB , & newval ) ;
if ( err )
return err ;
}
2013-10-18 19:43:38 +04:00
return 0 ;
}
static int bond_newlink ( struct net * src_net , struct net_device * bond_dev ,
2017-06-26 00:55:59 +03:00
struct nlattr * tb [ ] , struct nlattr * data [ ] ,
struct netlink_ext_ack * extack )
2013-10-18 19:43:38 +04:00
{
int err ;
2017-06-26 00:56:00 +03:00
err = bond_changelink ( bond_dev , tb , data , extack ) ;
2013-10-18 19:43:38 +04:00
if ( err < 0 )
return err ;
2016-07-13 19:25:08 +03:00
err = register_netdevice ( bond_dev ) ;
netif_carrier_off ( bond_dev ) ;
2017-04-20 22:49:24 +03:00
if ( ! err ) {
struct bonding * bond = netdev_priv ( bond_dev ) ;
bond_work_init_all ( bond ) ;
}
2016-07-13 19:25:08 +03:00
return err ;
2013-10-18 19:43:38 +04:00
}
static size_t bond_get_size ( const struct net_device * bond_dev )
{
2013-11-01 14:18:44 +04:00
return nla_total_size ( sizeof ( u8 ) ) + /* IFLA_BOND_MODE */
2013-12-13 02:09:55 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_ACTIVE_SLAVE */
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_MIIMON */
2013-12-13 02:10:02 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_UPDELAY */
2013-12-13 02:10:09 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_DOWNDELAY */
2013-12-13 02:10:16 +04:00
nla_total_size ( sizeof ( u8 ) ) + /* IFLA_BOND_USE_CARRIER */
2013-12-13 02:10:24 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_ARP_INTERVAL */
2013-12-13 02:10:31 +04:00
/* IFLA_BOND_ARP_IP_TARGET */
2014-01-04 02:28:11 +04:00
nla_total_size ( sizeof ( struct nlattr ) ) +
2013-12-13 02:10:31 +04:00
nla_total_size ( sizeof ( u32 ) ) * BOND_MAX_ARP_TARGETS +
2013-12-13 02:10:38 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_ARP_VALIDATE */
2013-12-13 02:10:45 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_ARP_ALL_TARGETS */
2013-12-16 04:41:51 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_PRIMARY */
2013-12-16 04:41:58 +04:00
nla_total_size ( sizeof ( u8 ) ) + /* IFLA_BOND_PRIMARY_RESELECT */
2013-12-16 04:42:05 +04:00
nla_total_size ( sizeof ( u8 ) ) + /* IFLA_BOND_FAIL_OVER_MAC */
2013-12-16 04:42:12 +04:00
nla_total_size ( sizeof ( u8 ) ) + /* IFLA_BOND_XMIT_HASH_POLICY */
2013-12-16 04:42:19 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_RESEND_IGMP */
2013-12-18 09:30:09 +04:00
nla_total_size ( sizeof ( u8 ) ) + /* IFLA_BOND_NUM_PEER_NOTIF */
2013-12-18 09:30:16 +04:00
nla_total_size ( sizeof ( u8 ) ) + /* IFLA_BOND_ALL_SLAVES_ACTIVE */
2013-12-18 09:30:23 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_MIN_LINKS */
2013-12-18 09:30:30 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_LP_INTERVAL */
2013-12-18 09:30:37 +04:00
nla_total_size ( sizeof ( u32 ) ) + /* IFLA_BOND_PACKETS_PER_SLAVE */
2014-01-04 02:18:41 +04:00
nla_total_size ( sizeof ( u8 ) ) + /* IFLA_BOND_AD_LACP_RATE */
2014-01-04 02:18:49 +04:00
nla_total_size ( sizeof ( u8 ) ) + /* IFLA_BOND_AD_SELECT */
2014-01-04 02:18:56 +04: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 10:01:58 +03: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 17:49:43 +03:00
nla_total_size ( sizeof ( u8 ) ) + /* IFLA_BOND_TLB_DYNAMIC_LB */
2013-12-13 02:09:55 +04:00
0 ;
2013-10-18 19:43:38 +04:00
}
2014-07-15 17:56:53 +04: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 19:43:38 +04: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-18 09:30:37 +04:00
unsigned int packets_per_slave ;
2014-07-15 17:56:53 +04:00
int ifindex , i , targets_added ;
struct nlattr * targets ;
2014-09-10 01:17:00 +04:00
struct slave * primary ;
2013-10-18 19:43:38 +04:00
2014-05-15 23:39:55 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_MODE , BOND_MODE ( bond ) ) )
2013-10-18 19:43:38 +04:00
goto nla_put_failure ;
2013-12-13 02:09:55 +04:00
2014-07-15 17:56:53 +04:00
ifindex = bond_option_active_slave_get_ifindex ( bond ) ;
if ( ifindex & & nla_put_u32 ( skb , IFLA_BOND_ACTIVE_SLAVE , ifindex ) )
2013-12-13 02:09:55 +04:00
goto nla_put_failure ;
if ( nla_put_u32 ( skb , IFLA_BOND_MIIMON , bond - > params . miimon ) )
goto nla_put_failure ;
2013-12-13 02:10:02 +04:00
if ( nla_put_u32 ( skb , IFLA_BOND_UPDELAY ,
bond - > params . updelay * bond - > params . miimon ) )
goto nla_put_failure ;
2013-12-13 02:10:09 +04:00
if ( nla_put_u32 ( skb , IFLA_BOND_DOWNDELAY ,
bond - > params . downdelay * bond - > params . miimon ) )
goto nla_put_failure ;
2013-12-13 02:10:16 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_USE_CARRIER , bond - > params . use_carrier ) )
goto nla_put_failure ;
2013-12-13 02:10:24 +04:00
if ( nla_put_u32 ( skb , IFLA_BOND_ARP_INTERVAL , bond - > params . arp_interval ) )
goto nla_put_failure ;
2013-12-13 02:10:31 +04:00
targets = nla_nest_start ( skb , IFLA_BOND_ARP_IP_TARGET ) ;
if ( ! targets )
goto nla_put_failure ;
targets_added = 0 ;
for ( i = 0 ; i < BOND_MAX_ARP_TARGETS ; i + + ) {
if ( bond - > params . arp_targets [ i ] ) {
2017-05-06 06:17:06 +03:00
if ( nla_put_be32 ( skb , i , bond - > params . arp_targets [ i ] ) )
goto nla_put_failure ;
2013-12-13 02:10:31 +04:00
targets_added = 1 ;
}
}
if ( targets_added )
nla_nest_end ( skb , targets ) ;
else
nla_nest_cancel ( skb , targets ) ;
2013-12-13 02:10:38 +04:00
if ( nla_put_u32 ( skb , IFLA_BOND_ARP_VALIDATE , bond - > params . arp_validate ) )
goto nla_put_failure ;
2013-12-13 02:10:45 +04:00
if ( nla_put_u32 ( skb , IFLA_BOND_ARP_ALL_TARGETS ,
bond - > params . arp_all_targets ) )
goto nla_put_failure ;
2014-09-10 01:17:00 +04:00
primary = rtnl_dereference ( bond - > primary_slave ) ;
if ( primary & &
nla_put_u32 ( skb , IFLA_BOND_PRIMARY , primary - > dev - > ifindex ) )
2013-12-16 04:41:51 +04:00
goto nla_put_failure ;
2013-12-16 04:41:58 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_PRIMARY_RESELECT ,
bond - > params . primary_reselect ) )
goto nla_put_failure ;
2013-12-16 04:42:05 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_FAIL_OVER_MAC ,
bond - > params . fail_over_mac ) )
goto nla_put_failure ;
2013-12-16 04:42:12 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_XMIT_HASH_POLICY ,
bond - > params . xmit_policy ) )
goto nla_put_failure ;
2013-12-16 04:42:19 +04:00
if ( nla_put_u32 ( skb , IFLA_BOND_RESEND_IGMP ,
bond - > params . resend_igmp ) )
goto nla_put_failure ;
2013-12-18 09:30:09 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_NUM_PEER_NOTIF ,
bond - > params . num_peer_notif ) )
goto nla_put_failure ;
2013-12-18 09:30:16 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_ALL_SLAVES_ACTIVE ,
bond - > params . all_slaves_active ) )
goto nla_put_failure ;
2013-12-18 09:30:23 +04:00
if ( nla_put_u32 ( skb , IFLA_BOND_MIN_LINKS ,
bond - > params . min_links ) )
goto nla_put_failure ;
2013-12-18 09:30:30 +04:00
if ( nla_put_u32 ( skb , IFLA_BOND_LP_INTERVAL ,
bond - > params . lp_interval ) )
goto nla_put_failure ;
2013-12-18 09:30:37 +04: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 ;
2014-01-04 02:18:41 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_AD_LACP_RATE ,
bond - > params . lacp_fast ) )
goto nla_put_failure ;
2014-01-04 02:18:49 +04:00
if ( nla_put_u8 ( skb , IFLA_BOND_AD_SELECT ,
bond - > params . ad_select ) )
goto nla_put_failure ;
2015-07-31 17:49:43 +03:00
if ( nla_put_u8 ( skb , IFLA_BOND_TLB_DYNAMIC_LB ,
bond - > params . tlb_dynamic_lb ) )
goto nla_put_failure ;
2014-05-15 23:39:55 +04:00
if ( BOND_MODE ( bond ) = = BOND_MODE_8023AD ) {
2014-01-04 02:18:56 +04:00
struct ad_info info ;
2015-06-18 21:30:54 +03: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 10:01:58 +03:00
2015-06-18 21:30:54 +03: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 10:01:58 +03:00
2015-06-18 21:30:54 +03:00
if ( nla_put ( skb , IFLA_BOND_AD_ACTOR_SYSTEM ,
sizeof ( bond - > params . ad_actor_system ) ,
& bond - > params . ad_actor_system ) )
goto nla_put_failure ;
}
2014-01-04 02:18:56 +04:00
if ( ! bond_3ad_get_active_agg_info ( bond , & info ) ) {
struct nlattr * nest ;
nest = nla_nest_start ( skb , IFLA_BOND_AD_INFO ) ;
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 19:43:38 +04:00
return 0 ;
nla_put_failure :
return - EMSGSIZE ;
}
2013-10-18 19:43:33 +04:00
struct rtnl_link_ops bond_link_ops __read_mostly = {
. kind = " bond " ,
. priv_size = sizeof ( struct bonding ) ,
. setup = bond_setup ,
2013-10-18 19:43:38 +04:00
. maxtype = IFLA_BOND_MAX ,
. policy = bond_policy ,
2013-10-18 19:43:33 +04:00
. validate = bond_validate ,
2013-10-18 19:43:38 +04:00
. newlink = bond_newlink ,
. changelink = bond_changelink ,
. get_size = bond_get_size ,
. fill_info = bond_fill_info ,
2013-10-18 19:43:33 +04: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 */
2014-09-05 13:36:34 +04:00
. slave_maxtype = IFLA_BOND_SLAVE_MAX ,
. slave_policy = bond_slave_policy ,
. slave_changelink = bond_slave_changelink ,
2014-01-22 12:05:56 +04:00
. get_slave_size = bond_get_slave_size ,
. fill_slave_info = bond_fill_slave_info ,
2013-10-18 19:43:33 +04:00
} ;
int __init bond_netlink_init ( void )
{
return rtnl_link_register ( & bond_link_ops ) ;
}
2013-10-20 03:09:18 +04:00
void bond_netlink_fini ( void )
2013-10-18 19:43:33 +04:00
{
rtnl_link_unregister ( & bond_link_ops ) ;
}
MODULE_ALIAS_RTNL_LINK ( " bond " ) ;