diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 66d32176314e..ad3183d06878 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -308,6 +308,9 @@ extern struct hlist_nulls_head *nf_conntrack_hash; extern unsigned int nf_conntrack_htable_size; extern seqcount_t nf_conntrack_generation; extern unsigned int nf_conntrack_max; +#ifdef CONFIG_ENABLE_SFE +extern unsigned int nf_conntrack_pkt_threshold; +#endif /* must be called with rcu read lock held */ static inline void diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h index 336014bf8868..3f354adb4d1e 100644 --- a/include/uapi/linux/netfilter/nf_conntrack_common.h +++ b/include/uapi/linux/netfilter/nf_conntrack_common.h @@ -131,10 +131,13 @@ enum ip_conntrack_events { IPCT_LABEL, /* new connlabel has been set */ IPCT_SYNPROXY, /* synproxy has been set */ #ifdef __KERNEL__ + IPCT_COUNTER, /* Packet counters have matched. */ __IPCT_MAX #endif }; +#define IPCT_COUNTER IPCT_COUNTER + enum ip_conntrack_expect_events { IPEXP_NEW, /* new expectation */ IPEXP_DESTROY, /* destroyed expectation */ diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 80ff416d4991..b8964418e66f 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -186,6 +186,12 @@ EXPORT_SYMBOL_GPL(nf_conntrack_htable_size); unsigned int nf_conntrack_max __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_max); seqcount_t nf_conntrack_generation __read_mostly; + +#ifdef CONFIG_ENABLE_SFE +unsigned int nf_conntrack_pkt_threshold __read_mostly; +EXPORT_SYMBOL(nf_conntrack_pkt_threshold); +#endif + static unsigned int nf_conntrack_hash_rnd __read_mostly; static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, @@ -1818,12 +1824,18 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, u32 extra_jiffies, bool do_acct) { + #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) bool (*nattype_ref_timer) (unsigned long nattype, unsigned long timeout_value); #endif +#ifdef CONFIG_ENABLE_SFE + struct nf_conn_acct *acct; + u64 pkts; +#endif + /* Only update if this is not a fixed timeout */ if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) goto acct; @@ -1843,8 +1855,32 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, #endif acct: +#ifdef CONFIG_ENABLE_SFE + if (do_acct) { + acct = nf_conn_acct_find(ct); + if (acct) { + struct nf_conn_counter *counter = acct->counter; + + atomic64_inc(&counter[CTINFO2DIR(ctinfo)].packets); + atomic64_add(skb->len, &counter + [CTINFO2DIR(ctinfo)].bytes); + + pkts = + atomic64_read(&counter[CTINFO2DIR(ctinfo)].packets) + + atomic64_read(&counter[!CTINFO2DIR(ctinfo)].packets); + /* Report if the packet threshold is reached. */ + if (nf_conntrack_pkt_threshold > 0 && + pkts == nf_conntrack_pkt_threshold) { + nf_conntrack_event_cache(IPCT_COUNTER, ct); + nf_conntrack_event_cache(IPCT_PROTOINFO, ct); + nf_ct_deliver_cached_events(ct); + } + } + } +#else if (do_acct) nf_ct_acct_update(ct, ctinfo, skb->len); +#endif } EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 835802cea270..76ff520d564d 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -788,6 +788,11 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) if (events & (1 << IPCT_SYNPROXY) && ctnetlink_dump_ct_synproxy(skb, ct) < 0) + +#ifdef CONFIG_ENABLE_SFE + if (events & (1 << IPCT_COUNTER) && + ctnetlink_dump_acct(skb, ct, 0) < 0) +#endif goto nla_put_failure; } diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 4912069627b6..dd7e890f9769 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -544,6 +544,9 @@ enum nf_ct_sysctl_index { NF_SYSCTL_CT_EXPECT_MAX, NF_SYSCTL_CT_ACCT, NF_SYSCTL_CT_HELPER, +#ifdef CONFIG_ENABLE_SFE + NF_SYSCTL_CT_PKT_THRESHOLD, +#endif #ifdef CONFIG_NF_CONNTRACK_EVENTS NF_SYSCTL_CT_EVENTS, #endif @@ -664,6 +667,16 @@ static struct ctl_table nf_ct_sysctl_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, }, +#ifdef CONFIG_ENABLE_SFE + [NF_SYSCTL_CT_PKT_THRESHOLD] = { + .procname = "nf_conntrack_pkt_threshold", + .data = &nf_conntrack_pkt_threshold, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, +#endif + #ifdef CONFIG_NF_CONNTRACK_EVENTS [NF_SYSCTL_CT_EVENTS] = { .procname = "nf_conntrack_events",