blob: 20e3a040da6250f0a0244501e029ddc3f99b7889 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Backend variables and functions.
3 *
Willy Tarreaue8c66af2008-01-13 18:40:14 +01004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <errno.h>
14#include <fcntl.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <syslog.h>
Willy Tarreauf19cf372006-11-14 15:40:51 +010018#include <string.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020019
Willy Tarreau2dd0d472006-06-29 17:53:05 +020020#include <common/compat.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020021#include <common/config.h>
Willy Tarreaub625a082007-11-26 01:15:43 +010022#include <common/eb32tree.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020023#include <common/time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020024
Willy Tarreaua9d3c1e2007-11-30 20:48:53 +010025#include <types/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020026#include <types/buffers.h>
27#include <types/global.h>
28#include <types/polling.h>
29#include <types/proxy.h>
30#include <types/server.h>
31#include <types/session.h>
32
Willy Tarreaua9d3c1e2007-11-30 20:48:53 +010033#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034#include <proto/backend.h>
Willy Tarreau14c8aac2007-05-08 19:46:30 +020035#include <proto/client.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <proto/fd.h>
Willy Tarreau80587432006-12-24 17:47:20 +010037#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038#include <proto/log.h>
39#include <proto/proto_http.h>
Willy Tarreaue8c66af2008-01-13 18:40:14 +010040#include <proto/proto_tcp.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/queue.h>
42#include <proto/stream_sock.h>
43#include <proto/task.h>
44
Willy Tarreau6d1a9882007-01-07 02:03:04 +010045#ifdef CONFIG_HAP_TCPSPLICE
46#include <libtcpsplice.h>
47#endif
48
Willy Tarreaub625a082007-11-26 01:15:43 +010049static inline void fwrr_remove_from_tree(struct server *s);
50static inline void fwrr_queue_by_weight(struct eb_root *root, struct server *s);
51static inline void fwrr_dequeue_srv(struct server *s);
52static void fwrr_get_srv(struct server *s);
53static void fwrr_queue_srv(struct server *s);
54
55/* This function returns non-zero if a server with the given weight and state
56 * is usable for LB, otherwise zero.
57 */
58static inline int srv_is_usable(int state, int weight)
59{
60 if (!weight)
61 return 0;
Willy Tarreau48494c02007-11-30 10:41:39 +010062 if (state & SRV_GOINGDOWN)
63 return 0;
Willy Tarreaub625a082007-11-26 01:15:43 +010064 if (!(state & SRV_RUNNING))
65 return 0;
66 return 1;
67}
68
Willy Tarreaubaaee002006-06-26 02:48:02 +020069/*
70 * This function recounts the number of usable active and backup servers for
71 * proxy <p>. These numbers are returned into the p->srv_act and p->srv_bck.
Willy Tarreaub625a082007-11-26 01:15:43 +010072 * This function also recomputes the total active and backup weights. However,
73 * it does nout update tot_weight nor tot_used. Use update_backend_weight() for
74 * this.
Willy Tarreaubaaee002006-06-26 02:48:02 +020075 */
Willy Tarreaub625a082007-11-26 01:15:43 +010076static void recount_servers(struct proxy *px)
Willy Tarreaubaaee002006-06-26 02:48:02 +020077{
78 struct server *srv;
79
Willy Tarreau20697042007-11-15 23:26:18 +010080 px->srv_act = px->srv_bck = 0;
81 px->lbprm.tot_wact = px->lbprm.tot_wbck = 0;
Willy Tarreaub625a082007-11-26 01:15:43 +010082 px->lbprm.fbck = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +020083 for (srv = px->srv; srv != NULL; srv = srv->next) {
Willy Tarreaub625a082007-11-26 01:15:43 +010084 if (!srv_is_usable(srv->state, srv->eweight))
85 continue;
86
87 if (srv->state & SRV_BACKUP) {
88 if (!px->srv_bck &&
Willy Tarreau31682232007-11-29 15:38:04 +010089 !(px->lbprm.algo & PR_O_USE_ALL_BK))
Willy Tarreaub625a082007-11-26 01:15:43 +010090 px->lbprm.fbck = srv;
91 px->srv_bck++;
92 px->lbprm.tot_wbck += srv->eweight;
93 } else {
94 px->srv_act++;
95 px->lbprm.tot_wact += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +020096 }
97 }
Willy Tarreaub625a082007-11-26 01:15:43 +010098}
Willy Tarreau20697042007-11-15 23:26:18 +010099
Willy Tarreaub625a082007-11-26 01:15:43 +0100100/* This function simply updates the backend's tot_weight and tot_used values
101 * after servers weights have been updated. It is designed to be used after
102 * recount_servers() or equivalent.
103 */
104static void update_backend_weight(struct proxy *px)
105{
Willy Tarreau20697042007-11-15 23:26:18 +0100106 if (px->srv_act) {
107 px->lbprm.tot_weight = px->lbprm.tot_wact;
108 px->lbprm.tot_used = px->srv_act;
109 }
Willy Tarreaub625a082007-11-26 01:15:43 +0100110 else if (px->lbprm.fbck) {
111 /* use only the first backup server */
112 px->lbprm.tot_weight = px->lbprm.fbck->eweight;
113 px->lbprm.tot_used = 1;
Willy Tarreau20697042007-11-15 23:26:18 +0100114 }
115 else {
Willy Tarreaub625a082007-11-26 01:15:43 +0100116 px->lbprm.tot_weight = px->lbprm.tot_wbck;
117 px->lbprm.tot_used = px->srv_bck;
Willy Tarreau20697042007-11-15 23:26:18 +0100118 }
Willy Tarreaub625a082007-11-26 01:15:43 +0100119}
120
121/* this function updates the map according to server <srv>'s new state */
122static void map_set_server_status_down(struct server *srv)
123{
124 struct proxy *p = srv->proxy;
125
126 if (srv->state == srv->prev_state &&
127 srv->eweight == srv->prev_eweight)
128 return;
129
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100130 if (srv_is_usable(srv->state, srv->eweight))
131 goto out_update_state;
132
Willy Tarreaub625a082007-11-26 01:15:43 +0100133 /* FIXME: could be optimized since we know what changed */
134 recount_servers(p);
135 update_backend_weight(p);
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100136 p->lbprm.map.state |= PR_MAP_RECALC;
137 out_update_state:
Willy Tarreaub625a082007-11-26 01:15:43 +0100138 srv->prev_state = srv->state;
139 srv->prev_eweight = srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200140}
141
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100142/* This function updates the map according to server <srv>'s new state */
Willy Tarreaub625a082007-11-26 01:15:43 +0100143static void map_set_server_status_up(struct server *srv)
144{
145 struct proxy *p = srv->proxy;
146
147 if (srv->state == srv->prev_state &&
148 srv->eweight == srv->prev_eweight)
149 return;
150
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100151 if (!srv_is_usable(srv->state, srv->eweight))
152 goto out_update_state;
153
Willy Tarreaub625a082007-11-26 01:15:43 +0100154 /* FIXME: could be optimized since we know what changed */
155 recount_servers(p);
156 update_backend_weight(p);
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100157 p->lbprm.map.state |= PR_MAP_RECALC;
158 out_update_state:
Willy Tarreaub625a082007-11-26 01:15:43 +0100159 srv->prev_state = srv->state;
160 srv->prev_eweight = srv->eweight;
Willy Tarreaub625a082007-11-26 01:15:43 +0100161}
162
Willy Tarreau20697042007-11-15 23:26:18 +0100163/* This function recomputes the server map for proxy px. It relies on
164 * px->lbprm.tot_wact, tot_wbck, tot_used, tot_weight, so it must be
165 * called after recount_servers(). It also expects px->lbprm.map.srv
166 * to be allocated with the largest size needed. It updates tot_weight.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167 */
168void recalc_server_map(struct proxy *px)
169{
170 int o, tot, flag;
171 struct server *cur, *best;
172
Willy Tarreau20697042007-11-15 23:26:18 +0100173 switch (px->lbprm.tot_used) {
174 case 0: /* no server */
175 px->lbprm.map.state &= ~PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176 return;
Willy Tarreau20697042007-11-15 23:26:18 +0100177 case 1: /* only one server, just fill first entry */
178 tot = 1;
179 break;
180 default:
181 tot = px->lbprm.tot_weight;
182 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183 }
184
Willy Tarreau20697042007-11-15 23:26:18 +0100185 /* here we *know* that we have some servers */
186 if (px->srv_act)
187 flag = SRV_RUNNING;
188 else
189 flag = SRV_RUNNING | SRV_BACKUP;
190
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191 /* this algorithm gives priority to the first server, which means that
192 * it will respect the declaration order for equivalent weights, and
193 * that whatever the weights, the first server called will always be
Willy Tarreau20697042007-11-15 23:26:18 +0100194 * the first declared. This is an important asumption for the backup
Willy Tarreaubaaee002006-06-26 02:48:02 +0200195 * case, where we want the first server only.
196 */
197 for (cur = px->srv; cur; cur = cur->next)
198 cur->wscore = 0;
199
200 for (o = 0; o < tot; o++) {
201 int max = 0;
202 best = NULL;
203 for (cur = px->srv; cur; cur = cur->next) {
Willy Tarreau48494c02007-11-30 10:41:39 +0100204 if (flag == (cur->state &
205 (SRV_RUNNING | SRV_GOINGDOWN | SRV_BACKUP))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206 int v;
207
208 /* If we are forced to return only one server, we don't want to
209 * go further, because we would return the wrong one due to
210 * divide overflow.
211 */
212 if (tot == 1) {
213 best = cur;
Willy Tarreau20697042007-11-15 23:26:18 +0100214 /* note that best->wscore will be wrong but we don't care */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 break;
216 }
217
Willy Tarreau417fae02007-03-25 21:16:40 +0200218 cur->wscore += cur->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 v = (cur->wscore + tot) / tot; /* result between 0 and 3 */
220 if (best == NULL || v > max) {
221 max = v;
222 best = cur;
223 }
224 }
225 }
Willy Tarreau20697042007-11-15 23:26:18 +0100226 px->lbprm.map.srv[o] = best;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 best->wscore -= tot;
228 }
Willy Tarreau20697042007-11-15 23:26:18 +0100229 px->lbprm.map.state &= ~PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230}
231
Willy Tarreau5dc2fa62007-11-19 19:10:18 +0100232/* This function is responsible of building the server MAP for map-based LB
233 * algorithms, allocating the map, and setting p->lbprm.wmult to the GCD of the
234 * weights if applicable. It should be called only once per proxy, at config
235 * time.
236 */
237void init_server_map(struct proxy *p)
238{
239 struct server *srv;
240 int pgcd;
241 int act, bck;
242
Willy Tarreaub625a082007-11-26 01:15:43 +0100243 p->lbprm.set_server_status_up = map_set_server_status_up;
244 p->lbprm.set_server_status_down = map_set_server_status_down;
245 p->lbprm.update_server_eweight = NULL;
246
Willy Tarreau5dc2fa62007-11-19 19:10:18 +0100247 if (!p->srv)
248 return;
249
250 /* We will factor the weights to reduce the table,
251 * using Euclide's largest common divisor algorithm
252 */
253 pgcd = p->srv->uweight;
254 for (srv = p->srv->next; srv && pgcd > 1; srv = srv->next) {
255 int w = srv->uweight;
256 while (w) {
257 int t = pgcd % w;
258 pgcd = w;
259 w = t;
260 }
261 }
262
263 /* It is sometimes useful to know what factor to apply
264 * to the backend's effective weight to know its real
265 * weight.
266 */
267 p->lbprm.wmult = pgcd;
268
269 act = bck = 0;
270 for (srv = p->srv; srv; srv = srv->next) {
271 srv->eweight = srv->uweight / pgcd;
Willy Tarreaub625a082007-11-26 01:15:43 +0100272 srv->prev_eweight = srv->eweight;
273 srv->prev_state = srv->state;
Willy Tarreau5dc2fa62007-11-19 19:10:18 +0100274 if (srv->state & SRV_BACKUP)
275 bck += srv->eweight;
276 else
277 act += srv->eweight;
278 }
279
280 /* this is the largest map we will ever need for this servers list */
281 if (act < bck)
282 act = bck;
283
284 p->lbprm.map.srv = (struct server **)calloc(act, sizeof(struct server *));
285 /* recounts servers and their weights */
286 p->lbprm.map.state = PR_MAP_RECALC;
287 recount_servers(p);
Willy Tarreaub625a082007-11-26 01:15:43 +0100288 update_backend_weight(p);
Willy Tarreau5dc2fa62007-11-19 19:10:18 +0100289 recalc_server_map(p);
290}
291
Willy Tarreaub625a082007-11-26 01:15:43 +0100292/* This function updates the server trees according to server <srv>'s new
293 * state. It should be called when server <srv>'s status changes to down.
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100294 * It is not important whether the server was already down or not. It is not
295 * important either that the new state is completely down (the caller may not
296 * know all the variables of a server's state).
Willy Tarreaub625a082007-11-26 01:15:43 +0100297 */
298static void fwrr_set_server_status_down(struct server *srv)
299{
300 struct proxy *p = srv->proxy;
301 struct fwrr_group *grp;
302
303 if (srv->state == srv->prev_state &&
304 srv->eweight == srv->prev_eweight)
305 return;
306
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100307 if (srv_is_usable(srv->state, srv->eweight))
308 goto out_update_state;
309
Willy Tarreaub625a082007-11-26 01:15:43 +0100310 if (!srv_is_usable(srv->prev_state, srv->prev_eweight))
311 /* server was already down */
312 goto out_update_backend;
313
314 grp = (srv->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
315 grp->next_weight -= srv->prev_eweight;
316
317 if (srv->state & SRV_BACKUP) {
318 p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
319 p->srv_bck--;
320
321 if (srv == p->lbprm.fbck) {
322 /* we lost the first backup server in a single-backup
323 * configuration, we must search another one.
324 */
325 struct server *srv2 = p->lbprm.fbck;
326 do {
327 srv2 = srv2->next;
328 } while (srv2 &&
329 !((srv2->state & SRV_BACKUP) &&
330 srv_is_usable(srv2->state, srv2->eweight)));
331 p->lbprm.fbck = srv2;
332 }
333 } else {
334 p->lbprm.tot_wact = p->lbprm.fwrr.act.next_weight;
335 p->srv_act--;
336 }
337
338 fwrr_dequeue_srv(srv);
339 fwrr_remove_from_tree(srv);
340
341out_update_backend:
342 /* check/update tot_used, tot_weight */
343 update_backend_weight(p);
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100344 out_update_state:
Willy Tarreaub625a082007-11-26 01:15:43 +0100345 srv->prev_state = srv->state;
346 srv->prev_eweight = srv->eweight;
Willy Tarreaub625a082007-11-26 01:15:43 +0100347}
348
349/* This function updates the server trees according to server <srv>'s new
350 * state. It should be called when server <srv>'s status changes to up.
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100351 * It is not important whether the server was already down or not. It is not
352 * important either that the new state is completely UP (the caller may not
353 * know all the variables of a server's state). This function will not change
Willy Tarreaub625a082007-11-26 01:15:43 +0100354 * the weight of a server which was already up.
355 */
356static void fwrr_set_server_status_up(struct server *srv)
357{
358 struct proxy *p = srv->proxy;
359 struct fwrr_group *grp;
360
361 if (srv->state == srv->prev_state &&
362 srv->eweight == srv->prev_eweight)
363 return;
364
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100365 if (!srv_is_usable(srv->state, srv->eweight))
366 goto out_update_state;
367
Willy Tarreaub625a082007-11-26 01:15:43 +0100368 if (srv_is_usable(srv->prev_state, srv->prev_eweight))
369 /* server was already up */
370 goto out_update_backend;
371
372 grp = (srv->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
373 grp->next_weight += srv->eweight;
374
375 if (srv->state & SRV_BACKUP) {
376 p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
377 p->srv_bck++;
378
379 if (p->lbprm.fbck) {
380 /* we may have restored a backup server prior to fbck,
381 * in which case it should replace it.
382 */
383 struct server *srv2 = srv;
384 do {
385 srv2 = srv2->next;
386 } while (srv2 && (srv2 != p->lbprm.fbck));
387 if (srv2)
388 p->lbprm.fbck = srv;
389 }
390 } else {
391 p->lbprm.tot_wact = p->lbprm.fwrr.act.next_weight;
392 p->srv_act++;
393 }
394
395 /* note that eweight cannot be 0 here */
396 fwrr_get_srv(srv);
397 srv->npos = grp->curr_pos + (grp->next_weight + grp->curr_weight - grp->curr_pos) / srv->eweight;
398 fwrr_queue_srv(srv);
399
400out_update_backend:
401 /* check/update tot_used, tot_weight */
402 update_backend_weight(p);
Willy Tarreau0ebe1062007-11-30 11:11:02 +0100403 out_update_state:
Willy Tarreaub625a082007-11-26 01:15:43 +0100404 srv->prev_state = srv->state;
405 srv->prev_eweight = srv->eweight;
406}
407
408/* This function must be called after an update to server <srv>'s effective
409 * weight. It may be called after a state change too.
410 */
411static void fwrr_update_server_weight(struct server *srv)
412{
413 int old_state, new_state;
414 struct proxy *p = srv->proxy;
415 struct fwrr_group *grp;
416
417 if (srv->state == srv->prev_state &&
418 srv->eweight == srv->prev_eweight)
419 return;
420
421 /* If changing the server's weight changes its state, we simply apply
422 * the procedures we already have for status change. If the state
423 * remains down, the server is not in any tree, so it's as easy as
424 * updating its values. If the state remains up with different weights,
425 * there are some computations to perform to find a new place and
426 * possibly a new tree for this server.
427 */
428
429 old_state = srv_is_usable(srv->prev_state, srv->prev_eweight);
430 new_state = srv_is_usable(srv->state, srv->eweight);
431
432 if (!old_state && !new_state) {
433 srv->prev_state = srv->state;
434 srv->prev_eweight = srv->eweight;
435 return;
436 }
437 else if (!old_state && new_state) {
438 fwrr_set_server_status_up(srv);
439 return;
440 }
441 else if (old_state && !new_state) {
442 fwrr_set_server_status_down(srv);
443 return;
444 }
445
446 grp = (srv->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
447 grp->next_weight = grp->next_weight - srv->prev_eweight + srv->eweight;
448
449 p->lbprm.tot_wact = p->lbprm.fwrr.act.next_weight;
450 p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
451
452 if (srv->lb_tree == grp->init) {
453 fwrr_dequeue_srv(srv);
454 fwrr_queue_by_weight(grp->init, srv);
455 }
456 else if (!srv->lb_tree) {
457 /* FIXME: server was down. This is not possible right now but
458 * may be needed soon for slowstart or graceful shutdown.
459 */
460 fwrr_dequeue_srv(srv);
461 fwrr_get_srv(srv);
462 srv->npos = grp->curr_pos + (grp->next_weight + grp->curr_weight - grp->curr_pos) / srv->eweight;
463 fwrr_queue_srv(srv);
464 } else {
465 /* The server is either active or in the next queue. If it's
466 * still in the active queue and it has not consumed all of its
467 * places, let's adjust its next position.
468 */
469 fwrr_get_srv(srv);
470
471 if (srv->eweight > 0) {
472 int prev_next = srv->npos;
473 int step = grp->next_weight / srv->eweight;
474
475 srv->npos = srv->lpos + step;
476 srv->rweight = 0;
477
478 if (srv->npos > prev_next)
479 srv->npos = prev_next;
480 if (srv->npos < grp->curr_pos + 2)
481 srv->npos = grp->curr_pos + step;
482 } else {
483 /* push it into the next tree */
484 srv->npos = grp->curr_pos + grp->curr_weight;
485 }
486
487 fwrr_dequeue_srv(srv);
488 fwrr_queue_srv(srv);
489 }
490
491 update_backend_weight(p);
492 srv->prev_state = srv->state;
493 srv->prev_eweight = srv->eweight;
494}
495
496/* Remove a server from a tree. It must have previously been dequeued. This
497 * function is meant to be called when a server is going down or has its
498 * weight disabled.
499 */
500static inline void fwrr_remove_from_tree(struct server *s)
501{
502 s->lb_tree = NULL;
503}
504
505/* Queue a server in the weight tree <root>, assuming the weight is >0.
506 * We want to sort them by inverted weights, because we need to place
507 * heavy servers first in order to get a smooth distribution.
508 */
509static inline void fwrr_queue_by_weight(struct eb_root *root, struct server *s)
510{
Willy Tarreaub698f0f2007-12-02 11:01:23 +0100511 s->lb_node.key = SRV_EWGHT_MAX - s->eweight;
Willy Tarreaub625a082007-11-26 01:15:43 +0100512 eb32_insert(root, &s->lb_node);
513 s->lb_tree = root;
514}
515
516/* This function is responsible for building the weight trees in case of fast
517 * weighted round-robin. It also sets p->lbprm.wdiv to the eweight to uweight
518 * ratio. Both active and backup groups are initialized.
519 */
520void fwrr_init_server_groups(struct proxy *p)
521{
522 struct server *srv;
523 struct eb_root init_head = EB_ROOT;
524
525 p->lbprm.set_server_status_up = fwrr_set_server_status_up;
526 p->lbprm.set_server_status_down = fwrr_set_server_status_down;
527 p->lbprm.update_server_eweight = fwrr_update_server_weight;
528
529 p->lbprm.wdiv = BE_WEIGHT_SCALE;
530 for (srv = p->srv; srv; srv = srv->next) {
531 srv->prev_eweight = srv->eweight = srv->uweight * BE_WEIGHT_SCALE;
532 srv->prev_state = srv->state;
533 }
534
535 recount_servers(p);
536 update_backend_weight(p);
537
538 /* prepare the active servers group */
539 p->lbprm.fwrr.act.curr_pos = p->lbprm.fwrr.act.curr_weight =
540 p->lbprm.fwrr.act.next_weight = p->lbprm.tot_wact;
541 p->lbprm.fwrr.act.curr = p->lbprm.fwrr.act.t0 =
542 p->lbprm.fwrr.act.t1 = init_head;
543 p->lbprm.fwrr.act.init = &p->lbprm.fwrr.act.t0;
544 p->lbprm.fwrr.act.next = &p->lbprm.fwrr.act.t1;
545
546 /* prepare the backup servers group */
547 p->lbprm.fwrr.bck.curr_pos = p->lbprm.fwrr.bck.curr_weight =
548 p->lbprm.fwrr.bck.next_weight = p->lbprm.tot_wbck;
549 p->lbprm.fwrr.bck.curr = p->lbprm.fwrr.bck.t0 =
550 p->lbprm.fwrr.bck.t1 = init_head;
551 p->lbprm.fwrr.bck.init = &p->lbprm.fwrr.bck.t0;
552 p->lbprm.fwrr.bck.next = &p->lbprm.fwrr.bck.t1;
553
554 /* queue active and backup servers in two distinct groups */
555 for (srv = p->srv; srv; srv = srv->next) {
556 if (!srv_is_usable(srv->state, srv->eweight))
557 continue;
558 fwrr_queue_by_weight((srv->state & SRV_BACKUP) ?
559 p->lbprm.fwrr.bck.init :
560 p->lbprm.fwrr.act.init,
561 srv);
562 }
563}
564
565/* simply removes a server from a weight tree */
566static inline void fwrr_dequeue_srv(struct server *s)
567{
568 eb32_delete(&s->lb_node);
569}
570
571/* queues a server into the appropriate group and tree depending on its
572 * backup status, and ->npos. If the server is disabled, simply assign
573 * it to the NULL tree.
574 */
575static void fwrr_queue_srv(struct server *s)
576{
577 struct proxy *p = s->proxy;
578 struct fwrr_group *grp;
579
580 grp = (s->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
581
582 /* Delay everything which does not fit into the window and everything
583 * which does not fit into the theorical new window.
584 */
585 if (!srv_is_usable(s->state, s->eweight)) {
586 fwrr_remove_from_tree(s);
587 }
588 else if (s->eweight <= 0 ||
589 s->npos >= 2 * grp->curr_weight ||
590 s->npos >= grp->curr_weight + grp->next_weight) {
591 /* put into next tree, and readjust npos in case we could
592 * finally take this back to current. */
593 s->npos -= grp->curr_weight;
594 fwrr_queue_by_weight(grp->next, s);
595 }
596 else {
Willy Tarreaub698f0f2007-12-02 11:01:23 +0100597 /* The sorting key is stored in units of s->npos * user_weight
598 * in order to avoid overflows. As stated in backend.h, the
599 * lower the scale, the rougher the weights modulation, and the
600 * higher the scale, the lower the number of servers without
601 * overflow. With this formula, the result is always positive,
602 * so we can use eb3é_insert().
Willy Tarreaub625a082007-11-26 01:15:43 +0100603 */
Willy Tarreaub698f0f2007-12-02 11:01:23 +0100604 s->lb_node.key = SRV_UWGHT_RANGE * s->npos +
605 (unsigned)(SRV_EWGHT_MAX + s->rweight - s->eweight) / BE_WEIGHT_SCALE;
606
607 eb32_insert(&grp->curr, &s->lb_node);
Willy Tarreaub625a082007-11-26 01:15:43 +0100608 s->lb_tree = &grp->curr;
609 }
610}
611
612/* prepares a server when extracting it from the "init" tree */
613static inline void fwrr_get_srv_init(struct server *s)
614{
615 s->npos = s->rweight = 0;
616}
617
618/* prepares a server when extracting it from the "next" tree */
619static inline void fwrr_get_srv_next(struct server *s)
620{
621 struct fwrr_group *grp = (s->state & SRV_BACKUP) ?
622 &s->proxy->lbprm.fwrr.bck :
623 &s->proxy->lbprm.fwrr.act;
624
625 s->npos += grp->curr_weight;
626}
627
628/* prepares a server when it was marked down */
629static inline void fwrr_get_srv_down(struct server *s)
630{
631 struct fwrr_group *grp = (s->state & SRV_BACKUP) ?
632 &s->proxy->lbprm.fwrr.bck :
633 &s->proxy->lbprm.fwrr.act;
634
635 s->npos = grp->curr_pos;
636}
637
638/* prepares a server when extracting it from its tree */
639static void fwrr_get_srv(struct server *s)
640{
641 struct proxy *p = s->proxy;
642 struct fwrr_group *grp = (s->state & SRV_BACKUP) ?
643 &p->lbprm.fwrr.bck :
644 &p->lbprm.fwrr.act;
645
646 if (s->lb_tree == grp->init) {
647 fwrr_get_srv_init(s);
648 }
649 else if (s->lb_tree == grp->next) {
650 fwrr_get_srv_next(s);
651 }
652 else if (s->lb_tree == NULL) {
653 fwrr_get_srv_down(s);
654 }
655}
656
657/* switches trees "init" and "next" for FWRR group <grp>. "init" should be empty
658 * when this happens, and "next" filled with servers sorted by weights.
659 */
660static inline void fwrr_switch_trees(struct fwrr_group *grp)
661{
662 struct eb_root *swap;
663 swap = grp->init;
664 grp->init = grp->next;
665 grp->next = swap;
666 grp->curr_weight = grp->next_weight;
667 grp->curr_pos = grp->curr_weight;
668}
669
670/* return next server from the current tree in FWRR group <grp>, or a server
671 * from the "init" tree if appropriate. If both trees are empty, return NULL.
672 */
673static struct server *fwrr_get_server_from_group(struct fwrr_group *grp)
674{
675 struct eb32_node *node;
676 struct server *s;
677
678 node = eb32_first(&grp->curr);
679 s = eb32_entry(node, struct server, lb_node);
680
681 if (!node || s->npos > grp->curr_pos) {
682 /* either we have no server left, or we have a hole */
683 struct eb32_node *node2;
684 node2 = eb32_first(grp->init);
685 if (node2) {
686 node = node2;
687 s = eb32_entry(node, struct server, lb_node);
688 fwrr_get_srv_init(s);
689 if (s->eweight == 0) /* FIXME: is it possible at all ? */
690 node = NULL;
691 }
692 }
693 if (node)
694 return s;
695 else
696 return NULL;
697}
698
699/* Computes next position of server <s> in the group. It is mandatory for <s>
700 * to have a non-zero, positive eweight.
701*/
702static inline void fwrr_update_position(struct fwrr_group *grp, struct server *s)
703{
704 if (!s->npos) {
705 /* first time ever for this server */
706 s->lpos = grp->curr_pos;
707 s->npos = grp->curr_pos + grp->next_weight / s->eweight;
708 s->rweight += grp->next_weight % s->eweight;
709
710 if (s->rweight >= s->eweight) {
711 s->rweight -= s->eweight;
712 s->npos++;
713 }
714 } else {
715 s->lpos = s->npos;
716 s->npos += grp->next_weight / s->eweight;
717 s->rweight += grp->next_weight % s->eweight;
718
719 if (s->rweight >= s->eweight) {
720 s->rweight -= s->eweight;
721 s->npos++;
722 }
723 }
724}
725
726/* Return next server from the current tree in backend <p>, or a server from
727 * the init tree if appropriate. If both trees are empty, return NULL.
728 * Saturated servers are skipped and requeued.
729 */
730static struct server *fwrr_get_next_server(struct proxy *p)
731{
732 struct server *srv;
733 struct fwrr_group *grp;
734 struct server *full;
735 int switched;
736
737 if (p->srv_act)
738 grp = &p->lbprm.fwrr.act;
739 else if (p->lbprm.fbck)
740 return p->lbprm.fbck;
741 else if (p->srv_bck)
742 grp = &p->lbprm.fwrr.bck;
743 else
744 return NULL;
745
746 switched = 0;
747 full = NULL; /* NULL-terminated list of saturated servers */
748 while (1) {
749 /* if we see an empty group, let's first try to collect weights
750 * which might have recently changed.
751 */
752 if (!grp->curr_weight)
753 grp->curr_pos = grp->curr_weight = grp->next_weight;
754
755 /* get first server from the "current" tree. When the end of
756 * the tree is reached, we may have to switch, but only once.
757 */
758 while (1) {
759 srv = fwrr_get_server_from_group(grp);
760 if (srv)
761 break;
762 if (switched)
763 goto requeue_servers;
764 switched = 1;
765 fwrr_switch_trees(grp);
766
767 }
768
769 /* OK, we have a server. However, it may be saturated, in which
770 * case we don't want to reconsider it for now. We'll update
771 * its position and dequeue it anyway, so that we can move it
772 * to a better place afterwards.
773 */
774 fwrr_update_position(grp, srv);
775 fwrr_dequeue_srv(srv);
776 grp->curr_pos++;
777 if (!srv->maxconn || srv->cur_sess < srv_dynamic_maxconn(srv))
778 break;
779
780 /* the server is saturated, let's chain it for later reinsertion */
781 srv->next_full = full;
782 full = srv;
783 }
784
785 /* OK, we got the best server, let's update it */
786 fwrr_queue_srv(srv);
787
788 requeue_servers:
789 if (unlikely(full)) {
790 if (switched) {
791 /* the tree has switched, requeue all extracted servers
792 * into "init", because their place was lost, and only
793 * their weight matters.
794 */
795 do {
796 fwrr_queue_by_weight(grp->init, full);
797 full = full->next_full;
798 } while (full);
799 } else {
800 /* requeue all extracted servers just as if they were consumed
801 * so that they regain their expected place.
802 */
803 do {
804 fwrr_queue_srv(full);
805 full = full->next_full;
806 } while (full);
807 }
808 }
809 return srv;
810}
811
Willy Tarreau01732802007-11-01 22:48:15 +0100812/*
813 * This function tries to find a running server for the proxy <px> following
814 * the URL parameter hash method. It looks for a specific parameter in the
815 * URL and hashes it to compute the server ID. This is useful to optimize
816 * performance by avoiding bounces between servers in contexts where sessions
817 * are shared but cookies are not usable. If the parameter is not found, NULL
818 * is returned. If any server is found, it will be returned. If no valid server
819 * is found, NULL is returned.
820 *
821 */
822struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len)
823{
824 unsigned long hash = 0;
825 char *p;
826 int plen;
827
Willy Tarreau20697042007-11-15 23:26:18 +0100828 if (px->lbprm.tot_weight == 0)
Willy Tarreau01732802007-11-01 22:48:15 +0100829 return NULL;
830
Willy Tarreau20697042007-11-15 23:26:18 +0100831 if (px->lbprm.map.state & PR_MAP_RECALC)
832 recalc_server_map(px);
833
Willy Tarreau01732802007-11-01 22:48:15 +0100834 p = memchr(uri, '?', uri_len);
835 if (!p)
836 return NULL;
837 p++;
838
839 uri_len -= (p - uri);
840 plen = px->url_param_len;
841
842 if (uri_len <= plen)
843 return NULL;
844
845 while (uri_len > plen) {
846 /* Look for the parameter name followed by an equal symbol */
847 if (p[plen] == '=') {
848 /* skip the equal symbol */
849 uri = p;
850 p += plen + 1;
851 uri_len -= plen + 1;
852 if (memcmp(uri, px->url_param_name, plen) == 0) {
853 /* OK, we have the parameter here at <uri>, and
854 * the value after the equal sign, at <p>
855 */
856 while (uri_len && *p != '&') {
857 hash = *p + (hash << 6) + (hash << 16) - hash;
858 uri_len--;
859 p++;
860 }
Willy Tarreau20697042007-11-15 23:26:18 +0100861 return px->lbprm.map.srv[hash % px->lbprm.tot_weight];
Willy Tarreau01732802007-11-01 22:48:15 +0100862 }
863 }
864
865 /* skip to next parameter */
866 uri = p;
867 p = memchr(uri, '&', uri_len);
868 if (!p)
869 return NULL;
870 p++;
871 uri_len -= (p - uri);
872 }
873 return NULL;
874}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875
876/*
877 * This function marks the session as 'assigned' in direct or dispatch modes,
878 * or tries to assign one in balance mode, according to the algorithm. It does
879 * nothing if the session had already been assigned a server.
880 *
881 * It may return :
882 * SRV_STATUS_OK if everything is OK. s->srv will be valid.
883 * SRV_STATUS_NOSRV if no server is available. s->srv = NULL.
884 * SRV_STATUS_FULL if all servers are saturated. s->srv = NULL.
885 * SRV_STATUS_INTERNAL for other unrecoverable errors.
886 *
887 * Upon successful return, the session flag SN_ASSIGNED to indicate that it does
888 * not need to be called anymore. This usually means that s->srv can be trusted
889 * in balance and direct modes. This flag is not cleared, so it's to the caller
890 * to clear it if required (eg: redispatch).
891 *
892 */
893
894int assign_server(struct session *s)
895{
896#ifdef DEBUG_FULL
897 fprintf(stderr,"assign_server : s=%p\n",s);
898#endif
899
900 if (s->pend_pos)
901 return SRV_STATUS_INTERNAL;
902
903 if (!(s->flags & SN_ASSIGNED)) {
Willy Tarreau31682232007-11-29 15:38:04 +0100904 if (s->be->lbprm.algo & BE_LB_ALGO) {
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100905 int len;
906
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100907 if (s->flags & SN_DIRECT) {
908 s->flags |= SN_ASSIGNED;
909 return SRV_STATUS_OK;
910 }
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100911
Willy Tarreaub625a082007-11-26 01:15:43 +0100912 if (!s->be->lbprm.tot_weight)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 return SRV_STATUS_NOSRV;
914
Willy Tarreau31682232007-11-29 15:38:04 +0100915 switch (s->be->lbprm.algo & BE_LB_ALGO) {
916 case BE_LB_ALGO_RR:
Willy Tarreaub625a082007-11-26 01:15:43 +0100917 s->srv = fwrr_get_next_server(s->be);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 if (!s->srv)
919 return SRV_STATUS_FULL;
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100920 break;
Willy Tarreau31682232007-11-29 15:38:04 +0100921 case BE_LB_ALGO_SH:
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 if (s->cli_addr.ss_family == AF_INET)
923 len = 4;
924 else if (s->cli_addr.ss_family == AF_INET6)
925 len = 16;
926 else /* unknown IP family */
927 return SRV_STATUS_INTERNAL;
928
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200929 s->srv = get_server_sh(s->be,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 (void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
931 len);
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100932 break;
Willy Tarreau31682232007-11-29 15:38:04 +0100933 case BE_LB_ALGO_UH:
Willy Tarreau2fcb5002007-05-08 13:35:26 +0200934 /* URI hashing */
935 s->srv = get_server_uh(s->be,
936 s->txn.req.sol + s->txn.req.sl.rq.u,
937 s->txn.req.sl.rq.u_l);
Willy Tarreau01732802007-11-01 22:48:15 +0100938 break;
Willy Tarreau31682232007-11-29 15:38:04 +0100939 case BE_LB_ALGO_PH:
Willy Tarreau01732802007-11-01 22:48:15 +0100940 /* URL Parameter hashing */
941 s->srv = get_server_ph(s->be,
942 s->txn.req.sol + s->txn.req.sl.rq.u,
943 s->txn.req.sl.rq.u_l);
944 if (!s->srv) {
Willy Tarreaub625a082007-11-26 01:15:43 +0100945 /* parameter not found, fall back to round robin on the map */
Willy Tarreau01732802007-11-01 22:48:15 +0100946 s->srv = get_server_rr_with_conns(s->be);
947 if (!s->srv)
948 return SRV_STATUS_FULL;
949 }
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100950 break;
951 default:
952 /* unknown balancing algorithm */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 return SRV_STATUS_INTERNAL;
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100954 }
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100955 s->be->cum_lbconn++;
956 s->srv->cum_lbconn++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
Alexandre Cassen5eb1a902007-11-29 15:43:32 +0100958 else if (s->be->options & PR_O_HTTP_PROXY) {
959 if (!s->srv_addr.sin_addr.s_addr)
960 return SRV_STATUS_NOSRV;
961 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200962 else if (!*(int *)&s->be->dispatch_addr.sin_addr &&
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100963 !(s->fe->options & PR_O_TRANSP)) {
Willy Tarreau1a1158b2007-01-20 11:07:46 +0100964 return SRV_STATUS_NOSRV;
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100965 }
966 s->flags |= SN_ASSIGNED;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
968 return SRV_STATUS_OK;
969}
970
971
972/*
973 * This function assigns a server address to a session, and sets SN_ADDR_SET.
974 * The address is taken from the currently assigned server, or from the
975 * dispatch or transparent address.
976 *
977 * It may return :
978 * SRV_STATUS_OK if everything is OK.
979 * SRV_STATUS_INTERNAL for other unrecoverable errors.
980 *
981 * Upon successful return, the session flag SN_ADDR_SET is set. This flag is
982 * not cleared, so it's to the caller to clear it if required.
983 *
984 */
985int assign_server_address(struct session *s)
986{
987#ifdef DEBUG_FULL
988 fprintf(stderr,"assign_server_address : s=%p\n",s);
989#endif
990
Willy Tarreau31682232007-11-29 15:38:04 +0100991 if ((s->flags & SN_DIRECT) || (s->be->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 /* A server is necessarily known for this session */
993 if (!(s->flags & SN_ASSIGNED))
994 return SRV_STATUS_INTERNAL;
995
996 s->srv_addr = s->srv->addr;
997
998 /* if this server remaps proxied ports, we'll use
999 * the port the client connected to with an offset. */
1000 if (s->srv->state & SRV_MAPPORTS) {
Willy Tarreau14c8aac2007-05-08 19:46:30 +02001001 if (!(s->fe->options & PR_O_TRANSP) && !(s->flags & SN_FRT_ADDR_SET))
1002 get_frt_addr(s);
1003 if (s->frt_addr.ss_family == AF_INET) {
1004 s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
1005 ntohs(((struct sockaddr_in *)&s->frt_addr)->sin_port));
1006 } else {
1007 s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
1008 ntohs(((struct sockaddr_in6 *)&s->frt_addr)->sin6_port));
1009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010 }
1011 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001012 else if (*(int *)&s->be->dispatch_addr.sin_addr) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001013 /* connect to the defined dispatch addr */
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001014 s->srv_addr = s->be->dispatch_addr;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 }
Willy Tarreau73de9892006-11-30 11:40:23 +01001016 else if (s->fe->options & PR_O_TRANSP) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 /* in transparent mode, use the original dest addr if no dispatch specified */
Willy Tarreaubd414282008-01-19 13:46:35 +01001018 if (!(s->flags & SN_FRT_ADDR_SET))
1019 get_frt_addr(s);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020
Willy Tarreaubd414282008-01-19 13:46:35 +01001021 memcpy(&s->srv_addr, &s->frt_addr, MIN(sizeof(s->srv_addr), sizeof(s->frt_addr)));
1022 /* when we support IPv6 on the backend, we may add other tests */
1023 //qfprintf(stderr, "Cannot get original server address.\n");
1024 //return SRV_STATUS_INTERNAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025 }
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01001026 else if (s->be->options & PR_O_HTTP_PROXY) {
1027 /* If HTTP PROXY option is set, then server is already assigned
1028 * during incoming client request parsing. */
1029 }
Willy Tarreau1a1158b2007-01-20 11:07:46 +01001030 else {
1031 /* no server and no LB algorithm ! */
1032 return SRV_STATUS_INTERNAL;
1033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034
1035 s->flags |= SN_ADDR_SET;
1036 return SRV_STATUS_OK;
1037}
1038
1039
1040/* This function assigns a server to session <s> if required, and can add the
1041 * connection to either the assigned server's queue or to the proxy's queue.
1042 *
1043 * Returns :
1044 *
1045 * SRV_STATUS_OK if everything is OK.
1046 * SRV_STATUS_NOSRV if no server is available. s->srv = NULL.
1047 * SRV_STATUS_QUEUED if the connection has been queued.
1048 * SRV_STATUS_FULL if the server(s) is/are saturated and the
1049 * connection could not be queued.
1050 * SRV_STATUS_INTERNAL for other unrecoverable errors.
1051 *
1052 */
1053int assign_server_and_queue(struct session *s)
1054{
1055 struct pendconn *p;
1056 int err;
1057
1058 if (s->pend_pos)
1059 return SRV_STATUS_INTERNAL;
1060
1061 if (s->flags & SN_ASSIGNED) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01001062 if ((s->flags & SN_REDIRECTABLE) && s->srv && s->srv->rdr_len) {
1063 /* server scheduled for redirection, and already assigned. We
1064 * don't want to go further nor check the queue.
1065 */
1066 return SRV_STATUS_OK;
1067 }
1068
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001069 if (s->srv && s->srv->maxqueue > 0 && s->srv->nbpend >= s->srv->maxqueue) {
1070 s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
1071 s->srv = NULL;
1072 http_flush_cookie_flags(&s->txn);
1073 } else {
1074 /* a server does not need to be assigned, perhaps because we're in
1075 * direct mode, or in dispatch or transparent modes where the server
1076 * is not needed.
1077 */
1078 if (s->srv &&
1079 s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
1080 p = pendconn_add(s);
1081 if (p)
1082 return SRV_STATUS_QUEUED;
1083 else
1084 return SRV_STATUS_FULL;
1085 }
1086 return SRV_STATUS_OK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 }
1089
1090 /* a server needs to be assigned */
1091 err = assign_server(s);
1092 switch (err) {
1093 case SRV_STATUS_OK:
Willy Tarreau21d2af32008-02-14 20:25:24 +01001094 if ((s->flags & SN_REDIRECTABLE) && s->srv && s->srv->rdr_len) {
1095 /* server supporting redirection and it is possible.
1096 * Let's report that and ignore maxconn !
1097 */
1098 return SRV_STATUS_OK;
1099 }
1100
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 /* in balance mode, we might have servers with connection limits */
1102 if (s->srv &&
1103 s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
1104 p = pendconn_add(s);
1105 if (p)
1106 return SRV_STATUS_QUEUED;
1107 else
1108 return SRV_STATUS_FULL;
1109 }
1110 return SRV_STATUS_OK;
1111
1112 case SRV_STATUS_FULL:
1113 /* queue this session into the proxy's queue */
1114 p = pendconn_add(s);
1115 if (p)
1116 return SRV_STATUS_QUEUED;
1117 else
1118 return SRV_STATUS_FULL;
1119
1120 case SRV_STATUS_NOSRV:
1121 case SRV_STATUS_INTERNAL:
1122 return err;
1123 default:
1124 return SRV_STATUS_INTERNAL;
1125 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001126}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127
1128/*
1129 * This function initiates a connection to the server assigned to this session
1130 * (s->srv, s->srv_addr). It will assign a server if none is assigned yet.
1131 * It can return one of :
1132 * - SN_ERR_NONE if everything's OK
1133 * - SN_ERR_SRVTO if there are no more servers
1134 * - SN_ERR_SRVCL if the connection was refused by the server
1135 * - SN_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
1136 * - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
1137 * - SN_ERR_INTERNAL for any other purely internal errors
1138 * Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
1139 */
1140int connect_server(struct session *s)
1141{
1142 int fd, err;
1143
1144 if (!(s->flags & SN_ADDR_SET)) {
1145 err = assign_server_address(s);
1146 if (err != SRV_STATUS_OK)
1147 return SN_ERR_INTERNAL;
1148 }
1149
1150 if ((fd = s->srv_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
1151 qfprintf(stderr, "Cannot get a server socket.\n");
1152
1153 if (errno == ENFILE)
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001154 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 "Proxy %s reached system FD limit at %d. Please check system tunables.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001156 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 else if (errno == EMFILE)
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001158 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 "Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001160 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161 else if (errno == ENOBUFS || errno == ENOMEM)
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001162 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 "Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001164 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001165 /* this is a resource error */
1166 return SN_ERR_RESOURCE;
1167 }
1168
1169 if (fd >= global.maxsock) {
1170 /* do not log anything there, it's a normal condition when this option
1171 * is used to serialize connections to a server !
1172 */
1173 Alert("socket(): not enough free sockets. Raise -n argument. Giving up.\n");
1174 close(fd);
1175 return SN_ERR_PRXCOND; /* it is a configuration limit */
1176 }
1177
Willy Tarreau6d1a9882007-01-07 02:03:04 +01001178#ifdef CONFIG_HAP_TCPSPLICE
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001179 if ((s->fe->options & s->be->options) & PR_O_TCPSPLICE) {
Willy Tarreau6d1a9882007-01-07 02:03:04 +01001180 /* TCP splicing supported by both FE and BE */
1181 tcp_splice_initfd(s->cli_fd, fd);
1182 }
1183#endif
1184
Willy Tarreaubaaee002006-06-26 02:48:02 +02001185 if ((fcntl(fd, F_SETFL, O_NONBLOCK)==-1) ||
1186 (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) == -1)) {
1187 qfprintf(stderr,"Cannot set client socket to non blocking mode.\n");
1188 close(fd);
1189 return SN_ERR_INTERNAL;
1190 }
1191
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001192 if (s->be->options & PR_O_TCP_SRV_KA)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
1194
Alexandre Cassen87ea5482007-10-11 20:48:58 +02001195 if (s->be->options & PR_O_TCP_NOLING)
1196 setsockopt(fd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
1197
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 /* allow specific binding :
1199 * - server-specific at first
1200 * - proxy-specific next
1201 */
1202 if (s->srv != NULL && s->srv->state & SRV_BIND_SRC) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001203 struct sockaddr_in *remote = NULL;
1204 int ret, flags = 0;
Willy Tarreau77074d52006-11-12 23:57:19 +01001205
Willy Tarreau786d1912008-01-13 18:10:06 +01001206 switch (s->srv->state & SRV_TPROXY_MASK) {
1207 case SRV_TPROXY_ADDR:
1208 remote = (struct sockaddr_in *)&s->srv->tproxy_addr;
1209 flags = 3;
1210 break;
1211 case SRV_TPROXY_CLI:
1212 flags |= 2;
1213 /* fall through */
1214 case SRV_TPROXY_CIP:
1215 /* FIXME: what can we do if the client connects in IPv6 ? */
1216 flags |= 1;
1217 remote = (struct sockaddr_in *)&s->cli_addr;
1218 break;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001219 }
Willy Tarreaue8c66af2008-01-13 18:40:14 +01001220 ret = tcpv4_bind_socket(fd, flags, &s->srv->source_addr, remote);
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001221 if (ret) {
1222 close(fd);
1223 if (ret == 1) {
1224 Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
1225 s->be->id, s->srv->id);
1226 send_log(s->be, LOG_EMERG,
1227 "Cannot bind to source address before connect() for server %s/%s.\n",
1228 s->be->id, s->srv->id);
1229 } else {
Willy Tarreau77074d52006-11-12 23:57:19 +01001230 Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001231 s->be->id, s->srv->id);
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001232 send_log(s->be, LOG_EMERG,
Willy Tarreau77074d52006-11-12 23:57:19 +01001233 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001234 s->be->id, s->srv->id);
Willy Tarreau77074d52006-11-12 23:57:19 +01001235 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001236 return SN_ERR_RESOURCE;
Willy Tarreau77074d52006-11-12 23:57:19 +01001237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001238 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001239 else if (s->be->options & PR_O_BIND_SRC) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001240 struct sockaddr_in *remote = NULL;
1241 int ret, flags = 0;
Willy Tarreau77074d52006-11-12 23:57:19 +01001242
Willy Tarreau786d1912008-01-13 18:10:06 +01001243 switch (s->be->options & PR_O_TPXY_MASK) {
1244 case PR_O_TPXY_ADDR:
1245 remote = (struct sockaddr_in *)&s->be->tproxy_addr;
1246 flags = 3;
1247 break;
1248 case PR_O_TPXY_CLI:
1249 flags |= 2;
1250 /* fall through */
1251 case PR_O_TPXY_CIP:
1252 /* FIXME: what can we do if the client connects in IPv6 ? */
1253 flags |= 1;
1254 remote = (struct sockaddr_in *)&s->cli_addr;
1255 break;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001256 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001257
Willy Tarreaue8c66af2008-01-13 18:40:14 +01001258 ret = tcpv4_bind_socket(fd, flags, &s->be->source_addr, remote);
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001259 if (ret) {
1260 close(fd);
1261 if (ret == 1) {
1262 Alert("Cannot bind to source address before connect() for proxy %s. Aborting.\n",
1263 s->be->id);
1264 send_log(s->be, LOG_EMERG,
1265 "Cannot bind to source address before connect() for proxy %s.\n",
1266 s->be->id);
1267 } else {
Willy Tarreau77074d52006-11-12 23:57:19 +01001268 Alert("Cannot bind to tproxy source address before connect() for proxy %s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001269 s->be->id);
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001270 send_log(s->be, LOG_EMERG,
Willy Tarreaufe10a062008-01-12 22:22:34 +01001271 "Cannot bind to tproxy source address before connect() for proxy %s.\n",
1272 s->be->id);
Willy Tarreau77074d52006-11-12 23:57:19 +01001273 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001274 return SN_ERR_RESOURCE;
Willy Tarreau77074d52006-11-12 23:57:19 +01001275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001276 }
1277
1278 if ((connect(fd, (struct sockaddr *)&s->srv_addr, sizeof(s->srv_addr)) == -1) &&
1279 (errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
1280
1281 if (errno == EAGAIN || errno == EADDRINUSE) {
1282 char *msg;
1283 if (errno == EAGAIN) /* no free ports left, try again later */
1284 msg = "no free ports";
1285 else
1286 msg = "local address already in use";
1287
1288 qfprintf(stderr,"Cannot connect: %s.\n",msg);
1289 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001290 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +02001291 "Connect() failed for server %s/%s: %s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001292 s->be->id, s->srv->id, msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293 return SN_ERR_RESOURCE;
1294 } else if (errno == ETIMEDOUT) {
1295 //qfprintf(stderr,"Connect(): ETIMEDOUT");
1296 close(fd);
1297 return SN_ERR_SRVTO;
1298 } else {
1299 // (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
1300 //qfprintf(stderr,"Connect(): %d", errno);
1301 close(fd);
1302 return SN_ERR_SRVCL;
1303 }
1304 }
1305
1306 fdtab[fd].owner = s->task;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307 fdtab[fd].state = FD_STCONN; /* connection in progress */
Willy Tarreaud7971282006-07-29 18:36:34 +02001308 fdtab[fd].cb[DIR_RD].f = &stream_sock_read;
Willy Tarreau54469402006-07-29 16:59:06 +02001309 fdtab[fd].cb[DIR_RD].b = s->rep;
Willy Tarreauf8306d52006-07-29 19:01:31 +02001310 fdtab[fd].cb[DIR_WR].f = &stream_sock_write;
Willy Tarreau54469402006-07-29 16:59:06 +02001311 fdtab[fd].cb[DIR_WR].b = s->req;
Willy Tarreaue94ebd02007-10-09 17:14:37 +02001312
1313 fdtab[fd].peeraddr = (struct sockaddr *)&s->srv_addr;
1314 fdtab[fd].peerlen = sizeof(s->srv_addr);
1315
Willy Tarreauf161a342007-04-08 16:59:42 +02001316 EV_FD_SET(fd, DIR_WR); /* for connect status */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001317
1318 fd_insert(fd);
1319 if (s->srv) {
1320 s->srv->cur_sess++;
1321 if (s->srv->cur_sess > s->srv->cur_sess_max)
1322 s->srv->cur_sess_max = s->srv->cur_sess;
1323 }
1324
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001325 if (!tv_add_ifset(&s->req->cex, &now, &s->be->timeout.connect))
Willy Tarreaud7971282006-07-29 18:36:34 +02001326 tv_eternity(&s->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327 return SN_ERR_NONE; /* connection is OK */
1328}
1329
1330
1331/*
1332 * This function checks the retry count during the connect() job.
1333 * It updates the session's srv_state and retries, so that the caller knows
1334 * what it has to do. It uses the last connection error to set the log when
1335 * it expires. It returns 1 when it has expired, and 0 otherwise.
1336 */
1337int srv_count_retry_down(struct session *t, int conn_err)
1338{
1339 /* we are in front of a retryable error */
1340 t->conn_retries--;
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +02001341 if (t->srv)
1342 t->srv->retries++;
1343 t->be->retries++;
1344
Willy Tarreaubaaee002006-06-26 02:48:02 +02001345 if (t->conn_retries < 0) {
1346 /* if not retryable anymore, let's abort */
Willy Tarreaud7971282006-07-29 18:36:34 +02001347 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 srv_close_with_err(t, conn_err, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +01001349 503, error_message(t, HTTP_ERR_503));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350 if (t->srv)
Willy Tarreau98937b82007-12-10 15:05:42 +01001351 t->srv->cum_sess++;
1352 if (t->srv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001354 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355
1356 /* We used to have a free connection slot. Since we'll never use it,
1357 * we have to inform the server that it may be used by another session.
1358 */
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001359 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +02001360 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 return 1;
1362 }
1363 return 0;
1364}
1365
1366
1367/*
1368 * This function performs the retryable part of the connect() job.
1369 * It updates the session's srv_state and retries, so that the caller knows
1370 * what it has to do. It returns 1 when it breaks out of the loop, or 0 if
1371 * it needs to redispatch.
1372 */
1373int srv_retryable_connect(struct session *t)
1374{
1375 int conn_err;
1376
1377 /* This loop ensures that we stop before the last retry in case of a
1378 * redispatchable server.
1379 */
1380 do {
1381 /* initiate a connection to the server */
1382 conn_err = connect_server(t);
1383 switch (conn_err) {
1384
1385 case SN_ERR_NONE:
1386 //fprintf(stderr,"0: c=%d, s=%d\n", c, s);
1387 t->srv_state = SV_STCONN;
Willy Tarreau98937b82007-12-10 15:05:42 +01001388 if (t->srv)
1389 t->srv->cum_sess++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 return 1;
1391
1392 case SN_ERR_INTERNAL:
Willy Tarreaud7971282006-07-29 18:36:34 +02001393 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +01001395 500, error_message(t, HTTP_ERR_500));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 if (t->srv)
Willy Tarreau98937b82007-12-10 15:05:42 +01001397 t->srv->cum_sess++;
1398 if (t->srv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001400 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 /* release other sessions waiting for this server */
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001402 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +02001403 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 return 1;
1405 }
1406 /* ensure that we have enough retries left */
1407 if (srv_count_retry_down(t, conn_err)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 return 1;
1409 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001410 } while (t->srv == NULL || t->conn_retries > 0 || !(t->be->options & PR_O_REDISP));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411
1412 /* We're on our last chance, and the REDISP option was specified.
1413 * We will ignore cookie and force to balance or use the dispatcher.
1414 */
1415 /* let's try to offer this slot to anybody */
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001416 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +02001417 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418
Krzysztof Piotr Oledzki25b501a2008-01-06 16:36:16 +01001419 if (t->srv) {
Willy Tarreau98937b82007-12-10 15:05:42 +01001420 t->srv->cum_sess++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 t->srv->failed_conns++;
Krzysztof Piotr Oledzki25b501a2008-01-06 16:36:16 +01001422 t->srv->redispatches++;
1423 }
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +02001424 t->be->redispatches++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425
1426 t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
Krzysztof Piotr Oledzki25b501a2008-01-06 16:36:16 +01001427 t->flags |= SN_REDISP;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428 t->srv = NULL; /* it's left to the dispatcher to choose a server */
Willy Tarreau3d300592007-03-18 18:34:41 +01001429 http_flush_cookie_flags(&t->txn);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430 return 0;
1431}
1432
1433
1434/* This function performs the "redispatch" part of a connection attempt. It
1435 * will assign a server if required, queue the connection if required, and
1436 * handle errors that might arise at this level. It can change the server
1437 * state. It will return 1 if it encounters an error, switches the server
1438 * state, or has to queue a connection. Otherwise, it will return 0 indicating
1439 * that the connection is ready to use.
1440 */
1441
1442int srv_redispatch_connect(struct session *t)
1443{
1444 int conn_err;
1445
1446 /* We know that we don't have any connection pending, so we will
1447 * try to get a new one, and wait in this state if it's queued
1448 */
1449 conn_err = assign_server_and_queue(t);
1450 switch (conn_err) {
1451 case SRV_STATUS_OK:
1452 break;
1453
1454 case SRV_STATUS_NOSRV:
1455 /* note: it is guaranteed that t->srv == NULL here */
Willy Tarreaud7971282006-07-29 18:36:34 +02001456 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +01001458 503, error_message(t, HTTP_ERR_503));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 if (t->srv)
Willy Tarreau98937b82007-12-10 15:05:42 +01001460 t->srv->cum_sess++;
1461 if (t->srv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001463 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464
1465 return 1;
1466
1467 case SRV_STATUS_QUEUED:
Willy Tarreau1fa31262007-12-03 00:36:16 +01001468 /* note: we use the connect expiration date for the queue. */
1469 if (!tv_add_ifset(&t->req->cex, &now, &t->be->timeout.queue))
Willy Tarreaud7971282006-07-29 18:36:34 +02001470 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 t->srv_state = SV_STIDLE;
1472 /* do nothing else and do not wake any other session up */
1473 return 1;
1474
1475 case SRV_STATUS_FULL:
1476 case SRV_STATUS_INTERNAL:
1477 default:
Willy Tarreaud7971282006-07-29 18:36:34 +02001478 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479 srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +01001480 500, error_message(t, HTTP_ERR_500));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 if (t->srv)
Willy Tarreau98937b82007-12-10 15:05:42 +01001482 t->srv->cum_sess++;
1483 if (t->srv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001485 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486
1487 /* release other sessions waiting for this server */
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001488 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +02001489 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 return 1;
1491 }
1492 /* if we get here, it's because we got SRV_STATUS_OK, which also
1493 * means that the connection has not been queued.
1494 */
1495 return 0;
1496}
1497
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001498int be_downtime(struct proxy *px) {
Willy Tarreaub625a082007-11-26 01:15:43 +01001499 if (px->lbprm.tot_weight && px->last_change < now.tv_sec) // ignore negative time
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001500 return px->down_time;
1501
1502 return now.tv_sec - px->last_change + px->down_time;
1503}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001505/* This function parses a "balance" statement in a backend section describing
1506 * <curproxy>. It returns -1 if there is any error, otherwise zero. If it
1507 * returns -1, it may write an error message into ther <err> buffer, for at
1508 * most <errlen> bytes, trailing zero included. The trailing '\n' will not be
1509 * written. The function must be called with <args> pointing to the first word
1510 * after "balance".
1511 */
1512int backend_parse_balance(const char **args, char *err, int errlen, struct proxy *curproxy)
1513{
1514 if (!*(args[0])) {
1515 /* if no option is set, use round-robin by default */
Willy Tarreau31682232007-11-29 15:38:04 +01001516 curproxy->lbprm.algo &= ~BE_LB_ALGO;
1517 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001518 return 0;
1519 }
1520
1521 if (!strcmp(args[0], "roundrobin")) {
Willy Tarreau31682232007-11-29 15:38:04 +01001522 curproxy->lbprm.algo &= ~BE_LB_ALGO;
1523 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001524 }
1525 else if (!strcmp(args[0], "source")) {
Willy Tarreau31682232007-11-29 15:38:04 +01001526 curproxy->lbprm.algo &= ~BE_LB_ALGO;
1527 curproxy->lbprm.algo |= BE_LB_ALGO_SH;
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001528 }
1529 else if (!strcmp(args[0], "uri")) {
Willy Tarreau31682232007-11-29 15:38:04 +01001530 curproxy->lbprm.algo &= ~BE_LB_ALGO;
1531 curproxy->lbprm.algo |= BE_LB_ALGO_UH;
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001532 }
Willy Tarreau01732802007-11-01 22:48:15 +01001533 else if (!strcmp(args[0], "url_param")) {
1534 if (!*args[1]) {
1535 snprintf(err, errlen, "'balance url_param' requires an URL parameter name.");
1536 return -1;
1537 }
Willy Tarreau31682232007-11-29 15:38:04 +01001538 curproxy->lbprm.algo &= ~BE_LB_ALGO;
1539 curproxy->lbprm.algo |= BE_LB_ALGO_PH;
Willy Tarreau01732802007-11-01 22:48:15 +01001540 if (curproxy->url_param_name)
1541 free(curproxy->url_param_name);
1542 curproxy->url_param_name = strdup(args[1]);
1543 curproxy->url_param_len = strlen(args[1]);
1544 }
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001545 else {
Willy Tarreau01732802007-11-01 22:48:15 +01001546 snprintf(err, errlen, "'balance' only supports 'roundrobin', 'source', 'uri' and 'url_param' options.");
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001547 return -1;
1548 }
1549 return 0;
1550}
1551
Willy Tarreaua9d3c1e2007-11-30 20:48:53 +01001552
1553/************************************************************************/
1554/* All supported keywords must be declared here. */
1555/************************************************************************/
1556
1557/* set test->i to the number of enabled servers on the proxy */
1558static int
1559acl_fetch_nbsrv(struct proxy *px, struct session *l4, void *l7, int dir,
1560 struct acl_expr *expr, struct acl_test *test)
1561{
1562 test->flags = ACL_TEST_F_VOL_TEST;
1563 if (expr->arg_len) {
1564 /* another proxy was designated, we must look for it */
1565 for (px = proxy; px; px = px->next)
1566 if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
1567 break;
1568 }
1569 if (!px)
1570 return 0;
1571
1572 if (px->srv_act)
1573 test->i = px->srv_act;
1574 else if (px->lbprm.fbck)
1575 test->i = 1;
1576 else
1577 test->i = px->srv_bck;
1578
1579 return 1;
1580}
1581
1582
1583/* Note: must not be declared <const> as its list will be overwritten */
1584static struct acl_kw_list acl_kws = {{ },{
1585 { "nbsrv", acl_parse_int, acl_fetch_nbsrv, acl_match_int },
1586 { NULL, NULL, NULL, NULL },
1587}};
1588
1589
1590__attribute__((constructor))
1591static void __backend_init(void)
1592{
1593 acl_register_keywords(&acl_kws);
1594}
1595
1596
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597/*
1598 * Local variables:
1599 * c-indent-level: 8
1600 * c-basic-offset: 8
1601 * End:
1602 */