Skip to content

Commit

Permalink
netfilter: nft_quota: dump consumed quota
Browse files Browse the repository at this point in the history
Add a new attribute NFTA_QUOTA_CONSUMED that displays the amount of
quota that has been already consumed. This allows us to restore the
internal state of the quota object between reboots as well as to monitor
how wasted it is.

This patch changes the logic to account for the consumed bytes, instead
of the bytes that remain to be consumed.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Pablo Neira Ayuso committed Dec 7, 2016
1 parent c97d22e commit 795595f
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 5 deletions.
2 changes: 2 additions & 0 deletions include/uapi/linux/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -988,12 +988,14 @@ enum nft_quota_flags {
*
* @NFTA_QUOTA_BYTES: quota in bytes (NLA_U16)
* @NFTA_QUOTA_FLAGS: flags (NLA_U32)
* @NFTA_QUOTA_CONSUMED: quota already consumed in bytes (NLA_U64)
*/
enum nft_quota_attributes {
NFTA_QUOTA_UNSPEC,
NFTA_QUOTA_BYTES,
NFTA_QUOTA_FLAGS,
NFTA_QUOTA_PAD,
NFTA_QUOTA_CONSUMED,
__NFTA_QUOTA_MAX
};
#define NFTA_QUOTA_MAX (__NFTA_QUOTA_MAX - 1)
Expand Down
21 changes: 16 additions & 5 deletions net/netfilter/nft_quota.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@
struct nft_quota {
u64 quota;
bool invert;
atomic64_t remain;
atomic64_t consumed;
};

static inline bool nft_overquota(struct nft_quota *priv,
const struct nft_pktinfo *pkt)
const struct sk_buff *skb)
{
return atomic64_sub_return(pkt->skb->len, &priv->remain) < 0;
return atomic64_add_return(skb->len, &priv->consumed) >= priv->quota;
}

static inline void nft_quota_do_eval(struct nft_quota *priv,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
if (nft_overquota(priv, pkt) ^ priv->invert)
if (nft_overquota(priv, pkt->skb) ^ priv->invert)
regs->verdict.code = NFT_BREAK;
}

Expand Down Expand Up @@ -70,7 +70,7 @@ static int nft_quota_do_init(const struct nlattr * const tb[],

priv->quota = quota;
priv->invert = (flags & NFT_QUOTA_F_INV) ? true : false;
atomic64_set(&priv->remain, quota);
atomic64_set(&priv->consumed, 0);

return 0;
}
Expand All @@ -86,9 +86,20 @@ static int nft_quota_obj_init(const struct nlattr * const tb[],
static int nft_quota_do_dump(struct sk_buff *skb, const struct nft_quota *priv)
{
u32 flags = priv->invert ? NFT_QUOTA_F_INV : 0;
u64 consumed;

consumed = atomic64_read(&priv->consumed);
/* Since we inconditionally increment consumed quota for each packet
* that we see, don't go over the quota boundary in what we send to
* userspace.
*/
if (consumed > priv->quota)
consumed = priv->quota;

if (nla_put_be64(skb, NFTA_QUOTA_BYTES, cpu_to_be64(priv->quota),
NFTA_QUOTA_PAD) ||
nla_put_be64(skb, NFTA_QUOTA_CONSUMED, cpu_to_be64(consumed),
NFTA_QUOTA_PAD) ||
nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags)))
goto nla_put_failure;
return 0;
Expand Down

0 comments on commit 795595f

Please sign in to comment.