@@ -2863,6 +2863,14 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
2863
2863
.len = sizeof (u8 ),
2864
2864
.align = __alignof__(u8 ),
2865
2865
},
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
+ },
2866
2874
};
2867
2875
EXPORT_SYMBOL_GPL (nft_set_ext_types );
2868
2876
@@ -2874,6 +2882,7 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
2874
2882
[NFTA_SET_ELEM_KEY ] = { .type = NLA_NESTED },
2875
2883
[NFTA_SET_ELEM_DATA ] = { .type = NLA_NESTED },
2876
2884
[NFTA_SET_ELEM_FLAGS ] = { .type = NLA_U32 },
2885
+ [NFTA_SET_ELEM_TIMEOUT ] = { .type = NLA_U64 },
2877
2886
};
2878
2887
2879
2888
static 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,
2935
2944
htonl (* nft_set_ext_flags (ext ))))
2936
2945
goto nla_put_failure ;
2937
2946
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
+
2938
2966
nla_nest_end (skb , nest );
2939
2967
return 0 ;
2940
2968
@@ -3158,7 +3186,7 @@ static void *nft_set_elem_init(const struct nft_set *set,
3158
3186
const struct nft_set_ext_tmpl * tmpl ,
3159
3187
const struct nft_data * key ,
3160
3188
const struct nft_data * data ,
3161
- gfp_t gfp )
3189
+ u64 timeout , gfp_t gfp )
3162
3190
{
3163
3191
struct nft_set_ext * ext ;
3164
3192
void * elem ;
@@ -3173,6 +3201,11 @@ static void *nft_set_elem_init(const struct nft_set *set,
3173
3201
memcpy (nft_set_ext_key (ext ), key , set -> klen );
3174
3202
if (nft_set_ext_exists (ext , NFT_SET_EXT_DATA ))
3175
3203
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 ;
3176
3209
3177
3210
return elem ;
3178
3211
}
@@ -3201,6 +3234,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3201
3234
struct nft_data data ;
3202
3235
enum nft_registers dreg ;
3203
3236
struct nft_trans * trans ;
3237
+ u64 timeout ;
3204
3238
u32 flags ;
3205
3239
int err ;
3206
3240
@@ -3241,6 +3275,15 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3241
3275
return - EINVAL ;
3242
3276
}
3243
3277
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
+
3244
3287
err = nft_data_init (ctx , & elem .key , & d1 , nla [NFTA_SET_ELEM_KEY ]);
3245
3288
if (err < 0 )
3246
3289
goto err1 ;
@@ -3249,6 +3292,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3249
3292
goto err2 ;
3250
3293
3251
3294
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
+ }
3252
3300
3253
3301
if (nla [NFTA_SET_ELEM_DATA ] != NULL ) {
3254
3302
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,
3277
3325
}
3278
3326
3279
3327
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 );
3281
3330
if (elem .priv == NULL )
3282
3331
goto err3 ;
3283
3332
0 commit comments