netdev
[Top] [All Lists]

[PATCH 2.5.73] update teql scheduler to dynamic net device

To: "David S. Miller" <davem@xxxxxxxxxx>, Alexey Kuznetsov <kuznet@xxxxxxxxxxxxx>
Subject: [PATCH 2.5.73] update teql scheduler to dynamic net device
From: Stephen Hemminger <shemminger@xxxxxxxx>
Date: Mon, 23 Jun 2003 11:57:55 -0700
Cc: netdev@xxxxxxxxxxx
Organization: Open Source Development Lab
Sender: netdev-bounce@xxxxxxxxxxx
Change teql scheduler to:
        - dynamically allocate and free the network device.
          previously, used static network device.
        - support multiple equalizers (default one) via module parameter 
(max_equalizers)
          previously, limited to one.

Tested with 2.5.73 on SMP.

--- linux-2.5.73/net/sched/sch_teql.c   2003-06-23 11:39:54.000000000 -0700
+++ linux-2.5-sysfs/net/sched/sch_teql.c        2003-06-23 11:42:22.000000000 
-0700
@@ -67,8 +67,9 @@
 struct teql_master
 {
        struct Qdisc_ops qops;
-       struct net_device dev;
+       struct net_device *dev;
        struct Qdisc *slaves;
+       struct list_head master_list;
        struct net_device_stats stats;
 };
 
@@ -122,13 +123,13 @@ teql_dequeue(struct Qdisc* sch)
 
        skb = __skb_dequeue(&dat->q);
        if (skb == NULL) {
-               struct net_device *m = dat->m->dev.qdisc->dev;
+               struct net_device *m = dat->m->dev->qdisc->dev;
                if (m) {
                        dat->m->slaves = sch;
                        netif_wake_queue(m);
                }
        }
-       sch->q.qlen = dat->q.qlen + dat->m->dev.qdisc->q.qlen;
+       sch->q.qlen = dat->q.qlen + dat->m->dev->qdisc->q.qlen;
        return skb;
 }
 
@@ -165,9 +166,9 @@ teql_destroy(struct Qdisc* sch)
                                        master->slaves = NEXT_SLAVE(q);
                                        if (q == master->slaves) {
                                                master->slaves = NULL;
-                                               
spin_lock_bh(&master->dev.queue_lock);
-                                               qdisc_reset(master->dev.qdisc);
-                                               
spin_unlock_bh(&master->dev.queue_lock);
+                                               
spin_lock_bh(&master->dev->queue_lock);
+                                               qdisc_reset(master->dev->qdisc);
+                                               
spin_unlock_bh(&master->dev->queue_lock);
                                        }
                                }
                                skb_queue_purge(&dat->q);
