Skip to content

Commit

Permalink
team: introduce random mode
Browse files Browse the repository at this point in the history
As suggested by Eric Dumazet, allow user to select mode which chooses
TX port randomly. Functionality should be more of less similar to
round-robin mode with even lower overhead.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jiri Pirko authored and David S. Miller committed Mar 6, 2013
1 parent acbba0d commit 753f993
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 21 deletions.
12 changes: 12 additions & 0 deletions drivers/net/team/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ config NET_TEAM_MODE_ROUNDROBIN
To compile this team mode as a module, choose M here: the module
will be called team_mode_roundrobin.

config NET_TEAM_MODE_RANDOM
tristate "Random mode support"
depends on NET_TEAM
---help---
Basic mode where port used for transmitting packets is selected
randomly.

All added ports are setup to have team's device address.

To compile this team mode as a module, choose M here: the module
will be called team_mode_random.

config NET_TEAM_MODE_ACTIVEBACKUP
tristate "Active-backup mode support"
depends on NET_TEAM
Expand Down
1 change: 1 addition & 0 deletions drivers/net/team/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
obj-$(CONFIG_NET_TEAM) += team.o
obj-$(CONFIG_NET_TEAM_MODE_BROADCAST) += team_mode_broadcast.o
obj-$(CONFIG_NET_TEAM_MODE_ROUNDROBIN) += team_mode_roundrobin.o
obj-$(CONFIG_NET_TEAM_MODE_RANDOM) += team_mode_random.o
obj-$(CONFIG_NET_TEAM_MODE_ACTIVEBACKUP) += team_mode_activebackup.o
obj-$(CONFIG_NET_TEAM_MODE_LOADBALANCE) += team_mode_loadbalance.o
71 changes: 71 additions & 0 deletions drivers/net/team/team_mode_random.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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/reciprocal_div.h>
#include <linux/if_team.h>

static u32 random_N(unsigned int N)
{
return reciprocal_divide(random32(), N);
}

static bool rnd_transmit(struct team *team, struct sk_buff *skb)
{
struct team_port *port;
int port_index;

port_index = random_N(team->en_port_count);
port = team_get_port_by_index_rcu(team, port_index);
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");
22 changes: 1 addition & 21 deletions drivers/net/team/team_mode_roundrobin.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,14 @@ static struct rr_priv *rr_priv(struct team *team)
return (struct rr_priv *) &team->mode_priv;
}

static struct team_port *__get_first_port_up(struct team *team,
struct team_port *port)
{
struct team_port *cur;

if (team_port_txable(port))
return port;
cur = port;
list_for_each_entry_continue_rcu(cur, &team->port_list, list)
if (team_port_txable(port))
return cur;
list_for_each_entry_rcu(cur, &team->port_list, list) {
if (cur == port)
break;
if (team_port_txable(port))
return cur;
}
return NULL;
}

static bool rr_transmit(struct team *team, struct sk_buff *skb)
{
struct team_port *port;
int port_index;

port_index = rr_priv(team)->sent_packets++ % team->en_port_count;
port = team_get_port_by_index_rcu(team, port_index);
port = __get_first_port_up(team, port);
port = team_get_first_port_txable_rcu(team, port);
if (unlikely(!port))
goto drop;
if (team_dev_queue_xmit(team, port, skb))
Expand Down
20 changes: 20 additions & 0 deletions include/linux/if_team.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,26 @@ static inline struct team_port *team_get_port_by_index_rcu(struct team *team,
return NULL;
}

static inline struct team_port *
team_get_first_port_txable_rcu(struct team *team, struct team_port *port)
{
struct team_port *cur;

if (likely(team_port_txable(port)))
return port;
cur = port;
list_for_each_entry_continue_rcu(cur, &team->port_list, list)
if (team_port_txable(port))
return cur;
list_for_each_entry_rcu(cur, &team->port_list, list) {
if (cur == port)
break;
if (team_port_txable(port))
return cur;
}
return NULL;
}

extern int team_options_register(struct team *team,
const struct team_option *option,
size_t option_count);
Expand Down

0 comments on commit 753f993

Please sign in to comment.