Attached four patches fixes conntracks for IPv6.

Ola Lundqvist wrote:
Thanks for this clarification.

Kir, please list the corrections that you can find. If they are more on improvement please mark that and we can discuss it further.

Best regards,

// Ola

Quoting maximilian attems <m...@stro.at>:

On Mon, Mar 16, 2009 at 02:19:39PM +0300, Kir Kolyshkin wrote:

So we can either disable IPv6 in config or fix it. It's up to you/Dann
to decide. I'd go with fixing.

Speaking of IPv6, we also have a bunch of patches for ipv6 conntracks in
containers which I haven't sent since it looks more like a new
functionality rather than a bugfix.

yes please fix it, we have explicit demand for ipv6
also ipv6 support is a release goal of lenny,
so such updates should just go in.






>From 2c1b2f728e1ae136ec1713bfec9892cf7cd656b6 Mon Sep 17 00:00:00 2001
From: Vitaliy Gusev <vgu...@openvz.org>
Date: Wed, 24 Sep 2008 14:51:32 +0400
Subject: [PATCH] conntrack: Allocate/free ve_nf_conntrack_l3proto_ipv6

Virtualize nf_ct_ipv6_sysctl_table and allocate/free 
ve_nf_conntrack_l3proto_ipv6.

Per VE nf_ct_ipv6_sysctl_table sysctl registration looks like:

        nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
                nf_ct_l3proto_register_sysctl(proto);
                        nf_ct_register_sysctl(&l3proto->ctl_table_header,
                                                l3proto->ctl_table_path,
                                                l3proto->ctl_table, NULL);

So ve_nf_conntrack_l3proto_ipv6 is allocated per VE as l3proto sysctl
registration changes l3proto->ctl_table_header.

Signed-off-by: Vitaliy Gusev <vgu...@openvz.org>
Signed-off-by: Pavel Emelyanov <xe...@openvz.org>
---
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |   34 +++++++++++++++++++++++-
 net/ipv6/netfilter/nf_conntrack_reasm.c        |   25 +++++++++++++++++-
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c 
b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 71b15ab..8623b7c 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -360,6 +360,33 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.koza...@toshiba.co.jp>");
 
+static int nf_ct_proto_ipv6_init_net(struct net *net)
+{
+       struct nf_conntrack_l3proto *ipv6;
+
+       ipv6 = &nf_conntrack_l3proto_ipv6;
+       if (net != &init_net) {
+               ipv6 = kmemdup(ipv6,
+                              sizeof(struct nf_conntrack_l3proto), GFP_KERNEL);
+               if (!ipv6)
+                       return -ENOMEM;
+       }
+
+       ve_nf_conntrack_l3proto_ipv6 = ipv6;
+       return 0;
+}
+
+static void nf_ct_proto_ipv6_exit_net(struct net *net)
+{
+       if (net != &init_net)
+               kfree(ve_nf_conntrack_l3proto_ipv6);
+}
+
+static struct pernet_operations nf_ct_ipv6_ops = {
+       .init = nf_ct_proto_ipv6_init_net,
+       .exit = nf_ct_proto_ipv6_exit_net,
+};
+
 int init_nf_ct_l3proto_ipv6(void)
 {
        int ret = -ENOMEM;
@@ -435,10 +462,12 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
 
        need_conntrack();
 
+       register_pernet_subsys(&nf_ct_ipv6_ops);
+
        ret = nf_ct_frag6_init();
        if (ret < 0) {
                printk("nf_conntrack_ipv6: can't initialize frag6.\n");
-               return ret;
+               goto unreg_subsys;
        }
 
        ret = init_nf_ct_l3proto_ipv6();
@@ -461,6 +490,8 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
 
 cleanup_frag6:
        nf_ct_frag6_cleanup();
+unreg_subsys:
+       unregister_pernet_subsys(&nf_ct_ipv6_ops);
        return ret;
 }
 
@@ -473,6 +504,7 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
        nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
        fini_nf_ct_l3proto_ipv6();
        nf_ct_frag6_cleanup();
+       unregister_pernet_subsys(&nf_ct_ipv6_ops);
 }
 
 module_init(nf_conntrack_l3proto_ipv6_init);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c 
b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 9faaa59..e8e4112 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -40,6 +40,7 @@
 #include <net/ndisc.h>
 #include <net/addrconf.h>
 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
 #include <linux/sysctl.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
