GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / net / netfilter / ipvs / ip_vs_wlc.c
blobbbddfdb10db2b1afc026618456f2bc99a8698c48
1 /*
2 * IPVS: Weighted Least-Connection Scheduling module
4 * Authors: Wensong Zhang <wensong@linuxvirtualserver.org>
5 * Peter Kese <peter.kese@ijs.si>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
12 * Changes:
13 * Wensong Zhang : changed the ip_vs_wlc_schedule to return dest
14 * Wensong Zhang : changed to use the inactconns in scheduling
15 * Wensong Zhang : changed some comestics things for debugging
16 * Wensong Zhang : changed for the d-linked destination list
17 * Wensong Zhang : added the ip_vs_wlc_update_svc
18 * Wensong Zhang : added any dest with weight=0 is quiesced
22 #define KMSG_COMPONENT "IPVS"
23 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
25 #include <linux/module.h>
26 #include <linux/kernel.h>
28 #include <net/ip_vs.h>
31 static inline unsigned int
32 ip_vs_wlc_dest_overhead(struct ip_vs_dest *dest)
35 * We think the overhead of processing active connections is 256
36 * times higher than that of inactive connections in average. (This
37 * 256 times might not be accurate, we will change it later) We
38 * use the following formula to estimate the overhead now:
39 * dest->activeconns*256 + dest->inactconns
41 return (atomic_read(&dest->activeconns) << 8) +
42 atomic_read(&dest->inactconns);
47 * Weighted Least Connection scheduling
49 static struct ip_vs_dest *
50 ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
52 struct ip_vs_dest *dest, *least;
53 unsigned int loh, doh;
55 IP_VS_DBG(6, "ip_vs_wlc_schedule(): Scheduling...\n");
58 * We calculate the load of each dest server as follows:
59 * (dest overhead) / dest->weight
61 * Remember -- no floats in kernel mode!!!
62 * The comparison of h1*w2 > h2*w1 is equivalent to that of
63 * h1/w1 > h2/w2
64 * if every weight is larger than zero.
66 * The server with weight=0 is quiesced and will not receive any
67 * new connections.
70 list_for_each_entry(dest, &svc->destinations, n_list) {
71 if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
72 atomic_read(&dest->weight) > 0) {
73 least = dest;
74 loh = ip_vs_wlc_dest_overhead(least);
75 goto nextstage;
78 IP_VS_ERR_RL("WLC: no destination available\n");
79 return NULL;
82 * Find the destination with the least load.
84 nextstage:
85 list_for_each_entry_continue(dest, &svc->destinations, n_list) {
86 if (dest->flags & IP_VS_DEST_F_OVERLOAD)
87 continue;
88 doh = ip_vs_wlc_dest_overhead(dest);
89 if (loh * atomic_read(&dest->weight) >
90 doh * atomic_read(&least->weight)) {
91 least = dest;
92 loh = doh;
96 IP_VS_DBG_BUF(6, "WLC: server %s:%u "
97 "activeconns %d refcnt %d weight %d overhead %d\n",
98 IP_VS_DBG_ADDR(svc->af, &least->addr), ntohs(least->port),
99 atomic_read(&least->activeconns),
100 atomic_read(&least->refcnt),
101 atomic_read(&least->weight), loh);
103 return least;
107 static struct ip_vs_scheduler ip_vs_wlc_scheduler =
109 .name = "wlc",
110 .refcnt = ATOMIC_INIT(0),
111 .module = THIS_MODULE,
112 .n_list = LIST_HEAD_INIT(ip_vs_wlc_scheduler.n_list),
113 .schedule = ip_vs_wlc_schedule,
117 static int __init ip_vs_wlc_init(void)
119 return register_ip_vs_scheduler(&ip_vs_wlc_scheduler);
122 static void __exit ip_vs_wlc_cleanup(void)
124 unregister_ip_vs_scheduler(&ip_vs_wlc_scheduler);
127 module_init(ip_vs_wlc_init);
128 module_exit(ip_vs_wlc_cleanup);
129 MODULE_LICENSE("GPL");