1 /* 2 * IPVS: Least-Connection Scheduling module 3 * 4 * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> 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 * Wensong Zhang : added the ip_vs_lc_update_svc 13 * Wensong Zhang : added any dest with weight=0 is quiesced 14 * 15 */ 16 17 #define KMSG_COMPONENT "IPVS" 18 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 19 20 #include <linux/module.h> 21 #include <linux/kernel.h> 22 23 #include <net/ip_vs.h> 24 25 /* 26 * Least Connection scheduling 27 */ 28 static struct ip_vs_dest * 29 ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) 30 { 31 struct ip_vs_dest *dest, *least = NULL; 32 unsigned int loh = 0, doh; 33 34 IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); 35 36 /* 37 * Simply select the server with the least number of 38 * (activeconns<<5) + inactconns 39 * Except whose weight is equal to zero. 40 * If the weight is equal to zero, it means that the server is 41 * quiesced, the existing connections to the server still get 42 * served, but no new connection is assigned to the server. 43 */ 44 45 list_for_each_entry(dest, &svc->destinations, n_list) { 46 if ((dest->flags & IP_VS_DEST_F_OVERLOAD) || 47 atomic_read(&dest->weight) == 0) 48 continue; 49 doh = ip_vs_dest_conn_overhead(dest); 50 if (!least || doh < loh) { 51 least = dest; 52 loh = doh; 53 } 54 } 55 56 if (!least) 57 ip_vs_scheduler_err(svc, "no destination available"); 58 else 59 IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d " 60 "inactconns %d\n", 61 IP_VS_DBG_ADDR(svc->af, &least->addr), 62 ntohs(least->port), 63 atomic_read(&least->activeconns), 64 atomic_read(&least->inactconns)); 65 66 return least; 67 } 68 69 70 static struct ip_vs_scheduler ip_vs_lc_scheduler = { 71 .name = "lc", 72 .refcnt = ATOMIC_INIT(0), 73 .module = THIS_MODULE, 74 .n_list = LIST_HEAD_INIT(ip_vs_lc_scheduler.n_list), 75 .schedule = ip_vs_lc_schedule, 76 }; 77 78 79 static int __init ip_vs_lc_init(void) 80 { 81 return register_ip_vs_scheduler(&ip_vs_lc_scheduler) ; 82 } 83 84 static void __exit ip_vs_lc_cleanup(void) 85 { 86 unregister_ip_vs_scheduler(&ip_vs_lc_scheduler); 87 } 88 89 module_init(ip_vs_lc_init); 90 module_exit(ip_vs_lc_cleanup); 91 MODULE_LICENSE("GPL"); 92