struct list_head stt_list;
struct list_head stt_up_list; /* Devices which are in IFF_UP state. */
int n_tunnels;
+#ifdef HAVE_NF_REGISTER_NET_HOOK
+ bool nf_hook_reg_done;
+#endif
};
static int stt_net_id;
* rtnl-lock, which results in dead lock in stt-dev-create. Therefore
* use this new API.
*/
+
+ if (sn->nf_hook_reg_done)
+ goto out;
+
err = nf_register_net_hook(net, &nf_hook_ops);
+ if (!err)
+ sn->nf_hook_reg_done = true;
#else
+ /* Register STT only on very first STT device addition. */
+ if (!list_empty(&nf_hook_ops.list))
+ goto out;
+
err = nf_register_hook(&nf_hook_ops);
#endif
if (err)
goto dec_n_tunnel;
+out:
sn->n_tunnels++;
return 0;
INIT_LIST_HEAD(&sn->stt_list);
INIT_LIST_HEAD(&sn->stt_up_list);
+#ifdef HAVE_NF_REGISTER_NET_HOOK
+ sn->nf_hook_reg_done = false;
+#endif
return 0;
}
/* Ideally this should be done from stt_stop(), But on some kernels
* nf-unreg operation needs RTNL-lock, which can cause deallock.
* So it is done from here. */
- if (!list_empty(&nf_hook_ops.list))
+ if (sn->nf_hook_reg_done)
nf_unregister_net_hook(net, &nf_hook_ops);
#endif