netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch net-next 1/2] team: add binary option type
@ 2012-04-04 22:16 Jiri Pirko
  2012-04-04 22:16 ` [patch net-next 2/2] team: add loadbalance mode Jiri Pirko
  2012-04-05  0:31 ` [patch net-next 1/2] team: add binary option type David Miller
  0 siblings, 2 replies; 6+ messages in thread
From: Jiri Pirko @ 2012-04-04 22:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, eric.dumazet, bhutchings, shemminger, raise.sail,
	nuno.martins, matt

For transfering generic binary data (e.g. BPF code), introduce new
binary option type.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
 drivers/net/team/team.c |   30 ++++++++++++++++++++++++++----
 include/linux/if_team.h |    8 ++++++++
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 0db6e66..ea96f82 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1145,10 +1145,7 @@ team_nl_option_policy[TEAM_ATTR_OPTION_MAX + 1] = {
 	},
 	[TEAM_ATTR_OPTION_CHANGED]		= { .type = NLA_FLAG },
 	[TEAM_ATTR_OPTION_TYPE]			= { .type = NLA_U8 },
-	[TEAM_ATTR_OPTION_DATA] = {
-		.type = NLA_BINARY,
-		.len = TEAM_STRING_MAX_LEN,
-	},
+	[TEAM_ATTR_OPTION_DATA]			= { .type = NLA_BINARY },
 };
 
 static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
@@ -1257,6 +1254,7 @@ static int team_nl_fill_options_get(struct sk_buff *skb,
 	list_for_each_entry(option, &team->option_list, list) {
 		struct nlattr *option_item;
 		long arg;
+		struct team_option_binary tbinary;
 
 		/* Include only changed options if fill all mode is not on */
 		if (!fillall && !option->changed)
@@ -1290,6 +1288,15 @@ static int team_nl_fill_options_get(struct sk_buff *skb,
 					   (char *) arg))
 				goto nla_put_failure;
 			break;
+		case TEAM_OPTION_TYPE_BINARY:
+			if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_BINARY))
+				goto nla_put_failure;
+			arg = (long) &tbinary;
+			team_option_get(team, option, &arg);
+			if (nla_put(skb, TEAM_ATTR_OPTION_DATA,
+				    tbinary.data_len, tbinary.data))
+				goto nla_put_failure;
+			break;
 		default:
 			BUG();
 		}
@@ -1374,6 +1381,9 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
 		case NLA_STRING:
 			opt_type = TEAM_OPTION_TYPE_STRING;
 			break;
+		case NLA_BINARY:
+			opt_type = TEAM_OPTION_TYPE_BINARY;
+			break;
 		default:
 			goto team_put;
 		}
