1414#include <linux/netfilter/nf_tables.h>
1515#include <net/netfilter/nf_tables.h>
1616
17- struct nft_limit_priv {
17+ struct nft_limit {
1818 spinlock_t lock ;
1919 u64 last ;
2020 u64 tokens ;
21+ };
22+
23+ struct nft_limit_priv {
24+ struct nft_limit * limit ;
2125 u64 tokens_max ;
2226 u64 rate ;
2327 u64 nsecs ;
@@ -30,21 +34,21 @@ static inline bool nft_limit_eval(struct nft_limit_priv *priv, u64 cost)
3034 u64 now , tokens ;
3135 s64 delta ;
3236
33- spin_lock_bh (& priv -> lock );
37+ spin_lock_bh (& priv -> limit -> lock );
3438 now = ktime_get_ns ();
35- tokens = priv -> tokens + now - priv -> last ;
39+ tokens = priv -> limit -> tokens + now - priv -> limit -> last ;
3640 if (tokens > priv -> tokens_max )
3741 tokens = priv -> tokens_max ;
3842
39- priv -> last = now ;
43+ priv -> limit -> last = now ;
4044 delta = tokens - cost ;
4145 if (delta >= 0 ) {
42- priv -> tokens = delta ;
43- spin_unlock_bh (& priv -> lock );
46+ priv -> limit -> tokens = delta ;
47+ spin_unlock_bh (& priv -> limit -> lock );
4448 return priv -> invert ;
4549 }
46- priv -> tokens = tokens ;
47- spin_unlock_bh (& priv -> lock );
50+ priv -> limit -> tokens = tokens ;
51+ spin_unlock_bh (& priv -> limit -> lock );
4852 return !priv -> invert ;
4953}
5054
@@ -86,17 +90,21 @@ static int nft_limit_init(struct nft_limit_priv *priv,
8690 priv -> rate );
8791 }
8892
89- priv -> tokens = tokens ;
90- priv -> tokens_max = priv -> tokens ;
93+ priv -> limit = kmalloc (sizeof (* priv -> limit ), GFP_KERNEL );
94+ if (!priv -> limit )
95+ return - ENOMEM ;
96+
97+ priv -> limit -> tokens = tokens ;
98+ priv -> tokens_max = priv -> limit -> tokens ;
9199
92100 if (tb [NFTA_LIMIT_FLAGS ]) {
93101 u32 flags = ntohl (nla_get_be32 (tb [NFTA_LIMIT_FLAGS ]));
94102
95103 if (flags & NFT_LIMIT_F_INV )
96104 priv -> invert = true;
97105 }
98- priv -> last = ktime_get_ns ();
99- spin_lock_init (& priv -> lock );
106+ priv -> limit -> last = ktime_get_ns ();
107+ spin_lock_init (& priv -> limit -> lock );
100108
101109 return 0 ;
102110}
@@ -121,6 +129,32 @@ static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit_priv *priv
121129 return -1 ;
122130}
123131
132+ static void nft_limit_destroy (const struct nft_ctx * ctx ,
133+ const struct nft_limit_priv * priv )
134+ {
135+ kfree (priv -> limit );
136+ }
137+
138+ static int nft_limit_clone (struct nft_limit_priv * priv_dst ,
139+ const struct nft_limit_priv * priv_src )
140+ {
141+ priv_dst -> tokens_max = priv_src -> tokens_max ;
142+ priv_dst -> rate = priv_src -> rate ;
143+ priv_dst -> nsecs = priv_src -> nsecs ;
144+ priv_dst -> burst = priv_src -> burst ;
145+ priv_dst -> invert = priv_src -> invert ;
146+
147+ priv_dst -> limit = kmalloc (sizeof (* priv_dst -> limit ), GFP_ATOMIC );
148+ if (priv_dst -> limit )
149+ return - ENOMEM ;
150+
151+ spin_lock_init (& priv_dst -> limit -> lock );
152+ priv_dst -> limit -> tokens = priv_src -> tokens_max ;
153+ priv_dst -> limit -> last = ktime_get_ns ();
154+
155+ return 0 ;
156+ }
157+
124158struct nft_limit_priv_pkts {
125159 struct nft_limit_priv limit ;
126160 u64 cost ;
@@ -166,12 +200,30 @@ static int nft_limit_pkts_dump(struct sk_buff *skb, const struct nft_expr *expr)
166200 return nft_limit_dump (skb , & priv -> limit , NFT_LIMIT_PKTS );
167201}
168202
203+ static void nft_limit_pkts_destroy (const struct nft_ctx * ctx ,
204+ const struct nft_expr * expr )
205+ {
206+ const struct nft_limit_priv_pkts * priv = nft_expr_priv (expr );
207+
208+ nft_limit_destroy (ctx , & priv -> limit );
209+ }
210+
211+ static int nft_limit_pkts_clone (struct nft_expr * dst , const struct nft_expr * src )
212+ {
213+ struct nft_limit_priv_pkts * priv_dst = nft_expr_priv (dst );
214+ struct nft_limit_priv_pkts * priv_src = nft_expr_priv (src );
215+
216+ return nft_limit_clone (& priv_dst -> limit , & priv_src -> limit );
217+ }
218+
169219static struct nft_expr_type nft_limit_type ;
170220static const struct nft_expr_ops nft_limit_pkts_ops = {
171221 .type = & nft_limit_type ,
172222 .size = NFT_EXPR_SIZE (sizeof (struct nft_limit_priv_pkts )),
173223 .eval = nft_limit_pkts_eval ,
174224 .init = nft_limit_pkts_init ,
225+ .destroy = nft_limit_pkts_destroy ,
226+ .clone = nft_limit_pkts_clone ,
175227 .dump = nft_limit_pkts_dump ,
176228};
177229
@@ -203,12 +255,30 @@ static int nft_limit_bytes_dump(struct sk_buff *skb,
203255 return nft_limit_dump (skb , priv , NFT_LIMIT_PKT_BYTES );
204256}
205257
258+ static void nft_limit_bytes_destroy (const struct nft_ctx * ctx ,
259+ const struct nft_expr * expr )
260+ {
261+ const struct nft_limit_priv * priv = nft_expr_priv (expr );
262+
263+ nft_limit_destroy (ctx , priv );
264+ }
265+
266+ static int nft_limit_bytes_clone (struct nft_expr * dst , const struct nft_expr * src )
267+ {
268+ struct nft_limit_priv * priv_dst = nft_expr_priv (dst );
269+ struct nft_limit_priv * priv_src = nft_expr_priv (src );
270+
271+ return nft_limit_clone (priv_dst , priv_src );
272+ }
273+
206274static const struct nft_expr_ops nft_limit_bytes_ops = {
207275 .type = & nft_limit_type ,
208276 .size = NFT_EXPR_SIZE (sizeof (struct nft_limit_priv )),
209277 .eval = nft_limit_bytes_eval ,
210278 .init = nft_limit_bytes_init ,
211279 .dump = nft_limit_bytes_dump ,
280+ .clone = nft_limit_bytes_clone ,
281+ .destroy = nft_limit_bytes_destroy ,
212282};
213283
214284static const struct nft_expr_ops *
0 commit comments