| 
									
										
										
										
											2013-03-06 01:31:13 +00: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 02:29:39 +01:00
										 |  |  | 	port_index = prandom_u32_max(team->en_port_count); | 
					
						
							| 
									
										
										
										
											2013-03-06 01:31:13 +00:00
										 |  |  | 	port = team_get_port_by_index_rcu(team, port_index); | 
					
						
							| 
									
										
										
										
											2013-06-08 15:00:53 +02:00
										 |  |  | 	if (unlikely(!port)) | 
					
						
							|  |  |  | 		goto drop; | 
					
						
							| 
									
										
										
										
											2013-03-06 01:31:13 +00: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, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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"); |