diff options
Diffstat (limited to 'src/ipcpd')
-rw-r--r-- | src/ipcpd/unicast/pol/ca-mb-ecn.c | 59 |
1 files changed, 41 insertions, 18 deletions
diff --git a/src/ipcpd/unicast/pol/ca-mb-ecn.c b/src/ipcpd/unicast/pol/ca-mb-ecn.c index 9f07fc77..7f570a9e 100644 --- a/src/ipcpd/unicast/pol/ca-mb-ecn.c +++ b/src/ipcpd/unicast/pol/ca-mb-ecn.c @@ -33,6 +33,7 @@ #include "ca-mb-ecn.h" +#include <inttypes.h> #include <stdlib.h> #include <string.h> #include <stdio.h> @@ -42,12 +43,12 @@ #define CA_WND (1 << CA_SHFT) /* 32 pkts receiver wnd */ #define CA_UPD (1 << (CA_SHFT - 3)) /* Update snd every 8 pkt */ #define CA_SLOT 24 /* Initial slot = 16 ms */ -#define CA_INC 1 << 16 /* ~4MiB/s^2 additive inc */ -#define CA_IWL 1 << 16 /* Initial limit ~4MiB/s */ +#define CA_INC 1UL << 16 /* ~4MiB/s^2 additive inc */ +#define CA_IWL 1UL << 16 /* Initial limit ~4MiB/s */ #define CA_MINPS 8 /* Mimimum pkts / slot */ #define CA_MAXPS 64 /* Maximum pkts / slot */ #define ECN_Q_SHFT 4 -#define ts_to_ns(ts) (ts.tv_sec * BILLION + ts.tv_nsec) +#define ts_to_ns(ts) ((size_t) ts.tv_sec * BILLION + ts.tv_nsec) struct mb_ecn_ctx { uint16_t rx_ece; /* Level of congestion (upstream) */ @@ -101,6 +102,8 @@ void mb_ecn_ctx_destroy(void * ctx) free(ctx); } +#define _slot_after(new, old) ((int64_t) (old - new) < 0) + ca_wnd_t mb_ecn_ctx_update_snd(void * _ctx, size_t len) { @@ -120,7 +123,9 @@ ca_wnd_t mb_ecn_ctx_update_snd(void * _ctx, if (ctx->tx_ctr > CA_WND) ctx->tx_ece = 0; - if (slot > ctx->tx_slot) { + if (_slot_after(slot, ctx->tx_slot)) { + bool carry = false; /* may carry over if window increases */ + ctx->tx_slot = slot; if (!ctx->tx_cav) { /* Slow start */ @@ -136,21 +141,39 @@ ca_wnd_t mb_ecn_ctx_update_snd(void * _ctx, /* Window scaling */ if (ctx->tx_wpc < CA_MINPS) { - ++ctx->tx_mul; - ctx->tx_slot >>= 1; - ctx->tx_wbl <<= 1; - ctx->tx_inc <<= 1; + size_t fact = 0; /* factor to scale the window up */ + size_t pkts = ctx->tx_wpc; + while (pkts < CA_MINPS) { + pkts <<= 1; + fact++; + } + ctx->tx_mul += fact; + ctx->tx_slot >>= fact; + if ((ctx->tx_slot & ((1 << fact) - 1)) == 0) { + carry = true; + ctx->tx_slot += 1; + } + ctx->tx_wbl <<= fact; + ctx->tx_inc <<= fact; + } else if (ctx->tx_wpc > CA_MAXPS) { + size_t fact = 0; /* factor to scale the window down */ + size_t pkts = ctx->tx_wpc; + while (pkts > CA_MAXPS) { + pkts >>= 1; + fact++; + } + ctx->tx_mul -= fact; + ctx->tx_slot <<= fact; + ctx->tx_wbl >>= fact; + ctx->tx_inc >>= fact; + } else { + ctx->tx_slot = slot; } - if (ctx->tx_wpc > CA_MAXPS) { - --ctx->tx_mul; /* Underflows at ~CA_MAXPS billion pps */ - ctx->tx_slot <<= 1; - ctx->tx_wbl >>= 1; - ctx->tx_inc >>= 1; + if (!carry) { + ctx->tx_wbc = 0; + ctx->tx_wpc = 0; } - - ctx->tx_wbc = 0; - ctx->tx_wpc = 0; } if (ctx->tx_wbc > ctx->tx_wbl) @@ -258,14 +281,14 @@ ssize_t mb_ecn_print_stats(void * _ctx, "Upstream packet counter: %20zu\n" "Downstream congestion level: %20u\n" "Downstream packet counter: %20zu\n" - "Congestion window size (ns): %20zu\n" + "Congestion window size (ns): %20" PRIu64 "\n" "Packets in this window: %20zu\n" "Bytes in this window: %20zu\n" "Max bytes in this window: %20zu\n" "Current congestion regime: %20s\n", "Multi-bit ECN", ctx->rx_ece, ctx->rx_ctr, - ctx->tx_ece, ctx->tx_ctr, (size_t) (1 << ctx->tx_mul), + ctx->tx_ece, ctx->tx_ctr, (size_t) (1UL << ctx->tx_mul), ctx->tx_wpc, ctx->tx_wbc, ctx->tx_wbl, regime); |