All of lore.kernel.org
 help / color / mirror / Atom feed
From: jamal <hadi@cyberus.ca>
To: "David S. Miller" <davem@davemloft.net>
Cc: netdev@oss.sgi.com
Subject: patch: Mirred action
Date: 11 Oct 2004 08:49:32 -0400	[thread overview]
Message-ID: <1097498972.15075.7.camel@jzny.localdomain> (raw)

[-- 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);
+

             reply	other threads:[~2004-10-11 12:49 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-10-11 12:49 jamal [this message]
2004-10-20  5:02 ` patch: Mirred action David S. Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1097498972.15075.7.camel@jzny.localdomain \
    --to=hadi@cyberus.ca \
    --cc=davem@davemloft.net \
    --cc=netdev@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.