From owner-svn-src-user@FreeBSD.ORG Fri Mar 12 04:44:20 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6C2091065689; Fri, 12 Mar 2010 04:44:20 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 5C4328FC1F; Fri, 12 Mar 2010 04:44:20 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o2C4iKvM093295; Fri, 12 Mar 2010 04:44:20 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o2C4iKHq093293; Fri, 12 Mar 2010 04:44:20 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201003120444.o2C4iKHq093293@svn.freebsd.org> From: Kip Macy Date: Fri, 12 Mar 2010 04:44:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r205065 - user/kmacy/head_flowtable_v6/sys/net X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Mar 2010 04:44:20 -0000 Author: kmacy Date: Fri Mar 12 04:44:20 2010 New Revision: 205065 URL: http://svn.freebsd.org/changeset/base/205065 Log: - cleanup whitespace - keep statistics per-cpu for per-cpu flowtables to avoid cache line contention - add sysctls to accumulate stats and report aggregate Modified: user/kmacy/head_flowtable_v6/sys/net/flowtable.c Modified: user/kmacy/head_flowtable_v6/sys/net/flowtable.c ============================================================================== --- user/kmacy/head_flowtable_v6/sys/net/flowtable.c Fri Mar 12 03:49:17 2010 (r205064) +++ user/kmacy/head_flowtable_v6/sys/net/flowtable.c Fri Mar 12 04:44:20 2010 (r205065) @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -145,14 +146,22 @@ union flentryp { struct flentry **pcpu[MAXCPU]; }; +struct flowtable_stats { + uint64_t ft_collisions; + uint64_t ft_allocated; + uint64_t ft_misses; + uint64_t ft_max_depth; + uint64_t ft_free_checks; + uint64_t ft_frees; + uint64_t ft_hits; + uint64_t ft_lookups; +} __aligned(128); + struct flowtable { + struct flowtable_stats ft_stats[MAXCPU]; int ft_size; int ft_lock_count; uint32_t ft_flags; - uint32_t ft_collisions; - uint32_t ft_allocated; - uint32_t ft_misses; - uint64_t ft_hits; uint32_t ft_udp_idle; uint32_t ft_fin_wait_idle; @@ -169,7 +178,7 @@ struct flowtable { bitstr_t *ft_masks[MAXCPU]; bitstr_t *ft_tmpmask; struct flowtable *ft_next; -}; +} __aligned(128); static struct proc *flowcleanerproc; static VNET_DEFINE(struct flowtable *, flow_list_head); @@ -217,13 +226,6 @@ do { \ */ VNET_DEFINE(int, flowtable_enable) = 1; static VNET_DEFINE(int, flowtable_debug); -static VNET_DEFINE(int, flowtable_hits); -static VNET_DEFINE(int, flowtable_lookups); -static VNET_DEFINE(int, flowtable_misses); -static VNET_DEFINE(int, flowtable_frees); -static VNET_DEFINE(int, flowtable_free_checks); -static VNET_DEFINE(int, flowtable_max_depth); -static VNET_DEFINE(int, flowtable_collisions); static VNET_DEFINE(int, flowtable_syn_expire) = SYN_IDLE; static VNET_DEFINE(int, flowtable_udp_expire) = UDP_IDLE; static VNET_DEFINE(int, flowtable_fin_wait_expire) = FIN_WAIT_IDLE; @@ -233,13 +235,6 @@ static VNET_DEFINE(int, flowtable_ready) #define V_flowtable_enable VNET(flowtable_enable) #define V_flowtable_debug VNET(flowtable_debug) -#define V_flowtable_hits VNET(flowtable_hits) -#define V_flowtable_lookups VNET(flowtable_lookups) -#define V_flowtable_misses VNET(flowtable_misses) -#define V_flowtable_frees VNET(flowtable_frees) -#define V_flowtable_free_checks VNET(flowtable_free_checks) -#define V_flowtable_max_depth VNET(flowtable_max_depth) -#define V_flowtable_collisions VNET(flowtable_collisions) #define V_flowtable_syn_expire VNET(flowtable_syn_expire) #define V_flowtable_udp_expire VNET(flowtable_udp_expire) #define V_flowtable_fin_wait_expire VNET(flowtable_fin_wait_expire) @@ -252,20 +247,6 @@ SYSCTL_VNET_INT(_net_inet_flowtable, OID &VNET_NAME(flowtable_debug), 0, "print debug info."); SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, enable, CTLFLAG_RW, &VNET_NAME(flowtable_enable), 0, "enable flowtable caching."); -SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, hits, CTLFLAG_RD, - &VNET_NAME(flowtable_hits), 0, "# flowtable hits."); -SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, lookups, CTLFLAG_RD, - &VNET_NAME(flowtable_lookups), 0, "# flowtable lookups."); -SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, misses, CTLFLAG_RD, - &VNET_NAME(flowtable_misses), 0, "#flowtable misses."); -SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, frees, CTLFLAG_RD, - &VNET_NAME(flowtable_frees), 0, "#flows freed."); -SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, free_checks, CTLFLAG_RD, - &VNET_NAME(flowtable_free_checks), 0, "#flows free checks."); -SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, max_depth, CTLFLAG_RD, - &VNET_NAME(flowtable_max_depth), 0, "max collision list length."); -SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, collisions, CTLFLAG_RD, - &VNET_NAME(flowtable_collisions), 0, "#flowtable collisions."); /* * XXX This does not end up updating timeouts at runtime @@ -315,6 +296,77 @@ SYSCTL_VNET_PROC(_net_inet_flowtable, OI CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_nmbflows, "IU", "Maximum number of flows allowed"); + + +#define FS_PRINT(sb, field) sbuf_printf((sb), "\t%s=%jd", #field, fs->ft_##field) + +static void +fs_print(struct flowtable_stats *fs) +{ + struct sbuf *sb; + + sb = sbuf_new(NULL, NULL, 32*1024, SBUF_FIXEDLEN); + + FS_PRINT(sb, collisions); + FS_PRINT(sb, allocated); + FS_PRINT(sb, misses); + FS_PRINT(sb, max_depth); + FS_PRINT(sb, free_checks); + FS_PRINT(sb, frees); + FS_PRINT(sb, hits); + FS_PRINT(sb, lookups); + sbuf_finish(sb); + +} + +static void +flowtable_show_stats(struct flowtable *ft) +{ + int i; + struct flowtable_stats fs, *pfs; + + if (ft->ft_flags & FL_PCPU) { + bzero(&fs, sizeof(fs)); + pfs = &fs; + for (i = 0; i <= mp_maxid; i++) { + if (CPU_ABSENT(i)) + continue; + pfs->ft_collisions += ft->ft_stats[i].ft_collisions; + pfs->ft_allocated += ft->ft_stats[i].ft_allocated; + pfs->ft_misses += ft->ft_stats[i].ft_misses; + pfs->ft_free_checks += ft->ft_stats[i].ft_free_checks; + pfs->ft_frees += ft->ft_stats[i].ft_frees; + pfs->ft_hits += ft->ft_stats[i].ft_hits; + pfs->ft_lookups += ft->ft_stats[i].ft_lookups; + if (ft->ft_stats[i].ft_max_depth > pfs->ft_max_depth) + pfs->ft_max_depth = ft->ft_stats[i].ft_max_depth; + } + } else { + pfs = &ft->ft_stats[0]; + } + + fs_print(pfs); +} + +static int +sysctl_flowtable_stats(SYSCTL_HANDLER_ARGS) +{ + struct flowtable *ft; + + ft = V_flow_list_head; + while (ft != NULL) { + printf("name: %s\n", ft->ft_name); + flowtable_show_stats(ft); + ft = ft->ft_next; + } + + return (0); +} +SYSCTL_VNET_PROC(_net_inet_flowtable, OID_AUTO, stats, + CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_flowtable_stats, "IU", + "flowtable statistics"); + + #ifndef RADIX_MPATH static void in_rtalloc_ign_wrapper(struct route *ro, uint32_t hash, u_int fibnum) @@ -867,6 +919,7 @@ flowtable_insert(struct flowtable *ft, u uint32_t fibnum, struct route *ro, uint16_t flags) { struct flentry *fle, *fletail, *newfle, **flep; + struct flowtable_stats *fs = &ft->ft_stats[curcpu]; int depth; uma_zone_t flezone; bitstr_t *mask; @@ -892,7 +945,7 @@ flowtable_insert(struct flowtable *ft, u } depth = 0; - V_flowtable_collisions++; + fs->ft_collisions++; /* * find end of list and make sure that we were not * preempted by another thread handling this flow @@ -921,8 +974,8 @@ flowtable_insert(struct flowtable *ft, u fle = fle->f_next; } - if (depth > V_flowtable_max_depth) - V_flowtable_max_depth = depth; + if (depth > fs->ft_max_depth) + fs->ft_max_depth = depth; fletail->f_next = newfle; fle = newfle; skip: @@ -1014,6 +1067,7 @@ flowtable_lookup(struct flowtable *ft, s { uint32_t key[9], hash; struct flentry *fle; + struct flowtable_stats *fs = &ft->ft_stats[curcpu]; uint8_t proto = 0; int error = 0; struct rtentry *rt; @@ -1066,7 +1120,7 @@ flowtable_lookup(struct flowtable *ft, s if (hash == 0 || (key[0] == 0 && (ft->ft_flags & FL_HASH_ALL))) return (NULL); - V_flowtable_lookups++; + fs->ft_lookups++; FL_ENTRY_LOCK(ft, hash); if ((fle = FL_ENTRY(ft, hash)) == NULL) { FL_ENTRY_UNLOCK(ft, hash); @@ -1082,7 +1136,7 @@ keycheck: && (fibnum == fle->f_fibnum) && (rt->rt_flags & RTF_UP) && (rt->rt_ifp != NULL)) { - V_flowtable_hits++; + fs->ft_hits++; fle->f_uptime = time_uptime; fle->f_flags |= flags; FL_ENTRY_UNLOCK(ft, hash); @@ -1096,7 +1150,7 @@ uncached: if (flags & FL_NOAUTO) return (NULL); - V_flowtable_misses++; + fs->ft_misses++; /* * This bit of code ends up locking the * same route 3 times (just like ip_output + ether_output) @@ -1291,7 +1345,8 @@ flowtable_free_stale(struct flowtable *f struct flentry *fle, **flehead, *fleprev; struct flentry *flefreehead, *flefreetail, *fletmp; bitstr_t *mask, *tmpmask; - + struct flowtable_stats *fs = &ft->ft_stats[curcpu]; + flefreehead = flefreetail = NULL; mask = flowtable_mask(ft); tmpmask = ft->ft_tmpmask; @@ -1308,12 +1363,12 @@ flowtable_free_stale(struct flowtable *f curbit); break; } - + FL_ENTRY_LOCK(ft, curbit); flehead = flowtable_entry(ft, curbit); fle = fleprev = *flehead; - V_flowtable_free_checks++; + fs->ft_free_checks++; #ifdef DIAGNOSTIC if (fle == NULL && curbit > 0) { log(LOG_ALERT, @@ -1351,7 +1406,7 @@ flowtable_free_stale(struct flowtable *f fleprev->f_next = fle->f_next; fle = fleprev->f_next; } - + if (flefreehead == NULL) flefreehead = flefreetail = fletmp; else { @@ -1370,7 +1425,7 @@ flowtable_free_stale(struct flowtable *f while ((fle = flefreehead) != NULL) { flefreehead = fle->f_next; count++; - V_flowtable_frees++; + fs->ft_frees++; fle_free(fle); } if (V_flowtable_debug && count) @@ -1381,6 +1436,7 @@ void flowtable_route_flush(struct flowtable *ft, struct rtentry *rt) { int i; + if (ft->ft_flags & FL_PCPU) { for (i = 0; i <= mp_maxid; i++) { if (CPU_ABSENT(i)) @@ -1471,7 +1527,7 @@ static void flowtable_flush(void *unused __unused) { uint64_t start; - + mtx_lock(&flowclean_lock); start = flowclean_cycles; while (start == flowclean_cycles) {