eql.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:24k
- /*
- * Equalizer Load-balancer for serial network interfaces.
- *
- * (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
- * NCM: Network and Communications Management, Inc.
- *
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * The author may be reached as simon@ncm.com, or C/O
- * NCM
- * Attn: Simon Janes
- * 6803 Whittier Ave
- * McLean VA 22101
- * Phone: 1-703-847-0040 ext 103
- */
- /*
- * Sources:
- * skeleton.c by Donald Becker.
- * Inspirations:
- * The Harried and Overworked Alan Cox
- * Conspiracies:
- * The Alan Cox and Mike McLagan plot to get someone else to do the code,
- * which turned out to be me.
- */
- /*
- * $Log: eql.c,v $
- * Revision 1.2 1996/04/11 17:51:52 guru
- * Added one-line eql_remove_slave patch.
- *
- * Revision 1.1 1996/04/11 17:44:17 guru
- * Initial revision
- *
- * Revision 3.13 1996/01/21 15:17:18 alan
- * tx_queue_len changes.
- * reformatted.
- *
- * Revision 3.12 1995/03/22 21:07:51 anarchy
- * Added capable() checks on configuration.
- * Moved header file.
- *
- * Revision 3.11 1995/01/19 23:14:31 guru
- * slave_load = (ULONG_MAX - (ULONG_MAX / 2)) -
- * (priority_Bps) + bytes_queued * 8;
- *
- * Revision 3.10 1995/01/19 23:07:53 guru
- * back to
- * slave_load = (ULONG_MAX - (ULONG_MAX / 2)) -
- * (priority_Bps) + bytes_queued;
- *
- * Revision 3.9 1995/01/19 22:38:20 guru
- * slave_load = (ULONG_MAX - (ULONG_MAX / 2)) -
- * (priority_Bps) + bytes_queued * 4;
- *
- * Revision 3.8 1995/01/19 22:30:55 guru
- * slave_load = (ULONG_MAX - (ULONG_MAX / 2)) -
- * (priority_Bps) + bytes_queued * 2;
- *
- * Revision 3.7 1995/01/19 21:52:35 guru
- * printk's trimmed out.
- *
- * Revision 3.6 1995/01/19 21:49:56 guru
- * This is working pretty well. I gained 1 K/s in speed.. now it's just
- * robustness and printk's to be diked out.
- *
- * Revision 3.5 1995/01/18 22:29:59 guru
- * still crashes the kernel when the lock_wait thing is woken up.
- *
- * Revision 3.4 1995/01/18 21:59:47 guru
- * Broken set-bit locking snapshot
- *
- * Revision 3.3 1995/01/17 22:09:18 guru
- * infinite sleep in a lock somewhere..
- *
- * Revision 3.2 1995/01/15 16:46:06 guru
- * Log trimmed of non-pertinent 1.x branch messages
- *
- * Revision 3.1 1995/01/15 14:41:45 guru
- * New Scheduler and timer stuff...
- *
- * Revision 1.15 1995/01/15 14:29:02 guru
- * Will make 1.14 (now 1.15) the 3.0 branch, and the 1.12 the 2.0 branch, the one
- * with the dumber scheduler
- *
- * Revision 1.14 1995/01/15 02:37:08 guru
- * shock.. the kept-new-versions could have zonked working
- * stuff.. shudder
- *
- * Revision 1.13 1995/01/15 02:36:31 guru
- * big changes
- *
- * scheduler was torn out and replaced with something smarter
- *
- * global names not prefixed with eql_ were renamed to protect
- * against namespace collisions
- *
- * a few more abstract interfaces were added to facilitate any
- * potential change of datastructure. the driver is still using
- * a linked list of slaves. going to a heap would be a bit of
- * an overkill.
- *
- * this compiles fine with no warnings.
- *
- * the locking mechanism and timer stuff must be written however,
- * this version will not work otherwise
- *
- */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/timer.h>
- #include <linux/netdevice.h>
- #include <linux/if.h>
- #include <linux/if_arp.h>
- #include <linux/if_eql.h>
- #include <asm/uaccess.h>
- static char version[] __initdata =
- "Equalizer1996: $Revision: 1.2.1 $ $Date: 1996/09/22 13:52:00 $ Simon Janes (simon@ncm.com)n";
- #ifndef EQL_DEBUG
- /* #undef EQL_DEBUG -* print nothing at all, not even a boot-banner */
- /* #define EQL_DEBUG 1 -* print only the boot-banner */
- /* #define EQL_DEBUG 5 -* print major function entries */
- /* #define EQL_DEBUG 20 -* print subfunction entries */
- /* #define EQL_DEBUG 50 -* print utility entries */
- /* #define EQL_DEBUG 100 -* print voluminous function entries */
- #define EQL_DEBUG 1
- #endif
- static unsigned int eql_debug = EQL_DEBUG;
- static int eql_init(struct net_device *dev); /* */
- static int eql_open(struct net_device *dev); /* */
- static int eql_close(struct net_device *dev); /* */
- static int eql_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); /* */
- static int eql_slave_xmit(struct sk_buff *skb, struct net_device *dev); /* */
- static struct net_device_stats *eql_get_stats(struct net_device *dev); /* */
- /* ioctl() handlers
- ---------------- */
- static int eql_enslave(struct net_device *dev, slaving_request_t *srq); /* */
- static int eql_emancipate(struct net_device *dev, slaving_request_t *srq); /* */
- static int eql_g_slave_cfg(struct net_device *dev, slave_config_t *sc); /* */
- static int eql_s_slave_cfg(struct net_device *dev, slave_config_t *sc); /* */
- static int eql_g_master_cfg(struct net_device *dev, master_config_t *mc); /* */
- static int eql_s_master_cfg(struct net_device *dev, master_config_t *mc); /* */
- static inline int eql_is_slave(struct net_device *dev); /* */
- static inline int eql_is_master(struct net_device *dev); /* */
- static slave_t *eql_new_slave(void); /* */
- static void eql_delete_slave(slave_t *slave); /* */
- /* static long eql_slave_priority(slave_t *slave); -* */
- static inline int eql_number_slaves(slave_queue_t *queue); /* */
- static inline int eql_is_empty(slave_queue_t *queue); /* */
- static inline int eql_is_full(slave_queue_t *queue); /* */
- static slave_queue_t *eql_new_slave_queue(struct net_device *dev); /* */
- static void eql_delete_slave_queue(slave_queue_t *queue); /* */
- static int eql_insert_slave(slave_queue_t *queue, slave_t *slave); /* */
- static slave_t *eql_remove_slave(slave_queue_t *queue, slave_t *slave); /* */
- /* static int eql_insert_slave_dev(slave_queue_t *queue, struct net_device *dev); -* */
- static int eql_remove_slave_dev(slave_queue_t *queue, struct net_device *dev); /* */
- static inline struct net_device *eql_best_slave_dev(slave_queue_t *queue); /* */
- static inline slave_t *eql_best_slave(slave_queue_t *queue); /* */
- static inline slave_t *eql_first_slave(slave_queue_t *queue); /* */
- static inline slave_t *eql_next_slave(slave_queue_t *queue, slave_t *slave); /* */
- static inline void eql_set_best_slave(slave_queue_t *queue, slave_t *slave); /* */
- static inline void eql_schedule_slaves(slave_queue_t *queue); /* */
- static slave_t *eql_find_slave_dev(slave_queue_t *queue, struct net_device *dev); /* */
- /* static inline eql_lock_slave_queue(slave_queue_t *queue); -* */
- /* static inline eql_unlock_slave_queue(slave_queue_t *queue); -* */
- static void eql_timer(unsigned long param); /* */
- /* struct net_device * interface functions
- ---------------------------------------------------------
- */
- static int __init eql_init(struct net_device *dev)
- {
- static unsigned version_printed;
- /* static unsigned num_masters = 0; */
- equalizer_t *eql = 0;
- SET_MODULE_OWNER(dev);
- if ( version_printed++ == 0 && eql_debug > 0)
- printk(version);
- /*
- * Initialize the device structure.
- */
- dev->priv = kmalloc (sizeof (equalizer_t), GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOMEM;
- memset (dev->priv, 0, sizeof (equalizer_t));
- eql = (equalizer_t *) dev->priv;
- eql->stats = kmalloc (sizeof (struct net_device_stats), GFP_KERNEL);
- if (eql->stats == NULL)
- {
- kfree(dev->priv);
- dev->priv = NULL;
- return -ENOMEM;
- }
- memset (eql->stats, 0, sizeof (struct net_device_stats));
- init_timer (&eql->timer);
- eql->timer.data = (unsigned long) dev->priv;
- eql->timer.expires = jiffies+EQL_DEFAULT_RESCHED_IVAL;
- eql->timer.function = &eql_timer;
- eql->timer_on = 0;
- dev->open = eql_open;
- dev->stop = eql_close;
- dev->do_ioctl = eql_ioctl;
- dev->hard_start_xmit = eql_slave_xmit;
- dev->get_stats = eql_get_stats;
-
- /*
- * Fill in the fields of the device structure with
- * eql-generic values.
- */
- /*
- * Now we undo some of the things that eth_setup does
- * that we don't like
- */
-
- dev->mtu = EQL_DEFAULT_MTU; /* set to 576 in eql.h */
- dev->flags = IFF_MASTER;
- dev->type = ARPHRD_SLIP;
- dev->tx_queue_len = 5; /* Hands them off fast */
- return 0;
- }
- static int eql_open(struct net_device *dev)
- {
- equalizer_t *eql = (equalizer_t *) dev->priv;
- slave_queue_t *new_queue;
- #ifdef EQL_DEBUG
- if (eql_debug >= 5)
- printk ("%s: openn", dev->name);
- #endif
- printk ("%s: remember to turn off Van-Jacobson compression on your slave devices.n", dev->name);
- new_queue = eql_new_slave_queue (dev);
-
- if (new_queue != 0)
- {
- new_queue->master_dev = dev;
- eql->queue = new_queue;
- eql->queue->lock = 0;
- eql->min_slaves = 1;
- eql->max_slaves = EQL_DEFAULT_MAX_SLAVES; /* 4 usually... */
- printk ("%s: adding timern", dev->name);
- eql->timer_on = 1;
- add_timer (&eql->timer);
- return 0;
- }
- return -ENOMEM;
- }
- static int eql_close(struct net_device *dev)
- {
- equalizer_t *eql = (equalizer_t *) dev->priv;
- #ifdef EQL_DEBUG
- if ( eql_debug >= 5)
- printk ("%s: closen", dev->name);
- #endif
- /*
- * The timer has to be stopped first before we start hacking away
- * at the data structure it scans every so often...
- */
- #ifdef EQL_DEBUG
- printk ("%s: stopping timern", dev->name);
- #endif
- eql->timer_on = 0;
- del_timer (&eql->timer);
- eql_delete_slave_queue (eql->queue);
- return 0;
- }
- static int eql_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
- {
- if(cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG &&
- !capable(CAP_NET_ADMIN))
- return -EPERM;
- switch (cmd)
- {
- case EQL_ENSLAVE:
- return eql_enslave (dev, (slaving_request_t *) ifr->ifr_data);
- case EQL_EMANCIPATE:
- return eql_emancipate (dev, (slaving_request_t *) ifr->ifr_data);
- case EQL_GETSLAVECFG:
- return eql_g_slave_cfg (dev, (slave_config_t *) ifr->ifr_data);
- case EQL_SETSLAVECFG:
- return eql_s_slave_cfg (dev, (slave_config_t *) ifr->ifr_data);
- case EQL_GETMASTRCFG:
- return eql_g_master_cfg (dev, (master_config_t *) ifr->ifr_data);
- case EQL_SETMASTRCFG:
- return eql_s_master_cfg (dev, (master_config_t *) ifr->ifr_data);
- default:
- return -EOPNOTSUPP;
- }
- }
- static int eql_slave_xmit(struct sk_buff *skb, struct net_device *dev)
- {
- equalizer_t *eql = (equalizer_t *) dev->priv;
- struct net_device *slave_dev = 0;
- slave_t *slave;
- if (skb == NULL)
- return 0;
- eql_schedule_slaves (eql->queue);
-
- slave = eql_best_slave (eql->queue);
- slave_dev = slave ? slave->dev : 0;
- if ( slave_dev != 0 )
- {
- #ifdef EQL_DEBUG
- if (eql_debug >= 100)
- printk ("%s: %d slaves xmitng %d B %sn",
- dev->name, eql_number_slaves (eql->queue), skb->len,
- slave_dev->name);
- #endif
- skb->dev = slave_dev;
- skb->priority = 1;
- slave->bytes_queued += skb->len;
- dev_queue_xmit (skb);
- eql->stats->tx_packets++;
- }
- else
- {
- /*
- * The alternative for this is the return 1 and have
- * dev_queue_xmit just queue it up on the eql's queue.
- */
- eql->stats->tx_dropped++;
- dev_kfree_skb(skb);
- }
- return 0;
- }
- static struct net_device_stats * eql_get_stats(struct net_device *dev)
- {
- equalizer_t *eql = (equalizer_t *) dev->priv;
- return eql->stats;
- }
- /*
- * Private ioctl functions
- */
- static int eql_enslave(struct net_device *dev, slaving_request_t *srqp)
- {
- struct net_device *master_dev;
- struct net_device *slave_dev;
- slaving_request_t srq;
- if (copy_from_user(&srq, srqp, sizeof (slaving_request_t)))
- {
- #ifdef EQL_DEBUG
- if (eql_debug >= 20)
- printk ("EQL enslave: error detected by copy_from_usern");
- #endif
- return -EFAULT;
- }
- #ifdef EQL_DEBUG
- if (eql_debug >= 20)
- printk ("%s: enslave '%s' %ld bpsn", dev->name,
- srq.slave_name, srq.priority);
- #endif
- master_dev = dev; /* for "clarity" */
- slave_dev = __dev_get_by_name (srq.slave_name);
- if (master_dev != 0 && slave_dev != 0)
- {
- if ((master_dev->flags & IFF_UP) == IFF_UP)
- {
- /*slave is not a master & not already a slave:*/
- if (! eql_is_master (slave_dev) &&
- ! eql_is_slave (slave_dev) )
- {
- slave_t *s = eql_new_slave ();
- equalizer_t *eql =
- (equalizer_t *) master_dev->priv;
- if (!s)
- return -ENOMEM;
- s->dev = slave_dev;
- s->priority = srq.priority;
- s->priority_bps = srq.priority;
- s->priority_Bps = srq.priority / 8;
- slave_dev->flags |= IFF_SLAVE;
- eql_insert_slave (eql->queue, s);
- return 0;
- }
- #ifdef EQL_DEBUG
- else if (eql_debug >= 20)
- printk ("EQL enslave: slave is master or slave is already slaven");
- #endif
- }
- #ifdef EQL_DEBUG
- else if (eql_debug >= 20)
- printk ("EQL enslave: master device not up!n");
- #endif
- }
- #ifdef EQL_DEBUG
- else if (eql_debug >= 20)
- printk ("EQL enslave: master or slave are NULL");
- #endif
- return -EINVAL;
- }
- static int eql_emancipate(struct net_device *dev, slaving_request_t *srqp)
- {
- struct net_device *master_dev;
- struct net_device *slave_dev;
- slaving_request_t srq;
- if (copy_from_user(&srq, srqp, sizeof (slaving_request_t)))
- return -EFAULT;
- #ifdef EQL_DEBUG
- if (eql_debug >= 20)
- printk ("%s: emancipate `%s`n", dev->name, srq.slave_name);
- #endif
- master_dev = dev; /* for "clarity" */
- slave_dev = __dev_get_by_name (srq.slave_name);
- if ( eql_is_slave (slave_dev) ) /* really is a slave */
- {
- equalizer_t *eql = (equalizer_t *) master_dev->priv;
- slave_dev->flags = slave_dev->flags & ~IFF_SLAVE;
- eql_remove_slave_dev (eql->queue, slave_dev);
- return 0;
- }
- return -EINVAL;
- }
- static int eql_g_slave_cfg(struct net_device *dev, slave_config_t *scp)
- {
- slave_t *slave;
- equalizer_t *eql;
- struct net_device *slave_dev;
- slave_config_t sc;
- if (copy_from_user (&sc, scp, sizeof (slave_config_t)))
- return -EFAULT;
- #ifdef EQL_DEBUG
- if (eql_debug >= 20)
- printk ("%s: get config for slave `%s'n", dev->name, sc.slave_name);
- #endif
- eql = (equalizer_t *) dev->priv;
- slave_dev = __dev_get_by_name (sc.slave_name);
- if ( eql_is_slave (slave_dev) )
- {
- slave = eql_find_slave_dev (eql->queue, slave_dev);
- if (slave != 0)
- {
- sc.priority = slave->priority;
- if (copy_to_user (scp, &sc, sizeof (slave_config_t)))
- return -EFAULT;
- return 0;
- }
- }
- return -EINVAL;
- }
- static int eql_s_slave_cfg(struct net_device *dev, slave_config_t *scp)
- {
- slave_t *slave;
- equalizer_t *eql;
- struct net_device *slave_dev;
- slave_config_t sc;
- if (copy_from_user (&sc, scp, sizeof (slave_config_t)))
- return -EFAULT;
- #ifdef EQL_DEBUG
- if (eql_debug >= 20)
- printk ("%s: set config for slave `%s'n", dev->name, sc.slave_name);
- #endif
-
- eql = (equalizer_t *) dev->priv;
- slave_dev = __dev_get_by_name (sc.slave_name);
- if ( eql_is_slave (slave_dev) )
- {
- slave = eql_find_slave_dev (eql->queue, slave_dev);
- if (slave != 0)
- {
- slave->priority = sc.priority;
- slave->priority_bps = sc.priority;
- slave->priority_Bps = sc.priority / 8;
- return 0;
- }
- }
- return -EINVAL;
- }
- static int eql_g_master_cfg(struct net_device *dev, master_config_t *mcp)
- {
- equalizer_t *eql;
- master_config_t mc;
- #if EQL_DEBUG
- if (eql_debug >= 20)
- printk ("%s: get master confign", dev->name);
- #endif
- if ( eql_is_master (dev) )
- {
- eql = (equalizer_t *) dev->priv;
- mc.max_slaves = eql->max_slaves;
- mc.min_slaves = eql->min_slaves;
- if (copy_to_user (mcp, &mc, sizeof (master_config_t)))
- return -EFAULT;
- return 0;
- }
- return -EINVAL;
- }
- static int eql_s_master_cfg(struct net_device *dev, master_config_t *mcp)
- {
- equalizer_t *eql;
- master_config_t mc;
- if (copy_from_user (&mc, mcp, sizeof (master_config_t)))
- return -EFAULT;
- #if EQL_DEBUG
- if (eql_debug >= 20)
- printk ("%s: set master confign", dev->name);
- #endif
- if ( eql_is_master (dev) )
- {
- eql = (equalizer_t *) dev->priv;
- eql->max_slaves = mc.max_slaves;
- eql->min_slaves = mc.min_slaves;
- return 0;
- }
- return -EINVAL;
- }
- /*
- * Private device support functions
- */
- static inline int eql_is_slave(struct net_device *dev)
- {
- if (dev)
- {
- if ((dev->flags & IFF_SLAVE) == IFF_SLAVE)
- return 1;
- }
- return 0;
- }
- static inline int eql_is_master(struct net_device *dev)
- {
- if (dev)
- {
- if ((dev->flags & IFF_MASTER) == IFF_MASTER)
- return 1;
- }
- return 0;
- }
- static slave_t *eql_new_slave(void)
- {
- slave_t *slave;
- slave = (slave_t *) kmalloc (sizeof (slave_t), GFP_KERNEL);
- if (slave)
- memset(slave, 0, sizeof (slave_t));
- return slave;
- }
- static void eql_delete_slave(slave_t *slave)
- {
- kfree (slave);
- }
- #if 0 /* not currently used, will be used
- when we really use a priority queue */
- static long slave_Bps(slave_t *slave)
- {
- return (slave->priority_Bps);
- }
- static long slave_bps(slave_t *slave)
- {
- return (slave->priority_bps);
- }
- #endif
- static inline int eql_number_slaves(slave_queue_t *queue)
- {
- return queue->num_slaves;
- }
- static inline int eql_is_empty(slave_queue_t *queue)
- {
- if (eql_number_slaves (queue) == 0)
- return 1;
- return 0;
- }
- static inline int eql_is_full(slave_queue_t *queue)
- {
- equalizer_t *eql = (equalizer_t *) queue->master_dev->priv;
- if (eql_number_slaves (queue) == eql->max_slaves)
- return 1;
- return 0;
- }
- static slave_queue_t *eql_new_slave_queue(struct net_device *dev)
- {
- slave_queue_t *queue;
- slave_t *head_slave;
- slave_t *tail_slave;
- queue = (slave_queue_t *) kmalloc (sizeof (slave_queue_t), GFP_KERNEL);
- if (!queue)
- goto err_out;
- head_slave = eql_new_slave ();
- if (!head_slave)
- goto err_out_queue;
- tail_slave = eql_new_slave ();
- if (!tail_slave)
- goto err_out_hs;
- memset (queue, 0, sizeof (slave_queue_t));
- head_slave->next = tail_slave;
- tail_slave->next = 0;
- queue->head = head_slave;
- queue->num_slaves = 0;
- queue->master_dev = dev;
- return queue;
- err_out_hs:
- kfree (head_slave);
- err_out_queue:
- kfree (queue);
- err_out:
- return NULL;
- }
- static void eql_delete_slave_queue(slave_queue_t *queue)
- {
- slave_t *zapped;
- /*
- * This should only be called when there isn't a
- * timer running that scans the data periodically..
- * dev_close stops the timer...
- */
- while ( ! eql_is_empty (queue) )
- {
- zapped = eql_remove_slave (queue, queue->head->next);
- eql_delete_slave (zapped);
- }
- kfree (queue->head->next);
- kfree (queue->head);
- kfree (queue);
- }
- static int eql_insert_slave(slave_queue_t *queue, slave_t *slave)
- {
- unsigned long flags;
- save_flags(flags);
- cli ();
- if ( ! eql_is_full (queue) )
- {
- slave_t *duplicate_slave = 0;
- duplicate_slave = eql_find_slave_dev (queue, slave->dev);
- if (duplicate_slave != 0)
- {
- /* printk ("%s: found a duplicate, killing it and replacingn",
- queue->master_dev->name); */
- eql_delete_slave (eql_remove_slave (queue, duplicate_slave));
- }
- slave->next = queue->head->next;
- queue->head->next = slave;
- queue->num_slaves++;
- restore_flags(flags);
- return 0;
- }
- restore_flags(flags);
- return 1;
- }
- static slave_t *eql_remove_slave(slave_queue_t *queue, slave_t *slave)
- {
- slave_t *prev;
- slave_t *curr;
- unsigned long flags;
- save_flags(flags);
- cli ();
- prev = queue->head;
- curr = queue->head->next;
- while (curr != slave &&
- curr->dev != 0 )
- {
- /* printk ("%s: remove_slave; searching...n", queue->master_dev->name); */
- prev = curr;
- curr = curr->next;
- }
- if (curr == slave)
- {
- prev->next = curr->next;
- queue->num_slaves--;
- curr->dev->flags = curr->dev->flags & ~IFF_SLAVE;
- restore_flags(flags);
- return curr;
- }
- restore_flags(flags);
- return 0; /* not found */
- }
- static int eql_remove_slave_dev(slave_queue_t *queue, struct net_device *dev)
- {
- slave_t *prev;
- slave_t *curr;
- slave_t *target;
- target = eql_find_slave_dev (queue, dev);
- if (target != 0)
- {
- unsigned long flags;
- save_flags(flags);
- cli ();
- prev = queue->head;
- curr = prev->next;
- while (curr != target)
- {
- prev = curr;
- curr = curr->next;
- }
- prev->next = curr->next;
- queue->num_slaves--;
- restore_flags(flags);
- eql_delete_slave (curr);
- return 0;
- }
- return 1;
- }
- static inline struct net_device *eql_best_slave_dev(slave_queue_t *queue)
- {
- if (queue->best_slave != 0)
- {
- if (queue->best_slave->dev != 0)
- return queue->best_slave->dev;
- else
- return 0;
- }
- else
- return 0;
- }
- static inline slave_t *eql_best_slave(slave_queue_t *queue)
- {
- return queue->best_slave;
- }
- static inline void eql_schedule_slaves(slave_queue_t *queue)
- {
- struct net_device *master_dev = queue->master_dev;
- slave_t *best_slave = 0;
- slave_t *slave_corpse = 0;
- #ifdef EQL_DEBUG
- if (eql_debug >= 100)
- printk ("%s: schedule %d slavesn",
- master_dev->name, eql_number_slaves (queue));
- #endif
- if ( eql_is_empty (queue) )
- {
- /*
- * No slaves to play with
- */
- eql_set_best_slave (queue, (slave_t *) 0);
- return;
- }
- else
- {
- /*
- * Make a pass to set the best slave
- */
- unsigned long best_load = (unsigned long) ULONG_MAX;
- slave_t *slave = 0;
- unsigned long flags;
- int i;
- save_flags(flags);
- cli ();
- for (i = 1, slave = eql_first_slave (queue);
- i <= eql_number_slaves (queue);
- i++, slave = eql_next_slave (queue, slave))
- {
- /*
- * Go through the slave list once, updating best_slave
- * whenever a new best_load is found, whenever a dead
- * slave is found, it is marked to be pulled out of the
- * queue
- */
-
- unsigned long slave_load;
- unsigned long bytes_queued;
- unsigned long priority_Bps;
-
- if (slave != 0)
- {
- bytes_queued = slave->bytes_queued;
- priority_Bps = slave->priority_Bps;
- if ( slave->dev != 0)
- {
- if ((slave->dev->flags & IFF_UP) == IFF_UP )
- {
- slave_load = (ULONG_MAX - (ULONG_MAX / 2)) -
- (priority_Bps) + bytes_queued * 8;
- if (slave_load < best_load)
- {
- best_load = slave_load;
- best_slave = slave;
- }
- }
- else /* we found a dead slave */
- {
- /*
- * We only bury one slave at a time, if more than
- * one slave dies, we will bury him on the next
- * reschedule. slaves don't die all at once that
- * much anyway
- */
- slave_corpse = slave;
- }
- }
- }
- } /* for */
- restore_flags(flags);
- eql_set_best_slave (queue, best_slave);
- } /* else */
- if (slave_corpse != 0)
- {
- printk ("eql: scheduler found dead slave, burying...n");
- eql_delete_slave (eql_remove_slave (queue, slave_corpse));
- }
- return;
- }
- static slave_t * eql_find_slave_dev(slave_queue_t *queue, struct net_device *dev)
- {
- slave_t *slave = 0;
- slave = eql_first_slave(queue);
- while (slave != 0 && slave->dev != dev && slave != 0)
- {
- #if 0
- if (slave->dev != 0)
- printk ("eql: find_slave_dev; looked at '%s'...n", slave->dev->name);
- else
- printk ("eql: find_slave_dev; looked at nothing...n");
- #endif
- slave = slave->next;
- }
- return slave;
- }
- static inline slave_t *eql_first_slave(slave_queue_t *queue)
- {
- return queue->head->next;
- }
- static inline slave_t *eql_next_slave(slave_queue_t *queue, slave_t *slave)
- {
- return slave->next;
- }
- static inline void eql_set_best_slave(slave_queue_t *queue, slave_t *slave)
- {
- queue->best_slave = slave;
- }
- static void eql_timer(unsigned long param)
- {
- equalizer_t *eql = (equalizer_t *) param;
- slave_t *slave;
- slave_t *slave_corpse = 0;
- int i;
- unsigned long flags;
-
- if ( ! eql_is_empty (eql->queue) )
- {
- save_flags(flags);
- cli ();
- for (i = 1, slave = eql_first_slave (eql->queue);
- i <= eql_number_slaves (eql->queue);
- i++, slave = eql_next_slave (eql->queue, slave))
- {
- if (slave != 0)
- {
- if ((slave->dev->flags & IFF_UP) == IFF_UP )
- {
- slave->bytes_queued -= slave->priority_Bps;
- if (slave->bytes_queued < 0)
- slave->bytes_queued = 0;
- }
- else
- slave_corpse = slave;
- }
- }
- restore_flags(flags);
- if (slave_corpse != 0)
- {
- printk ("eql: timer found dead slave, burying...n");
- eql_delete_slave (eql_remove_slave (eql->queue, slave_corpse));
- }
- }
- if (eql->timer_on != 0)
- {
- eql->timer.expires = jiffies+EQL_DEFAULT_RESCHED_IVAL;
- add_timer (&eql->timer);
- }
- }
- static struct net_device dev_eql;
- static int __init eql_init_module(void)
- {
- strcpy(dev_eql.name, "eql");
- dev_eql.init = eql_init;
- if (register_netdev(&dev_eql) != 0) {
- printk("eql: register_netdev() returned non-zero.n");
- return -EIO;
- }
- return 0;
- }
- static void __exit eql_cleanup_module(void)
- {
- kfree(((equalizer_t *)dev_eql.priv)->stats );
- kfree(dev_eql.priv);
- unregister_netdev(&dev_eql);
- }
- module_init(eql_init_module);
- module_exit(eql_cleanup_module);
- MODULE_LICENSE("GPL");
- /*
- * Local Variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c eql.c"
- * version-control: t
- * kept-new-versions: 20
- * End:
- */