📄 eql.c
字号:
/* * 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 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 */static const char *version = "Equalizer1996: $Revision: 1.2.1 $ $Date: 1996/09/22 13:52:00 $ Simon Janes (simon@ncm.com)\n";/* * 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 suser() 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/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/malloc.h>#include <linux/string.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/uaccess.h>#include <linux/errno.h> #include <linux/init.h>#include <linux/netdevice.h>#include <linux/if.h>#include <linux/if_arp.h>#include <linux/timer.h>#include <linux/if_eql.h>#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#endifstatic unsigned int eql_debug = EQL_DEBUG;int eql_init(struct device *dev); /* */static int eql_open(struct device *dev); /* */static int eql_close(struct device *dev); /* */static int eql_ioctl(struct device *dev, struct ifreq *ifr, int cmd); /* */static int eql_slave_xmit(struct sk_buff *skb, struct device *dev); /* */static struct net_device_stats *eql_get_stats(struct device *dev); /* *//* ioctl() handlers ---------------- */static int eql_enslave(struct device *dev, slaving_request_t *srq); /* */static int eql_emancipate(struct device *dev, slaving_request_t *srq); /* */static int eql_g_slave_cfg(struct device *dev, slave_config_t *sc); /* */static int eql_s_slave_cfg(struct device *dev, slave_config_t *sc); /* */static int eql_g_master_cfg(struct device *dev, master_config_t *mc); /* */static int eql_s_master_cfg(struct device *dev, master_config_t *mc); /* */static inline int eql_is_slave(struct device *dev); /* */static inline int eql_is_master(struct 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 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 device *dev); -* */static int eql_remove_slave_dev(slave_queue_t *queue, struct device *dev); /* */static inline struct 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 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 device * interface functions --------------------------------------------------------- */__initfunc(int eql_init(struct device *dev)){ static unsigned version_printed = 0; /* static unsigned num_masters = 0; */ equalizer_t *eql = 0; 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. */ dev_init_buffers(dev); /* * 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 device *dev){ equalizer_t *eql = (equalizer_t *) dev->priv; slave_queue_t *new_queue;#ifdef EQL_DEBUG if (eql_debug >= 5) printk ("%s: open\n", 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 timer\n", dev->name); eql->timer_on = 1; add_timer (&eql->timer); MOD_INC_USE_COUNT; return 0; } return 1;}static int eql_close(struct device *dev){ equalizer_t *eql = (equalizer_t *) dev->priv;#ifdef EQL_DEBUG if ( eql_debug >= 5) printk ("%s: close\n", 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 timer\n", dev->name);#endif eql->timer_on = 0; del_timer (&eql->timer); eql_delete_slave_queue (eql->queue); MOD_DEC_USE_COUNT; return 0;}static int eql_ioctl(struct 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 device *dev){ equalizer_t *eql = (equalizer_t *) dev->priv; struct device *slave_dev = 0; slave_t *slave; if (skb == NULL) return 0; eql_schedule_slaves (eql->queue); slave_dev = eql_best_slave_dev (eql->queue); slave = eql_best_slave (eql->queue); if ( slave_dev != 0 ) {#ifdef EQL_DEBUG if (eql_debug >= 100) printk ("%s: %d slaves xmitng %d B %s\n", dev->name, eql_number_slaves (eql->queue), skb->len, slave_dev->name);#endif skb->dev = slave_dev; skb->priority = 1; dev_queue_xmit (skb); eql->stats->tx_packets++; slave->bytes_queued += skb->len; } 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 device *dev){ equalizer_t *eql = (equalizer_t *) dev->priv; return eql->stats;}/* * Private ioctl functions */static int eql_enslave(struct device *dev, slaving_request_t *srqp){ struct device *master_dev; struct device *slave_dev; slaving_request_t srq; int err; err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t)); if (err) {#ifdef EQL_DEBUG if (eql_debug >= 20) printk ("EQL enslave: error detected by verify_area\n");#endif return err; } copy_from_user (&srq, srqp, sizeof (slaving_request_t));#ifdef EQL_DEBUG if (eql_debug >= 20) printk ("%s: enslave '%s' %ld bps\n", dev->name, srq.slave_name, srq.priority);#endif master_dev = dev; /* for "clarity" */ slave_dev = dev_get (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; 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 slave\n");#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 device *dev, slaving_request_t *srqp){ struct device *master_dev; struct device *slave_dev; slaving_request_t srq; int err; err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t)); if (err) return err; copy_from_user (&srq, srqp, sizeof (slaving_request_t));#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 (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 device *dev, slave_config_t *scp){ slave_t *slave; equalizer_t *eql; struct device *slave_dev; slave_config_t sc; int err; err = verify_area(VERIFY_READ, (void *)scp, sizeof (slave_config_t)); if (err) return err; copy_from_user (&sc, scp, sizeof (slave_config_t));#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 (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; err = verify_area(VERIFY_WRITE, (void *)scp, sizeof (slave_config_t));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -