- tune.maxaccept
- tune.maxpollevents
- tune.maxrewrite
+ - tune.pattern.cache-size
- tune.pipesize
- tune.rcvbuf.client
- tune.rcvbuf.server
larger than that. This means you don't have to worry about it when changing
bufsize.
+tune.pattern.cache-size <number>
+ Sets the size of the pattern lookup cache to <number> entries. This is an LRU
+ cache which reminds previous lookups and their results. It is used by ACLs
+ and maps on slow pattern lookups, namely the ones using the "sub", "reg",
+ "dir", "dom", "end", "bin" match methods as well as the case-insensitive
+ strings. It applies to pattern expressions which means that it will be able
+ to memorize the result of a lookup among all the patterns specified on a
+ configuration line (including all those loaded from files). It automatically
+ invalidates entries which are updated using HTTP actions or on the CLI. The
+ default cache size is set to 10000 entries, which limits its footprint to
+ about 5 MB on 32-bit systems and 8 MB on 64-bit systems. There is a very low
+ risk of collision in this cache, which is in the order of the size of the
+ cache divided by 2^64. Typically, at 10000 requests per second with the
+ default cache size of 10000 entries, there's 1% chance that a brute force
+ attack could cause a single collision after 60 years, or 0.1% after 6 years.
+ This is considered much lower than the risk of a memory corruption caused by
+ aging components. If this is not acceptable, the cache can be disabled by
+ setting this parameter to 0.
+
tune.pipesize <number>
Sets the kernel pipe buffer size to this size (in bytes). By default, pipes
are the default size for the system. But sometimes when using TCP splicing,
#include <proto/sample.h>
#include <ebsttree.h>
+#include <import/lru.h>
+#include <import/xxhash.h>
char *pat_match_names[PAT_MATCH_NUM] = {
[PAT_MATCH_FOUND] = "found",
/* This is the root of the list of all pattern_ref avalaibles. */
struct list pattern_reference = LIST_HEAD_INIT(pattern_reference);
+static struct lru64_head *pat_lru_tree;
+static unsigned long long pat_lru_seed;
+
/*
*
* The following functions are not exported and are used by internals process
struct pattern_tree *elt;
struct pattern_list *lst;
struct pattern *pattern;
+ struct pattern *ret = NULL;
+ struct lru64 *lru = NULL;
/* Lookup a string in the expression's pattern tree. */
if (!eb_is_empty(&expr->pattern_tree)) {
}
/* look in the list */
+ if (pat_lru_tree) {
+ unsigned long long seed = pat_lru_seed ^ (unsigned long long)expr;
+
+ lru = lru64_get(XXH64(smp->data.str.str, smp->data.str.len, seed),
+ pat_lru_tree, expr, expr->revision);
+ if (lru && lru->domain)
+ return lru->data;
+ }
+
list_for_each_entry(lst, &expr->patterns, list) {
pattern = &lst->pat;
icase = expr->mflags & PAT_MF_IGNORE_CASE;
if ((icase && strncasecmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0) ||
- (!icase && strncmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0))
- return pattern;
+ (!icase && strncmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0)) {
+ ret = pattern;
+ break;
+ }
}
- return NULL;
+ if (lru)
+ lru64_commit(lru, ret, expr, expr->revision);
+
+ return ret;
}
/* NB: For two binaries buf to be identical, it is required that their lengths match */
{
struct pattern_list *lst;
struct pattern *pattern;
+ struct pattern *ret = NULL;
+ struct lru64 *lru = NULL;
+
+ if (pat_lru_tree) {
+ unsigned long long seed = pat_lru_seed ^ (unsigned long long)expr;
+
+ lru = lru64_get(XXH64(smp->data.str.str, smp->data.str.len, seed),
+ pat_lru_tree, expr, expr->revision);
+ if (lru && lru->domain)
+ return lru->data;
+ }
- /* Look in the list. */
list_for_each_entry(lst, &expr->patterns, list) {
pattern = &lst->pat;
if (pattern->len != smp->data.str.len)
continue;
- if (memcmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0)
- return pattern;
+ if (memcmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0) {
+ ret = pattern;
+ break;
+ }
}
- return NULL;
+ if (lru)
+ lru64_commit(lru, ret, expr, expr->revision);
+
+ return ret;
}
/* Executes a regex. It temporarily changes the data to add a trailing zero,
{
struct pattern_list *lst;
struct pattern *pattern;
+ struct pattern *ret = NULL;
+ struct lru64 *lru = NULL;
+
+ if (pat_lru_tree) {
+ unsigned long long seed = pat_lru_seed ^ (unsigned long long)expr;
+
+ lru = lru64_get(XXH64(smp->data.str.str, smp->data.str.len, seed),
+ pat_lru_tree, expr, expr->revision);
+ if (lru && lru->domain)
+ return lru->data;
+ }
- /* look in the list */
list_for_each_entry(lst, &expr->patterns, list) {
pattern = &lst->pat;
- if (regex_exec2(pattern->ptr.reg, smp->data.str.str, smp->data.str.len))
- return pattern;
+ if (regex_exec2(pattern->ptr.reg, smp->data.str.str, smp->data.str.len)) {
+ ret = pattern;
+ break;
+ }
}
- return NULL;
+
+ if (lru)
+ lru64_commit(lru, ret, expr, expr->revision);
+
+ return ret;
}
/* Checks that the pattern matches the beginning of the tested string. */
struct pattern_tree *elt;
struct pattern_list *lst;
struct pattern *pattern;
+ struct pattern *ret = NULL;
+ struct lru64 *lru = NULL;
/* Lookup a string in the expression's pattern tree. */
if (!eb_is_empty(&expr->pattern_tree)) {
}
/* look in the list */
+ if (pat_lru_tree) {
+ unsigned long long seed = pat_lru_seed ^ (unsigned long long)expr;
+
+ lru = lru64_get(XXH64(smp->data.str.str, smp->data.str.len, seed),
+ pat_lru_tree, expr, expr->revision);
+ if (lru && lru->domain)
+ return lru->data;
+ }
+
list_for_each_entry(lst, &expr->patterns, list) {
pattern = &lst->pat;
(!icase && strncmp(pattern->ptr.str, smp->data.str.str, pattern->len) != 0))
continue;
- return pattern;
+ ret = pattern;
+ break;
}
- return NULL;
+
+ if (lru)
+ lru64_commit(lru, ret, expr, expr->revision);
+
+ return ret;
}
/* Checks that the pattern matches the end of the tested string. */
int icase;
struct pattern_list *lst;
struct pattern *pattern;
+ struct pattern *ret = NULL;
+ struct lru64 *lru = NULL;
+
+ if (pat_lru_tree) {
+ unsigned long long seed = pat_lru_seed ^ (unsigned long long)expr;
+
+ lru = lru64_get(XXH64(smp->data.str.str, smp->data.str.len, seed),
+ pat_lru_tree, expr, expr->revision);
+ if (lru && lru->domain)
+ return lru->data;
+ }
list_for_each_entry(lst, &expr->patterns, list) {
pattern = &lst->pat;
(!icase && strncmp(pattern->ptr.str, smp->data.str.str + smp->data.str.len - pattern->len, pattern->len) != 0))
continue;
- return pattern;
+ ret = pattern;
+ break;
}
- return NULL;
+
+ if (lru)
+ lru64_commit(lru, ret, expr, expr->revision);
+
+ return ret;
}
/* Checks that the pattern is included inside the tested string.
char *c;
struct pattern_list *lst;
struct pattern *pattern;
+ struct pattern *ret = NULL;
+ struct lru64 *lru = NULL;
+
+ if (pat_lru_tree) {
+ unsigned long long seed = pat_lru_seed ^ (unsigned long long)expr;
+
+ lru = lru64_get(XXH64(smp->data.str.str, smp->data.str.len, seed),
+ pat_lru_tree, expr, expr->revision);
+ if (lru && lru->domain)
+ return lru->data;
+ }
list_for_each_entry(lst, &expr->patterns, list) {
pattern = &lst->pat;
for (c = smp->data.str.str; c <= end; c++) {
if (tolower(*c) != tolower(*pattern->ptr.str))
continue;
- if (strncasecmp(pattern->ptr.str, c, pattern->len) == 0)
- return pattern;
+ if (strncasecmp(pattern->ptr.str, c, pattern->len) == 0) {
+ ret = pattern;
+ goto leave;
+ }
}
} else {
for (c = smp->data.str.str; c <= end; c++) {
if (*c != *pattern->ptr.str)
continue;
- if (strncmp(pattern->ptr.str, c, pattern->len) == 0)
- return pattern;
+ if (strncmp(pattern->ptr.str, c, pattern->len) == 0) {
+ ret = pattern;
+ goto leave;
+ }
}
}
}
- return NULL;
+ leave:
+ if (lru)
+ lru64_commit(lru, ret, expr, expr->revision);
+
+ return ret;
}
/* This one is used by other real functions. It checks that the pattern is
struct pat_ref *ref, *ref2, *ref3;
struct list pr = LIST_HEAD_INIT(pr);
+ pat_lru_seed = random();
+ if (global.tune.pattern_cache)
+ pat_lru_tree = lru64_new(global.tune.pattern_cache);
+
list_for_each_entry(ref, &pattern_reference, list) {
if (ref->unique_id == -1) {
/* Look for the first free id. */