netfilter: conntrack: move event caching to conntrack extension infrastructure
[safe/jmp/linux-2.6] / include / net / netfilter / nf_conntrack_ecache.h
index 1afb907..e7ae297 100644 (file)
@@ -6,61 +6,52 @@
 #define _NF_CONNTRACK_ECACHE_H
 #include <net/netfilter/nf_conntrack.h>
 
-#include <linux/interrupt.h>
 #include <net/net_namespace.h>
 #include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 
-/* Connection tracking event bits */
+/* Connection tracking event types */
 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),
-
-       /* Status has changed */
-       IPCT_STATUS_BIT = 3,
-       IPCT_STATUS = (1 << IPCT_STATUS_BIT),
+       IPCT_NEW                = 0,    /* new conntrack */
+       IPCT_RELATED            = 1,    /* related conntrack */
+       IPCT_DESTROY            = 2,    /* destroyed conntrack */
+       IPCT_STATUS             = 3,    /* status has changed */
+       IPCT_PROTOINFO          = 4,    /* protocol information has changed */
+       IPCT_HELPER             = 5,    /* new helper has been set */
+       IPCT_MARK               = 6,    /* new mark has been set */
+       IPCT_NATSEQADJ          = 7,    /* NAT is doing sequence adjustment */
+       IPCT_SECMARK            = 8,    /* new security mark has been set */
+};
 
-       /* Update of protocol info */
-       IPCT_PROTOINFO_BIT = 4,
-       IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT),
+enum ip_conntrack_expect_events {
+       IPEXP_NEW               = 0,    /* new expectation */
+};
 
-       /* New helper for conntrack */
-       IPCT_HELPER_BIT = 5,
-       IPCT_HELPER = (1 << IPCT_HELPER_BIT),
+struct nf_conntrack_ecache {
+       unsigned long cache;            /* bitops want long */
+};
 
-       /* Mark is set */
-       IPCT_MARK_BIT = 6,
-       IPCT_MARK = (1 << IPCT_MARK_BIT),
+static inline struct nf_conntrack_ecache *
+nf_ct_ecache_find(const struct nf_conn *ct)
+{
+       return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
+}
 
-       /* NAT sequence adjustment */
-       IPCT_NATSEQADJ_BIT = 7,
-       IPCT_NATSEQADJ = (1 << IPCT_NATSEQADJ_BIT),
+static inline struct nf_conntrack_ecache *
+nf_ct_ecache_ext_add(struct nf_conn *ct, gfp_t gfp)
+{
+       struct net *net = nf_ct_net(ct);
 
-       /* Secmark is set */
-       IPCT_SECMARK_BIT = 8,
-       IPCT_SECMARK = (1 << IPCT_SECMARK_BIT),
-};
+       if (!net->ct.sysctl_events)
+               return NULL;
 
-enum ip_conntrack_expect_events {
-       IPEXP_NEW_BIT = 0,
-       IPEXP_NEW = (1 << IPEXP_NEW_BIT),
+       return nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
 };
 
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
-struct nf_conntrack_ecache {
-       struct nf_conn *ct;
-       unsigned int events;
-};
-
 /* This structure is passed to event handler */
 struct nf_ct_event {
        struct nf_conn *ct;
@@ -76,30 +67,30 @@ extern struct nf_ct_event_notifier *nf_conntrack_event_cb;
 extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
 extern void 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);
-extern void nf_ct_event_cache_flush(struct net *net);
+extern void nf_ct_deliver_cached_events(struct nf_conn *ct);
 
 static inline void
 nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
 {
-       struct net *net = nf_ct_net(ct);
-       struct nf_conntrack_ecache *ecache;
-
-       local_bh_disable();
-       ecache = per_cpu_ptr(net->ct.ecache, raw_smp_processor_id());
-       if (ct != ecache->ct)
-               __nf_ct_event_cache_init(ct);
-       ecache->events |= event;
-       local_bh_enable();
+       struct nf_conntrack_ecache *e;
+
+       if (nf_conntrack_event_cb == NULL)
+               return;
+
+       e = nf_ct_ecache_find(ct);
+       if (e == NULL)
+               return;
+
+       set_bit(event, &e->cache);
 }
 
 static inline void
-nf_conntrack_event_report(enum ip_conntrack_events event,
-                         struct nf_conn *ct,
-                         u32 pid,
-                         int report)
+nf_conntrack_eventmask_report(unsigned int eventmask,
+                             struct nf_conn *ct,
+                             u32 pid,
+                             int report)
 {
+       struct net *net = nf_ct_net(ct);
        struct nf_ct_event_notifier *notify;
 
        rcu_read_lock();
@@ -107,22 +98,32 @@ nf_conntrack_event_report(enum ip_conntrack_events event,
        if (notify == NULL)
                goto out_unlock;
 
+       if (!net->ct.sysctl_events)
+               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);
+               notify->fcn(eventmask, &item);
        }
 out_unlock:
        rcu_read_unlock();
 }
 
 static inline void
+nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
+                         u32 pid, int report)
+{
+       nf_conntrack_eventmask_report(1 << event, ct, pid, report);
+}
+
+static inline void
 nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
 {
-       nf_conntrack_event_report(event, ct, 0, 0);
+       nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
 }
 
 struct nf_exp_event {
@@ -145,6 +146,7 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
                          u32 pid,
                          int report)
 {
+       struct net *net = nf_ct_exp_net(exp);
        struct nf_exp_event_notifier *notify;
 
        rcu_read_lock();
@@ -152,13 +154,16 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
        if (notify == NULL)
                goto out_unlock;
 
+       if (!net->ct.sysctl_events)
+               goto out_unlock;
+
        {
                struct nf_exp_event item = {
                        .exp    = exp,
                        .pid    = pid,
                        .report = report
                };
-               notify->fcn(event, &item);
+               notify->fcn(1 << event, &item);
        }
 out_unlock:
        rcu_read_unlock();
@@ -178,6 +183,10 @@ extern void nf_conntrack_ecache_fini(struct net *net);
 
 static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
                                            struct nf_conn *ct) {}
+static inline void nf_conntrack_eventmask_report(unsigned int eventmask,
+                                                struct nf_conn *ct,
+                                                u32 pid,
+                                                int report) {}
 static inline void nf_conntrack_event(enum ip_conntrack_events event,
                                      struct nf_conn *ct) {}
 static inline void nf_conntrack_event_report(enum ip_conntrack_events event,
@@ -191,7 +200,6 @@ static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
                                             struct nf_conntrack_expect *exp,
                                             u32 pid,
                                             int report) {}
-static inline void nf_ct_event_cache_flush(struct net *net) {}
 
 static inline int nf_conntrack_ecache_init(struct net *net)
 {