]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: pattern: only match patterns that match the current generation
authorWilly Tarreau <w@1wt.eu>
Thu, 29 Oct 2020 08:41:34 +0000 (09:41 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 5 Nov 2020 18:27:09 +0000 (19:27 +0100)
Instead of matching any pattern found in the tree, only match those
matching the current generation of entries. This will make sure that
reloads are atomic, regardless of the time they take to complete, and
that newly added data are not matched until the whole reference is
committed. For consistency we proceed the same way on "show map" and
"show acl".

This will have no impact for now since generations are not used.

src/map.c
src/pattern.c

index ee022e29ba6c775ce9a74950ab962e9953ac5ecd..cd356b920fa132aa7d740727499e4612df2cc35d 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -368,6 +368,9 @@ static int cli_io_handler_pat_list(struct appctx *appctx)
 
                        elt = LIST_ELEM(appctx->ctx.map.bref.ref, struct pat_ref_elt *, list);
 
+                       if (elt->gen_id != appctx->ctx.map.ref->curr_gen)
+                               goto skip;
+
                        /* build messages */
                        if (elt->sample)
                                chunk_appendf(&trash, "%p %s %s\n",
@@ -386,7 +389,7 @@ static int cli_io_handler_pat_list(struct appctx *appctx)
                                si_rx_room_blk(si);
                                return 0;
                        }
-
+               skip:
                        /* get next list entry and check the end of the list */
                        appctx->ctx.map.bref.ref = elt->list.n;
                }
