diff mbox

[RFC] act_cpu: packet distributing

Message ID AANLkTikXCWHO7xDKUPRi7ReAG8egmSfMAOfR9TlmhxWj@mail.gmail.com
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Changli Gao July 14, 2010, 3:27 a.m. UTC
On Wed, Jul 14, 2010 at 11:17 AM, Changli Gao <xiaosuo@gmail.com> wrote:
> I want to know if I can assign the sk to skb as nf_tproxy_core does to avoid
> the duplicate search later. Thanks.
>
> act_cpu: packet distributing
>
> This TC action can be used to redirect packets to the CPU:
>  * specified by the cpuid option
>  * specified by the class minor ID obtained previously
>  * on which the corresponding application runs
>
> It supports the similar functions of RPS and RFS, but is more flexible.
>
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>

The iproute2 patch against 2.6.31 is attached
diff mbox

Patch

diff -urN iproute2-2.6.31.orig/include/linux/tc_act/tc_cpu.h iproute2-2.6.31/include/linux/tc_act/tc_cpu.h
--- iproute2-2.6.31.orig/include/linux/tc_act/tc_cpu.h	1970-01-01 08:00:00.000000000 +0800
+++ iproute2-2.6.31/include/linux/tc_act/tc_cpu.h	2010-07-02 16:57:10.000000000 +0800
@@ -0,0 +1,31 @@ 
+#ifndef __LINUX_TC_CPU_H
+#define __LINUX_TC_CPU_H
+
+#include <linux/pkt_cls.h>
+#include <linux/types.h>
+
+#define TCA_ACT_CPU 12
+
+enum {
+	TCA_CPU_UNSPEC,
+	TCA_CPU_PARMS,
+	TCA_CPU_TM,
+	__TCA_CPU_MAX
+};
+#define TCA_CPU_MAX (__TCA_CPU_MAX - 1)
+
+enum {
+	TCA_CPU_TYPE_MAP,
+	TCA_CPU_TYPE_CPUID,
+	TCA_CPU_TYPE_SOCKET,
+	__TCA_CPU_TYPE_MAX
+};
+#define TCA_CPU_TYPE_MAX (__TCA_CPU_TYPE_MAX - 1)
+
+struct tc_cpu {
+	tc_gen;
+	__u32		type;
+	__u32		value;
+};
+
+#endif /* __LINUX_TC_CPU_H */
diff -urN iproute2-2.6.31.orig/tc/Makefile iproute2-2.6.31/tc/Makefile
--- iproute2-2.6.31.orig/tc/Makefile	2010-07-14 11:21:05.000000000 +0800
+++ iproute2-2.6.31/tc/Makefile	2010-07-02 16:56:41.000000000 +0800
@@ -32,6 +32,7 @@ 
 TCMODULES += m_gact.o
 TCMODULES += m_mirred.o
 TCMODULES += m_nat.o
+TCMODULES += m_cpu.o
 TCMODULES += m_pedit.o
 TCMODULES += m_skbedit.o
 TCMODULES += p_ip.o
