o ipv4/route: convert /proc/net/rt_cache to seq_file

parent 15d9a078
...@@ -107,7 +107,7 @@ struct rt_cache_stat ...@@ -107,7 +107,7 @@ struct rt_cache_stat
extern struct ip_rt_acct *ip_rt_acct; extern struct ip_rt_acct *ip_rt_acct;
struct in_device; struct in_device;
extern void ip_rt_init(void); extern int ip_rt_init(void);
extern void ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw, extern void ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw,
u32 src, u8 tos, struct net_device *dev); u32 src, u8 tos, struct net_device *dev);
extern void ip_rt_advice(struct rtable **rp, int advice); extern void ip_rt_advice(struct rtable **rp, int advice);
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
* Vladimir V. Ivanov : IP rule info (flowid) is really useful. * Vladimir V. Ivanov : IP rule info (flowid) is really useful.
* Marc Boucher : routing by fwmark * Marc Boucher : routing by fwmark
* Robert Olsson : Added rt_cache statistics * Robert Olsson : Added rt_cache statistics
* Arnaldo C. Melo : Convert proc stuff to seq_file
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -208,74 +209,107 @@ static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos) ...@@ -208,74 +209,107 @@ static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos)
return (hash ^ (hash >> 8)) & rt_hash_mask; return (hash ^ (hash >> 8)) & rt_hash_mask;
} }
static int rt_cache_get_info(char *buffer, char **start, off_t offset, #ifdef CONFIG_PROC_FS
int length) struct rt_cache_iter_state {
int bucket;
};
static struct rtable *rt_cache_get_first(struct seq_file *seq)
{ {
int len = 0; struct rtable *r = NULL;
off_t pos = 128; struct rt_cache_iter_state *st = seq->private;
char temp[256];
struct rtable *r;
int i;
if (offset < 128) { for (st->bucket = rt_hash_mask; st->bucket >= 0; --st->bucket) {
sprintf(buffer, "%-127s\n", read_lock_bh(&rt_hash_table[st->bucket].lock);
"Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\t" r = rt_hash_table[st->bucket].chain;
"Metric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\t" if (r)
"HHUptod\tSpecDst"); break;
len = 128; read_unlock_bh(&rt_hash_table[st->bucket].lock);
} }
return r;
}
for (i = rt_hash_mask; i >= 0; i--) { static struct rtable *rt_cache_get_next(struct seq_file *seq, struct rtable *r)
read_lock_bh(&rt_hash_table[i].lock); {
for (r = rt_hash_table[i].chain; r; r = r->u.rt_next) { struct rt_cache_iter_state *st = seq->private;
/*
* Spin through entries until we are ready
*/
pos += 128;
if (pos <= offset) { r = r->u.rt_next;
len = 0; while (!r) {
continue; read_unlock_bh(&rt_hash_table[st->bucket].lock);
if (--st->bucket < 0)
break;
read_lock_bh(&rt_hash_table[st->bucket].lock);
r = rt_hash_table[st->bucket].chain;
} }
return r;
}
static struct rtable *rt_cache_get_idx(struct seq_file *seq, loff_t pos)
{
struct rtable *r = rt_cache_get_first(seq);
if (r)
while (pos && (r = rt_cache_get_next(seq, r)))
--pos;
return pos ? NULL : r;
}
static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
{
return *pos ? rt_cache_get_idx(seq, *pos) : (void *)1;
}
static void *rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct rtable *r = NULL;
if (v == (void *)1)
r = rt_cache_get_first(seq);
else
r = rt_cache_get_next(seq, v);
++*pos;
return r;
}
static void rt_cache_seq_stop(struct seq_file *seq, void *v)
{
if (v && v != (void *)1) {
struct rt_cache_iter_state *st = seq->private;
read_unlock_bh(&rt_hash_table[st->bucket].lock);
}
}
static int rt_cache_seq_show(struct seq_file *seq, void *v)
{
if (v == (void *)1)
seq_printf(seq, "%-127s\n",
"Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\t"
"Metric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\t"
"HHUptod\tSpecDst");
else {
struct rtable *r = v;
char temp[256];
sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t" sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
"%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X", "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
r->u.dst.dev ? r->u.dst.dev->name : "*", r->u.dst.dev ? r->u.dst.dev->name : "*",
(unsigned long)r->rt_dst, (unsigned long)r->rt_dst, (unsigned long)r->rt_gateway,
(unsigned long)r->rt_gateway, r->rt_flags, atomic_read(&r->u.dst.__refcnt),
r->rt_flags, r->u.dst.__use, 0, (unsigned long)r->rt_src,
atomic_read(&r->u.dst.__refcnt),
r->u.dst.__use,
0,
(unsigned long)r->rt_src,
(dst_metric(&r->u.dst, RTAX_ADVMSS) ? (dst_metric(&r->u.dst, RTAX_ADVMSS) ?
(int) dst_metric(&r->u.dst, RTAX_ADVMSS) + 40 : 0), (int)dst_metric(&r->u.dst, RTAX_ADVMSS) + 40 : 0),
dst_metric(&r->u.dst, RTAX_WINDOW), dst_metric(&r->u.dst, RTAX_WINDOW),
(int)((dst_metric(&r->u.dst, RTAX_RTT) >> 3) (int)((dst_metric(&r->u.dst, RTAX_RTT) >> 3) +
+ dst_metric(&r->u.dst, RTAX_RTTVAR)), dst_metric(&r->u.dst, RTAX_RTTVAR)),
r->fl.fl4_tos, r->fl.fl4_tos,
r->u.dst.hh ? r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1,
atomic_read(&r->u.dst.hh->hh_refcnt) : r->u.dst.hh ? (r->u.dst.hh->hh_output ==
-1,
r->u.dst.hh ?
(r->u.dst.hh->hh_output ==
dev_queue_xmit) : 0, dev_queue_xmit) : 0,
r->rt_spec_dst); r->rt_spec_dst);
sprintf(buffer + len, "%-127s\n", temp); seq_printf(seq, "%-127s\n", temp);
len += 128;
if (pos >= offset+length) {
read_unlock_bh(&rt_hash_table[i].lock);
goto done;
}
}
read_unlock_bh(&rt_hash_table[i].lock);
} }
return 0;
done:
*start = buffer + len - (pos - offset);
len = pos - offset;
if (len > length)
len = length;
return len;
} }
static int rt_cache_stat_get_info(char *buffer, char **start, off_t offset, int length) static int rt_cache_stat_get_info(char *buffer, char **start, off_t offset, int length)
...@@ -317,6 +351,59 @@ static int rt_cache_stat_get_info(char *buffer, char **start, off_t offset, int ...@@ -317,6 +351,59 @@ static int rt_cache_stat_get_info(char *buffer, char **start, off_t offset, int
return len; return len;
} }
static struct seq_operations rt_cache_seq_ops = {
.start = rt_cache_seq_start,
.next = rt_cache_seq_next,
.stop = rt_cache_seq_stop,
.show = rt_cache_seq_show,
};
static int rt_cache_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
struct rt_cache_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
rc = seq_open(file, &rt_cache_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 rt_cache_seq_fops = {
.open = rt_cache_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = ip_seq_release,
};
int __init rt_cache_proc_init(void)
{
int rc = 0;
struct proc_dir_entry *p = create_proc_entry("rt_cache", S_IRUGO,
proc_net);
if (p)
p->proc_fops = &rt_cache_seq_fops;
else
rc = -ENOMEM;
return rc;
}
void __init rt_cache_proc_exit(void)
{
remove_proc_entry("rt_cache", proc_net);
}
#endif /* CONFIG_PROC_FS */
static __inline__ void rt_free(struct rtable *rt) static __inline__ void rt_free(struct rtable *rt)
{ {
dst_free(&rt->u.dst); dst_free(&rt->u.dst);
...@@ -2456,6 +2543,7 @@ struct ip_rt_acct *ip_rt_acct; ...@@ -2456,6 +2543,7 @@ struct ip_rt_acct *ip_rt_acct;
/* IP route accounting ptr for this logical cpu number. */ /* IP route accounting ptr for this logical cpu number. */
#define IP_RT_ACCT_CPU(i) (ip_rt_acct + i * 256) #define IP_RT_ACCT_CPU(i) (ip_rt_acct + i * 256)
#ifdef CONFIG_PROC_FS
static int ip_rt_acct_read(char *buffer, char **start, off_t offset, static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
int length, int *eof, void *data) int length, int *eof, void *data)
{ {
...@@ -2488,11 +2576,12 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset, ...@@ -2488,11 +2576,12 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
} }
return length; return length;
} }
#endif #endif /* CONFIG_PROC_FS */
#endif /* CONFIG_NET_CLS_ROUTE */
void __init ip_rt_init(void) int __init ip_rt_init(void)
{ {
int i, order, goal; int i, order, goal, rc = 0;
#ifdef CONFIG_NET_CLS_ROUTE #ifdef CONFIG_NET_CLS_ROUTE
for (order = 0; for (order = 0;
...@@ -2560,10 +2649,16 @@ void __init ip_rt_init(void) ...@@ -2560,10 +2649,16 @@ void __init ip_rt_init(void)
ip_rt_gc_interval; ip_rt_gc_interval;
add_timer(&rt_periodic_timer); add_timer(&rt_periodic_timer);
proc_net_create ("rt_cache", 0, rt_cache_get_info); if (rt_cache_proc_init())
goto out_enomem;
proc_net_create ("rt_cache_stat", 0, rt_cache_stat_get_info); proc_net_create ("rt_cache_stat", 0, rt_cache_stat_get_info);
#ifdef CONFIG_NET_CLS_ROUTE #ifdef CONFIG_NET_CLS_ROUTE
create_proc_read_entry("net/rt_acct", 0, 0, ip_rt_acct_read, NULL); create_proc_read_entry("net/rt_acct", 0, 0, ip_rt_acct_read, NULL);
#endif #endif
xfrm_init(); xfrm_init();
out:
return rc;
out_enomem:
rc = -ENOMEM;
goto out;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment