> David S. Miller writes: > Next, we should put similar metrics into fib_hash.c A starting point... Kernel hack enclosed and companion app from: ftp://robur.slu.se/pub/Linux/net-development/fibstat Just some hash metrics yet. Output below is from our DoS tests: lookup_total == hash lookup/sec zone_search == zones search/sec chain_search == chain search/sec lookup_total zone_search chain_search 0 0 0 0 0 0 0 0 0 475084 4513198 2454249 861704 8186188 4450394 867935 8245366 4480320 863319 8201514 4458924 864056 8208532 4463344 863788 8205986 4461238 861772 8186834 4449507 --- include/net/ip_fib.h.030617 2003-06-17 15:03:57.000000000 +0200 +++ include/net/ip_fib.h 2003-06-17 16:07:00.000000000 +0200 @@ -135,6 +135,21 @@ unsigned char tb_data[0]; }; +struct fib_stat +{ + unsigned int lookup_total; + unsigned int zone_search; + unsigned int chain_search; +}; + +extern struct fib_stat *fib_stat; +#define FIB_STAT_INC(field) \ + (per_cpu_ptr(fib_stat, smp_processor_id())->field++) + + +extern int __init fib_stat_init(void); + + #ifndef CONFIG_IP_MULTIPLE_TABLES extern struct fib_table *ip_fib_local_table; --- net/ipv4/fib_hash.c.030617 2003-06-15 23:02:21.000000000 +0200 +++ net/ipv4/fib_hash.c 2003-06-17 16:01:45.000000000 +0200 @@ -13,6 +13,11 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. + * + * + * Fixes: + * Robert Olsson : Added statistics + * */ #include <linux/config.h> @@ -107,6 +112,10 @@ struct fn_zone *fn_zone_list; }; + +struct fib_stat *fib_stat; + + static __inline__ fn_hash_idx_t fn_hash(fn_key_t key, struct fn_zone *fz) { u32 h = ntohl(key.datum)>>(32 - fz->fz_order); @@ -307,12 +316,19 @@ struct fn_zone *fz; struct fn_hash *t = (struct fn_hash*)tb->tb_data; + FIB_STAT_INC(lookup_total); + read_lock(&fib_hash_lock); for (fz = t->fn_zone_list; fz; fz = fz->fz_next) { struct fib_node *f; fn_key_t k = fz_key(flp->fl4_dst, fz); + FIB_STAT_INC(zone_search); + for (f = fz_chain(k, fz); f; f = f->fn_next) { + + FIB_STAT_INC(chain_search); + if (!fn_key_eq(k, f->fn_key)) { if (fn_key_leq(k, f->fn_key)) break; @@ -1108,6 +1124,54 @@ .release = ip_seq_release, }; +static int fib_stat_get_info(char *buffer, char **start, off_t offset, int length) +{ + int i; + int len = 0; + + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_possible(i)) + continue; + len += sprintf(buffer+len, "%08x %08x %08x \n", + per_cpu_ptr(fib_stat, i)->lookup_total, + per_cpu_ptr(fib_stat, i)->zone_search, + per_cpu_ptr(fib_stat, i)->chain_search + + ); + } + len -= offset; + + if (len > length) + len = length; + if (len < 0) + len = 0; + + *start = buffer + offset; + return len; +} + +int __init fib_stat_init(void) +{ + int i, rc = 0; + + fib_stat = kmalloc_percpu(sizeof (struct fib_stat), + GFP_KERNEL); + if (!fib_stat) { + rc = -ENOMEM; + goto out; + } + + for (i = 0; i < NR_CPUS; i++) { + if (cpu_possible(i)) { + memset(per_cpu_ptr(fib_stat, i), 0, + sizeof (struct fib_stat)); + } + } + + out: + return rc; +} + int __init fib_proc_init(void) { struct proc_dir_entry *p; @@ -1116,13 +1180,27 @@ p = create_proc_entry("route", S_IRUGO, proc_net); if (p) p->proc_fops = &fib_seq_fops; - else + else { + rc = -ENOMEM; + goto out; + } + + + + p = proc_net_create ("fib_stat", 0, fib_stat_get_info); + + if (!p) { rc = -ENOMEM; + remove_proc_entry("route", proc_net); + } + + out: return rc; } void __init fib_proc_exit(void) { remove_proc_entry("route", proc_net); + remove_proc_entry("fib_stat", proc_net); } #endif /* CONFIG_PROC_FS */ --- net/ipv4/route.c.030617 2003-06-16 16:56:34.000000000 +0200 +++ net/ipv4/route.c 2003-06-17 16:02:41.000000000 +0200 @@ -2754,7 +2754,8 @@ rt_cache_stat = kmalloc_percpu(sizeof (struct rt_cache_stat), GFP_KERNEL); if (!rt_cache_stat) - goto out_enomem1; + goto out_enomem0; + for (i = 0; i < NR_CPUS; i++) { if (cpu_possible(i)) { memset(per_cpu_ptr(rt_cache_stat, i), 0, @@ -2765,6 +2766,9 @@ devinet_init(); ip_fib_init(); + if(fib_stat_init()) + goto out_enomem1; + init_timer(&rt_flush_timer); rt_flush_timer.function = rt_run_flush; init_timer(&rt_periodic_timer); @@ -2785,7 +2789,7 @@ #ifdef CONFIG_PROC_FS if (rt_cache_proc_init()) - goto out_enomem; + goto out_enomem2; proc_net_create ("rt_cache_stat", 0, rt_cache_stat_get_info); #ifdef CONFIG_NET_CLS_ROUTE create_proc_read_entry("net/rt_acct", 0, 0, ip_rt_acct_read, NULL); @@ -2795,9 +2799,12 @@ xfrm4_init(); out: return rc; -out_enomem: - kfree_percpu(rt_cache_stat); + +out_enomem2: + kfree_percpu(fib_stat); out_enomem1: + kfree_percpu(rt_cache_stat); +out_enomem0: rc = -ENOMEM; goto out; } Cheers. --ro - : send the line "unsubscribe linux-net" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html