]> git.neil.brown.name Git - history.git/commitdiff
o ipv4: only produce one record per fib_seq_sholl call
authorArnaldo Carvalho de Melo <acme@conectiva.com.br>
Sun, 20 Oct 2002 00:03:19 +0000 (21:03 -0300)
committerArnaldo Carvalho de Melo <acme@conectiva.com.br>
Sun, 20 Oct 2002 00:03:19 +0000 (21:03 -0300)
Also move the fib code back to the fib implementation, and that will
now be done for udp and arp, then finally burying the ip_proc stillborn.

include/net/ip.h
include/net/ip_fib.h
net/ipv4/af_inet.c
net/ipv4/fib_hash.c
net/ipv4/fib_semantics.c
net/ipv4/ip_proc.c

index 2d61d26fd1882f684034b965a571431023ede5fa..bf14f1f50b90d8d3eebd6951dafa702bfd5e9fba 100644 (file)
@@ -282,6 +282,7 @@ extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
 extern void    ip_local_error(struct sock *sk, int err, u32 daddr, u16 dport,
                               u32 info);
 
+extern int ip_seq_release(struct inode *inode, struct file *file);
 extern int ipv4_proc_init(void);
 
 #endif /* _IP_H */
index 01ac6fdd2617be39df643995e6069f2c69ad10b2..debc59c4c2407b280acd5ced0528e334f00361dc 100644 (file)
@@ -129,7 +129,6 @@ struct fib_table
        int             (*tb_dump)(struct fib_table *table, struct sk_buff *skb,
                                     struct netlink_callback *cb);
        int             (*tb_flush)(struct fib_table *table);
-       int             (*tb_seq_show)(struct fib_table *table, struct seq_file *seq);
        void            (*tb_select_default)(struct fib_table *table,
                                             const struct flowi *flp, struct fib_result *res);
 
@@ -277,5 +276,6 @@ static inline void fib_res_put(struct fib_result *res)
 #endif
 }
 
+extern int fib_proc_init(void);
 
 #endif  /* _NET_FIB_H */
index 3b76048f7b01b4bae649496a8376bd50fcd7062c..19b614a4ec2fce5a0f1b8aabae65edb7fc8533d5 100644 (file)
@@ -1218,6 +1218,7 @@ static int __init inet_init(void)
 #endif
 
        ipv4_proc_init();
+       fib_proc_init();
        return 0;
 }
 
index ac266c630436ac909e054e57b901857ddbc3d8a7..05921a194fdebef1907e35d8e3bbbfdb970d7716 100644 (file)
@@ -745,37 +745,6 @@ static int fn_hash_flush(struct fib_table *tb)
 }
 
 
-#ifdef CONFIG_PROC_FS
-
-static int fn_hash_seq_show(struct fib_table *tb, struct seq_file *seq)
-{
-       struct fn_hash *table = (struct fn_hash *)tb->tb_data;
-       struct fn_zone *fz;
-
-       read_lock(&fib_hash_lock);
-       for (fz = table->fn_zone_list; fz; fz = fz->fz_next) {
-               int i;
-               struct fib_node *f;
-               int maxslot = fz->fz_divisor;
-               struct fib_node **fp = fz->fz_hash;
-
-               if (!fz->fz_nent)
-                       continue;
-
-               for (i = 0; i < maxslot; i++, fp++)
-                       for (f = *fp; f; f = f->fn_next)
-                               fib_node_seq_show(seq, f->fn_type,
-                                                 f->fn_state & FN_S_ZOMBIE,
-                                                 FIB_INFO(f),
-                                                 fz_prefix(f->fn_key, fz),
-                                                 FZ_MASK(fz));
-       }
-       read_unlock(&fib_hash_lock);
-       return 0;
-}
-#endif
-
-
 static __inline__ int
 fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb,
                     struct fib_table *tb,