index 7b4d876e2f99641c1b85e376809ca5613b2fa361..864dbd798dc9de34a74ea09870a81825d5483d0d 100644 (file)
@@ -465,9 +465,14 @@ struct pattern *pat_match_str(struct sample *smp, struct pattern_expr *expr, int
                node = ebst_lookup(&expr->pattern_tree, smp->data.u.str.area);
                if (prev)
                        smp->data.u.str.area[smp->data.u.str.data] = prev;
-               if (node) {
+
+               while (node) {
+                       elt = ebmb_entry(node, struct pattern_tree, node);
+                       if (elt->ref->gen_id != expr->ref->curr_gen) {
+                               node = ebmb_next(node);
+                               continue;
+                       }
                        if (fill) {
-                               elt = ebmb_entry(node, struct pattern_tree, node);
                                static_pattern.data = elt->data;
                                static_pattern.ref = elt->ref;
                                static_pattern.sflags = PAT_SF_TREE;
@@ -494,6 +499,9 @@ struct pattern *pat_match_str(struct sample *smp, struct pattern_expr *expr, int
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
 
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if (pattern->len != smp->data.u.str.data)
                        continue;
 
@@ -533,6 +541,9 @@ struct pattern *pat_match_bin(struct sample *smp, struct pattern_expr *expr, int
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
 
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if (pattern->len != smp->data.u.str.data)
                        continue;
 
@@ -561,6 +572,9 @@ struct pattern *pat_match_regm(struct sample *smp, struct pattern_expr *expr, in
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
 
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if (regex_exec_match2(pattern->ptr.reg, smp->data.u.str.area, smp->data.u.str.data,
                                      MAX_MATCH, pmatch, 0)) {
                        ret = pattern;
@@ -596,6 +610,9 @@ struct pattern *pat_match_reg(struct sample *smp, struct pattern_expr *expr, int
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
 
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if (regex_exec2(pattern->ptr.reg, smp->data.u.str.area, smp->data.u.str.data)) {
                        ret = pattern;
                        break;
@@ -644,9 +661,13 @@ struct pattern *pat_match_beg(struct sample *smp, struct pattern_expr *expr, int
                if (prev)
                        smp->data.u.str.area[smp->data.u.str.data] = prev;
 
-               if (node) {
+               while (node) {
+                       elt = ebmb_entry(node, struct pattern_tree, node);
+                       if (elt->ref->gen_id != expr->ref->curr_gen) {
+                               node = ebmb_next(node);
+                               continue;
+                       }
                        if (fill) {
-                               elt = ebmb_entry(node, struct pattern_tree, node);
                                static_pattern.data = elt->data;
                                static_pattern.ref = elt->ref;
                                static_pattern.sflags = PAT_SF_TREE;
@@ -672,6 +693,9 @@ struct pattern *pat_match_beg(struct sample *smp, struct pattern_expr *expr, int
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
 
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if (pattern->len > smp->data.u.str.data)
                        continue;
 
@@ -713,6 +737,9 @@ struct pattern *pat_match_end(struct sample *smp, struct pattern_expr *expr, int
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
 
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if (pattern->len > smp->data.u.str.data)
                        continue;
 
@@ -758,6 +785,9 @@ struct pattern *pat_match_sub(struct sample *smp, struct pattern_expr *expr, int
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
 
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if (pattern->len > smp->data.u.str.data)
                        continue;
 
@@ -856,6 +886,10 @@ struct pattern *pat_match_dir(struct sample *smp, struct pattern_expr *expr, int
 
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
+
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if (match_word(smp, pattern, expr->mflags, make_4delim('/', '?', '?', '?')))
                        return pattern;
        }
@@ -873,6 +907,10 @@ struct pattern *pat_match_dom(struct sample *smp, struct pattern_expr *expr, int
 
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
+
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if (match_word(smp, pattern, expr->mflags, make_4delim('/', '?', '.', ':')))
                        return pattern;
        }
@@ -887,6 +925,10 @@ struct pattern *pat_match_int(struct sample *smp, struct pattern_expr *expr, int
 
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
+
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if ((!pattern->val.range.min_set || pattern->val.range.min <= smp->data.u.sint) &&
                    (!pattern->val.range.max_set || smp->data.u.sint <= pattern->val.range.max))
                        return pattern;
@@ -902,6 +944,10 @@ struct pattern *pat_match_len(struct sample *smp, struct pattern_expr *expr, int
 
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
+
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                if ((!pattern->val.range.min_set || pattern->val.range.min <= smp->data.u.str.data) &&
                    (!pattern->val.range.max_set || smp->data.u.str.data <= pattern->val.range.max))
                        return pattern;
@@ -926,9 +972,13 @@ struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int
                 */
                s = &smp->data.u.ipv4;
                node = ebmb_lookup_longest(&expr->pattern_tree, &s->s_addr);
-               if (node) {
+               while (node) {
+                       elt = ebmb_entry(node, struct pattern_tree, node);
+                       if (elt->ref->gen_id != expr->ref->curr_gen) {
+                               node = ebmb_next(node);
+                               continue;
+                       }
                        if (fill) {
-                               elt = ebmb_entry(node, struct pattern_tree, node);
                                static_pattern.data = elt->data;
                                static_pattern.ref = elt->ref;
                                static_pattern.sflags = PAT_SF_TREE;
@@ -948,9 +998,13 @@ struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int
                write_u16(&tmp6.s6_addr[10], htons(0xffff));
                write_u32(&tmp6.s6_addr[12], smp->data.u.ipv4.s_addr);
                node = ebmb_lookup_longest(&expr->pattern_tree_2, &tmp6);
-               if (node) {
+               while (node) {
+                       elt = ebmb_entry(node, struct pattern_tree, node);
+                       if (elt->ref->gen_id != expr->ref->curr_gen) {
+                               node = ebmb_next(node);
+                               continue;
+                       }
                        if (fill) {
-                               elt = ebmb_entry(node, struct pattern_tree, node);
                                static_pattern.data = elt->data;
                                static_pattern.ref = elt->ref;
                                static_pattern.sflags = PAT_SF_TREE;
@@ -968,9 +1022,13 @@ struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int
                 * the longest match method.
                 */
                node = ebmb_lookup_longest(&expr->pattern_tree_2, &smp->data.u.ipv6);
-               if (node) {
+               while (node) {
+                       elt = ebmb_entry(node, struct pattern_tree, node);
+                       if (elt->ref->gen_id != expr->ref->curr_gen) {
+                               node = ebmb_next(node);
+                               continue;
+                       }
                        if (fill) {
-                               elt = ebmb_entry(node, struct pattern_tree, node);
                                static_pattern.data = elt->data;
                                static_pattern.ref = elt->ref;
                                static_pattern.sflags = PAT_SF_TREE;
@@ -1001,9 +1059,13 @@ struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int
                         * match method.
                         */
                        node = ebmb_lookup_longest(&expr->pattern_tree, &v4);
-                       if (node) {
+                       while (node) {
+                               elt = ebmb_entry(node, struct pattern_tree, node);
+                               if (elt->ref->gen_id != expr->ref->curr_gen) {
+                                       node = ebmb_next(node);
+                                       continue;
+                               }
                                if (fill) {
-                                       elt = ebmb_entry(node, struct pattern_tree, node);
                                        static_pattern.data = elt->data;
                                        static_pattern.ref = elt->ref;
                                        static_pattern.sflags = PAT_SF_TREE;
@@ -1021,6 +1083,9 @@ struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int
        list_for_each_entry(lst, &expr->patterns, list) {
                pattern = &lst->pat;
 
+               if (pattern->ref->gen_id != expr->ref->curr_gen)
+                       continue;
+
                /* The input sample is IPv4, use it as is. */
                if (smp->data.type == SMP_T_IPV4) {
                        v4 = smp->data.u.ipv4.s_addr;