Skip to content

Commit

Permalink
netfilter: nf_tables: consolidate timeout extension for elements
Browse files Browse the repository at this point in the history
Expiration and timeout are stored in separated set element extensions,
but they are tightly coupled. Consolidate them in a single extension to
simplify and prepare for set element updates.

Signed-off-by: Pablo Neira Ayuso <[email protected]>
  • Loading branch information
ummakynes committed Sep 3, 2024
1 parent 73d3c04 commit 4c5daea
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 44 deletions.
18 changes: 8 additions & 10 deletions include/net/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,6 @@ void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set);
* @NFT_SET_EXT_DATA: mapping data
* @NFT_SET_EXT_FLAGS: element flags
* @NFT_SET_EXT_TIMEOUT: element timeout
* @NFT_SET_EXT_EXPIRATION: element expiration time
* @NFT_SET_EXT_USERDATA: user data associated with the element
* @NFT_SET_EXT_EXPRESSIONS: expressions associated with the element
* @NFT_SET_EXT_OBJREF: stateful object reference associated with element
Expand All @@ -699,7 +698,6 @@ enum nft_set_extensions {
NFT_SET_EXT_DATA,
NFT_SET_EXT_FLAGS,
NFT_SET_EXT_TIMEOUT,
NFT_SET_EXT_EXPIRATION,
NFT_SET_EXT_USERDATA,
NFT_SET_EXT_EXPRESSIONS,
NFT_SET_EXT_OBJREF,
Expand Down Expand Up @@ -811,14 +809,14 @@ static inline u8 *nft_set_ext_flags(const struct nft_set_ext *ext)
return nft_set_ext(ext, NFT_SET_EXT_FLAGS);
}

static inline u64 *nft_set_ext_timeout(const struct nft_set_ext *ext)
{
return nft_set_ext(ext, NFT_SET_EXT_TIMEOUT);
}
struct nft_timeout {
u64 timeout;
u64 expiration;
};

static inline u64 *nft_set_ext_expiration(const struct nft_set_ext *ext)
static inline struct nft_timeout *nft_set_ext_timeout(const struct nft_set_ext *ext)
{
return nft_set_ext(ext, NFT_SET_EXT_EXPIRATION);
return nft_set_ext(ext, NFT_SET_EXT_TIMEOUT);
}

static inline struct nft_userdata *nft_set_ext_userdata(const struct nft_set_ext *ext)
Expand All @@ -834,8 +832,8 @@ static inline struct nft_set_elem_expr *nft_set_ext_expr(const struct nft_set_ex
static inline bool __nft_set_elem_expired(const struct nft_set_ext *ext,
u64 tstamp)
{
return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) &&
time_after_eq64(tstamp, READ_ONCE(*nft_set_ext_expiration(ext)));
return nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) &&
time_after_eq64(tstamp, READ_ONCE(nft_set_ext_timeout(ext)->expiration));
}

static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
Expand Down
43 changes: 17 additions & 26 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -5694,12 +5694,8 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
.align = __alignof__(u8),
},
[NFT_SET_EXT_TIMEOUT] = {
.len = sizeof(u64),
.align = __alignof__(u64),
},
[NFT_SET_EXT_EXPIRATION] = {
.len = sizeof(u64),
.align = __alignof__(u64),
.len = sizeof(struct nft_timeout),
.align = __alignof__(struct nft_timeout),
},
[NFT_SET_EXT_USERDATA] = {
.len = sizeof(struct nft_userdata),
Expand Down Expand Up @@ -5818,16 +5814,16 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
htonl(*nft_set_ext_flags(ext))))
goto nla_put_failure;

if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) &&
nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT,
nf_jiffies64_to_msecs(*nft_set_ext_timeout(ext)),
NFTA_SET_ELEM_PAD))
goto nla_put_failure;

if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT)) {
u64 expires, now = get_jiffies_64();

expires = READ_ONCE(*nft_set_ext_expiration(ext));
if (nft_set_ext_timeout(ext)->timeout != READ_ONCE(set->timeout) &&
nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT,
nf_jiffies64_to_msecs(nft_set_ext_timeout(ext)->timeout),
NFTA_SET_ELEM_PAD))
goto nla_put_failure;

expires = READ_ONCE(nft_set_ext_timeout(ext)->expiration);
if (time_before64(now, expires))
expires -= now;
else
Expand Down Expand Up @@ -6499,13 +6495,14 @@ struct nft_elem_priv *nft_set_elem_init(const struct nft_set *set,
nft_set_ext_data(ext), data, set->dlen) < 0)
goto err_ext_check;

if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
*nft_set_ext_expiration(ext) = get_jiffies_64() + expiration;
if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT)) {
nft_set_ext_timeout(ext)->timeout = timeout;

if (expiration == 0)
*nft_set_ext_expiration(ext) += timeout;
expiration = timeout;

nft_set_ext_timeout(ext)->expiration = get_jiffies_64() + expiration;
}
if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT))
*nft_set_ext_timeout(ext) = timeout;

return elem;

Expand Down Expand Up @@ -7019,15 +7016,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
}

if (timeout > 0) {
err = nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION);
err = nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT);
if (err < 0)
goto err_parse_key_end;

if (timeout != set->timeout) {
err = nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT);
if (err < 0)
goto err_parse_key_end;
}
}

if (num_exprs) {
Expand Down
13 changes: 5 additions & 8 deletions net/netfilter/nft_dynset.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ void nft_dynset_eval(const struct nft_expr *expr,
if (set->ops->update(set, &regs->data[priv->sreg_key], nft_dynset_new,
expr, regs, &ext)) {
if (priv->op == NFT_DYNSET_OP_UPDATE &&
nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT)) {
timeout = priv->timeout ? : READ_ONCE(set->timeout);
WRITE_ONCE(*nft_set_ext_expiration(ext), get_jiffies_64() + timeout);
WRITE_ONCE(nft_set_ext_timeout(ext)->expiration, get_jiffies_64() + timeout);
}

nft_set_elem_update_expr(ext, regs, pkt);
Expand Down Expand Up @@ -312,12 +312,9 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
if (priv->num_exprs)
nft_dynset_ext_add_expr(priv);

if (set->flags & NFT_SET_TIMEOUT) {
if (timeout || READ_ONCE(set->timeout)) {
nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_TIMEOUT);
nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_EXPIRATION);
}
}
if (set->flags & NFT_SET_TIMEOUT &&
(timeout || READ_ONCE(set->timeout)))
nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_TIMEOUT);

priv->timeout = timeout;

Expand Down

0 comments on commit 4c5daea

Please sign in to comment.