@@ -897,9 +866,229 @@ struct fib_table * __init fib_hash_init(int id)
        tb->tb_flush = fn_hash_flush;
        tb->tb_select_default = fn_hash_select_default;
        tb->tb_dump = fn_hash_dump;
-#ifdef CONFIG_PROC_FS
-       tb->tb_seq_show = fn_hash_seq_show;
-#endif
        memset(tb->tb_data, 0, sizeof(struct fn_hash));
        return tb;
 }
+
+/* ------------------------------------------------------------------------ */
+#ifdef CONFIG_PROC_FS
+
+struct fib_iter_state {
+       struct fn_zone  *zone;
+       int             bucket;
+       struct fib_node **hash;
+       struct fib_node *node;
+};
+
+static __inline__ struct fib_node *fib_get_first(struct seq_file *seq)
+{
+       struct fib_iter_state* iter = seq->private;
+       struct fn_hash *table = (struct fn_hash *)ip_fib_main_table->tb_data;
+
+       iter->bucket = 0;
+       iter->hash   = NULL;
+       iter->node   = NULL;
+
+       for (iter->zone = table->fn_zone_list; iter->zone;
+            iter->zone = iter->zone->fz_next) {
+               int maxslot;
+
+               if (!iter->zone->fz_next)
+                       continue;
+
+               iter->hash = iter->zone->fz_hash;
+               maxslot = iter->zone->fz_divisor;
+
+               for (iter->bucket = 0; iter->bucket < maxslot;
+                    ++iter->bucket, ++iter->hash) {
+                       iter->node = *iter->hash;
+
+                       if (iter->node)
+                               goto out;
+               }
+       }
+out:
+       return iter->node;
+}
+
+static __inline__ struct fib_node *fib_get_next(struct seq_file *seq)
+{
+       struct fib_iter_state* iter = seq->private;
+
+       if (iter->node)
+               iter->node = iter->node->fn_next;
+
+       if (iter->node)
+               goto out;
+
+       if (!iter->zone)
+               goto out;
+
+       for (;;) {
+               int maxslot;
+
+               maxslot = iter->zone->fz_divisor;
+
+               while (++iter->bucket < maxslot) {
+                       iter->node = *++iter->hash;
+
+                       if (iter->node)
+                               goto out;
+               }
+
+               for (;;) {
+                       iter->zone = iter->zone->fz_next;
+
+                       if (!iter->zone)
+                               goto out;
+                       if (iter->zone->fz_next);
+                               break;
+               }
+               
+               iter->hash = iter->zone->fz_hash;
+               iter->bucket = 0;
+               iter->node = *iter->hash;
+               if (iter->node)
+                       break;
+       }
+out:
+       return iter->node;
+}
+
+static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       void *v = NULL;
+
+       read_lock(&fib_hash_lock);
+       if (ip_fib_main_table)
+               v = *pos ? fib_get_next(seq) : (void *)1;
+       return v;
+}
+
+static void *fib_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       ++*pos;
+       return v == (void *)1 ? fib_get_first(seq) : fib_get_next(seq);
+}
+
+static void fib_seq_stop(struct seq_file *seq, void *v)
+{
+       read_unlock(&fib_hash_lock);
+}
+
+static unsigned fib_flag_trans(int type, int dead, u32 mask, struct fib_info *fi)
+{
+       static unsigned type2flags[RTN_MAX + 1] = {
+               [7] = RTF_REJECT, [8] = RTF_REJECT,
+       };
+       unsigned flags = type2flags[type];
+
+       if (fi && fi->fib_nh->nh_gw)
+               flags |= RTF_GATEWAY;
+       if (mask == 0xFFFFFFFF)
+               flags |= RTF_HOST;
+       if (!dead)
+               flags |= RTF_UP;
+       return flags;
+}
+
+/* 
+ *     This outputs /proc/net/route.
+ *
+ *     It always works in backward compatibility mode.
+ *     The format of the file is not supposed to be changed.
+ */
+static int fib_seq_show(struct seq_file *seq, void *v)
+{
+       struct fib_iter_state* iter;
+       char bf[128];
+       u32 prefix, mask;
+       unsigned flags;
+       struct fib_node *f;
+       struct fib_info *fi;
+
+       if (v == (void *)1) {
+               seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
+                          "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
+                          "\tWindow\tIRTT");
+               goto out;
+       }
+
+       f       = v;
+       fi      = FIB_INFO(f);
+       iter    = seq->private;
+       prefix  = fz_prefix(f->fn_key, iter->zone);
+       mask    = FZ_MASK(iter->zone);
+       flags   = fib_flag_trans(f->fn_type, f->fn_state & FN_S_ZOMBIE,
+                                mask, fi);
+       if (fi)
+               snprintf(bf, sizeof(bf),
+                        "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+                        fi->fib_dev ? fi->fib_dev->name : "*", prefix,
+                        fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
+                        mask, fi->fib_advmss + 40, fi->fib_window,
+                        fi->fib_rtt >> 3);
+       else
+               snprintf(bf, sizeof(bf),
+                        "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+                        prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0);
+       seq_printf(seq, "%-127s\n", bf);
+out:
+       return 0;
+}
+
+static struct seq_operations fib_seq_ops = {
+       .start  = fib_seq_start,
+       .next   = fib_seq_next,
+       .stop   = fib_seq_stop,
+       .show   = fib_seq_show,
+};
+
+static int fib_seq_open(struct inode *inode, struct file *file)
+{
+       struct seq_file *seq;
+       int rc = -ENOMEM;
+       struct fib_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+       
+       if (!s)
+               goto out;
+
+       rc = seq_open(file, &fib_seq_ops);
+       if (rc)
+               goto out_kfree;
+
+       seq          = file->private_data;
+       seq->private = s;
+       memset(s, 0, sizeof(*s));
+out:
+       return rc;
+out_kfree:
+       kfree(s);
+       goto out;
+}
+
+static struct file_operations fib_seq_fops = {
+       .open           = fib_seq_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = ip_seq_release,
+};
+
+int __init fib_proc_init(void)
+{
+       struct proc_dir_entry *p;
+       int rc = 0;
+
+       p = create_proc_entry("route", S_IRUGO, proc_net);
+       if (p)
+               p->proc_fops = &fib_seq_fops;
+       else
+               rc = -ENOMEM;
+       return rc;
+}
+#else /* CONFIG_PROC_FS */
+int __init fib_proc_init(void)
+{
+       return 0;
+}
+#endif /* CONFIG_PROC_FS */
index bfb3e7da150db2536eb5766d3d3914a647d55e17..5d35417db3dfa09d076e516b1e13a2656b048e1c 100644 (file)
@@ -997,44 +997,3 @@ void fib_select_multipath(const struct flowi *flp, struct fib_result *res)
        spin_unlock_bh(&fib_multipath_lock);
 }
 #endif
