Skip to content

Commit 48f66c9

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: nft_ct: add byte/packet counter support
If the accounting extension isn't present, we'll return a counter value of 0. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent ce1e798 commit 48f66c9

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,8 @@ enum nft_ct_keys {
757757
NFT_CT_PROTO_SRC,
758758
NFT_CT_PROTO_DST,
759759
NFT_CT_LABELS,
760+
NFT_CT_PKTS,
761+
NFT_CT_BYTES,
760762
};
761763

762764
/**

net/netfilter/nft_ct.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/netfilter/nf_tables.h>
1717
#include <net/netfilter/nf_tables.h>
1818
#include <net/netfilter/nf_conntrack.h>
19+
#include <net/netfilter/nf_conntrack_acct.h>
1920
#include <net/netfilter/nf_conntrack_tuple.h>
2021
#include <net/netfilter/nf_conntrack_helper.h>
2122
#include <net/netfilter/nf_conntrack_ecache.h>
@@ -30,6 +31,18 @@ struct nft_ct {
3031
};
3132
};
3233

34+
static u64 nft_ct_get_eval_counter(const struct nf_conn_counter *c,
35+
enum nft_ct_keys k,
36+
enum ip_conntrack_dir d)
37+
{
38+
if (d < IP_CT_DIR_MAX)
39+
return k == NFT_CT_BYTES ? atomic64_read(&c[d].bytes) :
40+
atomic64_read(&c[d].packets);
41+
42+
return nft_ct_get_eval_counter(c, k, IP_CT_DIR_ORIGINAL) +
43+
nft_ct_get_eval_counter(c, k, IP_CT_DIR_REPLY);
44+
}
45+
3346
static void nft_ct_get_eval(const struct nft_expr *expr,
3447
struct nft_regs *regs,
3548
const struct nft_pktinfo *pkt)
@@ -114,6 +127,17 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
114127
NF_CT_LABELS_MAX_SIZE - size);
115128
return;
116129
}
130+
case NFT_CT_BYTES: /* fallthrough */
131+
case NFT_CT_PKTS: {
132+
const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
133+
u64 count = 0;
134+
135+
if (acct)
136+
count = nft_ct_get_eval_counter(acct->counter,
137+
priv->key, priv->dir);
138+
memcpy(dest, &count, sizeof(count));
139+
return;
140+
}
117141
#endif
118142
default:
119143
break;
@@ -291,6 +315,13 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
291315
return -EINVAL;
292316
len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all);
293317
break;
318+
case NFT_CT_BYTES:
319+
case NFT_CT_PKTS:
320+
/* no direction? return sum of original + reply */
321+
if (tb[NFTA_CT_DIRECTION] == NULL)
322+
priv->dir = IP_CT_DIR_MAX;
323+
len = sizeof(u64);
324+
break;
294325
default:
295326
return -EOPNOTSUPP;
296327
}
@@ -373,6 +404,13 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
373404
case NFT_CT_PROTO_DST:
374405
if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
375406
goto nla_put_failure;
407+
break;
408+
case NFT_CT_BYTES:
409+
case NFT_CT_PKTS:
410+
if (priv->dir < IP_CT_DIR_MAX &&
411+
nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
412+
goto nla_put_failure;
413+
break;
376414
default:
377415
break;
378416
}

0 commit comments

Comments
 (0)