]> Pileus Git - ~andy/linux/blobdiff - net/ipv6/route.c
[NETNS][IPV6] ip6_fib - make it per network namespace
[~andy/linux] / net / ipv6 / route.c
index dbdae143ef5fa1312ff227eadf0ecc67f10b9017..09206f7ba525ee0c71769e73d6c22108f43eea08 100644 (file)
 
 #define CLONE_OFFLINK_ROUTE 0
 
-static int ip6_rt_max_size = 4096;
-static int ip6_rt_gc_min_interval = HZ / 2;
-static int ip6_rt_gc_timeout = 60*HZ;
-int ip6_rt_gc_interval = 30*HZ;
-static int ip6_rt_gc_elasticity = 9;
-static int ip6_rt_mtu_expires = 10*60*HZ;
-static int ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
-
 static struct rt6_info * ip6_rt_copy(struct rt6_info *ort);
 static struct dst_entry        *ip6_dst_check(struct dst_entry *dst, u32 cookie);
 static struct dst_entry *ip6_negative_advice(struct dst_entry *);
 static void            ip6_dst_destroy(struct dst_entry *);
 static void            ip6_dst_ifdown(struct dst_entry *,
                                       struct net_device *dev, int how);
-static int              ip6_dst_gc(void);
+static int              ip6_dst_gc(struct dst_ops *ops);
 
 static int             ip6_pkt_discard(struct sk_buff *skb);
 static int             ip6_pkt_discard_out(struct sk_buff *skb);
@@ -115,6 +107,7 @@ static struct dst_ops ip6_dst_ops = {
        .update_pmtu            =       ip6_rt_update_pmtu,
        .local_out              =       ip6_local_out,
        .entry_size             =       sizeof(struct rt6_info),
+       .entries                =       ATOMIC_INIT(0),
 };
 
 static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
@@ -128,6 +121,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
        .check                  =       ip6_dst_check,
        .update_pmtu            =       ip6_rt_blackhole_update_pmtu,
        .entry_size             =       sizeof(struct rt6_info),
+       .entries                =       ATOMIC_INIT(0),
 };
 
 struct rt6_info ip6_null_entry = {
@@ -577,7 +571,7 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
                flags |= RT6_LOOKUP_F_HAS_SADDR;
        }
 
-       dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup);
+       dst = fib6_rule_lookup(&init_net, &fl, flags, ip6_pol_route_lookup);
        if (dst->error == 0)
                return (struct rt6_info *) dst;
 
@@ -609,7 +603,10 @@ static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info)
 
 int ip6_ins_rt(struct rt6_info *rt)
 {
-       return __ip6_ins_rt(rt, NULL);
+       struct nl_info info = {
+               .nl_net = &init_net,
+       };
+       return __ip6_ins_rt(rt, &info);
 }
 
 static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr,
@@ -761,7 +758,7 @@ void ip6_route_input(struct sk_buff *skb)
        if (rt6_need_strict(&iph->daddr))
                flags |= RT6_LOOKUP_F_IFACE;
 
-       skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input);
+       skb->dst = fib6_rule_lookup(&init_net, &fl, flags, ip6_pol_route_input);
 }
 
 static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
@@ -780,7 +777,7 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
        if (!ipv6_addr_any(&fl->fl6_src))
                flags |= RT6_LOOKUP_F_HAS_SADDR;
 
-       return fib6_rule_lookup(fl, flags, ip6_pol_route_output);
+       return fib6_rule_lookup(&init_net, fl, flags, ip6_pol_route_output);
 }
 
 EXPORT_SYMBOL(ip6_route_output);
@@ -893,8 +890,8 @@ static inline unsigned int ipv6_advmss(unsigned int mtu)
 {
        mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr);
 
