diff options
-rw-r--r-- | net/netfilter/ipvs/Kconfig | 10 | ||||
-rw-r--r-- | net/netfilter/ipvs/Makefile | 1 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_fo.c | 79 |
3 files changed, 90 insertions, 0 deletions
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index 0c3b1670b0d1..3b6929dec748 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig | |||
@@ -152,6 +152,16 @@ config IP_VS_WLC | |||
152 | If you want to compile it in kernel, say Y. To compile it as a | 152 | If you want to compile it in kernel, say Y. To compile it as a |
153 | module, choose M here. If unsure, say N. | 153 | module, choose M here. If unsure, say N. |
154 | 154 | ||
155 | config IP_VS_FO | ||
156 | tristate "weighted failover scheduling" | ||
157 | ---help--- | ||
158 | The weighted failover scheduling algorithm directs network | ||
159 | connections to the server with the highest weight that is | ||
160 | currently available. | ||
161 | |||
162 | If you want to compile it in kernel, say Y. To compile it as a | ||
163 | module, choose M here. If unsure, say N. | ||
164 | |||
155 | config IP_VS_LBLC | 165 | config IP_VS_LBLC |
156 | tristate "locality-based least-connection scheduling" | 166 | tristate "locality-based least-connection scheduling" |
157 | ---help--- | 167 | ---help--- |
diff --git a/net/netfilter/ipvs/Makefile b/net/netfilter/ipvs/Makefile index 34ee602ddb66..38b2723b2e3d 100644 --- a/net/netfilter/ipvs/Makefile +++ b/net/netfilter/ipvs/Makefile | |||
@@ -26,6 +26,7 @@ obj-$(CONFIG_IP_VS_RR) += ip_vs_rr.o | |||
26 | obj-$(CONFIG_IP_VS_WRR) += ip_vs_wrr.o | 26 | obj-$(CONFIG_IP_VS_WRR) += ip_vs_wrr.o |
27 | obj-$(CONFIG_IP_VS_LC) += ip_vs_lc.o | 27 | obj-$(CONFIG_IP_VS_LC) += ip_vs_lc.o |
28 | obj-$(CONFIG_IP_VS_WLC) += ip_vs_wlc.o | 28 | obj-$(CONFIG_IP_VS_WLC) += ip_vs_wlc.o |
29 | obj-$(CONFIG_IP_VS_FO) += ip_vs_fo.o | ||
29 | obj-$(CONFIG_IP_VS_LBLC) += ip_vs_lblc.o | 30 | obj-$(CONFIG_IP_VS_LBLC) += ip_vs_lblc.o |
30 | obj-$(CONFIG_IP_VS_LBLCR) += ip_vs_lblcr.o | 31 | obj-$(CONFIG_IP_VS_LBLCR) += ip_vs_lblcr.o |
31 | obj-$(CONFIG_IP_VS_DH) += ip_vs_dh.o | 32 | obj-$(CONFIG_IP_VS_DH) += ip_vs_dh.o |
diff --git a/net/netfilter/ipvs/ip_vs_fo.c b/net/netfilter/ipvs/ip_vs_fo.c new file mode 100644 index 000000000000..6a2647d471ff --- /dev/null +++ b/net/netfilter/ipvs/ip_vs_fo.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * IPVS: Weighted Fail Over module | ||
3 | * | ||
4 | * Authors: Kenny Mathis <kmathis@chokepoint.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * Changes: | ||
12 | * Kenny Mathis : added initial functionality based on weight | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #define KMSG_COMPONENT "IPVS" | ||
17 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/kernel.h> | ||
21 | |||
22 | #include <net/ip_vs.h> | ||
23 | |||
24 | /* Weighted Fail Over Module */ | ||
25 | static struct ip_vs_dest * | ||
26 | ip_vs_fo_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, | ||
27 | struct ip_vs_iphdr *iph) | ||
28 | { | ||
29 | struct ip_vs_dest *dest, *hweight = NULL; | ||
30 | int hw = 0; /* Track highest weight */ | ||
31 | |||
32 | IP_VS_DBG(6, "ip_vs_fo_schedule(): Scheduling...\n"); | ||
33 | |||
34 | /* Basic failover functionality | ||
35 | * Find virtual server with highest weight and send it traffic | ||
36 | */ | ||
37 | list_for_each_entry_rcu(dest, &svc->destinations, n_list) { | ||
38 | if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) && | ||
39 | atomic_read(&dest->weight) > hw) { | ||
40 | hweight = dest; | ||
41 | hw = atomic_read(&dest->weight); | ||
42 | } | ||
43 | } | ||
44 | |||
45 | if (hweight) { | ||
46 | IP_VS_DBG_BUF(6, "FO: server %s:%u activeconns %d weight %d\n", | ||
47 | IP_VS_DBG_ADDR(svc->af, &hweight->addr), | ||
48 | ntohs(hweight->port), | ||
49 | atomic_read(&hweight->activeconns), | ||
50 | atomic_read(&hweight->weight)); | ||
51 | return hweight; | ||
52 | } | ||
53 | |||
54 | ip_vs_scheduler_err(svc, "no destination available"); | ||
55 | return NULL; | ||
56 | } | ||
57 | |||
58 | static struct ip_vs_scheduler ip_vs_fo_scheduler = { | ||
59 | .name = "fo", | ||
60 | .refcnt = ATOMIC_INIT(0), | ||
61 | .module = THIS_MODULE, | ||
62 | .n_list = LIST_HEAD_INIT(ip_vs_fo_scheduler.n_list), | ||
63 | .schedule = ip_vs_fo_schedule, | ||
64 | }; | ||
65 | |||
66 | static int __init ip_vs_fo_init(void) | ||
67 | { | ||
68 | return register_ip_vs_scheduler(&ip_vs_fo_scheduler); | ||
69 | } | ||
70 | |||
71 | static void __exit ip_vs_fo_cleanup(void) | ||
72 | { | ||
73 | unregister_ip_vs_scheduler(&ip_vs_fo_scheduler); | ||
74 | synchronize_rcu(); | ||
75 | } | ||
76 | |||
77 | module_init(ip_vs_fo_init); | ||
78 | module_exit(ip_vs_fo_cleanup); | ||
79 | MODULE_LICENSE("GPL"); | ||