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 31static int ip_vs_rr_init_svc(struct ip_vs_service *svc) 32{ 33 svc->sched_data = &svc->destinations; 34 return 0; 35} 36 37 38static 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 */ 48static struct ip_vs_dest * 49ip_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, "%s(): Scheduling...\n", __func__); 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 91static 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 101static int __init ip_vs_rr_init(void) 102{ 103 return register_ip_vs_scheduler(&ip_vs_rr_scheduler); 104} 105 106static void __exit ip_vs_rr_cleanup(void) 107{ 108 unregister_ip_vs_scheduler(&ip_vs_rr_scheduler); 109} 110 111module_init(ip_vs_rr_init); 112module_exit(ip_vs_rr_cleanup); 113MODULE_LICENSE("GPL"); 114