| @@ -3873,6 +3873,7 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = { · 3872 unmodified lines |
| 3873 | 3873 | [NFTA_SET_ELEM_DATA] = { .type = NLA_NESTED }, |
| 3874 | 3874 | [NFTA_SET_ELEM_FLAGS] = { .type = NLA_U32 }, |
| 3875 | 3875 | [NFTA_SET_ELEM_TIMEOUT] = { .type = NLA_U64 }, |
| 3876 | + [NFTA_SET_ELEM_EXPIRATION] = { .type = NLA_U64 }, |
| 3876 | 3877 | [NFTA_SET_ELEM_USERDATA] = { .type = NLA_BINARY, |
| 3877 | 3878 | .len = NFT_USERDATA_MAXLEN }, |
| 3878 | 3879 | [NFTA_SET_ELEM_EXPR] = { .type = NLA_NESTED }, |
| @@ -4326,7 +4327,7 @@ static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx, · 447 unmodified lines |
| 4326 | 4327 | void *nft_set_elem_init(const struct nft_set *set, |
| 4327 | 4328 | const struct nft_set_ext_tmpl *tmpl, |
| 4328 | 4329 | const u32 *key, const u32 *data, |
| 4329 | | − u64 timeout, gfp_t gfp) |
| 4330 | + u64 timeout, u64 expiration, gfp_t gfp) |
| 4330 | 4331 | { |
| 4331 | 4332 | struct nft_set_ext *ext; |
| 4332 | 4333 | void *elem; |
| @@ -4341,9 +4342,11 @@ void *nft_set_elem_init(const struct nft_set *set, · 8 unmodified lines |
| 4341 | 4342 | memcpy(nft_set_ext_key(ext), key, set->klen); |
| 4342 | 4343 | if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA)) |
| 4343 | 4344 | memcpy(nft_set_ext_data(ext), data, set->dlen); |
| 4344 | | − if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) |
| 4345 | | − *nft_set_ext_expiration(ext) = |
| 4346 | | − get_jiffies_64() + timeout; |
| 4345 | + if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) { |
| 4346 | + *nft_set_ext_expiration(ext) = get_jiffies_64() + expiration; |
| 4347 | + if (expiration == 0) |
| 4348 | + *nft_set_ext_expiration(ext) += timeout; |
| 4349 | + } |
| 4347 | 4350 | if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT)) |
| 4348 | 4351 | *nft_set_ext_timeout(ext) = timeout; |
| 4349 | 4352 | |
| @@ -4408,6 +4411,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 58 unmodified lines |
| 4408 | 4411 | struct nft_trans *trans; |
| 4409 | 4412 | u32 flags = 0; |
| 4410 | 4413 | u64 timeout; |
| 4414 | + u64 expiration; |
| 4411 | 4415 | u8 ulen; |
| 4412 | 4416 | int err; |
| 4413 | 4417 | |
| @@ -4451,6 +4455,16 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 37 unmodified lines |
| 4451 | 4455 | timeout = set->timeout; |
| 4452 | 4456 | } |
| 4453 | 4457 | |
| 4458 | + expiration = 0; |
| 4459 | + if (nla[NFTA_SET_ELEM_EXPIRATION] != NULL) { |
| 4460 | + if (!(set->flags & NFT_SET_TIMEOUT)) |
| 4461 | + return -EINVAL; |
| 4462 | + err = nf_msecs_to_jiffies64(nla[NFTA_SET_ELEM_EXPIRATION], |
| 4463 | + &expiration); |
| 4464 | + if (err) |
| 4465 | + return err; |
| 4466 | + } |
| 4467 | + |
| 4454 | 4468 | err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &d1, |
| 4455 | 4469 | nla[NFTA_SET_ELEM_KEY]); |
| 4456 | 4470 | if (err < 0) |
| @@ -4533,7 +4547,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 76 unmodified lines |
| 4533 | 4547 | |
| 4534 | 4548 | err = -ENOMEM; |
| 4535 | 4549 | elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, data.data, |
| 4536 | | − timeout, GFP_KERNEL); |
| 4550 | + timeout, expiration, GFP_KERNEL); |
| 4537 | 4551 | if (elem.priv == NULL) |
| 4538 | 4552 | goto err3; |
| 4539 | 4553 | |
| @@ -4735,7 +4749,7 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, · 195 unmodified lines |
| 4735 | 4749 | |
| 4736 | 4750 | err = -ENOMEM; |
| 4737 | 4751 | elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, NULL, 0, |
| 4738 | | − GFP_KERNEL); |
| 4752 | + 0, GFP_KERNEL); |
| 4739 | 4753 | if (elem.priv == NULL) |
| 4740 | 4754 | goto err2; |
| 4741 | 4755 | |