@@ -696,17 +697,39 @@ static int nf_ct_frag6_init_net(struct net *net)
 {
        struct netns_frags *frags = &net->ipv6.ct_frags;
 
+#ifdef CONFIG_SYSCTL
+       if (net != &init_net) {
+               struct nf_conntrack_l3proto *ipv6 =
+                       ve_nf_conntrack_l3proto_ipv6;
+
+               ipv6->ctl_table = kmemdup(nf_ct_ipv6_sysctl_table,
+                                         sizeof(nf_ct_ipv6_sysctl_table),
+                                         GFP_KERNEL);
+               if (!ipv6->ctl_table)
+                       return -ENOMEM;
+
+               ipv6->ctl_table_header = NULL;
+               ipv6->ctl_table_path = nf_net_netfilter_sysctl_path;
+
+               ipv6->ctl_table[0].data = &frags->timeout;
+               ipv6->ctl_table[1].data = &frags->low_thresh;
+               ipv6->ctl_table[2].data = &frags->high_thresh;
+       }
+#endif
        frags->timeout = IPV6_FRAG_TIMEOUT;
        frags->high_thresh = 256 * 1024;
        frags->low_thresh = 192 * 1024;
        inet_frags_init_net(frags);
 
-       return 0; /* FIXME : sysctls */
+       return 0;
 }
 
 static void nf_ct_frag6_exit_net(struct net *net)
 {
        inet_frags_exit_net(&net->ipv6.ct_frags, &nf_frags);
+       if (net != &init_net)
+               kfree(ve_nf_conntrack_l3proto_ipv6->ctl_table);
+
 }
 
 static struct pernet_operations nf_ct_frag6_ops = {
-- 
1.6.0.6

>From e29a555d7d8f88dbfcaed541e340a4e3977c76aa Mon Sep 17 00:00:00 2001
From: Vitaliy Gusev <vgu...@openvz.org>
Date: Wed, 24 Sep 2008 14:52:08 +0400
Subject: [PATCH] ct: Move _nf_conntrack_l3proto_ipv6 to net namespace

Move _nf_conntrack_l3proto_ipv6 from ve_nf_conntrack to net namespace.

The patch [4/5] "conntrack: Allocate/free ve_nf_conntrack_l3proto_ipv6"
has lines:

+static int nf_ct_proto_ipv6_init_net(struct net *net)
...
+       ve_nf_conntrack_l3proto_ipv6 = ipv6;
+       return 0;

ve_nf_conntrack_l3proto_ipv6 points to not allocated memory, as this function
is called during net initialization (conntrack isn't initialized yet).

So move ve_nf_conntrack_l3proto_ipv6 to net namespace

Signed-off-by: Vitaliy Gusev <vgu...@openvz.org>
Signed-off-by: Pavel Emelyanov <xe...@openvz.org>
---
 include/linux/ve.h                             |    1 -
 include/net/netfilter/nf_conntrack_l3proto.h   |    2 --
 include/net/netns/ipv6.h                       |    4 ++++
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |   12 ++++++++----
 net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c |    3 ++-
 net/ipv6/netfilter/nf_conntrack_reasm.c        |    4 ++--
 6 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/include/linux/ve.h b/include/linux/ve.h
index 970aadc..2180c1f 100644
--- a/include/linux/ve.h
+++ b/include/linux/ve.h
@@ -107,7 +107,6 @@ struct ve_nf_conntrack {
        struct nf_conntrack_l4proto     **_nf_ct_protos[PF_MAX];
        /* l3 protocols sysctl tables: */
        struct nf_conntrack_l3proto     *_nf_conntrack_l3proto_ipv4;
-       struct nf_conntrack_l3proto     *_nf_conntrack_l3proto_ipv6;
        struct nf_conntrack_l3proto     *_nf_ct_l3protos[AF_MAX];
        /* sysctl standalone stuff: */
        struct ctl_table_header         *_nf_ct_sysctl_header;
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h 
b/include/net/netfilter/nf_conntrack_l3proto.h
index 6b1f720..ac81973 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -79,14 +79,12 @@ struct nf_conntrack_l3proto
 #if defined(CONFIG_VE_IPTABLES) && defined(CONFIG_SYSCTL)
 #define ve_nf_ct_l3protos              ve_nf_ct3->_nf_ct_l3protos
 #define ve_nf_conntrack_l3proto_ipv4   (ve_nf_ct3->_nf_conntrack_l3proto_ipv4)
-#define        ve_nf_conntrack_l3proto_ipv6    
(ve_nf_ct3->_nf_conntrack_l3proto_ipv6)
 #define ve_nf_conntrack_max            (ve_nf_ct3->_nf_conntrack_max)
 #define ve_nf_conntrack_count          (ve_nf_ct3->_nf_conntrack_count)
 #define ve_nf_conntrack_checksum       (ve_nf_ct3->_nf_conntrack_checksum)
 #else /* !CONFIG_VE_IPTABLES || !CONFIG_SYSCTL: */
 #define ve_nf_ct_l3protos              nf_ct_l3protos
 #define ve_nf_conntrack_l3proto_ipv4   &nf_conntrack_l3proto_ipv4
-#define ve_nf_conntrack_l3proto_ipv6   &nf_conntrack_l3proto_ipv6
 #define ve_nf_conntrack_max            nf_conntrack_max
 #define ve_nf_conntrack_count          nf_conntrack_count
 #define ve_nf_conntrack_checksum       nf_conntrack_checksum
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index c368713..11c8cc8 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -33,6 +33,10 @@ struct netns_ipv6 {
        struct ipv6_devconf     *devconf_dflt;
        struct netns_frags      frags;
        struct netns_frags      ct_frags;
+
+#ifdef CONFIG_SYSCTL
+       struct nf_conntrack_l3proto *nf_conntrack_l3proto_ipv6;
+#endif
 #ifdef CONFIG_NETFILTER
        struct xt_table         *ip6table_filter;
        struct xt_table         *ip6table_mangle;
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c 
b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 8623b7c..8288efc 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -372,14 +372,14 @@ static int nf_ct_proto_ipv6_init_net(struct net *net)
                        return -ENOMEM;
        }
 
-       ve_nf_conntrack_l3proto_ipv6 = ipv6;
+       net->ipv6.nf_conntrack_l3proto_ipv6 = ipv6;
        return 0;
 }
 
 static void nf_ct_proto_ipv6_exit_net(struct net *net)
 {
        if (net != &init_net)
-               kfree(ve_nf_conntrack_l3proto_ipv6);
+               kfree(net->ipv6.nf_conntrack_l3proto_ipv6);
 }
 
 static struct pernet_operations nf_ct_ipv6_ops = {
@@ -389,6 +389,8 @@ static struct pernet_operations nf_ct_ipv6_ops = {
 
 int init_nf_ct_l3proto_ipv6(void)
 {
+       struct net *net = get_exec_env()->ve_netns;
+
        int ret = -ENOMEM;
 
 #ifdef CONFIG_VE_IPTABLES
@@ -417,7 +419,7 @@ int init_nf_ct_l3proto_ipv6(void)
                goto unreg_udp;
        }
 
-       ret = nf_conntrack_l3proto_register(ve_nf_conntrack_l3proto_ipv6);
+       ret = 
nf_conntrack_l3proto_register(net->ipv6.nf_conntrack_l3proto_ipv6);
        if (ret < 0) {
                printk("nf_conntrack_ipv6: can't register ipv6\n");
                goto unreg_icmpv6;
@@ -443,7 +445,9 @@ EXPORT_SYMBOL(init_nf_ct_l3proto_ipv6);
 
 void fini_nf_ct_l3proto_ipv6(void)
 {
-       nf_conntrack_l3proto_unregister(ve_nf_conntrack_l3proto_ipv6);
+       struct net *net = get_exec_env()->ve_netns;
+
+       nf_conntrack_l3proto_unregister(net->ipv6.nf_conntrack_l3proto_ipv6);
        nf_conntrack_l4proto_unregister(ve_nf_conntrack_l4proto_icmpv6);
        nf_conntrack_l4proto_unregister(ve_nf_conntrack_l4proto_udp6);
        nf_conntrack_l4proto_unregister(ve_nf_conntrack_l4proto_tcp6);
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c 
b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index cae064f..20e8750 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -132,6 +132,7 @@ icmpv6_error_message(struct sk_buff *skb,
        struct nf_conntrack_tuple intuple, origtuple;
        const struct nf_conntrack_tuple_hash *h;
        const struct nf_conntrack_l4proto *inproto;
+       struct net *net = get_exec_env()->ve_netns;
 
        NF_CT_ASSERT(skb->nfct == NULL);
 
@@ -151,7 +152,7 @@ icmpv6_error_message(struct sk_buff *skb,
        /* Ordinarily, we'd expect the inverted tupleproto, but it's
           been preserved inside the ICMP. */
        if (!nf_ct_invert_tuple(&intuple, &origtuple,
-                               ve_nf_conntrack_l3proto_ipv6, inproto)) {
+                               net->ipv6.nf_conntrack_l3proto_ipv6, inproto)) {
                pr_debug("icmpv6_error: Can't invert tuple\n");
                return -NF_ACCEPT;
        }
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c 
b/net/ipv6/netfilter/nf_conntrack_reasm.c
index e8e4112..c2236df 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -700,7 +700,7 @@ static int nf_ct_frag6_init_net(struct net *net)
 #ifdef CONFIG_SYSCTL
        if (net != &init_net) {
                struct nf_conntrack_l3proto *ipv6 =
-                       ve_nf_conntrack_l3proto_ipv6;
+                       net->ipv6.nf_conntrack_l3proto_ipv6;
 
                ipv6->ctl_table = kmemdup(nf_ct_ipv6_sysctl_table,
                                          sizeof(nf_ct_ipv6_sysctl_table),
@@ -728,7 +728,7 @@ static void nf_ct_frag6_exit_net(struct net *net)
 {
        inet_frags_exit_net(&net->ipv6.ct_frags, &nf_frags);
        if (net != &init_net)
-               kfree(ve_nf_conntrack_l3proto_ipv6->ctl_table);
+               kfree(net->ipv6.nf_conntrack_l3proto_ipv6->ctl_table);
 
 }
 
-- 
1.6.0.6

>From 43553442d9467e2cdca7be044ff0cd497abe987f Mon Sep 17 00:00:00 2001
From: Vitaliy Gusev <vgu...@openvz.org>
Date: Thu, 25 Sep 2008 13:06:13 +0400
Subject: [PATCH] conntrack: fix oops in nf_ct_frag6_gather

skb->dev == NULL in NF_LOCAL_OUT hook level. So dev_inet(skb->dev)
in nf_ct_frag6_gather() function causes OOPS.
Pass directly net namespace to nf_ct_frag6_gather() as parameter
to avoid this issue.

(#122210)

Signed-off-by: Vitaliy Gusev <vgu...@openvz.org>
Signed-off-by: Pavel Emelyanov <xe...@openvz.org>
---
 include/net/netfilter/ipv6/nf_conntrack_ipv6.h |    3 ++-
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |    3 ++-
 net/ipv6/netfilter/nf_conntrack_reasm.c        |    4 ++--
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h 
b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
index abc55ad..9cc2036 100644
--- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -9,7 +9,8 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
 
 extern int nf_ct_frag6_init(void);
 extern void nf_ct_frag6_cleanup(void);
-extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb);
+extern struct sk_buff *nf_ct_frag6_gather(struct net *net,
+                                         struct sk_buff *skb);
 extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
                               struct net_device *in,
                               struct net_device *out,
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c 
b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 8288efc..5ff46a2 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -191,12 +191,13 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
                                int (*okfn)(struct sk_buff *))
 {
        struct sk_buff *reasm;
+       struct net *net = out ? dev_net(out) : dev_net(in);
 
        /* Previously seen (loopback)?  */
        if (skb->nfct)
                return NF_ACCEPT;
 
-       reasm = nf_ct_frag6_gather(skb);
+       reasm = nf_ct_frag6_gather(net, skb);
 
        /* queued */
        if (reasm == NULL)
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c 
b/net/ipv6/netfilter/nf_conntrack_reasm.c
index c2236df..7036eba 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -593,7 +593,8 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int 
*prevhoff, int *fhoff)
        return 0;
 }
 
-struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
+struct sk_buff *nf_ct_frag6_gather(struct net *net,
+                                  struct sk_buff *skb)
 {
        struct sk_buff *clone;
        struct net_device *dev = skb->dev;
@@ -603,7 +604,6 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
        int fhoff, nhoff;
        u8 prevhdr;
        struct sk_buff *ret_skb = NULL;
-       struct net *net = dev_net(dev);
 
        /* Jumbo payload inhibits frag. header */
        if (ipv6_hdr(skb)->payload_len == 0) {
-- 
1.6.0.6

>From 6e9609de26cc3a730b423624ed442cc26308c873 Mon Sep 17 00:00:00 2001
From: Vitaliy Gusev <vgu...@openvz.org>
Date: Tue, 14 Oct 2008 19:14:31 +0400
Subject: [PATCH] conntrack ipv6: Fix error path if nf_register_hooks fails.

commit 482dd20b (conntrack: prevent call nf_register_hooks()) has a error:
immediate return without any cleanup.

Signed-off-by: Vitaliy Gusev <vgu...@openvz.org>
Signed-off-by: Pavel Emelyanov <xe...@openvz.org>
---
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c 
b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 5ff46a2..c047804 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -486,13 +486,15 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
        if (ret < 0) {
                printk(KERN_ERR "nf_conntrack_ipv6: can't register pre-routing "
                       "defrag hook.\n");
-               return ret;
+               goto cleanup_l3proto;
        }
        KSYMRESOLVE(init_nf_ct_l3proto_ipv6);
        KSYMRESOLVE(fini_nf_ct_l3proto_ipv6);
        KSYMMODRESOLVE(nf_conntrack_ipv6);
        return 0;
 
+cleanup_l3proto:
+       fini_nf_ct_l3proto_ipv6();
 cleanup_frag6:
        nf_ct_frag6_cleanup();
 unreg_subsys:
-- 
1.6.0.6

Reply via email to