⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip_vs_lblc.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	tbl->rover = j;}/* *      Periodical timer handler for IPVS lblc table *      It is used to collect stale entries when the number of entries *      exceeds the maximum size of the table. * *      Fixme: we probably need more complicated algorithm to collect *             entries that have not been used for a long time even *             if the number of entries doesn't exceed the maximum size *             of the table. *      The full expiration check is for this purpose now. */static void ip_vs_lblc_check_expire(unsigned long data){	struct ip_vs_lblc_table *tbl;	unsigned long now = jiffies;	int goal;	int i, j;	struct list_head *l, *e;	struct ip_vs_lblc_entry *en;	tbl = (struct ip_vs_lblc_table *)data;	if ((tbl->counter % COUNT_FOR_FULL_EXPIRATION) == 0) {		/* do full expiration check */		ip_vs_lblc_full_check(tbl);		tbl->counter = 1;		goto out;	}	if (atomic_read(&tbl->entries) <= tbl->max_size) {		tbl->counter++;		goto out;	}	goal = (atomic_read(&tbl->entries) - tbl->max_size)*4/3;	if (goal > tbl->max_size/2)		goal = tbl->max_size/2;	for (i=0, j=tbl->rover; i<IP_VS_LBLC_TAB_SIZE; i++) {		j = (j + 1) & IP_VS_LBLC_TAB_MASK;		e = l = &tbl->bucket[j];		write_lock(&tbl->lock);		while (e->next != l) {			en = list_entry(e->next,					struct ip_vs_lblc_entry, list);			if ((now - en->lastuse) < ENTRY_TIMEOUT) {				e = e->next;				continue;			}			ip_vs_lblc_free(en);			atomic_dec(&tbl->entries);			goal--;		}		write_unlock(&tbl->lock);		if (goal <= 0)			break;	}	tbl->rover = j;  out:	mod_timer(&tbl->periodic_timer, jiffies+CHECK_EXPIRE_INTERVAL);}static int ip_vs_lblc_init_svc(struct ip_vs_service *svc){	int i;	struct ip_vs_lblc_table *tbl;	/*	 *    Allocate the ip_vs_lblc_table for this service	 */	tbl = kmalloc(sizeof(struct ip_vs_lblc_table), GFP_ATOMIC);	if (tbl == NULL) {		IP_VS_ERR("ip_vs_lblc_init_svc(): no memory\n");		return -ENOMEM;	}	svc->sched_data = tbl;	IP_VS_DBG(6, "LBLC hash table (memory=%dbytes) allocated for "		  "current service\n",		  sizeof(struct ip_vs_lblc_table));	/*	 *    Initialize the hash buckets	 */	for (i=0; i<IP_VS_LBLC_TAB_SIZE; i++) {		INIT_LIST_HEAD(&tbl->bucket[i]);	}	tbl->lock = RW_LOCK_UNLOCKED;	tbl->max_size = IP_VS_LBLC_TAB_SIZE*16;	tbl->rover = 0;	tbl->counter = 1;	/*	 *    Hook periodic timer for garbage collection	 */	init_timer(&tbl->periodic_timer);	tbl->periodic_timer.data = (unsigned long)tbl;	tbl->periodic_timer.function = ip_vs_lblc_check_expire;	tbl->periodic_timer.expires = jiffies+CHECK_EXPIRE_INTERVAL;	add_timer(&tbl->periodic_timer);	return 0;}static int ip_vs_lblc_done_svc(struct ip_vs_service *svc){	struct ip_vs_lblc_table *tbl = svc->sched_data;	/* remove periodic timer */	del_timer_sync(&tbl->periodic_timer);	/* got to clean up table entries here */	ip_vs_lblc_flush(tbl);	/* release the table itself */	kfree(svc->sched_data);	IP_VS_DBG(6, "LBLC hash table (memory=%dbytes) released\n",		  sizeof(struct ip_vs_lblc_table));	return 0;}static int ip_vs_lblc_update_svc(struct ip_vs_service *svc){	return 0;}static inline struct ip_vs_dest *__ip_vs_wlc_schedule(struct ip_vs_service *svc, struct iphdr *iph){	register struct list_head *l, *e;	struct ip_vs_dest *dest, *least;	int loh, doh;	/*	 * We think the overhead of processing active connections is fifty	 * times higher than that of inactive connections in average. (This	 * fifty times might not be accurate, we will change it later.) We	 * use the following formula to estimate the overhead:	 *                dest->activeconns*50 + dest->inactconns	 * and the load:	 *                (dest overhead) / dest->weight	 *	 * Remember -- no floats in kernel mode!!!	 * The comparison of h1*w2 > h2*w1 is equivalent to that of	 *                h1/w1 > h2/w2	 * if every weight is larger than zero.	 *	 * The server with weight=0 is quiesced and will not receive any	 * new connection.	 */	l = &svc->destinations;	for (e=l->next; e!=l; e=e->next) {		least = list_entry(e, struct ip_vs_dest, n_list);		if (atomic_read(&least->weight) > 0) {			loh = atomic_read(&least->activeconns) * 50				+ atomic_read(&least->inactconns);			goto nextstage;		}	}	return NULL;	/*	 *    Find the destination with the least load.	 */  nextstage:	for (e=e->next; e!=l; e=e->next) {		dest = list_entry(e, struct ip_vs_dest, n_list);		doh = atomic_read(&dest->activeconns) * 50			+ atomic_read(&dest->inactconns);		if (loh * atomic_read(&dest->weight) >		    doh * atomic_read(&least->weight)) {			least = dest;			loh = doh;		}	}	IP_VS_DBG(6, "LBLC: server %d.%d.%d.%d:%d "		  "activeconns %d refcnt %d weight %d overhead %d\n",		  NIPQUAD(least->addr), ntohs(least->port),		  atomic_read(&least->activeconns),		  atomic_read(&least->refcnt),		  atomic_read(&least->weight), loh);	return least;}/* *   If this destination server is overloaded and there is a less loaded *   server, then return true. */static inline intis_overloaded(struct ip_vs_dest *dest, struct ip_vs_service *svc){	if (atomic_read(&dest->activeconns) > atomic_read(&dest->weight)) {		register struct list_head *l, *e;		struct ip_vs_dest *d;		l = &svc->destinations;		for (e=l->next; e!=l; e=e->next) {			d = list_entry(e, struct ip_vs_dest, n_list);			if (atomic_read(&d->activeconns)*2			    < atomic_read(&d->weight)) {				return 1;			}		}	}	return 0;}/* *    Locality-Based (weighted) Least-Connection scheduling */static struct ip_vs_dest *ip_vs_lblc_schedule(struct ip_vs_service *svc, struct iphdr *iph){	struct ip_vs_dest *dest;	struct ip_vs_lblc_table *tbl;	struct ip_vs_lblc_entry *en;	IP_VS_DBG(6, "ip_vs_lblc_schedule(): Scheduling...\n");	tbl = (struct ip_vs_lblc_table *)svc->sched_data;	en = ip_vs_lblc_get(tbl, iph->daddr);	if (en == NULL) {		dest = __ip_vs_wlc_schedule(svc, iph);		if (dest == NULL) {			IP_VS_DBG(1, "no destination available\n");			return NULL;		}		en = ip_vs_lblc_new(iph->daddr, dest);		if (en == NULL) {			return NULL;		}		ip_vs_lblc_hash(tbl, en);	} else {		dest = en->dest;		if (!(dest->flags & IP_VS_DEST_F_AVAILABLE)		    || atomic_read(&dest->weight) <= 0		    || is_overloaded(dest, svc)) {			dest = __ip_vs_wlc_schedule(svc, iph);			if (dest == NULL) {				IP_VS_DBG(1, "no destination available\n");				return NULL;			}			atomic_dec(&en->dest->refcnt);			atomic_inc(&dest->refcnt);			en->dest = dest;		}	}	en->lastuse = jiffies;	IP_VS_DBG(6, "LBLC: destination IP address %u.%u.%u.%u "		  "--> server %u.%u.%u.%u:%d\n",		  NIPQUAD(en->addr),		  NIPQUAD(dest->addr),		  ntohs(dest->port));	return dest;}/* *      IPVS LBLC Scheduler structure */static struct ip_vs_scheduler ip_vs_lblc_scheduler ={	{0},                    /* n_list */	"lblc",                 /* name */	ATOMIC_INIT(0),         /* refcnt */	THIS_MODULE,		/* this module */	ip_vs_lblc_init_svc,    /* service initializer */	ip_vs_lblc_done_svc,    /* service done */	ip_vs_lblc_update_svc,  /* service updater */	ip_vs_lblc_schedule,    /* select a server from the destination list */};static int __init ip_vs_lblc_init(void){	INIT_LIST_HEAD(&ip_vs_lblc_scheduler.n_list);	lblc_sysctl_table.sysctl_header =		register_sysctl_table(lblc_sysctl_table.root_dir, 0);	return register_ip_vs_scheduler(&ip_vs_lblc_scheduler);}static void __exit ip_vs_lblc_cleanup(void){	unregister_sysctl_table(lblc_sysctl_table.sysctl_header);	unregister_ip_vs_scheduler(&ip_vs_lblc_scheduler);}module_init(ip_vs_lblc_init);module_exit(ip_vs_lblc_cleanup);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -