OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [ipv4/] [ipvs/] [ip_vs_wrr.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * IPVS:        Weighted Round-Robin Scheduling module
3
 *
4
 * Version:     $Id: ip_vs_wrr.c,v 1.1.1.1 2004-04-15 01:14:05 phoenix Exp $
5
 *
6
 * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
7
 *
8
 *              This program is free software; you can redistribute it and/or
9
 *              modify it under the terms of the GNU General Public License
10
 *              as published by the Free Software Foundation; either version
11
 *              2 of the License, or (at your option) any later version.
12
 *
13
 * Changes:
14
 *     Wensong Zhang            :     changed the ip_vs_wrr_schedule to return dest
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_wrr_update_svc
18
 *     Julian Anastasov         :     fixed the bug of returning destination
19
 *                                    with weight 0 when all weights are zero
20
 *
21
 */
22
 
23
#include <linux/module.h>
24
#include <linux/kernel.h>
25
 
26
#include <net/ip_vs.h>
27
 
28
/*
29
 * current destination pointer for weighted round-robin scheduling
30
 */
31
struct ip_vs_wrr_mark {
32
        struct list_head *cl;   /* current list head */
33
        int cw;                 /* current weight */
34
        int mw;                 /* maximum weight */
35
        int di;                 /* decreasing interval */
36
};
37
 
38
 
39
/*
40
 *    Get the gcd of server weights
41
 */
42
static int gcd(int a, int b)
43
{
44
        int c;
45
 
46
        while ((c = a % b)) {
47
                a = b;
48
                b = c;
49
        }
50
        return b;
51
}
52
 
53
static int ip_vs_wrr_gcd_weight(struct ip_vs_service *svc)
54
{
55
        register struct list_head *l, *e;
56
        struct ip_vs_dest *dest;
57
        int weight;
58
        int g = 1;
59
 
60
        l = &svc->destinations;
61
        for (e=l->next; e!=l; e=e->next) {
62
                dest = list_entry(e, struct ip_vs_dest, n_list);
63
                weight = atomic_read(&dest->weight);
64
                if (weight > 0) {
65
                        g = weight;
66
                        break;
67
                }
68
        }
69
        if (e == l)
70
                return g;
71
 
72
        for (e=e->next; e!=l; e=e->next) {
73
                dest = list_entry(e, struct ip_vs_dest, n_list);
74
                weight = atomic_read(&dest->weight);
75
                if (weight > 0)
76
                        g = gcd(weight, g);
77
        }
78
 
79
        return g;
80
}
81
 
82
 
83
/*
84
 *    Get the maximum weight of the service destinations.
85
 */
86
static int ip_vs_wrr_max_weight(struct ip_vs_service *svc)
87
{
88
        register struct list_head *l, *e;
89
        struct ip_vs_dest *dest;
90
        int weight = 0;
91
 
92
        l = &svc->destinations;
93
        for (e=l->next; e!=l; e=e->next) {
94
                dest = list_entry(e, struct ip_vs_dest, n_list);
95
                if (atomic_read(&dest->weight) > weight)
96
                        weight = atomic_read(&dest->weight);
97
        }
98
 
99
        return weight;
100
}
101
 
102
 
103
static int ip_vs_wrr_init_svc(struct ip_vs_service *svc)
104
{
105
        struct ip_vs_wrr_mark *mark;
106
 
107
        /*
108
         *    Allocate the mark variable for WRR scheduling
109
         */
110
        mark = kmalloc(sizeof(struct ip_vs_wrr_mark), GFP_ATOMIC);
111
        if (mark == NULL) {
112
                IP_VS_ERR("ip_vs_wrr_init_svc(): no memory\n");
113
                return -ENOMEM;
114
        }
115
        mark->cl = &svc->destinations;
116
        mark->cw = 0;
117
        mark->mw = ip_vs_wrr_max_weight(svc);
118
        mark->di = ip_vs_wrr_gcd_weight(svc);
119
        svc->sched_data = mark;
120
 
121
        return 0;
122
}
123
 
124
 
125
static int ip_vs_wrr_done_svc(struct ip_vs_service *svc)
126
{
127
        /*
128
         *    Release the mark variable
129
         */
130
        kfree(svc->sched_data);
131
 
132
        return 0;
133
}
134
 
135
 
136
static int ip_vs_wrr_update_svc(struct ip_vs_service *svc)
137
{
138
        struct ip_vs_wrr_mark *mark = svc->sched_data;
139
 
140
        mark->cl = &svc->destinations;
141
        mark->mw = ip_vs_wrr_max_weight(svc);
142
        mark->di = ip_vs_wrr_gcd_weight(svc);
143
        return 0;
144
}
145
 
146
 
147
/*
148
 *    Weighted Round-Robin Scheduling
149
 */
150
static struct ip_vs_dest *
151
ip_vs_wrr_schedule(struct ip_vs_service *svc, struct iphdr *iph)
152
{
153
        struct ip_vs_dest *dest;
154
        struct ip_vs_wrr_mark *mark = svc->sched_data;
155
 
156
        IP_VS_DBG(6, "ip_vs_wrr_schedule(): Scheduling...\n");
157
 
158
        /*
159
         * This loop will always terminate, because 0<mark->cw<max_weight,
160
         * and at least one server has its weight equal to max_weight.
161
         */
162
        write_lock(&svc->sched_lock);
163
        while (1) {
164
                if (mark->cl == &svc->destinations) {
165
                        /* it is at the head of the destination list */
166
 
167
                        if (mark->cl == mark->cl->next) {
168
                                /* no dest entry */
169
                                write_unlock(&svc->sched_lock);
170
                                return NULL;
171
                        }
172
 
173
                        mark->cl = svc->destinations.next;
174
                        mark->cw -= mark->di;
175
                        if (mark->cw <= 0) {
176
                                mark->cw = mark->mw;
177
                                /*
178
                                 * Still zero, which means no availabe servers.
179
                                 */
180
                                if (mark->cw == 0) {
181
                                        mark->cl = &svc->destinations;
182
                                        write_unlock(&svc->sched_lock);
183
                                        IP_VS_INFO("ip_vs_wrr_schedule(): "
184
                                                   "no available servers\n");
185
                                        return NULL;
186
                                }
187
                        }
188
                }
189
                else mark->cl = mark->cl->next;
190
 
191
                if (mark->cl != &svc->destinations) {
192
                        /* not at the head of the list */
193
                        dest = list_entry(mark->cl, struct ip_vs_dest, n_list);
194
                        if (atomic_read(&dest->weight) >= mark->cw) {
195
                                write_unlock(&svc->sched_lock);
196
                                break;
197
                        }
198
                }
199
        }
200
 
201
        IP_VS_DBG(6, "WRR: server %u.%u.%u.%u:%u "
202
                  "activeconns %d refcnt %d weight %d\n",
203
                  NIPQUAD(dest->addr), ntohs(dest->port),
204
                  atomic_read(&dest->activeconns),
205
                  atomic_read(&dest->refcnt),
206
                  atomic_read(&dest->weight));
207
 
208
        return  dest;
209
}
210
 
211
 
212
static struct ip_vs_scheduler ip_vs_wrr_scheduler = {
213
        {0},                     /* n_list */
214
        "wrr",                  /* name */
215
        ATOMIC_INIT(0),          /* refcnt */
216
        THIS_MODULE,            /* this module */
217
        ip_vs_wrr_init_svc,     /* service initializer */
218
        ip_vs_wrr_done_svc,     /* service done */
219
        ip_vs_wrr_update_svc,   /* service updater */
220
        ip_vs_wrr_schedule,     /* select a server from the destination list */
221
};
222
 
223
static int __init ip_vs_wrr_init(void)
224
{
225
        INIT_LIST_HEAD(&ip_vs_wrr_scheduler.n_list);
226
        return register_ip_vs_scheduler(&ip_vs_wrr_scheduler) ;
227
}
228
 
229
static void __exit ip_vs_wrr_cleanup(void)
230
{
231
        unregister_ip_vs_scheduler(&ip_vs_wrr_scheduler);
232
}
233
 
234
module_init(ip_vs_wrr_init);
235
module_exit(ip_vs_wrr_cleanup);
236
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.