summaryrefslogtreecommitdiff
path: root/src/lib/timerwheel.c
diff options
context:
space:
mode:
authorDimitri Staessens <[email protected]>2022-03-10 08:23:15 +0100
committerSander Vrijders <[email protected]>2022-03-11 17:51:27 +0100
commitf300e609e7975dacc06996d407170fe58aa49439 (patch)
treeb6210cb429de6ab1a3cd555562b8b4b15a7f82c0 /src/lib/timerwheel.c
parenta7032da6bbe875596ea1cb348a747123cda7d408 (diff)
downloadouroboros-f300e609e7975dacc06996d407170fe58aa49439.tar.gz
ouroboros-f300e609e7975dacc06996d407170fe58aa49439.zip
lib: Fix buffer allocation when retransmitting0.19.0
The timerwheel was retransmitting packets and the error check for negative values of the rbuff allocation was instead checking for non-zero values, causing a buffer allocation to succeed but the program to continue down the unhappy path leaving that packet stuck in the buffer unattended. Also fixes wrongly scheduled retransmissions that cause packet storms. FRCP is much more stable now. Still needs some work for high bandwidth-delay products (fast-retransmit). Signed-off-by: Dimitri Staessens <[email protected]> Signed-off-by: Sander Vrijders <[email protected]>
Diffstat (limited to 'src/lib/timerwheel.c')
-rw-r--r--src/lib/timerwheel.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/src/lib/timerwheel.c b/src/lib/timerwheel.c
index 5c0fbfa0..0a6e48e1 100644
--- a/src/lib/timerwheel.c
+++ b/src/lib/timerwheel.c
@@ -174,6 +174,7 @@ static void timerwheel_move(void)
uint32_t snd_lwe;
uint32_t rcv_lwe;
time_t rto;
+ size_t new_i;
r = list_entry(p, struct rxm, next);
@@ -205,26 +206,36 @@ static void timerwheel_move(void)
if (ts_to_ns(now) - r->t0 > r->frcti->r)
goto flow_down;
+ pthread_rwlock_wrlock(&r->frcti->lock);
+
if (r->frcti->probe
- && (r->frcti->rttseq + 1) == r->seqno)
+ && (r->frcti->rttseq == r->seqno)) {
r->frcti->probe = false;
+ r->frcti->rto += (rto >> 3);
+ }
+
+ r->frcti->n_rtx++;
+
+ pthread_rwlock_unlock(&r->frcti->lock);
#ifdef RXM_BLOCKING
#ifdef RXM_BUFFER_ON_HEAP
- if (ipcp_sdb_reserve(&sdb, r->pkt_len))
+ if (ipcp_sdb_reserve(&sdb, r->pkt_len) < 0)
#else
- if (ipcp_sdb_reserve(&sdb, r->tail - r->head))
+ if (ipcp_sdb_reserve(&sdb,
+ r->tail - r->head) < 0)
#endif
#else
#ifdef RXM_BUFFER_ON_HEAP
if (shm_rdrbuff_alloc(ai.rdrb, r->pkt_len, NULL,
- &sdb))
+ &sdb) < 0)
#else
if (shm_rdrbuff_alloc(ai.rdrb,
r->tail - r->head, NULL,
- &sdb))
+ &sdb) < 0)
#endif
#endif
goto reschedule; /* rbuff full */
+
idx = shm_du_buff_get_idx(sdb);
head = shm_du_buff_head(sdb);
@@ -248,15 +259,24 @@ static void timerwheel_move(void)
#endif
shm_flow_set_notify(f->set, f->flow_id,
FLOW_PKT);
+
reschedule:
- r->mul++;
+ rslot = (rto << r->mul++) >> (RXMQ_RES * i);
+
+ new_i = i;
+ while (rslot >= RXMQ_SLOTS) {
+ ++ new_i;
+ rslot >>= RXMQ_BUMP;
+ }
+
+ if (new_i >= RXMQ_LVLS) /* Can't reschedule */
+ continue;
/* Schedule at least in the next time slot. */
- rslot = (rxm_slot
- + MAX(((rto * r->mul) >> RXMQ_RES), 1))
+ rslot = ((rxm_slot >> (RXMQ_BUMP * (new_i - 1))) + MAX(rslot, 1))
& (RXMQ_SLOTS - 1);
- list_add_tail(&r->next, &rw.rxms[i][rslot]);
+ list_add_tail(&r->next, &rw.rxms[new_i][rslot]);
continue;