Browse Source

ETCP: реализация keepalive пакетов для каждого линка

- Добавлены поля keepalive_timer и pkt_sent_since_keepalive в struct ETCP_LINK
- Реализована отправка пустых keepalive пакетов (только timestamp) по таймеру
- Keepalive пропускается если был отправлен другой пакет с момента последнего тика
- Таймер запускается после инициализации линка (keepalive_interval из конфига)
- Исправлен тест test_bgp_route_exchange: убран лишний htonl() при проверке маршрутов
nodeinfo-routing-update
Evgeny 2 months ago
parent
commit
15a9521559
  1. 93
      src/etcp_connections.c
  2. 4
      src/etcp_connections.h
  3. 5
      tests/test_bgp_route_exchange.c

93
src/etcp_connections.c

@ -36,6 +36,8 @@ static void packet_dump(const char* prefix, const uint8_t* data, size_t len, str
static void etcp_link_send_init(struct ETCP_LINK* link);
static int etcp_link_send_reset(struct ETCP_LINK* link);
static void etcp_link_init_timer_cbk(void* arg);
static void etcp_link_send_keepalive(struct ETCP_LINK* link);
static void keepalive_timer_cb(void* arg);
#define INIT_TIMEOUT_INITIAL 500
#define INIT_TIMEOUT_MAX 50000
@ -112,11 +114,69 @@ static void etcp_link_init_timer_cbk(void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
struct ETCP_LINK* link = (struct ETCP_LINK*)arg;
if (!link || link->initialized || link->is_server != 0) return;
link->init_timer = NULL;
etcp_link_send_init(link);
}
// Send empty keepalive packet (only timestamp, no sections)
static void etcp_link_send_keepalive(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!link || !link->etcp || !link->etcp->instance) return;
struct ETCP_DGRAM* dgram = malloc(sizeof(struct ETCP_DGRAM) + 2);
if (!dgram) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "etcp_link_send_keepalive: malloc failed");
return;
}
dgram->link = link;
dgram->data_len = 0; // Empty packet - only timestamp in header
dgram->noencrypt_len = 0;
dgram->timestamp = get_current_timestamp();
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Sending keepalive on link %p (local_id=%d)",
link->etcp->log_name, link, link->local_link_id);
etcp_encrypt_send(dgram);
free(dgram);
}
// Keepalive timer callback
static void keepalive_timer_cb(void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
struct ETCP_LINK* link = (struct ETCP_LINK*)arg;
if (!link || !link->etcp || !link->etcp->instance) return;
link->keepalive_timer = NULL;
// Skip if link is not initialized
if (!link->initialized) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Keepalive skipped - link not initialized",
link->etcp->log_name);
goto restart_timer;
}
// Send keepalive only if no packets were sent since last tick
if (!link->pkt_sent_since_keepalive) {
etcp_link_send_keepalive(link);
} else {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Keepalive skipped - packet sent since last tick",
link->etcp->log_name);
}
// Reset flag for next interval
link->pkt_sent_since_keepalive = 0;
restart_timer:
// Restart timer
if (link->keepalive_interval > 0) {
link->keepalive_timer = uasync_set_timeout(link->etcp->instance->ua,
link->keepalive_interval * 10,
link, keepalive_timer_cb);
}
}
static int etcp_link_send_reset(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!link) return -1;
@ -462,6 +522,12 @@ void etcp_link_close(struct ETCP_LINK* link) {
link->shaper_timer = NULL;
}
// Cancel keepalive timer if active
if (link->keepalive_timer) {
uasync_cancel_timeout(link->etcp->instance->ua, link->keepalive_timer);
link->keepalive_timer = NULL;
}
// универсальное удаление из односвязного списка
struct ETCP_LINK **pp = &link->etcp->links;
while (*pp) {
@ -482,6 +548,11 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "etcp_encrypt_send called, link=%p", dgram ? dgram->link : NULL);
// printf("[ETCP DEBUG] etcp_encrypt_send: ENTERING FUNCTION\n");
if (!dgram || !dgram->link) return -1;
// Mark that packet was sent (for keepalive logic)
dgram->link->pkt_sent_since_keepalive = 1;
int errcode=0;
sc_context_t* sc = &dgram->link->etcp->crypto_ctx;
int len=dgram->data_len-dgram->noencrypt_len;// не забываем добавить timestamp (2 bytes)
@ -702,6 +773,16 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
memory_pool_free(e_sock->instance->pkt_pool, pkt);
link->initialized = 1;// получен init request (server), считаем линк уже готовым к работе
// Start keepalive timer
if (!link->keepalive_timer && link->keepalive_interval > 0) {
link->keepalive_timer = uasync_set_timeout(link->etcp->instance->ua,
link->keepalive_interval * 10,
link, keepalive_timer_cb);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Keepalive timer started on link %p (interval=%d ms)",
link->etcp->log_name, link, link->keepalive_interval);
}
loadbalancer_link_ready(link);
// Notify BGP about new connection to send routing table
@ -792,6 +873,16 @@ process_decrypted:
// Mark link as initialized
// DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "Setting link->initialized=1, link=%p, is_server=%d", link, link->is_server);
link->initialized = 1;// получен init response (client)
// Start keepalive timer
if (!link->keepalive_timer && link->keepalive_interval > 0) {
link->keepalive_timer = uasync_set_timeout(link->etcp->instance->ua,
link->keepalive_interval * 10,
link, keepalive_timer_cb);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Keepalive timer started on link %p (interval=%d ms)",
link->etcp->log_name, link, link->keepalive_interval);
}
loadbalancer_link_ready(link);
// Notify BGP about new connection to send routing table

4
src/etcp_connections.h

@ -90,6 +90,10 @@ struct ETCP_LINK {
uint16_t nat_port; // NAT port (network byte order)
uint32_t nat_changes_count; // Counter of NAT address changes
uint32_t nat_hits_count; // Counter of NAT address matches (new init response with same IP:port)
// Keepalive state
void* keepalive_timer; // Таймер для отправки keepalive пакетов
uint8_t pkt_sent_since_keepalive; // Флаг: был ли отправлен пакет с последнего keepalive тика
};
// INITIALIZATION (создаёт listen-сокеты и подключения из конфига)

5
tests/test_bgp_route_exchange.c

@ -245,14 +245,15 @@ static int verify_bgp_exchange(void) {
// Check server learned client's routes (192.168.20.0/24, 192.168.21.0/24)
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Checking server learned client's routes...");
if (!check_learned_route(server_instance, htonl(0xC0A81400), 24, 0x2222222222222222ULL)) {
// Note: Routes are stored in host byte order, not network byte order
if (!check_learned_route(server_instance, 0xC0A81400, 24, 0x2222222222222222ULL)) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "FAIL: Server missing learned route 192.168.20.0/24");
success = 0;
} else {
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "PASS: Server has learned route 192.168.20.0/24");
}
if (!check_learned_route(server_instance, htonl(0xC0A81500), 24, 0x2222222222222222ULL)) {
if (!check_learned_route(server_instance, 0xC0A81500, 24, 0x2222222222222222ULL)) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "FAIL: Server missing learned route 192.168.21.0/24");
success = 0;
} else {

Loading…
Cancel
Save