mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
gnrc_sixlowpan_frag_sfr: provide statistics sub-module
This commit is contained in:
parent
ed4ac70887
commit
e980405cbc
@ -56,6 +56,7 @@ PSEUDOMODULES += gnrc_sixloenc
|
||||
PSEUDOMODULES += gnrc_sixlowpan_border_router_default
|
||||
PSEUDOMODULES += gnrc_sixlowpan_default
|
||||
PSEUDOMODULES += gnrc_sixlowpan_frag_hint
|
||||
PSEUDOMODULES += gnrc_sixlowpan_frag_sfr_stats
|
||||
PSEUDOMODULES += gnrc_sixlowpan_iphc_nhc
|
||||
PSEUDOMODULES += gnrc_sixlowpan_nd_border_router
|
||||
PSEUDOMODULES += gnrc_sixlowpan_router_default
|
||||
|
@ -333,6 +333,10 @@ ifneq (,$(filter gnrc_sixlowpan_frag_sfr,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_sfr_stats,$(USEMODULE)))
|
||||
USEMODULE += gnrc_sixlowpan_frag_sfr
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_vrb,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
USEMODULE += gnrc_sixlowpan_frag_fb
|
||||
|
@ -56,6 +56,28 @@ extern "C" {
|
||||
*/
|
||||
#define GNRC_SIXLOWPAN_FRAG_SFR_INTER_FRAG_GAP_MSG (0x0228)
|
||||
|
||||
/**
|
||||
* @brief Stats on selective fragment recovery
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t datagram_resends; /**< datagrams resent */
|
||||
struct {
|
||||
uint32_t usual; /**< non-abort fragments sent */
|
||||
uint32_t aborts; /**< abort pseudo-fragments sent */
|
||||
uint32_t forwarded; /**< forwarded fragments */
|
||||
} fragments_sent; /**< RFRAG packets sent */
|
||||
struct {
|
||||
uint32_t by_nack; /**< fragments resent due to a 0 in ACK's bitmap */
|
||||
uint32_t by_timeout; /**< fragments resent due to an ARQ timeout */
|
||||
} fragment_resends; /**< fragments resent */
|
||||
struct {
|
||||
uint32_t full; /**< full RFRAGs ACKs sent */
|
||||
uint32_t partly; /**< partly ACKing RFRAGs sent */
|
||||
uint32_t aborts; /**< abort RFRAG ACKs sent */
|
||||
uint32_t forwarded; /**< forwarded ACKs */
|
||||
} acks; /**< ACKs stats */
|
||||
} gnrc_sixlowpan_frag_sfr_stats_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize selective fragment recovery
|
||||
*/
|
||||
@ -163,6 +185,15 @@ void gnrc_sixlowpan_frag_sfr_arq_timeout(gnrc_sixlowpan_frag_fb_t *fbuf);
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_sfr_inter_frame_gap(void);
|
||||
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)
|
||||
/**
|
||||
* @brief Fetch current stats for selective fragment recovery
|
||||
*
|
||||
* @param[out] stats The current stats. Must not be NULL.
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_sfr_stats_get(gnrc_sixlowpan_frag_sfr_stats_t *stats);
|
||||
#endif /* IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -96,6 +96,8 @@ static clist_node_t _frame_queue;
|
||||
static const gnrc_sixlowpan_frag_sfr_bitmap_t _full_bitmap = { .u32 = UINT32_MAX };
|
||||
static const gnrc_sixlowpan_frag_sfr_bitmap_t _null_bitmap = { .u32 = 0U };
|
||||
|
||||
static gnrc_sixlowpan_frag_sfr_stats_t _stats;
|
||||
|
||||
/**
|
||||
* @brief Converts a @ref sys_bitmap based bitmap to a
|
||||
* gnrc_sixlowpan_frag_sfr_bitmap_t
|
||||
@ -495,6 +497,11 @@ void gnrc_sixlowpan_frag_sfr_arq_timeout(gnrc_sixlowpan_frag_fb_t *fbuf)
|
||||
error_no = ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
else if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
/* fragment was resent successfully, note this done in
|
||||
* the statistics */
|
||||
_stats.fragment_resends.by_timeout++;
|
||||
}
|
||||
/* fragment was resent successfully, schedule next ACK
|
||||
* timeout */
|
||||
reschedule_arq_timeout = true;
|
||||
@ -559,6 +566,13 @@ void gnrc_sixlowpan_frag_sfr_inter_frame_gap(void)
|
||||
}
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_frag_sfr_stats_get(gnrc_sixlowpan_frag_sfr_stats_t *stats)
|
||||
{
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
*stats = _stats;
|
||||
}
|
||||
}
|
||||
|
||||
/* ====== INTERNAL FUNCTION DEFINITIONS ====== */
|
||||
static inline uint16_t _min(uint16_t a, size_t b)
|
||||
{
|
||||
@ -770,6 +784,9 @@ static bool _send_fragment(gnrc_pktsnip_t *frag, gnrc_sixlowpan_frag_fb_t *fbuf,
|
||||
frag_desc->retries = 0;
|
||||
clist_rpush(&fbuf->sfr.window, &frag_desc->super);
|
||||
if ((res = _send_frame(frag, NULL, page))) {
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.fragments_sent.usual++;
|
||||
}
|
||||
frag_desc->last_sent = _last_frame_sent;
|
||||
fbuf->sfr.cur_seq++;
|
||||
fbuf->sfr.frags_sent++;
|
||||
@ -866,6 +883,9 @@ static void _try_reassembly(gnrc_netif_hdr_t *netif_hdr,
|
||||
"fragment\n");
|
||||
/* send abort */
|
||||
bitmap = &_null_bitmap;
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.acks.aborts++;
|
||||
}
|
||||
}
|
||||
else if (vrbe != NULL) {
|
||||
DEBUG("6lo sfr: packet was forwarded\n");
|
||||
@ -886,11 +906,17 @@ static void _try_reassembly(gnrc_netif_hdr_t *netif_hdr,
|
||||
_clean_up_rb_entry(entry);
|
||||
/* send abort */
|
||||
bitmap = &_null_bitmap;
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.acks.aborts++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (res) {
|
||||
DEBUG("6lo sfr: dispatched datagram to upper layer\n");
|
||||
bitmap = &_full_bitmap;
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.acks.full++;
|
||||
}
|
||||
}
|
||||
else if (ack_req) {
|
||||
DEBUG("6lo sfr: ACKing received fragments %02X%02X%02X%02X "
|
||||
@ -902,6 +928,9 @@ static void _try_reassembly(gnrc_netif_hdr_t *netif_hdr,
|
||||
entry->entry.base->current_size,
|
||||
entry->entry.base->datagram_size);
|
||||
bitmap = _to_bitmap(entry->entry.rb->received);
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.acks.partly++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* no ACK was requested and no error was causing an abort ACK*/
|
||||
@ -1087,6 +1116,17 @@ static void _handle_nth_rfrag(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
}
|
||||
}
|
||||
|
||||
static int _resend_failed_frag(clist_node_t *node, void *fbuf_ptr)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (((res = _resend_frag(node, fbuf_ptr)) == 0) &&
|
||||
IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.fragment_resends.by_nack++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void _check_failed_frags(sixlowpan_sfr_ack_t *ack,
|
||||
gnrc_sixlowpan_frag_fb_t *fbuf)
|
||||
{
|
||||
@ -1140,10 +1180,10 @@ static void _check_failed_frags(sixlowpan_sfr_ack_t *ack,
|
||||
else {
|
||||
fbuf->sfr.window = not_received;
|
||||
assert(fbuf->sfr.frags_sent == clist_count(&fbuf->sfr.window));
|
||||
/* use _resend_frag here instead of loop above, so _resend_frag
|
||||
* can know if the fragment is the last in the window by using
|
||||
* clist_rpeek() on fbuf->sfr.window */
|
||||
if (clist_foreach(&fbuf->sfr.window, _resend_frag, fbuf) != NULL) {
|
||||
/* use _resend_failed_frag here instead of loop above, so
|
||||
* _resend_frag can know if the fragment is the last in the window by
|
||||
* using clist_rpeek() on fbuf->sfr.window */
|
||||
if (clist_foreach(&fbuf->sfr.window, _resend_failed_frag, fbuf) != NULL) {
|
||||
/* XXX: it is unlikely that allocating an abort RFRAG will be
|
||||
* successful since the resources missing to cause the abort are
|
||||
* still in use, but we should at least try */
|
||||
@ -1310,6 +1350,9 @@ static bool _send_abort_frag(gnrc_pktsnip_t *pkt, uint8_t tag, bool req_ack,
|
||||
if (frag != NULL) {
|
||||
sixlowpan_sfr_rfrag_set_offset(frag->next->data, 0);
|
||||
_send_frame(frag, NULL, page);
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.fragments_sent.aborts++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1378,6 +1421,9 @@ static void _retry_datagram(gnrc_sixlowpan_frag_fb_t *fbuf)
|
||||
}
|
||||
else {
|
||||
DEBUG("6lo sfr: Retrying to send datagram %u completely\n", fbuf->tag);
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.datagram_resends++;
|
||||
}
|
||||
fbuf->sfr.retrans--;
|
||||
/* return fragmentation buffer to its original state to resend the whole
|
||||
* datagram again */
|
||||
@ -1396,6 +1442,9 @@ static void _abort_rb(gnrc_pktsnip_t *pkt, _generic_rb_entry_t *entry,
|
||||
netif_hdr->src_l2addr_len, addr_str),
|
||||
hdr->base.tag);
|
||||
if (send_ack) {
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.acks.aborts++;
|
||||
}
|
||||
_send_ack(gnrc_netif_hdr_get_netif(netif_hdr),
|
||||
gnrc_netif_hdr_get_src_addr(netif_hdr),
|
||||
netif_hdr->src_l2addr_len,
|
||||
@ -1513,6 +1562,9 @@ static void _handle_ack(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
addr_str), vrbe->super.tag);
|
||||
_send_ack(vrbe->in_netif, vrbe->super.src, vrbe->super.src_len,
|
||||
&mock_base, hdr->bitmap);
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.acks.forwarded++;
|
||||
}
|
||||
if ((unaligned_get_u32(hdr->bitmap) == _full_bitmap.u32) ||
|
||||
(unaligned_get_u32(hdr->bitmap) == _null_bitmap.u32)) {
|
||||
if (CONFIG_GNRC_SIXLOWPAN_FRAG_RBUF_DEL_TIMER > 0) {
|
||||
@ -1598,6 +1650,9 @@ static int _forward_rfrag(gnrc_pktsnip_t *pkt, _generic_rb_entry_t *entry,
|
||||
gnrc_netif_hdr_set_netif(new->data, entry->entry.vrb->out_netif);
|
||||
new->next = pkt;
|
||||
_send_frame(new, NULL, page);
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)) {
|
||||
_stats.fragments_sent.forwarded++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,9 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "net/gnrc/sixlowpan/frag/stats.h"
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS
|
||||
#include "net/gnrc/sixlowpan/frag/sfr.h"
|
||||
#endif
|
||||
|
||||
int _gnrc_6lo_frag_stats(int argc, char **argv)
|
||||
{
|
||||
@ -28,6 +31,24 @@ int _gnrc_6lo_frag_stats(int argc, char **argv)
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_VRB
|
||||
printf("VRB full: %u\n", stats->vrb_full);
|
||||
#endif
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS
|
||||
gnrc_sixlowpan_frag_sfr_stats_t sfr;
|
||||
|
||||
gnrc_sixlowpan_frag_sfr_stats_get(&sfr);
|
||||
printf("DG resends: %lu\n", (long unsigned)sfr.datagram_resends);
|
||||
printf("frags sent: usual: %lu, aborts: %lu, forwarded: %lu\n",
|
||||
(long unsigned)sfr.fragments_sent.usual,
|
||||
(long unsigned)sfr.fragments_sent.aborts,
|
||||
(long unsigned)sfr.fragments_sent.forwarded);
|
||||
printf("frag resends: NACK: %lu, timeout: %lu\n",
|
||||
(long unsigned)sfr.fragment_resends.by_nack,
|
||||
(long unsigned)sfr.fragment_resends.by_timeout);
|
||||
printf("ACKs: full: %lu, partly: %lu, aborts: %lu, forwarded: %lu\n",
|
||||
(long unsigned)sfr.acks.full,
|
||||
(long unsigned)sfr.acks.partly,
|
||||
(long unsigned)sfr.acks.aborts,
|
||||
(long unsigned)sfr.acks.forwarded);
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS */
|
||||
printf("frags complete: %u\n", stats->fragments);
|
||||
printf("dgs complete: %u\n", stats->datagrams);
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user