2005-04-17 05:20:36 +07:00
/*
* INET An implementation of the TCP / IP protocol suite for the LINUX
* operating system . INET is implemented using the BSD Socket
* interface as the means of communication with the user level .
*
* Routing netlink socket interface : protocol independent part .
*
* Authors : Alexey Kuznetsov , < kuznet @ ms2 . inr . ac . ru >
*
* 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 .
*
* Fixes :
* Vitaly E . Lavrov RTA_OK arithmetics was wrong .
*/
2017-06-22 08:25:04 +07:00
# include <linux/bitops.h>
2005-04-17 05:20:36 +07:00
# include <linux/errno.h>
# include <linux/module.h>
# include <linux/types.h>
# include <linux/socket.h>
# include <linux/kernel.h>
# include <linux/timer.h>
# include <linux/string.h>
# include <linux/sockios.h>
# include <linux/net.h>
# include <linux/fcntl.h>
# include <linux/mm.h>
# include <linux/slab.h>
# include <linux/interrupt.h>
# include <linux/capability.h>
# include <linux/skbuff.h>
# include <linux/init.h>
# include <linux/security.h>
2006-03-21 13:23:58 +07:00
# include <linux/mutex.h>
2006-08-05 13:04:54 +07:00
# include <linux/if_addr.h>
2012-04-15 13:43:56 +07:00
# include <linux/if_bridge.h>
2014-11-28 20:34:15 +07:00
# include <linux/if_vlan.h>
2010-02-10 08:44:05 +07:00
# include <linux/pci.h>
2012-04-15 13:43:56 +07:00
# include <linux/etherdevice.h>
2017-06-16 07:29:09 +07:00
# include <linux/bpf.h>
2005-04-17 05:20:36 +07:00
2016-12-25 02:46:01 +07:00
# include <linux/uaccess.h>
2005-04-17 05:20:36 +07:00
# include <linux/inet.h>
# include <linux/netdevice.h>
2014-11-28 20:34:18 +07:00
# include <net/switchdev.h>
2005-04-17 05:20:36 +07:00
# include <net/ip.h>
# include <net/protocol.h>
# include <net/arp.h>
# include <net/route.h>
# include <net/udp.h>
2015-01-06 05:57:47 +07:00
# include <net/tcp.h>
2005-04-17 05:20:36 +07:00
# include <net/sock.h>
# include <net/pkt_sched.h>
2006-08-04 17:38:38 +07:00
# include <net/fib_rules.h>
2007-03-23 01:48:11 +07:00
# include <net/rtnetlink.h>
2009-07-10 16:51:35 +07:00
# include <net/net_namespace.h>
2005-04-17 05:20:36 +07:00
2009-11-07 16:26:17 +07:00
struct rtnl_link {
2007-03-23 01:48:11 +07:00
rtnl_doit_func doit ;
rtnl_dumpit_func dumpit ;
2017-08-10 01:41:52 +07:00
unsigned int flags ;
2007-03-23 01:48:11 +07:00
} ;
2006-03-21 13:23:58 +07:00
static DEFINE_MUTEX ( rtnl_mutex ) ;
2005-04-17 05:20:36 +07:00
void rtnl_lock ( void )
{
2006-03-21 13:23:58 +07:00
mutex_lock ( & rtnl_mutex ) ;
2005-04-17 05:20:36 +07:00
}
2009-11-07 16:26:17 +07:00
EXPORT_SYMBOL ( rtnl_lock ) ;
2005-04-17 05:20:36 +07:00
2016-06-14 10:21:50 +07:00
static struct sk_buff * defer_kfree_skb_list ;
void rtnl_kfree_skbs ( struct sk_buff * head , struct sk_buff * tail )
{
if ( head & & tail ) {
tail - > next = defer_kfree_skb_list ;
defer_kfree_skb_list = head ;
}
}
EXPORT_SYMBOL ( rtnl_kfree_skbs ) ;
2006-03-21 13:23:58 +07:00
void __rtnl_unlock ( void )
2005-04-17 05:20:36 +07:00
{
2016-06-14 10:21:50 +07:00
struct sk_buff * head = defer_kfree_skb_list ;
defer_kfree_skb_list = NULL ;
2006-03-21 13:23:58 +07:00
mutex_unlock ( & rtnl_mutex ) ;
2016-06-14 10:21:50 +07:00
while ( head ) {
struct sk_buff * next = head - > next ;
kfree_skb ( head ) ;
cond_resched ( ) ;
head = next ;
}
2005-04-17 05:20:36 +07:00
}
2006-03-21 13:23:58 +07:00
2005-04-17 05:20:36 +07:00
void rtnl_unlock ( void )
{
2008-10-08 05:50:03 +07:00
/* This fellow will unlock it for us. */
2005-04-17 05:20:36 +07:00
netdev_run_todo ( ) ;
}
2009-11-07 16:26:17 +07:00
EXPORT_SYMBOL ( rtnl_unlock ) ;
2005-04-17 05:20:36 +07:00
2006-03-21 13:23:58 +07:00
int rtnl_trylock ( void )
{
return mutex_trylock ( & rtnl_mutex ) ;
}
2009-11-07 16:26:17 +07:00
EXPORT_SYMBOL ( rtnl_trylock ) ;
2006-03-21 13:23:58 +07:00
2008-04-24 12:10:48 +07:00
int rtnl_is_locked ( void )
{
return mutex_is_locked ( & rtnl_mutex ) ;
}
2009-11-07 16:26:17 +07:00
EXPORT_SYMBOL ( rtnl_is_locked ) ;
2008-04-24 12:10:48 +07:00
2010-02-23 08:04:49 +07:00
# ifdef CONFIG_PROVE_LOCKING
2015-10-08 20:29:02 +07:00
bool lockdep_rtnl_is_held ( void )
2010-02-23 08:04:49 +07:00
{
return lockdep_is_held ( & rtnl_mutex ) ;
}
EXPORT_SYMBOL ( lockdep_rtnl_is_held ) ;
# endif /* #ifdef CONFIG_PROVE_LOCKING */
2017-08-10 01:41:51 +07:00
static struct rtnl_link __rcu * rtnl_msg_handlers [ RTNL_FAMILY_MAX + 1 ] ;
2017-08-10 01:41:49 +07:00
static refcount_t rtnl_msg_handlers_ref [ RTNL_FAMILY_MAX + 1 ] ;
2007-03-23 01:48:11 +07:00
static inline int rtm_msgindex ( int msgtype )
{
int msgindex = msgtype - RTM_BASE ;
/*
* msgindex < 0 implies someone tried to register a netlink
* control code . msgindex > = RTM_NR_MSGTYPES may indicate that
* the message type has not been added to linux / rtnetlink . h
*/
BUG_ON ( msgindex < 0 | | msgindex > = RTM_NR_MSGTYPES ) ;
return msgindex ;
}
/**
* __rtnl_register - Register a rtnetlink message type
* @ protocol : Protocol family or PF_UNSPEC
* @ msgtype : rtnetlink message type
* @ doit : Function pointer called for each request message
* @ dumpit : Function pointer called for each dump request ( NLM_F_DUMP ) message
2017-08-10 01:41:48 +07:00
* @ flags : rtnl_link_flags to modifiy behaviour of doit / dumpit functions
2007-03-23 01:48:11 +07:00
*
* Registers the specified function pointers ( at least one of them has
* to be non - NULL ) to be called whenever a request message for the
* specified protocol family and message type is received .
*
* The special protocol family PF_UNSPEC may be used to define fallback
* function pointers for the case when no entry for the specific protocol
* family exists .
*
* Returns 0 on success or a negative error code .
*/
int __rtnl_register ( int protocol , int msgtype ,
2011-06-10 08:27:09 +07:00
rtnl_doit_func doit , rtnl_dumpit_func dumpit ,
2017-08-10 01:41:48 +07:00
unsigned int flags )
2007-03-23 01:48:11 +07:00
{
struct rtnl_link * tab ;
int msgindex ;
2010-04-26 21:02:05 +07:00
BUG_ON ( protocol < 0 | | protocol > RTNL_FAMILY_MAX ) ;
2007-03-23 01:48:11 +07:00
msgindex = rtm_msgindex ( msgtype ) ;
2017-08-10 21:52:57 +07:00
tab = rcu_dereference_raw ( rtnl_msg_handlers [ protocol ] ) ;
2007-03-23 01:48:11 +07:00
if ( tab = = NULL ) {
tab = kcalloc ( RTM_NR_MSGTYPES , sizeof ( * tab ) , GFP_KERNEL ) ;
if ( tab = = NULL )
return - ENOBUFS ;
2017-08-10 01:41:51 +07:00
rcu_assign_pointer ( rtnl_msg_handlers [ protocol ] , tab ) ;
2007-03-23 01:48:11 +07:00
}
if ( doit )
tab [ msgindex ] . doit = doit ;
if ( dumpit )
tab [ msgindex ] . dumpit = dumpit ;
2017-08-10 01:41:52 +07:00
tab [ msgindex ] . flags | = flags ;
2007-03-23 01:48:11 +07:00
return 0 ;
}
EXPORT_SYMBOL_GPL ( __rtnl_register ) ;
/**
* rtnl_register - Register a rtnetlink message type
*
* Identical to __rtnl_register ( ) but panics on failure . This is useful
* as failure of this function is very unlikely , it can only happen due
* to lack of memory when allocating the chain to store all message
* handlers for a protocol . Meant for use in init functions where lack
2011-03-31 08:57:33 +07:00
* of memory implies no sense in continuing .
2007-03-23 01:48:11 +07:00
*/
void rtnl_register ( int protocol , int msgtype ,
2011-06-10 08:27:09 +07:00
rtnl_doit_func doit , rtnl_dumpit_func dumpit ,
2017-08-10 01:41:48 +07:00
unsigned int flags )
2007-03-23 01:48:11 +07:00
{
2017-08-10 01:41:48 +07:00
if ( __rtnl_register ( protocol , msgtype , doit , dumpit , flags ) < 0 )
2007-03-23 01:48:11 +07:00
panic ( " Unable to register rtnetlink message handler, "
" protocol = %d, message type = %d \n " ,
protocol , msgtype ) ;
}
EXPORT_SYMBOL_GPL ( rtnl_register ) ;
/**
* rtnl_unregister - Unregister a rtnetlink message type
* @ protocol : Protocol family or PF_UNSPEC
* @ msgtype : rtnetlink message type
*
* Returns 0 on success or a negative error code .
*/
int rtnl_unregister ( int protocol , int msgtype )
{
2017-08-10 01:41:51 +07:00
struct rtnl_link * handlers ;
2007-03-23 01:48:11 +07:00
int msgindex ;
2010-04-26 21:02:05 +07:00
BUG_ON ( protocol < 0 | | protocol > RTNL_FAMILY_MAX ) ;
2007-03-23 01:48:11 +07:00
msgindex = rtm_msgindex ( msgtype ) ;
2017-08-10 01:41:51 +07:00
rtnl_lock ( ) ;
handlers = rtnl_dereference ( rtnl_msg_handlers [ protocol ] ) ;
if ( ! handlers ) {
rtnl_unlock ( ) ;
2007-03-23 01:48:11 +07:00
return - ENOENT ;
2017-08-10 01:41:51 +07:00
}
2007-03-23 01:48:11 +07:00
2017-08-10 01:41:51 +07:00
handlers [ msgindex ] . doit = NULL ;
handlers [ msgindex ] . dumpit = NULL ;
2017-08-10 01:41:52 +07:00
handlers [ msgindex ] . flags = 0 ;
2017-08-10 01:41:51 +07:00
rtnl_unlock ( ) ;
2007-03-23 01:48:11 +07:00
return 0 ;
}
EXPORT_SYMBOL_GPL ( rtnl_unregister ) ;
/**
* rtnl_unregister_all - Unregister all rtnetlink message type of a protocol
* @ protocol : Protocol family or PF_UNSPEC
*
* Identical to calling rtnl_unregster ( ) for all registered message types
* of a certain protocol family .
*/
void rtnl_unregister_all ( int protocol )
{
2017-08-10 01:41:49 +07:00
struct rtnl_link * handlers ;
2010-04-26 21:02:05 +07:00
BUG_ON ( protocol < 0 | | protocol > RTNL_FAMILY_MAX ) ;
2007-03-23 01:48:11 +07:00
2017-08-10 01:41:49 +07:00
rtnl_lock ( ) ;
2017-08-10 01:41:51 +07:00
handlers = rtnl_dereference ( rtnl_msg_handlers [ protocol ] ) ;
RCU_INIT_POINTER ( rtnl_msg_handlers [ protocol ] , NULL ) ;
2017-08-10 01:41:49 +07:00
rtnl_unlock ( ) ;
2017-08-10 01:41:51 +07:00
synchronize_net ( ) ;
2017-08-10 21:53:00 +07:00
while ( refcount_read ( & rtnl_msg_handlers_ref [ protocol ] ) > 1 )
2017-08-10 01:41:49 +07:00
schedule ( ) ;
kfree ( handlers ) ;
2007-03-23 01:48:11 +07:00
}
EXPORT_SYMBOL_GPL ( rtnl_unregister_all ) ;
2005-04-17 05:20:36 +07:00
2007-06-14 02:03:51 +07:00
static LIST_HEAD ( link_ops ) ;
2011-12-13 18:38:00 +07:00
static const struct rtnl_link_ops * rtnl_link_ops_get ( const char * kind )
{
const struct rtnl_link_ops * ops ;
list_for_each_entry ( ops , & link_ops , list ) {
if ( ! strcmp ( ops - > kind , kind ) )
return ops ;
}
return NULL ;
}
2007-06-14 02:03:51 +07:00
/**
* __rtnl_link_register - Register rtnl_link_ops with rtnetlink .
* @ ops : struct rtnl_link_ops * to register
*
* The caller must hold the rtnl_mutex . This function should be used
* by drivers that create devices during module initialization . It
* must be called before registering the devices .
*
* Returns 0 on success or a negative error code .
*/
int __rtnl_link_register ( struct rtnl_link_ops * ops )
{
2011-12-13 18:38:00 +07:00
if ( rtnl_link_ops_get ( ops - > kind ) )
return - EEXIST ;
2014-06-26 14:58:25 +07:00
/* The check for setup is here because if ops
* does not have that filled up , it is not possible
* to use the ops for creating device . So do not
* fill up dellink as well . That disables rtnl_dellink .
*/
if ( ops - > setup & & ! ops - > dellink )
2009-10-27 14:06:36 +07:00
ops - > dellink = unregister_netdevice_queue ;
2007-07-12 09:42:13 +07:00
2007-06-14 02:03:51 +07:00
list_add_tail ( & ops - > list , & link_ops ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( __rtnl_link_register ) ;
/**
* rtnl_link_register - Register rtnl_link_ops with rtnetlink .
* @ ops : struct rtnl_link_ops * to register
*
* Returns 0 on success or a negative error code .
*/
int rtnl_link_register ( struct rtnl_link_ops * ops )
{
int err ;
rtnl_lock ( ) ;
err = __rtnl_link_register ( ops ) ;
rtnl_unlock ( ) ;
return err ;
}
EXPORT_SYMBOL_GPL ( rtnl_link_register ) ;
2008-04-16 14:46:52 +07:00
static void __rtnl_kill_links ( struct net * net , struct rtnl_link_ops * ops )
{
struct net_device * dev ;
2009-10-27 14:06:36 +07:00
LIST_HEAD ( list_kill ) ;
2008-04-16 14:46:52 +07:00
for_each_netdev ( net , dev ) {
2009-10-27 14:06:36 +07:00
if ( dev - > rtnl_link_ops = = ops )
ops - > dellink ( dev , & list_kill ) ;
2008-04-16 14:46:52 +07:00
}
2009-10-27 14:06:36 +07:00
unregister_netdevice_many ( & list_kill ) ;
2008-04-16 14:46:52 +07:00
}
2007-06-14 02:03:51 +07:00
/**
* __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink .
* @ ops : struct rtnl_link_ops * to unregister
*
2007-07-12 09:42:13 +07:00
* The caller must hold the rtnl_mutex .
2007-06-14 02:03:51 +07:00
*/
void __rtnl_link_unregister ( struct rtnl_link_ops * ops )
{
2007-09-18 01:56:21 +07:00
struct net * net ;
2007-07-12 09:42:13 +07:00
2007-09-18 01:56:21 +07:00
for_each_net ( net ) {
2008-04-16 14:46:52 +07:00
__rtnl_kill_links ( net , ops ) ;
2007-07-12 09:42:13 +07:00
}
2007-06-14 02:03:51 +07:00
list_del ( & ops - > list ) ;
}
EXPORT_SYMBOL_GPL ( __rtnl_link_unregister ) ;
2014-05-13 05:11:20 +07:00
/* Return with the rtnl_lock held when there are no network
* devices unregistering in any network namespace .
*/
static void rtnl_lock_unregistering_all ( void )
{
struct net * net ;
bool unregistering ;
2014-10-29 23:04:56 +07:00
DEFINE_WAIT_FUNC ( wait , woken_wake_function ) ;
2014-05-13 05:11:20 +07:00
2014-10-29 23:04:56 +07:00
add_wait_queue ( & netdev_unregistering_wq , & wait ) ;
2014-05-13 05:11:20 +07:00
for ( ; ; ) {
unregistering = false ;
rtnl_lock ( ) ;
for_each_net ( net ) {
if ( net - > dev_unreg_count > 0 ) {
unregistering = true ;
break ;
}
}
if ( ! unregistering )
break ;
__rtnl_unlock ( ) ;
2014-10-29 23:04:56 +07:00
wait_woken ( & wait , TASK_UNINTERRUPTIBLE , MAX_SCHEDULE_TIMEOUT ) ;
2014-05-13 05:11:20 +07:00
}
2014-10-29 23:04:56 +07:00
remove_wait_queue ( & netdev_unregistering_wq , & wait ) ;
2014-05-13 05:11:20 +07:00
}
2007-06-14 02:03:51 +07:00
/**
* rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink .
* @ ops : struct rtnl_link_ops * to unregister
*/
void rtnl_link_unregister ( struct rtnl_link_ops * ops )
{
2014-05-13 05:11:20 +07:00
/* Close the race with cleanup_net() */
mutex_lock ( & net_mutex ) ;
rtnl_lock_unregistering_all ( ) ;
2007-06-14 02:03:51 +07:00
__rtnl_link_unregister ( ops ) ;
rtnl_unlock ( ) ;
2014-05-13 05:11:20 +07:00
mutex_unlock ( & net_mutex ) ;
2007-06-14 02:03:51 +07:00
}
EXPORT_SYMBOL_GPL ( rtnl_link_unregister ) ;
2014-01-22 15:05:55 +07:00
static size_t rtnl_link_get_slave_info_data_size ( const struct net_device * dev )
{
struct net_device * master_dev ;
const struct rtnl_link_ops * ops ;
2017-08-10 21:52:59 +07:00
size_t size = 0 ;
2014-01-22 15:05:55 +07:00
2017-08-10 21:52:59 +07:00
rcu_read_lock ( ) ;
master_dev = netdev_master_upper_dev_get_rcu ( ( struct net_device * ) dev ) ;
2014-01-22 15:05:55 +07:00
if ( ! master_dev )
2017-08-10 21:52:59 +07:00
goto out ;
2014-01-22 15:05:55 +07:00
ops = master_dev - > rtnl_link_ops ;
2014-02-04 17:35:02 +07:00
if ( ! ops | | ! ops - > get_slave_size )
2017-08-10 21:52:59 +07:00
goto out ;
2014-01-22 15:05:55 +07:00
/* IFLA_INFO_SLAVE_DATA + nested data */
2017-08-10 21:52:59 +07:00
size = nla_total_size ( sizeof ( struct nlattr ) ) +
2014-01-22 15:05:55 +07:00
ops - > get_slave_size ( master_dev , dev ) ;
2017-08-10 21:52:59 +07:00
out :
rcu_read_unlock ( ) ;
return size ;
2014-01-22 15:05:55 +07:00
}
2007-06-14 02:03:51 +07:00
static size_t rtnl_link_get_size ( const struct net_device * dev )
{
const struct rtnl_link_ops * ops = dev - > rtnl_link_ops ;
size_t size ;
if ( ! ops )
return 0 ;
2010-11-11 22:47:59 +07:00
size = nla_total_size ( sizeof ( struct nlattr ) ) + /* IFLA_LINKINFO */
nla_total_size ( strlen ( ops - > kind ) + 1 ) ; /* IFLA_INFO_KIND */
2007-06-14 02:03:51 +07:00
if ( ops - > get_size )
/* IFLA_INFO_DATA + nested data */
2010-11-11 22:47:59 +07:00
size + = nla_total_size ( sizeof ( struct nlattr ) ) +
2007-06-14 02:03:51 +07:00
ops - > get_size ( dev ) ;
if ( ops - > get_xstats_size )
2010-11-11 22:47:59 +07:00
/* IFLA_INFO_XSTATS */
size + = nla_total_size ( ops - > get_xstats_size ( dev ) ) ;
2007-06-14 02:03:51 +07:00
2014-01-22 15:05:55 +07:00
size + = rtnl_link_get_slave_info_data_size ( dev ) ;
2007-06-14 02:03:51 +07:00
return size ;
}
2010-11-16 11:30:14 +07:00
static LIST_HEAD ( rtnl_af_ops ) ;
static const struct rtnl_af_ops * rtnl_af_lookup ( const int family )
{
const struct rtnl_af_ops * ops ;
list_for_each_entry ( ops , & rtnl_af_ops , list ) {
if ( ops - > family = = family )
return ops ;
}
return NULL ;
}
/**
* rtnl_af_register - Register rtnl_af_ops with rtnetlink .
* @ ops : struct rtnl_af_ops * to register
*
* Returns 0 on success or a negative error code .
*/
2013-12-31 01:41:32 +07:00
void rtnl_af_register ( struct rtnl_af_ops * ops )
2010-11-16 11:30:14 +07:00
{
rtnl_lock ( ) ;
2013-12-31 01:41:32 +07:00
list_add_tail ( & ops - > list , & rtnl_af_ops ) ;
2010-11-16 11:30:14 +07:00
rtnl_unlock ( ) ;
}
EXPORT_SYMBOL_GPL ( rtnl_af_register ) ;
/**
* __rtnl_af_unregister - Unregister rtnl_af_ops from rtnetlink .
* @ ops : struct rtnl_af_ops * to unregister
*
* The caller must hold the rtnl_mutex .
*/
void __rtnl_af_unregister ( struct rtnl_af_ops * ops )
{
list_del ( & ops - > list ) ;
}
EXPORT_SYMBOL_GPL ( __rtnl_af_unregister ) ;
/**
* rtnl_af_unregister - Unregister rtnl_af_ops from rtnetlink .
* @ ops : struct rtnl_af_ops * to unregister
*/
void rtnl_af_unregister ( struct rtnl_af_ops * ops )
{
rtnl_lock ( ) ;
__rtnl_af_unregister ( ops ) ;
rtnl_unlock ( ) ;
}
EXPORT_SYMBOL_GPL ( rtnl_af_unregister ) ;
2015-10-19 23:23:28 +07:00
static size_t rtnl_link_get_af_size ( const struct net_device * dev ,
u32 ext_filter_mask )
2010-11-16 11:30:14 +07:00
{
struct rtnl_af_ops * af_ops ;
size_t size ;
/* IFLA_AF_SPEC */
size = nla_total_size ( sizeof ( struct nlattr ) ) ;
list_for_each_entry ( af_ops , & rtnl_af_ops , list ) {
if ( af_ops - > get_link_af_size ) {
/* AF_* + nested data */
size + = nla_total_size ( sizeof ( struct nlattr ) ) +
2015-10-19 23:23:28 +07:00
af_ops - > get_link_af_size ( dev , ext_filter_mask ) ;
2010-11-16 11:30:14 +07:00
}
}
return size ;
}
2014-01-22 15:05:55 +07:00
static bool rtnl_have_link_slave_info ( const struct net_device * dev )
2007-06-14 02:03:51 +07:00
{
2014-01-22 15:05:55 +07:00
struct net_device * master_dev ;
2017-09-26 18:58:43 +07:00
bool ret = false ;
2007-06-14 02:03:51 +07:00
2017-09-26 18:58:43 +07:00
rcu_read_lock ( ) ;
master_dev = netdev_master_upper_dev_get_rcu ( ( struct net_device * ) dev ) ;
2014-01-24 01:19:21 +07:00
if ( master_dev & & master_dev - > rtnl_link_ops )
2017-09-26 18:58:43 +07:00
ret = true ;
rcu_read_unlock ( ) ;
return ret ;
2014-01-22 15:05:55 +07:00
}
static int rtnl_link_slave_info_fill ( struct sk_buff * skb ,
const struct net_device * dev )
{
struct net_device * master_dev ;
const struct rtnl_link_ops * ops ;
struct nlattr * slave_data ;
int err ;
2007-06-14 02:03:51 +07:00
2014-01-22 15:05:55 +07:00
master_dev = netdev_master_upper_dev_get ( ( struct net_device * ) dev ) ;
if ( ! master_dev )
return 0 ;
ops = master_dev - > rtnl_link_ops ;
if ( ! ops )
return 0 ;
if ( nla_put_string ( skb , IFLA_INFO_SLAVE_KIND , ops - > kind ) < 0 )
return - EMSGSIZE ;
if ( ops - > fill_slave_info ) {
slave_data = nla_nest_start ( skb , IFLA_INFO_SLAVE_DATA ) ;
if ( ! slave_data )
return - EMSGSIZE ;
err = ops - > fill_slave_info ( skb , master_dev , dev ) ;
if ( err < 0 )
goto err_cancel_slave_data ;
nla_nest_end ( skb , slave_data ) ;
}
return 0 ;
err_cancel_slave_data :
nla_nest_cancel ( skb , slave_data ) ;
return err ;
}
static int rtnl_link_info_fill ( struct sk_buff * skb ,
const struct net_device * dev )
{
const struct rtnl_link_ops * ops = dev - > rtnl_link_ops ;
struct nlattr * data ;
int err ;
if ( ! ops )
return 0 ;
2007-06-14 02:03:51 +07:00
if ( nla_put_string ( skb , IFLA_INFO_KIND , ops - > kind ) < 0 )
2014-01-22 15:05:55 +07:00
return - EMSGSIZE ;
2007-06-14 02:03:51 +07:00
if ( ops - > fill_xstats ) {
err = ops - > fill_xstats ( skb , dev ) ;
if ( err < 0 )
2014-01-22 15:05:55 +07:00
return err ;
2007-06-14 02:03:51 +07:00
}
if ( ops - > fill_info ) {
data = nla_nest_start ( skb , IFLA_INFO_DATA ) ;
2014-01-22 15:05:55 +07:00
if ( data = = NULL )
return - EMSGSIZE ;
2007-06-14 02:03:51 +07:00
err = ops - > fill_info ( skb , dev ) ;
if ( err < 0 )
goto err_cancel_data ;
nla_nest_end ( skb , data ) ;
}
return 0 ;
err_cancel_data :
nla_nest_cancel ( skb , data ) ;
2014-01-22 15:05:55 +07:00
return err ;
}
static int rtnl_link_fill ( struct sk_buff * skb , const struct net_device * dev )
{
struct nlattr * linkinfo ;
int err = - EMSGSIZE ;
linkinfo = nla_nest_start ( skb , IFLA_LINKINFO ) ;
if ( linkinfo = = NULL )
goto out ;
err = rtnl_link_info_fill ( skb , dev ) ;
if ( err < 0 )
goto err_cancel_link ;
err = rtnl_link_slave_info_fill ( skb , dev ) ;
if ( err < 0 )
goto err_cancel_link ;
nla_nest_end ( skb , linkinfo ) ;
return 0 ;
2007-06-14 02:03:51 +07:00
err_cancel_link :
nla_nest_cancel ( skb , linkinfo ) ;
out :
return err ;
}
2012-04-15 12:58:06 +07:00
int rtnetlink_send ( struct sk_buff * skb , struct net * net , u32 pid , unsigned int group , int echo )
2005-04-17 05:20:36 +07:00
{
2007-11-20 13:26:51 +07:00
struct sock * rtnl = net - > rtnl ;
2005-04-17 05:20:36 +07:00
int err = 0 ;
2005-08-15 09:29:52 +07:00
NETLINK_CB ( skb ) . dst_group = group ;
2005-04-17 05:20:36 +07:00
if ( echo )
2017-06-30 17:07:58 +07:00
refcount_inc ( & skb - > users ) ;
2005-04-17 05:20:36 +07:00
netlink_broadcast ( rtnl , skb , pid , group , GFP_KERNEL ) ;
if ( echo )
err = netlink_unicast ( rtnl , skb , pid , MSG_DONTWAIT ) ;
return err ;
}
2007-11-20 13:26:51 +07:00
int rtnl_unicast ( struct sk_buff * skb , struct net * net , u32 pid )
2006-08-15 14:30:25 +07:00
{
2007-11-20 13:26:51 +07:00
struct sock * rtnl = net - > rtnl ;
2006-08-15 14:30:25 +07:00
return nlmsg_unicast ( rtnl , skb , pid ) ;
}
2009-11-07 16:26:17 +07:00
EXPORT_SYMBOL ( rtnl_unicast ) ;
2006-08-15 14:30:25 +07:00
2009-02-25 14:18:28 +07:00
void rtnl_notify ( struct sk_buff * skb , struct net * net , u32 pid , u32 group ,
struct nlmsghdr * nlh , gfp_t flags )
2006-08-15 14:31:41 +07:00
{
2007-11-20 13:26:51 +07:00
struct sock * rtnl = net - > rtnl ;
2006-08-15 14:31:41 +07:00
int report = 0 ;
if ( nlh )
report = nlmsg_report ( nlh ) ;
2009-02-25 14:18:28 +07:00
nlmsg_notify ( rtnl , skb , pid , group , report , flags ) ;
2006-08-15 14:31:41 +07:00
}
2009-11-07 16:26:17 +07:00
EXPORT_SYMBOL ( rtnl_notify ) ;
2006-08-15 14:31:41 +07:00
2007-11-20 13:26:51 +07:00
void rtnl_set_sk_err ( struct net * net , u32 group , int error )
2006-08-15 14:31:41 +07:00
{
2007-11-20 13:26:51 +07:00
struct sock * rtnl = net - > rtnl ;
2006-08-15 14:31:41 +07:00
netlink_set_err ( rtnl , 0 , group , error ) ;
}
2009-11-07 16:26:17 +07:00
EXPORT_SYMBOL ( rtnl_set_sk_err ) ;
2006-08-15 14:31:41 +07:00
2005-04-17 05:20:36 +07:00
int rtnetlink_put_metrics ( struct sk_buff * skb , u32 * metrics )
{
2006-08-22 14:01:27 +07:00
struct nlattr * mx ;
int i , valid = 0 ;
mx = nla_nest_start ( skb , RTA_METRICS ) ;
if ( mx = = NULL )
return - ENOBUFS ;
for ( i = 0 ; i < RTAX_MAX ; i + + ) {
if ( metrics [ i ] ) {
2015-01-06 05:57:47 +07:00
if ( i = = RTAX_CC_ALGO - 1 ) {
char tmp [ TCP_CA_NAME_MAX ] , * name ;
name = tcp_ca_get_name_by_key ( metrics [ i ] , tmp ) ;
if ( ! name )
continue ;
if ( nla_put_string ( skb , i + 1 , name ) )
goto nla_put_failure ;
tcp: use dctcp if enabled on the route to the initiator
Currently, the following case doesn't use DCTCP, even if it should:
A responder has f.e. Cubic as system wide default, but for a specific
route to the initiating host, DCTCP is being set in RTAX_CC_ALGO. The
initiating host then uses DCTCP as congestion control, but since the
initiator sets ECT(0), tcp_ecn_create_request() doesn't set ecn_ok,
and we have to fall back to Reno after 3WHS completes.
We were thinking on how to solve this in a minimal, non-intrusive
way without bloating tcp_ecn_create_request() needlessly: lets cache
the CA ecn option flag in RTAX_FEATURES. In other words, when ECT(0)
is set on the SYN packet, set ecn_ok=1 iff route RTAX_FEATURES
contains the unexposed (internal-only) DST_FEATURE_ECN_CA. This allows
to only do a single metric feature lookup inside tcp_ecn_create_request().
Joint work with Florian Westphal.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-08-31 20:58:47 +07:00
} else if ( i = = RTAX_FEATURES - 1 ) {
u32 user_features = metrics [ i ] & RTAX_FEATURE_MASK ;
2016-08-23 18:14:31 +07:00
if ( ! user_features )
continue ;
tcp: use dctcp if enabled on the route to the initiator
Currently, the following case doesn't use DCTCP, even if it should:
A responder has f.e. Cubic as system wide default, but for a specific
route to the initiating host, DCTCP is being set in RTAX_CC_ALGO. The
initiating host then uses DCTCP as congestion control, but since the
initiator sets ECT(0), tcp_ecn_create_request() doesn't set ecn_ok,
and we have to fall back to Reno after 3WHS completes.
We were thinking on how to solve this in a minimal, non-intrusive
way without bloating tcp_ecn_create_request() needlessly: lets cache
the CA ecn option flag in RTAX_FEATURES. In other words, when ECT(0)
is set on the SYN packet, set ecn_ok=1 iff route RTAX_FEATURES
contains the unexposed (internal-only) DST_FEATURE_ECN_CA. This allows
to only do a single metric feature lookup inside tcp_ecn_create_request().
Joint work with Florian Westphal.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-08-31 20:58:47 +07:00
BUILD_BUG_ON ( RTAX_FEATURE_MASK & DST_FEATURE_MASK ) ;
if ( nla_put_u32 ( skb , i + 1 , user_features ) )
goto nla_put_failure ;
2015-01-06 05:57:47 +07:00
} else {
if ( nla_put_u32 ( skb , i + 1 , metrics [ i ] ) )
goto nla_put_failure ;
}
2006-08-22 14:01:27 +07:00
valid + + ;
}
2005-04-17 05:20:36 +07:00
}
2006-08-23 12:20:14 +07:00
if ( ! valid ) {
nla_nest_cancel ( skb , mx ) ;
return 0 ;
}
2006-08-22 14:01:27 +07:00
return nla_nest_end ( skb , mx ) ;
nla_put_failure :
2008-06-04 06:36:54 +07:00
nla_nest_cancel ( skb , mx ) ;
return - EMSGSIZE ;
2005-04-17 05:20:36 +07:00
}
2009-11-07 16:26:17 +07:00
EXPORT_SYMBOL ( rtnetlink_put_metrics ) ;
2005-04-17 05:20:36 +07:00
2006-11-28 00:27:07 +07:00
int rtnl_put_cacheinfo ( struct sk_buff * skb , struct dst_entry * dst , u32 id ,
2012-07-10 19:06:14 +07:00
long expires , u32 error )
2006-11-28 00:27:07 +07:00
{
struct rta_cacheinfo ci = {
2012-08-09 04:13:53 +07:00
. rta_lastuse = jiffies_delta_to_clock_t ( jiffies - dst - > lastuse ) ,
2006-11-28 00:27:07 +07:00
. rta_used = dst - > __use ,
. rta_clntref = atomic_read ( & ( dst - > __refcnt ) ) ,
. rta_error = error ,
. rta_id = id ,
} ;
2012-07-29 23:01:30 +07:00
if ( expires ) {
unsigned long clock ;
2006-11-28 00:27:07 +07:00
2012-07-29 23:01:30 +07:00
clock = jiffies_to_clock_t ( abs ( expires ) ) ;
clock = min_t ( unsigned long , clock , INT_MAX ) ;
ci . rta_expires = ( expires > 0 ) ? clock : - clock ;
}
2006-11-28 00:27:07 +07:00
return nla_put ( skb , RTA_CACHEINFO , sizeof ( ci ) , & ci ) ;
}
EXPORT_SYMBOL_GPL ( rtnl_put_cacheinfo ) ;
2005-04-17 05:20:36 +07:00
2008-02-18 09:35:07 +07:00
static void set_operstate ( struct net_device * dev , unsigned char transition )
2006-03-21 08:09:11 +07:00
{
unsigned char operstate = dev - > operstate ;
2009-11-07 16:26:17 +07:00
switch ( transition ) {
2006-03-21 08:09:11 +07:00
case IF_OPER_UP :
if ( ( operstate = = IF_OPER_DORMANT | |
operstate = = IF_OPER_UNKNOWN ) & &
! netif_dormant ( dev ) )
operstate = IF_OPER_UP ;
break ;
case IF_OPER_DORMANT :
if ( operstate = = IF_OPER_UP | |
operstate = = IF_OPER_UNKNOWN )
operstate = IF_OPER_DORMANT ;
break ;
2007-04-21 07:09:22 +07:00
}
2006-03-21 08:09:11 +07:00
if ( dev - > operstate ! = operstate ) {
write_lock_bh ( & dev_base_lock ) ;
dev - > operstate = operstate ;
write_unlock_bh ( & dev_base_lock ) ;
2008-02-18 09:35:07 +07:00
netdev_state_change ( dev ) ;
}
2006-03-21 08:09:11 +07:00
}
2012-07-27 09:58:22 +07:00
static unsigned int rtnl_dev_get_flags ( const struct net_device * dev )
{
return ( dev - > flags & ~ ( IFF_PROMISC | IFF_ALLMULTI ) ) |
( dev - > gflags & ( IFF_PROMISC | IFF_ALLMULTI ) ) ;
}
rtnetlink: support specifying device flags on device creation
commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f
Author: Patrick McHardy <kaber@trash.net>
Date: Tue Feb 23 20:41:30 2010 +0100
Support specifying the initial device flags when creating a device though
rtnl_link. Devices allocated by rtnl_create_link() are marked as INITIALIZING
in order to surpress netlink registration notifications. To complete setup,
rtnl_configure_link() must be called, which performs the device flag changes
and invokes the deferred notifiers if everything went well.
Two examples:
# add macvlan to eth0
#
$ ip link add link eth0 up allmulticast on type macvlan
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 26:f8:84:02:f9:2a brd ff:ff:ff:ff:ff:ff
[ROUTE]ff00::/8 dev macvlan0 table local metric 256 mtu 1500 advmss 1440 hoplimit 0
[ROUTE]fe80::/64 dev macvlan0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500
link/ether 26:f8:84:02:f9:2a
[ADDR]11: macvlan0 inet6 fe80::24f8:84ff:fe02:f92a/64 scope link
valid_lft forever preferred_lft forever
[ROUTE]local fe80::24f8:84ff:fe02:f92a via :: dev lo table local proto none metric 0 mtu 16436 advmss 16376 hoplimit 0
[ROUTE]default via fe80::215:e9ff:fef0:10f8 dev macvlan0 proto kernel metric 1024 mtu 1500 advmss 1440 hoplimit 0
[NEIGH]fe80::215:e9ff:fef0:10f8 dev macvlan0 lladdr 00:15:e9:f0:10:f8 router STALE
[ROUTE]2001:6f8:974::/64 dev macvlan0 proto kernel metric 256 expires 0sec mtu 1500 advmss 1440 hoplimit 0
[PREFIX]prefix 2001:6f8:974::/64 dev macvlan0 onlink autoconf valid 14400 preferred 131084
[ADDR]11: macvlan0 inet6 2001:6f8:974:0:24f8:84ff:fe02:f92a/64 scope global dynamic
valid_lft 86399sec preferred_lft 14399sec
# add VLAN to eth1, eth1 is down
#
$ ip link add link eth1 up type vlan id 1000
RTNETLINK answers: Network is down
<no events>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-02-26 13:34:54 +07:00
static unsigned int rtnl_dev_combine_flags ( const struct net_device * dev ,
const struct ifinfomsg * ifm )
{
unsigned int flags = ifm - > ifi_flags ;
/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
if ( ifm - > ifi_change )
flags = ( flags & ifm - > ifi_change ) |
2012-07-27 09:58:22 +07:00
( rtnl_dev_get_flags ( dev ) & ~ ifm - > ifi_change ) ;
rtnetlink: support specifying device flags on device creation
commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f
Author: Patrick McHardy <kaber@trash.net>
Date: Tue Feb 23 20:41:30 2010 +0100
Support specifying the initial device flags when creating a device though
rtnl_link. Devices allocated by rtnl_create_link() are marked as INITIALIZING
in order to surpress netlink registration notifications. To complete setup,
rtnl_configure_link() must be called, which performs the device flag changes
and invokes the deferred notifiers if everything went well.
Two examples:
# add macvlan to eth0
#
$ ip link add link eth0 up allmulticast on type macvlan
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 26:f8:84:02:f9:2a brd ff:ff:ff:ff:ff:ff
[ROUTE]ff00::/8 dev macvlan0 table local metric 256 mtu 1500 advmss 1440 hoplimit 0
[ROUTE]fe80::/64 dev macvlan0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500
link/ether 26:f8:84:02:f9:2a
[ADDR]11: macvlan0 inet6 fe80::24f8:84ff:fe02:f92a/64 scope link
valid_lft forever preferred_lft forever
[ROUTE]local fe80::24f8:84ff:fe02:f92a via :: dev lo table local proto none metric 0 mtu 16436 advmss 16376 hoplimit 0
[ROUTE]default via fe80::215:e9ff:fef0:10f8 dev macvlan0 proto kernel metric 1024 mtu 1500 advmss 1440 hoplimit 0
[NEIGH]fe80::215:e9ff:fef0:10f8 dev macvlan0 lladdr 00:15:e9:f0:10:f8 router STALE
[ROUTE]2001:6f8:974::/64 dev macvlan0 proto kernel metric 256 expires 0sec mtu 1500 advmss 1440 hoplimit 0
[PREFIX]prefix 2001:6f8:974::/64 dev macvlan0 onlink autoconf valid 14400 preferred 131084
[ADDR]11: macvlan0 inet6 2001:6f8:974:0:24f8:84ff:fe02:f92a/64 scope global dynamic
valid_lft 86399sec preferred_lft 14399sec
# add VLAN to eth1, eth1 is down
#
$ ip link add link eth1 up type vlan id 1000
RTNETLINK answers: Network is down
<no events>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-02-26 13:34:54 +07:00
return flags ;
}
2006-08-05 13:05:34 +07:00
static void copy_rtnl_link_stats ( struct rtnl_link_stats * a ,
2010-06-08 14:19:54 +07:00
const struct rtnl_link_stats64 * b )
2005-04-17 05:20:36 +07:00
{
2006-08-05 13:05:34 +07:00
a - > rx_packets = b - > rx_packets ;
a - > tx_packets = b - > tx_packets ;
a - > rx_bytes = b - > rx_bytes ;
a - > tx_bytes = b - > tx_bytes ;
a - > rx_errors = b - > rx_errors ;
a - > tx_errors = b - > tx_errors ;
a - > rx_dropped = b - > rx_dropped ;
a - > tx_dropped = b - > tx_dropped ;
a - > multicast = b - > multicast ;
a - > collisions = b - > collisions ;
a - > rx_length_errors = b - > rx_length_errors ;
a - > rx_over_errors = b - > rx_over_errors ;
a - > rx_crc_errors = b - > rx_crc_errors ;
a - > rx_frame_errors = b - > rx_frame_errors ;
a - > rx_fifo_errors = b - > rx_fifo_errors ;
a - > rx_missed_errors = b - > rx_missed_errors ;
a - > tx_aborted_errors = b - > tx_aborted_errors ;
a - > tx_carrier_errors = b - > tx_carrier_errors ;
a - > tx_fifo_errors = b - > tx_fifo_errors ;
a - > tx_heartbeat_errors = b - > tx_heartbeat_errors ;
a - > tx_window_errors = b - > tx_window_errors ;
a - > rx_compressed = b - > rx_compressed ;
a - > tx_compressed = b - > tx_compressed ;
2016-02-02 06:51:05 +07:00
a - > rx_nohandler = b - > rx_nohandler ;
2010-03-11 16:57:29 +07:00
}
2010-05-16 15:05:45 +07:00
/* All VF info */
2012-02-22 04:54:48 +07:00
static inline int rtnl_vfinfo_size ( const struct net_device * dev ,
u32 ext_filter_mask )
2010-02-10 08:44:05 +07:00
{
2017-01-18 20:04:39 +07:00
if ( dev - > dev . parent & & ( ext_filter_mask & RTEXT_FILTER_VF ) ) {
2010-05-16 15:05:45 +07:00
int num_vfs = dev_num_vf ( dev - > dev . parent ) ;
2016-11-15 16:39:03 +07:00
size_t size = nla_total_size ( 0 ) ;
2010-05-28 17:42:43 +07:00
size + = num_vfs *
2016-11-15 16:39:03 +07:00
( nla_total_size ( 0 ) +
nla_total_size ( sizeof ( struct ifla_vf_mac ) ) +
nla_total_size ( sizeof ( struct ifla_vf_vlan ) ) +
nla_total_size ( 0 ) + /* nest IFLA_VF_VLAN_LIST */
2016-09-22 16:11:15 +07:00
nla_total_size ( MAX_VLAN_LIST_LEN *
sizeof ( struct ifla_vf_vlan_info ) ) +
net-next:v4: Add support to configure SR-IOV VF minimum and maximum Tx rate through ip tool.
o min_tx_rate puts lower limit on the VF bandwidth. VF is guaranteed
to have a bandwidth of at least this value.
max_tx_rate puts cap on the VF bandwidth. VF can have a bandwidth
of up to this value.
o A new handler set_vf_rate for attr IFLA_VF_RATE has been introduced
which takes 4 arguments:
netdev, VF number, min_tx_rate, max_tx_rate
o ndo_set_vf_rate replaces ndo_set_vf_tx_rate handler.
o Drivers that currently implement ndo_set_vf_tx_rate should now call
ndo_set_vf_rate instead and reject attempt to set a minimum bandwidth
greater than 0 for IFLA_VF_TX_RATE when IFLA_VF_RATE is not yet
implemented by driver.
o If user enters only one of either min_tx_rate or max_tx_rate, then,
userland should read back the other value from driver and set both
for IFLA_VF_RATE.
Drivers that have not yet implemented IFLA_VF_RATE should always
return min_tx_rate as 0 when read from ip tool.
o If both IFLA_VF_TX_RATE and IFLA_VF_RATE options are specified, then
IFLA_VF_RATE should override.
o Idea is to have consistent display of rate values to user.
o Usage example: -
./ip link set p4p1 vf 0 rate 900
./ip link show p4p1
32: p4p1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode
DEFAULT qlen 1000
link/ether 00:0e:1e:08:b0:f0 brd ff:ff:ff:ff:ff:ff
vf 0 MAC 3e:a0:ca:bd:ae:5a, tx rate 900 (Mbps), max_tx_rate 900Mbps
vf 1 MAC f6:c6:7c:3f:3d:6c
vf 2 MAC 56:32:43:98:d7:71
vf 3 MAC d6:be:c3:b5:85:ff
vf 4 MAC ee:a9:9a:1e:19:14
vf 5 MAC 4a:d0:4c:07:52:18
vf 6 MAC 3a:76:44:93:62:f9
vf 7 MAC 82:e9:e7:e3:15:1a
./ip link set p4p1 vf 0 max_tx_rate 300 min_tx_rate 200
./ip link show p4p1
32: p4p1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode
DEFAULT qlen 1000
link/ether 00:0e:1e:08:b0:f0 brd ff:ff:ff:ff:ff:ff
vf 0 MAC 3e:a0:ca:bd:ae:5a, tx rate 300 (Mbps), max_tx_rate 300Mbps,
min_tx_rate 200Mbps
vf 1 MAC f6:c6:7c:3f:3d:6c
vf 2 MAC 56:32:43:98:d7:71
vf 3 MAC d6:be:c3:b5:85:ff
vf 4 MAC ee:a9:9a:1e:19:14
vf 5 MAC 4a:d0:4c:07:52:18
vf 6 MAC 3a:76:44:93:62:f9
vf 7 MAC 82:e9:e7:e3:15:1a
./ip link set p4p1 vf 0 max_tx_rate 600 rate 300
./ip link show p4p1
32: p4p1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode
DEFAULT qlen 1000
link/ether 00:0e:1e:08:b0:f brd ff:ff:ff:ff:ff:ff
vf 0 MAC 3e:a0:ca:bd:ae:5, tx rate 600 (Mbps), max_tx_rate 600Mbps,
min_tx_rate 200Mbps
vf 1 MAC f6:c6:7c:3f:3d:6c
vf 2 MAC 56:32:43:98:d7:71
vf 3 MAC d6:be:c3:b5:85:ff
vf 4 MAC ee:a9:9a:1e:19:14
vf 5 MAC 4a:d0:4c:07:52:18
vf 6 MAC 3a:76:44:93:62:f9
vf 7 MAC 82:e9:e7:e3:15:1a
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-05-22 20:59:05 +07:00
nla_total_size ( sizeof ( struct ifla_vf_spoofchk ) ) +
2016-11-15 16:39:03 +07:00
nla_total_size ( sizeof ( struct ifla_vf_tx_rate ) ) +
2014-08-08 21:44:32 +07:00
nla_total_size ( sizeof ( struct ifla_vf_rate ) ) +
2015-03-31 01:35:23 +07:00
nla_total_size ( sizeof ( struct ifla_vf_link_state ) ) +
2015-06-15 21:59:07 +07:00
nla_total_size ( sizeof ( struct ifla_vf_rss_query_en ) ) +
2016-11-15 16:39:03 +07:00
nla_total_size ( 0 ) + /* nest IFLA_VF_STATS */
2015-06-15 21:59:07 +07:00
/* IFLA_VF_STATS_RX_PACKETS */
2016-04-25 15:25:14 +07:00
nla_total_size_64bit ( sizeof ( __u64 ) ) +
2015-06-15 21:59:07 +07:00
/* IFLA_VF_STATS_TX_PACKETS */
2016-04-25 15:25:14 +07:00
nla_total_size_64bit ( sizeof ( __u64 ) ) +
2015-06-15 21:59:07 +07:00
/* IFLA_VF_STATS_RX_BYTES */
2016-04-25 15:25:14 +07:00
nla_total_size_64bit ( sizeof ( __u64 ) ) +
2015-06-15 21:59:07 +07:00
/* IFLA_VF_STATS_TX_BYTES */
2016-04-25 15:25:14 +07:00
nla_total_size_64bit ( sizeof ( __u64 ) ) +
2015-06-15 21:59:07 +07:00
/* IFLA_VF_STATS_BROADCAST */
2016-04-25 15:25:14 +07:00
nla_total_size_64bit ( sizeof ( __u64 ) ) +
2015-06-15 21:59:07 +07:00
/* IFLA_VF_STATS_MULTICAST */
2016-04-25 15:25:14 +07:00
nla_total_size_64bit ( sizeof ( __u64 ) ) +
2015-08-28 13:57:55 +07:00
nla_total_size ( sizeof ( struct ifla_vf_trust ) ) ) ;
2010-05-16 15:05:45 +07:00
return size ;
} else
2010-02-10 08:44:05 +07:00
return 0 ;
}
2014-04-24 07:22:36 +07:00
static size_t rtnl_port_size ( const struct net_device * dev ,
u32 ext_filter_mask )
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
{
size_t port_size = nla_total_size ( 4 ) /* PORT_VF */
+ nla_total_size ( PORT_PROFILE_MAX ) /* PORT_PROFILE */
+ nla_total_size ( PORT_UUID_MAX ) /* PORT_INSTANCE_UUID */
+ nla_total_size ( PORT_UUID_MAX ) /* PORT_HOST_UUID */
+ nla_total_size ( 1 ) /* PROT_VDP_REQUEST */
+ nla_total_size ( 2 ) ; /* PORT_VDP_RESPONSE */
size_t vf_ports_size = nla_total_size ( sizeof ( struct nlattr ) ) ;
size_t vf_port_size = nla_total_size ( sizeof ( struct nlattr ) )
+ port_size ;
size_t port_self_size = nla_total_size ( sizeof ( struct nlattr ) )
+ port_size ;
2014-04-24 07:22:36 +07:00
if ( ! dev - > netdev_ops - > ndo_get_vf_port | | ! dev - > dev . parent | |
! ( ext_filter_mask & RTEXT_FILTER_VF ) )
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
return 0 ;
if ( dev_num_vf ( dev - > dev . parent ) )
return port_self_size + vf_ports_size +
vf_port_size * dev_num_vf ( dev - > dev . parent ) ;
else
return port_self_size ;
}
2017-04-19 02:36:58 +07:00
static size_t rtnl_xdp_size ( void )
2016-07-20 02:16:49 +07:00
{
2016-11-15 17:16:35 +07:00
size_t xdp_size = nla_total_size ( 0 ) + /* nest IFLA_XDP */
2017-06-16 07:29:09 +07:00
nla_total_size ( 1 ) + /* XDP_ATTACHED */
nla_total_size ( 4 ) ; /* XDP_PROG_ID */
2016-07-20 02:16:49 +07:00
2017-04-19 02:36:58 +07:00
return xdp_size ;
2016-07-20 02:16:49 +07:00
}
2012-02-22 04:54:48 +07:00
static noinline size_t if_nlmsg_size ( const struct net_device * dev ,
u32 ext_filter_mask )
2006-11-11 05:10:15 +07:00
{
return NLMSG_ALIGN ( sizeof ( struct ifinfomsg ) )
+ nla_total_size ( IFNAMSIZ ) /* IFLA_IFNAME */
2008-09-23 11:28:11 +07:00
+ nla_total_size ( IFALIASZ ) /* IFLA_IFALIAS */
2006-11-11 05:10:15 +07:00
+ nla_total_size ( IFNAMSIZ ) /* IFLA_QDISC */
2016-04-26 15:06:16 +07:00
+ nla_total_size_64bit ( sizeof ( struct rtnl_link_ifmap ) )
2006-11-11 05:10:15 +07:00
+ nla_total_size ( sizeof ( struct rtnl_link_stats ) )
2016-04-20 06:49:29 +07:00
+ nla_total_size_64bit ( sizeof ( struct rtnl_link_stats64 ) )
2006-11-11 05:10:15 +07:00
+ nla_total_size ( MAX_ADDR_LEN ) /* IFLA_ADDRESS */
+ nla_total_size ( MAX_ADDR_LEN ) /* IFLA_BROADCAST */
+ nla_total_size ( 4 ) /* IFLA_TXQLEN */
+ nla_total_size ( 4 ) /* IFLA_WEIGHT */
+ nla_total_size ( 4 ) /* IFLA_MTU */
+ nla_total_size ( 4 ) /* IFLA_LINK */
+ nla_total_size ( 4 ) /* IFLA_MASTER */
2012-12-28 06:49:39 +07:00
+ nla_total_size ( 1 ) /* IFLA_CARRIER */
2012-03-29 19:51:30 +07:00
+ nla_total_size ( 4 ) /* IFLA_PROMISCUITY */
2012-07-20 09:28:48 +07:00
+ nla_total_size ( 4 ) /* IFLA_NUM_TX_QUEUES */
+ nla_total_size ( 4 ) /* IFLA_NUM_RX_QUEUES */
2016-11-30 20:30:37 +07:00
+ nla_total_size ( 4 ) /* IFLA_GSO_MAX_SEGS */
+ nla_total_size ( 4 ) /* IFLA_GSO_MAX_SIZE */
2006-11-11 05:10:15 +07:00
+ nla_total_size ( 1 ) /* IFLA_OPERSTATE */
2007-06-14 02:03:51 +07:00
+ nla_total_size ( 1 ) /* IFLA_LINKMODE */
2014-03-29 23:48:35 +07:00
+ nla_total_size ( 4 ) /* IFLA_CARRIER_CHANGES */
2015-01-15 21:11:16 +07:00
+ nla_total_size ( 4 ) /* IFLA_LINK_NETNSID */
2017-06-20 18:35:23 +07:00
+ nla_total_size ( 4 ) /* IFLA_GROUP */
2012-02-22 04:54:48 +07:00
+ nla_total_size ( ext_filter_mask
& RTEXT_FILTER_VF ? 4 : 0 ) /* IFLA_NUM_VF */
+ rtnl_vfinfo_size ( dev , ext_filter_mask ) /* IFLA_VFINFO_LIST */
2014-04-24 07:22:36 +07:00
+ rtnl_port_size ( dev , ext_filter_mask ) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
2010-11-16 11:30:14 +07:00
+ rtnl_link_get_size ( dev ) /* IFLA_LINKINFO */
2015-10-19 23:23:28 +07:00
+ rtnl_link_get_af_size ( dev , ext_filter_mask ) /* IFLA_AF_SPEC */
2014-11-28 20:34:18 +07:00
+ nla_total_size ( MAX_PHYS_ITEM_ID_LEN ) /* IFLA_PHYS_PORT_ID */
2015-07-15 03:43:20 +07:00
+ nla_total_size ( MAX_PHYS_ITEM_ID_LEN ) /* IFLA_PHYS_SWITCH_ID */
2016-03-31 23:10:31 +07:00
+ nla_total_size ( IFNAMSIZ ) /* IFLA_PHYS_PORT_NAME */
2017-04-19 02:36:58 +07:00
+ rtnl_xdp_size ( ) /* IFLA_XDP */
2017-05-27 21:14:34 +07:00
+ nla_total_size ( 4 ) /* IFLA_EVENT */
2015-07-15 03:43:20 +07:00
+ nla_total_size ( 1 ) ; /* IFLA_PROTO_DOWN */
2006-11-11 05:10:15 +07:00
}
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
static int rtnl_vf_ports_fill ( struct sk_buff * skb , struct net_device * dev )
{
struct nlattr * vf_ports ;
struct nlattr * vf_port ;
int vf ;
int err ;
vf_ports = nla_nest_start ( skb , IFLA_VF_PORTS ) ;
if ( ! vf_ports )
return - EMSGSIZE ;
for ( vf = 0 ; vf < dev_num_vf ( dev - > dev . parent ) ; vf + + ) {
vf_port = nla_nest_start ( skb , IFLA_VF_PORT ) ;
2010-05-28 17:42:18 +07:00
if ( ! vf_port )
goto nla_put_failure ;
2012-04-02 07:12:00 +07:00
if ( nla_put_u32 ( skb , IFLA_PORT_VF , vf ) )
goto nla_put_failure ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
err = dev - > netdev_ops - > ndo_get_vf_port ( dev , vf , skb ) ;
2010-05-28 17:42:18 +07:00
if ( err = = - EMSGSIZE )
goto nla_put_failure ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
if ( err ) {
nla_nest_cancel ( skb , vf_port ) ;
continue ;
}
nla_nest_end ( skb , vf_port ) ;
}
nla_nest_end ( skb , vf_ports ) ;
return 0 ;
2010-05-28 17:42:18 +07:00
nla_put_failure :
nla_nest_cancel ( skb , vf_ports ) ;
return - EMSGSIZE ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
}
static int rtnl_port_self_fill ( struct sk_buff * skb , struct net_device * dev )
{
struct nlattr * port_self ;
int err ;
port_self = nla_nest_start ( skb , IFLA_PORT_SELF ) ;
if ( ! port_self )
return - EMSGSIZE ;
err = dev - > netdev_ops - > ndo_get_vf_port ( dev , PORT_SELF_VF , skb ) ;
if ( err ) {
nla_nest_cancel ( skb , port_self ) ;
2010-05-28 17:42:18 +07:00
return ( err = = - EMSGSIZE ) ? err : 0 ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
}
nla_nest_end ( skb , port_self ) ;
return 0 ;
}
2014-04-24 07:22:36 +07:00
static int rtnl_port_fill ( struct sk_buff * skb , struct net_device * dev ,
u32 ext_filter_mask )
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
{
int err ;
2014-04-24 07:22:36 +07:00
if ( ! dev - > netdev_ops - > ndo_get_vf_port | | ! dev - > dev . parent | |
! ( ext_filter_mask & RTEXT_FILTER_VF ) )
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
return 0 ;
err = rtnl_port_self_fill ( skb , dev ) ;
if ( err )
return err ;
if ( dev_num_vf ( dev - > dev . parent ) ) {
err = rtnl_vf_ports_fill ( skb , dev ) ;
if ( err )
return err ;
}
return 0 ;
}
2013-07-29 23:16:50 +07:00
static int rtnl_phys_port_id_fill ( struct sk_buff * skb , struct net_device * dev )
{
int err ;
2014-11-28 20:34:16 +07:00
struct netdev_phys_item_id ppid ;
2013-07-29 23:16:50 +07:00
err = dev_get_phys_port_id ( dev , & ppid ) ;
if ( err ) {
if ( err = = - EOPNOTSUPP )
return 0 ;
return err ;
}
if ( nla_put ( skb , IFLA_PHYS_PORT_ID , ppid . id_len , ppid . id ) )
return - EMSGSIZE ;
return 0 ;
}
2015-03-18 09:23:15 +07:00
static int rtnl_phys_port_name_fill ( struct sk_buff * skb , struct net_device * dev )
{
char name [ IFNAMSIZ ] ;
int err ;
err = dev_get_phys_port_name ( dev , name , sizeof ( name ) ) ;
if ( err ) {
if ( err = = - EOPNOTSUPP )
return 0 ;
return err ;
}
2017-05-04 21:48:58 +07:00
if ( nla_put_string ( skb , IFLA_PHYS_PORT_NAME , name ) )
2015-03-18 09:23:15 +07:00
return - EMSGSIZE ;
return 0 ;
}
2014-11-28 20:34:18 +07:00
static int rtnl_phys_switch_id_fill ( struct sk_buff * skb , struct net_device * dev )
{
int err ;
2015-05-10 23:47:49 +07:00
struct switchdev_attr attr = {
2015-12-15 22:03:35 +07:00
. orig_dev = dev ,
2015-10-01 16:03:42 +07:00
. id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID ,
2015-05-10 23:47:49 +07:00
. flags = SWITCHDEV_F_NO_RECURSE ,
} ;
2014-11-28 20:34:18 +07:00
2015-05-10 23:47:49 +07:00
err = switchdev_port_attr_get ( dev , & attr ) ;
2014-11-28 20:34:18 +07:00
if ( err ) {
if ( err = = - EOPNOTSUPP )
return 0 ;
return err ;
}
2015-05-14 01:16:50 +07:00
if ( nla_put ( skb , IFLA_PHYS_SWITCH_ID , attr . u . ppid . id_len ,
attr . u . ppid . id ) )
2014-11-28 20:34:18 +07:00
return - EMSGSIZE ;
return 0 ;
}
2015-11-17 20:16:52 +07:00
static noinline_for_stack int rtnl_fill_stats ( struct sk_buff * skb ,
struct net_device * dev )
{
2016-04-16 10:36:25 +07:00
struct rtnl_link_stats64 * sp ;
2015-11-17 20:16:52 +07:00
struct nlattr * attr ;
2016-04-20 01:30:10 +07:00
2016-04-21 23:58:25 +07:00
attr = nla_reserve_64bit ( skb , IFLA_STATS64 ,
sizeof ( struct rtnl_link_stats64 ) , IFLA_PAD ) ;
2015-11-17 20:16:52 +07:00
if ( ! attr )
return - EMSGSIZE ;
2016-04-16 10:36:25 +07:00
sp = nla_data ( attr ) ;
dev_get_stats ( dev , sp ) ;
2015-11-17 20:16:52 +07:00
2016-04-16 10:36:25 +07:00
attr = nla_reserve ( skb , IFLA_STATS ,
sizeof ( struct rtnl_link_stats ) ) ;
2015-11-17 20:16:52 +07:00
if ( ! attr )
return - EMSGSIZE ;
2016-04-16 10:36:25 +07:00
copy_rtnl_link_stats ( nla_data ( attr ) , sp ) ;
2015-11-17 20:16:52 +07:00
return 0 ;
}
static noinline_for_stack int rtnl_fill_vfinfo ( struct sk_buff * skb ,
struct net_device * dev ,
int vfs_num ,
struct nlattr * vfinfo )
{
struct ifla_vf_rss_query_en vf_rss_query_en ;
2016-09-22 16:11:15 +07:00
struct nlattr * vf , * vfstats , * vfvlanlist ;
2015-11-17 20:16:52 +07:00
struct ifla_vf_link_state vf_linkstate ;
2016-09-22 16:11:15 +07:00
struct ifla_vf_vlan_info vf_vlan_info ;
2015-11-17 20:16:52 +07:00
struct ifla_vf_spoofchk vf_spoofchk ;
struct ifla_vf_tx_rate vf_tx_rate ;
struct ifla_vf_stats vf_stats ;
struct ifla_vf_trust vf_trust ;
struct ifla_vf_vlan vf_vlan ;
struct ifla_vf_rate vf_rate ;
struct ifla_vf_mac vf_mac ;
struct ifla_vf_info ivi ;
2017-06-08 01:00:33 +07:00
memset ( & ivi , 0 , sizeof ( ivi ) ) ;
2015-11-17 20:16:52 +07:00
/* Not all SR-IOV capable drivers support the
* spoofcheck and " RSS query enable " query . Preset to
* - 1 so the user space tool can detect that the driver
* didn ' t report anything .
*/
ivi . spoofchk = - 1 ;
ivi . rss_query_en = - 1 ;
ivi . trusted = - 1 ;
/* The default value for VF link state is "auto"
* IFLA_VF_LINK_STATE_AUTO which equals zero
*/
ivi . linkstate = 0 ;
2016-09-22 16:11:15 +07:00
/* VLAN Protocol by default is 802.1Q */
ivi . vlan_proto = htons ( ETH_P_8021Q ) ;
2015-11-17 20:16:52 +07:00
if ( dev - > netdev_ops - > ndo_get_vf_config ( dev , vfs_num , & ivi ) )
return 0 ;
2016-10-13 15:45:28 +07:00
memset ( & vf_vlan_info , 0 , sizeof ( vf_vlan_info ) ) ;
2015-11-17 20:16:52 +07:00
vf_mac . vf =
vf_vlan . vf =
2016-09-22 16:11:15 +07:00
vf_vlan_info . vf =
2015-11-17 20:16:52 +07:00
vf_rate . vf =
vf_tx_rate . vf =
vf_spoofchk . vf =
vf_linkstate . vf =
vf_rss_query_en . vf =
vf_trust . vf = ivi . vf ;
memcpy ( vf_mac . mac , ivi . mac , sizeof ( ivi . mac ) ) ;
vf_vlan . vlan = ivi . vlan ;
vf_vlan . qos = ivi . qos ;
2016-09-22 16:11:15 +07:00
vf_vlan_info . vlan = ivi . vlan ;
vf_vlan_info . qos = ivi . qos ;
vf_vlan_info . vlan_proto = ivi . vlan_proto ;
2015-11-17 20:16:52 +07:00
vf_tx_rate . rate = ivi . max_tx_rate ;
vf_rate . min_tx_rate = ivi . min_tx_rate ;
vf_rate . max_tx_rate = ivi . max_tx_rate ;
vf_spoofchk . setting = ivi . spoofchk ;
vf_linkstate . link_state = ivi . linkstate ;
vf_rss_query_en . setting = ivi . rss_query_en ;
vf_trust . setting = ivi . trusted ;
vf = nla_nest_start ( skb , IFLA_VF_INFO ) ;
2016-09-22 16:11:15 +07:00
if ( ! vf )
goto nla_put_vfinfo_failure ;
2015-11-17 20:16:52 +07:00
if ( nla_put ( skb , IFLA_VF_MAC , sizeof ( vf_mac ) , & vf_mac ) | |
nla_put ( skb , IFLA_VF_VLAN , sizeof ( vf_vlan ) , & vf_vlan ) | |
nla_put ( skb , IFLA_VF_RATE , sizeof ( vf_rate ) ,
& vf_rate ) | |
nla_put ( skb , IFLA_VF_TX_RATE , sizeof ( vf_tx_rate ) ,
& vf_tx_rate ) | |
nla_put ( skb , IFLA_VF_SPOOFCHK , sizeof ( vf_spoofchk ) ,
& vf_spoofchk ) | |
nla_put ( skb , IFLA_VF_LINK_STATE , sizeof ( vf_linkstate ) ,
& vf_linkstate ) | |
nla_put ( skb , IFLA_VF_RSS_QUERY_EN ,
sizeof ( vf_rss_query_en ) ,
& vf_rss_query_en ) | |
nla_put ( skb , IFLA_VF_TRUST ,
sizeof ( vf_trust ) , & vf_trust ) )
2016-09-22 16:11:15 +07:00
goto nla_put_vf_failure ;
vfvlanlist = nla_nest_start ( skb , IFLA_VF_VLAN_LIST ) ;
if ( ! vfvlanlist )
goto nla_put_vf_failure ;
if ( nla_put ( skb , IFLA_VF_VLAN_INFO , sizeof ( vf_vlan_info ) ,
& vf_vlan_info ) ) {
nla_nest_cancel ( skb , vfvlanlist ) ;
goto nla_put_vf_failure ;
}
nla_nest_end ( skb , vfvlanlist ) ;
2015-11-17 20:16:52 +07:00
memset ( & vf_stats , 0 , sizeof ( vf_stats ) ) ;
if ( dev - > netdev_ops - > ndo_get_vf_stats )
dev - > netdev_ops - > ndo_get_vf_stats ( dev , vfs_num ,
& vf_stats ) ;
vfstats = nla_nest_start ( skb , IFLA_VF_STATS ) ;
2016-09-22 16:11:15 +07:00
if ( ! vfstats )
goto nla_put_vf_failure ;
2016-04-25 15:25:14 +07:00
if ( nla_put_u64_64bit ( skb , IFLA_VF_STATS_RX_PACKETS ,
vf_stats . rx_packets , IFLA_VF_STATS_PAD ) | |
nla_put_u64_64bit ( skb , IFLA_VF_STATS_TX_PACKETS ,
vf_stats . tx_packets , IFLA_VF_STATS_PAD ) | |
nla_put_u64_64bit ( skb , IFLA_VF_STATS_RX_BYTES ,
vf_stats . rx_bytes , IFLA_VF_STATS_PAD ) | |
nla_put_u64_64bit ( skb , IFLA_VF_STATS_TX_BYTES ,
vf_stats . tx_bytes , IFLA_VF_STATS_PAD ) | |
nla_put_u64_64bit ( skb , IFLA_VF_STATS_BROADCAST ,
vf_stats . broadcast , IFLA_VF_STATS_PAD ) | |
nla_put_u64_64bit ( skb , IFLA_VF_STATS_MULTICAST ,
2016-09-22 16:11:15 +07:00
vf_stats . multicast , IFLA_VF_STATS_PAD ) ) {
nla_nest_cancel ( skb , vfstats ) ;
goto nla_put_vf_failure ;
}
2015-11-17 20:16:52 +07:00
nla_nest_end ( skb , vfstats ) ;
nla_nest_end ( skb , vf ) ;
return 0 ;
2016-09-22 16:11:15 +07:00
nla_put_vf_failure :
nla_nest_cancel ( skb , vf ) ;
nla_put_vfinfo_failure :
nla_nest_cancel ( skb , vfinfo ) ;
return - EMSGSIZE ;
2015-11-17 20:16:52 +07:00
}
2017-09-26 18:58:41 +07:00
static noinline_for_stack int rtnl_fill_vf ( struct sk_buff * skb ,
struct net_device * dev ,
u32 ext_filter_mask )
{
struct nlattr * vfinfo ;
int i , num_vfs ;
if ( ! dev - > dev . parent | | ( ( ext_filter_mask & RTEXT_FILTER_VF ) = = 0 ) )
return 0 ;
num_vfs = dev_num_vf ( dev - > dev . parent ) ;
if ( nla_put_u32 ( skb , IFLA_NUM_VF , num_vfs ) )
return - EMSGSIZE ;
if ( ! dev - > netdev_ops - > ndo_get_vf_config )
return 0 ;
vfinfo = nla_nest_start ( skb , IFLA_VFINFO_LIST ) ;
if ( ! vfinfo )
return - EMSGSIZE ;
for ( i = 0 ; i < num_vfs ; i + + ) {
if ( rtnl_fill_vfinfo ( skb , dev , i , vfinfo ) )
return - EMSGSIZE ;
}
nla_nest_end ( skb , vfinfo ) ;
return 0 ;
}
2015-11-17 20:16:52 +07:00
static int rtnl_fill_link_ifmap ( struct sk_buff * skb , struct net_device * dev )
{
2016-05-04 03:46:24 +07:00
struct rtnl_link_ifmap map ;
memset ( & map , 0 , sizeof ( map ) ) ;
map . mem_start = dev - > mem_start ;
map . mem_end = dev - > mem_end ;
map . base_addr = dev - > base_addr ;
map . irq = dev - > irq ;
map . dma = dev - > dma ;
map . port = dev - > if_port ;
2016-04-26 15:06:16 +07:00
if ( nla_put_64bit ( skb , IFLA_MAP , sizeof ( map ) , & map , IFLA_PAD ) )
2015-11-17 20:16:52 +07:00
return - EMSGSIZE ;
return 0 ;
}
2017-06-16 07:29:09 +07:00
static u8 rtnl_xdp_attached_mode ( struct net_device * dev , u32 * prog_id )
xdp: refine xdp api with regards to generic xdp
While working on the iproute2 generic XDP frontend, I noticed that
as of right now it's possible to have native *and* generic XDP
programs loaded both at the same time for the case when a driver
supports native XDP.
The intended model for generic XDP from b5cdae3291f7 ("net: Generic
XDP") is, however, that only one out of the two can be present at
once which is also indicated as such in the XDP netlink dump part.
The main rationale for generic XDP is to ease accessibility (in
case a driver does not yet have XDP support) and to generically
provide a semantical model as an example for driver developers
wanting to add XDP support. The generic XDP option for an XDP
aware driver can still be useful for comparing and testing both
implementations.
However, it is not intended to have a second XDP processing stage
or layer with exactly the same functionality of the first native
stage. Only reason could be to have a partial fallback for future
XDP features that are not supported yet in the native implementation
and we probably also shouldn't strive for such fallback and instead
encourage native feature support in the first place. Given there's
currently no such fallback issue or use case, lets not go there yet
if we don't need to.
Therefore, change semantics for loading XDP and bail out if the
user tries to load a generic XDP program when a native one is
present and vice versa. Another alternative to bailing out would
be to handle the transition from one flavor to another gracefully,
but that would require to bring the device down, exchange both
types of programs, and bring it up again in order to avoid a tiny
window where a packet could hit both hooks. Given this complicates
the logic for just a debugging feature in the native case, I went
with the simpler variant.
For the dump, remove IFLA_XDP_FLAGS that was added with b5cdae3291f7
and reuse IFLA_XDP_ATTACHED for indicating the mode. Dumping all
or just a subset of flags that were used for loading the XDP prog
is suboptimal in the long run since not all flags are useful for
dumping and if we start to reuse the same flag definitions for
load and dump, then we'll waste bit space. What we really just
want is to dump the mode for now.
Current IFLA_XDP_ATTACHED semantics are: nothing was installed (0),
a program is running at the native driver layer (1). Thus, add a
mode that says that a program is running at generic XDP layer (2).
Applications will handle this fine in that older binaries will
just indicate that something is attached at XDP layer, effectively
this is similar to IFLA_XDP_FLAGS attr that we would have had
modulo the redundancy.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-05-12 06:04:46 +07:00
{
const struct net_device_ops * ops = dev - > netdev_ops ;
2017-06-16 07:29:09 +07:00
const struct bpf_prog * generic_xdp_prog ;
xdp: refine xdp api with regards to generic xdp
While working on the iproute2 generic XDP frontend, I noticed that
as of right now it's possible to have native *and* generic XDP
programs loaded both at the same time for the case when a driver
supports native XDP.
The intended model for generic XDP from b5cdae3291f7 ("net: Generic
XDP") is, however, that only one out of the two can be present at
once which is also indicated as such in the XDP netlink dump part.
The main rationale for generic XDP is to ease accessibility (in
case a driver does not yet have XDP support) and to generically
provide a semantical model as an example for driver developers
wanting to add XDP support. The generic XDP option for an XDP
aware driver can still be useful for comparing and testing both
implementations.
However, it is not intended to have a second XDP processing stage
or layer with exactly the same functionality of the first native
stage. Only reason could be to have a partial fallback for future
XDP features that are not supported yet in the native implementation
and we probably also shouldn't strive for such fallback and instead
encourage native feature support in the first place. Given there's
currently no such fallback issue or use case, lets not go there yet
if we don't need to.
Therefore, change semantics for loading XDP and bail out if the
user tries to load a generic XDP program when a native one is
present and vice versa. Another alternative to bailing out would
be to handle the transition from one flavor to another gracefully,
but that would require to bring the device down, exchange both
types of programs, and bring it up again in order to avoid a tiny
window where a packet could hit both hooks. Given this complicates
the logic for just a debugging feature in the native case, I went
with the simpler variant.
For the dump, remove IFLA_XDP_FLAGS that was added with b5cdae3291f7
and reuse IFLA_XDP_ATTACHED for indicating the mode. Dumping all
or just a subset of flags that were used for loading the XDP prog
is suboptimal in the long run since not all flags are useful for
dumping and if we start to reuse the same flag definitions for
load and dump, then we'll waste bit space. What we really just
want is to dump the mode for now.
Current IFLA_XDP_ATTACHED semantics are: nothing was installed (0),
a program is running at the native driver layer (1). Thus, add a
mode that says that a program is running at generic XDP layer (2).
Applications will handle this fine in that older binaries will
just indicate that something is attached at XDP layer, effectively
this is similar to IFLA_XDP_FLAGS attr that we would have had
modulo the redundancy.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-05-12 06:04:46 +07:00
ASSERT_RTNL ( ) ;
2017-06-16 07:29:09 +07:00
* prog_id = 0 ;
generic_xdp_prog = rtnl_dereference ( dev - > xdp_prog ) ;
if ( generic_xdp_prog ) {
* prog_id = generic_xdp_prog - > aux - > id ;
xdp: refine xdp api with regards to generic xdp
While working on the iproute2 generic XDP frontend, I noticed that
as of right now it's possible to have native *and* generic XDP
programs loaded both at the same time for the case when a driver
supports native XDP.
The intended model for generic XDP from b5cdae3291f7 ("net: Generic
XDP") is, however, that only one out of the two can be present at
once which is also indicated as such in the XDP netlink dump part.
The main rationale for generic XDP is to ease accessibility (in
case a driver does not yet have XDP support) and to generically
provide a semantical model as an example for driver developers
wanting to add XDP support. The generic XDP option for an XDP
aware driver can still be useful for comparing and testing both
implementations.
However, it is not intended to have a second XDP processing stage
or layer with exactly the same functionality of the first native
stage. Only reason could be to have a partial fallback for future
XDP features that are not supported yet in the native implementation
and we probably also shouldn't strive for such fallback and instead
encourage native feature support in the first place. Given there's
currently no such fallback issue or use case, lets not go there yet
if we don't need to.
Therefore, change semantics for loading XDP and bail out if the
user tries to load a generic XDP program when a native one is
present and vice versa. Another alternative to bailing out would
be to handle the transition from one flavor to another gracefully,
but that would require to bring the device down, exchange both
types of programs, and bring it up again in order to avoid a tiny
window where a packet could hit both hooks. Given this complicates
the logic for just a debugging feature in the native case, I went
with the simpler variant.
For the dump, remove IFLA_XDP_FLAGS that was added with b5cdae3291f7
and reuse IFLA_XDP_ATTACHED for indicating the mode. Dumping all
or just a subset of flags that were used for loading the XDP prog
is suboptimal in the long run since not all flags are useful for
dumping and if we start to reuse the same flag definitions for
load and dump, then we'll waste bit space. What we really just
want is to dump the mode for now.
Current IFLA_XDP_ATTACHED semantics are: nothing was installed (0),
a program is running at the native driver layer (1). Thus, add a
mode that says that a program is running at generic XDP layer (2).
Applications will handle this fine in that older binaries will
just indicate that something is attached at XDP layer, effectively
this is similar to IFLA_XDP_FLAGS attr that we would have had
modulo the redundancy.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-05-12 06:04:46 +07:00
return XDP_ATTACHED_SKB ;
2017-06-16 07:29:09 +07:00
}
2017-06-22 08:25:09 +07:00
if ( ! ops - > ndo_xdp )
return XDP_ATTACHED_NONE ;
xdp: refine xdp api with regards to generic xdp
While working on the iproute2 generic XDP frontend, I noticed that
as of right now it's possible to have native *and* generic XDP
programs loaded both at the same time for the case when a driver
supports native XDP.
The intended model for generic XDP from b5cdae3291f7 ("net: Generic
XDP") is, however, that only one out of the two can be present at
once which is also indicated as such in the XDP netlink dump part.
The main rationale for generic XDP is to ease accessibility (in
case a driver does not yet have XDP support) and to generically
provide a semantical model as an example for driver developers
wanting to add XDP support. The generic XDP option for an XDP
aware driver can still be useful for comparing and testing both
implementations.
However, it is not intended to have a second XDP processing stage
or layer with exactly the same functionality of the first native
stage. Only reason could be to have a partial fallback for future
XDP features that are not supported yet in the native implementation
and we probably also shouldn't strive for such fallback and instead
encourage native feature support in the first place. Given there's
currently no such fallback issue or use case, lets not go there yet
if we don't need to.
Therefore, change semantics for loading XDP and bail out if the
user tries to load a generic XDP program when a native one is
present and vice versa. Another alternative to bailing out would
be to handle the transition from one flavor to another gracefully,
but that would require to bring the device down, exchange both
types of programs, and bring it up again in order to avoid a tiny
window where a packet could hit both hooks. Given this complicates
the logic for just a debugging feature in the native case, I went
with the simpler variant.
For the dump, remove IFLA_XDP_FLAGS that was added with b5cdae3291f7
and reuse IFLA_XDP_ATTACHED for indicating the mode. Dumping all
or just a subset of flags that were used for loading the XDP prog
is suboptimal in the long run since not all flags are useful for
dumping and if we start to reuse the same flag definitions for
load and dump, then we'll waste bit space. What we really just
want is to dump the mode for now.
Current IFLA_XDP_ATTACHED semantics are: nothing was installed (0),
a program is running at the native driver layer (1). Thus, add a
mode that says that a program is running at generic XDP layer (2).
Applications will handle this fine in that older binaries will
just indicate that something is attached at XDP layer, effectively
this is similar to IFLA_XDP_FLAGS attr that we would have had
modulo the redundancy.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-05-12 06:04:46 +07:00
2017-06-22 08:25:09 +07:00
return __dev_xdp_attached ( dev , ops - > ndo_xdp , prog_id ) ;
xdp: refine xdp api with regards to generic xdp
While working on the iproute2 generic XDP frontend, I noticed that
as of right now it's possible to have native *and* generic XDP
programs loaded both at the same time for the case when a driver
supports native XDP.
The intended model for generic XDP from b5cdae3291f7 ("net: Generic
XDP") is, however, that only one out of the two can be present at
once which is also indicated as such in the XDP netlink dump part.
The main rationale for generic XDP is to ease accessibility (in
case a driver does not yet have XDP support) and to generically
provide a semantical model as an example for driver developers
wanting to add XDP support. The generic XDP option for an XDP
aware driver can still be useful for comparing and testing both
implementations.
However, it is not intended to have a second XDP processing stage
or layer with exactly the same functionality of the first native
stage. Only reason could be to have a partial fallback for future
XDP features that are not supported yet in the native implementation
and we probably also shouldn't strive for such fallback and instead
encourage native feature support in the first place. Given there's
currently no such fallback issue or use case, lets not go there yet
if we don't need to.
Therefore, change semantics for loading XDP and bail out if the
user tries to load a generic XDP program when a native one is
present and vice versa. Another alternative to bailing out would
be to handle the transition from one flavor to another gracefully,
but that would require to bring the device down, exchange both
types of programs, and bring it up again in order to avoid a tiny
window where a packet could hit both hooks. Given this complicates
the logic for just a debugging feature in the native case, I went
with the simpler variant.
For the dump, remove IFLA_XDP_FLAGS that was added with b5cdae3291f7
and reuse IFLA_XDP_ATTACHED for indicating the mode. Dumping all
or just a subset of flags that were used for loading the XDP prog
is suboptimal in the long run since not all flags are useful for
dumping and if we start to reuse the same flag definitions for
load and dump, then we'll waste bit space. What we really just
want is to dump the mode for now.
Current IFLA_XDP_ATTACHED semantics are: nothing was installed (0),
a program is running at the native driver layer (1). Thus, add a
mode that says that a program is running at generic XDP layer (2).
Applications will handle this fine in that older binaries will
just indicate that something is attached at XDP layer, effectively
this is similar to IFLA_XDP_FLAGS attr that we would have had
modulo the redundancy.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-05-12 06:04:46 +07:00
}
2016-07-20 02:16:49 +07:00
static int rtnl_xdp_fill ( struct sk_buff * skb , struct net_device * dev )
{
struct nlattr * xdp ;
2017-06-16 07:29:09 +07:00
u32 prog_id ;
2016-07-20 02:16:49 +07:00
int err ;
xdp = nla_nest_start ( skb , IFLA_XDP ) ;
if ( ! xdp )
return - EMSGSIZE ;
xdp: refine xdp api with regards to generic xdp
While working on the iproute2 generic XDP frontend, I noticed that
as of right now it's possible to have native *and* generic XDP
programs loaded both at the same time for the case when a driver
supports native XDP.
The intended model for generic XDP from b5cdae3291f7 ("net: Generic
XDP") is, however, that only one out of the two can be present at
once which is also indicated as such in the XDP netlink dump part.
The main rationale for generic XDP is to ease accessibility (in
case a driver does not yet have XDP support) and to generically
provide a semantical model as an example for driver developers
wanting to add XDP support. The generic XDP option for an XDP
aware driver can still be useful for comparing and testing both
implementations.
However, it is not intended to have a second XDP processing stage
or layer with exactly the same functionality of the first native
stage. Only reason could be to have a partial fallback for future
XDP features that are not supported yet in the native implementation
and we probably also shouldn't strive for such fallback and instead
encourage native feature support in the first place. Given there's
currently no such fallback issue or use case, lets not go there yet
if we don't need to.
Therefore, change semantics for loading XDP and bail out if the
user tries to load a generic XDP program when a native one is
present and vice versa. Another alternative to bailing out would
be to handle the transition from one flavor to another gracefully,
but that would require to bring the device down, exchange both
types of programs, and bring it up again in order to avoid a tiny
window where a packet could hit both hooks. Given this complicates
the logic for just a debugging feature in the native case, I went
with the simpler variant.
For the dump, remove IFLA_XDP_FLAGS that was added with b5cdae3291f7
and reuse IFLA_XDP_ATTACHED for indicating the mode. Dumping all
or just a subset of flags that were used for loading the XDP prog
is suboptimal in the long run since not all flags are useful for
dumping and if we start to reuse the same flag definitions for
load and dump, then we'll waste bit space. What we really just
want is to dump the mode for now.
Current IFLA_XDP_ATTACHED semantics are: nothing was installed (0),
a program is running at the native driver layer (1). Thus, add a
mode that says that a program is running at generic XDP layer (2).
Applications will handle this fine in that older binaries will
just indicate that something is attached at XDP layer, effectively
this is similar to IFLA_XDP_FLAGS attr that we would have had
modulo the redundancy.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-05-12 06:04:46 +07:00
err = nla_put_u8 ( skb , IFLA_XDP_ATTACHED ,
2017-06-16 07:29:09 +07:00
rtnl_xdp_attached_mode ( dev , & prog_id ) ) ;
2016-07-20 02:16:49 +07:00
if ( err )
goto err_cancel ;
2017-06-16 07:29:09 +07:00
if ( prog_id ) {
err = nla_put_u32 ( skb , IFLA_XDP_PROG_ID , prog_id ) ;
if ( err )
goto err_cancel ;
}
2016-07-20 02:16:49 +07:00
nla_nest_end ( skb , xdp ) ;
return 0 ;
err_cancel :
nla_nest_cancel ( skb , xdp ) ;
return err ;
}
2017-05-27 21:14:34 +07:00
static u32 rtnl_get_event ( unsigned long event )
{
u32 rtnl_event_type = IFLA_EVENT_NONE ;
switch ( event ) {
case NETDEV_REBOOT :
rtnl_event_type = IFLA_EVENT_REBOOT ;
break ;
case NETDEV_FEAT_CHANGE :
rtnl_event_type = IFLA_EVENT_FEATURES ;
break ;
case NETDEV_BONDING_FAILOVER :
rtnl_event_type = IFLA_EVENT_BONDING_FAILOVER ;
break ;
case NETDEV_NOTIFY_PEERS :
rtnl_event_type = IFLA_EVENT_NOTIFY_PEERS ;
break ;
case NETDEV_RESEND_IGMP :
rtnl_event_type = IFLA_EVENT_IGMP_RESEND ;
break ;
case NETDEV_CHANGEINFODATA :
rtnl_event_type = IFLA_EVENT_BONDING_OPTIONS ;
break ;
default :
break ;
}
return rtnl_event_type ;
}
2017-09-26 18:58:40 +07:00
static int put_master_ifindex ( struct sk_buff * skb , struct net_device * dev )
{
const struct net_device * upper_dev ;
int ret = 0 ;
rcu_read_lock ( ) ;
upper_dev = netdev_master_upper_dev_get_rcu ( dev ) ;
if ( upper_dev )
ret = nla_put_u32 ( skb , IFLA_MASTER , upper_dev - > ifindex ) ;
rcu_read_unlock ( ) ;
return ret ;
}
static int nla_put_iflink ( struct sk_buff * skb , const struct net_device * dev )
{
int ifindex = dev_get_iflink ( dev ) ;
if ( dev - > ifindex = = ifindex )
return 0 ;
return nla_put_u32 ( skb , IFLA_LINK , ifindex ) ;
}
2017-10-03 04:50:05 +07:00
static noinline_for_stack int nla_put_ifalias ( struct sk_buff * skb ,
struct net_device * dev )
{
char buf [ IFALIASZ ] ;
int ret ;
ret = dev_get_alias ( dev , buf , sizeof ( buf ) ) ;
return ret > 0 ? nla_put_string ( skb , IFLA_IFALIAS , buf ) : 0 ;
}
2017-09-26 18:58:42 +07:00
static int rtnl_fill_link_netnsid ( struct sk_buff * skb ,
const struct net_device * dev )
{
if ( dev - > rtnl_link_ops & & dev - > rtnl_link_ops - > get_link_net ) {
struct net * link_net = dev - > rtnl_link_ops - > get_link_net ( dev ) ;
if ( ! net_eq ( dev_net ( dev ) , link_net ) ) {
int id = peernet2id_alloc ( dev_net ( dev ) , link_net ) ;
if ( nla_put_s32 ( skb , IFLA_LINK_NETNSID , id ) )
return - EMSGSIZE ;
}
}
return 0 ;
}
2006-08-05 13:05:34 +07:00
static int rtnl_fill_ifinfo ( struct sk_buff * skb , struct net_device * dev ,
2007-05-23 07:00:49 +07:00
int type , u32 pid , u32 seq , u32 change ,
2017-05-27 21:14:34 +07:00
unsigned int flags , u32 ext_filter_mask ,
u32 event )
2006-08-05 13:05:34 +07:00
{
struct ifinfomsg * ifm ;
struct nlmsghdr * nlh ;
2015-11-17 20:16:52 +07:00
struct nlattr * af_spec ;
2010-11-16 11:30:14 +07:00
struct rtnl_af_ops * af_ops ;
2005-04-17 05:20:36 +07:00
2011-05-25 14:34:04 +07:00
ASSERT_RTNL ( ) ;
2006-08-05 13:05:34 +07:00
nlh = nlmsg_put ( skb , pid , seq , type , sizeof ( * ifm ) , flags ) ;
if ( nlh = = NULL )
2007-02-01 14:16:40 +07:00
return - EMSGSIZE ;
2005-04-17 05:20:36 +07:00
2006-08-05 13:05:34 +07:00
ifm = nlmsg_data ( nlh ) ;
ifm - > ifi_family = AF_UNSPEC ;
ifm - > __ifi_pad = 0 ;
ifm - > ifi_type = dev - > type ;
ifm - > ifi_index = dev - > ifindex ;
ifm - > ifi_flags = dev_get_flags ( dev ) ;
ifm - > ifi_change = change ;
2012-04-02 07:12:00 +07:00
if ( nla_put_string ( skb , IFLA_IFNAME , dev - > name ) | |
nla_put_u32 ( skb , IFLA_TXQLEN , dev - > tx_queue_len ) | |
nla_put_u8 ( skb , IFLA_OPERSTATE ,
netif_running ( dev ) ? dev - > operstate : IF_OPER_DOWN ) | |
nla_put_u8 ( skb , IFLA_LINKMODE , dev - > link_mode ) | |
nla_put_u32 ( skb , IFLA_MTU , dev - > mtu ) | |
nla_put_u32 ( skb , IFLA_GROUP , dev - > group ) | |
2012-03-29 19:51:30 +07:00
nla_put_u32 ( skb , IFLA_PROMISCUITY , dev - > promiscuity ) | |
2012-07-20 09:28:48 +07:00
nla_put_u32 ( skb , IFLA_NUM_TX_QUEUES , dev - > num_tx_queues ) | |
2016-03-21 23:55:10 +07:00
nla_put_u32 ( skb , IFLA_GSO_MAX_SEGS , dev - > gso_max_segs ) | |
nla_put_u32 ( skb , IFLA_GSO_MAX_SIZE , dev - > gso_max_size ) | |
2012-07-20 20:35:13 +07:00
# ifdef CONFIG_RPS
2012-07-20 09:28:48 +07:00
nla_put_u32 ( skb , IFLA_NUM_RX_QUEUES , dev - > num_rx_queues ) | |
2012-07-20 20:35:13 +07:00
# endif
2017-09-26 18:58:40 +07:00
nla_put_iflink ( skb , dev ) | |
put_master_ifindex ( skb , dev ) | |
2012-12-28 06:49:39 +07:00
nla_put_u8 ( skb , IFLA_CARRIER , netif_carrier_ok ( dev ) ) | |
2012-04-02 07:12:00 +07:00
( dev - > qdisc & &
nla_put_string ( skb , IFLA_QDISC , dev - > qdisc - > ops - > id ) ) | |
2017-10-03 04:50:05 +07:00
nla_put_ifalias ( skb , dev ) | |
2014-03-29 23:48:35 +07:00
nla_put_u32 ( skb , IFLA_CARRIER_CHANGES ,
2015-07-15 03:43:20 +07:00
atomic_read ( & dev - > carrier_changes ) ) | |
nla_put_u8 ( skb , IFLA_PROTO_DOWN , dev - > proto_down ) )
2012-04-02 07:12:00 +07:00
goto nla_put_failure ;
2008-09-23 11:28:11 +07:00
2017-05-27 21:14:34 +07:00
if ( event ! = IFLA_EVENT_NONE ) {
if ( nla_put_u32 ( skb , IFLA_EVENT , event ) )
goto nla_put_failure ;
}
2015-11-17 20:16:52 +07:00
if ( rtnl_fill_link_ifmap ( skb , dev ) )
goto nla_put_failure ;
2005-04-17 05:20:36 +07:00
if ( dev - > addr_len ) {
2012-04-02 07:12:00 +07:00
if ( nla_put ( skb , IFLA_ADDRESS , dev - > addr_len , dev - > dev_addr ) | |
nla_put ( skb , IFLA_BROADCAST , dev - > addr_len , dev - > broadcast ) )
goto nla_put_failure ;
2005-04-17 05:20:36 +07:00
}
2013-07-29 23:16:50 +07:00
if ( rtnl_phys_port_id_fill ( skb , dev ) )
goto nla_put_failure ;
2015-03-18 09:23:15 +07:00
if ( rtnl_phys_port_name_fill ( skb , dev ) )
goto nla_put_failure ;
2014-11-28 20:34:18 +07:00
if ( rtnl_phys_switch_id_fill ( skb , dev ) )
goto nla_put_failure ;
2015-11-17 20:16:52 +07:00
if ( rtnl_fill_stats ( skb , dev ) )
2010-03-11 16:57:29 +07:00
goto nla_put_failure ;
2017-09-26 18:58:41 +07:00
if ( rtnl_fill_vf ( skb , dev , ext_filter_mask ) )
2012-04-02 07:12:00 +07:00
goto nla_put_failure ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
2014-04-24 07:22:36 +07:00
if ( rtnl_port_fill ( skb , dev , ext_filter_mask ) )
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
goto nla_put_failure ;
2016-07-20 02:16:49 +07:00
if ( rtnl_xdp_fill ( skb , dev ) )
goto nla_put_failure ;
2014-01-22 15:05:55 +07:00
if ( dev - > rtnl_link_ops | | rtnl_have_link_slave_info ( dev ) ) {
2007-06-14 02:03:51 +07:00
if ( rtnl_link_fill ( skb , dev ) < 0 )
goto nla_put_failure ;
}
2017-09-26 18:58:42 +07:00
if ( rtnl_fill_link_netnsid ( skb , dev ) )
goto nla_put_failure ;
2015-01-15 21:11:16 +07:00
2010-11-16 11:30:14 +07:00
if ( ! ( af_spec = nla_nest_start ( skb , IFLA_AF_SPEC ) ) )
goto nla_put_failure ;
list_for_each_entry ( af_ops , & rtnl_af_ops , list ) {
if ( af_ops - > fill_link_af ) {
struct nlattr * af ;
int err ;
if ( ! ( af = nla_nest_start ( skb , af_ops - > family ) ) )
goto nla_put_failure ;
2015-09-12 03:48:48 +07:00
err = af_ops - > fill_link_af ( skb , dev , ext_filter_mask ) ;
2010-11-16 11:30:14 +07:00
/*
* Caller may return ENODATA to indicate that there
* was no data to be dumped . This is not an error , it
* means we should trim the attribute header and
* continue .
*/
if ( err = = - ENODATA )
nla_nest_cancel ( skb , af ) ;
else if ( err < 0 )
goto nla_put_failure ;
nla_nest_end ( skb , af ) ;
}
}
nla_nest_end ( skb , af_spec ) ;
2015-01-17 04:09:00 +07:00
nlmsg_end ( skb , nlh ) ;
return 0 ;
2006-08-05 13:05:34 +07:00
nla_put_failure :
2007-02-01 14:16:40 +07:00
nlmsg_cancel ( skb , nlh ) ;
return - EMSGSIZE ;
2005-04-17 05:20:36 +07:00
}
2014-02-19 02:53:18 +07:00
static const struct nla_policy ifla_policy [ IFLA_MAX + 1 ] = {
2006-08-27 10:13:18 +07:00
[ IFLA_IFNAME ] = { . type = NLA_STRING , . len = IFNAMSIZ - 1 } ,
2007-06-14 02:03:51 +07:00
[ IFLA_ADDRESS ] = { . type = NLA_BINARY , . len = MAX_ADDR_LEN } ,
[ IFLA_BROADCAST ] = { . type = NLA_BINARY , . len = MAX_ADDR_LEN } ,
2006-08-27 10:13:18 +07:00
[ IFLA_MAP ] = { . len = sizeof ( struct rtnl_link_ifmap ) } ,
2006-08-11 11:17:37 +07:00
[ IFLA_MTU ] = { . type = NLA_U32 } ,
2008-02-20 07:12:08 +07:00
[ IFLA_LINK ] = { . type = NLA_U32 } ,
2011-02-13 17:15:37 +07:00
[ IFLA_MASTER ] = { . type = NLA_U32 } ,
2012-12-28 06:49:39 +07:00
[ IFLA_CARRIER ] = { . type = NLA_U8 } ,
2006-08-11 11:17:37 +07:00
[ IFLA_TXQLEN ] = { . type = NLA_U32 } ,
[ IFLA_WEIGHT ] = { . type = NLA_U32 } ,
[ IFLA_OPERSTATE ] = { . type = NLA_U8 } ,
[ IFLA_LINKMODE ] = { . type = NLA_U8 } ,
2008-02-20 07:12:08 +07:00
[ IFLA_LINKINFO ] = { . type = NLA_NESTED } ,
2007-09-12 18:57:04 +07:00
[ IFLA_NET_NS_PID ] = { . type = NLA_U32 } ,
2011-05-05 07:51:50 +07:00
[ IFLA_NET_NS_FD ] = { . type = NLA_U32 } ,
2008-09-23 11:28:11 +07:00
[ IFLA_IFALIAS ] = { . type = NLA_STRING , . len = IFALIASZ - 1 } ,
2010-05-16 15:05:45 +07:00
[ IFLA_VFINFO_LIST ] = { . type = NLA_NESTED } ,
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
[ IFLA_VF_PORTS ] = { . type = NLA_NESTED } ,
[ IFLA_PORT_SELF ] = { . type = NLA_NESTED } ,
2010-11-16 11:30:14 +07:00
[ IFLA_AF_SPEC ] = { . type = NLA_NESTED } ,
2012-02-22 04:54:48 +07:00
[ IFLA_EXT_MASK ] = { . type = NLA_U32 } ,
2012-03-29 19:51:30 +07:00
[ IFLA_PROMISCUITY ] = { . type = NLA_U32 } ,
2012-07-20 09:28:48 +07:00
[ IFLA_NUM_TX_QUEUES ] = { . type = NLA_U32 } ,
[ IFLA_NUM_RX_QUEUES ] = { . type = NLA_U32 } ,
2014-11-28 20:34:16 +07:00
[ IFLA_PHYS_PORT_ID ] = { . type = NLA_BINARY , . len = MAX_PHYS_ITEM_ID_LEN } ,
2014-03-29 23:48:35 +07:00
[ IFLA_CARRIER_CHANGES ] = { . type = NLA_U32 } , /* ignored */
2014-11-28 20:34:18 +07:00
[ IFLA_PHYS_SWITCH_ID ] = { . type = NLA_BINARY , . len = MAX_PHYS_ITEM_ID_LEN } ,
2015-01-15 21:11:18 +07:00
[ IFLA_LINK_NETNSID ] = { . type = NLA_S32 } ,
2015-07-15 03:43:20 +07:00
[ IFLA_PROTO_DOWN ] = { . type = NLA_U8 } ,
2016-07-20 02:16:49 +07:00
[ IFLA_XDP ] = { . type = NLA_NESTED } ,
2017-05-27 21:14:34 +07:00
[ IFLA_EVENT ] = { . type = NLA_U32 } ,
2017-06-20 18:35:23 +07:00
[ IFLA_GROUP ] = { . type = NLA_U32 } ,
2006-08-11 11:17:37 +07:00
} ;
2007-06-14 02:03:51 +07:00
static const struct nla_policy ifla_info_policy [ IFLA_INFO_MAX + 1 ] = {
[ IFLA_INFO_KIND ] = { . type = NLA_STRING } ,
[ IFLA_INFO_DATA ] = { . type = NLA_NESTED } ,
2014-01-22 15:05:55 +07:00
[ IFLA_INFO_SLAVE_KIND ] = { . type = NLA_STRING } ,
[ IFLA_INFO_SLAVE_DATA ] = { . type = NLA_NESTED } ,
2007-06-14 02:03:51 +07:00
} ;
2010-05-16 15:05:45 +07:00
static const struct nla_policy ifla_vf_policy [ IFLA_VF_MAX + 1 ] = {
2015-02-06 00:44:04 +07:00
[ IFLA_VF_MAC ] = { . len = sizeof ( struct ifla_vf_mac ) } ,
[ IFLA_VF_VLAN ] = { . len = sizeof ( struct ifla_vf_vlan ) } ,
2016-09-22 16:11:15 +07:00
[ IFLA_VF_VLAN_LIST ] = { . type = NLA_NESTED } ,
2015-02-06 00:44:04 +07:00
[ IFLA_VF_TX_RATE ] = { . len = sizeof ( struct ifla_vf_tx_rate ) } ,
[ IFLA_VF_SPOOFCHK ] = { . len = sizeof ( struct ifla_vf_spoofchk ) } ,
[ IFLA_VF_RATE ] = { . len = sizeof ( struct ifla_vf_rate ) } ,
[ IFLA_VF_LINK_STATE ] = { . len = sizeof ( struct ifla_vf_link_state ) } ,
2015-03-31 01:35:23 +07:00
[ IFLA_VF_RSS_QUERY_EN ] = { . len = sizeof ( struct ifla_vf_rss_query_en ) } ,
2015-06-15 21:59:07 +07:00
[ IFLA_VF_STATS ] = { . type = NLA_NESTED } ,
2015-08-28 13:57:55 +07:00
[ IFLA_VF_TRUST ] = { . len = sizeof ( struct ifla_vf_trust ) } ,
2016-03-12 03:58:34 +07:00
[ IFLA_VF_IB_NODE_GUID ] = { . len = sizeof ( struct ifla_vf_guid ) } ,
[ IFLA_VF_IB_PORT_GUID ] = { . len = sizeof ( struct ifla_vf_guid ) } ,
2015-06-15 21:59:07 +07:00
} ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
static const struct nla_policy ifla_port_policy [ IFLA_PORT_MAX + 1 ] = {
[ IFLA_PORT_VF ] = { . type = NLA_U32 } ,
[ IFLA_PORT_PROFILE ] = { . type = NLA_STRING ,
. len = PORT_PROFILE_MAX } ,
[ IFLA_PORT_INSTANCE_UUID ] = { . type = NLA_BINARY ,
. len = PORT_UUID_MAX } ,
[ IFLA_PORT_HOST_UUID ] = { . type = NLA_STRING ,
. len = PORT_UUID_MAX } ,
[ IFLA_PORT_REQUEST ] = { . type = NLA_U8 , } ,
[ IFLA_PORT_RESPONSE ] = { . type = NLA_U16 , } ,
2017-02-17 07:56:11 +07:00
/* Unused, but we need to keep it here since user space could
* fill it . It ' s also broken with regard to NLA_BINARY use in
* combination with structs .
*/
[ IFLA_PORT_VSI_TYPE ] = { . type = NLA_BINARY ,
. len = sizeof ( struct ifla_port_vsi ) } ,
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
} ;
2016-07-20 02:16:49 +07:00
static const struct nla_policy ifla_xdp_policy [ IFLA_XDP_MAX + 1 ] = {
[ IFLA_XDP_FD ] = { . type = NLA_S32 } ,
[ IFLA_XDP_ATTACHED ] = { . type = NLA_U8 } ,
2016-11-29 05:16:54 +07:00
[ IFLA_XDP_FLAGS ] = { . type = NLA_U32 } ,
2017-06-16 07:29:09 +07:00
[ IFLA_XDP_PROG_ID ] = { . type = NLA_U32 } ,
2016-07-20 02:16:49 +07:00
} ;
2016-02-02 23:17:07 +07:00
static const struct rtnl_link_ops * linkinfo_to_kind_ops ( const struct nlattr * nla )
{
const struct rtnl_link_ops * ops = NULL ;
struct nlattr * linfo [ IFLA_INFO_MAX + 1 ] ;
2017-04-12 19:34:07 +07:00
if ( nla_parse_nested ( linfo , IFLA_INFO_MAX , nla ,
ifla_info_policy , NULL ) < 0 )
2016-02-02 23:17:07 +07:00
return NULL ;
if ( linfo [ IFLA_INFO_KIND ] ) {
char kind [ MODULE_NAME_LEN ] ;
nla_strlcpy ( kind , linfo [ IFLA_INFO_KIND ] , sizeof ( kind ) ) ;
ops = rtnl_link_ops_get ( kind ) ;
}
return ops ;
}
static bool link_master_filtered ( struct net_device * dev , int master_idx )
{
struct net_device * master ;
if ( ! master_idx )
return false ;
master = netdev_master_upper_dev_get ( dev ) ;
if ( ! master | | master - > ifindex ! = master_idx )
return true ;
return false ;
}
static bool link_kind_filtered ( const struct net_device * dev ,
const struct rtnl_link_ops * kind_ops )
{
if ( kind_ops & & dev - > rtnl_link_ops ! = kind_ops )
return true ;
return false ;
}
static bool link_dump_filtered ( struct net_device * dev ,
int master_idx ,
const struct rtnl_link_ops * kind_ops )
{
if ( link_master_filtered ( dev , master_idx ) | |
link_kind_filtered ( dev , kind_ops ) )
return true ;
return false ;
}
2014-02-19 02:53:18 +07:00
static int rtnl_dump_ifinfo ( struct sk_buff * skb , struct netlink_callback * cb )
{
struct net * net = sock_net ( skb - > sk ) ;
int h , s_h ;
int idx = 0 , s_idx ;
struct net_device * dev ;
struct hlist_head * head ;
struct nlattr * tb [ IFLA_MAX + 1 ] ;
u32 ext_filter_mask = 0 ;
2016-02-02 23:17:07 +07:00
const struct rtnl_link_ops * kind_ops = NULL ;
unsigned int flags = NLM_F_MULTI ;
int master_idx = 0 ;
2014-04-24 07:22:35 +07:00
int err ;
2014-05-28 19:15:19 +07:00
int hdrlen ;
2014-02-19 02:53:18 +07:00
s_h = cb - > args [ 0 ] ;
s_idx = cb - > args [ 1 ] ;
2014-05-28 19:15:19 +07:00
/* A hack to preserve kernel<->userspace interface.
* The correct header is ifinfomsg . It is consistent with rtnl_getlink .
* However , before Linux v3 .9 the code here assumed rtgenmsg and that ' s
* what iproute2 < v3 .9 .0 used .
* We can detect the old iproute2 . Even including the IFLA_EXT_MASK
* attribute , its netlink message is shorter than struct ifinfomsg .
*/
hdrlen = nlmsg_len ( cb - > nlh ) < sizeof ( struct ifinfomsg ) ?
sizeof ( struct rtgenmsg ) : sizeof ( struct ifinfomsg ) ;
2017-04-12 19:34:07 +07:00
if ( nlmsg_parse ( cb - > nlh , hdrlen , tb , IFLA_MAX ,
ifla_policy , NULL ) > = 0 ) {
2014-02-19 02:53:18 +07:00
if ( tb [ IFLA_EXT_MASK ] )
ext_filter_mask = nla_get_u32 ( tb [ IFLA_EXT_MASK ] ) ;
2016-02-02 23:17:07 +07:00
if ( tb [ IFLA_MASTER ] )
master_idx = nla_get_u32 ( tb [ IFLA_MASTER ] ) ;
if ( tb [ IFLA_LINKINFO ] )
kind_ops = linkinfo_to_kind_ops ( tb [ IFLA_LINKINFO ] ) ;
if ( master_idx | | kind_ops )
flags | = NLM_F_DUMP_FILTERED ;
2014-02-19 02:53:18 +07:00
}
for ( h = s_h ; h < NETDEV_HASHENTRIES ; h + + , s_idx = 0 ) {
idx = 0 ;
head = & net - > dev_index_head [ h ] ;
2015-02-28 00:42:50 +07:00
hlist_for_each_entry ( dev , head , index_hlist ) {
2016-02-02 23:17:07 +07:00
if ( link_dump_filtered ( dev , master_idx , kind_ops ) )
2016-11-19 22:28:32 +07:00
goto cont ;
2014-02-19 02:53:18 +07:00
if ( idx < s_idx )
goto cont ;
2014-04-24 07:22:35 +07:00
err = rtnl_fill_ifinfo ( skb , dev , RTM_NEWLINK ,
NETLINK_CB ( cb - > skb ) . portid ,
cb - > nlh - > nlmsg_seq , 0 ,
2016-02-02 23:17:07 +07:00
flags ,
2017-05-27 21:14:34 +07:00
ext_filter_mask , 0 ) ;
2014-04-24 07:22:35 +07:00
2017-05-16 13:19:17 +07:00
if ( err < 0 ) {
if ( likely ( skb - > len ) )
goto out ;
goto out_err ;
}
2014-02-19 02:53:18 +07:00
cont :
idx + + ;
}
}
out :
2017-05-16 13:19:17 +07:00
err = skb - > len ;
out_err :
2014-02-19 02:53:18 +07:00
cb - > args [ 1 ] = idx ;
cb - > args [ 0 ] = h ;
2017-08-09 22:39:12 +07:00
cb - > seq = net - > dev_base_seq ;
nl_dump_check_consistent ( cb , nlmsg_hdr ( skb ) ) ;
2014-02-19 02:53:18 +07:00
2017-05-16 13:19:17 +07:00
return err ;
2014-02-19 02:53:18 +07:00
}
2017-04-12 19:34:07 +07:00
int rtnl_nla_parse_ifla ( struct nlattr * * tb , const struct nlattr * head , int len ,
struct netlink_ext_ack * exterr )
2014-02-19 02:53:18 +07:00
{
2017-04-12 19:34:07 +07:00
return nla_parse ( tb , IFLA_MAX , head , len , ifla_policy , exterr ) ;
2014-02-19 02:53:18 +07:00
}
EXPORT_SYMBOL ( rtnl_nla_parse_ifla ) ;
2009-11-08 15:53:51 +07:00
struct net * rtnl_link_get_net ( struct net * src_net , struct nlattr * tb [ ] )
{
struct net * net ;
/* Examine the link attributes and figure out which
* network namespace we are talking about .
*/
if ( tb [ IFLA_NET_NS_PID ] )
net = get_net_ns_by_pid ( nla_get_u32 ( tb [ IFLA_NET_NS_PID ] ) ) ;
2011-05-05 07:51:50 +07:00
else if ( tb [ IFLA_NET_NS_FD ] )
net = get_net_ns_by_fd ( nla_get_u32 ( tb [ IFLA_NET_NS_FD ] ) ) ;
2009-11-08 15:53:51 +07:00
else
net = get_net ( src_net ) ;
return net ;
}
EXPORT_SYMBOL ( rtnl_link_get_net ) ;
2008-02-24 10:54:36 +07:00
static int validate_linkmsg ( struct net_device * dev , struct nlattr * tb [ ] )
{
if ( dev ) {
if ( tb [ IFLA_ADDRESS ] & &
nla_len ( tb [ IFLA_ADDRESS ] ) < dev - > addr_len )
return - EINVAL ;
if ( tb [ IFLA_BROADCAST ] & &
nla_len ( tb [ IFLA_BROADCAST ] ) < dev - > addr_len )
return - EINVAL ;
}
2010-11-22 08:31:54 +07:00
if ( tb [ IFLA_AF_SPEC ] ) {
struct nlattr * af ;
int rem , err ;
nla_for_each_nested ( af , tb [ IFLA_AF_SPEC ] , rem ) {
const struct rtnl_af_ops * af_ops ;
if ( ! ( af_ops = rtnl_af_lookup ( nla_type ( af ) ) ) )
return - EAFNOSUPPORT ;
if ( ! af_ops - > set_link_af )
return - EOPNOTSUPP ;
if ( af_ops - > validate_link_af ) {
2011-01-26 11:55:24 +07:00
err = af_ops - > validate_link_af ( dev , af ) ;
2010-11-22 08:31:54 +07:00
if ( err < 0 )
return err ;
}
}
}
2008-02-24 10:54:36 +07:00
return 0 ;
}
2016-03-12 03:58:34 +07:00
static int handle_infiniband_guid ( struct net_device * dev , struct ifla_vf_guid * ivt ,
int guid_type )
{
const struct net_device_ops * ops = dev - > netdev_ops ;
return ops - > ndo_set_vf_guid ( dev , ivt - > vf , ivt - > guid , guid_type ) ;
}
static int handle_vf_guid ( struct net_device * dev , struct ifla_vf_guid * ivt , int guid_type )
{
if ( dev - > type ! = ARPHRD_INFINIBAND )
return - EOPNOTSUPP ;
return handle_infiniband_guid ( dev , ivt , guid_type ) ;
}
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
static int do_setvfinfo ( struct net_device * dev , struct nlattr * * tb )
2010-05-16 15:05:45 +07:00
{
const struct net_device_ops * ops = dev - > netdev_ops ;
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
int err = - EINVAL ;
2010-05-16 15:05:45 +07:00
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
if ( tb [ IFLA_VF_MAC ] ) {
struct ifla_vf_mac * ivm = nla_data ( tb [ IFLA_VF_MAC ] ) ;
2015-03-31 01:35:23 +07:00
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_mac )
err = ops - > ndo_set_vf_mac ( dev , ivm - > vf ,
ivm - > mac ) ;
if ( err < 0 )
return err ;
}
if ( tb [ IFLA_VF_VLAN ] ) {
struct ifla_vf_vlan * ivv = nla_data ( tb [ IFLA_VF_VLAN ] ) ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_vlan )
err = ops - > ndo_set_vf_vlan ( dev , ivv - > vf , ivv - > vlan ,
2016-09-22 16:11:15 +07:00
ivv - > qos ,
htons ( ETH_P_8021Q ) ) ;
if ( err < 0 )
return err ;
}
if ( tb [ IFLA_VF_VLAN_LIST ] ) {
struct ifla_vf_vlan_info * ivvl [ MAX_VLAN_LIST_LEN ] ;
struct nlattr * attr ;
int rem , len = 0 ;
err = - EOPNOTSUPP ;
if ( ! ops - > ndo_set_vf_vlan )
return err ;
nla_for_each_nested ( attr , tb [ IFLA_VF_VLAN_LIST ] , rem ) {
if ( nla_type ( attr ) ! = IFLA_VF_VLAN_INFO | |
nla_len ( attr ) < NLA_HDRLEN ) {
return - EINVAL ;
}
if ( len > = MAX_VLAN_LIST_LEN )
return - EOPNOTSUPP ;
ivvl [ len ] = nla_data ( attr ) ;
len + + ;
}
2016-09-30 23:13:49 +07:00
if ( len = = 0 )
return - EINVAL ;
2016-09-22 16:11:15 +07:00
err = ops - > ndo_set_vf_vlan ( dev , ivvl [ 0 ] - > vf , ivvl [ 0 ] - > vlan ,
ivvl [ 0 ] - > qos , ivvl [ 0 ] - > vlan_proto ) ;
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
if ( err < 0 )
return err ;
2010-05-16 15:05:45 +07:00
}
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
if ( tb [ IFLA_VF_TX_RATE ] ) {
struct ifla_vf_tx_rate * ivt = nla_data ( tb [ IFLA_VF_TX_RATE ] ) ;
struct ifla_vf_info ivf ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_get_vf_config )
err = ops - > ndo_get_vf_config ( dev , ivt - > vf , & ivf ) ;
if ( err < 0 )
return err ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_rate )
err = ops - > ndo_set_vf_rate ( dev , ivt - > vf ,
ivf . min_tx_rate ,
ivt - > rate ) ;
if ( err < 0 )
return err ;
}
if ( tb [ IFLA_VF_RATE ] ) {
struct ifla_vf_rate * ivt = nla_data ( tb [ IFLA_VF_RATE ] ) ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_rate )
err = ops - > ndo_set_vf_rate ( dev , ivt - > vf ,
ivt - > min_tx_rate ,
ivt - > max_tx_rate ) ;
if ( err < 0 )
return err ;
}
if ( tb [ IFLA_VF_SPOOFCHK ] ) {
struct ifla_vf_spoofchk * ivs = nla_data ( tb [ IFLA_VF_SPOOFCHK ] ) ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_spoofchk )
err = ops - > ndo_set_vf_spoofchk ( dev , ivs - > vf ,
ivs - > setting ) ;
if ( err < 0 )
return err ;
}
if ( tb [ IFLA_VF_LINK_STATE ] ) {
struct ifla_vf_link_state * ivl = nla_data ( tb [ IFLA_VF_LINK_STATE ] ) ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_link_state )
err = ops - > ndo_set_vf_link_state ( dev , ivl - > vf ,
ivl - > link_state ) ;
if ( err < 0 )
return err ;
}
if ( tb [ IFLA_VF_RSS_QUERY_EN ] ) {
struct ifla_vf_rss_query_en * ivrssq_en ;
err = - EOPNOTSUPP ;
ivrssq_en = nla_data ( tb [ IFLA_VF_RSS_QUERY_EN ] ) ;
if ( ops - > ndo_set_vf_rss_query_en )
err = ops - > ndo_set_vf_rss_query_en ( dev , ivrssq_en - > vf ,
ivrssq_en - > setting ) ;
if ( err < 0 )
return err ;
}
2015-08-28 13:57:55 +07:00
if ( tb [ IFLA_VF_TRUST ] ) {
struct ifla_vf_trust * ivt = nla_data ( tb [ IFLA_VF_TRUST ] ) ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_trust )
err = ops - > ndo_set_vf_trust ( dev , ivt - > vf , ivt - > setting ) ;
if ( err < 0 )
return err ;
}
2016-03-12 03:58:34 +07:00
if ( tb [ IFLA_VF_IB_NODE_GUID ] ) {
struct ifla_vf_guid * ivt = nla_data ( tb [ IFLA_VF_IB_NODE_GUID ] ) ;
if ( ! ops - > ndo_set_vf_guid )
return - EOPNOTSUPP ;
return handle_vf_guid ( dev , ivt , IFLA_VF_IB_NODE_GUID ) ;
}
if ( tb [ IFLA_VF_IB_PORT_GUID ] ) {
struct ifla_vf_guid * ivt = nla_data ( tb [ IFLA_VF_IB_PORT_GUID ] ) ;
if ( ! ops - > ndo_set_vf_guid )
return - EOPNOTSUPP ;
return handle_vf_guid ( dev , ivt , IFLA_VF_IB_PORT_GUID ) ;
}
2010-05-16 15:05:45 +07:00
return err ;
}
2011-02-13 17:15:37 +07:00
static int do_set_master ( struct net_device * dev , int ifindex )
{
2013-01-04 05:48:52 +07:00
struct net_device * upper_dev = netdev_master_upper_dev_get ( dev ) ;
2011-02-13 17:15:37 +07:00
const struct net_device_ops * ops ;
int err ;
2013-01-04 05:48:52 +07:00
if ( upper_dev ) {
if ( upper_dev - > ifindex = = ifindex )
2011-02-13 17:15:37 +07:00
return 0 ;
2013-01-04 05:48:52 +07:00
ops = upper_dev - > netdev_ops ;
2011-02-13 17:15:37 +07:00
if ( ops - > ndo_del_slave ) {
2013-01-04 05:48:52 +07:00
err = ops - > ndo_del_slave ( upper_dev , dev ) ;
2011-02-13 17:15:37 +07:00
if ( err )
return err ;
} else {
return - EOPNOTSUPP ;
}
}
if ( ifindex ) {
2013-01-04 05:48:52 +07:00
upper_dev = __dev_get_by_index ( dev_net ( dev ) , ifindex ) ;
if ( ! upper_dev )
2011-02-13 17:15:37 +07:00
return - EINVAL ;
2013-01-04 05:48:52 +07:00
ops = upper_dev - > netdev_ops ;
2011-02-13 17:15:37 +07:00
if ( ops - > ndo_add_slave ) {
2013-01-04 05:48:52 +07:00
err = ops - > ndo_add_slave ( upper_dev , dev ) ;
2011-02-13 17:15:37 +07:00
if ( err )
return err ;
} else {
return - EOPNOTSUPP ;
}
}
return 0 ;
}
2014-09-01 21:07:28 +07:00
# define DO_SETLINK_MODIFIED 0x01
2014-09-01 21:07:29 +07:00
/* notify flag means notify + modified. */
# define DO_SETLINK_NOTIFY 0x03
2014-04-24 04:29:27 +07:00
static int do_setlink ( const struct sk_buff * skb ,
struct net_device * dev , struct ifinfomsg * ifm ,
2017-05-01 11:46:46 +07:00
struct netlink_ext_ack * extack ,
2014-09-01 21:07:28 +07:00
struct nlattr * * tb , char * ifname , int status )
2005-04-17 05:20:36 +07:00
{
2008-11-20 12:32:24 +07:00
const struct net_device_ops * ops = dev - > netdev_ops ;
2007-06-14 02:03:36 +07:00
int err ;
2005-04-17 05:20:36 +07:00
2011-05-05 07:51:50 +07:00
if ( tb [ IFLA_NET_NS_PID ] | | tb [ IFLA_NET_NS_FD ] ) {
2009-11-08 15:53:51 +07:00
struct net * net = rtnl_link_get_net ( dev_net ( dev ) , tb ) ;
2007-09-12 18:57:04 +07:00
if ( IS_ERR ( net ) ) {
err = PTR_ERR ( net ) ;
goto errout ;
}
2014-04-24 04:29:27 +07:00
if ( ! netlink_ns_capable ( skb , net - > user_ns , CAP_NET_ADMIN ) ) {
2014-11-27 16:16:15 +07:00
put_net ( net ) ;
2012-11-16 10:03:11 +07:00
err = - EPERM ;
goto errout ;
}
2007-09-12 18:57:04 +07:00
err = dev_change_net_namespace ( dev , net , ifname ) ;
put_net ( net ) ;
if ( err )
goto errout ;
2014-09-01 21:07:28 +07:00
status | = DO_SETLINK_MODIFIED ;
2007-09-12 18:57:04 +07:00
}
2006-08-11 11:17:37 +07:00
if ( tb [ IFLA_MAP ] ) {
2005-04-17 05:20:36 +07:00
struct rtnl_link_ifmap * u_map ;
struct ifmap k_map ;
2008-11-20 12:32:24 +07:00
if ( ! ops - > ndo_set_config ) {
2005-04-17 05:20:36 +07:00
err = - EOPNOTSUPP ;
2007-06-14 02:03:36 +07:00
goto errout ;
2005-04-17 05:20:36 +07:00
}
if ( ! netif_device_present ( dev ) ) {
err = - ENODEV ;
2007-06-14 02:03:36 +07:00
goto errout ;
2005-04-17 05:20:36 +07:00
}
2006-08-11 11:17:37 +07:00
u_map = nla_data ( tb [ IFLA_MAP ] ) ;
2005-04-17 05:20:36 +07:00
k_map . mem_start = ( unsigned long ) u_map - > mem_start ;
k_map . mem_end = ( unsigned long ) u_map - > mem_end ;
k_map . base_addr = ( unsigned short ) u_map - > base_addr ;
k_map . irq = ( unsigned char ) u_map - > irq ;
k_map . dma = ( unsigned char ) u_map - > dma ;
k_map . port = ( unsigned char ) u_map - > port ;
2008-11-20 12:32:24 +07:00
err = ops - > ndo_set_config ( dev , & k_map ) ;
2006-08-11 11:17:37 +07:00
if ( err < 0 )
2007-06-14 02:03:36 +07:00
goto errout ;
2005-04-17 05:20:36 +07:00
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
2005-04-17 05:20:36 +07:00
}
2006-08-11 11:17:37 +07:00
if ( tb [ IFLA_ADDRESS ] ) {
2006-08-09 06:47:37 +07:00
struct sockaddr * sa ;
int len ;
2017-07-21 01:27:57 +07:00
len = sizeof ( sa_family_t ) + max_t ( size_t , dev - > addr_len ,
sizeof ( * sa ) ) ;
2006-08-09 06:47:37 +07:00
sa = kmalloc ( len , GFP_KERNEL ) ;
if ( ! sa ) {
err = - ENOMEM ;
2007-06-14 02:03:36 +07:00
goto errout ;
2006-08-09 06:47:37 +07:00
}
sa - > sa_family = dev - > type ;
2006-08-11 11:17:37 +07:00
memcpy ( sa - > sa_data , nla_data ( tb [ IFLA_ADDRESS ] ) ,
2006-08-09 06:47:37 +07:00
dev - > addr_len ) ;
2013-01-01 10:30:13 +07:00
err = dev_set_mac_address ( dev , sa ) ;
2006-08-09 06:47:37 +07:00
kfree ( sa ) ;
2005-04-17 05:20:36 +07:00
if ( err )
2007-06-14 02:03:36 +07:00
goto errout ;
2014-09-01 21:07:28 +07:00
status | = DO_SETLINK_MODIFIED ;
2005-04-17 05:20:36 +07:00
}
2006-08-11 11:17:37 +07:00
if ( tb [ IFLA_MTU ] ) {
err = dev_set_mtu ( dev , nla_get_u32 ( tb [ IFLA_MTU ] ) ) ;
if ( err < 0 )
2007-06-14 02:03:36 +07:00
goto errout ;
2014-09-01 21:07:28 +07:00
status | = DO_SETLINK_MODIFIED ;
2005-04-17 05:20:36 +07:00
}
2011-01-14 06:38:30 +07:00
if ( tb [ IFLA_GROUP ] ) {
dev_set_group ( dev , nla_get_u32 ( tb [ IFLA_GROUP ] ) ) ;
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
2011-01-14 06:38:30 +07:00
}
2006-08-11 11:17:37 +07:00
/*
* Interface selected by interface index but interface
* name provided implies that a name change has been
* requested .
*/
2007-06-06 02:40:01 +07:00
if ( ifm - > ifi_index > 0 & & ifname [ 0 ] ) {
2006-08-11 11:17:37 +07:00
err = dev_change_name ( dev , ifname ) ;
if ( err < 0 )
2007-06-14 02:03:36 +07:00
goto errout ;
2014-09-01 21:07:28 +07:00
status | = DO_SETLINK_MODIFIED ;
2005-04-17 05:20:36 +07:00
}
2008-09-23 11:28:11 +07:00
if ( tb [ IFLA_IFALIAS ] ) {
err = dev_set_alias ( dev , nla_data ( tb [ IFLA_IFALIAS ] ) ,
nla_len ( tb [ IFLA_IFALIAS ] ) ) ;
if ( err < 0 )
goto errout ;
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
2008-09-23 11:28:11 +07:00
}
2006-08-11 11:17:37 +07:00
if ( tb [ IFLA_BROADCAST ] ) {
nla_memcpy ( dev - > broadcast , tb [ IFLA_BROADCAST ] , dev - > addr_len ) ;
2013-01-01 10:30:13 +07:00
call_netdevice_notifiers ( NETDEV_CHANGEADDR , dev ) ;
2005-04-17 05:20:36 +07:00
}
2007-05-23 07:00:01 +07:00
if ( ifm - > ifi_flags | | ifm - > ifi_change ) {
rtnetlink: support specifying device flags on device creation
commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f
Author: Patrick McHardy <kaber@trash.net>
Date: Tue Feb 23 20:41:30 2010 +0100
Support specifying the initial device flags when creating a device though
rtnl_link. Devices allocated by rtnl_create_link() are marked as INITIALIZING
in order to surpress netlink registration notifications. To complete setup,
rtnl_configure_link() must be called, which performs the device flag changes
and invokes the deferred notifiers if everything went well.
Two examples:
# add macvlan to eth0
#
$ ip link add link eth0 up allmulticast on type macvlan
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 26:f8:84:02:f9:2a brd ff:ff:ff:ff:ff:ff
[ROUTE]ff00::/8 dev macvlan0 table local metric 256 mtu 1500 advmss 1440 hoplimit 0
[ROUTE]fe80::/64 dev macvlan0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500
link/ether 26:f8:84:02:f9:2a
[ADDR]11: macvlan0 inet6 fe80::24f8:84ff:fe02:f92a/64 scope link
valid_lft forever preferred_lft forever
[ROUTE]local fe80::24f8:84ff:fe02:f92a via :: dev lo table local proto none metric 0 mtu 16436 advmss 16376 hoplimit 0
[ROUTE]default via fe80::215:e9ff:fef0:10f8 dev macvlan0 proto kernel metric 1024 mtu 1500 advmss 1440 hoplimit 0
[NEIGH]fe80::215:e9ff:fef0:10f8 dev macvlan0 lladdr 00:15:e9:f0:10:f8 router STALE
[ROUTE]2001:6f8:974::/64 dev macvlan0 proto kernel metric 256 expires 0sec mtu 1500 advmss 1440 hoplimit 0
[PREFIX]prefix 2001:6f8:974::/64 dev macvlan0 onlink autoconf valid 14400 preferred 131084
[ADDR]11: macvlan0 inet6 2001:6f8:974:0:24f8:84ff:fe02:f92a/64 scope global dynamic
valid_lft 86399sec preferred_lft 14399sec
# add VLAN to eth1, eth1 is down
#
$ ip link add link eth1 up type vlan id 1000
RTNETLINK answers: Network is down
<no events>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-02-26 13:34:54 +07:00
err = dev_change_flags ( dev , rtnl_dev_combine_flags ( dev , ifm ) ) ;
2008-11-17 14:20:31 +07:00
if ( err < 0 )
goto errout ;
2007-05-23 07:00:01 +07:00
}
2005-04-17 05:20:36 +07:00
2011-02-13 17:15:37 +07:00
if ( tb [ IFLA_MASTER ] ) {
err = do_set_master ( dev , nla_get_u32 ( tb [ IFLA_MASTER ] ) ) ;
if ( err )
goto errout ;
2014-09-01 21:07:28 +07:00
status | = DO_SETLINK_MODIFIED ;
2011-02-13 17:15:37 +07:00
}
2012-12-28 06:49:39 +07:00
if ( tb [ IFLA_CARRIER ] ) {
err = dev_change_carrier ( dev , nla_get_u8 ( tb [ IFLA_CARRIER ] ) ) ;
if ( err )
goto errout ;
2014-09-01 21:07:28 +07:00
status | = DO_SETLINK_MODIFIED ;
2012-12-28 06:49:39 +07:00
}
2014-09-01 21:07:26 +07:00
if ( tb [ IFLA_TXQLEN ] ) {
2017-05-17 17:30:44 +07:00
unsigned int value = nla_get_u32 ( tb [ IFLA_TXQLEN ] ) ;
unsigned int orig_len = dev - > tx_queue_len ;
2016-06-30 13:45:35 +07:00
if ( dev - > tx_queue_len ^ value ) {
dev - > tx_queue_len = value ;
err = call_netdevice_notifiers (
NETDEV_CHANGE_TX_QUEUE_LEN , dev ) ;
err = notifier_to_errno ( err ) ;
if ( err ) {
dev - > tx_queue_len = orig_len ;
goto errout ;
}
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
2016-06-30 13:45:35 +07:00
}
2014-09-01 21:07:26 +07:00
}
2006-03-21 08:09:11 +07:00
2006-08-11 11:17:37 +07:00
if ( tb [ IFLA_OPERSTATE ] )
2008-02-18 09:35:07 +07:00
set_operstate ( dev , nla_get_u8 ( tb [ IFLA_OPERSTATE ] ) ) ;
2006-03-21 08:09:11 +07:00
2006-08-11 11:17:37 +07:00
if ( tb [ IFLA_LINKMODE ] ) {
2014-09-01 21:07:27 +07:00
unsigned char value = nla_get_u8 ( tb [ IFLA_LINKMODE ] ) ;
2008-02-18 09:35:07 +07:00
write_lock_bh ( & dev_base_lock ) ;
2014-09-01 21:07:27 +07:00
if ( dev - > link_mode ^ value )
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
2014-09-01 21:07:27 +07:00
dev - > link_mode = value ;
2008-02-18 09:35:07 +07:00
write_unlock_bh ( & dev_base_lock ) ;
2006-03-21 08:09:11 +07:00
}
2010-05-16 15:05:45 +07:00
if ( tb [ IFLA_VFINFO_LIST ] ) {
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
struct nlattr * vfinfo [ IFLA_VF_MAX + 1 ] ;
2010-05-16 15:05:45 +07:00
struct nlattr * attr ;
int rem ;
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
2010-05-16 15:05:45 +07:00
nla_for_each_nested ( attr , tb [ IFLA_VFINFO_LIST ] , rem ) {
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
if ( nla_type ( attr ) ! = IFLA_VF_INFO | |
nla_len ( attr ) < NLA_HDRLEN ) {
2010-05-21 09:25:27 +07:00
err = - EINVAL ;
2010-05-16 15:05:45 +07:00
goto errout ;
2010-05-21 09:25:27 +07:00
}
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
err = nla_parse_nested ( vfinfo , IFLA_VF_MAX , attr ,
2017-04-12 19:34:07 +07:00
ifla_vf_policy , NULL ) ;
rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver
Jason Gunthorpe reported that since commit c02db8c6290b ("rtnetlink: make
SR-IOV VF interface symmetric"), we don't verify IFLA_VF_INFO attributes
anymore with respect to their policy, that is, ifla_vfinfo_policy[].
Before, they were part of ifla_policy[], but they have been nested since
placed under IFLA_VFINFO_LIST, that contains the attribute IFLA_VF_INFO,
which is another nested attribute for the actual VF attributes such as
IFLA_VF_MAC, IFLA_VF_VLAN, etc.
Despite the policy being split out from ifla_policy[] in this commit,
it's never applied anywhere. nla_for_each_nested() only does basic nla_ok()
testing for struct nlattr, but it doesn't know about the data context and
their requirements.
Fix, on top of Jason's initial work, does 1) parsing of the attributes
with the right policy, and 2) using the resulting parsed attribute table
from 1) instead of the nla_for_each_nested() loop (just like we used to
do when still part of ifla_policy[]).
Reference: http://thread.gmane.org/gmane.linux.network/368913
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Rony Efraim <ronye@mellanox.com>
Cc: Vlad Zolotarov <vladz@cloudius-systems.com>
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Vlad Zolotarov <vladz@cloudius-systems.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-07-07 05:07:52 +07:00
if ( err < 0 )
goto errout ;
err = do_setvfinfo ( dev , vfinfo ) ;
2010-05-16 15:05:45 +07:00
if ( err < 0 )
goto errout ;
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
2010-05-16 15:05:45 +07:00
}
2010-02-10 08:44:05 +07:00
}
2005-04-17 05:20:36 +07:00
err = 0 ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
if ( tb [ IFLA_VF_PORTS ] ) {
struct nlattr * port [ IFLA_PORT_MAX + 1 ] ;
struct nlattr * attr ;
int vf ;
int rem ;
err = - EOPNOTSUPP ;
if ( ! ops - > ndo_set_vf_port )
goto errout ;
nla_for_each_nested ( attr , tb [ IFLA_VF_PORTS ] , rem ) {
2015-07-13 05:06:02 +07:00
if ( nla_type ( attr ) ! = IFLA_VF_PORT | |
nla_len ( attr ) < NLA_HDRLEN ) {
err = - EINVAL ;
goto errout ;
}
err = nla_parse_nested ( port , IFLA_PORT_MAX , attr ,
2017-04-12 19:34:07 +07:00
ifla_port_policy , NULL ) ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
if ( err < 0 )
goto errout ;
if ( ! port [ IFLA_PORT_VF ] ) {
err = - EOPNOTSUPP ;
goto errout ;
}
vf = nla_get_u32 ( port [ IFLA_PORT_VF ] ) ;
err = ops - > ndo_set_vf_port ( dev , vf , port ) ;
if ( err < 0 )
goto errout ;
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
}
}
err = 0 ;
if ( tb [ IFLA_PORT_SELF ] ) {
struct nlattr * port [ IFLA_PORT_MAX + 1 ] ;
err = nla_parse_nested ( port , IFLA_PORT_MAX ,
2017-04-12 19:34:07 +07:00
tb [ IFLA_PORT_SELF ] , ifla_port_policy ,
NULL ) ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
if ( err < 0 )
goto errout ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_port )
err = ops - > ndo_set_vf_port ( dev , PORT_SELF_VF , port ) ;
if ( err < 0 )
goto errout ;
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
}
2010-11-16 11:30:14 +07:00
if ( tb [ IFLA_AF_SPEC ] ) {
struct nlattr * af ;
int rem ;
nla_for_each_nested ( af , tb [ IFLA_AF_SPEC ] , rem ) {
const struct rtnl_af_ops * af_ops ;
if ( ! ( af_ops = rtnl_af_lookup ( nla_type ( af ) ) ) )
2010-11-22 08:31:54 +07:00
BUG ( ) ;
2010-11-16 11:30:14 +07:00
2010-11-22 08:31:54 +07:00
err = af_ops - > set_link_af ( dev , af ) ;
2010-11-16 11:30:14 +07:00
if ( err < 0 )
goto errout ;
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
2010-11-16 11:30:14 +07:00
}
}
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of
port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
(added to end of IFLA_cmd list). These are both nested atrtibutes
using this layout:
[IFLA_NUM_VF]
[IFLA_VF_PORTS]
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
[IFLA_VF_PORT]
[IFLA_PORT_*], ...
...
[IFLA_PORT_SELF]
[IFLA_PORT_*], ...
These attributes are design to be set and get symmetrically. VF_PORTS
is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
device. PORT_SELF is for the PF of the SR-IOV device, in case it wants
to also have a port-profile, or for the case where the VF==PF, like in
enic patch 2/2 of this patch set.
A port-profile is used to configure/enable the external switch virtual port
backing the netdev interface, not to configure the host-facing side of the
netdev. A port-profile is an identifier known to the switch. How port-
profiles are installed on the switch or how available port-profiles are
made know to the host is outside the scope of this patch.
There are two types of port-profiles specs in the netlink msg. The first spec
is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices
that run a similar protocol as VDP but in firmware, thus hiding the protocol
details. In either case, the specs have much in common and makes sense to
define the netlink msg as the union of the two specs. For example, both specs
have a notition of associating/deassociating a port-profile. And both specs
require some information from the hypervisor manager, such as client port
instance ID.
The general flow is the port-profile is applied to a host netdev interface
using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
switch, and the switch virtual port backing the host netdev interface is
configured/enabled based on the settings defined by the port-profile. What
those settings comprise, and how those settings are managed is again
outside the scope of this patch, since this patch only deals with the
first step in the flow.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-05-18 12:49:55 +07:00
err = 0 ;
2015-07-15 03:43:20 +07:00
if ( tb [ IFLA_PROTO_DOWN ] ) {
err = dev_change_proto_down ( dev ,
nla_get_u8 ( tb [ IFLA_PROTO_DOWN ] ) ) ;
if ( err )
goto errout ;
status | = DO_SETLINK_NOTIFY ;
}
2016-07-20 02:16:49 +07:00
if ( tb [ IFLA_XDP ] ) {
struct nlattr * xdp [ IFLA_XDP_MAX + 1 ] ;
2016-11-29 05:16:54 +07:00
u32 xdp_flags = 0 ;
2016-07-20 02:16:49 +07:00
err = nla_parse_nested ( xdp , IFLA_XDP_MAX , tb [ IFLA_XDP ] ,
2017-04-12 19:34:07 +07:00
ifla_xdp_policy , NULL ) ;
2016-07-20 02:16:49 +07:00
if ( err < 0 )
goto errout ;
2017-06-16 07:29:09 +07:00
if ( xdp [ IFLA_XDP_ATTACHED ] | | xdp [ IFLA_XDP_PROG_ID ] ) {
2016-07-21 07:22:34 +07:00
err = - EINVAL ;
goto errout ;
}
2016-11-29 05:16:54 +07:00
if ( xdp [ IFLA_XDP_FLAGS ] ) {
xdp_flags = nla_get_u32 ( xdp [ IFLA_XDP_FLAGS ] ) ;
if ( xdp_flags & ~ XDP_FLAGS_MASK ) {
err = - EINVAL ;
goto errout ;
}
2017-06-22 08:25:04 +07:00
if ( hweight32 ( xdp_flags & XDP_FLAGS_MODES ) > 1 ) {
2017-05-12 06:04:45 +07:00
err = - EINVAL ;
goto errout ;
}
2016-11-29 05:16:54 +07:00
}
2016-07-20 02:16:49 +07:00
if ( xdp [ IFLA_XDP_FD ] ) {
2017-05-01 11:46:46 +07:00
err = dev_change_xdp_fd ( dev , extack ,
2016-11-29 05:16:54 +07:00
nla_get_s32 ( xdp [ IFLA_XDP_FD ] ) ,
xdp_flags ) ;
2016-07-20 02:16:49 +07:00
if ( err )
goto errout ;
status | = DO_SETLINK_NOTIFY ;
}
}
2007-06-14 02:03:36 +07:00
errout :
2014-09-01 21:07:29 +07:00
if ( status & DO_SETLINK_MODIFIED ) {
if ( status & DO_SETLINK_NOTIFY )
netdev_state_change ( dev ) ;
if ( err < 0 )
net_warn_ratelimited ( " A link change request failed with some changes committed already. Interface %s may have been left with an inconsistent configuration, please check. \n " ,
dev - > name ) ;
}
2006-08-11 11:17:37 +07:00
2007-06-14 02:03:36 +07:00
return err ;
}
2005-04-17 05:20:36 +07:00
2017-04-16 23:48:24 +07:00
static int rtnl_setlink ( struct sk_buff * skb , struct nlmsghdr * nlh ,
struct netlink_ext_ack * extack )
2007-06-14 02:03:36 +07:00
{
2008-03-26 00:26:21 +07:00
struct net * net = sock_net ( skb - > sk ) ;
2007-06-14 02:03:36 +07:00
struct ifinfomsg * ifm ;
struct net_device * dev ;
int err ;
struct nlattr * tb [ IFLA_MAX + 1 ] ;
char ifname [ IFNAMSIZ ] ;
2017-04-16 23:48:24 +07:00
err = nlmsg_parse ( nlh , sizeof ( * ifm ) , tb , IFLA_MAX , ifla_policy ,
extack ) ;
2007-06-14 02:03:36 +07:00
if ( err < 0 )
goto errout ;
if ( tb [ IFLA_IFNAME ] )
nla_strlcpy ( ifname , tb [ IFLA_IFNAME ] , IFNAMSIZ ) ;
else
ifname [ 0 ] = ' \0 ' ;
err = - EINVAL ;
ifm = nlmsg_data ( nlh ) ;
if ( ifm - > ifi_index > 0 )
2009-10-21 17:59:31 +07:00
dev = __dev_get_by_index ( net , ifm - > ifi_index ) ;
2007-06-14 02:03:36 +07:00
else if ( tb [ IFLA_IFNAME ] )
2009-10-21 17:59:31 +07:00
dev = __dev_get_by_name ( net , ifname ) ;
2007-06-14 02:03:36 +07:00
else
goto errout ;
if ( dev = = NULL ) {
err = - ENODEV ;
goto errout ;
}
2009-11-07 16:26:17 +07:00
err = validate_linkmsg ( dev , tb ) ;
if ( err < 0 )
2009-10-21 17:59:31 +07:00
goto errout ;
2007-06-14 02:03:36 +07:00
2017-05-01 11:46:46 +07:00
err = do_setlink ( skb , dev , ifm , extack , tb , ifname , 0 ) ;
2006-08-11 11:17:37 +07:00
errout :
2005-04-17 05:20:36 +07:00
return err ;
}
2015-03-25 01:53:31 +07:00
static int rtnl_group_dellink ( const struct net * net , int group )
{
struct net_device * dev , * aux ;
LIST_HEAD ( list_kill ) ;
bool found = false ;
if ( ! group )
return - EPERM ;
for_each_netdev ( net , dev ) {
if ( dev - > group = = group ) {
const struct rtnl_link_ops * ops ;
found = true ;
ops = dev - > rtnl_link_ops ;
if ( ! ops | | ! ops - > dellink )
return - EOPNOTSUPP ;
}
}
if ( ! found )
return - ENODEV ;
for_each_netdev_safe ( net , dev , aux ) {
if ( dev - > group = = group ) {
const struct rtnl_link_ops * ops ;
ops = dev - > rtnl_link_ops ;
ops - > dellink ( dev , & list_kill ) ;
}
}
unregister_netdevice_many ( & list_kill ) ;
return 0 ;
}
2015-07-21 15:44:06 +07:00
int rtnl_delete_link ( struct net_device * dev )
{
const struct rtnl_link_ops * ops ;
LIST_HEAD ( list_kill ) ;
ops = dev - > rtnl_link_ops ;
if ( ! ops | | ! ops - > dellink )
return - EOPNOTSUPP ;
ops - > dellink ( dev , & list_kill ) ;
unregister_netdevice_many ( & list_kill ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( rtnl_delete_link ) ;
2017-04-16 23:48:24 +07:00
static int rtnl_dellink ( struct sk_buff * skb , struct nlmsghdr * nlh ,
struct netlink_ext_ack * extack )
2007-06-14 02:03:51 +07:00
{
2008-03-26 00:26:21 +07:00
struct net * net = sock_net ( skb - > sk ) ;
2007-06-14 02:03:51 +07:00
struct net_device * dev ;
struct ifinfomsg * ifm ;
char ifname [ IFNAMSIZ ] ;
struct nlattr * tb [ IFLA_MAX + 1 ] ;
int err ;
2017-04-16 23:48:24 +07:00
err = nlmsg_parse ( nlh , sizeof ( * ifm ) , tb , IFLA_MAX , ifla_policy , extack ) ;
2007-06-14 02:03:51 +07:00
if ( err < 0 )
return err ;
if ( tb [ IFLA_IFNAME ] )
nla_strlcpy ( ifname , tb [ IFLA_IFNAME ] , IFNAMSIZ ) ;
ifm = nlmsg_data ( nlh ) ;
if ( ifm - > ifi_index > 0 )
2007-09-18 01:56:21 +07:00
dev = __dev_get_by_index ( net , ifm - > ifi_index ) ;
2007-06-14 02:03:51 +07:00
else if ( tb [ IFLA_IFNAME ] )
2007-09-18 01:56:21 +07:00
dev = __dev_get_by_name ( net , ifname ) ;
2015-03-25 01:53:31 +07:00
else if ( tb [ IFLA_GROUP ] )
return rtnl_group_dellink ( net , nla_get_u32 ( tb [ IFLA_GROUP ] ) ) ;
2007-06-14 02:03:51 +07:00
else
return - EINVAL ;
if ( ! dev )
return - ENODEV ;
2015-07-21 15:44:06 +07:00
return rtnl_delete_link ( dev ) ;
2007-06-14 02:03:51 +07:00
}
rtnetlink: support specifying device flags on device creation
commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f
Author: Patrick McHardy <kaber@trash.net>
Date: Tue Feb 23 20:41:30 2010 +0100
Support specifying the initial device flags when creating a device though
rtnl_link. Devices allocated by rtnl_create_link() are marked as INITIALIZING
in order to surpress netlink registration notifications. To complete setup,
rtnl_configure_link() must be called, which performs the device flag changes
and invokes the deferred notifiers if everything went well.
Two examples:
# add macvlan to eth0
#
$ ip link add link eth0 up allmulticast on type macvlan
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 26:f8:84:02:f9:2a brd ff:ff:ff:ff:ff:ff
[ROUTE]ff00::/8 dev macvlan0 table local metric 256 mtu 1500 advmss 1440 hoplimit 0
[ROUTE]fe80::/64 dev macvlan0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500
link/ether 26:f8:84:02:f9:2a
[ADDR]11: macvlan0 inet6 fe80::24f8:84ff:fe02:f92a/64 scope link
valid_lft forever preferred_lft forever
[ROUTE]local fe80::24f8:84ff:fe02:f92a via :: dev lo table local proto none metric 0 mtu 16436 advmss 16376 hoplimit 0
[ROUTE]default via fe80::215:e9ff:fef0:10f8 dev macvlan0 proto kernel metric 1024 mtu 1500 advmss 1440 hoplimit 0
[NEIGH]fe80::215:e9ff:fef0:10f8 dev macvlan0 lladdr 00:15:e9:f0:10:f8 router STALE
[ROUTE]2001:6f8:974::/64 dev macvlan0 proto kernel metric 256 expires 0sec mtu 1500 advmss 1440 hoplimit 0
[PREFIX]prefix 2001:6f8:974::/64 dev macvlan0 onlink autoconf valid 14400 preferred 131084
[ADDR]11: macvlan0 inet6 2001:6f8:974:0:24f8:84ff:fe02:f92a/64 scope global dynamic
valid_lft 86399sec preferred_lft 14399sec
# add VLAN to eth1, eth1 is down
#
$ ip link add link eth1 up type vlan id 1000
RTNETLINK answers: Network is down
<no events>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-02-26 13:34:54 +07:00
int rtnl_configure_link ( struct net_device * dev , const struct ifinfomsg * ifm )
{
unsigned int old_flags ;
int err ;
old_flags = dev - > flags ;
if ( ifm & & ( ifm - > ifi_flags | | ifm - > ifi_change ) ) {
err = __dev_change_flags ( dev , rtnl_dev_combine_flags ( dev , ifm ) ) ;
if ( err < 0 )
return err ;
}
dev - > rtnl_link_state = RTNL_LINK_INITIALIZED ;
2013-09-25 17:02:44 +07:00
__dev_notify_flags ( dev , old_flags , ~ 0U ) ;
rtnetlink: support specifying device flags on device creation
commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f
Author: Patrick McHardy <kaber@trash.net>
Date: Tue Feb 23 20:41:30 2010 +0100
Support specifying the initial device flags when creating a device though
rtnl_link. Devices allocated by rtnl_create_link() are marked as INITIALIZING
in order to surpress netlink registration notifications. To complete setup,
rtnl_configure_link() must be called, which performs the device flag changes
and invokes the deferred notifiers if everything went well.
Two examples:
# add macvlan to eth0
#
$ ip link add link eth0 up allmulticast on type macvlan
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 26:f8:84:02:f9:2a brd ff:ff:ff:ff:ff:ff
[ROUTE]ff00::/8 dev macvlan0 table local metric 256 mtu 1500 advmss 1440 hoplimit 0
[ROUTE]fe80::/64 dev macvlan0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500
link/ether 26:f8:84:02:f9:2a
[ADDR]11: macvlan0 inet6 fe80::24f8:84ff:fe02:f92a/64 scope link
valid_lft forever preferred_lft forever
[ROUTE]local fe80::24f8:84ff:fe02:f92a via :: dev lo table local proto none metric 0 mtu 16436 advmss 16376 hoplimit 0
[ROUTE]default via fe80::215:e9ff:fef0:10f8 dev macvlan0 proto kernel metric 1024 mtu 1500 advmss 1440 hoplimit 0
[NEIGH]fe80::215:e9ff:fef0:10f8 dev macvlan0 lladdr 00:15:e9:f0:10:f8 router STALE
[ROUTE]2001:6f8:974::/64 dev macvlan0 proto kernel metric 256 expires 0sec mtu 1500 advmss 1440 hoplimit 0
[PREFIX]prefix 2001:6f8:974::/64 dev macvlan0 onlink autoconf valid 14400 preferred 131084
[ADDR]11: macvlan0 inet6 2001:6f8:974:0:24f8:84ff:fe02:f92a/64 scope global dynamic
valid_lft 86399sec preferred_lft 14399sec
# add VLAN to eth1, eth1 is down
#
$ ip link add link eth1 up type vlan id 1000
RTNETLINK answers: Network is down
<no events>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-02-26 13:34:54 +07:00
return 0 ;
}
EXPORT_SYMBOL ( rtnl_configure_link ) ;
2012-11-30 08:08:47 +07:00
struct net_device * rtnl_create_link ( struct net * net ,
2015-04-10 06:45:53 +07:00
const char * ifname , unsigned char name_assign_type ,
2014-07-14 21:37:25 +07:00
const struct rtnl_link_ops * ops , struct nlattr * tb [ ] )
2007-08-09 12:16:38 +07:00
{
struct net_device * dev ;
2012-07-20 09:28:47 +07:00
unsigned int num_tx_queues = 1 ;
unsigned int num_rx_queues = 1 ;
2007-08-09 12:16:38 +07:00
2012-07-20 09:28:48 +07:00
if ( tb [ IFLA_NUM_TX_QUEUES ] )
num_tx_queues = nla_get_u32 ( tb [ IFLA_NUM_TX_QUEUES ] ) ;
else if ( ops - > get_num_tx_queues )
2012-07-20 09:28:47 +07:00
num_tx_queues = ops - > get_num_tx_queues ( ) ;
2012-07-20 09:28:48 +07:00
if ( tb [ IFLA_NUM_RX_QUEUES ] )
num_rx_queues = nla_get_u32 ( tb [ IFLA_NUM_RX_QUEUES ] ) ;
else if ( ops - > get_num_rx_queues )
2012-07-20 09:28:47 +07:00
num_rx_queues = ops - > get_num_rx_queues ( ) ;
2012-04-11 01:34:43 +07:00
2014-07-14 21:37:25 +07:00
dev = alloc_netdev_mqs ( ops - > priv_size , ifname , name_assign_type ,
net: set name_assign_type in alloc_netdev()
Extend alloc_netdev{,_mq{,s}}() to take name_assign_type as argument, and convert
all users to pass NET_NAME_UNKNOWN.
Coccinelle patch:
@@
expression sizeof_priv, name, setup, txqs, rxqs, count;
@@
(
-alloc_netdev_mqs(sizeof_priv, name, setup, txqs, rxqs)
+alloc_netdev_mqs(sizeof_priv, name, NET_NAME_UNKNOWN, setup, txqs, rxqs)
|
-alloc_netdev_mq(sizeof_priv, name, setup, count)
+alloc_netdev_mq(sizeof_priv, name, NET_NAME_UNKNOWN, setup, count)
|
-alloc_netdev(sizeof_priv, name, setup)
+alloc_netdev(sizeof_priv, name, NET_NAME_UNKNOWN, setup)
)
v9: move comments here from the wrong commit
Signed-off-by: Tom Gundersen <teg@jklm.no>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-07-14 21:37:24 +07:00
ops - > setup , num_tx_queues , num_rx_queues ) ;
2007-08-09 12:16:38 +07:00
if ( ! dev )
2017-02-20 22:32:06 +07:00
return ERR_PTR ( - ENOMEM ) ;
2007-08-09 12:16:38 +07:00
2009-11-08 15:53:51 +07:00
dev_net_set ( dev , net ) ;
dev - > rtnl_link_ops = ops ;
rtnetlink: support specifying device flags on device creation
commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f
Author: Patrick McHardy <kaber@trash.net>
Date: Tue Feb 23 20:41:30 2010 +0100
Support specifying the initial device flags when creating a device though
rtnl_link. Devices allocated by rtnl_create_link() are marked as INITIALIZING
in order to surpress netlink registration notifications. To complete setup,
rtnl_configure_link() must be called, which performs the device flag changes
and invokes the deferred notifiers if everything went well.
Two examples:
# add macvlan to eth0
#
$ ip link add link eth0 up allmulticast on type macvlan
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 26:f8:84:02:f9:2a brd ff:ff:ff:ff:ff:ff
[ROUTE]ff00::/8 dev macvlan0 table local metric 256 mtu 1500 advmss 1440 hoplimit 0
[ROUTE]fe80::/64 dev macvlan0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500
link/ether 26:f8:84:02:f9:2a
[ADDR]11: macvlan0 inet6 fe80::24f8:84ff:fe02:f92a/64 scope link
valid_lft forever preferred_lft forever
[ROUTE]local fe80::24f8:84ff:fe02:f92a via :: dev lo table local proto none metric 0 mtu 16436 advmss 16376 hoplimit 0
[ROUTE]default via fe80::215:e9ff:fef0:10f8 dev macvlan0 proto kernel metric 1024 mtu 1500 advmss 1440 hoplimit 0
[NEIGH]fe80::215:e9ff:fef0:10f8 dev macvlan0 lladdr 00:15:e9:f0:10:f8 router STALE
[ROUTE]2001:6f8:974::/64 dev macvlan0 proto kernel metric 256 expires 0sec mtu 1500 advmss 1440 hoplimit 0
[PREFIX]prefix 2001:6f8:974::/64 dev macvlan0 onlink autoconf valid 14400 preferred 131084
[ADDR]11: macvlan0 inet6 2001:6f8:974:0:24f8:84ff:fe02:f92a/64 scope global dynamic
valid_lft 86399sec preferred_lft 14399sec
# add VLAN to eth1, eth1 is down
#
$ ip link add link eth1 up type vlan id 1000
RTNETLINK answers: Network is down
<no events>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-02-26 13:34:54 +07:00
dev - > rtnl_link_state = RTNL_LINK_INITIALIZING ;
2009-11-08 15:53:51 +07:00
2007-08-09 12:16:38 +07:00
if ( tb [ IFLA_MTU ] )
dev - > mtu = nla_get_u32 ( tb [ IFLA_MTU ] ) ;
2013-01-06 19:41:57 +07:00
if ( tb [ IFLA_ADDRESS ] ) {
2007-08-09 12:16:38 +07:00
memcpy ( dev - > dev_addr , nla_data ( tb [ IFLA_ADDRESS ] ) ,
nla_len ( tb [ IFLA_ADDRESS ] ) ) ;
2013-01-06 19:41:57 +07:00
dev - > addr_assign_type = NET_ADDR_SET ;
}
2007-08-09 12:16:38 +07:00
if ( tb [ IFLA_BROADCAST ] )
memcpy ( dev - > broadcast , nla_data ( tb [ IFLA_BROADCAST ] ) ,
nla_len ( tb [ IFLA_BROADCAST ] ) ) ;
if ( tb [ IFLA_TXQLEN ] )
dev - > tx_queue_len = nla_get_u32 ( tb [ IFLA_TXQLEN ] ) ;
if ( tb [ IFLA_OPERSTATE ] )
2008-02-18 09:35:07 +07:00
set_operstate ( dev , nla_get_u8 ( tb [ IFLA_OPERSTATE ] ) ) ;
2007-08-09 12:16:38 +07:00
if ( tb [ IFLA_LINKMODE ] )
dev - > link_mode = nla_get_u8 ( tb [ IFLA_LINKMODE ] ) ;
2011-01-20 10:00:42 +07:00
if ( tb [ IFLA_GROUP ] )
dev_set_group ( dev , nla_get_u32 ( tb [ IFLA_GROUP ] ) ) ;
2007-08-09 12:16:38 +07:00
return dev ;
}
2009-11-07 16:26:17 +07:00
EXPORT_SYMBOL ( rtnl_create_link ) ;
2007-08-09 12:16:38 +07:00
2014-04-24 04:29:27 +07:00
static int rtnl_group_changelink ( const struct sk_buff * skb ,
struct net * net , int group ,
2011-01-14 06:38:31 +07:00
struct ifinfomsg * ifm ,
2017-05-01 11:46:46 +07:00
struct netlink_ext_ack * extack ,
2011-01-14 06:38:31 +07:00
struct nlattr * * tb )
{
2015-03-24 06:31:09 +07:00
struct net_device * dev , * aux ;
2011-01-14 06:38:31 +07:00
int err ;
2015-03-24 06:31:09 +07:00
for_each_netdev_safe ( net , dev , aux ) {
2011-01-14 06:38:31 +07:00
if ( dev - > group = = group ) {
2017-05-01 11:46:46 +07:00
err = do_setlink ( skb , dev , ifm , extack , tb , NULL , 0 ) ;
2011-01-14 06:38:31 +07:00
if ( err < 0 )
return err ;
}
}
return 0 ;
}
2017-04-16 23:48:24 +07:00
static int rtnl_newlink ( struct sk_buff * skb , struct nlmsghdr * nlh ,
struct netlink_ext_ack * extack )
2007-06-14 02:03:51 +07:00
{
2008-03-26 00:26:21 +07:00
struct net * net = sock_net ( skb - > sk ) ;
2007-06-14 02:03:51 +07:00
const struct rtnl_link_ops * ops ;
2014-01-22 15:05:55 +07:00
const struct rtnl_link_ops * m_ops = NULL ;
2007-06-14 02:03:51 +07:00
struct net_device * dev ;
2014-01-22 15:05:55 +07:00
struct net_device * master_dev = NULL ;
2007-06-14 02:03:51 +07:00
struct ifinfomsg * ifm ;
char kind [ MODULE_NAME_LEN ] ;
char ifname [ IFNAMSIZ ] ;
struct nlattr * tb [ IFLA_MAX + 1 ] ;
struct nlattr * linkinfo [ IFLA_INFO_MAX + 1 ] ;
2014-07-14 21:37:25 +07:00
unsigned char name_assign_type = NET_NAME_USER ;
2007-06-14 02:03:51 +07:00
int err ;
2008-10-17 05:24:51 +07:00
# ifdef CONFIG_MODULES
2007-06-14 02:03:51 +07:00
replay :
2007-08-01 04:13:50 +07:00
# endif
2017-04-16 23:48:24 +07:00
err = nlmsg_parse ( nlh , sizeof ( * ifm ) , tb , IFLA_MAX , ifla_policy , extack ) ;
2007-06-14 02:03:51 +07:00
if ( err < 0 )
return err ;
if ( tb [ IFLA_IFNAME ] )
nla_strlcpy ( ifname , tb [ IFLA_IFNAME ] , IFNAMSIZ ) ;
else
ifname [ 0 ] = ' \0 ' ;
ifm = nlmsg_data ( nlh ) ;
if ( ifm - > ifi_index > 0 )
2007-09-18 01:56:21 +07:00
dev = __dev_get_by_index ( net , ifm - > ifi_index ) ;
2011-01-14 06:38:31 +07:00
else {
if ( ifname [ 0 ] )
dev = __dev_get_by_name ( net , ifname ) ;
else
dev = NULL ;
}
2007-06-14 02:03:51 +07:00
2014-01-22 15:05:55 +07:00
if ( dev ) {
master_dev = netdev_master_upper_dev_get ( dev ) ;
if ( master_dev )
m_ops = master_dev - > rtnl_link_ops ;
}
2009-11-07 16:26:17 +07:00
err = validate_linkmsg ( dev , tb ) ;
if ( err < 0 )
2008-02-24 10:54:36 +07:00
return err ;
2007-06-14 02:03:51 +07:00
if ( tb [ IFLA_LINKINFO ] ) {
err = nla_parse_nested ( linkinfo , IFLA_INFO_MAX ,
2017-04-12 19:34:07 +07:00
tb [ IFLA_LINKINFO ] , ifla_info_policy ,
NULL ) ;
2007-06-14 02:03:51 +07:00
if ( err < 0 )
return err ;
} else
memset ( linkinfo , 0 , sizeof ( linkinfo ) ) ;
if ( linkinfo [ IFLA_INFO_KIND ] ) {
nla_strlcpy ( kind , linkinfo [ IFLA_INFO_KIND ] , sizeof ( kind ) ) ;
ops = rtnl_link_ops_get ( kind ) ;
} else {
kind [ 0 ] = ' \0 ' ;
ops = NULL ;
}
if ( 1 ) {
2015-02-25 02:14:35 +07:00
struct nlattr * attr [ ops ? ops - > maxtype + 1 : 1 ] ;
struct nlattr * slave_attr [ m_ops ? m_ops - > slave_maxtype + 1 : 1 ] ;
2014-01-22 15:05:55 +07:00
struct nlattr * * data = NULL ;
struct nlattr * * slave_data = NULL ;
2015-01-15 21:11:18 +07:00
struct net * dest_net , * link_net = NULL ;
2007-06-14 02:03:51 +07:00
if ( ops ) {
if ( ops - > maxtype & & linkinfo [ IFLA_INFO_DATA ] ) {
err = nla_parse_nested ( attr , ops - > maxtype ,
linkinfo [ IFLA_INFO_DATA ] ,
2017-04-12 19:34:07 +07:00
ops - > policy , NULL ) ;
2007-06-14 02:03:51 +07:00
if ( err < 0 )
return err ;
data = attr ;
}
if ( ops - > validate ) {
2017-06-26 04:56:01 +07:00
err = ops - > validate ( tb , data , extack ) ;
2007-06-14 02:03:51 +07:00
if ( err < 0 )
return err ;
}
}
2014-01-22 15:05:55 +07:00
if ( m_ops ) {
if ( m_ops - > slave_maxtype & &
linkinfo [ IFLA_INFO_SLAVE_DATA ] ) {
err = nla_parse_nested ( slave_attr ,
m_ops - > slave_maxtype ,
linkinfo [ IFLA_INFO_SLAVE_DATA ] ,
2017-04-12 19:34:07 +07:00
m_ops - > slave_policy ,
NULL ) ;
2014-01-22 15:05:55 +07:00
if ( err < 0 )
return err ;
slave_data = slave_attr ;
}
}
2007-06-14 02:03:51 +07:00
if ( dev ) {
2014-09-01 21:07:28 +07:00
int status = 0 ;
2007-06-14 02:03:51 +07:00
if ( nlh - > nlmsg_flags & NLM_F_EXCL )
return - EEXIST ;
if ( nlh - > nlmsg_flags & NLM_F_REPLACE )
return - EOPNOTSUPP ;
if ( linkinfo [ IFLA_INFO_DATA ] ) {
if ( ! ops | | ops ! = dev - > rtnl_link_ops | |
! ops - > changelink )
return - EOPNOTSUPP ;
2017-06-26 04:56:00 +07:00
err = ops - > changelink ( dev , tb , data , extack ) ;
2007-06-14 02:03:51 +07:00
if ( err < 0 )
return err ;
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
2007-06-14 02:03:51 +07:00
}
2014-01-22 15:05:55 +07:00
if ( linkinfo [ IFLA_INFO_SLAVE_DATA ] ) {
if ( ! m_ops | | ! m_ops - > slave_changelink )
return - EOPNOTSUPP ;
err = m_ops - > slave_changelink ( master_dev , dev ,
2017-06-26 04:56:02 +07:00
tb , slave_data ,
extack ) ;
2014-01-22 15:05:55 +07:00
if ( err < 0 )
return err ;
2014-09-01 21:07:29 +07:00
status | = DO_SETLINK_NOTIFY ;
2014-01-22 15:05:55 +07:00
}
2017-05-01 11:46:46 +07:00
return do_setlink ( skb , dev , ifm , extack , tb , ifname ,
status ) ;
2007-06-14 02:03:51 +07:00
}
2011-01-20 10:00:42 +07:00
if ( ! ( nlh - > nlmsg_flags & NLM_F_CREATE ) ) {
if ( ifm - > ifi_index = = 0 & & tb [ IFLA_GROUP ] )
2014-04-24 04:29:27 +07:00
return rtnl_group_changelink ( skb , net ,
2011-01-20 10:00:42 +07:00
nla_get_u32 ( tb [ IFLA_GROUP ] ) ,
2017-05-01 11:46:46 +07:00
ifm , extack , tb ) ;
2007-06-14 02:03:51 +07:00
return - ENODEV ;
2011-01-20 10:00:42 +07:00
}
2007-06-14 02:03:51 +07:00
2017-01-31 06:23:46 +07:00
if ( tb [ IFLA_MAP ] | | tb [ IFLA_PROTINFO ] )
2007-06-14 02:03:51 +07:00
return - EOPNOTSUPP ;
if ( ! ops ) {
2008-10-17 05:24:51 +07:00
# ifdef CONFIG_MODULES
2007-06-14 02:03:51 +07:00
if ( kind [ 0 ] ) {
__rtnl_unlock ( ) ;
request_module ( " rtnl-link-%s " , kind ) ;
rtnl_lock ( ) ;
ops = rtnl_link_ops_get ( kind ) ;
if ( ops )
goto replay ;
}
# endif
return - EOPNOTSUPP ;
}
2014-06-26 14:58:25 +07:00
if ( ! ops - > setup )
return - EOPNOTSUPP ;
2014-07-14 21:37:25 +07:00
if ( ! ifname [ 0 ] ) {
2007-06-14 02:03:51 +07:00
snprintf ( ifname , IFNAMSIZ , " %s%%d " , ops - > kind ) ;
2014-07-14 21:37:25 +07:00
name_assign_type = NET_NAME_ENUM ;
}
2007-08-09 12:16:38 +07:00
2009-11-08 15:53:51 +07:00
dest_net = rtnl_link_get_net ( net , tb ) ;
2011-01-29 21:57:22 +07:00
if ( IS_ERR ( dest_net ) )
return PTR_ERR ( dest_net ) ;
2015-02-27 05:19:00 +07:00
err = - EPERM ;
if ( ! netlink_ns_capable ( skb , dest_net - > user_ns , CAP_NET_ADMIN ) )
goto out ;
2015-01-15 21:11:18 +07:00
if ( tb [ IFLA_LINK_NETNSID ] ) {
int id = nla_get_s32 ( tb [ IFLA_LINK_NETNSID ] ) ;
link_net = get_net_ns_by_id ( dest_net , id ) ;
if ( ! link_net ) {
err = - EINVAL ;
goto out ;
}
2015-02-27 05:20:07 +07:00
err = - EPERM ;
if ( ! netlink_ns_capable ( skb , link_net - > user_ns , CAP_NET_ADMIN ) )
goto out ;
2015-01-15 21:11:18 +07:00
}
dev = rtnl_create_link ( link_net ? : dest_net , ifname ,
name_assign_type , ops , tb ) ;
2012-08-09 04:52:46 +07:00
if ( IS_ERR ( dev ) ) {
2007-08-09 12:16:38 +07:00
err = PTR_ERR ( dev ) ;
2012-08-09 04:52:46 +07:00
goto out ;
}
dev - > ifindex = ifm - > ifi_index ;
2014-02-12 06:51:30 +07:00
if ( ops - > newlink ) {
2017-06-26 04:55:59 +07:00
err = ops - > newlink ( link_net ? : net , dev , tb , data ,
extack ) ;
2014-02-12 06:51:30 +07:00
/* Drivers should call free_netdev() in ->destructor
2014-06-04 06:40:47 +07:00
* and unregister it on failure after registration
* so that device could be finally freed in rtnl_unlock .
2014-02-12 06:51:30 +07:00
*/
2014-06-04 06:40:47 +07:00
if ( err < 0 ) {
/* If device is not registered at all, free it now */
if ( dev - > reg_state = = NETREG_UNINITIALIZED )
free_netdev ( dev ) ;
2014-02-12 06:51:30 +07:00
goto out ;
2014-06-04 06:40:47 +07:00
}
2014-02-12 06:51:30 +07:00
} else {
2007-07-12 09:42:13 +07:00
err = register_netdevice ( dev ) ;
2014-02-12 06:51:30 +07:00
if ( err < 0 ) {
free_netdev ( dev ) ;
goto out ;
}
2013-08-14 16:35:42 +07:00
}
rtnetlink: support specifying device flags on device creation
commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f
Author: Patrick McHardy <kaber@trash.net>
Date: Tue Feb 23 20:41:30 2010 +0100
Support specifying the initial device flags when creating a device though
rtnl_link. Devices allocated by rtnl_create_link() are marked as INITIALIZING
in order to surpress netlink registration notifications. To complete setup,
rtnl_configure_link() must be called, which performs the device flag changes
and invokes the deferred notifiers if everything went well.
Two examples:
# add macvlan to eth0
#
$ ip link add link eth0 up allmulticast on type macvlan
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 26:f8:84:02:f9:2a brd ff:ff:ff:ff:ff:ff
[ROUTE]ff00::/8 dev macvlan0 table local metric 256 mtu 1500 advmss 1440 hoplimit 0
[ROUTE]fe80::/64 dev macvlan0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500
link/ether 26:f8:84:02:f9:2a
[ADDR]11: macvlan0 inet6 fe80::24f8:84ff:fe02:f92a/64 scope link
valid_lft forever preferred_lft forever
[ROUTE]local fe80::24f8:84ff:fe02:f92a via :: dev lo table local proto none metric 0 mtu 16436 advmss 16376 hoplimit 0
[ROUTE]default via fe80::215:e9ff:fef0:10f8 dev macvlan0 proto kernel metric 1024 mtu 1500 advmss 1440 hoplimit 0
[NEIGH]fe80::215:e9ff:fef0:10f8 dev macvlan0 lladdr 00:15:e9:f0:10:f8 router STALE
[ROUTE]2001:6f8:974::/64 dev macvlan0 proto kernel metric 256 expires 0sec mtu 1500 advmss 1440 hoplimit 0
[PREFIX]prefix 2001:6f8:974::/64 dev macvlan0 onlink autoconf valid 14400 preferred 131084
[ADDR]11: macvlan0 inet6 2001:6f8:974:0:24f8:84ff:fe02:f92a/64 scope global dynamic
valid_lft 86399sec preferred_lft 14399sec
# add VLAN to eth1, eth1 is down
#
$ ip link add link eth1 up type vlan id 1000
RTNETLINK answers: Network is down
<no events>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-02-26 13:34:54 +07:00
err = rtnl_configure_link ( dev , ifm ) ;
2015-03-11 08:58:32 +07:00
if ( err < 0 )
goto out_unregister ;
2015-01-20 21:15:42 +07:00
if ( link_net ) {
2015-01-15 21:11:18 +07:00
err = dev_change_net_namespace ( dev , dest_net , ifname ) ;
2015-01-20 21:15:42 +07:00
if ( err < 0 )
2015-03-11 08:58:32 +07:00
goto out_unregister ;
2015-01-20 21:15:42 +07:00
}
2017-01-31 06:23:46 +07:00
if ( tb [ IFLA_MASTER ] ) {
err = do_set_master ( dev , nla_get_u32 ( tb [ IFLA_MASTER ] ) ) ;
if ( err )
goto out_unregister ;
}
rtnetlink: support specifying device flags on device creation
commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f
Author: Patrick McHardy <kaber@trash.net>
Date: Tue Feb 23 20:41:30 2010 +0100
Support specifying the initial device flags when creating a device though
rtnl_link. Devices allocated by rtnl_create_link() are marked as INITIALIZING
in order to surpress netlink registration notifications. To complete setup,
rtnl_configure_link() must be called, which performs the device flag changes
and invokes the deferred notifiers if everything went well.
Two examples:
# add macvlan to eth0
#
$ ip link add link eth0 up allmulticast on type macvlan
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 26:f8:84:02:f9:2a brd ff:ff:ff:ff:ff:ff
[ROUTE]ff00::/8 dev macvlan0 table local metric 256 mtu 1500 advmss 1440 hoplimit 0
[ROUTE]fe80::/64 dev macvlan0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500
link/ether 26:f8:84:02:f9:2a
[ADDR]11: macvlan0 inet6 fe80::24f8:84ff:fe02:f92a/64 scope link
valid_lft forever preferred_lft forever
[ROUTE]local fe80::24f8:84ff:fe02:f92a via :: dev lo table local proto none metric 0 mtu 16436 advmss 16376 hoplimit 0
[ROUTE]default via fe80::215:e9ff:fef0:10f8 dev macvlan0 proto kernel metric 1024 mtu 1500 advmss 1440 hoplimit 0
[NEIGH]fe80::215:e9ff:fef0:10f8 dev macvlan0 lladdr 00:15:e9:f0:10:f8 router STALE
[ROUTE]2001:6f8:974::/64 dev macvlan0 proto kernel metric 256 expires 0sec mtu 1500 advmss 1440 hoplimit 0
[PREFIX]prefix 2001:6f8:974::/64 dev macvlan0 onlink autoconf valid 14400 preferred 131084
[ADDR]11: macvlan0 inet6 2001:6f8:974:0:24f8:84ff:fe02:f92a/64 scope global dynamic
valid_lft 86399sec preferred_lft 14399sec
# add VLAN to eth1, eth1 is down
#
$ ip link add link eth1 up type vlan id 1000
RTNETLINK answers: Network is down
<no events>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-02-26 13:34:54 +07:00
out :
2015-01-15 21:11:18 +07:00
if ( link_net )
put_net ( link_net ) ;
2009-11-08 15:53:51 +07:00
put_net ( dest_net ) ;
2007-06-14 02:03:51 +07:00
return err ;
2015-03-11 08:58:32 +07:00
out_unregister :
if ( ops - > newlink ) {
LIST_HEAD ( list_kill ) ;
ops - > dellink ( dev , & list_kill ) ;
unregister_netdevice_many ( & list_kill ) ;
} else {
unregister_netdevice ( dev ) ;
}
goto out ;
2007-06-14 02:03:51 +07:00
}
}
2017-04-16 23:48:24 +07:00
static int rtnl_getlink ( struct sk_buff * skb , struct nlmsghdr * nlh ,
struct netlink_ext_ack * extack )
2006-02-23 06:10:56 +07:00
{
2008-03-26 00:26:21 +07:00
struct net * net = sock_net ( skb - > sk ) ;
2006-08-05 13:05:34 +07:00
struct ifinfomsg * ifm ;
2009-10-21 17:59:31 +07:00
char ifname [ IFNAMSIZ ] ;
2006-08-05 13:05:34 +07:00
struct nlattr * tb [ IFLA_MAX + 1 ] ;
struct net_device * dev = NULL ;
struct sk_buff * nskb ;
2006-11-11 05:10:15 +07:00
int err ;
2012-02-22 04:54:48 +07:00
u32 ext_filter_mask = 0 ;
2006-02-23 06:10:56 +07:00
2017-04-16 23:48:24 +07:00
err = nlmsg_parse ( nlh , sizeof ( * ifm ) , tb , IFLA_MAX , ifla_policy , extack ) ;
2006-08-05 13:05:34 +07:00
if ( err < 0 )
2006-09-27 13:26:38 +07:00
return err ;
2006-08-05 13:05:34 +07:00
2009-10-21 17:59:31 +07:00
if ( tb [ IFLA_IFNAME ] )
nla_strlcpy ( ifname , tb [ IFLA_IFNAME ] , IFNAMSIZ ) ;
2012-02-22 04:54:48 +07:00
if ( tb [ IFLA_EXT_MASK ] )
ext_filter_mask = nla_get_u32 ( tb [ IFLA_EXT_MASK ] ) ;
2006-08-05 13:05:34 +07:00
ifm = nlmsg_data ( nlh ) ;
2009-10-21 17:59:31 +07:00
if ( ifm - > ifi_index > 0 )
dev = __dev_get_by_index ( net , ifm - > ifi_index ) ;
else if ( tb [ IFLA_IFNAME ] )
dev = __dev_get_by_name ( net , ifname ) ;
else
2006-02-23 06:10:56 +07:00
return - EINVAL ;
2009-10-21 17:59:31 +07:00
if ( dev = = NULL )
return - ENODEV ;
2012-02-22 04:54:48 +07:00
nskb = nlmsg_new ( if_nlmsg_size ( dev , ext_filter_mask ) , GFP_KERNEL ) ;
2009-10-21 17:59:31 +07:00
if ( nskb = = NULL )
return - ENOBUFS ;
2006-08-05 13:05:34 +07:00
2012-09-08 03:12:54 +07:00
err = rtnl_fill_ifinfo ( nskb , dev , RTM_NEWLINK , NETLINK_CB ( skb ) . portid ,
2017-05-27 21:14:34 +07:00
nlh - > nlmsg_seq , 0 , 0 , ext_filter_mask , 0 ) ;
2007-02-01 14:16:40 +07:00
if ( err < 0 ) {
/* -EMSGSIZE implies BUG in if_nlmsg_size */
WARN_ON ( err = = - EMSGSIZE ) ;
kfree_skb ( nskb ) ;
2009-10-21 17:59:31 +07:00
} else
2012-09-08 03:12:54 +07:00
err = rtnl_unicast ( nskb , net , NETLINK_CB ( skb ) . portid ) ;
2006-02-23 06:10:56 +07:00
2006-08-05 13:05:34 +07:00
return err ;
2006-02-23 06:10:56 +07:00
}
2012-02-22 04:54:48 +07:00
static u16 rtnl_calcit ( struct sk_buff * skb , struct nlmsghdr * nlh )
2011-06-10 08:27:09 +07:00
{
2012-02-22 04:54:48 +07:00
struct net * net = sock_net ( skb - > sk ) ;
struct net_device * dev ;
struct nlattr * tb [ IFLA_MAX + 1 ] ;
u32 ext_filter_mask = 0 ;
u16 min_ifinfo_dump_size = 0 ;
2014-05-28 19:15:19 +07:00
int hdrlen ;
/* Same kernel<->userspace interface hack as in rtnl_dump_ifinfo. */
hdrlen = nlmsg_len ( nlh ) < sizeof ( struct ifinfomsg ) ?
sizeof ( struct rtgenmsg ) : sizeof ( struct ifinfomsg ) ;
2012-02-22 04:54:48 +07:00
2017-04-12 19:34:07 +07:00
if ( nlmsg_parse ( nlh , hdrlen , tb , IFLA_MAX , ifla_policy , NULL ) > = 0 ) {
2012-03-04 19:32:10 +07:00
if ( tb [ IFLA_EXT_MASK ] )
ext_filter_mask = nla_get_u32 ( tb [ IFLA_EXT_MASK ] ) ;
}
2012-02-22 04:54:48 +07:00
if ( ! ext_filter_mask )
return NLMSG_GOODSIZE ;
/*
* traverse the list of net devices and compute the minimum
* buffer size based upon the filter mask .
*/
2017-08-10 01:41:51 +07:00
rcu_read_lock ( ) ;
for_each_netdev_rcu ( net , dev ) {
2012-02-22 04:54:48 +07:00
min_ifinfo_dump_size = max_t ( u16 , min_ifinfo_dump_size ,
if_nlmsg_size ( dev ,
ext_filter_mask ) ) ;
}
2017-08-10 01:41:51 +07:00
rcu_read_unlock ( ) ;
2012-02-22 04:54:48 +07:00
2016-11-22 13:14:28 +07:00
return nlmsg_total_size ( min_ifinfo_dump_size ) ;
2011-06-10 08:27:09 +07:00
}
2007-04-26 14:57:41 +07:00
static int rtnl_dump_all ( struct sk_buff * skb , struct netlink_callback * cb )
2005-04-17 05:20:36 +07:00
{
int idx ;
int s_idx = cb - > family ;
if ( s_idx = = 0 )
s_idx = 1 ;
2017-08-10 01:41:51 +07:00
2010-04-26 21:02:05 +07:00
for ( idx = 1 ; idx < = RTNL_FAMILY_MAX ; idx + + ) {
2005-04-17 05:20:36 +07:00
int type = cb - > nlh - > nlmsg_type - RTM_BASE ;
2017-08-10 01:41:51 +07:00
struct rtnl_link * handlers ;
rtnl_dumpit_func dumpit ;
2005-04-17 05:20:36 +07:00
if ( idx < s_idx | | idx = = PF_PACKET )
continue ;
2017-08-10 01:41:51 +07:00
handlers = rtnl_dereference ( rtnl_msg_handlers [ idx ] ) ;
if ( ! handlers )
2005-04-17 05:20:36 +07:00
continue ;
2017-08-10 01:41:51 +07:00
dumpit = READ_ONCE ( handlers [ type ] . dumpit ) ;
if ( ! dumpit )
continue ;
2013-03-22 13:28:42 +07:00
if ( idx > s_idx ) {
2005-04-17 05:20:36 +07:00
memset ( & cb - > args [ 0 ] , 0 , sizeof ( cb - > args ) ) ;
2013-03-22 13:28:42 +07:00
cb - > prev_seq = 0 ;
cb - > seq = 0 ;
}
2017-08-10 01:41:51 +07:00
if ( dumpit ( skb , cb ) )
2005-04-17 05:20:36 +07:00
break ;
}
cb - > family = idx ;
return skb - > len ;
}
2014-12-04 04:46:24 +07:00
struct sk_buff * rtmsg_ifinfo_build_skb ( int type , struct net_device * dev ,
2017-05-27 21:14:34 +07:00
unsigned int change ,
u32 event , gfp_t flags )
2005-04-17 05:20:36 +07:00
{
2008-03-25 19:47:49 +07:00
struct net * net = dev_net ( dev ) ;
2005-04-17 05:20:36 +07:00
struct sk_buff * skb ;
2006-08-15 14:37:09 +07:00
int err = - ENOBUFS ;
2011-06-10 08:27:09 +07:00
size_t if_info_size ;
2005-04-17 05:20:36 +07:00
2013-10-24 06:02:42 +07:00
skb = nlmsg_new ( ( if_info_size = if_nlmsg_size ( dev , 0 ) ) , flags ) ;
2006-08-15 14:37:09 +07:00
if ( skb = = NULL )
goto errout ;
2005-04-17 05:20:36 +07:00
2017-05-27 21:14:34 +07:00
err = rtnl_fill_ifinfo ( skb , dev , type , 0 , 0 , change , 0 , 0 , event ) ;
2007-02-01 14:16:40 +07:00
if ( err < 0 ) {
/* -EMSGSIZE implies BUG in if_nlmsg_size() */
WARN_ON ( err = = - EMSGSIZE ) ;
kfree_skb ( skb ) ;
goto errout ;
}
2014-12-04 04:46:24 +07:00
return skb ;
2006-08-15 14:37:09 +07:00
errout :
if ( err < 0 )
2007-11-20 13:27:40 +07:00
rtnl_set_sk_err ( net , RTNLGRP_LINK , err ) ;
2014-12-04 04:46:24 +07:00
return NULL ;
}
void rtmsg_ifinfo_send ( struct sk_buff * skb , struct net_device * dev , gfp_t flags )
{
struct net * net = dev_net ( dev ) ;
rtnl_notify ( skb , net , 0 , RTNLGRP_LINK , NULL , flags ) ;
}
2017-05-27 21:14:34 +07:00
static void rtmsg_ifinfo_event ( int type , struct net_device * dev ,
unsigned int change , u32 event ,
gfp_t flags )
2014-12-04 04:46:24 +07:00
{
struct sk_buff * skb ;
2015-05-13 19:19:42 +07:00
if ( dev - > reg_state ! = NETREG_REGISTERED )
return ;
2017-05-27 21:14:34 +07:00
skb = rtmsg_ifinfo_build_skb ( type , dev , change , event , flags ) ;
2014-12-04 04:46:24 +07:00
if ( skb )
rtmsg_ifinfo_send ( skb , dev , flags ) ;
2005-04-17 05:20:36 +07:00
}
2017-05-27 21:14:34 +07:00
void rtmsg_ifinfo ( int type , struct net_device * dev , unsigned int change ,
gfp_t flags )
{
2017-05-30 21:07:02 +07:00
rtmsg_ifinfo_event ( type , dev , change , rtnl_get_event ( 0 ) , flags ) ;
2017-05-27 21:14:34 +07:00
}
2013-01-04 05:49:01 +07:00
EXPORT_SYMBOL ( rtmsg_ifinfo ) ;
2005-04-17 05:20:36 +07:00
2012-04-15 13:44:08 +07:00
static int nlmsg_populate_fdb_fill ( struct sk_buff * skb ,
struct net_device * dev ,
2015-04-09 19:16:17 +07:00
u8 * addr , u16 vid , u32 pid , u32 seq ,
2014-03-19 23:47:49 +07:00
int type , unsigned int flags ,
2015-12-15 20:20:30 +07:00
int nlflags , u16 ndm_state )
2012-04-15 13:44:08 +07:00
{
struct nlmsghdr * nlh ;
struct ndmsg * ndm ;
2014-03-19 23:47:49 +07:00
nlh = nlmsg_put ( skb , pid , seq , type , sizeof ( * ndm ) , nlflags ) ;
2012-04-15 13:44:08 +07:00
if ( ! nlh )
return - EMSGSIZE ;
ndm = nlmsg_data ( nlh ) ;
ndm - > ndm_family = AF_BRIDGE ;
ndm - > ndm_pad1 = 0 ;
ndm - > ndm_pad2 = 0 ;
ndm - > ndm_flags = flags ;
ndm - > ndm_type = 0 ;
ndm - > ndm_ifindex = dev - > ifindex ;
2015-12-15 20:20:30 +07:00
ndm - > ndm_state = ndm_state ;
2012-04-15 13:44:08 +07:00
if ( nla_put ( skb , NDA_LLADDR , ETH_ALEN , addr ) )
goto nla_put_failure ;
2015-04-09 19:16:17 +07:00
if ( vid )
if ( nla_put ( skb , NDA_VLAN , sizeof ( u16 ) , & vid ) )
goto nla_put_failure ;
2012-04-15 13:44:08 +07:00
2015-01-17 04:09:00 +07:00
nlmsg_end ( skb , nlh ) ;
return 0 ;
2012-04-15 13:44:08 +07:00
nla_put_failure :
nlmsg_cancel ( skb , nlh ) ;
return - EMSGSIZE ;
}
2012-04-15 13:44:14 +07:00
static inline size_t rtnl_fdb_nlmsg_size ( void )
{
2016-11-18 21:50:39 +07:00
return NLMSG_ALIGN ( sizeof ( struct ndmsg ) ) +
nla_total_size ( ETH_ALEN ) + /* NDA_LLADDR */
nla_total_size ( sizeof ( u16 ) ) + /* NDA_VLAN */
0 ;
2012-04-15 13:44:14 +07:00
}
2015-12-15 20:20:30 +07:00
static void rtnl_fdb_notify ( struct net_device * dev , u8 * addr , u16 vid , int type ,
u16 ndm_state )
2012-04-15 13:44:14 +07:00
{
struct net * net = dev_net ( dev ) ;
struct sk_buff * skb ;
int err = - ENOBUFS ;
skb = nlmsg_new ( rtnl_fdb_nlmsg_size ( ) , GFP_ATOMIC ) ;
if ( ! skb )
goto errout ;
2015-04-09 19:16:17 +07:00
err = nlmsg_populate_fdb_fill ( skb , dev , addr , vid ,
2015-12-15 20:20:30 +07:00
0 , 0 , type , NTF_SELF , 0 , ndm_state ) ;
2012-04-15 13:44:14 +07:00
if ( err < 0 ) {
kfree_skb ( skb ) ;
goto errout ;
}
rtnl_notify ( skb , net , 0 , RTNLGRP_NEIGH , NULL , GFP_ATOMIC ) ;
return ;
errout :
rtnl_set_sk_err ( net , RTNLGRP_NEIGH , err ) ;
}
2013-03-06 22:39:42 +07:00
/**
* ndo_dflt_fdb_add - default netdevice operation to add an FDB entry
*/
int ndo_dflt_fdb_add ( struct ndmsg * ndm ,
struct nlattr * tb [ ] ,
struct net_device * dev ,
2014-11-28 20:34:15 +07:00
const unsigned char * addr , u16 vid ,
2013-03-06 22:39:42 +07:00
u16 flags )
{
int err = - EINVAL ;
/* If aging addresses are supported device will need to
* implement its own handler for this .
*/
if ( ndm - > ndm_state & & ! ( ndm - > ndm_state & NUD_PERMANENT ) ) {
pr_info ( " %s: FDB only supports static addresses \n " , dev - > name ) ;
return err ;
}
2014-12-14 23:19:05 +07:00
if ( vid ) {
pr_info ( " %s: vlans aren't supported yet for dev_uc|mc_add() \n " , dev - > name ) ;
return err ;
}
2013-03-06 22:39:42 +07:00
if ( is_unicast_ether_addr ( addr ) | | is_link_local_ether_addr ( addr ) )
err = dev_uc_add_excl ( dev , addr ) ;
else if ( is_multicast_ether_addr ( addr ) )
err = dev_mc_add_excl ( dev , addr ) ;
/* Only return duplicate errors if NLM_F_EXCL is set */
if ( err = = - EEXIST & & ! ( flags & NLM_F_EXCL ) )
err = 0 ;
return err ;
}
EXPORT_SYMBOL ( ndo_dflt_fdb_add ) ;
2014-11-28 20:34:15 +07:00
static int fdb_vid_parse ( struct nlattr * vlan_attr , u16 * p_vid )
{
u16 vid = 0 ;
if ( vlan_attr ) {
if ( nla_len ( vlan_attr ) ! = sizeof ( u16 ) ) {
pr_info ( " PF_BRIDGE: RTM_NEWNEIGH with invalid vlan \n " ) ;
return - EINVAL ;
}
vid = nla_get_u16 ( vlan_attr ) ;
if ( ! vid | | vid > = VLAN_VID_MASK ) {
pr_info ( " PF_BRIDGE: RTM_NEWNEIGH with invalid vlan id %d \n " ,
vid ) ;
return - EINVAL ;
}
}
* p_vid = vid ;
return 0 ;
}
2017-04-16 23:48:24 +07:00
static int rtnl_fdb_add ( struct sk_buff * skb , struct nlmsghdr * nlh ,
struct netlink_ext_ack * extack )
2012-04-15 13:43:56 +07:00
{
struct net * net = sock_net ( skb - > sk ) ;
struct ndmsg * ndm ;
struct nlattr * tb [ NDA_MAX + 1 ] ;
struct net_device * dev ;
u8 * addr ;
2014-11-28 20:34:15 +07:00
u16 vid ;
2012-04-15 13:43:56 +07:00
int err ;
2017-04-16 23:48:24 +07:00
err = nlmsg_parse ( nlh , sizeof ( * ndm ) , tb , NDA_MAX , NULL , extack ) ;
2012-04-15 13:43:56 +07:00
if ( err < 0 )
return err ;
ndm = nlmsg_data ( nlh ) ;
if ( ndm - > ndm_ifindex = = 0 ) {
pr_info ( " PF_BRIDGE: RTM_NEWNEIGH with invalid ifindex \n " ) ;
return - EINVAL ;
}
dev = __dev_get_by_index ( net , ndm - > ndm_ifindex ) ;
if ( dev = = NULL ) {
pr_info ( " PF_BRIDGE: RTM_NEWNEIGH with unknown ifindex \n " ) ;
return - ENODEV ;
}
if ( ! tb [ NDA_LLADDR ] | | nla_len ( tb [ NDA_LLADDR ] ) ! = ETH_ALEN ) {
pr_info ( " PF_BRIDGE: RTM_NEWNEIGH with invalid address \n " ) ;
return - EINVAL ;
}
addr = nla_data ( tb [ NDA_LLADDR ] ) ;
2014-11-28 20:34:15 +07:00
err = fdb_vid_parse ( tb [ NDA_VLAN ] , & vid ) ;
if ( err )
return err ;
2012-04-15 13:43:56 +07:00
err = - EOPNOTSUPP ;
/* Support fdb on master device the net/bridge default case */
if ( ( ! ndm - > ndm_flags | | ndm - > ndm_flags & NTF_MASTER ) & &
( dev - > priv_flags & IFF_BRIDGE_PORT ) ) {
2013-01-04 05:48:52 +07:00
struct net_device * br_dev = netdev_master_upper_dev_get ( dev ) ;
const struct net_device_ops * ops = br_dev - > netdev_ops ;
2014-11-28 20:34:15 +07:00
err = ops - > ndo_fdb_add ( ndm , tb , dev , addr , vid ,
nlh - > nlmsg_flags ) ;
2012-04-15 13:43:56 +07:00
if ( err )
goto out ;
else
ndm - > ndm_flags & = ~ NTF_MASTER ;
}
/* Embedded bridge, macvlan, and any other device support */
2013-03-06 22:39:42 +07:00
if ( ( ndm - > ndm_flags & NTF_SELF ) ) {
if ( dev - > netdev_ops - > ndo_fdb_add )
err = dev - > netdev_ops - > ndo_fdb_add ( ndm , tb , dev , addr ,
2014-11-28 20:34:15 +07:00
vid ,
2013-03-06 22:39:42 +07:00
nlh - > nlmsg_flags ) ;
else
2014-11-28 20:34:15 +07:00
err = ndo_dflt_fdb_add ( ndm , tb , dev , addr , vid ,
2013-03-06 22:39:42 +07:00
nlh - > nlmsg_flags ) ;
2012-04-15 13:43:56 +07:00
2012-04-15 13:44:14 +07:00
if ( ! err ) {
2015-12-15 20:20:30 +07:00
rtnl_fdb_notify ( dev , addr , vid , RTM_NEWNEIGH ,
ndm - > ndm_state ) ;
2012-04-15 13:43:56 +07:00
ndm - > ndm_flags & = ~ NTF_SELF ;
2012-04-15 13:44:14 +07:00
}
2012-04-15 13:43:56 +07:00
}
out :
return err ;
}
2013-03-06 22:39:42 +07:00
/**
* ndo_dflt_fdb_del - default netdevice operation to delete an FDB entry
*/
int ndo_dflt_fdb_del ( struct ndmsg * ndm ,
struct nlattr * tb [ ] ,
struct net_device * dev ,
2014-11-28 20:34:15 +07:00
const unsigned char * addr , u16 vid )
2013-03-06 22:39:42 +07:00
{
2014-07-16 05:15:20 +07:00
int err = - EINVAL ;
2013-03-06 22:39:42 +07:00
/* If aging addresses are supported device will need to
* implement its own handler for this .
*/
2013-08-09 05:19:48 +07:00
if ( ! ( ndm - > ndm_state & NUD_PERMANENT ) ) {
2013-03-06 22:39:42 +07:00
pr_info ( " %s: FDB only supports static addresses \n " , dev - > name ) ;
2014-07-16 05:15:20 +07:00
return err ;
2013-03-06 22:39:42 +07:00
}
if ( is_unicast_ether_addr ( addr ) | | is_link_local_ether_addr ( addr ) )
err = dev_uc_del ( dev , addr ) ;
else if ( is_multicast_ether_addr ( addr ) )
err = dev_mc_del ( dev , addr ) ;
return err ;
}
EXPORT_SYMBOL ( ndo_dflt_fdb_del ) ;
2017-04-16 23:48:24 +07:00
static int rtnl_fdb_del ( struct sk_buff * skb , struct nlmsghdr * nlh ,
struct netlink_ext_ack * extack )
2012-04-15 13:43:56 +07:00
{
struct net * net = sock_net ( skb - > sk ) ;
struct ndmsg * ndm ;
2013-02-13 19:00:18 +07:00
struct nlattr * tb [ NDA_MAX + 1 ] ;
2012-04-15 13:43:56 +07:00
struct net_device * dev ;
int err = - EINVAL ;
__u8 * addr ;
2014-11-28 20:34:15 +07:00
u16 vid ;
2012-04-15 13:43:56 +07:00
2014-04-24 04:29:27 +07:00
if ( ! netlink_capable ( skb , CAP_NET_ADMIN ) )
2013-02-13 19:00:18 +07:00
return - EPERM ;
2017-04-16 23:48:24 +07:00
err = nlmsg_parse ( nlh , sizeof ( * ndm ) , tb , NDA_MAX , NULL , extack ) ;
2013-02-13 19:00:18 +07:00
if ( err < 0 )
return err ;
2012-04-15 13:43:56 +07:00
ndm = nlmsg_data ( nlh ) ;
if ( ndm - > ndm_ifindex = = 0 ) {
pr_info ( " PF_BRIDGE: RTM_DELNEIGH with invalid ifindex \n " ) ;
return - EINVAL ;
}
dev = __dev_get_by_index ( net , ndm - > ndm_ifindex ) ;
if ( dev = = NULL ) {
pr_info ( " PF_BRIDGE: RTM_DELNEIGH with unknown ifindex \n " ) ;
return - ENODEV ;
}
2013-02-13 19:00:18 +07:00
if ( ! tb [ NDA_LLADDR ] | | nla_len ( tb [ NDA_LLADDR ] ) ! = ETH_ALEN ) {
pr_info ( " PF_BRIDGE: RTM_DELNEIGH with invalid address \n " ) ;
return - EINVAL ;
}
addr = nla_data ( tb [ NDA_LLADDR ] ) ;
2012-04-15 13:43:56 +07:00
2014-11-28 20:34:15 +07:00
err = fdb_vid_parse ( tb [ NDA_VLAN ] , & vid ) ;
if ( err )
return err ;
2012-04-15 13:43:56 +07:00
err = - EOPNOTSUPP ;
/* Support fdb on master device the net/bridge default case */
if ( ( ! ndm - > ndm_flags | | ndm - > ndm_flags & NTF_MASTER ) & &
( dev - > priv_flags & IFF_BRIDGE_PORT ) ) {
2013-01-04 05:48:52 +07:00
struct net_device * br_dev = netdev_master_upper_dev_get ( dev ) ;
const struct net_device_ops * ops = br_dev - > netdev_ops ;
2012-04-15 13:43:56 +07:00
2013-01-04 05:48:52 +07:00
if ( ops - > ndo_fdb_del )
2014-11-28 20:34:15 +07:00
err = ops - > ndo_fdb_del ( ndm , tb , dev , addr , vid ) ;
2012-04-15 13:43:56 +07:00
if ( err )
goto out ;
else
ndm - > ndm_flags & = ~ NTF_MASTER ;
}
/* Embedded bridge, macvlan, and any other device support */
2013-03-06 22:39:42 +07:00
if ( ndm - > ndm_flags & NTF_SELF ) {
if ( dev - > netdev_ops - > ndo_fdb_del )
2014-11-28 20:34:15 +07:00
err = dev - > netdev_ops - > ndo_fdb_del ( ndm , tb , dev , addr ,
vid ) ;
2013-03-06 22:39:42 +07:00
else
2014-11-28 20:34:15 +07:00
err = ndo_dflt_fdb_del ( ndm , tb , dev , addr , vid ) ;
2012-04-15 13:43:56 +07:00
2012-04-15 13:44:14 +07:00
if ( ! err ) {
2015-12-15 20:20:30 +07:00
rtnl_fdb_notify ( dev , addr , vid , RTM_DELNEIGH ,
ndm - > ndm_state ) ;
2012-04-15 13:43:56 +07:00
ndm - > ndm_flags & = ~ NTF_SELF ;
2012-04-15 13:44:14 +07:00
}
2012-04-15 13:43:56 +07:00
}
out :
return err ;
}
2012-04-15 13:44:08 +07:00
static int nlmsg_populate_fdb ( struct sk_buff * skb ,
struct netlink_callback * cb ,
struct net_device * dev ,
int * idx ,
struct netdev_hw_addr_list * list )
{
struct netdev_hw_addr * ha ;
int err ;
2012-09-08 03:12:54 +07:00
u32 portid , seq ;
2012-04-15 13:44:08 +07:00
2012-09-08 03:12:54 +07:00
portid = NETLINK_CB ( cb - > skb ) . portid ;
2012-04-15 13:44:08 +07:00
seq = cb - > nlh - > nlmsg_seq ;
list_for_each_entry ( ha , & list - > list , list ) {
2016-08-31 11:56:45 +07:00
if ( * idx < cb - > args [ 2 ] )
2012-04-15 13:44:08 +07:00
goto skip ;
2015-04-09 19:16:17 +07:00
err = nlmsg_populate_fdb_fill ( skb , dev , ha - > addr , 0 ,
2012-11-01 23:23:10 +07:00
portid , seq ,
2014-03-19 23:47:49 +07:00
RTM_NEWNEIGH , NTF_SELF ,
2015-12-15 20:20:30 +07:00
NLM_F_MULTI , NUD_PERMANENT ) ;
2012-04-15 13:44:08 +07:00
if ( err < 0 )
return err ;
skip :
* idx + = 1 ;
}
return 0 ;
}
/**
2012-07-10 17:55:09 +07:00
* ndo_dflt_fdb_dump - default netdevice operation to dump an FDB table .
2012-04-15 13:44:08 +07:00
* @ nlh : netlink message header
* @ dev : netdevice
*
* Default netdevice operation to dump the existing unicast address list .
2013-03-29 15:18:37 +07:00
* Returns number of addresses from list put in skb .
2012-04-15 13:44:08 +07:00
*/
int ndo_dflt_fdb_dump ( struct sk_buff * skb ,
struct netlink_callback * cb ,
struct net_device * dev ,
2014-07-10 18:01:58 +07:00
struct net_device * filter_dev ,
2016-08-31 11:56:45 +07:00
int * idx )
2012-04-15 13:44:08 +07:00
{
int err ;
netif_addr_lock_bh ( dev ) ;
2016-08-31 11:56:45 +07:00
err = nlmsg_populate_fdb ( skb , cb , dev , idx , & dev - > uc ) ;
2012-04-15 13:44:08 +07:00
if ( err )
goto out ;
2016-11-30 15:37:34 +07:00
err = nlmsg_populate_fdb ( skb , cb , dev , idx , & dev - > mc ) ;
2012-04-15 13:44:08 +07:00
out :
netif_addr_unlock_bh ( dev ) ;
2016-08-31 11:56:45 +07:00
return err ;
2012-04-15 13:44:08 +07:00
}
EXPORT_SYMBOL ( ndo_dflt_fdb_dump ) ;
2012-04-15 13:43:56 +07:00
static int rtnl_fdb_dump ( struct sk_buff * skb , struct netlink_callback * cb )
{
struct net_device * dev ;
2014-07-10 18:01:59 +07:00
struct nlattr * tb [ IFLA_MAX + 1 ] ;
struct net_device * br_dev = NULL ;
const struct net_device_ops * ops = NULL ;
const struct net_device_ops * cops = NULL ;
struct ifinfomsg * ifm = nlmsg_data ( cb - > nlh ) ;
struct net * net = sock_net ( skb - > sk ) ;
2016-08-31 11:56:45 +07:00
struct hlist_head * head ;
2014-07-10 18:01:59 +07:00
int brport_idx = 0 ;
int br_idx = 0 ;
2016-08-31 11:56:45 +07:00
int h , s_h ;
int idx = 0 , s_idx ;
int err = 0 ;
int fidx = 0 ;
2014-07-10 18:01:59 +07:00
net: rtnetlink: bail out from rtnl_fdb_dump() on parse error
rtnl_fdb_dump() failed to check the result of nlmsg_parse(), which led
to contents of |ifm| being uninitialized because nlh->nlmsglen was too
small to accommodate |ifm|. The uninitialized data may affect some
branches and result in unwanted effects, although kernel data doesn't
seem to leak to the userspace directly.
The bug has been detected with KMSAN and syzkaller.
For the record, here is the KMSAN report:
==================================================================
BUG: KMSAN: use of unitialized memory in rtnl_fdb_dump+0x5dc/0x1000
CPU: 0 PID: 1039 Comm: probe Not tainted 4.11.0-rc5+ #2727
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:16
dump_stack+0x143/0x1b0 lib/dump_stack.c:52
kmsan_report+0x12a/0x180 mm/kmsan/kmsan.c:1007
__kmsan_warning_32+0x66/0xb0 mm/kmsan/kmsan_instr.c:491
rtnl_fdb_dump+0x5dc/0x1000 net/core/rtnetlink.c:3230
netlink_dump+0x84f/0x1190 net/netlink/af_netlink.c:2168
__netlink_dump_start+0xc97/0xe50 net/netlink/af_netlink.c:2258
netlink_dump_start ./include/linux/netlink.h:165
rtnetlink_rcv_msg+0xae9/0xb40 net/core/rtnetlink.c:4094
netlink_rcv_skb+0x339/0x5a0 net/netlink/af_netlink.c:2339
rtnetlink_rcv+0x83/0xa0 net/core/rtnetlink.c:4110
netlink_unicast_kernel net/netlink/af_netlink.c:1272
netlink_unicast+0x13b7/0x1480 net/netlink/af_netlink.c:1298
netlink_sendmsg+0x10b8/0x10f0 net/netlink/af_netlink.c:1844
sock_sendmsg_nosec net/socket.c:633
sock_sendmsg net/socket.c:643
___sys_sendmsg+0xd4b/0x10f0 net/socket.c:1997
__sys_sendmsg net/socket.c:2031
SYSC_sendmsg+0x2c6/0x3f0 net/socket.c:2042
SyS_sendmsg+0x87/0xb0 net/socket.c:2038
do_syscall_64+0x102/0x150 arch/x86/entry/common.c:285
entry_SYSCALL64_slow_path+0x25/0x25 arch/x86/entry/entry_64.S:246
RIP: 0033:0x401300
RSP: 002b:00007ffc3b0e6d58 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 00000000004002b0 RCX: 0000000000401300
RDX: 0000000000000000 RSI: 00007ffc3b0e6d80 RDI: 0000000000000003
RBP: 00007ffc3b0e6e00 R08: 000000000000000b R09: 0000000000000004
R10: 000000000000000d R11: 0000000000000246 R12: 0000000000000000
R13: 00000000004065a0 R14: 0000000000406630 R15: 0000000000000000
origin: 000000008fe00056
save_stack_trace+0x59/0x60 arch/x86/kernel/stacktrace.c:59
kmsan_save_stack_with_flags mm/kmsan/kmsan.c:352
kmsan_internal_poison_shadow+0xb1/0x1a0 mm/kmsan/kmsan.c:247
kmsan_poison_shadow+0x6d/0xc0 mm/kmsan/kmsan.c:260
slab_alloc_node mm/slub.c:2743
__kmalloc_node_track_caller+0x1f4/0x390 mm/slub.c:4349
__kmalloc_reserve net/core/skbuff.c:138
__alloc_skb+0x2cd/0x740 net/core/skbuff.c:231
alloc_skb ./include/linux/skbuff.h:933
netlink_alloc_large_skb net/netlink/af_netlink.c:1144
netlink_sendmsg+0x934/0x10f0 net/netlink/af_netlink.c:1819
sock_sendmsg_nosec net/socket.c:633
sock_sendmsg net/socket.c:643
___sys_sendmsg+0xd4b/0x10f0 net/socket.c:1997
__sys_sendmsg net/socket.c:2031
SYSC_sendmsg+0x2c6/0x3f0 net/socket.c:2042
SyS_sendmsg+0x87/0xb0 net/socket.c:2038
do_syscall_64+0x102/0x150 arch/x86/entry/common.c:285
return_from_SYSCALL_64+0x0/0x6a arch/x86/entry/entry_64.S:246
==================================================================
and the reproducer:
==================================================================
#include <sys/socket.h>
#include <net/if_arp.h>
#include <linux/netlink.h>
#include <stdint.h>
int main()
{
int sock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, 0);
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
char nlmsg_buf[32];
memset(nlmsg_buf, 0, sizeof(nlmsg_buf));
struct nlmsghdr *nlmsg = nlmsg_buf;
nlmsg->nlmsg_len = 0x11;
nlmsg->nlmsg_type = 0x1e; // RTM_NEWROUTE = RTM_BASE + 0x0e
// type = 0x0e = 1110b
// kind = 2
nlmsg->nlmsg_flags = 0x101; // NLM_F_ROOT | NLM_F_REQUEST
nlmsg->nlmsg_seq = 0;
nlmsg->nlmsg_pid = 0;
nlmsg_buf[16] = (char)7;
struct iovec iov;
iov.iov_base = nlmsg_buf;
iov.iov_len = 17;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(sock, &msg, 0);
return 0;
}
==================================================================
Signed-off-by: Alexander Potapenko <glider@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-05-23 18:20:28 +07:00
err = nlmsg_parse ( cb - > nlh , sizeof ( struct ifinfomsg ) , tb ,
IFLA_MAX , ifla_policy , NULL ) ;
if ( err < 0 ) {
return - EINVAL ;
} else if ( err = = 0 ) {
2014-07-10 18:01:59 +07:00
if ( tb [ IFLA_MASTER ] )
br_idx = nla_get_u32 ( tb [ IFLA_MASTER ] ) ;
}
brport_idx = ifm - > ifi_index ;
if ( br_idx ) {
br_dev = __dev_get_by_index ( net , br_idx ) ;
if ( ! br_dev )
return - ENODEV ;
ops = br_dev - > netdev_ops ;
}
2016-08-31 11:56:45 +07:00
s_h = cb - > args [ 0 ] ;
s_idx = cb - > args [ 1 ] ;
2014-07-10 18:01:59 +07:00
2016-08-31 11:56:45 +07:00
for ( h = s_h ; h < NETDEV_HASHENTRIES ; h + + , s_idx = 0 ) {
idx = 0 ;
head = & net - > dev_index_head [ h ] ;
hlist_for_each_entry ( dev , head , index_hlist ) {
2014-07-10 18:01:59 +07:00
2016-08-31 11:56:45 +07:00
if ( brport_idx & & ( dev - > ifindex ! = brport_idx ) )
2014-07-10 18:01:59 +07:00
continue ;
2016-08-31 11:56:45 +07:00
if ( ! br_idx ) { /* user did not specify a specific bridge */
if ( dev - > priv_flags & IFF_BRIDGE_PORT ) {
br_dev = netdev_master_upper_dev_get ( dev ) ;
cops = br_dev - > netdev_ops ;
}
} else {
if ( dev ! = br_dev & &
! ( dev - > priv_flags & IFF_BRIDGE_PORT ) )
continue ;
2014-07-10 18:01:59 +07:00
2016-08-31 11:56:45 +07:00
if ( br_dev ! = netdev_master_upper_dev_get ( dev ) & &
! ( dev - > priv_flags & IFF_EBRIDGE ) )
continue ;
cops = ops ;
}
2012-04-15 13:43:56 +07:00
2016-08-31 11:56:45 +07:00
if ( idx < s_idx )
goto cont ;
2012-04-15 13:43:56 +07:00
2016-08-31 11:56:45 +07:00
if ( dev - > priv_flags & IFF_BRIDGE_PORT ) {
if ( cops & & cops - > ndo_fdb_dump ) {
err = cops - > ndo_fdb_dump ( skb , cb ,
br_dev , dev ,
& fidx ) ;
if ( err = = - EMSGSIZE )
goto out ;
}
}
2014-07-10 18:01:59 +07:00
2016-08-31 11:56:45 +07:00
if ( dev - > netdev_ops - > ndo_fdb_dump )
err = dev - > netdev_ops - > ndo_fdb_dump ( skb , cb ,
dev , NULL ,
& fidx ) ;
else
err = ndo_dflt_fdb_dump ( skb , cb , dev , NULL ,
& fidx ) ;
if ( err = = - EMSGSIZE )
goto out ;
cops = NULL ;
/* reset fdb offset to 0 for rest of the interfaces */
cb - > args [ 2 ] = 0 ;
fidx = 0 ;
cont :
idx + + ;
}
2012-04-15 13:43:56 +07:00
}
2016-08-31 11:56:45 +07:00
out :
cb - > args [ 0 ] = h ;
cb - > args [ 1 ] = idx ;
cb - > args [ 2 ] = fidx ;
2012-04-15 13:43:56 +07:00
return skb - > len ;
}
2014-11-28 20:34:25 +07:00
static int brport_nla_put_flag ( struct sk_buff * skb , u32 flags , u32 mask ,
unsigned int attrnum , unsigned int flag )
{
if ( mask & flag )
return nla_put_u8 ( skb , attrnum , ! ! ( flags & flag ) ) ;
return 0 ;
}
2012-10-24 15:13:09 +07:00
int ndo_dflt_bridge_getlink ( struct sk_buff * skb , u32 pid , u32 seq ,
2014-11-28 20:34:25 +07:00
struct net_device * dev , u16 mode ,
2015-06-22 14:27:17 +07:00
u32 flags , u32 mask , int nlflags ,
u32 filter_mask ,
int ( * vlan_fill ) ( struct sk_buff * skb ,
struct net_device * dev ,
u32 filter_mask ) )
2012-10-24 15:13:09 +07:00
{
struct nlmsghdr * nlh ;
struct ifinfomsg * ifm ;
struct nlattr * br_afspec ;
2014-11-28 20:34:25 +07:00
struct nlattr * protinfo ;
2012-10-24 15:13:09 +07:00
u8 operstate = netif_running ( dev ) ? dev - > operstate : IF_OPER_DOWN ;
2013-01-04 05:48:52 +07:00
struct net_device * br_dev = netdev_master_upper_dev_get ( dev ) ;
2015-06-22 14:27:17 +07:00
int err = 0 ;
2012-10-24 15:13:09 +07:00
2015-04-28 23:33:49 +07:00
nlh = nlmsg_put ( skb , pid , seq , RTM_NEWLINK , sizeof ( * ifm ) , nlflags ) ;
2012-10-24 15:13:09 +07:00
if ( nlh = = NULL )
return - EMSGSIZE ;
ifm = nlmsg_data ( nlh ) ;
ifm - > ifi_family = AF_BRIDGE ;
ifm - > __ifi_pad = 0 ;
ifm - > ifi_type = dev - > type ;
ifm - > ifi_index = dev - > ifindex ;
ifm - > ifi_flags = dev_get_flags ( dev ) ;
ifm - > ifi_change = 0 ;
if ( nla_put_string ( skb , IFLA_IFNAME , dev - > name ) | |
nla_put_u32 ( skb , IFLA_MTU , dev - > mtu ) | |
nla_put_u8 ( skb , IFLA_OPERSTATE , operstate ) | |
2013-01-04 05:48:52 +07:00
( br_dev & &
nla_put_u32 ( skb , IFLA_MASTER , br_dev - > ifindex ) ) | |
2012-10-24 15:13:09 +07:00
( dev - > addr_len & &
nla_put ( skb , IFLA_ADDRESS , dev - > addr_len , dev - > dev_addr ) ) | |
2015-04-02 22:07:00 +07:00
( dev - > ifindex ! = dev_get_iflink ( dev ) & &
nla_put_u32 ( skb , IFLA_LINK , dev_get_iflink ( dev ) ) ) )
2012-10-24 15:13:09 +07:00
goto nla_put_failure ;
br_afspec = nla_nest_start ( skb , IFLA_AF_SPEC ) ;
if ( ! br_afspec )
goto nla_put_failure ;
2014-12-09 05:04:20 +07:00
if ( nla_put_u16 ( skb , IFLA_BRIDGE_FLAGS , BRIDGE_FLAGS_SELF ) ) {
2012-10-24 15:13:09 +07:00
nla_nest_cancel ( skb , br_afspec ) ;
goto nla_put_failure ;
}
2014-12-09 05:04:20 +07:00
if ( mode ! = BRIDGE_MODE_UNDEF ) {
if ( nla_put_u16 ( skb , IFLA_BRIDGE_MODE , mode ) ) {
nla_nest_cancel ( skb , br_afspec ) ;
goto nla_put_failure ;
}
}
2015-06-22 14:27:17 +07:00
if ( vlan_fill ) {
err = vlan_fill ( skb , dev , filter_mask ) ;
if ( err ) {
nla_nest_cancel ( skb , br_afspec ) ;
goto nla_put_failure ;
}
}
2012-10-24 15:13:09 +07:00
nla_nest_end ( skb , br_afspec ) ;
2014-11-28 20:34:25 +07:00
protinfo = nla_nest_start ( skb , IFLA_PROTINFO | NLA_F_NESTED ) ;
if ( ! protinfo )
goto nla_put_failure ;
if ( brport_nla_put_flag ( skb , flags , mask ,
IFLA_BRPORT_MODE , BR_HAIRPIN_MODE ) | |
brport_nla_put_flag ( skb , flags , mask ,
IFLA_BRPORT_GUARD , BR_BPDU_GUARD ) | |
brport_nla_put_flag ( skb , flags , mask ,
IFLA_BRPORT_FAST_LEAVE ,
BR_MULTICAST_FAST_LEAVE ) | |
brport_nla_put_flag ( skb , flags , mask ,
IFLA_BRPORT_PROTECT , BR_ROOT_BLOCK ) | |
brport_nla_put_flag ( skb , flags , mask ,
IFLA_BRPORT_LEARNING , BR_LEARNING ) | |
brport_nla_put_flag ( skb , flags , mask ,
IFLA_BRPORT_LEARNING_SYNC , BR_LEARNING_SYNC ) | |
brport_nla_put_flag ( skb , flags , mask ,
IFLA_BRPORT_UNICAST_FLOOD , BR_FLOOD ) | |
brport_nla_put_flag ( skb , flags , mask ,
IFLA_BRPORT_PROXYARP , BR_PROXYARP ) ) {
nla_nest_cancel ( skb , protinfo ) ;
goto nla_put_failure ;
}
nla_nest_end ( skb , protinfo ) ;
2015-01-17 04:09:00 +07:00
nlmsg_end ( skb , nlh ) ;
return 0 ;
2012-10-24 15:13:09 +07:00
nla_put_failure :
nlmsg_cancel ( skb , nlh ) ;
2015-06-22 14:27:17 +07:00
return err ? err : - EMSGSIZE ;
2012-10-24 15:13:09 +07:00
}
2015-06-22 14:27:17 +07:00
EXPORT_SYMBOL_GPL ( ndo_dflt_bridge_getlink ) ;
2012-10-24 15:13:09 +07:00
2012-10-24 15:12:57 +07:00
static int rtnl_bridge_getlink ( struct sk_buff * skb , struct netlink_callback * cb )
{
struct net * net = sock_net ( skb - > sk ) ;
struct net_device * dev ;
int idx = 0 ;
u32 portid = NETLINK_CB ( cb - > skb ) . portid ;
u32 seq = cb - > nlh - > nlmsg_seq ;
2013-02-13 19:00:13 +07:00
u32 filter_mask = 0 ;
2015-09-16 04:44:29 +07:00
int err ;
2013-02-13 19:00:13 +07:00
2014-11-26 19:42:20 +07:00
if ( nlmsg_len ( cb - > nlh ) > sizeof ( struct ifinfomsg ) ) {
struct nlattr * extfilt ;
extfilt = nlmsg_find_attr ( cb - > nlh , sizeof ( struct ifinfomsg ) ,
IFLA_EXT_MASK ) ;
if ( extfilt ) {
if ( nla_len ( extfilt ) < sizeof ( filter_mask ) )
return - EINVAL ;
filter_mask = nla_get_u32 ( extfilt ) ;
}
}
2012-10-24 15:12:57 +07:00
rcu_read_lock ( ) ;
for_each_netdev_rcu ( net , dev ) {
const struct net_device_ops * ops = dev - > netdev_ops ;
2013-01-04 05:48:52 +07:00
struct net_device * br_dev = netdev_master_upper_dev_get ( dev ) ;
2012-10-24 15:12:57 +07:00
2013-01-04 05:48:52 +07:00
if ( br_dev & & br_dev - > netdev_ops - > ndo_bridge_getlink ) {
2015-09-16 04:44:29 +07:00
if ( idx > = cb - > args [ 0 ] ) {
err = br_dev - > netdev_ops - > ndo_bridge_getlink (
skb , portid , seq , dev ,
filter_mask , NLM_F_MULTI ) ;
2017-05-16 13:19:17 +07:00
if ( err < 0 & & err ! = - EOPNOTSUPP ) {
if ( likely ( skb - > len ) )
break ;
goto out_err ;
}
2015-09-16 04:44:29 +07:00
}
2012-11-02 19:56:52 +07:00
idx + + ;
2012-10-24 15:12:57 +07:00
}
if ( ops - > ndo_bridge_getlink ) {
2015-09-16 04:44:29 +07:00
if ( idx > = cb - > args [ 0 ] ) {
err = ops - > ndo_bridge_getlink ( skb , portid ,
seq , dev ,
filter_mask ,
NLM_F_MULTI ) ;
2017-05-16 13:19:17 +07:00
if ( err < 0 & & err ! = - EOPNOTSUPP ) {
if ( likely ( skb - > len ) )
break ;
goto out_err ;
}
2015-09-16 04:44:29 +07:00
}
2012-11-02 19:56:52 +07:00
idx + + ;
2012-10-24 15:12:57 +07:00
}
}
2017-05-16 13:19:17 +07:00
err = skb - > len ;
out_err :
2012-10-24 15:12:57 +07:00
rcu_read_unlock ( ) ;
cb - > args [ 0 ] = idx ;
2017-05-16 13:19:17 +07:00
return err ;
2012-10-24 15:12:57 +07:00
}
2012-10-24 15:13:03 +07:00
static inline size_t bridge_nlmsg_size ( void )
{
return NLMSG_ALIGN ( sizeof ( struct ifinfomsg ) )
+ nla_total_size ( IFNAMSIZ ) /* IFLA_IFNAME */
+ nla_total_size ( MAX_ADDR_LEN ) /* IFLA_ADDRESS */
+ nla_total_size ( sizeof ( u32 ) ) /* IFLA_MASTER */
+ nla_total_size ( sizeof ( u32 ) ) /* IFLA_MTU */
+ nla_total_size ( sizeof ( u32 ) ) /* IFLA_LINK */
+ nla_total_size ( sizeof ( u32 ) ) /* IFLA_OPERSTATE */
+ nla_total_size ( sizeof ( u8 ) ) /* IFLA_PROTINFO */
+ nla_total_size ( sizeof ( struct nlattr ) ) /* IFLA_AF_SPEC */
+ nla_total_size ( sizeof ( u16 ) ) /* IFLA_BRIDGE_FLAGS */
+ nla_total_size ( sizeof ( u16 ) ) ; /* IFLA_BRIDGE_MODE */
}
bridge: fix setlink/dellink notifications
problems with bridge getlink/setlink notifications today:
- bridge setlink generates two notifications to userspace
- one from the bridge driver
- one from rtnetlink.c (rtnl_bridge_notify)
- dellink generates one notification from rtnetlink.c. Which
means bridge setlink and dellink notifications are not
consistent
- Looking at the code it appears,
If both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF were set,
the size calculation in rtnl_bridge_notify can be wrong.
Example: if you set both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF
in a setlink request to rocker dev, rtnl_bridge_notify will
allocate skb for one set of bridge attributes, but,
both the bridge driver and rocker dev will try to add
attributes resulting in twice the number of attributes
being added to the skb. (rocker dev calls ndo_dflt_bridge_getlink)
There are multiple options:
1) Generate one notification including all attributes from master and self:
But, I don't think it will work, because both master and self may use
the same attributes/policy. Cannot pack the same set of attributes in a
single notification from both master and slave (duplicate attributes).
2) Generate one notification from master and the other notification from
self (This seems to be ideal):
For master: the master driver will send notification (bridge in this
example)
For self: the self driver will send notification (rocker in the above
example. It can use helpers from rtnetlink.c to do so. Like the
ndo_dflt_bridge_getlink api).
This patch implements 2) (leaving the 'rtnl_bridge_notify' around to be used
with 'self').
v1->v2 :
- rtnl_bridge_notify is now called only for self,
so, remove 'BRIDGE_FLAGS_SELF' check and cleanup a few things
- rtnl_bridge_dellink used to always send a RTM_NEWLINK msg
earlier. So, I have changed the notification from br_dellink to
go as RTM_NEWLINK
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-01-15 11:02:25 +07:00
static int rtnl_bridge_notify ( struct net_device * dev )
2012-10-24 15:13:03 +07:00
{
struct net * net = dev_net ( dev ) ;
struct sk_buff * skb ;
int err = - EOPNOTSUPP ;
bridge: fix setlink/dellink notifications
problems with bridge getlink/setlink notifications today:
- bridge setlink generates two notifications to userspace
- one from the bridge driver
- one from rtnetlink.c (rtnl_bridge_notify)
- dellink generates one notification from rtnetlink.c. Which
means bridge setlink and dellink notifications are not
consistent
- Looking at the code it appears,
If both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF were set,
the size calculation in rtnl_bridge_notify can be wrong.
Example: if you set both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF
in a setlink request to rocker dev, rtnl_bridge_notify will
allocate skb for one set of bridge attributes, but,
both the bridge driver and rocker dev will try to add
attributes resulting in twice the number of attributes
being added to the skb. (rocker dev calls ndo_dflt_bridge_getlink)
There are multiple options:
1) Generate one notification including all attributes from master and self:
But, I don't think it will work, because both master and self may use
the same attributes/policy. Cannot pack the same set of attributes in a
single notification from both master and slave (duplicate attributes).
2) Generate one notification from master and the other notification from
self (This seems to be ideal):
For master: the master driver will send notification (bridge in this
example)
For self: the self driver will send notification (rocker in the above
example. It can use helpers from rtnetlink.c to do so. Like the
ndo_dflt_bridge_getlink api).
This patch implements 2) (leaving the 'rtnl_bridge_notify' around to be used
with 'self').
v1->v2 :
- rtnl_bridge_notify is now called only for self,
so, remove 'BRIDGE_FLAGS_SELF' check and cleanup a few things
- rtnl_bridge_dellink used to always send a RTM_NEWLINK msg
earlier. So, I have changed the notification from br_dellink to
go as RTM_NEWLINK
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-01-15 11:02:25 +07:00
if ( ! dev - > netdev_ops - > ndo_bridge_getlink )
return 0 ;
2012-10-24 15:13:03 +07:00
skb = nlmsg_new ( bridge_nlmsg_size ( ) , GFP_ATOMIC ) ;
if ( ! skb ) {
err = - ENOMEM ;
goto errout ;
}
2015-04-28 23:33:49 +07:00
err = dev - > netdev_ops - > ndo_bridge_getlink ( skb , 0 , 0 , dev , 0 , 0 ) ;
bridge: fix setlink/dellink notifications
problems with bridge getlink/setlink notifications today:
- bridge setlink generates two notifications to userspace
- one from the bridge driver
- one from rtnetlink.c (rtnl_bridge_notify)
- dellink generates one notification from rtnetlink.c. Which
means bridge setlink and dellink notifications are not
consistent
- Looking at the code it appears,
If both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF were set,
the size calculation in rtnl_bridge_notify can be wrong.
Example: if you set both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF
in a setlink request to rocker dev, rtnl_bridge_notify will
allocate skb for one set of bridge attributes, but,
both the bridge driver and rocker dev will try to add
attributes resulting in twice the number of attributes
being added to the skb. (rocker dev calls ndo_dflt_bridge_getlink)
There are multiple options:
1) Generate one notification including all attributes from master and self:
But, I don't think it will work, because both master and self may use
the same attributes/policy. Cannot pack the same set of attributes in a
single notification from both master and slave (duplicate attributes).
2) Generate one notification from master and the other notification from
self (This seems to be ideal):
For master: the master driver will send notification (bridge in this
example)
For self: the self driver will send notification (rocker in the above
example. It can use helpers from rtnetlink.c to do so. Like the
ndo_dflt_bridge_getlink api).
This patch implements 2) (leaving the 'rtnl_bridge_notify' around to be used
with 'self').
v1->v2 :
- rtnl_bridge_notify is now called only for self,
so, remove 'BRIDGE_FLAGS_SELF' check and cleanup a few things
- rtnl_bridge_dellink used to always send a RTM_NEWLINK msg
earlier. So, I have changed the notification from br_dellink to
go as RTM_NEWLINK
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-01-15 11:02:25 +07:00
if ( err < 0 )
goto errout ;
2012-10-24 15:13:03 +07:00
2015-01-29 07:23:11 +07:00
if ( ! skb - > len )
goto errout ;
2012-10-24 15:13:03 +07:00
rtnl_notify ( skb , net , 0 , RTNLGRP_LINK , NULL , GFP_ATOMIC ) ;
return 0 ;
errout :
WARN_ON ( err = = - EMSGSIZE ) ;
kfree_skb ( skb ) ;
2015-01-29 07:23:11 +07:00
if ( err )
rtnl_set_sk_err ( net , RTNLGRP_LINK , err ) ;
2012-10-24 15:13:03 +07:00
return err ;
}
2017-04-16 23:48:24 +07:00
static int rtnl_bridge_setlink ( struct sk_buff * skb , struct nlmsghdr * nlh ,
struct netlink_ext_ack * extack )
2012-10-24 15:12:57 +07:00
{
struct net * net = sock_net ( skb - > sk ) ;
struct ifinfomsg * ifm ;
struct net_device * dev ;
2012-10-24 15:13:03 +07:00
struct nlattr * br_spec , * attr = NULL ;
int rem , err = - EOPNOTSUPP ;
2015-01-19 16:45:04 +07:00
u16 flags = 0 ;
2012-11-02 23:32:36 +07:00
bool have_flags = false ;
2012-10-24 15:12:57 +07:00
if ( nlmsg_len ( nlh ) < sizeof ( * ifm ) )
return - EINVAL ;
ifm = nlmsg_data ( nlh ) ;
if ( ifm - > ifi_family ! = AF_BRIDGE )
return - EPFNOSUPPORT ;
dev = __dev_get_by_index ( net , ifm - > ifi_index ) ;
if ( ! dev ) {
pr_info ( " PF_BRIDGE: RTM_SETLINK with unknown ifindex \n " ) ;
return - ENODEV ;
}
2012-10-24 15:13:03 +07:00
br_spec = nlmsg_find_attr ( nlh , sizeof ( struct ifinfomsg ) , IFLA_AF_SPEC ) ;
if ( br_spec ) {
nla_for_each_nested ( attr , br_spec , rem ) {
if ( nla_type ( attr ) = = IFLA_BRIDGE_FLAGS ) {
2014-11-26 19:42:16 +07:00
if ( nla_len ( attr ) < sizeof ( flags ) )
return - EINVAL ;
2012-11-02 23:32:36 +07:00
have_flags = true ;
2012-10-24 15:13:03 +07:00
flags = nla_get_u16 ( attr ) ;
break ;
}
}
}
if ( ! flags | | ( flags & BRIDGE_FLAGS_MASTER ) ) {
2013-01-04 05:48:52 +07:00
struct net_device * br_dev = netdev_master_upper_dev_get ( dev ) ;
if ( ! br_dev | | ! br_dev - > netdev_ops - > ndo_bridge_setlink ) {
2012-10-24 15:13:03 +07:00
err = - EOPNOTSUPP ;
goto out ;
}
2015-01-30 13:40:12 +07:00
err = br_dev - > netdev_ops - > ndo_bridge_setlink ( dev , nlh , flags ) ;
2012-10-24 15:12:57 +07:00
if ( err )
goto out ;
2012-10-24 15:13:03 +07:00
flags & = ~ BRIDGE_FLAGS_MASTER ;
2012-10-24 15:12:57 +07:00
}
2012-10-24 15:13:03 +07:00
if ( ( flags & BRIDGE_FLAGS_SELF ) ) {
if ( ! dev - > netdev_ops - > ndo_bridge_setlink )
err = - EOPNOTSUPP ;
else
2015-01-30 13:40:12 +07:00
err = dev - > netdev_ops - > ndo_bridge_setlink ( dev , nlh ,
flags ) ;
bridge: fix setlink/dellink notifications
problems with bridge getlink/setlink notifications today:
- bridge setlink generates two notifications to userspace
- one from the bridge driver
- one from rtnetlink.c (rtnl_bridge_notify)
- dellink generates one notification from rtnetlink.c. Which
means bridge setlink and dellink notifications are not
consistent
- Looking at the code it appears,
If both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF were set,
the size calculation in rtnl_bridge_notify can be wrong.
Example: if you set both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF
in a setlink request to rocker dev, rtnl_bridge_notify will
allocate skb for one set of bridge attributes, but,
both the bridge driver and rocker dev will try to add
attributes resulting in twice the number of attributes
being added to the skb. (rocker dev calls ndo_dflt_bridge_getlink)
There are multiple options:
1) Generate one notification including all attributes from master and self:
But, I don't think it will work, because both master and self may use
the same attributes/policy. Cannot pack the same set of attributes in a
single notification from both master and slave (duplicate attributes).
2) Generate one notification from master and the other notification from
self (This seems to be ideal):
For master: the master driver will send notification (bridge in this
example)
For self: the self driver will send notification (rocker in the above
example. It can use helpers from rtnetlink.c to do so. Like the
ndo_dflt_bridge_getlink api).
This patch implements 2) (leaving the 'rtnl_bridge_notify' around to be used
with 'self').
v1->v2 :
- rtnl_bridge_notify is now called only for self,
so, remove 'BRIDGE_FLAGS_SELF' check and cleanup a few things
- rtnl_bridge_dellink used to always send a RTM_NEWLINK msg
earlier. So, I have changed the notification from br_dellink to
go as RTM_NEWLINK
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-01-15 11:02:25 +07:00
if ( ! err ) {
2012-10-24 15:13:03 +07:00
flags & = ~ BRIDGE_FLAGS_SELF ;
bridge: fix setlink/dellink notifications
problems with bridge getlink/setlink notifications today:
- bridge setlink generates two notifications to userspace
- one from the bridge driver
- one from rtnetlink.c (rtnl_bridge_notify)
- dellink generates one notification from rtnetlink.c. Which
means bridge setlink and dellink notifications are not
consistent
- Looking at the code it appears,
If both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF were set,
the size calculation in rtnl_bridge_notify can be wrong.
Example: if you set both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF
in a setlink request to rocker dev, rtnl_bridge_notify will
allocate skb for one set of bridge attributes, but,
both the bridge driver and rocker dev will try to add
attributes resulting in twice the number of attributes
being added to the skb. (rocker dev calls ndo_dflt_bridge_getlink)
There are multiple options:
1) Generate one notification including all attributes from master and self:
But, I don't think it will work, because both master and self may use
the same attributes/policy. Cannot pack the same set of attributes in a
single notification from both master and slave (duplicate attributes).
2) Generate one notification from master and the other notification from
self (This seems to be ideal):
For master: the master driver will send notification (bridge in this
example)
For self: the self driver will send notification (rocker in the above
example. It can use helpers from rtnetlink.c to do so. Like the
ndo_dflt_bridge_getlink api).
This patch implements 2) (leaving the 'rtnl_bridge_notify' around to be used
with 'self').
v1->v2 :
- rtnl_bridge_notify is now called only for self,
so, remove 'BRIDGE_FLAGS_SELF' check and cleanup a few things
- rtnl_bridge_dellink used to always send a RTM_NEWLINK msg
earlier. So, I have changed the notification from br_dellink to
go as RTM_NEWLINK
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-01-15 11:02:25 +07:00
/* Generate event to notify upper layer of bridge
* change
*/
err = rtnl_bridge_notify ( dev ) ;
}
2012-10-24 15:13:03 +07:00
}
2012-10-24 15:12:57 +07:00
2012-11-02 23:32:36 +07:00
if ( have_flags )
2012-10-24 15:13:03 +07:00
memcpy ( nla_data ( attr ) , & flags , sizeof ( flags ) ) ;
2012-10-24 15:12:57 +07:00
out :
return err ;
}
2017-04-16 23:48:24 +07:00
static int rtnl_bridge_dellink ( struct sk_buff * skb , struct nlmsghdr * nlh ,
struct netlink_ext_ack * extack )
2013-02-13 19:00:12 +07:00
{
struct net * net = sock_net ( skb - > sk ) ;
struct ifinfomsg * ifm ;
struct net_device * dev ;
struct nlattr * br_spec , * attr = NULL ;
int rem , err = - EOPNOTSUPP ;
2015-01-19 16:45:04 +07:00
u16 flags = 0 ;
2013-02-13 19:00:12 +07:00
bool have_flags = false ;
if ( nlmsg_len ( nlh ) < sizeof ( * ifm ) )
return - EINVAL ;
ifm = nlmsg_data ( nlh ) ;
if ( ifm - > ifi_family ! = AF_BRIDGE )
return - EPFNOSUPPORT ;
dev = __dev_get_by_index ( net , ifm - > ifi_index ) ;
if ( ! dev ) {
pr_info ( " PF_BRIDGE: RTM_SETLINK with unknown ifindex \n " ) ;
return - ENODEV ;
}
br_spec = nlmsg_find_attr ( nlh , sizeof ( struct ifinfomsg ) , IFLA_AF_SPEC ) ;
if ( br_spec ) {
nla_for_each_nested ( attr , br_spec , rem ) {
if ( nla_type ( attr ) = = IFLA_BRIDGE_FLAGS ) {
2014-11-26 19:42:16 +07:00
if ( nla_len ( attr ) < sizeof ( flags ) )
return - EINVAL ;
2013-02-13 19:00:12 +07:00
have_flags = true ;
flags = nla_get_u16 ( attr ) ;
break ;
}
}
}
if ( ! flags | | ( flags & BRIDGE_FLAGS_MASTER ) ) {
struct net_device * br_dev = netdev_master_upper_dev_get ( dev ) ;
if ( ! br_dev | | ! br_dev - > netdev_ops - > ndo_bridge_dellink ) {
err = - EOPNOTSUPP ;
goto out ;
}
2015-01-30 13:40:12 +07:00
err = br_dev - > netdev_ops - > ndo_bridge_dellink ( dev , nlh , flags ) ;
2013-02-13 19:00:12 +07:00
if ( err )
goto out ;
flags & = ~ BRIDGE_FLAGS_MASTER ;
}
if ( ( flags & BRIDGE_FLAGS_SELF ) ) {
if ( ! dev - > netdev_ops - > ndo_bridge_dellink )
err = - EOPNOTSUPP ;
else
2015-01-30 13:40:12 +07:00
err = dev - > netdev_ops - > ndo_bridge_dellink ( dev , nlh ,
flags ) ;
2013-02-13 19:00:12 +07:00
bridge: fix setlink/dellink notifications
problems with bridge getlink/setlink notifications today:
- bridge setlink generates two notifications to userspace
- one from the bridge driver
- one from rtnetlink.c (rtnl_bridge_notify)
- dellink generates one notification from rtnetlink.c. Which
means bridge setlink and dellink notifications are not
consistent
- Looking at the code it appears,
If both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF were set,
the size calculation in rtnl_bridge_notify can be wrong.
Example: if you set both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF
in a setlink request to rocker dev, rtnl_bridge_notify will
allocate skb for one set of bridge attributes, but,
both the bridge driver and rocker dev will try to add
attributes resulting in twice the number of attributes
being added to the skb. (rocker dev calls ndo_dflt_bridge_getlink)
There are multiple options:
1) Generate one notification including all attributes from master and self:
But, I don't think it will work, because both master and self may use
the same attributes/policy. Cannot pack the same set of attributes in a
single notification from both master and slave (duplicate attributes).
2) Generate one notification from master and the other notification from
self (This seems to be ideal):
For master: the master driver will send notification (bridge in this
example)
For self: the self driver will send notification (rocker in the above
example. It can use helpers from rtnetlink.c to do so. Like the
ndo_dflt_bridge_getlink api).
This patch implements 2) (leaving the 'rtnl_bridge_notify' around to be used
with 'self').
v1->v2 :
- rtnl_bridge_notify is now called only for self,
so, remove 'BRIDGE_FLAGS_SELF' check and cleanup a few things
- rtnl_bridge_dellink used to always send a RTM_NEWLINK msg
earlier. So, I have changed the notification from br_dellink to
go as RTM_NEWLINK
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-01-15 11:02:25 +07:00
if ( ! err ) {
2013-02-13 19:00:12 +07:00
flags & = ~ BRIDGE_FLAGS_SELF ;
bridge: fix setlink/dellink notifications
problems with bridge getlink/setlink notifications today:
- bridge setlink generates two notifications to userspace
- one from the bridge driver
- one from rtnetlink.c (rtnl_bridge_notify)
- dellink generates one notification from rtnetlink.c. Which
means bridge setlink and dellink notifications are not
consistent
- Looking at the code it appears,
If both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF were set,
the size calculation in rtnl_bridge_notify can be wrong.
Example: if you set both BRIDGE_FLAGS_MASTER and BRIDGE_FLAGS_SELF
in a setlink request to rocker dev, rtnl_bridge_notify will
allocate skb for one set of bridge attributes, but,
both the bridge driver and rocker dev will try to add
attributes resulting in twice the number of attributes
being added to the skb. (rocker dev calls ndo_dflt_bridge_getlink)
There are multiple options:
1) Generate one notification including all attributes from master and self:
But, I don't think it will work, because both master and self may use
the same attributes/policy. Cannot pack the same set of attributes in a
single notification from both master and slave (duplicate attributes).
2) Generate one notification from master and the other notification from
self (This seems to be ideal):
For master: the master driver will send notification (bridge in this
example)
For self: the self driver will send notification (rocker in the above
example. It can use helpers from rtnetlink.c to do so. Like the
ndo_dflt_bridge_getlink api).
This patch implements 2) (leaving the 'rtnl_bridge_notify' around to be used
with 'self').
v1->v2 :
- rtnl_bridge_notify is now called only for self,
so, remove 'BRIDGE_FLAGS_SELF' check and cleanup a few things
- rtnl_bridge_dellink used to always send a RTM_NEWLINK msg
earlier. So, I have changed the notification from br_dellink to
go as RTM_NEWLINK
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-01-15 11:02:25 +07:00
/* Generate event to notify upper layer of bridge
* change
*/
err = rtnl_bridge_notify ( dev ) ;
}
2013-02-13 19:00:12 +07:00
}
if ( have_flags )
memcpy ( nla_data ( attr ) , & flags , sizeof ( flags ) ) ;
out :
return err ;
}
2016-04-30 15:25:26 +07:00
static bool stats_attr_valid ( unsigned int mask , int attrid , int idxattr )
{
return ( mask & IFLA_STATS_FILTER_BIT ( attrid ) ) & &
( ! idxattr | | idxattr = = attrid ) ;
}
2016-09-16 20:05:37 +07:00
# define IFLA_OFFLOAD_XSTATS_FIRST (IFLA_OFFLOAD_XSTATS_UNSPEC + 1)
static int rtnl_get_offload_stats_attr_size ( int attr_id )
{
switch ( attr_id ) {
case IFLA_OFFLOAD_XSTATS_CPU_HIT :
return sizeof ( struct rtnl_link_stats64 ) ;
}
return 0 ;
}
static int rtnl_get_offload_stats ( struct sk_buff * skb , struct net_device * dev ,
int * prividx )
{
struct nlattr * attr = NULL ;
int attr_id , size ;
void * attr_data ;
int err ;
if ( ! ( dev - > netdev_ops & & dev - > netdev_ops - > ndo_has_offload_stats & &
dev - > netdev_ops - > ndo_get_offload_stats ) )
return - ENODATA ;
for ( attr_id = IFLA_OFFLOAD_XSTATS_FIRST ;
attr_id < = IFLA_OFFLOAD_XSTATS_MAX ; attr_id + + ) {
if ( attr_id < * prividx )
continue ;
size = rtnl_get_offload_stats_attr_size ( attr_id ) ;
if ( ! size )
continue ;
2016-11-23 04:09:54 +07:00
if ( ! dev - > netdev_ops - > ndo_has_offload_stats ( dev , attr_id ) )
2016-09-16 20:05:37 +07:00
continue ;
attr = nla_reserve_64bit ( skb , attr_id , size ,
IFLA_OFFLOAD_XSTATS_UNSPEC ) ;
if ( ! attr )
goto nla_put_failure ;
attr_data = nla_data ( attr ) ;
memset ( attr_data , 0 , size ) ;
err = dev - > netdev_ops - > ndo_get_offload_stats ( attr_id , dev ,
attr_data ) ;
if ( err )
goto get_offload_stats_failure ;
}
if ( ! attr )
return - ENODATA ;
* prividx = 0 ;
return 0 ;
nla_put_failure :
err = - EMSGSIZE ;
get_offload_stats_failure :
* prividx = attr_id ;
return err ;
}
static int rtnl_get_offload_stats_size ( const struct net_device * dev )
{
int nla_size = 0 ;
int attr_id ;
int size ;
if ( ! ( dev - > netdev_ops & & dev - > netdev_ops - > ndo_has_offload_stats & &
dev - > netdev_ops - > ndo_get_offload_stats ) )
return 0 ;
for ( attr_id = IFLA_OFFLOAD_XSTATS_FIRST ;
attr_id < = IFLA_OFFLOAD_XSTATS_MAX ; attr_id + + ) {
2016-11-23 04:09:54 +07:00
if ( ! dev - > netdev_ops - > ndo_has_offload_stats ( dev , attr_id ) )
2016-09-16 20:05:37 +07:00
continue ;
size = rtnl_get_offload_stats_attr_size ( attr_id ) ;
nla_size + = nla_total_size_64bit ( size ) ;
}
if ( nla_size ! = 0 )
nla_size + = nla_total_size ( 0 ) ;
return nla_size ;
}
2016-04-20 22:43:43 +07:00
static int rtnl_fill_statsinfo ( struct sk_buff * skb , struct net_device * dev ,
int type , u32 pid , u32 seq , u32 change ,
2016-04-30 15:25:26 +07:00
unsigned int flags , unsigned int filter_mask ,
int * idxattr , int * prividx )
2016-04-20 22:43:43 +07:00
{
struct if_stats_msg * ifsm ;
struct nlmsghdr * nlh ;
struct nlattr * attr ;
2016-04-30 15:25:26 +07:00
int s_prividx = * prividx ;
2016-09-16 20:05:37 +07:00
int err ;
2016-04-20 22:43:43 +07:00
ASSERT_RTNL ( ) ;
nlh = nlmsg_put ( skb , pid , seq , type , sizeof ( * ifsm ) , flags ) ;
if ( ! nlh )
return - EMSGSIZE ;
ifsm = nlmsg_data ( nlh ) ;
ifsm - > ifindex = dev - > ifindex ;
ifsm - > filter_mask = filter_mask ;
2016-04-30 15:25:26 +07:00
if ( stats_attr_valid ( filter_mask , IFLA_STATS_LINK_64 , * idxattr ) ) {
2016-04-20 22:43:43 +07:00
struct rtnl_link_stats64 * sp ;
2016-04-21 23:58:25 +07:00
attr = nla_reserve_64bit ( skb , IFLA_STATS_LINK_64 ,
sizeof ( struct rtnl_link_stats64 ) ,
IFLA_STATS_UNSPEC ) ;
2016-04-20 22:43:43 +07:00
if ( ! attr )
goto nla_put_failure ;
sp = nla_data ( attr ) ;
dev_get_stats ( dev , sp ) ;
}
2016-04-30 15:25:27 +07:00
if ( stats_attr_valid ( filter_mask , IFLA_STATS_LINK_XSTATS , * idxattr ) ) {
const struct rtnl_link_ops * ops = dev - > rtnl_link_ops ;
if ( ops & & ops - > fill_linkxstats ) {
* idxattr = IFLA_STATS_LINK_XSTATS ;
attr = nla_nest_start ( skb ,
IFLA_STATS_LINK_XSTATS ) ;
if ( ! attr )
goto nla_put_failure ;
2016-06-28 21:57:05 +07:00
err = ops - > fill_linkxstats ( skb , dev , prividx , * idxattr ) ;
nla_nest_end ( skb , attr ) ;
if ( err )
goto nla_put_failure ;
* idxattr = 0 ;
}
}
if ( stats_attr_valid ( filter_mask , IFLA_STATS_LINK_XSTATS_SLAVE ,
* idxattr ) ) {
const struct rtnl_link_ops * ops = NULL ;
const struct net_device * master ;
master = netdev_master_upper_dev_get ( dev ) ;
if ( master )
ops = master - > rtnl_link_ops ;
if ( ops & & ops - > fill_linkxstats ) {
* idxattr = IFLA_STATS_LINK_XSTATS_SLAVE ;
attr = nla_nest_start ( skb ,
IFLA_STATS_LINK_XSTATS_SLAVE ) ;
if ( ! attr )
goto nla_put_failure ;
err = ops - > fill_linkxstats ( skb , dev , prividx , * idxattr ) ;
2016-04-30 15:25:27 +07:00
nla_nest_end ( skb , attr ) ;
if ( err )
goto nla_put_failure ;
* idxattr = 0 ;
}
}
2016-09-16 20:05:37 +07:00
if ( stats_attr_valid ( filter_mask , IFLA_STATS_LINK_OFFLOAD_XSTATS ,
* idxattr ) ) {
* idxattr = IFLA_STATS_LINK_OFFLOAD_XSTATS ;
attr = nla_nest_start ( skb , IFLA_STATS_LINK_OFFLOAD_XSTATS ) ;
if ( ! attr )
goto nla_put_failure ;
err = rtnl_get_offload_stats ( skb , dev , prividx ) ;
if ( err = = - ENODATA )
nla_nest_cancel ( skb , attr ) ;
else
nla_nest_end ( skb , attr ) ;
if ( err & & err ! = - ENODATA )
goto nla_put_failure ;
* idxattr = 0 ;
}
2017-01-16 21:16:36 +07:00
if ( stats_attr_valid ( filter_mask , IFLA_STATS_AF_SPEC , * idxattr ) ) {
struct rtnl_af_ops * af_ops ;
* idxattr = IFLA_STATS_AF_SPEC ;
attr = nla_nest_start ( skb , IFLA_STATS_AF_SPEC ) ;
if ( ! attr )
goto nla_put_failure ;
list_for_each_entry ( af_ops , & rtnl_af_ops , list ) {
if ( af_ops - > fill_stats_af ) {
struct nlattr * af ;
int err ;
af = nla_nest_start ( skb , af_ops - > family ) ;
if ( ! af )
goto nla_put_failure ;
err = af_ops - > fill_stats_af ( skb , dev ) ;
if ( err = = - ENODATA )
nla_nest_cancel ( skb , af ) ;
else if ( err < 0 )
goto nla_put_failure ;
nla_nest_end ( skb , af ) ;
}
}
nla_nest_end ( skb , attr ) ;
* idxattr = 0 ;
}
2016-04-20 22:43:43 +07:00
nlmsg_end ( skb , nlh ) ;
return 0 ;
nla_put_failure :
2016-04-30 15:25:26 +07:00
/* not a multi message or no progress mean a real error */
if ( ! ( flags & NLM_F_MULTI ) | | s_prividx = = * prividx )
nlmsg_cancel ( skb , nlh ) ;
else
nlmsg_end ( skb , nlh ) ;
2016-04-20 22:43:43 +07:00
return - EMSGSIZE ;
}
static size_t if_nlmsg_stats_size ( const struct net_device * dev ,
u32 filter_mask )
{
size_t size = 0 ;
2016-04-30 15:25:26 +07:00
if ( stats_attr_valid ( filter_mask , IFLA_STATS_LINK_64 , 0 ) )
2016-04-20 22:43:43 +07:00
size + = nla_total_size_64bit ( sizeof ( struct rtnl_link_stats64 ) ) ;
2016-04-30 15:25:27 +07:00
if ( stats_attr_valid ( filter_mask , IFLA_STATS_LINK_XSTATS , 0 ) ) {
const struct rtnl_link_ops * ops = dev - > rtnl_link_ops ;
2016-06-28 21:57:05 +07:00
int attr = IFLA_STATS_LINK_XSTATS ;
2016-04-30 15:25:27 +07:00
if ( ops & & ops - > get_linkxstats_size ) {
2016-06-28 21:57:05 +07:00
size + = nla_total_size ( ops - > get_linkxstats_size ( dev ,
attr ) ) ;
2016-04-30 15:25:27 +07:00
/* for IFLA_STATS_LINK_XSTATS */
size + = nla_total_size ( 0 ) ;
}
}
2016-06-28 21:57:05 +07:00
if ( stats_attr_valid ( filter_mask , IFLA_STATS_LINK_XSTATS_SLAVE , 0 ) ) {
struct net_device * _dev = ( struct net_device * ) dev ;
const struct rtnl_link_ops * ops = NULL ;
const struct net_device * master ;
/* netdev_master_upper_dev_get can't take const */
master = netdev_master_upper_dev_get ( _dev ) ;
if ( master )
ops = master - > rtnl_link_ops ;
if ( ops & & ops - > get_linkxstats_size ) {
int attr = IFLA_STATS_LINK_XSTATS_SLAVE ;
size + = nla_total_size ( ops - > get_linkxstats_size ( dev ,
attr ) ) ;
/* for IFLA_STATS_LINK_XSTATS_SLAVE */
size + = nla_total_size ( 0 ) ;
}
}
2016-09-16 20:05:37 +07:00
if ( stats_attr_valid ( filter_mask , IFLA_STATS_LINK_OFFLOAD_XSTATS , 0 ) )
size + = rtnl_get_offload_stats_size ( dev ) ;
2017-01-16 21:16:36 +07:00
if ( stats_attr_valid ( filter_mask , IFLA_STATS_AF_SPEC , 0 ) ) {
struct rtnl_af_ops * af_ops ;
/* for IFLA_STATS_AF_SPEC */
size + = nla_total_size ( 0 ) ;
list_for_each_entry ( af_ops , & rtnl_af_ops , list ) {
if ( af_ops - > get_stats_af_size ) {
size + = nla_total_size (
af_ops - > get_stats_af_size ( dev ) ) ;
/* for AF_* */
size + = nla_total_size ( 0 ) ;
}
}
}
2016-04-20 22:43:43 +07:00
return size ;
}
2017-04-16 23:48:24 +07:00
static int rtnl_stats_get ( struct sk_buff * skb , struct nlmsghdr * nlh ,
struct netlink_ext_ack * extack )
2016-04-20 22:43:43 +07:00
{
struct net * net = sock_net ( skb - > sk ) ;
struct net_device * dev = NULL ;
2016-04-30 15:25:26 +07:00
int idxattr = 0 , prividx = 0 ;
struct if_stats_msg * ifsm ;
2016-04-20 22:43:43 +07:00
struct sk_buff * nskb ;
u32 filter_mask ;
int err ;
2016-12-28 23:52:15 +07:00
if ( nlmsg_len ( nlh ) < sizeof ( * ifsm ) )
return - EINVAL ;
2016-04-20 22:43:43 +07:00
ifsm = nlmsg_data ( nlh ) ;
if ( ifsm - > ifindex > 0 )
dev = __dev_get_by_index ( net , ifsm - > ifindex ) ;
else
return - EINVAL ;
if ( ! dev )
return - ENODEV ;
filter_mask = ifsm - > filter_mask ;
if ( ! filter_mask )
return - EINVAL ;
nskb = nlmsg_new ( if_nlmsg_stats_size ( dev , filter_mask ) , GFP_KERNEL ) ;
if ( ! nskb )
return - ENOBUFS ;
err = rtnl_fill_statsinfo ( nskb , dev , RTM_NEWSTATS ,
NETLINK_CB ( skb ) . portid , nlh - > nlmsg_seq , 0 ,
2016-04-30 15:25:26 +07:00
0 , filter_mask , & idxattr , & prividx ) ;
2016-04-20 22:43:43 +07:00
if ( err < 0 ) {
/* -EMSGSIZE implies BUG in if_nlmsg_stats_size */
WARN_ON ( err = = - EMSGSIZE ) ;
kfree_skb ( nskb ) ;
} else {
err = rtnl_unicast ( nskb , net , NETLINK_CB ( skb ) . portid ) ;
}
return err ;
}
static int rtnl_stats_dump ( struct sk_buff * skb , struct netlink_callback * cb )
{
2016-04-30 15:25:26 +07:00
int h , s_h , err , s_idx , s_idxattr , s_prividx ;
2016-04-20 22:43:43 +07:00
struct net * net = sock_net ( skb - > sk ) ;
2016-04-30 15:25:26 +07:00
unsigned int flags = NLM_F_MULTI ;
2016-04-20 22:43:43 +07:00
struct if_stats_msg * ifsm ;
struct hlist_head * head ;
2016-04-30 15:25:26 +07:00
struct net_device * dev ;
2016-04-20 22:43:43 +07:00
u32 filter_mask = 0 ;
2016-04-30 15:25:26 +07:00
int idx = 0 ;
2016-04-20 22:43:43 +07:00
s_h = cb - > args [ 0 ] ;
s_idx = cb - > args [ 1 ] ;
2016-04-30 15:25:26 +07:00
s_idxattr = cb - > args [ 2 ] ;
s_prividx = cb - > args [ 3 ] ;
2016-04-20 22:43:43 +07:00
cb - > seq = net - > dev_base_seq ;
2016-12-28 23:52:15 +07:00
if ( nlmsg_len ( cb - > nlh ) < sizeof ( * ifsm ) )
return - EINVAL ;
2016-04-20 22:43:43 +07:00
ifsm = nlmsg_data ( cb - > nlh ) ;
filter_mask = ifsm - > filter_mask ;
if ( ! filter_mask )
return - EINVAL ;
for ( h = s_h ; h < NETDEV_HASHENTRIES ; h + + , s_idx = 0 ) {
idx = 0 ;
head = & net - > dev_index_head [ h ] ;
hlist_for_each_entry ( dev , head , index_hlist ) {
if ( idx < s_idx )
goto cont ;
err = rtnl_fill_statsinfo ( skb , dev , RTM_NEWSTATS ,
NETLINK_CB ( cb - > skb ) . portid ,
cb - > nlh - > nlmsg_seq , 0 ,
2016-04-30 15:25:26 +07:00
flags , filter_mask ,
& s_idxattr , & s_prividx ) ;
2016-04-20 22:43:43 +07:00
/* If we ran out of room on the first message,
* we ' re in trouble
*/
WARN_ON ( ( err = = - EMSGSIZE ) & & ( skb - > len = = 0 ) ) ;
if ( err < 0 )
goto out ;
2016-04-30 15:25:26 +07:00
s_prividx = 0 ;
s_idxattr = 0 ;
2016-04-20 22:43:43 +07:00
nl_dump_check_consistent ( cb , nlmsg_hdr ( skb ) ) ;
cont :
idx + + ;
}
}
out :
2016-04-30 15:25:26 +07:00
cb - > args [ 3 ] = s_prividx ;
cb - > args [ 2 ] = s_idxattr ;
2016-04-20 22:43:43 +07:00
cb - > args [ 1 ] = idx ;
cb - > args [ 0 ] = h ;
return skb - > len ;
}
2005-04-17 05:20:36 +07:00
/* Process one rtnetlink message. */
2017-04-12 19:34:04 +07:00
static int rtnetlink_rcv_msg ( struct sk_buff * skb , struct nlmsghdr * nlh ,
struct netlink_ext_ack * extack )
2005-04-17 05:20:36 +07:00
{
2008-03-26 00:26:21 +07:00
struct net * net = sock_net ( skb - > sk ) ;
2017-08-10 01:41:51 +07:00
struct rtnl_link * handlers ;
int err = - EOPNOTSUPP ;
2007-03-23 01:48:11 +07:00
rtnl_doit_func doit ;
2017-08-10 01:41:52 +07:00
unsigned int flags ;
2016-01-10 22:26:57 +07:00
int kind ;
2005-04-17 05:20:36 +07:00
int family ;
int type ;
type = nlh - > nlmsg_type ;
if ( type > RTM_MAX )
2007-04-06 04:35:52 +07:00
return - EOPNOTSUPP ;
2005-04-17 05:20:36 +07:00
type - = RTM_BASE ;
/* All the messages must have at least 1 byte length */
2013-03-27 13:47:04 +07:00
if ( nlmsg_len ( nlh ) < sizeof ( struct rtgenmsg ) )
2005-04-17 05:20:36 +07:00
return 0 ;
2013-03-27 13:47:04 +07:00
family = ( ( struct rtgenmsg * ) nlmsg_data ( nlh ) ) - > rtgen_family ;
2005-04-17 05:20:36 +07:00
kind = type & 3 ;
2014-04-24 04:29:27 +07:00
if ( kind ! = 2 & & ! netlink_net_capable ( skb , CAP_NET_ADMIN ) )
2007-03-23 13:30:12 +07:00
return - EPERM ;
2005-04-17 05:20:36 +07:00
2017-08-10 21:52:58 +07:00
if ( family > = ARRAY_SIZE ( rtnl_msg_handlers ) )
2017-08-10 01:41:51 +07:00
family = PF_UNSPEC ;
rcu_read_lock ( ) ;
handlers = rcu_dereference ( rtnl_msg_handlers [ family ] ) ;
if ( ! handlers ) {
family = PF_UNSPEC ;
handlers = rcu_dereference ( rtnl_msg_handlers [ family ] ) ;
}
2011-01-19 03:40:38 +07:00
if ( kind = = 2 & & nlh - > nlmsg_flags & NLM_F_DUMP ) {
2007-11-20 13:26:51 +07:00
struct sock * rtnl ;
2007-03-23 01:48:11 +07:00
rtnl_dumpit_func dumpit ;
2011-06-10 08:27:09 +07:00
u16 min_dump_alloc = 0 ;
2005-04-17 05:20:36 +07:00
2017-08-10 01:41:51 +07:00
dumpit = READ_ONCE ( handlers [ type ] . dumpit ) ;
if ( ! dumpit ) {
family = PF_UNSPEC ;
handlers = rcu_dereference ( rtnl_msg_handlers [ PF_UNSPEC ] ) ;
if ( ! handlers )
goto err_unlock ;
2017-08-10 01:41:50 +07:00
2017-08-10 01:41:51 +07:00
dumpit = READ_ONCE ( handlers [ type ] . dumpit ) ;
if ( ! dumpit )
goto err_unlock ;
}
2017-08-10 01:41:47 +07:00
2017-08-10 01:41:49 +07:00
refcount_inc ( & rtnl_msg_handlers_ref [ family ] ) ;
2017-08-10 21:52:58 +07:00
if ( type = = RTM_GETLINK - RTM_BASE )
2017-08-10 01:41:47 +07:00
min_dump_alloc = rtnl_calcit ( skb , nlh ) ;
2005-11-10 08:25:55 +07:00
2017-08-10 01:41:51 +07:00
rcu_read_unlock ( ) ;
2007-11-20 13:26:51 +07:00
rtnl = net - > rtnl ;
2012-02-24 21:30:15 +07:00
{
struct netlink_dump_control c = {
. dump = dumpit ,
. min_dump_alloc = min_dump_alloc ,
} ;
err = netlink_dump_start ( rtnl , skb , nlh , & c ) ;
}
2017-08-10 01:41:49 +07:00
refcount_dec ( & rtnl_msg_handlers_ref [ family ] ) ;
2011-05-25 14:34:04 +07:00
return err ;
2005-04-17 05:20:36 +07:00
}
2017-08-10 21:53:01 +07:00
doit = READ_ONCE ( handlers [ type ] . doit ) ;
if ( ! doit ) {
family = PF_UNSPEC ;
handlers = rcu_dereference ( rtnl_msg_handlers [ family ] ) ;
}
2017-08-10 01:41:52 +07:00
flags = READ_ONCE ( handlers [ type ] . flags ) ;
if ( flags & RTNL_FLAG_DOIT_UNLOCKED ) {
refcount_inc ( & rtnl_msg_handlers_ref [ family ] ) ;
doit = READ_ONCE ( handlers [ type ] . doit ) ;
rcu_read_unlock ( ) ;
if ( doit )
err = doit ( skb , nlh , extack ) ;
refcount_dec ( & rtnl_msg_handlers_ref [ family ] ) ;
return err ;
}
2017-08-10 01:41:51 +07:00
rcu_read_unlock ( ) ;
2005-04-17 05:20:36 +07:00
2017-08-10 01:41:51 +07:00
rtnl_lock ( ) ;
handlers = rtnl_dereference ( rtnl_msg_handlers [ family ] ) ;
if ( handlers ) {
doit = READ_ONCE ( handlers [ type ] . doit ) ;
if ( doit )
err = doit ( skb , nlh , extack ) ;
}
2017-08-10 01:41:50 +07:00
rtnl_unlock ( ) ;
return err ;
err_unlock :
2017-08-10 01:41:51 +07:00
rcu_read_unlock ( ) ;
2017-08-10 01:41:50 +07:00
return - EOPNOTSUPP ;
2005-04-17 05:20:36 +07:00
}
2007-10-11 11:15:29 +07:00
static void rtnetlink_rcv ( struct sk_buff * skb )
2005-04-17 05:20:36 +07:00
{
2007-10-11 11:15:29 +07:00
netlink_rcv_skb ( skb , & rtnetlink_rcv_msg ) ;
2005-04-17 05:20:36 +07:00
}
2017-06-21 03:54:16 +07:00
static int rtnetlink_bind ( struct net * net , int group )
{
switch ( group ) {
case RTNLGRP_IPV4_MROUTE_R :
case RTNLGRP_IPV6_MROUTE_R :
if ( ! ns_capable ( net - > user_ns , CAP_NET_ADMIN ) )
return - EPERM ;
break ;
}
return 0 ;
}
2005-04-17 05:20:36 +07:00
static int rtnetlink_event ( struct notifier_block * this , unsigned long event , void * ptr )
{
2013-05-28 08:30:21 +07:00
struct net_device * dev = netdev_notifier_info_to_dev ( ptr ) ;
2007-09-12 18:02:17 +07:00
2005-04-17 05:20:36 +07:00
switch ( event ) {
2017-04-04 20:23:41 +07:00
case NETDEV_REBOOT :
2017-07-20 00:22:40 +07:00
case NETDEV_CHANGEADDR :
2017-04-04 20:23:41 +07:00
case NETDEV_CHANGENAME :
case NETDEV_FEAT_CHANGE :
case NETDEV_BONDING_FAILOVER :
case NETDEV_NOTIFY_PEERS :
case NETDEV_RESEND_IGMP :
case NETDEV_CHANGEINFODATA :
2017-05-27 21:14:34 +07:00
rtmsg_ifinfo_event ( RTM_NEWLINK , dev , 0 , rtnl_get_event ( event ) ,
GFP_KERNEL ) ;
2005-04-17 05:20:36 +07:00
break ;
default :
break ;
}
return NOTIFY_DONE ;
}
static struct notifier_block rtnetlink_dev_notifier = {
. notifier_call = rtnetlink_event ,
} ;
2007-11-20 13:26:51 +07:00
2010-01-17 10:35:32 +07:00
static int __net_init rtnetlink_net_init ( struct net * net )
2007-11-20 13:26:51 +07:00
{
struct sock * sk ;
2012-06-29 13:15:21 +07:00
struct netlink_kernel_cfg cfg = {
. groups = RTNLGRP_MAX ,
. input = rtnetlink_rcv ,
. cb_mutex = & rtnl_mutex ,
2012-09-08 09:53:53 +07:00
. flags = NL_CFG_F_NONROOT_RECV ,
2017-06-21 03:54:16 +07:00
. bind = rtnetlink_bind ,
2012-06-29 13:15:21 +07:00
} ;
2012-09-08 09:53:54 +07:00
sk = netlink_kernel_create ( net , NETLINK_ROUTE , & cfg ) ;
2007-11-20 13:26:51 +07:00
if ( ! sk )
return - ENOMEM ;
net - > rtnl = sk ;
return 0 ;
}
2010-01-17 10:35:32 +07:00
static void __net_exit rtnetlink_net_exit ( struct net * net )
2007-11-20 13:26:51 +07:00
{
2008-01-19 14:55:19 +07:00
netlink_kernel_release ( net - > rtnl ) ;
net - > rtnl = NULL ;
2007-11-20 13:26:51 +07:00
}
static struct pernet_operations rtnetlink_net_ops = {
. init = rtnetlink_net_init ,
. exit = rtnetlink_net_exit ,
} ;
2005-04-17 05:20:36 +07:00
void __init rtnetlink_init ( void )
{
2017-08-10 21:53:00 +07:00
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( rtnl_msg_handlers_ref ) ; i + + )
refcount_set ( & rtnl_msg_handlers_ref [ i ] , 1 ) ;
2007-11-20 13:26:51 +07:00
if ( register_pernet_subsys ( & rtnetlink_net_ops ) )
2005-04-17 05:20:36 +07:00
panic ( " rtnetlink_init: cannot initialize rtnetlink \n " ) ;
2007-11-20 13:26:51 +07:00
2005-04-17 05:20:36 +07:00
register_netdevice_notifier ( & rtnetlink_dev_notifier ) ;
2007-03-23 01:49:22 +07:00
2011-06-10 08:27:09 +07:00
rtnl_register ( PF_UNSPEC , RTM_GETLINK , rtnl_getlink ,
2017-08-10 01:41:48 +07:00
rtnl_dump_ifinfo , 0 ) ;
rtnl_register ( PF_UNSPEC , RTM_SETLINK , rtnl_setlink , NULL , 0 ) ;
rtnl_register ( PF_UNSPEC , RTM_NEWLINK , rtnl_newlink , NULL , 0 ) ;
rtnl_register ( PF_UNSPEC , RTM_DELLINK , rtnl_dellink , NULL , 0 ) ;
2007-03-23 01:59:42 +07:00
2017-08-10 01:41:48 +07:00
rtnl_register ( PF_UNSPEC , RTM_GETADDR , NULL , rtnl_dump_all , 0 ) ;
rtnl_register ( PF_UNSPEC , RTM_GETROUTE , NULL , rtnl_dump_all , 0 ) ;
rtnl_register ( PF_UNSPEC , RTM_GETNETCONF , NULL , rtnl_dump_all , 0 ) ;
2012-04-15 13:43:56 +07:00
2017-08-10 01:41:48 +07:00
rtnl_register ( PF_BRIDGE , RTM_NEWNEIGH , rtnl_fdb_add , NULL , 0 ) ;
rtnl_register ( PF_BRIDGE , RTM_DELNEIGH , rtnl_fdb_del , NULL , 0 ) ;
rtnl_register ( PF_BRIDGE , RTM_GETNEIGH , NULL , rtnl_fdb_dump , 0 ) ;
2012-10-24 15:12:57 +07:00
2017-08-10 01:41:48 +07:00
rtnl_register ( PF_BRIDGE , RTM_GETLINK , NULL , rtnl_bridge_getlink , 0 ) ;
rtnl_register ( PF_BRIDGE , RTM_DELLINK , rtnl_bridge_dellink , NULL , 0 ) ;
rtnl_register ( PF_BRIDGE , RTM_SETLINK , rtnl_bridge_setlink , NULL , 0 ) ;
2016-04-20 22:43:43 +07:00
rtnl_register ( PF_UNSPEC , RTM_GETSTATS , rtnl_stats_get , rtnl_stats_dump ,
2017-08-10 01:41:48 +07:00
0 ) ;
2005-04-17 05:20:36 +07:00
}