svn commit: r205065 - user/kmacy/head_flowtable_v6/sys/net
Kip Macy
kmacy at FreeBSD.org
Fri Mar 12 04:44:20 UTC 2010
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 <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
+#include <sys/sbuf.h>
#include <sys/sched.h>
#include <sys/smp.h>
#include <sys/socket.h>
@@ -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) {
More information about the svn-src-user
mailing list