netfilter: nft_quota: move stateful fields out of expression data

In preparation for the rule blob representation.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Pablo Neira Ayuso 2022-01-09 17:11:15 +01:00
parent 33a24de37e
commit ed0a0c60f0
1 changed files with 47 additions and 5 deletions

View File

@ -15,13 +15,13 @@
struct nft_quota { struct nft_quota {
atomic64_t quota; atomic64_t quota;
unsigned long flags; unsigned long flags;
atomic64_t consumed; atomic64_t *consumed;
}; };
static inline bool nft_overquota(struct nft_quota *priv, static inline bool nft_overquota(struct nft_quota *priv,
const struct sk_buff *skb) const struct sk_buff *skb)
{ {
return atomic64_add_return(skb->len, &priv->consumed) >= return atomic64_add_return(skb->len, priv->consumed) >=
atomic64_read(&priv->quota); atomic64_read(&priv->quota);
} }
@ -90,13 +90,23 @@ static int nft_quota_do_init(const struct nlattr * const tb[],
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
priv->consumed = kmalloc(sizeof(*priv->consumed), GFP_KERNEL);
if (!priv->consumed)
return -ENOMEM;
atomic64_set(&priv->quota, quota); atomic64_set(&priv->quota, quota);
priv->flags = flags; priv->flags = flags;
atomic64_set(&priv->consumed, consumed); atomic64_set(priv->consumed, consumed);
return 0; return 0;
} }
static void nft_quota_do_destroy(const struct nft_ctx *ctx,
struct nft_quota *priv)
{
kfree(priv->consumed);
}
static int nft_quota_obj_init(const struct nft_ctx *ctx, static int nft_quota_obj_init(const struct nft_ctx *ctx,
const struct nlattr * const tb[], const struct nlattr * const tb[],
struct nft_object *obj) struct nft_object *obj)
@ -128,7 +138,7 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
* that we see, don't go over the quota boundary in what we send to * that we see, don't go over the quota boundary in what we send to
* userspace. * userspace.
*/ */
consumed = atomic64_read(&priv->consumed); consumed = atomic64_read(priv->consumed);
quota = atomic64_read(&priv->quota); quota = atomic64_read(&priv->quota);
if (consumed >= quota) { if (consumed >= quota) {
consumed_cap = quota; consumed_cap = quota;
@ -145,7 +155,7 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
goto nla_put_failure; goto nla_put_failure;
if (reset) { if (reset) {
atomic64_sub(consumed, &priv->consumed); atomic64_sub(consumed, priv->consumed);
clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags); clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags);
} }
return 0; return 0;
@ -162,11 +172,20 @@ static int nft_quota_obj_dump(struct sk_buff *skb, struct nft_object *obj,
return nft_quota_do_dump(skb, priv, reset); return nft_quota_do_dump(skb, priv, reset);
} }
static void nft_quota_obj_destroy(const struct nft_ctx *ctx,
struct nft_object *obj)
{
struct nft_quota *priv = nft_obj_data(obj);
return nft_quota_do_destroy(ctx, priv);
}
static struct nft_object_type nft_quota_obj_type; static struct nft_object_type nft_quota_obj_type;
static const struct nft_object_ops nft_quota_obj_ops = { static const struct nft_object_ops nft_quota_obj_ops = {
.type = &nft_quota_obj_type, .type = &nft_quota_obj_type,
.size = sizeof(struct nft_quota), .size = sizeof(struct nft_quota),
.init = nft_quota_obj_init, .init = nft_quota_obj_init,
.destroy = nft_quota_obj_destroy,
.eval = nft_quota_obj_eval, .eval = nft_quota_obj_eval,
.dump = nft_quota_obj_dump, .dump = nft_quota_obj_dump,
.update = nft_quota_obj_update, .update = nft_quota_obj_update,
@ -205,12 +224,35 @@ static int nft_quota_dump(struct sk_buff *skb, const struct nft_expr *expr)
return nft_quota_do_dump(skb, priv, false); return nft_quota_do_dump(skb, priv, false);
} }
static void nft_quota_destroy(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
struct nft_quota *priv = nft_expr_priv(expr);
return nft_quota_do_destroy(ctx, priv);
}
static int nft_quota_clone(struct nft_expr *dst, const struct nft_expr *src)
{
struct nft_quota *priv_dst = nft_expr_priv(dst);
priv_dst->consumed = kmalloc(sizeof(*priv_dst->consumed), GFP_ATOMIC);
if (priv_dst->consumed)
return -ENOMEM;
atomic64_set(priv_dst->consumed, 0);
return 0;
}
static struct nft_expr_type nft_quota_type; static struct nft_expr_type nft_quota_type;
static const struct nft_expr_ops nft_quota_ops = { static const struct nft_expr_ops nft_quota_ops = {
.type = &nft_quota_type, .type = &nft_quota_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_quota)), .size = NFT_EXPR_SIZE(sizeof(struct nft_quota)),
.eval = nft_quota_eval, .eval = nft_quota_eval,
.init = nft_quota_init, .init = nft_quota_init,
.destroy = nft_quota_destroy,
.clone = nft_quota_clone,
.dump = nft_quota_dump, .dump = nft_quota_dump,
}; };