+ "\t%u segment%s updated rtt (of %u attempt%s)\n");
+ p(tcps_rexmttimeo, "\t%u retransmit timeout%s\n");
+ p(tcps_timeoutdrop, "\t\t%u connection%s dropped by rexmit timeout\n");
+ p(tcps_rxtfindrop, "\t\t%u connection%s dropped after retransmitting FIN\n");
+ p(tcps_persisttimeo, "\t%u persist timeout%s\n");
+ p(tcps_persistdrop, "\t\t%u connection%s dropped by persist timeout\n");
+ p(tcps_keeptimeo, "\t%u keepalive timeout%s\n");
+ p(tcps_keepprobe, "\t\t%u keepalive probe%s sent\n");
+ p(tcps_keepdrops, "\t\t%u connection%s dropped by keepalive\n");
+ p(tcps_predack, "\t%u correct ACK header prediction%s\n");
+ p(tcps_preddat, "\t%u correct data packet header prediction%s\n");
+#ifdef TCP_MAX_SACK
+ /* TCP_MAX_SACK indicates the header has the SACK structures */
+ p(tcps_sack_recovery_episode, "\t%u SACK recovery episode%s\n");
+ p(tcps_sack_rexmits,
+ "\t%u segment rexmit%s in SACK recovery episodes\n");
+ p(tcps_sack_rexmit_bytes,
+ "\t%u byte rexmit%s in SACK recovery episodes\n");
+ p(tcps_sack_rcv_blocks,
+ "\t%u SACK option%s (SACK blocks) received\n");
+ p(tcps_sack_send_blocks, "\t%u SACK option%s (SACK blocks) sent\n");
+ p1a(tcps_sack_sboverflow, "\t%u SACK scoreboard overflow\n");
+#endif /* TCP_MAX_SACK */
+
+ p(tcps_coalesced_pack, "\t%u LRO coalesced packet%s\n");
+ p(tcps_flowtbl_full, "\t\t%u time%s LRO flow table was full\n");
+ p(tcps_flowtbl_collision, "\t\t%u collision%s in LRO flow table\n");
+ p(tcps_lro_twopack, "\t\t%u time%s LRO coalesced 2 packets\n");
+ p(tcps_lro_multpack, "\t\t%u time%s LRO coalesced 3 or 4 packets\n");
+ p(tcps_lro_largepack, "\t\t%u time%s LRO coalesced 5 or more packets\n");
+
+ p(tcps_limited_txt, "\t%u limited transmit%s done\n");
+ p(tcps_early_rexmt, "\t%u early retransmit%s done\n");
+ p(tcps_sack_ackadv, "\t%u time%s cumulative ack advanced along with SACK\n");
+
+ if (interval > 0) {
+ bcopy(&tcpstat, &ptcpstat, len);
+ pr_swcsum = r_swcsum;
+ pt_swcsum = t_swcsum;
+ }
+
+#undef TCPDIFF
+#undef p
+#undef p1a
+#undef p2
+#undef p2a
+#undef p3
+}
+
+#if TARGET_OS_EMBEDDED
+/*
+ * Dump MPTCP statistics
+ */
+void
+mptcp_stats(uint32_t off , char *name, int af)
+{
+ static struct tcpstat ptcpstat;
+ struct tcpstat tcpstat;
+ size_t len = sizeof tcpstat;
+
+ if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) {
+ warn("sysctl: net.inet.tcp.stats");
+ return;
+ }
+
+#ifdef INET6
+ if (mptcp_done != 0 && interval == 0)
+ return;
+ else
+ mptcp_done = 1;
+#endif
+
+ if (interval && vflag > 0)
+ print_time();
+ printf ("%s:\n", name);
+
+#define MPTCPDIFF(f) (tcpstat.f - ptcpstat.f)
+#define p(f, m) if (MPTCPDIFF(f) || sflag <= 1) \
+ printf(m, MPTCPDIFF(f), plural(MPTCPDIFF(f)))
+#define p1a(f, m) if (MPTCPDIFF(f) || sflag <= 1) \
+ printf(m, MPTCPDIFF(f))
+#define p2(f1, f2, m) if (MPTCPDIFF(f1) || MPTCPDIFF(f2) || sflag <= 1) \
+ printf(m, MPTCPDIFF(f1), plural(MPTCPDIFF(f1)), \
+ MPTCPDIFF(f2), plural(MPTCPDIFF(f2)))
+#define p2a(f1, f2, m) if (MPTCPDIFF(f1) || MPTCPDIFF(f2) || sflag <= 1) \
+ printf(m, MPTCPDIFF(f1), plural(MPTCPDIFF(f1)), MPTCPDIFF(f2))
+#define p3(f, m) if (MPTCPDIFF(f) || sflag <= 1) \
+ printf(m, MPTCPDIFF(f), plurales(MPTCPDIFF(f)))
+
+ p(tcps_mp_sndpacks, "\t%u data packet%s sent\n");
+ p(tcps_mp_sndbytes, "\t%u data byte%s sent\n");
+ p(tcps_mp_rcvtotal, "\t%u data packet%s received\n");
+ p(tcps_mp_rcvbytes, "\t%u data byte%s received\n");
+ p(tcps_invalid_mpcap, "\t%u packet%s with an invalid MPCAP option\n");
+ p(tcps_invalid_joins, "\t%u packet%s with an invalid MPJOIN option\n");
+ p(tcps_mpcap_fallback, "\t%u time%s primary subflow fell back to "
+ "TCP\n");
+ p(tcps_join_fallback, "\t%u time%s secondary subflow fell back to "
+ "TCP\n");
+ p(tcps_estab_fallback, "\t%u DSS option drop%s\n");
+ p(tcps_invalid_opt, "\t%u other invalid MPTCP option%s\n");
+ p(tcps_mp_reducedwin, "\t%u time%s the MPTCP subflow window was reduced\n");
+ p(tcps_mp_badcsum, "\t%u bad DSS checksum%s\n");
+ p(tcps_mp_oodata, "\t%u time%s received out of order data \n");
+ p3(tcps_mp_switches, "\t%u subflow switch%s\n");
+
+ if (interval > 0) {
+ bcopy(&tcpstat, &ptcpstat, len);
+ }
+
+#undef MPTCPDIFF