Skip to content

Commit

Permalink
Merge pull request #14448 from benpicco/l2-peerstats-rebased
Browse files Browse the repository at this point in the history
net/netstats: L1/L2 per neighbor statistics
  • Loading branch information
benpicco authored Feb 9, 2021
2 parents bd79f57 + cc9c58a commit 5fba2c8
Show file tree
Hide file tree
Showing 17 changed files with 938 additions and 14 deletions.
2 changes: 1 addition & 1 deletion cpu/nrf5x_common/radio/nrfmin/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ MODULE = nrfmin

SRC = nrfmin.c

ifneq (,$(filter gnrc_netdev_default,$(USEMODULE)))
ifneq (,$(filter gnrc_netif,$(USEMODULE)))
SRC += nrfmin_gnrc.c
endif

Expand Down
5 changes: 5 additions & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ PSEUDOMODULES += netdev_layer
PSEUDOMODULES += netdev_register
PSEUDOMODULES += netstats
PSEUDOMODULES += netstats_l2
PSEUDOMODULES += netstats_neighbor_etx
PSEUDOMODULES += netstats_neighbor_count
PSEUDOMODULES += netstats_neighbor_rssi
PSEUDOMODULES += netstats_neighbor_lqi
PSEUDOMODULES += netstats_neighbor_tx_time
PSEUDOMODULES += netstats_ipv6
PSEUDOMODULES += netstats_rpl
PSEUDOMODULES += nimble
Expand Down
3 changes: 3 additions & 0 deletions sys/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ endif
ifneq (,$(filter netopt,$(USEMODULE)))
DIRS += net/crosslayer/netopt
endif
ifneq (,$(filter netstats_neighbor,$(USEMODULE)))
DIRS += net/netstats
endif
ifneq (,$(filter sema,$(USEMODULE)))
DIRS += sema
endif
Expand Down
5 changes: 5 additions & 0 deletions sys/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,11 @@ ifneq (,$(filter netstats_%, $(USEMODULE)))
USEMODULE += netstats
endif

ifneq (,$(filter netstats_neighbor_%, $(USEMODULE)))
USEMODULE += netstats_neighbor
USEMODULE += xtimer
endif

ifneq (,$(filter gnrc_lwmac,$(USEMODULE)))
USEMODULE += gnrc_netif
USEMODULE += gnrc_nettype_lwmac
Expand Down
20 changes: 20 additions & 0 deletions sys/include/net/l2util.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,26 @@ char *l2util_addr_to_str(const uint8_t *addr, size_t addr_len, char *out);
*/
size_t l2util_addr_from_str(const char *str, uint8_t *out);

/**
* @brief Checks if two l2 addresses are equal.
*
* @param[in] addr_a First hardware address.
* @param[in] addr_a_len Length of first hardware address.
* @param[in] addr_b Second hardware address.
* @param[in] addr_b_len Length of second hardware address.
*
* @return true if the addresses match, false if not.
*/
static inline bool l2util_addr_equal(const uint8_t *addr_a, uint8_t addr_a_len,
const uint8_t *addr_b, uint8_t addr_b_len)
{
if (addr_a_len != addr_b_len) {
return false;
}

return memcmp(addr_a, addr_b, addr_a_len) == 0;
}

#ifdef __cplusplus
}
#endif
Expand Down
10 changes: 9 additions & 1 deletion sys/include/net/netif.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
#include "list.h"
#include "net/netopt.h"

#ifdef MODULE_NETSTATS_NEIGHBOR
#include "cib.h"
#include "net/netstats.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -61,7 +66,10 @@ extern "C" {
* @note All network interfaces should inherit from this structure.
*/
typedef struct {
list_node_t node; /**< Pointer to the next interface */
list_node_t node; /**< Pointer to the next interface */
#ifdef MODULE_NETSTATS_NEIGHBOR
netstats_nb_table_t neighbors; /**< Structure containing all L2 neighbors */
#endif
} netif_t;

/**
Expand Down
74 changes: 74 additions & 0 deletions sys/include/net/netstats.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
*/

#include <stdint.h>
#include "net/l2util.h"
#include "mutex.h"

