MEDIUM: bwlim: Support constants limit or period on set-bandwidth-limit actions
It is now possible to set a constant for the limit or period parameters on a
set-bandwidth-limit actions. The limit must follow the HAProxy size format
and is expressed in bytes. The period must follow the HAProxy time format
and is expressed in milliseconds. Of course, it is still possible to use
sample expressions instead.
The documentation was updated accordingly.
It is not really a bug. Only exemples were written this way in the
documentation. But it could be good to backport this change in 2.7.
diff --git a/src/flt_bwlim.c b/src/flt_bwlim.c
index d59da23..ff39d66 100644
--- a/src/flt_bwlim.c
+++ b/src/flt_bwlim.c
@@ -35,6 +35,11 @@
#define BWLIM_FL_OUT 0x00000002 /* Limit clients downloads */
#define BWLIM_FL_SHARED 0x00000004 /* Limit shared between clients (using stick-tables) */
+#define BWLIM_ACT_LIMIT_EXPR 0x00000001
+#define BWLIM_ACT_LIMIT_CONST 0x00000002
+#define BWLIM_ACT_PERIOD_EXPR 0x00000004
+#define BWLIM_ACT_PERIOD_CONST 0x00000008
+
struct bwlim_config {
struct proxy *proxy;
char *name;
@@ -384,16 +389,21 @@
st->limit = 0;
st->period = 0;
- if (rule->arg.act.p[1]) {
+ if (rule->action & BWLIM_ACT_LIMIT_EXPR) {
smp = sample_fetch_as_type(px, sess, s, opt, rule->arg.act.p[1], SMP_T_SINT);
if (smp && smp->data.u.sint > 0)
st->limit = smp->data.u.sint;
}
- if (rule->arg.act.p[2]) {
+ else if (rule->action & BWLIM_ACT_LIMIT_CONST)
+ st->limit = (uintptr_t)rule->arg.act.p[1];
+
+ if (rule->action & BWLIM_ACT_PERIOD_EXPR) {
smp = sample_fetch_as_type(px, sess, s, opt, rule->arg.act.p[2], SMP_T_SINT);
if (smp && smp->data.u.sint > 0)
st->period = smp->data.u.sint;
}
+ else if (rule->action & BWLIM_ACT_PERIOD_CONST)
+ st->period = (uintptr_t)rule->arg.act.p[2];
}
st->exp = TICK_ETERNITY;
@@ -445,7 +455,7 @@
if (px->cap & PR_CAP_BE)
where |= (rule->from == ACT_F_HTTP_REQ ? SMP_VAL_BE_HRQ_HDR : SMP_VAL_BE_HRS_HDR);
- if (rule->arg.act.p[1]) {
+ if ((rule->action & BWLIM_ACT_LIMIT_EXPR) && rule->arg.act.p[1]) {
struct sample_expr *expr = rule->arg.act.p[1];
if (!(expr->fetch->val & where)) {
@@ -465,7 +475,7 @@
}
}
- if (rule->arg.act.p[2]) {
+ if ((rule->action & BWLIM_ACT_PERIOD_EXPR) && rule->arg.act.p[2]) {
struct sample_expr *expr = rule->arg.act.p[2];
if (!(expr->fetch->val & where)) {
@@ -512,11 +522,11 @@
static void release_bwlim_action(struct act_rule *rule)
{
ha_free(&rule->arg.act.p[0]);
- if (rule->arg.act.p[1]) {
+ if ((rule->action & BWLIM_ACT_LIMIT_EXPR) && rule->arg.act.p[1]) {
release_sample_expr(rule->arg.act.p[1]);
rule->arg.act.p[1] = NULL;
}
- if (rule->arg.act.p[2]) {
+ if ((rule->action & BWLIM_ACT_PERIOD_EXPR) && rule->arg.act.p[2]) {
release_sample_expr(rule->arg.act.p[2]);
rule->arg.act.p[2] = NULL;
}
@@ -556,27 +566,55 @@
while (1) {
if (strcmp(args[cur_arg], "limit") == 0) {
+ const char *res;
+ unsigned int limit;
+
cur_arg++;
if (!args[cur_arg]) {
- memprintf(err, "missing limit expression");
+ memprintf(err, "missing limit value or expression");
goto error;
}
+ res = parse_size_err(args[cur_arg], &limit);
+ if (!res) {
+ rule->action |= BWLIM_ACT_LIMIT_CONST;
+ rule->arg.act.p[1] = (void *)(uintptr_t)limit;
+ cur_arg++;
+ continue;
+ }
+
- expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
- if (!expr)
+ expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, NULL, &px->conf.args, NULL);
+ if (!expr) {
+ memprintf(err, "'%s': invalid size value or unknown fetch method '%s'", args[cur_arg-1], args[cur_arg]);
goto error;
+ }
+ rule->action |= BWLIM_ACT_LIMIT_EXPR;
rule->arg.act.p[1] = expr;
}
else if (strcmp(args[cur_arg], "period") == 0) {
+ const char *res;
+ unsigned int period;
+
cur_arg++;
if (!args[cur_arg]) {
- memprintf(err, "missing period expression");
+ memprintf(err, "missing period value or expression");
goto error;
}
- expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
- if (!expr)
+ res = parse_time_err(args[cur_arg], &period, TIME_UNIT_MS);
+ if (!res) {
+ rule->action |= BWLIM_ACT_PERIOD_CONST;
+ rule->arg.act.p[2] = (void *)(uintptr_t)period;
+ cur_arg++;
+ continue;
+ }
+
+ expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, NULL, &px->conf.args, NULL);
+ if (!expr) {
+ memprintf(err, "'%s': invalid time value or unknown fetch method '%s'", args[cur_arg-1], args[cur_arg]);
goto error;
+ }
+ rule->action |= BWLIM_ACT_PERIOD_EXPR;
rule->arg.act.p[2] = expr;
}
else