2 * Copyright 1997,1999,2000 Andi Kleen. Subject to the GPL.
3 * $Id: statistics.c,v 1.17 2002/04/28 15:41:01 ak Exp $
4 * 19980630 - i18n - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
5 * 19981113 - i18n fixes - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
6 * 19990101 - added net/netstat, -t, -u, -w supprt - Bernd Eckenfels
23 int print_static
,f_raw
,f_tcp
,f_udp
,f_unknown
= 1;
26 number
= 0, opt_number
, i_forward
, i_inp_icmp
, i_outp_icmp
, i_rto_alg
,
43 struct statedesc states
[] = {
44 [number
] = { 4, NULL
},
45 [opt_number
] = { 4, NULL
},
46 [i_forward
] = { 4, NULL
},
47 [i_inp_icmp
] = { 8, N_("ICMP input histogram:") },
48 [i_outp_icmp
] = { 8, N_("ICMP output histogram:") },
52 static enum State state
;
54 #define I_STATIC (1<<16) /* static configuration option. */
55 #define I_TITLE (1<<17)
58 * XXX check against the snmp mib rfc.
60 * Don't mark the first field as translatable! It's a snmp MIB standard.
63 struct entry Iptab
[] =
65 {"Forwarding", N_("Forwarding is %s"), i_forward
| I_STATIC
},
66 {"DefaultTTL", N_("Default TTL is %u"), number
| I_STATIC
},
67 {"InReceives", N_("%u total packets received"), number
},
68 {"InHdrErrors", N_("%u with invalid headers"), opt_number
},
69 {"InAddrErrors", N_("%u with invalid addresses"), opt_number
},
70 {"ForwDatagrams", N_("%u forwarded"), number
},
71 {"InUnknownProtos", N_("%u with unknown protocol"), opt_number
},
72 {"InDiscards", N_("%u incoming packets discarded"), number
},
73 {"InDelivers", N_("%u incoming packets delivered"), number
},
74 {"OutRequests", N_("%u requests sent out"), number
}, /*? */
75 {"OutDiscards", N_("%u outgoing packets dropped"), opt_number
},
76 {"OutNoRoutes", N_("%u dropped because of missing route"), opt_number
},
77 {"ReasmTimeout", N_("%u fragments dropped after timeout"), opt_number
},
78 {"ReasmReqds", N_("%u reassemblies required"), opt_number
}, /* ? */
79 {"ReasmOKs", N_("%u packets reassembled ok"), opt_number
},
80 {"ReasmFails", N_("%u packet reassembles failed"), opt_number
},
81 {"FragOKs", N_("%u fragments received ok"), opt_number
},
82 {"FragFails", N_("%u fragments failed"), opt_number
},
83 {"FragCreates", N_("%u fragments created"), opt_number
}
86 struct entry Icmptab
[] =
88 {"InMsgs", N_("%u ICMP messages received"), number
},
89 {"InErrors", N_("%u input ICMP message failed."), number
},
90 {"InDestUnreachs", N_("destination unreachable: %u"), i_inp_icmp
| I_TITLE
},
91 {"InTimeExcds", N_("timeout in transit: %u"), i_inp_icmp
| I_TITLE
},
92 {"InParmProbs", N_("wrong parameters: %u"), i_inp_icmp
| I_TITLE
}, /*? */
93 {"InSrcQuenchs", N_("source quenches: %u"), i_inp_icmp
| I_TITLE
},
94 {"InRedirects", N_("redirects: %u"), i_inp_icmp
| I_TITLE
},
95 {"InEchos", N_("echo requests: %u"), i_inp_icmp
| I_TITLE
},
96 {"InEchoReps", N_("echo replies: %u"), i_inp_icmp
| I_TITLE
},
97 {"InTimestamps", N_("timestamp request: %u"), i_inp_icmp
| I_TITLE
},
98 {"InTimestampReps", N_("timestamp reply: %u"), i_inp_icmp
| I_TITLE
},
99 {"InAddrMasks", N_("address mask request: %u"), i_inp_icmp
| I_TITLE
}, /*? */
100 {"InAddrMaskReps", N_("address mask replies: %u"), i_inp_icmp
| I_TITLE
}, /*? */
101 {"OutMsgs", N_("%u ICMP messages sent"), number
},
102 {"OutErrors", N_("%u ICMP messages failed"), number
},
103 {"OutDestUnreachs", N_("destination unreachable: %u"), i_outp_icmp
| I_TITLE
},
104 {"OutTimeExcds", N_("time exceeded: %u"), i_outp_icmp
| I_TITLE
},
105 {"OutParmProbs", N_("wrong parameters: %u"), i_outp_icmp
| I_TITLE
}, /*? */
106 {"OutSrcQuenchs", N_("source quench: %u"), i_outp_icmp
| I_TITLE
},
107 {"OutRedirects", N_("redirect: %u"), i_outp_icmp
| I_TITLE
},
108 {"OutEchos", N_("echo request: %u"), i_outp_icmp
| I_TITLE
},
109 {"OutEchoReps", N_("echo replies: %u"), i_outp_icmp
| I_TITLE
},
110 {"OutTimestamps", N_("timestamp requests: %u"), i_outp_icmp
| I_TITLE
},
111 {"OutTimestampReps", N_("timestamp replies: %u"), i_outp_icmp
| I_TITLE
},
112 {"OutAddrMasks", N_("address mask requests: %u"), i_outp_icmp
| I_TITLE
},
113 {"OutAddrMaskReps", N_("address mask replies: %u"), i_outp_icmp
| I_TITLE
},
116 struct entry Tcptab
[] =
118 {"RtoAlgorithm", N_("RTO algorithm is %s"), i_rto_alg
| I_STATIC
},
119 {"RtoMin", "", number
},
120 {"RtoMax", "", number
},
121 {"MaxConn", "", number
},
122 {"ActiveOpens", N_("%u active connections openings"), number
},
123 {"PassiveOpens", N_("%u passive connection openings"), number
},
124 {"AttemptFails", N_("%u failed connection attempts"), number
},
125 {"EstabResets", N_("%u connection resets received"), number
},
126 {"CurrEstab", N_("%u connections established"), number
},
127 {"InSegs", N_("%u segments received"), number
},
128 {"OutSegs", N_("%u segments send out"), number
},
129 {"RetransSegs", N_("%u segments retransmited"), number
},
130 {"InErrs", N_("%u bad segments received."), number
},
131 {"OutRsts", N_("%u resets sent"), number
},
134 struct entry Udptab
[] =
136 {"InDatagrams", N_("%u packets received"), number
},
137 {"NoPorts", N_("%u packets to unknown port received."), number
},
138 {"InErrors", N_("%u packet receive errors"), number
},
139 {"OutDatagrams", N_("%u packets sent"), number
},
142 struct entry Tcpexttab
[] =
144 {"SyncookiesSent", N_("%u SYN cookies sent"), opt_number
},
145 {"SyncookiesRecv", N_("%u SYN cookies received"), opt_number
},
146 {"SyncookiesFailed", N_("%u invalid SYN cookies received"), opt_number
},
148 { "EmbryonicRsts", N_("%u resets received for embryonic SYN_RECV sockets"),
150 { "PruneCalled", N_("%u packets pruned from receive queue because of socket"
151 " buffer overrun"), opt_number
},
152 /* obsolete: 2.2.0 doesn't do that anymore */
153 { "RcvPruned", N_("%u packets pruned from receive queue"), opt_number
},
154 { "OfoPruned", N_("%u packets dropped from out-of-order queue because of"
155 " socket buffer overrun"), opt_number
},
156 { "OutOfWindowIcmps", N_("%u ICMP packets dropped because they were "
157 "out-of-window"), opt_number
},
158 { "LockDroppedIcmps", N_("%u ICMP packets dropped because"
159 " socket was locked"), opt_number
},
160 { "TW", N_("%u TCP sockets finished time wait in fast timer"), opt_number
},
161 { "TWRecycled", N_("%u time wait sockets recycled by time stamp"), opt_number
},
162 { "TWKilled", N_("%u TCP sockets finished time wait in slow timer"), opt_number
},
163 { "PAWSPassive", N_("%u passive connections rejected because of"
164 " time stamp"), opt_number
},
165 { "PAWSActive", N_("%u active connections rejected because of "
166 "time stamp"), opt_number
},
167 { "PAWSEstab", N_("%u packets rejects in established connections because of"
168 " timestamp"), opt_number
},
169 { "DelayedACKs", N_("%u delayed acks sent"), opt_number
},
170 { "DelayedACKLocked", N_("%u delayed acks further delayed because of"
171 " locked socket"), opt_number
},
172 { "DelayedACKLost", N_("Quick ack mode was activated %u times"), opt_number
},
173 { "ListenOverflows", N_("%u times the listen queue of a socket overflowed"),
175 { "ListenDrops", N_("%u SYNs to LISTEN sockets ignored"), opt_number
},
176 { "TCPPrequeued", N_("%u packets directly queued to recvmsg prequeue."),
178 { "TCPDirectCopyFromBacklog", N_("%u of bytes directly received"
179 " from backlog"), opt_number
},
180 { "TCPDirectCopyFromPrequeue", N_("%u of bytes directly received"
181 " from prequeue"), opt_number
},
182 { "TCPPrequeueDropped", N_("%u packets dropped from prequeue"), opt_number
},
183 { "TCPHPHits", N_("%u packet headers predicted"), number
},
184 { "TCPHPHitsToUser", N_("%u packets header predicted and "
185 "directly queued to user"), opt_number
},
186 { "SockMallocOOM", N_("Ran %u times out of system memory during "
187 "packet sending"), opt_number
},
188 { "TCPPureAcks", N_("%u acknowledgments not containing data received"), opt_number
},
189 { "TCPHPAcks", N_("%u predicted acknowledgments"), opt_number
},
190 { "TCPRenoRecovery", N_("%u times recovered from packet loss due to fast retransmit"), opt_number
},
191 { "TCPSackRecovery", N_("%u times recovered from packet loss due to SACK data"), opt_number
},
192 { "TCPSACKReneging", N_("%u bad SACKs received"), opt_number
},
193 { "TCPFACKReorder", N_("Detected reordering %u times using FACK"), opt_number
},
194 { "TCPSACKReorder", N_("Detected reordering %u times using SACK"), opt_number
},
195 { "TCPTSReorder", N_("Detected reordering %u times using time stamp"), opt_number
},
196 { "TCPRenoReorder", N_("Detected reordering %u times using reno fast retransmit"), opt_number
},
197 { "TCPFullUndo", N_("%u congestion windows fully recovered"), opt_number
},
198 { "TCPPartialUndo", N_("%u congestion windows partially recovered using Hoe heuristic"), opt_number
},
199 { "TCPDSackUndo", N_("%u congestion window recovered using DSACK"), opt_number
},
200 { "TCPLossUndo", N_("%u congestion windows recovered after partial ack"), opt_number
},
201 { "TCPLostRetransmits", N_("%u retransmits lost"), opt_number
},
202 { "TCPRenoFailures", N_("%u timeouts after reno fast retransmit"), opt_number
},
203 { "TCPSackFailures", N_("%u timeouts after SACK recovery"), opt_number
},
204 { "TCPLossFailures", N_("%u timeouts in loss state"), opt_number
},
205 { "TCPFastRetrans", N_("%u fast retransmits"), opt_number
},
206 { "TCPForwardRetrans", N_("%u forward retransmits"), opt_number
},
207 { "TCPSlowStartRetrans", N_("%u retransmits in slow start"), opt_number
},
208 { "TCPTimeouts", N_("%u other TCP timeouts"), opt_number
},
209 { "TCPRenoRecoveryFailed", N_("%u reno fast retransmits failed"), opt_number
},
210 { "TCPSackRecoveryFail", N_("%u sack retransmits failed"), opt_number
},
211 { "TCPSchedulerFailed", N_("%u times receiver scheduled too late for direct processing"), opt_number
},
212 { "TCPRcvCollapsed", N_("%u packets collapsed in receive queue due to low socket buffer"), opt_number
},
213 { "TCPDSACKOldSent", N_("%u DSACKs sent for old packets"), opt_number
},
214 { "TCPDSACKOfoSent", N_("%u DSACKs sent for out of order packets"), opt_number
},
215 { "TCPDSACKRecv", N_("%u DSACKs received"), opt_number
},
216 { "TCPDSACKOfoRecv", N_("%u DSACKs for out of order packets received"), opt_number
},
217 { "TCPAbortOnSyn", N_("%u connections reset due to unexpected SYN"), opt_number
},
218 { "TCPAbortOnData", N_("%u connections reset due to unexpected data"), opt_number
},
219 { "TCPAbortOnClose", N_("%u connections reset due to early user close"), opt_number
},
220 { "TCPAbortOnMemory", N_("%u connections aborted due to memory pressure"), opt_number
},
221 { "TCPAbortOnTimeout", N_("%u connections aborted due to timeout"), opt_number
},
222 { "TCPAbortOnLinger", N_("%u connections aborted after user close in linger timeout"), opt_number
},
223 { "TCPAbortFailed", N_("%u times unabled to send RST due to no memory"), opt_number
},
224 { "TCPMemoryPressures", N_("TCP ran low on memory %u times"), opt_number
},
225 { "TCPLoss", N_("%u TCP data loss events") },
235 struct tabtab snmptabs
[] =
237 {"Ip", Iptab
, sizeof(Iptab
), &f_raw
},
238 {"Icmp", Icmptab
, sizeof(Icmptab
), &f_raw
},
239 {"Tcp", Tcptab
, sizeof(Tcptab
), &f_tcp
},
240 {"Udp", Udptab
, sizeof(Udptab
), &f_udp
},
241 {"TcpExt", Tcpexttab
, sizeof(Tcpexttab
), &f_tcp
},
247 int cmpentries(const void *a
, const void *b
)
249 return strcmp(((struct entry
*) a
)->title
, ((struct entry
*) b
)->title
);
252 void printval(struct tabtab
*tab
, char *title
, int val
)
254 struct entry
*ent
= NULL
, key
;
260 ent
= bsearch(&key
, tab
->tab
, tab
->size
/ sizeof(struct entry
),
261 sizeof(struct entry
), cmpentries
);
262 if (!ent
) { /* try our best */
264 printf("%*s%s: %d\n", states
[state
].indent
, "", title
, val
);
268 if (type
& I_STATIC
) {
273 if (*ent
->out
== '\0')
276 if (type
& I_TITLE
) {
279 printf("%*s%s\n", states
[state
].indent
, "", _(states
[type
].title
));
288 snprintf(buf
, sizeof(buf
), _(ent
->out
), val
);
292 snprintf(buf
, sizeof(buf
), _(ent
->out
), val
== 2 ? _("enabled") : _("disabled"));
297 snprintf(buf
, sizeof(buf
), _(ent
->out
), val
);
299 case i_rto_alg
: /* XXXX */
305 printf("%*s%s\n", states
[type
].indent
, "", buf
);
310 struct tabtab
*newtable(struct tabtab
*tabs
, char *title
)
313 static struct tabtab dummytab
;
315 for (t
= tabs
; t
->title
; t
++) {
316 if (!strcmp(title
, t
->title
)) {
318 printf("%s:\n", _(title
));
325 printf("%s:\n", _(title
));
326 dummytab
.title
= title
;
327 dummytab
.flag
= &f_unknown
;
331 void process_fd(FILE *f
)
333 char buf1
[1024], buf2
[1024];
335 while (fgets(buf1
, sizeof buf1
, f
)) {
339 if (!fgets(buf2
, sizeof buf2
, f
))
341 sp
= strchr(buf1
, ':');
342 np
= strchr(buf2
, ':');
347 tab
= newtable(snmptabs
, buf1
);
349 printf("unknown %s\n", buf1
);
357 sp
+= strspn(sp
, " \t\n");
358 np
+= strspn(np
, " \t\n");
359 /*if (*np == '\0') goto formaterr; */
361 p
= sp
+strcspn(sp
, " \t\n");
366 if (*sp
!= '\0' && *(tab
->flag
))
367 printval(tab
, sp
, strtoul(np
, &np
, 10));
375 perror(_("error parsing /proc/net/snmp"));
380 void parsesnmp(int flag_raw
, int flag_tcp
, int flag_udp
)
384 f_raw
= flag_raw
; f_tcp
= flag_tcp
; f_udp
= flag_udp
;
386 f
= fopen("/proc/net/snmp", "r");
388 perror(_("cannot open /proc/net/snmp"));
394 perror("/proc/net/snmp");
398 f
= fopen("/proc/net/netstat", "r");
404 perror("/proc/net/netstat");
416 /* we sort at runtime because I'm lazy ;) */
417 for (t
= snmptabs
; t
->title
; t
++)
418 qsort(t
->tab
, t
->size
/ sizeof(struct entry
),
419 sizeof(struct entry
), cmpentries
);