Preserve the unsigned range of router RTT jitter
This commit is contained in:
1 parent
6c13755a5c
commit
dbf6bb759c
3 files changed
+26
-2
No files matched your search
@@ -1192,7 +1192,8 @@ static void router_handle_ack(struct UTUN_INSTANCE* inst, struct ETCP_ROUTER_CON
|
||||
uint16_t new_rtt = get_current_timestamp() - ack_ts;
|
||||
int d_rtt = (int)new_rtt - (int)rconn->rtt;
|
||||
if (d_rtt < 0) d_rtt = -d_rtt;
|
||||
rconn->rtt_jitter += (int32_t)(((int64_t)d_rtt * 65536 - rconn->rtt_jitter) / 32);
|
||||
int64_t jitter = rconn->rtt_jitter;
|
||||
rconn->rtt_jitter = (uint32_t)(jitter + ((int64_t)d_rtt * 65536 - jitter) / 32);
|
||||
rconn->rtt = new_rtt;
|
||||
}
|
||||
rconn->tx_acked = seq;
|
||||
|
||||
@@ -109,7 +109,7 @@ struct ETCP_ROUTER_CONN {
|
||||
uint8_t svc_id; // = data[16]
|
||||
uint16_t last_dgram_ts; // последний timestamp датаграммы (rx или tx, timebase 0.1ms)
|
||||
uint16_t rtt; // измеренный RTT (0.1ms)
|
||||
int32_t rtt_jitter; // EMA jitter, fixed-point *65536 (как в ETCP)
|
||||
uint32_t rtt_jitter; // EWMA |ΔRTT|, беззнаковый fixed-point *65536; монитор показывает удвоенный EWMA
|
||||
uint16_t max_inflight; // настраиваемый рабочий максимум (default=ROUTER_MAX_INFLIGHT)
|
||||
uint16_t inflight_limit; // текущий эффективный лимит (=max_inflight или MINRTT_PROBE_MAX_INFLIGHT)
|
||||
uint16_t minrtt; // скользящее среднее minRTT (0.1ms), default=100 (10ms)
|
||||
|
||||
@@ -642,6 +642,28 @@ static int test_delivery_stats(void) {
|
||||
TEARDOWN(); PASS(); return 0;
|
||||
}
|
||||
|
||||
/* Высокий RTT не должен переполнять fixed-point EWMA jitter в отрицательное значение. */
|
||||
static int test_jitter_range(void) {
|
||||
TEST("ACK jitter keeps the full unsigned 16.16 range");
|
||||
struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb;
|
||||
SETUP(); debug_set_category_level(DEBUG_CATEGORY_ETCPROUTE, DEBUG_LEVEL_INFO);
|
||||
establish(recv_cb, &inst, TEST_REMOTE_NODE, TEST_SVC_ID, TEST_REMOTE_NODE);
|
||||
struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID);
|
||||
c->tx_seq = c->tx_sent = 1; c->rtt = 0; c->rtt_jitter = INT32_MAX;
|
||||
struct SVC_ROUTE_HDR ack = {.cmd = ETCP_ID_SVC_ROUTE, .group_id = TOPO_GROUP_UTUN,
|
||||
.src_node_id = TEST_REMOTE_NODE, .dst_node_id = inst.node_id, .svc_id = TEST_SVC_ID, .seq = 1,
|
||||
.reset_id = c->peer_reset_id, .peer_reset_id = c->reset_id, .timestamp = (uint16_t)(get_current_timestamp() - 60000)};
|
||||
if (!ack.timestamp) ack.timestamp = 1;
|
||||
struct ll_entry* e = ll_alloc_lldgram(sizeof(ack)); TESTASSERT(e);
|
||||
memcpy(e->dgram, &ack, sizeof(ack)); e->len = sizeof(ack); recv_cb(&fake_conn, e);
|
||||
uint64_t expected = INT32_MAX + (((int64_t)c->rtt * 65536 - INT32_MAX) / 32);
|
||||
uint64_t measured = (uint64_t)c->rtt_jitter;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "[regression] RTT=%u jitter=%llu expected=%llu", c->rtt,
|
||||
(unsigned long long)measured, (unsigned long long)expected);
|
||||
TEARDOWN();
|
||||
TESTASSERT(measured == expected && measured > INT32_MAX); PASS(); return 0;
|
||||
}
|
||||
|
||||
static int test_ack_timer(void) {
|
||||
TEST("ACK timer scheduled on data receive");
|
||||
struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb;
|
||||
@@ -1574,6 +1596,7 @@ int main(void) {
|
||||
test_data_integrity();
|
||||
test_ack_receive();
|
||||
test_delivery_stats();
|
||||
test_jitter_range();
|
||||
test_ack_timer();
|
||||
test_send_q();
|
||||
test_loopback();
|
||||
|
||||
Reference in new issue
Block a user