@@ -1382,19 +1392,31 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
 		list_for_each_entry(option, &team->option_list, list) {
 			long arg;
 			struct nlattr *opt_data_attr;
+			struct team_option_binary tbinary;
+			int data_len;
 
 			if (option->type != opt_type ||
 			    strcmp(option->name, opt_name))
 				continue;
 			opt_found = true;
 			opt_data_attr = mode_attrs[TEAM_ATTR_OPTION_DATA];
+			data_len = nla_len(opt_data_attr);
 			switch (opt_type) {
 			case TEAM_OPTION_TYPE_U32:
 				arg = nla_get_u32(opt_data_attr);
 				break;
 			case TEAM_OPTION_TYPE_STRING:
+				if (data_len > TEAM_STRING_MAX_LEN) {
+					err = -EINVAL;
+					goto team_put;
+				}
 				arg = (long) nla_data(opt_data_attr);
 				break;
+			case TEAM_OPTION_TYPE_BINARY:
+				tbinary.data_len = data_len;
+				tbinary.data = nla_data(opt_data_attr);
+				arg = (long) &tbinary;
+				break;
 			default:
 				BUG();
 			}
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index 58404b0..41163ac 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -68,6 +68,7 @@ struct team_mode_ops {
 enum team_option_type {
 	TEAM_OPTION_TYPE_U32,
 	TEAM_OPTION_TYPE_STRING,
+	TEAM_OPTION_TYPE_BINARY,
 };
 
 struct team_option {
@@ -82,6 +83,13 @@ struct team_option {
 	bool removed;
 };
 
+struct team_option_binary {
+	u32 data_len;
+	void *data;
+};
+
+#define team_optarg_tbinary(arg) (*((struct team_option_binary **) arg))
+
 struct team_mode {
 	struct list_head list;
 	const char *kind;
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [patch net-next 2/2] team: add loadbalance mode
  2012-04-04 22:16 [patch net-next 1/2] team: add binary option type Jiri Pirko
@ 2012-04-04 22:16 ` Jiri Pirko
  2012-04-04 22:26   ` David Miller
  2012-04-05  0:31   ` David Miller
  2012-04-05  0:31 ` [patch net-next 1/2] team: add binary option type David Miller
  1 sibling, 2 replies; 6+ messages in thread
From: Jiri Pirko @ 2012-04-04 22:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, eric.dumazet, bhutchings, shemminger, raise.sail,
	nuno.martins, matt

This patch introduces new team mode. It's TX port is selected by
user-set BPF hash function.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
 drivers/net/team/Kconfig                 |   11 ++
 drivers/net/team/Makefile                |    1 +
 drivers/net/team/team_mode_loadbalance.c |  188 ++++++++++++++++++++++++++++++
 3 files changed, 200 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/team/team_mode_loadbalance.c

diff --git a/drivers/net/team/Kconfig b/drivers/net/team/Kconfig
index 248a144..89024d5 100644
--- a/drivers/net/team/Kconfig
+++ b/drivers/net/team/Kconfig
@@ -40,4 +40,15 @@ config NET_TEAM_MODE_ACTIVEBACKUP
 	  To compile this team mode as a module, choose M here: the module
 	  will be called team_mode_activebackup.
 
+config NET_TEAM_MODE_LOADBALANCE
+	tristate "Load-balance mode support"
+	depends on NET_TEAM
+	---help---
+	  This mode provides load balancing functionality. Tx port selection
+	  is done using BPF function set up from userspace (bpf_hash_func
+	  option)
+
+	  To compile this team mode as a module, choose M here: the module
+	  will be called team_mode_loadbalance.
+
 endif # NET_TEAM
diff --git a/drivers/net/team/Makefile b/drivers/net/team/Makefile
index 85f2028..fb9f4c1 100644
--- a/drivers/net/team/Makefile
+++ b/drivers/net/team/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_NET_TEAM) += team.o
 obj-$(CONFIG_NET_TEAM_MODE_ROUNDROBIN) += team_mode_roundrobin.o
 obj-$(CONFIG_NET_TEAM_MODE_ACTIVEBACKUP) += team_mode_activebackup.o
+obj-$(CONFIG_NET_TEAM_MODE_LOADBALANCE) += team_mode_loadbalance.o
diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
new file mode 100644
index 0000000..ed20f39
--- /dev/null
+++ b/drivers/net/team/team_mode_loadbalance.c
@@ -0,0 +1,188 @@
+/*
+ * drivers/net/team/team_mode_loadbalance.c - Load-balancing mode for team
+ * Copyright (c) 2012 Jiri Pirko <jpirko@redhat.com>
+ *
+ * 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/errno.h>
+#include <linux/netdevice.h>
+#include <linux/filter.h>
+#include <linux/if_team.h>
+
+struct lb_priv {
+	struct sk_filter __rcu *fp;
+	struct sock_fprog *orig_fprog;
+};
+
+static struct lb_priv *lb_priv(struct team *team)
+{
+	return (struct lb_priv *) &team->mode_priv;
+}
+
+static bool lb_transmit(struct team *team, struct sk_buff *skb)
+{
+	struct sk_filter *fp;
+	struct team_port *port;
+	unsigned int hash;
+	int port_index;
+
+	fp = rcu_dereference(lb_priv(team)->fp);
+	if (unlikely(!fp))
+		goto drop;
+	hash = SK_RUN_FILTER(fp, skb);
+	port_index = hash % team->port_count;
+	port = team_get_port_by_index_rcu(team, port_index);
+	if (unlikely(!port))
+		goto drop;
+	skb->dev = port->dev;
+	if (dev_queue_xmit(skb))
+		return false;
+	return true;
+
+drop:
+	dev_kfree_skb_any(skb);
+	return false;
+}
+
+static int lb_bpf_func_get(struct team *team, void *arg)
+{
+	struct team_option_binary *tbinary = team_optarg_tbinary(arg);
+
+	memset(tbinary, 0, sizeof(*tbinary));
+	if (!lb_priv(team)->orig_fprog)
+		return 0;
+
+	tbinary->data_len = lb_priv(team)->orig_fprog->len *
+			    sizeof(struct sock_filter);
+	tbinary->data = lb_priv(team)->orig_fprog->filter;
+	return 0;
+}
+
+static int __fprog_create(struct sock_fprog **pfprog, u32 data_len,
+			  void *data)
+{
+	struct sock_fprog *fprog;
+	struct sock_filter *filter = (struct sock_filter *) data;
+
+	if (data_len % sizeof(struct sock_filter))
+		return -EINVAL;
+	fprog = kmalloc(sizeof(struct sock_fprog), GFP_KERNEL);
+	if (!fprog)
+		return -ENOMEM;
+	fprog->filter = kmemdup(filter, data_len, GFP_KERNEL);
+	if (!fprog->filter) {
+		kfree(fprog);
+		return -ENOMEM;
+	}
+	fprog->len = data_len / sizeof(struct sock_filter);
+	*pfprog = fprog;
+	return 0;
+}
+
+static void __fprog_destroy(struct sock_fprog *fprog)
+{
+	kfree(fprog->filter);
+	kfree(fprog);
+}
+
+static int lb_bpf_func_set(struct team *team, void *arg)
+{
+	struct team_option_binary *tbinary = team_optarg_tbinary(arg);
+	struct sk_filter *fp = NULL;
+	struct sock_fprog *fprog = NULL;
+	int err;
+
+	if (tbinary->data_len) {
+		err = __fprog_create(&fprog, tbinary->data_len,
+				     tbinary->data);
+		if (err)
+			return err;
+		err = sk_unattached_filter_create(&fp, fprog);
+		if (err) {
+			__fprog_destroy(fprog);
+			return err;
+		}
+	}
+
+	if (lb_priv(team)->orig_fprog) {
+		/* Clear old filter data */
+		__fprog_destroy(lb_priv(team)->orig_fprog);
+		sk_unattached_filter_destroy(lb_priv(team)->fp);
+	}
+
+	rcu_assign_pointer(lb_priv(team)->fp, fp);
+	lb_priv(team)->orig_fprog = fprog;
+	return 0;
+}
+
+static const struct team_option lb_options[] = {
+	{
+		.name = "bpf_hash_func",
+		.type = TEAM_OPTION_TYPE_BINARY,
+		.getter = lb_bpf_func_get,
+		.setter = lb_bpf_func_set,
+	},
+};
+
+int lb_init(struct team *team)
+{
+	return team_options_register(team, lb_options,
+				     ARRAY_SIZE(lb_options));
+}
+
+void lb_exit(struct team *team)
+{
+	team_options_unregister(team, lb_options,
+				ARRAY_SIZE(lb_options));
+}
+
+static int lb_port_enter(struct team *team, struct team_port *port)
+{
+	return team_port_set_team_mac(port);
+}
+
+static void lb_port_change_mac(struct team *team, struct team_port *port)
+{
+	team_port_set_team_mac(port);
+}
+
+static const struct team_mode_ops lb_mode_ops = {
+	.init			= lb_init,
+	.exit			= lb_exit,
+	.transmit		= lb_transmit,
+	.port_enter		= lb_port_enter,
+	.port_change_mac	= lb_port_change_mac,
+};
+
+static struct team_mode lb_mode = {
+	.kind		= "loadbalance",
+	.owner		= THIS_MODULE,
+	.priv_size	= sizeof(struct lb_priv),
+	.ops		= &lb_mode_ops,
+};
+
+static int __init lb_init_module(void)
+{
+	return team_mode_register(&lb_mode);
+}
+
+static void __exit lb_cleanup_module(void)
+{
+	team_mode_unregister(&lb_mode);
+}
+
+module_init(lb_init_module);
+module_exit(lb_cleanup_module);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Jiri Pirko <jpirko@redhat.com>");
+MODULE_DESCRIPTION("Load-balancing mode for team");
+MODULE_ALIAS("team-mode-loadbalance");
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [patch net-next 2/2] team: add loadbalance mode
  2012-04-04 22:16 ` [patch net-next 2/2] team: add loadbalance mode Jiri Pirko
@ 2012-04-04 22:26   ` David Miller
  2012-04-05  6:37     ` Jiri Pirko
  2012-04-05  0:31   ` David Miller
  1 sibling, 1 reply; 6+ messages in thread
From: David Miller @ 2012-04-04 22:26 UTC (permalink / raw)
  To: jpirko
  Cc: netdev, eric.dumazet, bhutchings, shemminger, raise.sail,
	nuno.martins, matt


Hmmm, is the first patch stuck in a mail server queue somewhere?

I didn't see it.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [patch net-next 1/2] team: add binary option type
  2012-04-04 22:16 [patch net-next 1/2] team: add binary option type Jiri Pirko
  2012-04-04 22:16 ` [patch net-next 2/2] team: add loadbalance mode Jiri Pirko
@ 2012-04-05  0:31 ` David Miller
  1 sibling, 0 replies; 6+ messages in thread
From: David Miller @ 2012-04-05  0:31 UTC (permalink / raw)
  To: jpirko
  Cc: netdev, eric.dumazet, bhutchings, shemminger, raise.sail,
	nuno.martins, matt

From: Jiri Pirko <jpirko@redhat.com>
Date: Thu,  5 Apr 2012 00:16:26 +0200

> For transfering generic binary data (e.g. BPF code), introduce new
> binary option type.
> 
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>

Applied.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [patch net-next 2/2] team: add loadbalance mode
  2012-04-04 22:16 ` [patch net-next 2/2] team: add loadbalance mode Jiri Pirko
  2012-04-04 22:26   ` David Miller
@ 2012-04-05  0:31   ` David Miller
  1 sibling, 0 replies; 6+ messages in thread
From: David Miller @ 2012-04-05  0:31 UTC (permalink / raw)
  To: jpirko
  Cc: netdev, eric.dumazet, bhutchings, shemminger, raise.sail,
	nuno.martins, matt

From: Jiri Pirko <jpirko@redhat.com>
Date: Thu,  5 Apr 2012 00:16:27 +0200

> This patch introduces new team mode. It's TX port is selected by
> user-set BPF hash function.
> 
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>

Applied, thanks Jiri.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [patch net-next 2/2] team: add loadbalance mode
  2012-04-04 22:26   ` David Miller
@ 2012-04-05  6:37     ` Jiri Pirko
  0 siblings, 0 replies; 6+ messages in thread
From: Jiri Pirko @ 2012-04-05  6:37 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

Thu, Apr 05, 2012 at 12:26:24AM CEST, davem@davemloft.net wrote:
>
>Hmmm, is the first patch stuck in a mail server queue somewhere?

Looks like it. But it made it :)
Something odd is going on with mail... The similar thing happened for
my last patchset.

>
>I didn't see it.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-04-05  6:37 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-04 22:16 [patch net-next 1/2] team: add binary option type Jiri Pirko
2012-04-04 22:16 ` [patch net-next 2/2] team: add loadbalance mode Jiri Pirko
2012-04-04 22:26   ` David Miller
2012-04-05  6:37     ` Jiri Pirko
2012-04-05  0:31   ` David Miller
2012-04-05  0:31 ` [patch net-next 1/2] team: add binary option type David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).