diff --git a/src/routing_layer/etcp_router.c b/src/routing_layer/etcp_router.c index 5fd16d11..aa12dc8d 100644 --- a/src/routing_layer/etcp_router.c +++ b/src/routing_layer/etcp_router.c @@ -202,7 +202,7 @@ static int router_build_packet(struct ETCP_ROUTER_CONN* rconn, const uint8_t* pa hdr->seq = rconn->tx_seq++; hdr->svc_id = rconn->svc_id; { - uint8_t f = (rconn->sess_id << ROUTER_SESS_ID_SHIFT); + uint8_t f = 0; if (!rconn->start_sent && hdr->seq == 0 && pl_len > 0) f |= ROUTER_FLAG_START; hdr->flags = f; } @@ -232,7 +232,7 @@ static void router_send_ctrl(struct ETCP_ROUTER_CONN* rconn, uint8_t flag_bits) hdr->src_node_id = rconn->inst->node_id; hdr->seq = 0; hdr->svc_id = rconn->svc_id; - hdr->flags = (rconn->sess_id << ROUTER_SESS_ID_SHIFT) | flag_bits; + hdr->flags = flag_bits; hdr->timestamp = get_current_timestamp(); struct ll_entry* entry = queue_entry_new(0); if (!entry) { u_free(hdr); return; } @@ -263,7 +263,7 @@ static void router_send_rst(struct ETCP_ROUTER_CONN* rconn) { hdr->dst_node_id = rconn->remote_node_id; hdr->src_node_id = inst->node_id; hdr->seq = 0; - hdr->flags = ROUTER_FLAG_RST | (rconn->sess_id << ROUTER_SESS_ID_SHIFT); + hdr->flags = ROUTER_FLAG_RST; hdr->svc_id = rconn->svc_id; hdr->timestamp = get_current_timestamp(); struct ll_entry* entry = queue_entry_new(0); @@ -376,7 +376,6 @@ static void router_conn_reset(struct ETCP_ROUTER_CONN* rconn) { rconn->tx_seq = 0; rconn->rx_seq = 0; rconn->tx_acked = 0; rconn->last_sent_ack_seq = 0; rconn->last_ack_sent_tb = 0; - rconn->peer_sess_id = 0; rconn->send_blocked = 0; rconn->start_sent = 0; rconn->peer_sync_done = 0; rconn->no_route = 0; rconn->no_route_timer = NULL; rconn->no_ack_count = 0; rconn->closed = 0; rconn->c_pkts_sent = 0; rconn->c_pkts_send_err = 0; rconn->c_pkts_rcvd = 0; @@ -741,7 +740,7 @@ static void router_send_ack(struct ETCP_ROUTER_CONN* rconn) { hdr->src_node_id = inst->node_id; hdr->seq = rconn->rx_seq; hdr->svc_id = rconn->svc_id; - hdr->flags = (rconn->sess_id << ROUTER_SESS_ID_SHIFT); + hdr->flags = 0; if (rconn->last_recv_updated) { uint64_t now = get_time_tb(); hdr->timestamp = rconn->last_recv_pkt_ts + (uint32_t)(now - rconn->last_recv_pkt_local_tb); @@ -1028,17 +1027,13 @@ static void router_forward_transit(struct UTUN_INSTANCE* inst, struct ll_entry* static int router_check_peer_restart(struct UTUN_INSTANCE* inst, struct ETCP_ROUTER_CONN** prconn, struct SVC_ROUTE_HDR* hdr) { struct ETCP_ROUTER_CONN* rconn = *prconn; - uint8_t incoming_sess = (hdr->flags >> ROUTER_SESS_ID_SHIFT) & 0x3; - if (incoming_sess != rconn->peer_sess_id || - ((hdr->flags & ROUTER_FLAG_START) && rconn->rx_seq > 0)) { + if ((hdr->flags & ROUTER_FLAG_START) && rconn->rx_seq > 0) { DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, - "router: peer restart sess_id=%u→%u svc_id=%u from %016llx", - rconn->peer_sess_id, incoming_sess, hdr->svc_id, - (unsigned long long)hdr->src_node_id); + "router: peer restart svc_id=%u from %016llx", + hdr->svc_id, (unsigned long long)hdr->src_node_id); etcp_router_conn_restart(inst, hdr->group_id, hdr->src_node_id, hdr->svc_id); *prconn = etcp_router_conn_get(inst, hdr->group_id, hdr->src_node_id, hdr->svc_id); if (!*prconn) return -1; - (*prconn)->peer_sess_id = incoming_sess; rconn = *prconn; } return 0; @@ -1121,7 +1116,6 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) if (!rconn) { rconn = etcp_router_conn_get(inst, hdr->group_id, hdr->src_node_id, hdr->svc_id); if (!rconn) { free_entry(entry); return; } - rconn->peer_sess_id = (hdr->flags >> ROUTER_SESS_ID_SHIFT) & 0x3; } if (router_check_peer_restart(inst, &rconn, hdr) != 0) { free_entry(entry); return; } @@ -1256,8 +1250,8 @@ void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t group_id, uin struct ETCP_ROUTER_CONN* rconn = router_conn_find(inst, group_id, remote_node_id, svc_id); if (!rconn) return; - DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_restart: svc_id=%u remote=%016llx — resetting local state", - svc_id, (unsigned long long)remote_node_id); + DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router_restart: svc_id=%u remote=%016llx sess_id=%u→%u — resetting local state", + svc_id, (unsigned long long)remote_node_id, rconn->sess_id, rconn->sess_id + 1); etcp_recv_fn cb = inst->router_bindings.callbacks[svc_id]; if (cb) { @@ -1276,6 +1270,7 @@ void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t group_id, uin } router_conn_reset(rconn); + rconn->sess_id++; } void etcp_router_on_send_ready(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id, uint8_t svc_id, diff --git a/src/routing_layer/etcp_router.h b/src/routing_layer/etcp_router.h index cd43c97d..9c8776d4 100644 --- a/src/routing_layer/etcp_router.h +++ b/src/routing_layer/etcp_router.h @@ -5,7 +5,7 @@ // // Формат SVC_ROUTE пакета: // [cmd:1] [group_id:8] [dst_node_id:8] [src_node_id:8] [seq:4] [svc_id:1] [flags:1] [timestamp:2] [payload...] -// flags: bit7=START, bit6=RST, bit5-4=sess_id(0-3), bit3=SIGNED, bit2=ENCRYPTED, bit1=CLOSE +// flags: bit7=START, bit6=RST, bit3=SIGNED, bit2=ENCRYPTED, bit1=CLOSE // ACK-пакет: тот же заголовок, seq=rx_seq, payload_len=0 #ifndef ETCP_ROUTER_H #define ETCP_ROUTER_H @@ -28,7 +28,7 @@ struct SVC_ROUTE_HDR { uint64_t src_node_id; uint32_t seq; // data: tx_seq; ACK: rx_seq (ожидаемый seq) uint8_t svc_id; // идентификатор сервиса - uint8_t flags; // bit7=START, bit6=RST, bit5-4=sess_id, bit2=ENCRYPTED, bit1=CLOSE + uint8_t flags; // bit7=START, bit6=RST, bit3=SIGNED, bit2=ENCRYPTED, bit1=CLOSE uint16_t timestamp; // часы отправителя (0.1ms), для RTT; ACK: эхо последнего data-пакета }; #pragma pack(pop) @@ -51,8 +51,6 @@ struct SVC_ROUTE_HDR { #define ROUTER_FLAG_ENCRYPTED 0x04 // payload зашифрован AES-128-CCM (nonce+tag+crc) #define ROUTER_FLAG_SIGNED 0x08 // пакет содержит Ed25519 подпись (64 байта после payload) #define ROUTER_FLAG_CLOSE 0x02 // нормальное закрытие conn -#define ROUTER_SESS_ID_SHIFT 4 -#define ROUTER_SESS_ID_MASK 0x30 // Очередь транзитных пакетов для пары (group_id, src_node_id, dst_node_id) // Создаётся когда не получается отправить пакет в ETCP напрямую, @@ -114,8 +112,7 @@ struct ETCP_ROUTER_CONN { uint8_t closed; // 1 = в процессе закрытия, таймеры игнорируют void* close_callback; // пользовательский коллбэк завершения закрытия void* close_callback_arg; // аргумент для close_callback - uint8_t sess_id; // наш session id (0-3) - uint8_t peer_sess_id; // последний sess_id от peer'а + uint32_t sess_id; // локальный счётчик переустановок (0 при создании, ++ при рестарте; на wire не пишется) uint8_t start_sent; // 0 = нужно отправить START в первом data uint8_t peer_sync_done; // 0 = rx_seq ещё не синхронизирован с удалённым seq (авто-создание/рестарт) diff --git a/src/routing_layer/etcp_router_doc.md b/src/routing_layer/etcp_router_doc.md index cac1cec8..c2bfb5a0 100644 --- a/src/routing_layer/etcp_router_doc.md +++ b/src/routing_layer/etcp_router_doc.md @@ -68,7 +68,7 @@ etcp_route_send(inst, group_id, dst, e, force, ROUTE_CRYPTO_SIGN | ROUTE_CRYPTO_ **SVC_ROUTE_HDR** (33 байта) — заголовок пакета: `cmd(1) + group_id(8) + dst_node_id(8) + src_node_id(8) + seq(4) + svc_id(1) + flags(1) + timestamp(2)` -Флаги: `ROUTER_FLAG_START` (0x80), `ROUTER_FLAG_RST` (0x40), `ROUTER_FLAG_SIGNED` (0x08), `ROUTER_FLAG_ENCRYPTED` (0x04), `ROUTER_FLAG_CLOSE` (0x02). Sess_id в bits 5-4. +Флаги: `ROUTER_FLAG_START` (0x80), `ROUTER_FLAG_RST` (0x40), `ROUTER_FLAG_SIGNED` (0x08), `ROUTER_FLAG_ENCRYPTED` (0x04), `ROUTER_FLAG_CLOSE` (0x02). **Формат доставки сервису** (router → callback): `[svc_id:1][src_node_id:8][dst_node_id:8][rx_flags:1][payload...]` (ROUTER_SVC_HDR_SIZE = 18). diff --git a/tests/test_etcp_router_unit.c b/tests/test_etcp_router_unit.c index b7cc4d8e..25413fe6 100644 --- a/tests/test_etcp_router_unit.c +++ b/tests/test_etcp_router_unit.c @@ -718,54 +718,25 @@ static int test_client_restart(void) { return 0; } -static int test_sess_id_change(void) { - TEST("sess_id change — 0→1 with START triggers restart"); +static int test_sess_id_increment(void) { + TEST("sess_id — 0 on create, increments on restart"); struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; SETUP(); - g_notify_count = 0; - - int n = rand() % 10 + 1; - rx_reset(0xC1); - pump_data(recv_cb, &inst, 0xC1, n, 0); - if (rx.delivered != n) FAIL("initial pump failed"); - - rx_reset(0xC2); - uint8_t data[] = { TEST_SVC_ID, 0xC2, 0 }; - uint8_t f = (1 << ROUTER_SESS_ID_SHIFT) | ROUTER_FLAG_START; - inject(recv_cb, &inst, TEST_REMOTE_NODE, TEST_SVC_ID, 0, data + 1, 2, 0, f); - if (g_notify_count != 1) FAIL("restart not notified"); - if (rx.delivered < 1) FAIL("data after restart not delivered"); - - TEARDOWN(); - PASS(); - return 0; -} - -static int test_sess_id_wrap(void) { - TEST("sess_id wrap — 3→0 with START triggers restart"); - struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; - SETUP(); - g_notify_count = 0; - - int n = rand() % 10 + 1; - uint8_t f3 = (3 << ROUTER_SESS_ID_SHIFT); - rx_reset(0xD1); struct ETCP_ROUTER_CONN* c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); if (!c) FAIL("rconn not found"); - c->peer_sess_id = 3; + if (c->sess_id != 0) FAIL("sess_id != 0 on fresh conn"); - pump_data(recv_cb, &inst, 0xD1, n, f3); - if (rx.delivered != n) FAIL("initial pump failed"); + etcp_router_conn_restart(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); + c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); + if (!c) FAIL("rconn not found after first restart"); + if (c->sess_id != 1) FAIL("sess_id != 1 after first restart"); - rx_reset(0xD2); - g_notify_count = 0; - uint8_t data[] = { TEST_SVC_ID, 0xD2, 0 }; - uint8_t f0 = (0 << ROUTER_SESS_ID_SHIFT) | ROUTER_FLAG_START; - inject(recv_cb, &inst, TEST_REMOTE_NODE, TEST_SVC_ID, 0, data + 1, 2, 0, f0); - if (g_notify_count != 1) FAIL("restart not notified on wrap"); - if (rx.delivered < 1) FAIL("data after wrap not delivered"); + etcp_router_conn_restart(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); + c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); + if (c->sess_id != 2) FAIL("sess_id != 2 after second restart"); + etcp_router_conn_close(c); TEARDOWN(); PASS(); return 0; @@ -1187,8 +1158,7 @@ int main(void) { test_conn_send_no_bgp(); test_rst_flag(); test_client_restart(); - test_sess_id_change(); - test_sess_id_wrap(); + test_sess_id_increment(); test_server_reinit(); if (setup_sign_keys() != 0) { printf(" SKIP signed tests — crypto init failed\n"); }