]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/ip6mr.c
netns: ip6mr: declare counter cache_resolve_queue_len per-namespace
[net-next-2.6.git] / net / ipv6 / ip6mr.c
index 182f8a177e7f1acc6cfce06c36b1fe64ed4f6ccc..077c8198eb53b0602a40292702fa7c767af74d06 100644 (file)
@@ -49,9 +49,6 @@
 #include <net/addrconf.h>
 #include <linux/netfilter_ipv6.h>
 
-struct sock *mroute6_socket;
-
-
 /* Big lock, protecting vif table, mrt cache and mroute socket state.
    Note that the changes are semaphored via rtnl_lock.
  */
@@ -62,10 +59,7 @@ static DEFINE_RWLOCK(mrt_lock);
  *     Multicast router control variables
  */
 
-static struct mif_device vif6_table[MAXMIFS];          /* Devices              */
-static int maxvif;
-
-#define MIF_EXISTS(idx) (vif6_table[idx].dev != NULL)
+#define MIF_EXISTS(_net, _idx) ((_net)->ipv6.vif6_table[_idx].dev != NULL)
 
 static int mroute_do_assert;                           /* Set in PIM assert    */
 #ifdef CONFIG_IPV6_PIMSM_V2
@@ -74,10 +68,7 @@ static int mroute_do_pim;
 #define mroute_do_pim 0
 #endif
 
-static struct mfc6_cache *mfc6_cache_array[MFC6_LINES];        /* Forwarding cache     */
-
 static struct mfc6_cache *mfc_unres_queue;             /* Queue of unresolved entries */
-static atomic_t cache_resolve_queue_len;               /* Size of unresolved   */
 
 /* Special spinlock for queue of unresolved entries */
 static DEFINE_SPINLOCK(mfc_unres_lock);
