1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
5 * Development of this code funded by Astaro AG (http://www.astaro.com/)
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/spinlock.h>
12 #include <linux/netlink.h>
13 #include <linux/netfilter.h>
14 #include <linux/netfilter/nf_tables.h>
15 #include <net/netfilter/nf_tables.h>
23 struct nft_limit_priv
{
24 struct nft_limit
*limit
;
32 static inline bool nft_limit_eval(struct nft_limit_priv
*priv
, u64 cost
)
37 spin_lock_bh(&priv
->limit
->lock
);
39 tokens
= priv
->limit
->tokens
+ now
- priv
->limit
->last
;
40 if (tokens
> priv
->tokens_max
)
41 tokens
= priv
->tokens_max
;
43 priv
->limit
->last
= now
;
44 delta
= tokens
- cost
;
46 priv
->limit
->tokens
= delta
;
47 spin_unlock_bh(&priv
->limit
->lock
);
50 priv
->limit
->tokens
= tokens
;
51 spin_unlock_bh(&priv
->limit
->lock
);
55 /* Use same default as in iptables. */
56 #define NFT_LIMIT_PKT_BURST_DEFAULT 5
58 static int nft_limit_init(struct nft_limit_priv
*priv
,
59 const struct nlattr
* const tb
[], bool pkts
)
61 u64 unit
, tokens
, rate_with_burst
;
64 if (tb
[NFTA_LIMIT_RATE
] == NULL
||
65 tb
[NFTA_LIMIT_UNIT
] == NULL
)
68 priv
->rate
= be64_to_cpu(nla_get_be64(tb
[NFTA_LIMIT_RATE
]));
72 unit
= be64_to_cpu(nla_get_be64(tb
[NFTA_LIMIT_UNIT
]));
73 if (check_mul_overflow(unit
, NSEC_PER_SEC
, &priv
->nsecs
))
76 if (tb
[NFTA_LIMIT_BURST
])
77 priv
->burst
= ntohl(nla_get_be32(tb
[NFTA_LIMIT_BURST
]));
79 if (pkts
&& priv
->burst
== 0)
80 priv
->burst
= NFT_LIMIT_PKT_BURST_DEFAULT
;
82 if (check_add_overflow(priv
->rate
, priv
->burst
, &rate_with_burst
))
86 u64 tmp
= div64_u64(priv
->nsecs
, priv
->rate
);
88 if (check_mul_overflow(tmp
, priv
->burst
, &tokens
))
93 /* The token bucket size limits the number of tokens can be
94 * accumulated. tokens_max specifies the bucket size.
95 * tokens_max = unit * (rate + burst) / rate.
97 if (check_mul_overflow(priv
->nsecs
, rate_with_burst
, &tmp
))
100 tokens
= div64_u64(tmp
, priv
->rate
);
103 if (tb
[NFTA_LIMIT_FLAGS
]) {
104 u32 flags
= ntohl(nla_get_be32(tb
[NFTA_LIMIT_FLAGS
]));
106 if (flags
& ~NFT_LIMIT_F_INV
)
109 if (flags
& NFT_LIMIT_F_INV
)
113 priv
->limit
= kmalloc(sizeof(*priv
->limit
), GFP_KERNEL_ACCOUNT
);
117 priv
->limit
->tokens
= tokens
;
118 priv
->tokens_max
= priv
->limit
->tokens
;
119 priv
->invert
= invert
;
120 priv
->limit
->last
= ktime_get_ns();
121 spin_lock_init(&priv
->limit
->lock
);
126 static int nft_limit_dump(struct sk_buff
*skb
, const struct nft_limit_priv
*priv
,
127 enum nft_limit_type type
)
129 u32 flags
= priv
->invert
? NFT_LIMIT_F_INV
: 0;
130 u64 secs
= div_u64(priv
->nsecs
, NSEC_PER_SEC
);
132 if (nla_put_be64(skb
, NFTA_LIMIT_RATE
, cpu_to_be64(priv
->rate
),
134 nla_put_be64(skb
, NFTA_LIMIT_UNIT
, cpu_to_be64(secs
),
136 nla_put_be32(skb
, NFTA_LIMIT_BURST
, htonl(priv
->burst
)) ||
137 nla_put_be32(skb
, NFTA_LIMIT_TYPE
, htonl(type
)) ||
138 nla_put_be32(skb
, NFTA_LIMIT_FLAGS
, htonl(flags
)))
139 goto nla_put_failure
;
146 static void nft_limit_destroy(const struct nft_ctx
*ctx
,
147 const struct nft_limit_priv
*priv
)
152 static int nft_limit_clone(struct nft_limit_priv
*priv_dst
,
153 const struct nft_limit_priv
*priv_src
, gfp_t gfp
)
155 priv_dst
->tokens_max
= priv_src
->tokens_max
;
156 priv_dst
->rate
= priv_src
->rate
;
157 priv_dst
->nsecs
= priv_src
->nsecs
;
158 priv_dst
->burst
= priv_src
->burst
;
159 priv_dst
->invert
= priv_src
->invert
;
161 priv_dst
->limit
= kmalloc(sizeof(*priv_dst
->limit
), gfp
);
162 if (!priv_dst
->limit
)
165 spin_lock_init(&priv_dst
->limit
->lock
);
166 priv_dst
->limit
->tokens
= priv_src
->tokens_max
;
167 priv_dst
->limit
->last
= ktime_get_ns();
172 struct nft_limit_priv_pkts
{
173 struct nft_limit_priv limit
;
177 static void nft_limit_pkts_eval(const struct nft_expr
*expr
,
178 struct nft_regs
*regs
,
179 const struct nft_pktinfo
*pkt
)
181 struct nft_limit_priv_pkts
*priv
= nft_expr_priv(expr
);
183 if (nft_limit_eval(&priv
->limit
, priv
->cost
))
184 regs
->verdict
.code
= NFT_BREAK
;
187 static const struct nla_policy nft_limit_policy
[NFTA_LIMIT_MAX
+ 1] = {
188 [NFTA_LIMIT_RATE
] = { .type
= NLA_U64
},
189 [NFTA_LIMIT_UNIT
] = { .type
= NLA_U64
},
190 [NFTA_LIMIT_BURST
] = { .type
= NLA_U32
},
191 [NFTA_LIMIT_TYPE
] = { .type
= NLA_U32
},
192 [NFTA_LIMIT_FLAGS
] = { .type
= NLA_U32
},
195 static int nft_limit_pkts_init(const struct nft_ctx
*ctx
,
196 const struct nft_expr
*expr
,
197 const struct nlattr
* const tb
[])
199 struct nft_limit_priv_pkts
*priv
= nft_expr_priv(expr
);
202 err
= nft_limit_init(&priv
->limit
, tb
, true);
206 priv
->cost
= div64_u64(priv
->limit
.nsecs
, priv
->limit
.rate
);
210 static int nft_limit_pkts_dump(struct sk_buff
*skb
,
211 const struct nft_expr
*expr
, bool reset
)
213 const struct nft_limit_priv_pkts
*priv
= nft_expr_priv(expr
);
215 return nft_limit_dump(skb
, &priv
->limit
, NFT_LIMIT_PKTS
);
218 static void nft_limit_pkts_destroy(const struct nft_ctx
*ctx
,
219 const struct nft_expr
*expr
)
221 const struct nft_limit_priv_pkts
*priv
= nft_expr_priv(expr
);
223 nft_limit_destroy(ctx
, &priv
->limit
);
226 static int nft_limit_pkts_clone(struct nft_expr
*dst
, const struct nft_expr
*src
,
229 struct nft_limit_priv_pkts
*priv_dst
= nft_expr_priv(dst
);
230 struct nft_limit_priv_pkts
*priv_src
= nft_expr_priv(src
);
232 priv_dst
->cost
= priv_src
->cost
;
234 return nft_limit_clone(&priv_dst
->limit
, &priv_src
->limit
, gfp
);
237 static struct nft_expr_type nft_limit_type
;
238 static const struct nft_expr_ops nft_limit_pkts_ops
= {
239 .type
= &nft_limit_type
,
240 .size
= NFT_EXPR_SIZE(sizeof(struct nft_limit_priv_pkts
)),
241 .eval
= nft_limit_pkts_eval
,
242 .init
= nft_limit_pkts_init
,
243 .destroy
= nft_limit_pkts_destroy
,
244 .clone
= nft_limit_pkts_clone
,
245 .dump
= nft_limit_pkts_dump
,
246 .reduce
= NFT_REDUCE_READONLY
,
249 static void nft_limit_bytes_eval(const struct nft_expr
*expr
,
250 struct nft_regs
*regs
,
251 const struct nft_pktinfo
*pkt
)
253 struct nft_limit_priv
*priv
= nft_expr_priv(expr
);
254 u64 cost
= div64_u64(priv
->nsecs
* pkt
->skb
->len
, priv
->rate
);
256 if (nft_limit_eval(priv
, cost
))
257 regs
->verdict
.code
= NFT_BREAK
;
260 static int nft_limit_bytes_init(const struct nft_ctx
*ctx
,
261 const struct nft_expr
*expr
,
262 const struct nlattr
* const tb
[])
264 struct nft_limit_priv
*priv
= nft_expr_priv(expr
);
266 return nft_limit_init(priv
, tb
, false);
269 static int nft_limit_bytes_dump(struct sk_buff
*skb
,
270 const struct nft_expr
*expr
, bool reset
)
272 const struct nft_limit_priv
*priv
= nft_expr_priv(expr
);
274 return nft_limit_dump(skb
, priv
, NFT_LIMIT_PKT_BYTES
);
277 static void nft_limit_bytes_destroy(const struct nft_ctx
*ctx
,
278 const struct nft_expr
*expr
)
280 const struct nft_limit_priv
*priv
= nft_expr_priv(expr
);
282 nft_limit_destroy(ctx
, priv
);
285 static int nft_limit_bytes_clone(struct nft_expr
*dst
, const struct nft_expr
*src
,
288 struct nft_limit_priv
*priv_dst
= nft_expr_priv(dst
);
289 struct nft_limit_priv
*priv_src
= nft_expr_priv(src
);
291 return nft_limit_clone(priv_dst
, priv_src
, gfp
);
294 static const struct nft_expr_ops nft_limit_bytes_ops
= {
295 .type
= &nft_limit_type
,
296 .size
= NFT_EXPR_SIZE(sizeof(struct nft_limit_priv
)),
297 .eval
= nft_limit_bytes_eval
,
298 .init
= nft_limit_bytes_init
,
299 .dump
= nft_limit_bytes_dump
,
300 .clone
= nft_limit_bytes_clone
,
301 .destroy
= nft_limit_bytes_destroy
,
302 .reduce
= NFT_REDUCE_READONLY
,
305 static const struct nft_expr_ops
*
306 nft_limit_select_ops(const struct nft_ctx
*ctx
,
307 const struct nlattr
* const tb
[])
309 if (tb
[NFTA_LIMIT_TYPE
] == NULL
)
310 return &nft_limit_pkts_ops
;
312 switch (ntohl(nla_get_be32(tb
[NFTA_LIMIT_TYPE
]))) {
314 return &nft_limit_pkts_ops
;
315 case NFT_LIMIT_PKT_BYTES
:
316 return &nft_limit_bytes_ops
;
318 return ERR_PTR(-EOPNOTSUPP
);
321 static struct nft_expr_type nft_limit_type __read_mostly
= {
323 .select_ops
= nft_limit_select_ops
,
324 .policy
= nft_limit_policy
,
325 .maxattr
= NFTA_LIMIT_MAX
,
326 .flags
= NFT_EXPR_STATEFUL
,
327 .owner
= THIS_MODULE
,
330 static void nft_limit_obj_pkts_eval(struct nft_object
*obj
,
331 struct nft_regs
*regs
,
332 const struct nft_pktinfo
*pkt
)
334 struct nft_limit_priv_pkts
*priv
= nft_obj_data(obj
);
336 if (nft_limit_eval(&priv
->limit
, priv
->cost
))
337 regs
->verdict
.code
= NFT_BREAK
;
340 static int nft_limit_obj_pkts_init(const struct nft_ctx
*ctx
,
341 const struct nlattr
* const tb
[],
342 struct nft_object
*obj
)
344 struct nft_limit_priv_pkts
*priv
= nft_obj_data(obj
);
347 err
= nft_limit_init(&priv
->limit
, tb
, true);
351 priv
->cost
= div64_u64(priv
->limit
.nsecs
, priv
->limit
.rate
);
355 static int nft_limit_obj_pkts_dump(struct sk_buff
*skb
,
356 struct nft_object
*obj
,
359 const struct nft_limit_priv_pkts
*priv
= nft_obj_data(obj
);
361 return nft_limit_dump(skb
, &priv
->limit
, NFT_LIMIT_PKTS
);
364 static void nft_limit_obj_pkts_destroy(const struct nft_ctx
*ctx
,
365 struct nft_object
*obj
)
367 struct nft_limit_priv_pkts
*priv
= nft_obj_data(obj
);
369 nft_limit_destroy(ctx
, &priv
->limit
);
372 static struct nft_object_type nft_limit_obj_type
;
373 static const struct nft_object_ops nft_limit_obj_pkts_ops
= {
374 .type
= &nft_limit_obj_type
,
375 .size
= NFT_EXPR_SIZE(sizeof(struct nft_limit_priv_pkts
)),
376 .init
= nft_limit_obj_pkts_init
,
377 .destroy
= nft_limit_obj_pkts_destroy
,
378 .eval
= nft_limit_obj_pkts_eval
,
379 .dump
= nft_limit_obj_pkts_dump
,
382 static void nft_limit_obj_bytes_eval(struct nft_object
*obj
,
383 struct nft_regs
*regs
,
384 const struct nft_pktinfo
*pkt
)
386 struct nft_limit_priv
*priv
= nft_obj_data(obj
);
387 u64 cost
= div64_u64(priv
->nsecs
* pkt
->skb
->len
, priv
->rate
);
389 if (nft_limit_eval(priv
, cost
))
390 regs
->verdict
.code
= NFT_BREAK
;
393 static int nft_limit_obj_bytes_init(const struct nft_ctx
*ctx
,
394 const struct nlattr
* const tb
[],
395 struct nft_object
*obj
)
397 struct nft_limit_priv
*priv
= nft_obj_data(obj
);
399 return nft_limit_init(priv
, tb
, false);
402 static int nft_limit_obj_bytes_dump(struct sk_buff
*skb
,
403 struct nft_object
*obj
,
406 const struct nft_limit_priv
*priv
= nft_obj_data(obj
);
408 return nft_limit_dump(skb
, priv
, NFT_LIMIT_PKT_BYTES
);
411 static void nft_limit_obj_bytes_destroy(const struct nft_ctx
*ctx
,
412 struct nft_object
*obj
)
414 struct nft_limit_priv
*priv
= nft_obj_data(obj
);
416 nft_limit_destroy(ctx
, priv
);
419 static struct nft_object_type nft_limit_obj_type
;
420 static const struct nft_object_ops nft_limit_obj_bytes_ops
= {
421 .type
= &nft_limit_obj_type
,
422 .size
= sizeof(struct nft_limit_priv
),
423 .init
= nft_limit_obj_bytes_init
,
424 .destroy
= nft_limit_obj_bytes_destroy
,
425 .eval
= nft_limit_obj_bytes_eval
,
426 .dump
= nft_limit_obj_bytes_dump
,
429 static const struct nft_object_ops
*
430 nft_limit_obj_select_ops(const struct nft_ctx
*ctx
,
431 const struct nlattr
* const tb
[])
433 if (!tb
[NFTA_LIMIT_TYPE
])
434 return &nft_limit_obj_pkts_ops
;
436 switch (ntohl(nla_get_be32(tb
[NFTA_LIMIT_TYPE
]))) {
438 return &nft_limit_obj_pkts_ops
;
439 case NFT_LIMIT_PKT_BYTES
:
440 return &nft_limit_obj_bytes_ops
;
442 return ERR_PTR(-EOPNOTSUPP
);
445 static struct nft_object_type nft_limit_obj_type __read_mostly
= {
446 .select_ops
= nft_limit_obj_select_ops
,
447 .type
= NFT_OBJECT_LIMIT
,
448 .maxattr
= NFTA_LIMIT_MAX
,
449 .policy
= nft_limit_policy
,
450 .owner
= THIS_MODULE
,
453 static int __init
nft_limit_module_init(void)
457 err
= nft_register_obj(&nft_limit_obj_type
);
461 err
= nft_register_expr(&nft_limit_type
);
467 nft_unregister_obj(&nft_limit_obj_type
);
471 static void __exit
nft_limit_module_exit(void)
473 nft_unregister_expr(&nft_limit_type
);
474 nft_unregister_obj(&nft_limit_obj_type
);
477 module_init(nft_limit_module_init
);
478 module_exit(nft_limit_module_exit
);
480 MODULE_LICENSE("GPL");
481 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
482 MODULE_ALIAS_NFT_EXPR("limit");
483 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_LIMIT
);
484 MODULE_DESCRIPTION("nftables limit expression support");