* [PATCH 1/4] netfilter: conntrack: don't report events on module removal
2009-05-02 14:18 [PATCH 0/4] conntrack event subsystem updates for 2.6.31 Pablo Neira Ayuso
@ 2009-05-02 14:18 ` Pablo Neira Ayuso
2009-05-02 14:19 ` [PATCH 2/4] netfilter: conntrack: remove events flags from userspace exposed file Pablo Neira Ayuso
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2009-05-02 14:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber
During the module removal there are no possible event listeners
since ctnetlink must be removed before to allow removing
nf_conntrack. This patch removes the event reporting for the
module removal case which is not of any use in the existing code.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_conntrack.h | 2 +-
net/netfilter/nf_conntrack_core.c | 15 ++++++++++-----
net/netfilter/nf_conntrack_netlink.c | 6 +++---
3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 6c3f964..f34d596 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -201,7 +201,7 @@ __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple);
extern void nf_conntrack_hash_insert(struct nf_conn *ct);
-extern void nf_conntrack_flush(struct net *net, u32 pid, int report);
+extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report);
extern bool nf_ct_get_tuplepr(const struct sk_buff *skb,
unsigned int nhoff, u_int16_t l3num,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 8020db6..f59c4ed 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1001,7 +1001,7 @@ struct __nf_ct_flush_report {
int report;
};
-static int kill_all(struct nf_conn *i, void *data)
+static int kill_report(struct nf_conn *i, void *data)
{
struct __nf_ct_flush_report *fr = (struct __nf_ct_flush_report *)data;
@@ -1013,6 +1013,11 @@ static int kill_all(struct nf_conn *i, void *data)
return 1;
}
+static int kill_all(struct nf_conn *i, void *data)
+{
+ return 1;
+}
+
void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size)
{
if (vmalloced)
@@ -1023,15 +1028,15 @@ void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size)
}
EXPORT_SYMBOL_GPL(nf_ct_free_hashtable);
-void nf_conntrack_flush(struct net *net, u32 pid, int report)
+void nf_conntrack_flush_report(struct net *net, u32 pid, int report)
{
struct __nf_ct_flush_report fr = {
.pid = pid,
.report = report,
};
- nf_ct_iterate_cleanup(net, kill_all, &fr);
+ nf_ct_iterate_cleanup(net, kill_report, &fr);
}
-EXPORT_SYMBOL_GPL(nf_conntrack_flush);
+EXPORT_SYMBOL_GPL(nf_conntrack_flush_report);
static void nf_conntrack_cleanup_init_net(void)
{
@@ -1045,7 +1050,7 @@ static void nf_conntrack_cleanup_net(struct net *net)
nf_ct_event_cache_flush(net);
nf_conntrack_ecache_fini(net);
i_see_dead_people:
- nf_conntrack_flush(net, 0, 0);
+ nf_ct_iterate_cleanup(net, kill_all, NULL);
if (atomic_read(&net->ct.count) != 0) {
schedule();
goto i_see_dead_people;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index f13fc57..fa2bd2a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -802,9 +802,9 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
else {
/* Flush the whole table */
- nf_conntrack_flush(&init_net,
- NETLINK_CB(skb).pid,
- nlmsg_report(nlh));
+ nf_conntrack_flush_report(&init_net,
+ NETLINK_CB(skb).pid,
+ nlmsg_report(nlh));
return 0;
}
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 2/4] netfilter: conntrack: remove events flags from userspace exposed file
2009-05-02 14:18 [PATCH 0/4] conntrack event subsystem updates for 2.6.31 Pablo Neira Ayuso
2009-05-02 14:18 ` [PATCH 1/4] netfilter: conntrack: don't report events on module removal Pablo Neira Ayuso
@ 2009-05-02 14:19 ` Pablo Neira Ayuso
2009-05-02 14:19 ` [PATCH 3/4] netfilter: conntrack: simplify event caching system Pablo Neira Ayuso
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2009-05-02 14:19 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber
This patch moves the event flags from linux/netfilter/nf_conntrack_common.h
to net/netfilter/nf_conntrack_ecache.h. This flags are not of any use
from userspace.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/linux/netfilter/nf_conntrack_common.h | 69 -------------------------
include/net/netfilter/nf_conntrack_ecache.h | 69 +++++++++++++++++++++++++
2 files changed, 69 insertions(+), 69 deletions(-)
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index 885cbe2..a8248ee 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -75,75 +75,6 @@ enum ip_conntrack_status {
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
};
-/* Connection tracking event bits */
-enum ip_conntrack_events
-{
- /* New conntrack */
- IPCT_NEW_BIT = 0,
- IPCT_NEW = (1 << IPCT_NEW_BIT),
-
- /* Expected connection */
- IPCT_RELATED_BIT = 1,
- IPCT_RELATED = (1 << IPCT_RELATED_BIT),
-
- /* Destroyed conntrack */
- IPCT_DESTROY_BIT = 2,
- IPCT_DESTROY = (1 << IPCT_DESTROY_BIT),
-
- /* Timer has been refreshed */
- IPCT_REFRESH_BIT = 3,
- IPCT_REFRESH = (1 << IPCT_REFRESH_BIT),
-
- /* Status has changed */
- IPCT_STATUS_BIT = 4,
- IPCT_STATUS = (1 << IPCT_STATUS_BIT),
-
- /* Update of protocol info */
- IPCT_PROTOINFO_BIT = 5,
- IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT),
-
- /* Volatile protocol info */
- IPCT_PROTOINFO_VOLATILE_BIT = 6,
- IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT),
-
- /* New helper for conntrack */
- IPCT_HELPER_BIT = 7,
- IPCT_HELPER = (1 << IPCT_HELPER_BIT),
-
- /* Update of helper info */
- IPCT_HELPINFO_BIT = 8,
- IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT),
-
- /* Volatile helper info */
- IPCT_HELPINFO_VOLATILE_BIT = 9,
- IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT),
-
- /* NAT info */
- IPCT_NATINFO_BIT = 10,
- IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
-
- /* Counter highest bit has been set, unused */
- IPCT_COUNTER_FILLING_BIT = 11,
- IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
-
- /* Mark is set */
- IPCT_MARK_BIT = 12,
- IPCT_MARK = (1 << IPCT_MARK_BIT),
-
- /* NAT sequence adjustment */
- IPCT_NATSEQADJ_BIT = 13,
- IPCT_NATSEQADJ = (1 << IPCT_NATSEQADJ_BIT),
-
- /* Secmark is set */
- IPCT_SECMARK_BIT = 14,
- IPCT_SECMARK = (1 << IPCT_SECMARK_BIT),
-};
-
-enum ip_conntrack_expect_events {
- IPEXP_NEW_BIT = 0,
- IPEXP_NEW = (1 << IPEXP_NEW_BIT),
-};
-
#ifdef __KERNEL__
struct ip_conntrack_stat
{
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 0ff0dc6..892b8cd 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -11,6 +11,75 @@
#include <net/net_namespace.h>
#include <net/netfilter/nf_conntrack_expect.h>
+/* Connection tracking event bits */
+enum ip_conntrack_events
+{
+ /* New conntrack */
+ IPCT_NEW_BIT = 0,
+ IPCT_NEW = (1 << IPCT_NEW_BIT),
+
+ /* Expected connection */
+ IPCT_RELATED_BIT = 1,
+ IPCT_RELATED = (1 << IPCT_RELATED_BIT),
+
+ /* Destroyed conntrack */
+ IPCT_DESTROY_BIT = 2,
+ IPCT_DESTROY = (1 << IPCT_DESTROY_BIT),
+
+ /* Timer has been refreshed */
+ IPCT_REFRESH_BIT = 3,
+ IPCT_REFRESH = (1 << IPCT_REFRESH_BIT),
+
+ /* Status has changed */
+ IPCT_STATUS_BIT = 4,
+ IPCT_STATUS = (1 << IPCT_STATUS_BIT),
+
+ /* Update of protocol info */
+ IPCT_PROTOINFO_BIT = 5,
+ IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT),
+
+ /* Volatile protocol info */
+ IPCT_PROTOINFO_VOLATILE_BIT = 6,
+ IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT),
+
+ /* New helper for conntrack */
+ IPCT_HELPER_BIT = 7,
+ IPCT_HELPER = (1 << IPCT_HELPER_BIT),
+
+ /* Update of helper info */
+ IPCT_HELPINFO_BIT = 8,
+ IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT),
+
+ /* Volatile helper info */
+ IPCT_HELPINFO_VOLATILE_BIT = 9,
+ IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT),
+
+ /* NAT info */
+ IPCT_NATINFO_BIT = 10,
+ IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
+
+ /* Counter highest bit has been set, unused */
+ IPCT_COUNTER_FILLING_BIT = 11,
+ IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
+
+ /* Mark is set */
+ IPCT_MARK_BIT = 12,
+ IPCT_MARK = (1 << IPCT_MARK_BIT),
+
+ /* NAT sequence adjustment */
+ IPCT_NATSEQADJ_BIT = 13,
+ IPCT_NATSEQADJ = (1 << IPCT_NATSEQADJ_BIT),
+
+ /* Secmark is set */
+ IPCT_SECMARK_BIT = 14,
+ IPCT_SECMARK = (1 << IPCT_SECMARK_BIT),
+};
+
+enum ip_conntrack_expect_events {
+ IPEXP_NEW_BIT = 0,
+ IPEXP_NEW = (1 << IPEXP_NEW_BIT),
+};
+
#ifdef CONFIG_NF_CONNTRACK_EVENTS
struct nf_conntrack_ecache {
struct nf_conn *ct;
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 3/4] netfilter: conntrack: simplify event caching system
2009-05-02 14:18 [PATCH 0/4] conntrack event subsystem updates for 2.6.31 Pablo Neira Ayuso
2009-05-02 14:18 ` [PATCH 1/4] netfilter: conntrack: don't report events on module removal Pablo Neira Ayuso
2009-05-02 14:19 ` [PATCH 2/4] netfilter: conntrack: remove events flags from userspace exposed file Pablo Neira Ayuso
@ 2009-05-02 14:19 ` Pablo Neira Ayuso
2009-05-02 14:20 ` [PATCH 4/4] netfilter: conntrack: replace notify chain by function pointer Pablo Neira Ayuso
2009-05-06 13:36 ` [PATCH 0/4] conntrack event subsystem updates for 2.6.31 Pablo Neira Ayuso
4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2009-05-02 14:19 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber
This patch simplifies the conntrack event caching system by removing
several events:
* IPCT_[*]_VOLATILE, IPCT_HELPINFO and IPCT_NATINFO has been deleted
since the have no clients.
* IPCT_COUNTER_FILLING which is a leftover of the 32-bits counter
days.
* IPCT_REFRESH which is not of any use since we always include the
timeout in the messages.
After this patch, the existing events are:
* IPCT_NEW, IPCT_RELATED and IPCT_DESTROY, that are used to identify
addition and deletion of entries.
* IPCT_STATUS, that notes that the status bits have changes,
eg. IPS_SEEN_REPLY and IPS_ASSURED.
* IPCT_PROTOINFO, that reports that internal protocol information has
changed, eg. the TCP, DCCP and SCTP protocol state.
* IPCT_HELPER, that a helper has been assigned or unassigned to this
entry.
* IPCT_MARK and IPCT_SECMARK, that reports that the mark has changed, this
covers the case when a mark is set to zero.
* IPCT_NATSEQADJ, to report that there's updates in the NAT sequence
adjustment.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_conntrack_ecache.h | 36 ++++--------------------
net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 1 -
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 1 -
net/netfilter/nf_conntrack_core.c | 14 +--------
net/netfilter/nf_conntrack_ftp.c | 2 -
net/netfilter/nf_conntrack_netlink.c | 1 -
net/netfilter/nf_conntrack_proto_tcp.c | 1 -
7 files changed, 7 insertions(+), 49 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 892b8cd..2e17a2d 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -26,52 +26,28 @@ enum ip_conntrack_events
IPCT_DESTROY_BIT = 2,
IPCT_DESTROY = (1 << IPCT_DESTROY_BIT),
- /* Timer has been refreshed */
- IPCT_REFRESH_BIT = 3,
- IPCT_REFRESH = (1 << IPCT_REFRESH_BIT),
-
/* Status has changed */
- IPCT_STATUS_BIT = 4,
+ IPCT_STATUS_BIT = 3,
IPCT_STATUS = (1 << IPCT_STATUS_BIT),
/* Update of protocol info */
- IPCT_PROTOINFO_BIT = 5,
+ IPCT_PROTOINFO_BIT = 4,
IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT),
- /* Volatile protocol info */
- IPCT_PROTOINFO_VOLATILE_BIT = 6,
- IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT),
-
/* New helper for conntrack */
- IPCT_HELPER_BIT = 7,
+ IPCT_HELPER_BIT = 5,
IPCT_HELPER = (1 << IPCT_HELPER_BIT),
- /* Update of helper info */
- IPCT_HELPINFO_BIT = 8,
- IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT),
-
- /* Volatile helper info */
- IPCT_HELPINFO_VOLATILE_BIT = 9,
- IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT),
-
- /* NAT info */
- IPCT_NATINFO_BIT = 10,
- IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
-
- /* Counter highest bit has been set, unused */
- IPCT_COUNTER_FILLING_BIT = 11,
- IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
-
/* Mark is set */
- IPCT_MARK_BIT = 12,
+ IPCT_MARK_BIT = 6,
IPCT_MARK = (1 << IPCT_MARK_BIT),
/* NAT sequence adjustment */
- IPCT_NATSEQADJ_BIT = 13,
+ IPCT_NATSEQADJ_BIT = 7,
IPCT_NATSEQADJ = (1 << IPCT_NATSEQADJ_BIT),
/* Secmark is set */
- IPCT_SECMARK_BIT = 14,
+ IPCT_SECMARK_BIT = 8,
IPCT_SECMARK = (1 << IPCT_SECMARK_BIT),
};
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 23b2c2e..c6ab3d9 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -91,7 +91,6 @@ static int icmp_packet(struct nf_conn *ct,
nf_ct_kill_acct(ct, ctinfo, skb);
} else {
atomic_inc(&ct->proto.icmp.count);
- nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout);
}
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 9903227..a0acd96 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -104,7 +104,6 @@ static int icmpv6_packet(struct nf_conn *ct,
nf_ct_kill_acct(ct, ctinfo, skb);
} else {
atomic_inc(&ct->proto.icmp.count);
- nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout);
}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index f59c4ed..b54c234 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -398,11 +398,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
help = nfct_help(ct);
if (help && help->helper)
nf_conntrack_event_cache(IPCT_HELPER, ct);
-#ifdef CONFIG_NF_NAT_NEEDED
- if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
- test_bit(IPS_DST_NAT_DONE_BIT, &ct->status))
- nf_conntrack_event_cache(IPCT_NATINFO, ct);
-#endif
+
nf_conntrack_event_cache(master_ct(ct) ?
IPCT_RELATED : IPCT_NEW, ct);
return NF_ACCEPT;
@@ -807,8 +803,6 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
unsigned long extra_jiffies,
int do_acct)
{
- int event = 0;
-
NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct);
NF_CT_ASSERT(skb);
@@ -821,7 +815,6 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
/* If not in hash table, timer will not be active yet */
if (!nf_ct_is_confirmed(ct)) {
ct->timeout.expires = extra_jiffies;
- event = IPCT_REFRESH;
} else {
unsigned long newtime = jiffies + extra_jiffies;
@@ -832,7 +825,6 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
&& del_timer(&ct->timeout)) {
ct->timeout.expires = newtime;
add_timer(&ct->timeout);
- event = IPCT_REFRESH;
}
}
@@ -849,10 +841,6 @@ acct:
}
spin_unlock_bh(&nf_conntrack_lock);
-
- /* must be unlocked when calling event cache */
- if (event)
- nf_conntrack_event_cache(event, ct);
}
EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct);
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 00fecc3..5509dd1 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -338,11 +338,9 @@ static void update_nl_seq(struct nf_conn *ct, u32 nl_seq,
if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER) {
info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq;
- nf_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, ct);
} else if (oldest != NUM_SEQ_TO_REMEMBER &&
after(nl_seq, info->seq_aft_nl[dir][oldest])) {
info->seq_aft_nl[dir][oldest] = nl_seq;
- nf_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, ct);
}
}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index fa2bd2a..18ee471 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1198,7 +1198,6 @@ ctnetlink_event_report(struct nf_conn *ct, u32 pid, int report)
nf_conntrack_event_report(IPCT_STATUS |
IPCT_HELPER |
- IPCT_REFRESH |
IPCT_PROTOINFO |
IPCT_NATSEQADJ |
IPCT_MARK |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index b5ccf2b..47090ac 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -974,7 +974,6 @@ static int tcp_packet(struct nf_conn *ct,
timeout = tcp_timeouts[new_state];
write_unlock_bh(&tcp_lock);
- nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
if (new_state != old_state)
nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 4/4] netfilter: conntrack: replace notify chain by function pointer
2009-05-02 14:18 [PATCH 0/4] conntrack event subsystem updates for 2.6.31 Pablo Neira Ayuso
` (2 preceding siblings ...)
2009-05-02 14:19 ` [PATCH 3/4] netfilter: conntrack: simplify event caching system Pablo Neira Ayuso
@ 2009-05-02 14:20 ` Pablo Neira Ayuso
2009-05-06 13:36 ` [PATCH 0/4] conntrack event subsystem updates for 2.6.31 Pablo Neira Ayuso
4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2009-05-02 14:20 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber
This patch removes the notify chain infrastructure and replace it
by a simple function pointer. This issue has been mentioned in the
mailing list several times: the use of the notify chain adds
too much overhead for something that is only used by ctnetlink.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_conntrack_ecache.h | 68 +++++++++++++-----
net/netfilter/nf_conntrack_ecache.c | 101 +++++++++++++++++++++++----
net/netfilter/nf_conntrack_netlink.c | 37 +++++-----
3 files changed, 150 insertions(+), 56 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 2e17a2d..39efacb 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -6,7 +6,6 @@
#define _NF_CONNTRACK_ECACHE_H
#include <net/netfilter/nf_conntrack.h>
-#include <linux/notifier.h>
#include <linux/interrupt.h>
#include <net/net_namespace.h>
#include <net/netfilter/nf_conntrack_expect.h>
@@ -69,9 +68,13 @@ struct nf_ct_event {
int report;
};
-extern struct atomic_notifier_head nf_conntrack_chain;
-extern int nf_conntrack_register_notifier(struct notifier_block *nb);
-extern int nf_conntrack_unregister_notifier(struct notifier_block *nb);
+struct nf_ct_event_notifier {
+ int (*fcn)(unsigned int events, struct nf_ct_event *item);
+};
+
+extern struct nf_ct_event_notifier *nf_conntrack_event_cb;
+extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
+extern int nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
extern void __nf_ct_event_cache_init(struct nf_conn *ct);
@@ -97,13 +100,23 @@ nf_conntrack_event_report(enum ip_conntrack_events event,
u32 pid,
int report)
{
- struct nf_ct_event item = {
- .ct = ct,
- .pid = pid,
- .report = report
- };
- if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
- atomic_notifier_call_chain(&nf_conntrack_chain, event, &item);
+ struct nf_ct_event_notifier *notify;
+
+ rcu_read_lock();
+ notify = rcu_dereference(nf_conntrack_event_cb);
+ if (notify == NULL)
+ goto out_unlock;
+
+ if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
+ struct nf_ct_event item = {
+ .ct = ct,
+ .pid = pid,
+ .report = report
+ };
+ notify->fcn(event, &item);
+ }
+out_unlock:
+ rcu_read_unlock();
}
static inline void
@@ -118,9 +131,13 @@ struct nf_exp_event {
int report;
};
-extern struct atomic_notifier_head nf_ct_expect_chain;
-extern int nf_ct_expect_register_notifier(struct notifier_block *nb);
-extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb);
+struct nf_exp_event_notifier {
+ int (*fcn)(unsigned int events, struct nf_exp_event *item);
+};
+
+extern struct nf_exp_event_notifier *nf_expect_event_cb;
+extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb);
+extern int nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
static inline void
nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
@@ -128,12 +145,23 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
u32 pid,
int report)
{
- struct nf_exp_event item = {
- .exp = exp,
- .pid = pid,
- .report = report
- };
- atomic_notifier_call_chain(&nf_ct_expect_chain, event, &item);
+ struct nf_exp_event_notifier *notify;
+
+ rcu_read_lock();
+ notify = rcu_dereference(nf_expect_event_cb);
+ if (notify == NULL)
+ goto out_unlock;
+
+ {
+ struct nf_exp_event item = {
+ .exp = exp,
+ .pid = pid,
+ .report = report
+ };
+ notify->fcn(event, &item);
+ }
+out_unlock:
+ rcu_read_unlock();
}
static inline void
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index dee4190..780278b 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -16,24 +16,32 @@
#include <linux/stddef.h>
#include <linux/err.h>
#include <linux/percpu.h>
-#include <linux/notifier.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
-ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
-EXPORT_SYMBOL_GPL(nf_conntrack_chain);
+static DEFINE_MUTEX(nf_ct_ecache_mutex);
-ATOMIC_NOTIFIER_HEAD(nf_ct_expect_chain);
-EXPORT_SYMBOL_GPL(nf_ct_expect_chain);
+struct nf_ct_event_notifier *nf_conntrack_event_cb;
+EXPORT_SYMBOL_GPL(nf_conntrack_event_cb);
+
+struct nf_exp_event_notifier *nf_expect_event_cb;
+EXPORT_SYMBOL_GPL(nf_expect_event_cb);
/* deliver cached events and clear cache entry - must be called with locally
* disabled softirqs */
static inline void
__nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
{
+ struct nf_ct_event_notifier *notify;
+
+ rcu_read_lock();
+ notify = rcu_dereference(nf_conntrack_event_cb);
+ if (notify == NULL)
+ goto out_unlock;
+
if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct)
&& ecache->events) {
struct nf_ct_event item = {
@@ -42,14 +50,15 @@ __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
.report = 0
};
- atomic_notifier_call_chain(&nf_conntrack_chain,
- ecache->events,
- &item);
+ notify->fcn(ecache->events, &item);
}
ecache->events = 0;
nf_ct_put(ecache->ct);
ecache->ct = NULL;
+
+out_unlock:
+ rcu_read_unlock();
}
/* Deliver all cached events for a particular conntrack. This is called
@@ -111,26 +120,86 @@ void nf_conntrack_ecache_fini(struct net *net)
free_percpu(net->ct.ecache);
}
-int nf_conntrack_register_notifier(struct notifier_block *nb)
+int nf_conntrack_register_notifier(struct nf_ct_event_notifier *new)
{
- return atomic_notifier_chain_register(&nf_conntrack_chain, nb);
+ int ret = 0;
+ struct nf_ct_event_notifier *notify;
+
+ mutex_lock(&nf_ct_ecache_mutex);
+ notify = rcu_dereference(nf_conntrack_event_cb);
+ if (notify != NULL) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+ rcu_assign_pointer(nf_conntrack_event_cb, new);
+ mutex_unlock(&nf_ct_ecache_mutex);
+ return ret;
+
+out_unlock:
+ mutex_unlock(&nf_ct_ecache_mutex);
+ return ret;
}
EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier);
-int nf_conntrack_unregister_notifier(struct notifier_block *nb)
+int nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *new)
{
- return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb);
+ int ret = 0;
+ struct nf_ct_event_notifier *notify;
+
+ mutex_lock(&nf_ct_ecache_mutex);
+ notify = rcu_dereference(nf_conntrack_event_cb);
+ if (notify != new) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+ rcu_assign_pointer(nf_conntrack_event_cb, NULL);
+ mutex_unlock(&nf_ct_ecache_mutex);
+ return ret;
+
+out_unlock:
+ mutex_unlock(&nf_ct_ecache_mutex);
+ return ret;
}
EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
-int nf_ct_expect_register_notifier(struct notifier_block *nb)
+int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *new)
{
- return atomic_notifier_chain_register(&nf_ct_expect_chain, nb);
+ int ret = 0;
+ struct nf_exp_event_notifier *notify;
+
+ mutex_lock(&nf_ct_ecache_mutex);
+ notify = rcu_dereference(nf_expect_event_cb);
+ if (notify != NULL) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+ rcu_assign_pointer(nf_expect_event_cb, new);
+ mutex_unlock(&nf_ct_ecache_mutex);
+ return ret;
+
+out_unlock:
+ mutex_unlock(&nf_ct_ecache_mutex);
+ return ret;
}
EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier);
-int nf_ct_expect_unregister_notifier(struct notifier_block *nb)
+int nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *new)
{
- return atomic_notifier_chain_unregister(&nf_ct_expect_chain, nb);
+ int ret = 0;
+ struct nf_exp_event_notifier *notify;
+
+ mutex_lock(&nf_ct_ecache_mutex);
+ notify = rcu_dereference(nf_expect_event_cb);
+ if (notify != new) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+ rcu_assign_pointer(nf_expect_event_cb, NULL);
+ mutex_unlock(&nf_ct_ecache_mutex);
+ return ret;
+
+out_unlock:
+ mutex_unlock(&nf_ct_ecache_mutex);
+ return ret;
}
EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 18ee471..addd6e5 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -27,7 +27,6 @@
#include <linux/netlink.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
-#include <linux/notifier.h>
#include <linux/netfilter.h>
#include <net/netlink.h>
@@ -477,13 +476,12 @@ ctnetlink_alloc_skb(const struct nf_conntrack_tuple *tuple, gfp_t gfp)
return alloc_skb(len, gfp);
}
-static int ctnetlink_conntrack_event(struct notifier_block *this,
- unsigned long events, void *ptr)
+static int
+ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
{
struct nlmsghdr *nlh;
struct nfgenmsg *nfmsg;
struct nlattr *nest_parms;
- struct nf_ct_event *item = (struct nf_ct_event *)ptr;
struct nf_conn *ct = item->ct;
struct sk_buff *skb;
unsigned int type;
@@ -492,7 +490,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
/* ignore our fake conntrack entry */
if (ct == &nf_conntrack_untracked)
- return NOTIFY_DONE;
+ return 0;
if (events & IPCT_DESTROY) {
type = IPCTNL_MSG_CT_DELETE;
@@ -505,10 +503,10 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
type = IPCTNL_MSG_CT_NEW;
group = NFNLGRP_CONNTRACK_UPDATE;
} else
- return NOTIFY_DONE;
+ return 0;
if (!item->report && !nfnetlink_has_listeners(group))
- return NOTIFY_DONE;
+ return 0;
skb = ctnetlink_alloc_skb(tuple(ct, IP_CT_DIR_ORIGINAL), GFP_ATOMIC);
if (!skb)
@@ -586,7 +584,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
nlh->nlmsg_len = skb->tail - b;
nfnetlink_send(skb, item->pid, group, item->report);
- return NOTIFY_DONE;
+ return 0;
nla_put_failure:
rcu_read_unlock();
@@ -594,7 +592,7 @@ nlmsg_failure:
kfree_skb(skb);
errout:
nfnetlink_set_err(0, group, -ENOBUFS);
- return NOTIFY_DONE;
+ return 0;
}
#endif /* CONFIG_NF_CONNTRACK_EVENTS */
@@ -1540,12 +1538,11 @@ nla_put_failure:
}
#ifdef CONFIG_NF_CONNTRACK_EVENTS
-static int ctnetlink_expect_event(struct notifier_block *this,
- unsigned long events, void *ptr)
+static int
+ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
{
struct nlmsghdr *nlh;
struct nfgenmsg *nfmsg;
- struct nf_exp_event *item = (struct nf_exp_event *)ptr;
struct nf_conntrack_expect *exp = item->exp;
struct sk_buff *skb;
unsigned int type;
@@ -1556,11 +1553,11 @@ static int ctnetlink_expect_event(struct notifier_block *this,
type = IPCTNL_MSG_EXP_NEW;
flags = NLM_F_CREATE|NLM_F_EXCL;
} else
- return NOTIFY_DONE;
+ return 0;
if (!item->report &&
!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW))
- return NOTIFY_DONE;
+ return 0;
skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
if (!skb)
@@ -1584,7 +1581,7 @@ static int ctnetlink_expect_event(struct notifier_block *this,
nlh->nlmsg_len = skb->tail - b;
nfnetlink_send(skb, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, item->report);
- return NOTIFY_DONE;
+ return 0;
nla_put_failure:
rcu_read_unlock();
@@ -1592,7 +1589,7 @@ nlmsg_failure:
kfree_skb(skb);
errout:
nfnetlink_set_err(0, 0, -ENOBUFS);
- return NOTIFY_DONE;
+ return 0;
}
#endif
static int ctnetlink_exp_done(struct netlink_callback *cb)
@@ -1898,12 +1895,12 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
}
#ifdef CONFIG_NF_CONNTRACK_EVENTS
-static struct notifier_block ctnl_notifier = {
- .notifier_call = ctnetlink_conntrack_event,
+static struct nf_ct_event_notifier ctnl_notifier = {
+ .fcn = ctnetlink_conntrack_event,
};
-static struct notifier_block ctnl_notifier_exp = {
- .notifier_call = ctnetlink_expect_event,
+static struct nf_exp_event_notifier ctnl_notifier_exp = {
+ .fcn = ctnetlink_expect_event,
};
#endif
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH 0/4] conntrack event subsystem updates for 2.6.31
2009-05-02 14:18 [PATCH 0/4] conntrack event subsystem updates for 2.6.31 Pablo Neira Ayuso
` (3 preceding siblings ...)
2009-05-02 14:20 ` [PATCH 4/4] netfilter: conntrack: replace notify chain by function pointer Pablo Neira Ayuso
@ 2009-05-06 13:36 ` Pablo Neira Ayuso
4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2009-05-06 13:36 UTC (permalink / raw)
To: kaber; +Cc: netfilter-devel
Pablo Neira Ayuso wrote:
> Hi Patrick,
>
> This is the first bunch of patches oriented to the event caching
> system, I still have a couple more here but I'm still getting them
> into shape.
I noticed a "scheduling while atomic" problem in the event caching
"replace notify chain by function pointer" patch. It seems that
gfp_any(), which is used by nfnetlink_send(), returns GFP_KERNEL inside
a RCU read-side lock section, that's invalid. Moreover, this triggers a
backtrace when using very small buffers and making lots of requests from
user-context (we hit schedule() due to __GFP_WAIT in the netlink code).
Patrick, just to let you know in case that you look at these patches. I
have fixed this here. I'll resend these patches once nf-next-2.6 is open.
--
"Los honestos son inadaptados sociales" -- Les Luthiers
^ permalink raw reply [flat|nested] 6+ messages in thread