SOURCES (LINUX_2_6_14): linux-2.6-dummy-as-imq-replacement.patch -...

arekm arekm at pld-linux.org
Wed Jan 11 09:09:19 CET 2006


Author: arekm                        Date: Wed Jan 11 08:09:19 2006 GMT
Module: SOURCES                       Tag: LINUX_2_6_14
---- Log message:
- use IFB device since it went upstream instead of overloading dummy

---- Files affected:
SOURCES:
   linux-2.6-dummy-as-imq-replacement.patch (1.1.2.1 -> 1.1.2.1.2.1) 

---- Diffs:

================================================================
Index: SOURCES/linux-2.6-dummy-as-imq-replacement.patch
diff -u SOURCES/linux-2.6-dummy-as-imq-replacement.patch:1.1.2.1 SOURCES/linux-2.6-dummy-as-imq-replacement.patch:1.1.2.1.2.1
--- SOURCES/linux-2.6-dummy-as-imq-replacement.patch:1.1.2.1	Mon Dec  5 14:16:10 2005
+++ SOURCES/linux-2.6-dummy-as-imq-replacement.patch	Wed Jan 11 09:09:14 2006
@@ -1,194 +1,238 @@
---- a/drivers/net/dummy.c.orig	2004-12-24 16:34:33.000000000 -0500
-+++ b/drivers/net/dummy.c	2005-01-18 06:43:47.000000000 -0500
-@@ -26,7 +26,14 @@
- 			Nick Holloway, 27th May 1994
- 	[I tweaked this explanation a little but that's all]
- 			Alan Cox, 30th May 1994
-+
- */
-+/*
-+	* This driver isnt abused enough ;->
-+	* Here to add only just a feeew more features,
-+	* 10 years after AC added comment above ;-> hehe - JHS
+From: Jamal Hadi Salim <hadi at cyberus.ca>
+Date: Mon, 9 Jan 2006 06:34:25 +0000 (-0800)
+Subject: [NET]: Add IFB (Intermediate Functional Block) network device.
+X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=253af4235d24ddfcd9f5403485e9273b33d8fa5e
+
+[NET]: Add IFB (Intermediate Functional Block) network device.
+
+A new device to do intermidiate functional block in a system shared
+manner.  To use the new functionality, you need to turn on
+qos/classifier actions.
+
+The new functionality can be grouped as:
+
+1) qdiscs/policies that are per device as opposed to system wide.  ifb
+allows for a device which can be redirected to thus providing an
+impression of sharing.
+
+2) Allows for queueing incoming traffic for shaping instead of
+dropping.
+
+Packets are redirected to this device using tc/action mirred redirect
+construct. If they are sent to it by plain routing instead then they
+will merely be dropped and the stats would indicate that.
+
+Signed-off-by: Jamal Hadi Salim <hadi at cyberus.ca>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -27,6 +27,19 @@ config NETDEVICES
+ # that for each of the symbols.
+ if NETDEVICES
+ 
++config IFB
++	tristate "Intermediate Functional Block support"
++	depends on NET_CLS_ACT
++	---help---
++	  This is an intermidiate driver that allows sharing of
++	  resources.
++	  To compile this driver as a module, choose M here: the module
++	  will be called ifb.  If you want to use more than one ifb
++	  device at a time, you need to compile this driver as a module.
++	  Instead of 'ifb', the devices will then be called 'ifb0',
++	  'ifb1' etc.
++	  Look at the iproute2 documentation directory for usage etc
++
+ config DUMMY
+ 	tristate "Dummy net driver support"
+ 	---help---
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -125,6 +125,7 @@ ifeq ($(CONFIG_SLIP_COMPRESSED),y)
+ endif
+ 
+ obj-$(CONFIG_DUMMY) += dummy.o
++obj-$(CONFIG_IFB) += ifb.o
+ obj-$(CONFIG_DE600) += de600.o
+ obj-$(CONFIG_DE620) += de620.o
+ obj-$(CONFIG_LANCE) += lance.o
+--- /dev/null
++++ b/drivers/net/ifb.c
+@@ -0,0 +1,294 @@
++/* drivers/net/ifb.c: 
++
++	The purpose of this driver is to provide a device that allows
++	for sharing of resources:
++
++	1) qdiscs/policies that are per device as opposed to system wide.
++	ifb allows for a device which can be redirected to thus providing
++	an impression of sharing.
++
++	2) Allows for queueing incoming traffic for shaping instead of
++	dropping. 
++	
++	The original concept is based on what is known as the IMQ
++	driver initially written by Martin Devera, later rewritten
++	by Patrick McHardy and then maintained by Andre Correa.
++
++	You need the tc action  mirror or redirect to feed this device
++       	packets.
++
++	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 <linux/config.h>
- #include <linux/module.h>
-@@ -35,11 +42,128 @@
- #include <linux/etherdevice.h>
- #include <linux/init.h>
- #include <linux/moduleparam.h>
-+#ifdef CONFIG_NET_CLS_ACT
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/init.h>
++#include <linux/moduleparam.h>
 +#include <net/pkt_sched.h> 
-+#endif
 +
 +#define TX_TIMEOUT  (2*HZ)
 +                                                                                
 +#define TX_Q_LIMIT    32
-+struct dummy_private {
++struct ifb_private {
 +	struct net_device_stats stats;
-+#ifdef CONFIG_NET_CLS_ACT
-+	struct tasklet_struct   dummy_tasklet;
++	struct tasklet_struct   ifb_tasklet;
 +	int     tasklet_pending;
 +	/* mostly debug stats leave in for now */
-+	unsigned long   stat_r1;
-+	unsigned long   stat_r2;
-+	unsigned long   stat_r3;
-+	unsigned long   stat_r4;
-+	unsigned long   stat_r5;
-+	unsigned long   stat_r6;
-+	unsigned long   stat_r7;
-+	unsigned long   stat_r8;
++	unsigned long   st_task_enter; /* tasklet entered */
++	unsigned long   st_txq_refl_try; /* transmit queue refill attempt */
++	unsigned long   st_rxq_enter; /* receive queue entered */
++	unsigned long   st_rx2tx_tran; /* receive to trasmit transfers */
++	unsigned long   st_rxq_notenter; /*receiveQ not entered, resched */
++	unsigned long   st_rx_frm_egr; /* received from egress path */
++	unsigned long   st_rx_frm_ing; /* received from ingress path */
++	unsigned long   st_rxq_check;
++	unsigned long   st_rxq_rsch;
 +	struct sk_buff_head     rq;
 +	struct sk_buff_head     tq;
-+#endif
 +};
 +
