]> granicus.if.org Git - sysstat/blobdiff - pr_stats.c
sar: Add softnet statistics (part 3): Display statistics
[sysstat] / pr_stats.c
index bf8cca2a2a80f203219c0173ffe7aab149df0846..d8685205711987042f5a23ab6b5a22dd22be56a4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * pr_stats.c: Functions used by sar to display statistics
- * (C) 1999-2015 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2016 by Sebastien GODARD (sysstat <at> orange.fr)
  *
  ***************************************************************************
  * This program is free software; you can redistribute it and/or modify it *
@@ -15,7 +15,7 @@
  *                                                                         *
  * You should have received a copy of the GNU General Public License along *
  * with this program; if not, write to the Free Software Foundation, Inc., *
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                   *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA              *
  ***************************************************************************
  */
 
@@ -42,6 +42,70 @@ extern int  dis;
 extern char timestamp[][TIMESTAMP_LEN];
 extern unsigned long avg_count;
 
+
+/*
+ ***************************************************************************
+ * Display current activity header line.
+ *
+ * IN:
+ * @timestamp  Timestamp for previous stat sample.
+ * @a          Activity structure.
+ * @pos                Index in @.hdr_line string, 0 being the first one (header
+ *             are delimited by the '|' character).
+ * @iwidth     First column width (generally this is the item name). A
+ *             negative value means that the corresponding field shall be
+ *             displayed at the end of the line, with no indication of width.
+ * @vwidth     Column width for stats values.
+ ***************************************************************************
+ */
+void print_hdr_line(char *timestamp, struct activity *a, int pos, int iwidth, int vwidth)
+{
+       char hline[HEADER_LINE_LEN] = "";
+       char *hl, *tk, *it = NULL;
+       int i = -1, j;
+       int p = pos;
+
+       strncpy(hline, a->hdr_line, HEADER_LINE_LEN - 1);
+       hline[HEADER_LINE_LEN - 1] = '\0';
+       for (hl = strtok(hline, "|"); hl && (pos > 0); hl = strtok(NULL, "|"), pos--);
+       if (!hl)
+               /* Bad @pos arg given to function */
+               return;
+
+       printf("\n%-11s", timestamp);
+
+       if (strchr(hl, '&')) {
+               j = strcspn(hl, "&");
+               if ((a->opt_flags & 0xff00) & (1 << (8 + p))) {
+                       /* Display whole header line */
+                       *(hl + j) = ';';
+               }
+               else {
+                       /* Display only the first part of the header line */
+                       *(hl + j) = '\0';
+               }
+       }
+       /* Display each field */
+       for (tk = strtok(hl, ";"); tk; tk = strtok(NULL, ";"), i--) {
+               if (iwidth > 0) {
+                       printf(" %*s", iwidth, tk);
+                       iwidth = 0;
+                       continue;
+               }
+               if ((iwidth < 0) && (iwidth == i)) {
+                       it = tk;
+                       iwidth = 0;
+               }
+               else {
+                       printf(" %*s", vwidth, tk);
+               }
+       }
+       if (it) {
+               printf(" %s", it);
+       }
+       printf("\n");
+}
+
 /*
  ***************************************************************************
  * Display CPU statistics.
@@ -61,17 +125,7 @@ __print_funct_t print_cpu_stats(struct activity *a, int prev, int curr,
        struct stats_cpu *scc, *scp;
 
        if (dis) {
-               if (DISPLAY_CPU_DEF(a->opt_flags)) {
-                       printf("\n%-11s     CPU     %%user     %%nice   %%system"
-                              "   %%iowait    %%steal     %%idle\n",
-                              timestamp[!curr]);
-               }
-               else if (DISPLAY_CPU_ALL(a->opt_flags)) {
-                       printf("\n%-11s     CPU      %%usr     %%nice      %%sys"
-                              "   %%iowait    %%steal      %%irq     %%soft"
-                              "    %%guest    %%gnice     %%idle\n",
-                              timestamp[!curr]);
-               }
+               print_hdr_line(timestamp[!curr], a, FIRST + DISPLAY_CPU_ALL(a->opt_flags), 7, 9);
        }
 
        for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
@@ -226,7 +280,7 @@ __print_funct_t print_pcsw_stats(struct activity *a, int prev, int curr,
                *spp = (struct stats_pcsw *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s    proc/s   cswch/s\n", timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -254,7 +308,7 @@ __print_funct_t print_irq_stats(struct activity *a, int prev, int curr,
        struct stats_irq *sic, *sip;
 
        if (dis) {
-               printf("\n%-11s      INTR    intr/s\n", timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
@@ -308,7 +362,7 @@ __print_funct_t print_swap_stats(struct activity *a, int prev, int curr,
                *ssp = (struct stats_swap *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s  pswpin/s pswpout/s\n", timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -337,9 +391,7 @@ __print_funct_t print_paging_stats(struct activity *a, int prev, int curr,
                *spp = (struct stats_paging *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s"
-                      " pgscank/s pgscand/s pgsteal/s    %%vmeff\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -381,16 +433,26 @@ __print_funct_t print_io_stats(struct activity *a, int prev, int curr,
                *sip = (struct stats_io *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s       tps      rtps      wtps   bread/s   bwrtn/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
+       /*
+        * If we get negative values, this is probably because
+        * one or more devices/filesystems have been unmounted.
+        * We display 0.0 in this case though we should rather tell
+        * the user that the value cannot be calculated here.
+        */
        cprintf_f(5, 9, 2,
-                 S_VALUE(sip->dk_drive,      sic->dk_drive,      itv),
-                 S_VALUE(sip->dk_drive_rio,  sic->dk_drive_rio,  itv),
-                 S_VALUE(sip->dk_drive_wio,  sic->dk_drive_wio,  itv),
+                 sic->dk_drive < sip->dk_drive ? 0.0 :
+                 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
+                 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
+                 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
+                 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
+                 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
+                 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
                  S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
+                 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
                  S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv));
        printf("\n");
 }
