netfilter: nf_conntrack: use atomic64 for accounting counters
We can use atomic64_t infrastructure to avoid taking a spinlock in fast path, and remove inaccuracies while reading values in ctnetlink_dump_counters() and connbytes_mt() on 32bit arches. Suggested by Pablo. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
committed by
Pablo Neira Ayuso
parent
76ad94fc5d
commit
b3e0bfa71b
@@ -15,8 +15,8 @@
|
|||||||
#include <net/netfilter/nf_conntrack_extend.h>
|
#include <net/netfilter/nf_conntrack_extend.h>
|
||||||
|
|
||||||
struct nf_conn_counter {
|
struct nf_conn_counter {
|
||||||
u_int64_t packets;
|
atomic64_t packets;
|
||||||
u_int64_t bytes;
|
atomic64_t bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
|
@@ -46,8 +46,8 @@ seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return seq_printf(s, "packets=%llu bytes=%llu ",
|
return seq_printf(s, "packets=%llu bytes=%llu ",
|
||||||
(unsigned long long)acct[dir].packets,
|
(unsigned long long)atomic64_read(&acct[dir].packets),
|
||||||
(unsigned long long)acct[dir].bytes);
|
(unsigned long long)atomic64_read(&acct[dir].bytes));
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(seq_print_acct);
|
EXPORT_SYMBOL_GPL(seq_print_acct);
|
||||||
|
|
||||||
|
@@ -1044,10 +1044,8 @@ acct:
|
|||||||
|
|
||||||
acct = nf_conn_acct_find(ct);
|
acct = nf_conn_acct_find(ct);
|
||||||
if (acct) {
|
if (acct) {
|
||||||
spin_lock_bh(&ct->lock);
|
atomic64_inc(&acct[CTINFO2DIR(ctinfo)].packets);
|
||||||
acct[CTINFO2DIR(ctinfo)].packets++;
|
atomic64_add(skb->len, &acct[CTINFO2DIR(ctinfo)].bytes);
|
||||||
acct[CTINFO2DIR(ctinfo)].bytes += skb->len;
|
|
||||||
spin_unlock_bh(&ct->lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1063,11 +1061,9 @@ bool __nf_ct_kill_acct(struct nf_conn *ct,
|
|||||||
|
|
||||||
acct = nf_conn_acct_find(ct);
|
acct = nf_conn_acct_find(ct);
|
||||||
if (acct) {
|
if (acct) {
|
||||||
spin_lock_bh(&ct->lock);
|
atomic64_inc(&acct[CTINFO2DIR(ctinfo)].packets);
|
||||||
acct[CTINFO2DIR(ctinfo)].packets++;
|
atomic64_add(skb->len - skb_network_offset(skb),
|
||||||
acct[CTINFO2DIR(ctinfo)].bytes +=
|
&acct[CTINFO2DIR(ctinfo)].bytes);
|
||||||
skb->len - skb_network_offset(skb);
|
|
||||||
spin_unlock_bh(&ct->lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -219,9 +219,9 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
|
|||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS,
|
NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS,
|
||||||
cpu_to_be64(acct[dir].packets));
|
cpu_to_be64(atomic64_read(&acct[dir].packets)));
|
||||||
NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES,
|
NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES,
|
||||||
cpu_to_be64(acct[dir].bytes));
|
cpu_to_be64(atomic64_read(&acct[dir].bytes)));
|
||||||
|
|
||||||
nla_nest_end(skb, nest_count);
|
nla_nest_end(skb, nest_count);
|
||||||
|
|
||||||
@@ -720,8 +720,12 @@ restart:
|
|||||||
struct nf_conn_counter *acct;
|
struct nf_conn_counter *acct;
|
||||||
|
|
||||||
acct = nf_conn_acct_find(ct);
|
acct = nf_conn_acct_find(ct);
|
||||||
if (acct)
|
if (acct) {
|
||||||
memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]));
|
atomic64_set(&acct[IP_CT_DIR_ORIGINAL].bytes, 0);
|
||||||
|
atomic64_set(&acct[IP_CT_DIR_ORIGINAL].packets, 0);
|
||||||
|
atomic64_set(&acct[IP_CT_DIR_REPLY].bytes, 0);
|
||||||
|
atomic64_set(&acct[IP_CT_DIR_REPLY].packets, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cb->args[1]) {
|
if (cb->args[1]) {
|
||||||
|
@@ -40,46 +40,46 @@ connbytes_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
|||||||
case XT_CONNBYTES_PKTS:
|
case XT_CONNBYTES_PKTS:
|
||||||
switch (sinfo->direction) {
|
switch (sinfo->direction) {
|
||||||
case XT_CONNBYTES_DIR_ORIGINAL:
|
case XT_CONNBYTES_DIR_ORIGINAL:
|
||||||
what = counters[IP_CT_DIR_ORIGINAL].packets;
|
what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
|
||||||
break;
|
break;
|
||||||
case XT_CONNBYTES_DIR_REPLY:
|
case XT_CONNBYTES_DIR_REPLY:
|
||||||
what = counters[IP_CT_DIR_REPLY].packets;
|
what = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
|
||||||
break;
|
break;
|
||||||
case XT_CONNBYTES_DIR_BOTH:
|
case XT_CONNBYTES_DIR_BOTH:
|
||||||
what = counters[IP_CT_DIR_ORIGINAL].packets;
|
what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
|
||||||
what += counters[IP_CT_DIR_REPLY].packets;
|
what += atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XT_CONNBYTES_BYTES:
|
case XT_CONNBYTES_BYTES:
|
||||||
switch (sinfo->direction) {
|
switch (sinfo->direction) {
|
||||||
case XT_CONNBYTES_DIR_ORIGINAL:
|
case XT_CONNBYTES_DIR_ORIGINAL:
|
||||||
what = counters[IP_CT_DIR_ORIGINAL].bytes;
|
what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
|
||||||
break;
|
break;
|
||||||
case XT_CONNBYTES_DIR_REPLY:
|
case XT_CONNBYTES_DIR_REPLY:
|
||||||
what = counters[IP_CT_DIR_REPLY].bytes;
|
what = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
|
||||||
break;
|
break;
|
||||||
case XT_CONNBYTES_DIR_BOTH:
|
case XT_CONNBYTES_DIR_BOTH:
|
||||||
what = counters[IP_CT_DIR_ORIGINAL].bytes;
|
what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
|
||||||
what += counters[IP_CT_DIR_REPLY].bytes;
|
what += atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XT_CONNBYTES_AVGPKT:
|
case XT_CONNBYTES_AVGPKT:
|
||||||
switch (sinfo->direction) {
|
switch (sinfo->direction) {
|
||||||
case XT_CONNBYTES_DIR_ORIGINAL:
|
case XT_CONNBYTES_DIR_ORIGINAL:
|
||||||
bytes = counters[IP_CT_DIR_ORIGINAL].bytes;
|
bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
|
||||||
pkts = counters[IP_CT_DIR_ORIGINAL].packets;
|
pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
|
||||||
break;
|
break;
|
||||||
case XT_CONNBYTES_DIR_REPLY:
|
case XT_CONNBYTES_DIR_REPLY:
|
||||||
bytes = counters[IP_CT_DIR_REPLY].bytes;
|
bytes = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
|
||||||
pkts = counters[IP_CT_DIR_REPLY].packets;
|
pkts = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
|
||||||
break;
|
break;
|
||||||
case XT_CONNBYTES_DIR_BOTH:
|
case XT_CONNBYTES_DIR_BOTH:
|
||||||
bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
|
bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes) +
|
||||||
counters[IP_CT_DIR_REPLY].bytes;
|
atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
|
||||||
pkts = counters[IP_CT_DIR_ORIGINAL].packets +
|
pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets) +
|
||||||
counters[IP_CT_DIR_REPLY].packets;
|
atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (pkts != 0)
|
if (pkts != 0)
|
||||||
|
Reference in New Issue
Block a user