From c93da6950e2bba1bdd3c788ce2bc1d8d5d66ad38 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 29 Oct 2020 09:41:34 +0100 Subject: [PATCH] MEDIUM: pattern: only match patterns that match the current generation 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 | 5 ++- src/pattern.c | 89 ++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 13 deletions(-) diff --git a/src/map.c b/src/map.c index ee022e29b..cd356b920 100644 --- 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; } diff --git a/src/pattern.c b/src/pattern.c index 7b4d876e2..864dbd798 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -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;