diff -urN iproute2-2.6.31.orig/tc/m_cpu.c iproute2-2.6.31/tc/m_cpu.c
--- iproute2-2.6.31.orig/tc/m_cpu.c	1970-01-01 08:00:00.000000000 +0800
+++ iproute2-2.6.31/tc/m_cpu.c	2010-07-12 16:38:56.000000000 +0800
@@ -0,0 +1,186 @@ 
+/*
+ * m_cpu.c	Packet distributing module
+ *
+ *		This program is free software; you can distribute 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.
+ *
+ * Authors:	Changli Gao <xiaosuo@gmail.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include "utils.h"
+#include "tc_util.h"
+#include <linux/tc_act/tc_cpu.h>
+
+static void
+explain(void)
+{
+	fprintf(stderr, "Usage: ... cpu METHOD\n"
+			"METHOD := { CPUID-SPEC | MAP-SPEC | SOCKET-SPEC }\n"
+			"CPUID-SPEC := cpuid CPUID\n"
+			"MAP-SPEC := map OFFSET\n"
+			"SOCKET-SPEC := socket\n");
+}
+
+static void
+usage(void)
+{
+	explain();
+	exit(-1);
+}
+
+static int
+parse_cpu_args(int *argc_p, char ***argv_p,struct tc_cpu *sel)
+{
+	int argc = *argc_p;
+	char **argv = *argv_p;
+
+	if (argc <= 0)
+		return -1;
+
+	if (matches(*argv, "map") == 0)
+		sel->type = TCA_CPU_TYPE_MAP;
+	else if (matches(*argv, "cpuid") == 0)
+		sel->type = TCA_CPU_TYPE_CPUID;
+	else if (matches(*argv, "socket") == 0) {
+		sel->type = TCA_CPU_TYPE_SOCKET;
+		goto out;
+	} else
+		return -1;
+
+	NEXT_ARG();
+
+	if (get_u32(&sel->value, *argv, 10)) {
+		fprintf(stderr, "Cpu: Illegal \"%s\"\n",
+			sel->type == TCA_CPU_TYPE_CPUID ? "CPUID" : "OFFSET");
+		return -1;
+	}
+
+out:
+	argc--;
+	argv++;
+
+	*argc_p = argc;
+	*argv_p = argv;
+	return 0;
+}
+
+static int
+parse_cpu(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
+{
+	struct tc_cpu sel;
+	int argc = *argc_p;
+	char **argv = *argv_p;
+	struct rtattr *tail;
+
+	memset(&sel, 0, sizeof(sel));
+	sel.action = TC_ACT_STOLEN;
+
+	if (argc <= 0) {
+		explain();
+		return -1;
+	}
+
+	if (matches(*argv, "cpu") == 0) {
+		NEXT_ARG();
+	} else {
+		fprintf(stderr, "cpu bad arguments %s\n", *argv);
+		return -1;
+	}
+
+	if (matches(*argv, "help") == 0)
+		usage();
+	if (parse_cpu_args(&argc, &argv, &sel)) {
+		fprintf(stderr, "Illegal cpu construct (%s) \n", *argv);
+		explain();
+		return -1;
+	}
+
+	while (argc > 0) {
+		if (matches(*argv, "drop") == 0 ||
+		    matches(*argv, "shot") == 0) {
+		    	/* I have set it above */
+			argc--;
+			argv++;
+			continue;
+		} else if (matches(*argv, "index") == 0) {
+			NEXT_ARG();
+			if (get_u32(&sel.index, *argv, 10)) {
+				fprintf(stderr, "Cpu: Illegal \"index\"\n");
+				return -1;
+			}
+			argc--;
+			argv++;
+		} else {
+			fprintf(stderr, "Invalid option: %s\n", *argv);
+			usage();
+		}
+	}
+
+	tail = NLMSG_TAIL(n);
+	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
+	addattr_l(n, MAX_MSG, TCA_CPU_PARMS, &sel, sizeof(sel));
+	tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
+
+	*argc_p = argc;
+	*argv_p = argv;
+	return 0;
+}
+
+static int
+print_cpu(struct action_util *au,FILE * f, struct rtattr *arg)
+{
+	struct tc_cpu *sel;
+	struct rtattr *tb[TCA_CPU_MAX + 1];
+	char buf[12];
+	const static char *type_str[] = {
+		[TCA_CPU_TYPE_MAP] = "map",
+		[TCA_CPU_TYPE_CPUID] = "cpuid",
+		[TCA_CPU_TYPE_SOCKET] = "socket"
+	};
+
+	if (arg == NULL)
+		return -1;
+
+	parse_rtattr_nested(tb, TCA_CPU_MAX, arg);
+
+	if (tb[TCA_CPU_PARMS] == NULL) {
+		fprintf(f, "[NULL cpu parameters]");
+		return -1;
+	}
+	sel = RTA_DATA(tb[TCA_CPU_PARMS]);
+
+	if (sel->type != TCA_CPU_TYPE_SOCKET)
+		sprintf(buf, "%u", sel->value);
+	else
+		buf[0] = '\0';
+
+	fprintf(f, " cpu %s%s%s", type_str[sel->type],
+		sel->type == TCA_CPU_TYPE_SOCKET ? "" : " ", buf);
+
+	if (show_stats) {
+		if (tb[TCA_CPU_TM]) {
+			struct tcf_t *tm = RTA_DATA(tb[TCA_CPU_TM]);
+			print_tm(f,tm);
+		}
+	}
+
+	return 0;
+}
+
+struct action_util cpu_action_util = {
+	.id		= "cpu",
+	.parse_aopt	= parse_cpu,
+	.print_aopt	= print_cpu,
+};