All of lore.kernel.org
 help / color / mirror / Atom feed
* patch: Mirred action
@ 2004-10-11 12:49 jamal
  2004-10-20  5:02 ` David S. Miller
  0 siblings, 1 reply; 2+ messages in thread
From: jamal @ 2004-10-11 12:49 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev

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

Dave,
I am gonna start trickling these actions/driver patches to you.

signed off by me

cheers,
jamal

[-- Attachment #2: 269-rc3-mirred_kp --]
[-- Type: text/plain, Size: 9756 bytes --]

--- /dev/null	1998-05-05 16:32:27.000000000 -0400
+++ b/include/net/tc_act/tc_mirred.h	2004-10-01 09:18:32.000000000 -0400
@@ -0,0 +1,15 @@
+#ifndef __NET_TC_MIR_H
+#define __NET_TC_MIR_H
+
+#include <net/pkt_sched.h>
+
+struct tcf_mirred
+{
+	tca_gen(mirred);
+	int eaction;
+	int ifindex;
+	int ok_push;
+	struct net_device *dev;
+};
+
+#endif
--- /dev/null	1998-05-05 16:32:27.000000000 -0400
+++ b/include/linux/tc_act/tc_mirred.h	2004-10-01 09:18:32.000000000 -0400
@@ -0,0 +1,28 @@
+#ifndef __LINUX_TC_MIR_H
+#define __LINUX_TC_MIR_H
+
+#include <linux/pkt_cls.h>
+
+#define TCA_ACT_MIRRED 8
+#define TCA_EGRESS_REDIR 1  /* packet redirect to EGRESS*/
+#define TCA_EGRESS_MIRROR 2 /* mirror packet to EGRESS */
+#define TCA_INGRESS_REDIR 3  /* packet redirect to INGRESS*/
+#define TCA_INGRESS_MIRROR 4 /* mirror packet to INGRESS */
+                                                                                
+struct tc_mirred
+{
+	tc_gen;
+	int                     eaction;   /* one of IN/EGRESS_MIRROR/REDIR */
+	__u32                   ifindex;  /* ifindex of egress port */
+};
+                                                                                
+enum
+{
+	TCA_MIRRED_UNSPEC,
+	TCA_MIRRED_TM,
+	TCA_MIRRED_PARMS,
+	__TCA_MIRRED_MAX
+};
+#define TCA_MIRRED_MAX (__TCA_MIRRED_MAX - 1)
+                                                                                
+#endif
--- a/net/sched/Makefile	2004/10/01 13:16:40	1.1
+++ b/net/sched/Makefile	2004/10/01 13:17:34
@@ -11,6 +11,7 @@
 obj-$(CONFIG_NET_ACT_POLICE)	+= police.o
 obj-$(CONFIG_NET_CLS_POLICE)	+= police.o
 obj-$(CONFIG_NET_ACT_GACT)      += gact.o
+obj-$(CONFIG_NET_ACT_MIRRED)    += mirred.o
 obj-$(CONFIG_NET_SCH_CBQ)	+= sch_cbq.o
 obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
 obj-$(CONFIG_NET_SCH_HPFQ)	+= sch_hpfq.o
--- a/net/sched/Kconfig	2004/10/01 13:13:33	1.1
+++ b/net/sched/Kconfig	2004/10/01 13:16:34
@@ -399,3 +399,10 @@
         depends on NET_ACT_GACT
         ---help---
         Allows generic actions to be randomly  or deterministically used
+
+config NET_ACT_MIRRED
+        tristate "Packet In/Egress redirecton/mirror Actions"
+        depends on NET_CLS_ACT
+        ---help---
+        requires new iproute2
+        This allows packets to be mirrored or redirected to netdevices
--- /dev/null	1998-05-05 16:32:27.000000000 -0400
+++ b/net/sched/mirred.c	2004-10-11 08:34:34.000000000 -0400
@@ -0,0 +1,318 @@
+/*
+ * net/sched/mirred.c	packet mirroring and redirect actions
+ *
+ *		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 (2002-4)
+ *
+ * TODO: Add ingress support (and socket redirect support)
+ *
+ */
+
+#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 <linux/tc_act/tc_mirred.h>
+#include <net/tc_act/tc_mirred.h>
+
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
+
+/* use generic hash table */
+#define MY_TAB_SIZE     8
+#define MY_TAB_MASK     (MY_TAB_SIZE - 1)
+static u32 idx_gen;
+static struct tcf_mirred *tcf_mirred_ht[MY_TAB_SIZE];
+static rwlock_t mirred_lock = RW_LOCK_UNLOCKED;
+
+/* ovewrride the defaults */
+#define tcf_st  tcf_mirred
+#define tc_st  tc_mirred
+#define tcf_t_lock   mirred_lock
+#define tcf_ht tcf_mirred_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+
+static inline int
+tcf_mirred_release(struct tcf_mirred *p, int bind)
+{
+	if (p) {
+		if (bind) {
+			p->bindcnt--;
+		}
+
+		p->refcnt--;
+		if(!p->bindcnt && p->refcnt <= 0) {
+			dev_put(p->dev);
+			tcf_hash_destroy(p);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int
+tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,int ovr, int bind)
+{
+	struct rtattr *tb[TCA_MIRRED_MAX];
+	struct tc_mirred *parm;
+	struct tcf_mirred *p;
+	struct net_device *dev = NULL;
+	int size = sizeof (*p), new = 0;
+
+
+	if (rtattr_parse(tb, TCA_MIRRED_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0) {
+		DPRINTK("tcf_mirred_init BUG in user space couldnt parse properly\n");
+		return -1;
+	}
+
+	if (NULL == a || NULL == tb[TCA_MIRRED_PARMS - 1]) {
+		DPRINTK("BUG: tcf_mirred_init called with NULL params\n");
+		return -1;
+	}
+
+	parm = RTA_DATA(tb[TCA_MIRRED_PARMS - 1]);
+
+	p = tcf_hash_check(parm, a, ovr, bind);
+	if (NULL == p) { /* new */
+		p = tcf_hash_create(parm,est,a,size,ovr,bind);
+		new = 1;
+		if (NULL == p)
+			return -1;
+	}
+
+	if (parm->ifindex) {
+		dev = dev_get_by_index(parm->ifindex);
+		if (NULL == dev) {
+			printk("BUG: tcf_mirred_init called with bad device\n");
+			return -1;
+		}
+		switch (dev->type) {
+			case ARPHRD_TUNNEL:
+			case ARPHRD_TUNNEL6:
+			case ARPHRD_SIT:
+			case ARPHRD_IPGRE:
+			case ARPHRD_VOID:
+			case ARPHRD_NONE:
+				p->ok_push = 0;
+				break;
+			default:
+				p->ok_push = 1;
+				break;
+		}
+	} else {
+		if (new) {
+			kfree(p);
+			return -1;
+		}	
+	}
+
+	if (new || ovr) {
+		spin_lock(&p->lock);
+		p->action = parm->action;
+		p->eaction = parm->eaction;
+		if (parm->ifindex) {
+			p->ifindex = parm->ifindex;
+			p->dev = dev;
+			dev_hold(p->dev); 
+		}
+		spin_unlock(&p->lock);
+	}
+
+
+	DPRINTK(" tcf_mirred_init index %d action %d eaction %d device %s ifndex %d\n",parm->index,parm->action,parm->eaction,dev->name,parm->ifindex);
+	return new;
+
+}
+
+int
+tcf_mirred_cleanup(struct tc_action *a, int bind)
+{
+	struct tcf_mirred *p;
+	p = PRIV(a,mirred);
+	if (NULL != p)
+		return tcf_mirred_release(p, bind);
+	return 0;
+}
+
+int
+tcf_mirred(struct sk_buff **pskb, struct tc_action *a)
+{
+	struct tcf_mirred *p;
+	struct net_device *dev;
+	struct sk_buff *skb2 = NULL;
+	struct sk_buff *skb = *pskb;
+	__u32 at = G_TC_AT(skb->tc_verd);
+
+	if (NULL == a) {
+		if (net_ratelimit())
+			printk("BUG: tcf_mirred called with NULL action!\n");
+		return -1;
+	}
+
+	p = PRIV(a,mirred);
+
+	if (NULL == p) {
+		if (net_ratelimit())
+			printk("BUG: tcf_mirred called with NULL params\n");
+		return -1;
+	}
+
+	spin_lock(&p->lock);
+
+       	dev = p->dev;
+	p->tm.lastuse = jiffies;
+
+	if (NULL == dev || !(dev->flags&IFF_UP) ) {
+		if (net_ratelimit())
+			printk("mirred to Houston: device %s is gone!\n",
+					dev?dev->name:"");
+bad_mirred:
+		if (NULL != skb2)
+			kfree_skb(skb2);
+		p->stats.overlimits++;
+		p->stats.bytes += skb->len;
+		p->stats.packets++;
+		spin_unlock(&p->lock);
+		/* should we be asking for packet to be dropped?
+		 * may make sense for redirect case only 
+		*/
+		return TC_ACT_SHOT;
+	} 
+
+	skb2 = skb_clone(skb, GFP_ATOMIC);
+	if (skb2 == NULL) {
+		goto bad_mirred;
+	}
+	if (TCA_EGRESS_MIRROR != p->eaction &&
+		TCA_EGRESS_REDIR != p->eaction) {
+		if (net_ratelimit())
+			printk("tcf_mirred unknown action %d\n",p->eaction);
+		goto bad_mirred;
+	}
+
+	p->stats.bytes += skb2->len;
+	p->stats.packets++;
+	if ( !(at & AT_EGRESS)) {
+		if (p->ok_push) {
+			skb_push(skb2, skb2->dev->hard_header_len);
+		}
+	}
+
+	/* mirror is always swallowed */
+	if (TCA_EGRESS_MIRROR != p->eaction)
+		skb2->tc_verd = SET_TC_FROM(skb2->tc_verd,at);
+
+	skb2->dev = dev;
+	skb2->input_dev = skb->dev;
+	dev_queue_xmit(skb2);
+	spin_unlock(&p->lock);
+	return p->action;
+}
+
+int
+tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
+{
+	unsigned char *b = skb->tail;
+	struct tc_mirred opt;
+	struct tcf_mirred *p;
+	struct tcf_t t;
+
+	p = PRIV(a,mirred);
+	if (NULL == p) {
+		printk("BUG: tcf_mirred_dump called with NULL params\n");
+		goto rtattr_failure;
+	}
+
+	opt.index = p->index;
+	opt.action = p->action;
+	opt.refcnt = p->refcnt - ref;
+	opt.bindcnt = p->bindcnt - bind;
+	opt.eaction = p->eaction;
+	opt.ifindex = p->ifindex;
+	DPRINTK(" tcf_mirred_dump index %d action %d eaction %d ifndex %d\n",p->index,p->action,p->eaction,p->ifindex);
+	RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof (opt), &opt);
+	t.install = jiffies - p->tm.install;
+	t.lastuse = jiffies - p->tm.lastuse;
+	t.expires = p->tm.expires;
+	RTA_PUT(skb, TCA_MIRRED_TM, sizeof (t), &t);
+	return skb->len;
+
+      rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+int
+tcf_mirred_stats(struct sk_buff *skb, struct tc_action *a)
+{
+	struct tcf_mirred *p;
+	p = PRIV(a,mirred);
+
+	if (NULL != p)
+		return qdisc_copy_stats(skb, &p->stats, p->stats_lock);
+
+	return 1;
+}
+
+static struct tc_action_ops act_mirred_ops = {
+	.next		=	NULL,
+	.kind		=	"mirred",
+	.type		=	TCA_ACT_MIRRED,
+	.capab		=	TCA_CAP_NONE,
+	.owner		=	THIS_MODULE,
+	.act		=	tcf_mirred,
+	.get_stats	=	tcf_mirred_stats,
+	.dump		=	tcf_mirred_dump,
+	.cleanup	=	tcf_mirred_cleanup,
+	.lookup		=	tcf_hash_search,
+	.init		=	tcf_mirred_init,
+	.walk		=	tcf_generic_walker
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2002)");
+MODULE_DESCRIPTION("Device Mirror/redirect actions");
+MODULE_LICENSE("GPL");
+
+
+static int __init
+mirred_init_module(void)
+{
+	printk("Mirror/redirect action on\n");
+	return tcf_register_action(&act_mirred_ops);
+}
+
+static void __exit
+mirred_cleanup_module(void)
+{
+	tcf_unregister_action(&act_mirred_ops);
+}
+
+module_init(mirred_init_module);
+module_exit(mirred_cleanup_module);
+

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

* Re: patch: Mirred action
  2004-10-11 12:49 patch: Mirred action jamal
@ 2004-10-20  5:02 ` David S. Miller
  0 siblings, 0 replies; 2+ messages in thread
From: David S. Miller @ 2004-10-20  5:02 UTC (permalink / raw)
  To: hadi; +Cc: netdev

On 11 Oct 2004 08:49:32 -0400
jamal <hadi@cyberus.ca> wrote:

> I am gonna start trickling these actions/driver patches to you.
> 
> signed off by me

Applied, thanks Jamal.

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

end of thread, other threads:[~2004-10-20  5:02 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-10-11 12:49 patch: Mirred action jamal
2004-10-20  5:02 ` David S. Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.