Browse Source

Defer reachability probes while the first NAT ingress is protected

master
evgeny 6 days ago
parent
commit
9bd113054c
  1. 38
      src/routing_layer/route_connectivity.c
  2. 1
      src/routing_layer/topo_node.h

38
src/routing_layer/route_connectivity.c

@ -19,6 +19,7 @@
#include "route_connectivity.h"
#include "topo_node_sqlite.h"
#include "sock_match.h"
#include "nat_detection.h"
#ifdef UTUN_HAVE_STANDBY
#include "standby.h"
#endif
@ -253,6 +254,24 @@ static void conn_probe_finish(struct conn_probe_ctx* ctx, int ok) {
// ---- public API ----
struct route_nat_defer {
struct UTUN_INSTANCE *instance;
struct TOPO_GROUP *group;
struct TOPO_GROUP_NODE *node;
void *timer;
};
/* После NAT-окна запускает обычную проверку; удаление узла отменяет таймер и освобождает контекст. */
static void route_nat_deferred_cb(void *arg) {
struct route_nat_defer *deferred = arg;
struct UTUN_INSTANCE *instance = deferred->instance;
struct TOPO_GROUP *group = deferred->group;
struct TOPO_GROUP_NODE *node = deferred->node;
node->connectivity.nat_probe_wait = NULL; node->connectivity.probe_status = PROBE_STATUS_NONE;
u_free(deferred);
route_connectivity_probe_node(instance, group, node);
}
#ifdef UTUN_HAVE_STANDBY
/* Контекст пробы, отложенной до следующего активного интервала (standby_wait). */
struct route_probe_defer {
@ -277,6 +296,7 @@ void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct TOPO_G
struct TOPO_NODE* ni = topo_node_registry_find(instance->topo_groups, nq->node_id);
if (!ni) return;
if (nq->node_id == instance->node_id) return; // не пингуем себя
if (nq->connectivity.nat_probe_wait) return;
/* Пир в SLEEP-фазе: прямое соединение живо, probe будит пира — пропускаем. */
{
struct ETCP_CONN* c = instance_find_conn(instance, nq->node_id);
@ -303,6 +323,19 @@ void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct TOPO_G
return;
}
uint64_t nat_delay = nat_detection_probe_delay(instance->nat_det);
if (nat_delay) {
struct route_nat_defer *deferred = u_calloc(1, sizeof(*deferred));
if (!deferred) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "NAT probe defer allocation failed"); return; }
deferred->instance = instance; deferred->group = group; deferred->node = nq;
deferred->timer = uasync_set_timeout(instance->ua, nat_delay, deferred, route_nat_deferred_cb, "route_nat_defer");
if (!deferred->timer) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "NAT probe defer scheduling failed"); u_free(deferred); return; }
nq->connectivity.nat_probe_wait = deferred; nq->connectivity.probe_status = PROBE_STATUS_DEFERRED;
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "connectivity probe waits for initial NAT measurement node=%016llx delay_tb=%llu",
(unsigned long long)nq->node_id, (unsigned long long)nat_delay);
return;
}
nq->connectivity.probe_status = PROBE_STATUS_IN_PROGRESS;
nq->connectivity.probe_start_time = get_time_tb();
nq->connectivity.interface_status = PROBE_RESULT_UNKNOWN;
@ -422,6 +455,11 @@ void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct TOPO_G
* хендла — они отсоединяются и освобождаются своим штатным ping_timeout/PONG. */
static void conn_probe_cancel_nq(struct TOPO_GROUP_NODE* nq) {
if (!nq) return;
struct route_nat_defer *deferred = nq->connectivity.nat_probe_wait;
if (deferred) {
uasync_cancel_timeout(deferred->instance->ua, deferred->timer);
nq->connectivity.nat_probe_wait = NULL; u_free(deferred);
}
#ifdef UTUN_HAVE_STANDBY
{ struct route_probe_defer* d = (struct route_probe_defer*)nq->connectivity.probe_deferred_wait;
if (d) {

1
src/routing_layer/topo_node.h

@ -100,6 +100,7 @@ struct TOPO_CONNECTIVITY {
uint64_t last_ping_time;
void* probe_list; // принадлежащие узлу контексты текущих проб
void* probe_deferred_wait; /* контекст отложенной пробы (standby_wait, Android) */
void* nat_probe_wait; /* контекст таймера: NAT сохраняет холодный ingress перед фоновыми ping */
};
#define PING_TTL_TB (86400ULL * 10000ULL)

Loading…
Cancel
Save