summaryrefslogtreecommitdiffstats
path: root/collectors
diff options
context:
space:
mode:
authorthiagoftsm <thiagoftsm@gmail.com>2020-10-20 11:04:05 +0000
committerGitHub <noreply@github.com>2020-10-20 14:04:05 +0300
commit31b045aa3c290d1fdc25edf03721a24c38fd303e (patch)
tree722330f16f48f8007549d3f9089f95ec2c31d556 /collectors
parent6b2ffc355a0d450e4569f3d5412b18d709318986 (diff)
Wireless statistics (#10052)
Co-authored-by: Ilya Mashchenko <ilya@netdata.cloud> Co-authored-by: Joel Hans <joel.g.hans@gmail.com> Co-authored-by: ladakis <vaggosbboy@gmail.com>
Diffstat (limited to 'collectors')
-rw-r--r--collectors/all.h6
-rw-r--r--collectors/proc.plugin/README.md40
-rw-r--r--collectors/proc.plugin/plugin_proc.c1
-rw-r--r--collectors/proc.plugin/plugin_proc.h1
-rw-r--r--collectors/proc.plugin/proc_net_wireless.c453
5 files changed, 501 insertions, 0 deletions
diff --git a/collectors/all.h b/collectors/all.h
index 9cb2fcb4bb..153fce9316 100644
--- a/collectors/all.h
+++ b/collectors/all.h
@@ -312,11 +312,17 @@
#define NETDATA_CHART_PRIO_MDSTAT_SPEED 9006
// Linux Power Supply
+
#define NETDATA_CHART_PRIO_POWER_SUPPLY_CAPACITY 9500 // 4 charts per power supply
#define NETDATA_CHART_PRIO_POWER_SUPPLY_CHARGE 9501
#define NETDATA_CHART_PRIO_POWER_SUPPLY_ENERGY 9502
#define NETDATA_CHART_PRIO_POWER_SUPPLY_VOLTAGE 9503
+
+// Wireless
+
+#define NETDATA_CHART_PRIO_WIRELESS_IFACE 7110
+
// CGROUPS
#define NETDATA_CHART_PRIO_CGROUPS_SYSTEMD 19000 // many charts
diff --git a/collectors/proc.plugin/README.md b/collectors/proc.plugin/README.md
index 8ab2e64ccd..6a8dc71142 100644
--- a/collectors/proc.plugin/README.md
+++ b/collectors/proc.plugin/README.md
@@ -13,6 +13,7 @@ custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/proc.
- `/proc/net/snmp` (total IPv4, TCP and UDP usage)
- `/proc/net/snmp6` (total IPv6 usage)
- `/proc/net/netstat` (more IPv4 usage)
+- `/proc/net/wireless` (wireless extension)
- `/proc/net/stat/nf_conntrack` (connection tracking performance)
- `/proc/net/stat/synproxy` (synproxy performance)
- `/proc/net/ip_vs/stats` (IPVS connection statistics)
@@ -322,6 +323,45 @@ each state.
By default Netdata will enable monitoring metrics only when they are not zero. If they are constantly zero they are ignored. Metrics that will start having values, after Netdata is started, will be detected and charts will be automatically added to the dashboard (a refresh of the dashboard is needed for them to appear though).
+### Monitoring wireless network interfaces
+
+The settings for monitoring wireless is in the `[plugin:proc:/proc/net/wireless]` section of your `netdata.conf` file.
+
+```conf
+ status for all interfaces = yes
+ quality for all interfaces = yes
+ discarded packets for all interfaces = yes
+ missed beacon for all interface = yes
+```
+
+You can set the following values for each configuration option:
+
+- `auto` = enable monitoring if the collected values are not zero
+- `yes` = enable monitoring
+- `no` = disable monitoring
+
+#### Monitored wireless interface metrics
+
+- **Status**
+ The current state of the interface. This is a device-dependent option.
+
+- **Link**
+ Overall quality of the link.
+
+- **Level**
+ Received signal strength (RSSI), which indicates how strong the received signal is.
+
+- **Noise**
+ Background noise level.
+
+- **Discarded packets**
+ Discarded packets for: Number of packets received with a different NWID or ESSID (`nwid`), unable to decrypt (`crypt`), hardware was not able to properly re-assemble the link layer fragments (`frag`), packets failed to deliver (`retry`), and packets lost in relation with specific wireless operations (`misc`).
+
+- **Missed beacon**
+ Number of periodic beacons from the cell or the access point the interface has missed.
+
+#### Wireless configuration
+
#### alarms
There are several alarms defined in `health.d/net.conf`.
diff --git a/collectors/proc.plugin/plugin_proc.c b/collectors/proc.plugin/plugin_proc.c
index cbbe2301b8..19230c09d5 100644
--- a/collectors/proc.plugin/plugin_proc.c
+++ b/collectors/proc.plugin/plugin_proc.c
@@ -39,6 +39,7 @@ static struct proc_module {
// network metrics
{ .name = "/proc/net/dev", .dim = "netdev", .func = do_proc_net_dev },
+ { .name = "/proc/net/wireless", .dim = "netwireless", .func = do_proc_net_wireless },
{ .name = "/proc/net/sockstat", .dim = "sockstat", .func = do_proc_net_sockstat },
{ .name = "/proc/net/sockstat6", .dim = "sockstat6", .func = do_proc_net_sockstat6 },
{ .name = "/proc/net/netstat", .dim = "netstat", .func = do_proc_net_netstat }, // this has to be before /proc/net/snmp, because there is a shared metric
diff --git a/collectors/proc.plugin/plugin_proc.h b/collectors/proc.plugin/plugin_proc.h
index 9d6b3ddfee..50ffb184ed 100644
--- a/collectors/proc.plugin/plugin_proc.h
+++ b/collectors/proc.plugin/plugin_proc.h
@@ -25,6 +25,7 @@
extern void *proc_main(void *ptr);
extern int do_proc_net_dev(int update_every, usec_t dt);
+extern int do_proc_net_wireless(int update_every, usec_t dt);
extern int do_proc_diskstats(int update_every, usec_t dt);
extern int do_proc_mdstat(int update_every, usec_t dt);
extern int do_proc_net_snmp(int update_every, usec_t dt);
diff --git a/collectors/proc.plugin/proc_net_wireless.c b/collectors/proc.plugin/proc_net_wireless.c
new file mode 100644
index 0000000000..32a53c68f5
--- /dev/null
+++ b/collectors/proc.plugin/proc_net_wireless.c
@@ -0,0 +1,453 @@
+#include <stdbool.h>
+#include "plugin_proc.h"
+
+#define PLUGIN_PROC_MODULE_NETWIRELESS_NAME "/proc/net/wireless"
+
+#define CONFIG_SECTION_PLUGIN_PROC_NETWIRELESS "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_NETWIRELESS_NAME
+
+
+static struct netwireless {
+ char *name;
+ uint32_t hash;
+
+ //flags
+ bool configured;
+ struct timeval updated;
+
+ int do_status;
+ int do_quality;
+ int do_discarded_packets;
+ int do_missed_beacon;
+
+ // Data collected
+ // status
+ kernel_uint_t status;
+
+ // Quality
+ calculated_number link;
+ calculated_number level;
+ calculated_number noise;
+
+ // Discarded packets
+ kernel_uint_t nwid;
+ kernel_uint_t crypt;
+ kernel_uint_t frag;
+ kernel_uint_t retry;
+ kernel_uint_t misc;
+
+ // missed beacon
+ kernel_uint_t missed_beacon;
+
+ const char *chart_id_net_status;
+ const char *chart_id_net_link;
+ const char *chart_id_net_level;
+ const char *chart_id_net_noise;
+ const char *chart_id_net_discarded_packets;
+ const char *chart_id_net_missed_beacon;
+
+ const char *chart_family;
+
+ // charts
+ // satus
+ RRDSET *st_status;
+
+ // Quality
+ RRDSET *st_link;
+ RRDSET *st_level;
+ RRDSET *st_noise;
+
+ // Discarded Packets
+ RRDSET *st_discarded_packets;
+ // Missed beacon
+ RRDSET *st_missed_beacon;
+
+ // Dimensions
+ // status
+ RRDDIM *rd_status;
+
+ // Quality
+ RRDDIM *rd_link;
+ RRDDIM *rd_level;
+ RRDDIM *rd_noise;
+
+ // Discarded packets
+ RRDDIM *rd_nwid;
+ RRDDIM *rd_crypt;
+ RRDDIM *rd_frag;
+ RRDDIM *rd_retry;
+ RRDDIM *rd_misc;
+
+ // missed beacon
+ RRDDIM *rd_missed_beacon;
+
+ struct netwireless *next;
+} *netwireless_root = NULL;
+
+static void netwireless_free_st(struct netwireless *wireless_dev)
+{
+ if (wireless_dev->st_status) rrdset_is_obsolete(wireless_dev->st_status);
+ if (wireless_dev->st_link) rrdset_is_obsolete(wireless_dev->st_link);
+ if (wireless_dev->st_level) rrdset_is_obsolete(wireless_dev->st_level);
+ if (wireless_dev->st_noise) rrdset_is_obsolete(wireless_dev->st_noise);
+ if (wireless_dev->st_discarded_packets) rrdset_is_obsolete(wireless_dev->st_discarded_packets);
+ if (wireless_dev->st_missed_beacon) rrdset_is_obsolete(wireless_dev->st_missed_beacon);
+
+ wireless_dev->st_status = NULL;
+ wireless_dev->st_link = NULL;
+ wireless_dev->st_level = NULL;
+ wireless_dev->st_noise = NULL;
+ wireless_dev->st_discarded_packets = NULL;
+ wireless_dev->st_missed_beacon = NULL;
+}
+
+static void netwireless_free(struct netwireless *wireless_dev)
+{
+ wireless_dev->next = NULL;
+ freez((void *)wireless_dev->name);
+ netwireless_free_st(wireless_dev);
+ freez((void *)wireless_dev->chart_id_net_status);
+ freez((void *)wireless_dev->chart_id_net_link);
+ freez((void *)wireless_dev->chart_id_net_level);
+ freez((void *)wireless_dev->chart_id_net_noise);
+ freez((void *)wireless_dev->chart_id_net_discarded_packets);
+ freez((void *)wireless_dev->chart_id_net_missed_beacon);
+
+ freez((void *)wireless_dev);
+}
+
+static void netwireless_cleanup(struct timeval *timestamp)
+{
+ struct netwireless *previous = NULL;
+ struct netwireless *current;
+ // search it, from begining to the end
+ for (current = netwireless_root; current;) {
+
+ if (timercmp(&current->updated, timestamp, <)) {
+ struct netwireless *to_free = current;
+ current = current->next;
+ netwireless_free(to_free);
+
+ if (previous) {
+ previous->next = current;
+ } else {
+ netwireless_root = current;
+ }
+ } else {
+ previous = current;
+ current = current->next;
+ }
+ }
+}
+
+// finds an existing interface or creates a new entry
+static struct netwireless *find_or_create_wireless(const char *name)
+{
+ struct netwireless *wireless;
+ uint32_t hash = simple_hash(name);
+
+ // search it, from begining to the end
+ for (wireless = netwireless_root ; wireless ; wireless = wireless->next) {
+ if (unlikely(hash == wireless->hash && !strcmp(name, wireless->name))) {
+ return wireless;
+ }
+ }
+
+ // create a new one
+ wireless = callocz(1, sizeof(struct netwireless));
+ wireless->name = strdupz(name);
+ wireless->hash = hash;
+
+ // link it to the end
+ if (netwireless_root) {
+ struct netwireless *last_node;
+ for (last_node = netwireless_root; last_node->next ; last_node = last_node->next);
+
+ last_node->next = wireless;
+ } else
+ netwireless_root = wireless;
+
+ return wireless;
+}
+
+static void configure_device(int do_status, int do_quality, int do_discarded_packets, int do_missed,
+ struct netwireless *wireless_dev) {
+ wireless_dev->do_status = do_status;
+ wireless_dev->do_quality = do_quality;
+ wireless_dev->do_discarded_packets = do_discarded_packets;
+ wireless_dev->do_missed_beacon = do_missed;
+ wireless_dev->configured = true;
+
+ char buffer[RRD_ID_LENGTH_MAX + 1];
+
+ snprintfz(buffer, RRD_ID_LENGTH_MAX, "%s_status", wireless_dev->name);
+ wireless_dev->chart_id_net_status = strdupz(buffer);
+
+ snprintfz(buffer, RRD_ID_LENGTH_MAX, "%s_link_quality", wireless_dev->name);
+ wireless_dev->chart_id_net_link = strdupz(buffer);
+
+ snprintfz(buffer, RRD_ID_LENGTH_MAX, "%s_signal_level", wireless_dev->name);
+ wireless_dev->chart_id_net_level = strdupz(buffer);
+
+ snprintfz(buffer, RRD_ID_LENGTH_MAX, "%s_noise_level", wireless_dev->name);
+ wireless_dev->chart_id_net_noise = strdupz(buffer);
+
+ snprintfz(buffer, RRD_ID_LENGTH_MAX, "%s_discarded_packets", wireless_dev->name);
+ wireless_dev->chart_id_net_discarded_packets = strdupz(buffer);
+
+ snprintfz(buffer, RRD_ID_LENGTH_MAX, "%s_missed_beacon", wireless_dev->name);
+ wireless_dev->chart_id_net_missed_beacon = strdupz(buffer);
+}
+
+int do_proc_net_wireless(int update_every, usec_t dt)
+{
+ UNUSED(dt);
+ static procfile *ff = NULL;
+ static int do_status, do_quality = -1, do_discarded_packets, do_beacon;
+ static char *proc_net_wireless_filename = NULL;
+
+ if (unlikely(do_quality == -1)) {
+ char filename[FILENAME_MAX + 1];
+ snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/wireless");
+
+ proc_net_wireless_filename = config_get(CONFIG_SECTION_PLUGIN_PROC_NETWIRELESS,"filename to monitor",
+ filename);
+
+ do_status = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETWIRELESS,
+ "status for all interfaces", CONFIG_BOOLEAN_AUTO);
+
+ do_quality = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETWIRELESS,
+ "quality for all interfaces", CONFIG_BOOLEAN_AUTO);
+
+ do_discarded_packets = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETWIRELESS,
+ "discarded packets for all interfaces",
+ CONFIG_BOOLEAN_AUTO);
+
+ do_beacon = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETWIRELESS,
+ "missed beacon for all interface", CONFIG_BOOLEAN_AUTO);
+ }
+
+ if (unlikely(!ff)) {
+ ff = procfile_open(proc_net_wireless_filename, " \t,|", PROCFILE_FLAG_DEFAULT);
+ if (unlikely(!ff)) return 1;
+ }
+
+ ff = procfile_readall(ff);
+ if (unlikely(!ff)) return 1;
+
+ size_t lines = procfile_lines(ff);
+ struct timeval timestamp;
+ size_t l;
+ gettimeofday(&timestamp, NULL);
+ for (l = 2; l < lines; l++) {
+ if (unlikely(procfile_linewords(ff, l) < 11)) continue;
+
+ char *name = procfile_lineword(ff, l, 0);
+ size_t len = strlen(name);
+ if (name[len - 1] == ':') name[len - 1] = '\0';
+
+ struct netwireless *wireless_dev = find_or_create_wireless(name);
+
+ if (unlikely(!wireless_dev->configured)) {
+ configure_device(do_status, do_quality, do_discarded_packets, do_beacon, wireless_dev);
+ }
+
+ if (likely(do_status != CONFIG_BOOLEAN_NO)) {
+ wireless_dev->status = str2kernel_uint_t(procfile_lineword(ff, l, 1));
+
+ if (unlikely(!wireless_dev->st_status)) {
+ wireless_dev->st_status = rrdset_create_localhost("wireless",
+ wireless_dev->chart_id_net_status,
+ NULL,
+ wireless_dev->name,
+ "wireless.status",
+ "Internal status reported by interface.",
+ "status",
+ PLUGIN_PROC_NAME,
+ PLUGIN_PROC_MODULE_NETWIRELESS_NAME,
+ NETDATA_CHART_PRIO_WIRELESS_IFACE,
+ update_every,
+ RRDSET_TYPE_LINE);
+ rrdset_flag_set(wireless_dev->st_status, RRDSET_FLAG_DETAIL);
+
+ wireless_dev->rd_status = rrddim_add(wireless_dev->st_status, "status", NULL, 1,
+ 1, RRD_ALGORITHM_ABSOLUTE);
+ } else {
+ rrdset_next(wireless_dev->st_status);
+ }
+
+ rrddim_set_by_pointer(wireless_dev->st_status, wireless_dev->rd_status,
+ (collected_number)wireless_dev->status);
+ rrdset_done(wireless_dev->st_status);
+ }
+
+ if (likely(do_quality != CONFIG_BOOLEAN_NO)) {
+ wireless_dev->link = str2ld(procfile_lineword(ff, l, 2), NULL);
+ wireless_dev->level = str2ld(procfile_lineword(ff, l, 3), NULL);
+ wireless_dev->noise = str2ld(procfile_lineword(ff, l, 4), NULL);
+
+ if (unlikely(!wireless_dev->st_link)) {
+ wireless_dev->st_link = rrdset_create_localhost("wireless",
+ wireless_dev->chart_id_net_link,
+ NULL,
+ wireless_dev->name,
+ "wireless.link_quality",
+ "Overall quality of the link. This is an aggregate value, and depends on the driver and hardware.",
+ "value",
+ PLUGIN_PROC_NAME,
+ PLUGIN_PROC_MODULE_NETWIRELESS_NAME,
+ NETDATA_CHART_PRIO_WIRELESS_IFACE + 1,
+ update_every,
+ RRDSET_TYPE_LINE);
+ rrdset_flag_set(wireless_dev->st_link, RRDSET_FLAG_DETAIL);
+
+ wireless_dev->rd_link = rrddim_add(wireless_dev->st_link, "link_quality", NULL, 1, 1,
+ RRD_ALGORITHM_ABSOLUTE);
+ } else {
+ rrdset_next(wireless_dev->st_link);
+ }
+
+ if (unlikely(!wireless_dev->st_level)) {
+ wireless_dev->st_level = rrdset_create_localhost("wireless",
+ wireless_dev->chart_id_net_level,
+ NULL,
+ wireless_dev->name,
+ "wireless.signal_level",
+ "The signal level is the wireless signal power level received by the wireless client. The closer the value is to 0, the stronger the signal.",
+ "dBm",
+ PLUGIN_PROC_NAME,
+ PLUGIN_PROC_MODULE_NETWIRELESS_NAME,
+ NETDATA_CHART_PRIO_WIRELESS_IFACE + 2,
+ update_every,
+ RRDSET_TYPE_LINE);
+ rrdset_flag_set(wireless_dev->st_level, RRDSET_FLAG_DETAIL);
+
+ wireless_dev->rd_level = rrddim_add(wireless_dev->st_level, "signal_level", NULL, 1, 1,
+ RRD_ALGORITHM_ABSOLUTE);
+ } else {
+ rrdset_next(wireless_dev->st_level);
+ }
+
+ if (unlikely(!wireless_dev->st_noise)) {
+ wireless_dev->st_noise = rrdset_create_localhost("wireless",
+ wireless_dev->chart_id_net_noise,
+ NULL,
+ wireless_dev->name,
+ "wireless.noise_level",
+ "The noise level indicates the amount of background noise in your environment. The closer the value to 0, the greater the noise level.",
+ "dBm",
+ PLUGIN_PROC_NAME,
+ PLUGIN_PROC_MODULE_NETWIRELESS_NAME,
+ NETDATA_CHART_PRIO_WIRELESS_IFACE + 3,
+ update_every,
+ RRDSET_TYPE_LINE);
+ rrdset_flag_set(wireless_dev->st_noise, RRDSET_FLAG_DETAIL);
+
+ wireless_dev->rd_noise = rrddim_add(wireless_dev->st_noise, "noise_level", NULL, 1, 1,
+ RRD_ALGORITHM_ABSOLUTE);
+ } else {
+ rrdset_next(wireless_dev->st_noise);
+ }
+
+ rrddim_set_by_pointer(wireless_dev->st_link, wireless_dev->rd_link,
+ (collected_number)wireless_dev->link);
+ rrdset_done(wireless_dev->st_link);
+
+ rrddim_set_by_pointer(wireless_dev->st_level, wireless_dev->rd_level,
+ (collected_number)wireless_dev->level);
+ rrdset_done(wireless_dev->st_level);
+
+ rrddim_set_by_pointer(wireless_dev->st_noise, wireless_dev->rd_noise,
+ (collected_number)wireless_dev->noise);
+ rrdset_done(wireless_dev->st_noise);
+ }
+
+ if (likely(do_discarded_packets)) {
+ wireless_dev->nwid = str2kernel_uint_t(procfile_lineword(ff, l, 5));
+ wireless_dev->crypt = str2kernel_uint_t(procfile_lineword(ff, l, 6));
+ wireless_dev->frag = str2kernel_uint_t(procfile_lineword(ff, l, 7));
+ wireless_dev->retry = str2kernel_uint_t(procfile_lineword(ff, l, 8));
+ wireless_dev->misc = str2kernel_uint_t(procfile_lineword(ff, l, 9));
+
+ if (unlikely(!wireless_dev->st_discarded_packets)) {
+ wireless_dev->st_discarded_packets = rrdset_create_localhost("wireless",
+ wireless_dev->chart_id_net_discarded_packets,
+ NULL,
+ wireless_dev->name,
+ "wireless.discarded_packets",
+ "Packet discarded in the wireless adapter due to \"wireless\" specific problems.",
+ "packets/s",
+ PLUGIN_PROC_NAME,
+ PLUGIN_PROC_MODULE_NETWIRELESS_NAME,
+ NETDATA_CHART_PRIO_WIRELESS_IFACE + 4,
+ update_every,
+ RRDSET_TYPE_LINE);
+
+ rrdset_flag_set(wireless_dev->st_discarded_packets, RRDSET_FLAG_DETAIL);
+
+ wireless_dev->rd_nwid = rrddim_add(wireless_dev->st_discarded_packets, "nwid", NULL, 1,
+ 1, RRD_ALGORITHM_INCREMENTAL);
+ wireless_dev->rd_crypt = rrddim_add(wireless_dev->st_discarded_packets, "crypt", NULL, 1,
+ 1, RRD_ALGORITHM_INCREMENTAL);
+ wireless_dev->rd_frag = rrddim_add(wireless_dev->st_discarded_packets, "frag", NULL, 1,
+ 1, RRD_ALGORITHM_INCREMENTAL);
+ wireless_dev->rd_retry = rrddim_add(wireless_dev->st_discarded_packets, "retry", NULL, 1,
+ 1, RRD_ALGORITHM_INCREMENTAL);
+ wireless_dev->rd_misc = rrddim_add(wireless_dev->st_discarded_packets, "misc", NULL, 1,
+ 1, RRD_ALGORITHM_INCREMENTAL);
+ } else {
+ rrdset_next(wireless_dev->st_discarded_packets);
+ }
+
+ rrddim_set_by_pointer(wireless_dev->st_discarded_packets, wireless_dev->rd_nwid,
+ (collected_number)wireless_dev->nwid);
+
+ rrddim_set_by_pointer(wireless_dev->st_discarded_packets, wireless_dev->rd_crypt,
+ (collected_number)wireless_dev->crypt);
+
+ rrddim_set_by_pointer(wireless_dev->st_discarded_packets, wireless_dev->rd_frag,
+ (collected_number)wireless_dev->frag);
+
+ rrddim_set_by_pointer(wireless_dev->st_discarded_packets, wireless_dev->rd_retry,
+ (collected_number)wireless_dev->retry);
+
+ rrddim_set_by_pointer(wireless_dev->st_discarded_packets, wireless_dev->rd_misc,
+ (collected_number)wireless_dev->misc);
+
+ rrdset_done(wireless_dev->st_discarded_packets);
+ }
+
+ if (likely(do_beacon)) {
+ wireless_dev->missed_beacon = str2kernel_uint_t(procfile_lineword(ff, l, 10));
+
+ if (unlikely(!wireless_dev->st_missed_beacon)) {
+ wireless_dev->st_missed_beacon = rrdset_create_localhost("wireless",
+ wireless_dev->chart_id_net_missed_beacon,
+ NULL,
+ wireless_dev->name,
+ "wireless.missed_beacons",
+ "Number of missed beacons.",
+ "frames/s",
+ PLUGIN_PROC_NAME,
+ PLUGIN_PROC_MODULE_NETWIRELESS_NAME,
+ NETDATA_CHART_PRIO_WIRELESS_IFACE + 5,
+ update_every,
+ RRDSET_TYPE_LINE);
+ rrdset_flag_set(wireless_dev->st_missed_beacon, RRDSET_FLAG_DETAIL);
+
+ wireless_dev->rd_missed_beacon = rrddim_add(wireless_dev->st_missed_beacon, "missed_beacons",
+ NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
+ } else {
+ rrdset_next(wireless_dev->st_missed_beacon);
+ }
+
+ rrddim_set_by_pointer(wireless_dev->st_missed_beacon, wireless_dev->rd_missed_beacon,
+ (collected_number)wireless_dev->missed_beacon);
+ rrdset_done(wireless_dev->st_missed_beacon);
+ }
+
+ wireless_dev->updated = timestamp;
+ }
+
+ netwireless_cleanup(&timestamp);
+ return 0;
+}