1
2
3
4
5
6
7
8
9
10
11
12
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
25static struct ip_vs_dest *
26ip_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;
31
32 IP_VS_DBG(6, "ip_vs_fo_schedule(): Scheduling...\n");
33
34
35
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(hweight->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
58static 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
66static int __init ip_vs_fo_init(void)
67{
68 return register_ip_vs_scheduler(&ip_vs_fo_scheduler);
69}
70
71static void __exit ip_vs_fo_cleanup(void)
72{
73 unregister_ip_vs_scheduler(&ip_vs_fo_scheduler);
74 synchronize_rcu();
75}
76
77module_init(ip_vs_fo_init);
78module_exit(ip_vs_fo_cleanup);
79MODULE_LICENSE("GPL");
80