FILE
ip_vs_wlc.c
File preview with syntax highlighting.
linux-6.19.14/net/netfilter/ipvs/ip_vs_wlc.c
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * IPVS: Weighted Least-Connection Scheduling module 4 * 5 * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> 6 * Peter Kese <peter.kese@ijs.si> 7 * 8 * Changes: 9 * Wensong Zhang : changed the ip_vs_wlc_schedule to return dest 10 * Wensong Zhang : changed to use the inactconns in scheduling 11 * Wensong Zhang : changed some comestics things for debugging 12 * Wensong Zhang : changed for the d-linked destination list 13 * Wensong Zhang : added the ip_vs_wlc_update_svc 14 * Wensong Zhang : added any dest with weight=0 is quiesced 15 */ 16 17#define pr_fmt(fmt) "IPVS: " fmt 18 19#include <linux/module.h> 20#include <linux/kernel.h> 21 22#include <net/ip_vs.h> 23 24/* 25 * Weighted Least Connection scheduling 26 */ 27static struct ip_vs_dest * 28ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, 29 struct ip_vs_iphdr *iph) 30{ 31 struct ip_vs_dest *dest, *least; 32 int loh, doh; 33 34 IP_VS_DBG(6, "ip_vs_wlc_schedule(): Scheduling...\n"); 35 36 /* 37 * We calculate the load of each dest server as follows: 38 * (dest overhead) / dest->weight 39 * 40 * Remember -- no floats in kernel mode!!! 41 * The comparison of h1*w2 > h2*w1 is equivalent to that of 42 * h1/w1 > h2/w2 43 * if every weight is larger than zero. 44 * 45 * The server with weight=0 is quiesced and will not receive any 46 * new connections. 47 */ 48 49 list_for_each_entry_rcu(dest, &svc->destinations, n_list) { 50 if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) && 51 atomic_read(&dest->weight) > 0) { 52 least = dest; 53 loh = ip_vs_dest_conn_overhead(least); 54 goto nextstage; 55 } 56 } 57 ip_vs_scheduler_err(svc, "no destination available"); 58 return NULL; 59 60 /* 61 * Find the destination with the least load. 62 */ 63 nextstage: 64 list_for_each_entry_continue_rcu(dest, &svc->destinations, n_list) { 65 if (dest->flags & IP_VS_DEST_F_OVERLOAD) 66 continue; 67 doh = ip_vs_dest_conn_overhead(dest); 68 if ((__s64)loh * atomic_read(&dest->weight) > 69 (__s64)doh * atomic_read(&least->weight)) { 70 least = dest; 71 loh = doh; 72 } 73 } 74 75 IP_VS_DBG_BUF(6, "WLC: server %s:%u " 76 "activeconns %d refcnt %d weight %d overhead %d\n", 77 IP_VS_DBG_ADDR(least->af, &least->addr), 78 ntohs(least->port), 79 atomic_read(&least->activeconns), 80 refcount_read(&least->refcnt), 81 atomic_read(&least->weight), loh); 82 83 return least; 84} 85 86 87static struct ip_vs_scheduler ip_vs_wlc_scheduler = 88{ 89 .name = "wlc", 90 .refcnt = ATOMIC_INIT(0), 91 .module = THIS_MODULE, 92 .n_list = LIST_HEAD_INIT(ip_vs_wlc_scheduler.n_list), 93 .schedule = ip_vs_wlc_schedule, 94}; 95 96 97static int __init ip_vs_wlc_init(void) 98{ 99 return register_ip_vs_scheduler(&ip_vs_wlc_scheduler); 100} 101 102static void __exit ip_vs_wlc_cleanup(void) 103{ 104 unregister_ip_vs_scheduler(&ip_vs_wlc_scheduler); 105 synchronize_rcu(); 106} 107 108module_init(ip_vs_wlc_init); 109module_exit(ip_vs_wlc_cleanup); 110MODULE_LICENSE("GPL"); 111MODULE_DESCRIPTION("ipvs weighted least connection scheduler");
~/
Read-only file preview.