#define LI_O_TCP_RULES 0x0010 /* run TCP rules checks on the incoming connection */
#define LI_O_CHK_MONNET 0x0020 /* check the source against a monitor-net rule */
#define LI_O_ACC_PROXY 0x0040 /* find the proxied address in the first request line */
+#define LI_O_UNLIMITED 0x0080 /* listener not subject to global limits (peers & stats socket) */
+
+/* Note: if a listener uses LI_O_UNLIMITED, it is highly recommended that it adds its own
+ * maxconn setting to the global.maxsock value so that its resources are reserved.
+ */
/* The listener will be directly referenced by the fdtab[] which holds its
* socket. The listener provides the protocol-specific accept() function to
curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
curpeers->peers_fe->listen->handler = process_session;
curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
+ curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
+ global.maxsock += curpeers->peers_fe->listen->maxconn;
}
}
} /* neither "peer" nor "peers" */
}
global.stats_sock.state = LI_INIT;
- global.stats_sock.options = LI_O_NONE;
+ global.stats_sock.options = LI_O_UNLIMITED;
global.stats_sock.accept = session_accept;
global.stats_fe->accept = stats_accept;
global.stats_sock.handler = process_session;
#include <types/global.h>
#include <types/proto_tcp.h>
#include <types/acl.h>
+#include <types/peers.h>
#include <proto/auth.h>
#include <proto/acl.h>
global.maxsock += global.maxconn * 2; /* each connection needs two sockets */
global.maxsock += global.maxpipes * 2; /* each pipe needs two FDs */
+ if (global.stats_fe)
+ global.maxsock += global.stats_fe->maxconn;
+
+ if (peers) {
+ /* peers also need to bypass global maxconn */
+ struct peers *p = peers;
+
+ for (p = peers; p; p = p->next)
+ if (p->peers_fe)
+ global.maxsock += p->peers_fe->maxconn;
+ }
+
if (global.tune.maxpollevents <= 0)
global.tune.maxpollevents = MAX_POLL_EVENTS;
l->nbconn++; /* warning! right now, it's up to the handler to decrease this */
p->feconn++;/* beconn will be increased later */
jobs++;
- actconn++;
+ if (!(s->listener->options & LI_O_UNLIMITED))
+ actconn++;
totalconn++;
return s;
s->fe->feconn--;
if (s->flags & SN_BE_ASSIGNED)
s->be->beconn--;
- actconn--;
+ if (!(s->listener->options & LI_O_UNLIMITED))
+ actconn--;
jobs--;
s->listener->nbconn--;
if (s->listener->state == LI_FULL)
return 0;
}
- if (global.cps_lim) {
+ if (global.cps_lim && !(l->options & LI_O_UNLIMITED)) {
int max = freq_ctr_remain(&global.conn_per_sec, global.cps_lim, 0);
if (unlikely(!max)) {
struct sockaddr_storage addr;
socklen_t laddr = sizeof(addr);
- if (unlikely(actconn >= global.maxconn)) {
+ if (unlikely(actconn >= global.maxconn) && !(l->options & LI_O_UNLIMITED)) {
limit_listener(l, &global_listener_queue);
task_schedule(global_listener_queue_task, tick_add(now_ms, 1000)); /* try again in 1 second */
return 0;
}
/* increase the per-process number of cumulated connections */
- update_freq_ctr(&global.conn_per_sec, 1);
- if (global.conn_per_sec.curr_ctr > global.cps_max)
- global.cps_max = global.conn_per_sec.curr_ctr;
+ if (!(l->options & LI_O_UNLIMITED)) {
+ update_freq_ctr(&global.conn_per_sec, 1);
+ if (global.conn_per_sec.curr_ctr > global.cps_max)
+ global.cps_max = global.conn_per_sec.curr_ctr;
+ actconn++;
+ }
jobs++;
- actconn++;
totalconn++;
l->nbconn++;
* error due to a resource shortage, and we must stop the
* listener (ret < 0).
*/
+ if (!(l->options & LI_O_UNLIMITED))
+ actconn--;
jobs--;
- actconn--;
l->nbconn--;
if (ret == 0) /* successful termination */
continue;