"Fossies" - the Fresh Open Source Software Archive 
Member "atop-2.8.1/atopsar.c" (7 Jan 2023, 74150 Bytes) of package /linux/misc/atop-2.8.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "atopsar.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.7.1_vs_2.8.0.
1 /*
2 ** ATOP - System & Process Monitor
3 **
4 ** The program 'atop'/'atopsar' offers the possibility to view the activity of
5 ** the system on system-level as well as process-level.
6 **
7 ** This source-file contains the 'atopsar'-functionality, that makes use
8 ** of the 'atop'-framework.
9 ** ==========================================================================
10 ** Author: Gerlof Langeveld
11 ** E-mail: gerlof.langeveld@atoptool.nl
12 ** Initial: July 2007
13 ** --------------------------------------------------------------------------
14 ** Copyright (C) 2007-2010 Gerlof Langeveld
15 **
16 ** This program is free software; you can redistribute it and/or modify it
17 ** under the terms of the GNU General Public License as published by the
18 ** Free Software Foundation; either version 2, or (at your option) any
19 ** later version.
20 **
21 ** This program is distributed in the hope that it will be useful, but
22 ** WITHOUT ANY WARRANTY; without even the implied warranty of
23 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 ** See the GNU General Public License for more details.
25 **
26 ** You should have received a copy of the GNU General Public License
27 ** along with this program; if not, write to the Free Software
28 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 ** --------------------------------------------------------------------------
30 */
31
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/mman.h>
35 #include <sys/stat.h>
36 #include <time.h>
37 #include <stdio.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <signal.h>
43 #include <sys/utsname.h>
44 #include <string.h>
45 #include <sys/time.h>
46 #include <sys/resource.h>
47 #include <regex.h>
48 #include <sys/ioctl.h>
49
50 #include "atop.h"
51 #include "ifprop.h"
52 #include "photosyst.h"
53 #include "photoproc.h"
54 #include "gpucom.h"
55
56 #define MAXFL 64 /* maximum number of command-line flags */
57
58
59 /*
60 ** color definitions
61 */
62 #define COLSETHEAD "\033[30;43m" /* black on yellow */
63 #define COLSETMED "\033[36m" /* cyan */
64 #define COLSETHIGH "\033[31m" /* red */
65 #define COLRESET "\033[00m" /* reset any color */
66
67 /*
68 ** miscellaneous values
69 */
70 static unsigned int nsamples = 9999999;
71 static char stampalways;
72 static char usemarkers;
73 static char allresources;
74 static int numreports;
75 static time_t saved_begintime;
76 static unsigned int repeathead = 9999999;
77 static unsigned int summarycnt = 1;
78 static char *datemsg = "-------------------------- analysis "
79 "date: %s --------------------------\n";
80
81 /*
82 ** structure definition for print-functions
83 */
84 struct pridef {
85 char wanted; /* selected option (boolean) */
86 char *cntcat; /* used categories of counters */
87 char flag; /* flag on command line */
88 void (*prihead)(); /* print header of list */
89 int (*priline)(struct sstat *, struct tstat *, struct tstat **,
90 int, time_t, time_t, time_t,
91 int, int, int, char *,
92 int, int, int, int, int, int);
93 /* print counters per line (excl. time) */
94 char *about; /* statistics about what */
95 };
96
97 extern struct pridef pridef[]; /* table of print-functions */
98 extern int pricnt; /* total number of print-functions */
99
100 static time_t daylim; /* last second of day in epoch */
101 static int prinow; /* current selection */
102 static char coloron; /* boolean: colors active now */
103
104 /*
105 ** local prototypes
106 */
107 static void engine(void);
108 static void pratopsaruse(char *);
109 static void reportlive(time_t, int, struct sstat *);
110 static char reportraw (time_t, int,
111 struct devtstat *, struct sstat *,
112 int, unsigned int, char);
113
114 static void reportheader(struct utsname *, time_t);
115 static time_t daylimit(time_t);
116
117 int
118 atopsar(int argc, char *argv[])
119 {
120 register int i, c;
121 struct rlimit rlim;
122 char *p, *flaglist;
123
124 usecolors = 't';
125
126 /*
127 ** interpret command-line arguments & flags
128 */
129 if (argc > 1)
130 {
131 /*
132 ** gather all flags for the print-functions
133 */
134 flaglist = malloc(pricnt+32);
135
136 if (!flaglist)
137 ptrverify(flaglist, "Malloc failed for %d flags\n", pricnt+32);
138
139 for (i=0; i < pricnt; i++)
140 flaglist[i] = pridef[i].flag;
141
142 flaglist[i] = 0;
143
144 /*
145 ** add generic flags
146 */
147 strcat(flaglist, "b:e:SxCMHr:R:aA");
148
149 while ((c=getopt(argc, argv, flaglist)) != EOF)
150 {
151 switch (c)
152 {
153 case '?': /* usage wanted ? */
154 pratopsaruse(argv[0]);
155 break;
156
157 case 'b': /* begin time ? */
158 if ( !getbranchtime(optarg, &begintime) )
159 pratopsaruse(argv[0]);
160
161 saved_begintime = begintime;
162 break;
163
164 case 'e': /* end time ? */
165 if ( !getbranchtime(optarg, &endtime) )
166 pratopsaruse(argv[0]);
167 break;
168
169 case 'r': /* reading of file data ? */
170 strncpy(rawname, optarg, RAWNAMESZ-1);
171
172 if (strcmp(rawname, "-") == 0)
173 strcpy(rawname, "/dev/stdin");
174
175 rawreadflag++;
176 break;
177
178 case 'R': /* summarize samples */
179 if (!numeric(optarg))
180 pratopsaruse(argv[0]);
181
182 summarycnt = atoi(optarg);
183
184 if (summarycnt < 1)
185 pratopsaruse(argv[0]);
186 break;
187
188 case 'S': /* timestamp on every line */
189 stampalways = 1;
190 break;
191
192 case 'x': /* never use colors */
193 usecolors = 0;
194 break;
195
196 case 'C': /* always use colors */
197 usecolors = 'a';
198 break;
199
200 case 'M': /* markers for overload */
201 usemarkers = 1;
202 break;
203
204 case 'H': /* repeat headers */
205 repeathead = 23; /* define default */
206
207 if (isatty(fileno(stdout)))
208 {
209 struct winsize wsz;
210
211 if ( ioctl(1, TIOCGWINSZ, &wsz) != -1)
212 repeathead = wsz.ws_row - 1;
213 }
214 break;
215
216 case 'a': /* every interval all units */
217 allresources = 1;
218 break;
219
220 case 'A': /* all reports wanted ? */
221 for (i=0; i < pricnt; i++)
222 pridef[i].wanted = 1;
223
224 numreports = pricnt;
225 break;
226
227 default: /* gather report-flags */
228 for (i=0; i < pricnt; i++)
229 {
230 if (pridef[i].flag == c &&
231 pridef[i].wanted == 0 )
232 {
233 pridef[i].wanted = 1;
234 numreports++;
235 break;
236 }
237 }
238
239 if (i == pricnt)
240 pratopsaruse(argv[0]);
241 }
242 }
243
244 free(flaglist);
245
246 /*
247 ** get optional interval-value and
248 ** optional number of samples
249 */
250 if (optind < argc && optind < MAXFL)
251 {
252 if (rawreadflag)
253 pratopsaruse(argv[0]);
254
255 if (!numeric(argv[optind]))
256 pratopsaruse(argv[0]);
257
258 interval = atoi(argv[optind]);
259
260 optind++;
261
262 if (optind < argc)
263 {
264 if (!numeric(argv[optind]) )
265 pratopsaruse(argv[0]);
266
267 if ( (nsamples = atoi(argv[optind])) < 1)
268 pratopsaruse(argv[0]);
269 }
270 }
271 else /* if no interval specified, read from logfile */
272 {
273 rawreadflag++;
274 }
275 }
276 else /* if no flags specified at all, read from logfile */
277 {
278 rawreadflag++;
279 }
280
281 /*
282 ** if no report-flags have been specified, take the first
283 ** option in the print-list as default
284 */
285 if (numreports == 0)
286 {
287 pridef[0].wanted = 1;
288 numreports = 1;
289 }
290
291 /*
292 ** set stdout output on line-basis
293 */
294 setvbuf(stdout, (char *)0, _IOLBF, BUFSIZ);
295
296 /*
297 ** if only use colors when the output is directed to a tty,
298 ** be sure that output is directed to a tty
299 */
300 if (usecolors == 't')
301 {
302 if (! isatty(fileno(stdout)) )
303 usecolors = 0;
304 }
305
306 /*
307 ** check if raw data from a file must be viewed
308 */
309 if (rawreadflag)
310 {
311 /*
312 ** select own reportraw-function to be called
313 ** by the rawread function
314 */
315 vis.show_samp = reportraw;
316
317 for (i=0; i < pricnt; i++)
318 {
319 if ( pridef[i].wanted )
320 {
321 prinow = i;
322 daylim = 0;
323 begintime = saved_begintime;
324
325 if (!rawread()) // reading from named pipe
326 break; // can only be done once
327
328 printf("\n");
329 }
330 }
331
332 cleanstop(0);
333 }
334
335 /*
336 ** live data must be gathered
337 **
338 ** determine the name of this node (without domain-name)
339 ** and the kernel-version
340 */
341 (void) uname(&utsname);
342
343 if ( (p = strchr(utsname.nodename, '.')) )
344 *p = '\0';
345
346 sscanf(utsname.release, "%d.%d.%d", &osrel, &osvers, &ossub);
347
348 /*
349 ** determine the clock rate and memory page size for this machine
350 */
351 hertz = sysconf(_SC_CLK_TCK);
352 pagesize = sysconf(_SC_PAGESIZE);
353
354 /*
355 ** determine start-time for gathering current statistics
356 */
357 curtime = time(0);
358
359 /*
360 ** regain the root-privileges that we dropped at the beginning
361 ** to do some privileged work now
362 */
363 regainrootprivs();
364
365 /*
366 ** lock in memory to get reliable samples (also when
367 ** memory is low);
368 ** ignored if not running under superuser privileges!
369 */
370 rlim.rlim_cur = RLIM_INFINITY;
371 rlim.rlim_max = RLIM_INFINITY;
372 (void) setrlimit(RLIMIT_MEMLOCK, &rlim);
373 (void) mlockall(MCL_CURRENT|MCL_FUTURE);
374
375 /*
376 ** increment CPU scheduling-priority to get reliable samples (also
377 ** during heavy CPU load);
378 ** ignored if not running under superuser privileges!
379 */
380 if ( nice(-20) == -1)
381 ;
382 /*
383 ** determine properties (like speed) of all interfaces
384 */
385 initifprop();
386
387 /*
388 ** since privileged activities are finished now, there is no
389 ** need to keep running under root-privileges, so switch
390 ** effective user-id to real user-id
391 */
392 if (! droprootprivs() )
393 mcleanstop(42, "failed to drop root privs\n");
394
395 /*
396 ** start live reporting
397 */
398 engine();
399
400 return 0;
401 }
402
403 /*
404 ** engine() that drives the main-loop for atopsar
405 */
406 static void
407 engine(void)
408 {
409 struct sigaction sigact;
410 void getusr1(int);
411
412 int nrgpus; /* number of GPUs */
413 int nrgpuproc, /* number of GPU procs */
414 gpustats=0; /* boolean: request sent */
415
416 /*
417 ** reserve space for system-level statistics
418 */
419 static struct sstat *cursstat; /* current */
420 static struct sstat *presstat; /* previous */
421 static struct sstat *devsstat; /* deviation */
422 static struct sstat *hlpsstat;
423
424 /*
425 ** initialization: allocate required memory dynamically
426 */
427 cursstat = calloc(1, sizeof(struct sstat));
428 presstat = calloc(1, sizeof(struct sstat));
429 devsstat = calloc(1, sizeof(struct sstat));
430
431 ptrverify(cursstat, "Malloc failed for current sysstats\n");
432 ptrverify(presstat, "Malloc failed for prev sysstats\n");
433 ptrverify(devsstat, "Malloc failed for deviate sysstats\n");
434
435 /*
436 ** install the signal-handler for ALARM and SIGUSR1 (both triggers
437 ** for the next sample)
438 */
439 memset(&sigact, 0, sizeof sigact);
440 sigact.sa_handler = getusr1;
441 sigaction(SIGUSR1, &sigact, (struct sigaction *)0);
442
443 memset(&sigact, 0, sizeof sigact);
444 sigact.sa_handler = getalarm;
445 sigaction(SIGALRM, &sigact, (struct sigaction *)0);
446
447 if (interval > 0)
448 alarm(interval);
449
450 /*
451 ** print overall report header
452 */
453 reportheader(&utsname, time(0));
454
455 /*
456 ** open socket to the atopgpud daemon for GPU statistics
457 */
458 nrgpus = gpud_init();
459
460 /*
461 ** MAIN-LOOP:
462 ** - Wait for the requested number of seconds or for other trigger
463 **
464 ** - System-level counters
465 ** get current counters
466 ** calculate the differences with the previous sample
467 **
468 ** - Call the print-function to visualize the differences
469 */
470 for (sampcnt=0; sampcnt < nsamples+1; sampcnt++)
471 {
472 /*
473 ** wait for alarm-signal to arrive or
474 ** wait for SIGUSR1 in case of an interval of 0.
475 */
476 if (sampcnt > 0)
477 pause();
478
479 /*
480 ** gather time info for this sample
481 */
482 pretime = curtime;
483 curtime = time(0); /* seconds since 1-1-1970 */
484
485 /*
486 ** send request for statistics to atopgpud
487 */
488 if (nrgpus)
489 gpustats = gpud_statrequest();
490
491 /*
492 ** take a snapshot of the current system-level statistics
493 ** and calculate the deviations (i.e. calculate the activity
494 ** during the last sample)
495 */
496 hlpsstat = cursstat; /* swap current/prev. stats */
497 cursstat = presstat;
498 presstat = hlpsstat;
499
500 photosyst(cursstat); /* obtain new counters */
501
502 /*
503 ** receive and parse response from atopgpud
504 */
505 if (nrgpus && gpustats)
506 {
507 nrgpuproc = gpud_statresponse(nrgpus, cursstat->gpu.gpu, NULL);
508
509 // connection lost or timeout on receive?
510 if (nrgpuproc == -1)
511 {
512 int ng;
513
514 // try to reconnect
515 ng = gpud_init();
516
517 if (ng != nrgpus) // no success
518 nrgpus = 0;
519
520 if (nrgpus)
521 {
522 // request for stats again
523 if (gpud_statrequest())
524 {
525 // receive stats response
526 nrgpuproc = gpud_statresponse(nrgpus,
527 cursstat->gpu.gpu, NULL);
528
529 // persistent failure?
530 if (nrgpuproc == -1)
531 nrgpus = 0;
532 }
533 }
534 }
535
536 cursstat->gpu.nrgpus = nrgpus;
537 }
538
539 /*
540 ** calculate deviations, i.e. activity during interval
541 */
542 deviatsyst(cursstat, presstat, devsstat,
543 curtime-pretime > 0 ? curtime-pretime : 1);
544
545 /*
546 ** activate the report-function to visualize the deviations
547 */
548 reportlive(curtime,
549 curtime-pretime > 0 ? curtime-pretime : 1, devsstat);
550 } /* end of main-loop */
551 }
552
553 /*
554 ** report function to print a new sample in case of live measurements
555 */
556 static void
557 reportlive(time_t curtime, int numsecs, struct sstat *ss)
558 {
559 char timebuf[16], datebuf[16];
560 int i, nr = numreports, rv;
561 static unsigned int curline, headline;
562
563 /*
564 ** printing more reports needs another way of handling compared
565 ** to printing one report
566 */
567 if (numreports > 1)
568 {
569 /*
570 ** skip first sample
571 */
572 if (sampcnt == 0)
573 return;
574
575 printf(datemsg, convdate(curtime, datebuf));
576
577 for (i=0; i < pricnt && nr > 0; i++)
578 {
579 if ( !pridef[i].wanted )
580 continue;
581
582 nr--;
583
584 /*
585 ** print header-line
586 */
587 printf("\n");
588
589 if (usecolors)
590 printf(COLSETHEAD);
591
592 printf("%s ", convtime(curtime-numsecs, timebuf));
593
594 (pridef[i].prihead)(osvers, osrel, ossub);
595
596 if (usecolors)
597 printf(COLRESET);
598
599 printf("\n");
600
601 /*
602 ** print line with statistical counters
603 */
604 printf("%s ", convtime(curtime, timebuf));
605
606 if ( !(pridef[i].priline)(ss, (struct tstat *)0, 0, 0,
607 numsecs, numsecs*hertz, hertz,
608 osvers, osrel, ossub,
609 stampalways ? timebuf : " ",
610 0, 0, 0, 0, 0, 0) )
611 {
612 /*
613 ** print line has failed;
614 ** do not call function again
615 */
616 pridef[i].wanted = 0;
617
618 if (--numreports == 0)
619 cleanstop(1);
620 }
621 }
622
623 printf("\n");
624 }
625 else /* just one report to be printed */
626 {
627 /*
628 ** search required report
629 */
630 for (i=0; i < pricnt; i++)
631 if ( pridef[i].wanted )
632 break;
633
634 /*
635 ** verify if we have passed midnight of some day
636 */
637 if (curtime > daylim)
638 {
639 printf(datemsg, convdate(curtime, datebuf));
640 daylim = daylimit(curtime);
641 curline++;
642 }
643
644 /*
645 ** print first header
646 */
647 if (sampcnt == 0)
648 {
649 /*
650 ** print header-line
651 */
652 printf("\n");
653
654 if (usecolors)
655 printf(COLSETHEAD);
656
657 printf("%s ", convtime(curtime, timebuf));
658
659 (pridef[i].prihead)(osvers, osrel, ossub);
660
661 if (usecolors)
662 printf(COLRESET);
663
664 printf("\n");
665
666 curline+=2;
667
668 headline = repeathead;
669 return;
670 }
671
672 /*
673 ** print line with statistical counters
674 */
675 printf("%s ", convtime(curtime, timebuf));
676
677 if ( !(rv = (pridef[i].priline)(ss, (struct tstat *)0, 0, 0,
678 numsecs, numsecs*hertz, hertz,
679 osvers, osrel, ossub,
680 stampalways ? timebuf : " ",
681 0, 0, 0, 0, 0, 0) ) )
682 {
683 /*
684 ** print line has failed;
685 ** do not call function again
686 */
687 cleanstop(1);
688 }
689
690 curline+=rv;
691
692 if (curline >= headline)
693 {
694 headline = curline + repeathead;
695
696 /*
697 ** print header-line
698 */
699 printf("\n");
700
701 if (usecolors)
702 printf(COLSETHEAD);
703
704 printf("%s ", convtime(curtime, timebuf));
705
706 (pridef[i].prihead)(osvers, osrel, ossub);
707
708 if (usecolors)
709 printf(COLRESET);
710
711 printf("\n");
712
713 curline+=2;
714 }
715 }
716 }
717
718 /*
719 ** report function to print a new sample in case of logged measurements
720 */
721 static char
722 reportraw(time_t curtime, int numsecs,
723 struct devtstat *devtstat, struct sstat *sstat,
724 int nexit, unsigned int noverflow, char flags)
725 {
726 static char firstcall = 1;
727 char timebuf[16], datebuf[16];
728 unsigned int rv;
729 static unsigned int curline, headline, sampsum,
730 totalsec, totalexit, lastnpres,
731 lastntrun, lastntslpi, lastntslpu, lastnzomb;
732 static time_t lasttime;
733 static struct sstat totsyst;
734
735 /*
736 ** is this function still wanted?
737 */
738 if ( ! pridef[prinow].wanted )
739 return '\0';
740
741 /*
742 ** when this is first call to this function,
743 ** print overall header with system information
744 */
745 if (firstcall)
746 {
747 reportheader(&utsname, time(0));
748 firstcall = 0;
749 }
750
751 /*
752 ** verify if we have passed midnight
753 */
754 if (curtime > daylim)
755 {
756 printf(datemsg, convdate(curtime, datebuf));
757 daylim = daylimit(curtime);
758 curline++;
759 }
760
761 /*
762 ** when this is the first record for a new report,
763 ** initialize various variables
764 */
765 if (sampcnt == 1)
766 {
767 /*
768 ** initialize variables for new report
769 */
770 pretime = curtime;
771
772 curline = 1;
773 headline = 0;
774
775 sampsum = summarycnt + 1;
776 totalsec = 0;
777 totalexit = 0;
778 memset(&totsyst, 0, sizeof totsyst);
779
780 return '\0';
781 }
782
783 /*
784 ** check if a (new) report header needs to be printed
785 */
786 if (curline >= headline)
787 {
788 headline = curline + repeathead;
789
790 /*
791 ** print header-line
792 */
793 printf("\n");
794
795 if (usecolors)
796 printf(COLSETHEAD);
797
798 printf("%s ", convtime(pretime, timebuf));
799
800 (pridef[prinow].prihead)(osvers, osrel, ossub);
801
802 if (usecolors)
803 printf(COLRESET);
804
805 printf("\n");
806
807 curline+=2;
808 }
809
810 /*
811 ** when current record contains log-restart indicator,
812 ** print message and reinitialize variables
813 */
814 if (flags & RRBOOT)
815 {
816 /*
817 ** when accumulating counters, print results upto
818 ** the *previous* record
819 */
820 if (summarycnt > 1 && sampcnt <= sampsum && totalsec)
821 {
822 printf("%s ", convtime(lasttime, timebuf));
823
824 rv = (pridef[prinow].priline)(&totsyst,
825 (struct tstat *)0, 0, 0,
826 totalsec, totalsec*hertz, hertz,
827 osvers, osrel, ossub,
828 stampalways ? timebuf : " ",
829 lastnpres, lastntrun, lastntslpi, lastntslpu,
830 totalexit, lastnzomb);
831
832 if (rv == 0)
833 {
834 curline++;
835 pridef[prinow].wanted = 0; /* not call again */
836
837 if (--numreports == 0)
838 cleanstop(1);
839 }
840 else
841 {
842 curline += rv;
843 }
844 }
845
846 /*
847 ** print restart-line in case of logging restarted
848 */
849 printf("%s ", convtime(curtime, timebuf));
850
851 printf("......................... logging restarted "
852 ".........................\n");
853
854 pretime = curtime;
855 curline++;
856
857 /*
858 ** reinitialize variables
859 */
860 sampsum = summarycnt + sampcnt;
861 totalsec = 0;
862 totalexit = 0;
863 memset(&totsyst, 0, sizeof totsyst);
864
865 return '\0';
866 }
867
868 /*
869 ** when no accumulation is required,
870 ** just print current sample
871 */
872 if (summarycnt == 1)
873 {
874 printf("%s ", convtime(curtime, timebuf));
875
876 rv = (pridef[prinow].priline) (sstat, devtstat->taskall,
877 devtstat->procall, devtstat->nprocall,
878 numsecs, numsecs*hertz, hertz,
879 osvers, osrel, ossub,
880 stampalways ? timebuf : " ",
881 devtstat->ntaskall, devtstat->totrun,
882 devtstat->totslpi, devtstat->totslpu,
883 nexit, devtstat->totzombie);
884
885 if (rv == 0)
886 {
887 curline++;
888 pridef[prinow].wanted = 0; /* not call again */
889
890 if (--numreports == 0)
891 cleanstop(1);
892 }
893 else
894 {
895 curline += rv;
896 }
897 }
898 else /* accumulation is required */
899 {
900 char *cp = pridef[prinow].cntcat;
901
902 /*
903 ** maintain totals per category
904 */
905 while (*cp)
906 {
907 totalsyst(*cp, sstat, &totsyst);
908 cp++;
909 }
910
911 totalsec += numsecs;
912 totalexit += nexit;
913
914 /*
915 ** remember some values in case the next record
916 ** contains the log-restart indicator
917 */
918 lasttime = curtime;
919 lastnpres = devtstat->nprocall;
920 lastntrun = devtstat->totrun;
921 lastntslpi = devtstat->totslpi;
922 lastntslpu = devtstat->totslpu;
923 lastnzomb = devtstat->totzombie;
924
925 /*
926 ** print line only if needed
927 */
928 if (sampcnt >= sampsum || ( (flags&RRLAST) && totalsec) )
929 {
930 /*
931 ** print output line for required report
932 */
933 printf("%s ", convtime(curtime, timebuf));
934
935 rv = (pridef[prinow].priline) (&totsyst,
936 (struct tstat *)0, 0, 0,
937 totalsec, totalsec*hertz, hertz,
938 osvers, osrel, ossub,
939 stampalways ? timebuf : " ",
940 devtstat->ntaskall, devtstat->totrun,
941 devtstat->totslpi, devtstat->totslpu,
942 totalexit, devtstat->totzombie);
943
944 if (rv == 0)
945 {
946 curline++;
947 pridef[prinow].wanted = 0; /* not call again */
948
949 if (--numreports == 0)
950 cleanstop(1);
951 }
952 else
953 {
954 curline += rv;
955 }
956
957 sampsum = summarycnt + sampcnt;
958 totalsec = 0;
959 totalexit = 0;
960 memset(&totsyst, 0, sizeof totsyst);
961 }
962 else
963 {
964 rv = 1;
965 }
966 }
967
968 if (!rv)
969 {
970 /*
971 ** print for line has failed;
972 ** never call this function again
973 */
974 pridef[prinow].wanted = 0;
975
976 if (--numreports == 0)
977 cleanstop(1);
978 }
979
980 pretime = curtime;
981
982 return '\0';
983 }
984
985 /*
986 ** print overall header
987 */
988 static void
989 reportheader(struct utsname *uname, time_t mtime)
990 {
991 char cdate[16];
992
993 printf("\n%s %s %s %s %s\n\n",
994 uname->nodename,
995 uname->release,
996 uname->version,
997 uname->machine,
998 convdate(mtime, cdate));
999 }
1000
1001 /*
1002 ** print usage of atopsar command
1003 */
1004 void
1005 pratopsaruse(char *myname)
1006 {
1007 int i;
1008
1009 fprintf(stderr,
1010 "Usage: %s [-flags] [-r file|-|date|y...] [-R cnt] [-b time] [-e time]\n",
1011 myname);
1012 fprintf(stderr, "\t\tor\n");
1013 fprintf(stderr,
1014 "Usage: %s [-flags] interval [samples]\n", myname);
1015 fprintf(stderr, "\n");
1016 fprintf(stderr,
1017 "\tToday's atop logfile is used by default!\n");
1018 fprintf(stderr, "\n");
1019 fprintf(stderr,
1020 "\tGeneric flags:\n");
1021 fprintf(stderr,
1022 "\t -r read statistical data from specific atop logfile\n");
1023 fprintf(stderr,
1024 "\t (pathname, - for stdin, date in format YYYYMMDD, or y[y..])\n");
1025 fprintf(stderr,
1026 "\t -R summarize <cnt> samples into one sample\n");
1027 fprintf(stderr,
1028 "\t -b begin showing data from specified time as [YYYYMMDD]hhmm\n");
1029 fprintf(stderr,
1030 "\t -e finish showing data after specified time as [YYYYMMDD]hhmm\n");
1031 fprintf(stderr,
1032 "\t -S print timestamp on every line in case of more "
1033 "resources\n");
1034 fprintf(stderr,
1035 "\t -x never use colors to indicate overload"
1036 " (default: only if tty)\n");
1037 fprintf(stderr,
1038 "\t -C always use colors to indicate overload"
1039 " (default: only if tty)\n");
1040 fprintf(stderr,
1041 "\t -M use markers to indicate overload "
1042 "(* = critical, + = almost)\n");
1043 fprintf(stderr,
1044 "\t -H repeat report headers "
1045 "(in case of tty: depending on screen lines)\n");
1046 fprintf(stderr,
1047 "\t -a print all resources, even when inactive\n");
1048 fprintf(stderr, "\n");
1049 fprintf(stderr,
1050 "\tSpecific flags to select reports:\n");
1051 fprintf(stderr,
1052 "\t -A print all available reports\n");
1053
1054 for (i=0; i < pricnt; i++)
1055 fprintf(stderr,
1056 "\t -%c %s\n", pridef[i].flag, pridef[i].about);
1057
1058 fprintf(stderr, "\n");
1059 fprintf(stderr,
1060 "Please refer to the man-page of 'atopsar' "
1061 "for more details.\n");
1062
1063
1064 cleanstop(1);
1065 }
1066
1067 /*
1068 ** calculate the epoch-value for the last second
1069 ** of the day given a certain epoch
1070 */
1071 static time_t
1072 daylimit(time_t timval)
1073 {
1074 struct tm *tp = localtime(&timval);
1075
1076 tp->tm_hour = 23;
1077 tp->tm_min = 59;
1078 tp->tm_sec = 59;
1079
1080 return mktime(tp);
1081 }
1082
1083 /*
1084 ** function to be called before printing a statistics line
1085 ** to switch on colors when necessary
1086 */
1087 static void
1088 preprint(unsigned int badness)
1089 {
1090 if (usecolors)
1091 {
1092 if (badness >= 100)
1093 {
1094 coloron = 1;
1095 printf(COLSETHIGH);
1096 }
1097 else
1098 {
1099 if (almostcrit && badness >= almostcrit)
1100 {
1101 coloron = 1;
1102 printf(COLSETMED);
1103 }
1104 }
1105 }
1106 }
1107
1108 /*
1109 ** function to be called after printing a statistics line
1110 ** to switch off colors when necessary and print a line feed
1111 */
1112 static void
1113 postprint(unsigned int badness)
1114 {
1115 if (coloron)
1116 {
1117 coloron = 0;
1118 printf(COLRESET);
1119 }
1120
1121 if (usemarkers)
1122 {
1123 if (badness >= 100)
1124 {
1125 printf(" *");
1126 }
1127 else
1128 {
1129 if (almostcrit && badness >= almostcrit)
1130 printf(" +");
1131 }
1132 }
1133
1134 printf("\n");
1135 }
1136
1137 /*
1138 ** function to handle the default flags for atopsar as
1139 ** read from the files ~/.atoprc and /etc/atoprc
1140 */
1141 void
1142 do_atopsarflags(char *name, char *val)
1143 {
1144 int i, j;
1145
1146 for (i=0; val[i]; i++)
1147 {
1148 switch (val[i])
1149 {
1150 case '-':
1151 break;
1152
1153 case 'S': /* timestamp on every line */
1154 stampalways = 1;
1155 break;
1156
1157 case 'x': /* always colors for overload */
1158 usecolors = 0;
1159 break;
1160
1161 case 'C': /* always colors for overload */
1162 usecolors = 'a';
1163 break;
1164
1165 case 'M': /* markers for overload */
1166 usemarkers = 1;
1167 break;
1168
1169 case 'H': /* repeat headers */
1170 repeathead = 23; /* define default */
1171
1172 if (isatty(fileno(stdout)))
1173 {
1174 struct winsize wsz;
1175
1176 if ( ioctl(1, TIOCGWINSZ, &wsz) != -1)
1177 repeathead = wsz.ws_row - 1;
1178 }
1179 break;
1180
1181 case 'a': /* every interval all units */
1182 allresources = 1;
1183 break;
1184
1185 case 'A': /* all reports wanted ? */
1186 for (j=0; j < pricnt; j++)
1187 pridef[j].wanted = 1;
1188
1189 numreports = pricnt;
1190 break;
1191
1192 default: /* gather report-flags */
1193 for (j=0; j < pricnt; j++)
1194 {
1195 if (pridef[j].flag == val[i] &&
1196 pridef[j].wanted == 0 )
1197 {
1198 pridef[j].wanted = 1;
1199 numreports++;
1200 break;
1201 }
1202 }
1203 }
1204 }
1205 }
1206
1207 /**************************************************************************/
1208 /* Functions to print statistics */
1209 /**************************************************************************/
1210 /*
1211 ** CPU statistics
1212 */
1213 static void
1214 cpuhead(int osvers, int osrel, int ossub)
1215 {
1216 printf("cpu %%usr %%nice %%sys %%irq %%softirq %%steal %%guest "
1217 " %%wait %%idle _cpu_");
1218 }
1219
1220 static int
1221 cpuline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1222 time_t deltasec, time_t deltatic, time_t hz,
1223 int osvers, int osrel, int ossub, char *tstamp,
1224 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1225 {
1226 register int i, nlines = 1;
1227 count_t cputot;
1228 unsigned int badness;
1229
1230 /*
1231 ** print overall statistics
1232 */
1233 cputot = ss->cpu.all.stime + ss->cpu.all.utime +
1234 ss->cpu.all.ntime + ss->cpu.all.itime +
1235 ss->cpu.all.wtime + ss->cpu.all.Itime +
1236 ss->cpu.all.Stime + ss->cpu.all.steal;
1237
1238 if (cputot == 0)
1239 cputot = 1; /* avoid divide-by-zero */
1240
1241 if (cpubadness)
1242 badness = ((cputot - ss->cpu.all.itime - ss->cpu.all.wtime) *
1243 100.0 / cputot) * 100 / cpubadness;
1244 else
1245 badness = 0;
1246
1247 preprint(badness);
1248
1249 printf("all %5.0lf %5.0lf %4.0lf %4.0lf %8.0lf %7.0f %6.0f %6.0lf %5.0lf",
1250 (double) (ss->cpu.all.utime * 100.0) / cputot * ss->cpu.nrcpu,
1251 (double) (ss->cpu.all.ntime * 100.0) / cputot * ss->cpu.nrcpu,
1252 (double) (ss->cpu.all.stime * 100.0) / cputot * ss->cpu.nrcpu,
1253 (double) (ss->cpu.all.Itime * 100.0) / cputot * ss->cpu.nrcpu,
1254 (double) (ss->cpu.all.Stime * 100.0) / cputot * ss->cpu.nrcpu,
1255 (double) (ss->cpu.all.steal * 100.0) / cputot * ss->cpu.nrcpu,
1256 (double) (ss->cpu.all.guest * 100.0) / cputot * ss->cpu.nrcpu,
1257 (double) (ss->cpu.all.wtime * 100.0) / cputot * ss->cpu.nrcpu,
1258 (double) (ss->cpu.all.itime * 100.0) / cputot * ss->cpu.nrcpu);
1259
1260 postprint(badness);
1261
1262 /*
1263 ** print per-cpu statistics
1264 */
1265 if (ss->cpu.nrcpu > 1)
1266 {
1267 for (i=0; i < ss->cpu.nrcpu; i++)
1268 {
1269 cputot = ss->cpu.cpu[i].stime + ss->cpu.cpu[i].utime +
1270 ss->cpu.cpu[i].ntime + ss->cpu.cpu[i].itime +
1271 ss->cpu.cpu[i].wtime + ss->cpu.cpu[i].Itime +
1272 ss->cpu.cpu[i].Stime + ss->cpu.cpu[i].steal;
1273
1274 if (cputot == 0)
1275 cputot = 1; /* avoid divide-by-zero */
1276
1277 if (cpubadness)
1278 badness = ((cputot - ss->cpu.cpu[i].itime -
1279 ss->cpu.cpu[i].wtime) * 100.0 /
1280 cputot) * 100 / cpubadness;
1281 else
1282 badness = 0;
1283
1284 printf("%s ", tstamp);
1285
1286 preprint(badness);
1287
1288 printf("%4d %5.0lf %5.0lf %4.0lf %4.0lf %8.0lf "
1289 "%7.0f %6.0lf %6.0lf %5.0lf",
1290 i,
1291 (double)(ss->cpu.cpu[i].utime * 100.0) / cputot,
1292 (double)(ss->cpu.cpu[i].ntime * 100.0) / cputot,
1293 (double)(ss->cpu.cpu[i].stime * 100.0) / cputot,
1294 (double)(ss->cpu.cpu[i].Itime * 100.0) / cputot,
1295 (double)(ss->cpu.cpu[i].Stime * 100.0) / cputot,
1296 (double)(ss->cpu.cpu[i].steal * 100.0) / cputot,
1297 (double)(ss->cpu.cpu[i].guest * 100.0) / cputot,
1298 (double)(ss->cpu.cpu[i].wtime * 100.0) / cputot,
1299 (double)(ss->cpu.cpu[i].itime * 100.0) / cputot);
1300
1301 postprint(badness);
1302
1303 nlines++;
1304 }
1305 }
1306
1307 return nlines;
1308 }
1309
1310
1311 /*
1312 ** GPU statistics
1313 */
1314 static void
1315 gpuhead(int osvers, int osrel, int ossub)
1316 {
1317 printf(" busaddr gpubusy membusy memocc memtot memuse gputype"
1318 " _gpu_");
1319 }
1320
1321 static int
1322 gpuline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1323 time_t deltasec, time_t deltatic, time_t hz,
1324 int osvers, int osrel, int ossub, char *tstamp,
1325 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1326 {
1327 static char firstcall = 1;
1328 register long i, nlines = 0;
1329 char fmt1[16], fmt2[16];
1330 count_t avgmemuse;
1331
1332 for (i=0; i < ss->gpu.nrgpus; i++) /* per GPU */
1333 {
1334 /*
1335 ** determine whether or not the GPU has been active
1336 ** during interval
1337 */
1338 int wasactive;
1339
1340 wasactive = ss->gpu.gpu[i].gpuperccum +
1341 ss->gpu.gpu[i].memperccum;
1342
1343 if (wasactive == -2) // metrics not available?
1344 wasactive = 0;
1345
1346 if (ss->gpu.gpu[i].samples == 0)
1347 avgmemuse = ss->gpu.gpu[i].memusenow;
1348 else
1349 avgmemuse = ss->gpu.gpu[i].memusecum /
1350 ss->gpu.gpu[i].samples;
1351
1352 // memusage > 512 MiB (rather arbitrary)?
1353 //
1354 if (avgmemuse > 512*1024)
1355 wasactive = 1;
1356
1357 /*
1358 ** print for the first sample all GPUs that are found;
1359 ** afterwards print only info about the GPUs
1360 ** that were really active during the interval
1361 */
1362 if (!firstcall && !allresources && !wasactive)
1363 continue;
1364
1365 if (nlines++)
1366 printf("%s ", tstamp);
1367
1368 if (ss->gpu.gpu[i].samples == 0)
1369 ss->gpu.gpu[i].samples = 1;
1370
1371 if (ss->gpu.gpu[i].gpuperccum == -1)
1372 strcpy(fmt1, "N/A");
1373 else
1374 snprintf(fmt1, sizeof fmt1, "%lld%%",
1375 ss->gpu.gpu[i].gpuperccum / ss->gpu.gpu[i].samples);
1376
1377 if (ss->gpu.gpu[i].memperccum == -1)
1378 strcpy(fmt2, "N/A");
1379 else
1380 snprintf(fmt2, sizeof fmt2, "%lld%%",
1381 ss->gpu.gpu[i].memperccum / ss->gpu.gpu[i].samples);
1382
1383 if (ss->gpu.gpu[i].memtotnow == 0)
1384 ss->gpu.gpu[i].memtotnow = 1;
1385
1386 printf("%2ld/%9.9s %7s %7s %5lld%% %5lldM %5lldM %s\n",
1387 i, ss->gpu.gpu[i].busid,
1388 fmt1, fmt2,
1389 ss->gpu.gpu[i].memusenow*100/ss->gpu.gpu[i].memtotnow,
1390 ss->gpu.gpu[i].memtotnow / 1024,
1391 ss->gpu.gpu[i].memusenow / 1024,
1392 ss->gpu.gpu[i].type);
1393 }
1394
1395 if (nlines == 0)
1396 {
1397 printf("\n");
1398 nlines++;
1399 }
1400
1401 firstcall = 0;
1402 return nlines;
1403 }
1404
1405 /*
1406 ** other processor statistics
1407 */
1408 static void
1409 prochead(int osvers, int osrel, int ossub)
1410 {
1411 printf("pswch/s devintr/s clones/s loadavg1 loadavg5 loadavg15 "
1412 " _load_");
1413 }
1414
1415 static int
1416 procline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1417 time_t deltasec, time_t deltatic, time_t hz,
1418 int osvers, int osrel, int ossub, char *tstamp,
1419 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1420 {
1421 printf("%7.0lf %9.0lf %9.2lf %8.2lf %8.2lf %8.2lf\n",
1422 (double)ss->cpu.csw / deltasec,
1423 (double)ss->cpu.devint / deltasec,
1424 (double)ss->cpu.nprocs / deltasec,
1425 ss->cpu.lavg1, ss->cpu.lavg5, ss->cpu.lavg15);
1426 return 1;
1427 }
1428
1429 /*
1430 ** process statistics
1431 */
1432 static void
1433 taskhead(int osvers, int osrel, int ossub)
1434 {
1435 printf("clones/s pexit/s curproc curzomb thrrun thrslpi thrslpu "
1436 "_procthr_");
1437 }
1438
1439 static int
1440 taskline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1441 time_t deltasec, time_t deltatic, time_t hz,
1442 int osvers, int osrel, int ossub, char *tstamp,
1443 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1444 {
1445 if (ppres == 0)
1446 {
1447 printf("report not available for live measurements.....\n");
1448 return 0;
1449 }
1450
1451 if (ts) /* process statistics available */
1452 {
1453 printf("%8.2lf %7.2lf %7d %7d %6d %7d %7d\n",
1454 (double)ss->cpu.nprocs / deltasec,
1455 (double)pexit / deltasec,
1456 nactproc-pexit, pzombie, ntrun, ntslpi, ntslpu);
1457 }
1458 else
1459 {
1460 printf("%8.2lf %7.2lf %7d %7d\n",
1461 (double)ss->cpu.nprocs / deltasec,
1462 (double)pexit / deltasec,
1463 nactproc-pexit, pzombie);
1464 }
1465
1466 return 1;
1467 }
1468
1469 /*
1470 ** memory- & swap-usage
1471 */
1472 static void
1473 memhead(int osvers, int osrel, int ossub)
1474 {
1475 printf("memtotal memfree buffers cached dirty slabmem"
1476 " swptotal swpfree _mem_" );
1477 }
1478
1479 static int
1480 memline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1481 time_t deltasec, time_t deltatic, time_t hz,
1482 int osvers, int osrel, int ossub, char *tstamp,
1483 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1484 {
1485 unsigned int mbadness, sbadness;
1486
1487 if (membadness)
1488 mbadness = ((ss->mem.physmem - ss->mem.freemem
1489 - ss->mem.cachemem - ss->mem.buffermem
1490 + ss->mem.shmem) * 100.0 / ss->mem.physmem)
1491 * 100 / membadness;
1492 else
1493 mbadness = 0;
1494
1495 if (swpbadness)
1496 sbadness = ((ss->mem.totswap - ss->mem.freeswap)
1497 * 100.0 / ss->mem.totswap)
1498 * 100 / swpbadness;
1499 else
1500 sbadness = 0;
1501
1502 preprint(mbadness >= sbadness ? mbadness : sbadness);
1503
1504 printf("%7lldM %6lldM %6lldM %5lldM %4lldM %6lldM %7lldM %6lldM",
1505 ss->mem.physmem * (pagesize / 1024) /1024,
1506 ss->mem.freemem * (pagesize / 1024) /1024,
1507 ss->mem.buffermem * (pagesize / 1024) /1024,
1508 ss->mem.cachemem * (pagesize / 1024) /1024,
1509 ss->mem.cachedrt * (pagesize / 1024) /1024,
1510 ss->mem.slabmem * (pagesize / 1024) /1024,
1511 ss->mem.totswap * (pagesize / 1024) /1024,
1512 ss->mem.freeswap * (pagesize / 1024) /1024);
1513
1514 postprint(mbadness >= sbadness ? mbadness : sbadness);
1515
1516 return 1;
1517 }
1518
1519 /*
1520 ** swapping statistics
1521 */
1522 static void
1523 swaphead(int osvers, int osrel, int ossub)
1524 {
1525 printf("pagescan/s swapin/s swapout/s oomkill"
1526 " commitspc commitlim _swap_");
1527 }
1528
1529 static int
1530 swapline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1531 time_t deltasec, time_t deltatic, time_t hz,
1532 int osvers, int osrel, int ossub, char *tstamp,
1533 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1534 {
1535 unsigned int badness;
1536
1537 if (membadness)
1538 badness = (ss->mem.swouts / deltasec * pagbadness)
1539 * 100 / membadness;
1540 else
1541 badness = 0;
1542
1543 /*
1544 ** take care that this line is anyhow colored for
1545 ** 'almost critical' in case of swapouts > 1 per second
1546 */
1547 if (ss->mem.swouts / deltasec > 0 &&
1548 pagbadness && almostcrit && badness < almostcrit)
1549 badness = almostcrit;
1550
1551 if (ss->mem.commitlim && ss->mem.committed > ss->mem.commitlim)
1552 badness = 100; /* force colored output */
1553
1554 preprint(badness);
1555
1556 printf("%10.2lf %9.2lf %9.2lf %7lld %9lluM %9lluM",
1557 (double)ss->mem.pgscans / deltasec,
1558 (double)ss->mem.swins / deltasec,
1559 (double)ss->mem.swouts / deltasec,
1560 ss->mem.oomkills,
1561 ss->mem.committed * (pagesize / 1024) / 1024,
1562 ss->mem.commitlim * (pagesize / 1024) / 1024);
1563
1564 postprint(badness);
1565
1566 return 1;
1567 }
1568
1569 /*
1570 ** PSI statistics
1571 */
1572 static void
1573 psihead(int osvers, int osrel, int ossub)
1574 {
1575 printf("cpusome memsome memfull iosome iofull");
1576 }
1577
1578 static int
1579 psiline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1580 time_t deltasec, time_t deltatic, time_t hz,
1581 int osvers, int osrel, int ossub, char *tstamp,
1582 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1583 {
1584 // calculate pressure percentages for entire interval
1585 unsigned int csperc = ss->psi.cpusome.total/(deltatic*10000/hz);
1586 unsigned int msperc = ss->psi.memsome.total/(deltatic*10000/hz);
1587 unsigned int mfperc = ss->psi.memfull.total/(deltatic*10000/hz);
1588 unsigned int isperc = ss->psi.iosome.total /(deltatic*10000/hz);
1589 unsigned int ifperc = ss->psi.iofull.total /(deltatic*10000/hz);
1590 unsigned int badness = 0;
1591
1592 if (!ss->psi.present)
1593 {
1594 printf("no PSI stats available for this interval...\n");
1595 return 1;
1596 }
1597
1598 // correct percentages if needed
1599 if (csperc > 100)
1600 csperc = 100;
1601
1602 if (msperc > 100)
1603 msperc = 100;
1604
1605 if (mfperc > 100)
1606 mfperc = 100;
1607
1608 if (isperc > 100)
1609 isperc = 100;
1610
1611 if (ifperc > 100)
1612 ifperc = 100;
1613
1614 // consider a 'some' percentage > 0 as almost critical
1615 // (I/O full tends to increase rapidly as well)
1616 if (csperc || msperc || isperc || ifperc)
1617 badness = 80;
1618
1619 // consider a memory 'full' percentage > 0 as critical
1620 if (mfperc)
1621 badness = 100;
1622
1623 // show results
1624 preprint(badness);
1625
1626 printf(" %3u%% %3u%% %3u%% %3u%% %3u%%",
1627 csperc, msperc, mfperc, isperc, ifperc);
1628
1629 postprint(badness);
1630
1631 return 1;
1632 }
1633
1634
1635 /*
1636 ** disk statistics
1637 */
1638 static void
1639 lvmhead(int osvers, int osrel, int ossub)
1640 {
1641 printf("disk busy read/s KB/read "
1642 "writ/s KB/writ avque avserv _lvm_");
1643 }
1644
1645 static void
1646 mddhead(int osvers, int osrel, int ossub)
1647 {
1648 printf("disk busy read/s KB/read "
1649 "writ/s KB/writ avque avserv _mdd_");
1650 }
1651
1652 static void
1653 dskhead(int osvers, int osrel, int ossub)
1654 {
1655 printf("disk busy read/s KB/read "
1656 "writ/s KB/writ avque avserv _dsk_");
1657 }
1658
1659 static int
1660 gendskline(struct sstat *ss, char *tstamp, char selector)
1661 {
1662 static char firstcall = 1;
1663 register int i, nlines = 0, nunit = 0;
1664 count_t mstot, iotot;
1665 struct perdsk *dp;
1666 unsigned int badness;
1667
1668 switch (selector)
1669 {
1670 case 'l':
1671 dp = ss->dsk.lvm;
1672 nunit = ss->dsk.nlvm;
1673 break;
1674
1675 case 'm':
1676 dp = ss->dsk.mdd;
1677 nunit = ss->dsk.nmdd;
1678 break;
1679
1680 case 'd':
1681 dp = ss->dsk.dsk;
1682 nunit = ss->dsk.ndsk;
1683 break;
1684
1685 default:
1686 return 0;
1687 }
1688
1689 mstot = (ss->cpu.all.stime + ss->cpu.all.utime +
1690 ss->cpu.all.ntime + ss->cpu.all.itime +
1691 ss->cpu.all.wtime + ss->cpu.all.Itime +
1692 ss->cpu.all.Stime + ss->cpu.all.steal )
1693 * (count_t)1000 / hertz / ss->cpu.nrcpu;
1694
1695 for (i=0; i < nunit; i++, dp++)
1696 {
1697 char *pn;
1698 int len;
1699
1700 iotot = dp->nread + dp->nwrite +
1701 (dp->ndisc != -1 ? dp->ndisc : 0);
1702
1703 if (iotot == 0 && !firstcall && !allresources)
1704 continue; /* no activity on this disk */
1705
1706 /*
1707 ** disk was active during last interval; print info
1708 */
1709 if (nlines++)
1710 printf("%s ", tstamp);
1711
1712 if (dskbadness)
1713 badness = (dp->io_ms * 100.0 / mstot) * 100/dskbadness;
1714 else
1715 badness = 0;
1716
1717 preprint(badness);
1718
1719 if ( (len = strlen(dp->name)) > 14)
1720 pn = dp->name + len - 14;
1721 else
1722 pn = dp->name;
1723
1724 printf("%-14s %3.0lf%% %6.1lf %7.1lf %7.1lf %7.1lf "
1725 "%5.1lf %9.5lf ms",
1726 pn,
1727 mstot ? (double)dp->io_ms * 100.0 / mstot : 0.0,
1728 mstot ? (double)dp->nread * 1000.0 / mstot : 0.0,
1729 dp->nread ?
1730 (double)dp->nrsect / dp->nread / 2.0 : 0.0,
1731 mstot ? (double)dp->nwrite * 1000.0 / mstot : 0.0,
1732 dp->nwrite ?
1733 (double)dp->nwsect / dp->nwrite / 2.0 : 0.0,
1734 dp->io_ms ? (double)dp->avque / dp->io_ms : 0.0,
1735 iotot ? (double)dp->io_ms / iotot : 0.0);
1736
1737 postprint(badness);
1738 }
1739
1740 if (nlines == 0)
1741 {
1742 printf("\n");
1743 nlines++;
1744 }
1745
1746 firstcall = 0;
1747
1748 return nlines;
1749 }
1750
1751 static int
1752 lvmline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1753 time_t deltasec, time_t deltatic, time_t hz,
1754 int osvers, int osrel, int ossub, char *tstamp,
1755 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1756 {
1757 return gendskline(ss, tstamp, 'l');
1758 }
1759
1760 static int
1761 mddline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1762 time_t deltasec, time_t deltatic, time_t hz,
1763 int osvers, int osrel, int ossub, char *tstamp,
1764 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1765 {
1766 return gendskline(ss, tstamp, 'm');
1767 }
1768
1769 static int
1770 dskline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1771 time_t deltasec, time_t deltatic, time_t hz,
1772 int osvers, int osrel, int ossub, char *tstamp,
1773 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1774 {
1775 return gendskline(ss, tstamp, 'd');
1776 }
1777
1778 /*
1779 ** NFS client statistics
1780 */
1781 static void
1782 nfmhead(int osvers, int osrel, int ossub)
1783 {
1784 printf("mounted_device physread/s physwrit/s"
1785 " _nfm_");
1786 }
1787
1788 static int
1789 nfmline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1790 time_t deltasec, time_t deltatic, time_t hz,
1791 int osvers, int osrel, int ossub, char *tstamp,
1792 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1793 {
1794 static char firstcall = 1;
1795 register long i, nlines = 0;
1796 char *pn, state;
1797 int len;
1798
1799 for (i=0; i < ss->nfs.nfsmounts.nrmounts; i++) /* per NFS mount */
1800 {
1801 /*
1802 ** print for the first sample all mounts that
1803 ** are found; afterwards print only the mounts
1804 ** that were really active during the interval
1805 */
1806 if (firstcall ||
1807 allresources ||
1808 ss->nfs.nfsmounts.nfsmnt[i].age < deltasec ||
1809 ss->nfs.nfsmounts.nfsmnt[i].bytestotread ||
1810 ss->nfs.nfsmounts.nfsmnt[i].bytestotwrite )
1811 {
1812 if (nlines++)
1813 printf("%s ", tstamp);
1814
1815 if ( (len = strlen(ss->nfs.nfsmounts.nfsmnt[i].mountdev)) > 38)
1816 pn = ss->nfs.nfsmounts.nfsmnt[i].mountdev + len - 38;
1817 else
1818 pn = ss->nfs.nfsmounts.nfsmnt[i].mountdev;
1819
1820 if (ss->nfs.nfsmounts.nfsmnt[i].age < deltasec)
1821 state = 'M';
1822 else
1823 state = ' ';
1824
1825 printf("%-38s %10.3lfK %10.3lfK %c\n",
1826 pn,
1827 (double)ss->nfs.nfsmounts.nfsmnt[i].bytestotread /
1828 1024 / deltasec,
1829 (double)ss->nfs.nfsmounts.nfsmnt[i].bytestotwrite /
1830 1024 / deltasec,
1831 state);
1832 }
1833 }
1834
1835 if (nlines == 0)
1836 {
1837 printf("\n");
1838 nlines++;
1839 }
1840
1841 firstcall= 0;
1842 return nlines;
1843 }
1844
1845 static void
1846 nfchead(int osvers, int osrel, int ossub)
1847 {
1848 printf(" rpc/s rpcread/s rpcwrite/s retrans/s autrefresh/s "
1849 " _nfc_");
1850 }
1851
1852 static int
1853 nfcline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1854 time_t deltasec, time_t deltatic, time_t hz,
1855 int osvers, int osrel, int ossub, char *tstamp,
1856 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1857 {
1858 printf("%10.2lf %10.2lf %10.2lf %10.2lf %12.2lf\n",
1859 (double)ss->nfs.client.rpccnt / deltasec,
1860 (double)ss->nfs.client.rpcread / deltasec,
1861 (double)ss->nfs.client.rpcwrite / deltasec,
1862 (double)ss->nfs.client.rpcretrans / deltasec,
1863 (double)ss->nfs.client.rpcautrefresh / deltasec);
1864
1865 return 1;
1866 }
1867
1868 static void
1869 nfshead(int osvers, int osrel, int ossub)
1870 {
1871 printf(" rpc/s rpcread/s rpcwrite/s MBcr/s MBcw/s "
1872 "nettcp/s netudp/s _nfs_");
1873 }
1874
1875 static int
1876 nfsline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1877 time_t deltasec, time_t deltatic, time_t hz,
1878 int osvers, int osrel, int ossub, char *tstamp,
1879 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1880 {
1881 printf("%7.2lf %10.2lf %10.2lf %6.2lf %7.2lf %9.2lf %8.2lf\n",
1882 (double)ss->nfs.server.rpccnt / deltasec,
1883 (double)ss->nfs.server.rpcread / deltasec,
1884 (double)ss->nfs.server.rpcwrite / deltasec,
1885 (double)ss->nfs.server.nrbytes / 1024.0 / 1024.0 / deltasec,
1886 (double)ss->nfs.server.nwbytes / 1024.0 / 1024.0 / deltasec,
1887 (double)ss->nfs.server.nettcpcnt / deltasec,
1888 (double)ss->nfs.server.netudpcnt / deltasec);
1889
1890 return 1;
1891 }
1892
1893 /*
1894 ** network-interface statistics
1895 */
1896 static void
1897 ibhead(int osvers, int osrel, int ossub)
1898 {
1899 printf("controller port busy ipack/s opack/s "
1900 "igbps ogbps maxgbps lanes _ib_");
1901 }
1902
1903 static int
1904 ibline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1905 time_t deltasec, time_t deltatic, time_t hz,
1906 int osvers, int osrel, int ossub, char *tstamp,
1907 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1908 {
1909 static char firstcall = 1;
1910 register long i, nlines = 0;
1911 double busy;
1912 unsigned int badness;
1913
1914 for (i=0; i < ss->ifb.nrports; i++) /* per interface */
1915 {
1916 count_t ival, oval;
1917
1918 /*
1919 ** print for the first sample all ports that
1920 ** are found; afterwards print only the ports
1921 ** that were really active during the interval
1922 */
1923 if (!firstcall && !allresources &&
1924 !ss->ifb.ifb[i].rcvb && !ss->ifb.ifb[i].sndb)
1925 continue;
1926
1927 /*
1928 ** convert byte-transfers to bit-transfers (* 8)
1929 ** convert bit-transfers to gigabit-transfers (/ 1000000000)
1930 ** per second
1931 */
1932 ival = ss->ifb.ifb[i].rcvb*ss->ifb.ifb[i].lanes/125000000/deltasec;
1933 oval = ss->ifb.ifb[i].sndb*ss->ifb.ifb[i].lanes/125000000/deltasec;
1934
1935 /*
1936 ** calculate busy-percentage for port
1937 */
1938 busy = (ival > oval ? ival*100 : oval*100)/ss->ifb.ifb[i].rate;
1939
1940 if (nlines++)
1941 printf("%s ", tstamp);
1942
1943 if (netbadness)
1944 badness = busy * 100 / netbadness;
1945 else
1946 badness = 0;
1947
1948 preprint(badness);
1949
1950 printf("%-10s %4hd %4.0f%% %7.1lf %7.1lf %5lld %5lld %7lld %5d",
1951 ss->ifb.ifb[i].ibname,
1952 ss->ifb.ifb[i].portnr,
1953 busy,
1954 (double)ss->ifb.ifb[i].rcvp / deltasec,
1955 (double)ss->ifb.ifb[i].sndp / deltasec,
1956 ival, oval,
1957 ss->ifb.ifb[i].rate / 1000,
1958 ss->ifb.ifb[i].lanes);
1959
1960 postprint(badness);
1961 }
1962
1963 if (nlines == 0)
1964 {
1965 printf("\n");
1966 nlines++;
1967 }
1968
1969 firstcall = 0;
1970 return nlines;
1971 }
1972
1973
1974 /*
1975 ** network-interface statistics
1976 */
1977 static void
1978 ifhead(int osvers, int osrel, int ossub)
1979 {
1980 printf("interf busy ipack/s opack/s iKbyte/s oKbyte/s "
1981 "imbps ombps maxmbps_if_");
1982 }
1983
1984 static int
1985 ifline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
1986 time_t deltasec, time_t deltatic, time_t hz,
1987 int osvers, int osrel, int ossub, char *tstamp,
1988 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
1989 {
1990 static char firstcall = 1;
1991 register long i, nlines = 0;
1992 double busy;
1993 char busyval[16], dupval;
1994 unsigned int badness;
1995 char *pn;
1996 int len;
1997
1998 for (i=0; i < ss->intf.nrintf; i++) /* per interface */
1999 {
2000 count_t ival, oval;
2001
2002 /*
2003 ** print for the first sample all interfaces which
2004 ** are found; afterwards print only the interfaces
2005 ** which were really active during the interval
2006 */
2007 if (!firstcall && !allresources &&
2008 !ss->intf.intf[i].rpack && !ss->intf.intf[i].spack)
2009 continue;
2010
2011 /*
2012 ** convert byte-transfers to bit-transfers (* 8)
2013 ** convert bit-transfers to megabit-transfers (/ 1000000)
2014 ** per second
2015 */
2016 ival = ss->intf.intf[i].rbyte/125000/deltasec;
2017 oval = ss->intf.intf[i].sbyte/125000/deltasec;
2018
2019 /*
2020 ** calculate busy-percentage for interface
2021 */
2022 if (ss->intf.intf[i].speed) /* speed known? */
2023 {
2024 if (ss->intf.intf[i].duplex)
2025 busy = (ival > oval ? ival*100 : oval*100) /
2026 ss->intf.intf[i].speed;
2027 else
2028 busy = (ival + oval) * 100 /
2029 ss->intf.intf[i].speed;
2030
2031 // especially with wireless, the speed might have
2032 // dropped temporarily to a very low value (snapshot)
2033 // it might be better to take the speed of the
2034 // previous sample
2035 if (busy > 100 && ss->intf.intf[i].speed <
2036 ss->intf.intf[i].speedp )
2037 {
2038 ss->intf.intf[i].speed =
2039 ss->intf.intf[i].speedp;
2040
2041 if (ss->intf.intf[i].duplex)
2042 busy = (ival > oval ?
2043 ival*100 : oval*100) /
2044 ss->intf.intf[i].speed;
2045 else
2046 busy = (ival + oval) * 100 /
2047 ss->intf.intf[i].speed;
2048 }
2049
2050 snprintf(busyval, sizeof busyval,
2051 "%3.0lf%%", busy);
2052 }
2053 else
2054 {
2055 strcpy(busyval, "?"); /* speed unknown */
2056 busy = 0;
2057 }
2058
2059 if (nlines++)
2060 printf("%s ", tstamp);
2061
2062 if (ss->intf.intf[i].speed)
2063 {
2064 if (ss->intf.intf[i].duplex)
2065 dupval = 'f';
2066 else
2067 dupval = 'h';
2068 }
2069 else
2070 {
2071 dupval = ' ';
2072 }
2073
2074 if (netbadness)
2075 badness = busy * 100 / netbadness;
2076 else
2077 badness = 0;
2078
2079 if ( (len = strlen(ss->intf.intf[i].name)) > 6)
2080 pn = ss->intf.intf[i].name + len - 6;
2081 else
2082 pn = ss->intf.intf[i].name;
2083
2084 preprint(badness);
2085
2086 printf("%-6s %4s %7.1lf %7.1lf %8.0lf %8.0lf "
2087 "%5lld %5lld %7ld %c",
2088 pn, busyval,
2089 (double)ss->intf.intf[i].rpack / deltasec,
2090 (double)ss->intf.intf[i].spack / deltasec,
2091 (double)ss->intf.intf[i].rbyte / 1024 / deltasec,
2092 (double)ss->intf.intf[i].sbyte / 1024 / deltasec,
2093 ival, oval,
2094 ss->intf.intf[i].speed, dupval);
2095
2096 postprint(badness);
2097 }
2098
2099 if (nlines == 0)
2100 {
2101 printf("\n");
2102 nlines++;
2103 }
2104
2105 firstcall = 0;
2106 return nlines;
2107 }
2108
2109 static void
2110 IFhead(int osvers, int osrel, int ossub)
2111 {
2112 printf("interf ierr/s oerr/s coll/s idrop/s odrop/s "
2113 "iframe/s ocarrier/s _if_");
2114 }
2115
2116 static int
2117 IFline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2118 time_t deltasec, time_t deltatic, time_t hz,
2119 int osvers, int osrel, int ossub, char *tstamp,
2120 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2121 {
2122 static char firstcall = 1;
2123 register long i, nlines = 0;
2124 char *pn;
2125 int len;
2126
2127 for (i=0; i < ss->intf.nrintf; i++) /* per interface */
2128 {
2129 /*
2130 ** print for the first sample all interfaces which
2131 ** are found; afterwards print only the interfaces
2132 ** which were really active during the interval
2133 */
2134 if (!firstcall && !allresources &&
2135 !ss->intf.intf[i].rpack && !ss->intf.intf[i].spack)
2136 continue;
2137
2138 if (nlines++)
2139 printf("%s ", tstamp);
2140
2141 if ( (len = strlen(ss->intf.intf[i].name)) > 6)
2142 pn = ss->intf.intf[i].name + len - 6;
2143 else
2144 pn = ss->intf.intf[i].name;
2145
2146 printf("%-6s %6.2lf %6.2lf %6.2lf %7.2lf %7.2lf "
2147 "%8.2lf %10.2lf\n",
2148 pn,
2149 (double)ss->intf.intf[i].rerrs / deltasec,
2150 (double)ss->intf.intf[i].serrs / deltasec,
2151 (double)ss->intf.intf[i].scollis / deltasec,
2152 (double)ss->intf.intf[i].rdrop / deltasec,
2153 (double)ss->intf.intf[i].sdrop / deltasec,
2154 (double)ss->intf.intf[i].rframe / deltasec,
2155 (double)ss->intf.intf[i].scarrier / deltasec);
2156 }
2157
2158 if (nlines == 0)
2159 {
2160 printf("\n");
2161 nlines++;
2162 }
2163
2164 firstcall= 0;
2165 return nlines;
2166 }
2167
2168 /*
2169 ** IP version 4 statistics
2170 */
2171 static void
2172 ipv4head(int osvers, int osrel, int ossub)
2173 {
2174 printf("inrecv/s outreq/s indeliver/s forward/s "
2175 "reasmok/s fragcreat/s _ipv4_");
2176 }
2177
2178 static int
2179 ipv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2180 time_t deltasec, time_t deltatic, time_t hz,
2181 int osvers, int osrel, int ossub, char *tstamp,
2182 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2183 {
2184 printf("%8.1lf %8.1lf %11.1lf %9.1lf %9.1lf %11.1lf\n",
2185 (double)ss->net.ipv4.InReceives / deltasec,
2186 (double)ss->net.ipv4.OutRequests / deltasec,
2187 (double)ss->net.ipv4.InDelivers / deltasec,
2188 (double)ss->net.ipv4.Forwarding / deltasec,
2189 (double)ss->net.ipv4.ReasmOKs / deltasec,
2190 (double)ss->net.ipv4.FragCreates / deltasec);
2191 return 1;
2192 }
2193
2194 static void
2195 IPv4head(int osvers, int osrel, int ossub)
2196 {
2197 printf("in: dsc/s hder/s ader/s unkp/s ratim/s rfail/s "
2198 "out: dsc/s nrt/s_ipv4_");
2199 }
2200
2201 static int
2202 IPv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2203 time_t deltasec, time_t deltatic, time_t hz,
2204 int osvers, int osrel, int ossub, char *tstamp,
2205 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2206 {
2207 printf(" %5.1lf %6.1lf %6.1lf %6.1lf %7.1lf %7.1lf "
2208 " %5.1lf %5.1lf\n",
2209 (double)ss->net.ipv4.InDiscards / deltasec,
2210 (double)ss->net.ipv4.InHdrErrors / deltasec,
2211 (double)ss->net.ipv4.InAddrErrors / deltasec,
2212 (double)ss->net.ipv4.InUnknownProtos / deltasec,
2213 (double)ss->net.ipv4.ReasmTimeout / deltasec,
2214 (double)ss->net.ipv4.ReasmFails / deltasec,
2215 (double)ss->net.ipv4.OutDiscards / deltasec,
2216 (double)ss->net.ipv4.OutNoRoutes / deltasec);
2217 return 1;
2218 }
2219
2220 /*
2221 ** ICMP version 4 statistics
2222 */
2223 static void
2224 icmpv4head(int osvers, int osrel, int ossub)
2225 {
2226 printf("intot/s outtot/s inecho/s inerep/s "
2227 "otecho/s oterep/s _icmpv4_" );
2228 }
2229
2230 static int
2231 icmpv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2232 time_t deltasec, time_t deltatic, time_t hz,
2233 int osvers, int osrel, int ossub, char *tstamp,
2234 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2235 {
2236 printf("%7.1lf %8.1lf %8.2lf %8.2lf %8.2lf %8.2lf\n",
2237 (double)ss->net.icmpv4.InMsgs / deltasec,
2238 (double)ss->net.icmpv4.OutMsgs / deltasec,
2239 (double)ss->net.icmpv4.InEchos / deltasec,
2240 (double)ss->net.icmpv4.OutEchos / deltasec,
2241 (double)ss->net.icmpv4.InEchoReps / deltasec,
2242 (double)ss->net.icmpv4.OutEchoReps / deltasec);
2243 return 1;
2244 }
2245
2246 static void
2247 ICMPv4head(int osvers, int osrel, int ossub)
2248 {
2249 printf("ierr/s isq/s ird/s idu/s ite/s "
2250 "oerr/s osq/s ord/s odu/s ote/s_icmpv4_");
2251 }
2252
2253 static int
2254 ICMPv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2255 time_t deltasec, time_t deltatic, time_t hz,
2256 int osvers, int osrel, int ossub, char *tstamp,
2257 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2258 {
2259 printf("%6.2lf %5.2lf %5.2lf %5.2lf %5.2lf "
2260 "%6.2lf %5.2lf %5.2lf %5.2lf %5.2lf\n",
2261 (double)ss->net.icmpv4.InErrors / deltasec,
2262 (double)ss->net.icmpv4.InSrcQuenchs / deltasec,
2263 (double)ss->net.icmpv4.InRedirects / deltasec,
2264 (double)ss->net.icmpv4.InDestUnreachs / deltasec,
2265 (double)ss->net.icmpv4.InTimeExcds / deltasec,
2266 (double)ss->net.icmpv4.OutErrors / deltasec,
2267 (double)ss->net.icmpv4.OutSrcQuenchs / deltasec,
2268 (double)ss->net.icmpv4.OutRedirects / deltasec,
2269 (double)ss->net.icmpv4.OutDestUnreachs / deltasec,
2270 (double)ss->net.icmpv4.OutTimeExcds / deltasec);
2271 return 1;
2272 }
2273
2274 /*
2275 ** UDP version 4 statistics
2276 */
2277 static void
2278 udpv4head(int osvers, int osrel, int ossub)
2279 {
2280 printf("indgram/s outdgram/s inerr/s noport/s "
2281 " _udpv4_");
2282 }
2283
2284 static int
2285 udpv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2286 time_t deltasec, time_t deltatic, time_t hz,
2287 int osvers, int osrel, int ossub, char *tstamp,
2288 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2289 {
2290 printf("%9.1lf %10.1lf %7.2lf %9.2lf\n",
2291 (double)ss->net.udpv4.InDatagrams / deltasec,
2292 (double)ss->net.udpv4.OutDatagrams / deltasec,
2293 (double)ss->net.udpv4.InErrors / deltasec,
2294 (double)ss->net.udpv4.NoPorts / deltasec);
2295 return 1;
2296 }
2297
2298 /*
2299 ** IP version 6 statistics
2300 */
2301 static void
2302 ipv6head(int osvers, int osrel, int ossub)
2303 {
2304 printf("inrecv/s outreq/s inmc/s outmc/s indeliv/s "
2305 "reasmok/s fragcre/s _ipv6_");
2306 }
2307
2308 static int
2309 ipv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2310 time_t deltasec, time_t deltatic, time_t hz,
2311 int osvers, int osrel, int ossub, char *tstamp,
2312 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2313 {
2314 printf("%8.1lf %8.1lf %6.1lf %7.1lf %9.1lf %9.1lf %9.1lf\n",
2315 (double)ss->net.ipv6.Ip6InReceives / deltasec,
2316 (double)ss->net.ipv6.Ip6OutRequests / deltasec,
2317 (double)ss->net.ipv6.Ip6InMcastPkts / deltasec,
2318 (double)ss->net.ipv6.Ip6OutMcastPkts / deltasec,
2319 (double)ss->net.ipv6.Ip6InDelivers / deltasec,
2320 (double)ss->net.ipv6.Ip6ReasmOKs / deltasec,
2321 (double)ss->net.ipv6.Ip6FragCreates / deltasec);
2322 return 1;
2323 }
2324
2325 static void
2326 IPv6head(int osvers, int osrel, int ossub)
2327 {
2328 printf("in: dsc/s hder/s ader/s unkp/s ratim/s rfail/s "
2329 "out: dsc/s nrt/s_ipv6_");
2330 }
2331
2332 static int
2333 IPv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2334 time_t deltasec, time_t deltatic, time_t hz,
2335 int osvers, int osrel, int ossub, char *tstamp,
2336 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2337 {
2338 printf(" %5.1lf %6.1lf %6.1lf %6.1lf %7.1lf %7.1lf "
2339 " %5.1lf %5.1lf\n",
2340 (double)ss->net.ipv6.Ip6InDiscards / deltasec,
2341 (double)ss->net.ipv6.Ip6InHdrErrors / deltasec,
2342 (double)ss->net.ipv6.Ip6InAddrErrors / deltasec,
2343 (double)ss->net.ipv6.Ip6InUnknownProtos / deltasec,
2344 (double)ss->net.ipv6.Ip6ReasmTimeout / deltasec,
2345 (double)ss->net.ipv6.Ip6ReasmFails / deltasec,
2346 (double)ss->net.ipv6.Ip6OutDiscards / deltasec,
2347 (double)ss->net.ipv6.Ip6OutNoRoutes / deltasec);
2348 return 1;
2349 }
2350
2351 /*
2352 ** ICMP version 6 statistics
2353 */
2354 static void
2355 icmpv6head(int osvers, int osrel, int ossub)
2356 {
2357 printf("intot/s outtot/s inerr/s innsol/s innadv/s "
2358 "otnsol/s otnadv/s _icmp6_" );
2359 }
2360
2361 static int
2362 icmpv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2363 time_t deltasec, time_t deltatic, time_t hz,
2364 int osvers, int osrel, int ossub, char *tstamp,
2365 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2366 {
2367 printf("%7.1lf %8.1lf %7.2lf %8.2lf %8.2lf %8.2lf %8.2lf\n",
2368 (double)ss->net.icmpv6.Icmp6InMsgs / deltasec,
2369 (double)ss->net.icmpv6.Icmp6OutMsgs / deltasec,
2370 (double)ss->net.icmpv6.Icmp6InErrors / deltasec,
2371 (double)ss->net.icmpv6.Icmp6InNeighborSolicits / deltasec,
2372 (double)ss->net.icmpv6.Icmp6InNeighborAdvertisements/ deltasec,
2373 (double)ss->net.icmpv6.Icmp6OutNeighborSolicits / deltasec,
2374 (double)ss->net.icmpv6.Icmp6OutNeighborAdvertisements
2375 /deltasec);
2376 return 1;
2377 }
2378
2379 static void
2380 ICMPv6head(int osvers, int osrel, int ossub)
2381 {
2382 printf("iecho/s ierep/s oerep/s idu/s odu/s ird/s ord/s ite/s "
2383 "ote/s _icmpv6_");
2384 }
2385
2386 static int
2387 ICMPv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2388 time_t deltasec, time_t deltatic, time_t hz,
2389 int osvers, int osrel, int ossub, char *tstamp,
2390 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2391 {
2392 printf("%7.2lf %7.2lf %7.2lf %5.2lf %5.2lf "
2393 "%5.2lf %5.2lf %5.2lf %5.2lf\n",
2394 (double)ss->net.icmpv6.Icmp6InEchos / deltasec,
2395 (double)ss->net.icmpv6.Icmp6InEchoReplies / deltasec,
2396 (double)ss->net.icmpv6.Icmp6OutEchoReplies / deltasec,
2397 (double)ss->net.icmpv6.Icmp6InDestUnreachs / deltasec,
2398 (double)ss->net.icmpv6.Icmp6OutDestUnreachs / deltasec,
2399 (double)ss->net.icmpv6.Icmp6InRedirects / deltasec,
2400 (double)ss->net.icmpv6.Icmp6OutRedirects / deltasec,
2401 (double)ss->net.icmpv6.Icmp6InTimeExcds / deltasec,
2402 (double)ss->net.icmpv6.Icmp6OutTimeExcds / deltasec);
2403 return 1;
2404 }
2405
2406 /*
2407 ** UDP version 6 statistics
2408 */
2409 static void
2410 udpv6head(int osvers, int osrel, int ossub)
2411 {
2412 printf("indgram/s outdgram/s inerr/s noport/s "
2413 " _udpv6_");
2414 }
2415
2416 static int
2417 udpv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2418 time_t deltasec, time_t deltatic, time_t hz,
2419 int osvers, int osrel, int ossub, char *tstamp,
2420 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2421 {
2422 printf("%9.1lf %10.1lf %7.2lf %9.2lf\n",
2423 (double)ss->net.udpv6.Udp6InDatagrams / deltasec,
2424 (double)ss->net.udpv6.Udp6OutDatagrams / deltasec,
2425 (double)ss->net.udpv6.Udp6InErrors / deltasec,
2426 (double)ss->net.udpv6.Udp6NoPorts / deltasec);
2427 return 1;
2428 }
2429
2430 /*
2431 ** TCP statistics
2432 */
2433 static void
2434 tcphead(int osvers, int osrel, int ossub)
2435 {
2436 printf("insegs/s outsegs/s actopen/s pasopen/s "
2437 "nowopen _tcp_");
2438 }
2439
2440 static int
2441 tcpline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2442 time_t deltasec, time_t deltatic, time_t hz,
2443 int osvers, int osrel, int ossub, char *tstamp,
2444 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2445 {
2446 printf("%8.1lf %9.1lf %9.1lf %9.1lf %7lld\n",
2447 (double)ss->net.tcp.InSegs / deltasec,
2448 (double)ss->net.tcp.OutSegs / deltasec,
2449 (double)ss->net.tcp.ActiveOpens / deltasec,
2450 (double)ss->net.tcp.PassiveOpens / deltasec,
2451 ss->net.tcp.CurrEstab);
2452 return 1;
2453 }
2454
2455 static void
2456 TCPhead(int osvers, int osrel, int ossub)
2457 {
2458 printf("inerr/s retrans/s attfail/s "
2459 "estabreset/s outreset/s _tcp_");
2460 }
2461
2462 static int
2463 TCPline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2464 time_t deltasec, time_t deltatic, time_t hz,
2465 int osvers, int osrel, int ossub, char *tstamp,
2466 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2467 {
2468 printf("%7.1lf %9.1lf %9.1lf %12.1lf %10.1lf\n",
2469 (double)ss->net.tcp.InErrs / deltasec,
2470 (double)ss->net.tcp.RetransSegs / deltasec,
2471 (double)ss->net.tcp.AttemptFails / deltasec,
2472 (double)ss->net.tcp.EstabResets / deltasec,
2473 (double)ss->net.tcp.OutRsts / deltasec);
2474 return 1;
2475 }
2476
2477 #if HTTPSTATS
2478 static void
2479 httphead(int osvers, int osrel, int ossub)
2480 {
2481 printf("requests/s Kbytes/s bytes/req "
2482 "idleworkers busyworkers _http_");
2483 }
2484
2485 static int
2486 httpline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2487 time_t deltasec, time_t deltatic, time_t hz,
2488 int osvers, int osrel, int ossub, char *tstamp,
2489 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2490 {
2491 printf("%10.2lf %8.2lf %9.2lf %11d %11d\n",
2492 (double)ss->www.accesses / deltasec,
2493 (double)ss->www.totkbytes / deltasec,
2494 ss->www.accesses ?
2495 (double)ss->www.totkbytes*1024/ss->www.accesses : 0,
2496 ss->www.iworkers,
2497 ss->www.bworkers);
2498
2499 return 1;
2500 }
2501 #endif
2502
2503 /*
2504 ** per-process statistics: top-3 processor consumers
2505 */
2506 static void
2507 topchead(int osvers, int osrel, int ossub)
2508 {
2509 printf(" pid command cpu%% | pid command cpu%% | "
2510 " pid command cpu%%_top3_");
2511 }
2512
2513 static int
2514 topcline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2515 time_t deltasec, time_t deltatic, time_t hz,
2516 int osvers, int osrel, int ossub, char *tstamp,
2517 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2518 {
2519 count_t availcpu;
2520
2521 if (!ts)
2522 {
2523 printf("report not available.....\n");
2524 return 0;
2525 }
2526
2527 /*
2528 ** sort process list in cpu order
2529 */
2530 qsort(ps, nactproc, sizeof(struct tstat *), compcpu);
2531
2532 availcpu = ss->cpu.all.stime + ss->cpu.all.utime +
2533 ss->cpu.all.ntime + ss->cpu.all.itime +
2534 ss->cpu.all.wtime + ss->cpu.all.Itime +
2535 ss->cpu.all.Stime + ss->cpu.all.steal;
2536
2537 availcpu /= ss->cpu.nrcpu;
2538
2539 if (availcpu == 0)
2540 availcpu = 1; /* avoid divide-by-zero */
2541
2542 if (nactproc >= 1 && (ps[0])->cpu.stime + (ps[0])->cpu.utime > 0)
2543 printf("%5d %-8.8s %3.0lf%% | ",
2544 (ps[0])->gen.pid, (ps[0])->gen.name,
2545 (double)((ps[0])->cpu.stime + (ps[0])->cpu.utime)*100.0/availcpu);
2546 else
2547 printf("%19s | ", " ");
2548
2549 if (nactproc >= 2 && (ps[1])->cpu.stime + (ps[1])->cpu.utime > 0)
2550 printf("%5d %-8.8s %3.0lf%% | ",
2551 (ps[1])->gen.pid, (ps[1])->gen.name,
2552 (double)((ps[1])->cpu.stime + (ps[1])->cpu.utime)*100.0/availcpu);
2553 else
2554 printf("%19s | ", " ");
2555
2556 if (nactproc >= 3 && (ps[2])->cpu.stime + (ps[2])->cpu.utime > 0)
2557 printf("%5d %-8.8s %3.0lf%%\n",
2558 (ps[2])->gen.pid, (ps[2])->gen.name,
2559 (double)((ps[2])->cpu.stime + (ps[2])->cpu.utime)*100.0/availcpu);
2560 else
2561 printf("%19s\n", " ");
2562
2563
2564 return 1;
2565 }
2566
2567 /*
2568 ** per-process statistics: top-3 memory consumers
2569 */
2570 static void
2571 topmhead(int osvers, int osrel, int ossub)
2572 {
2573 printf(" pid command mem%% | pid command mem%% | "
2574 " pid command mem%%_top3_");
2575 }
2576
2577 static int
2578 topmline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2579 time_t deltasec, time_t deltatic, time_t hz,
2580 int osvers, int osrel, int ossub, char *tstamp,
2581 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2582 {
2583 count_t availmem;
2584
2585 if (!ts)
2586 {
2587 printf("report not available.....\n");
2588 return 0;
2589 }
2590
2591 /*
2592 ** sort process list in memory order
2593 */
2594 qsort(ps, nactproc, sizeof(struct tstat *), compmem);
2595
2596 availmem = ss->mem.physmem * pagesize/1024;
2597
2598 if (nactproc >= 1)
2599 printf("%5d %-8.8s %3.0lf%% | ",
2600 (ps[0])->gen.pid, (ps[0])->gen.name,
2601 (double)(ps[0])->mem.rmem * 100.0 / availmem);
2602 else
2603 printf("%19s | ", " ");
2604
2605 if (nactproc >= 2)
2606 printf("%5d %-8.8s %3.0lf%% | ",
2607 (ps[1])->gen.pid, (ps[1])->gen.name,
2608 (double)(ps[1])->mem.rmem * 100.0 / availmem);
2609 else
2610 printf("%19s | ", " ");
2611
2612 if (nactproc >= 3)
2613 printf("%5d %-8.8s %3.0lf%%\n",
2614 (ps[2])->gen.pid, (ps[2])->gen.name,
2615 (double)(ps[2])->mem.rmem * 100.0 / availmem);
2616 else
2617 printf("%19s\n", " ");
2618
2619
2620 return 1;
2621 }
2622
2623 /*
2624 ** per-process statistics: top-3 disk consumers
2625 */
2626 static void
2627 topdhead(int osvers, int osrel, int ossub)
2628 {
2629 printf(" pid command dsk%% | pid command dsk%% | "
2630 " pid command dsk%%_top3_");
2631 }
2632
2633 static int
2634 topdline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2635 time_t deltasec, time_t deltatic, time_t hz,
2636 int osvers, int osrel, int ossub, char *tstamp,
2637 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2638 {
2639 int i;
2640 count_t availdsk;
2641
2642 if (!ts)
2643 {
2644 printf("report not available.....\n");
2645 return 0;
2646 }
2647
2648 if ( !(supportflags & IOSTAT) )
2649 {
2650 printf("no per-process disk counters available.....\n");
2651 return 0;
2652 }
2653
2654 /*
2655 ** determine total disk accesses for all processes
2656 */
2657 for (i=0, availdsk=0; i < nactproc; i++)
2658 {
2659 availdsk += (ps[i])->dsk.rio + (ps[i])->dsk.wio;
2660 }
2661
2662 if (availdsk == 0)
2663 availdsk = 1;
2664
2665 /*
2666 ** sort process list in disk order
2667 */
2668 qsort(ps, nactproc, sizeof(struct tstat *), compdsk);
2669
2670 if (nactproc >= 1 && (ps[0])->dsk.rio + (ps[0])->dsk.wio > 0)
2671 printf("%5d %-8.8s %3.0lf%% | ",
2672 (ps[0])->gen.pid, (ps[0])->gen.name,
2673 (double)((ps[0])->dsk.rio+(ps[0])->dsk.wio) *100.0/availdsk);
2674 else
2675 printf("%19s | ", " ");
2676
2677 if (nactproc >= 2 && (ps[1])->dsk.rio + (ps[1])->dsk.wio > 0)
2678 printf("%5d %-8.8s %3.0lf%% | ",
2679 (ps[1])->gen.pid, (ps[1])->gen.name,
2680 (double)((ps[1])->dsk.rio+(ps[1])->dsk.wio) *100.0/availdsk);
2681 else
2682 printf("%19s | ", " ");
2683
2684 if (nactproc >= 3 && (ps[2])->dsk.rio + (ps[2])->dsk.wio > 0)
2685 printf("%5d %-8.8s %3.0lf%%\n",
2686 (ps[2])->gen.pid, (ps[2])->gen.name,
2687 (double)((ps[2])->dsk.rio+(ps[2])->dsk.wio) *100.0/availdsk);
2688 else
2689 printf("%19s\n", " ");
2690
2691
2692 return 1;
2693 }
2694
2695 /*
2696 ** per-process statistics: top-3 network consumers
2697 */
2698 static void
2699 topnhead(int osvers, int osrel, int ossub)
2700 {
2701 printf(" pid command net%% | pid command net%% | "
2702 " pid command net%%_top3_");
2703 }
2704
2705 static int
2706 topnline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc,
2707 time_t deltasec, time_t deltatic, time_t hz,
2708 int osvers, int osrel, int ossub, char *tstamp,
2709 int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie)
2710 {
2711 int i;
2712 count_t availnet;
2713 count_t totbytes;
2714
2715 if (!ts)
2716 {
2717 printf("report not available.....\n");
2718 return 0;
2719 }
2720
2721 if ( !(supportflags & NETATOP) )
2722 {
2723 printf("no per-process network counters available.....\n");
2724 return 0;
2725 }
2726
2727 /*
2728 ** determine total network accesses for all processes
2729 */
2730 for (i=0, availnet=0; i < nactproc; i++)
2731 {
2732 availnet += (*(ps+i))->net.tcpssz + (*(ps+i))->net.tcprsz +
2733 (*(ps+i))->net.udpssz + (*(ps+i))->net.udprsz;
2734 }
2735
2736 if (availnet == 0)
2737 availnet = 1;
2738
2739 /*
2740 ** sort process list in network order
2741 */
2742 qsort(ps, nactproc, sizeof(struct tstat *), compnet);
2743
2744 if (nactproc >= 1)
2745 {
2746 totbytes = (ps[0])->net.tcpssz + (ps[0])->net.tcprsz +
2747 (ps[0])->net.udpssz + (ps[0])->net.udprsz;
2748
2749 if (totbytes > 0)
2750 printf("%5d %-8.8s %3.0lf%% | ",
2751 (ps[0])->gen.pid, (ps[0])->gen.name,
2752 (double)totbytes * 100.0 / availnet);
2753 else
2754 printf("%19s | ", " ");
2755 }
2756 else
2757 printf("%19s | ", " ");
2758
2759 if (nactproc >= 2)
2760 {
2761 totbytes = (ps[1])->net.tcpssz + (ps[1])->net.tcprsz +
2762 (ps[1])->net.udpssz + (ps[1])->net.udprsz;
2763
2764 if (totbytes > 0)
2765 printf("%5d %-8.8s %3.0lf%% | ",
2766 (ps[1])->gen.pid, (ps[1])->gen.name,
2767 (double)totbytes * 100.0 / availnet);
2768 else
2769 printf("%19s | ", " ");
2770 }
2771 else
2772 printf("%19s | ", " ");
2773
2774 if (nactproc >= 3)
2775 {
2776 totbytes = (ps[2])->net.tcpssz + (ps[2])->net.tcprsz +
2777 (ps[2])->net.udpssz + (ps[2])->net.udprsz;
2778
2779 if (totbytes > 0)
2780 printf("%5d %-8.8s %3.0lf%%\n",
2781 (ps[2])->gen.pid, (ps[2])->gen.name,
2782 (double)totbytes * 100.0 / availnet);
2783 else
2784 printf("%19s\n", " ");
2785 }
2786 else
2787 printf("%19s\n", " ");
2788
2789
2790 return 1;
2791 }
2792
2793 /*********************************************************************/
2794 /* Function definition table. */
2795 /* */
2796 /* The layout of this table is as follows: */
2797 /* Column 1: */
2798 /* Boolean which indicates if the specified function is */
2799 /* active during a run of 'atopsar'. When started, */
2800 /* this boolean will be defined 'true' for all entries for */
2801 /* which the command-line flag has been specified. Initially */
2802 /* this column should contain 0 (false), unless this function */
2803 /* is always required. */
2804 /* If no flags are specified for 'atopsar', the first entry */
2805 /* in this table is defined active (default flag). */
2806 /* */
2807 /* Column 2: */
2808 /* Categories of counters used by this function. */
2809 /* c = cpu counters, m = memory counters, */
2810 /* d = disk counters, n = network counters */
2811 /* */
2812 /* Column 3: */
2813 /* Flag which can be used as command-line argument to */
2814 /* select the function defined in this table-entry. Be sure */
2815 /* that a unique character is choosen. */
2816 /* Notice that certain flags are reserved! */
2817 /* */
2818 /* Column 4: */
2819 /* Entry-point of the 'printhead' function. */
2820 /* */
2821 /* Column 5: */
2822 /* Entry-point of the 'printline' function. */
2823 /* */
2824 /* Column 6: */
2825 /* Information about the statistics shown by the function */
2826 /* specified by the table-entry. This text is printed as */
2827 /* command-usage. */
2828 /*********************************************************************/
2829 struct pridef pridef[] =
2830 {
2831 {0, "c", 'c', cpuhead, cpuline, "cpu utilization", },
2832 {0, "c", 'p', prochead, procline, "process(or) load", },
2833 {0, "c", 'P', taskhead, taskline, "processes & threads", },
2834 {0, "c", 'g', gpuhead, gpuline, "gpu utilization", },
2835 {0, "m", 'm', memhead, memline, "memory & swapspace", },
2836 {0, "m", 's', swaphead, swapline, "swap rate", },
2837 {0, "cmd",'B', psihead, psiline, "pressure stall info (PSI)",},
2838 {0, "cd", 'l', lvmhead, lvmline, "logical volume activity", },
2839 {0, "cd", 'f', mddhead, mddline, "multiple device activity",},
2840 {0, "cd", 'd', dskhead, dskline, "disk activity", },
2841 {0, "n", 'h', ibhead, ibline, "infiniband utilization", },
2842 {0, "n", 'n', nfmhead, nfmline, "NFS client mounts", },
2843 {0, "n", 'j', nfchead, nfcline, "NFS client activity", },
2844 {0, "n", 'J', nfshead, nfsline, "NFS server activity", },
2845 {0, "n", 'i', ifhead, ifline, "net-interf (general)", },
2846 {0, "n", 'I', IFhead, IFline, "net-interf (errors)", },
2847 {0, "n", 'w', ipv4head, ipv4line, "ip v4 (general)", },
2848 {0, "n", 'W', IPv4head, IPv4line, "ip v4 (errors)", },
2849 {0, "n", 'y', icmpv4head, icmpv4line, "icmp v4 (general)", },
2850 {0, "n", 'Y', ICMPv4head, ICMPv4line, "icmp v4 (per type)", },
2851 {0, "n", 'u', udpv4head, udpv4line, "udp v4", },
2852 {0, "n", 'z', ipv6head, ipv6line, "ip v6 (general)", },
2853 {0, "n", 'Z', IPv6head, IPv6line, "ip v6 (errors)", },
2854 {0, "n", 'k', icmpv6head, icmpv6line, "icmp v6 (general)", },
2855 {0, "n", 'K', ICMPv6head, ICMPv6line, "icmp v6 (per type)", },
2856 {0, "n", 'U', udpv6head, udpv6line, "udp v6", },
2857 {0, "n", 't', tcphead, tcpline, "tcp (general)", },
2858 {0, "n", 'T', TCPhead, TCPline, "tcp (errors)", },
2859 #if HTTPSTATS
2860 {0, "n", 'o', httphead, httpline, "HTTP activity", },
2861 #endif
2862 {0, "", 'O', topchead, topcline, "top-3 processes cpu", },
2863 {0, "", 'G', topmhead, topmline, "top-3 processes memory", },
2864 {0, "", 'D', topdhead, topdline, "top-3 processes disk", },
2865 {0, "", 'N', topnhead, topnline, "top-3 processes network",},
2866 };
2867
2868 int pricnt = sizeof(pridef)/sizeof(struct pridef);