On Fri, Nov 18, 2016 at 03:30:48PM +1000, David Gwynne wrote:
> i didnt even know these existed.
>
> turns out you can see them with netstat -sr
jmatthew@ points out i didnt alloc the counters, and sparc64 says
im bad at testing alignment.
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 <sys/percpu.h>
+
+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)));
}
/*