--- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -113,6 +113,9 @@ struct netns_ct { struct ct_pcpu __percpu *pcpu_lists; struct ip_conntrack_stat __percpu *stat; +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + struct atomic_notifier_head nf_conntrack_chain; +#endif struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb; struct nf_ip_net nf_ct_proto; #if defined(CONFIG_NF_CONNTRACK_LABELS) --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -78,6 +78,11 @@ struct nf_exp_event { int report; }; +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +extern int nf_conntrack_register_chain_notifier(struct net *net, struct notifier_block *nb); +extern int nf_conntrack_unregister_chain_notifier(struct net *net, struct notifier_block *nb); +#endif + struct nf_ct_event_notifier { int (*ct_event)(unsigned int events, const struct nf_ct_event *item); int (*exp_event)(unsigned int events, const struct nf_exp_event *item); @@ -111,11 +116,13 @@ static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) { #ifdef CONFIG_NF_CONNTRACK_EVENTS - struct net *net = nf_ct_net(ct); struct nf_conntrack_ecache *e; +#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + struct net *net = nf_ct_net(ct); if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) return; +#endif e = nf_ct_ecache_find(ct); if (e == NULL) @@ -130,10 +137,12 @@ nf_conntrack_event_report(enum ip_conntr u32 portid, int report) { #ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS const struct net *net = nf_ct_net(ct); if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) return 0; +#endif return nf_conntrack_eventmask_report(1 << event, ct, portid, report); #else @@ -145,10 +154,12 @@ static inline int nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) { #ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS const struct net *net = nf_ct_net(ct); if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) return 0; +#endif return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); #else --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -160,6 +160,21 @@ config NF_CONNTRACK_TIMEOUT If unsure, say `N'. +config NF_CONNTRACK_DSCPREMARK_EXT + bool 'Connection tracking extension for dscp remark target' + depends on NETFILTER_ADVANCED + help + This option enables support for connection tracking extension + for dscp remark. + +config NF_CONNTRACK_CHAIN_EVENTS + bool "Register multiple callbacks to ct events" + depends on NF_CONNTRACK_EVENTS + help + Support multiple registrations. + + If unsure, say `N'. + config NF_CONNTRACK_TIMESTAMP bool 'Connection tracking timestamping' depends on NETFILTER_ADVANCED --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -2899,6 +2899,9 @@ int nf_conntrack_init_net(struct net *ne nf_conntrack_ecache_pernet_init(net); nf_conntrack_helper_pernet_init(net); nf_conntrack_proto_pernet_init(net); +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + ATOMIC_INIT_NOTIFIER_HEAD(&net->ct.nf_conntrack_chain); +#endif return 0; --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -17,6 +17,9 @@ #include #include #include +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +#include +#endif #include #include #include @@ -150,8 +153,15 @@ static int __nf_conntrack_eventmask_repo rcu_read_unlock(); return 0; } - +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + ret = atomic_notifier_call_chain(&net->ct.nf_conntrack_chain, + events | missed, &item); + + if (notify) + ret = notify->ct_event(events | missed, item); +#else ret = notify->ct_event(events | missed, item); +#endif rcu_read_unlock(); if (likely(ret >= 0 && missed == 0)) @@ -245,7 +255,11 @@ void nf_ct_expect_event_report(enum ip_c rcu_read_lock(); notify = rcu_dereference(net->ct.nf_conntrack_event_cb); +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + if (!notify && !rcu_dereference_raw(net->ct.nf_conntrack_chain.head)) +#else if (!notify) +#endif goto out_unlock; e = nf_ct_ecache_find(exp->master); @@ -264,6 +278,14 @@ out_unlock: rcu_read_unlock(); } +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +int nf_conntrack_register_chain_notifier(struct net *net, struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&net->ct.nf_conntrack_chain, nb); +} +EXPORT_SYMBOL_GPL(nf_conntrack_register_chain_notifier); +#endif + void nf_conntrack_register_notifier(struct net *net, const struct nf_ct_event_notifier *new) { @@ -278,6 +300,14 @@ void nf_conntrack_register_notifier(stru } EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier); +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +int nf_conntrack_unregister_chain_notifier(struct net *net, struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&net->ct.nf_conntrack_chain, nb); +} +EXPORT_SYMBOL_GPL(nf_conntrack_unregister_chain_notifier); +#endif + void nf_conntrack_unregister_notifier(struct net *net) { mutex_lock(&nf_ct_ecache_mutex); --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -28,6 +28,10 @@ enum nf_ct_ext_id { #if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY) NF_CT_EXT_SYNPROXY, #endif +#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT + NF_CT_EXT_DSCPREMARK, /* QCA NSS ECM support */ +#endif + NF_CT_EXT_NUM, }; @@ -40,6 +44,9 @@ enum nf_ct_ext_id { #define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout #define NF_CT_EXT_LABELS_TYPE struct nf_conn_labels #define NF_CT_EXT_SYNPROXY_TYPE struct nf_conn_synproxy +/* QCA NSS ECM support - Start */ +#define NF_CT_EXT_DSCPREMARK_TYPE struct nf_ct_dscpremark_ext +/* QCA NSS ECM support - End */ /* Extensions: optional stuff which isn't permanently in struct. */ struct nf_ct_ext { --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -14,6 +14,7 @@ nf_conntrack-$(CONFIG_NF_CONNTRACK_LABEL nf_conntrack-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o nf_conntrack-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o nf_conntrack-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o +nf_conntrack-$(CONFIG_NF_CONNTRACK_DSCPREMARK_EXT) += nf_conntrack_dscpremark_ext.o obj-$(CONFIG_NETFILTER) = netfilter.o