249
251
/* We will factor the weights to reduce the table,
250
* using Euclide's largest common divisor algorithm
252
* using Euclide's largest common divisor algorithm.
253
* Since we may have zero weights, we have to first
254
* find a non-zero weight server.
252
pgcd = p->srv->uweight;
253
for (srv = p->srv->next; srv && pgcd > 1; srv = srv->next) {
254
int w = srv->uweight;
258
while (srv && !srv->uweight)
262
pgcd = srv->uweight; /* note: cannot be zero */
263
while (pgcd > 1 && (srv = srv->next)) {
264
int w = srv->uweight;
1812
1826
if (s->srv->iface_name)
1813
1827
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, s->srv->iface_name, s->srv->iface_len + 1);
1815
ret = tcpv4_bind_socket(fd, flags, &s->srv->source_addr, remote);
1830
if (s->srv->sport_range) {
1831
int attempts = 10; /* should be more than enough to find a spare port */
1832
struct sockaddr_in src;
1835
src = s->srv->source_addr;
1838
/* note: in case of retry, we may have to release a previously
1839
* allocated port, hence this loop's construct.
1841
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
1842
fdtab[fd].port_range = NULL;
1848
fdtab[fd].local_port = port_range_alloc_port(s->srv->sport_range);
1849
if (!fdtab[fd].local_port)
1852
fdtab[fd].port_range = s->srv->sport_range;
1853
src.sin_port = htons(fdtab[fd].local_port);
1855
ret = tcpv4_bind_socket(fd, flags, &src, remote);
1856
} while (ret != 0); /* binding NOK */
1859
ret = tcpv4_bind_socket(fd, flags, &s->srv->source_addr, remote);
1863
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
1864
fdtab[fd].port_range = NULL;
1818
1867
if (ret == 1) {
1819
1868
Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
1820
1869
s->be->id, s->srv->id);
1887
1936
msg = "local address already in use";
1889
1938
qfprintf(stderr,"Cannot connect: %s.\n",msg);
1939
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
1940
fdtab[fd].port_range = NULL;
1891
1942
send_log(s->be, LOG_EMERG,
1892
1943
"Connect() failed for server %s/%s: %s.\n",
1894
1945
return SN_ERR_RESOURCE;
1895
1946
} else if (errno == ETIMEDOUT) {
1896
1947
//qfprintf(stderr,"Connect(): ETIMEDOUT");
1948
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
1949
fdtab[fd].port_range = NULL;
1898
1951
return SN_ERR_SRVTO;
1900
1953
// (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
1901
1954
//qfprintf(stderr,"Connect(): %d", errno);
1955
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
1956
fdtab[fd].port_range = NULL;
1903
1958
return SN_ERR_SRVCL;
2307
/* set test->i to the number of concurrent connections on the frontend */
2309
acl_fetch_fe_conn(struct proxy *px, struct session *l4, void *l7, int dir,
2310
struct acl_expr *expr, struct acl_test *test)
2312
test->flags = ACL_TEST_F_VOL_TEST;
2313
if (expr->arg_len) {
2314
/* another proxy was designated, we must look for it */
2315
for (px = proxy; px; px = px->next)
2316
if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->arg.str))
2322
test->i = px->feconn;
2326
/* set test->i to the number of concurrent connections on the backend */
2328
acl_fetch_be_conn(struct proxy *px, struct session *l4, void *l7, int dir,
2329
struct acl_expr *expr, struct acl_test *test)
2331
test->flags = ACL_TEST_F_VOL_TEST;
2332
if (expr->arg_len) {
2333
/* another proxy was designated, we must look for it */
2334
for (px = proxy; px; px = px->next)
2335
if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
2341
test->i = px->beconn;
2345
/* set test->i to the total number of queued connections on the backend */
2347
acl_fetch_queue_size(struct proxy *px, struct session *l4, void *l7, int dir,
2348
struct acl_expr *expr, struct acl_test *test)
2350
test->flags = ACL_TEST_F_VOL_TEST;
2351
if (expr->arg_len) {
2352
/* another proxy was designated, we must look for it */
2353
for (px = proxy; px; px = px->next)
2354
if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
2360
test->i = px->totpend;
2364
/* set test->i to the total number of queued connections on the backend divided
2365
* by the number of running servers and rounded up. If there is no running
2366
* server, we return twice the total, just as if we had half a running server.
2367
* This is more or less correct anyway, since we expect the last server to come
2371
acl_fetch_avg_queue_size(struct proxy *px, struct session *l4, void *l7, int dir,
2372
struct acl_expr *expr, struct acl_test *test)
2376
test->flags = ACL_TEST_F_VOL_TEST;
2377
if (expr->arg_len) {
2378
/* another proxy was designated, we must look for it */
2379
for (px = proxy; px; px = px->next)
2380
if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
2387
nbsrv = px->srv_act;
2388
else if (px->lbprm.fbck)
2391
nbsrv = px->srv_bck;
2394
test->i = (px->totpend + nbsrv - 1) / nbsrv;
2396
test->i = px->totpend * 2;
2253
2401
/* Note: must not be declared <const> as its list will be overwritten */
2254
2402
static struct acl_kw_list acl_kws = {{ },{
2256
2404
{ "connslots", acl_parse_int, acl_fetch_connslots, acl_match_int, ACL_USE_NOTHING },
2257
2405
{ "fe_sess_rate", acl_parse_int, acl_fetch_fe_sess_rate, acl_match_int, ACL_USE_NOTHING },
2258
2406
{ "be_sess_rate", acl_parse_int, acl_fetch_be_sess_rate, acl_match_int, ACL_USE_NOTHING },
2407
{ "fe_conn", acl_parse_int, acl_fetch_fe_conn, acl_match_int, ACL_USE_NOTHING },
2408
{ "be_conn", acl_parse_int, acl_fetch_be_conn, acl_match_int, ACL_USE_NOTHING },
2409
{ "queue", acl_parse_int, acl_fetch_queue_size, acl_match_int, ACL_USE_NOTHING },
2410
{ "avg_queue", acl_parse_int, acl_fetch_avg_queue_size, acl_match_int, ACL_USE_NOTHING },
2259
2411
{ NULL, NULL, NULL, NULL },