netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* instead of eaction
@ 2005-02-06 22:13 jamal
  2005-02-06 23:08 ` Thomas Graf
  0 siblings, 1 reply; 4+ messages in thread
From: jamal @ 2005-02-06 22:13 UTC (permalink / raw)
  To: Thomas Graf; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 299 bytes --]


I think i am going to throw out the idea of eaction; instead
just provide some defaults.
First patch adds some defaults and second a quick simple example.

I have to take off; but maybe i will get time to work on meta action as
well as csum action when i get back.

Comments welcome

cheers,
jamal

[-- Attachment #2: p15 --]
[-- Type: text/plain, Size: 4234 bytes --]

--- /dev/null	2004-01-29 13:33:32.773091056 -0500
+++ 2611-rc3+bk3/include/net/act_generic.h	2005-02-06 15:55:36.000000000 -0500
@@ -0,0 +1,135 @@
+/*
+*/
+static inline int tcf_defact_release(struct tcf_defact *p, int bind)
+{
+	int ret = 0;
+	if (p) {
+		if (bind) {
+			p->bindcnt--;
+		}
+		p->refcnt--;
+		if (p->bindcnt <= 0 && p->refcnt <= 0) {
+			kfree(p->defdata);
+			tcf_hash_destroy(p);
+			ret = 1;
+		}
+	}
+	return ret;
+}
+
+static inline int
+alloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
+{
+	p->defdata = kmalloc(datalen, GFP_KERNEL);
+	if (p->defdata == NULL)
+		return -ENOMEM;
+	p->datalen = datalen;
+	memcpy(p->defdata, defdata, datalen);
+	return 0;
+}
+
+static inline int
+realloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
+{
+	/* safer to be just brute force for now */
+	kfree(p->defdata);
+	return alloc_defdata(p, datalen, defdata);
+}
+
+static inline int
+tcf_defact_init(struct rtattr *rta, struct rtattr *est,
+		struct tc_action *a, int ovr, int bind)
+{
+	struct rtattr *tb[TCA_DEF_MAX];
+	struct tc_defact *parm;
+	struct tcf_defact *p;
+	void *defdata;
+	u32 datalen = 0;
+	int ret = 0;
+
+	if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)
+		return -EINVAL;
+
+	if (tb[TCA_DEF_PARMS - 1] == NULL)
+		return -EINVAL;
+	parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);
+	defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]);
+	if (defdata == NULL)
+		return -EINVAL;
+
+	datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]);
+	if (datalen <= 0)
+		return -EINVAL;
+
+	p = tcf_hash_check(parm->index, a, ovr, bind);
+	if (p == NULL) {
+		p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
+		if (p == NULL)
+			return -ENOMEM;
+
+		ret = alloc_defdata(p, datalen, defdata);
+		if (ret < 0) {
+			kfree(p);
+			return ret;
+		}
+		ret = ACT_P_CREATED;
+	} else {
+		if (!ovr) {
+			tcf_defact_release(p, bind);
+			return -EEXIST;
+		}
+		realloc_defdata(p, datalen, defdata);
+	}
+
+	spin_lock_bh(&p->lock);
+	p->action = parm->action;
+	spin_unlock_bh(&p->lock);
+	if (ret == ACT_P_CREATED)
+		tcf_hash_insert(p);
+	return ret;
+}
+
+static inline int tcf_defact_cleanup(struct tc_action *a, int bind)
+{
+	struct tcf_defact *p = PRIV(a, defact);
+
+	if (p != NULL)
+		return tcf_defact_release(p, bind);
+	return 0;
+}
+
+static inline int
+tcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+	unsigned char *b = skb->tail;
+	struct tc_defact opt;
+	struct tcf_defact *p = PRIV(a, defact);
+	struct tcf_t t;
+
+	opt.index = p->index;
+	opt.refcnt = p->refcnt - ref;
+	opt.bindcnt = p->bindcnt - bind;
+	opt.action = p->action;
+	RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
+	RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata);
+	t.install = jiffies_to_clock_t(jiffies - p->tm.install);
+	t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
+	t.expires = jiffies_to_clock_t(p->tm.expires);
+	RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);
+	return skb->len;
+
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+#define tca_use_default_ops \
+	.dump           =       tcf_defact_dump, \
+	.cleanup        =       tcf_defact_cleanup, \
+	.init           =       tcf_defact_init, \
+	.walk           =       tcf_generic_walker, \
+
+#define tca_use_default_defines(name) \
+	static u32 idx_gen; \
+	static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \
+	static DEFINE_RWLOCK(##name_lock);
--- /dev/null	2004-01-29 13:33:32.773091056 -0500
+++ 2611-rc3+bk3/include/net/tc_act/tc_defact.h	2005-02-06 15:03:05.000000000 -0500
@@ -0,0 +1,13 @@
+#ifndef __NET_TC_DEF_H
+#define __NET_TC_DEF_H
+
+#include <net/act_api.h>
+
+struct tcf_defact
+{
+	tca_gen(defact);
+	u32     datalen;
+	void    *defdata;
+};
+
+#endif
--- /dev/null	2004-01-29 13:33:32.773091056 -0500
+++ 2611-rc3+bk3/include/linux/tc_act/tc_defact.h	2005-02-06 16:47:20.039209336 -0500
@@ -0,0 +1,21 @@
+#ifndef __LINUX_TC_DEF_H
+#define __LINUX_TC_DEF_H
+
+#include <linux/pkt_cls.h>
+
+struct tc_defact
+{
+	tc_gen;
+};
+                                                                                
+enum
+{
+	TCA_DEF_UNSPEC,
+	TCA_DEF_TM,
+	TCA_DEF_PARMS,
+	TCA_DEF_DATA,
+	__TCA_DEF_MAX
+};
+#define TCA_DEF_MAX (__TCA_DEF_MAX - 1)
+
+#endif

[-- Attachment #3: p16 --]
[-- Type: text/plain, Size: 2911 bytes --]

--- /dev/null	2004-01-29 13:33:32.773091056 -0500
+++ 2611-rc3+bk3/net/sched/simple.c	2005-02-06 15:55:57.000000000 -0500
@@ -0,0 +1,107 @@
+/*
+ * net/sched/simp.c	Simple example of an action
+ *
+ *		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.
+ *
+ * Authors:	Jamal Hadi Salim (2005)
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+
+#define TCA_ACT_SIMP 22
+
+/* XXX: Hide all these common elements under some macro 
+ * probably
+*/
+#include <linux/tc_act/tc_defact.h>
+#include <net/tc_act/tc_defact.h>
+
+/* use generic hash table with 8 buckets */
+#define MY_TAB_SIZE     8
+#define MY_TAB_MASK     (MY_TAB_SIZE - 1)
+static u32 idx_gen;
+static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE];
+static DEFINE_RWLOCK(simp_lock);
+
+/* override the defaults */
+#define tcf_st		tcf_defact
+#define tc_st		tc_defact
+#define tcf_t_lock	simp_lock
+#define tcf_ht		tcf_simp_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+#include <net/act_generic.h>
+
+static int tcf_simp(struct sk_buff **pskb, struct tc_action *a)
+{
+	struct sk_buff *skb = *pskb;
+	struct tcf_defact *p = PRIV(a, defact);
+
+	spin_lock(&p->lock);
+	p->tm.lastuse = jiffies;
+	p->bstats.bytes += skb->len;
+	p->bstats.packets++;
+
+	/* print policy string followed by _ then packet count 
+	 * Example if this was the 3rd packet and the string was "hello" 
+	 * then it would look like "hello_3" (without quotes) 
+	 **/
+	printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets);
+	spin_unlock(&p->lock);
+	return p->action;
+}
+
+static struct tc_action_ops act_simp_ops = {
+	.kind = "simple",
+	.type = TCA_ACT_SIMP,
+	.capab = TCA_CAP_NONE,
+	.owner = THIS_MODULE,
+	.act = tcf_simp,
+	tca_use_default_ops
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2005)");
+MODULE_DESCRIPTION("Simple example action");
+MODULE_LICENSE("GPL");
+
+static int __init simp_init_module(void)
+{
+	int ret = tcf_register_action(&act_simp_ops);
+	if (!ret)
+		printk("Simple TC action Loaded\n");
+	return ret;
+}
+
+static void __exit simp_cleanup_module(void)
+{
+	tcf_unregister_action(&act_simp_ops);
+}
+
+module_init(simp_init_module);
+module_exit(simp_cleanup_module);

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

* Re: instead of eaction
  2005-02-06 22:13 instead of eaction jamal
@ 2005-02-06 23:08 ` Thomas Graf
  2005-02-07 13:57   ` jamal
  0 siblings, 1 reply; 4+ messages in thread
From: Thomas Graf @ 2005-02-06 23:08 UTC (permalink / raw)
  To: jamal; +Cc: netdev

* jamal <1107728020.1055.50.camel@jzny.localdomain> 2005-02-06 17:13
> 
> I think i am going to throw out the idea of eaction; instead
> just provide some defaults.
> First patch adds some defaults and second a quick simple example.
> 
> I have to take off; but maybe i will get time to work on meta action as
> well as csum action when i get back.
> 
> Comments welcome
> 
> cheers,
> jamal

> --- /dev/null	2004-01-29 13:33:32.773091056 -0500
> +++ 2611-rc3+bk3/include/net/act_generic.h	2005-02-06 15:55:36.000000000 -0500
> +	if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)
> +		return -EINVAL;
> +
> +	if (tb[TCA_DEF_PARMS - 1] == NULL)
> +		return -EINVAL;

Maybe check for tb[TCA_DEF_DATA - 1] == NULL here as well?

> +	parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);

RTA_PAYLOAD check for TCA_DEF_PARMS?

> --- /dev/null	2004-01-29 13:33:32.773091056 -0500
> +++ 2611-rc3+bk3/net/sched/simple.c	2005-02-06 15:55:57.000000000 -0500
> @@ -0,0 +1,107 @@

> +#include <linux/tc_act/tc_defact.h>
> +#include <net/tc_act/tc_defact.h>
> +
> +/* use generic hash table with 8 buckets */
> +#define MY_TAB_SIZE     8
> +#define MY_TAB_MASK     (MY_TAB_SIZE - 1)
> +static u32 idx_gen;
> +static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE];
> +static DEFINE_RWLOCK(simp_lock);

I guess this is supposed to be tca_use_default_defines
and move MY_TAB_SIZE before the includes?

It looks pretty simple to use and makes up ematches quite well. Any
userspace code alreay written?

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

* Re: instead of eaction
  2005-02-06 23:08 ` Thomas Graf
