From 58c637ce1ab94fb9b738c91b85d1ea4ece55ab39 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Thu, 26 Mar 2026 02:31:48 +0300 Subject: [PATCH] add bgp request "send all" --- src/route_bgp.c | 67 +++++++++++++++++++++++++++++++++++++++++++------ src/route_bgp.h | 11 ++++++++ 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/route_bgp.c b/src/route_bgp.c index dde95de..92b3a6e 100644 --- a/src/route_bgp.c +++ b/src/route_bgp.c @@ -80,6 +80,53 @@ static void route_bgp_send_route(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn, } } +static void route_bgp_send_table_request(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) { + if (!bgp || !conn) return; + + struct BGP_ROUTE_REQUEST* req = u_calloc(1, sizeof(struct BGP_ROUTE_REQUEST)); + if (!req) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_send_table_request: alloc failed"); + return; + } + + req->cmd = ETCP_ID_ROUTE_ENTRY; + req->subcmd = ROUTE_SUBCMD_REQUEST_TABLE; + req->version = 0; + + struct ll_entry* send_entry = queue_entry_new(0); + if (!send_entry) { + u_free(req); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_send_table_request: queue_entry_new failed"); + return; + } + + send_entry->dgram = (uint8_t*)req; + send_entry->len = sizeof(struct BGP_ROUTE_REQUEST); + + if (etcp_send(conn, send_entry) != 0) { + queue_entry_free(send_entry); + u_free(req); + DEBUG_WARN(DEBUG_CATEGORY_BGP, "Failed to send table request to %s", conn ? conn->log_name : "unknown"); + } else { + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sent table request to %s (version=0)", conn->log_name); + } +} + +static void route_bgp_send_full_table(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) { + if (!bgp || !conn || !conn->instance || !conn->instance->rt) { + DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_bgp_send_full_table: invalid args"); + return; + } + + struct ROUTE_TABLE* rt = conn->instance->rt; + for (size_t i = 0; i < rt->count; i++) { + route_bgp_send_route(bgp, conn, &rt->entries[i], ROUTE_SUBCMD_ENTRY); + } + + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sent full routing table to %s (version=%u)", + conn->log_name, bgp->table_version); +} + // ============================================================================ // Broadcast / Withdraw // ============================================================================ @@ -282,6 +329,16 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* // === ИСПРАВЛЕНИЕ: поддержка резервных путей === route_remove_path(instance->rt, from_conn, node_id); // callback внутри route_remove_path уже сделает broadcast (withdraw или reroute) + } else if (subcmd == ROUTE_SUBCMD_REQUEST_TABLE) { + if (entry->len < sizeof(struct BGP_ROUTE_REQUEST)) { + queue_dgram_free(entry); queue_entry_free(entry); + return; + } + struct BGP_ROUTE_REQUEST* req = (struct BGP_ROUTE_REQUEST*)data; + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Received table request from %s (version=%u), sending full table", + from_conn->log_name, be32toh(req->version)); + + route_bgp_send_full_table(bgp, from_conn); } queue_dgram_free(entry); @@ -337,6 +394,7 @@ struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) { } bgp->instance = instance; + bgp->table_version = 1; bgp->senders_list = queue_new(instance->ua, 0, "BGP_senders"); if (!bgp->senders_list) { @@ -433,13 +491,8 @@ void route_bgp_new_conn(struct ETCP_CONN* conn) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "New connection added to senders_list"); } - // === 3. В любом случае отправляем полную таблицу (это и нужно при переподключении) === - for (size_t i = 0; i < rt->count; i++) { - route_bgp_send_route(bgp, conn, &rt->entries[i], ROUTE_SUBCMD_ENTRY); - } - - DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sent full routing table to %s (reconnect OK)", - conn->log_name); + // === 3. Отправляем запрос на получение таблицы (обе стороны при on_up) === + route_bgp_send_table_request(bgp, conn); } void route_bgp_remove_conn(struct ETCP_CONN* conn) { diff --git a/src/route_bgp.h b/src/route_bgp.h index 4ded8b5..2bc4590 100644 --- a/src/route_bgp.h +++ b/src/route_bgp.h @@ -13,6 +13,7 @@ #define ROUTE_SUBCMD_ENTRY_REROUTE 0x02 // Reroute (preferred_conn изменился) — пока обрабатывается как ENTRY #define ROUTE_SUBCMD_WITHDRAW 0x03 #define ROUTE_SUBCMD_NODEINFO 0x04 +#define ROUTE_SUBCMD_REQUEST_TABLE 0x05 // запрос полной таблицы (version=0 в запросе) #define MAX_HOPS 16 @@ -39,6 +40,15 @@ struct BGP_WITHDRAW_PACKET { uint64_t node_id; } __attribute__((packed)); +/** + * @brief Пакет запроса полной таблицы + */ +struct BGP_ROUTE_REQUEST { + uint8_t cmd; // ETCP_ID_ROUTE_ENTRY + uint8_t subcmd; // ROUTE_SUBCMD_REQUEST_TABLE + uint32_t version; // 0 для запроса +} __attribute__((packed)); + struct ROUTE_BGP_CONN_ITEM { struct ll_entry ll; struct ETCP_CONN* conn; @@ -47,6 +57,7 @@ struct ROUTE_BGP_CONN_ITEM { struct ROUTE_BGP { struct UTUN_INSTANCE* instance; struct ll_queue* senders_list; + uint32_t table_version; // starts at 1, for future use }; struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance);