Browse Source

Retain down ETCP connections while local NCD handles exist

master
evgeny 12 hours ago
parent
commit
11f1a14063
  1. 28
      src/transport_layer/etcp.c
  2. 4
      src/transport_layer/etcp.h

28
src/transport_layer/etcp.c

@ -4,6 +4,7 @@
#include "etcp_api.h"
#include "etcp_session.h"
#include "etcp_connect.h"
#include "node_conn_direct.h"
#include "etcp_debug.h"
#include "call_ring.h"
#include "etcp_loadbalancer.h"
@ -195,7 +196,7 @@ static uint16_t timestamp_diff(uint16_t t1, uint16_t t2) {
static const char EMPTY_NAME[] = "";
// Create new ETCP connection
// Таймаут непрерывного DOWN удаляет транспорт независимо от внешних ссылок.
// Таймаут DOWN удаляет только транспорт без локальных NCD владельцев.
static void etcp_down_timeout_cb(void* arg) {
struct ETCP_CONN* conn = arg;
conn->down_timer = NULL;
@ -204,26 +205,37 @@ static void etcp_down_timeout_cb(void* arg) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] DOWN timeout ignored: transport is UP", conn->log_name);
return;
}
int handles = node_conn_direct_handle_count(conn);
if (handles) {
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] DOWN timeout: retaining transport peer=%016llx handles=%d refs=%d",
conn->log_name, (unsigned long long)conn->peer_node_id, handles, conn->ref_count);
return;
}
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] DOWN timeout: deleting transport peer=%016llx refs=%d timeout_ms=%d",
conn->log_name, (unsigned long long)conn->peer_node_id, conn->ref_count, ETCP_DOWN_TIMEOUT_TB / 10);
etcp_connection_close(conn);
}
// Повторный DOWN не продлевает ожидание; первое подключение тоже имеет конечный срок.
static int etcp_down_timer_start(struct ETCP_CONN* conn) {
int etcp_conn_schedule_down_close(struct ETCP_CONN* conn) {
if (conn->down_timer || conn->links_up || conn->close_requested || conn->state == 2) return 0;
conn->down_timer = uasync_set_timeout(conn->instance->ua, ETCP_DOWN_TIMEOUT_TB, conn, etcp_down_timeout_cb, "etcp_down");
uint64_t now = get_time_tb();
if (!conn->down_deadline_tb) conn->down_deadline_tb = now + ETCP_DOWN_TIMEOUT_TB;
if (conn->down_deadline_tb <= now && node_conn_direct_handle_count(conn)) return 0;
int remaining = conn->down_deadline_tb > now ? (int)(conn->down_deadline_tb - now) : 1;
conn->down_timer = uasync_set_timeout(conn->instance->ua, remaining, conn, etcp_down_timeout_cb, "etcp_down");
if (!conn->down_timer) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "[%s] cannot schedule DOWN timeout", conn->log_name);
return -1;
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] DOWN timer started timeout_ms=%d refs=%d",
conn->log_name, ETCP_DOWN_TIMEOUT_TB / 10, conn->ref_count);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] DOWN timer started remaining_tb=%d handles=%d refs=%d",
conn->log_name, remaining, node_conn_direct_handle_count(conn), conn->ref_count);
return 0;
}
// UP и окончательное закрытие отменяют отложенное удаление.
static void etcp_down_timer_cancel(struct ETCP_CONN* conn) {
conn->down_deadline_tb = 0;
if (!conn->down_timer) return;
uasync_cancel_timeout(conn->instance->ua, conn->down_timer); conn->down_timer = NULL;
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] DOWN timer cancelled up=%u closing=%u",
@ -316,7 +328,7 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* n
return NULL;
}
if (etcp_down_timer_start(etcp) < 0) { etcp_connection_close(etcp); return NULL; }
if (etcp_conn_schedule_down_close(etcp) < 0) { etcp_connection_close(etcp); return NULL; }
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] connection initialized. ETCP=%p mtu=%d, next_tx_id=%u state=pending",
etcp->log_name, etcp, etcp->mtu, etcp->next_tx_id);
@ -1113,7 +1125,9 @@ void etcp_on_link_down(struct ETCP_CONN* etcp, struct ETCP_LINK* down_link) {
int was_up = etcp->links_up;
etcp->links_up = up;
if (!up) {
if (etcp_down_timer_start(etcp) < 0) { etcp_connection_close(etcp); return; }
if (etcp_conn_schedule_down_close(etcp) < 0 && !node_conn_direct_handle_count(etcp)) {
etcp_connection_close(etcp); return;
}
} else etcp_down_timer_cancel(etcp);
if (up == 0 && was_up != 0) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "All links fall down");

4
src/transport_layer/etcp.h

@ -188,6 +188,7 @@ struct ETCP_CONN {
void* retrans_timer; // Retrans check timer
void* ack_resp_timer; // ACK send timer
void* down_timer; // удаление после непрерывного DOWN, включая первоначальное ожидание
uint64_t down_deadline_tb; // сохраняется при наличии NCD handles после истечения таймера
// Bandwidth measurement state
// uint8_t burst_in_progress; // Burst transmission flag - Not used
@ -248,6 +249,9 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* n
#define ETCP_DOWN_TIMEOUT_TB 300000 /* 30 секунд в 0.1 ms */
/* Поставить удаление DOWN без NCD handles с учётом уже прошедшего срока; -1 при отказе таймера. */
int etcp_conn_schedule_down_close(struct ETCP_CONN* conn);
/**
* @brief Закрыть соединение: фаза-1 detach + отложенная фаза-2 очистка.
*

Loading…
Cancel
Save