#ifndef lint static char *RCSid = "$Header: /proj/freeware1.0/nfswatch/nfswatch4.1/RCS/nfslogsum.c,v 1.1 1995/08/08 04:40:33 rck Exp $"; #endif #include "os.h" /* * nfslogsum - summarize nfswatch log file * * David A. Curry Jeffrey C. Mogul * Purdue University Digital Equipment Corporation * Engineering Computer Network Western Research Laboratory * 1285 Electrical Engineering Building 250 University Avenue * West Lafayette, IN 47907-1285 Palo Alto, CA 94301 * davy@ecn.purdue.edu mogul@decwrl.dec.com * * $Log: nfslogsum.c,v $ * Revision 1.1 1995/08/08 04:40:33 rck * initial checkin * * Revision 4.0 1993/03/01 19:59:00 davy * NFSWATCH Version 4.0. * * Revision 3.4 1993/01/16 19:08:59 davy * Corrected Jeff's address. * * Revision 3.3 1993/01/15 19:33:39 davy * Miscellaneous cleanups. * * Revision 3.2 1993/01/14 03:41:21 davy * Changed "Yellow Pages/NIS" to "YP/NIS/NIS+". * * Revision 3.1 1993/01/13 20:18:17 davy * Put in OS-specific define scheme, and merged in Tim Hudson's code for * SGI systems (as yet untested). * * Revision 3.0 1991/01/23 08:23:08 davy * NFSWATCH Version 3.0. * * Revision 1.2 90/08/17 15:47:27 davy * NFSWATCH Version 2.0. * * Revision 1.1 88/11/29 11:20:38 davy * NFSWATCH Release 1.0 * */ #include #include #include "nfswatch.h" char *pname; /* program name */ char *logfile = LOGFILE; /* log file name */ int logentries; /* # of entries */ int verbose = 0; /* print more info */ int maxlogentries = -1; /* stop at this many */ Counter total_pkts; /* total pkts this time */ Counter tohost_pkts; /* total pkts to host */ Counter dropped_pkts; /* total dropped pkts */ char *startdate; /* time started */ char *enddate; /* time finished */ char srchost[MAXHOSTNAMELEN]; /* source host name */ char dsthost[MAXHOSTNAMELEN]; /* destination host name*/ NFSCounter nfs_counters[MAXEXPORT]; /* NFS pkt counters */ FileCounter fil_counters[MAXEXPORT]; /* file pkt counters */ PacketCounter pkt_counters[PKT_NCOUNTERS]; /* type pkt counters */ char *nfs_procs[] = { "NULLPROC", " GETATTR", " SETATTR", " GETROOT", " LOOKUP", "READLINK", " READ", " WCACHE", " WRITE", " CREATE", " REMOVE", " RENAME", " LINK", " SYMLINK", " MKDIR", " RMDIR", " READDIR", " STATFS", 0 }; char *index(); char *savestr(); void dumpit(); void dumpit2(); void parsenfs(); void parsetop(); void parsefile(); void parsepkts(); void parseproc(); void clearvars(); void parsetotals(); main(argc, argv) int argc; char **argv; { FILE *logfp; int printed = 0; char line[BUFSIZ]; pname = *argv; /* * Process arguments. */ while (--argc) { if (**++argv != '-') { logfile = *argv; continue; } switch (*++*argv) { case 'v': verbose++; break; default: maxlogentries = atoi(*argv); break; } } /* * Open the log file. */ if ((logfp = fopen(logfile, "r")) == NULL) { (void) fprintf(stderr, "%s: cannot open \"%s\"\n", pname, logfile); (void) exit(1); } /* * Read lines... */ while (fgets(line, sizeof(line), logfp) != NULL) { /* * Skip blank comments. */ if (!strcmp(line, "#\n")) continue; /* * Start of a new log session. */ if (!strcmp(line, "# startlog\n")) { clearvars(); printed = 0; continue; } /* * Start of a new log entry. */ if (!strcmp(line, "# begin\n")) { parsetop(logfp); continue; } /* * End of a log entry. */ if (!strcmp(line, "# end\n")) { logentries++; /* * If we've read the max, we're done. */ if ((maxlogentries > 0) && (logentries >= maxlogentries)) { dumpit(); exit(0); } continue; } /* * End of log session. */ if (!strcmp(line, "# endlog\n")) { printed++; dumpit(); continue; } /* * Start of NFS counter section. */ if (!strncmp(line, "# nfs counters ", 15)) { parsenfs(logfp); continue; } /* * Start of file counter section. */ if (!strncmp(line, "# file counters ", 16)) { parsefile(logfp); continue; } /* * Start of total packet section. */ if (!strncmp(line, "# total packets ", 16)) { parsetotals(logfp); continue; } /* * Start of packet counter section. */ if (!strncmp(line, "# packet counters ", 18)) { parsepkts(logfp); continue; } /* * Source host. */ if (!strncmp(line, "# Packets from: ", 19)) { (void) strcpy(srchost, line + 19); continue; } /* * Destination host. */ if (!strncmp(line, "# Packets to: ", 19)) { (void) strcpy(dsthost, line + 19); continue; } } /* * In case there's no endlog (logfile in progress). */ if (!printed) dumpit(); (void) fclose(logfp); (void) exit(0); } /* * clearvars - clear variables between log sessions. */ void clearvars() { register int i; logentries = 0; total_pkts = 0; tohost_pkts = 0; dropped_pkts = 0; if (startdate != NULL) { (void) free(startdate); startdate = NULL; } if (enddate != NULL) { (void) free(enddate); enddate = NULL; } (void) bzero((char *) pkt_counters, PKT_NCOUNTERS * sizeof(PacketCounter)); /* * Set up the strings. */ pkt_counters[PKT_NDREAD].pc_name = "ND Read"; pkt_counters[PKT_NDWRITE].pc_name = "ND Write"; pkt_counters[PKT_NFSREAD].pc_name = "NFS Read"; pkt_counters[PKT_NFSWRITE].pc_name = "NFS Write"; pkt_counters[PKT_NFSMOUNT].pc_name = "NFS Mount"; pkt_counters[PKT_YELLOWPAGES].pc_name = "YP/NIS/NIS+"; pkt_counters[PKT_RPCAUTH].pc_name = "RPC Authorization"; pkt_counters[PKT_OTHERRPC].pc_name = "Other RPC Packets"; pkt_counters[PKT_TCP].pc_name = "TCP Packets"; pkt_counters[PKT_UDP].pc_name = "UDP Packets"; pkt_counters[PKT_ICMP].pc_name = "ICMP Packets"; pkt_counters[PKT_ROUTING].pc_name = "Routing Control"; pkt_counters[PKT_ARP].pc_name = "Address Resolution"; pkt_counters[PKT_RARP].pc_name = "Reverse Addr Resol"; pkt_counters[PKT_BROADCAST].pc_name = "Ethernet Broadcast"; pkt_counters[PKT_OTHER].pc_name = "Other Packets"; for (i = 0; i < MAXEXPORT; i++) { if (nfs_counters[i].nc_name != NULL) { (void) free(nfs_counters[i].nc_name); nfs_counters[i].nc_name = NULL; } } (void) bzero((char *) nfs_counters, MAXEXPORT * sizeof(NFSCounter)); (void) bzero((char *) fil_counters, MAXEXPORT * sizeof(FileCounter)); } /* * parsetop - parse the top of the log session. */ void parsetop(fp) FILE *fp; { int nskip = 0; char line[BUFSIZ]; /* * Get lines... */ while (fgets(line, sizeof(line), fp) != NULL) { /* * Second blank comment terminates this section. */ if (!strcmp(line, "#\n")) { if (++nskip == 2) return; continue; } /* * Grab the date - first one is start, * otherwise end. */ if (!strncmp(line, "Date: ", 6)) { if (startdate == NULL) { startdate = savestr(line + 6); enddate = savestr(line + 6); } else { (void) strcpy(enddate, line + 6); } continue; } } } /* * parsetotals - parse the totals section. */ void parsetotals(fp) FILE *fp; { int x, y, z; int nskip = 0; register char *s; char line[BUFSIZ]; /* * Get lines... */ while (fgets(line, sizeof(line), fp) != NULL) { /* * Seond blank comment terminates this section. */ if (!strcmp(line, "#\n")) { if (++nskip == 2) return; continue; } /* * Grab the interval packets and add them. */ if (!strncmp(line, "Interval Packets:", 17)) { (void) sscanf(line + 17, "%d %d %d", &x, &y, &z); total_pkts += x; tohost_pkts += y; dropped_pkts += z; continue; } } } /* * parsepkts - parse packet counter section. */ void parsepkts(fp) FILE *fp; { int x, y, z; int nskip = 0; register int i; register char *s; char line[BUFSIZ]; /* * Get lines... */ while (fgets(line, sizeof(line), fp) != NULL) { /* * Second blank comment terminates this section. */ if (!strcmp(line, "#\n")) { if (++nskip == 2) return; continue; } /* * Find the numbers. */ if ((s = index(line, ':')) == NULL) continue; *s++ = NULL; /* * Find the type we need. */ for (i = 0; i < PKT_NCOUNTERS; i++) { if (!strcmp(line, pkt_counters[i].pc_name)) { (void) sscanf(s, "%d %d%% %d", &x, &y, &z); pkt_counters[i].pc_total += x; break; } } } } /* * parsenfs - parse the NFS counter section. */ void parsenfs(fp) FILE *fp; { int x, y, z; int nskip = 0; register int i; register char *s; char line[BUFSIZ]; /* * Get lines... */ while (fgets(line, sizeof(line), fp) != NULL) { /* * Second blank comment terminates this section. */ if (!strcmp(line, "#\n")) { if (++nskip == 2) return; continue; } /* * Find the numbers. */ if ((s = index(line, ':')) == NULL) continue; *s++ = NULL; /* * Find the NFS counter we want. */ if ((i = findnfs(line)) < 0) continue; (void) sscanf(s, "%d %d%% %d", &x, &y, &z); nfs_counters[i].nc_total += x; if ((s = index(s, '(')) != NULL) parseproc(s, nfs_counters[i].nc_proc); } } /* * parsefile - parse the file counter section. */ void parsefile(fp) FILE *fp; { int x, y, z; int nskip = 0; register int i; register char *s; char line[BUFSIZ]; /* * Get lines... */ while (fgets(line, sizeof(line), fp) != NULL) { /* * Second blank comment terminates this section. */ if (!strcmp(line, "#\n")) { if (++nskip == 2) return; continue; } /* * Find the numbers. */ if ((s = index(line, ':')) == NULL) continue; *s++ = NULL; /* * Find the file counter we want. */ if ((i = findfile(line)) < 0) continue; (void) sscanf(s, "%d %d%% %d", &x, &y, &z); fil_counters[i].fc_total += x; if ((s = index(s, '(')) != NULL) parseproc(s, fil_counters[i].fc_proc); } } /* * parseproc - parse the NFS procedure counters. */ void parseproc(line, ctrs) Counter *ctrs; char *line; { register int i; register char *s; s = line + 1; for (i = 0; i < MAXNFSPROC; i++) { ctrs[i] += atoi(s); if ((s = index(s, '/')) == NULL) return; s++; } } /* * dumpit - print out the information. */ void dumpit() { float percent; char buf[BUFSIZ]; register int i, nfstotal; (void) printf("NFSwatch logfile summary:\n"); (void) printf(" Log time: %.24s to %.24s\n", startdate, enddate); (void) printf(" Log entries: %d\n", logentries); (void) printf(" Packets from: %s", srchost); (void) printf(" Packets to: %s\n", dsthost); (void) printf("Total packets:\n"); (void) printf(" %8d (network) %8d (to host) %8d (dropped)\n\n", total_pkts, tohost_pkts, dropped_pkts); (void) printf("Packet counters:\n"); /* * Print the packet counters. Percentage is calculated as * this counter over total packets. */ for (i = 0; i < PKT_NCOUNTERS; i++) { if (total_pkts) { percent = ((float) pkt_counters[i].pc_total / (float) tohost_pkts) * 100.0; } else { percent = 0.0; } (void) sprintf(buf, "%s:", pkt_counters[i].pc_name); (void) printf(" %-25s %8d %7.0f%%\n", buf, pkt_counters[i].pc_total, percent); if (i == (PKT_NCOUNTERS/2 - 1)) (void) putchar('\n'); } /* * Calculate the total number of NFS packets. */ nfstotal = pkt_counters[PKT_NFSWRITE].pc_total + pkt_counters[PKT_NFSREAD].pc_total; if (nfs_counters[0].nc_name != NULL) (void) printf("\nNFS counters:\n"); /* * Print the NFS counters. Percentage is calculated as * packets this file system over total NFS packets. */ for (i = 0; i < MAXEXPORT; i++) { if (nfs_counters[i].nc_name == NULL) continue; if (nfstotal) { percent = ((float) nfs_counters[i].nc_total / (float) nfstotal) * 100.0; } else { percent = 0.0; } (void) sprintf(buf, "%s:", nfs_counters[i].nc_name); (void) printf(" %-25s %8d %7.0f%%\n", buf, nfs_counters[i].nc_total, percent); } if (fil_counters[0].fc_name != NULL) (void) printf("\nFile counters:\n"); /* * Print the file counters. Percentage is calculated as * packets this file over total NFS packets. */ for (i = 0; i < MAXEXPORT; i++) { if (fil_counters[i].fc_name == NULL) continue; if (nfstotal) { percent = ((float) fil_counters[i].fc_total / (float) nfstotal) * 100.0; } else { percent = 0.0; } (void) sprintf(buf, "%s:", fil_counters[i].fc_name); (void) printf(" %-25s %8d %7.0f%%\n", buf, fil_counters[i].fc_total, percent); } (void) putchar('\014'); /* * If needed, put out the extra info. */ if (verbose) dumpit2(); } /* * dumpit2 - dump even more information. */ void dumpit2() { register int i, j, k; /* * Print NFS procs in groups of 6. */ for (i = 0; i < MAXNFSPROC; i += 6) { /* * Print header. */ (void) printf("NFSwatch logfile summary:\n"); (void) printf(" Log time: %.24s to %.24s\n", startdate, enddate); (void) printf(" Log entries: %d\n", logentries); (void) printf(" Packets from: %s", srchost); (void) printf(" Packets to: %s\n", dsthost); (void) printf("NFS Procedure Call Summary (part %d):\n", ((i / 6) + 1)); (void) printf(" "); for (j = 0; j < 6; j++) (void) printf("%s ", nfs_procs[i+j]); (void) putchar('\n'); /* * Print NFS counters. */ for (j = 0; j < MAXEXPORT; j++) { if (nfs_counters[j].nc_name == NULL) continue; (void) printf("%-25s", nfs_counters[j].nc_name); for (k = 0; k < 6; k++) { (void) printf("%8d ", nfs_counters[j].nc_proc[i+k]); } (void) putchar('\n'); } if (fil_counters[0].fc_name != NULL) (void) putchar('\n'); /* * Print file counters. */ for (j = 0; j < MAXEXPORT; j++) { if (fil_counters[j].fc_name == NULL) continue; (void) printf("%-25s", fil_counters[j].fc_name); for (k = 0; k < 6; k++) { (void) printf("%8d ", fil_counters[j].fc_proc[i+k]); } (void) putchar('\n'); } (void) putchar('\014'); } } /* * findnfs - find the counter associated with name. */ int findnfs(name) char *name; { register int i; /* * Look for it. */ for (i = 0; i < MAXEXPORT; i++) { /* * At end of list. */ if (nfs_counters[i].nc_name == NULL) break; /* * Found it. */ if (!strcmp(name, nfs_counters[i].nc_name)) return(i); } /* * If there's room, add it to the list. */ if (i < MAXEXPORT) { nfs_counters[i].nc_name = savestr(name); return(i); } return(-1); } /* * findfile - find the counter assopciated with name. */ int findfile(name) char *name; { register int i; /* * Look for it. */ for (i = 0; i < MAXEXPORT; i++) { /* * At end of list. */ if (fil_counters[i].fc_name == NULL) break; /* * Found it. */ if (!strcmp(name, fil_counters[i].fc_name)) return(i); } /* * If there's room, add it to the list. */ if (i < MAXEXPORT) { fil_counters[i].fc_name = savestr(name); return(i); } return(-1); } /* * savestr - save string in dynamic memory. */ char * savestr(s) char *s; { char *t; char *malloc(); if ((t = malloc(strlen(s) + 1)) == NULL) { (void) fprintf(stderr, "%s: out of memory.\n", pname); (void) exit(1); } (void) strcpy(t, s); return(t); }