@@ -185,10 +186,10 @@ static int teql_qdisc_init(struct Qdisc 
        struct teql_master *m = (struct teql_master*)sch->ops;
        struct teql_sched_data *q = (struct teql_sched_data *)sch->data;
 
-       if (dev->hard_header_len > m->dev.hard_header_len)
+       if (dev->hard_header_len > m->dev->hard_header_len)
                return -EINVAL;
 
-       if (&m->dev == dev)
+       if (m->dev == dev)
                return -ELOOP;
 
        q->m = m;
@@ -196,29 +197,29 @@ static int teql_qdisc_init(struct Qdisc 
        skb_queue_head_init(&q->q);
 
        if (m->slaves) {
-               if (m->dev.flags & IFF_UP) {
-                       if ((m->dev.flags&IFF_POINTOPOINT && 
!(dev->flags&IFF_POINTOPOINT))
-                           || (m->dev.flags&IFF_BROADCAST && 
!(dev->flags&IFF_BROADCAST))
-                           || (m->dev.flags&IFF_MULTICAST && 
!(dev->flags&IFF_MULTICAST))
-                           || dev->mtu < m->dev.mtu)
+               if (m->dev->flags & IFF_UP) {
+                       if ((m->dev->flags&IFF_POINTOPOINT && 
!(dev->flags&IFF_POINTOPOINT))
+                           || (m->dev->flags&IFF_BROADCAST && 
!(dev->flags&IFF_BROADCAST))
+                           || (m->dev->flags&IFF_MULTICAST && 
!(dev->flags&IFF_MULTICAST))
+                           || dev->mtu < m->dev->mtu)
                                return -EINVAL;
                } else {
                        if (!(dev->flags&IFF_POINTOPOINT))
-                               m->dev.flags &= ~IFF_POINTOPOINT;
+                               m->dev->flags &= ~IFF_POINTOPOINT;
                        if (!(dev->flags&IFF_BROADCAST))
-                               m->dev.flags &= ~IFF_BROADCAST;
+                               m->dev->flags &= ~IFF_BROADCAST;
                        if (!(dev->flags&IFF_MULTICAST))
-                               m->dev.flags &= ~IFF_MULTICAST;
-                       if (dev->mtu < m->dev.mtu)
-                               m->dev.mtu = dev->mtu;
+                               m->dev->flags &= ~IFF_MULTICAST;
+                       if (dev->mtu < m->dev->mtu)
+                               m->dev->mtu = dev->mtu;
                }
                q->next = NEXT_SLAVE(m->slaves);
                NEXT_SLAVE(m->slaves) = sch;
        } else {
                q->next = sch;
                m->slaves = sch;
-               m->dev.mtu = dev->mtu;
-               m->dev.flags = (m->dev.flags&~FMASK)|(dev->flags&FMASK);
+               m->dev->mtu = dev->mtu;
+               m->dev->flags = (m->dev->flags&~FMASK)|(dev->flags&FMASK);
        }
        return 0;
 }
@@ -379,9 +380,9 @@ static int teql_master_open(struct net_d
                        flags &= ~IFF_MULTICAST;
        } while ((q = NEXT_SLAVE(q)) != m->slaves);
 
-       m->dev.mtu = mtu;
-       m->dev.flags = (m->dev.flags&~FMASK) | flags;
-       netif_start_queue(&m->dev);
+       m->dev->mtu = mtu;
+       m->dev->flags = (m->dev->flags&~FMASK) | flags;
+       netif_start_queue(m->dev);
        return 0;
 }
 
@@ -417,8 +418,30 @@ static int teql_master_mtu(struct net_de
        return 0;
 }
 
-static int teql_master_init(struct net_device *dev)
+static __init int teql_master_init(struct net_device *dev)
 {
+       struct teql_master *master = dev->priv;
+       struct Qdisc_ops *ops = &master->qops;
+
+       master->dev     = dev;
+
+       strlcpy(ops->id, dev->name, IFNAMSIZ);
+       ops->priv_size  = sizeof(struct teql_sched_data);
+       
+       ops->enqueue    =       teql_enqueue;
+       ops->dequeue    =       teql_dequeue;
+       ops->requeue    =       teql_requeue;
+       ops->init       =       teql_qdisc_init;
+       ops->reset      =       teql_reset;
+       ops->destroy    =       teql_destroy;
+       ops->owner      =       THIS_MODULE;
+
+       return register_qdisc(ops);
+}
+
+static __init void teql_master_setup(struct net_device *dev)
+{
+       dev->init               = teql_master_init;
        dev->open               = teql_master_open;
        dev->hard_start_xmit    = teql_master_xmit;
        dev->stop               = teql_master_close;
@@ -429,62 +452,58 @@ static int teql_master_init(struct net_d
        dev->tx_queue_len       = 100;
        dev->flags              = IFF_NOARP;
        dev->hard_header_len    = LL_MAX_HEADER;
-       return 0;
+       SET_MODULE_OWNER(dev);
 }
 
-static struct teql_master the_master = {
-{
-       .next           =       NULL,
-       .cl_ops         =       NULL,
-       .id             =       "",
-       .priv_size      =       sizeof(struct teql_sched_data),
-       .enqueue        =       teql_enqueue,
-       .dequeue        =       teql_dequeue,
-       .requeue        =       teql_requeue,
-       .drop           =       NULL,
-       .init           =       teql_qdisc_init,
-       .reset          =       teql_reset,
-       .destroy        =       teql_destroy,
-       .dump           =       NULL,
-       .owner          =       THIS_MODULE,
-},};
-
-
-#ifdef MODULE
-int init_module(void)
-#else
+static LIST_HEAD(master_dev_list);
+static spinlock_t master_dev_lock = SPIN_LOCK_UNLOCKED;
+static int max_equalizers = 1;
+MODULE_PARM(max_equalizers, "i");
+MODULE_PARM_DESC(max_equalizers, "Max number of link equalizers");
+
 int __init teql_init(void)
-#endif
 {
-       int err;
-
-       rtnl_lock();
+       int i;
+       int err = 0;
 
-       the_master.dev.priv = (void*)&the_master;
-       err = dev_alloc_name(&the_master.dev, "teql%d");
-       if (err < 0)
-               return err;
-       memcpy(the_master.qops.id, the_master.dev.name, IFNAMSIZ);
-       the_master.dev.init = teql_master_init;
-
-       SET_MODULE_OWNER(&the_master.dev);
-       err = register_netdevice(&the_master.dev);
-       if (err == 0) {
-               err = register_qdisc(&the_master.qops);
-               if (err)
-                       unregister_netdevice(&the_master.dev);
+       for (i = 0; i < max_equalizers; i++) {
+               struct net_device *dev;
+               struct teql_master *master;
+
+               dev = alloc_netdev(sizeof(struct teql_master),
+                                 "teql%d", teql_master_setup);
+               if (!dev)
+                       return -ENOMEM;
+
+               if ((err = register_netdev(dev)))
+                       goto out;
+
+               master = dev->priv;
+               spin_lock(&master_dev_lock);
+               list_add_tail(&master->master_list, &master_dev_list);
+               spin_unlock(&master_dev_lock);
        }
-       rtnl_unlock();
+ out:
        return err;
 }
 
-#ifdef MODULE
-void cleanup_module(void) 
+static void __exit teql_exit(void) 
 {
-       rtnl_lock();
-       unregister_qdisc(&the_master.qops);
-       unregister_netdevice(&the_master.dev);
-       rtnl_unlock();
+       struct teql_master *master, *nxt;
+
+       spin_lock(&master_dev_lock);
+       list_for_each_entry_safe(master, nxt, &master_dev_list, master_list) {
+
+               list_del(&master->master_list);
+
+               unregister_qdisc(&master->qops);
+               unregister_netdev(master->dev);
+               kfree(master->dev);
+       }
+       spin_unlock(&master_dev_lock);
 }
-#endif
+
+module_init(teql_init);
+module_exit(teql_exit);
+
 MODULE_LICENSE("GPL");

<Prev in Thread] Current Thread [Next in Thread>