* [PATCH nf-next v2] netfilter: conntrack: simplify init/uninit of L4 protocol trackers
@ 2016-10-28 8:42 Davide Caratti
2016-10-28 8:47 ` Pablo Neira Ayuso
2016-11-01 22:11 ` Pablo Neira Ayuso
0 siblings, 2 replies; 5+ messages in thread
From: Davide Caratti @ 2016-10-28 8:42 UTC (permalink / raw)
To: Pablo Neira Ayuso, Patrick McHardy, Jozsef Kadlecsik,
David S . Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI
Cc: netfilter-devel, coreteam
modify registration and deregistration of layer-4 protocol trackers to
facilitate inclusion of new elements into the current list of builtin
protocols. Both builtin (TCP, UDP, ICMP) and non-builtin (DCCP, GRE, SCTP,
UDPlite) layer-4 protocol trackers usually register/deregister themselves
using consecutive calls to nf_ct_l4proto_{,pernet}_{,un}register(...).
This sequence is interrupted and rolled back in case of error; in order to
simplify addition of builtin protocols, the input of the above functions
has been modified to allow registering/unregistering multiple protocols.
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
---
Notes:
v2:
- reword commit message
- change input of nf_ct_l4proto_{,pernet}_{,un}register(...) to
accept arrays of struct nf_conntrack_l4proto *.
please note:
checkpatch.pl complains about coding style on some of the lines that
were moved into a for() loop. This can be fixed too, but I propose to
do that in a separate commit.
include/net/netfilter/nf_conntrack_l4proto.h | 12 +-
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 76 +++-------
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 78 ++++------
net/netfilter/nf_conntrack_proto.c | 191 +++++++++++++++----------
net/netfilter/nf_conntrack_proto_dccp.c | 48 ++-----
net/netfilter/nf_conntrack_proto_gre.c | 28 ++--
net/netfilter/nf_conntrack_proto_sctp.c | 50 ++-----
net/netfilter/nf_conntrack_proto_udplite.c | 50 ++-----
8 files changed, 222 insertions(+), 311 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index de629f1..28f6d79 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -126,13 +126,17 @@ void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
/* Protocol pernet registration. */
int nf_ct_l4proto_pernet_register(struct net *net,
- struct nf_conntrack_l4proto *proto);
+ struct nf_conntrack_l4proto *proto[],
+ int num_proto);
void nf_ct_l4proto_pernet_unregister(struct net *net,
- struct nf_conntrack_l4proto *proto);
+ struct nf_conntrack_l4proto *proto[],
+ int num_proto);
/* Protocol global registration. */
-int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto);
-void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto);
+int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto[],
+ int num_proto);
+void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto[],
+ int num_proto);
/* Generic netlink helpers */
int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 713c09a..7130ed5 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -336,47 +336,34 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
MODULE_ALIAS("ip_conntrack");
MODULE_LICENSE("GPL");
+static struct nf_conntrack_l4proto *builtin_l4proto4[] = {
+ &nf_conntrack_l4proto_tcp4,
+ &nf_conntrack_l4proto_udp4,
+ &nf_conntrack_l4proto_icmp,
+};
+
static int ipv4_net_init(struct net *net)
{
int ret = 0;
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_tcp4);
- if (ret < 0) {
- pr_err("nf_conntrack_tcp4: pernet registration failed\n");
- goto out_tcp;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_udp4);
- if (ret < 0) {
- pr_err("nf_conntrack_udp4: pernet registration failed\n");
- goto out_udp;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_icmp);
- if (ret < 0) {
- pr_err("nf_conntrack_icmp4: pernet registration failed\n");
- goto out_icmp;
- }
+ ret = nf_ct_l4proto_pernet_register(net, builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
+ if (ret < 0)
+ return ret;
ret = nf_ct_l3proto_pernet_register(net, &nf_conntrack_l3proto_ipv4);
if (ret < 0) {
pr_err("nf_conntrack_ipv4: pernet registration failed\n");
- goto out_ipv4;
+ nf_ct_l4proto_pernet_unregister(net, builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
}
- return 0;
-out_ipv4:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmp);
-out_icmp:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp4);
-out_udp:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp4);
-out_tcp:
return ret;
}
static void ipv4_net_exit(struct net *net)
{
nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv4);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmp);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp4);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp4);
+ nf_ct_l4proto_pernet_unregister(net, builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
}
static struct pernet_operations ipv4_net_ops = {
@@ -410,37 +397,21 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
goto cleanup_pernet;
}
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_tcp4);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv4: can't register tcp4 proto.\n");
+ ret = nf_ct_l4proto_register(builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
+ if (ret < 0)
goto cleanup_hooks;
- }
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udp4);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv4: can't register udp4 proto.\n");
- goto cleanup_tcp4;
- }
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_icmp);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv4: can't register icmpv4 proto.\n");
- goto cleanup_udp4;
- }
ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv4);
if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register ipv4 proto.\n");
- goto cleanup_icmpv4;
+ goto cleanup_l4proto;
}
return ret;
- cleanup_icmpv4:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmp);
- cleanup_udp4:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp4);
- cleanup_tcp4:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
+cleanup_l4proto:
+ nf_ct_l4proto_unregister(builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
cleanup_hooks:
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
cleanup_pernet:
@@ -454,9 +425,8 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void)
{
synchronize_net();
nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmp);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp4);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
+ nf_ct_l4proto_unregister(builtin_l4proto4,
+ ARRAY_SIZE(builtin_l4proto4));
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
unregister_pernet_subsys(&ipv4_net_ops);
nf_unregister_sockopt(&so_getorigdst);
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 963ee38..500be28 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -336,47 +336,35 @@ static struct nf_sockopt_ops so_getorigdst6 = {
.owner = THIS_MODULE,
};
+static struct nf_conntrack_l4proto *builtin_l4proto6[] = {
+ &nf_conntrack_l4proto_tcp6,
+ &nf_conntrack_l4proto_udp6,
+ &nf_conntrack_l4proto_icmpv6,
+};
+
static int ipv6_net_init(struct net *net)
{
int ret = 0;
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_tcp6);
- if (ret < 0) {
- pr_err("nf_conntrack_tcp6: pernet registration failed\n");
- goto out;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_udp6);
- if (ret < 0) {
- pr_err("nf_conntrack_udp6: pernet registration failed\n");
- goto cleanup_tcp6;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_icmpv6);
- if (ret < 0) {
- pr_err("nf_conntrack_icmp6: pernet registration failed\n");
- goto cleanup_udp6;
- }
+ ret = nf_ct_l4proto_pernet_register(net, builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
+ if (ret < 0)
+ return ret;
+
ret = nf_ct_l3proto_pernet_register(net, &nf_conntrack_l3proto_ipv6);
if (ret < 0) {
pr_err("nf_conntrack_ipv6: pernet registration failed.\n");
- goto cleanup_icmpv6;
+ nf_ct_l4proto_pernet_unregister(net, builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
}
- return 0;
- cleanup_icmpv6:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmpv6);
- cleanup_udp6:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp6);
- cleanup_tcp6:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp6);
- out:
return ret;
}
static void ipv6_net_exit(struct net *net)
{
nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv6);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmpv6);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp6);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp6);
+ nf_ct_l4proto_pernet_unregister(net, builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
}
static struct pernet_operations ipv6_net_ops = {
@@ -409,37 +397,20 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
goto cleanup_pernet;
}
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_tcp6);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv6: can't register tcp6 proto.\n");
+ ret = nf_ct_l4proto_register(builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
+ if (ret < 0)
goto cleanup_hooks;
- }
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udp6);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv6: can't register udp6 proto.\n");
- goto cleanup_tcp6;
- }
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_icmpv6);
- if (ret < 0) {
- pr_err("nf_conntrack_ipv6: can't register icmpv6 proto.\n");
- goto cleanup_udp6;
- }
ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv6);
if (ret < 0) {
pr_err("nf_conntrack_ipv6: can't register ipv6 proto.\n");
- goto cleanup_icmpv6;
+ goto cleanup_l4proto;
}
return ret;
-
- cleanup_icmpv6:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
- cleanup_udp6:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp6);
- cleanup_tcp6:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
+cleanup_l4proto:
+ nf_ct_l4proto_unregister(builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
cleanup_hooks:
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
cleanup_pernet:
@@ -453,9 +424,8 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
synchronize_net();
nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp6);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
+ nf_ct_l4proto_unregister(builtin_l4proto6,
+ ARRAY_SIZE(builtin_l4proto6));
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
unregister_pernet_subsys(&ipv6_net_ops);
nf_unregister_sockopt(&so_getorigdst6);
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 8d2c7d8..10e609c 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -281,99 +281,136 @@ void nf_ct_l4proto_unregister_sysctl(struct net *net,
/* FIXME: Allow NULL functions and sub in pointers to generic for
them. --RR */
-int nf_ct_l4proto_register(struct nf_conntrack_l4proto *l4proto)
+int nf_ct_l4proto_register(struct nf_conntrack_l4proto *l4proto[],
+ int num_proto)
{
- int ret = 0;
-
- if (l4proto->l3proto >= PF_MAX)
- return -EBUSY;
-
- if ((l4proto->to_nlattr && !l4proto->nlattr_size)
- || (l4proto->tuple_to_nlattr && !l4proto->nlattr_tuple_size))
- return -EINVAL;
+ struct nf_conntrack_l4proto *l4;
+ int ret = 0, j;
+
+ for (j = 0; j < num_proto; j++) {
+ l4 = l4proto[j];
+ if (l4->l3proto >= PF_MAX)
+ return -EBUSY;
+ if ((l4->to_nlattr && !l4->nlattr_size)
+ || (l4->tuple_to_nlattr && !l4->nlattr_tuple_size))
+ return -EINVAL;
+ }
mutex_lock(&nf_ct_proto_mutex);
- if (!nf_ct_protos[l4proto->l3proto]) {
- /* l3proto may be loaded latter. */
- struct nf_conntrack_l4proto __rcu **proto_array;
- int i;
-
- proto_array = kmalloc(MAX_NF_CT_PROTO *
- sizeof(struct nf_conntrack_l4proto *),
- GFP_KERNEL);
- if (proto_array == NULL) {
- ret = -ENOMEM;
- goto out_unlock;
- }
+ for (j = 0; j < num_proto; j++) {
+ l4 = l4proto[j];
+ if (!nf_ct_protos[l4->l3proto]) {
+ /* l3proto may be loaded latter. */
+ struct nf_conntrack_l4proto __rcu **proto_array;
+ int i;
+
+ proto_array = kmalloc(MAX_NF_CT_PROTO *
+ sizeof(l4), GFP_KERNEL);
+ if (proto_array == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
- for (i = 0; i < MAX_NF_CT_PROTO; i++)
- RCU_INIT_POINTER(proto_array[i], &nf_conntrack_l4proto_generic);
+ for (i = 0; i < MAX_NF_CT_PROTO; i++)
+ RCU_INIT_POINTER(proto_array[i],
+ &nf_conntrack_l4proto_generic);
+
+ /* Before making proto_array visible to lockless readers
+ * we must make sure its content is committed to memory.
+ */
+ smp_wmb();
+
+ nf_ct_protos[l4->l3proto] = proto_array;
+ } else if (rcu_dereference_protected(
+ nf_ct_protos[l4->l3proto][l4->l4proto],
+ lockdep_is_held(&nf_ct_proto_mutex)
+ ) != &nf_conntrack_l4proto_generic) {
+ ret = -EBUSY;
+ break;
+ }
- /* Before making proto_array visible to lockless readers,
- * we must make sure its content is committed to memory.
- */
- smp_wmb();
+ l4->nla_size = 0;
+ if (l4->nlattr_size)
+ l4->nla_size += l4->nlattr_size();
+ if (l4->nlattr_tuple_size)
+ l4->nla_size += 3 * l4->nlattr_tuple_size();
- nf_ct_protos[l4proto->l3proto] = proto_array;
- } else if (rcu_dereference_protected(
- nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
- lockdep_is_held(&nf_ct_proto_mutex)
- ) != &nf_conntrack_l4proto_generic) {
- ret = -EBUSY;
- goto out_unlock;
+ rcu_assign_pointer(nf_ct_protos[l4->l3proto][l4->l4proto], l4);
+ }
+ if (j < num_proto) {
+ int ver = l4->l3proto == PF_INET6 ? 6 : 4;
+
+ pr_err("nf_conntrack_ipv%d: can't register %s%d proto.\n",
+ ver, l4->name, ver);
+ while (--j >= 0) {
+ l4 = l4proto[j];
+ BUG_ON(rcu_dereference_protected(
+ nf_ct_protos[l4->l3proto][l4->l4proto],
+ lockdep_is_held(&nf_ct_proto_mutex)
+ ) != l4);
+ rcu_assign_pointer(
+ nf_ct_protos[l4->l3proto][l4->l4proto],
+ &nf_conntrack_l4proto_generic);
+ }
}
-
- l4proto->nla_size = 0;
- if (l4proto->nlattr_size)
- l4proto->nla_size += l4proto->nlattr_size();
- if (l4proto->nlattr_tuple_size)
- l4proto->nla_size += 3 * l4proto->nlattr_tuple_size();
-
- rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
- l4proto);
-out_unlock:
mutex_unlock(&nf_ct_proto_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(nf_ct_l4proto_register);
int nf_ct_l4proto_pernet_register(struct net *net,
- struct nf_conntrack_l4proto *l4proto)
+ struct nf_conntrack_l4proto *l4proto[],
+ int num_proto)
{
- int ret = 0;
struct nf_proto_net *pn = NULL;
+ int i, ret = 0;
- if (l4proto->init_net) {
- ret = l4proto->init_net(net, l4proto->l3proto);
- if (ret < 0)
- goto out;
- }
+ for (i = 0; i < num_proto; i++) {
+ if (l4proto[i]->init_net) {
+ ret = l4proto[i]->init_net(net, l4proto[i]->l3proto);
+ if (ret < 0)
+ break;
+ }
- pn = nf_ct_l4proto_net(net, l4proto);
- if (pn == NULL)
- goto out;
+ pn = nf_ct_l4proto_net(net, l4proto[i]);
+ if (pn == NULL)
+ continue;
- ret = nf_ct_l4proto_register_sysctl(net, pn, l4proto);
- if (ret < 0)
- goto out;
+ ret = nf_ct_l4proto_register_sysctl(net, pn, l4proto[i]);
+ if (ret < 0)
+ break;
- pn->users++;
-out:
+ pn->users++;
+ }
+ if (i < num_proto) {
+ pr_err("nf_conntrack_%s%d: pernet registration failed.\n",
+ l4proto[i]->name,
+ l4proto[i]->l3proto == PF_INET6 ? 6 : 4);
+ nf_ct_l4proto_pernet_unregister(net, l4proto, i);
+ }
return ret;
}
EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_register);
-void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
+void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto[],
+ int num_proto)
{
- BUG_ON(l4proto->l3proto >= PF_MAX);
+ int i;
+
+ for (i = 0; i < num_proto; i++)
+ BUG_ON(l4proto[i]->l3proto >= PF_MAX);
mutex_lock(&nf_ct_proto_mutex);
- BUG_ON(rcu_dereference_protected(
- nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
- lockdep_is_held(&nf_ct_proto_mutex)
- ) != l4proto);
- rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
- &nf_conntrack_l4proto_generic);
+ while (--num_proto >= 0) {
+ struct nf_conntrack_l4proto *l4 = l4proto[num_proto];
+
+ BUG_ON(rcu_dereference_protected(
+ nf_ct_protos[l4->l3proto][l4->l4proto],
+ lockdep_is_held(&nf_ct_proto_mutex)
+ ) != l4);
+ rcu_assign_pointer(nf_ct_protos[l4->l3proto][l4->l4proto],
+ &nf_conntrack_l4proto_generic);
+ }
mutex_unlock(&nf_ct_proto_mutex);
synchronize_rcu();
@@ -381,19 +418,23 @@ void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
EXPORT_SYMBOL_GPL(nf_ct_l4proto_unregister);
void nf_ct_l4proto_pernet_unregister(struct net *net,
- struct nf_conntrack_l4proto *l4proto)
+ struct nf_conntrack_l4proto *l4proto[],
+ int num_proto)
{
struct nf_proto_net *pn = NULL;
- pn = nf_ct_l4proto_net(net, l4proto);
- if (pn == NULL)
- return;
+ while (--num_proto >= 0) {
+ pn = nf_ct_l4proto_net(net, l4proto[num_proto]);
+ if (pn == NULL)
+ continue;
- pn->users--;
- nf_ct_l4proto_unregister_sysctl(net, pn, l4proto);
+ pn->users--;
+ nf_ct_l4proto_unregister_sysctl(net, pn, l4proto[num_proto]);
- /* Remove all contrack entries for this protocol */
- nf_ct_iterate_cleanup(net, kill_l4proto, l4proto, 0, 0);
+ /* Remove all contrack entries for this protocol */
+ nf_ct_iterate_cleanup(net, kill_l4proto, l4proto[num_proto],
+ 0, 0);
+ }
}
EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_unregister);
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index a45bee5..ac89769 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -936,30 +936,21 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
.init_net = dccp_init_net,
};
+static struct nf_conntrack_l4proto *dccp_proto[] = {
+ &dccp_proto4,
+ &dccp_proto6,
+};
+
static __net_init int dccp_net_init(struct net *net)
{
- int ret = 0;
- ret = nf_ct_l4proto_pernet_register(net, &dccp_proto4);
- if (ret < 0) {
- pr_err("nf_conntrack_dccp4: pernet registration failed.\n");
- goto out;
- }
- ret = nf_ct_l4proto_pernet_register(net, &dccp_proto6);
- if (ret < 0) {
- pr_err("nf_conntrack_dccp6: pernet registration failed.\n");
- goto cleanup_dccp4;
- }
- return 0;
-cleanup_dccp4:
- nf_ct_l4proto_pernet_unregister(net, &dccp_proto4);
-out:
- return ret;
+ return nf_ct_l4proto_pernet_register(net, dccp_proto,
+ ARRAY_SIZE(dccp_proto));
}
static __net_exit void dccp_net_exit(struct net *net)
{
- nf_ct_l4proto_pernet_unregister(net, &dccp_proto6);
- nf_ct_l4proto_pernet_unregister(net, &dccp_proto4);
+ nf_ct_l4proto_pernet_unregister(net, dccp_proto,
+ ARRAY_SIZE(dccp_proto));
}
static struct pernet_operations dccp_net_ops = {
@@ -975,29 +966,16 @@ static int __init nf_conntrack_proto_dccp_init(void)
ret = register_pernet_subsys(&dccp_net_ops);
if (ret < 0)
- goto out_pernet;
-
- ret = nf_ct_l4proto_register(&dccp_proto4);
- if (ret < 0)
- goto out_dccp4;
-
- ret = nf_ct_l4proto_register(&dccp_proto6);
+ return ret;
+ ret = nf_ct_l4proto_register(dccp_proto, ARRAY_SIZE(dccp_proto));
if (ret < 0)
- goto out_dccp6;
-
- return 0;
-out_dccp6:
- nf_ct_l4proto_unregister(&dccp_proto4);
-out_dccp4:
- unregister_pernet_subsys(&dccp_net_ops);
-out_pernet:
+ unregister_pernet_subsys(&dccp_net_ops);
return ret;
}
static void __exit nf_conntrack_proto_dccp_fini(void)
{
- nf_ct_l4proto_unregister(&dccp_proto6);
- nf_ct_l4proto_unregister(&dccp_proto4);
+ nf_ct_l4proto_unregister(dccp_proto, ARRAY_SIZE(dccp_proto));
unregister_pernet_subsys(&dccp_net_ops);
}
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 9a715f8..3054f73 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -393,18 +393,20 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
.init_net = gre_init_net,
};
+static struct nf_conntrack_l4proto *proto_gre[] = {
+ &nf_conntrack_l4proto_gre4,
+};
+
static int proto_gre_net_init(struct net *net)
{
- int ret = 0;
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_gre4);
- if (ret < 0)
- pr_err("nf_conntrack_gre4: pernet registration failed.\n");
- return ret;
+ return nf_ct_l4proto_pernet_register(net, proto_gre,
+ ARRAY_SIZE(proto_gre));
}
static void proto_gre_net_exit(struct net *net)
{
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_gre4);
+ nf_ct_l4proto_pernet_unregister(net, proto_gre,
+ ARRAY_SIZE(proto_gre));
nf_ct_gre_keymap_flush(net);
}
@@ -421,22 +423,16 @@ static int __init nf_ct_proto_gre_init(void)
ret = register_pernet_subsys(&proto_gre_net_ops);
if (ret < 0)
- goto out_pernet;
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_gre4);
+ return ret;
+ ret = nf_ct_l4proto_register(proto_gre, ARRAY_SIZE(proto_gre));
if (ret < 0)
- goto out_gre4;
-
- return 0;
-out_gre4:
- unregister_pernet_subsys(&proto_gre_net_ops);
-out_pernet:
+ unregister_pernet_subsys(&proto_gre_net_ops);
return ret;
}
static void __exit nf_ct_proto_gre_fini(void)
{
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_gre4);
+ nf_ct_l4proto_unregister(proto_gre, ARRAY_SIZE(proto_gre));
unregister_pernet_subsys(&proto_gre_net_ops);
}
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 982ea62..17c0ade 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -816,32 +816,21 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
.init_net = sctp_init_net,
};
+static struct nf_conntrack_l4proto *sctp_proto[] = {
+ &nf_conntrack_l4proto_sctp4,
+ &nf_conntrack_l4proto_sctp6,
+};
+
static int sctp_net_init(struct net *net)
{
- int ret = 0;
-
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_sctp4);
- if (ret < 0) {
- pr_err("nf_conntrack_sctp4: pernet registration failed.\n");
- goto out;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_sctp6);
- if (ret < 0) {
- pr_err("nf_conntrack_sctp6: pernet registration failed.\n");
- goto cleanup_sctp4;
- }
- return 0;
-
-cleanup_sctp4:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_sctp4);
-out:
- return ret;
+ return nf_ct_l4proto_pernet_register(net, sctp_proto,
+ ARRAY_SIZE(sctp_proto));
}
static void sctp_net_exit(struct net *net)
{
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_sctp6);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_sctp4);
+ nf_ct_l4proto_pernet_unregister(net, sctp_proto,
+ ARRAY_SIZE(sctp_proto));
}
static struct pernet_operations sctp_net_ops = {
@@ -857,29 +846,16 @@ static int __init nf_conntrack_proto_sctp_init(void)
ret = register_pernet_subsys(&sctp_net_ops);
if (ret < 0)
- goto out_pernet;
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_sctp4);
- if (ret < 0)
- goto out_sctp4;
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_sctp6);
+ return ret;
+ ret = nf_ct_l4proto_register(sctp_proto, ARRAY_SIZE(sctp_proto));
if (ret < 0)
- goto out_sctp6;
-
- return 0;
-out_sctp6:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
-out_sctp4:
- unregister_pernet_subsys(&sctp_net_ops);
-out_pernet:
+ unregister_pernet_subsys(&sctp_net_ops);
return ret;
}
static void __exit nf_conntrack_proto_sctp_fini(void)
{
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
+ nf_ct_l4proto_unregister(sctp_proto, ARRAY_SIZE(sctp_proto));
unregister_pernet_subsys(&sctp_net_ops);
}
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index 029206e..8cdb4b1 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -336,32 +336,21 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
.init_net = udplite_init_net,
};
+static struct nf_conntrack_l4proto *udplite_proto[] = {
+ &nf_conntrack_l4proto_udplite4,
+ &nf_conntrack_l4proto_udplite6,
+};
+
static int udplite_net_init(struct net *net)
{
- int ret = 0;
-
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_udplite4);
- if (ret < 0) {
- pr_err("nf_conntrack_udplite4: pernet registration failed.\n");
- goto out;
- }
- ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_udplite6);
- if (ret < 0) {
- pr_err("nf_conntrack_udplite6: pernet registration failed.\n");
- goto cleanup_udplite4;
- }
- return 0;
-
-cleanup_udplite4:
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udplite4);
-out:
- return ret;
+ return nf_ct_l4proto_pernet_register(net, udplite_proto,
+ ARRAY_SIZE(udplite_proto));
}
static void udplite_net_exit(struct net *net)
{
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udplite6);
- nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udplite4);
+ nf_ct_l4proto_pernet_unregister(net, udplite_proto,
+ ARRAY_SIZE(udplite_proto));
}
static struct pernet_operations udplite_net_ops = {
@@ -377,29 +366,16 @@ static int __init nf_conntrack_proto_udplite_init(void)
ret = register_pernet_subsys(&udplite_net_ops);
if (ret < 0)
- goto out_pernet;
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udplite4);
- if (ret < 0)
- goto out_udplite4;
-
- ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udplite6);
+ return ret;
+ ret = nf_ct_l4proto_register(udplite_proto, ARRAY_SIZE(udplite_proto));
if (ret < 0)
- goto out_udplite6;
-
- return 0;
-out_udplite6:
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
-out_udplite4:
- unregister_pernet_subsys(&udplite_net_ops);
-out_pernet:
+ unregister_pernet_subsys(&udplite_net_ops);
return ret;
}
static void __exit nf_conntrack_proto_udplite_exit(void)
{
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
- nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
+ nf_ct_l4proto_unregister(udplite_proto, ARRAY_SIZE(udplite_proto));
unregister_pernet_subsys(&udplite_net_ops);
}
--
2.7.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH nf-next v2] netfilter: conntrack: simplify init/uninit of L4 protocol trackers
2016-10-28 8:42 [PATCH nf-next v2] netfilter: conntrack: simplify init/uninit of L4 protocol trackers Davide Caratti
@ 2016-10-28 8:47 ` Pablo Neira Ayuso
2016-10-28 9:03 ` Pablo Neira Ayuso
2016-11-01 22:11 ` Pablo Neira Ayuso
1 sibling, 1 reply; 5+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-28 8:47 UTC (permalink / raw)
To: Davide Caratti
Cc: Patrick McHardy, Jozsef Kadlecsik, David S . Miller,
Alexey Kuznetsov, James Morris, Hideaki YOSHIFUJI,
netfilter-devel, coreteam
On Fri, Oct 28, 2016 at 10:42:09AM +0200, Davide Caratti wrote:
> modify registration and deregistration of layer-4 protocol trackers to
> facilitate inclusion of new elements into the current list of builtin
> protocols. Both builtin (TCP, UDP, ICMP) and non-builtin (DCCP, GRE, SCTP,
> UDPlite) layer-4 protocol trackers usually register/deregister themselves
> using consecutive calls to nf_ct_l4proto_{,pernet}_{,un}register(...).
> This sequence is interrupted and rolled back in case of error; in order to
> simplify addition of builtin protocols, the input of the above functions
> has been modified to allow registering/unregistering multiple protocols.
Applied, thanks Davide.
[...]
> include/net/netfilter/nf_conntrack_l4proto.h | 12 +-
> net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 76 +++-------
> net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 78 ++++------
> net/netfilter/nf_conntrack_proto.c | 191 +++++++++++++++----------
> net/netfilter/nf_conntrack_proto_dccp.c | 48 ++-----
> net/netfilter/nf_conntrack_proto_gre.c | 28 ++--
> net/netfilter/nf_conntrack_proto_sctp.c | 50 ++-----
> net/netfilter/nf_conntrack_proto_udplite.c | 50 ++-----
> 8 files changed, 222 insertions(+), 311 deletions(-)
Less boilerplate registration code, nice.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH nf-next v2] netfilter: conntrack: simplify init/uninit of L4 protocol trackers
2016-10-28 8:47 ` Pablo Neira Ayuso
@ 2016-10-28 9:03 ` Pablo Neira Ayuso
0 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-28 9:03 UTC (permalink / raw)
To: Davide Caratti
Cc: Patrick McHardy, Jozsef Kadlecsik, David S . Miller,
Alexey Kuznetsov, James Morris, Hideaki YOSHIFUJI,
netfilter-devel, coreteam
On Fri, Oct 28, 2016 at 10:47:52AM +0200, Pablo Neira Ayuso wrote:
> On Fri, Oct 28, 2016 at 10:42:09AM +0200, Davide Caratti wrote:
> > modify registration and deregistration of layer-4 protocol trackers to
> > facilitate inclusion of new elements into the current list of builtin
> > protocols. Both builtin (TCP, UDP, ICMP) and non-builtin (DCCP, GRE, SCTP,
> > UDPlite) layer-4 protocol trackers usually register/deregister themselves
> > using consecutive calls to nf_ct_l4proto_{,pernet}_{,un}register(...).
> > This sequence is interrupted and rolled back in case of error; in order to
> > simplify addition of builtin protocols, the input of the above functions
> > has been modified to allow registering/unregistering multiple protocols.
>
> Applied, thanks Davide.
Wait, let me get back to you with a bit more feedback. There are a few
nitpicks, and looking at this again, I guess we can improve
maintainability by splitting code into smaller functions.
Will get back to you in a while with more feedback, sorry,
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH nf-next v2] netfilter: conntrack: simplify init/uninit of L4 protocol trackers
2016-10-28 8:42 [PATCH nf-next v2] netfilter: conntrack: simplify init/uninit of L4 protocol trackers Davide Caratti
2016-10-28 8:47 ` Pablo Neira Ayuso
@ 2016-11-01 22:11 ` Pablo Neira Ayuso
2016-11-02 10:38 ` Davide Caratti
1 sibling, 1 reply; 5+ messages in thread
From: Pablo Neira Ayuso @ 2016-11-01 22:11 UTC (permalink / raw)
To: Davide Caratti
Cc: Patrick McHardy, Jozsef Kadlecsik, David S . Miller,
Alexey Kuznetsov, James Morris, Hideaki YOSHIFUJI,
netfilter-devel, coreteam
Minor nitpicks as I said, see below.
On Fri, Oct 28, 2016 at 10:42:09AM +0200, Davide Caratti wrote:
> modify registration and deregistration of layer-4 protocol trackers to
> facilitate inclusion of new elements into the current list of builtin
> protocols. Both builtin (TCP, UDP, ICMP) and non-builtin (DCCP, GRE, SCTP,
> UDPlite) layer-4 protocol trackers usually register/deregister themselves
> using consecutive calls to nf_ct_l4proto_{,pernet}_{,un}register(...).
> This sequence is interrupted and rolled back in case of error; in order to
> simplify addition of builtin protocols, the input of the above functions
> has been modified to allow registering/unregistering multiple protocols.
>
> Signed-off-by: Davide Caratti <dcaratti@redhat.com>
> ---
>
> Notes:
> v2:
> - reword commit message
> - change input of nf_ct_l4proto_{,pernet}_{,un}register(...) to
> accept arrays of struct nf_conntrack_l4proto *.
>
> please note:
> checkpatch.pl complains about coding style on some of the lines that
> were moved into a for() loop. This can be fixed too, but I propose to
> do that in a separate commit.
>
> include/net/netfilter/nf_conntrack_l4proto.h | 12 +-
> net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 76 +++-------
> net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 78 ++++------
> net/netfilter/nf_conntrack_proto.c | 191 +++++++++++++++----------
> net/netfilter/nf_conntrack_proto_dccp.c | 48 ++-----
> net/netfilter/nf_conntrack_proto_gre.c | 28 ++--
> net/netfilter/nf_conntrack_proto_sctp.c | 50 ++-----
> net/netfilter/nf_conntrack_proto_udplite.c | 50 ++-----
> 8 files changed, 222 insertions(+), 311 deletions(-)
>
> diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
> index de629f1..28f6d79 100644
> --- a/include/net/netfilter/nf_conntrack_l4proto.h
> +++ b/include/net/netfilter/nf_conntrack_l4proto.h
> @@ -126,13 +126,17 @@ void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
>
> /* Protocol pernet registration. */
> int nf_ct_l4proto_pernet_register(struct net *net,
> - struct nf_conntrack_l4proto *proto);
> + struct nf_conntrack_l4proto *proto[],
> + int num_proto);
You can use unsigned here:
unsigned int n);
> void nf_ct_l4proto_pernet_unregister(struct net *net,
> - struct nf_conntrack_l4proto *proto);
> + struct nf_conntrack_l4proto *proto[],
> + int num_proto);
Same here.
> /* Protocol global registration. */
> -int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto);
> -void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto);
> +int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto[],
> + int num_proto);
> +void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto[],
> + int num_proto);
Same thing here.
> /* Generic netlink helpers */
> int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
> diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
> index 713c09a..7130ed5 100644
> --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
> +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
> @@ -336,47 +336,34 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
> MODULE_ALIAS("ip_conntrack");
> MODULE_LICENSE("GPL");
>
> +static struct nf_conntrack_l4proto *builtin_l4proto4[] = {
> + &nf_conntrack_l4proto_tcp4,
> + &nf_conntrack_l4proto_udp4,
> + &nf_conntrack_l4proto_icmp,
> +};
> +
> static int ipv4_net_init(struct net *net)
> {
> int ret = 0;
>
> - ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_tcp4);
> - if (ret < 0) {
> - pr_err("nf_conntrack_tcp4: pernet registration failed\n");
> - goto out_tcp;
> - }
> - ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_udp4);
> - if (ret < 0) {
> - pr_err("nf_conntrack_udp4: pernet registration failed\n");
> - goto out_udp;
> - }
> - ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_icmp);
> - if (ret < 0) {
> - pr_err("nf_conntrack_icmp4: pernet registration failed\n");
> - goto out_icmp;
> - }
> + ret = nf_ct_l4proto_pernet_register(net, builtin_l4proto4,
> + ARRAY_SIZE(builtin_l4proto4));
> + if (ret < 0)
> + return ret;
> ret = nf_ct_l3proto_pernet_register(net, &nf_conntrack_l3proto_ipv4);
> if (ret < 0) {
> pr_err("nf_conntrack_ipv4: pernet registration failed\n");
> - goto out_ipv4;
> + nf_ct_l4proto_pernet_unregister(net, builtin_l4proto4,
> + ARRAY_SIZE(builtin_l4proto4));
> }
> - return 0;
> -out_ipv4:
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmp);
> -out_icmp:
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp4);
> -out_udp:
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp4);
> -out_tcp:
> return ret;
> }
>
> static void ipv4_net_exit(struct net *net)
> {
> nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv4);
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmp);
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp4);
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp4);
> + nf_ct_l4proto_pernet_unregister(net, builtin_l4proto4,
> + ARRAY_SIZE(builtin_l4proto4));
> }
>
> static struct pernet_operations ipv4_net_ops = {
> @@ -410,37 +397,21 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
> goto cleanup_pernet;
> }
>
> - ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_tcp4);
> - if (ret < 0) {
> - pr_err("nf_conntrack_ipv4: can't register tcp4 proto.\n");
> + ret = nf_ct_l4proto_register(builtin_l4proto4,
> + ARRAY_SIZE(builtin_l4proto4));
> + if (ret < 0)
> goto cleanup_hooks;
> - }
> -
> - ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udp4);
> - if (ret < 0) {
> - pr_err("nf_conntrack_ipv4: can't register udp4 proto.\n");
> - goto cleanup_tcp4;
> - }
> -
> - ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_icmp);
> - if (ret < 0) {
> - pr_err("nf_conntrack_ipv4: can't register icmpv4 proto.\n");
> - goto cleanup_udp4;
> - }
>
> ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv4);
> if (ret < 0) {
> pr_err("nf_conntrack_ipv4: can't register ipv4 proto.\n");
> - goto cleanup_icmpv4;
> + goto cleanup_l4proto;
Is this correct?
nf_ct_l4proto_register() has failed, then we jump to cleanup_l4proto ...
> }
>
> return ret;
> - cleanup_icmpv4:
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmp);
> - cleanup_udp4:
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp4);
> - cleanup_tcp4:
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
> +cleanup_l4proto:
> + nf_ct_l4proto_unregister(builtin_l4proto4,
> + ARRAY_SIZE(builtin_l4proto4));
... that is unregistering what we failed to register. So
nf_ct_l4proto_register() should clean up this internally.
> cleanup_hooks:
> nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
> cleanup_pernet:
> @@ -454,9 +425,8 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void)
> {
> synchronize_net();
> nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmp);
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp4);
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
> + nf_ct_l4proto_unregister(builtin_l4proto4,
> + ARRAY_SIZE(builtin_l4proto4));
> nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
> unregister_pernet_subsys(&ipv4_net_ops);
> nf_unregister_sockopt(&so_getorigdst);
> diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
> index 963ee38..500be28 100644
> --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
> +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
> @@ -336,47 +336,35 @@ static struct nf_sockopt_ops so_getorigdst6 = {
> .owner = THIS_MODULE,
> };
>
> +static struct nf_conntrack_l4proto *builtin_l4proto6[] = {
> + &nf_conntrack_l4proto_tcp6,
> + &nf_conntrack_l4proto_udp6,
> + &nf_conntrack_l4proto_icmpv6,
> +};
> +
> static int ipv6_net_init(struct net *net)
> {
> int ret = 0;
>
> - ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_tcp6);
> - if (ret < 0) {
> - pr_err("nf_conntrack_tcp6: pernet registration failed\n");
> - goto out;
> - }
> - ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_udp6);
> - if (ret < 0) {
> - pr_err("nf_conntrack_udp6: pernet registration failed\n");
> - goto cleanup_tcp6;
> - }
> - ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_icmpv6);
> - if (ret < 0) {
> - pr_err("nf_conntrack_icmp6: pernet registration failed\n");
> - goto cleanup_udp6;
> - }
> + ret = nf_ct_l4proto_pernet_register(net, builtin_l4proto6,
> + ARRAY_SIZE(builtin_l4proto6));
> + if (ret < 0)
> + return ret;
> +
> ret = nf_ct_l3proto_pernet_register(net, &nf_conntrack_l3proto_ipv6);
> if (ret < 0) {
> pr_err("nf_conntrack_ipv6: pernet registration failed.\n");
> - goto cleanup_icmpv6;
> + nf_ct_l4proto_pernet_unregister(net, builtin_l4proto6,
> + ARRAY_SIZE(builtin_l4proto6));
> }
> - return 0;
> - cleanup_icmpv6:
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmpv6);
> - cleanup_udp6:
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp6);
> - cleanup_tcp6:
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp6);
> - out:
> return ret;
> }
>
> static void ipv6_net_exit(struct net *net)
> {
> nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv6);
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmpv6);
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp6);
> - nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp6);
> + nf_ct_l4proto_pernet_unregister(net, builtin_l4proto6,
> + ARRAY_SIZE(builtin_l4proto6));
> }
>
> static struct pernet_operations ipv6_net_ops = {
> @@ -409,37 +397,20 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
> goto cleanup_pernet;
> }
>
> - ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_tcp6);
> - if (ret < 0) {
> - pr_err("nf_conntrack_ipv6: can't register tcp6 proto.\n");
> + ret = nf_ct_l4proto_register(builtin_l4proto6,
> + ARRAY_SIZE(builtin_l4proto6));
> + if (ret < 0)
> goto cleanup_hooks;
> - }
> -
> - ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udp6);
> - if (ret < 0) {
> - pr_err("nf_conntrack_ipv6: can't register udp6 proto.\n");
> - goto cleanup_tcp6;
> - }
> -
> - ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_icmpv6);
> - if (ret < 0) {
> - pr_err("nf_conntrack_ipv6: can't register icmpv6 proto.\n");
> - goto cleanup_udp6;
> - }
>
> ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv6);
> if (ret < 0) {
> pr_err("nf_conntrack_ipv6: can't register ipv6 proto.\n");
> - goto cleanup_icmpv6;
> + goto cleanup_l4proto;
Same thing here.
> }
> return ret;
> -
> - cleanup_icmpv6:
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
> - cleanup_udp6:
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp6);
> - cleanup_tcp6:
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
> +cleanup_l4proto:
> + nf_ct_l4proto_unregister(builtin_l4proto6,
> + ARRAY_SIZE(builtin_l4proto6));
> cleanup_hooks:
> nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
> cleanup_pernet:
> @@ -453,9 +424,8 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
> {
> synchronize_net();
> nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp6);
> - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
> + nf_ct_l4proto_unregister(builtin_l4proto6,
> + ARRAY_SIZE(builtin_l4proto6));
> nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
> unregister_pernet_subsys(&ipv6_net_ops);
> nf_unregister_sockopt(&so_getorigdst6);
> diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
> index 8d2c7d8..10e609c 100644
> --- a/net/netfilter/nf_conntrack_proto.c
> +++ b/net/netfilter/nf_conntrack_proto.c
> @@ -281,99 +281,136 @@ void nf_ct_l4proto_unregister_sysctl(struct net *net,
>
> /* FIXME: Allow NULL functions and sub in pointers to generic for
> them. --RR */
> -int nf_ct_l4proto_register(struct nf_conntrack_l4proto *l4proto)
> +int nf_ct_l4proto_register(struct nf_conntrack_l4proto *l4proto[],
> + int num_proto)
> {
> - int ret = 0;
> -
> - if (l4proto->l3proto >= PF_MAX)
> - return -EBUSY;
> -
> - if ((l4proto->to_nlattr && !l4proto->nlattr_size)
> - || (l4proto->tuple_to_nlattr && !l4proto->nlattr_tuple_size))
> - return -EINVAL;
> + struct nf_conntrack_l4proto *l4;
> + int ret = 0, j;
> +
> + for (j = 0; j < num_proto; j++) {
> + l4 = l4proto[j];
> + if (l4->l3proto >= PF_MAX)
> + return -EBUSY;
> + if ((l4->to_nlattr && !l4->nlattr_size)
> + || (l4->tuple_to_nlattr && !l4->nlattr_tuple_size))
Not your fault, but while at it, fix this coding style:
if ((l4->to_nlattr && !l4->nlattr_size) ||
(l4->tuple_to_nlattr && !l4->nlattr_tuple_size))
> + return -EINVAL;
> + }
>
> mutex_lock(&nf_ct_proto_mutex);
> - if (!nf_ct_protos[l4proto->l3proto]) {
> - /* l3proto may be loaded latter. */
> - struct nf_conntrack_l4proto __rcu **proto_array;
> - int i;
> -
> - proto_array = kmalloc(MAX_NF_CT_PROTO *
> - sizeof(struct nf_conntrack_l4proto *),
> - GFP_KERNEL);
> - if (proto_array == NULL) {
> - ret = -ENOMEM;
> - goto out_unlock;
> - }
> + for (j = 0; j < num_proto; j++) {
I wonder if you can wrap this code below into a function, to save one
level of indentation and improve maintainability. Probably in an
initial patch so the indent happening here doesn't generate so many
changes. This becomes harder to review.
Suggested name: nf_ct_l4proto_register_one()
> + l4 = l4proto[j];
> + if (!nf_ct_protos[l4->l3proto]) {
> + /* l3proto may be loaded latter. */
> + struct nf_conntrack_l4proto __rcu **proto_array;
> + int i;
> +
> + proto_array = kmalloc(MAX_NF_CT_PROTO *
> + sizeof(l4), GFP_KERNEL);
> + if (proto_array == NULL) {
> + ret = -ENOMEM;
> + break;
> + }
>
> - for (i = 0; i < MAX_NF_CT_PROTO; i++)
> - RCU_INIT_POINTER(proto_array[i], &nf_conntrack_l4proto_generic);
> + for (i = 0; i < MAX_NF_CT_PROTO; i++)
> + RCU_INIT_POINTER(proto_array[i],
> + &nf_conntrack_l4proto_generic);
> +
> + /* Before making proto_array visible to lockless readers
> + * we must make sure its content is committed to memory.
> + */
> + smp_wmb();
> +
> + nf_ct_protos[l4->l3proto] = proto_array;
> + } else if (rcu_dereference_protected(
> + nf_ct_protos[l4->l3proto][l4->l4proto],
> + lockdep_is_held(&nf_ct_proto_mutex)
> + ) != &nf_conntrack_l4proto_generic) {
> + ret = -EBUSY;
> + break;
> + }
>
> - /* Before making proto_array visible to lockless readers,
> - * we must make sure its content is committed to memory.
> - */
> - smp_wmb();
> + l4->nla_size = 0;
> + if (l4->nlattr_size)
> + l4->nla_size += l4->nlattr_size();
> + if (l4->nlattr_tuple_size)
> + l4->nla_size += 3 * l4->nlattr_tuple_size();
>
> - nf_ct_protos[l4proto->l3proto] = proto_array;
> - } else if (rcu_dereference_protected(
> - nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
> - lockdep_is_held(&nf_ct_proto_mutex)
> - ) != &nf_conntrack_l4proto_generic) {
> - ret = -EBUSY;
> - goto out_unlock;
> + rcu_assign_pointer(nf_ct_protos[l4->l3proto][l4->l4proto], l4);
> + }
> + if (j < num_proto) {
> + int ver = l4->l3proto == PF_INET6 ? 6 : 4;
> +
> + pr_err("nf_conntrack_ipv%d: can't register %s%d proto.\n",
> + ver, l4->name, ver);
> + while (--j >= 0) {
> + l4 = l4proto[j];
> + BUG_ON(rcu_dereference_protected(
> + nf_ct_protos[l4->l3proto][l4->l4proto],
> + lockdep_is_held(&nf_ct_proto_mutex)
> + ) != l4);
> + rcu_assign_pointer(
> + nf_ct_protos[l4->l3proto][l4->l4proto],
> + &nf_conntrack_l4proto_generic);
> + }
> }
> -
> - l4proto->nla_size = 0;
> - if (l4proto->nlattr_size)
> - l4proto->nla_size += l4proto->nlattr_size();
> - if (l4proto->nlattr_tuple_size)
> - l4proto->nla_size += 3 * l4proto->nlattr_tuple_size();
> -
> - rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
> - l4proto);
> -out_unlock:
> mutex_unlock(&nf_ct_proto_mutex);
> return ret;
> }
> EXPORT_SYMBOL_GPL(nf_ct_l4proto_register);
>
> int nf_ct_l4proto_pernet_register(struct net *net,
> - struct nf_conntrack_l4proto *l4proto)
> + struct nf_conntrack_l4proto *l4proto[],
> + int num_proto)
> {
> - int ret = 0;
> struct nf_proto_net *pn = NULL;
> + int i, ret = 0;
>
> - if (l4proto->init_net) {
> - ret = l4proto->init_net(net, l4proto->l3proto);
> - if (ret < 0)
> - goto out;
> - }
> + for (i = 0; i < num_proto; i++) {
As above, same thing here.
> + if (l4proto[i]->init_net) {
> + ret = l4proto[i]->init_net(net, l4proto[i]->l3proto);
> + if (ret < 0)
> + break;
> + }
>
> - pn = nf_ct_l4proto_net(net, l4proto);
> - if (pn == NULL)
> - goto out;
> + pn = nf_ct_l4proto_net(net, l4proto[i]);
> + if (pn == NULL)
> + continue;
>
> - ret = nf_ct_l4proto_register_sysctl(net, pn, l4proto);
> - if (ret < 0)
> - goto out;
> + ret = nf_ct_l4proto_register_sysctl(net, pn, l4proto[i]);
> + if (ret < 0)
> + break;
>
> - pn->users++;
> -out:
> + pn->users++;
> + }
> + if (i < num_proto) {
> + pr_err("nf_conntrack_%s%d: pernet registration failed.\n",
> + l4proto[i]->name,
> + l4proto[i]->l3proto == PF_INET6 ? 6 : 4);
> + nf_ct_l4proto_pernet_unregister(net, l4proto, i);
> + }
> return ret;
> }
> EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_register);
>
> -void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
> +void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto[],
> + int num_proto)
> {
> - BUG_ON(l4proto->l3proto >= PF_MAX);
> + int i;
> +
> + for (i = 0; i < num_proto; i++)
> + BUG_ON(l4proto[i]->l3proto >= PF_MAX);
>
> mutex_lock(&nf_ct_proto_mutex);
> - BUG_ON(rcu_dereference_protected(
> - nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
> - lockdep_is_held(&nf_ct_proto_mutex)
> - ) != l4proto);
> - rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
> - &nf_conntrack_l4proto_generic);
> + while (--num_proto >= 0) {
> + struct nf_conntrack_l4proto *l4 = l4proto[num_proto];
> +
> + BUG_ON(rcu_dereference_protected(
> + nf_ct_protos[l4->l3proto][l4->l4proto],
> + lockdep_is_held(&nf_ct_proto_mutex)
> + ) != l4);
> + rcu_assign_pointer(nf_ct_protos[l4->l3proto][l4->l4proto],
> + &nf_conntrack_l4proto_generic);
> + }
And same comment as above here.
> mutex_unlock(&nf_ct_proto_mutex);
>
> synchronize_rcu();
> @@ -381,19 +418,23 @@ void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
> EXPORT_SYMBOL_GPL(nf_ct_l4proto_unregister);
>
> void nf_ct_l4proto_pernet_unregister(struct net *net,
> - struct nf_conntrack_l4proto *l4proto)
> + struct nf_conntrack_l4proto *l4proto[],
> + int num_proto)
> {
> struct nf_proto_net *pn = NULL;
>
> - pn = nf_ct_l4proto_net(net, l4proto);
> - if (pn == NULL)
> - return;
> + while (--num_proto >= 0) {
> + pn = nf_ct_l4proto_net(net, l4proto[num_proto]);
> + if (pn == NULL)
> + continue;
>
> - pn->users--;
> - nf_ct_l4proto_unregister_sysctl(net, pn, l4proto);
> + pn->users--;
> + nf_ct_l4proto_unregister_sysctl(net, pn, l4proto[num_proto]);
>
> - /* Remove all contrack entries for this protocol */
> - nf_ct_iterate_cleanup(net, kill_l4proto, l4proto, 0, 0);
> + /* Remove all contrack entries for this protocol */
> + nf_ct_iterate_cleanup(net, kill_l4proto, l4proto[num_proto],
> + 0, 0);
And same thing here, wrap this code into a function so you don't need
to reindent.
Thanks for your patience.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH nf-next v2] netfilter: conntrack: simplify init/uninit of L4 protocol trackers
2016-11-01 22:11 ` Pablo Neira Ayuso
@ 2016-11-02 10:38 ` Davide Caratti
0 siblings, 0 replies; 5+ messages in thread
From: Davide Caratti @ 2016-11-02 10:38 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: Patrick McHardy, Jozsef Kadlecsik, David S . Miller,
Alexey Kuznetsov, James Morris, Hideaki YOSHIFUJI,
netfilter-devel, coreteam
On Tue, 2016-11-01 at 23:11 +0100, Pablo Neira Ayuso wrote:
> Minor nitpicks as I said, see below.
>
hello Pablo,
thank you for reviewing!
> On Fri, Oct 28, 2016 at 10:42:09AM +0200, Davide Caratti wrote:
> >
> > static struct pernet_operations ipv4_net_ops = {
> > @@ -410,37 +397,21 @@ static int __init
> > nf_conntrack_l3proto_ipv4_init(void)
> > goto cleanup_pernet;
> > }
> >
> > - ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_tcp4);
> > - if (ret < 0) {
> > - pr_err("nf_conntrack_ipv4: can't register tcp4
> > proto.\n");
> > + ret = nf_ct_l4proto_register(builtin_l4proto4,
> > + ARRAY_SIZE(builtin_l4proto4));
> > + if (ret < 0)
> > goto cleanup_hooks;
> > - }
> > -
> > - ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udp4);
> > - if (ret < 0) {
> > - pr_err("nf_conntrack_ipv4: can't register udp4
> > proto.\n");
> > - goto cleanup_tcp4;
> > - }
> > -
> > - ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_icmp);
> > - if (ret < 0) {
> > - pr_err("nf_conntrack_ipv4: can't register icmpv4
> > proto.\n");
> > - goto cleanup_udp4;
> > - }
> >
> > ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv4);
> > if (ret < 0) {
> > pr_err("nf_conntrack_ipv4: can't register ipv4
> > proto.\n");
> > - goto cleanup_icmpv4;
> > + goto cleanup_l4proto;
>
> Is this correct?
>
> nf_ct_l4proto_register() has failed, then we jump to cleanup_l4proto ...
>
It looks correct to me - and the behavior is not changed with this patch:
when the code hits
if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register ipv4 proto.\n");
goto cleanup_icmpv4; /* before patch */
}
or
if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register ipv4 proto.\n");
goto cleanup_l4proto; /* after patch */
}
nf_ct_l4proto_register() surely didn't fail: 'ret' is return value of
nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv4). 'cleanup_l4proto'
label is there to unregister all L4 protocols in the builtin list, in case
any failure follows a successful call to nf_ct_l4proto_register().
> >
> > }
> >
> > return ret;
> > - cleanup_icmpv4:
> > - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmp);
> > - cleanup_udp4:
> > - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp4);
> > - cleanup_tcp4:
> > - nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
> > +cleanup_l4proto:
> > + nf_ct_l4proto_unregister(builtin_l4proto4,
> > + ARRAY_SIZE(builtin_l4proto4));
>
> ... that is unregistering what we failed to register. So
> nf_ct_l4proto_register() should clean up this internally.
Yes, and the patched code already does this actually. If a failure happens
in nf_ct_l4proto_register(), rollback of all previously registered L4
protocols in the builtin list is done before function returns a negative
value of 'ret':
if (j < num_proto) {
int ver = l4->l3proto == PF_INET6 ? 6 : 4;
pr_err(".... "); /* <-- same printout as before patch */
while (--j >= 0) {
l4 = l4proto[j];
rcu_assign_pointer(
nf_ct_protos[l4->l3proto][l4->l4proto],
&nf_conntrack_l4proto_generic);
}
}
and in this case
if (ret < 0)
goto cleanup_hooks;
is hit.
But I understand it's not so evident, nf_ct_l4proto_register() is very
long
and contains two lines copypasted from nf_ct_l4proto_unregister().
So I will follow the advice you did below and write
nf_ct_l4proto_unregister_one()
that will be called in the while() loops of nf_ct_l4proto_register()
when the function is going to return a negative value, and in
nf_ct_l4proto_unregister().
> > + return -EINVAL;
> > + }
> >
> > mutex_lock(&nf_ct_proto_mutex);
> > - if (!nf_ct_protos[l4proto->l3proto]) {
> > - /* l3proto may be loaded latter. */
> > - struct nf_conntrack_l4proto __rcu **proto_array;
> > - int i;
> > -
> > - proto_array = kmalloc(MAX_NF_CT_PROTO *
> > - sizeof(struct
> > nf_conntrack_l4proto *),
> > - GFP_KERNEL);
> > - if (proto_array == NULL) {
> > - ret = -ENOMEM;
> > - goto out_unlock;
> > - }
> > + for (j = 0; j < num_proto; j++) {
>
> I wonder if you can wrap this code below into a function, to save one
> level of indentation and improve maintainability. Probably in an
> initial patch so the indent happening here doesn't generate so many
> changes. This becomes harder to review.
>
> Suggested name: nf_ct_l4proto_register_one()
ok,
<...>
> And same thing here, wrap this code into a function so you don't need
> to reindent.
and ok. Also this one is a preparatory commit for something else (i.e.
builtinization of conntrack for SCTP, DCCP, UDPlite), so I'm going to
repost this patch as a series.
regards,
--
davide
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-11-02 10:38 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-28 8:42 [PATCH nf-next v2] netfilter: conntrack: simplify init/uninit of L4 protocol trackers Davide Caratti
2016-10-28 8:47 ` Pablo Neira Ayuso
2016-10-28 9:03 ` Pablo Neira Ayuso
2016-11-01 22:11 ` Pablo Neira Ayuso
2016-11-02 10:38 ` Davide Caratti
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.