@@ -2863,6 +2863,14 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
28632863 .len = sizeof (u8 ),
28642864 .align = __alignof__(u8 ),
28652865 },
2866+ [NFT_SET_EXT_TIMEOUT ] = {
2867+ .len = sizeof (u64 ),
2868+ .align = __alignof__(u64 ),
2869+ },
2870+ [NFT_SET_EXT_EXPIRATION ] = {
2871+ .len = sizeof (unsigned long ),
2872+ .align = __alignof__(unsigned long ),
2873+ },
28662874};
28672875EXPORT_SYMBOL_GPL (nft_set_ext_types );
28682876
@@ -2874,6 +2882,7 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
28742882 [NFTA_SET_ELEM_KEY ] = { .type = NLA_NESTED },
28752883 [NFTA_SET_ELEM_DATA ] = { .type = NLA_NESTED },
28762884 [NFTA_SET_ELEM_FLAGS ] = { .type = NLA_U32 },
2885+ [NFTA_SET_ELEM_TIMEOUT ] = { .type = NLA_U64 },
28772886};
28782887
28792888static const struct nla_policy nft_set_elem_list_policy [NFTA_SET_ELEM_LIST_MAX + 1 ] = {
@@ -2935,6 +2944,25 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
29352944 htonl (* nft_set_ext_flags (ext ))))
29362945 goto nla_put_failure ;
29372946
2947+ if (nft_set_ext_exists (ext , NFT_SET_EXT_TIMEOUT ) &&
2948+ nla_put_be64 (skb , NFTA_SET_ELEM_TIMEOUT ,
2949+ cpu_to_be64 (* nft_set_ext_timeout (ext ))))
2950+ goto nla_put_failure ;
2951+
2952+ if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPIRATION )) {
2953+ unsigned long expires , now = jiffies ;
2954+
2955+ expires = * nft_set_ext_expiration (ext );
2956+ if (time_before (now , expires ))
2957+ expires -= now ;
2958+ else
2959+ expires = 0 ;
2960+
2961+ if (nla_put_be64 (skb , NFTA_SET_ELEM_EXPIRATION ,
2962+ cpu_to_be64 (jiffies_to_msecs (expires ))))
2963+ goto nla_put_failure ;
2964+ }
2965+
29382966 nla_nest_end (skb , nest );
29392967 return 0 ;
29402968
@@ -3158,7 +3186,7 @@ static void *nft_set_elem_init(const struct nft_set *set,
31583186 const struct nft_set_ext_tmpl * tmpl ,
31593187 const struct nft_data * key ,
31603188 const struct nft_data * data ,
3161- gfp_t gfp )
3189+ u64 timeout , gfp_t gfp )
31623190{
31633191 struct nft_set_ext * ext ;
31643192 void * elem ;
@@ -3173,6 +3201,11 @@ static void *nft_set_elem_init(const struct nft_set *set,
31733201 memcpy (nft_set_ext_key (ext ), key , set -> klen );
31743202 if (nft_set_ext_exists (ext , NFT_SET_EXT_DATA ))
31753203 memcpy (nft_set_ext_data (ext ), data , set -> dlen );
3204+ if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPIRATION ))
3205+ * nft_set_ext_expiration (ext ) =
3206+ jiffies + msecs_to_jiffies (timeout );
3207+ if (nft_set_ext_exists (ext , NFT_SET_EXT_TIMEOUT ))
3208+ * nft_set_ext_timeout (ext ) = timeout ;
31763209
31773210 return elem ;
31783211}
@@ -3201,6 +3234,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
32013234 struct nft_data data ;
32023235 enum nft_registers dreg ;
32033236 struct nft_trans * trans ;
3237+ u64 timeout ;
32043238 u32 flags ;
32053239 int err ;
32063240
@@ -3241,6 +3275,15 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
32413275 return - EINVAL ;
32423276 }
32433277
3278+ timeout = 0 ;
3279+ if (nla [NFTA_SET_ELEM_TIMEOUT ] != NULL ) {
3280+ if (!(set -> flags & NFT_SET_TIMEOUT ))
3281+ return - EINVAL ;
3282+ timeout = be64_to_cpu (nla_get_be64 (nla [NFTA_SET_ELEM_TIMEOUT ]));
3283+ } else if (set -> flags & NFT_SET_TIMEOUT ) {
3284+ timeout = set -> timeout ;
3285+ }
3286+
32443287 err = nft_data_init (ctx , & elem .key , & d1 , nla [NFTA_SET_ELEM_KEY ]);
32453288 if (err < 0 )
32463289 goto err1 ;
@@ -3249,6 +3292,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
32493292 goto err2 ;
32503293
32513294 nft_set_ext_add (& tmpl , NFT_SET_EXT_KEY );
3295+ if (timeout > 0 ) {
3296+ nft_set_ext_add (& tmpl , NFT_SET_EXT_EXPIRATION );
3297+ if (timeout != set -> timeout )
3298+ nft_set_ext_add (& tmpl , NFT_SET_EXT_TIMEOUT );
3299+ }
32523300
32533301 if (nla [NFTA_SET_ELEM_DATA ] != NULL ) {
32543302 err = nft_data_init (ctx , & data , & d2 , nla [NFTA_SET_ELEM_DATA ]);
@@ -3277,7 +3325,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
32773325 }
32783326
32793327 err = - ENOMEM ;
3280- elem .priv = nft_set_elem_init (set , & tmpl , & elem .key , & data , GFP_KERNEL );
3328+ elem .priv = nft_set_elem_init (set , & tmpl , & elem .key , & data ,
3329+ timeout , GFP_KERNEL );
32813330 if (elem .priv == NULL )
32823331 goto err3 ;
32833332
0 commit comments