summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2022-04-03 12:01:20 +0200
committerSander Vrijders <sander@ouroboros.rocks>2022-04-03 18:01:02 +0200
commit783d3adfdb0a074ae7a6e0dd37fe8efaf7e2b39a (patch)
tree6a57ba7ac8bcb16e1c690b9e0db0613aa4a5d834
parent8f6985bb6dc919408f57ac4cafa8e7a04f917f5d (diff)
downloadouroboros-783d3adfdb0a074ae7a6e0dd37fe8efaf7e2b39a.tar.gz
ouroboros-783d3adfdb0a074ae7a6e0dd37fe8efaf7e2b39a.zip
lib: Fix RTO update on timeout
This fixes the RTO doubling on timeout according to Karn/Partridge. Exponentially increasing RTO when it times out (e.g. doubling) fixes the problem that a sudden increase in real RTT starves the sRTT updates by never getting out of backoff as retransmitted packets can't update RTT. Added an parameter to make it less aggressive, default is doubling. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
-rw-r--r--src/lib/CMakeLists.txt2
-rw-r--r--src/lib/config.h.in1
-rw-r--r--src/lib/timerwheel.c18
3 files changed, 9 insertions, 12 deletions
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 4f7d5d18..196bb905 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -200,6 +200,8 @@ set(FRCT_LINUX_RTT_ESTIMATOR TRUE CACHE BOOL
"Use Linux RTT estimator formula instead of the TCP RFC formula")
set(FRCT_RTO_MDEV_MULTIPLIER 2 CACHE STRING
"Multiplier for deviation term in the RTO: RTO = sRTT + (mdev << X)")
+set(FRCT_RTO_INC_FACTOR 0 CACHE STRING
+ "Divisor for RTO increase after timeout: RTO += RTX >> X, 0: Karn/Partridge")
set(FRCT_RTO_MIN 250 CACHE STRING
"Minimum Retransmission Timeout (RTO) for FRCT (us)")
set(FRCT_TICK_TIME 5000 CACHE STRING
diff --git a/src/lib/config.h.in b/src/lib/config.h.in
index e413a0c9..fd54dcd8 100644
--- a/src/lib/config.h.in
+++ b/src/lib/config.h.in
@@ -76,6 +76,7 @@
#define RQ_SIZE (@FRCT_REORDER_QUEUE_SIZE@)
#define START_WINDOW (@FRCT_START_WINDOW@)
#define RTO_MIN (@FRCT_RTO_MIN@ * 1000)
+#define RTO_DIV (@FRCT_RTO_INC_FACTOR@)
#define MDEV_MUL (@FRCT_RTO_MDEV_MULTIPLIER@)
#define TICTIME (@FRCT_TICK_TIME@ * 1000) /* ns */
diff --git a/src/lib/timerwheel.c b/src/lib/timerwheel.c
index f30f867d..cf4e1eef 100644
--- a/src/lib/timerwheel.c
+++ b/src/lib/timerwheel.c
@@ -36,7 +36,6 @@ struct rxm {
struct frct_pci * pkt;
size_t len;
time_t t0; /* Time when original was sent (us). */
- size_t mul; /* RTO multiplier. */
struct frcti * frcti;
int fd;
int flow_id; /* Prevent rtx when fd reused. */
@@ -166,9 +165,7 @@ static void timerwheel_move(void)
struct flow * f;
uint32_t snd_lwe;
uint32_t rcv_lwe;
- time_t rto;
size_t lvl = 0;
- time_t act;
r = list_entry(p, struct rxm, next);
@@ -188,8 +185,6 @@ static void timerwheel_move(void)
snd_lwe = snd_cr->lwe;
rcv_lwe = rcv_cr->lwe;
- rto = r->frcti->rto;
- act = ts_to_ns(r->frcti->rcv_cr.act);
pthread_rwlock_unlock(&r->frcti->lock);
@@ -203,20 +198,20 @@ static void timerwheel_move(void)
pthread_rwlock_wrlock(&r->frcti->lock);
- if (r->frcti->probe
- && (r->frcti->rttseq == r->seqno))
+ if (r->seqno == r->frcti->rttseq) {
+ r->frcti->rto +=
+ f->frcti->rto >> RTO_DIV;
r->frcti->probe = false;
+ }
#ifdef PROC_FLOW_STATS
r->frcti->n_rtx++;
#endif
- pthread_rwlock_unlock(&r->frcti->lock);
+ rslot = r->frcti->rto >> RXMQ_RES;
- if (ts_to_ns(now) - act > (rto << 2))
- rto <<= r->mul++;
+ pthread_rwlock_unlock(&r->frcti->lock);
/* Schedule at least in the next time slot. */
slot = ts_to_ns(now) >> RXMQ_RES;
- rslot = rto >> RXMQ_RES;
while (rslot >= RXMQ_SLOTS) {
++lvl;
@@ -326,7 +321,6 @@ static int timerwheel_rxm(struct frcti * frcti,
clock_gettime(PTHREAD_COND_CLOCK, &now);
r->t0 = ts_to_ns(now);
- r->mul = 0;
r->seqno = seqno;
r->frcti = frcti;
r->len = shm_du_buff_len(sdb);