@@ -434,8 +496,7 @@ void stub_print_memory_stats(struct activity *a, int prev, int curr,
 
        if (DISPLAY_MEMORY(a->opt_flags)) {
                if (dis) {
-                       printf("\n%-11s   frmpg/s   bufpg/s   campg/s\n",
-                              timestamp[!curr]);
+                       print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
                }
 
                printf("%-11s", timestamp[curr]);
@@ -448,45 +509,40 @@ void stub_print_memory_stats(struct activity *a, int prev, int curr,
 
        if (DISPLAY_MEM_AMT(a->opt_flags)) {
                if (dis) {
-                       printf("\n%-11s kbmemfree kbmemused  %%memused kbbuffers  kbcached"
-                              "  kbcommit   %%commit  kbactive   kbinact   kbdirty", timestamp[!curr]);
-                       if (DISPLAY_MEM_ALL(a->opt_flags)) {
-                               printf("  kbanonpg    kbslab  kbkstack   kbpgtbl  kbvmused");
-                       }
-                       printf("\n");
+                       print_hdr_line(timestamp[!curr], a, SECOND, 0, 9);
                }
 
                if (!dispavg) {
                        /* Display instantaneous values */
                        printf("%-11s", timestamp[curr]);
                        cprintf_u64(2, 9,
-                                   smc->frmkb,
-                                   smc->tlmkb - smc->frmkb);
+                                   (unsigned long long) smc->frmkb,
+                                   (unsigned long long) (smc->tlmkb - smc->frmkb));
                        cprintf_pc(1, 9, 2,
                                   smc->tlmkb ?
                                   SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb)
                                   : 0.0);
                        cprintf_u64(3, 9,
-                                   smc->bufkb,
-                                   smc->camkb,
-                                   smc->comkb);
+                                   (unsigned long long) smc->bufkb,
+                                   (unsigned long long) smc->camkb,
+                                   (unsigned long long) smc->comkb);
                        cprintf_pc(1, 9, 2,
                                   (smc->tlmkb + smc->tlskb) ?
                                   SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb)
                                   : 0.0);
                        cprintf_u64(3, 9,
-                                   smc->activekb,
-                                   smc->inactkb,
-                                   smc->dirtykb);
+                                   (unsigned long long) smc->activekb,
+                                   (unsigned long long) smc->inactkb,
+                                   (unsigned long long) smc->dirtykb);
 
                        if (DISPLAY_MEM_ALL(a->opt_flags)) {
                                /* Display extended memory statistics */
                                cprintf_u64(5, 9,
-                                           smc->anonpgkb,
-                                           smc->slabkb,
-                                           smc->kstackkb,
-                                           smc->pgtblkb,
-                                           smc->vmusedkb);
+                                           (unsigned long long) smc->anonpgkb,
+                                           (unsigned long long) smc->slabkb,
+                                           (unsigned long long) smc->kstackkb,
+                                           (unsigned long long) smc->pgtblkb,
+                                           (unsigned long long) smc->vmusedkb);
                        }
 
                        printf("\n");
