Merge tag 'Wimplicit-fallthrough-clang-5.14-rc1' of git://git.kernel.org/pub/scm...
[linux-2.6-microblaze.git] / net / netfilter / ipvs / ip_vs_fo.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * IPVS:        Weighted Fail Over module
4  *
5  * Authors:     Kenny Mathis <kmathis@chokepoint.net>
6  *
7  * Changes:
8  *     Kenny Mathis            :     added initial functionality based on weight
9  */
10
11 #define KMSG_COMPONENT "IPVS"
12 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
13
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16
17 #include <net/ip_vs.h>
18
19 /* Weighted Fail Over Module */
20 static struct ip_vs_dest *
21 ip_vs_fo_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
22                   struct ip_vs_iphdr *iph)
23 {
24         struct ip_vs_dest *dest, *hweight = NULL;
25         int hw = 0; /* Track highest weight */
26
27         IP_VS_DBG(6, "ip_vs_fo_schedule(): Scheduling...\n");
28
29         /* Basic failover functionality
30          * Find virtual server with highest weight and send it traffic
31          */
32         list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
33                 if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
34                     atomic_read(&dest->weight) > hw) {
35                         hweight = dest;
36                         hw = atomic_read(&dest->weight);
37                 }
38         }
39
40         if (hweight) {
41                 IP_VS_DBG_BUF(6, "FO: server %s:%u activeconns %d weight %d\n",
42                               IP_VS_DBG_ADDR(hweight->af, &hweight->addr),
43                               ntohs(hweight->port),
44                               atomic_read(&hweight->activeconns),
45                               atomic_read(&hweight->weight));
46                 return hweight;
47         }
48
49         ip_vs_scheduler_err(svc, "no destination available");
50         return NULL;
51 }
52
53 static struct ip_vs_scheduler ip_vs_fo_scheduler = {
54         .name =                 "fo",
55         .refcnt =               ATOMIC_INIT(0),
56         .module =               THIS_MODULE,
57         .n_list =               LIST_HEAD_INIT(ip_vs_fo_scheduler.n_list),
58         .schedule =             ip_vs_fo_schedule,
59 };
60
61 static int __init ip_vs_fo_init(void)
62 {
63         return register_ip_vs_scheduler(&ip_vs_fo_scheduler);
64 }
65
66 static void __exit ip_vs_fo_cleanup(void)
67 {
68         unregister_ip_vs_scheduler(&ip_vs_fo_scheduler);
69         synchronize_rcu();
70 }
71
72 module_init(ip_vs_fo_init);
73 module_exit(ip_vs_fo_cleanup);
74 MODULE_LICENSE("GPL");