@ 2005-02-07 13:57   ` jamal
  2005-02-07 14:18     ` jamal
  0 siblings, 1 reply; 4+ messages in thread
From: jamal @ 2005-02-07 13:57 UTC (permalink / raw)
  To: Thomas Graf; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 1600 bytes --]

On Sun, 2005-02-06 at 18:08, Thomas Graf wrote:

> 
> > --- /dev/null	2004-01-29 13:33:32.773091056 -0500
> > +++ 2611-rc3+bk3/include/net/act_generic.h	2005-02-06 15:55:36.000000000 -0500
> > +	if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)
> > +		return -EINVAL;
> > +
> > +	if (tb[TCA_DEF_PARMS - 1] == NULL)
> > +		return -EINVAL;
> 
> Maybe check for tb[TCA_DEF_DATA - 1] == NULL here as well?
> 

Good point; i will check for all

> > +	parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);
> 
> RTA_PAYLOAD check for TCA_DEF_PARMS?
> 

sure

> > --- /dev/null	2004-01-29 13:33:32.773091056 -0500
> > +++ 2611-rc3+bk3/net/sched/simple.c	2005-02-06 15:55:57.000000000 -0500
> > @@ -0,0 +1,107 @@
> 
> > +#include <linux/tc_act/tc_defact.h>
> > +#include <net/tc_act/tc_defact.h>
> > +
> > +/* use generic hash table with 8 buckets */
> > +#define MY_TAB_SIZE     8
> > +#define MY_TAB_MASK     (MY_TAB_SIZE - 1)
> > +static u32 idx_gen;
> > +static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE];
> > +static DEFINE_RWLOCK(simp_lock);
> 
> I guess this is supposed to be tca_use_default_defines
> and move MY_TAB_SIZE before the includes?

