From 208aeeacf048a343683aee630963e8dba73f5f4e Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 19 Mar 2021 14:06:24 +0100 Subject: [PATCH] fixup! gnrc_sixlowpan_frag_sfr: provide CongURE support --- .../net/gnrc/sixlowpan/frag/sfr/congure.h | 6 +++ .../frag/sfr/gnrc_sixlowpan_frag_sfr.c | 45 +++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/sys/include/net/gnrc/sixlowpan/frag/sfr/congure.h b/sys/include/net/gnrc/sixlowpan/frag/sfr/congure.h index 737bee07d9675..071b2cf002cea 100644 --- a/sys/include/net/gnrc/sixlowpan/frag/sfr/congure.h +++ b/sys/include/net/gnrc/sixlowpan/frag/sfr/congure.h @@ -136,6 +136,9 @@ static inline void gnrc_sixlowpan_frag_sfr_congure_snd_setup(gnrc_sixlowpan_frag fb->sfr.congure = gnrc_sixlowpan_frag_sfr_congure_snd_get(); assert(fb->sfr.congure); gnrc_sixlowpan_frag_sfr_congure_snd_init(fb); + if (fb->sfr.congure->cwnd > CONFIG_GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE) { + fb->sfr.congure->cwnd = CONFIG_GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE; + } } #else (void)fb; @@ -372,6 +375,9 @@ static inline void gnrc_sixlowpan_frag_sfr_congure_snd_report_frag_acked( congure_snd_t *c = fb->sfr.congure; c->driver->report_msg_acked(c, frag, ack); + if (c->cwnd > CONFIG_GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE) { + c->cwnd = CONFIG_GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE; + } #else (void)fb; (void)frag; 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 db4fe8a4d5863..9d7dcafccffa0 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 @@ -175,6 +175,15 @@ static bool _send_abort_frag(gnrc_pktsnip_t *pkt, gnrc_sixlowpan_frag_fb_t *fbuf, bool req_ack, unsigned page); +/** + * @brief Adapts currently sent number of fragments to current window size + * + * Balances `fbuf->sfr.window` with `fbuf->sfr.congure->cwnd` + * + * @param[in] fbuf Fragmentation buffer to adapt window for + */ +static void _shrink_window(gnrc_sixlowpan_frag_fb_t *fbuf); + /** * @brief Re-send a fragment * @@ -467,8 +476,7 @@ static int _report_non_ack_req_window_sent(clist_node_t *node, void *fbuf_ptr) void gnrc_sixlowpan_frag_sfr_arq_timeout(gnrc_sixlowpan_frag_fb_t *fbuf) { uint32_t now = xtimer_now_usec() / US_PER_MS; - _frag_desc_t * const head = (_frag_desc_t *)fbuf->sfr.window.next; - _frag_desc_t *frag_desc = head; + _frag_desc_t *frag_desc = (_frag_desc_t *)fbuf->sfr.window.next; uint32_t next_arq_offset = fbuf->sfr.arq_timeout; bool reschedule_arq_timeout = false; int error_no = ETIMEDOUT; /* assume time out for fbuf->pkt */ @@ -479,9 +487,14 @@ void gnrc_sixlowpan_frag_sfr_arq_timeout(gnrc_sixlowpan_frag_fb_t *fbuf) /* time goes by ;-) */ now -= (fbuf->sfr.arq_timeout * US_PER_MS) + 1; } + if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_CONGURE) && frag_desc) { + gnrc_sixlowpan_frag_sfr_congure_snd_report_frags_timeout(fbuf); + _shrink_window(fbuf); + frag_desc = (_frag_desc_t *)fbuf->sfr.window.next; + } + _frag_desc_t * const head = frag_desc; /* copying clist_foreach because we can't work just in function context */ if (frag_desc) { - gnrc_sixlowpan_frag_sfr_congure_snd_report_frags_timeout(fbuf); do { uint32_t diff; @@ -1249,6 +1262,7 @@ static void _check_failed_frags(sixlowpan_sfr_ack_t *ack, (congure_snd_msg_t *)¬_received ); fbuf->sfr.window = not_received; + _shrink_window(fbuf); assert(fbuf->sfr.frags_sent == clist_count(&fbuf->sfr.window)); /* use _resend_failed_frag here instead of loop above, so * _resend_frag can know if the fragment is the last in the window by @@ -1429,6 +1443,31 @@ static bool _send_abort_frag(gnrc_pktsnip_t *pkt, return false; } +static void _shrink_window(gnrc_sixlowpan_frag_fb_t *fbuf) +{ + if (!IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_CONGURE)) { + /* window does not shrink without congure */ + return; + } + if (!gnrc_sixlowpan_frag_sfr_congure_snd_in_cwnd(fbuf)) { + clist_node_t new_window = { .next = NULL }; + _frag_desc_t *last; + + fbuf->sfr.frags_sent = 0; + while (gnrc_sixlowpan_frag_sfr_congure_snd_in_cwnd(fbuf)) { + clist_rpush(&new_window, clist_lpop(&fbuf->sfr.window)); + fbuf->sfr.frags_sent++; + } + for (clist_node_t *node = clist_lpop(&fbuf->sfr.window); + node != NULL; node = clist_lpop(&fbuf->sfr.window)) { + clist_rpush(&_frag_descs_free, node); + } + fbuf->sfr.window.next = new_window.next; + last = (_frag_desc_t *)clist_rpeek(&fbuf->sfr.window); + fbuf->offset = last->offset + _frag_size(last); + } +} + static int _resend_frag(clist_node_t *node, void *fbuf_ptr) { _frag_desc_t *frag_desc = (_frag_desc_t *)node;