summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2015-03-23 21:34:57 +0000
committerPatrick McHardy <kaber@trash.net>2015-04-12 19:59:27 +0100
commit38a077f7af8a2151b565e3cb324901b48afd299e (patch)
treefd119cd653996dbb421f2d0f8450d167bc213cbb
parent52532335290457cc449564b7e011f73bef3a83e2 (diff)
set: add timeout support for sets
Timeout support can be enabled in one of two ways: 1. Using a default timeout value: set test { type ipv4_addr; timeout 1h; } 2. Using the timeout flag without a default: set test { type ipv4_addr; flags timeout; } Optionally a garbage collection interval can be specified using gc-interval <interval>; Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/linux/netfilter/nf_tables.h6
-rw-r--r--include/rule.h5
-rw-r--r--src/evaluate.c4
-rw-r--r--src/netlink.c10
-rw-r--r--src/parser_bison.y13
-rw-r--r--src/rule.c23
-rw-r--r--src/scanner.l2
7 files changed, 62 insertions, 1 deletions
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 832bc46d..8671505e 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -207,12 +207,14 @@ enum nft_rule_compat_attributes {
* @NFT_SET_CONSTANT: set contents may not change while bound
* @NFT_SET_INTERVAL: set contains intervals
* @NFT_SET_MAP: set is used as a dictionary
+ * @NFT_SET_TIMEOUT: set uses timeouts
*/
enum nft_set_flags {
NFT_SET_ANONYMOUS = 0x1,
NFT_SET_CONSTANT = 0x2,
NFT_SET_INTERVAL = 0x4,
NFT_SET_MAP = 0x8,
+ NFT_SET_TIMEOUT = 0x10,
};
/**
@@ -251,6 +253,8 @@ enum nft_set_desc_attributes {
* @NFTA_SET_POLICY: selection policy (NLA_U32)
* @NFTA_SET_DESC: set description (NLA_NESTED)
* @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
+ * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
+ * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
*/
enum nft_set_attributes {
NFTA_SET_UNSPEC,
@@ -264,6 +268,8 @@ enum nft_set_attributes {
NFTA_SET_POLICY,
NFTA_SET_DESC,
NFTA_SET_ID,
+ NFTA_SET_TIMEOUT,
+ NFTA_SET_GC_INTERVAL,
__NFTA_SET_MAX
};
#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
diff --git a/include/rule.h b/include/rule.h
index 97959f7b..5d445993 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -173,6 +173,7 @@ enum set_flags {
SET_F_CONSTANT = 0x2,
SET_F_INTERVAL = 0x4,
SET_F_MAP = 0x8,
+ SET_F_TIMEOUT = 0x10,
};
/**
@@ -183,6 +184,8 @@ enum set_flags {
* @location: location the set was defined/declared at
* @refcnt: reference count
* @flags: bitmask of set flags
+ * @gc_int: garbage collection interval
+ * @timeout: default timeout value
* @keytype: key data type
* @keylen: key length
* @datatype: mapping data type
@@ -197,6 +200,8 @@ struct set {
struct location location;
unsigned int refcnt;
uint32_t flags;
+ uint32_t gc_int;
+ uint64_t timeout;
const struct datatype *keytype;
unsigned int keylen;
const struct datatype *datatype;
diff --git a/src/evaluate.c b/src/evaluate.c
index 37db107b..04ca08df 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1737,6 +1737,10 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
return -1;
}
+ /* Default timeout value implies timeout support */
+ if (set->timeout)
+ set->flags |= SET_F_TIMEOUT;
+
if (!(set->flags & SET_F_MAP))
return 0;
diff --git a/src/netlink.c b/src/netlink.c
index 0827034e..e1d6421f 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1068,6 +1068,11 @@ static struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
set->datalen = data_len * BITS_PER_BYTE;
}
+ if (nft_set_attr_is_set(nls, NFT_SET_ATTR_TIMEOUT))
+ set->timeout = nft_set_attr_get_u64(nls, NFT_SET_ATTR_TIMEOUT);
+ if (nft_set_attr_is_set(nls, NFT_SET_ATTR_GC_INTERVAL))
+ set->gc_int = nft_set_attr_get_u32(nls, NFT_SET_ATTR_GC_INTERVAL);
+
if (nft_set_attr_is_set(nls, NFT_SET_ATTR_POLICY))
set->policy = nft_set_attr_get_u32(nls, NFT_SET_ATTR_POLICY);
@@ -1131,6 +1136,11 @@ static int netlink_add_set_batch(struct netlink_ctx *ctx,
nft_set_attr_set_u32(nls, NFT_SET_ATTR_DATA_LEN,
set->datalen / BITS_PER_BYTE);
}
+ if (set->timeout)
+ nft_set_attr_set_u64(nls, NFT_SET_ATTR_TIMEOUT, set->timeout);
+ if (set->gc_int)
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_GC_INTERVAL, set->gc_int);
+
set->handle.set_id = ++set_id;
nft_set_attr_set_u32(nls, NFT_SET_ATTR_ID, set->handle.set_id);
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 9fbc590c..80831878 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -201,6 +201,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token CONSTANT "constant"
%token INTERVAL "interval"
+%token TIMEOUT "timeout"
+%token GC_INTERVAL "gc-interval"
%token ELEMENTS "elements"
%token POLICY "policy"
@@ -944,6 +946,16 @@ set_block : /* empty */ { $$ = $<set>-1; }
$1->flags = $3;
$$ = $1;
}
+ | set_block TIMEOUT time_spec stmt_seperator
+ {
+ $1->timeout = $3 * 1000;
+ $$ = $1;
+ }
+ | set_block GC_INTERVAL time_spec stmt_seperator
+ {
+ $1->gc_int = $3 * 1000;
+ $$ = $1;
+ }
| set_block ELEMENTS '=' set_expr
{
$1->init = $4;
@@ -961,6 +973,7 @@ set_flag_list : set_flag_list COMMA set_flag
set_flag : CONSTANT { $$ = SET_F_CONSTANT; }
| INTERVAL { $$ = SET_F_INTERVAL; }
+ | TIMEOUT { $$ = SET_F_TIMEOUT; }
;
map_block_alloc : /* empty */
diff --git a/src/rule.c b/src/rule.c
index 71143807..b2090ddd 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -136,6 +136,7 @@ static void do_set_print(const struct set *set, struct print_fmt_options *opts)
{
const char *delim = "";
const char *type;
+ uint32_t flags;
type = set->flags & SET_F_MAP ? "map" : "set";
printf("%s%s", opts->tab, type);
@@ -167,7 +168,12 @@ static void do_set_print(const struct set *set, struct print_fmt_options *opts)
}
}
- if (set->flags & (SET_F_CONSTANT | SET_F_INTERVAL)) {
+ flags = set->flags;
+ /* "timeout" flag is redundant if a default timeout exists */
+ if (set->timeout)
+ flags &= ~SET_F_TIMEOUT;
+
+ if (flags & (SET_F_CONSTANT | SET_F_INTERVAL | SET_F_TIMEOUT)) {
printf("%s%sflags ", opts->tab, opts->tab);
if (set->flags & SET_F_CONSTANT) {
printf("%sconstant", delim);
@@ -177,6 +183,21 @@ static void do_set_print(const struct set *set, struct print_fmt_options *opts)
printf("%sinterval", delim);
delim = ",";
}
+ if (set->flags & SET_F_TIMEOUT) {
+ printf("%stimeout", delim);
+ delim = ",";
+ }
+ printf("%s", opts->nl);
+ }
+
+ if (set->timeout) {
+ printf("%s%stimeout ", opts->tab, opts->tab);
+ time_print(set->timeout / 1000);
+ printf("%s", opts->nl);
+ }
+ if (set->gc_int) {
+ printf("%s%sgc-interval ", opts->tab, opts->tab);
+ time_print(set->gc_int / 1000);
printf("%s", opts->nl);
}
diff --git a/src/scanner.l b/src/scanner.l
index 27d95bfc..4231d270 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -271,6 +271,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"constant" { return CONSTANT; }
"interval" { return INTERVAL; }
+"timeout" { return TIMEOUT; }
+"gc-interval" { return GC_INTERVAL; }
"elements" { return ELEMENTS; }
"policy" { return POLICY; }