]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/route.c
[IPV6] ROUTE: Make sending algorithm more friendly with RFC 4861.
[net-next-2.6.git] / net / ipv6 / route.c
index 95f8e4a62f68f6048f01e964ae1b619d9e90a947..20083e0d3995cf13fcb3c3853b04925c3b2612bc 100644 (file)
 #include <linux/in6.h>
 #include <linux/init.h>
 #include <linux/if_arp.h>
-
-#ifdef         CONFIG_PROC_FS
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#endif
-
 #include <net/net_namespace.h>
 #include <net/snmp.h>
 #include <net/ipv6.h>
@@ -333,7 +329,7 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
 static inline int rt6_check_neigh(struct rt6_info *rt)
 {
        struct neighbour *neigh = rt->rt6i_nexthop;
-       int m = 0;
+       int m;
        if (rt->rt6i_flags & RTF_NONEXTHOP ||
            !(rt->rt6i_flags & RTF_GATEWAY))
                m = 1;
@@ -341,10 +337,15 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
                read_lock_bh(&neigh->lock);
                if (neigh->nud_state & NUD_VALID)
                        m = 2;
-               else if (!(neigh->nud_state & NUD_FAILED))
+#ifdef CONFIG_IPV6_ROUTER_PREF
+               else if (neigh->nud_state & NUD_FAILED)
+                       m = 0;
+#endif
+               else
                        m = 1;
                read_unlock_bh(&neigh->lock);
-       }
+       } else
+               m = 0;
        return m;
 }
 
@@ -548,12 +549,8 @@ restart:
        rt = rt6_device_match(rt, fl->oif, flags);
        BACKTRACK(&fl->fl6_src);
 out:
-       dst_hold(&rt->u.dst);
+       dst_use(&rt->u.dst, jiffies);
        read_unlock_bh(&table->tb6_lock);
-
-       rt->u.dst.lastuse = jiffies;
-       rt->u.dst.__use++;
-
        return rt;
 
 }
@@ -2288,71 +2285,50 @@ struct rt6_proc_arg
 
 static int rt6_info_route(struct rt6_info *rt, void *p_arg)
 {
-       struct rt6_proc_arg *arg = (struct rt6_proc_arg *) p_arg;
-
-       if (arg->skip < arg->offset / RT6_INFO_LEN) {
-               arg->skip++;
-               return 0;
-       }
-
-       if (arg->len >= arg->length)
-               return 0;
+       struct seq_file *m = p_arg;
 
-       arg->len += sprintf(arg->buffer + arg->len,
-                           NIP6_SEQFMT " %02x ",
-                           NIP6(rt->rt6i_dst.addr),
-                           rt->rt6i_dst.plen);
+       seq_printf(m, NIP6_SEQFMT " %02x ", NIP6(rt->rt6i_dst.addr),
+                  rt->rt6i_dst.plen);
 
 #ifdef CONFIG_IPV6_SUBTREES
-       arg->len += sprintf(arg->buffer + arg->len,
-                           NIP6_SEQFMT " %02x ",
-                           NIP6(rt->rt6i_src.addr),
-                           rt->rt6i_src.plen);
+       seq_printf(m, NIP6_SEQFMT " %02x ", NIP6(rt->rt6i_src.addr),
+                  rt->rt6i_src.plen);
 #else
-       arg->len += sprintf(arg->buffer + arg->len,
-                           "00000000000000000000000000000000 00 ");
+       seq_puts(m, "00000000000000000000000000000000 00 ");
 #endif
 
        if (rt->rt6i_nexthop) {
-               arg->len += sprintf(arg->buffer + arg->len,
-                                   NIP6_SEQFMT,
-                                   NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key)));
+               seq_printf(m, NIP6_SEQFMT,
+                          NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key)));
        } else {
-               arg->len += sprintf(arg->buffer + arg->len,
-                                   "00000000000000000000000000000000");
+               seq_puts(m, "00000000000000000000000000000000");
        }
-       arg->len += sprintf(arg->buffer + arg->len,
-                           " %08x %08x %08x %08x %8s\n",
-                           rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt),
-                           rt->u.dst.__use, rt->rt6i_flags,
-                           rt->rt6i_dev ? rt->rt6i_dev->name : "");
+       seq_printf(m, " %08x %08x %08x %08x %8s\n",
+                  rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt),
+                  rt->u.dst.__use, rt->rt6i_flags,
+                  rt->rt6i_dev ? rt->rt6i_dev->name : "");
        return 0;
 }
 
-static int rt6_proc_info(char *buffer, char **start, off_t offset, int length)
+static int ipv6_route_show(struct seq_file *m, void *v)
 {
-       struct rt6_proc_arg arg = {
-               .buffer = buffer,
-               .offset = offset,
-               .length = length,
-       };
-
-       fib6_clean_all(rt6_info_route, 0, &arg);
-
-       *start = buffer;
-       if (offset)
-               *start += offset % RT6_INFO_LEN;
-
-       arg.len -= offset % RT6_INFO_LEN;
-
-       if (arg.len > length)
-               arg.len = length;
-       if (arg.len < 0)
-               arg.len = 0;
+       fib6_clean_all(rt6_info_route, 0, m);
+       return 0;
+}
 
-       return arg.len;
+static int ipv6_route_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ipv6_route_show, NULL);
 }
 
+static const struct file_operations ipv6_route_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = ipv6_route_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static int rt6_stats_seq_show(struct seq_file *seq, void *v)
 {
        seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",
@@ -2489,22 +2465,14 @@ ctl_table ipv6_route_table[] = {
 
 void __init ip6_route_init(void)
 {
-#ifdef         CONFIG_PROC_FS
-       struct proc_dir_entry *p;
-#endif
        ip6_dst_ops.kmem_cachep =
                kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
                                  SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
        ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
 
        fib6_init();
-#ifdef         CONFIG_PROC_FS
-       p = proc_net_create(&init_net, "ipv6_route", 0, rt6_proc_info);
-       if (p)
-               p->owner = THIS_MODULE;
-
+       proc_net_fops_create(&init_net, "ipv6_route", 0, &ipv6_route_proc_fops);
        proc_net_fops_create(&init_net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
-#endif
 #ifdef CONFIG_XFRM
        xfrm6_init();
 #endif