-       if (mtu < ip6_rt_min_advmss)
-               mtu = ip6_rt_min_advmss;
+       if (mtu < init_net.ipv6.sysctl.ip6_rt_min_advmss)
+               mtu = init_net.ipv6.sysctl.ip6_rt_min_advmss;
 
        /*
         * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and
@@ -907,13 +904,12 @@ static inline unsigned int ipv6_advmss(unsigned int mtu)
        return mtu;
 }
 
-static struct dst_entry *ndisc_dst_gc_list;
-static DEFINE_SPINLOCK(ndisc_lock);
+static struct dst_entry *icmp6_dst_gc_list;
+static DEFINE_SPINLOCK(icmp6_dst_lock);
 
-struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
+struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
                                  struct neighbour *neigh,
-                                 struct in6_addr *addr,
-                                 int (*output)(struct sk_buff *))
+                                 struct in6_addr *addr)
 {
        struct rt6_info *rt;
        struct inet6_dev *idev = in6_dev_get(dev);
@@ -940,7 +936,7 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
        rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
        rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
        rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
-       rt->u.dst.output  = output;
+       rt->u.dst.output  = ip6_output;
 
 #if 0  /* there's no chance to use these for ndisc */
        rt->u.dst.flags   = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST
@@ -950,10 +946,10 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
        rt->rt6i_dst.plen = 128;
 #endif
 
-       spin_lock_bh(&ndisc_lock);
-       rt->u.dst.next = ndisc_dst_gc_list;
-       ndisc_dst_gc_list = &rt->u.dst;
-       spin_unlock_bh(&ndisc_lock);
+       spin_lock_bh(&icmp6_dst_lock);
+       rt->u.dst.next = icmp6_dst_gc_list;
+       icmp6_dst_gc_list = &rt->u.dst;
+       spin_unlock_bh(&icmp6_dst_lock);
 
        fib6_force_start_gc();
 
@@ -961,7 +957,7 @@ out:
        return &rt->u.dst;
 }
 
-int ndisc_dst_gc(int *more)
+int icmp6_dst_gc(int *more)
 {
        struct dst_entry *dst, *next, **pprev;
        int freed;
@@ -969,8 +965,8 @@ int ndisc_dst_gc(int *more)
        next = NULL;
        freed = 0;
 
-       spin_lock_bh(&ndisc_lock);
-       pprev = &ndisc_dst_gc_list;
+       spin_lock_bh(&icmp6_dst_lock);
+       pprev = &icmp6_dst_gc_list;
 
        while ((dst = *pprev) != NULL) {
                if (!atomic_read(&dst->__refcnt)) {
@@ -983,30 +979,30 @@ int ndisc_dst_gc(int *more)
                }
        }
 
-       spin_unlock_bh(&ndisc_lock);
+       spin_unlock_bh(&icmp6_dst_lock);
 
        return freed;
 }
 
-static int ip6_dst_gc(void)
+static int ip6_dst_gc(struct dst_ops *ops)
 {
        static unsigned expire = 30*HZ;
        static unsigned long last_gc;
        unsigned long now = jiffies;
 
-       if (time_after(last_gc + ip6_rt_gc_min_interval, now) &&
-           atomic_read(&ip6_dst_ops.entries) <= ip6_rt_max_size)
+       if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) &&
+           atomic_read(&ip6_dst_ops.entries) <= init_net.ipv6.sysctl.ip6_rt_max_size)
                goto out;
 
        expire++;
        fib6_run_gc(expire);
        last_gc = now;
        if (atomic_read(&ip6_dst_ops.entries) < ip6_dst_ops.gc_thresh)
-               expire = ip6_rt_gc_timeout>>1;
+               expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1;
 
 out:
-       expire -= expire>>ip6_rt_gc_elasticity;
-       return (atomic_read(&ip6_dst_ops.entries) > ip6_rt_max_size);
+       expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity;
+       return (atomic_read(&ip6_dst_ops.entries) > init_net.ipv6.sysctl.ip6_rt_max_size);
 }
 
 /* Clean host part of a prefix. Not necessary in radix tree,
@@ -1073,7 +1069,7 @@ int ip6_route_add(struct fib6_config *cfg)
        if (cfg->fc_metric == 0)
                cfg->fc_metric = IP6_RT_PRIO_USER;
 
-       table = fib6_new_table(cfg->fc_table);
+       table = fib6_new_table(&init_net, cfg->fc_table);
        if (table == NULL) {
                err = -ENOBUFS;
                goto out;
@@ -1266,7 +1262,10 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
 
 int ip6_del_rt(struct rt6_info *rt)
 {
-       return __ip6_del_rt(rt, NULL);
+       struct nl_info info = {
+               .nl_net = &init_net,
+       };
+       return __ip6_del_rt(rt, &info);
 }
 
 static int ip6_route_del(struct fib6_config *cfg)
@@ -1276,7 +1275,7 @@ static int ip6_route_del(struct fib6_config *cfg)
        struct rt6_info *rt;
        int err = -ESRCH;
 
-       table = fib6_get_table(cfg->fc_table);
+       table = fib6_get_table(&init_net, cfg->fc_table);
        if (table == NULL)
                return err;
 
@@ -1391,7 +1390,9 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
        if (rt6_need_strict(dest))
                flags |= RT6_LOOKUP_F_IFACE;
 
-       return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect);
+       return (struct rt6_info *)fib6_rule_lookup(&init_net,
+                                                  (struct flowi *)&rdfl,
+                                                  flags, __ip6_route_redirect);
 }
 
 void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
@@ -1511,7 +1512,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
                rt->u.dst.metrics[RTAX_MTU-1] = pmtu;
                if (allfrag)
                        rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
-               dst_set_expires(&rt->u.dst, ip6_rt_mtu_expires);
+               dst_set_expires(&rt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires);
                rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
                goto out;
        }
@@ -1537,7 +1538,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
                 * which is 10 mins. After 10 mins the decreased pmtu is expired
                 * and detecting PMTU increase will be automatically happened.
                 */
