Date: Mon, 27 Jul 2009 13:18:11 GMT From: Gabor Pali <pgj@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 166616 for review Message-ID: <200907271318.n6RDIBGE082109@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=166616 Change 166616 by pgj@petymeg-current on 2009/07/27 13:17:25 Make netstat(1) to use libnetstat(3) for displaying and resetting TCP statistics. Affected files ... .. //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/extern.h#10 edit .. //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/inet.c#24 edit .. //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/main.c#18 edit Differences ... ==== //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/extern.h#10 (text+ko) ==== @@ -74,7 +74,7 @@ void inetpr(void *, int, int); void inetppr(const struct socket_type *); void unixdomainpr(const struct socket_type *); -void tcp_stats(u_long, const char *, int, int); +void tcp_stats(void *, const char *); void udp_stats(u_long, const char *, int, int); #ifdef SCTP void sctp_protopr(u_long, const char *, int, int); ==== //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/inet.c#24 (text+ko) ==== @@ -242,10 +242,11 @@ * Dump TCP statistics structure. */ void -tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) +tcp_stats(void *kvmd, const char *name) { - struct tcpstat tcpstat, zerostat; - size_t len = sizeof tcpstat; + const struct tcp_stat *s; + struct stat_type *sttp; + int stt_flags; #ifdef INET6 if (tcp_done != 0) @@ -254,125 +255,139 @@ tcp_done = 1; #endif - if (live) { - if (zflag) - memset(&zerostat, 0, len); - if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, - zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { - warn("sysctl: net.inet.tcp.stats"); - return; - } - } else - kread(off, &tcpstat, len); + if (zflag) { + netstat_zerostat(stat_TCP); + return; + } + + stt_flags = 0; + if (!live) + stt_flags |= NETSTAT_STAT_KVM; + + sttp = netstat_stat_alloc(); + if (sttp == NULL) { + warn("netstat_stat_alloc"); + return; + } + + if (netstat_stat(stat_TCP, sttp, stt_flags, kvmd) < 0) { + return; + } + + s = netstat_get_tcpstats(sttp); 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, pluralies(tcpstat.f)) +#define p(f, m) if (netstat_tcps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_tcps_get_##f(s), plural(netstat_tcps_get_##f(s))) +#define p1a(f, m) if (netstat_tcps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_tcps_get_##f(s)) +#define p2(f1, f2, m) if (netstat_tcps_get_##f1(s) || netstat_tcps_get_##f2(s) || sflag <= 1) \ + printf(m, netstat_tcps_get_##f1(s), plural(netstat_tcps_get_##f1(s)), \ + netstat_tcps_get_##f2(s), plural(netstat_tcps_get_##f2(s))) +#define p2a(f1, f2, m) if (netstat_tcps_get_##f1(s) || netstat_tcps_get_##f2(s) || sflag <= 1) \ + printf(m, netstat_tcps_get_##f1(s), plural(netstat_tcps_get_##f1(s)), \ + netstat_tcps_get_##f2(s)) +#define p3(f, m) if (netstat_tcps_get_##f(s) || sflag <= 1) \ + printf(m, netstat_tcps_get_##f(s), plural(netstat_tcps_get_##f(s))) + + p(sndtotal, "\t%ju packet%s sent\n"); + p2(sndpack,sndbyte, "\t\t%ju data packet%s (%ju byte%s)\n"); + p2(sndrexmitpack, sndrexmitbyte, + "\t\t%ju data packet%s (%ju byte%s) retransmitted\n"); + p(sndrexmitbad, + "\t\t%ju data packet%s unnecessarily retransmitted\n"); + p(mturesent, "\t\t%ju resend%s initiated by MTU discovery\n"); + p2a(sndacks, delack, + "\t\t%ju ack-only packet%s (%ju delayed)\n"); + p(sndurg, "\t\t%ju URG only packet%s\n"); + p(sndprobe, "\t\t%ju window probe packet%s\n"); + p(sndwinup, "\t\t%ju window update packet%s\n"); + p(sndctrl, "\t\t%ju control packet%s\n"); + p(rcvtotal, "\t%ju packet%s received\n"); + p2(rcvackpack, rcvackbyte, + "\t\t%ju ack%s (for %ju byte%s)\n"); + p(rcvdupack, "\t\t%ju duplicate ack%s\n"); + p(rcvacktoomuch, "\t\t%ju ack%s for unsent data\n"); + p2(rcvpack, rcvbyte, + "\t\t%ju packet%s (%ju byte%s) received in-sequence\n"); + p2(rcvduppack, rcvdupbyte, + "\t\t%ju completely duplicate packet%s (%ju byte%s)\n"); + p(pawsdrop, "\t\t%ju old duplicate packet%s\n"); + p2(rcvpartduppack, rcvpartdupbyte, + "\t\t%ju packet%s with some dup. data (%ju byte%s duped)\n"); + p2(rcvoopack, rcvoobyte, + "\t\t%ju out-of-order packet%s (%ju byte%s)\n"); + p2(rcvpackafterwin, rcvbyteafterwin, + "\t\t%ju packet%s (%ju byte%s) of data after window\n"); + p(rcvwinprobe, "\t\t%ju window probe%s\n"); + p(rcvwinupd, "\t\t%ju window update packet%s\n"); + p(rcvafterclose, "\t\t%ju packet%s received after close\n"); + p(rcvbadsum, "\t\t%ju discarded for bad checksum%s\n"); + p(rcvbadoff, "\t\t%ju discarded for bad header offset field%s\n"); + p1a(rcvshort, "\t\t%ju discarded because packet too short\n"); + p1a(rcvmemdrop, "\t\t%ju discarded due to memory problems\n"); + p(connattempt, "\t%ju connection request%s\n"); + p(accepts, "\t%ju connection accept%s\n"); + p(badsyn, "\t%ju bad connection attempt%s\n"); + p(listendrop, "\t%ju listen queue overflow%s\n"); + p(badrst, "\t%ju ignored RSTs in the window%s\n"); + p(connects, "\t%ju connection%s established (including accepts)\n"); + p2(closed, drops, + "\t%ju connection%s closed (including %ju drop%s)\n"); + p(cachedrtt, "\t\t%ju connection%s updated cached RTT on close\n"); + p(cachedrttvar, + "\t\t%ju connection%s updated cached RTT variance on close\n"); + p(cachedssthresh, + "\t\t%ju connection%s updated cached ssthresh on close\n"); + p(conndrops, "\t%ju embryonic connection%s dropped\n"); + p2(rttupdated, segstimed, + "\t%ju segment%s updated rtt (of %ju attempt%s)\n"); + p(rexmttimeo, "\t%ju retransmit timeout%s\n"); + p(timeoutdrop, "\t\t%ju connection%s dropped by rexmit timeout\n"); + p(persisttimeo, "\t%ju persist timeout%s\n"); + p(persistdrop, "\t\t%ju connection%s dropped by persist timeout\n"); + p(finwait2_drops, + "\t%ju Connection%s (fin_wait_2) dropped because of timeout\n"); + p(keeptimeo, "\t%ju keepalive timeout%s\n"); + p(keepprobe, "\t\t%ju keepalive probe%s sent\n"); + p(keepdrops, "\t\t%ju connection%s dropped by keepalive\n"); + p(predack, "\t%ju correct ACK header prediction%s\n"); + p(preddat, "\t%ju correct data packet header prediction%s\n"); - 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"); - p(tcps_sndrexmitbad, - "\t\t%lu data packet%s unnecessarily retransmitted\n"); - p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\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"); - p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\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"); - p1a(tcps_rcvmemdrop, "\t\t%lu discarded due to memory problems\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_badrst, "\t%lu ignored RSTs in the window%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_finwait2_drops, - "\t%lu Connection%s (fin_wait_2) dropped because of 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"); + p3(sc_added, "\t%ju syncache entr%s added\n"); + p1a(sc_retransmitted, "\t\t%ju retransmitted\n"); + p1a(sc_dupsyn, "\t\t%ju dupsyn\n"); + p1a(sc_dropped, "\t\t%ju dropped\n"); + p1a(sc_completed, "\t\t%ju completed\n"); + p1a(sc_bucketoverflow, "\t\t%ju bucket overflow\n"); + p1a(sc_cacheoverflow, "\t\t%ju cache overflow\n"); + p1a(sc_reset, "\t\t%ju reset\n"); + p1a(sc_stale, "\t\t%ju stale\n"); + p1a(sc_aborted, "\t\t%ju aborted\n"); + p1a(sc_badack, "\t\t%ju badack\n"); + p1a(sc_unreach, "\t\t%ju unreach\n"); + p(sc_zonefail, "\t\t%ju zone failure%s\n"); + p(sc_sendcookie, "\t%ju cookie%s sent\n"); + p(sc_recvcookie, "\t%ju cookie%s received\n"); - p3(tcps_sc_added, "\t%lu syncache entr%s 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"); - p(tcps_sc_zonefail, "\t\t%lu zone failure%s\n"); - p(tcps_sc_sendcookie, "\t%lu cookie%s sent\n"); - p(tcps_sc_recvcookie, "\t%lu cookie%s received\n"); + p(sack_recovery_episode, "\t%ju SACK recovery episode%s\n"); + p(sack_rexmits, + "\t%ju segment rexmit%s in SACK recovery episodes\n"); + p(sack_rexmit_bytes, + "\t%ju byte rexmit%s in SACK recovery episodes\n"); + p(sack_rcv_blocks, + "\t%ju SACK option%s (SACK blocks) received\n"); + p(sack_send_blocks, "\t%ju SACK option%s (SACK blocks) sent\n"); + p1a(sack_sboverflow, "\t%ju SACK scoreboard overflow\n"); - p(tcps_sack_recovery_episode, "\t%lu SACK recovery episode%s\n"); - p(tcps_sack_rexmits, - "\t%lu segment rexmit%s in SACK recovery episodes\n"); - p(tcps_sack_rexmit_bytes, - "\t%lu byte rexmit%s in SACK recovery episodes\n"); - p(tcps_sack_rcv_blocks, - "\t%lu SACK option%s (SACK blocks) received\n"); - p(tcps_sack_send_blocks, "\t%lu SACK option%s (SACK blocks) sent\n"); - p1a(tcps_sack_sboverflow, "\t%lu SACK scoreboard overflow\n"); + p(ecn_ce, "\t%ju packet%s with ECN CE bit set\n"); + p(ecn_ect0, "\t%ju packet%s with ECN ECT(0) bit set\n"); + p(ecn_ect1, "\t%ju packet%s with ECN ECT(1) bit set\n"); + p(ecn_shs, "\t%ju successful ECN handshake%s\n"); + p(ecn_rcwnd, "\t%ju time%s ECN reduced the congestion window\n"); - p(tcps_ecn_ce, "\t%lu packet%s with ECN CE bit set\n"); - p(tcps_ecn_ect0, "\t%lu packet%s with ECN ECT(0) bit set\n"); - p(tcps_ecn_ect1, "\t%lu packet%s with ECN ECT(1) bit set\n"); - p(tcps_ecn_shs, "\t%lu successful ECN handshake%s\n"); - p(tcps_ecn_rcwnd, "\t%lu time%s ECN reduced the congestion window\n"); + netstat_stat_free(sttp); #undef p #undef p1a #undef p2 ==== //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/main.c#18 (text+ko) ==== @@ -129,23 +129,21 @@ { .n_name = "_espstat" }, #define N_IPCOMPSTAT 25 { .n_name = "_ipcompstat" }, -#define N_TCPSTAT 26 - { .n_name = "_tcpstat" }, -#define N_UDPSTAT 27 +#define N_UDPSTAT 26 { .n_name = "_udpstat" }, -#define N_IPSTAT 28 +#define N_IPSTAT 27 { .n_name = "_ipstat" }, -#define N_ICMPSTAT 29 +#define N_ICMPSTAT 28 { .n_name = "_icmpstat" }, -#define N_IGMPSTAT 30 +#define N_IGMPSTAT 29 { .n_name = "_igmpstat" }, -#define N_PIMSTAT 31 +#define N_PIMSTAT 30 { .n_name = "_pimstat" }, -#define N_RIP6STAT 32 +#define N_RIP6STAT 31 { .n_name = "_rip6stat" }, -#define N_SCTPSTAT 33 +#define N_SCTPSTAT 32 { .n_name = "_sctpstat" }, -#define N_MFCTABLESIZE 34 +#define N_MFCTABLESIZE 33 { .n_name = "_mfctablesize" }, { .n_name = NULL }, }; @@ -163,8 +161,8 @@ int pr_usesysctl; /* non-zero if we use sysctl, not kvm */ int pr_protocol; } protox[] = { - { 0, N_TCPSTAT, 1, NULL, - tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, + { 0, 0, 1, NULL, + NULL, NULL, "tcp", 1, IPPROTO_TCP }, { 0, N_UDPSTAT, 1, NULL, udp_stats, NULL, "udp", 1, IPPROTO_UDP }, #ifdef SCTP @@ -201,8 +199,8 @@ #ifdef INET6 struct protox ip6protox[] = { - { 0, N_TCPSTAT, 1, NULL, - tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, + { 0, 0, 1, NULL, + NULL, NULL, "tcp", 1, IPPROTO_TCP }, { 0, N_UDPSTAT, 1, NULL, udp_stats, NULL, "udp", 1, IPPROTO_UDP }, { 0, N_IP6STAT, 1, NULL, @@ -534,6 +532,8 @@ } if (tp) { + if (!live) + kread(0, NULL, 0); printproto(tp, tp->pr_name); exit(0); } @@ -561,11 +561,11 @@ kread(0, NULL, 0); unixpr(kvmd); } - if (af == AF_UNSPEC || af == AF_INET + if ((af == AF_UNSPEC || af == AF_INET #ifdef INET6 || af == AF_INET6 #endif - ) { + ) && !sflag) { stlp = netstat_stl_alloc(); if (stlp == NULL) { warn("netstat_stl_alloc"); @@ -603,6 +603,14 @@ netstat_sti_free(stip); netstat_stl_free(stlp); } + + if (sflag && af == AF_UNSPEC) { + if (!live) + kread(0, NULL, 0); + for (tp = protox; tp->pr_name; tp++) + printproto(tp, tp->pr_name); + } + exit(0); } @@ -644,23 +652,31 @@ tp->pr_name); return; } else { - pr = tp->pr_stats; - if (!pr) { - if (pflag) - printf("%s: no stats routine\n", - tp->pr_name); - return; + /* XXX: temp. hack */ + switch (tp->pr_protocol) { + case IPPROTO_TCP: + tcp_stats(kvmd, "tcp"); + break; + default: + pr = tp->pr_stats; + if (!pr) { + if (pflag) + printf("%s: no stats routine\n", + tp->pr_name); + return; + } + if (tp->pr_usesysctl && live) + off = 0; + else if (tp->pr_sindex < 0) { + if (pflag) + printf( + "%s: stats routine doesn't work on cores\n", + tp->pr_name); + return; + } else + off = nl[tp->pr_sindex].n_value; + break; } - if (tp->pr_usesysctl && live) - off = 0; - else if (tp->pr_sindex < 0) { - if (pflag) - printf( - "%s: stats routine doesn't work on cores\n", - tp->pr_name); - return; - } else - off = nl[tp->pr_sindex].n_value; } } else { pr = tp->pr_cblocks; @@ -675,6 +691,10 @@ } else off = nl[tp->pr_index].n_value; } + + if (sflag) + return; + if ((off || (live && tp->pr_usesysctl) || af != AF_UNSPEC)) { /* XXX: temp. hack */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907271318.n6RDIBGE082109>