2013-03-06 05:31:13 +04:00
/*
* drivers / net / team / team_mode_random . c - Random mode for team
* Copyright ( c ) 2013 Jiri Pirko < jiri @ resnulli . us >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/skbuff.h>
# include <linux/if_team.h>
static bool rnd_transmit ( struct team * team , struct sk_buff * skb )
{
struct team_port * port ;
int port_index ;
random32: add prandom_u32_max and convert open coded users
Many functions have open coded a function that returns a random
number in range [0,N-1]. Under the assumption that we have a PRNG
such as taus113 with being well distributed in [0, ~0U] space,
we can implement such a function as uword t = (n*m')>>32, where
m' is a random number obtained from PRNG, n the right open interval
border and t our resulting random number, with n,m',t in u32 universe.
Lets go with Joe and simply call it prandom_u32_max(), although
technically we have an right open interval endpoint, but that we
have documented. Other users can further be migrated to the new
prandom_u32_max() function later on; for now, we need to make sure
to migrate reciprocal_divide() users for the reciprocal_divide()
follow-up fixup since their function signatures are going to change.
Joint work with Hannes Frederic Sowa.
Cc: Jakub Zawadzki <darkjames-ws@darkjames.pl>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-01-22 05:29:39 +04:00
port_index = prandom_u32_max ( team - > en_port_count ) ;
2013-03-06 05:31:13 +04:00
port = team_get_port_by_index_rcu ( team , port_index ) ;
2013-06-08 17:00:53 +04:00
if ( unlikely ( ! port ) )
goto drop ;
2013-03-06 05:31:13 +04:00
port = team_get_first_port_txable_rcu ( team , port ) ;
if ( unlikely ( ! port ) )
goto drop ;
if ( team_dev_queue_xmit ( team , port , skb ) )
return false ;
return true ;
drop :
dev_kfree_skb_any ( skb ) ;
return false ;
}
static const struct team_mode_ops rnd_mode_ops = {
. transmit = rnd_transmit ,
. port_enter = team_modeop_port_enter ,
. port_change_dev_addr = team_modeop_port_change_dev_addr ,
} ;
static const struct team_mode rnd_mode = {
. kind = " random " ,
. owner = THIS_MODULE ,
. ops = & rnd_mode_ops ,
2015-12-03 14:12:13 +03:00
. lag_tx_type = NETDEV_LAG_TX_TYPE_RANDOM ,
2013-03-06 05:31:13 +04:00
} ;
static int __init rnd_init_module ( void )
{
return team_mode_register ( & rnd_mode ) ;
}
static void __exit rnd_cleanup_module ( void )
{
team_mode_unregister ( & rnd_mode ) ;
}
module_init ( rnd_init_module ) ;
module_exit ( rnd_cleanup_module ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_AUTHOR ( " Jiri Pirko <jiri@resnulli.us> " ) ;
MODULE_DESCRIPTION ( " Random mode for team " ) ;
MODULE_ALIAS ( " team-mode-random " ) ;