@@ -553,25 +609,24 @@ void stub_print_memory_stats(struct activity *a, int prev, int curr,
 
        if (DISPLAY_SWAP(a->opt_flags)) {
                if (dis) {
-                       printf("\n%-11s kbswpfree kbswpused  %%swpused  kbswpcad   %%swpcad\n",
-                              timestamp[!curr]);
+                       print_hdr_line(timestamp[!curr], a, THIRD, 0, 9);
                }
 
                if (!dispavg) {
                        /* Display instantaneous values */
                        printf("%-11s", timestamp[curr]);
                        cprintf_u64(2, 9,
-                                   smc->frskb,
-                                   smc->tlskb - smc->frskb);
+                                   (unsigned long long) smc->frskb,
+                                   (unsigned long long) (smc->tlskb - smc->frskb));
                        cprintf_pc(1, 9, 2,
                                   smc->tlskb ?
-                                  SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) 
+                                  SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb)
                                   : 0.0);
                        cprintf_u64(1, 9,
-                                   smc->caskb);
+                                   (unsigned long long) smc->caskb);
                        cprintf_pc(1, 9, 2,
                                   (smc->tlskb - smc->frskb) ?
-                                  SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) 
+                                  SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb)
                                   : 0.0);
 
                        printf("\n");
@@ -670,18 +725,17 @@ void stub_print_ktables_stats(struct activity *a, int curr, int dispavg)
 
 
        if (dis) {
-               printf("\n%-11s dentunusd   file-nr  inode-nr    pty-nr\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        if (!dispavg) {
                /* Display instantaneous values */
                printf("%-11s", timestamp[curr]);
                cprintf_u64(4, 9,
-                           skc->dentry_stat,
-                           skc->file_used,
-                           skc->inode_used,
-                           skc->pty_nr);
+                           (unsigned long long) skc->dentry_stat,
+                           (unsigned long long) skc->file_used,
+                           (unsigned long long) skc->inode_used,
+                           (unsigned long long) skc->pty_nr);
                printf("\n");
 
                /*
@@ -766,22 +820,21 @@ void stub_print_queue_stats(struct activity *a, int curr, int dispavg)
                avg_procs_blocked = 0;
 
        if (dis) {
-               printf("\n%-11s   runq-sz  plist-sz   ldavg-1   ldavg-5  ldavg-15   blocked\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        if (!dispavg) {
                /* Display instantaneous values */
                printf("%-11s", timestamp[curr]);
                cprintf_u64(2, 9,
-                           sqc->nr_running,
-                           sqc->nr_threads);
+                           (unsigned long long) sqc->nr_running,
+                           (unsigned long long) sqc->nr_threads);
                cprintf_f(3, 9, 2,
                          (double) sqc->load_avg_1  / 100,
                          (double) sqc->load_avg_5  / 100,
                          (double) sqc->load_avg_15 / 100);
                cprintf_u64(1, 9,
-                           sqc->procs_blocked);
+                           (unsigned long long) sqc->procs_blocked);
                printf("\n");
 
                /* Will be used to compute the average */
