2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
14 #include <sys/types.h>
19 #include <sys/socket.h>
22 #include <arpa/inet.h>
24 #ifdef HAVE_NETINET_IN_H
25 #include <netinet/in.h>
27 #ifdef HAVE_SYS_TIME_H
35 #include <afs/afsutil.h>
41 #include <rx/rx_user.h>
42 #include <rx/rx_clock.h>
43 #include <rx/rx_queue.h>
45 #include <rx/rx_globals.h>
51 PortNumber(char *aport)
57 while ((tc = *aport++)) {
58 if (tc < '0' || tc > '9')
59 return -1; /* bad port number */
61 total += tc - (int)'0';
69 register struct servent *ts;
70 ts = getservbyname(aname, NULL);
73 return ts->s_port; /* returns it in network byte order */
77 MainCommand(struct cmd_syndesc *as, void *arock)
82 struct sockaddr_in taddr;
84 struct in_addr hostAddr;
87 register afs_int32 code;
91 int onlyClient, onlyServer;
105 struct rx_debugStats tstats;
106 char *portName, *hostName;
108 struct rx_debugConn tconn;
114 afs_int32 length = 64;
116 afs_uint32 supportedDebugValues = 0;
117 afs_uint32 supportedStatValues = 0;
118 afs_uint32 supportedConnValues = 0;
119 afs_uint32 supportedPeerValues = 0;
120 afs_int32 nextconn = 0;
121 afs_int32 nextpeer = 0;
123 nodally = (as->parms[2].items ? 1 : 0);
124 allconns = (as->parms[3].items ? 1 : 0);
125 rxstats = (as->parms[4].items ? 1 : 0);
126 onlyServer = (as->parms[5].items ? 1 : 0);
127 onlyClient = (as->parms[6].items ? 1 : 0);
128 version_flag = (as->parms[10].items ? 1 : 0);
129 noConns = (as->parms[11].items ? 1 : 0);
130 showPeers = (as->parms[12].items ? 1 : 0);
131 showLong = (as->parms[13].items ? 1 : 0);
133 if (as->parms[0].items)
134 hostName = as->parms[0].items->data;
138 if (as->parms[1].items)
139 portName = as->parms[1].items->data;
143 if (as->parms[7].items) {
144 char *name = as->parms[7].items->data;
145 if ((onlyPort = PortNumber(name)) == -1)
146 onlyPort = PortName(name);
147 if (onlyPort == -1) {
148 printf("rxdebug: can't resolve port name %s\n", name);
154 if (as->parms[8].items) {
155 char *name = as->parms[8].items->data;
157 th = hostutil_GetHostByName(name);
159 printf("rxdebug: host %s not found in host table\n", name);
162 memcpy(&onlyHost, th->h_addr, sizeof(afs_int32));
166 if (as->parms[9].items) {
167 char *name = as->parms[9].items->data;
168 if (strcmp(name, "clear") == 0)
170 else if (strcmp(name, "auth") == 0)
172 else if (strcmp(name, "crypt") == 0)
174 else if ((strcmp(name, "null") == 0) || (strcmp(name, "none") == 0)
175 || (strncmp(name, "noauth", 6) == 0)
176 || (strncmp(name, "unauth", 6) == 0))
179 fprintf(stderr, "Unknown authentication level: %s\n", name);
187 th = hostutil_GetHostByName(hostName);
189 printf("rxdebug: host %s not found in host table\n", hostName);
192 memcpy(&host, th->h_addr, sizeof(afs_int32));
194 host = htonl(0x7f000001); /* IP localhost */
197 port = htons(7000); /* default is fileserver */
199 if ((port = PortNumber(portName)) == -1)
200 port = PortName(portName);
202 printf("rxdebug: can't resolve port name %s\n", portName);
209 hostAddr.s_addr = host;
210 afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
211 printf("Trying %s (port %d):\n", hoststr, ntohs(port));
212 s = socket(AF_INET, SOCK_DGRAM, 0);
213 taddr.sin_family = AF_INET;
215 taddr.sin_addr.s_addr = 0;
216 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
217 taddr.sin_len = sizeof(struct sockaddr_in);
219 code = bind(s, (struct sockaddr *)&taddr, sizeof(struct sockaddr_in));
227 code = rx_GetServerVersion(s, host, port, length, version);
229 printf("get version call failed with code %d, errno %d\n", code,
233 printf("AFS version: %s\n", version);
241 code = rx_GetServerDebug(s, host, port, &tstats, &supportedDebugValues);
243 printf("getstats call failed with code %d\n", code);
247 withSecStats = (supportedDebugValues & RX_SERVER_DEBUG_SEC_STATS);
248 withAllConn = (supportedDebugValues & RX_SERVER_DEBUG_ALL_CONN);
249 withRxStats = (supportedDebugValues & RX_SERVER_DEBUG_RX_STATS);
250 withWaiters = (supportedDebugValues & RX_SERVER_DEBUG_WAITER_CNT);
251 withIdleThreads = (supportedDebugValues & RX_SERVER_DEBUG_IDLE_THREADS);
252 withWaited = (supportedDebugValues & RX_SERVER_DEBUG_WAITED_CNT);
253 withPeers = (supportedDebugValues & RX_SERVER_DEBUG_ALL_PEER);
254 withPackets = (supportedDebugValues & RX_SERVER_DEBUG_PACKETS_CNT);
257 printf("Free packets: %d/%d, packet reclaims: %d, calls: %d, used FDs: %d\n",
258 tstats.nFreePackets, tstats.nPackets, tstats.packetReclaims,
259 tstats.callsExecuted, tstats.usedFDs);
261 printf("Free packets: %d, packet reclaims: %d, calls: %d, used FDs: %d\n",
262 tstats.nFreePackets, tstats.packetReclaims, tstats.callsExecuted,
264 if (!tstats.waitingForPackets)
266 printf("waiting for packets.\n");
268 printf("%d calls waiting for a thread\n", tstats.nWaiting);
270 printf("%d threads are idle\n", tstats.idleThreads);
272 printf("%d calls have waited for a thread\n", tstats.nWaited);
279 "WARNING: Server doesn't support retrieval of Rx statistics\n");
281 struct rx_statistics rxstats;
283 /* should gracefully handle the case where rx_stats grows */
285 rx_GetServerStats(s, host, port, &rxstats,
286 &supportedStatValues);
288 printf("rxstats call failed with code %d\n", code);
291 if (code != sizeof(rxstats)) {
292 struct rx_debugIn debug;
293 memcpy(&debug, &rxstats, sizeof(debug));
294 if (debug.type == RX_DEBUGI_BADTYPE)
297 ("WARNING: returned Rx statistics of unexpected size (got %d)\n",
299 /* handle other versions?... */
302 rx_PrintTheseStats(stdout, &rxstats, sizeof(rxstats),
303 tstats.nFreePackets, tstats.version);
311 "WARNING: Server doesn't support retrieval of all connections,\n getting only interesting instead.\n");
315 printf("Showing only server connections\n");
317 printf("Showing only client connections\n");
318 if (onlyAuth != 999) {
319 static char *name[] =
320 { "unauthenticated", "rxkad_clear", "rxkad_auth",
323 printf("Showing only %s connections\n", name[onlyAuth + 1]);
325 if (onlyHost != -1) {
326 hostAddr.s_addr = onlyHost;
327 afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
328 printf("Showing only connections from host %s\n",
332 printf("Showing only connections on port %u\n", ntohs(onlyPort));
336 rx_GetServerConnections(s, host, port, &nextconn, allconns,
337 supportedDebugValues, &tconn,
338 &supportedConnValues);
340 printf("getconn call failed with code %d\n", code);
343 if (tconn.cid == (afs_int32) 0xffffffff) {
348 /* see if we're in nodally mode and all calls are dallying */
351 for (j = 0; j < RX_MAXCALLS; j++) {
352 if (tconn.callState[j] != RX_STATE_NOTINIT
353 && tconn.callState[j] != RX_STATE_DALLY) {
359 /* this call looks too ordinary, bump skipped count and go
365 if ((onlyHost != -1) && (onlyHost != tconn.host))
367 if ((onlyPort != -1) && (onlyPort != tconn.port))
369 if (onlyServer && (tconn.type != RX_SERVER_CONNECTION))
371 if (onlyClient && (tconn.type != RX_CLIENT_CONNECTION))
373 if (onlyAuth != 999) {
374 if (onlyAuth == -1) {
375 if (tconn.securityIndex != 0)
378 if (tconn.securityIndex != 2)
380 if (withSecStats && (tconn.secStats.type == 3)
381 && (tconn.secStats.level != onlyAuth))
386 /* now display the connection */
387 hostAddr.s_addr = tconn.host;
388 afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
389 printf("Connection from host %s, port %hu, ", hoststr,
392 printf("Cuid %x/%x", tconn.epoch, tconn.cid);
394 printf("cid %x", tconn.cid);
396 printf(", error %d", tconn.error);
397 printf("\n serial %d, ", tconn.serial);
398 printf(" natMTU %d, ", tconn.natMTU);
402 if (tconn.flags & RX_CONN_MAKECALL_WAITING)
403 printf(" MAKECALL_WAITING");
404 if (tconn.flags & RX_CONN_DESTROY_ME)
405 printf(" DESTROYED");
406 if (tconn.flags & RX_CONN_USING_PACKET_CKSUM)
408 if (tconn.flags & RX_CONN_KNOW_WINDOW)
409 printf(" knowWindow");
410 if (tconn.flags & RX_CONN_RESET)
412 if (tconn.flags & RX_CONN_BUSY)
414 if (tconn.flags & RX_CONN_ATTACHWAIT)
415 printf(" attachWait");
418 printf("security index %d, ", tconn.securityIndex);
419 if (tconn.type == RX_CLIENT_CONNECTION)
420 printf("client conn\n");
422 printf("server conn\n");
425 switch ((int)tconn.secStats.type) {
427 if (tconn.securityIndex == 2)
429 (" no GetStats procedure for security object\n");
432 printf(" rxnull level=%d, flags=%d\n",
433 tconn.secStats.level, tconn.secStats.flags);
436 printf(" rxvab level=%d, flags=%d\n",
437 tconn.secStats.level, tconn.secStats.flags);
441 char flags = tconn.secStats.flags;
442 if (tconn.secStats.level == 0)
444 else if (tconn.secStats.level == 1)
446 else if (tconn.secStats.level == 2)
450 printf(" rxkad: level %s", level);
456 printf(" authenticated");
461 if (tconn.secStats.expires)
462 /* Apparently due to a bug in the RT compiler that
463 * prevents (afs_uint32)0xffffffff => (double) from working,
464 * this code produces negative lifetimes when run on the
466 printf(", expires in %.1f hours",
467 ((afs_uint32) tconn.secStats.expires -
470 printf("\n Received %u bytes in %u packets\n",
471 tconn.secStats.bytesReceived,
472 tconn.secStats.packetsReceived);
473 printf(" Sent %u bytes in %u packets\n",
474 tconn.secStats.bytesSent,
475 tconn.secStats.packetsSent);
482 printf(" unknown\n");
486 for (j = 0; j < RX_MAXCALLS; j++) {
487 printf(" call %d: # %d, state ", j, tconn.callNumber[j]);
488 if (tconn.callState[j] == RX_STATE_NOTINIT) {
489 printf("not initialized\n");
491 } else if (tconn.callState[j] == RX_STATE_PRECALL)
493 else if (tconn.callState[j] == RX_STATE_ACTIVE)
495 else if (tconn.callState[j] == RX_STATE_DALLY)
497 else if (tconn.callState[j] == RX_STATE_HOLD)
499 else if (tconn.callState[j] == RX_STATE_RESET)
502 if (tconn.callMode[j] == RX_MODE_SENDING)
504 else if (tconn.callMode[j] == RX_MODE_RECEIVING)
506 else if (tconn.callMode[j] == RX_MODE_ERROR)
508 else if (tconn.callMode[j] == RX_MODE_EOF)
512 if (tconn.callFlags[j]) {
514 if (tconn.callFlags[j] & RX_CALL_READER_WAIT)
515 printf(" reader_wait");
516 if (tconn.callFlags[j] & RX_CALL_WAIT_WINDOW_ALLOC)
517 printf(" window_alloc");
518 if (tconn.callFlags[j] & RX_CALL_WAIT_WINDOW_SEND)
519 printf(" window_send");
520 if (tconn.callFlags[j] & RX_CALL_WAIT_PACKETS)
521 printf(" wait_packets");
522 if (tconn.callFlags[j] & RX_CALL_WAIT_PROC)
523 printf(" waiting_for_process");
524 if (tconn.callFlags[j] & RX_CALL_RECEIVE_DONE)
525 printf(" receive_done");
526 if (tconn.callFlags[j] & RX_CALL_CLEARED)
527 printf(" call_cleared");
529 if (tconn.callOther[j] & RX_OTHER_IN)
530 printf(", has_input_packets");
531 if (tconn.callOther[j] & RX_OTHER_OUT)
532 printf(", has_output_packets");
537 printf("Skipped %d dallying connections.\n", dallyCounter);
539 if (showPeers && withPeers) {
541 struct rx_debugPeer tpeer;
543 rx_GetServerPeers(s, host, port, &nextpeer, allconns, &tpeer,
544 &supportedPeerValues);
546 printf("getpeer call failed with code %d\n", code);
549 if (tpeer.host == 0xffffffff) {
554 if ((onlyHost != -1) && (onlyHost != tpeer.host))
556 if ((onlyPort != -1) && (onlyPort != tpeer.port))
559 /* now display the peer */
560 hostAddr.s_addr = tpeer.host;
561 afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
562 printf("Peer at host %s, port %hu\n", hoststr,
564 printf("\tifMTU %hu\tnatMTU %hu\tmaxMTU %hu\n", tpeer.ifMTU,
565 tpeer.natMTU, tpeer.maxMTU);
566 printf("\tpackets sent %u\tpacket resends %u\n", tpeer.nSent,
568 printf("\tbytes sent high %u low %u\n", tpeer.bytesSent.high,
569 tpeer.bytesSent.low);
570 printf("\tbytes received high %u low %u\n",
571 tpeer.bytesReceived.high, tpeer.bytesReceived.low);
572 printf("\trtt %u msec, rtt_dev %u msec\n", tpeer.rtt >> 3,
574 printf("\ttimeout %u.%03u sec\n", tpeer.timeout.sec,
575 tpeer.timeout.usec / 1000);
579 printf("\tin/out packet skew: %d/%d\n", tpeer.inPacketSkew,
580 tpeer.outPacketSkew);
581 printf("\tcongestion window %d, MTU %d\n", tpeer.cwind,
583 printf("\tcurrent/if/max jumbogram size: %d/%d/%d\n",
584 tpeer.nDgramPackets, tpeer.ifDgramPackets,
585 tpeer.maxDgramPackets);
591 /* simple main program */
593 #include "AFS_component_version_number.c"
596 main(int argc, char **argv)
598 struct cmd_syndesc *ts;
604 if (afs_winsockInit() < 0) {
605 printf("%s: Couldn't initialize winsock. Exiting...\n", argv[0]);
610 ts = cmd_CreateSyntax(NULL, MainCommand, NULL, "probe RX server");
611 cmd_AddParm(ts, "-servers", CMD_SINGLE, CMD_REQUIRED, "server machine");
612 cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port");
613 cmd_AddParm(ts, "-nodally", CMD_FLAG, CMD_OPTIONAL,
614 "don't show dallying conns");
615 cmd_AddParm(ts, "-allconnections", CMD_FLAG, CMD_OPTIONAL,
616 "don't filter out uninteresting connections on server");
617 cmd_AddParm(ts, "-rxstats", CMD_FLAG, CMD_OPTIONAL, "show Rx statistics");
618 cmd_AddParm(ts, "-onlyserver", CMD_FLAG, CMD_OPTIONAL,
619 "only show server conns");
620 cmd_AddParm(ts, "-onlyclient", CMD_FLAG, CMD_OPTIONAL,
621 "only show client conns");
622 cmd_AddParm(ts, "-onlyport", CMD_SINGLE, CMD_OPTIONAL,
624 cmd_AddParm(ts, "-onlyhost", CMD_SINGLE, CMD_OPTIONAL,
626 cmd_AddParm(ts, "-onlyauth", CMD_SINGLE, CMD_OPTIONAL,
627 "show only <auth level>");
629 cmd_AddParm(ts, "-version", CMD_FLAG, CMD_OPTIONAL,
630 "show AFS version id");
631 cmd_AddParm(ts, "-noconns", CMD_FLAG, CMD_OPTIONAL,
632 "show no connections");
633 cmd_AddParm(ts, "-peers", CMD_FLAG, CMD_OPTIONAL, "show peers");
634 cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "detailed output");
636 cmd_Dispatch(argc, argv);