[MEDIUM] splice: add configuration options and set global.maxpipes

Three new options have been added when CONFIG_HAP_LINUX_SPLICE is
set :
  - splice-request
  - splice-response
  - splice-auto

They are used to enable splicing per frontend/backend. They are also
supported in defaults sections. The "splice-auto" option is meant to
automatically turn splice on for buffers marked as fast streamers.
This should save quite a bunch of file descriptors.

It was required to add a new "options2" field to the proxy structure
because the original "options" is full.

When global.maxpipes is not set, it is automatically adjusted to
the max of the sums of all frontend's and backend's maxconns for
those which have at least one splice option enabled.
This commit is contained in:
Willy Tarreau 2009-01-18 21:44:07 +01:00
parent 3ec79b9c42
commit 66aa61f76b
3 changed files with 65 additions and 7 deletions

View File

@ -104,6 +104,13 @@
#define PR_O_CONTSTATS 0x10000000 /* continous counters */
#define PR_O_HTTP_PROXY 0x20000000 /* Enable session to use HTTP proxy operations */
#define PR_O_DISABLE404 0x40000000 /* Disable a server on a 404 response to a health-check */
/* unused: 0x80000000 */
/* bits for proxy->options2 */
#define PR_O2_SPLIC_REQ 0x00000001 /* transfer requests using linux kernel's splice() */
#define PR_O2_SPLIC_RTR 0x00000002 /* transfer responses using linux kernel's splice() */
#define PR_O2_SPLIC_AUT 0x00000004 /* automatically use linux kernel's splice() */
#define PR_O2_SPLIC_ANY (PR_O2_SPLIC_REQ|PR_O2_SPLIC_RTR|PR_O2_SPLIC_AUT)
/* This structure is used to apply fast weighted round robin on a server group */
struct fwrr_group {
@ -121,6 +128,7 @@ struct proxy {
struct in_addr mon_net, mon_mask; /* don't forward connections from this net (network order) FIXME: should support IPv6 */
int state; /* proxy state */
int options; /* PR_O_REDISP, PR_O_TRANSP, ... */
int options2; /* PR_O2_* */
int mode; /* mode = PR_MODE_TCP, PR_MODE_HTTP or PR_MODE_HEALTH */
struct sockaddr_in dispatch_addr; /* the default address to connect to */
union {

View File

@ -81,12 +81,15 @@ const char sslv3_client_hello_pkt[] = {
};
/* some of the most common options which are also the easiest to handle */
static const struct {
struct cfg_opt {
const char *name;
unsigned int val;
unsigned int cap;
unsigned int checks;
} cfg_opts[] =
};
/* proxy->options */
static const struct cfg_opt cfg_opts[] =
{
{ "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
{ "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
@ -113,6 +116,16 @@ static const struct {
{ NULL, 0, 0, 0 }
};
/* proxy->options2 */
static const struct cfg_opt cfg_opts2[] =
{
#ifdef CONFIG_HAP_LINUX_SPLICE
{ "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
{ "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
{ "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
#endif
{ NULL, 0, 0, 0 }
};
static char *cursection = NULL;
static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
@ -652,6 +665,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
/* set default values */
curproxy->state = defproxy.state;
curproxy->options = defproxy.options;
curproxy->options2 = defproxy.options2;
curproxy->lbprm.algo = defproxy.lbprm.algo;
curproxy->except_net = defproxy.except_net;
curproxy->except_mask = defproxy.except_mask;
@ -1402,6 +1416,20 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
}
}
for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
if (!strcmp(args[1], cfg_opts2[optnum].name)) {
if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
return 0;
if (!inv)
curproxy->options2 |= cfg_opts2[optnum].val;
else
curproxy->options2 &= ~cfg_opts2[optnum].val;
return 0;
}
}
if (inv) {
Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
file, linenum, args[1]);
@ -3328,12 +3356,13 @@ int readcfgfile(const char *file)
for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
int optnum;
for (optnum = 0; cfg_opts[optnum].name; optnum++) {
if (!(curproxy->options & cfg_opts[optnum].val))
continue;
for (optnum = 0; cfg_opts[optnum].name; optnum++)
if (curproxy->options & cfg_opts[optnum].val)
global.last_checks |= cfg_opts[optnum].checks;
global.last_checks |= cfg_opts[optnum].checks;
}
for (optnum = 0; cfg_opts2[optnum].name; optnum++)
if (curproxy->options2 & cfg_opts2[optnum].val)
global.last_checks |= cfg_opts2[optnum].checks;
}
free(cursection);

View File

@ -548,6 +548,27 @@ void init(int argc, char **argv)
if (global.maxconn == 0)
global.maxconn = DEFAULT_MAXCONN;
if (!global.maxpipes) {
/* maxpipes not specified. Count how many frontends and backends
* may be using splicing, and bound that to maxconn.
*/
struct proxy *cur;
int nbfe = 0, nbbe = 0;
for (cur = proxy; cur; cur = cur->next) {
if (cur->options2 & (PR_O2_SPLIC_ANY)) {
if (cur->cap & PR_CAP_FE)
nbfe += cur->maxconn;
if (cur->cap & PR_CAP_BE)
nbbe += cur->fullconn;
}
}
global.maxpipes = MAX(nbfe, nbbe);
if (global.maxpipes > global.maxconn)
global.maxpipes = global.maxconn;
}
global.maxsock += global.maxconn * 2; /* each connection needs two sockets */
global.maxsock += global.maxpipes * 2; /* each pipe needs two FDs */