@@ -115,10 +106,11 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos)
 {
        struct mfc6_cache *mfc;
 
-       it->cache = mfc6_cache_array;
+       it->cache = init_net.ipv6.mfc6_cache_array;
        read_lock(&mrt_lock);
-       for (it->ct = 0; it->ct < ARRAY_SIZE(mfc6_cache_array); it->ct++)
-               for (mfc = mfc6_cache_array[it->ct]; mfc; mfc = mfc->next)
+       for (it->ct = 0; it->ct < MFC6_LINES; it->ct++)
+               for (mfc = init_net.ipv6.mfc6_cache_array[it->ct];
+                    mfc; mfc = mfc->next)
                        if (pos-- == 0)
                                return mfc;
        read_unlock(&mrt_lock);
@@ -148,11 +140,11 @@ struct ipmr_vif_iter {
 static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter,
                                            loff_t pos)
 {
-       for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) {
-               if (!MIF_EXISTS(iter->ct))
+       for (iter->ct = 0; iter->ct < init_net.ipv6.maxvif; ++iter->ct) {
+               if (!MIF_EXISTS(&init_net, iter->ct))
                        continue;
                if (pos-- == 0)
-                       return &vif6_table[iter->ct];
+                       return &init_net.ipv6.vif6_table[iter->ct];
        }
        return NULL;
 }
@@ -173,10 +165,10 @@ static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        if (v == SEQ_START_TOKEN)
                return ip6mr_vif_seq_idx(iter, 0);
 
-       while (++iter->ct < maxvif) {
-               if (!MIF_EXISTS(iter->ct))
+       while (++iter->ct < init_net.ipv6.maxvif) {
+               if (!MIF_EXISTS(&init_net, iter->ct))
                        continue;
-               return &vif6_table[iter->ct];
+               return &init_net.ipv6.vif6_table[iter->ct];
        }
        return NULL;
 }
@@ -198,7 +190,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
 
                seq_printf(seq,
                           "%2td %-10s %8ld %7ld  %8ld %7ld %05X\n",
-                          vif - vif6_table,
+                          vif - init_net.ipv6.vif6_table,
                           name, vif->bytes_in, vif->pkt_in,
                           vif->bytes_out, vif->pkt_out,
                           vif->flags);
@@ -224,7 +216,7 @@ static struct file_operations ip6mr_vif_fops = {
        .open    = ip6mr_vif_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_private,
 };
 
 static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
@@ -249,10 +241,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        if (it->cache == &mfc_unres_queue)
                goto end_of_list;
 
-       BUG_ON(it->cache != mfc6_cache_array);
+       BUG_ON(it->cache != init_net.ipv6.mfc6_cache_array);
 
-       while (++it->ct < ARRAY_SIZE(mfc6_cache_array)) {
-               mfc = mfc6_cache_array[it->ct];
+       while (++it->ct < MFC6_LINES) {
+               mfc = init_net.ipv6.mfc6_cache_array[it->ct];
                if (mfc)
                        return mfc;
        }
@@ -280,7 +272,7 @@ static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
 
        if (it->cache == &mfc_unres_queue)
                spin_unlock_bh(&mfc_unres_lock);
-       else if (it->cache == mfc6_cache_array)
+       else if (it->cache == init_net.ipv6.mfc6_cache_array)
                read_unlock(&mrt_lock);
 }
 
@@ -297,23 +289,28 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
                const struct mfc6_cache *mfc = v;
                const struct ipmr_mfc_iter *it = seq->private;
 
-               seq_printf(seq,
-                          NIP6_FMT " " NIP6_FMT " %-3d %8ld %8ld %8ld",
-                          NIP6(mfc->mf6c_mcastgrp), NIP6(mfc->mf6c_origin),
-                          mfc->mf6c_parent,
-                          mfc->mfc_un.res.pkt,
-                          mfc->mfc_un.res.bytes,
-                          mfc->mfc_un.res.wrong_if);
+               seq_printf(seq, "%pI6 %pI6 %-3hd",
+                          &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
+                          mfc->mf6c_parent);
 
                if (it->cache != &mfc_unres_queue) {
+                       seq_printf(seq, " %8lu %8lu %8lu",
+                                  mfc->mfc_un.res.pkt,
+                                  mfc->mfc_un.res.bytes,
+                                  mfc->mfc_un.res.wrong_if);
                        for (n = mfc->mfc_un.res.minvif;
                             n < mfc->mfc_un.res.maxvif; n++) {
-                               if (MIF_EXISTS(n) &&
+                               if (MIF_EXISTS(&init_net, n) &&
                                    mfc->mfc_un.res.ttls[n] < 255)
                                        seq_printf(seq,
                                                   " %2d:%-3d",
                                                   n, mfc->mfc_un.res.ttls[n]);
                        }
+               } else {
+                       /* unresolved mfc_caches don't contain
+                        * pkt, bytes and wrong_if values
+                        */
+                       seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
                }
                seq_putc(seq, '\n');
        }
@@ -338,7 +335,7 @@ static struct file_operations ip6mr_mfc_fops = {
        .open    = ipmr_mfc_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_private,
 };
 #endif
 
@@ -372,7 +369,7 @@ static int pim6_rcv(struct sk_buff *skb)
 
        read_lock(&mrt_lock);
        if (reg_vif_num >= 0)
-               reg_dev = vif6_table[reg_vif_num].dev;
+               reg_dev = init_net.ipv6.vif6_table[reg_vif_num].dev;
        if (reg_dev)
                dev_hold(reg_dev);
        read_unlock(&mrt_lock);
@@ -417,12 +414,16 @@ static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
+static const struct net_device_ops reg_vif_netdev_ops = {
+       .ndo_start_xmit = reg_vif_xmit,
+};
+
 static void reg_vif_setup(struct net_device *dev)
 {
        dev->type               = ARPHRD_PIMREG;
        dev->mtu                = 1500 - sizeof(struct ipv6hdr) - 8;
        dev->flags              = IFF_NOARP;
-       dev->hard_start_xmit    = reg_vif_xmit;
+       dev->netdev_ops         = &reg_vif_netdev_ops;
        dev->destructor         = free_netdev;
 }
 
@@ -464,10 +465,10 @@ static int mif6_delete(int vifi)
 {
        struct mif_device *v;
        struct net_device *dev;
-       if (vifi < 0 || vifi >= maxvif)
+       if (vifi < 0 || vifi >= init_net.ipv6.maxvif)
                return -EADDRNOTAVAIL;
 
-       v = &vif6_table[vifi];
+       v = &init_net.ipv6.vif6_table[vifi];
 
        write_lock_bh(&mrt_lock);
        dev = v->dev;
@@ -483,13 +484,13 @@ static int mif6_delete(int vifi)
                reg_vif_num = -1;
 #endif
 
-       if (vifi + 1 == maxvif) {
+       if (vifi + 1 == init_net.ipv6.maxvif) {
                int tmp;
                for (tmp = vifi - 1; tmp >= 0; tmp--) {
-                       if (MIF_EXISTS(tmp))
+                       if (MIF_EXISTS(&init_net, tmp))
                                break;
                }
-               maxvif = tmp + 1;
+               init_net.ipv6.maxvif = tmp + 1;
        }
 
        write_unlock_bh(&mrt_lock);
@@ -503,6 +504,12 @@ static int mif6_delete(int vifi)
        return 0;
 }
 
+static inline void ip6mr_cache_free(struct mfc6_cache *c)
+{
+       release_net(mfc6_net(c));
+       kmem_cache_free(mrt_cachep, c);
+}
+
 /* Destroy an unresolved cache entry, killing queued skbs
    and reporting error to netlink readers.
  */
@@ -511,7 +518,7 @@ static void ip6mr_destroy_unres(struct mfc6_cache *c)
 {
        struct sk_buff *skb;
 
-       atomic_dec(&cache_resolve_queue_len);
+       atomic_dec(&init_net.ipv6.cache_resolve_queue_len);
 
        while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) {
                if (ipv6_hdr(skb)->version == 0) {
@@ -525,7 +532,7 @@ static void ip6mr_destroy_unres(struct mfc6_cache *c)
                        kfree_skb(skb);
        }
 
-       kmem_cache_free(mrt_cachep, c);
+       ip6mr_cache_free(c);
 }
 
 
@@ -553,7 +560,7 @@ static void ipmr_do_expire_process(unsigned long dummy)
                ip6mr_destroy_unres(c);
        }
 
-       if (atomic_read(&cache_resolve_queue_len))
+       if (mfc_unres_queue != NULL)
                mod_timer(&ipmr_expire_timer, jiffies + expires);
 }
 
