2006-06-25 20:48:02 -04:00
|
|
|
/*
|
2010-05-24 15:02:37 -04:00
|
|
|
* Frontend variables and functions.
|
2006-06-25 20:48:02 -04:00
|
|
|
*
|
2013-01-07 16:48:29 -05:00
|
|
|
* Copyright 2000-2013 Willy Tarreau <w@1wt.eu>
|
2006-06-25 20:48:02 -04:00
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version
|
|
|
|
|
* 2 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2006-06-29 11:53:05 -04:00
|
|
|
#include <string.h>
|
2006-06-25 20:48:02 -04:00
|
|
|
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
2010-12-24 09:26:39 -05:00
|
|
|
#include <netinet/tcp.h>
|
|
|
|
|
|
2020-06-04 13:11:43 -04:00
|
|
|
#include <haproxy/acl.h>
|
2020-05-27 06:58:42 -04:00
|
|
|
#include <haproxy/api.h>
|
2020-06-09 03:07:15 -04:00
|
|
|
#include <haproxy/arg.h>
|
2020-06-02 04:22:45 -04:00
|
|
|
#include <haproxy/chunk.h>
|
2022-03-29 11:53:09 -04:00
|
|
|
#include <haproxy/connection.h>
|
2025-05-15 13:55:11 -04:00
|
|
|
#include <haproxy/counters.h>
|
2020-06-09 03:07:15 -04:00
|
|
|
#include <haproxy/fd.h>
|
2020-06-04 05:23:07 -04:00
|
|
|
#include <haproxy/frontend.h>
|
2020-06-09 03:07:15 -04:00
|
|
|
#include <haproxy/global.h>
|
2020-06-04 15:21:03 -04:00
|
|
|
#include <haproxy/http_ana.h>
|
2020-06-04 16:01:04 -04:00
|
|
|
#include <haproxy/log.h>
|
2020-06-09 03:07:15 -04:00
|
|
|
#include <haproxy/proto_tcp.h>
|
2020-06-04 16:29:18 -04:00
|
|
|
#include <haproxy/proxy.h>
|
2020-06-04 09:33:47 -04:00
|
|
|
#include <haproxy/sample.h>
|
2022-05-27 03:25:10 -04:00
|
|
|
#include <haproxy/sc_strm.h>
|
2020-06-04 17:46:14 -04:00
|
|
|
#include <haproxy/stream.h>
|
2020-06-04 11:25:40 -04:00
|
|
|
#include <haproxy/task.h>
|
2021-10-06 10:18:40 -04:00
|
|
|
#include <haproxy/ticks.h>
|
2020-06-09 03:07:15 -04:00
|
|
|
#include <haproxy/tools.h>
|
2006-06-25 20:48:02 -04:00
|
|
|
|
|
|
|
|
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 18:22:06 -04:00
|
|
|
/* Finish a stream accept() for a proxy (TCP or HTTP). It returns a negative
|
2010-11-11 04:56:04 -05:00
|
|
|
* value in case of a critical failure which must cause the listener to be
|
2015-04-05 12:01:06 -04:00
|
|
|
* disabled, a positive or null value in case of success.
|
2006-06-25 20:48:02 -04:00
|
|
|
*/
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 18:22:06 -04:00
|
|
|
int frontend_accept(struct stream *s)
|
2010-05-28 12:46:57 -04:00
|
|
|
{
|
2021-10-22 11:39:06 -04:00
|
|
|
const struct sockaddr_storage *src, *dst;
|
2015-04-03 09:40:56 -04:00
|
|
|
struct session *sess = s->sess;
|
2015-04-05 12:01:06 -04:00
|
|
|
struct connection *conn = objt_conn(sess->origin);
|
2015-04-03 09:40:56 -04:00
|
|
|
struct listener *l = sess->listener;
|
|
|
|
|
struct proxy *fe = sess->fe;
|
2015-04-03 08:46:27 -04:00
|
|
|
|
2015-04-03 09:40:56 -04:00
|
|
|
if ((fe->mode == PR_MODE_TCP || fe->mode == PR_MODE_HTTP)
|
MEDIUM: tree-wide: logsrv struct becomes logger
When 'log' directive was implemented, the internal representation was
named 'struct logsrv', because the 'log' directive would directly point
to the log target, which used to be a (UDP) log server exclusively at
that time, hence the name.
But things have become more complex, since today 'log' directive can point
to ring targets (implicit, or named) for example.
Indeed, a 'log' directive does no longer reference the "final" server to
which the log will be sent, but instead it describes which log API and
parameters to use for transporting the log messages to the proper log
destination.
So now the term 'logsrv' is rather confusing and prevents us from
introducing a new level of abstraction because they would be mixed
with logsrv.
So in order to better designate this 'log' directive, and make it more
generic, we chose the word 'logger' which now replaces logsrv everywhere
it was used in the code (including related comments).
This is internal rewording, so no functional change should be expected
on user-side.
2023-09-11 09:06:53 -04:00
|
|
|
&& (!LIST_ISEMPTY(&fe->loggers))) {
|
MEDIUM: log: consider log-steps proxy setting for existing log origins
During tcp/http transaction processing, haproxy may produce logs at
different steps during the processing (accept, connect, request,
response, close). But the behavior is hardly configurable because
haproxy will only emit a single log per transaction, and by default
it will try to produce the log once all log aliases or fetches used
in the logformat could be satisfied, which means the log is often
emitted during connection teardown, unless "option logasap" is used.
We were often asked to have a way to emit multiple logs for a single
transaction, like for instance emit log during accept, then request,
response and close for instance, see GH #401 for more context.
Thanks to "log-steps" keyword introduced by commit "MINOR: log:
introduce "log-steps" proxy keyword", it is now possible to explictly
configure when logs should be generated by haproxy when processing a
transaction. This commit adds the required checks so that log-steps
proxy option is properly considered for existing logs generated by
haproxy. If "log-steps" is not specified on the proxy, the old behavior
is preserved.
Note: a slight cpu overhead should only be visible when "log-steps"
keyword will be used due to the implementation relying on eb32 lookup
instead of basic bitfield check as described in "MINOR: proxy: add
log_steps struct member". However, the default behavior shouldn't be
affected.
When combining log-steps with log-profiles, user has the ability to
explicitly control how and when haproxy should generate logs during
requests handling.
2024-09-04 09:03:46 -04:00
|
|
|
if (fe->to_log == LW_LOGSTEPS) {
|
|
|
|
|
if (log_orig_proxy(LOG_ORIG_TXN_ACCEPT, fe))
|
|
|
|
|
s->do_log(s, log_orig(LOG_ORIG_TXN_ACCEPT, LOG_ORIG_FL_NONE));
|
|
|
|
|
}
|
|
|
|
|
else if (likely(!lf_expr_isempty(&fe->logformat))) {
|
2010-05-28 12:46:57 -04:00
|
|
|
/* we have the client ip */
|
|
|
|
|
if (s->logs.logwait & LW_CLIP)
|
BUG/MINOR: log: make log-format, unique-id-format and add-header more independant
It happens that all of them call parse_logformat_line() which sets
proxy->to_log with a number of flags affecting the line format for
all three users. For example, having a unique-id specified disables
the default log-format since fe->to_log is tested when the session
is established.
Similarly, having "option logasap" will cause "+" to be inserted in
unique-id or headers referencing some of the fields depending on
LW_BYTES.
This patch first removes most of the dependency on fe->to_log whenever
possible. The first possible cleanup is to stop checking fe->to_log
for being null, considering that it always contains at least LW_INIT
when any such usage is made of the log-format!
Also, some checks are wrong. s->logs.logwait cannot be nulled by
"logwait &= ~LW_*" since LW_INIT is always there. This results in
getting the wrong log at the end of a request or session when a
unique-id or add-header is set, because logwait is still not null
but the log-format is not checked.
Further cleanups are required. Most LW_* flags should be removed or at
least replaced with what they really mean (eg: depend on client-side
connection, depend on server-side connection, etc...) and this should
only affect logging, not other mechanisms.
This patch fixes the default log-format and tries to limit interferences
between the log formats, but does not pretend to do more for the moment,
since it's the most visible breakage.
2012-12-28 03:40:16 -05:00
|
|
|
if (!(s->logs.logwait &= ~(LW_CLIP|LW_INIT)))
|
2024-09-23 11:22:45 -04:00
|
|
|
s->do_log(s, log_orig(LOG_ORIG_TXN_ACCEPT, LOG_ORIG_FL_NONE));
|
2009-07-10 17:52:51 -04:00
|
|
|
}
|
2015-04-05 12:01:06 -04:00
|
|
|
else if (conn) {
|
2022-05-27 02:57:21 -04:00
|
|
|
src = sc_src(s->scf);
|
2021-10-22 11:39:06 -04:00
|
|
|
if (!src)
|
|
|
|
|
send_log(fe, LOG_INFO, "Connect from unknown source to listener %d (%s/%s)\n",
|
|
|
|
|
l->luid, fe->id, (fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
|
|
|
|
|
else {
|
|
|
|
|
char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN];
|
|
|
|
|
int port;
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2021-10-22 11:39:06 -04:00
|
|
|
switch (addr_to_str(src, pn, sizeof(pn))) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
case AF_INET6:
|
2022-05-27 02:57:21 -04:00
|
|
|
dst = sc_dst(s->scf);
|
2021-10-22 11:39:06 -04:00
|
|
|
if (dst) {
|
|
|
|
|
addr_to_str(dst, sn, sizeof(sn));
|
|
|
|
|
port = get_host_port(dst);
|
|
|
|
|
} else {
|
2023-04-07 12:11:39 -04:00
|
|
|
strlcpy2(sn, "undetermined address", sizeof(sn));
|
2021-10-22 11:39:06 -04:00
|
|
|
port = 0;
|
|
|
|
|
}
|
|
|
|
|
send_log(fe, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n",
|
|
|
|
|
pn, get_host_port(src),
|
|
|
|
|
sn, port,
|
|
|
|
|
fe->id, (fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
|
|
|
|
|
break;
|
|
|
|
|
case AF_UNIX:
|
MEDIUM: protocol: make abns a custom unix socket address family
This is a pre-requisite to adding the abnsz socket address family:
in this patch we make use of protocol API rework started by 732913f
("MINOR: protocol: properly assign the sock_domain and sock_family") in
order to implement a dedicated address family for ABNS sockets (based on
UNIX parent family).
Thanks to this, it will become trivial to implement a new ABNSZ (for abns
zero) family which is essentially the same as ABNS but with a slight
difference when it comes to path handling (ABNS uses the whole sun_path
length, while ABNSZ's path is zero terminated and evaluation stops at 0)
It was verified that this patch doesn't break reg-tests and behaves
properly (tests performed on the CLI with show sess and show fd).
Anywhere relevant, AF_CUST_ABNS is handled alongside AF_UNIX. If no
distinction needs to be made, real_family() is used to fetch the proper
real family type to handle it properly.
Both stream and dgram were converted, so no functional change should be
expected for this "internal" rework, except that proto will be displayed
as "abns_{stream,dgram}" instead of "unix_{stream,dgram}".
Before ("show sess" output):
0x64c35528aab0: proto=unix_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=00 epoch=0 age=0s calls=1 rate=0 cpu=0 lat=0 rq[f=848000h,i=0,an=00h,ax=] rp[f=80008000h,i=0,an=00h,ax=] scf=[8,0h,fd=21,rex=10s,wex=] scb=[8,1h,fd=-1,rex=,wex=] exp=10s rc=0 c_exp=
After:
0x619da7ad74c0: proto=abns_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=00 epoch=0 age=0s calls=1 rate=0 cpu=0 lat=0 rq[f=848000h,i=0,an=00h,ax=] rp[f=80008000h,i=0,an=00h,ax=] scf=[8,0h,fd=22,rex=10s,wex=] scb=[8,1h,fd=-1,rex=,wex=] exp=10s rc=0 c_exp=
Co-authored-by: Aurelien DARRAGON <adarragon@haproxy.com>
2024-08-09 12:48:14 -04:00
|
|
|
case AF_CUST_ABNS:
|
2024-08-09 15:12:23 -04:00
|
|
|
case AF_CUST_ABNSZ:
|
2021-10-22 11:39:06 -04:00
|
|
|
/* UNIX socket, only the destination is known */
|
|
|
|
|
send_log(fe, LOG_INFO, "Connect to unix:%d (%s/%s)\n",
|
|
|
|
|
l->luid,
|
|
|
|
|
fe->id, (fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
|
|
|
|
|
break;
|
2019-07-17 05:25:46 -04:00
|
|
|
}
|
2006-06-25 20:48:02 -04:00
|
|
|
}
|
|
|
|
|
}
|
2010-05-28 12:46:57 -04:00
|
|
|
}
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2015-04-05 12:01:06 -04:00
|
|
|
if (unlikely((global.mode & MODE_DEBUG) && conn &&
|
|
|
|
|
(!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
|
2011-09-04 18:36:48 -04:00
|
|
|
char pn[INET6_ADDRSTRLEN];
|
2016-12-04 13:05:24 -05:00
|
|
|
char alpn[16] = "<none>";
|
2017-09-15 05:43:32 -04:00
|
|
|
const char *alpn_str = NULL;
|
|
|
|
|
int alpn_len;
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2017-09-15 05:43:32 -04:00
|
|
|
/* try to report the ALPN value when available (also works for NPN) */
|
2022-05-18 10:23:22 -04:00
|
|
|
if (conn == sc_conn(s->scf)) {
|
2017-09-15 05:43:32 -04:00
|
|
|
if (conn_get_alpn(conn, &alpn_str, &alpn_len) && alpn_str) {
|
|
|
|
|
int len = MIN(alpn_len, sizeof(alpn) - 1);
|
|
|
|
|
memcpy(alpn, alpn_str, len);
|
|
|
|
|
alpn[len] = 0;
|
|
|
|
|
}
|
2016-12-04 13:05:24 -05:00
|
|
|
}
|
|
|
|
|
|
2022-05-27 02:57:21 -04:00
|
|
|
src = sc_src(s->scf);
|
2021-10-22 11:39:06 -04:00
|
|
|
if (!src) {
|
2019-07-17 05:25:46 -04:00
|
|
|
chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [listener:%d] ALPN=%s\n",
|
2020-08-27 02:16:52 -04:00
|
|
|
s->uniq_id, fe->id, (unsigned short)l->rx.fd, (unsigned short)conn->handle.fd,
|
2019-07-17 05:25:46 -04:00
|
|
|
l->luid, alpn);
|
|
|
|
|
}
|
2021-10-22 11:39:06 -04:00
|
|
|
else switch (addr_to_str(src, pn, sizeof(pn))) {
|
2011-09-04 18:36:48 -04:00
|
|
|
case AF_INET:
|
|
|
|
|
case AF_INET6:
|
2016-12-04 13:05:24 -05:00
|
|
|
chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [%s:%d] ALPN=%s\n",
|
2020-08-27 02:16:52 -04:00
|
|
|
s->uniq_id, fe->id, (unsigned short)l->rx.fd, (unsigned short)conn->handle.fd,
|
2021-10-22 11:39:06 -04:00
|
|
|
pn, get_host_port(src), alpn);
|
2011-09-04 18:36:48 -04:00
|
|
|
break;
|
|
|
|
|
case AF_UNIX:
|
MEDIUM: protocol: make abns a custom unix socket address family
This is a pre-requisite to adding the abnsz socket address family:
in this patch we make use of protocol API rework started by 732913f
("MINOR: protocol: properly assign the sock_domain and sock_family") in
order to implement a dedicated address family for ABNS sockets (based on
UNIX parent family).
Thanks to this, it will become trivial to implement a new ABNSZ (for abns
zero) family which is essentially the same as ABNS but with a slight
difference when it comes to path handling (ABNS uses the whole sun_path
length, while ABNSZ's path is zero terminated and evaluation stops at 0)
It was verified that this patch doesn't break reg-tests and behaves
properly (tests performed on the CLI with show sess and show fd).
Anywhere relevant, AF_CUST_ABNS is handled alongside AF_UNIX. If no
distinction needs to be made, real_family() is used to fetch the proper
real family type to handle it properly.
Both stream and dgram were converted, so no functional change should be
expected for this "internal" rework, except that proto will be displayed
as "abns_{stream,dgram}" instead of "unix_{stream,dgram}".
Before ("show sess" output):
0x64c35528aab0: proto=unix_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=00 epoch=0 age=0s calls=1 rate=0 cpu=0 lat=0 rq[f=848000h,i=0,an=00h,ax=] rp[f=80008000h,i=0,an=00h,ax=] scf=[8,0h,fd=21,rex=10s,wex=] scb=[8,1h,fd=-1,rex=,wex=] exp=10s rc=0 c_exp=
After:
0x619da7ad74c0: proto=abns_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=00 epoch=0 age=0s calls=1 rate=0 cpu=0 lat=0 rq[f=848000h,i=0,an=00h,ax=] rp[f=80008000h,i=0,an=00h,ax=] scf=[8,0h,fd=22,rex=10s,wex=] scb=[8,1h,fd=-1,rex=,wex=] exp=10s rc=0 c_exp=
Co-authored-by: Aurelien DARRAGON <adarragon@haproxy.com>
2024-08-09 12:48:14 -04:00
|
|
|
case AF_CUST_ABNS:
|
2024-08-09 15:12:23 -04:00
|
|
|
case AF_CUST_ABNSZ:
|
2011-09-04 18:36:48 -04:00
|
|
|
/* UNIX socket, only the destination is known */
|
2016-12-04 13:05:24 -05:00
|
|
|
chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [unix:%d] ALPN=%s\n",
|
2020-08-27 02:16:52 -04:00
|
|
|
s->uniq_id, fe->id, (unsigned short)l->rx.fd, (unsigned short)conn->handle.fd,
|
2016-12-04 13:05:24 -05:00
|
|
|
l->luid, alpn);
|
2011-09-04 18:36:48 -04:00
|
|
|
break;
|
2010-10-22 10:33:18 -04:00
|
|
|
}
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2020-03-14 06:03:20 -04:00
|
|
|
DISGUISE(write(1, trash.area, trash.data));
|
2010-05-28 12:46:57 -04:00
|
|
|
}
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2015-04-03 09:40:56 -04:00
|
|
|
if (fe->mode == PR_MODE_HTTP)
|
2023-03-16 09:40:03 -04:00
|
|
|
s->scf->flags |= SC_FL_RCV_ONCE; /* one read is usually enough */
|
2009-10-04 09:43:17 -04:00
|
|
|
|
2016-12-04 12:39:22 -05:00
|
|
|
if (unlikely(fe->nb_req_cap > 0)) {
|
2021-03-22 16:06:21 -04:00
|
|
|
if ((s->req_cap = pool_zalloc(fe->req_cap_pool)) == NULL)
|
2016-12-04 12:39:22 -05:00
|
|
|
goto out_return; /* no memory */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unlikely(fe->nb_rsp_cap > 0)) {
|
2021-03-22 16:06:21 -04:00
|
|
|
if ((s->res_cap = pool_zalloc(fe->rsp_cap_pool)) == NULL)
|
2016-12-04 12:39:22 -05:00
|
|
|
goto out_free_reqcap; /* no memory */
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-08 13:12:58 -05:00
|
|
|
if ((fe->http_needed || IS_HTX_STRM(s)) && !http_create_txn(s))
|
|
|
|
|
goto out_free_rspcap;
|
2016-12-04 12:39:22 -05:00
|
|
|
|
2010-06-01 11:45:26 -04:00
|
|
|
/* everything's OK, let's go on */
|
2010-05-28 12:46:57 -04:00
|
|
|
return 1;
|
2007-11-04 11:51:50 -05:00
|
|
|
|
|
|
|
|
/* Error unrolling */
|
2010-06-01 11:12:40 -04:00
|
|
|
out_free_rspcap:
|
2017-11-24 11:34:44 -05:00
|
|
|
pool_free(fe->rsp_cap_pool, s->res_cap);
|
2010-06-01 11:12:40 -04:00
|
|
|
out_free_reqcap:
|
2017-11-24 11:34:44 -05:00
|
|
|
pool_free(fe->req_cap_pool, s->req_cap);
|
2010-11-11 04:56:04 -05:00
|
|
|
out_return:
|
2010-05-28 12:46:57 -04:00
|
|
|
return -1;
|
2006-06-25 20:48:02 -04:00
|
|
|
}
|
|
|
|
|
|
2023-10-25 09:32:28 -04:00
|
|
|
/* Increment current active connection counter. This ensures that global
|
|
|
|
|
* maxconn is not reached or exceeded. This must be done for every new frontend
|
|
|
|
|
* connection allocation.
|
|
|
|
|
*
|
|
|
|
|
* Returns the new actconn global value. If maxconn reached or exceeded, 0 is
|
|
|
|
|
* returned : the connection allocation should be cancelled.
|
|
|
|
|
*/
|
|
|
|
|
int increment_actconn()
|
|
|
|
|
{
|
|
|
|
|
unsigned int count, next_actconn;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
count = actconn;
|
|
|
|
|
if (unlikely(count >= global.maxconn)) {
|
|
|
|
|
/* maxconn reached */
|
|
|
|
|
next_actconn = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* try to increment actconn */
|
|
|
|
|
next_actconn = count + 1;
|
|
|
|
|
} while (!_HA_ATOMIC_CAS(&actconn, (int *)(&count), next_actconn) && __ha_cpu_relax());
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
return next_actconn;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-07 16:48:29 -05:00
|
|
|
/************************************************************************/
|
|
|
|
|
/* All supported sample and ACL keywords must be declared here. */
|
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
2011-12-16 11:06:15 -05:00
|
|
|
/* set temp integer to the id of the frontend */
|
2007-06-10 04:06:18 -04:00
|
|
|
static int
|
2015-05-11 09:42:45 -04:00
|
|
|
smp_fetch_fe_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
2012-04-23 10:16:37 -04:00
|
|
|
{
|
2012-04-23 12:53:56 -04:00
|
|
|
smp->flags = SMP_F_VOL_SESS;
|
2015-08-19 03:00:18 -04:00
|
|
|
smp->data.type = SMP_T_SINT;
|
2015-08-19 03:07:19 -04:00
|
|
|
smp->data.u.sint = smp->sess->fe->uuid;
|
2010-01-04 09:47:45 -05:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-12 08:08:05 -05:00
|
|
|
/* set string to the name of the frontend */
|
|
|
|
|
static int
|
|
|
|
|
smp_fetch_fe_name(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
|
|
|
|
{
|
2018-07-13 04:54:26 -04:00
|
|
|
smp->data.u.str.area = (char *)smp->sess->fe->id;
|
|
|
|
|
if (!smp->data.u.str.area)
|
2016-12-12 08:08:05 -05:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
smp->data.type = SMP_T_STR;
|
|
|
|
|
smp->flags = SMP_F_CONST;
|
2018-07-13 04:54:26 -04:00
|
|
|
smp->data.u.str.data = strlen(smp->data.u.str.area);
|
2016-12-12 08:08:05 -05:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-13 08:37:50 -04:00
|
|
|
/* set string to the name of the default backend */
|
|
|
|
|
static int
|
|
|
|
|
smp_fetch_fe_defbe(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
|
|
|
|
{
|
|
|
|
|
if (!smp->sess->fe->defbe.be)
|
|
|
|
|
return 0;
|
2018-07-13 04:54:26 -04:00
|
|
|
smp->data.u.str.area = (char *)smp->sess->fe->defbe.be->id;
|
|
|
|
|
if (!smp->data.u.str.area)
|
2018-04-13 08:37:50 -04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
smp->data.type = SMP_T_STR;
|
|
|
|
|
smp->flags = SMP_F_CONST;
|
2018-07-13 04:54:26 -04:00
|
|
|
smp->data.u.str.data = strlen(smp->data.u.str.area);
|
2018-04-13 08:37:50 -04:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 22:57:37 -04:00
|
|
|
/* set temp integer to the number of HTTP requests per second reaching the frontend.
|
|
|
|
|
* Accepts exactly 1 argument. Argument is a frontend, other types will cause
|
|
|
|
|
* an undefined behaviour.
|
|
|
|
|
*/
|
|
|
|
|
static int
|
|
|
|
|
smp_fetch_fe_req_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
|
|
|
|
{
|
2021-10-12 12:48:05 -04:00
|
|
|
struct proxy *px = args->data.prx;
|
|
|
|
|
|
|
|
|
|
if (px == NULL)
|
|
|
|
|
return 0;
|
|
|
|
|
if (px->cap & PR_CAP_DEF)
|
|
|
|
|
px = smp->px;
|
|
|
|
|
|
2016-10-02 22:57:37 -04:00
|
|
|
smp->flags = SMP_F_VOL_TEST;
|
|
|
|
|
smp->data.type = SMP_T_SINT;
|
2025-07-22 11:15:02 -04:00
|
|
|
smp->data.u.sint = COUNTERS_SHARED_TOTAL(px->fe_counters.shared.tg, req_per_sec, read_freq_ctr);
|
2016-10-02 22:57:37 -04:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-19 11:16:54 -04:00
|
|
|
/* set temp integer to the number of connections per second reaching the frontend.
|
2012-04-20 05:37:56 -04:00
|
|
|
* Accepts exactly 1 argument. Argument is a frontend, other types will cause
|
2012-04-19 11:16:54 -04:00
|
|
|
* an undefined behaviour.
|
|
|
|
|
*/
|
2007-06-10 04:06:18 -04:00
|
|
|
static int
|
2015-05-11 09:42:45 -04:00
|
|
|
smp_fetch_fe_sess_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
2007-05-08 13:56:15 -04:00
|
|
|
{
|
2021-10-12 12:48:05 -04:00
|
|
|
struct proxy *px = args->data.prx;
|
|
|
|
|
|
|
|
|
|
if (px == NULL)
|
|
|
|
|
return 0;
|
|
|
|
|
if (px->cap & PR_CAP_DEF)
|
|
|
|
|
px = smp->px;
|
|
|
|
|
|
2012-04-23 10:16:37 -04:00
|
|
|
smp->flags = SMP_F_VOL_TEST;
|
2015-08-19 03:00:18 -04:00
|
|
|
smp->data.type = SMP_T_SINT;
|
2025-07-22 11:15:02 -04:00
|
|
|
smp->data.u.sint = COUNTERS_SHARED_TOTAL(px->fe_counters.shared.tg, sess_per_sec, read_freq_ctr);
|
2010-01-04 09:47:45 -05:00
|
|
|
return 1;
|
|
|
|
|
}
|
2007-11-29 09:43:32 -05:00
|
|
|
|
2012-04-19 11:16:54 -04:00
|
|
|
/* set temp integer to the number of concurrent connections on the frontend
|
2012-04-20 05:37:56 -04:00
|
|
|
* Accepts exactly 1 argument. Argument is a frontend, other types will cause
|
2012-04-19 11:16:54 -04:00
|
|
|
* an undefined behaviour.
|
|
|
|
|
*/
|
2007-06-10 04:06:18 -04:00
|
|
|
static int
|
2015-05-11 09:42:45 -04:00
|
|
|
smp_fetch_fe_conn(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
2007-05-06 18:55:35 -04:00
|
|
|
{
|
2021-10-12 12:48:05 -04:00
|
|
|
struct proxy *px = args->data.prx;
|
|
|
|
|
|
|
|
|
|
if (px == NULL)
|
|
|
|
|
return 0;
|
|
|
|
|
if (px->cap & PR_CAP_DEF)
|
|
|
|
|
px = smp->px;
|
|
|
|
|
|
2012-04-23 10:16:37 -04:00
|
|
|
smp->flags = SMP_F_VOL_TEST;
|
2015-08-19 03:00:18 -04:00
|
|
|
smp->data.type = SMP_T_SINT;
|
2021-10-12 12:48:05 -04:00
|
|
|
smp->data.u.sint = px->feconn;
|
2010-01-12 15:59:30 -05:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-10 07:43:55 -05:00
|
|
|
static int
|
|
|
|
|
smp_fetch_fe_client_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
|
|
|
|
|
{
|
|
|
|
|
smp->flags = SMP_F_VOL_TXN;
|
|
|
|
|
smp->data.type = SMP_T_SINT;
|
|
|
|
|
smp->data.u.sint = TICKS_TO_MS(smp->sess->fe->timeout.client);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-18 09:56:36 -05:00
|
|
|
static int
|
|
|
|
|
smp_fetch_fe_tarpit_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
|
|
|
|
|
{
|
|
|
|
|
smp->flags = SMP_F_VOL_TXN;
|
|
|
|
|
smp->data.type = SMP_T_SINT;
|
|
|
|
|
smp->data.u.sint = TICKS_TO_MS(smp->sess->fe->timeout.tarpit);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2007-05-06 18:55:35 -04:00
|
|
|
|
2013-01-07 16:48:29 -05:00
|
|
|
/* Note: must not be declared <const> as its list will be overwritten.
|
|
|
|
|
* Please take care of keeping this list alphabetically sorted.
|
|
|
|
|
*/
|
2013-06-21 17:16:39 -04:00
|
|
|
static struct sample_fetch_kw_list smp_kws = {ILH, {
|
2020-12-10 07:43:55 -05:00
|
|
|
{ "fe_client_timeout", smp_fetch_fe_client_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, },
|
2026-02-18 09:56:36 -05:00
|
|
|
{ "fe_tarpit_timeout", smp_fetch_fe_tarpit_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, },
|
2020-12-10 07:43:55 -05:00
|
|
|
{ "fe_conn", smp_fetch_fe_conn, ARG1(1,FE), NULL, SMP_T_SINT, SMP_USE_INTRN, },
|
|
|
|
|
{ "fe_defbe", smp_fetch_fe_defbe, 0, NULL, SMP_T_STR, SMP_USE_FTEND, },
|
|
|
|
|
{ "fe_id", smp_fetch_fe_id, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, },
|
|
|
|
|
{ "fe_name", smp_fetch_fe_name, 0, NULL, SMP_T_STR, SMP_USE_FTEND, },
|
|
|
|
|
{ "fe_req_rate", smp_fetch_fe_req_rate, ARG1(1,FE), NULL, SMP_T_SINT, SMP_USE_INTRN, },
|
|
|
|
|
{ "fe_sess_rate", smp_fetch_fe_sess_rate, ARG1(1,FE), NULL, SMP_T_SINT, SMP_USE_INTRN, },
|
2013-01-07 16:48:29 -05:00
|
|
|
{ /* END */ },
|
|
|
|
|
}};
|
|
|
|
|
|
2018-11-25 13:14:37 -05:00
|
|
|
INITCALL1(STG_REGISTER, sample_register_fetches, &smp_kws);
|
2013-01-07 16:48:29 -05:00
|
|
|
|
2012-04-19 12:42:05 -04:00
|
|
|
/* Note: must not be declared <const> as its list will be overwritten.
|
|
|
|
|
* Please take care of keeping this list alphabetically sorted.
|
|
|
|
|
*/
|
2013-06-21 17:16:39 -04:00
|
|
|
static struct acl_kw_list acl_kws = {ILH, {
|
2013-01-07 16:48:29 -05:00
|
|
|
{ /* END */ },
|
2007-05-06 18:55:35 -04:00
|
|
|
}};
|
|
|
|
|
|
2018-11-25 13:14:37 -05:00
|
|
|
INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
|
2007-05-06 18:55:35 -04:00
|
|
|
|
2006-06-25 20:48:02 -04:00
|
|
|
/*
|
|
|
|
|
* Local variables:
|
|
|
|
|
* c-indent-level: 8
|
|
|
|
|
* c-basic-offset: 8
|
|
|
|
|
* End:
|
|
|
|
|
*/
|