MINOR: proxy: Add use-small-buffers option to set where to use small buffers

Thanks to previous commits, it is possible to use small buffers at different
places: to store the request when a connection is queued or when L7 retries
are enabled, or for health-checks requests. However, there was no
configuration parameter to fine tune small buffer use.

It is now possible, thanks to the proxy option "use-small-buffers".
Documentation was updated accordingly.
This commit is contained in:
Christopher Faulet 2026-03-19 14:19:37 +01:00
parent 163eba5c8c
commit ada33006ef
6 changed files with 82 additions and 6 deletions

View file

@ -4165,8 +4165,11 @@ tune.bufsize.small <size>
If however a small buffer is not sufficient, a reallocation is automatically
done to switch to a standard size buffer.
For the moment, it is used only by HTTP/3 protocol to emit the response
headers.
For the moment, it is automatically used only by HTTP/3 protocol to emit the
response headers. Otherwise, small buffers support can be enabled for
specific proxies via the "use-small-buffers" option.
See also: option use-small-buffers
tune.comp.maxlevel <number>
Sets the maximum compression level. The compression level affects CPU
@ -6066,6 +6069,7 @@ option tcp-smart-connect (*) X - X X
option tcpka X X X X
option tcplog X X X -
option transparent (deprecated) (*) X - X X
option use-small-buffers (*) X - X X
persist rdp-cookie X - X X
quic-initial X (!) X X -
rate-limit sessions X X X -
@ -11905,6 +11909,36 @@ no option transparent (deprecated)
"transparent" option of the "bind" keyword.
option use-small-buffers [ queue | l7-retries | check ]*
Enable support for small buffers for the given categories.
May be used in the following contexts: tcp, http
May be used in sections : defaults | frontend | listen | backend
yes | no | yes | yes
This option can be used to enable the small buffers support at diffent places
to save memory. By default, with no parameter, small buffers are used as far
as possible at all possible places. Otherwise, it is possible to limit it to
following the places:
- queue: When set, small buffers will be used to store the requests, if
small enough, when the connection is queued.
- l7-retries: When set, small buffers will be used to save the requests
when L7 retries are enabled.
- check: When set, small buffers will be used for the health-checks
requests.
When enabled, small buffers are used, but only if it is possible. Otherwise,
when data are too large, a regular buffer is automtically used. The size of
small buffers is configurable via the "tune.bufsize.small" global setting.
If this option has been enabled in a "defaults" section, it can be disabled
in a specific instance by prepending the "no" keyword before it.
See also: tune.bufsize.small
persist rdp-cookie
persist rdp-cookie(<name>)
Enable RDP cookie-based persistence

View file

@ -162,7 +162,11 @@ enum PR_SRV_STATE_FILE {
#define PR_O2_EXT_CHK 0x04000000 /* use external command for server health */
#define PR_O2_CHK_ANY 0x06000000 /* Mask to cover any check */
/* unused : 0x08000000 ... 0x80000000 */
#define PR_O2_USE_SBUF_QUEUE 0x08000000 /* use small buffer for request when stream are queued*/
#define PR_O2_USE_SBUF_L7_RETRY 0x10000000 /* use small buffer for request when L7 retires are enabled */
#define PR_O2_USE_SBUF_CHECK 0x20000000 /* use small buffer for request's healthchecks */
#define PR_O2_USE_SBUF_ALL 0x38000000 /* all flags for use-large-buffer option */
/* unused : 0x40000000 ... 0x80000000 */
/* end of proxy->options2 */
/* bits for proxy->options3 */

View file

@ -2200,6 +2200,42 @@ stats_error_parsing:
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (strcmp(args[1], "use-small-buffers") == 0) {
unsigned int flags = PR_O2_USE_SBUF_ALL;
if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
err_code |= ERR_WARN;
goto out;
}
if (*(args[2])) {
int cur_arg;
flags = 0;
for (cur_arg = 2; *(args[cur_arg]); cur_arg++) {
if (strcmp(args[cur_arg], "queue") == 0)
flags |= PR_O2_USE_SBUF_QUEUE;
else if (strcmp(args[cur_arg], "l7-retries") == 0)
flags |= PR_O2_USE_SBUF_L7_RETRY;
else if (strcmp(args[cur_arg], "check") == 0)
flags |= PR_O2_USE_SBUF_CHECK;
else {
ha_alert("parsing [%s:%d] : invalid parameter '%s'. option '%s' expects 'queue', 'l7-retries' or 'check' value.\n",
file, linenum, args[cur_arg], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
}
}
if (kwm == KWM_STD) {
curproxy->options2 &= ~PR_O2_USE_SBUF_ALL;
curproxy->options2 |= flags;
}
else if (kwm == KWM_NO) {
curproxy->options2 &= ~flags;
}
goto out;
}
if (kwm != KWM_STD) {
ha_alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",

View file

@ -1685,7 +1685,8 @@ static int start_checks()
*/
for (px = proxies_list; px; px = px->next) {
for (s = px->srv; s; s = s->next) {
if (s->check.tcpcheck_rules->flags & TCPCHK_RULES_MAY_USE_SBUF)
if ((px->options2 & PR_O2_USE_SBUF_CHECK) &&
(s->check.tcpcheck_rules->flags & TCPCHK_RULES_MAY_USE_SBUF))
s->check.state |= CHK_ST_USE_SMALL_BUFF;
if (s->check.state & CHK_ST_CONFIGURED) {

View file

@ -1496,7 +1496,8 @@ int sc_conn_send(struct stconn *sc)
if (s->txn->req.msg_state != HTTP_MSG_DONE || b_is_large(&oc->buf))
s->txn->flags &= ~TX_L7_RETRY;
else {
if (!htx_copy_to_small_buffer(&s->txn->l7_buffer, &oc->buf)) {
if (!(s->be->options2 & PR_O2_USE_SBUF_L7_RETRY) ||
!htx_copy_to_small_buffer(&s->txn->l7_buffer, &oc->buf)) {
if (b_alloc(&s->txn->l7_buffer, DB_UNLIKELY) == NULL)
s->txn->flags &= ~TX_L7_RETRY;
else {

View file

@ -2512,7 +2512,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
if (scb->state == SC_ST_ASS && srv && srv->rdr_len && (s->flags & SF_REDIRECTABLE))
http_perform_server_redirect(s, scb);
if (unlikely(scb->state == SC_ST_QUE)) {
if (unlikely((s->be->options2 & PR_O2_USE_SBUF_QUEUE) && scb->state == SC_ST_QUE)) {
struct buffer sbuf = BUF_NULL;
if (IS_HTX_STRM(s)) {