PERFORCE change 166616 for review
Gabor Pali
pgj at FreeBSD.org
Mon Jul 27 13:18:20 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=166616
Change 166616 by pgj at 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 */
More information about the p4-projects
mailing list