summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_input.c
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2013-04-08 19:57:21 +0000
committerglebius <glebius@FreeBSD.org>2013-04-08 19:57:21 +0000
commit2a0fbb38ed223899ff5d9aaa8c88b3894a38ed5e (patch)
tree15680da61ff68a997e81ff315a361bf8f550f0a8 /sys/netinet/tcp_input.c
parent9cf64d6c35c62c34531273aadc2bfc0e0606fd77 (diff)
downloadFreeBSD-src-2a0fbb38ed223899ff5d9aaa8c88b3894a38ed5e.zip
FreeBSD-src-2a0fbb38ed223899ff5d9aaa8c88b3894a38ed5e.tar.gz
Merge from projects/counters: TCP/IP stats.
Convert 'struct ipstat' and 'struct tcpstat' to counter(9). This speeds up IP forwarding at extreme packet rates, and makes accounting more precise. Sponsored by: Nginx, Inc.
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r--sys/netinet/tcp_input.c74
1 files changed, 64 insertions, 10 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index ad92cfe..c490508 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -120,11 +120,6 @@ __FBSDID("$FreeBSD$");
const int tcprexmtthresh = 3;
-VNET_DEFINE(struct tcpstat, tcpstat);
-SYSCTL_VNET_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats, CTLFLAG_RW,
- &VNET_NAME(tcpstat), tcpstat,
- "TCP statistics (struct tcpstat, netinet/tcp_var.h)");
-
int tcp_log_in_vain = 0;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_in_vain, CTLFLAG_RW,
&tcp_log_in_vain, 0,
@@ -245,17 +240,76 @@ static void inline hhook_run_tcp_est_in(struct tcpcb *tp,
struct tcphdr *th, struct tcpopt *to);
/*
+ * TCP statistics are stored in struct tcpstat_p, which is
+ * an "array" of counter(9)s. Although it isn't a real
+ * array, we treat it as array to reduce code bloat.
+ */
+VNET_DEFINE(struct tcpstat_p, tcpstatp);
+
+static void
+vnet_tcpstatp_init(const void *unused)
+{
+ counter_u64_t *c;
+ int i;
+
+ for (i = 0, c = (counter_u64_t *)&V_tcpstatp;
+ i < sizeof(V_tcpstatp) / sizeof(counter_u64_t);
+ i++, c++) {
+ *c = counter_u64_alloc(M_WAITOK);
+ counter_u64_zero(*c);
+ }
+}
+VNET_SYSINIT(vnet_tcpstatp_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_tcpstatp_init, NULL);
+
+#ifdef VIMAGE
+static void
+vnet_tcpstatp_uninit(const void *unused)
+{
+ counter_u64_t *c;
+ int i;
+
+ for (i = 0, c = (counter_u64_t *)&V_tcpstatp;
+ i < sizeof(V_tcpstatp) / sizeof(counter_u64_t);
+ i++, c++)
+ counter_u64_free(*c);
+}
+VNET_SYSUNINIT(vnet_tcpstatp_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_ipstatp_uninit, NULL);
+#endif /* VIMAGE */
+
+static int
+tcpstat_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct tcpstat tcpstat;
+ counter_u64_t *c;
+ uint64_t *v;
+ int i;
+
+ for (i = 0, c = (counter_u64_t *)&V_tcpstatp, v = (uint64_t *)&tcpstat;
+ i < sizeof(V_tcpstatp) / sizeof(counter_u64_t);
+ i++, c++, v++) {
+ *v = counter_u64_fetch(*c);
+ if (req->newptr)
+ counter_u64_zero(*c);
+ }
+
+ return (SYSCTL_OUT(req, &tcpstat, sizeof(tcpstat)));
+}
+
+SYSCTL_VNET_PROC(_net_inet_tcp, TCPCTL_STATS, stats, CTLTYPE_OPAQUE |
+ CTLFLAG_RW, NULL, 0, tcpstat_sysctl, "I",
+ "TCP statistics (struct tcpstat, netinet/tcp_var.h)");
+
+/*
* Kernel module interface for updating tcpstat. The argument is an index
- * into tcpstat treated as an array of u_long. While this encodes the
- * general layout of tcpstat into the caller, it doesn't encode its location,
- * so that future changes to add, for example, per-CPU stats support won't
- * cause binary compatibility problems for kernel modules.
+ * into tcpstat treated as an array.
*/
void
kmod_tcpstat_inc(int statnum)
{
- (*((u_long *)&V_tcpstat + statnum))++;
+ counter_u64_add((counter_u64_t )&V_tcpstatp + statnum, 1);
}
/*
OpenPOWER on IntegriCloud