0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-05-21 00:09:54 +00:00

Wireless statistics ()

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>
This commit is contained in:
thiagoftsm 2020-10-20 11:04:05 +00:00 committed by GitHub
parent 6b2ffc355a
commit 31b045aa3c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 509 additions and 0 deletions

View file

@ -501,6 +501,7 @@ set(PROC_PLUGIN_FILES
collectors/proc.plugin/proc_meminfo.c
collectors/proc.plugin/proc_pagetypeinfo.c
collectors/proc.plugin/proc_net_dev.c
collectors/proc.plugin/proc_net_wireless.c
collectors/proc.plugin/proc_net_ip_vs_stats.c
collectors/proc.plugin/proc_net_netstat.c
collectors/proc.plugin/proc_net_rpc_nfs.c

View file

@ -305,6 +305,7 @@ PROC_PLUGIN_FILES = \
collectors/proc.plugin/proc_pressure.c \
collectors/proc.plugin/proc_pressure.h \
collectors/proc.plugin/proc_net_dev.c \
collectors/proc.plugin/proc_net_wireless.c \
collectors/proc.plugin/proc_net_ip_vs_stats.c \
collectors/proc.plugin/proc_net_netstat.c \
collectors/proc.plugin/proc_net_rpc_nfs.c \

View file

@ -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

View file

@ -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`.

View file

@ -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

View file

@ -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);

View file

@ -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;
}

View file

@ -50,6 +50,12 @@ netdataDashboard.menu = {
info: 'Performance metrics for network interfaces.'
},
'wireless': {
title: 'Wireless Interfaces',
icon: '<i class="fas fa-wifi"></i>',
info: 'Performance metrics for wireless interfaces.'
},
'ip': {
title: 'Networking Stack',
icon: '<i class="fas fa-cloud"></i>',