Commit 6ad5331e authored by Harald Welte's avatar Harald Welte Committed by David S. Miller

[NET]: Generic network statistics

This patch moves the following files in /proc:
	/proc/net/rt_cache_stat 	/proc/net/stat/rt_cache
	/proc/net/ip_conntrack_stat	/proc/net/stat/ip_conntrack
	/proc/net/arp_cache_stat	/proc/net/stat/arp_cache
	/proc/net/clip_arp_cache_stat	/proc/net/stat/clip_arp_cache
	/proc/net/dn_neigh_cache_stat	/proc/net/stat/dn_neigh_cache

This allows a generic statistics tool to scan for all available statistics
by doing readdir(2) on /proc/net/stat

It also adds a special first 'template' line to rt_cache and ip_conntrack
in order to facilitate compatibility once somebody adds new fields to the
output lines.

WARNING: 
	This breaks existing rtstat.c and ctstat.c userspace programs
	(hopefully for the last time).  rtstat is non-existant or broken in
	major distributions anyway, and ctstat is too new for any distros
	having it picked up.  Therefore, we justify this breakage.

A new unified statistics tool for routing cache, connection tracking and
neighbour cache is under development and will be included with iproute2.
Signed-off-by: default avatarHarald Welte <laforge@gnumonks.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4d22a9cc
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <asm/bitops.h> #include <asm/bitops.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver; struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
struct proc_dir_entry *proc_sys_root; struct proc_dir_entry *proc_sys_root;
...@@ -53,6 +53,8 @@ void __init proc_root_init(void) ...@@ -53,6 +53,8 @@ void __init proc_root_init(void)
} }
proc_misc_init(); proc_misc_init();
proc_net = proc_mkdir("net", NULL); proc_net = proc_mkdir("net", NULL);
proc_net_stat = proc_mkdir("net/stat", NULL);
#ifdef CONFIG_SYSVIPC #ifdef CONFIG_SYSVIPC
proc_mkdir("sysvipc", NULL); proc_mkdir("sysvipc", NULL);
#endif #endif
...@@ -157,5 +159,6 @@ EXPORT_SYMBOL(remove_proc_entry); ...@@ -157,5 +159,6 @@ EXPORT_SYMBOL(remove_proc_entry);
EXPORT_SYMBOL(proc_root); EXPORT_SYMBOL(proc_root);
EXPORT_SYMBOL(proc_root_fs); EXPORT_SYMBOL(proc_root_fs);
EXPORT_SYMBOL(proc_net); EXPORT_SYMBOL(proc_net);
EXPORT_SYMBOL(proc_net_stat);
EXPORT_SYMBOL(proc_bus); EXPORT_SYMBOL(proc_bus);
EXPORT_SYMBOL(proc_root_driver); EXPORT_SYMBOL(proc_root_driver);
...@@ -79,6 +79,7 @@ struct kcore_list { ...@@ -79,6 +79,7 @@ struct kcore_list {
extern struct proc_dir_entry proc_root; extern struct proc_dir_entry proc_root;
extern struct proc_dir_entry *proc_root_fs; extern struct proc_dir_entry *proc_root_fs;
extern struct proc_dir_entry *proc_net; extern struct proc_dir_entry *proc_net;
extern struct proc_dir_entry *proc_net_stat;
extern struct proc_dir_entry *proc_bus; extern struct proc_dir_entry *proc_bus;
extern struct proc_dir_entry *proc_root_driver; extern struct proc_dir_entry *proc_root_driver;
extern struct proc_dir_entry *proc_root_kcore; extern struct proc_dir_entry *proc_root_kcore;
......
...@@ -1334,22 +1334,11 @@ void neigh_table_init(struct neigh_table *tbl) ...@@ -1334,22 +1334,11 @@ void neigh_table_init(struct neigh_table *tbl)
panic("cannot create neighbour cache statistics"); panic("cannot create neighbour cache statistics");
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
#define NC_STAT_SUFFIX "_stat" tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat);
{
char *proc_stat_name;
proc_stat_name = kmalloc(strlen(tbl->id) +
strlen(NC_STAT_SUFFIX) + 1, GFP_KERNEL);
if (!proc_stat_name)
panic("cannot allocate neighbour cache proc name buffer");
strcpy(proc_stat_name, tbl->id);
strcat(proc_stat_name, NC_STAT_SUFFIX);
tbl->pde = create_proc_entry(proc_stat_name, 0, proc_net);
if (!tbl->pde) if (!tbl->pde)
panic("cannot create neighbour proc dir entry"); panic("cannot create neighbour proc dir entry");
tbl->pde->proc_fops = &neigh_stat_seq_fops; tbl->pde->proc_fops = &neigh_stat_seq_fops;
tbl->pde->data = tbl; tbl->pde->data = tbl;
}
#endif #endif
tbl->hash_mask = 1; tbl->hash_mask = 1;
......
...@@ -268,10 +268,13 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) ...@@ -268,10 +268,13 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
{ {
int cpu; int cpu;
for (cpu = *pos; cpu < NR_CPUS; ++cpu) { if (*pos == 0)
return SEQ_START_TOKEN;
for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
if (!cpu_possible(cpu)) if (!cpu_possible(cpu))
continue; continue;
*pos = cpu; *pos = cpu+1;
return &per_cpu(ip_conntrack_stat, cpu); return &per_cpu(ip_conntrack_stat, cpu);
} }
...@@ -282,10 +285,10 @@ static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -282,10 +285,10 @@ static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ {
int cpu; int cpu;
for (cpu = *pos + 1; cpu < NR_CPUS; ++cpu) { for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
if (!cpu_possible(cpu)) if (!cpu_possible(cpu))
continue; continue;
*pos = cpu; *pos = cpu+1;
return &per_cpu(ip_conntrack_stat, cpu); return &per_cpu(ip_conntrack_stat, cpu);
} }
...@@ -301,6 +304,11 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v) ...@@ -301,6 +304,11 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v)
unsigned int nr_conntracks = atomic_read(&ip_conntrack_count); unsigned int nr_conntracks = atomic_read(&ip_conntrack_count);
struct ip_conntrack_stat *st = v; struct ip_conntrack_stat *st = v;
if (v == SEQ_START_TOKEN) {
seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete\n");
return 0;
}
seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x " seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x "
"%08x %08x %08x %08x %08x %08x %08x %08x \n", "%08x %08x %08x %08x %08x %08x %08x %08x \n",
nr_conntracks, nr_conntracks,
...@@ -735,10 +743,11 @@ static int init_or_cleanup(int init) ...@@ -735,10 +743,11 @@ static int init_or_cleanup(int init)
&exp_file_ops); &exp_file_ops);
if (!proc_exp) goto cleanup_proc; if (!proc_exp) goto cleanup_proc;
proc_stat = proc_net_fops_create("ip_conntrack_stat", S_IRUGO, proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
&ct_cpu_seq_fops);
if (!proc_stat) if (!proc_stat)
goto cleanup_proc_exp; goto cleanup_proc_exp;
proc_stat->proc_fops = &ct_cpu_seq_fops;
proc_stat->owner = THIS_MODULE; proc_stat->owner = THIS_MODULE;
#endif #endif
......
...@@ -356,10 +356,13 @@ static void *rt_cpu_seq_start(struct seq_file *seq, loff_t *pos) ...@@ -356,10 +356,13 @@ static void *rt_cpu_seq_start(struct seq_file *seq, loff_t *pos)
{ {
int cpu; int cpu;
for (cpu = *pos; cpu < NR_CPUS; ++cpu) { if (*pos == 0)
return SEQ_START_TOKEN;
for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
if (!cpu_possible(cpu)) if (!cpu_possible(cpu))
continue; continue;
*pos = cpu; *pos = cpu+1;
return per_cpu_ptr(rt_cache_stat, cpu); return per_cpu_ptr(rt_cache_stat, cpu);
} }
return NULL; return NULL;
...@@ -369,10 +372,10 @@ static void *rt_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -369,10 +372,10 @@ static void *rt_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ {
int cpu; int cpu;
for (cpu = *pos + 1; cpu < NR_CPUS; ++cpu) { for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
if (!cpu_possible(cpu)) if (!cpu_possible(cpu))
continue; continue;
*pos = cpu; *pos = cpu+1;
return per_cpu_ptr(rt_cache_stat, cpu); return per_cpu_ptr(rt_cache_stat, cpu);
} }
return NULL; return NULL;
...@@ -388,6 +391,11 @@ static int rt_cpu_seq_show(struct seq_file *seq, void *v) ...@@ -388,6 +391,11 @@ static int rt_cpu_seq_show(struct seq_file *seq, void *v)
{ {
struct rt_cache_stat *st = v; struct rt_cache_stat *st = v;
if (v == SEQ_START_TOKEN) {
seq_printf(seq, "entries in_hit in_slow_tot in_no_route in_brd in_martian_dst in_martian_src out_hit out_slow_tot out_slow_mc gc_total gc_ignored gc_goal_miss gc_dst_overflow in_hlist_search out_hlist_search\n");
return 0;
}
seq_printf(seq,"%08x %08x %08x %08x %08x %08x %08x %08x " seq_printf(seq,"%08x %08x %08x %08x %08x %08x %08x %08x "
" %08x %08x %08x %08x %08x %08x %08x %08x %08x \n", " %08x %08x %08x %08x %08x %08x %08x %08x %08x \n",
atomic_read(&ipv4_dst_ops.entries), atomic_read(&ipv4_dst_ops.entries),
...@@ -2783,12 +2791,16 @@ int __init ip_rt_init(void) ...@@ -2783,12 +2791,16 @@ int __init ip_rt_init(void)
add_timer(&rt_secret_timer); add_timer(&rt_secret_timer);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
{
struct proc_dir_entry *rtstat_pde = NULL; /* keep gcc happy */
if (!proc_net_fops_create("rt_cache", S_IRUGO, &rt_cache_seq_fops) || if (!proc_net_fops_create("rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
!proc_net_fops_create("rt_cache_stat", S_IRUGO, &rt_cpu_seq_fops)) { !(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO,
proc_net_stat))) {
free_percpu(rt_cache_stat); free_percpu(rt_cache_stat);
return -ENOMEM; return -ENOMEM;
} }
rtstat_pde->proc_fops = &rt_cpu_seq_fops;
}
#ifdef CONFIG_NET_CLS_ROUTE #ifdef CONFIG_NET_CLS_ROUTE
create_proc_read_entry("rt_acct", 0, proc_net, ip_rt_acct_read, NULL); create_proc_read_entry("rt_acct", 0, proc_net, ip_rt_acct_read, NULL);
#endif #endif
......
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