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 @@
#include <asm/bitops.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
struct proc_dir_entry *proc_sys_root;
......@@ -53,6 +53,8 @@ void __init proc_root_init(void)
}
proc_misc_init();
proc_net = proc_mkdir("net", NULL);
proc_net_stat = proc_mkdir("net/stat", NULL);
#ifdef CONFIG_SYSVIPC
proc_mkdir("sysvipc", NULL);
#endif
......@@ -157,5 +159,6 @@ EXPORT_SYMBOL(remove_proc_entry);
EXPORT_SYMBOL(proc_root);
EXPORT_SYMBOL(proc_root_fs);
EXPORT_SYMBOL(proc_net);
EXPORT_SYMBOL(proc_net_stat);
EXPORT_SYMBOL(proc_bus);
EXPORT_SYMBOL(proc_root_driver);
......@@ -79,6 +79,7 @@ struct kcore_list {
extern struct proc_dir_entry proc_root;
extern struct proc_dir_entry *proc_root_fs;
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_root_driver;
extern struct proc_dir_entry *proc_root_kcore;
......
......@@ -1334,22 +1334,11 @@ void neigh_table_init(struct neigh_table *tbl)
panic("cannot create neighbour cache statistics");
#ifdef CONFIG_PROC_FS
#define NC_STAT_SUFFIX "_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);
tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat);
if (!tbl->pde)
panic("cannot create neighbour proc dir entry");
tbl->pde->proc_fops = &neigh_stat_seq_fops;
tbl->pde->data = tbl;
}
#endif
tbl->hash_mask = 1;
......
......@@ -268,10 +268,13 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
{
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))
continue;
*pos = cpu;
*pos = cpu+1;
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)
{
int cpu;
for (cpu = *pos + 1; cpu < NR_CPUS; ++cpu) {
for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
if (!cpu_possible(cpu))
continue;
*pos = cpu;
*pos = cpu+1;
return &per_cpu(ip_conntrack_stat, cpu);
}
......@@ -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);
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 "
"%08x %08x %08x %08x %08x %08x %08x %08x \n",
nr_conntracks,
......@@ -735,10 +743,11 @@ static int init_or_cleanup(int init)
&exp_file_ops);
if (!proc_exp) goto cleanup_proc;
proc_stat = proc_net_fops_create("ip_conntrack_stat", S_IRUGO,
&ct_cpu_seq_fops);
proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
if (!proc_stat)
goto cleanup_proc_exp;
proc_stat->proc_fops = &ct_cpu_seq_fops;
proc_stat->owner = THIS_MODULE;
#endif
......
......@@ -356,10 +356,13 @@ static void *rt_cpu_seq_start(struct seq_file *seq, loff_t *pos)
{
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))
continue;
*pos = cpu;
*pos = cpu+1;
return per_cpu_ptr(rt_cache_stat, cpu);
}
return NULL;
......@@ -369,10 +372,10 @@ static void *rt_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
int cpu;
for (cpu = *pos + 1; cpu < NR_CPUS; ++cpu) {
for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
if (!cpu_possible(cpu))
continue;
*pos = cpu;
*pos = cpu+1;
return per_cpu_ptr(rt_cache_stat, cpu);
}
return NULL;
......@@ -387,6 +390,11 @@ static void rt_cpu_seq_stop(struct seq_file *seq, void *v)
static int rt_cpu_seq_show(struct seq_file *seq, void *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 "
" %08x %08x %08x %08x %08x %08x %08x %08x %08x \n",
......@@ -2783,12 +2791,16 @@ int __init ip_rt_init(void)
add_timer(&rt_secret_timer);
#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) ||
!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);
return -ENOMEM;
}
rtstat_pde->proc_fops = &rt_cpu_seq_fops;
}
#ifdef CONFIG_NET_CLS_ROUTE
create_proc_read_entry("rt_acct", 0, proc_net, ip_rt_acct_read, NULL);
#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