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