1616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis/* 2616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * IPVS: Weighted Fail Over module 3616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * 4616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * Authors: Kenny Mathis <kmathis@chokepoint.net> 5616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * 6616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * This program is free software; you can redistribute it and/or 7616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * modify it under the terms of the GNU General Public License 8616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * as published by the Free Software Foundation; either version 9616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * 2 of the License, or (at your option) any later version. 10616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * 11616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * Changes: 12616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * Kenny Mathis : added initial functionality based on weight 13616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * 14616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis */ 15616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 16616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis#define KMSG_COMPONENT "IPVS" 17616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 18616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 19616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis#include <linux/module.h> 20616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis#include <linux/kernel.h> 21616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 22616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis#include <net/ip_vs.h> 23616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 24616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis/* Weighted Fail Over Module */ 25616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathisstatic struct ip_vs_dest * 26616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathisip_vs_fo_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, 27616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis struct ip_vs_iphdr *iph) 28616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis{ 29616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis struct ip_vs_dest *dest, *hweight = NULL; 30616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis int hw = 0; /* Track highest weight */ 31616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 32616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis IP_VS_DBG(6, "ip_vs_fo_schedule(): Scheduling...\n"); 33616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 34616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis /* Basic failover functionality 35616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis * Find virtual server with highest weight and send it traffic 36616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis */ 37616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis list_for_each_entry_rcu(dest, &svc->destinations, n_list) { 38616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) && 39616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis atomic_read(&dest->weight) > hw) { 40616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis hweight = dest; 41616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis hw = atomic_read(&dest->weight); 42616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis } 43616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis } 44616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 45616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis if (hweight) { 46616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis IP_VS_DBG_BUF(6, "FO: server %s:%u activeconns %d weight %d\n", 474d316f3f9ae3d5fad8d3198eec0a4ef2511471d7Julian Anastasov IP_VS_DBG_ADDR(hweight->af, &hweight->addr), 48616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis ntohs(hweight->port), 49616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis atomic_read(&hweight->activeconns), 50616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis atomic_read(&hweight->weight)); 51616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis return hweight; 52616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis } 53616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 54616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis ip_vs_scheduler_err(svc, "no destination available"); 55616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis return NULL; 56616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis} 57616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 58616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathisstatic struct ip_vs_scheduler ip_vs_fo_scheduler = { 59616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis .name = "fo", 60616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis .refcnt = ATOMIC_INIT(0), 61616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis .module = THIS_MODULE, 62616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis .n_list = LIST_HEAD_INIT(ip_vs_fo_scheduler.n_list), 63616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis .schedule = ip_vs_fo_schedule, 64616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis}; 65616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 66616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathisstatic int __init ip_vs_fo_init(void) 67616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis{ 68616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis return register_ip_vs_scheduler(&ip_vs_fo_scheduler); 69616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis} 70616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 71616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathisstatic void __exit ip_vs_fo_cleanup(void) 72616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis{ 73616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis unregister_ip_vs_scheduler(&ip_vs_fo_scheduler); 74616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis synchronize_rcu(); 75616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis} 76616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathis 77616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathismodule_init(ip_vs_fo_init); 78616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny Mathismodule_exit(ip_vs_fo_cleanup); 79616a9be25cb9516e546c0de55d61e1e46e54ade9Kenny MathisMODULE_LICENSE("GPL"); 80