|
|
|
|
@ -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) { |
|
|
|
|
|