-
-
-#ifdef CONFIG_PROC_FS
-
-static unsigned fib_flag_trans(int type, int dead, u32 mask, struct fib_info *fi)
-{
-       static unsigned type2flags[RTN_MAX+1] = {
-               0, 0, 0, 0, 0, 0, 0, RTF_REJECT, RTF_REJECT, 0, 0, 0
-       };
-       unsigned flags = type2flags[type];
-
-       if (fi && fi->fib_nh->nh_gw)
-               flags |= RTF_GATEWAY;
-       if (mask == 0xFFFFFFFF)
-               flags |= RTF_HOST;
-       if (!dead)
-               flags |= RTF_UP;
-       return flags;
-}
-
-void fib_node_seq_show(struct seq_file *seq, int type, int dead,
-                      struct fib_info *fi, u32 prefix, u32 mask)
-{
-       char bf[128];
-       unsigned flags = fib_flag_trans(type, dead, mask, fi);
-
-       if (fi)
-               snprintf(bf, sizeof(bf),
-                        "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
-                        fi->fib_dev ? fi->fib_dev->name : "*", prefix,
-                        fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
-                        mask, fi->fib_advmss + 40, fi->fib_window,
-                        fi->fib_rtt >> 3);
-       else
-               snprintf(bf, sizeof(bf),
-                        "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
-                        prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0);
-       seq_printf(seq, "%-127s\n", bf);
-}
-
-#endif
index a115fc01ce0ef4251e2c9043f9c1307cdc6cc89f..d909790861e8af52631182a09b0f2eab239920b3 100644 (file)
@@ -21,7 +21,6 @@
 #include <net/udp.h>
 #include <linux/rtnetlink.h>
 #include <linux/route.h>
