shortcut-fe: rework netfilter conntrack notification

The original patch from QCA over rode the nf_conntrack_un/register_notifier API, which
will break other modules relying on the API.  Reworked the notification APIs to play nice
with others.
This commit is contained in:
quarkysg 2020-06-25 14:49:37 +08:00 committed by CN_SZTL
parent c3bbc9cf36
commit e639e20437
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
3 changed files with 64 additions and 29 deletions

View File

@ -1807,10 +1807,12 @@ static int __init fast_classifier_init(void)
goto exit3;
}
#ifdef CONFIG_NF_CONNTRACK_EVENTS
/*
* Register a notifier hook to get fast notifications of expired connections.
*/
#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
result = nf_conntrack_register_chain_notifier(&init_net, &fast_classifier_conntrack_notifier);
#else
result = nf_conntrack_register_notifier(&init_net, &fast_classifier_conntrack_notifier);
if (result < 0) {
DEBUG_ERROR("can't register nf notifier hook: %d\n", result);
@ -1877,7 +1879,11 @@ exit6:
exit5:
#ifdef CONFIG_NF_CONNTRACK_EVENTS
#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
nf_conntrack_unregister_chain_notifier(&init_net, &fast_classifier_conntrack_notifier);
#else
nf_conntrack_unregister_notifier(&init_net, &fast_classifier_conntrack_notifier);
#endif
exit4:
#endif
@ -1945,8 +1951,11 @@ static void __exit fast_classifier_exit(void)
}
#ifdef CONFIG_NF_CONNTRACK_EVENTS
#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
nf_conntrack_unregister_chain_notifier(&init_net, &fast_classifier_conntrack_notifier);
#else
nf_conntrack_unregister_notifier(&init_net, &fast_classifier_conntrack_notifier);
#endif
#endif
nf_unregister_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing));

View File

@ -1049,7 +1049,7 @@ static int __init sfe_cm_init(void)
*/
#ifdef CONFIG_NF_CONNTRACK_EVENTS
#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
(void)nf_conntrack_register_notifier(&init_net, &sfe_cm_conntrack_notifier);
(void)nf_conntrack_register_chain_notifier(&init_net, &sfe_cm_conntrack_notifier);
#else
result = nf_conntrack_register_notifier(&init_net, &sfe_cm_conntrack_notifier);
if (result < 0) {
@ -1123,8 +1123,11 @@ static void __exit sfe_cm_exit(void)
sfe_ipv6_destroy_all_rules_for_dev(NULL);
#ifdef CONFIG_NF_CONNTRACK_EVENTS
#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
nf_conntrack_unregister_chain_notifier(&init_net, &sfe_cm_conntrack_notifier);
#else
nf_conntrack_unregister_notifier(&init_net, &sfe_cm_conntrack_notifier);
#endif
#endif
nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing));

View File

@ -36,6 +36,17 @@
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -75,6 +75,8 @@ struct nf_ct_event {
#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
extern int nf_conntrack_register_notifier(struct net *net, struct notifier_block *nb);
extern int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb);
+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);
#else
struct nf_ct_event_notifier {
int (*fcn)(unsigned int events, struct nf_ct_event *item);
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -746,6 +746,28 @@ void br_port_flags_change(struct net_bri
@ -161,57 +172,45 @@
static int nf_ct_tcp_loose __read_mostly = 1;
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -153,13 +153,17 @@ int nf_conntrack_eventmask_report(unsign
{
int ret = 0;
struct net *net = nf_ct_net(ct);
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
struct nf_ct_event_notifier *notify;
+#endif
struct nf_conntrack_ecache *e;
@@ -162,7 +162,11 @@ int nf_conntrack_eventmask_report(unsign
rcu_read_lock();
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
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)
goto out_unlock;
+#endif
goto out_unlock;
e = nf_ct_ecache_find(ct);
if (!e)
@@ -177,7 +181,12 @@ int nf_conntrack_eventmask_report(unsign
@@ -177,7 +181,14 @@ int nf_conntrack_eventmask_report(unsign
if (!((eventmask | missed) & e->ctmask))
goto out_unlock;
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ ret = atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
+ eventmask | missed, &item);
+ if (notify)
+ ret = notify->fcn(eventmask | missed, &item);
+#else
ret = notify->fcn(eventmask | missed, &item);
+#endif
if (unlikely(ret < 0 || missed)) {
spin_lock_bh(&ct->lock);
if (ret < 0) {
@@ -252,15 +261,19 @@ void nf_ct_deliver_cached_events(struct
{
struct net *net = nf_ct_net(ct);
unsigned long events, missed;
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
struct nf_ct_event_notifier *notify;
+#endif
struct nf_conntrack_ecache *e;
struct nf_ct_event item;
int ret;
@@ -263,7 +274,11 @@ void nf_ct_deliver_cached_events(struct
rcu_read_lock();
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ if ((notify == NULL) && !rcu_dereference_raw(net->ct.nf_conntrack_chain.head))
+#else
if (notify == NULL)
goto out_unlock;
+#endif
goto out_unlock;
e = nf_ct_ecache_find(ct);
if (e == NULL)
@@ -283,7 +296,13 @@ void nf_ct_deliver_cached_events(struct
item.portid = 0;
item.report = 0;
@ -226,3 +225,27 @@
if (likely(ret == 0 && !missed))
goto out_unlock;
@@ -340,6 +363,11 @@ int nf_conntrack_register_notifier(struct net *net, struct notifier_block *nb)
{
return atomic_notifier_chain_register(&net->ct.nf_conntrack_chain, nb);
}
+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);
#else
int nf_conntrack_register_notifier(struct net *net,
struct nf_ct_event_notifier *new)
@@ -369,6 +397,11 @@ int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb)
{
return atomic_notifier_chain_unregister(&net->ct.nf_conntrack_chain, nb);
}
+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);
#else
void nf_conntrack_unregister_notifier(struct net *net,
struct nf_ct_event_notifier *new)