* @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,
};
/**
* @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,
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)
SET_F_CONSTANT = 0x2,
SET_F_INTERVAL = 0x4,
SET_F_MAP = 0x8,
+ SET_F_TIMEOUT = 0x10,
};
/**
* @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
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;
return -1;
}
+ /* Default timeout value implies timeout support */
+ if (set->timeout)
+ set->flags |= SET_F_TIMEOUT;
+
if (!(set->flags & SET_F_MAP))
return 0;
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);
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);
%token CONSTANT "constant"
%token INTERVAL "interval"
+%token TIMEOUT "timeout"
+%token GC_INTERVAL "gc-interval"
%token ELEMENTS "elements"
%token POLICY "policy"
$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;
set_flag : CONSTANT { $$ = SET_F_CONSTANT; }
| INTERVAL { $$ = SET_F_INTERVAL; }
+ | TIMEOUT { $$ = SET_F_TIMEOUT; }
;
map_block_alloc : /* empty */
{
const char *delim = "";
const char *type;
+ uint32_t flags;
type = set->flags & SET_F_MAP ? "map" : "set";
printf("%s%s", opts->tab, type);
}
}
- 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);
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);
}
"constant" { return CONSTANT; }
"interval" { return INTERVAL; }
+"timeout" { return TIMEOUT; }
+"gc-interval" { return GC_INTERVAL; }
"elements" { return ELEMENTS; }
"policy" { return POLICY; }