]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] splice: add configuration options and set global.maxpipes
authorWilly Tarreau <w@1wt.eu>
Sun, 18 Jan 2009 20:44:07 +0000 (21:44 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 18 Jan 2009 20:44:07 +0000 (21:44 +0100)
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.

include/types/proxy.h
src/cfgparse.c
src/haproxy.c

index 90d5c4e5262c04d87ad24fedb38823577894f5b5..5d0869cb5aee8b73dc17ecc85db7fbf8f362e19c 100644 (file)
 #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 {
index caf259ba37e0554dc1096078e6f1e228cef4d114..af72b15f292c1ba3bb391dee700014d74dcb6c9e 100644 (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);
index d6c18f951ed75cd2fcc78cbc32bb91d7d25f26e5..771fa0b9b29070215e8a596d83eaee27df280a57 100644 (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 */