test(nat): exercise full retry budget with high RTT and lost reports

This commit is contained in:
evgeny committed 2026-10-17 23:45:35 +02:00
1 parent 305b61ccab
commit 7bf877b7d6
1 file changed
+17 -9
+17 -9
View File
@@ -7,7 +7,7 @@
enum fault_mode { FAULT_NONE, FAULT_NO_PONG, FAULT_FILTERED, FAULT_LATE_PRE, FAULT_CONTACT, enum fault_mode { FAULT_NONE, FAULT_NO_PONG, FAULT_FILTERED, FAULT_LATE_PRE, FAULT_CONTACT,
FAULT_DEPENDENT, FAULT_UNSTABLE, FAULT_NO_REPORT, FAULT_INGRESS_BLOCKED, FAULT_NO_ANCHOR, FAULT_DEPENDENT, FAULT_UNSTABLE, FAULT_NO_REPORT, FAULT_INGRESS_BLOCKED, FAULT_NO_ANCHOR,
FAULT_LOCAL_INGRESS, FAULT_LOCAL_OBSERVER, FAULT_LOCAL_HELPER_MAPPING, FAULT_CONTROL_STALL, FAULT_EIM_UNVERIFIED, FAULT_LOCAL_INGRESS, FAULT_LOCAL_OBSERVER, FAULT_LOCAL_HELPER_MAPPING, FAULT_CONTROL_STALL, FAULT_EIM_UNVERIFIED,
FAULT_KNOWN_ALIAS, FAULT_BUDGET }; FAULT_KNOWN_ALIAS, FAULT_BUDGET, FAULT_RESUME_TIMEOUT };
static struct { static struct {
struct nat_fixture *fixture; struct nat_fixture *fixture;
@@ -123,6 +123,10 @@ ssize_t __wrap_socket_sendto(socket_t fd, const void *packet, size_t length, con
void __wrap_nat_detection_record_observation(struct NAT_DETECTION *detector, struct ETCP_SOCKET *socket, void __wrap_nat_detection_record_observation(struct NAT_DETECTION *detector, struct ETCP_SOCKET *socket,
const uint8_t *key, const struct sockaddr_storage *source, const uint8_t *tag, size_t length) { const uint8_t *key, const struct sockaddr_storage *source, const uint8_t *tag, size_t length) {
if (fault.fixture && fault.mode == FAULT_RESUME_TIMEOUT && socket->instance == fault.observer &&
length == ROUTE_OBSERVE_TAG_SIZE + 9 && !memcmp(key, fault.owner->my_keys.public_key, 32)) {
fault.dropped++; return;
}
if (fault.fixture && fault.mode == FAULT_EIM_UNVERIFIED && length == ROUTE_OBSERVE_TAG_SIZE + 9 && if (fault.fixture && fault.mode == FAULT_EIM_UNVERIFIED && length == ROUTE_OBSERVE_TAG_SIZE + 9 &&
!memcmp(key, fault.owner->my_keys.public_key, 32)) { !memcmp(key, fault.owner->my_keys.public_key, 32)) {
/* Два направления видят один переведённый адрес. История помощника уже загрязнена настоящим PING. */ /* Два направления видят один переведённый адрес. История помощника уже загрязнена настоящим PING. */
@@ -425,14 +429,18 @@ static void run_budget_resume(void) {
assert(!nat_detection_get_status(owner->nat_det, fault.socket, &status)); assert(!nat_detection_get_status(owner->nat_det, fault.socket, &status));
assert(!status.phase && status.cycling && status.round == paused_round && status.helper_reselections == completed_pairs); assert(!status.phase && status.cycling && status.round == paused_round && status.helper_reselections == completed_pairs);
assert(fault.socket->address_profile.inbound == ADDRESS_IN_UNKNOWN); assert(fault.socket->address_profile.inbound == ADDRESS_IN_UNKNOWN);
fault.delayed_length = 0; end = get_time_tb() + 1300000; fault.mode = FAULT_RESUME_TIMEOUT; fault.delayed_length = 0; end = get_time_tb() + 1300000;
do { test_clock_poll(fixture.ua, 1000); assert(!nat_detection_get_status(owner->nat_det, fault.socket, &status)); } uint32_t resumed_rounds = 0;
while (get_time_tb() < end && status.round == paused_round); /* Большой RTT увеличивает ожидание UDP-отчёта за общий предел; отчёты B теряются в сети. */
assert(status.round != paused_round && status.helper == paused_helper && status.helper_reselections == completed_pairs); struct ETCP_CONN *connection = instance_find_conn(owner, observer->node_id); assert(connection);
uint32_t resumed_rounds = status.rounds; do {
/* Полный бюджет уже дан этой паре: следующий предел завершает её, а не запускает бесконечные повторы. */ for (struct ETCP_LINK *link = connection->links; link; link = link->next) link->rtt_last = 60000;
do { test_clock_poll(fixture.ua, 1000); assert(!nat_detection_get_status(owner->nat_det, fault.socket, &status)); } test_clock_poll(fixture.ua, 1000); assert(!nat_detection_get_status(owner->nat_det, fault.socket, &status));
while (get_time_tb() < end && status.cycling); if (status.round != paused_round && !resumed_rounds) {
assert(status.helper == paused_helper && status.helper_reselections == completed_pairs);
resumed_rounds = status.rounds;
}
} while (get_time_tb() < end && status.cycling);
assert(!status.phase && !status.cycling && status.round != paused_round && status.helper == paused_helper); assert(!status.phase && !status.cycling && status.round != paused_round && status.helper == paused_helper);
assert(status.rounds == resumed_rounds); assert(status.rounds == resumed_rounds);
assert(status.helper_reselections == completed_pairs + 1 && fault.socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED && assert(status.helper_reselections == completed_pairs + 1 && fault.socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED &&