diff options
| author | Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 2002-10-19 21:03:19 -0300 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 2002-10-19 21:03:19 -0300 |
| commit | 53008588b765cc238dd7b42a0455bb02df76cd39 (patch) | |
| tree | 7084c793fed718a8b274f2ddfdd1317aa2ccdd09 | |
| parent | ecf2c2143f0865f447020144b2ee6e4181f65814 (diff) | |
o ipv4: only produce one record per fib_seq_sholl call
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.
| -rw-r--r-- | include/net/ip.h | 1 | ||||
| -rw-r--r-- | include/net/ip_fib.h | 2 | ||||
| -rw-r--r-- | net/ipv4/af_inet.c | 1 | ||||
| -rw-r--r-- | net/ipv4/fib_hash.c | 257 | ||||
| -rw-r--r-- | net/ipv4/fib_semantics.c | 41 | ||||
| -rw-r--r-- | net/ipv4/ip_proc.c | 74 |
6 files changed, 229 insertions, 147 deletions
diff --git a/include/net/ip.h b/include/net/ip.h index 2d61d26fd188..bf14f1f50b90 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -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 */ diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 01ac6fdd2617..debc59c4c240 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -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 */ diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 3b76048f7b01..19b614a4ec2f 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1218,6 +1218,7 @@ static int __init inet_init(void) #endif ipv4_proc_init(); + fib_proc_init(); return 0; } diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index ac266c630436..05921a194fde 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -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 */ diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index bfb3e7da150d..5d35417db3df 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -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 diff --git a/net/ipv4/ip_proc.c b/net/ipv4/ip_proc.c index a115fc01ce0e..d909790861e8 100644 --- a/net/ipv4/ip_proc.c +++ b/net/ipv4/ip_proc.c @@ -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: |
