MINOR: config: Extract the code of "stick-table" line parsing.
With this patch we move the code responsible of parsing "stick-table"
lines to implement parse_stick_table() function in src/stick-tabble.c
so that to be able to parse "stick-table" elsewhere than in proxy sections.
We have have also added a conf struct to stktable struct to store the filename
and the line in the file the stick-table has been parsed to help in
diagnosing and displaying any configuration issue.
diff --git a/include/proto/stick_table.h b/include/proto/stick_table.h
index 40bb8ca..962c95a 100644
--- a/include/proto/stick_table.h
+++ b/include/proto/stick_table.h
@@ -38,6 +38,8 @@
int stktable_init(struct stktable *t);
int stktable_parse_type(char **args, int *idx, unsigned long *type, size_t *key_size);
+int parse_stick_table(const char *file, int linenum, char **args,
+ struct stktable *t, char *id, struct peers *peers);
struct stksess *stktable_get_entry(struct stktable *table, struct stktable_key *key);
struct stksess *stktable_set_entry(struct stktable *table, struct stksess *nts);
void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int decrefcount, int expire);
diff --git a/include/types/stick_table.h b/include/types/stick_table.h
index 28e255f..695a75c 100644
--- a/include/types/stick_table.h
+++ b/include/types/stick_table.h
@@ -144,6 +144,13 @@
/* stick table */
struct stktable {
char *id; /* table id name */
+ struct stktable *next; /* The stick-table may be linked when belonging to
+ * the same configuration section.
+ */
+ struct {
+ const char *file; /* The file where the stick-table is declared. */
+ int line; /* The line in this <file> the stick-table is declared. */
+ } conf;
struct eb_root keys; /* head of sticky session tree */
struct eb_root exps; /* head of sticky session expiration tree */
struct eb_root updates; /* head of sticky updates sequence tree */
@@ -175,6 +182,7 @@
unsigned int u;
void *p;
} data_arg[STKTABLE_DATA_TYPES]; /* optional argument of each data type */
+ struct proxy *proxy; /* The proxy this stick-table is attached to, if any.*/
};
extern struct stktable_data_type stktable_data_types[STKTABLE_DATA_TYPES];
diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
index e7cd066..c0f4a46 100644
--- a/src/cfgparse-listen.c
+++ b/src/cfgparse-listen.c
@@ -25,6 +25,7 @@
#include <proto/protocol.h>
#include <proto/proxy.h>
#include <proto/server.h>
+#include <proto/stick_table.h>
/* Report a warning if a rule is placed after a 'tcp-request session' rule.
* Return 1 if the warning has been emitted, otherwise 0.
@@ -1710,7 +1711,6 @@
LIST_ADDQ(&curproxy->persist_rules, &rule->list);
}
else if (!strcmp(args[0], "stick-table")) {
- int myidx = 1;
struct proxy *other;
if (curproxy == &defproxy) {
@@ -1728,163 +1728,12 @@
goto out;
}
- curproxy->table.id = curproxy->id;
- curproxy->table.type = (unsigned int)-1;
- while (*args[myidx]) {
- const char *err;
-
- if (strcmp(args[myidx], "size") == 0) {
- myidx++;
- if (!*(args[myidx])) {
- ha_alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
- file, linenum, args[myidx-1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
- ha_alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
- file, linenum, *err, args[myidx-1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- myidx++;
- }
- else if (strcmp(args[myidx], "peers") == 0) {
- myidx++;
- if (!*(args[myidx])) {
- ha_alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
- file, linenum, args[myidx-1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- curproxy->table.peers.name = strdup(args[myidx++]);
- }
- else if (strcmp(args[myidx], "expire") == 0) {
- myidx++;
- if (!*(args[myidx])) {
- ha_alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
- file, linenum, args[myidx-1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
- if (err) {
- ha_alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
- file, linenum, *err, args[myidx-1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- if (val > INT_MAX) {
- ha_alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
- file, linenum, val);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- curproxy->table.expire = val;
- myidx++;
- }
- else if (strcmp(args[myidx], "nopurge") == 0) {
- curproxy->table.nopurge = 1;
- myidx++;
- }
- else if (strcmp(args[myidx], "type") == 0) {
- myidx++;
- if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
- ha_alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
- file, linenum, args[myidx]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- /* myidx already points to next arg */
- }
- else if (strcmp(args[myidx], "store") == 0) {
- int type, err;
- char *cw, *nw, *sa;
-
- myidx++;
- nw = args[myidx];
- while (*nw) {
- /* the "store" keyword supports a comma-separated list */
- cw = nw;
- sa = NULL; /* store arg */
- while (*nw && *nw != ',') {
- if (*nw == '(') {
- *nw = 0;
- sa = ++nw;
- while (*nw != ')') {
- if (!*nw) {
- ha_alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
- file, linenum, args[0], cw);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- nw++;
- }
- *nw = '\0';
- }
- nw++;
- }
- if (*nw)
- *nw++ = '\0';
- type = stktable_get_data_type(cw);
- if (type < 0) {
- ha_alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
- file, linenum, args[0], cw);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- err = stktable_alloc_data_type(&curproxy->table, type, sa);
- switch (err) {
- case PE_NONE: break;
- case PE_EXIST:
- ha_warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
- file, linenum, args[0], cw);
- err_code |= ERR_WARN;
- break;
-
- case PE_ARG_MISSING:
- ha_alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
- file, linenum, args[0], cw);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
-
- case PE_ARG_NOT_USED:
- ha_alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
- file, linenum, args[0], cw);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
-
- default:
- ha_alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
- file, linenum, args[0], cw);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- myidx++;
- }
- else {
- ha_alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
- file, linenum, args[myidx]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
-
- if (!curproxy->table.size) {
- ha_alert("parsing [%s:%d] : stick-table: missing size.\n",
- file, linenum);
- err_code |= ERR_ALERT | ERR_FATAL;
+ err_code |= parse_stick_table(file, linenum, args, &curproxy->table, curproxy->id, NULL);
+ if (err_code & ERR_FATAL)
goto out;
- }
- if (curproxy->table.type == (unsigned int)-1) {
- ha_alert("parsing [%s:%d] : stick-table: missing type.\n",
- file, linenum);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
+ /* Store the proxy in the stick-table. */
+ curproxy->table->proxy = curproxy;
}
else if (!strcmp(args[0], "stick")) {
struct sticking_rule *rule;
diff --git a/src/stick_table.c b/src/stick_table.c
index e24ef65..d8053dc 100644
--- a/src/stick_table.c
+++ b/src/stick_table.c
@@ -15,6 +15,7 @@
#include <errno.h>
#include <common/config.h>
+#include <common/cfgparse.h>
#include <common/initcall.h>
#include <common/memory.h>
#include <common/mini-clist.h>
@@ -664,6 +665,197 @@
return 1;
}
+/*
+ * Parse a line with <linenum> as number in <file> configuration file to configure the
+ * stick-table with <t> as address and <id> as ID.
+ * <peers> provides the "peers" section pointer only if this function is called from a "peers" section.
+ * Return an error status with ERR_* flags set if required, 0 if no error was encountered.
+ */
+int parse_stick_table(const char *file, int linenum, char **args,
+ struct stktable *t, char *id, struct peers *peers)
+{
+ int err_code = 0;
+ int idx = 1;
+ unsigned int val;
+
+ if (!id || !*id) {
+ ha_alert("parsing [%s:%d] : %s: ID not provided.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_ABORT;
+ goto out;
+ }
+
+ /* Store the "peers" section if this function is called from a "peers" section. */
+ if (peers) {
+ t->peers.p = peers;
+ idx++;
+ }
+
+ t->id = id;
+ t->type = (unsigned int)-1;
+ t->conf.file = file;
+ t->conf.line = linenum;
+
+ while (*args[idx]) {
+ const char *err;
+
+ if (strcmp(args[idx], "size") == 0) {
+ idx++;
+ if (!*(args[idx])) {
+ ha_alert("parsing [%s:%d] : %s: missing argument after '%s'.\n",
+ file, linenum, args[0], args[idx-1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ if ((err = parse_size_err(args[idx], &t->size))) {
+ ha_alert("parsing [%s:%d] : %s: unexpected character '%c' in argument of '%s'.\n",
+ file, linenum, args[0], *err, args[idx-1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ idx++;
+ }
+ /* This argument does not exit in "peers" section. */
+ else if (!peers && strcmp(args[idx], "peers") == 0) {
+ idx++;
+ if (!*(args[idx])) {
+ ha_alert("parsing [%s:%d] : %s: missing argument after '%s'.\n",
+ file, linenum, args[0], args[idx-1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ t->peers.name = strdup(args[idx++]);
+ }
+ else if (strcmp(args[idx], "expire") == 0) {
+ idx++;
+ if (!*(args[idx])) {
+ ha_alert("parsing [%s:%d] : %s: missing argument after '%s'.\n",
+ file, linenum, args[0], args[idx-1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ err = parse_time_err(args[idx], &val, TIME_UNIT_MS);
+ if (err) {
+ ha_alert("parsing [%s:%d] : %s: unexpected character '%c' in argument of '%s'.\n",
+ file, linenum, args[0], *err, args[idx-1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ if (val > INT_MAX) {
+ ha_alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
+ file, linenum, val);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ t->expire = val;
+ idx++;
+ }
+ else if (strcmp(args[idx], "nopurge") == 0) {
+ t->nopurge = 1;
+ idx++;
+ }
+ else if (strcmp(args[idx], "type") == 0) {
+ idx++;
+ if (stktable_parse_type(args, &idx, &t->type, &t->key_size) != 0) {
+ ha_alert("parsing [%s:%d] : %s: unknown type '%s'.\n",
+ file, linenum, args[0], args[idx]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ /* idx already points to next arg */
+ }
+ else if (strcmp(args[idx], "store") == 0) {
+ int type, err;
+ char *cw, *nw, *sa;
+
+ idx++;
+ nw = args[idx];
+ while (*nw) {
+ /* the "store" keyword supports a comma-separated list */
+ cw = nw;
+ sa = NULL; /* store arg */
+ while (*nw && *nw != ',') {
+ if (*nw == '(') {
+ *nw = 0;
+ sa = ++nw;
+ while (*nw != ')') {
+ if (!*nw) {
+ ha_alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
+ file, linenum, args[0], cw);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ nw++;
+ }
+ *nw = '\0';
+ }
+ nw++;
+ }
+ if (*nw)
+ *nw++ = '\0';
+ type = stktable_get_data_type(cw);
+ if (type < 0) {
+ ha_alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
+ file, linenum, args[0], cw);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ err = stktable_alloc_data_type(t, type, sa);
+ switch (err) {
+ case PE_NONE: break;
+ case PE_EXIST:
+ ha_warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
+ file, linenum, args[0], cw);
+ err_code |= ERR_WARN;
+ break;
+
+ case PE_ARG_MISSING:
+ ha_alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
+ file, linenum, args[0], cw);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+
+ case PE_ARG_NOT_USED:
+ ha_alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
+ file, linenum, args[0], cw);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+
+ default:
+ ha_alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
+ file, linenum, args[0], cw);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ idx++;
+ }
+ else {
+ ha_alert("parsing [%s:%d] : %s: unknown argument '%s'.\n",
+ file, linenum, args[0], args[idx]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+
+ if (!t->size) {
+ ha_alert("parsing [%s:%d] : %s: missing size.\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ if (t->type == (unsigned int)-1) {
+ ha_alert("parsing [%s:%d] : %s: missing type.\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ out:
+ return err_code;
+}
+
/* Prepares a stktable_key from a sample <smp> to search into table <t>.
* Note that the sample *is* modified and that the returned key may point
* to it, so the sample must not be modified afterwards before the lookup.