xref: /openbmc/linux/net/netfilter/ipvs/ip_vs_fo.c (revision 23c2b932)
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");
80