Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / net / netfilter / ipvs / ip_vs_fo.c
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(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
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");