Merge pull request #4801 from OlegHahm/netstats
netstats: introduce L2 netstats
This commit is contained in:
commit
1f4d73dde1
@ -18,6 +18,7 @@ PSEUDOMODULES += gnrc_pktbuf
|
|||||||
PSEUDOMODULES += log
|
PSEUDOMODULES += log
|
||||||
PSEUDOMODULES += log_printfnoformat
|
PSEUDOMODULES += log_printfnoformat
|
||||||
PSEUDOMODULES += netdev_default
|
PSEUDOMODULES += netdev_default
|
||||||
|
PSEUDOMODULES += netstats_l2
|
||||||
PSEUDOMODULES += newlib
|
PSEUDOMODULES += newlib
|
||||||
PSEUDOMODULES += newlib_nano
|
PSEUDOMODULES += newlib_nano
|
||||||
PSEUDOMODULES += pktqueue
|
PSEUDOMODULES += pktqueue
|
||||||
|
|||||||
@ -240,6 +240,10 @@ static int _recv(netdev2_t *netdev2, char *buf, int len, void *info)
|
|||||||
|
|
||||||
_native_in_syscall--;
|
_native_in_syscall--;
|
||||||
|
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
netdev2->stats.rx_count++;
|
||||||
|
netdev2->stats.rx_bytes += nread;
|
||||||
|
#endif
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
else if (nread == -1) {
|
else if (nread == -1) {
|
||||||
@ -262,7 +266,17 @@ static int _recv(netdev2_t *netdev2, char *buf, int len, void *info)
|
|||||||
static int _send(netdev2_t *netdev, const struct iovec *vector, int n)
|
static int _send(netdev2_t *netdev, const struct iovec *vector, int n)
|
||||||
{
|
{
|
||||||
netdev2_tap_t *dev = (netdev2_tap_t*)netdev;
|
netdev2_tap_t *dev = (netdev2_tap_t*)netdev;
|
||||||
return _native_writev(dev->tap_fd, vector, n);
|
int res = _native_writev(dev->tap_fd, vector, n);
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
size_t bytes = 0;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
bytes += vector->iov_len;
|
||||||
|
vector++;
|
||||||
|
}
|
||||||
|
netdev->stats.tx_bytes += bytes;
|
||||||
|
#endif
|
||||||
|
netdev->event_callback(netdev, NETDEV2_EVENT_TX_COMPLETE, NULL);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void netdev2_tap_setup(netdev2_tap_t *dev, const netdev2_tap_params_t *params) {
|
void netdev2_tap_setup(netdev2_tap_t *dev, const netdev2_tap_params_t *params) {
|
||||||
@ -367,6 +381,9 @@ static int _init(netdev2_t *netdev)
|
|||||||
err(EXIT_FAILURE, "gnrc_tabnet_init(): fcntl(F_SETFL)");
|
err(EXIT_FAILURE, "gnrc_tabnet_init(): fcntl(F_SETFL)");
|
||||||
}
|
}
|
||||||
#endif /* not OSX */
|
#endif /* not OSX */
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
memset(&netdev->stats, 0, sizeof(netstats_t));
|
||||||
|
#endif
|
||||||
DEBUG("gnrc_tapnet: initialized.\n");
|
DEBUG("gnrc_tapnet: initialized.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,6 +100,9 @@ void at86rf2xx_reset(at86rf2xx_t *dev)
|
|||||||
at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA, true);
|
at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA, true);
|
||||||
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START, false);
|
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START, false);
|
||||||
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_END, true);
|
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_END, true);
|
||||||
|
#ifdef NETSTATS
|
||||||
|
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_TX_END, true);
|
||||||
|
#endif
|
||||||
/* set default protocol */
|
/* set default protocol */
|
||||||
#ifdef MODULE_GNRC_SIXLOWPAN
|
#ifdef MODULE_GNRC_SIXLOWPAN
|
||||||
dev->netdev.proto = GNRC_NETTYPE_SIXLOWPAN;
|
dev->netdev.proto = GNRC_NETTYPE_SIXLOWPAN;
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
@ -87,6 +88,9 @@ static int _init(netdev2_t *netdev)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
memset(&netdev->stats, 0, sizeof(netstats_t));
|
||||||
|
#endif
|
||||||
/* reset device to default values and put it into RX state */
|
/* reset device to default values and put it into RX state */
|
||||||
at86rf2xx_reset(dev);
|
at86rf2xx_reset(dev);
|
||||||
|
|
||||||
@ -109,6 +113,9 @@ static int _send(netdev2_t *netdev, const struct iovec *vector, int count)
|
|||||||
(unsigned)len + 2);
|
(unsigned)len + 2);
|
||||||
return -EOVERFLOW;
|
return -EOVERFLOW;
|
||||||
}
|
}
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
netdev->stats.tx_bytes += len;
|
||||||
|
#endif
|
||||||
len = at86rf2xx_tx_load(dev, ptr->iov_base, ptr->iov_len, len);
|
len = at86rf2xx_tx_load(dev, ptr->iov_base, ptr->iov_len, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +148,10 @@ static int _recv(netdev2_t *netdev, char *buf, int len, void *info)
|
|||||||
at86rf2xx_fb_stop(dev);
|
at86rf2xx_fb_stop(dev);
|
||||||
return pkt_len;
|
return pkt_len;
|
||||||
}
|
}
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
netdev->stats.rx_count++;
|
||||||
|
netdev->stats.rx_bytes += pkt_len;
|
||||||
|
#endif
|
||||||
/* not enough space in buf */
|
/* not enough space in buf */
|
||||||
if (pkt_len > len) {
|
if (pkt_len > len) {
|
||||||
at86rf2xx_fb_stop(dev);
|
at86rf2xx_fb_stop(dev);
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
#include "xtimer.h"
|
#include "xtimer.h"
|
||||||
@ -226,6 +227,9 @@ static int nd_send(netdev2_t *netdev, const struct iovec *data, int count)
|
|||||||
|
|
||||||
mutex_lock(&dev->devlock);
|
mutex_lock(&dev->devlock);
|
||||||
|
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
netdev->stats.tx_bytes += count;
|
||||||
|
#endif
|
||||||
/* set write pointer */
|
/* set write pointer */
|
||||||
cmd_w_addr(dev, ADDR_WRITE_PTR, BUF_TX_START);
|
cmd_w_addr(dev, ADDR_WRITE_PTR, BUF_TX_START);
|
||||||
/* write control byte and the actual data into the buffer */
|
/* write control byte and the actual data into the buffer */
|
||||||
@ -262,6 +266,10 @@ static int nd_recv(netdev2_t *netdev, char *buf, int max_len, void *info)
|
|||||||
size = (size_t)((head[3] << 8) | head[2]) - 4; /* discard CRC */
|
size = (size_t)((head[3] << 8) | head[2]) - 4; /* discard CRC */
|
||||||
|
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
netdev->stats.rx_count++;
|
||||||
|
netdev2->stats.rx_bytes += size;
|
||||||
|
#endif
|
||||||
/* read packet content into the supplied buffer */
|
/* read packet content into the supplied buffer */
|
||||||
if (size <= max_len) {
|
if (size <= max_len) {
|
||||||
cmd_rbm(dev, (uint8_t *)buf, size);
|
cmd_rbm(dev, (uint8_t *)buf, size);
|
||||||
@ -416,6 +424,9 @@ static void nd_isr(netdev2_t *netdev)
|
|||||||
}
|
}
|
||||||
eir = cmd_rcr(dev, REG_EIR, -1);
|
eir = cmd_rcr(dev, REG_EIR, -1);
|
||||||
}
|
}
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
memset(&netdev->stats, 0, sizeof(netstats_t));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nd_get(netdev2_t *netdev, netopt_t opt, void *value, size_t max_len)
|
static int nd_get(netdev2_t *netdev, netopt_t opt, void *value, size_t max_len)
|
||||||
|
|||||||
@ -46,6 +46,7 @@ extern "C" {
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
|
#include "net/netstats.h"
|
||||||
#include "net/netopt.h"
|
#include "net/netopt.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -106,6 +107,9 @@ struct netdev2 {
|
|||||||
const struct netdev2_driver *driver; /**< ptr to that driver's interface. */
|
const struct netdev2_driver *driver; /**< ptr to that driver's interface. */
|
||||||
netdev2_event_cb_t event_callback; /**< callback for device events */
|
netdev2_event_cb_t event_callback; /**< callback for device events */
|
||||||
void *isr_arg; /**< argument to pass on isr event */
|
void *isr_arg; /**< argument to pass on isr event */
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
netstats_t stats; /**< transceiver's statistics */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -79,6 +79,15 @@ int netdev2_eth_get(netdev2_t *dev, netopt_t opt, void *value, size_t max_len)
|
|||||||
{
|
{
|
||||||
return _get_iid(dev, value, max_len);
|
return _get_iid(dev, value, max_len);
|
||||||
}
|
}
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
case NETOPT_STATS:
|
||||||
|
{
|
||||||
|
assert(max_len >= sizeof(uintptr_t));
|
||||||
|
*((netstats_t**)value) = &dev->stats;
|
||||||
|
res = sizeof(uintptr_t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
res = -ENOTSUP;
|
res = -ENOTSUP;
|
||||||
|
|||||||
@ -148,6 +148,16 @@ int netdev2_ieee802154_get(netdev2_ieee802154_t *dev, netopt_t opt, void *value,
|
|||||||
case NETOPT_IPV6_IID:
|
case NETOPT_IPV6_IID:
|
||||||
res = _get_iid(dev, value, max_len);
|
res = _get_iid(dev, value, max_len);
|
||||||
break;
|
break;
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
case NETOPT_STATS:
|
||||||
|
if (max_len < sizeof(uintptr_t)) {
|
||||||
|
res = -EOVERFLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*((netstats_t**)value) = &dev->netdev.stats;
|
||||||
|
res = sizeof(uintptr_t);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,6 +75,14 @@ static void _event_cb(netdev2_t *dev, netdev2_event_t event, void *data)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
case NETDEV2_EVENT_TX_MEDIUM_BUSY:
|
||||||
|
dev->stats.tx_failed++;
|
||||||
|
break;
|
||||||
|
case NETDEV2_EVENT_TX_COMPLETE:
|
||||||
|
dev->stats.tx_success++;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
DEBUG("gnrc_netdev2: warning: unhandled event %u.\n", event);
|
DEBUG("gnrc_netdev2: warning: unhandled event %u.\n", event);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -203,6 +203,15 @@ static int _send(gnrc_netdev2_t *gnrc_netdev2, gnrc_pktsnip_t *pkt)
|
|||||||
struct iovec *vector = (struct iovec *)pkt->data;
|
struct iovec *vector = (struct iovec *)pkt->data;
|
||||||
vector[0].iov_base = (char*)&hdr;
|
vector[0].iov_base = (char*)&hdr;
|
||||||
vector[0].iov_len = sizeof(ethernet_hdr_t);
|
vector[0].iov_len = sizeof(ethernet_hdr_t);
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
if ((netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) ||
|
||||||
|
(netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
|
||||||
|
gnrc_netdev2->dev->stats.tx_mcast_count++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gnrc_netdev2->dev->stats.tx_unicast_count++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
res = dev->driver->send(dev, vector, n);
|
res = dev->driver->send(dev, vector, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -198,6 +198,14 @@ static int _send(gnrc_netdev2_t *gnrc_netdev2, gnrc_pktsnip_t *pkt)
|
|||||||
vector = (struct iovec *)pkt->data;
|
vector = (struct iovec *)pkt->data;
|
||||||
vector[0].iov_base = mhr;
|
vector[0].iov_base = mhr;
|
||||||
vector[0].iov_len = (size_t)res;
|
vector[0].iov_len = (size_t)res;
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
if (flags & IEEE802154_BCAST) {
|
||||||
|
gnrc_netdev2->dev->stats.tx_mcast_count++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gnrc_netdev2->dev->stats.tx_unicast_count++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
res = netdev->driver->send(netdev, vector, n);
|
res = netdev->driver->send(netdev, vector, n);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
*
|
*
|
||||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
* @author Oliver Hahm <oliver.hahm@inria.fr>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -25,6 +26,7 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
#include "net/netstats.h"
|
||||||
#include "net/ipv6/addr.h"
|
#include "net/ipv6/addr.h"
|
||||||
#include "net/gnrc/ipv6/netif.h"
|
#include "net/gnrc/ipv6/netif.h"
|
||||||
#include "net/gnrc/netif.h"
|
#include "net/gnrc/netif.h"
|
||||||
@ -71,6 +73,35 @@ static bool _is_iface(kernel_pid_t dev)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
static int _netif_stats(kernel_pid_t dev, bool reset)
|
||||||
|
{
|
||||||
|
netstats_t *stats;
|
||||||
|
int res = -ENOTSUP;
|
||||||
|
res = gnrc_netapi_get(dev, NETOPT_STATS, 0, &stats, sizeof(&stats));
|
||||||
|
if (res < 0) {
|
||||||
|
puts(" Protocol or device doesn't provide statistics.");
|
||||||
|
}
|
||||||
|
else if (reset) {
|
||||||
|
memset(stats, 0, sizeof(netstats_t));
|
||||||
|
puts("Reset statistics!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf(" RX packets %u bytes %u\n"
|
||||||
|
" TX packets %u (Multicast: %u) bytes %u\n"
|
||||||
|
" TX succeeded %u errors %u\n",
|
||||||
|
(unsigned) stats->rx_count,
|
||||||
|
(unsigned) stats->rx_bytes,
|
||||||
|
(unsigned) (stats->tx_unicast_count + stats->tx_mcast_count),
|
||||||
|
(unsigned) stats->tx_mcast_count,
|
||||||
|
(unsigned) stats->tx_bytes,
|
||||||
|
(unsigned) stats->tx_success,
|
||||||
|
(unsigned) stats->tx_failed);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void _set_usage(char *cmd_name)
|
static void _set_usage(char *cmd_name)
|
||||||
{
|
{
|
||||||
printf("usage: %s <if_id> set <key> <value>\n", cmd_name);
|
printf("usage: %s <if_id> set <key> <value>\n", cmd_name);
|
||||||
@ -120,6 +151,11 @@ static void _del_usage(char *cmd_name)
|
|||||||
cmd_name);
|
cmd_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _stats_usage(char *cmd_name)
|
||||||
|
{
|
||||||
|
printf("usage: %s <if_id> stats [reset]\n", cmd_name);
|
||||||
|
}
|
||||||
|
|
||||||
static void _print_netopt(netopt_t opt)
|
static void _print_netopt(netopt_t opt)
|
||||||
{
|
{
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@ -412,6 +448,10 @@ static void _netif_list(kernel_pid_t dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
puts("");
|
||||||
|
_netif_stats(dev, false);
|
||||||
|
#endif
|
||||||
puts("");
|
puts("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,7 +874,6 @@ static int _netif_mtu(kernel_pid_t dev, char *mtu_str)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* shell commands */
|
/* shell commands */
|
||||||
int _netif_send(int argc, char **argv)
|
int _netif_send(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -948,6 +987,15 @@ int _netif_config(int argc, char **argv)
|
|||||||
|
|
||||||
return _netif_mtu((kernel_pid_t)dev, argv[3]);
|
return _netif_mtu((kernel_pid_t)dev, argv[3]);
|
||||||
}
|
}
|
||||||
|
#ifdef MODULE_NETSTATS_L2
|
||||||
|
else if (strcmp(argv[2], "stats") == 0) {
|
||||||
|
bool reset = false;
|
||||||
|
if ((argc > 3) && (strncmp(argv[3], "reset", 5) == 0)) {
|
||||||
|
reset = true;
|
||||||
|
}
|
||||||
|
return _netif_stats((kernel_pid_t)dev, reset);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef MODULE_GNRC_IPV6_NETIF
|
#ifdef MODULE_GNRC_IPV6_NETIF
|
||||||
else if (strcmp(argv[2], "hl") == 0) {
|
else if (strcmp(argv[2], "hl") == 0) {
|
||||||
if (argc < 4) {
|
if (argc < 4) {
|
||||||
@ -988,5 +1036,6 @@ int _netif_config(int argc, char **argv)
|
|||||||
_flag_usage(argv[0]);
|
_flag_usage(argv[0]);
|
||||||
_add_usage(argv[0]);
|
_add_usage(argv[0]);
|
||||||
_del_usage(argv[0]);
|
_del_usage(argv[0]);
|
||||||
|
_stats_usage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user