1 /* 2 * IPVS: Round-Robin Scheduling module 3 * 4 * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> 5 * Peter Kese <peter.kese@ijs.si> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 10 * 2 of the License, or (at your option) any later version. 11 * 12 * Fixes/Changes: 13 * Wensong Zhang : changed the ip_vs_rr_schedule to return dest 14 * Julian Anastasov : fixed the NULL pointer access bug in debugging 15 * Wensong Zhang : changed some comestics things for debugging 16 * Wensong Zhang : changed for the d-linked destination list 17 * Wensong Zhang : added the ip_vs_rr_update_svc 18 * Wensong Zhang : added any dest with weight=0 is quiesced 19 * 20 */ 21 22 #define KMSG_COMPONENT "IPVS" 23 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 24 25 #include <linux/module.h> 26 #include <linux/kernel.h> 27 28 #include <net/ip_vs.h> 29 30 31 static int ip_vs_rr_init_svc(struct ip_vs_service *svc) 32 { 33 svc->sched_data = &svc->destinations; 34 return 0; 35 } 36 37 38 static int ip_vs_rr_update_svc(struct ip_vs_service *svc) 39 { 40 svc->sched_data = &svc->destinations; 41 return 0; 42 } 43 44 45 /* 46 * Round-Robin Scheduling 47 */ 48 static struct ip_vs_dest * 49 ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) 50 { 51 struct list_head *p, *q; 52 struct ip_vs_dest *dest; 53 54 IP_VS_DBG(6, "ip_vs_rr_schedule(): Scheduling...\n"); 55 56 write_lock(&svc->sched_lock); 57 p = (struct list_head *)svc->sched_data; 58 p = p->next; 59 q = p; 60 do { 61 /* skip list head */ 62 if (q == &svc->destinations) { 63 q = q->next; 64 continue; 65 } 66 67 dest = list_entry(q, struct ip_vs_dest, n_list); 68 if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) && 69 atomic_read(&dest->weight) > 0) 70 /* HIT */ 71 goto out; 72 q = q->next; 73 } while (q != p); 74 write_unlock(&svc->sched_lock); 75 IP_VS_ERR_RL("RR: no destination available\n"); 76 return NULL; 77 78 out: 79 svc->sched_data = q; 80 write_unlock(&svc->sched_lock); 81 IP_VS_DBG_BUF(6, "RR: server %s:%u " 82 "activeconns %d refcnt %d weight %d\n", 83 IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port), 84 atomic_read(&dest->activeconns), 85 atomic_read(&dest->refcnt), atomic_read(&dest->weight)); 86 87 return dest; 88 } 89 90 91 static struct ip_vs_scheduler ip_vs_rr_scheduler = { 92 .name = "rr", /* name */ 93 .refcnt = ATOMIC_INIT(0), 94 .module = THIS_MODULE, 95 .n_list = LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list), 96 .init_service = ip_vs_rr_init_svc, 97 .update_service = ip_vs_rr_update_svc, 98 .schedule = ip_vs_rr_schedule, 99 }; 100 101 static int __init ip_vs_rr_init(void) 102 { 103 return register_ip_vs_scheduler(&ip_vs_rr_scheduler); 104 } 105 106 static void __exit ip_vs_rr_cleanup(void) 107 { 108 unregister_ip_vs_scheduler(&ip_vs_rr_scheduler); 109 } 110 111 module_init(ip_vs_rr_init); 112 module_exit(ip_vs_rr_cleanup); 113 MODULE_LICENSE("GPL"); 114