Commit | Line | Data |
---|---|---|
eefa32d3 RD |
1 | /* |
2 | * IPVS: Overflow-Connection Scheduling module | |
3 | * | |
4 | * Authors: Raducu Deaconu <rhadoo_io@yahoo.com> | |
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 | * Scheduler implements "overflow" loadbalancing according to number of active | |
12 | * connections , will keep all conections to the node with the highest weight | |
13 | * and overflow to the next node if the number of connections exceeds the node's | |
14 | * weight. | |
15 | * Note that this scheduler might not be suitable for UDP because it only uses | |
16 | * active connections | |
17 | * | |
18 | */ | |
19 | ||
20 | #define KMSG_COMPONENT "IPVS" | |
21 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
22 | ||
23 | #include <linux/module.h> | |
24 | #include <linux/kernel.h> | |
25 | ||
26 | #include <net/ip_vs.h> | |
27 | ||
28 | /* OVF Connection scheduling */ | |
29 | static struct ip_vs_dest * | |
30 | ip_vs_ovf_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, | |
31 | struct ip_vs_iphdr *iph) | |
32 | { | |
33 | struct ip_vs_dest *dest, *h = NULL; | |
34 | int hw = 0, w; | |
35 | ||
36 | IP_VS_DBG(6, "ip_vs_ovf_schedule(): Scheduling...\n"); | |
37 | /* select the node with highest weight, go to next in line if active | |
38 | * connections exceed weight | |
39 | */ | |
40 | list_for_each_entry_rcu(dest, &svc->destinations, n_list) { | |
41 | w = atomic_read(&dest->weight); | |
42 | if ((dest->flags & IP_VS_DEST_F_OVERLOAD) || | |
43 | atomic_read(&dest->activeconns) > w || | |
44 | w == 0) | |
45 | continue; | |
46 | if (!h || w > hw) { | |
47 | h = dest; | |
48 | hw = w; | |
49 | } | |
50 | } | |
51 | ||
52 | if (h) { | |
53 | IP_VS_DBG_BUF(6, "OVF: server %s:%u active %d w %d\n", | |
54 | IP_VS_DBG_ADDR(h->af, &h->addr), | |
55 | ntohs(h->port), | |
56 | atomic_read(&h->activeconns), | |
57 | atomic_read(&h->weight)); | |
58 | return h; | |
59 | } | |
60 | ||
61 | ip_vs_scheduler_err(svc, "no destination available"); | |
62 | return NULL; | |
63 | } | |
64 | ||
65 | static struct ip_vs_scheduler ip_vs_ovf_scheduler = { | |
66 | .name = "ovf", | |
67 | .refcnt = ATOMIC_INIT(0), | |
68 | .module = THIS_MODULE, | |
69 | .n_list = LIST_HEAD_INIT(ip_vs_ovf_scheduler.n_list), | |
70 | .schedule = ip_vs_ovf_schedule, | |
71 | }; | |
72 | ||
73 | static int __init ip_vs_ovf_init(void) | |
74 | { | |
75 | return register_ip_vs_scheduler(&ip_vs_ovf_scheduler); | |
76 | } | |
77 | ||
78 | static void __exit ip_vs_ovf_cleanup(void) | |
79 | { | |
80 | unregister_ip_vs_scheduler(&ip_vs_ovf_scheduler); | |
81 | synchronize_rcu(); | |
82 | } | |
83 | ||
84 | module_init(ip_vs_ovf_init); | |
85 | module_exit(ip_vs_ovf_cleanup); | |
86 | MODULE_LICENSE("GPL"); |