blob: cc12f7ad62a43029f5bdb2b20586c9726decf0ef [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Backend variables and functions.
3 *
Willy Tarreaud825eef2007-05-12 22:35:00 +02004 * Copyright 2000-2007 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
25#include <types/buffers.h>
26#include <types/global.h>
27#include <types/polling.h>
28#include <types/proxy.h>
29#include <types/server.h>
30#include <types/session.h>
31
32#include <proto/backend.h>
Willy Tarreau14c8aac2007-05-08 19:46:30 +020033#include <proto/client.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034#include <proto/fd.h>
Willy Tarreau80587432006-12-24 17:47:20 +010035#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <proto/log.h>
37#include <proto/proto_http.h>
38#include <proto/queue.h>
39#include <proto/stream_sock.h>
40#include <proto/task.h>
41
Willy Tarreau77074d52006-11-12 23:57:19 +010042#ifdef CONFIG_HAP_CTTPROXY
43#include <import/ip_tproxy.h>
44#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
Willy Tarreau6d1a9882007-01-07 02:03:04 +010046#ifdef CONFIG_HAP_TCPSPLICE
47#include <libtcpsplice.h>
48#endif
49
Willy Tarreaub625a082007-11-26 01:15:43 +010050static inline void fwrr_remove_from_tree(struct server *s);
51static inline void fwrr_queue_by_weight(struct eb_root *root, struct server *s);
52static inline void fwrr_dequeue_srv(struct server *s);
53static void fwrr_get_srv(struct server *s);
54static void fwrr_queue_srv(struct server *s);
55
56/* This function returns non-zero if a server with the given weight and state
57 * is usable for LB, otherwise zero.
58 */
59static inline int srv_is_usable(int state, int weight)
60{
61 if (!weight)
62 return 0;
Willy Tarreau48494c02007-11-30 10:41:39 +010063 if (state & SRV_GOINGDOWN)
64 return 0;
Willy Tarreaub625a082007-11-26 01:15:43 +010065 if (!(state & SRV_RUNNING))
66 return 0;
67 return 1;
68}
69
Willy Tarreaubaaee002006-06-26 02:48:02 +020070/*
71 * This function recounts the number of usable active and backup servers for
72 * proxy <p>. These numbers are returned into the p->srv_act and p->srv_bck.
Willy Tarreaub625a082007-11-26 01:15:43 +010073 * This function also recomputes the total active and backup weights. However,
74 * it does nout update tot_weight nor tot_used. Use update_backend_weight() for
75 * this.
Willy Tarreaubaaee002006-06-26 02:48:02 +020076 */
Willy Tarreaub625a082007-11-26 01:15:43 +010077static void recount_servers(struct proxy *px)
Willy Tarreaubaaee002006-06-26 02:48:02 +020078{
79 struct server *srv;
80
Willy Tarreau20697042007-11-15 23:26:18 +010081 px->srv_act = px->srv_bck = 0;
82 px->lbprm.tot_wact = px->lbprm.tot_wbck = 0;
Willy Tarreaub625a082007-11-26 01:15:43 +010083 px->lbprm.fbck = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +020084 for (srv = px->srv; srv != NULL; srv = srv->next) {
Willy Tarreaub625a082007-11-26 01:15:43 +010085 if (!srv_is_usable(srv->state, srv->eweight))
86 continue;
87
88 if (srv->state & SRV_BACKUP) {
89 if (!px->srv_bck &&
Willy Tarreau31682232007-11-29 15:38:04 +010090 !(px->lbprm.algo & PR_O_USE_ALL_BK))
Willy Tarreaub625a082007-11-26 01:15:43 +010091 px->lbprm.fbck = srv;
92 px->srv_bck++;
93 px->lbprm.tot_wbck += srv->eweight;
94 } else {
95 px->srv_act++;
96 px->lbprm.tot_wact += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +020097 }
98 }
Willy Tarreaub625a082007-11-26 01:15:43 +010099}
Willy Tarreau20697042007-11-15 23:26:18 +0100100
Willy Tarreaub625a082007-11-26 01:15:43 +0100101/* This function simply updates the backend's tot_weight and tot_used values
102 * after servers weights have been updated. It is designed to be used after
103 * recount_servers() or equivalent.
104 */
105static void update_backend_weight(struct proxy *px)
106{
Willy Tarreau20697042007-11-15 23:26:18 +0100107 if (px->srv_act) {
108 px->lbprm.tot_weight = px->lbprm.tot_wact;
109 px->lbprm.tot_used = px->srv_act;
110 }
Willy Tarreaub625a082007-11-26 01:15:43 +0100111 else if (px->lbprm.fbck) {
112 /* use only the first backup server */
113 px->lbprm.tot_weight = px->lbprm.fbck->eweight;
114 px->lbprm.tot_used = 1;
Willy Tarreau20697042007-11-15 23:26:18 +0100115 }
116 else {
Willy Tarreaub625a082007-11-26 01:15:43 +0100117 px->lbprm.tot_weight = px->lbprm.tot_wbck;
118 px->lbprm.tot_used = px->srv_bck;
Willy Tarreau20697042007-11-15 23:26:18 +0100119 }
Willy Tarreaub625a082007-11-26 01:15:43 +0100120}
121
122/* this function updates the map according to server <srv>'s new state */
123static void map_set_server_status_down(struct server *srv)
124{
125 struct proxy *p = srv->proxy;
126
127 if (srv->state == srv->prev_state &&
128 srv->eweight == srv->prev_eweight)
129 return;
130
131 /* FIXME: could be optimized since we know what changed */
132 recount_servers(p);
133 update_backend_weight(p);
134 srv->prev_state = srv->state;
135 srv->prev_eweight = srv->eweight;
136 p->lbprm.map.state |= PR_MAP_RECALC;
Willy Tarreau20697042007-11-15 23:26:18 +0100137
Willy Tarreaubaaee002006-06-26 02:48:02 +0200138}
139
Willy Tarreaub625a082007-11-26 01:15:43 +0100140/* this function updates the map according to server <srv>'s new state */
141static void map_set_server_status_up(struct server *srv)
142{
143 struct proxy *p = srv->proxy;
144
145 if (srv->state == srv->prev_state &&
146 srv->eweight == srv->prev_eweight)
147 return;
148
149 /* FIXME: could be optimized since we know what changed */
150 recount_servers(p);
151 update_backend_weight(p);
152 srv->prev_state = srv->state;
153 srv->prev_eweight = srv->eweight;
154 p->lbprm.map.state |= PR_MAP_RECALC;
155}
156
Willy Tarreau20697042007-11-15 23:26:18 +0100157/* This function recomputes the server map for proxy px. It relies on
158 * px->lbprm.tot_wact, tot_wbck, tot_used, tot_weight, so it must be
159 * called after recount_servers(). It also expects px->lbprm.map.srv
160 * to be allocated with the largest size needed. It updates tot_weight.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200161 */
162void recalc_server_map(struct proxy *px)
163{
164 int o, tot, flag;
165 struct server *cur, *best;
166
Willy Tarreau20697042007-11-15 23:26:18 +0100167 switch (px->lbprm.tot_used) {
168 case 0: /* no server */
169 px->lbprm.map.state &= ~PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170 return;
Willy Tarreau20697042007-11-15 23:26:18 +0100171 case 1: /* only one server, just fill first entry */
172 tot = 1;
173 break;
174 default:
175 tot = px->lbprm.tot_weight;
176 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177 }
178
Willy Tarreau20697042007-11-15 23:26:18 +0100179 /* here we *know* that we have some servers */
180 if (px->srv_act)
181 flag = SRV_RUNNING;
182 else
183 flag = SRV_RUNNING | SRV_BACKUP;
184
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 /* this algorithm gives priority to the first server, which means that
186 * it will respect the declaration order for equivalent weights, and
187 * that whatever the weights, the first server called will always be
Willy Tarreau20697042007-11-15 23:26:18 +0100188 * the first declared. This is an important asumption for the backup
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189 * case, where we want the first server only.
190 */
191 for (cur = px->srv; cur; cur = cur->next)
192 cur->wscore = 0;
193
194 for (o = 0; o < tot; o++) {
195 int max = 0;
196 best = NULL;
197 for (cur = px->srv; cur; cur = cur->next) {
Willy Tarreau48494c02007-11-30 10:41:39 +0100198 if (flag == (cur->state &
199 (SRV_RUNNING | SRV_GOINGDOWN | SRV_BACKUP))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 int v;
201
202 /* If we are forced to return only one server, we don't want to
203 * go further, because we would return the wrong one due to
204 * divide overflow.
205 */
206 if (tot == 1) {
207 best = cur;
Willy Tarreau20697042007-11-15 23:26:18 +0100208 /* note that best->wscore will be wrong but we don't care */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209 break;
210 }
211
Willy Tarreau417fae02007-03-25 21:16:40 +0200212 cur->wscore += cur->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213 v = (cur->wscore + tot) / tot; /* result between 0 and 3 */
214 if (best == NULL || v > max) {
215 max = v;
216 best = cur;
217 }
218 }
219 }
Willy Tarreau20697042007-11-15 23:26:18 +0100220 px->lbprm.map.srv[o] = best;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 best->wscore -= tot;
222 }
Willy Tarreau20697042007-11-15 23:26:18 +0100223 px->lbprm.map.state &= ~PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224}
225
Willy Tarreau5dc2fa62007-11-19 19:10:18 +0100226/* This function is responsible of building the server MAP for map-based LB
227 * algorithms, allocating the map, and setting p->lbprm.wmult to the GCD of the
228 * weights if applicable. It should be called only once per proxy, at config
229 * time.
230 */
231void init_server_map(struct proxy *p)
232{
233 struct server *srv;
234 int pgcd;
235 int act, bck;
236
Willy Tarreaub625a082007-11-26 01:15:43 +0100237 p->lbprm.set_server_status_up = map_set_server_status_up;
238 p->lbprm.set_server_status_down = map_set_server_status_down;
239 p->lbprm.update_server_eweight = NULL;
240
Willy Tarreau5dc2fa62007-11-19 19:10:18 +0100241 if (!p->srv)
242 return;
243
244 /* We will factor the weights to reduce the table,
245 * using Euclide's largest common divisor algorithm
246 */
247 pgcd = p->srv->uweight;
248 for (srv = p->srv->next; srv && pgcd > 1; srv = srv->next) {
249 int w = srv->uweight;
250 while (w) {
251 int t = pgcd % w;
252 pgcd = w;
253 w = t;
254 }
255 }
256
257 /* It is sometimes useful to know what factor to apply
258 * to the backend's effective weight to know its real
259 * weight.
260 */
261 p->lbprm.wmult = pgcd;
262
263 act = bck = 0;
264 for (srv = p->srv; srv; srv = srv->next) {
265 srv->eweight = srv->uweight / pgcd;
Willy Tarreaub625a082007-11-26 01:15:43 +0100266 srv->prev_eweight = srv->eweight;
267 srv->prev_state = srv->state;
Willy Tarreau5dc2fa62007-11-19 19:10:18 +0100268 if (srv->state & SRV_BACKUP)
269 bck += srv->eweight;
270 else
271 act += srv->eweight;
272 }
273
274 /* this is the largest map we will ever need for this servers list */
275 if (act < bck)
276 act = bck;
277
278 p->lbprm.map.srv = (struct server **)calloc(act, sizeof(struct server *));
279 /* recounts servers and their weights */
280 p->lbprm.map.state = PR_MAP_RECALC;
281 recount_servers(p);
Willy Tarreaub625a082007-11-26 01:15:43 +0100282 update_backend_weight(p);
Willy Tarreau5dc2fa62007-11-19 19:10:18 +0100283 recalc_server_map(p);
284}
285
Willy Tarreaub625a082007-11-26 01:15:43 +0100286/* This function updates the server trees according to server <srv>'s new
287 * state. It should be called when server <srv>'s status changes to down.
288 * It is not important whether the server was already down or not. However,
289 * it is mandatory that the new state be down.
290 */
291static void fwrr_set_server_status_down(struct server *srv)
292{
293 struct proxy *p = srv->proxy;
294 struct fwrr_group *grp;
295
296 if (srv->state == srv->prev_state &&
297 srv->eweight == srv->prev_eweight)
298 return;
299
300 if (!srv_is_usable(srv->prev_state, srv->prev_eweight))
301 /* server was already down */
302 goto out_update_backend;
303
304 grp = (srv->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
305 grp->next_weight -= srv->prev_eweight;
306
307 if (srv->state & SRV_BACKUP) {
308 p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
309 p->srv_bck--;
310
311 if (srv == p->lbprm.fbck) {
312 /* we lost the first backup server in a single-backup
313 * configuration, we must search another one.
314 */
315 struct server *srv2 = p->lbprm.fbck;
316 do {
317 srv2 = srv2->next;
318 } while (srv2 &&
319 !((srv2->state & SRV_BACKUP) &&
320 srv_is_usable(srv2->state, srv2->eweight)));
321 p->lbprm.fbck = srv2;
322 }
323 } else {
324 p->lbprm.tot_wact = p->lbprm.fwrr.act.next_weight;
325 p->srv_act--;
326 }
327
328 fwrr_dequeue_srv(srv);
329 fwrr_remove_from_tree(srv);
330
331out_update_backend:
332 /* check/update tot_used, tot_weight */
333 update_backend_weight(p);
334 srv->prev_state = srv->state;
335 srv->prev_eweight = srv->eweight;
336
337}
338
339/* This function updates the server trees according to server <srv>'s new
340 * state. It should be called when server <srv>'s status changes to up.
341 * It is not important whether the server was already down or not. However,
342 * it is mandatory that the new state be up. This function will not change
343 * the weight of a server which was already up.
344 */
345static void fwrr_set_server_status_up(struct server *srv)
346{
347 struct proxy *p = srv->proxy;
348 struct fwrr_group *grp;
349
350 if (srv->state == srv->prev_state &&
351 srv->eweight == srv->prev_eweight)
352 return;
353
354 if (srv_is_usable(srv->prev_state, srv->prev_eweight))
355 /* server was already up */
356 goto out_update_backend;
357
358 grp = (srv->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
359 grp->next_weight += srv->eweight;
360
361 if (srv->state & SRV_BACKUP) {
362 p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
363 p->srv_bck++;
364
365 if (p->lbprm.fbck) {
366 /* we may have restored a backup server prior to fbck,
367 * in which case it should replace it.
368 */
369 struct server *srv2 = srv;
370 do {
371 srv2 = srv2->next;
372 } while (srv2 && (srv2 != p->lbprm.fbck));
373 if (srv2)
374 p->lbprm.fbck = srv;
375 }
376 } else {
377 p->lbprm.tot_wact = p->lbprm.fwrr.act.next_weight;
378 p->srv_act++;
379 }
380
381 /* note that eweight cannot be 0 here */
382 fwrr_get_srv(srv);
383 srv->npos = grp->curr_pos + (grp->next_weight + grp->curr_weight - grp->curr_pos) / srv->eweight;
384 fwrr_queue_srv(srv);
385
386out_update_backend:
387 /* check/update tot_used, tot_weight */
388 update_backend_weight(p);
389 srv->prev_state = srv->state;
390 srv->prev_eweight = srv->eweight;
391}
392
393/* This function must be called after an update to server <srv>'s effective
394 * weight. It may be called after a state change too.
395 */
396static void fwrr_update_server_weight(struct server *srv)
397{
398 int old_state, new_state;
399 struct proxy *p = srv->proxy;
400 struct fwrr_group *grp;
401
402 if (srv->state == srv->prev_state &&
403 srv->eweight == srv->prev_eweight)
404 return;
405
406 /* If changing the server's weight changes its state, we simply apply
407 * the procedures we already have for status change. If the state
408 * remains down, the server is not in any tree, so it's as easy as
409 * updating its values. If the state remains up with different weights,
410 * there are some computations to perform to find a new place and
411 * possibly a new tree for this server.
412 */
413
414 old_state = srv_is_usable(srv->prev_state, srv->prev_eweight);
415 new_state = srv_is_usable(srv->state, srv->eweight);
416
417 if (!old_state && !new_state) {
418 srv->prev_state = srv->state;
419 srv->prev_eweight = srv->eweight;
420 return;
421 }
422 else if (!old_state && new_state) {
423 fwrr_set_server_status_up(srv);
424 return;
425 }
426 else if (old_state && !new_state) {
427 fwrr_set_server_status_down(srv);
428 return;
429 }
430
431 grp = (srv->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
432 grp->next_weight = grp->next_weight - srv->prev_eweight + srv->eweight;
433
434 p->lbprm.tot_wact = p->lbprm.fwrr.act.next_weight;
435 p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
436
437 if (srv->lb_tree == grp->init) {
438 fwrr_dequeue_srv(srv);
439 fwrr_queue_by_weight(grp->init, srv);
440 }
441 else if (!srv->lb_tree) {
442 /* FIXME: server was down. This is not possible right now but
443 * may be needed soon for slowstart or graceful shutdown.
444 */
445 fwrr_dequeue_srv(srv);
446 fwrr_get_srv(srv);
447 srv->npos = grp->curr_pos + (grp->next_weight + grp->curr_weight - grp->curr_pos) / srv->eweight;
448 fwrr_queue_srv(srv);
449 } else {
450 /* The server is either active or in the next queue. If it's
451 * still in the active queue and it has not consumed all of its
452 * places, let's adjust its next position.
453 */
454 fwrr_get_srv(srv);
455
456 if (srv->eweight > 0) {
457 int prev_next = srv->npos;
458 int step = grp->next_weight / srv->eweight;
459
460 srv->npos = srv->lpos + step;
461 srv->rweight = 0;
462
463 if (srv->npos > prev_next)
464 srv->npos = prev_next;
465 if (srv->npos < grp->curr_pos + 2)
466 srv->npos = grp->curr_pos + step;
467 } else {
468 /* push it into the next tree */
469 srv->npos = grp->curr_pos + grp->curr_weight;
470 }
471
472 fwrr_dequeue_srv(srv);
473 fwrr_queue_srv(srv);
474 }
475
476 update_backend_weight(p);
477 srv->prev_state = srv->state;
478 srv->prev_eweight = srv->eweight;
479}
480
481/* Remove a server from a tree. It must have previously been dequeued. This
482 * function is meant to be called when a server is going down or has its
483 * weight disabled.
484 */
485static inline void fwrr_remove_from_tree(struct server *s)
486{
487 s->lb_tree = NULL;
488}
489
490/* Queue a server in the weight tree <root>, assuming the weight is >0.
491 * We want to sort them by inverted weights, because we need to place
492 * heavy servers first in order to get a smooth distribution.
493 */
494static inline void fwrr_queue_by_weight(struct eb_root *root, struct server *s)
495{
496 /* eweight can be as high as 256*255 */
497 s->lb_node.key = BE_WEIGHT_SCALE*255 - s->eweight;
498 eb32_insert(root, &s->lb_node);
499 s->lb_tree = root;
500}
501
502/* This function is responsible for building the weight trees in case of fast
503 * weighted round-robin. It also sets p->lbprm.wdiv to the eweight to uweight
504 * ratio. Both active and backup groups are initialized.
505 */
506void fwrr_init_server_groups(struct proxy *p)
507{
508 struct server *srv;
509 struct eb_root init_head = EB_ROOT;
510
511 p->lbprm.set_server_status_up = fwrr_set_server_status_up;
512 p->lbprm.set_server_status_down = fwrr_set_server_status_down;
513 p->lbprm.update_server_eweight = fwrr_update_server_weight;
514
515 p->lbprm.wdiv = BE_WEIGHT_SCALE;
516 for (srv = p->srv; srv; srv = srv->next) {
517 srv->prev_eweight = srv->eweight = srv->uweight * BE_WEIGHT_SCALE;
518 srv->prev_state = srv->state;
519 }
520
521 recount_servers(p);
522 update_backend_weight(p);
523
524 /* prepare the active servers group */
525 p->lbprm.fwrr.act.curr_pos = p->lbprm.fwrr.act.curr_weight =
526 p->lbprm.fwrr.act.next_weight = p->lbprm.tot_wact;
527 p->lbprm.fwrr.act.curr = p->lbprm.fwrr.act.t0 =
528 p->lbprm.fwrr.act.t1 = init_head;
529 p->lbprm.fwrr.act.init = &p->lbprm.fwrr.act.t0;
530 p->lbprm.fwrr.act.next = &p->lbprm.fwrr.act.t1;
531
532 /* prepare the backup servers group */
533 p->lbprm.fwrr.bck.curr_pos = p->lbprm.fwrr.bck.curr_weight =
534 p->lbprm.fwrr.bck.next_weight = p->lbprm.tot_wbck;
535 p->lbprm.fwrr.bck.curr = p->lbprm.fwrr.bck.t0 =
536 p->lbprm.fwrr.bck.t1 = init_head;
537 p->lbprm.fwrr.bck.init = &p->lbprm.fwrr.bck.t0;
538 p->lbprm.fwrr.bck.next = &p->lbprm.fwrr.bck.t1;
539
540 /* queue active and backup servers in two distinct groups */
541 for (srv = p->srv; srv; srv = srv->next) {
542 if (!srv_is_usable(srv->state, srv->eweight))
543 continue;
544 fwrr_queue_by_weight((srv->state & SRV_BACKUP) ?
545 p->lbprm.fwrr.bck.init :
546 p->lbprm.fwrr.act.init,
547 srv);
548 }
549}
550
551/* simply removes a server from a weight tree */
552static inline void fwrr_dequeue_srv(struct server *s)
553{
554 eb32_delete(&s->lb_node);
555}
556
557/* queues a server into the appropriate group and tree depending on its
558 * backup status, and ->npos. If the server is disabled, simply assign
559 * it to the NULL tree.
560 */
561static void fwrr_queue_srv(struct server *s)
562{
563 struct proxy *p = s->proxy;
564 struct fwrr_group *grp;
565
566 grp = (s->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
567
568 /* Delay everything which does not fit into the window and everything
569 * which does not fit into the theorical new window.
570 */
571 if (!srv_is_usable(s->state, s->eweight)) {
572 fwrr_remove_from_tree(s);
573 }
574 else if (s->eweight <= 0 ||
575 s->npos >= 2 * grp->curr_weight ||
576 s->npos >= grp->curr_weight + grp->next_weight) {
577 /* put into next tree, and readjust npos in case we could
578 * finally take this back to current. */
579 s->npos -= grp->curr_weight;
580 fwrr_queue_by_weight(grp->next, s);
581 }
582 else {
583 /* FIXME: we want to multiply by a constant to avoid overrides
584 * after weight changes, but this can easily overflow on 32-bit
585 * values. We need to change this for a 64-bit tree, and keep
586 * the 65536 factor for optimal smoothness (both rweight and
587 * eweight are 16 bit entities). s->npos is bound by the number
588 * of servers times the maximum eweight (~= nsrv << 16).
589 */
590 //s->lb_node.key = grp->curr_weight * s->npos + s->rweight - s->eweight;
591 //s->lb_node.key = 65536 * s->npos + s->rweight - s->eweight;
592 s->lb_node.key = 16 * s->npos + (s->rweight - s->eweight) / 4096;
593 eb32i_insert(&grp->curr, &s->lb_node);
594 s->lb_tree = &grp->curr;
595 }
596}
597
598/* prepares a server when extracting it from the "init" tree */
599static inline void fwrr_get_srv_init(struct server *s)
600{
601 s->npos = s->rweight = 0;
602}
603
604/* prepares a server when extracting it from the "next" tree */
605static inline void fwrr_get_srv_next(struct server *s)
606{
607 struct fwrr_group *grp = (s->state & SRV_BACKUP) ?
608 &s->proxy->lbprm.fwrr.bck :
609 &s->proxy->lbprm.fwrr.act;
610
611 s->npos += grp->curr_weight;
612}
613
614/* prepares a server when it was marked down */
615static inline void fwrr_get_srv_down(struct server *s)
616{
617 struct fwrr_group *grp = (s->state & SRV_BACKUP) ?
618 &s->proxy->lbprm.fwrr.bck :
619 &s->proxy->lbprm.fwrr.act;
620
621 s->npos = grp->curr_pos;
622}
623
624/* prepares a server when extracting it from its tree */
625static void fwrr_get_srv(struct server *s)
626{
627 struct proxy *p = s->proxy;
628 struct fwrr_group *grp = (s->state & SRV_BACKUP) ?
629 &p->lbprm.fwrr.bck :
630 &p->lbprm.fwrr.act;
631
632 if (s->lb_tree == grp->init) {
633 fwrr_get_srv_init(s);
634 }
635 else if (s->lb_tree == grp->next) {
636 fwrr_get_srv_next(s);
637 }
638 else if (s->lb_tree == NULL) {
639 fwrr_get_srv_down(s);
640 }
641}
642
643/* switches trees "init" and "next" for FWRR group <grp>. "init" should be empty
644 * when this happens, and "next" filled with servers sorted by weights.
645 */
646static inline void fwrr_switch_trees(struct fwrr_group *grp)
647{
648 struct eb_root *swap;
649 swap = grp->init;
650 grp->init = grp->next;
651 grp->next = swap;
652 grp->curr_weight = grp->next_weight;
653 grp->curr_pos = grp->curr_weight;
654}
655
656/* return next server from the current tree in FWRR group <grp>, or a server
657 * from the "init" tree if appropriate. If both trees are empty, return NULL.
658 */
659static struct server *fwrr_get_server_from_group(struct fwrr_group *grp)
660{
661 struct eb32_node *node;
662 struct server *s;
663
664 node = eb32_first(&grp->curr);
665 s = eb32_entry(node, struct server, lb_node);
666
667 if (!node || s->npos > grp->curr_pos) {
668 /* either we have no server left, or we have a hole */
669 struct eb32_node *node2;
670 node2 = eb32_first(grp->init);
671 if (node2) {
672 node = node2;
673 s = eb32_entry(node, struct server, lb_node);
674 fwrr_get_srv_init(s);
675 if (s->eweight == 0) /* FIXME: is it possible at all ? */
676 node = NULL;
677 }
678 }
679 if (node)
680 return s;
681 else
682 return NULL;
683}
684
685/* Computes next position of server <s> in the group. It is mandatory for <s>
686 * to have a non-zero, positive eweight.
687*/
688static inline void fwrr_update_position(struct fwrr_group *grp, struct server *s)
689{
690 if (!s->npos) {
691 /* first time ever for this server */
692 s->lpos = grp->curr_pos;
693 s->npos = grp->curr_pos + grp->next_weight / s->eweight;
694 s->rweight += grp->next_weight % s->eweight;
695
696 if (s->rweight >= s->eweight) {
697 s->rweight -= s->eweight;
698 s->npos++;
699 }
700 } else {
701 s->lpos = s->npos;
702 s->npos += grp->next_weight / s->eweight;
703 s->rweight += grp->next_weight % s->eweight;
704
705 if (s->rweight >= s->eweight) {
706 s->rweight -= s->eweight;
707 s->npos++;
708 }
709 }
710}
711
712/* Return next server from the current tree in backend <p>, or a server from
713 * the init tree if appropriate. If both trees are empty, return NULL.
714 * Saturated servers are skipped and requeued.
715 */
716static struct server *fwrr_get_next_server(struct proxy *p)
717{
718 struct server *srv;
719 struct fwrr_group *grp;
720 struct server *full;
721 int switched;
722
723 if (p->srv_act)
724 grp = &p->lbprm.fwrr.act;
725 else if (p->lbprm.fbck)
726 return p->lbprm.fbck;
727 else if (p->srv_bck)
728 grp = &p->lbprm.fwrr.bck;
729 else
730 return NULL;
731
732 switched = 0;
733 full = NULL; /* NULL-terminated list of saturated servers */
734 while (1) {
735 /* if we see an empty group, let's first try to collect weights
736 * which might have recently changed.
737 */
738 if (!grp->curr_weight)
739 grp->curr_pos = grp->curr_weight = grp->next_weight;
740
741 /* get first server from the "current" tree. When the end of
742 * the tree is reached, we may have to switch, but only once.
743 */
744 while (1) {
745 srv = fwrr_get_server_from_group(grp);
746 if (srv)
747 break;
748 if (switched)
749 goto requeue_servers;
750 switched = 1;
751 fwrr_switch_trees(grp);
752
753 }
754
755 /* OK, we have a server. However, it may be saturated, in which
756 * case we don't want to reconsider it for now. We'll update
757 * its position and dequeue it anyway, so that we can move it
758 * to a better place afterwards.
759 */
760 fwrr_update_position(grp, srv);
761 fwrr_dequeue_srv(srv);
762 grp->curr_pos++;
763 if (!srv->maxconn || srv->cur_sess < srv_dynamic_maxconn(srv))
764 break;
765
766 /* the server is saturated, let's chain it for later reinsertion */
767 srv->next_full = full;
768 full = srv;
769 }
770
771 /* OK, we got the best server, let's update it */
772 fwrr_queue_srv(srv);
773
774 requeue_servers:
775 if (unlikely(full)) {
776 if (switched) {
777 /* the tree has switched, requeue all extracted servers
778 * into "init", because their place was lost, and only
779 * their weight matters.
780 */
781 do {
782 fwrr_queue_by_weight(grp->init, full);
783 full = full->next_full;
784 } while (full);
785 } else {
786 /* requeue all extracted servers just as if they were consumed
787 * so that they regain their expected place.
788 */
789 do {
790 fwrr_queue_srv(full);
791 full = full->next_full;
792 } while (full);
793 }
794 }
795 return srv;
796}
797
Willy Tarreau01732802007-11-01 22:48:15 +0100798/*
799 * This function tries to find a running server for the proxy <px> following
800 * the URL parameter hash method. It looks for a specific parameter in the
801 * URL and hashes it to compute the server ID. This is useful to optimize
802 * performance by avoiding bounces between servers in contexts where sessions
803 * are shared but cookies are not usable. If the parameter is not found, NULL
804 * is returned. If any server is found, it will be returned. If no valid server
805 * is found, NULL is returned.
806 *
807 */
808struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len)
809{
810 unsigned long hash = 0;
811 char *p;
812 int plen;
813
Willy Tarreau20697042007-11-15 23:26:18 +0100814 if (px->lbprm.tot_weight == 0)
Willy Tarreau01732802007-11-01 22:48:15 +0100815 return NULL;
816
Willy Tarreau20697042007-11-15 23:26:18 +0100817 if (px->lbprm.map.state & PR_MAP_RECALC)
818 recalc_server_map(px);
819
Willy Tarreau01732802007-11-01 22:48:15 +0100820 p = memchr(uri, '?', uri_len);
821 if (!p)
822 return NULL;
823 p++;
824
825 uri_len -= (p - uri);
826 plen = px->url_param_len;
827
828 if (uri_len <= plen)
829 return NULL;
830
831 while (uri_len > plen) {
832 /* Look for the parameter name followed by an equal symbol */
833 if (p[plen] == '=') {
834 /* skip the equal symbol */
835 uri = p;
836 p += plen + 1;
837 uri_len -= plen + 1;
838 if (memcmp(uri, px->url_param_name, plen) == 0) {
839 /* OK, we have the parameter here at <uri>, and
840 * the value after the equal sign, at <p>
841 */
842 while (uri_len && *p != '&') {
843 hash = *p + (hash << 6) + (hash << 16) - hash;
844 uri_len--;
845 p++;
846 }
Willy Tarreau20697042007-11-15 23:26:18 +0100847 return px->lbprm.map.srv[hash % px->lbprm.tot_weight];
Willy Tarreau01732802007-11-01 22:48:15 +0100848 }
849 }
850
851 /* skip to next parameter */
852 uri = p;
853 p = memchr(uri, '&', uri_len);
854 if (!p)
855 return NULL;
856 p++;
857 uri_len -= (p - uri);
858 }
859 return NULL;
860}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200861
862/*
863 * This function marks the session as 'assigned' in direct or dispatch modes,
864 * or tries to assign one in balance mode, according to the algorithm. It does
865 * nothing if the session had already been assigned a server.
866 *
867 * It may return :
868 * SRV_STATUS_OK if everything is OK. s->srv will be valid.
869 * SRV_STATUS_NOSRV if no server is available. s->srv = NULL.
870 * SRV_STATUS_FULL if all servers are saturated. s->srv = NULL.
871 * SRV_STATUS_INTERNAL for other unrecoverable errors.
872 *
873 * Upon successful return, the session flag SN_ASSIGNED to indicate that it does
874 * not need to be called anymore. This usually means that s->srv can be trusted
875 * in balance and direct modes. This flag is not cleared, so it's to the caller
876 * to clear it if required (eg: redispatch).
877 *
878 */
879
880int assign_server(struct session *s)
881{
882#ifdef DEBUG_FULL
883 fprintf(stderr,"assign_server : s=%p\n",s);
884#endif
885
886 if (s->pend_pos)
887 return SRV_STATUS_INTERNAL;
888
889 if (!(s->flags & SN_ASSIGNED)) {
Willy Tarreau31682232007-11-29 15:38:04 +0100890 if (s->be->lbprm.algo & BE_LB_ALGO) {
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100891 int len;
892
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100893 if (s->flags & SN_DIRECT) {
894 s->flags |= SN_ASSIGNED;
895 return SRV_STATUS_OK;
896 }
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100897
Willy Tarreaub625a082007-11-26 01:15:43 +0100898 if (!s->be->lbprm.tot_weight)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899 return SRV_STATUS_NOSRV;
900
Willy Tarreau31682232007-11-29 15:38:04 +0100901 switch (s->be->lbprm.algo & BE_LB_ALGO) {
902 case BE_LB_ALGO_RR:
Willy Tarreaub625a082007-11-26 01:15:43 +0100903 s->srv = fwrr_get_next_server(s->be);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 if (!s->srv)
905 return SRV_STATUS_FULL;
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100906 break;
Willy Tarreau31682232007-11-29 15:38:04 +0100907 case BE_LB_ALGO_SH:
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 if (s->cli_addr.ss_family == AF_INET)
909 len = 4;
910 else if (s->cli_addr.ss_family == AF_INET6)
911 len = 16;
912 else /* unknown IP family */
913 return SRV_STATUS_INTERNAL;
914
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200915 s->srv = get_server_sh(s->be,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 (void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
917 len);
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100918 break;
Willy Tarreau31682232007-11-29 15:38:04 +0100919 case BE_LB_ALGO_UH:
Willy Tarreau2fcb5002007-05-08 13:35:26 +0200920 /* URI hashing */
921 s->srv = get_server_uh(s->be,
922 s->txn.req.sol + s->txn.req.sl.rq.u,
923 s->txn.req.sl.rq.u_l);
Willy Tarreau01732802007-11-01 22:48:15 +0100924 break;
Willy Tarreau31682232007-11-29 15:38:04 +0100925 case BE_LB_ALGO_PH:
Willy Tarreau01732802007-11-01 22:48:15 +0100926 /* URL Parameter hashing */
927 s->srv = get_server_ph(s->be,
928 s->txn.req.sol + s->txn.req.sl.rq.u,
929 s->txn.req.sl.rq.u_l);
930 if (!s->srv) {
Willy Tarreaub625a082007-11-26 01:15:43 +0100931 /* parameter not found, fall back to round robin on the map */
Willy Tarreau01732802007-11-01 22:48:15 +0100932 s->srv = get_server_rr_with_conns(s->be);
933 if (!s->srv)
934 return SRV_STATUS_FULL;
935 }
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100936 break;
937 default:
938 /* unknown balancing algorithm */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 return SRV_STATUS_INTERNAL;
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100940 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200941 }
Alexandre Cassen5eb1a902007-11-29 15:43:32 +0100942 else if (s->be->options & PR_O_HTTP_PROXY) {
943 if (!s->srv_addr.sin_addr.s_addr)
944 return SRV_STATUS_NOSRV;
945 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200946 else if (!*(int *)&s->be->dispatch_addr.sin_addr &&
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100947 !(s->fe->options & PR_O_TRANSP)) {
Willy Tarreau1a1158b2007-01-20 11:07:46 +0100948 return SRV_STATUS_NOSRV;
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100949 }
950 s->flags |= SN_ASSIGNED;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 }
952 return SRV_STATUS_OK;
953}
954
955
956/*
957 * This function assigns a server address to a session, and sets SN_ADDR_SET.
958 * The address is taken from the currently assigned server, or from the
959 * dispatch or transparent address.
960 *
961 * It may return :
962 * SRV_STATUS_OK if everything is OK.
963 * SRV_STATUS_INTERNAL for other unrecoverable errors.
964 *
965 * Upon successful return, the session flag SN_ADDR_SET is set. This flag is
966 * not cleared, so it's to the caller to clear it if required.
967 *
968 */
969int assign_server_address(struct session *s)
970{
971#ifdef DEBUG_FULL
972 fprintf(stderr,"assign_server_address : s=%p\n",s);
973#endif
974
Willy Tarreau31682232007-11-29 15:38:04 +0100975 if ((s->flags & SN_DIRECT) || (s->be->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200976 /* A server is necessarily known for this session */
977 if (!(s->flags & SN_ASSIGNED))
978 return SRV_STATUS_INTERNAL;
979
980 s->srv_addr = s->srv->addr;
981
982 /* if this server remaps proxied ports, we'll use
983 * the port the client connected to with an offset. */
984 if (s->srv->state & SRV_MAPPORTS) {
Willy Tarreau14c8aac2007-05-08 19:46:30 +0200985 if (!(s->fe->options & PR_O_TRANSP) && !(s->flags & SN_FRT_ADDR_SET))
986 get_frt_addr(s);
987 if (s->frt_addr.ss_family == AF_INET) {
988 s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
989 ntohs(((struct sockaddr_in *)&s->frt_addr)->sin_port));
990 } else {
991 s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
992 ntohs(((struct sockaddr_in6 *)&s->frt_addr)->sin6_port));
993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200994 }
995 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200996 else if (*(int *)&s->be->dispatch_addr.sin_addr) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 /* connect to the defined dispatch addr */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200998 s->srv_addr = s->be->dispatch_addr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
Willy Tarreau73de9892006-11-30 11:40:23 +01001000 else if (s->fe->options & PR_O_TRANSP) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001001 /* in transparent mode, use the original dest addr if no dispatch specified */
1002 socklen_t salen = sizeof(s->srv_addr);
1003
1004 if (get_original_dst(s->cli_fd, &s->srv_addr, &salen) == -1) {
1005 qfprintf(stderr, "Cannot get original server address.\n");
1006 return SRV_STATUS_INTERNAL;
1007 }
1008 }
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01001009 else if (s->be->options & PR_O_HTTP_PROXY) {
1010 /* If HTTP PROXY option is set, then server is already assigned
1011 * during incoming client request parsing. */
1012 }
Willy Tarreau1a1158b2007-01-20 11:07:46 +01001013 else {
1014 /* no server and no LB algorithm ! */
1015 return SRV_STATUS_INTERNAL;
1016 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017
1018 s->flags |= SN_ADDR_SET;
1019 return SRV_STATUS_OK;
1020}
1021
1022
1023/* This function assigns a server to session <s> if required, and can add the
1024 * connection to either the assigned server's queue or to the proxy's queue.
1025 *
1026 * Returns :
1027 *
1028 * SRV_STATUS_OK if everything is OK.
1029 * SRV_STATUS_NOSRV if no server is available. s->srv = NULL.
1030 * SRV_STATUS_QUEUED if the connection has been queued.
1031 * SRV_STATUS_FULL if the server(s) is/are saturated and the
1032 * connection could not be queued.
1033 * SRV_STATUS_INTERNAL for other unrecoverable errors.
1034 *
1035 */
1036int assign_server_and_queue(struct session *s)
1037{
1038 struct pendconn *p;
1039 int err;
1040
1041 if (s->pend_pos)
1042 return SRV_STATUS_INTERNAL;
1043
1044 if (s->flags & SN_ASSIGNED) {
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001045 if (s->srv && s->srv->maxqueue > 0 && s->srv->nbpend >= s->srv->maxqueue) {
1046 s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
1047 s->srv = NULL;
1048 http_flush_cookie_flags(&s->txn);
1049 } else {
1050 /* a server does not need to be assigned, perhaps because we're in
1051 * direct mode, or in dispatch or transparent modes where the server
1052 * is not needed.
1053 */
1054 if (s->srv &&
1055 s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
1056 p = pendconn_add(s);
1057 if (p)
1058 return SRV_STATUS_QUEUED;
1059 else
1060 return SRV_STATUS_FULL;
1061 }
1062 return SRV_STATUS_OK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 }
1065
1066 /* a server needs to be assigned */
1067 err = assign_server(s);
1068 switch (err) {
1069 case SRV_STATUS_OK:
1070 /* in balance mode, we might have servers with connection limits */
1071 if (s->srv &&
1072 s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
1073 p = pendconn_add(s);
1074 if (p)
1075 return SRV_STATUS_QUEUED;
1076 else
1077 return SRV_STATUS_FULL;
1078 }
1079 return SRV_STATUS_OK;
1080
1081 case SRV_STATUS_FULL:
1082 /* queue this session into the proxy's queue */
1083 p = pendconn_add(s);
1084 if (p)
1085 return SRV_STATUS_QUEUED;
1086 else
1087 return SRV_STATUS_FULL;
1088
1089 case SRV_STATUS_NOSRV:
1090 case SRV_STATUS_INTERNAL:
1091 return err;
1092 default:
1093 return SRV_STATUS_INTERNAL;
1094 }
1095}
1096
1097
1098/*
1099 * This function initiates a connection to the server assigned to this session
1100 * (s->srv, s->srv_addr). It will assign a server if none is assigned yet.
1101 * It can return one of :
1102 * - SN_ERR_NONE if everything's OK
1103 * - SN_ERR_SRVTO if there are no more servers
1104 * - SN_ERR_SRVCL if the connection was refused by the server
1105 * - SN_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
1106 * - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
1107 * - SN_ERR_INTERNAL for any other purely internal errors
1108 * Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
1109 */
1110int connect_server(struct session *s)
1111{
1112 int fd, err;
1113
1114 if (!(s->flags & SN_ADDR_SET)) {
1115 err = assign_server_address(s);
1116 if (err != SRV_STATUS_OK)
1117 return SN_ERR_INTERNAL;
1118 }
1119
1120 if ((fd = s->srv_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
1121 qfprintf(stderr, "Cannot get a server socket.\n");
1122
1123 if (errno == ENFILE)
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001124 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 "Proxy %s reached system FD limit at %d. Please check system tunables.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001126 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 else if (errno == EMFILE)
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001128 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 "Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001130 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131 else if (errno == ENOBUFS || errno == ENOMEM)
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001132 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 "Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001134 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 /* this is a resource error */
1136 return SN_ERR_RESOURCE;
1137 }
1138
1139 if (fd >= global.maxsock) {
1140 /* do not log anything there, it's a normal condition when this option
1141 * is used to serialize connections to a server !
1142 */
1143 Alert("socket(): not enough free sockets. Raise -n argument. Giving up.\n");
1144 close(fd);
1145 return SN_ERR_PRXCOND; /* it is a configuration limit */
1146 }
1147
Willy Tarreau6d1a9882007-01-07 02:03:04 +01001148#ifdef CONFIG_HAP_TCPSPLICE
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001149 if ((s->fe->options & s->be->options) & PR_O_TCPSPLICE) {
Willy Tarreau6d1a9882007-01-07 02:03:04 +01001150 /* TCP splicing supported by both FE and BE */
1151 tcp_splice_initfd(s->cli_fd, fd);
1152 }
1153#endif
1154
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 if ((fcntl(fd, F_SETFL, O_NONBLOCK)==-1) ||
1156 (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) == -1)) {
1157 qfprintf(stderr,"Cannot set client socket to non blocking mode.\n");
1158 close(fd);
1159 return SN_ERR_INTERNAL;
1160 }
1161
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001162 if (s->be->options & PR_O_TCP_SRV_KA)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
1164
Alexandre Cassen87ea5482007-10-11 20:48:58 +02001165 if (s->be->options & PR_O_TCP_NOLING)
1166 setsockopt(fd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
1167
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 /* allow specific binding :
1169 * - server-specific at first
1170 * - proxy-specific next
1171 */
1172 if (s->srv != NULL && s->srv->state & SRV_BIND_SRC) {
1173 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
1174 if (bind(fd, (struct sockaddr *)&s->srv->source_addr, sizeof(s->srv->source_addr)) == -1) {
1175 Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001176 s->be->id, s->srv->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001178 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179 "Cannot bind to source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001180 s->be->id, s->srv->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001181 return SN_ERR_RESOURCE;
1182 }
Willy Tarreau77074d52006-11-12 23:57:19 +01001183#ifdef CONFIG_HAP_CTTPROXY
1184 if (s->srv->state & SRV_TPROXY_MASK) {
1185 struct in_tproxy itp1, itp2;
1186 memset(&itp1, 0, sizeof(itp1));
1187
1188 itp1.op = TPROXY_ASSIGN;
1189 switch (s->srv->state & SRV_TPROXY_MASK) {
1190 case SRV_TPROXY_ADDR:
1191 itp1.v.addr.faddr = s->srv->tproxy_addr.sin_addr;
1192 itp1.v.addr.fport = s->srv->tproxy_addr.sin_port;
1193 break;
1194 case SRV_TPROXY_CLI:
1195 itp1.v.addr.fport = ((struct sockaddr_in *)&s->cli_addr)->sin_port;
1196 /* fall through */
1197 case SRV_TPROXY_CIP:
1198 /* FIXME: what can we do if the client connects in IPv6 ? */
1199 itp1.v.addr.faddr = ((struct sockaddr_in *)&s->cli_addr)->sin_addr;
1200 break;
1201 }
1202
1203 /* set connect flag on socket */
1204 itp2.op = TPROXY_FLAGS;
1205 itp2.v.flags = ITP_CONNECT | ITP_ONCE;
1206
1207 if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
1208 setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
1209 Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001210 s->be->id, s->srv->id);
Willy Tarreau77074d52006-11-12 23:57:19 +01001211 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001212 send_log(s->be, LOG_EMERG,
Willy Tarreau77074d52006-11-12 23:57:19 +01001213 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001214 s->be->id, s->srv->id);
Willy Tarreau77074d52006-11-12 23:57:19 +01001215 return SN_ERR_RESOURCE;
1216 }
1217 }
1218#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001220 else if (s->be->options & PR_O_BIND_SRC) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001221 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001222 if (bind(fd, (struct sockaddr *)&s->be->source_addr, sizeof(s->be->source_addr)) == -1) {
1223 Alert("Cannot bind to source address before connect() for proxy %s. Aborting.\n", s->be->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001225 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +02001226 "Cannot bind to source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001227 s->be->id, s->srv->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 return SN_ERR_RESOURCE;
1229 }
Willy Tarreau77074d52006-11-12 23:57:19 +01001230#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001231 if (s->be->options & PR_O_TPXY_MASK) {
Willy Tarreau77074d52006-11-12 23:57:19 +01001232 struct in_tproxy itp1, itp2;
1233 memset(&itp1, 0, sizeof(itp1));
1234
1235 itp1.op = TPROXY_ASSIGN;
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001236 switch (s->be->options & PR_O_TPXY_MASK) {
Willy Tarreau77074d52006-11-12 23:57:19 +01001237 case PR_O_TPXY_ADDR:
1238 itp1.v.addr.faddr = s->srv->tproxy_addr.sin_addr;
1239 itp1.v.addr.fport = s->srv->tproxy_addr.sin_port;
1240 break;
1241 case PR_O_TPXY_CLI:
1242 itp1.v.addr.fport = ((struct sockaddr_in *)&s->cli_addr)->sin_port;
1243 /* fall through */
1244 case PR_O_TPXY_CIP:
1245 /* FIXME: what can we do if the client connects in IPv6 ? */
1246 itp1.v.addr.faddr = ((struct sockaddr_in *)&s->cli_addr)->sin_addr;
1247 break;
1248 }
1249
1250 /* set connect flag on socket */
1251 itp2.op = TPROXY_FLAGS;
1252 itp2.v.flags = ITP_CONNECT | ITP_ONCE;
1253
1254 if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
1255 setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
1256 Alert("Cannot bind to tproxy source address before connect() for proxy %s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001257 s->be->id);
Willy Tarreau77074d52006-11-12 23:57:19 +01001258 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001259 send_log(s->be, LOG_EMERG,
Willy Tarreau77074d52006-11-12 23:57:19 +01001260 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001261 s->be->id, s->srv->id);
Willy Tarreau77074d52006-11-12 23:57:19 +01001262 return SN_ERR_RESOURCE;
1263 }
1264 }
1265#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 }
1267
1268 if ((connect(fd, (struct sockaddr *)&s->srv_addr, sizeof(s->srv_addr)) == -1) &&
1269 (errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
1270
1271 if (errno == EAGAIN || errno == EADDRINUSE) {
1272 char *msg;
1273 if (errno == EAGAIN) /* no free ports left, try again later */
1274 msg = "no free ports";
1275 else
1276 msg = "local address already in use";
1277
1278 qfprintf(stderr,"Cannot connect: %s.\n",msg);
1279 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001280 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +02001281 "Connect() failed for server %s/%s: %s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001282 s->be->id, s->srv->id, msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 return SN_ERR_RESOURCE;
1284 } else if (errno == ETIMEDOUT) {
1285 //qfprintf(stderr,"Connect(): ETIMEDOUT");
1286 close(fd);
1287 return SN_ERR_SRVTO;
1288 } else {
1289 // (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
1290 //qfprintf(stderr,"Connect(): %d", errno);
1291 close(fd);
1292 return SN_ERR_SRVCL;
1293 }
1294 }
1295
1296 fdtab[fd].owner = s->task;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001297 fdtab[fd].state = FD_STCONN; /* connection in progress */
Willy Tarreaud7971282006-07-29 18:36:34 +02001298 fdtab[fd].cb[DIR_RD].f = &stream_sock_read;
Willy Tarreau54469402006-07-29 16:59:06 +02001299 fdtab[fd].cb[DIR_RD].b = s->rep;
Willy Tarreauf8306d52006-07-29 19:01:31 +02001300 fdtab[fd].cb[DIR_WR].f = &stream_sock_write;
Willy Tarreau54469402006-07-29 16:59:06 +02001301 fdtab[fd].cb[DIR_WR].b = s->req;
Willy Tarreaue94ebd02007-10-09 17:14:37 +02001302
1303 fdtab[fd].peeraddr = (struct sockaddr *)&s->srv_addr;
1304 fdtab[fd].peerlen = sizeof(s->srv_addr);
1305
Willy Tarreauf161a342007-04-08 16:59:42 +02001306 EV_FD_SET(fd, DIR_WR); /* for connect status */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307
1308 fd_insert(fd);
1309 if (s->srv) {
1310 s->srv->cur_sess++;
1311 if (s->srv->cur_sess > s->srv->cur_sess_max)
1312 s->srv->cur_sess_max = s->srv->cur_sess;
1313 }
1314
Willy Tarreaua8b55e32007-05-13 16:08:19 +02001315 if (!tv_add_ifset(&s->req->cex, &now, &s->be->contimeout))
Willy Tarreaud7971282006-07-29 18:36:34 +02001316 tv_eternity(&s->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001317 return SN_ERR_NONE; /* connection is OK */
1318}
1319
1320
1321/*
1322 * This function checks the retry count during the connect() job.
1323 * It updates the session's srv_state and retries, so that the caller knows
1324 * what it has to do. It uses the last connection error to set the log when
1325 * it expires. It returns 1 when it has expired, and 0 otherwise.
1326 */
1327int srv_count_retry_down(struct session *t, int conn_err)
1328{
1329 /* we are in front of a retryable error */
1330 t->conn_retries--;
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +02001331 if (t->srv)
1332 t->srv->retries++;
1333 t->be->retries++;
1334
Willy Tarreaubaaee002006-06-26 02:48:02 +02001335 if (t->conn_retries < 0) {
1336 /* if not retryable anymore, let's abort */
Willy Tarreaud7971282006-07-29 18:36:34 +02001337 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338 srv_close_with_err(t, conn_err, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +01001339 503, error_message(t, HTTP_ERR_503));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 if (t->srv)
1341 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001342 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343
1344 /* We used to have a free connection slot. Since we'll never use it,
1345 * we have to inform the server that it may be used by another session.
1346 */
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001347 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +02001348 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 return 1;
1350 }
1351 return 0;
1352}
1353
1354
1355/*
1356 * This function performs the retryable part of the connect() job.
1357 * It updates the session's srv_state and retries, so that the caller knows
1358 * what it has to do. It returns 1 when it breaks out of the loop, or 0 if
1359 * it needs to redispatch.
1360 */
1361int srv_retryable_connect(struct session *t)
1362{
1363 int conn_err;
1364
1365 /* This loop ensures that we stop before the last retry in case of a
1366 * redispatchable server.
1367 */
1368 do {
1369 /* initiate a connection to the server */
1370 conn_err = connect_server(t);
1371 switch (conn_err) {
1372
1373 case SN_ERR_NONE:
1374 //fprintf(stderr,"0: c=%d, s=%d\n", c, s);
1375 t->srv_state = SV_STCONN;
1376 return 1;
1377
1378 case SN_ERR_INTERNAL:
Willy Tarreaud7971282006-07-29 18:36:34 +02001379 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +01001381 500, error_message(t, HTTP_ERR_500));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382 if (t->srv)
1383 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001384 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 /* release other sessions waiting for this server */
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001386 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +02001387 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 return 1;
1389 }
1390 /* ensure that we have enough retries left */
1391 if (srv_count_retry_down(t, conn_err)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 return 1;
1393 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001394 } while (t->srv == NULL || t->conn_retries > 0 || !(t->be->options & PR_O_REDISP));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395
1396 /* We're on our last chance, and the REDISP option was specified.
1397 * We will ignore cookie and force to balance or use the dispatcher.
1398 */
1399 /* let's try to offer this slot to anybody */
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001400 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +02001401 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402
1403 if (t->srv)
1404 t->srv->failed_conns++;
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +02001405 t->be->redispatches++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406
1407 t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
1408 t->srv = NULL; /* it's left to the dispatcher to choose a server */
Willy Tarreau3d300592007-03-18 18:34:41 +01001409 http_flush_cookie_flags(&t->txn);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 return 0;
1411}
1412
1413
1414/* This function performs the "redispatch" part of a connection attempt. It
1415 * will assign a server if required, queue the connection if required, and
1416 * handle errors that might arise at this level. It can change the server
1417 * state. It will return 1 if it encounters an error, switches the server
1418 * state, or has to queue a connection. Otherwise, it will return 0 indicating
1419 * that the connection is ready to use.
1420 */
1421
1422int srv_redispatch_connect(struct session *t)
1423{
1424 int conn_err;
1425
1426 /* We know that we don't have any connection pending, so we will
1427 * try to get a new one, and wait in this state if it's queued
1428 */
1429 conn_err = assign_server_and_queue(t);
1430 switch (conn_err) {
1431 case SRV_STATUS_OK:
1432 break;
1433
1434 case SRV_STATUS_NOSRV:
1435 /* note: it is guaranteed that t->srv == NULL here */
Willy Tarreaud7971282006-07-29 18:36:34 +02001436 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +01001438 503, error_message(t, HTTP_ERR_503));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 if (t->srv)
1440 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001441 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442
1443 return 1;
1444
1445 case SRV_STATUS_QUEUED:
1446 /* FIXME-20060503 : we should use the queue timeout instead */
Willy Tarreaua8b55e32007-05-13 16:08:19 +02001447 if (!tv_add_ifset(&t->req->cex, &now, &t->be->contimeout))
Willy Tarreaud7971282006-07-29 18:36:34 +02001448 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449 t->srv_state = SV_STIDLE;
1450 /* do nothing else and do not wake any other session up */
1451 return 1;
1452
1453 case SRV_STATUS_FULL:
1454 case SRV_STATUS_INTERNAL:
1455 default:
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_INTERNAL, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +01001458 500, error_message(t, HTTP_ERR_500));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 if (t->srv)
1460 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001461 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462
1463 /* release other sessions waiting for this server */
Willy Tarreaue2e27a52007-04-01 00:01:37 +02001464 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +02001465 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466 return 1;
1467 }
1468 /* if we get here, it's because we got SRV_STATUS_OK, which also
1469 * means that the connection has not been queued.
1470 */
1471 return 0;
1472}
1473
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001474int be_downtime(struct proxy *px) {
Willy Tarreaub625a082007-11-26 01:15:43 +01001475 if (px->lbprm.tot_weight && px->last_change < now.tv_sec) // ignore negative time
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001476 return px->down_time;
1477
1478 return now.tv_sec - px->last_change + px->down_time;
1479}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001481/* This function parses a "balance" statement in a backend section describing
1482 * <curproxy>. It returns -1 if there is any error, otherwise zero. If it
1483 * returns -1, it may write an error message into ther <err> buffer, for at
1484 * most <errlen> bytes, trailing zero included. The trailing '\n' will not be
1485 * written. The function must be called with <args> pointing to the first word
1486 * after "balance".
1487 */
1488int backend_parse_balance(const char **args, char *err, int errlen, struct proxy *curproxy)
1489{
1490 if (!*(args[0])) {
1491 /* if no option is set, use round-robin by default */
Willy Tarreau31682232007-11-29 15:38:04 +01001492 curproxy->lbprm.algo &= ~BE_LB_ALGO;
1493 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001494 return 0;
1495 }
1496
1497 if (!strcmp(args[0], "roundrobin")) {
Willy Tarreau31682232007-11-29 15:38:04 +01001498 curproxy->lbprm.algo &= ~BE_LB_ALGO;
1499 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001500 }
1501 else if (!strcmp(args[0], "source")) {
Willy Tarreau31682232007-11-29 15:38:04 +01001502 curproxy->lbprm.algo &= ~BE_LB_ALGO;
1503 curproxy->lbprm.algo |= BE_LB_ALGO_SH;
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001504 }
1505 else if (!strcmp(args[0], "uri")) {
Willy Tarreau31682232007-11-29 15:38:04 +01001506 curproxy->lbprm.algo &= ~BE_LB_ALGO;
1507 curproxy->lbprm.algo |= BE_LB_ALGO_UH;
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001508 }
Willy Tarreau01732802007-11-01 22:48:15 +01001509 else if (!strcmp(args[0], "url_param")) {
1510 if (!*args[1]) {
1511 snprintf(err, errlen, "'balance url_param' requires an URL parameter name.");
1512 return -1;
1513 }
Willy Tarreau31682232007-11-29 15:38:04 +01001514 curproxy->lbprm.algo &= ~BE_LB_ALGO;
1515 curproxy->lbprm.algo |= BE_LB_ALGO_PH;
Willy Tarreau01732802007-11-01 22:48:15 +01001516 if (curproxy->url_param_name)
1517 free(curproxy->url_param_name);
1518 curproxy->url_param_name = strdup(args[1]);
1519 curproxy->url_param_len = strlen(args[1]);
1520 }
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001521 else {
Willy Tarreau01732802007-11-01 22:48:15 +01001522 snprintf(err, errlen, "'balance' only supports 'roundrobin', 'source', 'uri' and 'url_param' options.");
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001523 return -1;
1524 }
1525 return 0;
1526}
1527
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528/*
1529 * Local variables:
1530 * c-indent-level: 8
1531 * c-basic-offset: 8
1532 * End:
1533 */