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