]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/netfilter/nft_limit.c
batman-adv: fix hardif_neigh refcount on queue_work() failure
[mirror_ubuntu-bionic-kernel.git] / net / netfilter / nft_limit.c
index a9fc298ef4c3a9be6c1a4b9fb65cacfd71c3dc46..72f13a1144dd6a88d508f33696aa0646fa79988b 100644 (file)
@@ -51,10 +51,13 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
        return !limit->invert;
 }
 
+/* Use same default as in iptables. */
+#define NFT_LIMIT_PKT_BURST_DEFAULT    5
+
 static int nft_limit_init(struct nft_limit *limit,
-                         const struct nlattr * const tb[])
+                         const struct nlattr * const tb[], bool pkts)
 {
-       u64 unit;
+       u64 unit, tokens;
 
        if (tb[NFTA_LIMIT_RATE] == NULL ||
            tb[NFTA_LIMIT_UNIT] == NULL)
@@ -68,18 +71,25 @@ static int nft_limit_init(struct nft_limit *limit,
 
        if (tb[NFTA_LIMIT_BURST])
                limit->burst = ntohl(nla_get_be32(tb[NFTA_LIMIT_BURST]));
-       else
-               limit->burst = 0;
+
+       if (pkts && limit->burst == 0)
+               limit->burst = NFT_LIMIT_PKT_BURST_DEFAULT;
 
        if (limit->rate + limit->burst < limit->rate)
                return -EOVERFLOW;
 
-       /* The token bucket size limits the number of tokens can be
-        * accumulated. tokens_max specifies the bucket size.
-        * tokens_max = unit * (rate + burst) / rate.
-        */
-       limit->tokens = div_u64(limit->nsecs * (limit->rate + limit->burst),
-                               limit->rate);
+       if (pkts) {
+               tokens = div_u64(limit->nsecs, limit->rate) * limit->burst;
+       } else {
+               /* The token bucket size limits the number of tokens can be
+                * accumulated. tokens_max specifies the bucket size.
+                * tokens_max = unit * (rate + burst) / rate.
+                */
+               tokens = div_u64(limit->nsecs * (limit->rate + limit->burst),
+                                limit->rate);
+       }
+
+       limit->tokens = tokens;
        limit->tokens_max = limit->tokens;
 
        if (tb[NFTA_LIMIT_FLAGS]) {
@@ -144,7 +154,7 @@ static int nft_limit_pkts_init(const struct nft_ctx *ctx,
        struct nft_limit_pkts *priv = nft_expr_priv(expr);
        int err;
 
-       err = nft_limit_init(&priv->limit, tb);
+       err = nft_limit_init(&priv->limit, tb, true);
        if (err < 0)
                return err;
 
@@ -185,7 +195,7 @@ static int nft_limit_bytes_init(const struct nft_ctx *ctx,
 {
        struct nft_limit *priv = nft_expr_priv(expr);
 
-       return nft_limit_init(priv, tb);
+       return nft_limit_init(priv, tb, false);
 }
 
 static int nft_limit_bytes_dump(struct sk_buff *skb,
@@ -246,7 +256,7 @@ static int nft_limit_obj_pkts_init(const struct nft_ctx *ctx,
        struct nft_limit_pkts *priv = nft_obj_data(obj);
        int err;
 
-       err = nft_limit_init(&priv->limit, tb);
+       err = nft_limit_init(&priv->limit, tb, true);
        if (err < 0)
                return err;
 
@@ -289,7 +299,7 @@ static int nft_limit_obj_bytes_init(const struct nft_ctx *ctx,
 {
        struct nft_limit *priv = nft_obj_data(obj);
 
-       return nft_limit_init(priv, tb);
+       return nft_limit_init(priv, tb, false);
 }
 
 static int nft_limit_obj_bytes_dump(struct sk_buff *skb,