-               dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
+               dst_set_expires(&nrt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires);
                nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
 
                ip6_ins_rt(nrt);
@@ -1590,7 +1591,7 @@ static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixle
        struct rt6_info *rt = NULL;
        struct fib6_table *table;
 
-       table = fib6_get_table(RT6_TABLE_INFO);
+       table = fib6_get_table(&init_net, RT6_TABLE_INFO);
        if (table == NULL)
                return NULL;
 
@@ -1620,7 +1621,7 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle
 {
        struct fib6_config cfg = {
                .fc_table       = RT6_TABLE_INFO,
-               .fc_metric      = 1024,
+               .fc_metric      = IP6_RT_PRIO_USER,
                .fc_ifindex     = ifindex,
                .fc_dst_len     = prefixlen,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
@@ -1645,7 +1646,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
        struct rt6_info *rt;
        struct fib6_table *table;
 
-       table = fib6_get_table(RT6_TABLE_DFLT);
+       table = fib6_get_table(&init_net, RT6_TABLE_DFLT);
        if (table == NULL)
                return NULL;
 
@@ -1670,7 +1671,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
 {
        struct fib6_config cfg = {
                .fc_table       = RT6_TABLE_DFLT,
-               .fc_metric      = 1024,
+               .fc_metric      = IP6_RT_PRIO_USER,
                .fc_ifindex     = dev->ifindex,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
                                  RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
@@ -1689,7 +1690,7 @@ void rt6_purge_dflt_routers(void)
        struct fib6_table *table;
 
        /* NOTE: Keep consistent with rt6_get_dflt_router */
-       table = fib6_get_table(RT6_TABLE_DFLT);
+       table = fib6_get_table(&init_net, RT6_TABLE_DFLT);
        if (table == NULL)
                return;
 
@@ -1719,6 +1720,8 @@ static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg,
        cfg->fc_src_len = rtmsg->rtmsg_src_len;
        cfg->fc_flags = rtmsg->rtmsg_flags;
 
+       cfg->fc_nlinfo.nl_net = &init_net;
+
        ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst);
        ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src);
        ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway);
@@ -1765,8 +1768,7 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
  *     Drop the packet on the floor
  */
 
-static inline int ip6_pkt_drop(struct sk_buff *skb, int code,
-                              int ipstats_mib_noroutes)
+static int ip6_pkt_drop(struct sk_buff *skb, int code, int ipstats_mib_noroutes)
 {
        int type;
        switch (ipstats_mib_noroutes) {
@@ -1851,7 +1853,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 
        ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
        rt->rt6i_dst.plen = 128;
-       rt->rt6i_table = fib6_get_table(RT6_TABLE_LOCAL);
+       rt->rt6i_table = fib6_get_table(&init_net, RT6_TABLE_LOCAL);
 
        atomic_set(&rt->u.dst.__refcnt, 1);
 
@@ -1910,7 +1912,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
         */
        if (rt->rt6i_dev == arg->dev &&
            !dst_metric_locked(&rt->u.dst, RTAX_MTU) &&
-           (dst_mtu(&rt->u.dst) > arg->mtu ||
+           (dst_mtu(&rt->u.dst) >= arg->mtu ||
             (dst_mtu(&rt->u.dst) < arg->mtu &&
              dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) {
                rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu;
@@ -1963,6 +1965,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
 
        cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
        cfg->fc_nlinfo.nlh = nlh;
+       cfg->fc_nlinfo.nl_net = skb->sk->sk_net;
 
        if (tb[RTA_GATEWAY]) {
                nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16);
@@ -2120,7 +2123,8 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
                NLA_PUT_U32(skb, RTA_IIF, iif);
        else if (dst) {
                struct in6_addr saddr_buf;
-               if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0)
+               if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev,
+                                      dst, &saddr_buf) == 0)
                        NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
        }
 
@@ -2243,29 +2247,26 @@ errout:
 void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
 {
        struct sk_buff *skb;
-       u32 pid = 0, seq = 0;
-       struct nlmsghdr *nlh = NULL;
-       int err = -ENOBUFS;
-
-       if (info) {
-               pid = info->pid;
-               nlh = info->nlh;
-               if (nlh)
-                       seq = nlh->nlmsg_seq;
-       }
+       u32 seq;
+       int err;
+
+       err = -ENOBUFS;
+       seq = info->nlh != NULL ? info->nlh->nlmsg_seq : 0;
 
        skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
        if (skb == NULL)
                goto errout;
 
-       err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
+       err = rt6_fill_node(skb, rt, NULL, NULL, 0,
+                               event, info->pid, seq, 0, 0);
        if (err < 0) {
                /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
                WARN_ON(err == -EMSGSIZE);
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, &init_net, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
+       err = rtnl_notify(skb, &init_net, info->pid,
+                               RTNLGRP_IPV6_ROUTE, info->nlh, gfp_any());
 errout:
        if (err < 0)
                rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err);
@@ -2396,24 +2397,23 @@ static inline void ipv6_route_proc_fini(struct net *net)
 
 #ifdef CONFIG_SYSCTL
 
-static int flush_delay;
-
 static
 int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,
                              void __user *buffer, size_t *lenp, loff_t *ppos)
 {
+       int delay = init_net.ipv6.sysctl.flush_delay;
        if (write) {
                proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
-               fib6_run_gc(flush_delay <= 0 ? ~0UL : (unsigned long)flush_delay);
+               fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay);
                return 0;
        } else
                return -EINVAL;
 }
 
-ctl_table ipv6_route_table[] = {
+ctl_table ipv6_route_table_template[] = {
        {
                .procname       =       "flush",
-               .data           =       &flush_delay,
+               .data           =       &init_net.ipv6.sysctl.flush_delay,
                .maxlen         =       sizeof(int),
                .mode           =       0200,
                .proc_handler   =       &ipv6_sysctl_rtcache_flush
@@ -2429,7 +2429,7 @@ ctl_table ipv6_route_table[] = {
        {
                .ctl_name       =       NET_IPV6_ROUTE_MAX_SIZE,
                .procname       =       "max_size",
-               .data           =       &ip6_rt_max_size,
+               .data           =       &init_net.ipv6.sysctl.ip6_rt_max_size,
                .maxlen         =       sizeof(int),
                .mode           =       0644,
                .proc_handler   =       &proc_dointvec,
@@ -2437,7 +2437,7 @@ ctl_table ipv6_route_table[] = {
        {
                .ctl_name       =       NET_IPV6_ROUTE_GC_MIN_INTERVAL,
                .procname       =       "gc_min_interval",
-               .data           =       &ip6_rt_gc_min_interval,
+               .data           =       &init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
                .maxlen         =       sizeof(int),
                .mode           =       0644,
                .proc_handler   =       &proc_dointvec_jiffies,
@@ -2446,7 +2446,7 @@ ctl_table ipv6_route_table[] = {
        {
                .ctl_name       =       NET_IPV6_ROUTE_GC_TIMEOUT,
                .procname       =       "gc_timeout",
-               .data           =       &ip6_rt_gc_timeout,
+               .data           =       &init_net.ipv6.sysctl.ip6_rt_gc_timeout,
                .maxlen         =       sizeof(int),
                .mode           =       0644,
                .proc_handler   =       &proc_dointvec_jiffies,
@@ -2455,7 +2455,7 @@ ctl_table ipv6_route_table[] = {
        {
                .ctl_name       =       NET_IPV6_ROUTE_GC_INTERVAL,
                .procname       =       "gc_interval",
-               .data           =       &ip6_rt_gc_interval,
+               .data           =       &init_net.ipv6.sysctl.ip6_rt_gc_interval,
                .maxlen         =       sizeof(int),
                .mode           =       0644,
                .proc_handler   =       &proc_dointvec_jiffies,
@@ -2464,7 +2464,7 @@ ctl_table ipv6_route_table[] = {
        {
                .ctl_name       =       NET_IPV6_ROUTE_GC_ELASTICITY,
                .procname       =       "gc_elasticity",
-               .data           =       &ip6_rt_gc_elasticity,
+               .data           =       &init_net.ipv6.sysctl.ip6_rt_gc_elasticity,
                .maxlen         =       sizeof(int),
                .mode           =       0644,
                .proc_handler   =       &proc_dointvec_jiffies,
@@ -2473,7 +2473,7 @@ ctl_table ipv6_route_table[] = {
        {
                .ctl_name       =       NET_IPV6_ROUTE_MTU_EXPIRES,
                .procname       =       "mtu_expires",
-               .data           =       &ip6_rt_mtu_expires,
+               .data           =       &init_net.ipv6.sysctl.ip6_rt_mtu_expires,
                .maxlen         =       sizeof(int),
                .mode           =       0644,
                .proc_handler   =       &proc_dointvec_jiffies,
@@ -2482,7 +2482,7 @@ ctl_table ipv6_route_table[] = {
        {
                .ctl_name       =       NET_IPV6_ROUTE_MIN_ADVMSS,
                .procname       =       "min_adv_mss",
-               .data           =       &ip6_rt_min_advmss,
+               .data           =       &init_net.ipv6.sysctl.ip6_rt_min_advmss,
                .maxlen         =       sizeof(int),
                .mode           =       0644,
                .proc_handler   =       &proc_dointvec_jiffies,
@@ -2491,7 +2491,7 @@ ctl_table ipv6_route_table[] = {
        {
                .ctl_name       =       NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS,
                .procname       =       "gc_min_interval_ms",
-               .data           =       &ip6_rt_gc_min_interval,
+               .data           =       &init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
                .maxlen         =       sizeof(int),
                .mode           =       0644,
                .proc_handler   =       &proc_dointvec_ms_jiffies,
@@ -2500,6 +2500,29 @@ ctl_table ipv6_route_table[] = {
        { .ctl_name = 0 }
 };
 
+struct ctl_table *ipv6_route_sysctl_init(struct net *net)
+{
+       struct ctl_table *table;
+
+       table = kmemdup(ipv6_route_table_template,
+                       sizeof(ipv6_route_table_template),
+                       GFP_KERNEL);
+
+       if (table) {
+               table[0].data = &net->ipv6.sysctl.flush_delay;
+               /* table[1].data will be handled when we have
+                  routes per namespace */
+               table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
+               table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
+               table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
+               table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval;
+               table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity;
+               table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
+               table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
+       }
+
+       return table;
+}
 #endif
 
 int __init ip6_route_init(void)
@@ -2522,16 +2545,14 @@ int __init ip6_route_init(void)
        if (ret)
                goto out_fib6_init;
 
-#ifdef CONFIG_XFRM
        ret = xfrm6_init();
        if (ret)
                goto out_proc_init;
-#endif
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+
        ret = fib6_rules_init();
        if (ret)
                goto xfrm6_init;
-#endif
+
        ret = -ENOBUFS;
        if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) ||
            __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) ||
@@ -2543,13 +2564,9 @@ out:
        return ret;
 
 fib6_rules_init:
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
        fib6_rules_cleanup();
 xfrm6_init:
-#endif
-#ifdef CONFIG_XFRM
        xfrm6_fini();
-#endif
 out_proc_init:
        ipv6_route_proc_fini(&init_net);
 out_fib6_init:
@@ -2562,13 +2579,9 @@ out_kmem_cache:
 
 void ip6_route_cleanup(void)
 {
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
        fib6_rules_cleanup();
-#endif
        ipv6_route_proc_fini(&init_net);
-#ifdef CONFIG_XFRM
        xfrm6_fini();
-#endif
        rt6_ifdown(NULL);
        fib6_gc_cleanup();
        kmem_cache_destroy(ip6_dst_ops.kmem_cachep);