diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 7359f6086257f..4e3c36601412c 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -59,6 +59,10 @@ PSEUDOMODULES += gnrc_sixloenc PSEUDOMODULES += gnrc_sixlowpan_border_router_default PSEUDOMODULES += gnrc_sixlowpan_default PSEUDOMODULES += gnrc_sixlowpan_frag_hint +PSEUDOMODULES += gnrc_sixlowpan_frag_sfr_ecn +PSEUDOMODULES += gnrc_sixlowpan_frag_sfr_ecn_if_in +PSEUDOMODULES += gnrc_sixlowpan_frag_sfr_ecn_if_out +PSEUDOMODULES += gnrc_sixlowpan_frag_sfr_ecn_fqueue PSEUDOMODULES += gnrc_sixlowpan_frag_sfr_stats PSEUDOMODULES += gnrc_sixlowpan_iphc_nhc PSEUDOMODULES += gnrc_sixlowpan_nd_border_router diff --git a/sys/Makefile.dep b/sys/Makefile.dep index e441215437ce9..0a425f21bd55f 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -344,6 +344,18 @@ ifneq (,$(filter gnrc_sixlowpan_frag_sfr,$(USEMODULE))) endif endif +ifneq (,$(filter gnrc_sixlowpan_frag_sfr_ecn_%,$(USEMODULE))) + USEMODULE += gnrc_sixlowpan_frag_sfr_ecn +endif + +ifneq (,$(filter gnrc_sixlowpan_frag_sfr_ecn_if_out,$(USEMODULE))) + USEMODULE += gnrc_netif_pktq +endif + +ifneq (,$(filter gnrc_sixlowpan_frag_sfr_ecn,$(USEMODULE))) + USEMODULE += gnrc_sixlowpan_frag_sfr +endif + ifneq (,$(filter gnrc_sixlowpan_frag_sfr_stats,$(USEMODULE))) USEMODULE += gnrc_sixlowpan_frag_sfr endif diff --git a/sys/include/net/gnrc/sixlowpan/config.h b/sys/include/net/gnrc/sixlowpan/config.h index 343d17bb6c759..f13cf10e4ef13 100644 --- a/sys/include/net/gnrc/sixlowpan/config.h +++ b/sys/include/net/gnrc/sixlowpan/config.h @@ -301,6 +301,84 @@ extern "C" { #ifndef CONFIG_GNRC_SIXLOWPAN_SFR_DG_RETRIES #define CONFIG_GNRC_SIXLOWPAN_SFR_DG_RETRIES 0U #endif + +/** + * @brief The denominator for the factor for when to mark ECN on `netif` input + * queue state + * + * When `gnrc_sixlowpan_frag_sfr_ecn_if_in` is compiled in, nodes will set + * the ECN bit of an RFRAG header when the input queue of the outgoing `netif` + * is filled by + * @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_IN_NUM / @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_IN_DEN + */ +#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_IN_NUM +#define CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_IN_NUM 1U +#endif + +/** + * @brief The denominator for the factor for when to mark ECN on `netif` input + * queue state + * + * When `gnrc_sixlowpan_frag_sfr_ecn_if_in` is compiled in, nodes will set the + * ECN bit of an RFRAG header when the input queue of the outgoing `netif` is + * filled by + * @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_IN_NUM / @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_IN_DEN + */ +#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_IN_DEN +#define CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_IN_DEN 2U +#endif + +/** + * @brief The denominator for the factor for when to mark ECN on `netif` + * output queue state + * + * When `gnrc_sixlowpan_frag_sfr_ecn_if_out` is compiled in, nodes will set + * the ECN bit of an RFRAG header when the output queue of the outgoing `netif` + * is filled by + * @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_OUT_NUM / @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_OUT_DEN + */ +#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_OUT_NUM +#define CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_OUT_NUM 1U +#endif + +/** + * @brief The denominator for the factor for when to mark ECN on `netif` + * output queue state + * + * When `gnrc_sixlowpan_frag_sfr_ecn_if_out` is compiled in, nodes will set the + * ECN bit of an RFRAG header when the output queue of the outgoing `netif` is + * filled by + * @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_OUT_NUM / @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_OUT_DEN + */ +#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_OUT_DEN +#define CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_OUT_DEN 2U +#endif + +/** + * @brief The numerator for the factor for when to mark ECN on frame queue + * state + * + * When `gnrc_sixlowpan_frag_sfr_ecn_fqueue` is compiled in, nodes will set the + * ECN bit of an RFRAG header when the input queue of the outgoing `netif` is + * filled by + * @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_NUM / @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_DEN + */ +#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_NUM +#define CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_NUM 1U +#endif + +/** + * @brief The denominator for the factor for when to mark ECN on frame queue + * state + * + * When `gnrc_sixlowpan_frag_sfr_ecn_fqueue` is compiled in, nodes will set the + * ECN bit of an RFRAG header when the input queue of the outgoing `netif` is + * filled by + * @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_NUM / @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_DEN + */ +#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_DEN +#define CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_DEN 2U +#endif /** @} */ /** diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/sfr/Kconfig b/sys/net/gnrc/network_layer/sixlowpan/frag/sfr/Kconfig index 3db6a9e11a205..a7a9ef739772f 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/frag/sfr/Kconfig +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/sfr/Kconfig @@ -98,4 +98,54 @@ config GNRC_SIXLOWPAN_SFR_DG_RETRIES int "The maximum number of retries from scratch for a particular datagram (MaxDatagramRetries)" default 0 +menuconfig KCONFIG_USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR_ECN_NETIF + bool "Configure SFR ECN based on netif queue" + depends on USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR_ECN_NETIF + +if KCONFIG_USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR_ECN_NETIF +config GNRC_SIXLOWPAN_SFR_ECN_NETIF_NUM + int "The numerator for the factor for when to mark ECN on `netif` queue state" + default 1 + help + When `gnrc_sixlowpan_frag_sfr_ecn_netif` is compiled in, nodes will set + the ECN bit of an RFRAG header when the input queue of the outgoing + `netif` is filled by + @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_NETIF_NUM / @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_NETIF_DEN + + +config GNRC_SIXLOWPAN_SFR_ECN_NETIF_DEN + int "The denominator for the factor for when to mark ECN on `netif` queue state" + default 2 + help + When `gnrc_sixlowpan_frag_sfr_ecn_netif` is compiled in, nodes will set + the ECN bit of an RFRAG header when the input queue of the outgoing + `netif` is filled by + @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_NETIF_NUM / @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_NETIF_DEN +endif + +menuconfig KCONFIG_USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR_ECN_FQUEUE + bool "Configure SFR ECN based on SFR's frame queue" + depends on USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR_ECN_FQUEUE + +if KCONFIG_USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR_ECN_FQUEUE +config GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_NUM + int "The numerator for the factor for when to mark ECN on frame queue state" + default 1 + help + When `gnrc_sixlowpan_frag_sfr_ecn_fqueue` is compiled in, nodes will set + the ECN bit of an RFRAG header when the input queue of the outgoing + `netif` is filled by + @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_NUM / @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_DEN + + +config GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_DEN + int "The denominator for the factor for when to mark ECN on frame queue state" + default 2 + help + When `gnrc_sixlowpan_frag_sfr_ecn_fqueue` is compiled in, nodes will set + the ECN bit of an RFRAG header when the input queue of the outgoing + `netif` is filled by + @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_NUM / @ref CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_DEN +endif + endif diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/sfr/gnrc_sixlowpan_frag_sfr.c b/sys/net/gnrc/network_layer/sixlowpan/frag/sfr/gnrc_sixlowpan_frag_sfr.c index 8058a5b545c62..fb0af55daf35e 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/frag/sfr/gnrc_sixlowpan_frag_sfr.c +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/sfr/gnrc_sixlowpan_frag_sfr.c @@ -23,6 +23,7 @@ #endif #include "net/gnrc/neterr.h" #include "net/gnrc/netif/internal.h" +#include "net/gnrc/netif/pktq.h" #include "net/gnrc/pkt.h" #include "net/gnrc/sixlowpan.h" #include "net/gnrc/sixlowpan/config.h" @@ -548,6 +549,51 @@ void gnrc_sixlowpan_frag_sfr_arq_timeout(gnrc_sixlowpan_frag_fb_t *fbuf) _clean_up_fbuf(fbuf, error_no); } +static void _6lo_dispatch_send(gnrc_pktsnip_t *frame, void *ctx, unsigned page) +{ + if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_ECN) && + (sixlowpan_sfr_rfrag_is(frame->next->data))) { + int queue_state = 0; + int queue_size = 0; + + if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_ECN_IF_IN)) { + gnrc_netif_t *netif = gnrc_netif_hdr_get_netif(frame->data); + + assert(frame->type == GNRC_NETTYPE_NETIF); + assert(frame->next->type == GNRC_NETTYPE_SIXLOWPAN); + queue_state = msg_avail_thread(netif->pid); + queue_size = msg_queue_capacity(netif->pid); + assert(queue_size > 0); + + if ((queue_state * CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_IN_DEN) > + (queue_size * CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_IN_NUM)) { + sixlowpan_sfr_set_ecn(frame->next->data); + } + } + + if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_ECN_IF_OUT)) { + queue_state = gnrc_netif_pktq_usage(); + queue_size = CONFIG_GNRC_NETIF_PKTQ_POOL_SIZE; + + if ((queue_state * CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_OUT_DEN) > + ((unsigned)queue_size * CONFIG_GNRC_SIXLOWPAN_SFR_ECN_IF_OUT_NUM)) { + sixlowpan_sfr_set_ecn(frame->next->data); + } + } + + if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_ECN_FQUEUE)) { + queue_state = clist_count(&_frame_queue); + queue_size = FRAME_QUEUE_POOL_SIZE; + + if ((queue_state * CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_DEN) > + (queue_size * CONFIG_GNRC_SIXLOWPAN_SFR_ECN_FQUEUE_NUM)) { + sixlowpan_sfr_set_ecn(frame->next->data); + } + } + } + gnrc_sixlowpan_dispatch_send(frame, ctx, page); +} + void gnrc_sixlowpan_frag_sfr_inter_frame_gap(void) { if (CONFIG_GNRC_SIXLOWPAN_SFR_INTER_FRAME_GAP_US > 0) { @@ -555,7 +601,7 @@ void gnrc_sixlowpan_frag_sfr_inter_frame_gap(void) if (node != NULL) { _last_frame_sent = xtimer_now_usec(); - gnrc_sixlowpan_dispatch_send(node->frame, NULL, node->page); + _6lo_dispatch_send(node->frame, NULL, node->page); /* unset packet just to be safe */ node->frame = NULL; clist_rpush(&_frame_queue_free, &node->super); @@ -747,7 +793,7 @@ static bool _send_frame(gnrc_pktsnip_t *frame, void *ctx, unsigned page) ((now - _last_frame_sent) > CONFIG_GNRC_SIXLOWPAN_SFR_INTER_FRAME_GAP_US)) { DEBUG("6lo sfr: dispatch frame to network interface\n"); _last_frame_sent = now; - gnrc_sixlowpan_dispatch_send(frame, ctx, page); + _6lo_dispatch_send(frame, ctx, page); return true; } else {