2005-04-17 02:20:36 +04: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 .
*/
# 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 09:23:58 +03:00
# include <linux/mutex.h>
2006-08-05 10:04:54 +04:00
# include <linux/if_addr.h>
2012-04-15 10:43:56 +04:00
# include <linux/if_bridge.h>
2010-02-10 04:44:05 +03:00
# include <linux/pci.h>
2012-04-15 10:43:56 +04:00
# include <linux/etherdevice.h>
2005-04-17 02:20:36 +04:00
# include <asm/uaccess.h>
# include <linux/inet.h>
# include <linux/netdevice.h>
# include <net/ip.h>
# include <net/protocol.h>
# include <net/arp.h>
# include <net/route.h>
# include <net/udp.h>
# include <net/sock.h>
# include <net/pkt_sched.h>
2006-08-04 14:38:38 +04:00
# include <net/fib_rules.h>
2007-03-22 21:48:11 +03:00
# include <net/rtnetlink.h>
2009-07-10 13:51:35 +04:00
# include <net/net_namespace.h>
2005-04-17 02:20:36 +04:00
2009-11-07 12:26:17 +03:00
struct rtnl_link {
2007-03-22 21:48:11 +03:00
rtnl_doit_func doit ;
rtnl_dumpit_func dumpit ;
2011-06-10 05:27:09 +04:00
rtnl_calcit_func calcit ;
2007-03-22 21:48:11 +03:00
} ;
2006-03-21 09:23:58 +03:00
static DEFINE_MUTEX ( rtnl_mutex ) ;
2005-04-17 02:20:36 +04:00
void rtnl_lock ( void )
{
2006-03-21 09:23:58 +03:00
mutex_lock ( & rtnl_mutex ) ;
2005-04-17 02:20:36 +04:00
}
2009-11-07 12:26:17 +03:00
EXPORT_SYMBOL ( rtnl_lock ) ;
2005-04-17 02:20:36 +04:00
2006-03-21 09:23:58 +03:00
void __rtnl_unlock ( void )
2005-04-17 02:20:36 +04:00
{
2006-03-21 09:23:58 +03:00
mutex_unlock ( & rtnl_mutex ) ;
2005-04-17 02:20:36 +04:00
}
2006-03-21 09:23:58 +03:00
2005-04-17 02:20:36 +04:00
void rtnl_unlock ( void )
{
2008-10-08 02:50:03 +04:00
/* This fellow will unlock it for us. */
2005-04-17 02:20:36 +04:00
netdev_run_todo ( ) ;
}
2009-11-07 12:26:17 +03:00
EXPORT_SYMBOL ( rtnl_unlock ) ;
2005-04-17 02:20:36 +04:00
2006-03-21 09:23:58 +03:00
int rtnl_trylock ( void )
{
return mutex_trylock ( & rtnl_mutex ) ;
}
2009-11-07 12:26:17 +03:00
EXPORT_SYMBOL ( rtnl_trylock ) ;
2006-03-21 09:23:58 +03:00
2008-04-24 09:10:48 +04:00
int rtnl_is_locked ( void )
{
return mutex_is_locked ( & rtnl_mutex ) ;
}
2009-11-07 12:26:17 +03:00
EXPORT_SYMBOL ( rtnl_is_locked ) ;
2008-04-24 09:10:48 +04:00
2010-02-23 04:04:49 +03:00
# ifdef CONFIG_PROVE_LOCKING
int lockdep_rtnl_is_held ( void )
{
return lockdep_is_held ( & rtnl_mutex ) ;
}
EXPORT_SYMBOL ( lockdep_rtnl_is_held ) ;
# endif /* #ifdef CONFIG_PROVE_LOCKING */
2010-04-26 18:02:05 +04:00
static struct rtnl_link * rtnl_msg_handlers [ RTNL_FAMILY_MAX + 1 ] ;
2007-03-22 21:48:11 +03: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 ;
}
static rtnl_doit_func rtnl_get_doit ( int protocol , int msgindex )
{
struct rtnl_link * tab ;
2010-04-26 18:02:05 +04:00
if ( protocol < = RTNL_FAMILY_MAX )
2010-04-13 09:03:17 +04:00
tab = rtnl_msg_handlers [ protocol ] ;
else
tab = NULL ;
2007-03-23 07:41:06 +03:00
if ( tab = = NULL | | tab [ msgindex ] . doit = = NULL )
2007-03-22 21:48:11 +03:00
tab = rtnl_msg_handlers [ PF_UNSPEC ] ;
2012-10-23 02:21:23 +04:00
return tab [ msgindex ] . doit ;
2007-03-22 21:48:11 +03:00
}
static rtnl_dumpit_func rtnl_get_dumpit ( int protocol , int msgindex )
{
struct rtnl_link * tab ;
2010-04-26 18:02:05 +04:00
if ( protocol < = RTNL_FAMILY_MAX )
2010-04-13 09:03:17 +04:00
tab = rtnl_msg_handlers [ protocol ] ;
else
tab = NULL ;
2007-03-23 07:41:06 +03:00
if ( tab = = NULL | | tab [ msgindex ] . dumpit = = NULL )
2007-03-22 21:48:11 +03:00
tab = rtnl_msg_handlers [ PF_UNSPEC ] ;
2012-10-23 02:21:23 +04:00
return tab [ msgindex ] . dumpit ;
2007-03-22 21:48:11 +03:00
}
2011-06-10 05:27:09 +04:00
static rtnl_calcit_func rtnl_get_calcit ( int protocol , int msgindex )
{
struct rtnl_link * tab ;
if ( protocol < = RTNL_FAMILY_MAX )
tab = rtnl_msg_handlers [ protocol ] ;
else
tab = NULL ;
if ( tab = = NULL | | tab [ msgindex ] . calcit = = NULL )
tab = rtnl_msg_handlers [ PF_UNSPEC ] ;
2012-10-23 02:21:23 +04:00
return tab [ msgindex ] . calcit ;
2011-06-10 05:27:09 +04:00
}
2007-03-22 21:48:11 +03:00
/**
* __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
2011-06-10 05:27:09 +04:00
* @ calcit : Function pointer to calc size of dump message
2007-03-22 21:48:11 +03: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 05:27:09 +04:00
rtnl_doit_func doit , rtnl_dumpit_func dumpit ,
rtnl_calcit_func calcit )
2007-03-22 21:48:11 +03:00
{
struct rtnl_link * tab ;
int msgindex ;
2010-04-26 18:02:05 +04:00
BUG_ON ( protocol < 0 | | protocol > RTNL_FAMILY_MAX ) ;
2007-03-22 21:48:11 +03:00
msgindex = rtm_msgindex ( msgtype ) ;
tab = rtnl_msg_handlers [ protocol ] ;
if ( tab = = NULL ) {
tab = kcalloc ( RTM_NR_MSGTYPES , sizeof ( * tab ) , GFP_KERNEL ) ;
if ( tab = = NULL )
return - ENOBUFS ;
rtnl_msg_handlers [ protocol ] = tab ;
}
if ( doit )
tab [ msgindex ] . doit = doit ;
if ( dumpit )
tab [ msgindex ] . dumpit = dumpit ;
2011-06-10 05:27:09 +04:00
if ( calcit )
tab [ msgindex ] . calcit = calcit ;
2007-03-22 21:48:11 +03: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 05:57:33 +04:00
* of memory implies no sense in continuing .
2007-03-22 21:48:11 +03:00
*/
void rtnl_register ( int protocol , int msgtype ,
2011-06-10 05:27:09 +04:00
rtnl_doit_func doit , rtnl_dumpit_func dumpit ,
rtnl_calcit_func calcit )
2007-03-22 21:48:11 +03:00
{
2011-06-10 05:27:09 +04:00
if ( __rtnl_register ( protocol , msgtype , doit , dumpit , calcit ) < 0 )
2007-03-22 21:48:11 +03: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 )
{
int msgindex ;
2010-04-26 18:02:05 +04:00
BUG_ON ( protocol < 0 | | protocol > RTNL_FAMILY_MAX ) ;
2007-03-22 21:48:11 +03:00
msgindex = rtm_msgindex ( msgtype ) ;
if ( rtnl_msg_handlers [ protocol ] = = NULL )
return - ENOENT ;
rtnl_msg_handlers [ protocol ] [ msgindex ] . doit = NULL ;
rtnl_msg_handlers [ protocol ] [ msgindex ] . dumpit = NULL ;
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 )
{
2010-04-26 18:02:05 +04:00
BUG_ON ( protocol < 0 | | protocol > RTNL_FAMILY_MAX ) ;
2007-03-22 21:48:11 +03:00
kfree ( rtnl_msg_handlers [ protocol ] ) ;
rtnl_msg_handlers [ protocol ] = NULL ;
}
EXPORT_SYMBOL_GPL ( rtnl_unregister_all ) ;
2005-04-17 02:20:36 +04:00
2007-06-13 23:03:51 +04:00
static LIST_HEAD ( link_ops ) ;
2011-12-13 15:38:00 +04: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-13 23:03:51 +04: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 15:38:00 +04:00
if ( rtnl_link_ops_get ( ops - > kind ) )
return - EEXIST ;
2007-07-12 06:42:13 +04:00
if ( ! ops - > dellink )
2009-10-27 10:06:36 +03:00
ops - > dellink = unregister_netdevice_queue ;
2007-07-12 06:42:13 +04:00
2007-06-13 23:03:51 +04: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 11:46:52 +04:00
static void __rtnl_kill_links ( struct net * net , struct rtnl_link_ops * ops )
{
struct net_device * dev ;
2009-10-27 10:06:36 +03:00
LIST_HEAD ( list_kill ) ;
2008-04-16 11:46:52 +04:00
for_each_netdev ( net , dev ) {
2009-10-27 10:06:36 +03:00
if ( dev - > rtnl_link_ops = = ops )
ops - > dellink ( dev , & list_kill ) ;
2008-04-16 11:46:52 +04:00
}
2009-10-27 10:06:36 +03:00
unregister_netdevice_many ( & list_kill ) ;
2008-04-16 11:46:52 +04:00
}
2007-06-13 23:03:51 +04:00
/**
* __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink .
* @ ops : struct rtnl_link_ops * to unregister
*
2007-07-12 06:42:13 +04:00
* The caller must hold the rtnl_mutex .
2007-06-13 23:03:51 +04:00
*/
void __rtnl_link_unregister ( struct rtnl_link_ops * ops )
{
2007-09-17 22:56:21 +04:00
struct net * net ;
2007-07-12 06:42:13 +04:00
2007-09-17 22:56:21 +04:00
for_each_net ( net ) {
2008-04-16 11:46:52 +04:00
__rtnl_kill_links ( net , ops ) ;
2007-07-12 06:42:13 +04:00
}
2007-06-13 23:03:51 +04:00
list_del ( & ops - > list ) ;
}
EXPORT_SYMBOL_GPL ( __rtnl_link_unregister ) ;
/**
* 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 )
{
rtnl_lock ( ) ;
__rtnl_link_unregister ( ops ) ;
rtnl_unlock ( ) ;
}
EXPORT_SYMBOL_GPL ( rtnl_link_unregister ) ;
2014-01-22 12:05:55 +04: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 ;
master_dev = netdev_master_upper_dev_get ( ( struct net_device * ) dev ) ;
if ( ! master_dev )
return 0 ;
ops = master_dev - > rtnl_link_ops ;
2014-02-04 14:35:02 +04:00
if ( ! ops | | ! ops - > get_slave_size )
2014-01-22 12:05:55 +04:00
return 0 ;
/* IFLA_INFO_SLAVE_DATA + nested data */
return nla_total_size ( sizeof ( struct nlattr ) ) +
ops - > get_slave_size ( master_dev , dev ) ;
}
2007-06-13 23:03:51 +04: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 18:47:59 +03:00
size = nla_total_size ( sizeof ( struct nlattr ) ) + /* IFLA_LINKINFO */
nla_total_size ( strlen ( ops - > kind ) + 1 ) ; /* IFLA_INFO_KIND */
2007-06-13 23:03:51 +04:00
if ( ops - > get_size )
/* IFLA_INFO_DATA + nested data */
2010-11-11 18:47:59 +03:00
size + = nla_total_size ( sizeof ( struct nlattr ) ) +
2007-06-13 23:03:51 +04:00
ops - > get_size ( dev ) ;
if ( ops - > get_xstats_size )
2010-11-11 18:47:59 +03:00
/* IFLA_INFO_XSTATS */
size + = nla_total_size ( ops - > get_xstats_size ( dev ) ) ;
2007-06-13 23:03:51 +04:00
2014-01-22 12:05:55 +04:00
size + = rtnl_link_get_slave_info_data_size ( dev ) ;
2007-06-13 23:03:51 +04:00
return size ;
}
2010-11-16 07:30:14 +03: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-30 22:41:32 +04:00
void rtnl_af_register ( struct rtnl_af_ops * ops )
2010-11-16 07:30:14 +03:00
{
rtnl_lock ( ) ;
2013-12-30 22:41:32 +04:00
list_add_tail ( & ops - > list , & rtnl_af_ops ) ;
2010-11-16 07:30:14 +03: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 ) ;
static size_t rtnl_link_get_af_size ( const struct net_device * dev )
{
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 ) ) +
af_ops - > get_link_af_size ( dev ) ;
}
}
return size ;
}
2014-01-22 12:05:55 +04:00
static bool rtnl_have_link_slave_info ( const struct net_device * dev )
2007-06-13 23:03:51 +04:00
{
2014-01-22 12:05:55 +04:00
struct net_device * master_dev ;
2007-06-13 23:03:51 +04:00
2014-01-22 12:05:55 +04:00
master_dev = netdev_master_upper_dev_get ( ( struct net_device * ) dev ) ;
2014-01-23 22:19:21 +04:00
if ( master_dev & & master_dev - > rtnl_link_ops )
2014-01-22 12:05:55 +04:00
return true ;
return false ;
}
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-13 23:03:51 +04:00
2014-01-22 12:05:55 +04: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-13 23:03:51 +04:00
if ( nla_put_string ( skb , IFLA_INFO_KIND , ops - > kind ) < 0 )
2014-01-22 12:05:55 +04:00
return - EMSGSIZE ;
2007-06-13 23:03:51 +04:00
if ( ops - > fill_xstats ) {
err = ops - > fill_xstats ( skb , dev ) ;
if ( err < 0 )
2014-01-22 12:05:55 +04:00
return err ;
2007-06-13 23:03:51 +04:00
}
if ( ops - > fill_info ) {
data = nla_nest_start ( skb , IFLA_INFO_DATA ) ;
2014-01-22 12:05:55 +04:00
if ( data = = NULL )
return - EMSGSIZE ;
2007-06-13 23:03:51 +04: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 12:05:55 +04: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-13 23:03:51 +04:00
err_cancel_link :
nla_nest_cancel ( skb , linkinfo ) ;
out :
return err ;
}
2012-04-15 09:58:06 +04:00
int rtnetlink_send ( struct sk_buff * skb , struct net * net , u32 pid , unsigned int group , int echo )
2005-04-17 02:20:36 +04:00
{
2007-11-20 09:26:51 +03:00
struct sock * rtnl = net - > rtnl ;
2005-04-17 02:20:36 +04:00
int err = 0 ;
2005-08-15 06:29:52 +04:00
NETLINK_CB ( skb ) . dst_group = group ;
2005-04-17 02:20:36 +04:00
if ( echo )
atomic_inc ( & skb - > users ) ;
netlink_broadcast ( rtnl , skb , pid , group , GFP_KERNEL ) ;
if ( echo )
err = netlink_unicast ( rtnl , skb , pid , MSG_DONTWAIT ) ;
return err ;
}
2007-11-20 09:26:51 +03:00
int rtnl_unicast ( struct sk_buff * skb , struct net * net , u32 pid )
2006-08-15 11:30:25 +04:00
{
2007-11-20 09:26:51 +03:00
struct sock * rtnl = net - > rtnl ;
2006-08-15 11:30:25 +04:00
return nlmsg_unicast ( rtnl , skb , pid ) ;
}
2009-11-07 12:26:17 +03:00
EXPORT_SYMBOL ( rtnl_unicast ) ;
2006-08-15 11:30:25 +04:00
2009-02-25 10:18:28 +03:00
void rtnl_notify ( struct sk_buff * skb , struct net * net , u32 pid , u32 group ,
struct nlmsghdr * nlh , gfp_t flags )
2006-08-15 11:31:41 +04:00
{
2007-11-20 09:26:51 +03:00
struct sock * rtnl = net - > rtnl ;
2006-08-15 11:31:41 +04:00
int report = 0 ;
if ( nlh )
report = nlmsg_report ( nlh ) ;
2009-02-25 10:18:28 +03:00
nlmsg_notify ( rtnl , skb , pid , group , report , flags ) ;
2006-08-15 11:31:41 +04:00
}
2009-11-07 12:26:17 +03:00
EXPORT_SYMBOL ( rtnl_notify ) ;
2006-08-15 11:31:41 +04:00
2007-11-20 09:26:51 +03:00
void rtnl_set_sk_err ( struct net * net , u32 group , int error )
2006-08-15 11:31:41 +04:00
{
2007-11-20 09:26:51 +03:00
struct sock * rtnl = net - > rtnl ;
2006-08-15 11:31:41 +04:00
netlink_set_err ( rtnl , 0 , group , error ) ;
}
2009-11-07 12:26:17 +03:00
EXPORT_SYMBOL ( rtnl_set_sk_err ) ;
2006-08-15 11:31:41 +04:00
2005-04-17 02:20:36 +04:00
int rtnetlink_put_metrics ( struct sk_buff * skb , u32 * metrics )
{
2006-08-22 11:01:27 +04: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 ] ) {
valid + + ;
2012-04-02 04:12:00 +04:00
if ( nla_put_u32 ( skb , i + 1 , metrics [ i ] ) )
goto nla_put_failure ;
2006-08-22 11:01:27 +04:00
}
2005-04-17 02:20:36 +04:00
}
2006-08-23 09:20:14 +04:00
if ( ! valid ) {
nla_nest_cancel ( skb , mx ) ;
return 0 ;
}
2006-08-22 11:01:27 +04:00
return nla_nest_end ( skb , mx ) ;
nla_put_failure :
2008-06-04 03:36:54 +04:00
nla_nest_cancel ( skb , mx ) ;
return - EMSGSIZE ;
2005-04-17 02:20:36 +04:00
}
2009-11-07 12:26:17 +03:00
EXPORT_SYMBOL ( rtnetlink_put_metrics ) ;
2005-04-17 02:20:36 +04:00
2006-11-27 20:27:07 +03:00
int rtnl_put_cacheinfo ( struct sk_buff * skb , struct dst_entry * dst , u32 id ,
2012-07-10 16:06:14 +04:00
long expires , u32 error )
2006-11-27 20:27:07 +03:00
{
struct rta_cacheinfo ci = {
2012-08-09 01:13:53 +04:00
. rta_lastuse = jiffies_delta_to_clock_t ( jiffies - dst - > lastuse ) ,
2006-11-27 20:27:07 +03:00
. rta_used = dst - > __use ,
. rta_clntref = atomic_read ( & ( dst - > __refcnt ) ) ,
. rta_error = error ,
. rta_id = id ,
} ;
2012-07-29 20:01:30 +04:00
if ( expires ) {
unsigned long clock ;
2006-11-27 20:27:07 +03:00
2012-07-29 20:01:30 +04: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-27 20:27:07 +03:00
return nla_put ( skb , RTA_CACHEINFO , sizeof ( ci ) , & ci ) ;
}
EXPORT_SYMBOL_GPL ( rtnl_put_cacheinfo ) ;
2005-04-17 02:20:36 +04:00
2008-02-18 05:35:07 +03:00
static void set_operstate ( struct net_device * dev , unsigned char transition )
2006-03-21 04:09:11 +03:00
{
unsigned char operstate = dev - > operstate ;
2009-11-07 12:26:17 +03:00
switch ( transition ) {
2006-03-21 04:09:11 +03: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 04:09:22 +04:00
}
2006-03-21 04:09:11 +03:00
if ( dev - > operstate ! = operstate ) {
write_lock_bh ( & dev_base_lock ) ;
dev - > operstate = operstate ;
write_unlock_bh ( & dev_base_lock ) ;
2008-02-18 05:35:07 +03:00
netdev_state_change ( dev ) ;
}
2006-03-21 04:09:11 +03:00
}
2012-07-27 06:58:22 +04: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 09:34:54 +03: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 06:58:22 +04: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 09:34:54 +03:00
return flags ;
}
2006-08-05 10:05:34 +04:00
static void copy_rtnl_link_stats ( struct rtnl_link_stats * a ,
2010-06-08 11:19:54 +04:00
const struct rtnl_link_stats64 * b )
2005-04-17 02:20:36 +04:00
{
2006-08-05 10:05:34 +04: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 ;
2010-03-11 12:57:29 +03:00
}
2010-06-08 11:19:54 +04:00
static void copy_rtnl_link_stats64 ( void * v , const struct rtnl_link_stats64 * b )
2010-03-11 12:57:29 +03:00
{
2010-08-23 11:14:36 +04:00
memcpy ( v , b , sizeof ( * b ) ) ;
2010-03-11 12:57:29 +03:00
}
2005-04-17 02:20:36 +04:00
2010-05-16 12:05:45 +04:00
/* All VF info */
2012-02-22 01:54:48 +04:00
static inline int rtnl_vfinfo_size ( const struct net_device * dev ,
u32 ext_filter_mask )
2010-02-10 04:44:05 +03:00
{
2012-02-22 01:54:48 +04:00
if ( dev - > dev . parent & & dev_is_pci ( dev - > dev . parent ) & &
( ext_filter_mask & RTEXT_FILTER_VF ) ) {
2010-05-16 12:05:45 +04:00
int num_vfs = dev_num_vf ( dev - > dev . parent ) ;
2010-05-28 14:42:43 +04:00
size_t size = nla_total_size ( sizeof ( struct nlattr ) ) ;
size + = nla_total_size ( num_vfs * sizeof ( struct nlattr ) ) ;
size + = num_vfs *
( nla_total_size ( sizeof ( struct ifla_vf_mac ) ) +
nla_total_size ( sizeof ( struct ifla_vf_vlan ) ) +
2011-10-08 07:05:24 +04:00
nla_total_size ( sizeof ( struct ifla_vf_tx_rate ) ) +
nla_total_size ( sizeof ( struct ifla_vf_spoofchk ) ) ) ;
2010-05-16 12:05:45 +04:00
return size ;
} else
2010-02-10 04:44:05 +03:00
return 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 09:49:55 +04:00
static size_t rtnl_port_size ( const struct net_device * dev )
{
size_t port_size = nla_total_size ( 4 ) /* PORT_VF */
+ nla_total_size ( PORT_PROFILE_MAX ) /* PORT_PROFILE */
+ nla_total_size ( sizeof ( struct ifla_port_vsi ) )
/* PORT_VSI_TYPE */
+ 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 ;
if ( ! dev - > netdev_ops - > ndo_get_vf_port | | ! dev - > dev . parent )
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 ;
}
2012-02-22 01:54:48 +04:00
static noinline size_t if_nlmsg_size ( const struct net_device * dev ,
u32 ext_filter_mask )
2006-11-11 01:10:15 +03:00
{
return NLMSG_ALIGN ( sizeof ( struct ifinfomsg ) )
+ nla_total_size ( IFNAMSIZ ) /* IFLA_IFNAME */
2008-09-23 08:28:11 +04:00
+ nla_total_size ( IFALIASZ ) /* IFLA_IFALIAS */
2006-11-11 01:10:15 +03:00
+ nla_total_size ( IFNAMSIZ ) /* IFLA_QDISC */
+ nla_total_size ( sizeof ( struct rtnl_link_ifmap ) )
+ nla_total_size ( sizeof ( struct rtnl_link_stats ) )
2010-03-28 04:15:29 +04:00
+ nla_total_size ( sizeof ( struct rtnl_link_stats64 ) )
2006-11-11 01:10:15 +03: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 03:49:39 +04:00
+ nla_total_size ( 1 ) /* IFLA_CARRIER */
2012-03-29 16:51:30 +04:00
+ nla_total_size ( 4 ) /* IFLA_PROMISCUITY */
2012-07-20 06:28:48 +04:00
+ nla_total_size ( 4 ) /* IFLA_NUM_TX_QUEUES */
+ nla_total_size ( 4 ) /* IFLA_NUM_RX_QUEUES */
2006-11-11 01:10:15 +03:00
+ nla_total_size ( 1 ) /* IFLA_OPERSTATE */
2007-06-13 23:03:51 +04:00
+ nla_total_size ( 1 ) /* IFLA_LINKMODE */
2014-03-29 20:48:35 +04:00
+ nla_total_size ( 4 ) /* IFLA_CARRIER_CHANGES */
2012-02-22 01:54:48 +04: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 */
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 09:49:55 +04:00
+ rtnl_port_size ( dev ) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
2010-11-16 07:30:14 +03:00
+ rtnl_link_get_size ( dev ) /* IFLA_LINKINFO */
2013-07-29 20:16:50 +04:00
+ rtnl_link_get_af_size ( dev ) /* IFLA_AF_SPEC */
+ nla_total_size ( MAX_PHYS_PORT_ID_LEN ) ; /* IFLA_PHYS_PORT_ID */
2006-11-11 01:10:15 +03: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 09:49:55 +04: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 14:42:18 +04:00
if ( ! vf_port )
goto nla_put_failure ;
2012-04-02 04:12:00 +04: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 09:49:55 +04:00
err = dev - > netdev_ops - > ndo_get_vf_port ( dev , vf , skb ) ;
2010-05-28 14:42:18 +04: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 09:49:55 +04: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 14:42:18 +04: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 09:49:55 +04: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 14:42:18 +04: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 09:49:55 +04:00
}
nla_nest_end ( skb , port_self ) ;
return 0 ;
}
static int rtnl_port_fill ( struct sk_buff * skb , struct net_device * dev )
{
int err ;
if ( ! dev - > netdev_ops - > ndo_get_vf_port | | ! dev - > dev . parent )
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 20:16:50 +04:00
static int rtnl_phys_port_id_fill ( struct sk_buff * skb , struct net_device * dev )
{
int err ;
struct netdev_phys_port_id ppid ;
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 ;
}
2006-08-05 10:05:34 +04:00
static int rtnl_fill_ifinfo ( struct sk_buff * skb , struct net_device * dev ,
2007-05-23 04:00:49 +04:00
int type , u32 pid , u32 seq , u32 change ,
2012-02-22 01:54:48 +04:00
unsigned int flags , u32 ext_filter_mask )
2006-08-05 10:05:34 +04:00
{
struct ifinfomsg * ifm ;
struct nlmsghdr * nlh ;
2010-07-08 01:58:56 +04:00
struct rtnl_link_stats64 temp ;
2010-06-08 11:19:54 +04:00
const struct rtnl_link_stats64 * stats ;
2010-11-16 07:30:14 +03:00
struct nlattr * attr , * af_spec ;
struct rtnl_af_ops * af_ops ;
2013-01-04 02:48:52 +04:00
struct net_device * upper_dev = netdev_master_upper_dev_get ( dev ) ;
2005-04-17 02:20:36 +04:00
2011-05-25 11:34:04 +04:00
ASSERT_RTNL ( ) ;
2006-08-05 10:05:34 +04:00
nlh = nlmsg_put ( skb , pid , seq , type , sizeof ( * ifm ) , flags ) ;
if ( nlh = = NULL )
2007-02-01 10:16:40 +03:00
return - EMSGSIZE ;
2005-04-17 02:20:36 +04:00
2006-08-05 10:05:34 +04: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 04:12:00 +04: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 16:51:30 +04:00
nla_put_u32 ( skb , IFLA_PROMISCUITY , dev - > promiscuity ) | |
2012-07-20 06:28:48 +04:00
nla_put_u32 ( skb , IFLA_NUM_TX_QUEUES , dev - > num_tx_queues ) | |
2012-07-20 17:35:13 +04:00
# ifdef CONFIG_RPS
2012-07-20 06:28:48 +04:00
nla_put_u32 ( skb , IFLA_NUM_RX_QUEUES , dev - > num_rx_queues ) | |
2012-07-20 17:35:13 +04:00
# endif
2012-04-02 04:12:00 +04:00
( dev - > ifindex ! = dev - > iflink & &
nla_put_u32 ( skb , IFLA_LINK , dev - > iflink ) ) | |
2013-01-04 02:48:52 +04:00
( upper_dev & &
nla_put_u32 ( skb , IFLA_MASTER , upper_dev - > ifindex ) ) | |
2012-12-28 03:49:39 +04:00
nla_put_u8 ( skb , IFLA_CARRIER , netif_carrier_ok ( dev ) ) | |
2012-04-02 04:12:00 +04:00
( dev - > qdisc & &
nla_put_string ( skb , IFLA_QDISC , dev - > qdisc - > ops - > id ) ) | |
( dev - > ifalias & &
2014-03-29 20:48:35 +04:00
nla_put_string ( skb , IFLA_IFALIAS , dev - > ifalias ) ) | |
nla_put_u32 ( skb , IFLA_CARRIER_CHANGES ,
atomic_read ( & dev - > carrier_changes ) ) )
2012-04-02 04:12:00 +04:00
goto nla_put_failure ;
2008-09-23 08:28:11 +04:00
2005-04-17 02:20:36 +04:00
if ( 1 ) {
struct rtnl_link_ifmap map = {
. mem_start = dev - > mem_start ,
. mem_end = dev - > mem_end ,
. base_addr = dev - > base_addr ,
. irq = dev - > irq ,
. dma = dev - > dma ,
. port = dev - > if_port ,
} ;
2012-04-02 04:12:00 +04:00
if ( nla_put ( skb , IFLA_MAP , sizeof ( map ) , & map ) )
goto nla_put_failure ;
2005-04-17 02:20:36 +04:00
}
if ( dev - > addr_len ) {
2012-04-02 04:12:00 +04: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 02:20:36 +04:00
}
2013-07-29 20:16:50 +04:00
if ( rtnl_phys_port_id_fill ( skb , dev ) )
goto nla_put_failure ;
2008-05-22 01:12:46 +04:00
attr = nla_reserve ( skb , IFLA_STATS ,
sizeof ( struct rtnl_link_stats ) ) ;
if ( attr = = NULL )
goto nla_put_failure ;
2006-08-05 10:05:34 +04:00
2010-07-08 01:58:56 +04:00
stats = dev_get_stats ( dev , & temp ) ;
2008-05-22 01:12:46 +04:00
copy_rtnl_link_stats ( nla_data ( attr ) , stats ) ;
2005-04-17 02:20:36 +04:00
2010-03-11 12:57:29 +03:00
attr = nla_reserve ( skb , IFLA_STATS64 ,
sizeof ( struct rtnl_link_stats64 ) ) ;
if ( attr = = NULL )
goto nla_put_failure ;
copy_rtnl_link_stats64 ( nla_data ( attr ) , stats ) ;
2012-04-02 04:12:00 +04:00
if ( dev - > dev . parent & & ( ext_filter_mask & RTEXT_FILTER_VF ) & &
nla_put_u32 ( skb , IFLA_NUM_VF , dev_num_vf ( dev - > dev . parent ) ) )
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 09:49:55 +04:00
2012-02-22 01:54:48 +04:00
if ( dev - > netdev_ops - > ndo_get_vf_config & & dev - > dev . parent
& & ( ext_filter_mask & RTEXT_FILTER_VF ) ) {
2010-02-10 04:44:05 +03:00
int i ;
2010-05-16 12:05:45 +04:00
struct nlattr * vfinfo , * vf ;
int num_vfs = dev_num_vf ( dev - > dev . parent ) ;
vfinfo = nla_nest_start ( skb , IFLA_VFINFO_LIST ) ;
if ( ! vfinfo )
goto nla_put_failure ;
for ( i = 0 ; i < num_vfs ; i + + ) {
struct ifla_vf_info ivi ;
struct ifla_vf_mac vf_mac ;
struct ifla_vf_vlan vf_vlan ;
struct ifla_vf_tx_rate vf_tx_rate ;
2011-10-08 07:05:24 +04:00
struct ifla_vf_spoofchk vf_spoofchk ;
2013-06-13 14:19:10 +04:00
struct ifla_vf_link_state vf_linkstate ;
2011-10-08 07:05:24 +04:00
/*
* Not all SR - IOV capable drivers support the
* spoofcheck query . Preset to - 1 so the user
* space tool can detect that the driver didn ' t
* report anything .
*/
ivi . spoofchk = - 1 ;
2013-03-09 09:52:20 +04:00
memset ( ivi . mac , 0 , sizeof ( ivi . mac ) ) ;
2013-06-13 14:19:10 +04:00
/* The default value for VF link state is "auto"
* IFLA_VF_LINK_STATE_AUTO which equals zero
*/
ivi . linkstate = 0 ;
2010-02-10 04:44:05 +03:00
if ( dev - > netdev_ops - > ndo_get_vf_config ( dev , i , & ivi ) )
break ;
2011-10-08 07:05:24 +04:00
vf_mac . vf =
vf_vlan . vf =
vf_tx_rate . vf =
2013-06-13 14:19:10 +04:00
vf_spoofchk . vf =
vf_linkstate . vf = ivi . vf ;
2011-10-08 07:05:24 +04:00
2010-05-16 12:05:45 +04:00
memcpy ( vf_mac . mac , ivi . mac , sizeof ( ivi . mac ) ) ;
vf_vlan . vlan = ivi . vlan ;
vf_vlan . qos = ivi . qos ;
vf_tx_rate . rate = ivi . tx_rate ;
2011-10-08 07:05:24 +04:00
vf_spoofchk . setting = ivi . spoofchk ;
2013-06-13 14:19:10 +04:00
vf_linkstate . link_state = ivi . linkstate ;
2010-05-16 12:05:45 +04:00
vf = nla_nest_start ( skb , IFLA_VF_INFO ) ;
if ( ! vf ) {
nla_nest_cancel ( skb , vfinfo ) ;
goto nla_put_failure ;
}
2012-04-02 04:12:00 +04: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_TX_RATE , sizeof ( vf_tx_rate ) ,
& vf_tx_rate ) | |
nla_put ( skb , IFLA_VF_SPOOFCHK , sizeof ( vf_spoofchk ) ,
2013-06-13 14:19:10 +04:00
& vf_spoofchk ) | |
nla_put ( skb , IFLA_VF_LINK_STATE , sizeof ( vf_linkstate ) ,
& vf_linkstate ) )
2012-04-02 04:12:00 +04:00
goto nla_put_failure ;
2010-05-16 12:05:45 +04:00
nla_nest_end ( skb , vf ) ;
2010-02-10 04:44:05 +03:00
}
2010-05-16 12:05:45 +04:00
nla_nest_end ( skb , vfinfo ) ;
2010-02-10 04:44:05 +03: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 09:49:55 +04:00
if ( rtnl_port_fill ( skb , dev ) )
goto nla_put_failure ;
2014-01-22 12:05:55 +04:00
if ( dev - > rtnl_link_ops | | rtnl_have_link_slave_info ( dev ) ) {
2007-06-13 23:03:51 +04:00
if ( rtnl_link_fill ( skb , dev ) < 0 )
goto nla_put_failure ;
}
2010-11-16 07:30:14 +03: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 ;
err = af_ops - > fill_link_af ( skb , dev ) ;
/*
* 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 ) ;
2006-08-05 10:05:34 +04:00
return nlmsg_end ( skb , nlh ) ;
nla_put_failure :
2007-02-01 10:16:40 +03:00
nlmsg_cancel ( skb , nlh ) ;
return - EMSGSIZE ;
2005-04-17 02:20:36 +04:00
}
2014-02-18 23:53:18 +04:00
static const struct nla_policy ifla_policy [ IFLA_MAX + 1 ] = {
2006-08-27 07:13:18 +04:00
[ IFLA_IFNAME ] = { . type = NLA_STRING , . len = IFNAMSIZ - 1 } ,
2007-06-13 23:03:51 +04:00
[ IFLA_ADDRESS ] = { . type = NLA_BINARY , . len = MAX_ADDR_LEN } ,
[ IFLA_BROADCAST ] = { . type = NLA_BINARY , . len = MAX_ADDR_LEN } ,
2006-08-27 07:13:18 +04:00
[ IFLA_MAP ] = { . len = sizeof ( struct rtnl_link_ifmap ) } ,
2006-08-11 08:17:37 +04:00
[ IFLA_MTU ] = { . type = NLA_U32 } ,
2008-02-20 03:12:08 +03:00
[ IFLA_LINK ] = { . type = NLA_U32 } ,
2011-02-13 13:15:37 +03:00
[ IFLA_MASTER ] = { . type = NLA_U32 } ,
2012-12-28 03:49:39 +04:00
[ IFLA_CARRIER ] = { . type = NLA_U8 } ,
2006-08-11 08:17:37 +04:00
[ IFLA_TXQLEN ] = { . type = NLA_U32 } ,
[ IFLA_WEIGHT ] = { . type = NLA_U32 } ,
[ IFLA_OPERSTATE ] = { . type = NLA_U8 } ,
[ IFLA_LINKMODE ] = { . type = NLA_U8 } ,
2008-02-20 03:12:08 +03:00
[ IFLA_LINKINFO ] = { . type = NLA_NESTED } ,
2007-09-12 15:57:04 +04:00
[ IFLA_NET_NS_PID ] = { . type = NLA_U32 } ,
2011-05-05 04:51:50 +04:00
[ IFLA_NET_NS_FD ] = { . type = NLA_U32 } ,
2008-09-23 08:28:11 +04:00
[ IFLA_IFALIAS ] = { . type = NLA_STRING , . len = IFALIASZ - 1 } ,
2010-05-16 12:05:45 +04: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 09:49:55 +04:00
[ IFLA_VF_PORTS ] = { . type = NLA_NESTED } ,
[ IFLA_PORT_SELF ] = { . type = NLA_NESTED } ,
2010-11-16 07:30:14 +03:00
[ IFLA_AF_SPEC ] = { . type = NLA_NESTED } ,
2012-02-22 01:54:48 +04:00
[ IFLA_EXT_MASK ] = { . type = NLA_U32 } ,
2012-03-29 16:51:30 +04:00
[ IFLA_PROMISCUITY ] = { . type = NLA_U32 } ,
2012-07-20 06:28:48 +04:00
[ IFLA_NUM_TX_QUEUES ] = { . type = NLA_U32 } ,
[ IFLA_NUM_RX_QUEUES ] = { . type = NLA_U32 } ,
2013-07-29 20:16:50 +04:00
[ IFLA_PHYS_PORT_ID ] = { . type = NLA_BINARY , . len = MAX_PHYS_PORT_ID_LEN } ,
2014-03-29 20:48:35 +04:00
[ IFLA_CARRIER_CHANGES ] = { . type = NLA_U32 } , /* ignored */
2006-08-11 08:17:37 +04:00
} ;
2007-06-13 23:03:51 +04: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 12:05:55 +04:00
[ IFLA_INFO_SLAVE_KIND ] = { . type = NLA_STRING } ,
[ IFLA_INFO_SLAVE_DATA ] = { . type = NLA_NESTED } ,
2007-06-13 23:03:51 +04:00
} ;
2010-05-16 12:05:45 +04:00
static const struct nla_policy ifla_vfinfo_policy [ IFLA_VF_INFO_MAX + 1 ] = {
[ IFLA_VF_INFO ] = { . type = NLA_NESTED } ,
} ;
static const struct nla_policy ifla_vf_policy [ IFLA_VF_MAX + 1 ] = {
[ IFLA_VF_MAC ] = { . type = NLA_BINARY ,
. len = sizeof ( struct ifla_vf_mac ) } ,
[ IFLA_VF_VLAN ] = { . type = NLA_BINARY ,
. len = sizeof ( struct ifla_vf_vlan ) } ,
[ IFLA_VF_TX_RATE ] = { . type = NLA_BINARY ,
. len = sizeof ( struct ifla_vf_tx_rate ) } ,
2012-02-08 04:45:00 +04:00
[ IFLA_VF_SPOOFCHK ] = { . type = NLA_BINARY ,
. len = sizeof ( struct ifla_vf_spoofchk ) } ,
2010-05-16 12:05:45 +04: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 09:49:55 +04: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_VSI_TYPE ] = { . type = NLA_BINARY ,
. len = sizeof ( struct ifla_port_vsi ) } ,
[ 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 , } ,
} ;
2014-02-18 23:53:18 +04: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 ;
s_h = cb - > args [ 0 ] ;
s_idx = cb - > args [ 1 ] ;
rcu_read_lock ( ) ;
cb - > seq = net - > dev_base_seq ;
if ( nlmsg_parse ( cb - > nlh , sizeof ( struct ifinfomsg ) , tb , IFLA_MAX ,
ifla_policy ) > = 0 ) {
if ( tb [ IFLA_EXT_MASK ] )
ext_filter_mask = nla_get_u32 ( tb [ IFLA_EXT_MASK ] ) ;
}
for ( h = s_h ; h < NETDEV_HASHENTRIES ; h + + , s_idx = 0 ) {
idx = 0 ;
head = & net - > dev_index_head [ h ] ;
hlist_for_each_entry_rcu ( dev , head , index_hlist ) {
if ( idx < s_idx )
goto cont ;
if ( rtnl_fill_ifinfo ( skb , dev , RTM_NEWLINK ,
NETLINK_CB ( cb - > skb ) . portid ,
cb - > nlh - > nlmsg_seq , 0 ,
NLM_F_MULTI ,
ext_filter_mask ) < = 0 )
goto out ;
nl_dump_check_consistent ( cb , nlmsg_hdr ( skb ) ) ;
cont :
idx + + ;
}
}
out :
rcu_read_unlock ( ) ;
cb - > args [ 1 ] = idx ;
cb - > args [ 0 ] = h ;
return skb - > len ;
}
int rtnl_nla_parse_ifla ( struct nlattr * * tb , const struct nlattr * head , int len )
{
return nla_parse ( tb , IFLA_MAX , head , len , ifla_policy ) ;
}
EXPORT_SYMBOL ( rtnl_nla_parse_ifla ) ;
2009-11-08 11:53:51 +03: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 04:51:50 +04: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 11:53:51 +03:00
else
net = get_net ( src_net ) ;
return net ;
}
EXPORT_SYMBOL ( rtnl_link_get_net ) ;
2008-02-24 06:54:36 +03: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 04:31:54 +03: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 07:55:24 +03:00
err = af_ops - > validate_link_af ( dev , af ) ;
2010-11-22 04:31:54 +03:00
if ( err < 0 )
return err ;
}
}
}
2008-02-24 06:54:36 +03:00
return 0 ;
}
2010-05-16 12:05:45 +04:00
static int do_setvfinfo ( struct net_device * dev , struct nlattr * attr )
{
int rem , err = - EINVAL ;
struct nlattr * vf ;
const struct net_device_ops * ops = dev - > netdev_ops ;
nla_for_each_nested ( vf , attr , rem ) {
switch ( nla_type ( vf ) ) {
case IFLA_VF_MAC : {
struct ifla_vf_mac * ivm ;
ivm = nla_data ( vf ) ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_mac )
err = ops - > ndo_set_vf_mac ( dev , ivm - > vf ,
ivm - > mac ) ;
break ;
}
case IFLA_VF_VLAN : {
struct ifla_vf_vlan * ivv ;
ivv = nla_data ( vf ) ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_vlan )
err = ops - > ndo_set_vf_vlan ( dev , ivv - > vf ,
ivv - > vlan ,
ivv - > qos ) ;
break ;
}
case IFLA_VF_TX_RATE : {
struct ifla_vf_tx_rate * ivt ;
ivt = nla_data ( vf ) ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_tx_rate )
err = ops - > ndo_set_vf_tx_rate ( dev , ivt - > vf ,
ivt - > rate ) ;
break ;
}
2011-10-08 07:05:24 +04:00
case IFLA_VF_SPOOFCHK : {
struct ifla_vf_spoofchk * ivs ;
ivs = nla_data ( vf ) ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_spoofchk )
err = ops - > ndo_set_vf_spoofchk ( dev , ivs - > vf ,
ivs - > setting ) ;
break ;
}
2013-06-13 14:19:10 +04:00
case IFLA_VF_LINK_STATE : {
struct ifla_vf_link_state * ivl ;
ivl = nla_data ( vf ) ;
err = - EOPNOTSUPP ;
if ( ops - > ndo_set_vf_link_state )
err = ops - > ndo_set_vf_link_state ( dev , ivl - > vf ,
ivl - > link_state ) ;
break ;
}
2010-05-16 12:05:45 +04:00
default :
err = - EINVAL ;
break ;
}
if ( err )
break ;
}
return err ;
}
2011-02-13 13:15:37 +03:00
static int do_set_master ( struct net_device * dev , int ifindex )
{
2013-01-04 02:48:52 +04:00
struct net_device * upper_dev = netdev_master_upper_dev_get ( dev ) ;
2011-02-13 13:15:37 +03:00
const struct net_device_ops * ops ;
int err ;
2013-01-04 02:48:52 +04:00
if ( upper_dev ) {
if ( upper_dev - > ifindex = = ifindex )
2011-02-13 13:15:37 +03:00
return 0 ;
2013-01-04 02:48:52 +04:00
ops = upper_dev - > netdev_ops ;
2011-02-13 13:15:37 +03:00
if ( ops - > ndo_del_slave ) {
2013-01-04 02:48:52 +04:00
err = ops - > ndo_del_slave ( upper_dev , dev ) ;
2011-02-13 13:15:37 +03:00
if ( err )
return err ;
} else {
return - EOPNOTSUPP ;
}
}
if ( ifindex ) {
2013-01-04 02:48:52 +04:00
upper_dev = __dev_get_by_index ( dev_net ( dev ) , ifindex ) ;
if ( ! upper_dev )
2011-02-13 13:15:37 +03:00
return - EINVAL ;
2013-01-04 02:48:52 +04:00
ops = upper_dev - > netdev_ops ;
2011-02-13 13:15:37 +03:00
if ( ops - > ndo_add_slave ) {
2013-01-04 02:48:52 +04:00
err = ops - > ndo_add_slave ( upper_dev , dev ) ;
2011-02-13 13:15:37 +03:00
if ( err )
return err ;
} else {
return - EOPNOTSUPP ;
}
}
return 0 ;
}
2007-06-13 23:03:36 +04:00
static int do_setlink ( struct net_device * dev , struct ifinfomsg * ifm ,
2007-06-13 23:03:51 +04:00
struct nlattr * * tb , char * ifname , int modified )
2005-04-17 02:20:36 +04:00
{
2008-11-20 08:32:24 +03:00
const struct net_device_ops * ops = dev - > netdev_ops ;
2007-06-13 23:03:36 +04:00
int err ;
2005-04-17 02:20:36 +04:00
2011-05-05 04:51:50 +04:00
if ( tb [ IFLA_NET_NS_PID ] | | tb [ IFLA_NET_NS_FD ] ) {
2009-11-08 11:53:51 +03:00
struct net * net = rtnl_link_get_net ( dev_net ( dev ) , tb ) ;
2007-09-12 15:57:04 +04:00
if ( IS_ERR ( net ) ) {
err = PTR_ERR ( net ) ;
goto errout ;
}
2012-11-16 07:03:11 +04:00
if ( ! ns_capable ( net - > user_ns , CAP_NET_ADMIN ) ) {
err = - EPERM ;
goto errout ;
}
2007-09-12 15:57:04 +04:00
err = dev_change_net_namespace ( dev , net , ifname ) ;
put_net ( net ) ;
if ( err )
goto errout ;
modified = 1 ;
}
2006-08-11 08:17:37 +04:00
if ( tb [ IFLA_MAP ] ) {
2005-04-17 02:20:36 +04:00
struct rtnl_link_ifmap * u_map ;
struct ifmap k_map ;
2008-11-20 08:32:24 +03:00
if ( ! ops - > ndo_set_config ) {
2005-04-17 02:20:36 +04:00
err = - EOPNOTSUPP ;
2007-06-13 23:03:36 +04:00
goto errout ;
2005-04-17 02:20:36 +04:00
}
if ( ! netif_device_present ( dev ) ) {
err = - ENODEV ;
2007-06-13 23:03:36 +04:00
goto errout ;
2005-04-17 02:20:36 +04:00
}
2006-08-11 08:17:37 +04:00
u_map = nla_data ( tb [ IFLA_MAP ] ) ;
2005-04-17 02:20:36 +04: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 08:32:24 +03:00
err = ops - > ndo_set_config ( dev , & k_map ) ;
2006-08-11 08:17:37 +04:00
if ( err < 0 )
2007-06-13 23:03:36 +04:00
goto errout ;
2005-04-17 02:20:36 +04:00
2006-08-11 08:17:37 +04:00
modified = 1 ;
2005-04-17 02:20:36 +04:00
}
2006-08-11 08:17:37 +04:00
if ( tb [ IFLA_ADDRESS ] ) {
2006-08-09 03:47:37 +04:00
struct sockaddr * sa ;
int len ;
len = sizeof ( sa_family_t ) + dev - > addr_len ;
sa = kmalloc ( len , GFP_KERNEL ) ;
if ( ! sa ) {
err = - ENOMEM ;
2007-06-13 23:03:36 +04:00
goto errout ;
2006-08-09 03:47:37 +04:00
}
sa - > sa_family = dev - > type ;
2006-08-11 08:17:37 +04:00
memcpy ( sa - > sa_data , nla_data ( tb [ IFLA_ADDRESS ] ) ,
2006-08-09 03:47:37 +04:00
dev - > addr_len ) ;
2013-01-01 07:30:13 +04:00
err = dev_set_mac_address ( dev , sa ) ;
2006-08-09 03:47:37 +04:00
kfree ( sa ) ;
2005-04-17 02:20:36 +04:00
if ( err )
2007-06-13 23:03:36 +04:00
goto errout ;
2006-08-11 08:17:37 +04:00
modified = 1 ;
2005-04-17 02:20:36 +04:00
}
2006-08-11 08:17:37 +04:00
if ( tb [ IFLA_MTU ] ) {
err = dev_set_mtu ( dev , nla_get_u32 ( tb [ IFLA_MTU ] ) ) ;
if ( err < 0 )
2007-06-13 23:03:36 +04:00
goto errout ;
2006-08-11 08:17:37 +04:00
modified = 1 ;
2005-04-17 02:20:36 +04:00
}
2011-01-14 02:38:30 +03:00
if ( tb [ IFLA_GROUP ] ) {
dev_set_group ( dev , nla_get_u32 ( tb [ IFLA_GROUP ] ) ) ;
modified = 1 ;
}
2006-08-11 08:17:37 +04:00
/*
* Interface selected by interface index but interface
* name provided implies that a name change has been
* requested .
*/
2007-06-05 23:40:01 +04:00
if ( ifm - > ifi_index > 0 & & ifname [ 0 ] ) {
2006-08-11 08:17:37 +04:00
err = dev_change_name ( dev , ifname ) ;
if ( err < 0 )
2007-06-13 23:03:36 +04:00
goto errout ;
2006-08-11 08:17:37 +04:00
modified = 1 ;
2005-04-17 02:20:36 +04:00
}
2008-09-23 08:28:11 +04: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 ;
modified = 1 ;
}
2006-08-11 08:17:37 +04:00
if ( tb [ IFLA_BROADCAST ] ) {
nla_memcpy ( dev - > broadcast , tb [ IFLA_BROADCAST ] , dev - > addr_len ) ;
2013-01-01 07:30:13 +04:00
call_netdevice_notifiers ( NETDEV_CHANGEADDR , dev ) ;
2005-04-17 02:20:36 +04:00
}
2007-05-23 04:00:01 +04: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 09:34:54 +03:00
err = dev_change_flags ( dev , rtnl_dev_combine_flags ( dev , ifm ) ) ;
2008-11-17 10:20:31 +03:00
if ( err < 0 )
goto errout ;
2007-05-23 04:00:01 +04:00
}
2005-04-17 02:20:36 +04:00
2011-02-13 13:15:37 +03:00
if ( tb [ IFLA_MASTER ] ) {
err = do_set_master ( dev , nla_get_u32 ( tb [ IFLA_MASTER ] ) ) ;
if ( err )
goto errout ;
modified = 1 ;
}
2012-12-28 03:49:39 +04:00
if ( tb [ IFLA_CARRIER ] ) {
err = dev_change_carrier ( dev , nla_get_u8 ( tb [ IFLA_CARRIER ] ) ) ;
if ( err )
goto errout ;
modified = 1 ;
}
2008-02-18 05:35:07 +03:00
if ( tb [ IFLA_TXQLEN ] )
dev - > tx_queue_len = nla_get_u32 ( tb [ IFLA_TXQLEN ] ) ;
2006-03-21 04:09:11 +03:00
2006-08-11 08:17:37 +04:00
if ( tb [ IFLA_OPERSTATE ] )
2008-02-18 05:35:07 +03:00
set_operstate ( dev , nla_get_u8 ( tb [ IFLA_OPERSTATE ] ) ) ;
2006-03-21 04:09:11 +03:00
2006-08-11 08:17:37 +04:00
if ( tb [ IFLA_LINKMODE ] ) {
2008-02-18 05:35:07 +03:00
write_lock_bh ( & dev_base_lock ) ;
dev - > link_mode = nla_get_u8 ( tb [ IFLA_LINKMODE ] ) ;
write_unlock_bh ( & dev_base_lock ) ;
2006-03-21 04:09:11 +03:00
}
2010-05-16 12:05:45 +04:00
if ( tb [ IFLA_VFINFO_LIST ] ) {
struct nlattr * attr ;
int rem ;
nla_for_each_nested ( attr , tb [ IFLA_VFINFO_LIST ] , rem ) {
2010-05-21 06:25:27 +04:00
if ( nla_type ( attr ) ! = IFLA_VF_INFO ) {
err = - EINVAL ;
2010-05-16 12:05:45 +04:00
goto errout ;
2010-05-21 06:25:27 +04:00
}
2010-05-16 12:05:45 +04:00
err = do_setvfinfo ( dev , attr ) ;
if ( err < 0 )
goto errout ;
modified = 1 ;
}
2010-02-10 04:44:05 +03:00
}
2005-04-17 02:20:36 +04: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 09:49:55 +04: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 ) {
if ( nla_type ( attr ) ! = IFLA_VF_PORT )
continue ;
err = nla_parse_nested ( port , IFLA_PORT_MAX ,
attr , ifla_port_policy ) ;
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 ;
modified = 1 ;
}
}
err = 0 ;
if ( tb [ IFLA_PORT_SELF ] ) {
struct nlattr * port [ IFLA_PORT_MAX + 1 ] ;
err = nla_parse_nested ( port , IFLA_PORT_MAX ,
tb [ IFLA_PORT_SELF ] , ifla_port_policy ) ;
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 ;
modified = 1 ;
}
2010-11-16 07:30:14 +03: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 04:31:54 +03:00
BUG ( ) ;
2010-11-16 07:30:14 +03:00
2010-11-22 04:31:54 +03:00
err = af_ops - > set_link_af ( dev , af ) ;
2010-11-16 07:30:14 +03:00
if ( err < 0 )
goto errout ;
modified = 1 ;
}
}
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 09:49:55 +04:00
err = 0 ;
2007-06-13 23:03:36 +04:00
errout :
2012-05-14 01:56:26 +04:00
if ( err < 0 & & modified )
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 08:17:37 +04:00
2007-06-13 23:03:36 +04:00
return err ;
}
2005-04-17 02:20:36 +04:00
2013-03-21 11:45:29 +04:00
static int rtnl_setlink ( struct sk_buff * skb , struct nlmsghdr * nlh )
2007-06-13 23:03:36 +04:00
{
2008-03-25 20:26:21 +03:00
struct net * net = sock_net ( skb - > sk ) ;
2007-06-13 23:03:36 +04:00
struct ifinfomsg * ifm ;
struct net_device * dev ;
int err ;
struct nlattr * tb [ IFLA_MAX + 1 ] ;
char ifname [ IFNAMSIZ ] ;
err = nlmsg_parse ( nlh , sizeof ( * ifm ) , tb , IFLA_MAX , ifla_policy ) ;
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 14:59:31 +04:00
dev = __dev_get_by_index ( net , ifm - > ifi_index ) ;
2007-06-13 23:03:36 +04:00
else if ( tb [ IFLA_IFNAME ] )
2009-10-21 14:59:31 +04:00
dev = __dev_get_by_name ( net , ifname ) ;
2007-06-13 23:03:36 +04:00
else
goto errout ;
if ( dev = = NULL ) {
err = - ENODEV ;
goto errout ;
}
2009-11-07 12:26:17 +03:00
err = validate_linkmsg ( dev , tb ) ;
if ( err < 0 )
2009-10-21 14:59:31 +04:00
goto errout ;
2007-06-13 23:03:36 +04:00
2007-06-13 23:03:51 +04:00
err = do_setlink ( dev , ifm , tb , ifname , 0 ) ;
2006-08-11 08:17:37 +04:00
errout :
2005-04-17 02:20:36 +04:00
return err ;
}
2013-03-21 11:45:29 +04:00
static int rtnl_dellink ( struct sk_buff * skb , struct nlmsghdr * nlh )
2007-06-13 23:03:51 +04:00
{
2008-03-25 20:26:21 +03:00
struct net * net = sock_net ( skb - > sk ) ;
2007-06-13 23:03:51 +04:00
const struct rtnl_link_ops * ops ;
struct net_device * dev ;
struct ifinfomsg * ifm ;
char ifname [ IFNAMSIZ ] ;
struct nlattr * tb [ IFLA_MAX + 1 ] ;
int err ;
2011-05-09 03:17:57 +04:00
LIST_HEAD ( list_kill ) ;
2007-06-13 23:03:51 +04:00
err = nlmsg_parse ( nlh , sizeof ( * ifm ) , tb , IFLA_MAX , ifla_policy ) ;
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-17 22:56:21 +04:00
dev = __dev_get_by_index ( net , ifm - > ifi_index ) ;
2007-06-13 23:03:51 +04:00
else if ( tb [ IFLA_IFNAME ] )
2007-09-17 22:56:21 +04:00
dev = __dev_get_by_name ( net , ifname ) ;
2007-06-13 23:03:51 +04:00
else
return - EINVAL ;
if ( ! dev )
return - ENODEV ;
ops = dev - > rtnl_link_ops ;
if ( ! ops )
return - EOPNOTSUPP ;
2011-05-09 03:17:57 +04:00
ops - > dellink ( dev , & list_kill ) ;
unregister_netdevice_many ( & list_kill ) ;
list_del ( & list_kill ) ;
2007-06-13 23:03:51 +04:00
return 0 ;
}
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 09:34:54 +03: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 14:02:44 +04: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 09:34:54 +03:00
return 0 ;
}
EXPORT_SYMBOL ( rtnl_configure_link ) ;
2012-11-30 05:08:47 +04:00
struct net_device * rtnl_create_link ( struct net * net ,
2009-11-08 11:53:51 +03:00
char * ifname , const struct rtnl_link_ops * ops , struct nlattr * tb [ ] )
2007-08-09 09:16:38 +04:00
{
int err ;
struct net_device * dev ;
2012-07-20 06:28:47 +04:00
unsigned int num_tx_queues = 1 ;
unsigned int num_rx_queues = 1 ;
2007-08-09 09:16:38 +04:00
2012-07-20 06:28:48 +04: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 06:28:47 +04:00
num_tx_queues = ops - > get_num_tx_queues ( ) ;
2012-07-20 06:28:48 +04: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 06:28:47 +04:00
num_rx_queues = ops - > get_num_rx_queues ( ) ;
2012-04-10 22:34:43 +04:00
2007-08-09 09:16:38 +04:00
err = - ENOMEM ;
2012-07-20 06:28:47 +04:00
dev = alloc_netdev_mqs ( ops - > priv_size , ifname , ops - > setup ,
num_tx_queues , num_rx_queues ) ;
2007-08-09 09:16:38 +04:00
if ( ! dev )
goto err ;
2009-11-08 11:53:51 +03: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 09:34:54 +03:00
dev - > rtnl_link_state = RTNL_LINK_INITIALIZING ;
2009-11-08 11:53:51 +03:00
2007-08-09 09:16:38 +04:00
if ( tb [ IFLA_MTU ] )
dev - > mtu = nla_get_u32 ( tb [ IFLA_MTU ] ) ;
2013-01-06 16:41:57 +04:00
if ( tb [ IFLA_ADDRESS ] ) {
2007-08-09 09:16:38 +04:00
memcpy ( dev - > dev_addr , nla_data ( tb [ IFLA_ADDRESS ] ) ,
nla_len ( tb [ IFLA_ADDRESS ] ) ) ;
2013-01-06 16:41:57 +04:00
dev - > addr_assign_type = NET_ADDR_SET ;
}
2007-08-09 09:16:38 +04: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 05:35:07 +03:00
set_operstate ( dev , nla_get_u8 ( tb [ IFLA_OPERSTATE ] ) ) ;
2007-08-09 09:16:38 +04:00
if ( tb [ IFLA_LINKMODE ] )
dev - > link_mode = nla_get_u8 ( tb [ IFLA_LINKMODE ] ) ;
2011-01-20 06:00:42 +03:00
if ( tb [ IFLA_GROUP ] )
dev_set_group ( dev , nla_get_u32 ( tb [ IFLA_GROUP ] ) ) ;
2007-08-09 09:16:38 +04:00
return dev ;
err :
return ERR_PTR ( err ) ;
}
2009-11-07 12:26:17 +03:00
EXPORT_SYMBOL ( rtnl_create_link ) ;
2007-08-09 09:16:38 +04:00
2011-01-14 02:38:31 +03:00
static int rtnl_group_changelink ( struct net * net , int group ,
struct ifinfomsg * ifm ,
struct nlattr * * tb )
{
struct net_device * dev ;
int err ;
for_each_netdev ( net , dev ) {
if ( dev - > group = = group ) {
err = do_setlink ( dev , ifm , tb , NULL , 0 ) ;
if ( err < 0 )
return err ;
}
}
return 0 ;
}
2013-03-21 11:45:29 +04:00
static int rtnl_newlink ( struct sk_buff * skb , struct nlmsghdr * nlh )
2007-06-13 23:03:51 +04:00
{
2008-03-25 20:26:21 +03:00
struct net * net = sock_net ( skb - > sk ) ;
2007-06-13 23:03:51 +04:00
const struct rtnl_link_ops * ops ;
2014-01-22 12:05:55 +04:00
const struct rtnl_link_ops * m_ops = NULL ;
2007-06-13 23:03:51 +04:00
struct net_device * dev ;
2014-01-22 12:05:55 +04:00
struct net_device * master_dev = NULL ;
2007-06-13 23:03:51 +04: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 ] ;
int err ;
2008-10-17 02:24:51 +04:00
# ifdef CONFIG_MODULES
2007-06-13 23:03:51 +04:00
replay :
2007-08-01 01:13:50 +04:00
# endif
2007-06-13 23:03:51 +04:00
err = nlmsg_parse ( nlh , sizeof ( * ifm ) , tb , IFLA_MAX , ifla_policy ) ;
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-17 22:56:21 +04:00
dev = __dev_get_by_index ( net , ifm - > ifi_index ) ;
2011-01-14 02:38:31 +03:00
else {
if ( ifname [ 0 ] )
dev = __dev_get_by_name ( net , ifname ) ;
else
dev = NULL ;
}
2007-06-13 23:03:51 +04:00
2014-01-22 12:05:55 +04:00
if ( dev ) {
master_dev = netdev_master_upper_dev_get ( dev ) ;
if ( master_dev )
m_ops = master_dev - > rtnl_link_ops ;
}
2009-11-07 12:26:17 +03:00
err = validate_linkmsg ( dev , tb ) ;
if ( err < 0 )
2008-02-24 06:54:36 +03:00
return err ;
2007-06-13 23:03:51 +04:00
if ( tb [ IFLA_LINKINFO ] ) {
err = nla_parse_nested ( linkinfo , IFLA_INFO_MAX ,
tb [ IFLA_LINKINFO ] , ifla_info_policy ) ;
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 ) {
2014-01-22 12:05:55 +04:00
struct nlattr * attr [ ops ? ops - > maxtype + 1 : 0 ] ;
struct nlattr * slave_attr [ m_ops ? m_ops - > slave_maxtype + 1 : 0 ] ;
struct nlattr * * data = NULL ;
struct nlattr * * slave_data = NULL ;
2009-11-08 11:53:51 +03:00
struct net * dest_net ;
2007-06-13 23:03:51 +04:00
if ( ops ) {
if ( ops - > maxtype & & linkinfo [ IFLA_INFO_DATA ] ) {
err = nla_parse_nested ( attr , ops - > maxtype ,
linkinfo [ IFLA_INFO_DATA ] ,
ops - > policy ) ;
if ( err < 0 )
return err ;
data = attr ;
}
if ( ops - > validate ) {
err = ops - > validate ( tb , data ) ;
if ( err < 0 )
return err ;
}
}
2014-01-22 12:05:55 +04: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 ] ,
m_ops - > slave_policy ) ;
if ( err < 0 )
return err ;
slave_data = slave_attr ;
}
if ( m_ops - > slave_validate ) {
err = m_ops - > slave_validate ( tb , slave_data ) ;
if ( err < 0 )
return err ;
}
}
2007-06-13 23:03:51 +04:00
if ( dev ) {
int modified = 0 ;
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 ;
err = ops - > changelink ( dev , tb , data ) ;
if ( err < 0 )
return err ;
modified = 1 ;
}
2014-01-22 12:05:55 +04:00
if ( linkinfo [ IFLA_INFO_SLAVE_DATA ] ) {
if ( ! m_ops | | ! m_ops - > slave_changelink )
return - EOPNOTSUPP ;
err = m_ops - > slave_changelink ( master_dev , dev ,
tb , slave_data ) ;
if ( err < 0 )
return err ;
modified = 1 ;
}
2007-06-13 23:03:51 +04:00
return do_setlink ( dev , ifm , tb , ifname , modified ) ;
}
2011-01-20 06:00:42 +03:00
if ( ! ( nlh - > nlmsg_flags & NLM_F_CREATE ) ) {
if ( ifm - > ifi_index = = 0 & & tb [ IFLA_GROUP ] )
return rtnl_group_changelink ( net ,
nla_get_u32 ( tb [ IFLA_GROUP ] ) ,
ifm , tb ) ;
2007-06-13 23:03:51 +04:00
return - ENODEV ;
2011-01-20 06:00:42 +03:00
}
2007-06-13 23:03:51 +04:00
2007-07-12 06:42:31 +04:00
if ( tb [ IFLA_MAP ] | | tb [ IFLA_MASTER ] | | tb [ IFLA_PROTINFO ] )
2007-06-13 23:03:51 +04:00
return - EOPNOTSUPP ;
if ( ! ops ) {
2008-10-17 02:24:51 +04:00
# ifdef CONFIG_MODULES
2007-06-13 23:03:51 +04: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 ;
}
if ( ! ifname [ 0 ] )
snprintf ( ifname , IFNAMSIZ , " %s%%d " , ops - > kind ) ;
2007-08-09 09:16:38 +04:00
2009-11-08 11:53:51 +03:00
dest_net = rtnl_link_get_net ( net , tb ) ;
2011-01-29 17:57:22 +03:00
if ( IS_ERR ( dest_net ) )
return PTR_ERR ( dest_net ) ;
2012-11-30 05:08:47 +04:00
dev = rtnl_create_link ( dest_net , ifname , ops , tb ) ;
2012-08-09 01:52:46 +04:00
if ( IS_ERR ( dev ) ) {
2007-08-09 09:16:38 +04:00
err = PTR_ERR ( dev ) ;
2012-08-09 01:52:46 +04:00
goto out ;
}
dev - > ifindex = ifm - > ifi_index ;
2014-02-12 03:51:30 +04:00
if ( ops - > newlink ) {
2009-11-08 11:53:51 +03:00
err = ops - > newlink ( net , dev , tb , data ) ;
2014-02-12 03:51:30 +04:00
/* Drivers should call free_netdev() in ->destructor
* and unregister it on failure so that device could be
* finally freed in rtnl_unlock .
*/
if ( err < 0 )
goto out ;
} else {
2007-07-12 06:42:13 +04:00
err = register_netdevice ( dev ) ;
2014-02-12 03:51:30 +04:00
if ( err < 0 ) {
free_netdev ( dev ) ;
goto out ;
}
2013-08-14 13:35:42 +04: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 09:34:54 +03:00
err = rtnl_configure_link ( dev , ifm ) ;
if ( err < 0 )
unregister_netdevice ( dev ) ;
out :
2009-11-08 11:53:51 +03:00
put_net ( dest_net ) ;
2007-06-13 23:03:51 +04:00
return err ;
}
}
2013-03-21 11:45:29 +04:00
static int rtnl_getlink ( struct sk_buff * skb , struct nlmsghdr * nlh )
2006-02-23 02:10:56 +03:00
{
2008-03-25 20:26:21 +03:00
struct net * net = sock_net ( skb - > sk ) ;
2006-08-05 10:05:34 +04:00
struct ifinfomsg * ifm ;
2009-10-21 14:59:31 +04:00
char ifname [ IFNAMSIZ ] ;
2006-08-05 10:05:34 +04:00
struct nlattr * tb [ IFLA_MAX + 1 ] ;
struct net_device * dev = NULL ;
struct sk_buff * nskb ;
2006-11-11 01:10:15 +03:00
int err ;
2012-02-22 01:54:48 +04:00
u32 ext_filter_mask = 0 ;
2006-02-23 02:10:56 +03:00
2006-08-05 10:05:34 +04:00
err = nlmsg_parse ( nlh , sizeof ( * ifm ) , tb , IFLA_MAX , ifla_policy ) ;
if ( err < 0 )
2006-09-27 10:26:38 +04:00
return err ;
2006-08-05 10:05:34 +04:00
2009-10-21 14:59:31 +04:00
if ( tb [ IFLA_IFNAME ] )
nla_strlcpy ( ifname , tb [ IFLA_IFNAME ] , IFNAMSIZ ) ;
2012-02-22 01:54:48 +04:00
if ( tb [ IFLA_EXT_MASK ] )
ext_filter_mask = nla_get_u32 ( tb [ IFLA_EXT_MASK ] ) ;
2006-08-05 10:05:34 +04:00
ifm = nlmsg_data ( nlh ) ;
2009-10-21 14:59:31 +04: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 02:10:56 +03:00
return - EINVAL ;
2009-10-21 14:59:31 +04:00
if ( dev = = NULL )
return - ENODEV ;
2012-02-22 01:54:48 +04:00
nskb = nlmsg_new ( if_nlmsg_size ( dev , ext_filter_mask ) , GFP_KERNEL ) ;
2009-10-21 14:59:31 +04:00
if ( nskb = = NULL )
return - ENOBUFS ;
2006-08-05 10:05:34 +04:00
2012-09-08 00:12:54 +04:00
err = rtnl_fill_ifinfo ( nskb , dev , RTM_NEWLINK , NETLINK_CB ( skb ) . portid ,
2012-02-22 01:54:48 +04:00
nlh - > nlmsg_seq , 0 , 0 , ext_filter_mask ) ;
2007-02-01 10:16:40 +03:00
if ( err < 0 ) {
/* -EMSGSIZE implies BUG in if_nlmsg_size */
WARN_ON ( err = = - EMSGSIZE ) ;
kfree_skb ( nskb ) ;
2009-10-21 14:59:31 +04:00
} else
2012-09-08 00:12:54 +04:00
err = rtnl_unicast ( nskb , net , NETLINK_CB ( skb ) . portid ) ;
2006-02-23 02:10:56 +03:00
2006-08-05 10:05:34 +04:00
return err ;
2006-02-23 02:10:56 +03:00
}
2012-02-22 01:54:48 +04:00
static u16 rtnl_calcit ( struct sk_buff * skb , struct nlmsghdr * nlh )
2011-06-10 05:27:09 +04:00
{
2012-02-22 01:54:48 +04: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 ;
2013-04-08 09:45:26 +04:00
if ( nlmsg_parse ( nlh , sizeof ( struct ifinfomsg ) , tb , IFLA_MAX ,
2012-03-04 16:32:10 +04:00
ifla_policy ) > = 0 ) {
if ( tb [ IFLA_EXT_MASK ] )
ext_filter_mask = nla_get_u32 ( tb [ IFLA_EXT_MASK ] ) ;
}
2012-02-22 01:54:48 +04: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 .
*/
list_for_each_entry ( dev , & net - > dev_base_head , dev_list ) {
min_ifinfo_dump_size = max_t ( u16 , min_ifinfo_dump_size ,
if_nlmsg_size ( dev ,
ext_filter_mask ) ) ;
}
2011-06-10 05:27:09 +04:00
return min_ifinfo_dump_size ;
}
2007-04-26 11:57:41 +04:00
static int rtnl_dump_all ( struct sk_buff * skb , struct netlink_callback * cb )
2005-04-17 02:20:36 +04:00
{
int idx ;
int s_idx = cb - > family ;
if ( s_idx = = 0 )
s_idx = 1 ;
2010-04-26 18:02:05 +04:00
for ( idx = 1 ; idx < = RTNL_FAMILY_MAX ; idx + + ) {
2005-04-17 02:20:36 +04:00
int type = cb - > nlh - > nlmsg_type - RTM_BASE ;
if ( idx < s_idx | | idx = = PF_PACKET )
continue ;
2007-03-22 21:48:11 +03:00
if ( rtnl_msg_handlers [ idx ] = = NULL | |
rtnl_msg_handlers [ idx ] [ type ] . dumpit = = NULL )
2005-04-17 02:20:36 +04:00
continue ;
2013-03-22 10:28:42 +04:00
if ( idx > s_idx ) {
2005-04-17 02:20:36 +04:00
memset ( & cb - > args [ 0 ] , 0 , sizeof ( cb - > args ) ) ;
2013-03-22 10:28:42 +04:00
cb - > prev_seq = 0 ;
cb - > seq = 0 ;
}
2007-03-22 21:48:11 +03:00
if ( rtnl_msg_handlers [ idx ] [ type ] . dumpit ( skb , cb ) )
2005-04-17 02:20:36 +04:00
break ;
}
cb - > family = idx ;
return skb - > len ;
}
2013-10-24 03:02:42 +04:00
void rtmsg_ifinfo ( int type , struct net_device * dev , unsigned int change ,
gfp_t flags )
2005-04-17 02:20:36 +04:00
{
2008-03-25 15:47:49 +03:00
struct net * net = dev_net ( dev ) ;
2005-04-17 02:20:36 +04:00
struct sk_buff * skb ;
2006-08-15 11:37:09 +04:00
int err = - ENOBUFS ;
2011-06-10 05:27:09 +04:00
size_t if_info_size ;
2005-04-17 02:20:36 +04:00
2013-10-24 03:02:42 +04:00
skb = nlmsg_new ( ( if_info_size = if_nlmsg_size ( dev , 0 ) ) , flags ) ;
2006-08-15 11:37:09 +04:00
if ( skb = = NULL )
goto errout ;
2005-04-17 02:20:36 +04:00
2012-02-22 01:54:48 +04:00
err = rtnl_fill_ifinfo ( skb , dev , type , 0 , 0 , change , 0 , 0 ) ;
2007-02-01 10:16:40 +03:00
if ( err < 0 ) {
/* -EMSGSIZE implies BUG in if_nlmsg_size() */
WARN_ON ( err = = - EMSGSIZE ) ;
kfree_skb ( skb ) ;
goto errout ;
}
2013-10-24 03:02:42 +04:00
rtnl_notify ( skb , net , 0 , RTNLGRP_LINK , NULL , flags ) ;
2009-02-25 10:18:28 +03:00
return ;
2006-08-15 11:37:09 +04:00
errout :
if ( err < 0 )
2007-11-20 09:27:40 +03:00
rtnl_set_sk_err ( net , RTNLGRP_LINK , err ) ;
2005-04-17 02:20:36 +04:00
}
2013-01-04 02:49:01 +04:00
EXPORT_SYMBOL ( rtmsg_ifinfo ) ;
2005-04-17 02:20:36 +04:00
2012-04-15 10:44:08 +04:00
static int nlmsg_populate_fdb_fill ( struct sk_buff * skb ,
struct net_device * dev ,
u8 * addr , u32 pid , u32 seq ,
2014-03-19 20:47:49 +04:00
int type , unsigned int flags ,
int nlflags )
2012-04-15 10:44:08 +04:00
{
struct nlmsghdr * nlh ;
struct ndmsg * ndm ;
2014-03-19 20:47:49 +04:00
nlh = nlmsg_put ( skb , pid , seq , type , sizeof ( * ndm ) , nlflags ) ;
2012-04-15 10:44:08 +04: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 ;
ndm - > ndm_state = NUD_PERMANENT ;
if ( nla_put ( skb , NDA_LLADDR , ETH_ALEN , addr ) )
goto nla_put_failure ;
return nlmsg_end ( skb , nlh ) ;
nla_put_failure :
nlmsg_cancel ( skb , nlh ) ;
return - EMSGSIZE ;
}
2012-04-15 10:44:14 +04:00
static inline size_t rtnl_fdb_nlmsg_size ( void )
{
return NLMSG_ALIGN ( sizeof ( struct ndmsg ) ) + nla_total_size ( ETH_ALEN ) ;
}
static void rtnl_fdb_notify ( struct net_device * dev , u8 * addr , int type )
{
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 ;
2014-03-19 20:47:49 +04:00
err = nlmsg_populate_fdb_fill ( skb , dev , addr , 0 , 0 , type , NTF_SELF , 0 ) ;
2012-04-15 10:44:14 +04: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 19:39:42 +04: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 ,
const unsigned char * addr ,
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 ;
}
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 ) ;
2013-03-21 11:45:29 +04:00
static int rtnl_fdb_add ( struct sk_buff * skb , struct nlmsghdr * nlh )
2012-04-15 10:43:56 +04:00
{
struct net * net = sock_net ( skb - > sk ) ;
struct ndmsg * ndm ;
struct nlattr * tb [ NDA_MAX + 1 ] ;
struct net_device * dev ;
u8 * addr ;
int err ;
err = nlmsg_parse ( nlh , sizeof ( * ndm ) , tb , NDA_MAX , NULL ) ;
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 ] ) ;
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 02:48:52 +04:00
struct net_device * br_dev = netdev_master_upper_dev_get ( dev ) ;
const struct net_device_ops * ops = br_dev - > netdev_ops ;
err = ops - > ndo_fdb_add ( ndm , tb , dev , addr , nlh - > nlmsg_flags ) ;
2012-04-15 10:43:56 +04:00
if ( err )
goto out ;
else
ndm - > ndm_flags & = ~ NTF_MASTER ;
}
/* Embedded bridge, macvlan, and any other device support */
2013-03-06 19:39:42 +04: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 ,
nlh - > nlmsg_flags ) ;
else
err = ndo_dflt_fdb_add ( ndm , tb , dev , addr ,
nlh - > nlmsg_flags ) ;
2012-04-15 10:43:56 +04:00
2012-04-15 10:44:14 +04:00
if ( ! err ) {
rtnl_fdb_notify ( dev , addr , RTM_NEWNEIGH ) ;
2012-04-15 10:43:56 +04:00
ndm - > ndm_flags & = ~ NTF_SELF ;
2012-04-15 10:44:14 +04:00
}
2012-04-15 10:43:56 +04:00
}
out :
return err ;
}
2013-03-06 19:39:42 +04: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 ,
const unsigned char * addr )
{
int err = - EOPNOTSUPP ;
/* If aging addresses are supported device will need to
* implement its own handler for this .
*/
2013-08-09 02:19:48 +04:00
if ( ! ( ndm - > ndm_state & NUD_PERMANENT ) ) {
2013-03-06 19:39:42 +04:00
pr_info ( " %s: FDB only supports static addresses \n " , dev - > name ) ;
return - EINVAL ;
}
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 ) ;
else
err = - EINVAL ;
return err ;
}
EXPORT_SYMBOL ( ndo_dflt_fdb_del ) ;
2013-03-21 11:45:29 +04:00
static int rtnl_fdb_del ( struct sk_buff * skb , struct nlmsghdr * nlh )
2012-04-15 10:43:56 +04:00
{
struct net * net = sock_net ( skb - > sk ) ;
struct ndmsg * ndm ;
2013-02-13 16:00:18 +04:00
struct nlattr * tb [ NDA_MAX + 1 ] ;
2012-04-15 10:43:56 +04:00
struct net_device * dev ;
int err = - EINVAL ;
__u8 * addr ;
2013-02-13 16:00:18 +04:00
if ( ! capable ( CAP_NET_ADMIN ) )
return - EPERM ;
err = nlmsg_parse ( nlh , sizeof ( * ndm ) , tb , NDA_MAX , NULL ) ;
if ( err < 0 )
return err ;
2012-04-15 10:43:56 +04: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 16:00:18 +04: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 10:43:56 +04: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 02:48:52 +04: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 10:43:56 +04:00
2013-01-04 02:48:52 +04:00
if ( ops - > ndo_fdb_del )
2013-02-13 16:00:18 +04:00
err = ops - > ndo_fdb_del ( ndm , tb , dev , addr ) ;
2012-04-15 10:43:56 +04:00
if ( err )
goto out ;
else
ndm - > ndm_flags & = ~ NTF_MASTER ;
}
/* Embedded bridge, macvlan, and any other device support */
2013-03-06 19:39:42 +04:00
if ( ndm - > ndm_flags & NTF_SELF ) {
if ( dev - > netdev_ops - > ndo_fdb_del )
err = dev - > netdev_ops - > ndo_fdb_del ( ndm , tb , dev , addr ) ;
else
err = ndo_dflt_fdb_del ( ndm , tb , dev , addr ) ;
2012-04-15 10:43:56 +04:00
2012-04-15 10:44:14 +04:00
if ( ! err ) {
rtnl_fdb_notify ( dev , addr , RTM_DELNEIGH ) ;
2012-04-15 10:43:56 +04:00
ndm - > ndm_flags & = ~ NTF_SELF ;
2012-04-15 10:44:14 +04:00
}
2012-04-15 10:43:56 +04:00
}
out :
return err ;
}
2012-04-15 10:44:08 +04: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 00:12:54 +04:00
u32 portid , seq ;
2012-04-15 10:44:08 +04:00
2012-09-08 00:12:54 +04:00
portid = NETLINK_CB ( cb - > skb ) . portid ;
2012-04-15 10:44:08 +04:00
seq = cb - > nlh - > nlmsg_seq ;
list_for_each_entry ( ha , & list - > list , list ) {
if ( * idx < cb - > args [ 0 ] )
goto skip ;
err = nlmsg_populate_fdb_fill ( skb , dev , ha - > addr ,
2012-11-01 20:23:10 +04:00
portid , seq ,
2014-03-19 20:47:49 +04:00
RTM_NEWNEIGH , NTF_SELF ,
NLM_F_MULTI ) ;
2012-04-15 10:44:08 +04:00
if ( err < 0 )
return err ;
skip :
* idx + = 1 ;
}
return 0 ;
}
/**
2012-07-10 14:55:09 +04:00
* ndo_dflt_fdb_dump - default netdevice operation to dump an FDB table .
2012-04-15 10:44:08 +04:00
* @ nlh : netlink message header
* @ dev : netdevice
*
* Default netdevice operation to dump the existing unicast address list .
2013-03-29 12:18:37 +04:00
* Returns number of addresses from list put in skb .
2012-04-15 10:44:08 +04:00
*/
int ndo_dflt_fdb_dump ( struct sk_buff * skb ,
struct netlink_callback * cb ,
struct net_device * dev ,
int idx )
{
int err ;
netif_addr_lock_bh ( dev ) ;
err = nlmsg_populate_fdb ( skb , cb , dev , & idx , & dev - > uc ) ;
if ( err )
goto out ;
nlmsg_populate_fdb ( skb , cb , dev , & idx , & dev - > mc ) ;
out :
netif_addr_unlock_bh ( dev ) ;
return idx ;
}
EXPORT_SYMBOL ( ndo_dflt_fdb_dump ) ;
2012-04-15 10:43:56 +04:00
static int rtnl_fdb_dump ( struct sk_buff * skb , struct netlink_callback * cb )
{
int idx = 0 ;
struct net * net = sock_net ( skb - > sk ) ;
struct net_device * dev ;
rcu_read_lock ( ) ;
for_each_netdev_rcu ( net , dev ) {
if ( dev - > priv_flags & IFF_BRIDGE_PORT ) {
2013-01-04 02:48:52 +04:00
struct net_device * br_dev ;
const struct net_device_ops * ops ;
2012-04-15 10:43:56 +04:00
2013-01-04 02:48:52 +04:00
br_dev = netdev_master_upper_dev_get ( dev ) ;
ops = br_dev - > netdev_ops ;
2012-04-15 10:43:56 +04:00
if ( ops - > ndo_fdb_dump )
idx = ops - > ndo_fdb_dump ( skb , cb , dev , idx ) ;
}
if ( dev - > netdev_ops - > ndo_fdb_dump )
idx = dev - > netdev_ops - > ndo_fdb_dump ( skb , cb , dev , idx ) ;
2013-03-06 19:39:42 +04:00
else
2013-03-29 12:18:37 +04:00
idx = ndo_dflt_fdb_dump ( skb , cb , dev , idx ) ;
2012-04-15 10:43:56 +04:00
}
rcu_read_unlock ( ) ;
cb - > args [ 0 ] = idx ;
return skb - > len ;
}
2012-10-24 12:13:09 +04:00
int ndo_dflt_bridge_getlink ( struct sk_buff * skb , u32 pid , u32 seq ,
struct net_device * dev , u16 mode )
{
struct nlmsghdr * nlh ;
struct ifinfomsg * ifm ;
struct nlattr * br_afspec ;
u8 operstate = netif_running ( dev ) ? dev - > operstate : IF_OPER_DOWN ;
2013-01-04 02:48:52 +04:00
struct net_device * br_dev = netdev_master_upper_dev_get ( dev ) ;
2012-10-24 12:13:09 +04:00
nlh = nlmsg_put ( skb , pid , seq , RTM_NEWLINK , sizeof ( * ifm ) , NLM_F_MULTI ) ;
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 02:48:52 +04:00
( br_dev & &
nla_put_u32 ( skb , IFLA_MASTER , br_dev - > ifindex ) ) | |
2012-10-24 12:13:09 +04:00
( dev - > addr_len & &
nla_put ( skb , IFLA_ADDRESS , dev - > addr_len , dev - > dev_addr ) ) | |
( dev - > ifindex ! = dev - > iflink & &
nla_put_u32 ( skb , IFLA_LINK , dev - > iflink ) ) )
goto nla_put_failure ;
br_afspec = nla_nest_start ( skb , IFLA_AF_SPEC ) ;
if ( ! br_afspec )
goto nla_put_failure ;
if ( nla_put_u16 ( skb , IFLA_BRIDGE_FLAGS , BRIDGE_FLAGS_SELF ) | |
nla_put_u16 ( skb , IFLA_BRIDGE_MODE , mode ) ) {
nla_nest_cancel ( skb , br_afspec ) ;
goto nla_put_failure ;
}
nla_nest_end ( skb , br_afspec ) ;
return nlmsg_end ( skb , nlh ) ;
nla_put_failure :
nlmsg_cancel ( skb , nlh ) ;
return - EMSGSIZE ;
}
EXPORT_SYMBOL ( ndo_dflt_bridge_getlink ) ;
2012-10-24 12:12:57 +04: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 16:00:13 +04:00
struct nlattr * extfilt ;
u32 filter_mask = 0 ;
rtnetlink: rtnl_bridge_getlink: Call nlmsg_find_attr() with ifinfomsg header
Fix the iproute2 command `bridge vlan show`, after switching from
rtgenmsg to ifinfomsg.
Let's start with a little history:
Feb 20: Vlad Yasevich got his VLAN-aware bridge patchset included in
the 3.9 merge window.
In the kernel commit 6cbdceeb, he added attribute support to
bridge GETLINK requests sent with rtgenmsg.
Mar 6th: Vlad got this iproute2 reference implementation of the bridge
vlan netlink interface accepted (iproute2 9eff0e5c)
Apr 25th: iproute2 switched from using rtgenmsg to ifinfomsg (63338dca)
http://patchwork.ozlabs.org/patch/239602/
http://marc.info/?t=136680900700007
Apr 28th: Linus released 3.9
Apr 30th: Stephen released iproute2 3.9.0
The `bridge vlan show` command haven't been working since the switch to
ifinfomsg, or in a released version of iproute2. Since the kernel side
only supports rtgenmsg, which iproute2 switched away from just prior to
the iproute2 3.9.0 release.
I haven't been able to find any documentation, about neither rtgenmsg
nor ifinfomsg, and in which situation to use which, but kernel commit
88c5b5ce seams to suggest that ifinfomsg should be used.
Fixing this in kernel will break compatibility, but I doubt that anybody
have been using it due to this bug in the user space reference
implementation, at least not without noticing this bug. That said the
functionality is still fully functional in 3.9, when reversing iproute2
commit 63338dca.
This could also be fixed in iproute2, but thats an ugly patch that would
reintroduce rtgenmsg in iproute2, and from searching in netdev it seams
like rtgenmsg usage is discouraged. I'm assuming that the only reason
that Vlad implemented the kernel side to use rtgenmsg, was because
iproute2 was using it at the time.
Signed-off-by: Asbjoern Sloth Toennesen <ast@fiberby.net>
Reviewed-by: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-08-12 20:30:09 +04:00
extfilt = nlmsg_find_attr ( cb - > nlh , sizeof ( struct ifinfomsg ) ,
2013-02-13 16:00:13 +04:00
IFLA_EXT_MASK ) ;
if ( extfilt )
filter_mask = nla_get_u32 ( extfilt ) ;
2012-10-24 12:12:57 +04:00
rcu_read_lock ( ) ;
for_each_netdev_rcu ( net , dev ) {
const struct net_device_ops * ops = dev - > netdev_ops ;
2013-01-04 02:48:52 +04:00
struct net_device * br_dev = netdev_master_upper_dev_get ( dev ) ;
2012-10-24 12:12:57 +04:00
2013-01-04 02:48:52 +04:00
if ( br_dev & & br_dev - > netdev_ops - > ndo_bridge_getlink ) {
2012-11-02 16:56:52 +04:00
if ( idx > = cb - > args [ 0 ] & &
2013-01-04 02:48:52 +04:00
br_dev - > netdev_ops - > ndo_bridge_getlink (
2013-02-13 16:00:13 +04:00
skb , portid , seq , dev , filter_mask ) < 0 )
2012-10-24 12:12:57 +04:00
break ;
2012-11-02 16:56:52 +04:00
idx + + ;
2012-10-24 12:12:57 +04:00
}
if ( ops - > ndo_bridge_getlink ) {
2012-11-02 16:56:52 +04:00
if ( idx > = cb - > args [ 0 ] & &
2013-02-13 16:00:13 +04:00
ops - > ndo_bridge_getlink ( skb , portid , seq , dev ,
filter_mask ) < 0 )
2012-10-24 12:12:57 +04:00
break ;
2012-11-02 16:56:52 +04:00
idx + + ;
2012-10-24 12:12:57 +04:00
}
}
rcu_read_unlock ( ) ;
cb - > args [ 0 ] = idx ;
return skb - > len ;
}
2012-10-24 12:13:03 +04: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 */
}
static int rtnl_bridge_notify ( struct net_device * dev , u16 flags )
{
struct net * net = dev_net ( dev ) ;
2013-01-04 02:48:52 +04:00
struct net_device * br_dev = netdev_master_upper_dev_get ( dev ) ;
2012-10-24 12:13:03 +04:00
struct sk_buff * skb ;
int err = - EOPNOTSUPP ;
skb = nlmsg_new ( bridge_nlmsg_size ( ) , GFP_ATOMIC ) ;
if ( ! skb ) {
err = - ENOMEM ;
goto errout ;
}
2012-11-02 20:32:36 +04:00
if ( ( ! flags | | ( flags & BRIDGE_FLAGS_MASTER ) ) & &
2013-01-04 02:48:52 +04:00
br_dev & & br_dev - > netdev_ops - > ndo_bridge_getlink ) {
2013-02-13 16:00:13 +04:00
err = br_dev - > netdev_ops - > ndo_bridge_getlink ( skb , 0 , 0 , dev , 0 ) ;
2012-11-02 20:32:36 +04:00
if ( err < 0 )
goto errout ;
}
2012-10-24 12:13:03 +04:00
2012-11-02 20:32:36 +04:00
if ( ( flags & BRIDGE_FLAGS_SELF ) & &
dev - > netdev_ops - > ndo_bridge_getlink ) {
2013-02-13 16:00:13 +04:00
err = dev - > netdev_ops - > ndo_bridge_getlink ( skb , 0 , 0 , dev , 0 ) ;
2012-11-02 20:32:36 +04:00
if ( err < 0 )
goto errout ;
}
2012-10-24 12:13:03 +04:00
rtnl_notify ( skb , net , 0 , RTNLGRP_LINK , NULL , GFP_ATOMIC ) ;
return 0 ;
errout :
WARN_ON ( err = = - EMSGSIZE ) ;
kfree_skb ( skb ) ;
rtnl_set_sk_err ( net , RTNLGRP_LINK , err ) ;
return err ;
}
2013-03-21 11:45:29 +04:00
static int rtnl_bridge_setlink ( struct sk_buff * skb , struct nlmsghdr * nlh )
2012-10-24 12:12:57 +04:00
{
struct net * net = sock_net ( skb - > sk ) ;
struct ifinfomsg * ifm ;
struct net_device * dev ;
2012-10-24 12:13:03 +04:00
struct nlattr * br_spec , * attr = NULL ;
int rem , err = - EOPNOTSUPP ;
2012-11-02 20:32:36 +04:00
u16 oflags , flags = 0 ;
bool have_flags = false ;
2012-10-24 12:12:57 +04: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 12:13:03 +04: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 ) {
2012-11-02 20:32:36 +04:00
have_flags = true ;
2012-10-24 12:13:03 +04:00
flags = nla_get_u16 ( attr ) ;
break ;
}
}
}
2012-11-02 20:32:36 +04:00
oflags = flags ;
2012-10-24 12:13:03 +04:00
if ( ! flags | | ( flags & BRIDGE_FLAGS_MASTER ) ) {
2013-01-04 02:48:52 +04: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 12:13:03 +04:00
err = - EOPNOTSUPP ;
goto out ;
}
2013-01-04 02:48:52 +04:00
err = br_dev - > netdev_ops - > ndo_bridge_setlink ( dev , nlh ) ;
2012-10-24 12:12:57 +04:00
if ( err )
goto out ;
2012-10-24 12:13:03 +04:00
flags & = ~ BRIDGE_FLAGS_MASTER ;
2012-10-24 12:12:57 +04:00
}
2012-10-24 12:13:03 +04:00
if ( ( flags & BRIDGE_FLAGS_SELF ) ) {
if ( ! dev - > netdev_ops - > ndo_bridge_setlink )
err = - EOPNOTSUPP ;
else
err = dev - > netdev_ops - > ndo_bridge_setlink ( dev , nlh ) ;
if ( ! err )
flags & = ~ BRIDGE_FLAGS_SELF ;
}
2012-10-24 12:12:57 +04:00
2012-11-02 20:32:36 +04:00
if ( have_flags )
2012-10-24 12:13:03 +04:00
memcpy ( nla_data ( attr ) , & flags , sizeof ( flags ) ) ;
/* Generate event to notify upper layer of bridge change */
if ( ! err )
2012-11-02 20:32:36 +04:00
err = rtnl_bridge_notify ( dev , oflags ) ;
2012-10-24 12:12:57 +04:00
out :
return err ;
}
2013-03-21 11:45:29 +04:00
static int rtnl_bridge_dellink ( struct sk_buff * skb , struct nlmsghdr * nlh )
2013-02-13 16:00:12 +04: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 ;
u16 oflags , flags = 0 ;
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 ) {
have_flags = true ;
flags = nla_get_u16 ( attr ) ;
break ;
}
}
}
oflags = flags ;
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 ;
}
err = br_dev - > netdev_ops - > ndo_bridge_dellink ( dev , nlh ) ;
if ( err )
goto out ;
flags & = ~ BRIDGE_FLAGS_MASTER ;
}
if ( ( flags & BRIDGE_FLAGS_SELF ) ) {
if ( ! dev - > netdev_ops - > ndo_bridge_dellink )
err = - EOPNOTSUPP ;
else
err = dev - > netdev_ops - > ndo_bridge_dellink ( dev , nlh ) ;
if ( ! err )
flags & = ~ BRIDGE_FLAGS_SELF ;
}
if ( have_flags )
memcpy ( nla_data ( attr ) , & flags , sizeof ( flags ) ) ;
/* Generate event to notify upper layer of bridge change */
if ( ! err )
err = rtnl_bridge_notify ( dev , oflags ) ;
out :
return err ;
}
2005-04-17 02:20:36 +04:00
/* Process one rtnetlink message. */
2007-03-23 09:30:12 +03:00
static int rtnetlink_rcv_msg ( struct sk_buff * skb , struct nlmsghdr * nlh )
2005-04-17 02:20:36 +04:00
{
2008-03-25 20:26:21 +03:00
struct net * net = sock_net ( skb - > sk ) ;
2007-03-22 21:48:11 +03:00
rtnl_doit_func doit ;
2005-04-17 02:20:36 +04:00
int sz_idx , kind ;
int family ;
int type ;
2011-05-25 11:34:04 +04:00
int err ;
2005-04-17 02:20:36 +04:00
type = nlh - > nlmsg_type ;
if ( type > RTM_MAX )
2007-04-06 01:35:52 +04:00
return - EOPNOTSUPP ;
2005-04-17 02:20:36 +04:00
type - = RTM_BASE ;
/* All the messages must have at least 1 byte length */
2013-03-27 10:47:04 +04:00
if ( nlmsg_len ( nlh ) < sizeof ( struct rtgenmsg ) )
2005-04-17 02:20:36 +04:00
return 0 ;
2013-03-27 10:47:04 +04:00
family = ( ( struct rtgenmsg * ) nlmsg_data ( nlh ) ) - > rtgen_family ;
2005-04-17 02:20:36 +04:00
sz_idx = type > > 2 ;
kind = type & 3 ;
2012-11-16 07:03:00 +04:00
if ( kind ! = 2 & & ! ns_capable ( net - > user_ns , CAP_NET_ADMIN ) )
2007-03-23 09:30:12 +03:00
return - EPERM ;
2005-04-17 02:20:36 +04:00
2011-01-18 23:40:38 +03:00
if ( kind = = 2 & & nlh - > nlmsg_flags & NLM_F_DUMP ) {
2007-11-20 09:26:51 +03:00
struct sock * rtnl ;
2007-03-22 21:48:11 +03:00
rtnl_dumpit_func dumpit ;
2011-06-10 05:27:09 +04:00
rtnl_calcit_func calcit ;
u16 min_dump_alloc = 0 ;
2005-04-17 02:20:36 +04:00
2007-03-22 21:48:11 +03:00
dumpit = rtnl_get_dumpit ( family , type ) ;
if ( dumpit = = NULL )
2007-04-06 01:35:52 +04:00
return - EOPNOTSUPP ;
2011-06-10 05:27:09 +04:00
calcit = rtnl_get_calcit ( family , type ) ;
if ( calcit )
2012-02-22 01:54:48 +04:00
min_dump_alloc = calcit ( skb , nlh ) ;
2005-11-10 04:25:55 +03:00
2011-05-25 11:34:04 +04:00
__rtnl_unlock ( ) ;
2007-11-20 09:26:51 +03:00
rtnl = net - > rtnl ;
2012-02-24 18:30:15 +04:00
{
struct netlink_dump_control c = {
. dump = dumpit ,
. min_dump_alloc = min_dump_alloc ,
} ;
err = netlink_dump_start ( rtnl , skb , nlh , & c ) ;
}
2011-05-25 11:34:04 +04:00
rtnl_lock ( ) ;
return err ;
2005-04-17 02:20:36 +04:00
}
2007-03-22 21:48:11 +03:00
doit = rtnl_get_doit ( family , type ) ;
if ( doit = = NULL )
2007-04-06 01:35:52 +04:00
return - EOPNOTSUPP ;
2005-04-17 02:20:36 +04:00
2013-03-21 11:45:29 +04:00
return doit ( skb , nlh ) ;
2005-04-17 02:20:36 +04:00
}
2007-10-11 08:15:29 +04:00
static void rtnetlink_rcv ( struct sk_buff * skb )
2005-04-17 02:20:36 +04:00
{
2007-10-11 08:15:29 +04:00
rtnl_lock ( ) ;
netlink_rcv_skb ( skb , & rtnetlink_rcv_msg ) ;
rtnl_unlock ( ) ;
2005-04-17 02:20:36 +04:00
}
static int rtnetlink_event ( struct notifier_block * this , unsigned long event , void * ptr )
{
2013-05-28 05:30:21 +04:00
struct net_device * dev = netdev_notifier_info_to_dev ( ptr ) ;
2007-09-12 15:02:17 +04:00
2005-04-17 02:20:36 +04:00
switch ( event ) {
case NETDEV_UP :
case NETDEV_DOWN :
2010-02-26 09:34:50 +03:00
case NETDEV_PRE_UP :
2009-12-13 01:11:15 +03:00
case NETDEV_POST_INIT :
case NETDEV_REGISTER :
2005-04-17 02:20:36 +04:00
case NETDEV_CHANGE :
2010-03-19 07:42:24 +03:00
case NETDEV_PRE_TYPE_CHANGE :
2005-04-17 02:20:36 +04:00
case NETDEV_GOING_DOWN :
2010-02-26 09:34:51 +03:00
case NETDEV_UNREGISTER :
2012-08-22 21:19:46 +04:00
case NETDEV_UNREGISTER_FINAL :
2011-05-20 03:06:32 +04:00
case NETDEV_RELEASE :
case NETDEV_JOIN :
2005-04-17 02:20:36 +04:00
break ;
default :
2013-10-24 03:02:42 +04:00
rtmsg_ifinfo ( RTM_NEWLINK , dev , 0 , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
break ;
}
return NOTIFY_DONE ;
}
static struct notifier_block rtnetlink_dev_notifier = {
. notifier_call = rtnetlink_event ,
} ;
2007-11-20 09:26:51 +03:00
2010-01-17 06:35:32 +03:00
static int __net_init rtnetlink_net_init ( struct net * net )
2007-11-20 09:26:51 +03:00
{
struct sock * sk ;
2012-06-29 10:15:21 +04:00
struct netlink_kernel_cfg cfg = {
. groups = RTNLGRP_MAX ,
. input = rtnetlink_rcv ,
. cb_mutex = & rtnl_mutex ,
2012-09-08 06:53:53 +04:00
. flags = NL_CFG_F_NONROOT_RECV ,
2012-06-29 10:15:21 +04:00
} ;
2012-09-08 06:53:54 +04:00
sk = netlink_kernel_create ( net , NETLINK_ROUTE , & cfg ) ;
2007-11-20 09:26:51 +03:00
if ( ! sk )
return - ENOMEM ;
net - > rtnl = sk ;
return 0 ;
}
2010-01-17 06:35:32 +03:00
static void __net_exit rtnetlink_net_exit ( struct net * net )
2007-11-20 09:26:51 +03:00
{
2008-01-19 10:55:19 +03:00
netlink_kernel_release ( net - > rtnl ) ;
net - > rtnl = NULL ;
2007-11-20 09:26:51 +03:00
}
static struct pernet_operations rtnetlink_net_ops = {
. init = rtnetlink_net_init ,
. exit = rtnetlink_net_exit ,
} ;
2005-04-17 02:20:36 +04:00
void __init rtnetlink_init ( void )
{
2007-11-20 09:26:51 +03:00
if ( register_pernet_subsys ( & rtnetlink_net_ops ) )
2005-04-17 02:20:36 +04:00
panic ( " rtnetlink_init: cannot initialize rtnetlink \n " ) ;
2007-11-20 09:26:51 +03:00
2005-04-17 02:20:36 +04:00
register_netdevice_notifier ( & rtnetlink_dev_notifier ) ;
2007-03-22 21:49:22 +03:00
2011-06-10 05:27:09 +04:00
rtnl_register ( PF_UNSPEC , RTM_GETLINK , rtnl_getlink ,
rtnl_dump_ifinfo , rtnl_calcit ) ;
rtnl_register ( PF_UNSPEC , RTM_SETLINK , rtnl_setlink , NULL , NULL ) ;
rtnl_register ( PF_UNSPEC , RTM_NEWLINK , rtnl_newlink , NULL , NULL ) ;
rtnl_register ( PF_UNSPEC , RTM_DELLINK , rtnl_dellink , NULL , NULL ) ;
2007-03-22 21:59:42 +03:00
2011-06-10 05:27:09 +04:00
rtnl_register ( PF_UNSPEC , RTM_GETADDR , NULL , rtnl_dump_all , NULL ) ;
rtnl_register ( PF_UNSPEC , RTM_GETROUTE , NULL , rtnl_dump_all , NULL ) ;
2012-04-15 10:43:56 +04:00
rtnl_register ( PF_BRIDGE , RTM_NEWNEIGH , rtnl_fdb_add , NULL , NULL ) ;
rtnl_register ( PF_BRIDGE , RTM_DELNEIGH , rtnl_fdb_del , NULL , NULL ) ;
rtnl_register ( PF_BRIDGE , RTM_GETNEIGH , NULL , rtnl_fdb_dump , NULL ) ;
2012-10-24 12:12:57 +04:00
rtnl_register ( PF_BRIDGE , RTM_GETLINK , NULL , rtnl_bridge_getlink , NULL ) ;
2013-02-13 16:00:12 +04:00
rtnl_register ( PF_BRIDGE , RTM_DELLINK , rtnl_bridge_dellink , NULL , NULL ) ;
2012-10-24 12:12:57 +04:00
rtnl_register ( PF_BRIDGE , RTM_SETLINK , rtnl_bridge_setlink , NULL , NULL ) ;
2005-04-17 02:20:36 +04:00
}