FILE
ip_vs_rr.c
File preview with syntax highlighting.
linux-6.19.14/net/netfilter/ipvs/ip_vs_rr.c
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * IPVS: Round-Robin Scheduling module 4 * 5 * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> 6 * Peter Kese <peter.kese@ijs.si> 7 * 8 * Fixes/Changes: 9 * Wensong Zhang : changed the ip_vs_rr_schedule to return dest 10 * Julian Anastasov : fixed the NULL pointer access bug in debugging 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_rr_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 25static int ip_vs_rr_init_svc(struct ip_vs_service *svc) 26{ 27 svc->sched_data = &svc->destinations; 28 return 0; 29} 30 31 32static int ip_vs_rr_del_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest) 33{ 34 struct list_head *p; 35 36 spin_lock_bh(&svc->sched_lock); 37 p = (struct list_head *) svc->sched_data; 38 /* dest is already unlinked, so p->prev is not valid but 39 * p->next is valid, use it to reach previous entry. 40 */ 41 if (p == &dest->n_list) 42 svc->sched_data = p->next->prev; 43 spin_unlock_bh(&svc->sched_lock); 44 return 0; 45} 46 47 48/* 49 * Round-Robin Scheduling 50 */ 51static struct ip_vs_dest * 52ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, 53 struct ip_vs_iphdr *iph) 54{ 55 struct list_head *p; 56 struct ip_vs_dest *dest, *last; 57 int pass = 0; 58 59 IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); 60 61 spin_lock_bh(&svc->sched_lock); 62 p = (struct list_head *) svc->sched_data; 63 last = dest = list_entry(p, struct ip_vs_dest, n_list); 64 65 do { 66 list_for_each_entry_continue_rcu(dest, 67 &svc->destinations, 68 n_list) { 69 if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) && 70 atomic_read(&dest->weight) > 0) 71 /* HIT */ 72 goto out; 73 if (dest == last) 74 goto stop; 75 } 76 pass++; 77 /* Previous dest could be unlinked, do not loop forever. 78 * If we stay at head there is no need for 2nd pass. 79 */ 80 } while (pass < 2 && p != &svc->destinations); 81 82stop: 83 spin_unlock_bh(&svc->sched_lock); 84 ip_vs_scheduler_err(svc, "no destination available"); 85 return NULL; 86 87 out: 88 svc->sched_data = &dest->n_list; 89 spin_unlock_bh(&svc->sched_lock); 90 IP_VS_DBG_BUF(6, "RR: server %s:%u " 91 "activeconns %d refcnt %d weight %d\n", 92 IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port), 93 atomic_read(&dest->activeconns), 94 refcount_read(&dest->refcnt), atomic_read(&dest->weight)); 95 96 return dest; 97} 98 99 100static struct ip_vs_scheduler ip_vs_rr_scheduler = { 101 .name = "rr", /* name */ 102 .refcnt = ATOMIC_INIT(0), 103 .module = THIS_MODULE, 104 .n_list = LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list), 105 .init_service = ip_vs_rr_init_svc, 106 .add_dest = NULL, 107 .del_dest = ip_vs_rr_del_dest, 108 .schedule = ip_vs_rr_schedule, 109}; 110 111static int __init ip_vs_rr_init(void) 112{ 113 return register_ip_vs_scheduler(&ip_vs_rr_scheduler); 114} 115 116static void __exit ip_vs_rr_cleanup(void) 117{ 118 unregister_ip_vs_scheduler(&ip_vs_rr_scheduler); 119 synchronize_rcu(); 120} 121 122module_init(ip_vs_rr_init); 123module_exit(ip_vs_rr_cleanup); 124MODULE_DESCRIPTION("ipvs round-robin scheduler"); 125MODULE_LICENSE("GPL");
~/
Read-only file preview.