This is a tricky one; maybe i am playing too many macro tricks ;->
Theres some dependencies - need to think a little

> It looks pretty simple to use and makes up ematches quite well. Any
> userspace code alreay written?

User space could be simplified as well; attached is what i used to test
simple action. Theres a _lot_ of common code there as well.

I am also bgining to work on the checksum action; i will then do the
meta action. 

cheers,
jamal

[-- Attachment #2: m_simple.c --]
[-- Type: text/x-c, Size: 2852 bytes --]

/*
 * m_defact.c		simple example action 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:  J Hadi Salim (hadi@cyberus.ca) 
 * 
 */

#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_defact.h>

static void
explain(void)
{
	fprintf(stderr, "Usage: ... simp <ACT_STRING> index [INDEX]\n");
	fprintf(stderr,
		"Where: ACT_STRING := a simple string (not exceeding 16 chars"
		"INDEX := index value used\n");
}

#define usage() return(-1)

#ifndef ANAMSIZ
#define ANAMSIZ 16
#endif

int
parse_simple(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
{
	int argc = *argc_p;
	char **argv = *argv_p;
	struct tc_defact *p;
	char  k[ANAMSIZ];
	struct rtattr *tail;

	if (argc < 2)
		return -1;

	p = malloc(sizeof(*p));
	memset(p, 0, sizeof(*p));
	memset (&k,0,ANAMSIZ);

	NEXT_ARG();
	strncpy(k, *argv, sizeof(k)-1);
	argc--; argv++;
	if (argc && matches(*argv, "index") == 0) {
		NEXT_ARG();
		if (get_u32(&p->index, *argv, 10)) {
			fprintf(stderr, "Illegal \"index\"\n");
			return -1;
		}
		argc--;
		argv++;
	}
		

	p->action = TC_ACT_PIPE;

	tail = (struct rtattr *) (((void *) n) + NLMSG_ALIGN(n->nlmsg_len));
	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
	addattr_l(n, MAX_MSG, TCA_DEF_PARMS, p, sizeof(*p));
	addattr_l(n, MAX_MSG, TCA_DEF_DATA, k, strlen(k)+1);
	tail->rta_len =
	    (((void *) n) + NLMSG_ALIGN(n->nlmsg_len)) - (void *) tail;

	*argc_p = argc;
	*argv_p = argv;
	return 0;
}

int
print_simple(struct action_util *au,FILE * f, struct rtattr *arg)
{
	SPRINT_BUF(b1);
	struct tc_defact *p = NULL;
	struct rtattr *tb[TCA_DEF_MAX + 1];
	char *str;

	if (arg == NULL)
		return -1;

	memset(tb, 0, sizeof (tb));
	parse_rtattr(tb, TCA_DEF_MAX, RTA_DATA(arg), RTA_PAYLOAD(arg));

	if (tb[TCA_DEF_PARMS] == NULL) {
		fprintf(f, "[NULL simple parameters]");
		return -1;
	}
	p = RTA_DATA(tb[TCA_DEF_PARMS]);

	fprintf(f, "simple action %s", action_n2a(p->action, b1, sizeof (b1)));
	fprintf(f, "\n\t index %d ref %d bind %d",p->index, p->refcnt, p->bindcnt);
	if (show_stats) {
		if (tb[TCA_DEF_TM]) {
			struct tcf_t *tm = RTA_DATA(tb[TCA_DEF_TM]);
			print_tm(f,tm);
		}
	}
	str = RTA_DATA(tb[TCA_DEF_DATA]);

	if (!strlen(str)) {
		 fprintf(f, "\n\t EMPTY string!!!\n");
	} else {
		 fprintf(f, "\n\t DATA: <%s>\n",str);
	}

	fprintf(f, "\n ");
	return 0;
}

struct action_util simple_action_util = {
	.id = "simple",
	.parse_aopt = parse_simple,
	.print_aopt = print_simple,
};

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

* Re: instead of eaction
  2005-02-07 13:57   ` jamal
@ 2005-02-07 14:18     ` jamal
  0 siblings, 0 replies; 4+ messages in thread
From: jamal @ 2005-02-07 14:18 UTC (permalink / raw)
  To: Thomas Graf; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 569 bytes --]


I havent finished this and wont touch it for a few days, but should give
you a general view of the csum action. It is slightly more complex
in that it needs to at least check for the data passed from user space
to avoid doing it in the fast/data path and and so overwrittes the
default ->init().
Only thing ive done so far is to compile this. Still a lot of
validation, cleanup and meat to be added. Theres a lot that could be 
done such as incremental checksums, for now this is simple and should
work albeit a little perfomance squeak here and there.

cheers,
jamal

[-- Attachment #2: p1 --]
[-- Type: text/plain, Size: 6223 bytes --]

--- /dev/null	2005-01-29 13:33:32.773091056 -0500
+++ 2611-rc3+bk3/include/net/tc_act/tc_csuma.h	2005-02-07 08:39:52.594700248 -0500
@@ -0,0 +1,28 @@
+#ifndef __NET_TCA_CSUMA_H
+#define __NET_TCA_CSUMA_H
+
+#include <net/act_api.h>
+#include <net/checksum.h>
+
+struct tcf_csum {
+	u16 ctype;
+	u16 atype;
+	u32 vldact;
+	u32 invact;
+};
+
+enum
+{
+	CSUMA_INVALID = -1,
+	CSUMA_IPVLD,
+	CSUMA_IPSET,
+	CSUMA_TCPVLD,
+	CSUMA_TCPSET,
+	CSUMA_UDPVLD,
+	CSUMA_UDPSET,
+	__CSUMA_MAX
+};
+#define CSUMA_MAX (__CSUMA_MAX - 1)
+
+
+#endif
--- /dev/null	2005-01-29 13:33:32.773091056 -0500
+++ 2611-rc3+bk3/net/sched/csumact.c	2005-02-07 08:37:33.000000000 -0500
@@ -0,0 +1,208 @@
+/*
+ * net/sched/csumact.c	Checksum validate+recompute action
+ *
+ *		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.
+ *
+ * Authors:	Jamal Hadi Salim (2005)
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/checksum.h>
+
+#define TCA_ACT_CSUMA 23
+
+#define MY_TAB_SIZE     8
+#define MY_TAB_MASK     (MY_TAB_SIZE - 1)
+#include <linux/tc_act/tc_defact.h>
+#include <net/tc_act/tc_defact.h>
+#include <net/tc_act/tc_csuma.h>
+
+static u32 idx_gen;
+static struct tcf_defact *tcf_csuma_ht[MY_TAB_SIZE]; 
+static DEFINE_RWLOCK(csuma_lock);
+
+/* override the defaults */
+#define tcf_st		tcf_defact
+#define tc_st		tc_defact
+#define tcf_t_lock	csuma_lock
+#define tcf_ht		tcf_csuma_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+#include <net/act_generic.h>
+
+/* the diffferent csum computers and validators */
+/* 
+ * XXXX: There is a lot of optimizations that could be
+ * done here. each valid and set could share code and 
+ * all the tcp/udp really should be sharing the same code
+ * base
+*/
+static int ipvalid(struct tcf_csum *p, struct sk_buff *skb)
+{
+	struct iphdr *iph = skb->nh.iph;
+	if (ip_fast_csum((unsigned char *)iph, iph->ihl))
+			return p->invact;
+	return p->vldact;
+}
+
+/* XXXX: the usual rules for trampling on pkts must be followed */
+static int ipset(struct tcf_csum *p, struct sk_buff *skb)
+{
+	struct iphdr *iph = skb->nh.iph;
+	iph->check = 0;
+	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+	return p->vldact;
+}
+
+static int tcpvalid(struct tcf_csum *p, struct sk_buff *skb)
+{
+	struct iphdr *iph = skb->nh.iph;
+	unsigned int tcphoff = skb->nh.iph->ihl * 4;
+	unsigned int tcplen = skb->len - tcphoff;
+
+	skb->csum = skb_checksum(skb, tcphoff, tcplen, 0);
+
+	if (csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP, skb->csum))
+		return p->invact;
+
+	return p->vldact;
+}
+
+/* XXXX: the usual rules for trampling on pkts must be followed */
+static int tcpset(struct tcf_csum *p, struct sk_buff *skb)
+{
+	struct tcphdr *tcph = skb->h.th;
+	struct iphdr *iph = skb->nh.iph;
+	unsigned int tcphoff = skb->nh.iph->ihl * 4;
+	unsigned int tcplen = skb->len - tcphoff;
+
+	tcph->check = 0;
+	skb->csum = skb_checksum(skb, tcphoff, tcplen, 0);
+
+	tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
+			tcplen, IPPROTO_TCP, skb->csum);
+
+	return p->vldact;
+}
+
+static int udpvalid(struct tcf_csum *p, struct sk_buff *skb)
+{
+	struct iphdr *iph = skb->nh.iph;
+	unsigned int udphoff = skb->nh.iph->ihl * 4;
+	unsigned int udplen = skb->len - udphoff;
+
+	skb->csum = skb_checksum(skb, udphoff, udplen, 0);
+
+	if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP, skb->csum))
+		return p->invact;
+
+	return p->vldact;
+}
+
+/* XXXX: the usual rules for trampling on pkts must be followed */
+static int udpset(struct tcf_csum *p, struct sk_buff *skb)
+{
+	struct udphdr *udph = skb->h.uh;
+	struct iphdr *iph = skb->nh.iph;
+	unsigned int udphoff = skb->nh.iph->ihl * 4;
+	unsigned int udplen = skb->len - udphoff;
+
+	udph->check = 0;
+	skb->csum = skb_checksum(skb, udphoff, udplen, 0);
+
+	udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
+			udplen, IPPROTO_UDP, skb->csum);
+
+	return p->vldact;
+}
+
+typedef int (*f_csum)(struct tcf_csum *p, struct sk_buff *skb);
+static f_csum csumfuncs[CSUMA_MAX + 1] = {ipvalid,ipset,tcpvalid,tcpset,udpvalid,udpset };
+
+static int tcf_csuma(struct sk_buff **pskb, struct tc_action *a)
+{
+	int ret;
+	struct sk_buff *skb = *pskb;
+	struct tcf_defact *p = PRIV(a, defact);
+	struct tcf_csum *c = p->defdata;
+
+	spin_lock(&p->lock);
+	p->tm.lastuse = jiffies;
+	p->bstats.bytes += skb->len;
+	p->bstats.packets++;
+	ret = csumfuncs[c->ctype](c, skb);
+	spin_unlock(&p->lock);
+	return ret;
+}
+
+static inline int
+tcf_csuma_init(struct rtattr *rta, struct rtattr *est,
+	       struct tc_action *a, int ovr, int bind)
+{
+	/* cutnpaste tcf_defact_init and check that
+	 * the ctype passed is valid */
+	       return 0;
+}
+
+static struct tc_action_ops act_csuma_ops = {
+	.kind = "csumact",
+	.type = TCA_ACT_CSUMA,
+	.capab = TCA_CAP_NONE,
+	.owner = THIS_MODULE,
+	.act = tcf_csuma,
+	tca_use_default_ops
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2005)");
+MODULE_DESCRIPTION("checksum action");
+MODULE_LICENSE("GPL");
+
+static int __init csuma_init_module(void)
+{
+	int ret = tcf_register_action(&act_csuma_ops);
+	if (!ret) {
+		printk("Simple TC action Loaded\n");
+		/* overwrite the init */
+		act_csuma_ops.init = tcf_csuma_init;
+	}
+	return ret;
+}
+
+static void __exit csuma_cleanup_module(void)
+{
+	tcf_unregister_action(&act_csuma_ops);
+}
+
+module_init(csuma_init_module);
+module_exit(csuma_cleanup_module);

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

end of thread, other threads:[~2005-02-07 14:18 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-02-06 22:13 instead of eaction jamal
2005-02-06 23:08 ` Thomas Graf
2005-02-07 13:57   ` jamal
2005-02-07 14:18     ` jamal

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).