Browse Source

fix(collectors/cgroups): use different context for cgroup network charts (#12454)

Ilya Mashchenko 3 years ago
parent
commit
e1f2464103
4 changed files with 238 additions and 124 deletions
  1. 64 23
      collectors/proc.plugin/proc_net_dev.c
  2. 37 0
      health/health.d/cgroups.conf
  3. 4 4
      health/health.d/net.conf
  4. 133 97
      web/gui/dashboard_info.js

+ 64 - 23
collectors/proc.plugin/proc_net_dev.c

@@ -75,6 +75,19 @@ static struct netdev {
     const char *chart_id_net_carrier;
     const char *chart_id_net_mtu;
 
+    const char *chart_ctx_net_bytes;
+    const char *chart_ctx_net_packets;
+    const char *chart_ctx_net_errors;
+    const char *chart_ctx_net_fifo;
+    const char *chart_ctx_net_events;
+    const char *chart_ctx_net_drops;
+    const char *chart_ctx_net_compressed;
+    const char *chart_ctx_net_speed;
+    const char *chart_ctx_net_duplex;
+    const char *chart_ctx_net_operstate;
+    const char *chart_ctx_net_carrier;
+    const char *chart_ctx_net_mtu;
+
     const char *chart_family;
 
     struct label *chart_labels;
@@ -241,6 +254,19 @@ static void netdev_free_chart_strings(struct netdev *d) {
     freez((void *)d->chart_id_net_carrier);
     freez((void *)d->chart_id_net_mtu);
 
+    freez((void *)d->chart_ctx_net_bytes);
+    freez((void *)d->chart_ctx_net_compressed);
+    freez((void *)d->chart_ctx_net_drops);
+    freez((void *)d->chart_ctx_net_errors);
+    freez((void *)d->chart_ctx_net_events);
+    freez((void *)d->chart_ctx_net_fifo);
+    freez((void *)d->chart_ctx_net_packets);
+    freez((void *)d->chart_ctx_net_speed);
+    freez((void *)d->chart_ctx_net_duplex);
+    freez((void *)d->chart_ctx_net_operstate);
+    freez((void *)d->chart_ctx_net_carrier);
+    freez((void *)d->chart_ctx_net_mtu);
+
     freez((void *)d->chart_family);
 }
 
@@ -384,40 +410,42 @@ static inline void netdev_rename_cgroup(struct netdev *d, struct netdev_rename *
 
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_%s", r->container_device);
     d->chart_id_net_bytes      = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_compressed_%s", r->container_device);
     d->chart_id_net_compressed = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_drops_%s", r->container_device);
     d->chart_id_net_drops      = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_errors_%s", r->container_device);
     d->chart_id_net_errors     = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_events_%s", r->container_device);
     d->chart_id_net_events     = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_fifo_%s", r->container_device);
     d->chart_id_net_fifo       = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_packets_%s", r->container_device);
     d->chart_id_net_packets    = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_speed_%s", r->container_device);
     d->chart_id_net_speed      = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_duplex_%s", r->container_device);
     d->chart_id_net_duplex     = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_operstate_%s", r->container_device);
     d->chart_id_net_operstate  = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_carrier_%s", r->container_device);
     d->chart_id_net_carrier    = strdupz(buffer);
-
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_mtu_%s", r->container_device);
     d->chart_id_net_mtu        = strdupz(buffer);
 
+    d->chart_ctx_net_bytes      = strdupz("cgroup.net_net");
+    d->chart_ctx_net_compressed = strdupz("cgroup.net_compressed");
+    d->chart_ctx_net_drops      = strdupz("cgroup.net_drops");
+    d->chart_ctx_net_errors     = strdupz("cgroup.net_errors");
+    d->chart_ctx_net_events     = strdupz("cgroup.net_events");
+    d->chart_ctx_net_fifo       = strdupz("cgroup.net_fifo");
+    d->chart_ctx_net_packets    = strdupz("cgroup.net_packets");
+    d->chart_ctx_net_speed      = strdupz("cgroup.net_speed");
+    d->chart_ctx_net_duplex     = strdupz("cgroup.net_duplex");
+    d->chart_ctx_net_operstate  = strdupz("cgroup.net_operstate");
+    d->chart_ctx_net_carrier    = strdupz("cgroup.net_carrier");
+    d->chart_ctx_net_mtu        = strdupz("cgroup.net_mtu");
+
     snprintfz(buffer, RRD_ID_LENGTH_MAX, "net %s", r->container_device);
     d->chart_family = strdupz(buffer);
 
@@ -541,6 +569,19 @@ static struct netdev *get_netdev(const char *name) {
     d->chart_id_net_carrier    = strdupz(d->name);
     d->chart_id_net_mtu        = strdupz(d->name);
 
+    d->chart_ctx_net_bytes      = strdupz("net.net");
+    d->chart_ctx_net_compressed = strdupz("net.compressed");
+    d->chart_ctx_net_drops      = strdupz("net.drops");
+    d->chart_ctx_net_errors     = strdupz("net.errors");
+    d->chart_ctx_net_events     = strdupz("net.events");
+    d->chart_ctx_net_fifo       = strdupz("net.fifo");
+    d->chart_ctx_net_packets    = strdupz("net.packets");
+    d->chart_ctx_net_speed      = strdupz("net.speed");
+    d->chart_ctx_net_duplex     = strdupz("net.duplex");
+    d->chart_ctx_net_operstate  = strdupz("net.operstate");
+    d->chart_ctx_net_carrier    = strdupz("net.carrier");
+    d->chart_ctx_net_mtu        = strdupz("net.mtu");
+
     d->chart_family = strdupz(d->name);
     d->priority = NETDATA_CHART_PRIO_FIRST_NET_IFACE;
 
@@ -825,7 +866,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_bytes
                         , NULL
                         , d->chart_family
-                        , "net.net"
+                        , d->chart_ctx_net_bytes
                         , "Bandwidth"
                         , "kilobits/s"
                         , PLUGIN_PROC_NAME
@@ -881,7 +922,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                                         , d->chart_id_net_speed
                                         , NULL
                                         , d->chart_family
-                                        , "net.speed"
+                                        , d->chart_ctx_net_speed
                                         , "Interface Speed"
                                         , "kilobits/s"
                                         , PLUGIN_PROC_NAME
@@ -916,7 +957,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_duplex
                         , NULL
                         , d->chart_family
-                        , "net.duplex"
+                        , d->chart_ctx_net_duplex
                         , "Interface Duplex State"
                         , "state"
                         , PLUGIN_PROC_NAME
@@ -947,7 +988,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_operstate
                         , NULL
                         , d->chart_family
-                        , "net.operstate"
+                        , d->chart_ctx_net_operstate
                         , "Interface Operational State"
                         , "state"
                         , PLUGIN_PROC_NAME
@@ -978,7 +1019,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_carrier
                         , NULL
                         , d->chart_family
-                        , "net.carrier"
+                        , d->chart_ctx_net_carrier
                         , "Interface Physical Link State"
                         , "state"
                         , PLUGIN_PROC_NAME
@@ -1009,7 +1050,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_mtu
                         , NULL
                         , d->chart_family
-                        , "net.mtu"
+                        , d->chart_ctx_net_mtu
                         , "Interface MTU"
                         , "octets"
                         , PLUGIN_PROC_NAME
@@ -1045,7 +1086,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_packets
                         , NULL
                         , d->chart_family
-                        , "net.packets"
+                        , d->chart_ctx_net_packets
                         , "Packets"
                         , "packets/s"
                         , PLUGIN_PROC_NAME
@@ -1093,7 +1134,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_errors
                         , NULL
                         , d->chart_family
-                        , "net.errors"
+                        , d->chart_ctx_net_errors
                         , "Interface Errors"
                         , "errors/s"
                         , PLUGIN_PROC_NAME
@@ -1139,7 +1180,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_drops
                         , NULL
                         , d->chart_family
-                        , "net.drops"
+                        , d->chart_ctx_net_drops
                         , "Interface Drops"
                         , "drops/s"
                         , PLUGIN_PROC_NAME
@@ -1185,7 +1226,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_fifo
                         , NULL
                         , d->chart_family
-                        , "net.fifo"
+                        , d->chart_ctx_net_fifo
                         , "Interface FIFO Buffer Errors"
                         , "errors"
                         , PLUGIN_PROC_NAME
@@ -1231,7 +1272,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_compressed
                         , NULL
                         , d->chart_family
-                        , "net.compressed"
+                        , d->chart_ctx_net_compressed
                         , "Compressed Packets"
                         , "packets/s"
                         , PLUGIN_PROC_NAME
@@ -1277,7 +1318,7 @@ int do_proc_net_dev(int update_every, usec_t dt) {
                         , d->chart_id_net_events
                         , NULL
                         , d->chart_family
-                        , "net.events"
+                        , d->chart_ctx_net_events
                         , "Network Interface Events"
                         , "events/s"
                         , PLUGIN_PROC_NAME

+ 37 - 0
health/health.d/cgroups.conf

@@ -32,3 +32,40 @@ component: Memory
     delay: down 15m multiplier 1.5 max 1h
      info: cgroup memory utilization
        to: sysadmin
+
+# -----------------------------------------------------------------------------
+# check for packet storms
+
+# 1. calculate the rate packets are received in 1m: 1m_received_packets_rate
+# 2. do the same for the last 10s
+# 3. raise an alarm if the later is 10x or 20x the first
+# we assume the minimum packet storm should at least have
+# 10000 packets/s, average of the last 10 seconds
+
+ template: cgroup_1m_received_packets_rate
+       on: cgroup.net_packets
+    class: Workload
+     type: Cgroups
+component: Network
+    hosts: *
+   lookup: average -1m unaligned of received
+    units: packets
+    every: 10s
+     info: average number of packets received by the network interface $family over the last minute
+
+ template: cgroup_10s_received_packets_storm
+       on: cgroup.net_packets
+    class: Workload
+     type: Cgroups
+component: Network
+    hosts: *
+   lookup: average -10s unaligned of received
+     calc: $this * 100 / (($1m_received_packets_rate < 1000)?(1000):($1m_received_packets_rate))
+    every: 10s
+    units: %
+     warn: $this > (($status >= $WARNING)?(200):(5000))
+     crit: $this > (($status == $CRITICAL)?(5000):(6000))
+  options: no-clear-notification
+     info: ratio of average number of received packets for the network interface $family over the last 10 seconds, \
+           compared to the rate over the last minute
+       to: sysadmin

+ 4 - 4
health/health.d/net.conf

@@ -68,7 +68,7 @@ component: Network
 component: Network
        os: linux
     hosts: *
- families: !net* *
+ families: *
    lookup: sum -10m unaligned absolute of inbound
     units: packets
     every: 1m
@@ -81,7 +81,7 @@ component: Network
 component: Network
        os: linux
     hosts: *
- families: !net* *
+ families: *
    lookup: sum -10m unaligned absolute of outbound
     units: packets
     every: 1m
@@ -94,7 +94,7 @@ component: Network
 component: Network
        os: linux
     hosts: *
- families: !net* !wl* *
+ families: !wl* *
    lookup: sum -10m unaligned absolute of received
      calc: (($inbound_packets_dropped != nan AND $this > 10000) ? ($inbound_packets_dropped * 100 / $this) : (0))
     units: %
@@ -111,7 +111,7 @@ component: Network
 component: Network
        os: linux
     hosts: *
- families: !net* !wl* *
+ families: !wl* *
    lookup: sum -10m unaligned absolute of sent
      calc: (($outbound_packets_dropped != nan AND $this > 1000) ? ($outbound_packets_dropped * 100 / $this) : (0))
     units: %

+ 133 - 97
web/gui/dashboard_info.js

@@ -1080,6 +1080,62 @@ netdataDashboard.submenu = {
 var cgroupCPULimitIsSet = 0;
 var cgroupMemLimitIsSet = 0;
 
+const netBytesInfo = 'The amount of traffic transferred by the network interface.'
+const netPacketsInfo = 'The number of packets transferred by the network interface. ' +
+    'Received <a href="https://en.wikipedia.org/wiki/Multicast" target="_blank">multicast</a> counter is ' +
+    'commonly calculated at the device level (unlike <b>received</b>) and therefore may include packets which did not reach the host.'
+const netErrorsInfo = '<p>The number of errors encountered by the network interface.</p>' +
+    '<p><b>Inbound</b> - bad packets received on this interface. ' +
+    'It includes dropped packets due to invalid length, CRC, frame alignment, and other errors. ' +
+    '<b>Outbound</b> - transmit problems. ' +
+    'It includes frames transmission errors due to loss of carrier, FIFO underrun/underflow, heartbeat, ' +
+    'late collisions, and other problems.</p>'
+const netFIFOInfo = '<p>The number of FIFO errors encountered by the network interface.</p>' +
+    '<p><b>Inbound</b> - packets dropped because they did not fit into buffers provided by the host, ' +
+    'e.g. packets larger than MTU or next buffer in the ring was not available for a scatter transfer. ' +
+    '<b>Outbound</b> - frame transmission errors due to device FIFO underrun/underflow. ' +
+    'This condition occurs when the device begins transmission of a frame ' +
+    'but is unable to deliver the entire frame to the transmitter in time for transmission.</p>'
+const netDropsInfo = '<p>The number of packets that have been dropped at the network interface level.</p>' +
+    '<p><b>Inbound</b> - packets received but not processed, e.g. due to ' +
+    '<a href="#menu_system_submenu_softnet_stat">softnet backlog</a> overflow, bad/unintended VLAN tags, ' +
+    'unknown or unregistered protocols, IPv6 frames when the server is not configured for IPv6. ' +
+    '<b>Outbound</b> - packets dropped on their way to transmission, e.g. due to lack of resources.</p>'
+const netCompressedInfo = 'The number of correctly transferred compressed packets by the network interface. ' +
+    'These counters are only meaningful for interfaces which support packet compression (e.g. CSLIP, PPP).'
+const netEventsInfo = '<p>The number of errors encountered by the network interface.</p>' +
+    '<p><b>Frames</b> - aggregated counter for dropped packets due to ' +
+    'invalid length, FIFO overflow, CRC, and frame alignment errors. ' +
+    '<b>Collisions</b> - ' +
+    '<a href="https://en.wikipedia.org/wiki/Collision_(telecommunications)" target="blank">collisions</a> during packet transmissions. ' +
+    '<b>Carrier</b> - aggregated counter for frame transmission errors due to ' +
+    'excessive collisions, loss of carrier, device FIFO underrun/underflow, Heartbeat/SQE Test errors, and  late collisions.</p>'
+const netDuplexInfo = '<p>The interface\'s latest or current ' +
+    '<a href="https://en.wikipedia.org/wiki/Duplex_(telecommunications)" target="_blank">duplex</a> that the network adapter ' +
+    '<a href="https://en.wikipedia.org/wiki/Autonegotiation" target="_blank">negotiated</a> with the device it is connected to.</p>' +
+    '<p><b>Unknown</b> - the duplex mode can not be determined. ' +
+    '<b>Half duplex</b> - the communication is one direction at a time. ' +
+    '<b>Full duplex</b> - the interface is able to send and receive data simultaneously.</p>' +
+    '<p><b>State map</b>: 0 - unknown, 1 - half, 2 - full.</p>'
+const netOperstateInfo = '<p>The current ' +
+    '<a href="https://datatracker.ietf.org/doc/html/rfc2863" target="_blank">operational state</a> of the interface.</p>' +
+    '<p><b>Unknown</b> - the state can not be determined. ' +
+    '<b>NotPresent</b> - the interface has missing (typically, hardware) components. ' +
+    '<b>Down</b> - the interface is unable to transfer data on L1, e.g. ethernet is not plugged or interface is administratively down. ' +
+    '<b>LowerLayerDown</b> - the interface is down due to state of lower-layer interface(s). ' +
+    '<b>Testing</b> - the interface is in testing mode, e.g. cable test. It can’t be used for normal traffic until tests complete. ' +
+    '<b>Dormant</b> - the interface is L1 up, but waiting for an external event, e.g. for a protocol to establish. ' +
+    '<b>Up</b> - the interface is ready to pass packets and can be used.</p>' +
+    '<p><b>State map</b>: 0 - unknown, 1 - notpresent, 2 - down, 3 - lowerlayerdown, 4 - testing, 5 - dormant, 6 - up.</p>'
+const netCarrierInfo = '<p>The current physical link state of the interface.</p>' +
+    '<p><b>State map</b>: 0 - down, 1 - up.</p>'
+const netSpeedInfo = 'The interface\'s latest or current speed that the network adapter ' +
+    '<a href="https://en.wikipedia.org/wiki/Autonegotiation" target="_blank">negotiated</a> with the device it is connected to. ' +
+    'This does not give the max supported speed of the NIC.'
+const netMTUInfo = 'The interface\'s currently configured ' +
+    '<a href="https://en.wikipedia.org/wiki/Maximum_transmission_unit" target="_blank">Maximum transmission unit</a> (MTU) value. ' +
+    'MTU is the size of the largest protocol data unit that can be communicated in a single network layer transaction.'
+
 netdataDashboard.context = {
     'system.cpu': {
         info: function (os) {
@@ -2654,127 +2710,107 @@ netdataDashboard.context = {
     // NETWORK INTERFACES
 
     'net.net': {
-        mainheads: [
-            function (os, id) {
-                void (os);
-                if (id.match(/^cgroup_.*/)) {
-                    var iface;
-                    try {
-                        iface = ' ' + id.substring(id.lastIndexOf('.net_') + 5, id.length);
-                    } catch (e) {
-                        iface = '';
-                    }
-                    return netdataDashboard.gaugeChart('Received' + iface, '12%', 'received');
-                } else
-                    return '';
-            },
-            function (os, id) {
-                void (os);
-                if (id.match(/^cgroup_.*/)) {
-                    var iface;
-                    try {
-                        iface = ' ' + id.substring(id.lastIndexOf('.net_') + 5, id.length);
-                    } catch (e) {
-                        iface = '';
-                    }
-                    return netdataDashboard.gaugeChart('Sent' + iface, '12%', 'sent');
-                } else
-                    return '';
-            }
-        ],
         heads: [
-            function (os, id) {
-                void (os);
-                if (!id.match(/^cgroup_.*/))
-                    return netdataDashboard.gaugeChart('Received', '12%', 'received');
-                else
-                    return '';
-            },
-            function (os, id) {
-                void (os);
-                if (!id.match(/^cgroup_.*/))
-                    return netdataDashboard.gaugeChart('Sent', '12%', 'sent');
-                else
-                    return '';
-            }
+            netdataDashboard.gaugeChart('Received', '12%', 'received'),
+            netdataDashboard.gaugeChart('Sent', '12%', 'sent'),
         ],
-        info: 'The amount of traffic transferred by the network interface.'
+        info: netBytesInfo
     },
     'net.packets': {
-        info: 'The number of packets transferred by the network interface. '+
-        'Received <a href="https://en.wikipedia.org/wiki/Multicast" target="_blank">multicast</a> counter is '+
-        'commonly calculated at the device level (unlike <b>received</b>) and therefore may include packets which did not reach the host.'
+        info: netPacketsInfo
     },
     'net.errors': {
-        info: '<p>The number of errors encountered by the network interface.</p>'+
-        '<p><b>Inbound</b> - bad packets received on this interface. '+
-        'It includes dropped packets due to invalid length, CRC, frame alignment, and other errors. '+
-        '<b>Outbound</b> - transmit problems. '+
-        'It includes frames transmission errors due to loss of carrier, FIFO underrun/underflow, heartbeat, '+
-        'late collisions, and other problems.</p>'
+        info: netErrorsInfo
     },
     'net.fifo': {
-        info: '<p>The number of FIFO errors encountered by the network interface.</p>'+
-        '<p><b>Inbound</b> - packets dropped because they did not fit into buffers provided by the host, '+
-        'e.g. packets larger than MTU or next buffer in the ring was not available for a scatter transfer. '+
-        '<b>Outbound</b> - frame transmission errors due to device FIFO underrun/underflow. '+
-        'This condition occurs when the device begins transmission of a frame '+
-        'but is unable to deliver the entire frame to the transmitter in time for transmission.</p>'
+        info: netFIFOInfo
     },
     'net.drops': {
-        info: '<p>The number of packets that have been dropped at the network interface level.</p>'+
-        '<p><b>Inbound</b> - packets received but not processed, e.g. due to '+
-        '<a href="#menu_system_submenu_softnet_stat">softnet backlog</a> overflow, bad/unintended VLAN tags, '+
-        'unknown or unregistered protocols, IPv6 frames when the server is not configured for IPv6. '+
-        '<b>Outbound</b> - packets dropped on their way to transmission, e.g. due to lack of resources.</p>'
+        info: netDropsInfo
     },
     'net.compressed': {
-        info: 'The number of correctly transferred compressed packets by the network interface. '+
-        'These counters are only meaningful for interfaces which support packet compression (e.g. CSLIP, PPP).'
+        info: netCompressedInfo
     },
     'net.events': {
-        info: '<p>The number of errors encountered by the network interface.</p>'+
-        '<p><b>Frames</b> - aggregated counter for dropped packets due to '+
-        'invalid length, FIFO overflow, CRC, and frame alignment errors. '+
-        '<b>Collisions</b> - '+
-        '<a href="https://en.wikipedia.org/wiki/Collision_(telecommunications)" target="blank">collisions</a> during packet transmissions. '+
-        '<b>Carrier</b> - aggregated counter for frame transmission errors due to '+
-        'excessive collisions, loss of carrier, device FIFO underrun/underflow, Heartbeat/SQE Test errors, and  late collisions.</p>'
+        info: netEventsInfo
     },
     'net.duplex': {
-        info: '<p>The interface\'s latest or current '+
-        '<a href="https://en.wikipedia.org/wiki/Duplex_(telecommunications)" target="_blank">duplex</a> that the network adapter '+
-        '<a href="https://en.wikipedia.org/wiki/Autonegotiation" target="_blank">negotiated</a> with the device it is connected to.</p>'+
-        '<p><b>Unknown</b> - the duplex mode can not be determined. '+
-        '<b>Half duplex</b> - the communication is one direction at a time. '+
-        '<b>Full duplex</b> - the interface is able to send and receive data simultaneously.</p>'+
-        '<p><b>State map</b>: 0 - unknown, 1 - half, 2 - full.</p>'
+        info: netDuplexInfo
     },
     'net.operstate': {
-        info: '<p>The current '+
-        '<a href="https://datatracker.ietf.org/doc/html/rfc2863" target="_blank">operational state</a> of the interface.</p>'+
-        '<p><b>Unknown</b> - the state can not be determined. '+
-        '<b>NotPresent</b> - the interface has missing (typically, hardware) components. '+
-        '<b>Down</b> - the interface is unable to transfer data on L1, e.g. ethernet is not plugged or interface is administratively down. '+
-        '<b>LowerLayerDown</b> - the interface is down due to state of lower-layer interface(s). '+
-        '<b>Testing</b> - the interface is in testing mode, e.g. cable test. It can’t be used for normal traffic until tests complete. '+
-        '<b>Dormant</b> - the interface is L1 up, but waiting for an external event, e.g. for a protocol to establish. '+
-        '<b>Up</b> - the interface is ready to pass packets and can be used.</p>'+
-        '<p><b>State map</b>: 0 - unknown, 1 - notpresent, 2 - down, 3 - lowerlayerdown, 4 - testing, 5 - dormant, 6 - up.</p>'
+        info: netOperstateInfo
     },
     'net.carrier': {
-        info: '<p>The current physical link state of the interface.</p>'+
-        '<p><b>State map</b>: 0 - down, 1 - up.</p>'
+        info: netCarrierInfo
     },
     'net.speed': {
-        info: 'The interface\'s latest or current speed that the network adapter '+
-        '<a href="https://en.wikipedia.org/wiki/Autonegotiation" target="_blank">negotiated</a> with the device it is connected to. '+
-        'This does not give the max supported speed of the NIC.'
+        info: netSpeedInfo
     },
     'net.mtu': {
-        info: 'The interface\'s currently configured '+
-        '<a href="https://en.wikipedia.org/wiki/Maximum_transmission_unit" target="_blank">Maximum transmission unit</a> (MTU) value. '+
-        'MTU is the size of the largest protocol data unit that can be communicated in a single network layer transaction.'
+        info: netMTUInfo
+    },
+
+    // ------------------------------------------------------------------------
+    // CGROUP NETWORK INTERFACES
+
+    'cgroup.net_net': {
+        mainheads: [
+            function (os, id) {
+                void (os);
+                var iface;
+                try {
+                    iface = ' ' + id.substring(id.lastIndexOf('.net_') + 5, id.length);
+                } catch (e) {
+                    iface = '';
+                }
+                return netdataDashboard.gaugeChart('Received' + iface, '12%', 'received');
+
+            },
+            function (os, id) {
+                void (os);
+                var iface;
+                try {
+                    iface = ' ' + id.substring(id.lastIndexOf('.net_') + 5, id.length);
+                } catch (e) {
+                    iface = '';
+                }
+                return netdataDashboard.gaugeChart('Sent' + iface, '12%', 'sent');
+            }
+        ],
+        info: netBytesInfo
+    },
+    'cgroup.net_packets': {
+        info: netPacketsInfo
+    },
+    'cgroup.net_errors': {
+        info: netErrorsInfo
+    },
+    'cgroup.net_fifo': {
+        info: netFIFOInfo
+    },
+    'cgroup.net_drops': {
+        info: netDropsInfo
+    },
+    'cgroup.net_compressed': {
+        info: netCompressedInfo
+    },
+    'cgroup.net_events': {
+        info: netEventsInfo
+    },
+    'cgroup.net_duplex': {
+        info: netDuplexInfo
+    },
+    'cgroup.net_operstate': {
+        info: netOperstateInfo
+    },
+    'cgroup.net_carrier': {
+        info: netCarrierInfo
+    },
+    'cgroup.net_speed': {
+        info: netSpeedInfo
+    },
+    'cgroup.net_mtu': {
+        info: netMTUInfo
     },
 
     // ------------------------------------------------------------------------