-#include <net/ip_fib.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
 
@@ -250,38 +249,6 @@ static int arp_seq_show(struct seq_file *seq, void *v)
 
 /* ------------------------------------------------------------------------ */
 
-static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       return *pos ? NULL : (void *)1;
-}
-
-static void *fib_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       return NULL;
-}
-
-static void fib_seq_stop(struct seq_file *seq, void *v)
-{
-}
-/* 
- *     This outputs /proc/net/route.
- *
- *     It always works in backward compatibility mode.
- *     The format of the file is not supposed to be changed.
- */
-static int fib_seq_show(struct seq_file *seq, void *v)
-{
-       seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
-                       "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
-                       "\tWindow\tIRTT");
-       if (ip_fib_main_table)
-               ip_fib_main_table->tb_seq_show(ip_fib_main_table, seq);
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-
 struct udp_iter_state {
        int bucket;
 };
@@ -384,13 +351,6 @@ static struct seq_operations arp_seq_ops = {
        .show   = arp_seq_show,
 };
 
-static struct seq_operations fib_seq_ops = {
-       .start  = fib_seq_start,
-       .next   = fib_seq_next,
-       .stop   = fib_seq_stop,
-       .show   = fib_seq_show,
-};
-
 static struct seq_operations udp_seq_ops = {
        .start  = udp_seq_start,
        .next   = udp_seq_next,
@@ -421,7 +381,7 @@ out_kfree:
        goto out;
 }
 
-static int arp_seq_release(struct inode *inode, struct file *file)
+int ip_seq_release(struct inode *inode, struct file *file)
 {
        struct seq_file *seq = (struct seq_file *)file->private_data;
 
@@ -431,11 +391,6 @@ static int arp_seq_release(struct inode *inode, struct file *file)
        return seq_release(inode, file);
 }
 
-static int fib_seq_open(struct inode *inode, struct file *file)
-{
-       return seq_open(file, &fib_seq_ops);
-}
-
 static int udp_seq_open(struct inode *inode, struct file *file)
 {
        struct seq_file *seq;
@@ -459,35 +414,18 @@ out_kfree:
        goto out;
 }
 
-static int udp_seq_release(struct inode *inode, struct file *file)
-{
-       struct seq_file *seq = (struct seq_file *)file->private_data;
-
-       kfree(seq->private);
-       seq->private = NULL;
-
-       return seq_release(inode, file);
-}
-
 static struct file_operations arp_seq_fops = {
        .open           = arp_seq_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = arp_seq_release,
-};
-
-static struct file_operations fib_seq_fops = {
-       .open           = fib_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = ip_seq_release,
 };
 
 static struct file_operations udp_seq_fops = {
        .open           = udp_seq_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = udp_seq_release,
+       .release        = ip_seq_release,
 };
 
 /* ------------------------------------------------------------------------ */
@@ -522,14 +460,8 @@ int __init ipv4_proc_init(void)
                goto out_arp;
        p->proc_fops = &arp_seq_fops;
 
-       p = create_proc_entry("route", S_IRUGO, proc_net);
-       if (!p)
-               goto out_route;
-       p->proc_fops = &fib_seq_fops;
 out:
        return rc;
-out_route:
-       remove_proc_entry("route", proc_net);
 out_arp:
        remove_proc_entry("udp", proc_net);
 out_udp: