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>
16 #include <afs/afsutil.h>
19 #include <rx/rx_user.h>
20 #include <rx/rx_clock.h>
21 #include <rx/rx_queue.h>
23 #include <rx/rx_globals.h>
33 PortNumber(char *aport)
39 while ((tc = *aport++)) {
40 if (tc < '0' || tc > '9')
41 return -1; /* bad port number */
43 total += tc - (int)'0';
52 ts = getservbyname(aname, NULL);
55 return ts->s_port; /* returns it in network byte order */
59 MainCommand(struct cmd_syndesc *as, void *arock)
63 struct sockaddr_in taddr;
65 struct in_addr hostAddr;
72 int onlyClient, onlyServer;
86 struct rx_debugStats tstats;
87 char *portName, *hostName;
89 struct rx_debugConn tconn;
95 afs_int32 length = 64;
97 afs_uint32 supportedDebugValues = 0;
98 afs_uint32 supportedStatValues = 0;
99 afs_uint32 supportedConnValues = 0;
100 afs_uint32 supportedPeerValues = 0;
101 afs_int32 nextconn = 0;
102 afs_int32 nextpeer = 0;
104 nodally = (as->parms[2].items ? 1 : 0);
105 allconns = (as->parms[3].items ? 1 : 0);
106 rxstats = (as->parms[4].items ? 1 : 0);
107 onlyServer = (as->parms[5].items ? 1 : 0);
108 onlyClient = (as->parms[6].items ? 1 : 0);
109 version_flag = (as->parms[10].items ? 1 : 0);
110 noConns = (as->parms[11].items ? 1 : 0);
111 showPeers = (as->parms[12].items ? 1 : 0);
112 showLong = (as->parms[13].items ? 1 : 0);
114 if (as->parms[0].items)
115 hostName = as->parms[0].items->data;
119 if (as->parms[1].items)
120 portName = as->parms[1].items->data;
124 if (as->parms[7].items) {
125 char *name = as->parms[7].items->data;
126 if ((onlyPort = PortNumber(name)) == -1)
127 onlyPort = PortName(name);
128 if (onlyPort == -1) {
129 printf("rxdebug: can't resolve port name %s\n", name);
135 if (as->parms[8].items) {
136 char *name = as->parms[8].items->data;
138 th = hostutil_GetHostByName(name);
140 printf("rxdebug: host %s not found in host table\n", name);
143 memcpy(&onlyHost, th->h_addr, sizeof(afs_int32));
147 if (as->parms[9].items) {
148 char *name = as->parms[9].items->data;
149 /* Note that this assumes that the security levels for rxkad and rxgk
150 * use the same constants (0, 1, and 2). Perhaps a little ugly, but the
151 * constants being identical makes it really convenient to do it this
153 if (strcmp(name, "clear") == 0)
155 else if (strcmp(name, "auth") == 0)
157 else if (strcmp(name, "crypt") == 0)
159 else if ((strcmp(name, "null") == 0) || (strcmp(name, "none") == 0)
160 || (strncmp(name, "noauth", 6) == 0)
161 || (strncmp(name, "unauth", 6) == 0))
164 fprintf(stderr, "Unknown authentication level: %s\n", name);
172 th = hostutil_GetHostByName(hostName);
174 printf("rxdebug: host %s not found in host table\n", hostName);
177 memcpy(&host, th->h_addr, sizeof(afs_int32));
179 host = htonl(0x7f000001); /* IP localhost */
182 port = htons(7000); /* default is fileserver */
184 if ((port = PortNumber(portName)) == -1)
185 port = PortName(portName);
187 printf("rxdebug: can't resolve port name %s\n", portName);
194 hostAddr.s_addr = host;
195 afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
196 printf("Trying %s (port %d):\n", hoststr, ntohs(port));
197 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
198 if (s == OSI_NULLSOCKET) {
200 fprintf(stderr, "socket() failed with error %u\n", WSAGetLastError());
206 taddr.sin_family = AF_INET;
208 taddr.sin_addr.s_addr = 0;
209 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
210 taddr.sin_len = sizeof(struct sockaddr_in);
212 code = bind(s, (struct sockaddr *)&taddr, sizeof(struct sockaddr_in));
215 fprintf(stderr, "bind() failed with error %u\n", WSAGetLastError());
223 memset(version, 0, sizeof(version));
225 code = rx_GetServerVersion(s, host, port, length, version);
227 printf("get version call failed with code %d, errno %d\n", code,
231 version[sizeof(version) - 1] = '\0';
232 printf("AFS version: %s\n", version);
240 code = rx_GetServerDebug(s, host, port, &tstats, &supportedDebugValues);
242 printf("getstats call failed with code %d\n", code);
246 withSecStats = (supportedDebugValues & RX_SERVER_DEBUG_SEC_STATS);
247 withAllConn = (supportedDebugValues & RX_SERVER_DEBUG_ALL_CONN);
248 withRxStats = (supportedDebugValues & RX_SERVER_DEBUG_RX_STATS);
249 withWaiters = (supportedDebugValues & RX_SERVER_DEBUG_WAITER_CNT);
250 withIdleThreads = (supportedDebugValues & RX_SERVER_DEBUG_IDLE_THREADS);
251 withWaited = (supportedDebugValues & RX_SERVER_DEBUG_WAITED_CNT);
252 withPeers = (supportedDebugValues & RX_SERVER_DEBUG_ALL_PEER);
253 withPackets = (supportedDebugValues & RX_SERVER_DEBUG_PACKETS_CNT);
256 printf("Free packets: %d/%d, packet reclaims: %d, calls: %d, used FDs: %d\n",
257 tstats.nFreePackets, tstats.nPackets, tstats.packetReclaims,
258 tstats.callsExecuted, tstats.usedFDs);
260 printf("Free packets: %d, packet reclaims: %d, calls: %d, used FDs: %d\n",
261 tstats.nFreePackets, tstats.packetReclaims, tstats.callsExecuted,
263 if (!tstats.waitingForPackets)
265 printf("waiting for packets.\n");
267 printf("%d calls waiting for a thread\n", tstats.nWaiting);
269 printf("%d threads are idle\n", tstats.idleThreads);
271 printf("%d calls have waited for a thread\n", tstats.nWaited);
278 "WARNING: Server doesn't support retrieval of Rx statistics\n");
280 struct rx_statistics rxstats;
282 /* should gracefully handle the case where rx_stats grows */
284 rx_GetServerStats(s, host, port, &rxstats,
285 &supportedStatValues);
287 printf("rxstats call failed with code %d\n", code);
290 if (code != sizeof(rxstats)) {
291 struct rx_debugIn debug;
292 memcpy(&debug, &rxstats, sizeof(debug));
293 if (debug.type == RX_DEBUGI_BADTYPE)
296 ("WARNING: returned Rx statistics of unexpected size (got %d)\n",
298 /* handle other versions?... */
301 rx_PrintTheseStats(stdout, &rxstats, sizeof(rxstats),
302 tstats.nFreePackets, tstats.version);
310 "WARNING: Server doesn't support retrieval of all connections,\n getting only interesting instead.\n");
314 printf("Showing only server connections\n");
316 printf("Showing only client connections\n");
317 if (onlyAuth != 999) {
318 static char *name[] =
319 { "unauthenticated", "clear", "auth",
322 printf("Showing only %s connections\n", name[onlyAuth + 1]);
324 if (onlyHost != -1) {
325 hostAddr.s_addr = onlyHost;
326 afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
327 printf("Showing only connections from host %s\n",
331 printf("Showing only connections on port %u\n", ntohs(onlyPort));
335 rx_GetServerConnections(s, host, port, &nextconn, allconns,
336 supportedDebugValues, &tconn,
337 &supportedConnValues);
339 printf("getconn call failed with code %d\n", code);
342 if (tconn.cid == (afs_int32) 0xffffffff) {
347 /* see if we're in nodally mode and all calls are dallying */
350 for (j = 0; j < RX_MAXCALLS; j++) {
351 if (tconn.callState[j] != RX_STATE_NOTINIT
352 && tconn.callState[j] != RX_STATE_DALLY) {
358 /* this call looks too ordinary, bump skipped count and go
364 if ((onlyHost != -1) && (onlyHost != tconn.host))
366 if ((onlyPort != -1) && (onlyPort != tconn.port))
368 if (onlyServer && (tconn.type != RX_SERVER_CONNECTION))
370 if (onlyClient && (tconn.type != RX_CLIENT_CONNECTION))
372 if (onlyAuth != 999) {
373 if (onlyAuth == -1) {
374 if (tconn.securityIndex != RX_SECIDX_NULL)
377 if (tconn.securityIndex != RX_SECIDX_KAD) {
379 if (tconn.securityIndex != RX_SECIDX_GK)
383 if (withSecStats && (tconn.secStats.type == RX_SECTYPE_KAD)
384 && (tconn.secStats.level != onlyAuth))
387 if (withSecStats && (tconn.secStats.type == RX_SECTYPE_GK)
388 && (tconn.secStats.level != onlyAuth))
394 /* now display the connection */
395 hostAddr.s_addr = tconn.host;
396 afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
397 printf("Connection from host %s, port %hu, ", hoststr,
400 printf("Cuid %x/%x", tconn.epoch, tconn.cid);
402 printf("cid %x", tconn.cid);
404 printf(", error %d", tconn.error);
405 printf("\n serial %d, ", tconn.serial);
406 printf(" natMTU %d, ", tconn.natMTU);
410 if (tconn.flags & RX_CONN_MAKECALL_WAITING)
411 printf(" MAKECALL_WAITING");
412 if (tconn.flags & RX_CONN_DESTROY_ME)
413 printf(" DESTROYED");
414 if (tconn.flags & RX_CONN_USING_PACKET_CKSUM)
416 if (tconn.flags & RX_CONN_KNOW_WINDOW)
417 printf(" knowWindow");
418 if (tconn.flags & RX_CONN_RESET)
420 if (tconn.flags & RX_CONN_BUSY)
422 if (tconn.flags & RX_CONN_ATTACHWAIT)
423 printf(" attachWait");
426 printf("security index %d, ", tconn.securityIndex);
427 if (tconn.type == RX_CLIENT_CONNECTION)
428 printf("client conn\n");
430 printf("server conn\n");
433 switch ((int)tconn.secStats.type) {
435 if (tconn.securityIndex == RX_SECIDX_KAD)
437 (" no GetStats procedure for security object\n");
439 case RX_SECTYPE_NULL:
440 printf(" rxnull level=%d, flags=%d\n",
441 tconn.secStats.level, tconn.secStats.flags);
444 printf(" rxvab level=%d, flags=%d\n",
445 tconn.secStats.level, tconn.secStats.flags);
447 case RX_SECTYPE_KAD:{
449 char flags = tconn.secStats.flags;
450 if (tconn.secStats.level == 0)
452 else if (tconn.secStats.level == 1)
454 else if (tconn.secStats.level == 2)
458 printf(" rxkad: level %s", level);
464 printf(" authenticated");
469 if (tconn.secStats.expires)
470 /* Apparently due to a bug in the RT compiler that
471 * prevents (afs_uint32)0xffffffff => (double) from working,
472 * this code produces negative lifetimes when run on the
474 printf(", expires in %.1f hours",
475 ((afs_uint32) tconn.secStats.expires -
478 printf("\n Received %u bytes in %u packets\n",
479 tconn.secStats.bytesReceived,
480 tconn.secStats.packetsReceived);
481 printf(" Sent %u bytes in %u packets\n",
482 tconn.secStats.bytesSent,
483 tconn.secStats.packetsSent);
489 case RX_SECTYPE_GK: {
491 char flags = tconn.secStats.flags;
492 if (tconn.secStats.level == RXGK_LEVEL_CLEAR)
494 else if (tconn.secStats.level == RXGK_LEVEL_AUTH)
496 else if (tconn.secStats.level == RXGK_LEVEL_CRYPT)
500 printf(" rxgk: level %s", level);
503 if ((flags & RXGK_STATS_UNALLOC))
505 if ((flags & RXGK_STATS_AUTH))
506 printf(" authenticated");
507 if (tconn.secStats.expires)
508 printf(", expires in %.1f hours",
509 ((afs_uint32) tconn.secStats.expires -
511 if (!(flags & RXGK_STATS_UNALLOC)) {
512 printf("\n Received %u bytes in %u packets\n",
513 tconn.secStats.bytesReceived,
514 tconn.secStats.packetsReceived);
515 printf(" Sent %u bytes in %u packets\n",
516 tconn.secStats.bytesSent,
517 tconn.secStats.packetsSent);
522 #endif /* ENABLE_RXGK */
525 printf(" unknown\n");
529 for (j = 0; j < RX_MAXCALLS; j++) {
530 printf(" call %d: # %d, state ", j, tconn.callNumber[j]);
531 if (tconn.callState[j] == RX_STATE_NOTINIT) {
532 printf("not initialized\n");
534 } else if (tconn.callState[j] == RX_STATE_PRECALL)
536 else if (tconn.callState[j] == RX_STATE_ACTIVE)
538 else if (tconn.callState[j] == RX_STATE_DALLY)
540 else if (tconn.callState[j] == RX_STATE_HOLD)
542 else if (tconn.callState[j] == RX_STATE_RESET)
545 if (tconn.callMode[j] == RX_MODE_SENDING)
547 else if (tconn.callMode[j] == RX_MODE_RECEIVING)
549 else if (tconn.callMode[j] == RX_MODE_ERROR)
551 else if (tconn.callMode[j] == RX_MODE_EOF)
555 if (tconn.callFlags[j]) {
557 if (tconn.callFlags[j] & RX_CALL_READER_WAIT)
558 printf(" reader_wait");
559 if (tconn.callFlags[j] & RX_CALL_WAIT_WINDOW_ALLOC)
560 printf(" window_alloc");
561 if (tconn.callFlags[j] & RX_CALL_WAIT_WINDOW_SEND)
562 printf(" window_send");
563 if (tconn.callFlags[j] & RX_CALL_WAIT_PACKETS)
564 printf(" wait_packets");
565 if (tconn.callFlags[j] & RX_CALL_WAIT_PROC)
566 printf(" waiting_for_process");
567 if (tconn.callFlags[j] & RX_CALL_RECEIVE_DONE)
568 printf(" receive_done");
569 if (tconn.callFlags[j] & RX_CALL_CLEARED)
570 printf(" call_cleared");
572 if (tconn.callOther[j] & RX_OTHER_IN)
573 printf(", has_input_packets");
574 if (tconn.callOther[j] & RX_OTHER_OUT)
575 printf(", has_output_packets");
580 printf("Skipped %d dallying connections.\n", dallyCounter);
582 if (showPeers && withPeers) {
584 struct rx_debugPeer tpeer;
586 rx_GetServerPeers(s, host, port, &nextpeer, allconns, &tpeer,
587 &supportedPeerValues);
589 printf("getpeer call failed with code %d\n", code);
592 if (tpeer.host == 0xffffffff) {
597 if ((onlyHost != -1) && (onlyHost != tpeer.host))
599 if ((onlyPort != -1) && (onlyPort != tpeer.port))
602 /* now display the peer */
603 hostAddr.s_addr = tpeer.host;
604 afs_inet_ntoa_r(hostAddr.s_addr, hoststr);
605 printf("Peer at host %s, port %hu\n", hoststr,
607 printf("\tifMTU %hu\tnatMTU %hu\tmaxMTU %hu\n", tpeer.ifMTU,
608 tpeer.natMTU, tpeer.maxMTU);
609 printf("\tpackets sent %u\tpacket resends %u\n", tpeer.nSent,
611 printf("\tbytes sent high %u low %u\n", tpeer.bytesSent.high,
612 tpeer.bytesSent.low);
613 printf("\tbytes received high %u low %u\n",
614 tpeer.bytesReceived.high, tpeer.bytesReceived.low);
615 printf("\trtt %u msec, rtt_dev %u msec\n", tpeer.rtt >> 3,
617 printf("\ttimeout %u.%03u sec\n", tpeer.timeout.sec,
618 tpeer.timeout.usec / 1000);
622 printf("\tin/out packet skew: %d/%d\n", tpeer.inPacketSkew,
623 tpeer.outPacketSkew);
624 printf("\tcongestion window %d, MTU %d\n", tpeer.cwind,
626 printf("\tcurrent/if/max jumbogram size: %d/%d/%d\n",
627 tpeer.nDgramPackets, tpeer.ifDgramPackets,
628 tpeer.maxDgramPackets);
634 /* simple main program */
636 #include "AFS_component_version_number.c"
639 main(int argc, char **argv)
641 struct cmd_syndesc *ts;
647 if (afs_winsockInit() < 0) {
648 printf("%s: Couldn't initialize winsock. Exiting...\n", argv[0]);
653 ts = cmd_CreateSyntax(NULL, MainCommand, NULL, 0, "probe RX server");
654 cmd_AddParm(ts, "-servers", CMD_SINGLE, CMD_REQUIRED, "server machine");
655 cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port");
656 cmd_AddParm(ts, "-nodally", CMD_FLAG, CMD_OPTIONAL,
657 "don't show dallying conns");
658 cmd_AddParm(ts, "-allconnections", CMD_FLAG, CMD_OPTIONAL,
659 "don't filter out uninteresting connections on server");
660 cmd_AddParm(ts, "-rxstats", CMD_FLAG, CMD_OPTIONAL, "show Rx statistics");
661 cmd_AddParm(ts, "-onlyserver", CMD_FLAG, CMD_OPTIONAL,
662 "only show server conns");
663 cmd_AddParm(ts, "-onlyclient", CMD_FLAG, CMD_OPTIONAL,
664 "only show client conns");
665 cmd_AddParm(ts, "-onlyport", CMD_SINGLE, CMD_OPTIONAL,
667 cmd_AddParm(ts, "-onlyhost", CMD_SINGLE, CMD_OPTIONAL,
669 cmd_AddParm(ts, "-onlyauth", CMD_SINGLE, CMD_OPTIONAL,
670 "show only <auth level>");
672 cmd_AddParm(ts, "-version", CMD_FLAG, CMD_OPTIONAL,
673 "show AFS version id");
674 cmd_AddParm(ts, "-noconns", CMD_FLAG, CMD_OPTIONAL,
675 "show no connections");
676 cmd_AddParm(ts, "-peers", CMD_FLAG, CMD_OPTIONAL, "show peers");
677 cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "detailed output");
679 cmd_Dispatch(argc, argv);