@@ -564,7 +571,7 @@ static void ipmr_expire_process(unsigned long dummy)
                return;
        }
 
-       if (atomic_read(&cache_resolve_queue_len))
+       if (mfc_unres_queue != NULL)
                ipmr_do_expire_process(dummy);
 
        spin_unlock(&mfc_unres_lock);
@@ -580,8 +587,9 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl
        cache->mfc_un.res.maxvif = 0;
        memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
 
-       for (vifi = 0; vifi < maxvif; vifi++) {
-               if (MIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) {
+       for (vifi = 0; vifi < init_net.ipv6.maxvif; vifi++) {
+               if (MIF_EXISTS(&init_net, vifi) &&
+                   ttls[vifi] && ttls[vifi] < 255) {
                        cache->mfc_un.res.ttls[vifi] = ttls[vifi];
                        if (cache->mfc_un.res.minvif > vifi)
                                cache->mfc_un.res.minvif = vifi;
@@ -594,12 +602,12 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl
 static int mif6_add(struct mif6ctl *vifc, int mrtsock)
 {
        int vifi = vifc->mif6c_mifi;
-       struct mif_device *v = &vif6_table[vifi];
+       struct mif_device *v = &init_net.ipv6.vif6_table[vifi];
        struct net_device *dev;
        int err;
 
        /* Is vif busy ? */
-       if (MIF_EXISTS(vifi))
+       if (MIF_EXISTS(&init_net, vifi))
                return -EADDRINUSE;
 
        switch (vifc->mif6c_flags) {
@@ -659,8 +667,8 @@ static int mif6_add(struct mif6ctl *vifc, int mrtsock)
        if (v->flags & MIFF_REGISTER)
                reg_vif_num = vifi;
 #endif
-       if (vifi + 1 > maxvif)
-               maxvif = vifi + 1;
+       if (vifi + 1 > init_net.ipv6.maxvif)
+               init_net.ipv6.maxvif = vifi + 1;
        write_unlock_bh(&mrt_lock);
        return 0;
 }
@@ -670,7 +678,7 @@ static struct mfc6_cache *ip6mr_cache_find(struct in6_addr *origin, struct in6_a
        int line = MFC6_HASH(mcastgrp, origin);
        struct mfc6_cache *c;
 
-       for (c = mfc6_cache_array[line]; c; c = c->next) {
+       for (c = init_net.ipv6.mfc6_cache_array[line]; c; c = c->next) {
                if (ipv6_addr_equal(&c->mf6c_origin, origin) &&
                    ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp))
                        break;
@@ -681,24 +689,24 @@ static struct mfc6_cache *ip6mr_cache_find(struct in6_addr *origin, struct in6_a
 /*
  *     Allocate a multicast cache entry
  */
-static struct mfc6_cache *ip6mr_cache_alloc(void)
+static struct mfc6_cache *ip6mr_cache_alloc(struct net *net)
 {
-       struct mfc6_cache *c = kmem_cache_alloc(mrt_cachep, GFP_KERNEL);
+       struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
        if (c == NULL)
                return NULL;
-       memset(c, 0, sizeof(*c));
        c->mfc_un.res.minvif = MAXMIFS;
+       mfc6_net_set(c, net);
        return c;
 }
 
-static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
+static struct mfc6_cache *ip6mr_cache_alloc_unres(struct net *net)
 {
-       struct mfc6_cache *c = kmem_cache_alloc(mrt_cachep, GFP_ATOMIC);
+       struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
        if (c == NULL)
                return NULL;
-       memset(c, 0, sizeof(*c));
        skb_queue_head_init(&c->mfc_un.unres.unresolved);
        c->mfc_un.unres.expires = jiffies + 10 * HZ;
+       mfc6_net_set(c, net);
        return c;
 }
 
@@ -813,7 +821,7 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
        skb_pull(skb, sizeof(struct ipv6hdr));
        }
 
-       if (mroute6_socket == NULL) {
+       if (init_net.ipv6.mroute6_sk == NULL) {
                kfree_skb(skb);
                return -EINVAL;
        }
@@ -821,7 +829,8 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
        /*
         *      Deliver to user space multicast routing algorithms
         */
-       if ((ret = sock_queue_rcv_skb(mroute6_socket, skb)) < 0) {
+       ret = sock_queue_rcv_skb(init_net.ipv6.mroute6_sk, skb);
+       if (ret < 0) {
                if (net_ratelimit())
                        printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n");
                kfree_skb(skb);
@@ -842,7 +851,8 @@ ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
 
        spin_lock_bh(&mfc_unres_lock);
        for (c = mfc_unres_queue; c; c = c->next) {
-               if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
+               if (net_eq(mfc6_net(c), &init_net) &&
+                   ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
                    ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr))
                        break;
        }
@@ -852,8 +862,8 @@ ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
                 *      Create a new entry if allowable
                 */
 
-               if (atomic_read(&cache_resolve_queue_len) >= 10 ||
-                   (c = ip6mr_cache_alloc_unres()) == NULL) {
+               if (atomic_read(&init_net.ipv6.cache_resolve_queue_len) >= 10 ||
+                   (c = ip6mr_cache_alloc_unres(&init_net)) == NULL) {
                        spin_unlock_bh(&mfc_unres_lock);
 
                        kfree_skb(skb);
@@ -876,12 +886,12 @@ ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
                         */
                        spin_unlock_bh(&mfc_unres_lock);
 
-                       kmem_cache_free(mrt_cachep, c);
+                       ip6mr_cache_free(c);
                        kfree_skb(skb);
                        return err;
                }
 
-               atomic_inc(&cache_resolve_queue_len);
+               atomic_inc(&init_net.ipv6.cache_resolve_queue_len);
                c->next = mfc_unres_queue;
                mfc_unres_queue = c;
 
@@ -914,14 +924,15 @@ static int ip6mr_mfc_delete(struct mf6cctl *mfc)
 
        line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
 
-       for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) {
+       for (cp = &init_net.ipv6.mfc6_cache_array[line];
+            (c = *cp) != NULL; cp = &c->next) {
                if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
                    ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) {
                        write_lock_bh(&mrt_lock);
                        *cp = c->next;
                        write_unlock_bh(&mrt_lock);
 
-                       kmem_cache_free(mrt_cachep, c);
+                       ip6mr_cache_free(c);
                        return 0;
                }
        }
@@ -941,8 +952,8 @@ static int ip6mr_device_event(struct notifier_block *this,
        if (event != NETDEV_UNREGISTER)
                return NOTIFY_DONE;
 
-       v = &vif6_table[0];
-       for (ct = 0; ct < maxvif; ct++, v++) {
+       v = &init_net.ipv6.vif6_table[0];
+       for (ct = 0; ct < init_net.ipv6.maxvif; ct++, v++) {
                if (v->dev == dev)
                        mif6_delete(ct);
        }
@@ -957,6 +968,44 @@ static struct notifier_block ip6_mr_notifier = {
  *     Setup for IP multicast routing
  */
 
+static int __net_init ip6mr_net_init(struct net *net)
+{
+       int err = 0;
+
+       net->ipv6.vif6_table = kcalloc(MAXMIFS, sizeof(struct mif_device),
+                                      GFP_KERNEL);
+       if (!net->ipv6.vif6_table) {
+               err = -ENOMEM;
+               goto fail;
+       }
+
+       /* Forwarding cache */
+       net->ipv6.mfc6_cache_array = kcalloc(MFC6_LINES,
+                                            sizeof(struct mfc6_cache *),
+                                            GFP_KERNEL);
+       if (!net->ipv6.mfc6_cache_array) {
+               err = -ENOMEM;
+               goto fail_mfc6_cache;
+       }
+       return 0;
+
+fail_mfc6_cache:
+       kfree(net->ipv6.vif6_table);
+fail:
+       return err;
+}
+
+static void __net_exit ip6mr_net_exit(struct net *net)
+{
+       kfree(net->ipv6.mfc6_cache_array);
+       kfree(net->ipv6.vif6_table);
+}
+
+static struct pernet_operations ip6mr_net_ops = {
+       .init = ip6mr_net_init,
+       .exit = ip6mr_net_exit,
+};
+
 int __init ip6_mr_init(void)
 {
        int err;
@@ -968,6 +1017,10 @@ int __init ip6_mr_init(void)
        if (!mrt_cachep)
                return -ENOMEM;
 
+       err = register_pernet_subsys(&ip6mr_net_ops);
+       if (err)
+               goto reg_pernet_fail;
+
        setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
        err = register_netdevice_notifier(&ip6_mr_notifier);
        if (err)
@@ -981,14 +1034,17 @@ int __init ip6_mr_init(void)
                goto proc_cache_fail;
 #endif
        return 0;
-reg_notif_fail:
-       kmem_cache_destroy(mrt_cachep);
 #ifdef CONFIG_PROC_FS
-proc_vif_fail:
-       unregister_netdevice_notifier(&ip6_mr_notifier);
 proc_cache_fail:
        proc_net_remove(&init_net, "ip6_mr_vif");
+proc_vif_fail:
+       unregister_netdevice_notifier(&ip6_mr_notifier);
 #endif
+reg_notif_fail:
+       del_timer(&ipmr_expire_timer);
+       unregister_pernet_subsys(&ip6mr_net_ops);
+reg_pernet_fail:
+       kmem_cache_destroy(mrt_cachep);
        return err;
 }
 
@@ -1000,6 +1056,7 @@ void ip6_mr_cleanup(void)
 #endif
        unregister_netdevice_notifier(&ip6_mr_notifier);
        del_timer(&ipmr_expire_timer);
+       unregister_pernet_subsys(&ip6mr_net_ops);
        kmem_cache_destroy(mrt_cachep);
 }
 
@@ -1019,7 +1076,8 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
 
        line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
 
-       for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) {
+       for (cp = &init_net.ipv6.mfc6_cache_array[line];
+            (c = *cp) != NULL; cp = &c->next) {
                if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
                    ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr))
                        break;
@@ -1038,7 +1096,7 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
        if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
                return -EINVAL;
 
-       c = ip6mr_cache_alloc();
+       c = ip6mr_cache_alloc(&init_net);
        if (c == NULL)
                return -ENOMEM;
 
@@ -1050,8 +1108,8 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
                c->mfc_flags |= MFC_STATIC;
 
        write_lock_bh(&mrt_lock);
-       c->next = mfc6_cache_array[line];
-       mfc6_cache_array[line] = c;
+       c->next = init_net.ipv6.mfc6_cache_array[line];
+       init_net.ipv6.mfc6_cache_array[line] = c;
        write_unlock_bh(&mrt_lock);
 
        /*
@@ -1061,19 +1119,21 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
        spin_lock_bh(&mfc_unres_lock);
        for (cp = &mfc_unres_queue; (uc = *cp) != NULL;
             cp = &uc->next) {
-               if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
+               if (net_eq(mfc6_net(uc), &init_net) &&
+                   ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
                    ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
                        *cp = uc->next;
-                       if (atomic_dec_and_test(&cache_resolve_queue_len))
-                               del_timer(&ipmr_expire_timer);
+                       atomic_dec(&init_net.ipv6.cache_resolve_queue_len);
                        break;
                }
        }
+       if (mfc_unres_queue == NULL)
+               del_timer(&ipmr_expire_timer);
        spin_unlock_bh(&mfc_unres_lock);
 
        if (uc) {
                ip6mr_cache_resolve(uc, c);
-               kmem_cache_free(mrt_cachep, uc);
+               ip6mr_cache_free(uc);
        }
        return 0;
 }
@@ -1089,18 +1149,18 @@ static void mroute_clean_tables(struct sock *sk)
        /*
         *      Shut down all active vif entries
         */
-       for (i = 0; i < maxvif; i++) {
-               if (!(vif6_table[i].flags & VIFF_STATIC))
+       for (i = 0; i < init_net.ipv6.maxvif; i++) {
+               if (!(init_net.ipv6.vif6_table[i].flags & VIFF_STATIC))
                        mif6_delete(i);
        }
 
        /*
         *      Wipe the cache
         */
-       for (i = 0; i < ARRAY_SIZE(mfc6_cache_array); i++) {
+       for (i = 0; i < MFC6_LINES; i++) {
                struct mfc6_cache *c, **cp;
 
-               cp = &mfc6_cache_array[i];
+               cp = &init_net.ipv6.mfc6_cache_array[i];
                while ((c = *cp) != NULL) {
                        if (c->mfc_flags & MFC_STATIC) {
                                cp = &c->next;
@@ -1110,22 +1170,22 @@ static void mroute_clean_tables(struct sock *sk)
                        *cp = c->next;
                        write_unlock_bh(&mrt_lock);
 
-                       kmem_cache_free(mrt_cachep, c);
+                       ip6mr_cache_free(c);
                }
        }
 
-       if (atomic_read(&cache_resolve_queue_len) != 0) {
-               struct mfc6_cache *c;
+       if (atomic_read(&init_net.ipv6.cache_resolve_queue_len) != 0) {
+               struct mfc6_cache *c, **cp;
 
                spin_lock_bh(&mfc_unres_lock);
-               while (mfc_unres_queue != NULL) {
-                       c = mfc_unres_queue;
-                       mfc_unres_queue = c->next;
-                       spin_unlock_bh(&mfc_unres_lock);
-
+               cp = &mfc_unres_queue;
+               while ((c = *cp) != NULL) {
+                       if (!net_eq(mfc6_net(c), &init_net)) {
+                               cp = &c->next;
+                               continue;
+                       }
+                       *cp = c->next;
                        ip6mr_destroy_unres(c);
-
-                       spin_lock_bh(&mfc_unres_lock);
                }
                spin_unlock_bh(&mfc_unres_lock);
        }
@@ -1137,8 +1197,8 @@ static int ip6mr_sk_init(struct sock *sk)
 
        rtnl_lock();
        write_lock_bh(&mrt_lock);
-       if (likely(mroute6_socket == NULL))
-               mroute6_socket = sk;
+       if (likely(init_net.ipv6.mroute6_sk == NULL))
+               init_net.ipv6.mroute6_sk = sk;
        else
                err = -EADDRINUSE;
        write_unlock_bh(&mrt_lock);
@@ -1153,9 +1213,9 @@ int ip6mr_sk_done(struct sock *sk)
        int err = 0;
 
        rtnl_lock();
-       if (sk == mroute6_socket) {
+       if (sk == init_net.ipv6.mroute6_sk) {
                write_lock_bh(&mrt_lock);
-               mroute6_socket = NULL;
+               init_net.ipv6.mroute6_sk = NULL;
                write_unlock_bh(&mrt_lock);
 
                mroute_clean_tables(sk);
@@ -1181,7 +1241,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
        mifi_t mifi;
 
        if (optname != MRT6_INIT) {
-               if (sk != mroute6_socket && !capable(CAP_NET_ADMIN))
+               if (sk != init_net.ipv6.mroute6_sk && !capable(CAP_NET_ADMIN))
                        return -EACCES;
        }
 
@@ -1206,7 +1266,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
                if (vif.mif6c_mifi >= MAXMIFS)
                        return -ENFILE;
                rtnl_lock();
-               ret = mif6_add(&vif, sk == mroute6_socket);
+               ret = mif6_add(&vif, sk == init_net.ipv6.mroute6_sk);
                rtnl_unlock();
                return ret;
 
@@ -1234,7 +1294,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
                if (optname == MRT6_DEL_MFC)
                        ret = ip6mr_mfc_delete(&mfc);
                else
-                       ret = ip6mr_mfc_add(&mfc, sk == mroute6_socket);
+                       ret = ip6mr_mfc_add(&mfc, sk == init_net.ipv6.mroute6_sk);
                rtnl_unlock();
                return ret;
 
@@ -1340,11 +1400,11 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
        case SIOCGETMIFCNT_IN6:
                if (copy_from_user(&vr, arg, sizeof(vr)))
                        return -EFAULT;
-               if (vr.mifi >= maxvif)
+               if (vr.mifi >= init_net.ipv6.maxvif)
                        return -EINVAL;
                read_lock(&mrt_lock);
-               vif = &vif6_table[vr.mifi];
-               if (MIF_EXISTS(vr.mifi)) {
+               vif = &init_net.ipv6.vif6_table[vr.mifi];
+               if (MIF_EXISTS(&init_net, vr.mifi)) {
                        vr.icount = vif->pkt_in;
                        vr.ocount = vif->pkt_out;
                        vr.ibytes = vif->bytes_in;
@@ -1395,7 +1455,7 @@ static inline int ip6mr_forward2_finish(struct sk_buff *skb)
 static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi)
 {
        struct ipv6hdr *ipv6h;
-       struct mif_device *vif = &vif6_table[vifi];
+       struct mif_device *vif = &init_net.ipv6.vif6_table[vifi];
        struct net_device *dev;
        struct dst_entry *dst;
        struct flowi fl;
@@ -1468,8 +1528,8 @@ out_free:
 static int ip6mr_find_vif(struct net_device *dev)
 {
        int ct;
-       for (ct = maxvif - 1; ct >= 0; ct--) {
-               if (vif6_table[ct].dev == dev)
+       for (ct = init_net.ipv6.maxvif - 1; ct >= 0; ct--) {
+               if (init_net.ipv6.vif6_table[ct].dev == dev)
                        break;
        }
        return ct;
@@ -1487,7 +1547,7 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
        /*
         * Wrong interface: drop packet and (maybe) send PIM assert.
         */
-       if (vif6_table[vif].dev != skb->dev) {
+       if (init_net.ipv6.vif6_table[vif].dev != skb->dev) {
                int true_vifi;
 
                cache->mfc_un.res.wrong_if++;
@@ -1508,8 +1568,8 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
                goto dont_forward;
        }
 
-       vif6_table[vif].pkt_in++;
-       vif6_table[vif].bytes_in += skb->len;
+       init_net.ipv6.vif6_table[vif].pkt_in++;
+       init_net.ipv6.vif6_table[vif].bytes_in += skb->len;
 
        /*
         *      Forward the frame
@@ -1577,7 +1637,7 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
 {
        int ct;
        struct rtnexthop *nhp;
-       struct net_device *dev = vif6_table[c->mf6c_parent].dev;
+       struct net_device *dev = init_net.ipv6.vif6_table[c->mf6c_parent].dev;
        u8 *b = skb_tail_pointer(skb);
        struct rtattr *mp_head;
 
@@ -1593,7 +1653,7 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
                        nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
                        nhp->rtnh_flags = 0;
                        nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
-                       nhp->rtnh_ifindex = vif6_table[ct].dev->ifindex;
+                       nhp->rtnh_ifindex = init_net.ipv6.vif6_table[ct].dev->ifindex;
                        nhp->rtnh_len = sizeof(*nhp);
                }
        }