netfilter: nft_quota: add quota object update support

Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Fernando Fernandez Mancera 2019-08-26 13:40:53 +02:00 committed by Pablo Neira Ayuso
parent d62d0ba97b
commit 85936e56e9
1 changed files with 22 additions and 7 deletions

View File

@ -13,7 +13,7 @@
#include <net/netfilter/nf_tables.h>
struct nft_quota {
u64 quota;
atomic64_t quota;
unsigned long flags;
atomic64_t consumed;
};
@ -21,7 +21,8 @@ struct nft_quota {
static inline bool nft_overquota(struct nft_quota *priv,
const struct sk_buff *skb)
{
return atomic64_add_return(skb->len, &priv->consumed) >= priv->quota;
return atomic64_add_return(skb->len, &priv->consumed) >=
atomic64_read(&priv->quota);
}
static inline bool nft_quota_invert(struct nft_quota *priv)
@ -89,7 +90,7 @@ static int nft_quota_do_init(const struct nlattr * const tb[],
return -EOPNOTSUPP;
}
priv->quota = quota;
atomic64_set(&priv->quota, quota);
priv->flags = flags;
atomic64_set(&priv->consumed, consumed);
@ -105,10 +106,22 @@ static int nft_quota_obj_init(const struct nft_ctx *ctx,
return nft_quota_do_init(tb, priv);
}
static void nft_quota_obj_update(struct nft_object *obj,
struct nft_object *newobj)
{
struct nft_quota *newpriv = nft_obj_data(newobj);
struct nft_quota *priv = nft_obj_data(obj);
u64 newquota;
newquota = atomic64_read(&newpriv->quota);
atomic64_set(&priv->quota, newquota);
priv->flags = newpriv->flags;
}
static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
bool reset)
{
u64 consumed, consumed_cap;
u64 consumed, consumed_cap, quota;
u32 flags = priv->flags;
/* Since we inconditionally increment consumed quota for each packet
@ -116,14 +129,15 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
* userspace.
*/
consumed = atomic64_read(&priv->consumed);
if (consumed >= priv->quota) {
consumed_cap = priv->quota;
quota = atomic64_read(&priv->quota);
if (consumed >= quota) {
consumed_cap = quota;
flags |= NFT_QUOTA_F_DEPLETED;
} else {
consumed_cap = consumed;
}
if (nla_put_be64(skb, NFTA_QUOTA_BYTES, cpu_to_be64(priv->quota),
if (nla_put_be64(skb, NFTA_QUOTA_BYTES, cpu_to_be64(quota),
NFTA_QUOTA_PAD) ||
nla_put_be64(skb, NFTA_QUOTA_CONSUMED, cpu_to_be64(consumed_cap),
NFTA_QUOTA_PAD) ||
@ -155,6 +169,7 @@ static const struct nft_object_ops nft_quota_obj_ops = {
.init = nft_quota_obj_init,
.eval = nft_quota_obj_eval,
.dump = nft_quota_obj_dump,
.update = nft_quota_obj_update,
};
static struct nft_object_type nft_quota_obj_type __read_mostly = {