1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#define KMSG_COMPONENT "IPVS"
35#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
36
37#include <linux/module.h>
38#include <linux/kernel.h>
39
40#include <net/ip_vs.h>
41
42
43static inline int
44ip_vs_nq_dest_overhead(struct ip_vs_dest *dest)
45{
46
47
48
49
50 return atomic_read(&dest->activeconns) + 1;
51}
52
53
54
55
56
57static struct ip_vs_dest *
58ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
59 struct ip_vs_iphdr *iph)
60{
61 struct ip_vs_dest *dest, *least = NULL;
62 int loh = 0, doh;
63
64 IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
80
81 if (dest->flags & IP_VS_DEST_F_OVERLOAD ||
82 !atomic_read(&dest->weight))
83 continue;
84
85 doh = ip_vs_nq_dest_overhead(dest);
86
87
88 if (atomic_read(&dest->activeconns) == 0) {
89 least = dest;
90 loh = doh;
91 goto out;
92 }
93
94 if (!least ||
95 ((__s64)loh * atomic_read(&dest->weight) >
96 (__s64)doh * atomic_read(&least->weight))) {
97 least = dest;
98 loh = doh;
99 }
100 }
101
102 if (!least) {
103 ip_vs_scheduler_err(svc, "no destination available");
104 return NULL;
105 }
106
107 out:
108 IP_VS_DBG_BUF(6, "NQ: server %s:%u "
109 "activeconns %d refcnt %d weight %d overhead %d\n",
110 IP_VS_DBG_ADDR(least->af, &least->addr),
111 ntohs(least->port),
112 atomic_read(&least->activeconns),
113 refcount_read(&least->refcnt),
114 atomic_read(&least->weight), loh);
115
116 return least;
117}
118
119
120static struct ip_vs_scheduler ip_vs_nq_scheduler =
121{
122 .name = "nq",
123 .refcnt = ATOMIC_INIT(0),
124 .module = THIS_MODULE,
125 .n_list = LIST_HEAD_INIT(ip_vs_nq_scheduler.n_list),
126 .schedule = ip_vs_nq_schedule,
127};
128
129
130static int __init ip_vs_nq_init(void)
131{
132 return register_ip_vs_scheduler(&ip_vs_nq_scheduler);
133}
134
135static void __exit ip_vs_nq_cleanup(void)
136{
137 unregister_ip_vs_scheduler(&ip_vs_nq_scheduler);
138 synchronize_rcu();
139}
140
141module_init(ip_vs_nq_init);
142module_exit(ip_vs_nq_cleanup);
143MODULE_LICENSE("GPL");
144