Index: route.c =================================================================== RCS file: /cvs/src/sys/net/route.c,v retrieving revision 1.338 diff -u -p -r1.338 route.c --- route.c 15 Nov 2016 10:09:28 -0000 1.338 +++ route.c 18 Nov 2016 07:25:36 -0000 @@ -150,7 +150,7 @@ static uint32_t rt_hashjitter; extern unsigned int rtmap_limit; -struct rtstat rtstat; +struct cpumem * rtcounters; int rttrash; /* routes not in table but not freed */ int ifatrash; /* ifas not in ifp list but not free */ @@ -191,6 +191,8 @@ TAILQ_HEAD(rt_labels, rt_label) rt_label void route_init(void) { + rtcounters = counters_alloc(rts_ncounters, M_COUNTERS); + pool_init(&rtentry_pool, sizeof(struct rtentry), 0, IPL_SOFTNET, 0, "rtentry", NULL); @@ -265,7 +267,7 @@ rt_match(struct sockaddr *dst, uint32_t } rt->rt_use++; } else - rtstat.rts_unreach++; + rtstat_inc(rts_unreach); splx(s); return (rt); } @@ -538,7 +540,7 @@ rtredirect(struct sockaddr *dst, struct { struct rtentry *rt; int error = 0; - u_int32_t *stat = NULL; + enum rtstat_counters stat = rts_ncounters; struct rt_addrinfo info; struct ifaddr *ifa; unsigned int ifidx = 0; @@ -610,7 +612,7 @@ create: flags = rt->rt_flags; prio = rt->rt_priority; } - stat = &rtstat.rts_dynamic; + stat = rts_dynamic; } else { /* * Smash the current notion of the gateway to @@ -619,7 +621,7 @@ create: rt->rt_flags |= RTF_MODIFIED; flags |= RTF_MODIFIED; prio = rt->rt_priority; - stat = &rtstat.rts_newgateway; + stat = rts_newgateway; rt_setgate(rt, gateway, rdomain); } } else @@ -633,9 +635,9 @@ done: } out: if (error) - rtstat.rts_badredirect++; - else if (stat != NULL) - (*stat)++; + rtstat_inc(rts_badredirect); + else if (stat != rts_ncounters) + rtstat_inc(stat); bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = dst; info.rti_info[RTAX_GATEWAY] = gateway; Index: route.h =================================================================== RCS file: /cvs/src/sys/net/route.h,v retrieving revision 1.148 diff -u -p -r1.148 route.h --- route.h 24 Sep 2016 19:27:10 -0000 1.148 +++ route.h 18 Nov 2016 07:25:36 -0000 @@ -317,6 +317,26 @@ struct rt_addrinfo { #ifdef _KERNEL +#include + +enum rtstat_counters { + rts_badredirect, /* bogus redirect calls */ + rts_dynamic, /* routes created by redirects */ + rts_newgateway, /* routes modified by redirects */ + rts_unreach, /* lookups which failed */ + rts_wildcard, /* lookups satisfied by a wildcard */ + + rts_ncounters +}; + +static inline void +rtstat_inc(enum rtstat_counters c) +{ + extern struct cpumem *rtcounters; + + counters_inc(rtcounters, c); +} + /* * This structure, and the prototypes for the rt_timer_{init,remove_all, * add,timer} functions all used with the kind permission of BSDI. Index: rtsock.c =================================================================== RCS file: /cvs/src/sys/net/rtsock.c,v retrieving revision 1.208 diff -u -p -r1.208 rtsock.c --- rtsock.c 18 Oct 2016 11:05:45 -0000 1.208 +++ rtsock.c 18 Nov 2016 07:25:36 -0000 @@ -111,6 +111,7 @@ void rt_xaddrs(caddr_t, caddr_t, struc int sysctl_iflist(int, struct walkarg *); int sysctl_ifnames(struct walkarg *); +int sysctl_rtable_rtstat(void *, size_t *, void *); struct routecb { struct rawcb rcb; @@ -1611,10 +1612,8 @@ sysctl_rtable(int *name, u_int namelen, break; case NET_RT_STATS: - error = sysctl_rdstruct(where, given, new, - &rtstat, sizeof(rtstat)); splx(s); - return (error); + return (sysctl_rtable_rtstat(where, given, new)); case NET_RT_TABLE: tableid = w.w_arg; if (!rtable_exists(tableid)) { @@ -1642,6 +1641,25 @@ sysctl_rtable(int *name, u_int namelen, *given = (11 * w.w_needed) / 10; return (error); +} + +int +sysctl_rtable_rtstat(void *oldp, size_t *oldlenp, void *newp) +{ + extern struct cpumem *rtcounters; + uint64_t counters[rts_ncounters]; + struct rtstat rtstat; + uint32_t *words = (uint32_t *)&rtstat; + int i; + + KASSERT(sizeof(rtstat) == (nitems(counters) * sizeof(uint32_t))); + + counters_read(rtcounters, counters, nitems(counters)); + + for (i = 0; i < nitems(counters); i++) + words[i] = (uint32_t)counters[i]; + + return (sysctl_rdstruct(oldp, oldlenp, newp, &rtstat, sizeof(rtstat))); } /*