From c44c37ad6f1f22b905bbef94f9640e69aefd5064 Mon Sep 17 00:00:00 2001 From: Fei Li Date: Wed, 8 Feb 2023 20:13:08 +0800 Subject: [PATCH 1/6] Move ifprop assignment more earlier We already get the attibutes of ifprop during getifprop() after reading /proc/net/dev, thus remove the unnecessary second getter in deviatsyst(). Signed-off-by: Fei Li --- deviate.c | 15 --------------- photosyst.c | 5 +++++ 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/deviate.c b/deviate.c index 1652a8f4..8923cb68 100644 --- a/deviate.c +++ b/deviate.c @@ -45,7 +45,6 @@ #include #include "atop.h" -#include "ifprop.h" #include "photoproc.h" #include "photosyst.h" @@ -617,7 +616,6 @@ deviatsyst(struct sstat *cur, struct sstat *pre, struct sstat *dev, { register int i, j; count_t *cdev, *ccur, *cpre; - struct ifprop ifprop; dev->cpu.nrcpu = cur->cpu.nrcpu; dev->cpu.devint = subcount(cur->cpu.devint, pre->cpu.devint); @@ -887,19 +885,6 @@ deviatsyst(struct sstat *cur, struct sstat *pre, struct sstat *dev, /* ** calculate deviations for interfaces */ - for (i=0; cur->intf.intf[i].name[0]; i++) - { - // fill current properties for each valid interface - strcpy(ifprop.name, cur->intf.intf[i].name); - - getifprop(&ifprop); - - cur->intf.intf[i].type = ifprop.type; - cur->intf.intf[i].speed = ifprop.speed; - cur->intf.intf[i].speedp = ifprop.speed; - cur->intf.intf[i].duplex = ifprop.fullduplex; - } - if (pre->intf.intf[0].name[0] == '\0') /* first sample? */ { for (i=0; cur->intf.intf[i].name[0]; i++) diff --git a/photosyst.c b/photosyst.c index ef508356..e7604e3c 100644 --- a/photosyst.c +++ b/photosyst.c @@ -1101,6 +1101,11 @@ photosyst(struct sstat *si) if (!getifprop(&ifprop)) continue; + si->intf.intfns[0].intf[i].type = ifprop.type; + si->intf.intfns[0].intf[i].speed = ifprop.speed; + si->intf.intfns[0].intf[i].speedp = ifprop.speed; + si->intf.intfns[0].intf[i].duplex = ifprop.fullduplex; + /* ** accept this interface but skip the remaining ** interfaces because we reached the total number From ab7ee8c13bb470cb68caddf5a17caa92bb96fa40 Mon Sep 17 00:00:00 2001 From: Fei Li Date: Wed, 1 Feb 2023 20:38:26 +0800 Subject: [PATCH 2/6] Add network namespace attributes for NET The network devices, like eth2, are settled in another network namespace via `ip netns add` in some scenarios in the production environment. In this case, we have to switch to that new netns to get network related statistics, e.g. reading from /proc/net/dev, /proc/net/snmp, /proc/net/snmp6. This patch firstly adds the needed attributes, like 'netns', for collecting and displaying network namespace statistics. Then the following patches will do the real implementation. To pass the compiling, also update for atopsar, parsable and json. Also format some lines according to astyle. Signed-off-by: Fei Li --- atopsar.c | 527 +++++++++++++++++++++++++------------------- deviate.c | 590 ++++++++++++++++++++++++++------------------------ json.c | 128 ++++++----- parseable.c | 82 +++---- photosyst.c | 66 +++--- photosyst.h | 21 +- showgeneric.c | 10 +- showlinux.c | 291 +++++++++++++------------ showlinux.h | 2 + showsys.c | 359 ++++++++++++++++-------------- 10 files changed, 1146 insertions(+), 930 deletions(-) diff --git a/atopsar.c b/atopsar.c index 10bf35f8..fd638f84 100644 --- a/atopsar.c +++ b/atopsar.c @@ -1976,7 +1976,7 @@ ibline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, static void ifhead(int osvers, int osrel, int ossub) { - printf("interf busy ipack/s opack/s iKbyte/s oKbyte/s " + printf("netns interf busy ipack/s opack/s iKbyte/s oKbyte/s " "imbps ombps maxmbps_if_"); } @@ -1992,107 +1992,111 @@ ifline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, char busyval[16], dupval; unsigned int badness; char *pn; - int len; + int len, nr; - for (i=0; i < ss->intf.nrintf; i++) /* per interface */ + for (nr = 0; nr < ss->intf.nrintfns; nr++) /* per net namespace */ { - count_t ival, oval; + for (i=0; i < ss->intf.intfns[nr].nrintf; i++) /* per interface */ + { + count_t ival, oval; - /* - ** print for the first sample all interfaces which - ** are found; afterwards print only the interfaces - ** which were really active during the interval - */ - if (!firstcall && !allresources && - !ss->intf.intf[i].rpack && !ss->intf.intf[i].spack) - continue; + /* + ** print for the first sample all interfaces which + ** are found; afterwards print only the interfaces + ** which were really active during the interval + */ + if (!firstcall && !allresources && + !ss->intf.intfns[nr].intf[i].rpack && !ss->intf.intfns[nr].intf[i].spack) + continue; - /* - ** convert byte-transfers to bit-transfers (* 8) - ** convert bit-transfers to megabit-transfers (/ 1000000) - ** per second - */ - ival = ss->intf.intf[i].rbyte/125000/deltasec; - oval = ss->intf.intf[i].sbyte/125000/deltasec; + /* + ** convert byte-transfers to bit-transfers (* 8) + ** convert bit-transfers to megabit-transfers (/ 1000000) + ** per second + */ + ival = ss->intf.intfns[nr].intf[i].rbyte/125000/deltasec; + oval = ss->intf.intfns[nr].intf[i].sbyte/125000/deltasec; - /* - ** calculate busy-percentage for interface - */ - if (ss->intf.intf[i].speed) /* speed known? */ - { - if (ss->intf.intf[i].duplex) - busy = (ival > oval ? ival*100 : oval*100) / - ss->intf.intf[i].speed; - else - busy = (ival + oval) * 100 / - ss->intf.intf[i].speed; - - // especially with wireless, the speed might have - // dropped temporarily to a very low value (snapshot) - // it might be better to take the speed of the - // previous sample - if (busy > 100 && ss->intf.intf[i].speed < - ss->intf.intf[i].speedp ) + /* + ** calculate busy-percentage for interface + */ + if (ss->intf.intfns[nr].intf[i].speed) /* speed known? */ { - ss->intf.intf[i].speed = - ss->intf.intf[i].speedp; - - if (ss->intf.intf[i].duplex) - busy = (ival > oval ? - ival*100 : oval*100) / - ss->intf.intf[i].speed; + if (ss->intf.intfns[nr].intf[i].duplex) + busy = (ival > oval ? ival*100 : oval*100) / + ss->intf.intfns[nr].intf[i].speed; else busy = (ival + oval) * 100 / - ss->intf.intf[i].speed; - } + ss->intf.intfns[nr].intf[i].speed; + + // especially with wireless, the speed might have + // dropped temporarily to a very low value (snapshot) + // it might be better to take the speed of the + // previous sample + if (busy > 100 && ss->intf.intfns[nr].intf[i].speed < + ss->intf.intfns[nr].intf[i].speedp ) + { + ss->intf.intfns[nr].intf[i].speed = + ss->intf.intfns[nr].intf[i].speedp; + + if (ss->intf.intfns[nr].intf[i].duplex) + busy = (ival > oval ? + ival*100 : oval*100) / + ss->intf.intfns[nr].intf[i].speed; + else + busy = (ival + oval) * 100 / + ss->intf.intfns[nr].intf[i].speed; + } - snprintf(busyval, sizeof busyval, - "%3.0lf%%", busy); - } - else - { - strcpy(busyval, "?"); /* speed unknown */ - busy = 0; - } + snprintf(busyval, sizeof busyval, + "%3.0lf%%", busy); + } + else + { + strcpy(busyval, "?"); /* speed unknown */ + busy = 0; + } - if (nlines++) - printf("%s ", tstamp); + if (nlines++) + printf("%s ", tstamp); - if (ss->intf.intf[i].speed) - { - if (ss->intf.intf[i].duplex) - dupval = 'f'; + if (ss->intf.intfns[nr].intf[i].speed) + { + if (ss->intf.intfns[nr].intf[i].duplex) + dupval = 'f'; + else + dupval = 'h'; + } else - dupval = 'h'; - } - else - { - dupval = ' '; - } + { + dupval = ' '; + } - if (netbadness) - badness = busy * 100 / netbadness; - else - badness = 0; + if (netbadness) + badness = busy * 100 / netbadness; + else + badness = 0; - if ( (len = strlen(ss->intf.intf[i].name)) > 6) - pn = ss->intf.intf[i].name + len - 6; - else - pn = ss->intf.intf[i].name; + if ( (len = strlen(ss->intf.intfns[nr].intf[i].name)) > 6) + pn = ss->intf.intfns[nr].intf[i].name + len - 6; + else + pn = ss->intf.intfns[nr].intf[i].name; - preprint(badness); + preprint(badness); - printf("%-6s %4s %7.1lf %7.1lf %8.0lf %8.0lf " - "%5lld %5lld %7ld %c", - pn, busyval, - (double)ss->intf.intf[i].rpack / deltasec, - (double)ss->intf.intf[i].spack / deltasec, - (double)ss->intf.intf[i].rbyte / 1024 / deltasec, - (double)ss->intf.intf[i].sbyte / 1024 / deltasec, - ival, oval, - ss->intf.intf[i].speed, dupval); + printf("%s %-6s %4s %7.1lf %7.1lf %8.0lf %8.0lf " + "%5lld %5lld %7ld %c", + ss->intf.intfns[nr].nsname, + pn, busyval, + (double)ss->intf.intfns[nr].intf[i].rpack / deltasec, + (double)ss->intf.intfns[nr].intf[i].spack / deltasec, + (double)ss->intf.intfns[nr].intf[i].rbyte / 1024 / deltasec, + (double)ss->intf.intfns[nr].intf[i].sbyte / 1024 / deltasec, + ival, oval, + ss->intf.intfns[nr].intf[i].speed, dupval); - postprint(badness); + postprint(badness); + } } if (nlines == 0) @@ -2108,7 +2112,7 @@ ifline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, static void IFhead(int osvers, int osrel, int ossub) { - printf("interf ierr/s oerr/s coll/s idrop/s odrop/s " + printf("netns interf ierr/s oerr/s coll/s idrop/s odrop/s " "iframe/s ocarrier/s _if_"); } @@ -2121,37 +2125,41 @@ IFline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, static char firstcall = 1; register long i, nlines = 0; char *pn; - int len; + int len, nr; - for (i=0; i < ss->intf.nrintf; i++) /* per interface */ + for (nr = 0; nr < ss->intf.nrintfns; nr++) { - /* - ** print for the first sample all interfaces which - ** are found; afterwards print only the interfaces - ** which were really active during the interval - */ - if (!firstcall && !allresources && - !ss->intf.intf[i].rpack && !ss->intf.intf[i].spack) - continue; + for (i=0; i < ss->intf.intfns[nr].nrintf; i++) /* per interface */ + { + /* + ** print for the first sample all interfaces which + ** are found; afterwards print only the interfaces + ** which were really active during the interval + */ + if (!firstcall && !allresources && + !ss->intf.intfns[nr].intf[i].rpack && !ss->intf.intfns[nr].intf[i].spack) + continue; - if (nlines++) - printf("%s ", tstamp); + if (nlines++) + printf("%s ", tstamp); - if ( (len = strlen(ss->intf.intf[i].name)) > 6) - pn = ss->intf.intf[i].name + len - 6; - else - pn = ss->intf.intf[i].name; - - printf("%-6s %6.2lf %6.2lf %6.2lf %7.2lf %7.2lf " - "%8.2lf %10.2lf\n", - pn, - (double)ss->intf.intf[i].rerrs / deltasec, - (double)ss->intf.intf[i].serrs / deltasec, - (double)ss->intf.intf[i].scollis / deltasec, - (double)ss->intf.intf[i].rdrop / deltasec, - (double)ss->intf.intf[i].sdrop / deltasec, - (double)ss->intf.intf[i].rframe / deltasec, - (double)ss->intf.intf[i].scarrier / deltasec); + if ( (len = strlen(ss->intf.intfns[nr].intf[i].name)) > 6) + pn = ss->intf.intfns[nr].intf[i].name + len - 6; + else + pn = ss->intf.intfns[nr].intf[i].name; + + printf("%s %-6s %6.2lf %6.2lf %6.2lf %7.2lf %7.2lf " + "%8.2lf %10.2lf\n", + ss->intf.intfns[nr].nsname, + pn, + (double)ss->intf.intfns[nr].intf[i].rerrs / deltasec, + (double)ss->intf.intfns[nr].intf[i].serrs / deltasec, + (double)ss->intf.intfns[nr].intf[i].scollis / deltasec, + (double)ss->intf.intfns[nr].intf[i].rdrop / deltasec, + (double)ss->intf.intfns[nr].intf[i].sdrop / deltasec, + (double)ss->intf.intfns[nr].intf[i].rframe / deltasec, + (double)ss->intf.intfns[nr].intf[i].scarrier / deltasec); + } } if (nlines == 0) @@ -2170,7 +2178,7 @@ IFline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, static void ipv4head(int osvers, int osrel, int ossub) { - printf("inrecv/s outreq/s indeliver/s forward/s " + printf("netns inrecv/s outreq/s indeliver/s forward/s " "reasmok/s fragcreat/s _ipv4_"); } @@ -2180,20 +2188,28 @@ ipv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf("%8.1lf %8.1lf %11.1lf %9.1lf %9.1lf %11.1lf\n", - (double)ss->net.ipv4.InReceives / deltasec, - (double)ss->net.ipv4.OutRequests / deltasec, - (double)ss->net.ipv4.InDelivers / deltasec, - (double)ss->net.ipv4.Forwarding / deltasec, - (double)ss->net.ipv4.ReasmOKs / deltasec, - (double)ss->net.ipv4.FragCreates / deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s %8.1lf %8.1lf %11.1lf %9.1lf %9.1lf %11.1lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].ipv4.InReceives / deltasec, + (double)ss->net.netns[nr].ipv4.OutRequests / deltasec, + (double)ss->net.netns[nr].ipv4.InDelivers / deltasec, + (double)ss->net.netns[nr].ipv4.Forwarding / deltasec, + (double)ss->net.netns[nr].ipv4.ReasmOKs / deltasec, + (double)ss->net.netns[nr].ipv4.FragCreates / deltasec); + } + return 1; } static void IPv4head(int osvers, int osrel, int ossub) { - printf("in: dsc/s hder/s ader/s unkp/s ratim/s rfail/s " + printf("netns " + "in: dsc/s hder/s ader/s unkp/s ratim/s rfail/s " "out: dsc/s nrt/s_ipv4_"); } @@ -2203,16 +2219,23 @@ IPv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf(" %5.1lf %6.1lf %6.1lf %6.1lf %7.1lf %7.1lf " - " %5.1lf %5.1lf\n", - (double)ss->net.ipv4.InDiscards / deltasec, - (double)ss->net.ipv4.InHdrErrors / deltasec, - (double)ss->net.ipv4.InAddrErrors / deltasec, - (double)ss->net.ipv4.InUnknownProtos / deltasec, - (double)ss->net.ipv4.ReasmTimeout / deltasec, - (double)ss->net.ipv4.ReasmFails / deltasec, - (double)ss->net.ipv4.OutDiscards / deltasec, - (double)ss->net.ipv4.OutNoRoutes / deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s " + " %5.1lf %6.1lf %6.1lf %6.1lf %7.1lf %7.1lf " + " %5.1lf %5.1lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].ipv4.InDiscards / deltasec, + (double)ss->net.netns[nr].ipv4.InHdrErrors / deltasec, + (double)ss->net.netns[nr].ipv4.InAddrErrors / deltasec, + (double)ss->net.netns[nr].ipv4.InUnknownProtos / deltasec, + (double)ss->net.netns[nr].ipv4.ReasmTimeout / deltasec, + (double)ss->net.netns[nr].ipv4.ReasmFails / deltasec, + (double)ss->net.netns[nr].ipv4.OutDiscards / deltasec, + (double)ss->net.netns[nr].ipv4.OutNoRoutes / deltasec); + } return 1; } @@ -2222,7 +2245,7 @@ IPv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, static void icmpv4head(int osvers, int osrel, int ossub) { - printf("intot/s outtot/s inecho/s inerep/s " + printf("netns intot/s outtot/s inecho/s inerep/s " "otecho/s oterep/s _icmpv4_" ); } @@ -2232,20 +2255,26 @@ icmpv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf("%7.1lf %8.1lf %8.2lf %8.2lf %8.2lf %8.2lf\n", - (double)ss->net.icmpv4.InMsgs / deltasec, - (double)ss->net.icmpv4.OutMsgs / deltasec, - (double)ss->net.icmpv4.InEchos / deltasec, - (double)ss->net.icmpv4.OutEchos / deltasec, - (double)ss->net.icmpv4.InEchoReps / deltasec, - (double)ss->net.icmpv4.OutEchoReps / deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s %7.1lf %8.1lf %8.2lf %8.2lf %8.2lf %8.2lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].icmpv4.InMsgs / deltasec, + (double)ss->net.netns[nr].icmpv4.OutMsgs / deltasec, + (double)ss->net.netns[nr].icmpv4.InEchos / deltasec, + (double)ss->net.netns[nr].icmpv4.OutEchos / deltasec, + (double)ss->net.netns[nr].icmpv4.InEchoReps / deltasec, + (double)ss->net.netns[nr].icmpv4.OutEchoReps / deltasec); + } return 1; } static void ICMPv4head(int osvers, int osrel, int ossub) { - printf("ierr/s isq/s ird/s idu/s ite/s " + printf("netns ierr/s isq/s ird/s idu/s ite/s " "oerr/s osq/s ord/s odu/s ote/s_icmpv4_"); } @@ -2255,18 +2284,24 @@ ICMPv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf("%6.2lf %5.2lf %5.2lf %5.2lf %5.2lf " - "%6.2lf %5.2lf %5.2lf %5.2lf %5.2lf\n", - (double)ss->net.icmpv4.InErrors / deltasec, - (double)ss->net.icmpv4.InSrcQuenchs / deltasec, - (double)ss->net.icmpv4.InRedirects / deltasec, - (double)ss->net.icmpv4.InDestUnreachs / deltasec, - (double)ss->net.icmpv4.InTimeExcds / deltasec, - (double)ss->net.icmpv4.OutErrors / deltasec, - (double)ss->net.icmpv4.OutSrcQuenchs / deltasec, - (double)ss->net.icmpv4.OutRedirects / deltasec, - (double)ss->net.icmpv4.OutDestUnreachs / deltasec, - (double)ss->net.icmpv4.OutTimeExcds / deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s %6.2lf %5.2lf %5.2lf %5.2lf %5.2lf " + "%6.2lf %5.2lf %5.2lf %5.2lf %5.2lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].icmpv4.InErrors / deltasec, + (double)ss->net.netns[nr].icmpv4.InSrcQuenchs / deltasec, + (double)ss->net.netns[nr].icmpv4.InRedirects / deltasec, + (double)ss->net.netns[nr].icmpv4.InDestUnreachs / deltasec, + (double)ss->net.netns[nr].icmpv4.InTimeExcds / deltasec, + (double)ss->net.netns[nr].icmpv4.OutErrors / deltasec, + (double)ss->net.netns[nr].icmpv4.OutSrcQuenchs / deltasec, + (double)ss->net.netns[nr].icmpv4.OutRedirects / deltasec, + (double)ss->net.netns[nr].icmpv4.OutDestUnreachs / deltasec, + (double)ss->net.netns[nr].icmpv4.OutTimeExcds / deltasec); + } return 1; } @@ -2276,7 +2311,7 @@ ICMPv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, static void udpv4head(int osvers, int osrel, int ossub) { - printf("indgram/s outdgram/s inerr/s noport/s " + printf("netns indgram/s outdgram/s inerr/s noport/s " " _udpv4_"); } @@ -2286,11 +2321,17 @@ udpv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf("%9.1lf %10.1lf %7.2lf %9.2lf\n", - (double)ss->net.udpv4.InDatagrams / deltasec, - (double)ss->net.udpv4.OutDatagrams / deltasec, - (double)ss->net.udpv4.InErrors / deltasec, - (double)ss->net.udpv4.NoPorts / deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s %9.1lf %10.1lf %7.2lf %9.2lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].udpv4.InDatagrams / deltasec, + (double)ss->net.netns[nr].udpv4.OutDatagrams / deltasec, + (double)ss->net.netns[nr].udpv4.InErrors / deltasec, + (double)ss->net.netns[nr].udpv4.NoPorts / deltasec); + } return 1; } @@ -2300,7 +2341,7 @@ udpv4line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, static void ipv6head(int osvers, int osrel, int ossub) { - printf("inrecv/s outreq/s inmc/s outmc/s indeliv/s " + printf("netns inrecv/s outreq/s inmc/s outmc/s indeliv/s " "reasmok/s fragcre/s _ipv6_"); } @@ -2310,21 +2351,28 @@ ipv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf("%8.1lf %8.1lf %6.1lf %7.1lf %9.1lf %9.1lf %9.1lf\n", - (double)ss->net.ipv6.Ip6InReceives / deltasec, - (double)ss->net.ipv6.Ip6OutRequests / deltasec, - (double)ss->net.ipv6.Ip6InMcastPkts / deltasec, - (double)ss->net.ipv6.Ip6OutMcastPkts / deltasec, - (double)ss->net.ipv6.Ip6InDelivers / deltasec, - (double)ss->net.ipv6.Ip6ReasmOKs / deltasec, - (double)ss->net.ipv6.Ip6FragCreates / deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s %8.1lf %8.1lf %6.1lf %7.1lf %9.1lf %9.1lf %9.1lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].ipv6.Ip6InReceives / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6OutRequests / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6InMcastPkts / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6OutMcastPkts / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6InDelivers / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6ReasmOKs / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6FragCreates / deltasec); + } return 1; } static void IPv6head(int osvers, int osrel, int ossub) { - printf("in: dsc/s hder/s ader/s unkp/s ratim/s rfail/s " + printf("netns " + "in: dsc/s hder/s ader/s unkp/s ratim/s rfail/s " "out: dsc/s nrt/s_ipv6_"); } @@ -2334,16 +2382,23 @@ IPv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf(" %5.1lf %6.1lf %6.1lf %6.1lf %7.1lf %7.1lf " - " %5.1lf %5.1lf\n", - (double)ss->net.ipv6.Ip6InDiscards / deltasec, - (double)ss->net.ipv6.Ip6InHdrErrors / deltasec, - (double)ss->net.ipv6.Ip6InAddrErrors / deltasec, - (double)ss->net.ipv6.Ip6InUnknownProtos / deltasec, - (double)ss->net.ipv6.Ip6ReasmTimeout / deltasec, - (double)ss->net.ipv6.Ip6ReasmFails / deltasec, - (double)ss->net.ipv6.Ip6OutDiscards / deltasec, - (double)ss->net.ipv6.Ip6OutNoRoutes / deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s " + " %5.1lf %6.1lf %6.1lf %6.1lf %7.1lf %7.1lf " + " %5.1lf %5.1lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].ipv6.Ip6InDiscards / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6InHdrErrors / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6InAddrErrors / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6InUnknownProtos / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6ReasmTimeout / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6ReasmFails / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6OutDiscards / deltasec, + (double)ss->net.netns[nr].ipv6.Ip6OutNoRoutes / deltasec); + } return 1; } @@ -2353,7 +2408,7 @@ IPv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, static void icmpv6head(int osvers, int osrel, int ossub) { - printf("intot/s outtot/s inerr/s innsol/s innadv/s " + printf("netns intot/s outtot/s inerr/s innsol/s innadv/s " "otnsol/s otnadv/s _icmp6_" ); } @@ -2363,22 +2418,28 @@ icmpv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf("%7.1lf %8.1lf %7.2lf %8.2lf %8.2lf %8.2lf %8.2lf\n", - (double)ss->net.icmpv6.Icmp6InMsgs / deltasec, - (double)ss->net.icmpv6.Icmp6OutMsgs / deltasec, - (double)ss->net.icmpv6.Icmp6InErrors / deltasec, - (double)ss->net.icmpv6.Icmp6InNeighborSolicits / deltasec, - (double)ss->net.icmpv6.Icmp6InNeighborAdvertisements/ deltasec, - (double)ss->net.icmpv6.Icmp6OutNeighborSolicits / deltasec, - (double)ss->net.icmpv6.Icmp6OutNeighborAdvertisements - /deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s %7.1lf %8.1lf %7.2lf %8.2lf %8.2lf %8.2lf %8.2lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].icmpv6.Icmp6InMsgs / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6OutMsgs / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6InErrors / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6InNeighborSolicits / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6InNeighborAdvertisements/ deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6OutNeighborSolicits / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6OutNeighborAdvertisements + /deltasec); + } return 1; } static void ICMPv6head(int osvers, int osrel, int ossub) { - printf("iecho/s ierep/s oerep/s idu/s odu/s ird/s ord/s ite/s " + printf("netns iecho/s ierep/s oerep/s idu/s odu/s ird/s ord/s ite/s " "ote/s _icmpv6_"); } @@ -2388,17 +2449,23 @@ ICMPv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf("%7.2lf %7.2lf %7.2lf %5.2lf %5.2lf " - "%5.2lf %5.2lf %5.2lf %5.2lf\n", - (double)ss->net.icmpv6.Icmp6InEchos / deltasec, - (double)ss->net.icmpv6.Icmp6InEchoReplies / deltasec, - (double)ss->net.icmpv6.Icmp6OutEchoReplies / deltasec, - (double)ss->net.icmpv6.Icmp6InDestUnreachs / deltasec, - (double)ss->net.icmpv6.Icmp6OutDestUnreachs / deltasec, - (double)ss->net.icmpv6.Icmp6InRedirects / deltasec, - (double)ss->net.icmpv6.Icmp6OutRedirects / deltasec, - (double)ss->net.icmpv6.Icmp6InTimeExcds / deltasec, - (double)ss->net.icmpv6.Icmp6OutTimeExcds / deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s %7.2lf %7.2lf %7.2lf %5.2lf %5.2lf " + "%5.2lf %5.2lf %5.2lf %5.2lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].icmpv6.Icmp6InEchos / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6InEchoReplies / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6OutEchoReplies / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6InDestUnreachs / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6OutDestUnreachs / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6InRedirects / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6OutRedirects / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6InTimeExcds / deltasec, + (double)ss->net.netns[nr].icmpv6.Icmp6OutTimeExcds / deltasec); + } return 1; } @@ -2408,7 +2475,7 @@ ICMPv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, static void udpv6head(int osvers, int osrel, int ossub) { - printf("indgram/s outdgram/s inerr/s noport/s " + printf("netns indgram/s outdgram/s inerr/s noport/s " " _udpv6_"); } @@ -2418,11 +2485,17 @@ udpv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf("%9.1lf %10.1lf %7.2lf %9.2lf\n", - (double)ss->net.udpv6.Udp6InDatagrams / deltasec, - (double)ss->net.udpv6.Udp6OutDatagrams / deltasec, - (double)ss->net.udpv6.Udp6InErrors / deltasec, - (double)ss->net.udpv6.Udp6NoPorts / deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s %9.1lf %10.1lf %7.2lf %9.2lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].udpv6.Udp6InDatagrams / deltasec, + (double)ss->net.netns[nr].udpv6.Udp6OutDatagrams / deltasec, + (double)ss->net.netns[nr].udpv6.Udp6InErrors / deltasec, + (double)ss->net.netns[nr].udpv6.Udp6NoPorts / deltasec); + } return 1; } @@ -2432,7 +2505,7 @@ udpv6line(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, static void tcphead(int osvers, int osrel, int ossub) { - printf("insegs/s outsegs/s actopen/s pasopen/s " + printf("netns insegs/s outsegs/s actopen/s pasopen/s " "nowopen _tcp_"); } @@ -2442,19 +2515,25 @@ tcpline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf("%8.1lf %9.1lf %9.1lf %9.1lf %7lld\n", - (double)ss->net.tcp.InSegs / deltasec, - (double)ss->net.tcp.OutSegs / deltasec, - (double)ss->net.tcp.ActiveOpens / deltasec, - (double)ss->net.tcp.PassiveOpens / deltasec, - ss->net.tcp.CurrEstab); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s %8.1lf %9.1lf %9.1lf %9.1lf %7lld\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].tcp.InSegs / deltasec, + (double)ss->net.netns[nr].tcp.OutSegs / deltasec, + (double)ss->net.netns[nr].tcp.ActiveOpens / deltasec, + (double)ss->net.netns[nr].tcp.PassiveOpens / deltasec, + ss->net.netns[nr].tcp.CurrEstab); + } return 1; } static void TCPhead(int osvers, int osrel, int ossub) { - printf("inerr/s retrans/s attfail/s " + printf("netns inerr/s retrans/s attfail/s " "estabreset/s outreset/s _tcp_"); } @@ -2464,12 +2543,18 @@ TCPline(struct sstat *ss, struct tstat *ts, struct tstat **ps, int nactproc, int osvers, int osrel, int ossub, char *tstamp, int ppres, int ntrun, int ntslpi, int ntslpu, int pexit, int pzombie) { - printf("%7.1lf %9.1lf %9.1lf %12.1lf %10.1lf\n", - (double)ss->net.tcp.InErrs / deltasec, - (double)ss->net.tcp.RetransSegs / deltasec, - (double)ss->net.tcp.AttemptFails / deltasec, - (double)ss->net.tcp.EstabResets / deltasec, - (double)ss->net.tcp.OutRsts / deltasec); + int nr; + + for (nr = 0; nr < ss->net.nrnetns; nr++) + { + printf("%s %7.1lf %9.1lf %9.1lf %12.1lf %10.1lf\n", + ss->net.netns[nr].nsname, + (double)ss->net.netns[nr].tcp.InErrs / deltasec, + (double)ss->net.netns[nr].tcp.RetransSegs / deltasec, + (double)ss->net.netns[nr].tcp.AttemptFails / deltasec, + (double)ss->net.netns[nr].tcp.EstabResets / deltasec, + (double)ss->net.netns[nr].tcp.OutRsts / deltasec); + } return 1; } diff --git a/deviate.c b/deviate.c index 8923cb68..0c984a6d 100644 --- a/deviate.c +++ b/deviate.c @@ -805,178 +805,195 @@ deviatsyst(struct sstat *cur, struct sstat *pre, struct sstat *dev, ** as tables of frequency-counters that have to be subtracted; ** values that do not represent a frequency are corrected afterwards */ - for (cdev = (count_t *)&dev->net.ipv4, - ccur = (count_t *)&cur->net.ipv4, - cpre = (count_t *)&pre->net.ipv4, - i = 0; - i < (sizeof dev->net.ipv4 / sizeof(count_t)); - cdev++, ccur++, cpre++, i++) - *cdev = *ccur - *cpre; - - dev->net.ipv4.Forwarding = cur->net.ipv4.Forwarding; - dev->net.ipv4.DefaultTTL = cur->net.ipv4.DefaultTTL; - - /* ------------- */ - - for (cdev = (count_t *)&dev->net.icmpv4, - ccur = (count_t *)&cur->net.icmpv4, - cpre = (count_t *)&pre->net.icmpv4, - i = 0; - i < (sizeof dev->net.icmpv4 / sizeof(count_t)); - cdev++, ccur++, cpre++, i++) - *cdev = *ccur - *cpre; - - /* ------------- */ - - for (cdev = (count_t *)&dev->net.udpv4, - ccur = (count_t *)&cur->net.udpv4, - cpre = (count_t *)&pre->net.udpv4, - i = 0; - i < (sizeof dev->net.udpv4 / sizeof(count_t)); - cdev++, ccur++, cpre++, i++) - *cdev = *ccur - *cpre; - - /* ------------- */ - - for (cdev = (count_t *)&dev->net.ipv6, - ccur = (count_t *)&cur->net.ipv6, - cpre = (count_t *)&pre->net.ipv6, - i = 0; - i < (sizeof dev->net.ipv6 / sizeof(count_t)); - cdev++, ccur++, cpre++, i++) - *cdev = *ccur - *cpre; - - /* ------------- */ - - for (cdev = (count_t *)&dev->net.icmpv6, - ccur = (count_t *)&cur->net.icmpv6, - cpre = (count_t *)&pre->net.icmpv6, - i = 0; - i < (sizeof dev->net.icmpv6 / sizeof(count_t)); - cdev++, ccur++, cpre++, i++) - *cdev = *ccur - *cpre; - - /* ------------- */ - - for (cdev = (count_t *)&dev->net.udpv6, - ccur = (count_t *)&cur->net.udpv6, - cpre = (count_t *)&pre->net.udpv6, - i = 0; - i < (sizeof dev->net.udpv6 / sizeof(count_t)); - cdev++, ccur++, cpre++, i++) - *cdev = *ccur - *cpre; - - /* ------------- */ - - for (cdev = (count_t *)&dev->net.tcp, - ccur = (count_t *)&cur->net.tcp, - cpre = (count_t *)&pre->net.tcp, - i = 0; - i < (sizeof dev->net.tcp / sizeof(count_t)); - cdev++, ccur++, cpre++, i++) - *cdev = *ccur - *cpre; - - dev->net.tcp.RtoAlgorithm = cur->net.tcp.RtoAlgorithm; - dev->net.tcp.RtoMin = cur->net.tcp.RtoMin; - dev->net.tcp.RtoMax = cur->net.tcp.RtoMax; - dev->net.tcp.MaxConn = cur->net.tcp.MaxConn; - dev->net.tcp.CurrEstab = cur->net.tcp.CurrEstab; + int nr = 0; + dev->net.nrnetns = cur->net.nrnetns; + if (dev->net.nrnetns > 0) + { + for (nr = 0; nr < dev->net.nrnetns; nr++) + { + for (cdev = (count_t *)&dev->net.netns[nr].ipv4, + ccur = (count_t *)&cur->net.netns[nr].ipv4, + cpre = (count_t *)&pre->net.netns[nr].ipv4, + i = 0; + i < (sizeof dev->net.netns[nr].ipv4 / sizeof(count_t)); + cdev++, ccur++, cpre++, i++) + *cdev = *ccur - *cpre; + + dev->net.netns[nr].ipv4.Forwarding = cur->net.netns[nr].ipv4.Forwarding; + dev->net.netns[nr].ipv4.DefaultTTL = cur->net.netns[nr].ipv4.DefaultTTL; + + /* ------------- */ + + for (cdev = (count_t *)&dev->net.netns[nr].icmpv4, + ccur = (count_t *)&cur->net.netns[nr].icmpv4, + cpre = (count_t *)&pre->net.netns[nr].icmpv4, + i = 0; + i < (sizeof dev->net.netns[nr].icmpv4 / sizeof(count_t)); + cdev++, ccur++, cpre++, i++) + *cdev = *ccur - *cpre; + + /* ------------- */ + + for (cdev = (count_t *)&dev->net.netns[nr].udpv4, + ccur = (count_t *)&cur->net.netns[nr].udpv4, + cpre = (count_t *)&pre->net.netns[nr].udpv4, + i = 0; + i < (sizeof dev->net.netns[nr].udpv4 / sizeof(count_t)); + cdev++, ccur++, cpre++, i++) + *cdev = *ccur - *cpre; + + /* ------------- */ + + for (cdev = (count_t *)&dev->net.netns[nr].ipv6, + ccur = (count_t *)&cur->net.netns[nr].ipv6, + cpre = (count_t *)&pre->net.netns[nr].ipv6, + i = 0; + i < (sizeof dev->net.netns[nr].ipv6 / sizeof(count_t)); + cdev++, ccur++, cpre++, i++) + *cdev = *ccur - *cpre; + + /* ------------- */ + + for (cdev = (count_t *)&dev->net.netns[nr].icmpv6, + ccur = (count_t *)&cur->net.netns[nr].icmpv6, + cpre = (count_t *)&pre->net.netns[nr].icmpv6, + i = 0; + i < (sizeof dev->net.netns[nr].icmpv6 / sizeof(count_t)); + cdev++, ccur++, cpre++, i++) + *cdev = *ccur - *cpre; + + /* ------------- */ + + for (cdev = (count_t *)&dev->net.netns[nr].udpv6, + ccur = (count_t *)&cur->net.netns[nr].udpv6, + cpre = (count_t *)&pre->net.netns[nr].udpv6, + i = 0; + i < (sizeof dev->net.netns[nr].udpv6 / sizeof(count_t)); + cdev++, ccur++, cpre++, i++) + *cdev = *ccur - *cpre; + + /* ------------- */ + + for (cdev = (count_t *)&dev->net.netns[nr].tcp, + ccur = (count_t *)&cur->net.netns[nr].tcp, + cpre = (count_t *)&pre->net.netns[nr].tcp, + i = 0; + i < (sizeof dev->net.netns[nr].tcp / sizeof(count_t)); + cdev++, ccur++, cpre++, i++) + *cdev = *ccur - *cpre; + + dev->net.netns[nr].tcp.RtoAlgorithm = cur->net.netns[nr].tcp.RtoAlgorithm; + dev->net.netns[nr].tcp.RtoMin = cur->net.netns[nr].tcp.RtoMin; + dev->net.netns[nr].tcp.RtoMax = cur->net.netns[nr].tcp.RtoMax; + dev->net.netns[nr].tcp.MaxConn = cur->net.netns[nr].tcp.MaxConn; + dev->net.netns[nr].tcp.CurrEstab = cur->net.netns[nr].tcp.CurrEstab; + strcpy(dev->net.netns[nr].nsname, cur->net.netns[nr].nsname); + } + } /* ** calculate deviations for interfaces */ - if (pre->intf.intf[0].name[0] == '\0') /* first sample? */ - { - for (i=0; cur->intf.intf[i].name[0]; i++) - { - strcpy(pre->intf.intf[i].name, cur->intf.intf[i].name); - - pre->intf.intf[i].type = cur->intf.intf[i].type; - pre->intf.intf[i].speed = cur->intf.intf[i].speed; - pre->intf.intf[i].speedp = cur->intf.intf[i].speedp; - pre->intf.intf[i].duplex = cur->intf.intf[i].duplex; - } - } - - for (i=0, j=0; cur->intf.intf[i].name[0]; i++, j++) + dev->intf.nrintfns = cur->intf.nrintfns; + if (dev->intf.nrintfns > 0) { - /* - ** be sure that we have the same interface - ** (interfaces could have been added or removed since - ** previous sample) - */ - if (strcmp(cur->intf.intf[i].name, pre->intf.intf[j].name) != 0) + for (nr = 0; nr < dev->intf.nrintfns; nr++) { - // try to resync - for (j=0; pre->intf.intf[j].name[0]; j++) + if (pre->intf.intfns[nr].intf[0].name[0] == '\0') /* first sample? */ { - if (strcmp(cur->intf.intf[i].name, - pre->intf.intf[j].name) == 0) - break; + for (i=0; cur->intf.intfns[nr].intf[i].name[0]; i++) + { + strcpy(pre->intf.intfns[nr].intf[i].name, cur->intf.intfns[nr].intf[i].name); + + pre->intf.intfns[nr].intf[i].type = cur->intf.intfns[nr].intf[i].type; + pre->intf.intfns[nr].intf[i].speed = cur->intf.intfns[nr].intf[i].speed; + pre->intf.intfns[nr].intf[i].speedp = cur->intf.intfns[nr].intf[i].speedp; + pre->intf.intfns[nr].intf[i].duplex = cur->intf.intfns[nr].intf[i].duplex; + } } - // resync not succeeded? - if (! pre->intf.intf[j].name[0]) + for (i=0, j=0; cur->intf.intfns[nr].intf[i].name[0]; i++, j++) { - memcpy(&dev->intf.intf[i], - &cur->intf.intf[i], - sizeof cur->intf.intf[i]); + /* + ** be sure that we have the same interface + ** (interfaces could have been added or removed since + ** previous sample) + */ + if (strcmp(cur->intf.intfns[nr].intf[i].name, pre->intf.intfns[nr].intf[j].name) != 0) + { + // try to resync + for (j=0; pre->intf.intfns[nr].intf[j].name[0]; j++) + { + if (strcmp(cur->intf.intfns[nr].intf[i].name, + pre->intf.intfns[nr].intf[j].name) == 0) + break; + } + + // resync not succeeded? + if (! pre->intf.intfns[nr].intf[j].name[0]) + { + memcpy(&dev->intf.intfns[nr].intf[i], + &cur->intf.intfns[nr].intf[i], + sizeof cur->intf.intfns[nr].intf[i]); + + j = 0; + continue; + } + } - j = 0; - continue; + /* + ** calculate interface deviations for this sample + */ + strcpy(dev->intf.intfns[nr].intf[i].name, cur->intf.intfns[nr].intf[i].name); + + dev->intf.intfns[nr].intf[i].rbyte = subcount(cur->intf.intfns[nr].intf[i].rbyte, + pre->intf.intfns[nr].intf[j].rbyte); + dev->intf.intfns[nr].intf[i].rpack = subcount(cur->intf.intfns[nr].intf[i].rpack, + pre->intf.intfns[nr].intf[j].rpack); + dev->intf.intfns[nr].intf[i].rerrs = subcount(cur->intf.intfns[nr].intf[i].rerrs, + pre->intf.intfns[nr].intf[j].rerrs); + dev->intf.intfns[nr].intf[i].rdrop = subcount(cur->intf.intfns[nr].intf[i].rdrop, + pre->intf.intfns[nr].intf[j].rdrop); + dev->intf.intfns[nr].intf[i].rfifo = subcount(cur->intf.intfns[nr].intf[i].rfifo, + pre->intf.intfns[nr].intf[j].rfifo); + dev->intf.intfns[nr].intf[i].rframe= subcount(cur->intf.intfns[nr].intf[i].rframe, + pre->intf.intfns[nr].intf[j].rframe); + dev->intf.intfns[nr].intf[i].rcompr= subcount(cur->intf.intfns[nr].intf[i].rcompr, + pre->intf.intfns[nr].intf[j].rcompr); + dev->intf.intfns[nr].intf[i].rmultic=subcount(cur->intf.intfns[nr].intf[i].rmultic, + pre->intf.intfns[nr].intf[j].rmultic); + + dev->intf.intfns[nr].intf[i].sbyte = subcount(cur->intf.intfns[nr].intf[i].sbyte, + pre->intf.intfns[nr].intf[j].sbyte); + dev->intf.intfns[nr].intf[i].spack = subcount(cur->intf.intfns[nr].intf[i].spack, + pre->intf.intfns[nr].intf[j].spack); + dev->intf.intfns[nr].intf[i].serrs = subcount(cur->intf.intfns[nr].intf[i].serrs, + pre->intf.intfns[nr].intf[j].serrs); + dev->intf.intfns[nr].intf[i].sdrop = subcount(cur->intf.intfns[nr].intf[i].sdrop, + pre->intf.intfns[nr].intf[j].sdrop); + dev->intf.intfns[nr].intf[i].sfifo = subcount(cur->intf.intfns[nr].intf[i].sfifo, + pre->intf.intfns[nr].intf[j].sfifo); + dev->intf.intfns[nr].intf[i].scollis= subcount(cur->intf.intfns[nr].intf[i].scollis, + pre->intf.intfns[nr].intf[j].scollis); + dev->intf.intfns[nr].intf[i].scarrier= subcount(cur->intf.intfns[nr].intf[i].scarrier, + pre->intf.intfns[nr].intf[j].scarrier); + dev->intf.intfns[nr].intf[i].scompr= subcount(cur->intf.intfns[nr].intf[i].scompr, + pre->intf.intfns[nr].intf[j].scompr); + + dev->intf.intfns[nr].intf[i].type = cur->intf.intfns[nr].intf[i].type; + dev->intf.intfns[nr].intf[i].duplex = cur->intf.intfns[nr].intf[i].duplex; + dev->intf.intfns[nr].intf[i].speed = cur->intf.intfns[nr].intf[i].speed; + dev->intf.intfns[nr].intf[i].speedp = pre->intf.intfns[nr].intf[j].speed; + + cur->intf.intfns[nr].intf[i].speedp = pre->intf.intfns[nr].intf[j].speed; } - } - /* - ** calculate interface deviations for this sample - */ - strcpy(dev->intf.intf[i].name, cur->intf.intf[i].name); - - dev->intf.intf[i].rbyte = subcount(cur->intf.intf[i].rbyte, - pre->intf.intf[j].rbyte); - dev->intf.intf[i].rpack = subcount(cur->intf.intf[i].rpack, - pre->intf.intf[j].rpack); - dev->intf.intf[i].rerrs = subcount(cur->intf.intf[i].rerrs, - pre->intf.intf[j].rerrs); - dev->intf.intf[i].rdrop = subcount(cur->intf.intf[i].rdrop, - pre->intf.intf[j].rdrop); - dev->intf.intf[i].rfifo = subcount(cur->intf.intf[i].rfifo, - pre->intf.intf[j].rfifo); - dev->intf.intf[i].rframe= subcount(cur->intf.intf[i].rframe, - pre->intf.intf[j].rframe); - dev->intf.intf[i].rcompr= subcount(cur->intf.intf[i].rcompr, - pre->intf.intf[j].rcompr); - dev->intf.intf[i].rmultic=subcount(cur->intf.intf[i].rmultic, - pre->intf.intf[j].rmultic); - - dev->intf.intf[i].sbyte = subcount(cur->intf.intf[i].sbyte, - pre->intf.intf[j].sbyte); - dev->intf.intf[i].spack = subcount(cur->intf.intf[i].spack, - pre->intf.intf[j].spack); - dev->intf.intf[i].serrs = subcount(cur->intf.intf[i].serrs, - pre->intf.intf[j].serrs); - dev->intf.intf[i].sdrop = subcount(cur->intf.intf[i].sdrop, - pre->intf.intf[j].sdrop); - dev->intf.intf[i].sfifo = subcount(cur->intf.intf[i].sfifo, - pre->intf.intf[j].sfifo); - dev->intf.intf[i].scollis= subcount(cur->intf.intf[i].scollis, - pre->intf.intf[j].scollis); - dev->intf.intf[i].scarrier= subcount(cur->intf.intf[i].scarrier, - pre->intf.intf[j].scarrier); - dev->intf.intf[i].scompr= subcount(cur->intf.intf[i].scompr, - pre->intf.intf[j].scompr); - - dev->intf.intf[i].type = cur->intf.intf[i].type; - dev->intf.intf[i].duplex = cur->intf.intf[i].duplex; - dev->intf.intf[i].speed = cur->intf.intf[i].speed; - dev->intf.intf[i].speedp = pre->intf.intf[j].speed; - - cur->intf.intf[i].speedp = pre->intf.intf[j].speed; + dev->intf.intfns[nr].intf[i].name[0] = '\0'; + dev->intf.intfns[nr].nrintf = i; + strcpy(dev->intf.intfns[nr].nsname, cur->intf.intfns[nr].nsname); + } } - dev->intf.intf[i].name[0] = '\0'; - dev->intf.nrintf = i; - /* ** calculate deviations for disks */ @@ -1567,127 +1584,142 @@ totalsyst(char category, struct sstat *new, struct sstat *tot) ** values that do not represent a frequency are corrected ** afterwards */ - for (ctot = (count_t *)&tot->net.ipv4, - cnew = (count_t *)&new->net.ipv4, i = 0; - i < (sizeof tot->net.ipv4 / sizeof(count_t)); - ctot++, cnew++, i++) - *ctot += *cnew; - - tot->net.ipv4.Forwarding = new->net.ipv4.Forwarding; - tot->net.ipv4.DefaultTTL = new->net.ipv4.DefaultTTL; - - /* ------------- */ - - for (ctot = (count_t *)&tot->net.icmpv4, - cnew = (count_t *)&new->net.icmpv4, i = 0; - i < (sizeof tot->net.icmpv4 / sizeof(count_t)); - ctot++, cnew++, i++) - *ctot += *cnew; - - /* ------------- */ - - for (ctot = (count_t *)&tot->net.udpv4, - cnew = (count_t *)&new->net.udpv4, i = 0; - i < (sizeof tot->net.udpv4 / sizeof(count_t)); - ctot++, cnew++, i++) - *ctot += *cnew; - - /* ------------- */ - - for (ctot = (count_t *)&tot->net.ipv6, - cnew = (count_t *)&new->net.ipv6, i = 0; - i < (sizeof tot->net.ipv6 / sizeof(count_t)); - ctot++, cnew++, i++) - *ctot += *cnew; - - /* ------------- */ - - for (ctot = (count_t *)&tot->net.icmpv6, - cnew = (count_t *)&new->net.icmpv6, i = 0; - i < (sizeof tot->net.icmpv6 / sizeof(count_t)); - ctot++, cnew++, i++) - *ctot += *cnew; - - /* ------------- */ - - for (ctot = (count_t *)&tot->net.udpv6, - cnew = (count_t *)&new->net.udpv6, i = 0; - i < (sizeof tot->net.udpv6 / sizeof(count_t)); - ctot++, cnew++, i++) - *ctot += *cnew; - - /* ------------- */ - - for (ctot = (count_t *)&tot->net.tcp, - cnew = (count_t *)&new->net.tcp, i = 0; - i < (sizeof tot->net.tcp / sizeof(count_t)); - ctot++, cnew++, i++) - *ctot += *cnew; - - tot->net.tcp.RtoAlgorithm = new->net.tcp.RtoAlgorithm; - tot->net.tcp.RtoMin = new->net.tcp.RtoMin; - tot->net.tcp.RtoMax = new->net.tcp.RtoMax; - tot->net.tcp.MaxConn = new->net.tcp.MaxConn; - tot->net.tcp.CurrEstab = new->net.tcp.CurrEstab; - - for (i=0; new->intf.intf[i].name[0]; i++) + int nr = 0; + if (new->net.nrnetns > 0) { - /* - ** check if an interface has been added or removed; - ** in that case, zero all counters - */ - if (strcmp(new->intf.intf[i].name, - tot->intf.intf[i].name) != 0) + for (nr = 0; nr < new->net.nrnetns; nr++) { - tot->intf.intf[i].rbyte = 0; - tot->intf.intf[i].rpack = 0; - tot->intf.intf[i].rerrs = 0; - tot->intf.intf[i].rdrop = 0; - tot->intf.intf[i].rfifo = 0; - tot->intf.intf[i].rframe = 0; - tot->intf.intf[i].rcompr = 0; - tot->intf.intf[i].rmultic = 0; - - tot->intf.intf[i].sbyte = 0; - tot->intf.intf[i].spack = 0; - tot->intf.intf[i].serrs = 0; - tot->intf.intf[i].sdrop = 0; - tot->intf.intf[i].sfifo = 0; - tot->intf.intf[i].scollis = 0; - tot->intf.intf[i].scarrier = 0; - tot->intf.intf[i].scompr = 0; + for (ctot = (count_t *)&tot->net.netns[nr].ipv4, + cnew = (count_t *)&new->net.netns[nr].ipv4, i = 0; + i < (sizeof tot->net.netns[nr].ipv4 / sizeof(count_t)); + ctot++, cnew++, i++) + *ctot += *cnew; + + tot->net.netns[nr].ipv4.Forwarding = new->net.netns[nr].ipv4.Forwarding; + tot->net.netns[nr].ipv4.DefaultTTL = new->net.netns[nr].ipv4.DefaultTTL; + + /* ------------- */ + + for (ctot = (count_t *)&tot->net.netns[nr].icmpv4, + cnew = (count_t *)&new->net.netns[nr].icmpv4, i = 0; + i < (sizeof tot->net.netns[nr].icmpv4 / sizeof(count_t)); + ctot++, cnew++, i++) + *ctot += *cnew; + + /* ------------- */ + + for (ctot = (count_t *)&tot->net.netns[nr].udpv4, + cnew = (count_t *)&new->net.netns[nr].udpv4, i = 0; + i < (sizeof tot->net.netns[nr].udpv4 / sizeof(count_t)); + ctot++, cnew++, i++) + *ctot += *cnew; + + /* ------------- */ + + for (ctot = (count_t *)&tot->net.netns[nr].ipv6, + cnew = (count_t *)&new->net.netns[nr].ipv6, i = 0; + i < (sizeof tot->net.netns[nr].ipv6 / sizeof(count_t)); + ctot++, cnew++, i++) + *ctot += *cnew; + + /* ------------- */ + + for (ctot = (count_t *)&tot->net.netns[nr].icmpv6, + cnew = (count_t *)&new->net.netns[nr].icmpv6, i = 0; + i < (sizeof tot->net.netns[nr].icmpv6 / sizeof(count_t)); + ctot++, cnew++, i++) + *ctot += *cnew; + + /* ------------- */ + + for (ctot = (count_t *)&tot->net.netns[nr].udpv6, + cnew = (count_t *)&new->net.netns[nr].udpv6, i = 0; + i < (sizeof tot->net.netns[nr].udpv6 / sizeof(count_t)); + ctot++, cnew++, i++) + *ctot += *cnew; + + /* ------------- */ + + for (ctot = (count_t *)&tot->net.netns[nr].tcp, + cnew = (count_t *)&new->net.netns[nr].tcp, i = 0; + i < (sizeof tot->net.netns[nr].tcp / sizeof(count_t)); + ctot++, cnew++, i++) + *ctot += *cnew; + + tot->net.netns[nr].tcp.RtoAlgorithm = new->net.netns[nr].tcp.RtoAlgorithm; + tot->net.netns[nr].tcp.RtoMin = new->net.netns[nr].tcp.RtoMin; + tot->net.netns[nr].tcp.RtoMax = new->net.netns[nr].tcp.RtoMax; + tot->net.netns[nr].tcp.MaxConn = new->net.netns[nr].tcp.MaxConn; + tot->net.netns[nr].tcp.CurrEstab = new->net.netns[nr].tcp.CurrEstab; + strcpy(tot->net.netns[nr].nsname, new->net.netns[nr].nsname); + } + } + + if (new->intf.nrintfns > 0) + { + for (nr = 0; nr < new->intf.nrintfns; nr++) + { + for (i=0; new->intf.intfns[nr].intf[i].name[0]; i++) + { + /* + ** check if an interface has been added or removed; + ** in that case, zero all counters + */ + if (strcmp(new->intf.intfns[nr].intf[i].name, + tot->intf.intfns[nr].intf[i].name) != 0) + { + tot->intf.intfns[nr].intf[i].rbyte = 0; + tot->intf.intfns[nr].intf[i].rpack = 0; + tot->intf.intfns[nr].intf[i].rerrs = 0; + tot->intf.intfns[nr].intf[i].rdrop = 0; + tot->intf.intfns[nr].intf[i].rfifo = 0; + tot->intf.intfns[nr].intf[i].rframe = 0; + tot->intf.intfns[nr].intf[i].rcompr = 0; + tot->intf.intfns[nr].intf[i].rmultic = 0; + + tot->intf.intfns[nr].intf[i].sbyte = 0; + tot->intf.intfns[nr].intf[i].spack = 0; + tot->intf.intfns[nr].intf[i].serrs = 0; + tot->intf.intfns[nr].intf[i].sdrop = 0; + tot->intf.intfns[nr].intf[i].sfifo = 0; + tot->intf.intfns[nr].intf[i].scollis = 0; + tot->intf.intfns[nr].intf[i].scarrier = 0; + tot->intf.intfns[nr].intf[i].scompr = 0; + } + + /* + ** accumulate counters for this sample + */ + strcpy(tot->intf.intfns[nr].intf[i].name, new->intf.intfns[nr].intf[i].name); + + tot->intf.intfns[nr].intf[i].rbyte += new->intf.intfns[nr].intf[i].rbyte; + tot->intf.intfns[nr].intf[i].rpack += new->intf.intfns[nr].intf[i].rpack; + tot->intf.intfns[nr].intf[i].rerrs += new->intf.intfns[nr].intf[i].rerrs; + tot->intf.intfns[nr].intf[i].rdrop += new->intf.intfns[nr].intf[i].rdrop; + tot->intf.intfns[nr].intf[i].rfifo += new->intf.intfns[nr].intf[i].rfifo; + tot->intf.intfns[nr].intf[i].rframe += new->intf.intfns[nr].intf[i].rframe; + tot->intf.intfns[nr].intf[i].rcompr += new->intf.intfns[nr].intf[i].rcompr; + tot->intf.intfns[nr].intf[i].rmultic += new->intf.intfns[nr].intf[i].rmultic; + + tot->intf.intfns[nr].intf[i].sbyte += new->intf.intfns[nr].intf[i].sbyte; + tot->intf.intfns[nr].intf[i].spack += new->intf.intfns[nr].intf[i].spack; + tot->intf.intfns[nr].intf[i].serrs += new->intf.intfns[nr].intf[i].serrs; + tot->intf.intfns[nr].intf[i].sdrop += new->intf.intfns[nr].intf[i].sdrop; + tot->intf.intfns[nr].intf[i].sfifo += new->intf.intfns[nr].intf[i].sfifo; + tot->intf.intfns[nr].intf[i].scollis += new->intf.intfns[nr].intf[i].scollis; + tot->intf.intfns[nr].intf[i].scarrier+= new->intf.intfns[nr].intf[i].scarrier; + tot->intf.intfns[nr].intf[i].scompr += new->intf.intfns[nr].intf[i].scompr; + + tot->intf.intfns[nr].intf[i].type = new->intf.intfns[nr].intf[i].type; + tot->intf.intfns[nr].intf[i].speed = new->intf.intfns[nr].intf[i].speed; + tot->intf.intfns[nr].intf[i].duplex = new->intf.intfns[nr].intf[i].duplex; + } + + tot->intf.intfns[nr].intf[i].name[0] = '\0'; + tot->intf.intfns[nr].nrintf = i; + strcpy(tot->intf.intfns[nr].nsname, new->intf.intfns[nr].nsname); } - - /* - ** accumulate counters for this sample - */ - strcpy(tot->intf.intf[i].name, new->intf.intf[i].name); - - tot->intf.intf[i].rbyte += new->intf.intf[i].rbyte; - tot->intf.intf[i].rpack += new->intf.intf[i].rpack; - tot->intf.intf[i].rerrs += new->intf.intf[i].rerrs; - tot->intf.intf[i].rdrop += new->intf.intf[i].rdrop; - tot->intf.intf[i].rfifo += new->intf.intf[i].rfifo; - tot->intf.intf[i].rframe += new->intf.intf[i].rframe; - tot->intf.intf[i].rcompr += new->intf.intf[i].rcompr; - tot->intf.intf[i].rmultic += new->intf.intf[i].rmultic; - - tot->intf.intf[i].sbyte += new->intf.intf[i].sbyte; - tot->intf.intf[i].spack += new->intf.intf[i].spack; - tot->intf.intf[i].serrs += new->intf.intf[i].serrs; - tot->intf.intf[i].sdrop += new->intf.intf[i].sdrop; - tot->intf.intf[i].sfifo += new->intf.intf[i].sfifo; - tot->intf.intf[i].scollis += new->intf.intf[i].scollis; - tot->intf.intf[i].scarrier+= new->intf.intf[i].scarrier; - tot->intf.intf[i].scompr += new->intf.intf[i].scompr; - - tot->intf.intf[i].type = new->intf.intf[i].type; - tot->intf.intf[i].speed = new->intf.intf[i].speed; - tot->intf.intf[i].duplex = new->intf.intf[i].duplex; } - - tot->intf.intf[i].name[0] = '\0'; - tot->intf.nrintf = i; #if HTTPSTATS tot->www.accesses += new->www.accesses; @@ -1716,14 +1748,14 @@ totalsyst(char category, struct sstat *new, struct sstat *tot) } } - + tot->dsk.dsk[i].name[0] = '\0'; tot->dsk.ndsk = i; for (i=0; new->dsk.lvm[i].name[0]; i++) { strcpy(tot->dsk.lvm[i].name, new->dsk.lvm[i].name); - + tot->dsk.lvm[i].nread += new->dsk.lvm[i].nread; tot->dsk.lvm[i].nrsect += new->dsk.lvm[i].nrsect; tot->dsk.lvm[i].nwrite += new->dsk.lvm[i].nwrite; @@ -1737,14 +1769,14 @@ totalsyst(char category, struct sstat *new, struct sstat *tot) tot->dsk.lvm[i].ndsect += new->dsk.lvm[i].ndsect; } } - + tot->dsk.lvm[i].name[0] = '\0'; tot->dsk.nlvm = i; for (i=0; new->dsk.mdd[i].name[0]; i++) { strcpy(tot->dsk.mdd[i].name, new->dsk.mdd[i].name); - + tot->dsk.mdd[i].nread += new->dsk.mdd[i].nread; tot->dsk.mdd[i].nrsect += new->dsk.mdd[i].nrsect; tot->dsk.mdd[i].nwrite += new->dsk.mdd[i].nwrite; @@ -1758,7 +1790,7 @@ totalsyst(char category, struct sstat *new, struct sstat *tot) tot->dsk.mdd[i].ndsect += new->dsk.lvm[i].ndsect; } } - + tot->dsk.mdd[i].name[0] = '\0'; tot->dsk.nmdd = i; break; diff --git a/json.c b/json.c index 09ddbf99..ea997bb6 100644 --- a/json.c +++ b/json.c @@ -726,68 +726,82 @@ static void json_print_NFS(char *hp, struct sstat *ss, struct tstat *ps, int nac static void json_print_NET(char *hp, struct sstat *ss, struct tstat *ps, int nact) { - register int i; + register int i, nr; - printf(", \"NET_GENERAL\": {" - "\"rpacketsTCP\": %lld, " - "\"spacketsTCP\": %lld, " - "\"activeOpensTCP\": %lld, " - "\"passiveOpensTCP\": %lld, " - "\"retransSegsTCP\": %lld, " - "\"rpacketsUDP\": %lld, " - "\"spacketsUDP\": %lld, " - "\"rpacketsIP\": %lld, " - "\"spacketsIP\": %lld, " - "\"dpacketsIP\": %lld, " - "\"fpacketsIP\": %lld, " - "\"icmpi\" : %lld, " - "\"icmpo\" : %lld}", - ss->net.tcp.InSegs, - ss->net.tcp.OutSegs, - ss->net.tcp.ActiveOpens, - ss->net.tcp.PassiveOpens, - ss->net.tcp.RetransSegs, - ss->net.udpv4.InDatagrams + - ss->net.udpv6.Udp6InDatagrams, - ss->net.udpv4.OutDatagrams + - ss->net.udpv6.Udp6OutDatagrams, - ss->net.ipv4.InReceives + - ss->net.ipv6.Ip6InReceives, - ss->net.ipv4.OutRequests + - ss->net.ipv6.Ip6OutRequests, - ss->net.ipv4.InDelivers + - ss->net.ipv6.Ip6InDelivers, - ss->net.ipv4.ForwDatagrams + - ss->net.ipv6.Ip6OutForwDatagrams, - ss->net.icmpv4.InMsgs + - ss->net.icmpv6.Icmp6InMsgs, - ss->net.icmpv4.OutMsgs + - ss->net.icmpv6.Icmp6OutMsgs); + printf(", \"NET_GENERAL\": ["); + for (nr = 0; nr < ss->net.nrnetns; nr++) { + if (nr > 0) { + printf(", "); + } + printf("{\"netns\": \"%.19s\", " + "\"rpacketsTCP\": %lld, " + "\"spacketsTCP\": %lld, " + "\"activeOpensTCP\": %lld, " + "\"passiveOpensTCP\": %lld, " + "\"retransSegsTCP\": %lld, " + "\"rpacketsUDP\": %lld, " + "\"spacketsUDP\": %lld, " + "\"rpacketsIP\": %lld, " + "\"spacketsIP\": %lld, " + "\"dpacketsIP\": %lld, " + "\"fpacketsIP\": %lld, " + "\"icmpi\" : %lld, " + "\"icmpo\" : %lld}", + ss->net.netns[nr].nsname, + ss->net.netns[nr].tcp.InSegs, + ss->net.netns[nr].tcp.OutSegs, + ss->net.netns[nr].tcp.ActiveOpens, + ss->net.netns[nr].tcp.PassiveOpens, + ss->net.netns[nr].tcp.RetransSegs, + ss->net.netns[nr].udpv4.InDatagrams + + ss->net.netns[nr].udpv6.Udp6InDatagrams, + ss->net.netns[nr].udpv4.OutDatagrams + + ss->net.netns[nr].udpv6.Udp6OutDatagrams, + ss->net.netns[nr].ipv4.InReceives + + ss->net.netns[nr].ipv6.Ip6InReceives, + ss->net.netns[nr].ipv4.OutRequests + + ss->net.netns[nr].ipv6.Ip6OutRequests, + ss->net.netns[nr].ipv4.InDelivers + + ss->net.netns[nr].ipv6.Ip6InDelivers, + ss->net.netns[nr].ipv4.ForwDatagrams + + ss->net.netns[nr].ipv6.Ip6OutForwDatagrams, + ss->net.netns[nr].icmpv4.InMsgs + + ss->net.netns[nr].icmpv6.Icmp6InMsgs, + ss->net.netns[nr].icmpv4.OutMsgs + + ss->net.netns[nr].icmpv6.Icmp6OutMsgs); + } - printf(", %s: [", hp); + printf(", %s: [", hp); - for (i = 0; ss->intf.intf[i].name[0]; i++) { - if (i > 0) { + for (nr = 0; nr < ss->intf.nrintfns; nr++) { + if (nr > 0) { printf(", "); } - printf("{\"name\": \"%.19s\", " - "\"rpack\": %lld, " - "\"rbyte\": %lld, " - "\"rerrs\": %lld, " - "\"spack\": %lld, " - "\"sbyte\": %lld, " - "\"serrs\": %lld, " - "\"speed\": \"%ld\", " - "\"duplex\": %d}", - ss->intf.intf[i].name, - ss->intf.intf[i].rpack, - ss->intf.intf[i].rbyte, - ss->intf.intf[i].rerrs, - ss->intf.intf[i].spack, - ss->intf.intf[i].sbyte, - ss->intf.intf[i].serrs, - ss->intf.intf[i].speed, - ss->intf.intf[i].duplex); + for (i = 0; ss->intf.intfns[nr].intf[i].name[0]; i++) { + if (i > 0) { + printf(", "); + } + printf("{\"name\": \"%.19s\", " + "\"netns\": \"%.12s\", " + "\"rpack\": %lld, " + "\"rbyte\": %lld, " + "\"rerrs\": %lld, " + "\"spack\": %lld, " + "\"sbyte\": %lld, " + "\"serrs\": %lld, " + "\"speed\": \"%ld\", " + "\"duplex\": %d}", + ss->intf.intfns[nr].intf[i].name, + ss->intf.intfns[nr].nsname, + ss->intf.intfns[nr].intf[i].rpack, + ss->intf.intfns[nr].intf[i].rbyte, + ss->intf.intfns[nr].intf[i].rerrs, + ss->intf.intfns[nr].intf[i].spack, + ss->intf.intfns[nr].intf[i].sbyte, + ss->intf.intfns[nr].intf[i].serrs, + ss->intf.intfns[nr].intf[i].speed, + ss->intf.intfns[nr].intf[i].duplex); + } } printf("]"); diff --git a/parseable.c b/parseable.c index ebf2207c..ef398a3f 100644 --- a/parseable.c +++ b/parseable.c @@ -598,47 +598,51 @@ print_NFS(char *hp, struct sstat *ss, struct tstat *ps, int nact) void print_NET(char *hp, struct sstat *ss, struct tstat *ps, int nact) { - register int i; + register int i, nr; - printf( "%s %s %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n", - hp, + for (nr = 0; nr < ss->net.nrnetns; nr++) { + printf( "%s %s %s %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n", + hp, ss->net.netns[nr].nsname, "upper", - ss->net.tcp.InSegs, - ss->net.tcp.OutSegs, - ss->net.udpv4.InDatagrams + - ss->net.udpv6.Udp6InDatagrams, - ss->net.udpv4.OutDatagrams + - ss->net.udpv6.Udp6OutDatagrams, - ss->net.ipv4.InReceives + - ss->net.ipv6.Ip6InReceives, - ss->net.ipv4.OutRequests + - ss->net.ipv6.Ip6OutRequests, - ss->net.ipv4.InDelivers + - ss->net.ipv6.Ip6InDelivers, - ss->net.ipv4.ForwDatagrams + - ss->net.ipv6.Ip6OutForwDatagrams, - ss->net.udpv4.InErrors + - ss->net.udpv6.Udp6InErrors, - ss->net.udpv4.NoPorts + - ss->net.udpv6.Udp6NoPorts, - ss->net.tcp.ActiveOpens, - ss->net.tcp.PassiveOpens, - ss->net.tcp.CurrEstab, - ss->net.tcp.RetransSegs, - ss->net.tcp.InErrs, - ss->net.tcp.OutRsts); - - for (i=0; ss->intf.intf[i].name[0]; i++) - { - printf( "%s %s %lld %lld %lld %lld %ld %d\n", - hp, - ss->intf.intf[i].name, - ss->intf.intf[i].rpack, - ss->intf.intf[i].rbyte, - ss->intf.intf[i].spack, - ss->intf.intf[i].sbyte, - ss->intf.intf[i].speed, - ss->intf.intf[i].duplex); + ss->net.netns[nr].tcp.InSegs, + ss->net.netns[nr].tcp.OutSegs, + ss->net.netns[nr].udpv4.InDatagrams + + ss->net.netns[nr].udpv6.Udp6InDatagrams, + ss->net.netns[nr].udpv4.OutDatagrams + + ss->net.netns[nr].udpv6.Udp6OutDatagrams, + ss->net.netns[nr].ipv4.InReceives + + ss->net.netns[nr].ipv6.Ip6InReceives, + ss->net.netns[nr].ipv4.OutRequests + + ss->net.netns[nr].ipv6.Ip6OutRequests, + ss->net.netns[nr].ipv4.InDelivers + + ss->net.netns[nr].ipv6.Ip6InDelivers, + ss->net.netns[nr].ipv4.ForwDatagrams + + ss->net.netns[nr].ipv6.Ip6OutForwDatagrams, + ss->net.netns[nr].udpv4.InErrors + + ss->net.netns[nr].udpv6.Udp6InErrors, + ss->net.netns[nr].udpv4.NoPorts + + ss->net.netns[nr].udpv6.Udp6NoPorts, + ss->net.netns[nr].tcp.ActiveOpens, + ss->net.netns[nr].tcp.PassiveOpens, + ss->net.netns[nr].tcp.CurrEstab, + ss->net.netns[nr].tcp.RetransSegs, + ss->net.netns[nr].tcp.InErrs, + ss->net.netns[nr].tcp.OutRsts); + } + + for (nr = 0; nr < ss->intf.nrintfns; nr++) { + for (i=0; ss->intf.intfns[nr].intf[i].name[0]; i++) + { + printf( "%s %s %s %lld %lld %lld %lld %ld %d\n", + hp, ss->intf.intfns[nr].nsname, + ss->intf.intfns[nr].intf[i].name, + ss->intf.intfns[nr].intf[i].rpack, + ss->intf.intfns[nr].intf[i].rbyte, + ss->intf.intfns[nr].intf[i].spack, + ss->intf.intfns[nr].intf[i].sbyte, + ss->intf.intfns[nr].intf[i].speed, + ss->intf.intfns[nr].intf[i].duplex); + } } } diff --git a/photosyst.c b/photosyst.c index e7604e3c..8c5551a0 100644 --- a/photosyst.c +++ b/photosyst.c @@ -1066,23 +1066,23 @@ photosyst(struct sstat *si) "%15s %lld %lld %lld %lld %lld %lld %lld " "%lld %lld %lld %lld %lld %lld %lld %lld " "%lld\n", - si->intf.intf[i].name, - &(si->intf.intf[i].rbyte), - &(si->intf.intf[i].rpack), - &(si->intf.intf[i].rerrs), - &(si->intf.intf[i].rdrop), - &(si->intf.intf[i].rfifo), - &(si->intf.intf[i].rframe), - &(si->intf.intf[i].rcompr), - &(si->intf.intf[i].rmultic), - &(si->intf.intf[i].sbyte), - &(si->intf.intf[i].spack), - &(si->intf.intf[i].serrs), - &(si->intf.intf[i].sdrop), - &(si->intf.intf[i].sfifo), - &(si->intf.intf[i].scollis), - &(si->intf.intf[i].scarrier), - &(si->intf.intf[i].scompr)); + si->intf.intfns[0].intf[i].name, + &(si->intf.intfns[0].intf[i].rbyte), + &(si->intf.intfns[0].intf[i].rpack), + &(si->intf.intfns[0].intf[i].rerrs), + &(si->intf.intfns[0].intf[i].rdrop), + &(si->intf.intfns[0].intf[i].rfifo), + &(si->intf.intfns[0].intf[i].rframe), + &(si->intf.intfns[0].intf[i].rcompr), + &(si->intf.intfns[0].intf[i].rmultic), + &(si->intf.intfns[0].intf[i].sbyte), + &(si->intf.intfns[0].intf[i].spack), + &(si->intf.intfns[0].intf[i].serrs), + &(si->intf.intfns[0].intf[i].sdrop), + &(si->intf.intfns[0].intf[i].sfifo), + &(si->intf.intfns[0].intf[i].scollis), + &(si->intf.intfns[0].intf[i].scarrier), + &(si->intf.intfns[0].intf[i].scompr)); /* ** skip header line and lines without stats @@ -1096,7 +1096,7 @@ photosyst(struct sstat *si) ** because the total number of interfaces ** exceeds the maximum supported by atop (MAXINTF) */ - strcpy(ifprop.name, si->intf.intf[i].name); + strcpy(ifprop.name, si->intf.intfns[0].intf[i].name); if (!getifprop(&ifprop)) continue; @@ -1115,8 +1115,10 @@ photosyst(struct sstat *si) break; } - si->intf.intf[i].name[0] = '\0'; /* set terminator for table */ - si->intf.nrintf = i; + si->intf.intfns[0].intf[i].name[0] = '\0'; /* set terminator for table */ + si->intf.intfns[0].nrintf = i; + strcpy(si->intf.intfns[0].nsname, "init"); + si->intf.nrintfns = 1; fclose(fp); } @@ -1151,34 +1153,36 @@ photosyst(struct sstat *si) if ( strcmp("Ip:", nam) == 0) { - memcpy(&si->net.ipv4, cnts, - sizeof si->net.ipv4); + memcpy(&si->net.netns[0].ipv4, cnts, + sizeof si->net.netns[0].ipv4); continue; } if ( strcmp("Icmp:", nam) == 0) { - memcpy(&si->net.icmpv4, cnts, - sizeof si->net.icmpv4); + memcpy(&si->net.netns[0].icmpv4, cnts, + sizeof si->net.netns[0].icmpv4); continue; } if ( strcmp("Tcp:", nam) == 0) { - memcpy(&si->net.tcp, cnts, - sizeof si->net.tcp); + memcpy(&si->net.netns[0].tcp, cnts, + sizeof si->net.netns[0].tcp); continue; } if ( strcmp("Udp:", nam) == 0) { - memcpy(&si->net.udpv4, cnts, - sizeof si->net.udpv4); + memcpy(&si->net.netns[0].udpv4, cnts, + sizeof si->net.netns[0].udpv4); continue; } } fclose(fp); + strcpy(si->net.netns[0].nsname, "init"); + si->net.nrnetns = 1; } /* @@ -1221,9 +1225,9 @@ photosyst(struct sstat *si) cur = 0; } - memcpy(&si->net.ipv6, &ipv6_tmp, sizeof ipv6_tmp); - memcpy(&si->net.icmpv6, &icmpv6_tmp, sizeof icmpv6_tmp); - memcpy(&si->net.udpv6, &udpv6_tmp, sizeof udpv6_tmp); + memcpy(&si->net.netns[0].ipv6, &ipv6_tmp, sizeof ipv6_tmp); + memcpy(&si->net.netns[0].icmpv6, &icmpv6_tmp, sizeof icmpv6_tmp); + memcpy(&si->net.netns[0].udpv6, &udpv6_tmp, sizeof udpv6_tmp); fclose(fp); } diff --git a/photosyst.h b/photosyst.h index 2ed884a2..1850a2e5 100644 --- a/photosyst.h +++ b/photosyst.h @@ -43,6 +43,9 @@ #define MAXDKNAM 32 #define MAXIBNAME 12 +#define MAXNETNS 8 +#define NETNSNAMELEN 128 + /************************************************************************/ struct memstat { count_t physmem; // number of physical pages @@ -138,7 +141,9 @@ struct cpunuma { /************************************************************************/ -struct netstat { +struct netperns { + int nsnr; /* the net namespace number */ + char nsname[NETNSNAMELEN]; /* the net namespace name */ struct ipv4_stats ipv4; struct icmpv4_stats icmpv4; struct udpv4_stats udpv4; @@ -150,6 +155,11 @@ struct netstat { struct tcp_stats tcp; }; +struct netstat { + count_t nrnetns; + struct netperns netns[MAXNETNS]; +}; + /************************************************************************/ struct freqcnt { @@ -247,11 +257,18 @@ struct perintf { count_t cfuture[4]; /* reserved for future use */ }; -struct intfstat { +struct intfperns { int nrintf; + int nsnr; /* the net namespace number */ + char nsname[NETNSNAMELEN]; /* the net namespace name */ struct perintf intf[MAXINTF]; }; +struct intfstat { + count_t nrintfns; + struct intfperns intfns[MAXNETNS]; +}; + /************************************************************************/ struct pernfsmount { diff --git a/showgeneric.c b/showgeneric.c index 5553bda1..2cfb5c16 100644 --- a/showgeneric.c +++ b/showgeneric.c @@ -128,7 +128,7 @@ generic_samp(time_t curtime, int nsecs, char *p; - register int i, curline, statline, nproc; + register int i, curline, statline, nproc, nr; int firstproc = 0, plistsz, alistsz, killpid, killsig; int lastchar; char format1[16], format2[16], branchtime[32]; @@ -240,9 +240,11 @@ generic_samp(time_t curtime, int nsecs, qsort(sstat->dsk.dsk, sstat->dsk.ndsk, sizeof sstat->dsk.dsk[0], diskcompar); - if (sstat->intf.nrintf > 1 && maxintlines > 0) - qsort(sstat->intf.intf, sstat->intf.nrintf, - sizeof sstat->intf.intf[0], intfcompar); + for (nr = 0; nr < sstat->intf.nrintfns; nr++) { + if (sstat->intf.intfns[nr].nrintf > 1 && maxintlines > 0) + qsort(sstat->intf.intfns[nr].intf, sstat->intf.intfns[nr].nrintf, + sizeof sstat->intf.intfns[nr].intf[0], intfcompar); + } if (sstat->ifb.nrports > 1 && maxifblines > 0) qsort(sstat->ifb.ifb, sstat->ifb.nrports, diff --git a/showlinux.c b/showlinux.c index cba40980..a186cebc 100644 --- a/showlinux.c +++ b/showlinux.c @@ -352,6 +352,7 @@ sys_printdef *netnetsyspdefs[] = { }; sys_printdef *netintfsyspdefs[] = { &syspdef_NETNAME, + &syspdef_NETINTFNS, &syspdef_NETPCKI, &syspdef_NETPCKO, &syspdef_NETSPEEDMAX, @@ -1197,7 +1198,7 @@ pricumproc(struct sstat *sstat, struct devtstat *devtstat, { make_sys_prints(netinterfaceline, MAXITEMS, "NETNAME:8 " - "BLANKBOX:0 " + "NETINTFNS:4 " "NETPCKI:7 " "NETPCKO:7 " "BLANKBOX:0 " @@ -2169,154 +2170,164 @@ prisyst(struct sstat *sstat, int curline, int nsecs, int avgval, curline++; } - /* - ** NET statistics: transport - */ - if (sstat->net.tcp.InSegs || - sstat->net.tcp.OutSegs || - sstat->net.udpv4.InDatagrams || - sstat->net.udpv6.Udp6InDatagrams || - sstat->net.udpv4.OutDatagrams || - sstat->net.udpv6.Udp6OutDatagrams || - fixedhead ) - { - if (screen) - move(curline, 0); - - showsysline(nettransportline, sstat, &extra, "NET", 0); - curline++; - } - - /* - ** NET statistics: network - */ - if (sstat->net.ipv4.InReceives || - sstat->net.ipv6.Ip6InReceives || - sstat->net.ipv4.OutRequests || - sstat->net.ipv6.Ip6OutRequests || - fixedhead ) - { - if (screen) - move(curline, 0); - - showsysline(netnetline, sstat, &extra, "NET", 0); - curline++; - } - - /* - ** NET statistics: interfaces - */ - for (extra.index=0, lin=0; - sstat->intf.intf[extra.index].name[0] && lin < maxintlines; - extra.index++) - { - if (sstat->intf.intf[extra.index].rpack || - sstat->intf.intf[extra.index].spack || fixedhead) - { - if (selp->itfnamesz && regexec(&(selp->itfregex), - sstat->intf.intf[extra.index].name, 0, NULL, 0)) - continue; // suppress (not selected) - - /* - ** calculate busy-percentage for interface - */ - - count_t ival, oval; - - /* - ** convert byte-transfers to bit-transfers (* 8) - ** convert bit-transfers to kilobit-transfers (/ 1000) - ** per second - */ - ival = sstat->intf.intf[extra.index].rbyte/125/nsecs; - oval = sstat->intf.intf[extra.index].sbyte/125/nsecs; - - /* speed known? */ - if (sstat->intf.intf[extra.index].speed) - { - if (sstat->intf.intf[extra.index].duplex) - busy = (ival > oval ? ival : oval) / - (sstat->intf.intf[extra.index].speed - *10); - else - busy = (ival + oval) / - (sstat->intf.intf[extra.index].speed - *10); + int nr; + for (nr = 0; nr < sstat->net.nrnetns; nr++) + { + /* + ** NET statistics: transport per netns + */ + if (sstat->net.netns[nr].tcp.InSegs || + sstat->net.netns[nr].tcp.OutSegs || + sstat->net.netns[nr].udpv4.InDatagrams || + sstat->net.netns[nr].udpv6.Udp6InDatagrams || + sstat->net.netns[nr].udpv4.OutDatagrams || + sstat->net.netns[nr].udpv6.Udp6OutDatagrams || + fixedhead ) + { + if (screen) + move(curline, 0); - } - else - { - busy = 0; - } + extra.nsnr = nr; /* the network namespace */ + showsysline(nettransportline, sstat, &extra, "NET", 0); + curline++; + } - if (netbadness) - badness = busy * 100 / netbadness; - else - badness = 0; + /* + ** NET statistics: network per netns + */ + if (sstat->net.netns[nr].ipv4.InReceives || + sstat->net.netns[nr].ipv6.Ip6InReceives || + sstat->net.netns[nr].ipv4.OutRequests || + sstat->net.netns[nr].ipv6.Ip6OutRequests || + fixedhead ) + { + if (screen) + move(curline, 0); - if (highbadness < badness && (supportflags & NETATOP) ) - { - highbadness = badness; - *highorderp = MSORTNET; - } + extra.nsnr = nr; /* the network namespace */ + showsysline(netnetline, sstat, &extra, "NET", 0); + curline++; + } + } - if (screen) - move(curline, 0); + for (nr = 0; nr < sstat->intf.nrintfns; nr++) + { + /* + ** NET statistics: interfaces per netns + */ + for (extra.index=0, lin=0; + sstat->intf.intfns[nr].intf[extra.index].name[0] && lin < maxintlines; + extra.index++) + { + if (sstat->intf.intfns[nr].intf[extra.index].rpack || + sstat->intf.intfns[nr].intf[extra.index].spack || fixedhead) + { + if (selp->itfnamesz && regexec(&(selp->itfregex), + sstat->intf.intfns[nr].intf[extra.index].name, 0, NULL, 0)) + continue; // suppress (not selected) + + /* + ** calculate busy-percentage for interface + */ + + count_t ival, oval; + + /* + ** convert byte-transfers to bit-transfers (* 8) + ** convert bit-transfers to kilobit-transfers (/ 1000) + ** per second + */ + ival = sstat->intf.intfns[nr].intf[extra.index].rbyte/125/nsecs; + oval = sstat->intf.intfns[nr].intf[extra.index].sbyte/125/nsecs; + + /* speed known? */ + if (sstat->intf.intfns[nr].intf[extra.index].speed) + { + if (sstat->intf.intfns[nr].intf[extra.index].duplex) + busy = (ival > oval ? ival : oval) / + (sstat->intf.intfns[nr].intf[extra.index].speed + *10); + else + busy = (ival + oval) / + (sstat->intf.intfns[nr].intf[extra.index].speed + *10); + + } + else + { + busy = 0; + } - showsysline(netinterfaceline, sstat, &extra, - "NET", badness); - curline++; - lin++; - } - } + if (netbadness) + badness = busy * 100 / netbadness; + else + badness = 0; + + if (highbadness < badness && (supportflags & NETATOP) ) + { + highbadness = badness; + *highorderp = MSORTNET; + } + + if (screen) + move(curline, 0); + + extra.nsnr = nr; + showsysline(netinterfaceline, sstat, &extra, + "NET", badness); + curline++; + lin++; + } + } - /* - ** NET statistics: InfiniBand - */ - for (extra.index=0, lin=0; - extra.index < sstat->ifb.nrports && lin < maxifblines; - extra.index++) - { - if (sstat->ifb.ifb[extra.index].rcvb || - sstat->ifb.ifb[extra.index].sndb || fixedhead) - { - /* - ** calculate busy-percentage for IB port - */ - count_t ival, oval; - - /* - ** convert byte-transfers to bit-transfers (* 8) - ** convert bit-transfers to kilobit-transfers (/ 1000) - ** per second - */ - ival = sstat->ifb.ifb[extra.index].rcvb/125/nsecs; - oval = sstat->ifb.ifb[extra.index].sndb/125/nsecs; - - busy = (ival > oval ? ival : oval) * - sstat->ifb.ifb[extra.index].lanes / - (sstat->ifb.ifb[extra.index].rate * 10); - - if (netbadness) - badness = busy * 100 / netbadness; - else - badness = 0; + /* + ** NET statistics: InfiniBand + */ + for (extra.index=0, lin=0; + extra.index < sstat->ifb.nrports && lin < maxifblines; + extra.index++) + { + if (sstat->ifb.ifb[extra.index].rcvb || + sstat->ifb.ifb[extra.index].sndb || fixedhead) + { + /* + ** calculate busy-percentage for IB port + */ + count_t ival, oval; + + /* + ** convert byte-transfers to bit-transfers (* 8) + ** convert bit-transfers to kilobit-transfers (/ 1000) + ** per second + */ + ival = sstat->ifb.ifb[extra.index].rcvb/125/nsecs; + oval = sstat->ifb.ifb[extra.index].sndb/125/nsecs; + + busy = (ival > oval ? ival : oval) * + sstat->ifb.ifb[extra.index].lanes / + (sstat->ifb.ifb[extra.index].rate * 10); + + if (netbadness) + badness = busy * 100 / netbadness; + else + badness = 0; - if (highbadness < badness) - { - highbadness = badness; - *highorderp = MSORTNET; - } + if (highbadness < badness) + { + highbadness = badness; + *highorderp = MSORTNET; + } - if (screen) - move(curline, 0); + if (screen) + move(curline, 0); - showsysline(infinibandline, sstat, &extra, - "IFB", badness); - curline++; - lin++; - } - } + showsysline(infinibandline, sstat, &extra, + "IFB", badness); + curline++; + lin++; + } + } + } /* ** application statistics diff --git a/showlinux.h b/showlinux.h index ad4ab514..7d9afecd 100644 --- a/showlinux.h +++ b/showlinux.h @@ -51,6 +51,7 @@ typedef struct { count_t iotot; struct perdsk *perdsk; int index; + int nsnr; count_t cputot; count_t pernumacputot; count_t percputot; @@ -324,6 +325,7 @@ extern sys_printdef syspdef_NETIPDELIV; extern sys_printdef syspdef_NETICMPIN; extern sys_printdef syspdef_NETICMPOUT; extern sys_printdef syspdef_NETNAME; +extern sys_printdef syspdef_NETINTFNS; extern sys_printdef syspdef_NETPCKI; extern sys_printdef syspdef_NETPCKO; extern sys_printdef syspdef_NETSPEEDMAX; diff --git a/showsys.c b/showsys.c index 4948db7a..94aa7b6c 100644 --- a/showsys.c +++ b/showsys.c @@ -2489,9 +2489,23 @@ sysprt_DSKAVIO(struct sstat *sstat, extraparam *as, int badness, int *color) sys_printdef syspdef_DSKAVIO = {"DSKAVIO", sysprt_DSKAVIO, NULL}; /*******************************************************************/ static char * -sysprt_NETTRANSPORT(struct sstat *sstat, extraparam *notused, int badness, int *color) +sysprt_NETTRANSPORT(struct sstat *sstat, extraparam *as, int badness, int *color) { - return "transport "; + static char buf[16], splitted[9]; + char *src = sstat->net.netns[as->nsnr].nsname; + int i, len = strlen(src); + + for ( i = len - 1; i >= 0 && src[i] != '\0'; i-- ) + if ( src[i] == '/' ) + break; + + if ( len - i - 1 > 9 ) + strncpy(splitted, src + len - 9, 9); + else + strncpy(splitted, src + i + 1, 9); + + sprintf(buf, "tl %9.9s", splitted); /* transport layer */ + return buf; } sys_printdef syspdef_NETTRANSPORT = {"NETTRANSPORT", sysprt_NETTRANSPORT, NULL}; @@ -2499,9 +2513,9 @@ sys_printdef syspdef_NETTRANSPORT = {"NETTRANSPORT", sysprt_NETTRANSPORT, NULL}; static char * sysprt_NETTCPI(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="tcpi "; - val2valstr(sstat->net.tcp.InSegs, buf+5, 7, as->avgval, as->nsecs); - return buf; + static char buf[16]="tcpi "; + val2valstr(sstat->net.netns[as->nsnr].tcp.InSegs, buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETTCPI = {"NETTCPI", sysprt_NETTCPI, NULL}; @@ -2509,9 +2523,9 @@ sys_printdef syspdef_NETTCPI = {"NETTCPI", sysprt_NETTCPI, NULL}; static char * sysprt_NETTCPO(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="tcpo "; - val2valstr(sstat->net.tcp.OutSegs, buf+5, 7, as->avgval, as->nsecs); - return buf; + static char buf[16]="tcpo "; + val2valstr(sstat->net.netns[as->nsnr].tcp.OutSegs, buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETTCPO = {"NETTCPO", sysprt_NETTCPO, NULL}; @@ -2519,9 +2533,9 @@ sys_printdef syspdef_NETTCPO = {"NETTCPO", sysprt_NETTCPO, NULL}; static char * sysprt_NETTCPACTOPEN(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="tcpao "; - val2valstr(sstat->net.tcp.ActiveOpens, buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="tcpao "; + val2valstr(sstat->net.netns[as->nsnr].tcp.ActiveOpens, buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETTCPACTOPEN = {"NETTCPACTOPEN", sysprt_NETTCPACTOPEN, NULL}; @@ -2529,9 +2543,9 @@ sys_printdef syspdef_NETTCPACTOPEN = {"NETTCPACTOPEN", sysprt_NETTCPACTOPEN, NUL static char * sysprt_NETTCPPASVOPEN(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="tcppo "; - val2valstr(sstat->net.tcp.PassiveOpens, buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="tcppo "; + val2valstr(sstat->net.netns[as->nsnr].tcp.PassiveOpens, buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETTCPPASVOPEN = {"NETTCPPASVOPEN", sysprt_NETTCPPASVOPEN, NULL}; @@ -2539,9 +2553,9 @@ sys_printdef syspdef_NETTCPPASVOPEN = {"NETTCPPASVOPEN", sysprt_NETTCPPASVOPEN, static char * sysprt_NETTCPRETRANS(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="tcprs "; - val2valstr(sstat->net.tcp.RetransSegs, buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="tcprs "; + val2valstr(sstat->net.netns[as->nsnr].tcp.RetransSegs, buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETTCPRETRANS = {"NETTCPRETRANS", sysprt_NETTCPRETRANS, NULL}; @@ -2549,9 +2563,9 @@ sys_printdef syspdef_NETTCPRETRANS = {"NETTCPRETRANS", sysprt_NETTCPRETRANS, NUL static char * sysprt_NETTCPINERR(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="tcpie "; - val2valstr(sstat->net.tcp.InErrs, buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="tcpie "; + val2valstr(sstat->net.netns[as->nsnr].tcp.InErrs, buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETTCPINERR = {"NETTCPINERR", sysprt_NETTCPINERR, NULL}; @@ -2559,9 +2573,9 @@ sys_printdef syspdef_NETTCPINERR = {"NETTCPINERR", sysprt_NETTCPINERR, NULL}; static char * sysprt_NETTCPORESET(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="tcpor "; - val2valstr(sstat->net.tcp.OutRsts, buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="tcpor "; + val2valstr(sstat->net.netns[as->nsnr].tcp.OutRsts, buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETTCPORESET = {"NETTCPORESET", sysprt_NETTCPORESET, NULL}; @@ -2569,9 +2583,9 @@ sys_printdef syspdef_NETTCPORESET = {"NETTCPORESET", sysprt_NETTCPORESET, NULL}; static char * sysprt_NETUDPNOPORT(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="udpnp "; - val2valstr(sstat->net.udpv4.NoPorts, buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="udpnp "; + val2valstr(sstat->net.netns[as->nsnr].udpv4.NoPorts, buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETUDPNOPORT = {"NETUDPNOPORT", sysprt_NETUDPNOPORT, NULL}; @@ -2579,9 +2593,9 @@ sys_printdef syspdef_NETUDPNOPORT = {"NETUDPNOPORT", sysprt_NETUDPNOPORT, NULL}; static char * sysprt_NETUDPINERR(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="udpie "; - val2valstr(sstat->net.udpv4.InErrors, buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="udpie "; + val2valstr(sstat->net.netns[as->nsnr].udpv4.InErrors, buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETUDPINERR = {"NETUDPINERR", sysprt_NETUDPINERR, NULL}; @@ -2589,11 +2603,11 @@ sys_printdef syspdef_NETUDPINERR = {"NETUDPINERR", sysprt_NETUDPINERR, NULL}; static char * sysprt_NETUDPI(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="udpi "; - count_t udpin = sstat->net.udpv4.InDatagrams + - sstat->net.udpv6.Udp6InDatagrams; - val2valstr(udpin, buf+5, 7, as->avgval, as->nsecs); - return buf; + static char buf[16]="udpi "; + count_t udpin = sstat->net.netns[as->nsnr].udpv4.InDatagrams + + sstat->net.netns[as->nsnr].udpv6.Udp6InDatagrams; + val2valstr(udpin, buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETUDPI = {"NETUDPI", sysprt_NETUDPI, NULL}; @@ -2601,19 +2615,33 @@ sys_printdef syspdef_NETUDPI = {"NETUDPI", sysprt_NETUDPI, NULL}; static char * sysprt_NETUDPO(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="udpo "; - count_t udpout = sstat->net.udpv4.OutDatagrams + - sstat->net.udpv6.Udp6OutDatagrams; - val2valstr(udpout, buf+5, 7, as->avgval, as->nsecs); - return buf; + static char buf[16]="udpo "; + count_t udpout = sstat->net.netns[as->nsnr].udpv4.OutDatagrams + + sstat->net.netns[as->nsnr].udpv6.Udp6OutDatagrams; + val2valstr(udpout, buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETUDPO = {"NETUDPO", sysprt_NETUDPO, NULL}; /*******************************************************************/ static char * -sysprt_NETNETWORK(struct sstat *sstat, extraparam *notused, int badness, int *color) +sysprt_NETNETWORK(struct sstat *sstat, extraparam *as, int badness, int *color) { - return "network "; + static char buf[16], splitted[9]; + char *src = sstat->net.netns[as->nsnr].nsname; + int i, len = strlen(src); + + for ( i = len - 1; i >= 0 && src[i] != '\0'; i-- ) + if ( src[i] == '/' ) + break; + + if ( len - i - 1 > 9 ) + strncpy(splitted, src + len - 9, 9); + else + strncpy(splitted, src + i + 1, 9); + + sprintf(buf, "nl %9.9s", splitted); /* network layer */ + return buf; } sys_printdef syspdef_NETNETWORK = {"NETNETWORK", sysprt_NETNETWORK, NULL}; @@ -2621,11 +2649,11 @@ sys_printdef syspdef_NETNETWORK = {"NETNETWORK", sysprt_NETNETWORK, NULL}; static char * sysprt_NETIPI(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="ipi "; - count_t ipin = sstat->net.ipv4.InReceives + - sstat->net.ipv6.Ip6InReceives; - val2valstr(ipin, buf+4, 8, as->avgval, as->nsecs); - return buf; + static char buf[16]="ipi "; + count_t ipin = sstat->net.netns[as->nsnr].ipv4.InReceives + + sstat->net.netns[as->nsnr].ipv6.Ip6InReceives; + val2valstr(ipin, buf+4, 8, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETIPI = {"NETIPI", sysprt_NETIPI, NULL}; @@ -2633,11 +2661,11 @@ sys_printdef syspdef_NETIPI = {"NETIPI", sysprt_NETIPI, NULL}; static char * sysprt_NETIPO(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="ipo "; - count_t ipout = sstat->net.ipv4.OutRequests + - sstat->net.ipv6.Ip6OutRequests; - val2valstr(ipout, buf+4, 8, as->avgval, as->nsecs); - return buf; + static char buf[16]="ipo "; + count_t ipout = sstat->net.netns[as->nsnr].ipv4.OutRequests + + sstat->net.netns[as->nsnr].ipv6.Ip6OutRequests; + val2valstr(ipout, buf+4, 8, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETIPO = {"NETIPO", sysprt_NETIPO, NULL}; @@ -2645,11 +2673,11 @@ sys_printdef syspdef_NETIPO = {"NETIPO", sysprt_NETIPO, NULL}; static char * sysprt_NETIPFRW(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="ipfrw "; - count_t ipfrw = sstat->net.ipv4.ForwDatagrams + - sstat->net.ipv6.Ip6OutForwDatagrams; - val2valstr(ipfrw, buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="ipfrw "; + count_t ipfrw = sstat->net.netns[as->nsnr].ipv4.ForwDatagrams + + sstat->net.netns[as->nsnr].ipv6.Ip6OutForwDatagrams; + val2valstr(ipfrw, buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETIPFRW = {"NETIPFRW", sysprt_NETIPFRW, NULL}; @@ -2657,11 +2685,11 @@ sys_printdef syspdef_NETIPFRW = {"NETIPFRW", sysprt_NETIPFRW, NULL}; static char * sysprt_NETIPDELIV(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="deliv "; - count_t ipindel = sstat->net.ipv4.InDelivers + - sstat->net.ipv6.Ip6InDelivers; - val2valstr(ipindel, buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="deliv "; + count_t ipindel = sstat->net.netns[as->nsnr].ipv4.InDelivers + + sstat->net.netns[as->nsnr].ipv6.Ip6InDelivers; + val2valstr(ipindel, buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETIPDELIV = {"NETIPDELIV", sysprt_NETIPDELIV, NULL}; @@ -2669,11 +2697,11 @@ sys_printdef syspdef_NETIPDELIV = {"NETIPDELIV", sysprt_NETIPDELIV, NULL}; static char * sysprt_NETICMPIN(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="icmpi "; - count_t icmpin = sstat->net.icmpv4.InMsgs+ - sstat->net.icmpv6.Icmp6InMsgs; - val2valstr(icmpin , buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="icmpi "; + count_t icmpin = sstat->net.netns[as->nsnr].icmpv4.InMsgs+ + sstat->net.netns[as->nsnr].icmpv6.Icmp6InMsgs; + val2valstr(icmpin , buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETICMPIN = {"NETICMPIN", sysprt_NETICMPIN, NULL}; @@ -2681,11 +2709,11 @@ sys_printdef syspdef_NETICMPIN = {"NETICMPIN", sysprt_NETICMPIN, NULL}; static char * sysprt_NETICMPOUT(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="icmpo "; - count_t icmpin = sstat->net.icmpv4.OutMsgs+ - sstat->net.icmpv6.Icmp6OutMsgs; - val2valstr(icmpin , buf+6, 6, as->avgval, as->nsecs); - return buf; + static char buf[16]="icmpo "; + count_t icmpin = sstat->net.netns[as->nsnr].icmpv4.OutMsgs+ + sstat->net.netns[as->nsnr].icmpv6.Icmp6OutMsgs; + val2valstr(icmpin , buf+6, 6, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETICMPOUT = {"NETICMPOUT", sysprt_NETICMPOUT, NULL}; @@ -2693,40 +2721,40 @@ sys_printdef syspdef_NETICMPOUT = {"NETICMPOUT", sysprt_NETICMPOUT, NULL}; static char * sysprt_NETNAME(struct sstat *sstat, extraparam *as, int badness, int *color) { - count_t busy; - count_t ival = sstat->intf.intf[as->index].rbyte/125/as->nsecs; - count_t oval = sstat->intf.intf[as->index].sbyte/125/as->nsecs; + count_t busy; + count_t ival = sstat->intf.intfns[as->nsnr].intf[as->index].rbyte/125/as->nsecs; + count_t oval = sstat->intf.intfns[as->nsnr].intf[as->index].sbyte/125/as->nsecs; - static char buf[16] = "ethxxxx ----"; + static char buf[16] = "ethxxxx ----"; // 012345678901 *color = -1; - if (sstat->intf.intf[as->index].speed) /* speed known? */ - { - if (sstat->intf.intf[as->index].duplex) - busy = (ival > oval ? ival : oval) / - (sstat->intf.intf[as->index].speed *10); - else - busy = (ival + oval) / - (sstat->intf.intf[as->index].speed *10); + if (sstat->intf.intfns[as->nsnr].intf[as->index].speed) /* speed known? */ + { + if (sstat->intf.intfns[as->nsnr].intf[as->index].duplex) + busy = (ival > oval ? ival : oval) / + (sstat->intf.intfns[as->nsnr].intf[as->index].speed *10); + else + busy = (ival + oval) / + (sstat->intf.intfns[as->nsnr].intf[as->index].speed *10); // especially with wireless, the speed might have dropped // temporarily to a very low value (snapshot) // then it might be better to take the speed of the previous // sample - if (busy > 100 && sstat->intf.intf[as->index].speed < - sstat->intf.intf[as->index].speedp) + if (busy > 100 && sstat->intf.intfns[as->nsnr].intf[as->index].speed < + sstat->intf.intfns[as->nsnr].intf[as->index].speedp) { - sstat->intf.intf[as->index].speed = - sstat->intf.intf[as->index].speedp; + sstat->intf.intfns[as->nsnr].intf[as->index].speed = + sstat->intf.intfns[as->nsnr].intf[as->index].speedp; - if (sstat->intf.intf[as->index].duplex) - busy = (ival > oval ? ival : oval) / - (sstat->intf.intf[as->index].speed *10); + if (sstat->intf.intfns[as->nsnr].intf[as->index].duplex) + busy = (ival > oval ? ival : oval) / + (sstat->intf.intfns[as->nsnr].intf[as->index].speed *10); else - busy = (ival + oval) / - (sstat->intf.intf[as->index].speed *10); + busy = (ival + oval) / + (sstat->intf.intfns[as->nsnr].intf[as->index].speed *10); } if( busy < -99 ) @@ -2738,45 +2766,64 @@ sysprt_NETNAME(struct sstat *sstat, extraparam *as, int badness, int *color) { busy = 999; } - snprintf(buf, sizeof(buf)-1, "%-7.7s %3lld%%", - sstat->intf.intf[as->index].name, busy); - - } - else - { - snprintf(buf, sizeof(buf)-1, "%-7.7s ----", - sstat->intf.intf[as->index].name); - strcpy(buf+8, "----"); - } - return buf; + snprintf(buf, sizeof(buf)-1, "%-7.7s %3lld%%", + sstat->intf.intfns[as->nsnr].intf[as->index].name, busy); + } + else + { + snprintf(buf, sizeof(buf)-1, "%-7.7s ----", + sstat->intf.intfns[as->nsnr].intf[as->index].name); + strcpy(buf+8, "----"); + } + return buf; } sys_printdef syspdef_NETNAME = {"NETNAME", sysprt_NETNAME, NULL}; /*******************************************************************/ static char * -sysprt_NETPCKI(struct sstat *sstat, extraparam *as, int badness, int *color) +sysprt_NETINTFNS(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="pcki "; + static char buf[16], splitted[9]; + char *src = sstat->intf.intfns[as->nsnr].nsname; + int i, len = strlen(src); + + for ( i = len - 1; i >= 0 && src[i] != '\0'; i-- ) + if ( src[i] == '/' ) + break; + if ( len - i - 1 > 9 ) + strncpy(splitted, src + len - 9, 9); + else + strncpy(splitted, src + i + 1, 9); + + sprintf(buf, "ns %9.9s", splitted); + return buf; +} + +sys_printdef syspdef_NETINTFNS = {"NETINTFNS", sysprt_NETINTFNS, NULL}; +/*******************************************************************/ +static char * +sysprt_NETPCKI(struct sstat *sstat, extraparam *as, int badness, int *color) +{ + static char buf[16]="pcki "; *color = -1; - val2valstr(sstat->intf.intf[as->index].rpack, - buf+5, 7, as->avgval, as->nsecs); - return buf; + val2valstr(sstat->intf.intfns[as->nsnr].intf[as->index].rpack, + buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETPCKI = {"NETPCKI", sysprt_NETPCKI, NULL}; /*******************************************************************/ static char * -sysprt_NETPCKO(struct sstat *sstat, extraparam *as, int badness, int *color) +sysprt_NETPCKO(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="pcko "; - + static char buf[16]="pcko "; *color = -1; - val2valstr(sstat->intf.intf[as->index].spack, - buf+5, 7, as->avgval, as->nsecs); - return buf; + val2valstr(sstat->intf.intfns[as->nsnr].intf[as->index].spack, + buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETPCKO = {"NETPCKO", sysprt_NETPCKO, NULL}; @@ -2832,8 +2879,8 @@ static char *makenetspeed(count_t val, int nsecs) static char * sysprt_NETSPEEDMAX(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]; - count_t speed = sstat->intf.intf[as->index].speed; + static char buf[16]; + count_t speed = sstat->intf.intfns[as->nsnr].intf[as->index].speed; *color = -1; @@ -2855,7 +2902,7 @@ sysprt_NETSPEEDMAX(struct sstat *sstat, extraparam *as, int badness, int *color) snprintf(buf, sizeof buf, "sp %4lld Gbps", speed); } - return buf; + return buf; } sys_printdef syspdef_NETSPEEDMAX = {"NETSPEEDMAX", sysprt_NETSPEEDMAX, NULL}; @@ -2863,13 +2910,12 @@ sys_printdef syspdef_NETSPEEDMAX = {"NETSPEEDMAX", sysprt_NETSPEEDMAX, NULL}; static char * sysprt_NETSPEEDIN(struct sstat *sstat, extraparam *as, int badness, int *color) { - *color = -1; - char *ps=makenetspeed(sstat->intf.intf[as->index].rbyte,as->nsecs); - ps[0]='s'; - ps[1]='i'; - return ps; + char *ps=makenetspeed(sstat->intf.intfns[as->nsnr].intf[as->index].rbyte,as->nsecs); + ps[0]='s'; + ps[1]='i'; + return ps; } sys_printdef syspdef_NETSPEEDIN = {"NETSPEEDIN", sysprt_NETSPEEDIN, NULL}; @@ -2877,79 +2923,78 @@ sys_printdef syspdef_NETSPEEDIN = {"NETSPEEDIN", sysprt_NETSPEEDIN, NULL}; static char * sysprt_NETSPEEDOUT(struct sstat *sstat, extraparam *as, int badness, int *color) { - *color = -1; - char *ps=makenetspeed(sstat->intf.intf[as->index].sbyte,as->nsecs); - ps[0]='s'; - ps[1]='o'; - return ps; + char *ps=makenetspeed(sstat->intf.intfns[as->nsnr].intf[as->index].sbyte,as->nsecs); + ps[0]='s'; + ps[1]='o'; + return ps; } sys_printdef syspdef_NETSPEEDOUT = {"NETSPEEDOUT", sysprt_NETSPEEDOUT, NULL}; /*******************************************************************/ static char * -sysprt_NETCOLLIS(struct sstat *sstat, extraparam *as, int badness, int *color) +sysprt_NETCOLLIS(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="coll "; - val2valstr(sstat->intf.intf[as->index].scollis, - buf+5, 7, as->avgval, as->nsecs); - return buf; + static char buf[16]="coll "; + val2valstr(sstat->intf.intfns[as->nsnr].intf[as->index].scollis, + buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETCOLLIS = {"NETCOLLIS", sysprt_NETCOLLIS, NULL}; /*******************************************************************/ static char * -sysprt_NETMULTICASTIN(struct sstat *sstat, extraparam *as, int badness, int *color) +sysprt_NETMULTICASTIN(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="mlti "; - val2valstr(sstat->intf.intf[as->index].rmultic, - buf+5, 7, as->avgval, as->nsecs); - return buf; + static char buf[16]="mlti "; + val2valstr(sstat->intf.intfns[as->nsnr].intf[as->index].rmultic, + buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETMULTICASTIN = {"NETMULTICASTIN", sysprt_NETMULTICASTIN, NULL}; /*******************************************************************/ static char * -sysprt_NETRCVERR(struct sstat *sstat, extraparam *as, int badness, int *color) +sysprt_NETRCVERR(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="erri "; - val2valstr(sstat->intf.intf[as->index].rerrs, - buf+5, 7, as->avgval, as->nsecs); - return buf; + static char buf[16]="erri "; + val2valstr(sstat->intf.intfns[as->nsnr].intf[as->index].rerrs, + buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETRCVERR = {"NETRCVERR", sysprt_NETRCVERR, NULL}; /*******************************************************************/ static char * -sysprt_NETSNDERR(struct sstat *sstat, extraparam *as, int badness, int *color) +sysprt_NETSNDERR(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="erro "; - val2valstr(sstat->intf.intf[as->index].serrs, - buf+5, 7, as->avgval, as->nsecs); - return buf; + static char buf[16]="erro "; + val2valstr(sstat->intf.intfns[as->nsnr].intf[as->index].serrs, + buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETSNDERR = {"NETSNDERR", sysprt_NETSNDERR, NULL}; /*******************************************************************/ static char * -sysprt_NETRCVDROP(struct sstat *sstat, extraparam *as, int badness, int *color) +sysprt_NETRCVDROP(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="drpi "; - val2valstr(sstat->intf.intf[as->index].rdrop, - buf+5, 7, as->avgval, as->nsecs); - return buf; + static char buf[16]="drpi "; + val2valstr(sstat->intf.intfns[as->nsnr].intf[as->index].rdrop, + buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETRCVDROP = {"NETRCVDROP", sysprt_NETRCVDROP, NULL}; /*******************************************************************/ static char * -sysprt_NETSNDDROP(struct sstat *sstat, extraparam *as, int badness, int *color) +sysprt_NETSNDDROP(struct sstat *sstat, extraparam *as, int badness, int *color) { - static char buf[16]="drpo "; - val2valstr(sstat->intf.intf[as->index].sdrop, - buf+5, 7, as->avgval, as->nsecs); - return buf; + static char buf[16]="drpo "; + val2valstr(sstat->intf.intfns[as->nsnr].intf[as->index].sdrop, + buf+5, 7, as->avgval, as->nsecs); + return buf; } sys_printdef syspdef_NETSNDDROP = {"NETSNDDROP", sysprt_NETSNDDROP, NULL}; From 6d3a305fa7c19c2b4c1bdb79d10f9097ed0b578f Mon Sep 17 00:00:00 2001 From: Fei Li Date: Mon, 20 Feb 2023 19:11:37 +0800 Subject: [PATCH 3/6] Add man for netns attributes Signed-off-by: Fei Li --- man/atop.1 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/man/atop.1 b/man/atop.1 index a32b0f50..aecd55f3 100644 --- a/man/atop.1 +++ b/man/atop.1 @@ -1442,7 +1442,7 @@ Network utilization (TCP/IP). One line is shown for activity of the transport layer (TCP and UDP), one line for the IP layer and one line per active interface. .br -For the transport layer, +For the transport layer (shown as `tl $netns_name'), counters are shown concerning the number of received TCP segments including those received in error (`tcpi'), the number of transmitted TCP segments excluding @@ -1462,7 +1462,8 @@ only a relevant subset is shown. .br These counters are related to IPv4 and IPv6 combined. -For the IP layer, counters are shown concerning the number of IP datagrams +For the IP layer (shown as `nl $netns_name'), +counters are shown concerning the number of IP datagrams received from interfaces, including those received in error (`ipi'), the number of IP datagrams that local higher-layer protocols offered for transmission (`ipo'), the number of received IP datagrams which were @@ -1487,7 +1488,8 @@ highest of either the transmitted or the received bits. When the interface speed can not be determined (e.g. for the loopback interface), `---' is shown instead of the percentage. .br -Furthermore the number of received packets (`pcki'), +Furthermore the netns the interface belongs to (`ns'), +the number of received packets (`pcki'), the number of transmitted packets (`pcko'), the line speed of the interface (`sp'), the effective amount of bits received per second (`si'), From fd4ba502d48e2d3f5d6a393f42cba7290aeee367 Mon Sep 17 00:00:00 2001 From: Fei Li Date: Fri, 10 Feb 2023 21:14:46 +0800 Subject: [PATCH 4/6] photosys: add idx for v6tab to mark its position For linux kernel, it exposes almost 100 lines for /proc/net/snmp6 file. Considering multiple-netns situations, too many lines had to be read and transferred, which is quite time consuming and space consuming. Let's optimize this by adding 'idx' to mark the needed indicators' position in struct v6tab. During the first time reading, e.i. the init_net namespace, we record the positions. Then in the following other netns, we only need to store and transfer indicators' values according to their positions. Signed-off-by: Fei Li --- photosyst.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/photosyst.c b/photosyst.c index 8c5551a0..b5f64a06 100644 --- a/photosyst.c +++ b/photosyst.c @@ -116,6 +116,7 @@ static struct udpv6_stats udpv6_tmp; struct v6tab { char *nam; count_t *val; + int idx; /* the position of nam in /proc/snmp6 file */ }; static struct v6tab v6tab[] = { @@ -1195,7 +1196,7 @@ photosyst(struct sstat *si) if ( (fp = fopen("net/snmp6", "r")) != NULL) { count_t countval; - int cur = 0; + int cur = 0, idx = 0; /* ** one name-value pair per line @@ -1210,6 +1211,7 @@ photosyst(struct sstat *si) if (strcmp(v6tab[cur].nam, nam) == 0) { *(v6tab[cur].val) = countval; + v6tab[cur].idx = idx; } else { @@ -1217,12 +1219,16 @@ photosyst(struct sstat *si) if (strcmp(v6tab[cur].nam, nam) == 0) break; - if (cur < v6tab_entries) /* found ? */ + if (cur < v6tab_entries) {/* found ? */ *(v6tab[cur].val) = countval; + v6tab[cur].idx = idx; + } } if (++cur >= v6tab_entries) cur = 0; + + idx++; } memcpy(&si->net.netns[0].ipv6, &ipv6_tmp, sizeof ipv6_tmp); From befa9a2ceac8df1f253d92648bd5f58eaa36d1d6 Mon Sep 17 00:00:00 2001 From: Fei Li Date: Sun, 29 Jan 2023 21:16:54 +0800 Subject: [PATCH 5/6] Collect statistics from other network namespace This patch implements how to collect statistics for other netns by using `setns` to switch to another netns to read /proc files, and then use shared memory for parent-child IPC. Combined with actual needs and performance considerations, this patch only collects other netns's physical network devices stats. Virtual devices are ignored except the 'lo'. Signed-off-by: Fei Li --- Makefile | 1 + ifprop.c | 26 ++++- ifprop.h | 2 + photosyst.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++++++++ photosyst.h | 34 ++++++ 5 files changed, 372 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 251cf571..a3171d76 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ PMPATH2 = /usr/lib64/pm-utils/sleep.d PMPATHD = /usr/lib/systemd/system-sleep CFLAGS += -O2 -I. -Wall -Wno-stringop-truncation -Wmissing-prototypes -Wmissing-declarations # -DNOPERFEVENT # -DHTTPSTATS +LDFLAGS = -lpthread OBJMOD0 = version.o OBJMOD1 = various.o deviate.o procdbase.o OBJMOD2 = acctproc.o photoproc.o photosyst.o rawlog.o ifprop.o parseable.o diff --git a/ifprop.c b/ifprop.c index d4fbd2bd..185e1d5b 100644 --- a/ifprop.c +++ b/ifprop.c @@ -55,7 +55,6 @@ typedef __u8 u8; #include "photosyst.h" static int calcbucket(char *); -static int getphysprop(struct ifprop *); /* ** hash table for linked lists with *all* interfaces @@ -304,7 +303,7 @@ calcbucket(char *p) ** ** return value reflects true (success) or false (unknown interface type) */ -static int +int getphysprop(struct ifprop *p) { int sockfd; @@ -440,3 +439,26 @@ getphysprop(struct ifprop *p) return 1; } + +int getbusinfo(struct ifprop *p) { + int sockfd, ret = 0; + struct ifreq ifreq; + struct ethtool_drvinfo drv; + + if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ) + return 0; + + memset(&ifreq, 0, sizeof ifreq); + strncpy((void *)&ifreq.ifr_ifrn.ifrn_name, p->name, + sizeof ifreq.ifr_ifrn.ifrn_name - 1); + + drv.cmd = ETHTOOL_GDRVINFO; + ifreq.ifr_ifru.ifru_data = (void *)&drv; + if ( ioctl(sockfd, SIOCETHTOOL, &ifreq) == 0 ) + if ( strlen(drv.bus_info) > 0 ) + ret = 1; + + close(sockfd); + + return ret; +} diff --git a/ifprop.h b/ifprop.h index 1635c86c..cdcf9f5c 100644 --- a/ifprop.h +++ b/ifprop.h @@ -39,3 +39,5 @@ struct ifprop { int getifprop(struct ifprop *); void initifprop(void); +int getphysprop(struct ifprop *); +int getbusinfo(struct ifprop *); diff --git a/photosyst.c b/photosyst.c index b5f64a06..76030496 100644 --- a/photosyst.c +++ b/photosyst.c @@ -29,13 +29,16 @@ ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ** -------------------------------------------------------------------------- */ +#define _GNU_SOURCE #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -46,6 +49,8 @@ #include #include #include +#include +#include #define SCALINGMAXCPU 8 // threshold for scaling info per CPU @@ -187,6 +192,8 @@ static struct v6tab v6tab[] = { static int v6tab_entries = sizeof(v6tab)/sizeof(struct v6tab); +static char othernetns[MAXNETNS][NETNSNAMELEN]; + // The following values are used to accumulate cpu statistics per numa. // The bitmask realization is from numactl #define CPUMASK_SZ (64 * 8) @@ -1270,6 +1277,108 @@ photosyst(struct sstat *si) fclose(fp); } + /* + ** gather other net namespaces' network-related statistics + */ + if ( strlen(othernetns[0]) > 0 ) + { + int nsnr, wstatus; + pid_t pid; + struct timespec maxsemwait; + + struct shmbuf *shmp = mmap(NULL, sizeof(*shmp), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); + if ( shmp == MAP_FAILED ) + mcleanstop(53, "mmap failed when collecting othernetns, errno is %d\n", errno); + + if ( (sem_init(&shmp->sem, 1, 0) == -1) ) + mcleanstop(53, "sem_init failed when collecting othernetns, errno is %d\n", errno); + + pid = fork(); + if ( pid == -1 ) + mcleanstop(53, "fork failed when collecting othernetns, errno is %d\n", errno); + else if ( pid == 0 ) + /* collect other netns statistics */ + getothernetns(shmp); + else + { + if ( clock_gettime(CLOCK_REALTIME, &maxsemwait) == -1 ) + mcleanstop(53, "failed to gettime in getothernetns, errno is %d\n", errno); + + /* firstly timeout-wait: wait for 'sem' to be posted by child before touching shared memory. */ + maxsemwait.tv_sec += 3; + if ( sem_timedwait(&shmp->sem, &maxsemwait) == -1 ) + mcleanstop(53, "sem_wait failed when collecting othernetns, errno is %d\n", errno); + + /* secondly: kill & waitpid to cleanup zombie child. */ + kill(pid, SIGKILL); + waitpid(pid, &wstatus, 0); + + if ( shmp->netnsdata.nssum > 0 ) + { + for (nsnr = 0; nsnr < shmp->netnsdata.nssum; nsnr++) + { + /* 1. interface stats from the file /proc/net/dev */ + for (i = 0; i < shmp->netnsdata.pernetns[nsnr].nrintf; i++) + { + strcpy(si->intf.intfns[nsnr+1].intf[i].name, shmp->netnsdata.pernetns[nsnr].perintf[i].name); + si->intf.intfns[nsnr+1].intf[i].rbyte = shmp->netnsdata.pernetns[nsnr].perintf[i].rbyte; + si->intf.intfns[nsnr+1].intf[i].rpack = shmp->netnsdata.pernetns[nsnr].perintf[i].rpack; + si->intf.intfns[nsnr+1].intf[i].rerrs = shmp->netnsdata.pernetns[nsnr].perintf[i].rerrs; + si->intf.intfns[nsnr+1].intf[i].rdrop = shmp->netnsdata.pernetns[nsnr].perintf[i].rdrop; + si->intf.intfns[nsnr+1].intf[i].rfifo = shmp->netnsdata.pernetns[nsnr].perintf[i].rfifo; + si->intf.intfns[nsnr+1].intf[i].rframe = shmp->netnsdata.pernetns[nsnr].perintf[i].rframe; + si->intf.intfns[nsnr+1].intf[i].rcompr = shmp->netnsdata.pernetns[nsnr].perintf[i].rcompr; + si->intf.intfns[nsnr+1].intf[i].rmultic = shmp->netnsdata.pernetns[nsnr].perintf[i].rmultic; + si->intf.intfns[nsnr+1].intf[i].sbyte = shmp->netnsdata.pernetns[nsnr].perintf[i].sbyte; + si->intf.intfns[nsnr+1].intf[i].spack = shmp->netnsdata.pernetns[nsnr].perintf[i].spack; + si->intf.intfns[nsnr+1].intf[i].serrs = shmp->netnsdata.pernetns[nsnr].perintf[i].serrs; + si->intf.intfns[nsnr+1].intf[i].sdrop = shmp->netnsdata.pernetns[nsnr].perintf[i].sdrop; + si->intf.intfns[nsnr+1].intf[i].sfifo = shmp->netnsdata.pernetns[nsnr].perintf[i].sfifo; + si->intf.intfns[nsnr+1].intf[i].scollis = shmp->netnsdata.pernetns[nsnr].perintf[i].scollis; + si->intf.intfns[nsnr+1].intf[i].scarrier = shmp->netnsdata.pernetns[nsnr].perintf[i].scarrier; + si->intf.intfns[nsnr+1].intf[i].scompr = shmp->netnsdata.pernetns[nsnr].perintf[i].scompr; + si->intf.intfns[nsnr+1].intf[i].type = shmp->netnsdata.pernetns[nsnr].perintf[i].type; + si->intf.intfns[nsnr+1].intf[i].speed = shmp->netnsdata.pernetns[nsnr].perintf[i].speed; + si->intf.intfns[nsnr+1].intf[i].speedp = shmp->netnsdata.pernetns[nsnr].perintf[i].speedp; + si->intf.intfns[nsnr+1].intf[i].duplex = shmp->netnsdata.pernetns[nsnr].perintf[i].duplex; + } + si->intf.intfns[nsnr+1].intf[i].name[0] = '\0'; + si->intf.intfns[nsnr+1].nrintf = i + 1; + strcpy(si->intf.intfns[nsnr+1].nsname, shmp->netnsdata.pernetns[nsnr].nsname); + + /* 2. IPv4 stats from the file /proc/net/snmp */ + memcpy(&si->net.netns[nsnr+1].ipv4, shmp->netnsdata.pernetns[nsnr].snmp.ipv4, + sizeof si->net.netns[nsnr].ipv4); + memcpy(&si->net.netns[nsnr+1].icmpv4, shmp->netnsdata.pernetns[nsnr].snmp.icmpv4, + sizeof si->net.netns[nsnr].icmpv4); + memcpy(&si->net.netns[nsnr+1].udpv4, shmp->netnsdata.pernetns[nsnr].snmp.udpv4, + sizeof si->net.netns[nsnr].udpv4); + memcpy(&si->net.netns[nsnr+1].tcp, shmp->netnsdata.pernetns[nsnr].snmp.tcp, + sizeof si->net.netns[nsnr].tcp); + + /* 3. IPv6 stats from the file /proc/net/snmp6 */ + memset(&ipv6_tmp, 0, sizeof ipv6_tmp); + memset(&icmpv6_tmp, 0, sizeof icmpv6_tmp); + memset(&udpv6_tmp, 0, sizeof udpv6_tmp); + + for (i = 0; i < v6tab_entries; i++) + *(v6tab[i].val) = shmp->netnsdata.pernetns[nsnr].snmp6.val[i]; + + memcpy(&si->net.netns[nsnr+1].ipv6, &ipv6_tmp, sizeof ipv6_tmp); + memcpy(&si->net.netns[nsnr+1].icmpv6, &icmpv6_tmp, sizeof icmpv6_tmp); + memcpy(&si->net.netns[nsnr+1].udpv6, &udpv6_tmp, sizeof udpv6_tmp); + + strcpy(si->net.netns[nsnr+1].nsname, shmp->netnsdata.pernetns[nsnr].nsname); + + si->net.nrnetns += 1; + si->intf.nrintfns += 1; + } + } + } + + munmap(shmp, sizeof(*shmp)); + } + /* ** check if extended partition-statistics are provided < kernel 2.6 */ @@ -2809,3 +2918,205 @@ do_perfevents(char *tagname, char *tagvalue) mcleanstop(1, "atop built with NOPERFEVENT, cannot use perfevents\n"); } #endif + +int getothernetns(struct shmbuf *shmp) { + int fd, ret, nr, i = 0; + int nsnr = 0, validns = 0; + FILE *fp = NULL; + count_t cnts[64], countval; + char linebuf[1024], nam[64]; + + while ( strlen(othernetns[nsnr]) ) + { + fd = open(othernetns[nsnr], O_RDONLY); + if ( fd < 0 ) + { + fprintf(stderr, "failed to open %s, errno is %d\n", othernetns[nsnr], errno); + nsnr++; + continue; + } + + /* use setns to validate if the netns can be collected, if not: pass */ + ret = setns(fd, CLONE_NEWNET); + if ( ret == -1 ) + { + close(fd); + nsnr++; + continue; + } + + close(fd); + + /* 1. interface stats from the file /proc/net/dev */ + if ( (fp = fopen("/proc/net/dev", "r")) != NULL ) + { + struct ifprop ifprop; + char *cp; + i = 0; + + while ( fgets(linebuf, sizeof(linebuf), fp) != NULL ) + { + if ( (cp = strchr(linebuf, ':')) != NULL ) + *cp = ' '; /* substitute ':' by space */ + + nr = sscanf(linebuf, + "%15s %lld %lld %lld %lld %lld %lld %lld " + "%lld %lld %lld %lld %lld %lld %lld %lld " + "%lld\n", + nam, + &cnts[0], &cnts[1], &cnts[2], &cnts[3], + &cnts[4], &cnts[5], &cnts[6], &cnts[7], + &cnts[8], &cnts[9], &cnts[10], &cnts[11], + &cnts[12], &cnts[13], &cnts[14], &cnts[15]); + + /* skip header line and lines without stats */ + if ( nr != 17 ) + continue; + + /* omit virtual net, but keep lo */ + strcpy(ifprop.name, nam); + + /* If `ethtool -i` failed or bus-info is null: not physical, omit */ + if ( getbusinfo(&ifprop) == 0 && strcmp(nam, "lo") != 0 ) + continue; + + if ( getphysprop(&ifprop) == 0 ) + continue; + + /* If rpack and spack is both zero, omit */ + if ( ! (cnts[1] || cnts[9]) ) + continue; + + strcpy(shmp->netnsdata.pernetns[validns].perintf[i].name, nam); + shmp->netnsdata.pernetns[validns].perintf[i].rbyte = cnts[0]; + shmp->netnsdata.pernetns[validns].perintf[i].rpack = cnts[1]; + shmp->netnsdata.pernetns[validns].perintf[i].rerrs = cnts[2]; + shmp->netnsdata.pernetns[validns].perintf[i].rdrop = cnts[3]; + shmp->netnsdata.pernetns[validns].perintf[i].rfifo = cnts[4]; + shmp->netnsdata.pernetns[validns].perintf[i].rframe = cnts[5]; + shmp->netnsdata.pernetns[validns].perintf[i].rcompr = cnts[6]; + shmp->netnsdata.pernetns[validns].perintf[i].rmultic = cnts[7]; + shmp->netnsdata.pernetns[validns].perintf[i].sbyte = cnts[8]; + shmp->netnsdata.pernetns[validns].perintf[i].spack = cnts[9]; + shmp->netnsdata.pernetns[validns].perintf[i].serrs = cnts[10]; + shmp->netnsdata.pernetns[validns].perintf[i].sdrop = cnts[11]; + shmp->netnsdata.pernetns[validns].perintf[i].sfifo = cnts[12]; + shmp->netnsdata.pernetns[validns].perintf[i].scollis = cnts[13]; + shmp->netnsdata.pernetns[validns].perintf[i].scarrier = cnts[14]; + shmp->netnsdata.pernetns[validns].perintf[i].scompr = cnts[15]; + + shmp->netnsdata.pernetns[validns].perintf[i].type = ifprop.type; + shmp->netnsdata.pernetns[validns].perintf[i].speed = ifprop.speed; + shmp->netnsdata.pernetns[validns].perintf[i].speedp = ifprop.speed; + shmp->netnsdata.pernetns[validns].perintf[i].duplex = ifprop.fullduplex; + + + if ( ++i >= PHYNETMAX - 1 ) + break; + } + + if ( i > 0 ) + { + shmp->netnsdata.pernetns[validns].nrintf = i; + shmp->netnsdata.pernetns[validns].perintf[i].name[0] = '\0'; /* set terminator for table */ + } + fclose(fp); + } + + /* If neither physical nic nor 'lo' has statistics, omit this netns */ + if ( i == 0 ) + { + close(fd); + nsnr++; + continue; + } + + /* 2. IPv4 stats from the file /proc/net/snmp */ + if ( (fp = fopen("/proc/net/snmp", "r")) != NULL ) + { + while ( fgets(linebuf, sizeof(linebuf), fp) != NULL ) + { + nr = sscanf(linebuf, + "%s %lld %lld %lld %lld %lld %lld %lld %lld %lld " + "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld " + "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld " + "%lld\n", + nam, + &cnts[0], &cnts[1], &cnts[2], &cnts[3], + &cnts[4], &cnts[5], &cnts[6], &cnts[7], + &cnts[8], &cnts[9], &cnts[10], &cnts[11], + &cnts[12], &cnts[13], &cnts[14], &cnts[15], + &cnts[16], &cnts[17], &cnts[18], &cnts[19], + &cnts[20], &cnts[21], &cnts[22], &cnts[23], + &cnts[24], &cnts[25], &cnts[26], &cnts[27], + &cnts[28], &cnts[29]); + + if ( nr < 2 ) /* headerline ? --> skip */ + continue; + + if ( strcmp("Ip:", nam) == 0 ) + { + memcpy(&shmp->netnsdata.pernetns[validns].snmp.ipv4, cnts, + sizeof shmp->netnsdata.pernetns[validns].snmp.ipv4); + continue; + } + + if ( strcmp("Icmp:", nam) == 0 ) + { + memcpy(&shmp->netnsdata.pernetns[validns].snmp.icmpv4, cnts, + sizeof shmp->netnsdata.pernetns[validns].snmp.icmpv4); + continue; + } + + if ( strcmp("Tcp:", nam) == 0 ) + { + memcpy(&shmp->netnsdata.pernetns[validns].snmp.tcp, cnts, + sizeof shmp->netnsdata.pernetns[validns].snmp.tcp); + continue; + } + + if ( strcmp("Udp:", nam) == 0 ) + { + memcpy(&shmp->netnsdata.pernetns[validns].snmp.udpv4, cnts, + sizeof shmp->netnsdata.pernetns[validns].snmp.udpv4); + continue; + } + } + + fclose(fp); + } + + /* 3. IPv6 stats from the file /proc/net/snmp6 */ + if ( (fp = fopen("/proc/net/snmp6", "r")) != NULL ) + { + int idx = 0, cur = 0; + + while ( fgets(linebuf, sizeof(linebuf), fp) != NULL ) + { + /* headerline ? --> skip */ + if ( sscanf(linebuf, "%15s %lld\n", nam, &countval) < 2 ) + continue; + + if ( v6tab[cur].idx == idx ) + { + shmp->netnsdata.pernetns[validns].snmp6.val[cur] = countval; + cur++; + } + idx++; + } + + fclose(fp); + } + + strncpy(shmp->netnsdata.pernetns[validns].nsname, othernetns[nsnr], sizeof(othernetns[0])); + shmp->netnsdata.nssum++; + + validns++; + nsnr++; + } + + if ( sem_post(&shmp->sem) == -1 ) + mcleanstop(53, "failed to sem_post in getothernetns, errno is %d\n", errno); + + exit(0); +} diff --git a/photosyst.h b/photosyst.h index 1850a2e5..5bcc40be 100644 --- a/photosyst.h +++ b/photosyst.h @@ -24,6 +24,7 @@ #ifndef __PHOTOSYST__ #define __PHOTOSYST__ +#include #include "netstats.h" #define MAXCPU 2048 @@ -467,4 +468,37 @@ void photosyst (struct sstat *); void deviatsyst(struct sstat *, struct sstat *, struct sstat *, long); void totalsyst (char, struct sstat *, struct sstat *); void do_perfevents(char *, char *); + +#define PHYNETMAX 8 +struct snmp { + count_t ipv4[20]; + count_t icmpv4[30]; + count_t udpv4[5]; + count_t tcp[20]; +}; + +struct snmp6 { + count_t val[100]; +}; + +struct pernetns { + int nsnr; + char nsname[NETNSNAMELEN]; + int nrintf; + struct perintf perintf[PHYNETMAX]; /* max physical nic */ + struct snmp snmp; + struct snmp6 snmp6; +}; + +struct netnsdata { + int nssum; + struct pernetns pernetns[MAXNETNS - 1]; +}; + +struct shmbuf { + sem_t sem; /* POSIX unnamed semaphore */ + struct netnsdata netnsdata; /* Data being transferred */ +}; + +int getothernetns(struct shmbuf *); #endif From 63fc86cea929e047c7537435bd40441037de016e Mon Sep 17 00:00:00 2001 From: Fei Li Date: Wed, 15 Feb 2023 10:41:20 +0800 Subject: [PATCH 6/6] Add netns configuration for /etc/atoprc The default rule is splitting netns by blank space. And make sure the netns path exits. Signed-off-by: Fei Li --- atop.c | 1 + photosyst.c | 33 +++++++++++++++++++++++++++++++++ photosyst.h | 1 + 3 files changed, 35 insertions(+) diff --git a/atop.c b/atop.c index de880549..8ce6671f 100644 --- a/atop.c +++ b/atop.c @@ -254,6 +254,7 @@ static struct { { "atopsarflags", do_atopsarflags, 0, }, { "perfevents", do_perfevents, 0, }, { "pacctdir", do_pacctdir, 1, }, + { "netns", do_netns, 1, }, }; /* diff --git a/photosyst.c b/photosyst.c index 76030496..29e6b7f8 100644 --- a/photosyst.c +++ b/photosyst.c @@ -3120,3 +3120,36 @@ int getothernetns(struct shmbuf *shmp) { exit(0); } + +void +do_netns(char *name, char *val) +{ + char *pernetns, *validnetns; + int ns = 0; + struct stat nsstat; + + if ( strlen(val) == 0 ) + return; + + validnetns = malloc( (MAXNETNS - 1) * NETNSNAMELEN * sizeof(char) ); + strncpy(validnetns, val, (MAXNETNS - 1) * NETNSNAMELEN); + + /* split netns by blank space */ + pernetns = strtok(validnetns, " "); + while (pernetns) + { + /* valid if this file exits, and later setns() will prove the netns is available */ + if ( stat(pernetns, &nsstat) ) + { + fprintf(stderr, "netns %s stat failed, errno is %d\n", pernetns, errno); + pernetns = strtok(NULL, " "); + continue; + } + + strncpy(othernetns[ns], pernetns, sizeof(othernetns[ns])); + if (++ns >= MAXNETNS - 1) + break; + pernetns = strtok(NULL, " "); + } + free(validnetns); +} diff --git a/photosyst.h b/photosyst.h index 5bcc40be..82ea62bf 100644 --- a/photosyst.h +++ b/photosyst.h @@ -468,6 +468,7 @@ void photosyst (struct sstat *); void deviatsyst(struct sstat *, struct sstat *, struct sstat *, long); void totalsyst (char, struct sstat *, struct sstat *); void do_perfevents(char *, char *); +void do_netns(char *, char *); #define PHYNETMAX 8 struct snmp {