From: Florian Westphal <fw@strlen.de>
To: <netfilter-devel@vger.kernel.org>
Cc: Florian Westphal <fw@strlen.de>
Subject: [PATCH nft 2/3] meta: add short-hand mnemonic for probalistic matching
Date: Tue, 5 Jul 2016 09:35:34 +0200 [thread overview]
Message-ID: <1467704135-9154-3-git-send-email-fw@strlen.de> (raw)
In-Reply-To: <1467704135-9154-1-git-send-email-fw@strlen.de>
Allow users to use a simpler way to specify probalistic matching, e. g.:
meta probability 0.5 (match approx. every 2nd packet)
meta probability 0.001 (match approx. once every 1000 packets)
nft list will still show
meta random <= 2147483647
meta random <= 4294967
a followup patch will hide this internal representation (comparing
random 32 bit value with the scaled constant) -- we will munge the
expression statement and turn it into a special-cased meta one during
netlink delinearization.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/meta.h | 4 ++++
src/meta.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/parser_bison.y | 19 +++++++++++++++++++
src/scanner.l | 5 +++++
4 files changed, 83 insertions(+)
diff --git a/include/meta.h b/include/meta.h
index f25b147..aafd232 100644
--- a/include/meta.h
+++ b/include/meta.h
@@ -26,6 +26,10 @@ struct meta_template {
extern struct expr *meta_expr_alloc(const struct location *loc,
enum nft_meta_keys key);
+struct error_record *meta_probability_parse(const struct location *loc,
+ const char *s, uint32_t *v);
+struct stmt *meta_stmt_meta_probability(const struct location *loc, uint32_t p);
+
struct stmt *meta_stmt_meta_iiftype(const struct location *loc, uint16_t type);
const struct datatype ifindex_type;
diff --git a/src/meta.c b/src/meta.c
index 8b1a2fc..2b0d5f0 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -364,6 +364,47 @@ static const struct datatype devgroup_type = {
.flags = DTYPE_F_PREFIX,
};
+#define META_PROB_FMT "%.9f"
+
+/* UINT_MAX == 1.0, UINT_MAX/2 == 0.5, etc. */
+struct error_record *meta_probability_parse(const struct location *loc, const char *str,
+ uint32_t *value)
+{
+ static const uint64_t precision = 1000000000;
+ uint64_t tmp;
+ char *end;
+ double d, scaled;
+
+ errno = 0;
+ d = strtod(str, &end);
+
+ if (errno)
+ return error(loc, "Could not parse probability %s: %s", str, strerror(errno));
+ if (end == str)
+ return error(loc, "Could not parse probability %s", str);
+
+ scaled = d;
+ scaled *= precision;
+ tmp = (uint64_t) scaled;
+
+ if (tmp > UINT_MAX)
+ goto overflow;
+
+ tmp *= UINT_MAX;
+ tmp /= precision;
+
+ if (tmp >= UINT_MAX)
+ goto overflow;
+
+ *value = (uint32_t) tmp;
+ if (*value == 0)
+ return error(loc, "Probability " META_PROB_FMT " too %s", d, "small");
+
+ return NULL;
+ overflow:
+ return error(loc, "Probability " META_PROB_FMT " too %s", d, "big");
+}
+
static const struct meta_template meta_templates[] = {
[NFT_META_LEN] = META_TEMPLATE("length", &integer_type,
4 * 8, BYTEORDER_HOST_ENDIAN),
@@ -618,3 +659,17 @@ struct stmt *meta_stmt_meta_iiftype(const struct location *loc, uint16_t type)
dep = relational_expr_alloc(loc, OP_EQ, left, right);
return expr_stmt_alloc(&dep->location, dep);
}
+
+struct stmt *meta_stmt_meta_probability(const struct location *loc, uint32_t p)
+{
+ struct expr *e, *left, *right;
+
+ left = meta_expr_alloc(loc, NFT_META_PRANDOM);
+ right = constant_expr_alloc(loc, &integer_type,
+ BYTEORDER_HOST_ENDIAN,
+ sizeof(p) * BITS_PER_BYTE, &p);
+
+ e = relational_expr_alloc(loc, OP_LTE, left, right);
+
+ return expr_stmt_alloc(&e->location, e);
+}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index fdbfed9..dceb90f 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -2367,6 +2367,25 @@ meta_stmt : META meta_key SET expr
{
$$ = meta_stmt_alloc(&@$, $1, $3);
}
+ | META STRING STRING
+ {
+ struct error_record *erec;
+ uint32_t value;
+
+ if (strcmp($2, "probability") != 0) {
+ erec_queue(error(&@$, "unknown meta option %s", $2),
+ state->msgs);
+ YYERROR;
+ }
+
+ erec = meta_probability_parse(&@$, $3, &value);
+ if (erec != NULL) {
+ erec_queue(erec, state->msgs);
+ YYERROR;
+ }
+
+ $$ = meta_stmt_meta_probability(&@$, value);
+ }
;
ct_expr : CT ct_key
diff --git a/src/scanner.l b/src/scanner.l
index 88669d0..29ffe94 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -110,6 +110,7 @@ digit [0-9]
hexdigit [0-9a-fA-F]
decstring {digit}+
hexstring 0[xX]{hexdigit}+
+probability 0.{decstring}
range ({decstring}?:{decstring}?)
letter [a-zA-Z]
string ({letter})({letter}|{digit}|[/\-_\.])*
@@ -490,6 +491,10 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
return NUM;
}
+{probability} {
+ yylval->string = xstrdup(yytext);
+ return STRING;
+ }
{hexstring} {
errno = 0;
yylval->val = strtoull(yytext, NULL, 0);
--
2.7.3
next prev parent reply other threads:[~2016-07-05 7:35 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-05 7:35 [PATCH nft 1/3] meta: add random and probability match Florian Westphal
2016-07-05 7:35 ` [PATCH nft 1/3] meta: add random expression key Florian Westphal
2016-07-18 19:34 ` Pablo Neira Ayuso
2016-07-18 22:09 ` Florian Westphal
2016-07-05 7:35 ` Florian Westphal [this message]
2016-07-14 10:41 ` [PATCH nft 2/3] meta: add short-hand mnemonic for probalistic matching Pablo Neira Ayuso
2016-07-14 10:52 ` Florian Westphal
2016-07-14 11:32 ` Pablo Neira Ayuso
2016-07-14 12:08 ` Florian Westphal
2016-07-14 12:17 ` Pablo Neira Ayuso
2016-07-05 7:35 ` [PATCH nft 3/3] netlink_delinearize, meta: show meta prandom <= value as probability mnemonic Florian Westphal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1467704135-9154-3-git-send-email-fw@strlen.de \
--to=fw@strlen.de \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).