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/clib_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: Harald Welte Index: linux-2.6.9-rc2-bk9-neigh1/net/ipv4/netfilter/ip_conntrack_standalone.c =================================================================== --- linux-2.6.9-rc2-bk9-neigh1.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-09-28 10:33:07.000000000 +0200 +++ linux-2.6.9-rc2-bk9-neigh1/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-09-28 10:55:17.000000000 +0200 @@ -270,10 +270,13 @@ { 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); } @@ -284,10 +287,10 @@ { 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); } @@ -303,6 +306,11 @@ 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, @@ -729,10 +737,11 @@ &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 Index: linux-2.6.9-rc2-bk9-neigh1/net/ipv4/route.c =================================================================== --- linux-2.6.9-rc2-bk9-neigh1.orig/net/ipv4/route.c 2004-09-26 12:11:20.000000000 +0200 +++ linux-2.6.9-rc2-bk9-neigh1/net/ipv4/route.c 2004-09-28 12:12:42.000000000 +0200 @@ -356,10 +356,13 @@ { 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 @@ { 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 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 @@ 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 Index: linux-2.6.9-rc2-bk9-neigh1/fs/proc/root.c =================================================================== --- linux-2.6.9-rc2-bk9-neigh1.orig/fs/proc/root.c 2004-09-13 07:33:11.000000000 +0200 +++ linux-2.6.9-rc2-bk9-neigh1/fs/proc/root.c 2004-09-28 11:41:10.000000000 +0200 @@ -18,7 +18,7 @@ #include #include -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 @@ } 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(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); Index: linux-2.6.9-rc2-bk9-neigh1/include/linux/proc_fs.h =================================================================== --- linux-2.6.9-rc2-bk9-neigh1.orig/include/linux/proc_fs.h 2004-09-13 07:33:39.000000000 +0200 +++ linux-2.6.9-rc2-bk9-neigh1/include/linux/proc_fs.h 2004-09-28 10:47:17.000000000 +0200 @@ -79,6 +79,7 @@ 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; Index: linux-2.6.9-rc2-bk9-neigh1/net/core/neighbour.c =================================================================== --- linux-2.6.9-rc2-bk9-neigh1.orig/net/core/neighbour.c 2004-09-28 00:15:51.000000000 +0200 +++ linux-2.6.9-rc2-bk9-neigh1/net/core/neighbour.c 2004-09-28 10:56:44.000000000 +0200 @@ -1333,22 +1333,11 @@ 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 = 0x1f;