-+#ifdef CONFIG_NET_CLS_ACT
-+static void ri_tasklet(unsigned long dev);
-+#endif
++static int numifbs = 1;
 +
- 
- static int numdummies = 1;
- 
- static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
- static struct net_device_stats *dummy_get_stats(struct net_device *dev);
-+static void dummy_timeout(struct net_device *dev);
-+static int dummy_open(struct net_device *dev);
-+static int dummy_close(struct net_device *dev);
-+
-+static void dummy_timeout(struct net_device *dev) {
-+
-+	int cpu = smp_processor_id();
-+
-+	dev->trans_start = jiffies;
-+	printk("%s: BUG tx timeout on CPU %d\n",dev->name,cpu);
-+	if (spin_is_locked((&dev->xmit_lock)))
-+		printk("xmit lock grabbed already\n");
-+	if (spin_is_locked((&dev->queue_lock)))
-+		printk("queue lock grabbed already\n");
-+}
++static void ri_tasklet(unsigned long dev);
++static int ifb_xmit(struct sk_buff *skb, struct net_device *dev);
++static struct net_device_stats *ifb_get_stats(struct net_device *dev);
++static int ifb_open(struct net_device *dev);
++static int ifb_close(struct net_device *dev);
 +
-+#ifdef CONFIG_NET_CLS_ACT
-+static void ri_tasklet(unsigned long dev) {
++static void ri_tasklet(unsigned long dev) 
++{
 +
-+	struct net_device *dv = (struct net_device *)dev;
-+	struct dummy_private *dp = ((struct net_device *)dev)->priv;
++	struct net_device *_dev = (struct net_device *)dev;
++	struct ifb_private *dp = netdev_priv(_dev);
 +	struct net_device_stats *stats = &dp->stats;
-+	struct sk_buff *skb = NULL;
++	struct sk_buff *skb;
 +
-+	dp->stat_r4 +=1;
-+	if (NULL == (skb = skb_peek(&dp->tq))) {
-+		dp->stat_r5 +=1;
-+		if (spin_trylock(&dv->xmit_lock)) {
-+			dp->stat_r8 +=1;
-+			while (NULL != (skb = skb_dequeue(&dp->rq))) {
++	dp->st_task_enter++;
++	if ((skb = skb_peek(&dp->tq)) == NULL) {
++		dp->st_txq_refl_try++;
++		if (spin_trylock(&_dev->xmit_lock)) {
++			dp->st_rxq_enter++;
++			while ((skb = skb_dequeue(&dp->rq)) != NULL) {
 +				skb_queue_tail(&dp->tq, skb);
++				dp->st_rx2tx_tran++;
 +			}
-+			spin_unlock(&dv->xmit_lock);
++			spin_unlock(&_dev->xmit_lock);
 +		} else {
-+	/* reschedule */
-+			dp->stat_r1 +=1;
++			/* reschedule */
++			dp->st_rxq_notenter++;
 +			goto resched;
 +		}
 +	}
 +
-+	while (NULL != (skb = skb_dequeue(&dp->tq))) {
-+		__u32 from = G_TC_FROM(skb->tc_verd);
++	while ((skb = skb_dequeue(&dp->tq)) != NULL) {
++		u32 from = G_TC_FROM(skb->tc_verd);
 +
 +		skb->tc_verd = 0;
 +		skb->tc_verd = SET_TC_NCLS(skb->tc_verd);
 +		stats->tx_packets++;
-+		stats->tx_bytes+=skb->len;
++		stats->tx_bytes +=skb->len;
 +		if (from & AT_EGRESS) {
-+			dp->stat_r6 +=1;
++			dp->st_rx_frm_egr++;
 +			dev_queue_xmit(skb);
 +		} else if (from & AT_INGRESS) {
 +
-+			dp->stat_r7 +=1;
++			dp->st_rx_frm_ing++;
 +			netif_rx(skb);
 +		} else {
-+			/* if netfilt is compiled in and packet is
-+			tagged, we could reinject the packet back
-+			this would make it do remaining 10%
-+			of what current IMQ does  
-+			if someone really really insists then
-+			this is the spot .. jhs */
 +			dev_kfree_skb(skb);
 +			stats->tx_dropped++;
 +		}
 +	}
 +
-+	if (spin_trylock(&dv->xmit_lock)) {
-+		dp->stat_r3 +=1;
-+		if (NULL == (skb = skb_peek(&dp->rq))) {
++	if (spin_trylock(&_dev->xmit_lock)) {
++		dp->st_rxq_check++;
++		if ((skb = skb_peek(&dp->rq)) == NULL) {
 +			dp->tasklet_pending = 0;
-+		if (netif_queue_stopped(dv))
-+			//netif_start_queue(dv);
-+			netif_wake_queue(dv);
++			if (netif_queue_stopped(_dev))
++				netif_wake_queue(_dev);
 +		} else {
-+			dp->stat_r2 +=1;
-+			spin_unlock(&dv->xmit_lock);
++			dp->st_rxq_rsch++;
++			spin_unlock(&_dev->xmit_lock);
 +			goto resched;
 +		}
-+		spin_unlock(&dv->xmit_lock);
-+		} else {
++		spin_unlock(&_dev->xmit_lock);
++	} else {
 +resched:
-+			dp->tasklet_pending = 1;
-+			tasklet_schedule(&dp->dummy_tasklet);
-+		}
++		dp->tasklet_pending = 1;
++		tasklet_schedule(&dp->ifb_tasklet);
++	}
 +
 +}
-+#endif
- 
- static int dummy_set_address(struct net_device *dev, void *p)
- {
-@@ -62,12 +186,17 @@
- 	/* Initialize the device structure. */
- 	dev->get_stats = dummy_get_stats;
- 	dev->hard_start_xmit = dummy_xmit;
-+	dev->tx_timeout = &dummy_timeout;
-+	dev->watchdog_timeo = TX_TIMEOUT;
-+	dev->open = &dummy_open;
-+	dev->stop = &dummy_close;
 +
- 	dev->set_multicast_list = set_multicast_list;
- 	dev->set_mac_address = dummy_set_address;
- 
- 	/* Fill in device structure with ethernet-generic values. */
- 	ether_setup(dev);
--	dev->tx_queue_len = 0;
++static void __init ifb_setup(struct net_device *dev)
++{
++	/* Initialize the device structure. */
++	dev->get_stats = ifb_get_stats;
++	dev->hard_start_xmit = ifb_xmit;
++	dev->open = &ifb_open;
++	dev->stop = &ifb_close;
++
++	/* Fill in device structure with ethernet-generic values. */
++	ether_setup(dev);
 +	dev->tx_queue_len = TX_Q_LIMIT;
- 	dev->change_mtu = NULL;
- 	dev->flags |= IFF_NOARP;
- 	dev->flags &= ~IFF_MULTICAST;
-@@ -77,18 +206,64 @@
- 
- static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
- {
--	struct net_device_stats *stats = netdev_priv(dev);
-+	struct dummy_private *dp = ((struct net_device *)dev)->priv;
++	dev->change_mtu = NULL;
++	dev->flags |= IFF_NOARP;
++	dev->flags &= ~IFF_MULTICAST;
++	SET_MODULE_OWNER(dev);
++	random_ether_addr(dev->dev_addr);
++}
++
++static int ifb_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	struct ifb_private *dp = netdev_priv(dev);
 +	struct net_device_stats *stats = &dp->stats;
 +	int ret = 0;
-
-+	{
- 	stats->tx_packets++;
- 	stats->tx_bytes+=skb->len;
-+	}
-+#ifdef CONFIG_NET_CLS_ACT
-+	__u32 from = G_TC_FROM(skb->tc_verd);
-+	if (!from || !skb->input_dev ) {
++	u32 from = G_TC_FROM(skb->tc_verd);
++
++	stats->tx_packets++;
++	stats->tx_bytes+=skb->len;
++
++	if (!from || !skb->input_dev) {
 +dropped:
-+		 dev_kfree_skb(skb);
-+		 stats->rx_dropped++;
-+		 return ret;
++		dev_kfree_skb(skb);
++		stats->rx_dropped++;
++		return ret;
 +	} else {
-+		if (skb->input_dev)
-+			skb->dev = skb->input_dev;
-+		else
-+			printk("warning!!! no idev %s\n",skb->dev->name);
-
++		/* 
++		 * note we could be going
++		 * ingress -> egress or
++		 * egress -> ingress
++		*/
++		skb->dev = skb->input_dev;
 +		skb->input_dev = dev;
 +		if (from & AT_INGRESS) {
 +			skb_pull(skb, skb->dev->hard_header_len);
@@ -198,79 +242,116 @@
 +			}
 +		}
 +	}
++
 +	if (skb_queue_len(&dp->rq) >= dev->tx_queue_len) {
 +		netif_stop_queue(dev);
 +	}
++
 +	dev->trans_start = jiffies;
 +	skb_queue_tail(&dp->rq, skb);
 +	if (!dp->tasklet_pending) {
 +		dp->tasklet_pending = 1;
-+		tasklet_schedule(&dp->dummy_tasklet);
++		tasklet_schedule(&dp->ifb_tasklet);
 +	}
 +
-+#else
-+	stats->rx_dropped++;
- 	dev_kfree_skb(skb);
--	return 0;
-+#endif
 +	return ret;
- }
- 
- static struct net_device_stats *dummy_get_stats(struct net_device *dev)
- {
--	return netdev_priv(dev);
-+	struct dummy_private *dp = ((struct net_device *)dev)->priv;
++}
++
++static struct net_device_stats *ifb_get_stats(struct net_device *dev)
++{
++	struct ifb_private *dp = netdev_priv(dev);
 +	struct net_device_stats *stats = &dp->stats;
-+#ifdef CONFIG_NET_CLS_ACT_DEB
-+	printk("tasklets stats %ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld \n",
-+		dp->stat_r1,dp->stat_r2,dp->stat_r3,dp->stat_r4,
-+		dp->stat_r5,dp->stat_r6,dp->stat_r7,dp->stat_r8);
-+#endif
++
++	pr_debug("tasklets stats %ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld \n",
++		dp->st_task_enter, dp->st_txq_refl_try, dp->st_rxq_enter, 
++		dp->st_rx2tx_tran dp->st_rxq_notenter, dp->st_rx_frm_egr,
++		dp->st_rx_frm_ing, dp->st_rxq_check, dp->st_rxq_rsch );
 +
 +	return stats;
- }
- 
- static struct net_device **dummies;
-@@ -97,12 +272,41 @@
- module_param(numdummies, int, 0);
- MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
- 
-+static int dummy_close(struct net_device *dev)
-+{
++}
 +
-+#ifdef CONFIG_NET_CLS_ACT
-+	struct dummy_private *dp = ((struct net_device *)dev)->priv;
++static struct net_device **ifbs;
 +
-+	tasklet_kill(&dp->dummy_tasklet);
++/* Number of ifb devices to be set up by this module. */
++module_param(numifbs, int, 0);
++MODULE_PARM_DESC(numifbs, "Number of ifb devices");
++
++static int ifb_close(struct net_device *dev)
++{
++	struct ifb_private *dp = netdev_priv(dev);
++
++	tasklet_kill(&dp->ifb_tasklet);
++	netif_stop_queue(dev);
 +	skb_queue_purge(&dp->rq);
 +	skb_queue_purge(&dp->tq);
-+#endif
-+	netif_stop_queue(dev);
 +	return 0;
 +}
 +
-+static int dummy_open(struct net_device *dev)
++static int ifb_open(struct net_device *dev)
 +{
++	struct ifb_private *dp = netdev_priv(dev);
 +
-+#ifdef CONFIG_NET_CLS_ACT
-+	struct dummy_private *dp = ((struct net_device *)dev)->priv;
-+
-+	tasklet_init(&dp->dummy_tasklet, ri_tasklet, (unsigned long)dev);
++	tasklet_init(&dp->ifb_tasklet, ri_tasklet, (unsigned long)dev);
 +	skb_queue_head_init(&dp->rq);
 +	skb_queue_head_init(&dp->tq);
-+#endif
 +	netif_start_queue(dev);
++
 +	return 0;
 +}
 +
++static int __init ifb_init_one(int index)
++{
++	struct net_device *dev_ifb;
++	int err;
 +
- static int __init dummy_init_one(int index)
- {
- 	struct net_device *dev_dummy;
- 	int err;
- 
--	dev_dummy = alloc_netdev(sizeof(struct net_device_stats),
-+	dev_dummy = alloc_netdev(sizeof(struct dummy_private),
- 				 "dummy%d", dummy_setup);
- 
- 	if (!dev_dummy)
++	dev_ifb = alloc_netdev(sizeof(struct ifb_private),
++				 "ifb%d", ifb_setup);
++
++	if (!dev_ifb)
++		return -ENOMEM;
++
++	if ((err = register_netdev(dev_ifb))) {
++		free_netdev(dev_ifb);
++		dev_ifb = NULL;
++	} else {
++		ifbs[index] = dev_ifb; 
++	}
++
++	return err;
++}
++
++static void ifb_free_one(int index)
++{
++	unregister_netdev(ifbs[index]);
++	free_netdev(ifbs[index]);
++} 
++
++static int __init ifb_init_module(void)
++{ 
++	int i, err = 0;
++	ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL); 
++	if (!ifbs)
++		return -ENOMEM; 
++	for (i = 0; i < numifbs && !err; i++)
++		err = ifb_init_one(i); 
++	if (err) { 
++		while (--i >= 0)
++			ifb_free_one(i);
++	}
++
++	return err;
++} 
++
++static void __exit ifb_cleanup_module(void)
++{
++	int i;
++
++	for (i = 0; i < numifbs; i++) 
++		ifb_free_one(i); 
++	kfree(ifbs);	
++}
++
++module_init(ifb_init_module);
++module_exit(ifb_cleanup_module);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jamal Hadi Salim");
================================================================

---- CVS-web:
    http://cvs.pld-linux.org/SOURCES/linux-2.6-dummy-as-imq-replacement.patch?r1=1.1.2.1&r2=1.1.2.1.2.1&f=u



More information about the pld-cvs-commit mailing list