Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ip_vs_rr.c
Go to the documentation of this file.
1 /*
2  * IPVS: Round-Robin Scheduling module
3  *
4  * Authors: Wensong Zhang <[email protected]>
5  * Peter Kese <[email protected]>
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, "%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_scheduler_err(svc, "no destination available");
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");