#ifndef NET_NETSTATS_H
#define NET_NETSTATS_H
Expand All @@ -27,6 +29,20 @@
extern "C" {
#endif

/**
* @brief The max number of entries in the peer stats table
*/
#ifndef NETSTATS_NB_SIZE
#define NETSTATS_NB_SIZE (8)
#endif

/**
* @brief The CIB size for tx correlation
*/
#ifndef NETSTATS_NB_QUEUE_SIZE
#define NETSTATS_NB_QUEUE_SIZE (4)
#endif

/**
* @name @ref net_netstats module names
* @{
Expand All @@ -53,6 +69,64 @@ typedef struct {
uint32_t rx_bytes; /**< received bytes */
} netstats_t;

/**
* @brief Stats per peer struct
*/
typedef struct {
#if IS_USED(MODULE_NETSTATS_NEIGHBOR_TX_TIME) || DOXYGEN
uint32_t time_tx_avg; /**< Average frame TX time in µs */
#endif
#if IS_USED(MODULE_NETSTATS_NEIGHBOR_ETX) || DOXYGEN
uint16_t etx; /**< ETX of this peer */
#endif
#if IS_USED(MODULE_NETSTATS_NEIGHBOR_COUNT) || DOXYGEN
uint16_t tx_count; /**< Number of sent frames to this peer */
uint16_t tx_fail; /**< Number of sent frames that did not get ACKed */
uint16_t rx_count; /**< Number of received frames */
#endif
uint16_t last_updated; /**< seconds timestamp of last update */
uint16_t last_halved; /**< seconds timestamp of last halving */
uint8_t l2_addr[L2UTIL_ADDR_MAX_LEN]; /**< Link layer address of the neighbor */
uint8_t l2_addr_len; /**< Length of netstats_nb::l2_addr */
uint8_t freshness; /**< Freshness counter */
#if IS_USED(MODULE_NETSTATS_NEIGHBOR_RSSI) || DOXYGEN
uint8_t rssi; /**< Average RSSI of received frames in abs([dBm]) */
#endif
#if IS_USED(MODULE_NETSTATS_NEIGHBOR_LQI) || DOXYGEN
uint8_t lqi; /**< Average LQI of received frames */
#endif
} netstats_nb_t;

/**
* @brief L2 Peer Info struct
*/
typedef struct {
/**
* @brief CIB for the tx correlation
*/
cib_t stats_idx;

/**
* @brief send/callback mac association array
*/
netstats_nb_t *stats_queue[NETSTATS_NB_QUEUE_SIZE];

/**
* @brief TX timestamp of stats_queue entries
*/
uint32_t stats_queue_time_tx[NETSTATS_NB_QUEUE_SIZE];

/**
* @brief Per neighbor statistics array
*/
netstats_nb_t pstats[NETSTATS_NB_SIZE];

/**
* @brief Neighbor Table access lock
*/
mutex_t lock;
} netstats_nb_table_t;

#ifdef __cplusplus
}
#endif
Expand Down
194 changes: 194 additions & 0 deletions sys/include/net/netstats/neighbor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
* Copyright (C) 2017 Koen Zandberg <[email protected]>
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for
* more details.
*/

/**
* @ingroup net_netstats
* @brief Records statistics about link layer neighbors
* @{
*
* @file
* @brief Neighbor stats definitions
*
* @author Koen Zandberg <[email protected]>
*/
#ifndef NET_NETSTATS_NEIGHBOR_H
#define NET_NETSTATS_NEIGHBOR_H