@@ -865,8 +918,7 @@ __print_funct_t print_serial_stats(struct activity *a, int prev, int curr,
        struct stats_serial *ssc, *ssp;
 
        if (dis) {
-               printf("\n%-11s       TTY   rcvin/s   xmtin/s framerr/s prtyerr/s"
-                      "     brk/s   ovrun/s\n", timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        for (i = 0; i < a->nr; i++) {
@@ -917,9 +969,7 @@ __print_funct_t print_disk_stats(struct activity *a, int prev, int curr,
        char *dev_name, *persist_dev_name;
 
        if (dis) {
-               printf("\n%-11s       DEV       tps  rd_sec/s  wr_sec/s  avgrq-sz"
-                      "  avgqu-sz     await     svctm     %%util\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        for (i = 0; i < a->nr; i++) {
@@ -993,8 +1043,7 @@ __print_funct_t print_net_dev_stats(struct activity *a, int prev, int curr,
        double rxkb, txkb, ifutil;
 
        if (dis) {
-               printf("\n%-11s     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s"
-                      "   rxcmp/s   txcmp/s  rxmcst/s   %%ifutil\n", timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        for (i = 0; i < a->nr; i++) {
@@ -1045,9 +1094,7 @@ __print_funct_t print_net_edev_stats(struct activity *a, int prev, int curr,
        struct stats_net_edev *snedc, *snedp;
 
        if (dis) {
-               printf("\n%-11s     IFACE   rxerr/s   txerr/s    coll/s  rxdrop/s"
-                      "  txdrop/s  txcarr/s  rxfram/s  rxfifo/s  txfifo/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        for (i = 0; i < a->nr; i++) {
@@ -1096,8 +1143,7 @@ __print_funct_t print_net_nfs_stats(struct activity *a, int prev, int curr,
                *snnp = (struct stats_net_nfs *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s    call/s retrans/s    read/s   write/s  access/s"
-                      "  getatt/s\n", timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1130,9 +1176,7 @@ __print_funct_t print_net_nfsd_stats(struct activity *a, int prev, int curr,
                *snndp = (struct stats_net_nfsd *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s   scall/s badcall/s  packet/s     udp/s     tcp/s     "
-                      "hit/s    miss/s   sread/s  swrite/s saccess/s sgetatt/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1175,20 +1219,19 @@ void stub_print_net_sock_stats(struct activity *a, int curr, int dispavg)
                avg_tcp_tw     = 0;
 
        if (dis) {
-               printf("\n%-11s    totsck    tcpsck    udpsck    rawsck   ip-frag    tcp-tw\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        if (!dispavg) {
                /* Display instantaneous values */
                printf("%-11s", timestamp[curr]);
                cprintf_u64(6, 9,
-                           snsc->sock_inuse,
-                           snsc->tcp_inuse,
-                           snsc->udp_inuse,
-                           snsc->raw_inuse,
-                           snsc->frag_inuse,
-                           snsc->tcp_tw);
+                           (unsigned long long) snsc->sock_inuse,
+                           (unsigned long long) snsc->tcp_inuse,
+                           (unsigned long long) snsc->udp_inuse,
+                           (unsigned long long) snsc->raw_inuse,
+                           (unsigned long long) snsc->frag_inuse,
+                           (unsigned long long) snsc->tcp_tw);
                printf("\n");
 
                /* Will be used to compute the average */
@@ -1270,8 +1313,7 @@ __print_funct_t print_net_ip_stats(struct activity *a, int prev, int curr,
                *snip = (struct stats_net_ip *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s    irec/s  fwddgm/s    idel/s     orq/s   asmrq/s"
-                      "   asmok/s  fragok/s fragcrt/s\n", timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1289,7 +1331,7 @@ __print_funct_t print_net_ip_stats(struct activity *a, int prev, int curr,
 
 /*
  ***************************************************************************
- * Display IP network error statistics.
+ * Display IP network errors statistics.
  *
  * IN:
  * @a          Activity structure with statistics.
@@ -1306,8 +1348,7 @@ __print_funct_t print_net_eip_stats(struct activity *a, int prev, int curr,
                *sneip = (struct stats_net_eip *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s ihdrerr/s iadrerr/s iukwnpr/s   idisc/s   odisc/s"
-                      "   onort/s    asmf/s   fragf/s\n", timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1342,9 +1383,7 @@ __print_funct_t print_net_icmp_stats(struct activity *a, int prev, int curr,
                *snip = (struct stats_net_icmp *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s    imsg/s    omsg/s    iech/s   iechr/s    oech/s"
-                      "   oechr/s     itm/s    itmr/s     otm/s    otmr/s"
-                      "  iadrmk/s iadrmkr/s  oadrmk/s oadrmkr/s\n", timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1368,7 +1407,7 @@ __print_funct_t print_net_icmp_stats(struct activity *a, int prev, int curr,
 
 /*
  ***************************************************************************
- * Display ICMP network error statistics.
+ * Display ICMP network errors statistics.
  *
  * IN:
  * @a          Activity structure with statistics.
@@ -1385,9 +1424,7 @@ __print_funct_t print_net_eicmp_stats(struct activity *a, int prev, int curr,
                *sneip = (struct stats_net_eicmp *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s    ierr/s    oerr/s idstunr/s odstunr/s   itmex/s"
-                      "   otmex/s iparmpb/s oparmpb/s   isrcq/s   osrcq/s"
-                      "  iredir/s  oredir/s\n", timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1426,8 +1463,7 @@ __print_funct_t print_net_tcp_stats(struct activity *a, int prev, int curr,
                *sntp = (struct stats_net_tcp *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s  active/s passive/s    iseg/s    oseg/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1441,7 +1477,7 @@ __print_funct_t print_net_tcp_stats(struct activity *a, int prev, int curr,
 
 /*
  ***************************************************************************
- * Display TCP network error statistics.
+ * Display TCP network errors statistics.
  *
  * IN:
  * @a          Activity structure with statistics.
@@ -1458,8 +1494,7 @@ __print_funct_t print_net_etcp_stats(struct activity *a, int prev, int curr,
                *snetp = (struct stats_net_etcp *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s  atmptf/s  estres/s retrans/s isegerr/s   orsts/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1491,8 +1526,7 @@ __print_funct_t print_net_udp_stats(struct activity *a, int prev, int curr,
                *snup = (struct stats_net_udp *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s    idgm/s    odgm/s  noport/s idgmerr/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1526,18 +1560,17 @@ void stub_print_net_sock6_stats(struct activity *a, int curr, int dispavg)
                avg_frag6_inuse = 0;
 
        if (dis) {
-               printf("\n%-11s   tcp6sck   udp6sck   raw6sck  ip6-frag\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        if (!dispavg) {
                /* Display instantaneous values */
                printf("%-11s", timestamp[curr]);
                cprintf_u64(4, 9,
-                           snsc->tcp6_inuse,
-                           snsc->udp6_inuse,
-                           snsc->raw6_inuse,
-                           snsc->frag6_inuse);
+                           (unsigned long long) snsc->tcp6_inuse,
+                           (unsigned long long) snsc->udp6_inuse,
+                           (unsigned long long) snsc->raw6_inuse,
+                           (unsigned long long) snsc->frag6_inuse);
                printf("\n");
 
                /* Will be used to compute the average */
@@ -1614,9 +1647,7 @@ __print_funct_t print_net_ip6_stats(struct activity *a, int prev, int curr,
                *snip = (struct stats_net_ip6 *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s   irec6/s fwddgm6/s   idel6/s    orq6/s  asmrq6/s"
-                      "  asmok6/s imcpck6/s omcpck6/s fragok6/s fragcr6/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1636,7 +1667,7 @@ __print_funct_t print_net_ip6_stats(struct activity *a, int prev, int curr,
 
 /*
  ***************************************************************************
- * Display IPv6 network error statistics.
+ * Display IPv6 network errors statistics.
  *
  * IN:
  * @a          Activity structure with statistics.
@@ -1653,9 +1684,7 @@ __print_funct_t print_net_eip6_stats(struct activity *a, int prev, int curr,
                *sneip = (struct stats_net_eip6 *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s ihdrer6/s iadrer6/s iukwnp6/s  i2big6/s  idisc6/s  odisc6/s"
-                      "  inort6/s  onort6/s   asmf6/s  fragf6/s itrpck6/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1693,10 +1722,7 @@ __print_funct_t print_net_icmp6_stats(struct activity *a, int prev, int curr,
                *snip = (struct stats_net_icmp6 *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s   imsg6/s   omsg6/s   iech6/s  iechr6/s  oechr6/s"
-                      "  igmbq6/s  igmbr6/s  ogmbr6/s igmbrd6/s ogmbrd6/s irtsol6/s ortsol6/s"
-                      "  irtad6/s inbsol6/s onbsol6/s  inbad6/s  onbad6/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1723,7 +1749,7 @@ __print_funct_t print_net_icmp6_stats(struct activity *a, int prev, int curr,
 
 /*
  ***************************************************************************
- * Display ICMPv6 network error statistics.
+ * Display ICMPv6 network errors statistics.
  *
  * IN:
  * @a          Activity structure with statistics.
@@ -1740,9 +1766,7 @@ __print_funct_t print_net_eicmp6_stats(struct activity *a, int prev, int curr,
                *sneip = (struct stats_net_eicmp6 *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s   ierr6/s idtunr6/s odtunr6/s  itmex6/s  otmex6/s"
-                      " iprmpb6/s oprmpb6/s iredir6/s oredir6/s ipck2b6/s opck2b6/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1780,8 +1804,7 @@ __print_funct_t print_net_udp6_stats(struct activity *a, int prev, int curr,
                *snup = (struct stats_net_udp6 *) a->buf[prev];
 
        if (dis) {
-               printf("\n%-11s   idgm6/s   odgm6/s noport6/s idgmer6/s\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        printf("%-11s", timestamp[curr]);
@@ -1822,8 +1845,7 @@ void stub_print_pwr_cpufreq_stats(struct activity *a, int curr, int dispavg)
        }
 
        if (dis) {
-               printf("\n%-11s     CPU       MHz\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 7, 9);
        }
 
        for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
@@ -1935,7 +1957,6 @@ __print_funct_t print_avg_pwr_cpufreq_stats(struct activity *a, int prev, int cu
 void stub_print_pwr_fan_stats(struct activity *a, int curr, int dispavg)
 {
        int i;
-       char fmt[16];
        struct stats_pwr_fan *spc;
        static double *avg_fan = NULL;
        static double *avg_fan_min = NULL;
@@ -1957,15 +1978,14 @@ void stub_print_pwr_fan_stats(struct activity *a, int curr, int dispavg)
        }
 
        if (dis) {
-               printf("\n%-11s     FAN       rpm      drpm %*s\n",
-                      timestamp[!curr], MAX_SENSORS_DEV_LEN, "DEVICE");
+               print_hdr_line(timestamp[!curr], a, FIRST, -2, 9);
        }
 
        for (i = 0; i < a->nr; i++) {
                spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%-11s", timestamp[curr]);
-               cprintf_in(IS_INT, "     %3d", "", i + 1);
+               cprintf_in(IS_INT, "     %5d", "", i + 1);
 
                if (dispavg) {
                        /* Display average values */
@@ -1982,8 +2002,7 @@ void stub_print_pwr_fan_stats(struct activity *a, int curr, int dispavg)
                        avg_fan_min[i] += spc->rpm_min;
                }
 
-               snprintf(fmt, 16, " %%%ds\n", MAX_SENSORS_DEV_LEN);
-               cprintf_in(IS_STR, fmt, spc->device, 0);
+               cprintf_in(IS_STR, " %s\n", spc->device, 0);
        }
 
        if (dispavg) {
@@ -2046,7 +2065,6 @@ __print_funct_t print_avg_pwr_fan_stats(struct activity *a, int prev, int curr,
 void stub_print_pwr_temp_stats(struct activity *a, int curr, int dispavg)
 {
        int i;
-       char fmt[16];
        struct stats_pwr_temp *spc;
        static double *avg_temp = NULL;
        static double *avg_temp_min = NULL, *avg_temp_max = NULL;
@@ -2075,15 +2093,14 @@ void stub_print_pwr_temp_stats(struct activity *a, int curr, int dispavg)
        }
 
        if (dis) {
-               printf("\n%-11s    TEMP      degC     %%temp %*s\n",
-                      timestamp[!curr], MAX_SENSORS_DEV_LEN, "DEVICE");
+               print_hdr_line(timestamp[!curr], a, FIRST, -2, 9);
        }
 
        for (i = 0; i < a->nr; i++) {
                spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%-11s", timestamp[curr]);
-               cprintf_in(IS_INT, "     %3d", "", i + 1);
+               cprintf_in(IS_INT, "     %5d", "", i + 1);
 
                if (dispavg) {
                        /* Display average values */
@@ -2106,8 +2123,7 @@ void stub_print_pwr_temp_stats(struct activity *a, int curr, int dispavg)
                        avg_temp_max[i] = spc->temp_max;
                }
 
-               snprintf(fmt, 16, " %%%ds\n", MAX_SENSORS_DEV_LEN);
-               cprintf_in(IS_STR, fmt, spc->device, 0);
+               cprintf_in(IS_STR, " %s\n", spc->device, 0);
        }
 
        if (dispavg) {
@@ -2174,7 +2190,6 @@ __print_funct_t print_avg_pwr_temp_stats(struct activity *a, int prev, int curr,
 void stub_print_pwr_in_stats(struct activity *a, int curr, int dispavg)
 {
        int i;
-       char fmt[16];
        struct stats_pwr_in *spc;
        static double *avg_in = NULL;
        static double *avg_in_min = NULL, *avg_in_max = NULL;
@@ -2203,15 +2218,14 @@ void stub_print_pwr_in_stats(struct activity *a, int curr, int dispavg)
        }
 
        if (dis) {
-               printf("\n%-11s      IN       inV       %%in %*s\n",
-                      timestamp[!curr], MAX_SENSORS_DEV_LEN, "DEVICE");
+               print_hdr_line(timestamp[!curr], a, FIRST, -2, 9);
        }
 
        for (i = 0; i < a->nr; i++) {
                spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%-11s", timestamp[curr]);
-               cprintf_in(IS_INT, "     %3d", "", i);
+               cprintf_in(IS_INT, "     %5d", "", i);
 
                if (dispavg) {
                        /* Display average values */
@@ -2234,8 +2248,7 @@ void stub_print_pwr_in_stats(struct activity *a, int curr, int dispavg)
                        avg_in_max[i] = spc->in_max;
                }
 
-               snprintf(fmt, 16, " %%%ds\n", MAX_SENSORS_DEV_LEN);
-               cprintf_in(IS_STR, fmt, spc->device, 0);
+               cprintf_in(IS_STR, " %s\n", spc->device, 0);
        }
 
        if (dispavg) {
@@ -2308,16 +2321,15 @@ void stub_print_huge_stats(struct activity *a, int curr, int dispavg)
                avg_tlhkb = 0;
 
        if (dis) {
-               printf("\n%-11s kbhugfree kbhugused  %%hugused\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
        if (!dispavg) {
                /* Display instantaneous values */
                printf("%-11s", timestamp[curr]);
                cprintf_u64(2, 9,
-                           smc->frhkb,
-                           smc->tlhkb - smc->frhkb);
+                           (unsigned long long) smc->frhkb,
+                           (unsigned long long) (smc->tlhkb - smc->frhkb));
                cprintf_pc(1, 9, 2,
                           smc->tlhkb ?
                           SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0);
@@ -2400,8 +2412,7 @@ void print_pwr_wghfreq_stats(struct activity *a, int prev, int curr,
        unsigned long long tis, tisfreq;
 
        if (dis) {
-               printf("\n%-11s     CPU    wghMHz\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, 7, 9);
        }
 
        for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
@@ -2481,8 +2492,7 @@ void stub_print_pwr_usb_stats(struct activity *a, int curr, int dispavg)
        if (dis) {
                printf("\n%-11s     BUS  idvendor    idprod  maxpower",
                       (dispavg ? _("Summary:") : timestamp[!curr]));
-               printf(" %*s", MAX_MANUF_LEN - 1, "manufact");
-               printf(" %*s\n", MAX_PROD_LEN - 1, "product");
+               printf(" %-*s product\n", MAX_MANUF_LEN - 1, "manufact");
        }
 
        for (i = 0; i < a->nr; i++) {
@@ -2499,12 +2509,11 @@ void stub_print_pwr_usb_stats(struct activity *a, int curr, int dispavg)
                          suc->product_id);
                cprintf_u64(1, 9,
                            /* bMaxPower is expressed in 2 mA units */
-                           suc->bmaxpower << 1);
+                           (unsigned long long) (suc->bmaxpower << 1));
 
-               snprintf(fmt, 16, " %%%ds", MAX_MANUF_LEN - 1);
+               snprintf(fmt, 16, " %%-%ds", MAX_MANUF_LEN - 1);
                cprintf_s(IS_STR, fmt, suc->manufacturer);
-               snprintf(fmt, 16, " %%%ds\n", MAX_PROD_LEN - 1);
-               cprintf_s(IS_STR, fmt, suc->product);
+               cprintf_s(IS_STR, " %s\n", suc->product);
 
                if (!dispavg) {
                        /* Save current USB device in summary list */
@@ -2594,17 +2603,15 @@ __print_funct_t stub_print_filesystem_stats(struct activity *a, int curr, int di
        struct stats_filesystem *sfc, *sfm;
 
        if (dis) {
-               printf("\n%-11s  MBfsfree  MBfsused   %%fsused  %%ufsused"
-                      "     Ifree     Iused    %%Iused %s\n",
-                      (dispavg ? _("Summary:") : timestamp[!curr]),
-                      DISPLAY_MOUNT(a->opt_flags) ? "MOUNTPOINT" : "FILESYSTEM");
+               print_hdr_line((dispavg ? _("Summary:") : timestamp[!curr]),
+                              a, FIRST + DISPLAY_MOUNT(a->opt_flags), -1, 9);
        }
 
        for (i = 0; i < a->nr; i++) {
                sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
 
                if (!sfc->f_blocks)
-                       /* Size of filesystem is null: We are at the end of the list */
+                       /* Size of filesystem is zero: We are at the end of the list */
                        break;
 
                printf("%-11s", (dispavg ? _("Summary:") : timestamp[curr]));
@@ -2612,14 +2619,14 @@ __print_funct_t stub_print_filesystem_stats(struct activity *a, int curr, int di
                          (double) sfc->f_bfree / 1024 / 1024,
                          (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024);
                cprintf_pc(2, 9, 2,
-                          /* f_blocks is not null. But test it anyway ;-) */
+                          /* f_blocks is not zero. But test it anyway ;-) */
                           sfc->f_blocks ? SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks)
                           : 0.0,
                           sfc->f_blocks ? SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks)
                           : 0.0);
                cprintf_u64(2, 9,
-                           sfc->f_ffree,
-                           sfc->f_files - sfc->f_ffree);
+                           (unsigned long long) sfc->f_ffree,
+                           (unsigned long long) (sfc->f_files - sfc->f_ffree));
                cprintf_pc(1, 9, 2,
                           sfc->f_files ? SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files)
                           : 0.0);
@@ -2697,8 +2704,7 @@ __print_funct_t print_fchost_stats(struct activity *a, int prev, int curr,
        struct stats_fchost *sfcc,*sfcp;
 
        if (dis) {
-               printf("\n%-11s fch_rxf/s fch_txf/s fch_rxw/s fch_txw/s FCHOST\n",
-                      timestamp[!curr]);
+               print_hdr_line(timestamp[!curr], a, FIRST, -1, 9);
        }
 
        for (i = 0; i < a->nr; i++) {
@@ -2719,3 +2725,70 @@ __print_funct_t print_fchost_stats(struct activity *a, int prev, int curr,
                cprintf_in(IS_STR, " %s\n", sfcc->fchost_name, 0);
        }
 }
+
+/*
+ ***************************************************************************
+ * Display softnet statistics.
+ *
+ * IN:
+ * @a          Activity structure with statistics.
+ * @prev       Index in array where stats used as reference are.
+ * @curr       Index in array for current sample statistics.
+ * @itv                Interval of time in jiffies.
+ ***************************************************************************
+ */
+__print_funct_t print_softnet_stats(struct activity *a, int prev, int curr,
+                                   unsigned long long itv)
+{
+       struct stats_softnet
+               *ssnc = (struct stats_softnet *) a->buf[curr],
+               *ssnp = (struct stats_softnet *) a->buf[prev];
+       int i;
+
+       if (dis) {
+               print_hdr_line(timestamp[!curr], a, FIRST, 7, 9);
+       }
+
+       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+
+               /*
+                * The size of a->buf[...] CPU structure may be different from the default
+                * sizeof(struct stats_pwr_cpufreq) value if data have been read from a file!
+                * That's why we don't use a syntax like:
+                * ssnc = (struct stats_softnet *) a->buf[...] + i;
+                 */
+                ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
+                ssnp = (struct stats_softnet *) ((char *) a->buf[prev] + i * a->msize);
+
+               /*
+                * Note: a->nr is in [1, NR_CPUS + 1].
+                * Bitmap size is provided for (NR_CPUS + 1) CPUs.
+                * Anyway, NR_CPUS may vary between the version of sysstat
+                * used by sadc to create a file, and the version of sysstat
+                * used by sar to read it...
+                */
+
+               /* Should current CPU (including CPU "all") be displayed? */
+               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
+
+                       /* Yes: Display it */
+                       printf("%-11s", timestamp[curr]);
+
+                       if (!i) {
+                               /* This is CPU "all" */
+                               cprintf_in(IS_STR, " %s", "    all", 0);
+                       }
+                       else {
+                               cprintf_in(IS_INT, " %7d", "", i - 1);
+                       }
+
+                       cprintf_f(5, 9, 2,
+                                 S_VALUE(ssnp->processed,    ssnc->processed,    itv),
+                                 S_VALUE(ssnp->dropped,      ssnc->dropped,      itv),
+                                 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
+                                 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
+                                 S_VALUE(ssnp->flow_limit,   ssnc->flow_limit,   itv));
+                       printf("\n");
+               }
+       }
+}