You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

83 lines
4.3 KiB

/**
* @file topo_recovery.h
* @brief Восстановление каскадно отвалившихся узлов после разрыва ETCP-соединения.
*
* Когда рвётся соединение, узлы достижимые только через него становятся недоступны.
* Модуль собирает их перед удалением из BGP-таблицы и пробует переподключиться
* напрямую (ncd):
* 1. add_node — из hop_list вычисляет next_hop относительно failed_peer,
* группирует узлы по next_hop в отдельные recovery-контексты
* 2. start — для каждого контекста запускает асинхронный перебор:
* сперва пробует next_hop-узел (is_next_hop=1), затем остальные по мин. RTT
* 3. Таймаут 2с на каждую попытку node_conn_direct_open
*
* Группировка: <мы> -> <failed_peer N> -> <next_hop A, B...>
* Каждый next_hop со своим subtree — отдельный recovery-контекст.
* Восстановление next_hop автоматически оживляет его subtree через BGP.
*
* Отмена: topo_group_new_conn (узел появился в сети) сканирует все active recovery,
* при совпадении отменяет контекст целиком. Самоуничтожение при исчерпании списков.
*/
#ifndef TOPO_RECOVERY_H
#define TOPO_RECOVERY_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
struct TOPO_GROUP;
struct TOPO_GROUP_NODE;
struct NODE_CONN_DIRECT;
#define TOPO_RECOVERY_CONNECT_TIMEOUT_MS 2000
struct TOPO_RECOVERY_NODE {
uint64_t node_id;
uint16_t min_rtt; /* 0.1ms, из connectivity-проб (interface/nat/real) */
uint8_t is_next_hop; /* 1 = прямой downstream отвалившегося узла, пробуется первым */
};
struct TOPO_RECOVERY_CTX {
struct TOPO_RECOVERY_CTX* next; /* следующий в group->recovery_list */
struct UTUN_INSTANCE* instance;
struct TOPO_GROUP* group;
uint64_t next_hop_id; /* ключ группировки: node_id next-hop'а от failed_peer */
struct TOPO_RECOVERY_NODE* nodes; /* кандидаты на восстановление (прямые) */
size_t count; /* текущее количество */
size_t capacity; /* выделенная ёмкость */
uint64_t current_node_id; /* node_id в текущей попытке, 0=нет активной */
struct NODE_CONN_DIRECT* current_handle; /* handle текущей попытки node_conn_direct_open */
void* connect_timer; /* внешний таймер 2с (uasync) */
uint8_t started; /* 0=сбор узлов (add_node), 1=перебор запущен */
};
/**
* Добавляет узел в pending-контекст, сгруппированный по next_hop относительно failed_peer.
* Вызывается из topo_group_remove_conn ДО topo_node_free_lists (нужен hop_list).
* @param failed_peer node_id отвалившегося пира (conn->peer_node_id)
*/
void topo_recovery_add_node(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* nq, uint64_t next_hop);
/**
* Запускает перебор узлов для всех pending-контекстов.
* Вызывается после цикла в topo_group_remove_conn если есть каскадные узлы.
*/
void topo_recovery_start(struct TOPO_GROUP* group);
/**
* Сканирует все active recovery: если node_id найден в любом контексте —
* отменяет текущую попытку connect и освобождает контекст.
* Вызывается из topo_group_new_conn (узел появился в сети).
*/
void topo_recovery_cancel_for_node(struct TOPO_GROUP* group, uint64_t node_id);
/** Отменяет все recovery-контексты. Вызывается из topo_group_destroy. */
void topo_recovery_cancel_all(struct TOPO_GROUP* group);
#ifdef __cplusplus
}
#endif
#endif