#include <string.h>
#include "net/netif.h"
#include "xtimer.h"
#include "timex.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Result of the transmission
* @{
*/
typedef enum {
NETSTATS_NB_BUSY, /**< Failed due to medium busy */
NETSTATS_NB_NOACK, /**< Failed due to no ack received */
NETSTATS_NB_SUCCESS, /**< Successful transmission */
} netstats_nb_result_t;
/** @} */

/**
* @name @ref EWMA parameters
* @{
*/
/**
* @brief Multiplication factor of the EWMA
*/
#define NETSTATS_NB_EWMA_SCALE 100

/**
* @brief Alpha factor of the EWMA
*/
#define NETSTATS_NB_EWMA_ALPHA 15

/**
* @brief Alpha factor of the EWMA when stats are not fresh
*/
#define NETSTATS_NB_EWMA_ALPHA_RAMP 30
/** @} */

/**
* @name @ref ETX parameters
* @{
*/
/**
* @brief ETX penalty for not receiving any ACK
*/
#define NETSTATS_NB_ETX_NOACK_PENALTY 6
/**
* @brief ETX fixed point divisor (rfc 6551)
*/
#define NETSTATS_NB_ETX_DIVISOR 128
/**
* @brief Initial ETX, assume a mediocre link
*/
#define NETSTATS_NB_ETX_INIT 2
/** @} */

/**
* @name @ref Freshness parameters
* @{
*/
/**
* @brief seconds after the freshness counter is halved
*/
#define NETSTATS_NB_FRESHNESS_HALF 600
/**
* @brief freshness count needed before considering the statistics fresh
*/
#define NETSTATS_NB_FRESHNESS_TARGET 4
/**
* @brief Maximum freshness
*/
#define NETSTATS_NB_FRESHNESS_MAX 16
/**
* @brief seconds after statistics have expired
*/
#define NETSTATS_NB_FRESHNESS_EXPIRATION 1200
/** @} */
/**
* @name @ref Timeout Parameters
* @{
*/
/**
* @brief milliseconds without TX done notification after which
* a TX event is discarded
*/
#define NETSTATS_NB_TX_TIMEOUT_MS 100
/** @} */

/**
* @brief Initialize the neighbor stats
*
* @param[in] netif network interface descriptor
*
*/
void netstats_nb_init(netif_t *netif);

/**
* @brief Find a neighbor stat by the mac address.
*
* @param[in] netif network interface descriptor
* @param[in] l2_addr pointer to the L2 address
* @param[in] len length of the L2 address
* @param[out] out destination for the matching neighbor entry
*
* @return true if a matching peer was found, false otherwise
*/
bool netstats_nb_get(netif_t *netif, const uint8_t *l2_addr, uint8_t len, netstats_nb_t *out);

/**
* @brief Store this neighbor as next in the transmission queue.
*
* Set @p len to zero if a nop record is needed, for example if the
* transmission has a multicast address as a destination.
*
* @param[in] netif network interface descriptor
* @param[in] l2_addr pointer to the L2 address
* @param[in] len length of the L2 address
*
*/
void netstats_nb_record(netif_t *netif, const uint8_t *l2_addr, uint8_t len);

/**
* @brief Update the next recorded neighbor with the provided numbers
*
* This only increments the statistics if the length of the l2-address of the retrieved record
* is non-zero. See also @ref netstats_nb_record. The numbers indicate the number of transmissions
* the radio had to perform before a successful transmission was performed. For example: in the case
* of a single send operation needing 3 tries before an ACK was received, there are 2 failed
* transmissions and 1 successful transmission.
*
* @param[in] netif network interface descriptor
* @param[in] result Result of the transmission
* @param[in] transmissions Number of times the packet was sent over the air
*
* @return pointer to the record
*/
netstats_nb_t *netstats_nb_update_tx(netif_t *netif, netstats_nb_result_t result,
uint8_t transmissions);

/**
* @brief Record rx stats for the l2_addr
*
* @param[in] netif network interface descriptor
* @param[in] l2_addr pointer to the L2 address
* @param[in] l2_addr_len length of the L2 address
* @param[in] rssi RSSI of the received transmission in abs([dBm])
* @param[in] lqi Link Quality Indication provided by the radio
*
* @return pointer to the updated record
*/
netstats_nb_t *netstats_nb_update_rx(netif_t *netif, const uint8_t *l2_addr,
uint8_t l2_addr_len, uint8_t rssi, uint8_t lqi);

/**
* @brief Check if a record is fresh
*
* Freshness half time is checked and updated before verifying freshness.
*
* @param[in] netif network interface the statistic belongs to
* @param[in] stats pointer to the statistic
*/
bool netstats_nb_isfresh(netif_t *netif, netstats_nb_t *stats);

#ifdef __cplusplus
}
#endif

#endif /* NET_NETSTATS_NEIGHBOR_H */
/**
* @}
*/
Loading

0 comments on commit 5fba2c8

Please sign in to comment.