static int fetch_tcpstats(struct tcp_stats *st) { struct tcp_stats stattmp[SMP_MAXCPU]; size_t len; int name[4], cpucnt; name[0] = CTL_NET; name[1] = PF_INET; name[2] = IPPROTO_TCP; name[3] = TCPCTL_STATS; len = sizeof(struct tcp_stats) * SMP_MAXCPU; if (sysctl(name, 4, stattmp, &len, NULL, 0) < 0) { error("sysctl getting tcp_stats failed"); return -1; } cpucnt = len / sizeof(struct tcp_stats); tcp_stats_agg(stattmp, st, cpucnt); return 0; }
/* * Dump TCP statistics structure. */ void tcp_stats(u_long off __unused, const char *name, int af1 __unused) { struct tcp_stats tcpstat, *stattmp; struct tcp_stats zerostat[SMP_MAXCPU]; size_t len = sizeof(struct tcp_stats) * SMP_MAXCPU; int cpucnt; if (zflag) memset(zerostat, 0, len); if ((stattmp = malloc(len)) == NULL) { return; } else { if (sysctlbyname("net.inet.tcp.stats", stattmp, &len, zflag ? zerostat : NULL, zflag ? len : 0) < 0) { warn("sysctl: net.inet.tcp.stats"); free(stattmp); return; } else { if ((stattmp = realloc(stattmp, len)) == NULL) { warn("tcp_stats"); return; } } } cpucnt = len / sizeof(struct tcp_stats); tcp_stats_agg(stattmp, &tcpstat, cpucnt); #ifdef INET6 if (tcp_done != 0) return; else tcp_done = 1; #endif printf ("%s:\n", name); #define p(f, m) if (tcpstat.f || sflag <= 1) \ printf(m, tcpstat.f, plural(tcpstat.f)) #define p1a(f, m) if (tcpstat.f || sflag <= 1) \ printf(m, tcpstat.f) #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) #define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2) #define p3(f, m) if (tcpstat.f || sflag <= 1) \ printf(m, tcpstat.f, plurales(tcpstat.f)) p(tcps_sndtotal, "\t%lu packet%s sent\n"); p2(tcps_sndpack,tcps_sndbyte, "\t\t%lu data packet%s (%lu byte%s)\n"); p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, "\t\t%lu data packet%s (%lu byte%s) retransmitted\n"); p2(tcps_sndsackrtopack, tcps_sndsackrtobyte, "\t\t%lu data packet%s (%lu byte%s) retransmitted by SACK\n"); p2(tcps_sndsackpack, tcps_sndsackbyte, "\t\t%lu data packet%s (%lu byte%s) sent by SACK recovery\n"); p2(tcps_sackrescue, tcps_sackrescue_try, "\t\t%lu SACK rescue packet%s sent (of %lu attempt%s)\n"); p2a(tcps_sndfastrexmit, tcps_sndearlyrexmit, "\t\t%lu Fast Retransmit%s (%lu early)\n"); p(tcps_sndlimited, "\t\t%lu packet%s sent by Limited Transmit\n"); p2(tcps_sndrtobad, tcps_eifelresponse, "\t\t%lu spurious RTO retransmit%s (%lu Eifel-response%s)\n"); p2a(tcps_sndfastrexmitbad, tcps_sndearlyrexmitbad, "\t\t%lu spurious Fast Retransmit%s (%lu early)\n"); p2a(tcps_eifeldetected, tcps_rttcantdetect, "\t\t%lu Eifel-detected spurious retransmit%s (%lu non-RTT)\n"); p(tcps_rttdetected, "\t\t%lu RTT-detected spurious retransmit%s\n"); p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n"); p(tcps_sndsackopt, "\t\t%lu SACK option%s sent\n"); p(tcps_snddsackopt, "\t\t%lu D-SACK option%s sent\n"); p2a(tcps_sndacks, tcps_delack, "\t\t%lu ack-only packet%s (%lu delayed)\n"); p(tcps_sndurg, "\t\t%lu URG only packet%s\n"); p(tcps_sndprobe, "\t\t%lu window probe packet%s\n"); p(tcps_sndwinup, "\t\t%lu window update packet%s\n"); p(tcps_sndctrl, "\t\t%lu control packet%s\n"); p(tcps_rcvtotal, "\t%lu packet%s received\n"); p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n"); p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n"); p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n"); p2(tcps_rcvpack, tcps_rcvbyte, "\t\t%lu packet%s (%lu byte%s) received in-sequence\n"); p2(tcps_rcvduppack, tcps_rcvdupbyte, "\t\t%lu completely duplicate packet%s (%lu byte%s)\n"); p2(tcps_pawsdrop, tcps_pawsaccept, "\t\t%lu old duplicate packet%s (%lu packet%s accepted)\n"); p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n"); p2(tcps_rcvoopack, tcps_rcvoobyte, "\t\t%lu out-of-order packet%s (%lu byte%s)\n"); p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, "\t\t%lu packet%s (%lu byte%s) of data after window\n"); p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n"); p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n"); p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n"); p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n"); p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n"); p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n"); p(tcps_rcvbadsackopt, "\t\t%lu bad SACK option%s\n"); p1a(tcps_sackrenege, "\t\t%lu other side reneged\n"); p(tcps_connattempt, "\t%lu connection request%s\n"); p(tcps_accepts, "\t%lu connection accept%s\n"); p(tcps_badsyn, "\t%lu bad connection attempt%s\n"); p(tcps_listendrop, "\t%lu listen queue overflow%s\n"); p(tcps_connects, "\t%lu connection%s established (including accepts)\n"); p2(tcps_closed, tcps_drops, "\t%lu connection%s closed (including %lu drop%s)\n"); p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n"); p(tcps_cachedrttvar, "\t\t%lu connection%s updated cached RTT variance on close\n"); p(tcps_cachedssthresh, "\t\t%lu connection%s updated cached ssthresh on close\n"); p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n"); p2(tcps_rttupdated, tcps_segstimed, "\t%lu segment%s updated rtt (of %lu attempt%s)\n"); p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n"); p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n"); p(tcps_persisttimeo, "\t%lu persist timeout%s\n"); p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n"); p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n"); p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n"); p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n"); p(tcps_predack, "\t%lu correct ACK header prediction%s\n"); p(tcps_preddat, "\t%lu correct data packet header prediction%s\n"); p(tcps_sndidle, "\t%lu send idle%s\n"); p1a(tcps_sc_added, "\t%lu syncache entries added\n"); p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n"); p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n"); p1a(tcps_sc_dropped, "\t\t%lu dropped\n"); p1a(tcps_sc_completed, "\t\t%lu completed\n"); p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n"); p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n"); p1a(tcps_sc_reset, "\t\t%lu reset\n"); p1a(tcps_sc_stale, "\t\t%lu stale\n"); p1a(tcps_sc_aborted, "\t\t%lu aborted\n"); p1a(tcps_sc_badack, "\t\t%lu badack\n"); p1a(tcps_sc_unreach, "\t\t%lu unreach\n"); p1a(tcps_sc_zonefail, "\t\t%lu zone failures\n"); p1a(tcps_sc_sendcookie, "\t\t%lu cookies sent\n"); p1a(tcps_sc_recvcookie, "\t\t%lu cookies received\n"); p(tcps_sacksbupdate, "\t%lu SACK scoreboard update%s\n"); p(tcps_sacksboverflow, "\t\t%lu overflow%s\n"); p(tcps_sacksbfailed, "\t\t%lu failure%s\n"); p(tcps_sacksbreused, "\t\t%lu record%s reused\n"); p(tcps_sacksbfast, "\t\t%lu record%s fast allocated\n"); free(stattmp); #undef p #undef p1a #undef p2 #undef p2a #undef p3 }