route redesign + tests

This commit is contained in:
Evgeny committed 2026-03-30 18:26:56 +03:00
1 parent be6058c642
commit 9f13cf5459
13 files changed
+524 -324

No files matched your search

+284 -138
View File
@@ -2,11 +2,9 @@
* @file route_bgp.c
* @brief BGP-like обмен маршрутами — исправленная версия под новую route_lib
*/
#include <stdlib.h>
#include <string.h>
#include "../lib/platform_compat.h"
#include "route_node.h"
#include "route_lib.h"
#include "route_bgp.h"
@@ -19,84 +17,84 @@
#include "../lib/debug_config.h"
#include "../lib/mem.h"
// ============================================================================
// Вспомогательные функции
// ============================================================================
// ============================================================================
// Отправка (только preferred_conn + hop_list)
// ============================================================================
/* Old route packet sending function removed - using NODEINFO only now */
static void route_bgp_send_table_request(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
if (!bgp || !conn) return;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending table request to %s", conn->log_name);
route_bgp_send_nodeinfo(bgp, conn);
}
/* Old full table sending removed - now using NODEINFO */
// ============================================================================
// Broadcast / Withdraw
// ============================================================================
/* Old broadcast route function removed - using NODEINFO broadcast now */
static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id,
struct ETCP_CONN* exclude) {
if (!bgp) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_broadcast_withdraw: bgp is NULL");
static void route_bgp_send_table_request(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn)
{
if (!bgp || !conn) {
return;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_broadcast_withdraw: node_id=%016llx exclude=%p",
(unsigned long long)node_id, (void*)exclude);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending table request to %s", conn->log_name);
struct BGP_ROUTE_REQUEST* req = u_calloc(1, sizeof(struct BGP_ROUTE_REQUEST));
if (!req) return;
req->cmd = ETCP_ID_ROUTE_ENTRY;
req->subcmd = ROUTE_SUBCMD_REQUEST_TABLE;
struct ll_entry* e = queue_entry_new(0);
if (!e) {
u_free(req);
return;
}
e->dgram = (uint8_t*)req;
e->len = sizeof(struct BGP_ROUTE_REQUEST);
etcp_send(conn, e);
}
/* Old full table sending removed - now using NODEINFO broadcast now */
// ============================================================================
// Broadcast / Withdraw: node_id - удаляемый узел, wd_source - от кого получена команда удалить
// ============================================================================
static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id, uint64_t wd_source, struct ETCP_CONN* exclude)
{
if (!bgp) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "bgp is NULL");
return;
}
struct NODEINFO_Q* nq = route_bgp_get_node(bgp, node_id);
if (!nq) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "node not found");
return;
}
if (wd_source != 0 && nq->paths) {
}
if (nq->paths && queue_entry_count(nq->paths) == 0) {
if (bgp->instance && bgp->instance->rt) route_delete(bgp->instance->rt, nq);
nq->dirty = 1;
}
struct BGP_WITHDRAW_PACKET* pkt = u_calloc(1, sizeof(struct BGP_WITHDRAW_PACKET));
if (!pkt) return;
pkt->cmd = ETCP_ID_ROUTE_ENTRY;
pkt->subcmd = ROUTE_SUBCMD_WITHDRAW;
pkt->node_id = htobe64(node_id);
struct ll_entry* send_entry = queue_entry_new(0);
if (!send_entry) { u_free(pkt); return; }
send_entry->dgram = (uint8_t*)pkt;
send_entry->len = sizeof(struct BGP_WITHDRAW_PACKET);
struct ll_entry* e = bgp->senders_list->head;
pkt->wd_source = htobe64(wd_source);
struct ll_entry* e = bgp->senders_list ? bgp->senders_list->head : NULL;
while (e) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data;
if (item->conn != exclude) {
if (item && item->conn && item->conn != exclude) {
struct ll_entry* copy = queue_entry_new(0);
if (copy) {
copy->dgram = u_malloc(send_entry->len);
memcpy(copy->dgram, send_entry->dgram, send_entry->len);
copy->len = send_entry->len;
copy->dgram = u_malloc(sizeof(*pkt));
if (copy->dgram) memcpy(copy->dgram, pkt, sizeof(*pkt));
copy->len = sizeof(*pkt);
etcp_send(item->conn, copy);
}
}
e = e->next;
}
queue_entry_free(send_entry);
u_free(pkt);
}
// ============================================================================
// Callback на изменение таблицы (insert / update / delete)
// ============================================================================
/* Old route change callback removed - now using NODEINFO updates */
// ============================================================================
// Приём пакетов
// ============================================================================
static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry) {
static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry)
{
if (!from_conn || !entry || entry->len < 2) {
if (entry) {
queue_dgram_free(entry);
@@ -108,7 +106,7 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
struct UTUN_INSTANCE* instance = from_conn->instance;
if (!instance || !instance->bgp) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_receive_cbk: invalid instance/bgp");
queue_dgram_free(entry);
queue_dgram_free(entry);
queue_entry_free(entry);
return;
}
@@ -119,21 +117,21 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
uint8_t subcmd = data[1];
if (cmd != ETCP_ID_ROUTE_ENTRY) {
queue_dgram_free(entry);
queue_dgram_free(entry);
queue_entry_free(entry);
return;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Received BGP packet from %s, subcmd=%d, len=%zu",
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Received BGP packet from %s, subcmd=%d, len=%zu",
from_conn->log_name, subcmd, entry->len);
if (subcmd == ROUTE_SUBCMD_NODEINFO) {
route_bgp_process_nodeinfo(bgp, from_conn, data, entry->len);
} else if (subcmd == ROUTE_SUBCMD_WITHDRAW) {
route_bgp_process_withdraw(bgp, data, entry->len);
route_bgp_process_withdraw(bgp, from_conn, data, entry->len);
} else if (subcmd == ROUTE_SUBCMD_REQUEST_TABLE) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Received table request from %s", from_conn->log_name);
route_bgp_send_nodeinfo(bgp, from_conn);
route_bgp_send_nodeinfo(bgp->local_node, from_conn); /* всегда отправляем свой local_node */
}
queue_dgram_free(entry);
@@ -146,7 +144,8 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
// ============================================================================
// Callback для готовности ETCP соединения - отправляет маршруты
static void route_bgp_on_conn_up(struct ETCP_CONN* conn, void* arg) {
static void route_bgp_on_conn_up(struct ETCP_CONN* conn, void* arg)
{
(void)arg;
if (conn && conn->instance && conn->instance->bgp) {
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "BGP ON UP %s", conn->log_name);
@@ -155,7 +154,8 @@ static void route_bgp_on_conn_up(struct ETCP_CONN* conn, void* arg) {
}
}
static void route_bgp_on_conn_down(struct ETCP_CONN* conn, void* arg) {
static void route_bgp_on_conn_down(struct ETCP_CONN* conn, void* arg)
{
(void)arg;
if (conn && conn->instance && conn->instance->bgp) {
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "BGP ON DOWN %s", conn->log_name);
@@ -165,7 +165,8 @@ static void route_bgp_on_conn_down(struct ETCP_CONN* conn, void* arg) {
}
// Callback для новых ETCP соединений - устанавливает ready callback
static void route_bgp_etcp_conn_cbk(struct ETCP_CONN* conn, void* arg) {
static void route_bgp_etcp_conn_cbk(struct ETCP_CONN* conn, void* arg)
{
(void)arg;
if (conn && conn->instance && conn->instance->bgp) {
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "BGP SET CBKS %s", conn->log_name);
@@ -175,13 +176,15 @@ static void route_bgp_etcp_conn_cbk(struct ETCP_CONN* conn, void* arg) {
}
}
struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) {
struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance)
{
if (!instance) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: instance is NULL");
return NULL;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_init: node_id=%016llx", (unsigned long long)instance->node_id);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_init: node_id=%016llx",
(unsigned long long)instance->node_id);
struct ROUTE_BGP* bgp = u_calloc(1, sizeof(struct ROUTE_BGP));
if (!bgp) {
@@ -207,10 +210,27 @@ struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) {
return NULL;
}
// Build initial my_nodeinfo
if (route_bgp_build_my_nodeinfo(instance, bgp) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: build_my_nodeinfo failed");
int vc = 0;
struct CFG_ROUTE_ENTRY* s = instance->config->my_subnets;
while (s) {
if (s->ip.family == AF_INET) vc++;
s = s->next;
}
size_t d = vc * sizeof(struct NODEINFO_IPV4_SUBNET);
bgp->local_node = u_calloc(1, sizeof(struct NODEINFO_Q) + d);
if (!bgp->local_node) {
queue_free(bgp->nodes);
queue_free(bgp->senders_list);
u_free(bgp);
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: local_node alloc failed");
return NULL;
}
bgp->local_node->node.node_id = htobe64(instance->node_id);
bgp->local_node->node.hop_count = 0;
bgp->local_node->node.ver = 1;
bgp->local_node->dirty = 0;
route_bgp_update_my_nodeinfo(instance, bgp);
etcp_bind(instance, ETCP_ID_ROUTE_ENTRY, route_bgp_receive_cbk);
@@ -221,7 +241,8 @@ struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) {
return bgp;
}
void route_bgp_destroy(struct UTUN_INSTANCE* instance) {
void route_bgp_destroy(struct UTUN_INSTANCE* instance)
{
if (!instance) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_destroy: instance is NULL");
return;
@@ -231,32 +252,34 @@ void route_bgp_destroy(struct UTUN_INSTANCE* instance) {
return;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_destroy: node_id=%016llx", (unsigned long long)instance->node_id);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_destroy: node_id=%016llx",
(unsigned long long)instance->node_id);
etcp_unbind(instance, ETCP_ID_ROUTE_ENTRY);
// очистка списка senders
struct ll_entry* e;
while ((e = queue_data_get(instance->bgp->senders_list)) != NULL) {
queue_entry_free(e);
}
queue_free(instance->bgp->senders_list);
// очистка nodes
if (instance->bgp->nodes) {
queue_free(instance->bgp->nodes);
if (instance->bgp->local_node) {
if (instance->bgp->local_node->paths) {
queue_free(instance->bgp->local_node->paths);
}
u_free(instance->bgp->local_node);
}
// Free my_nodeinfo
if (instance->bgp->my_nodeinfo) {
u_free(instance->bgp->my_nodeinfo);
if (instance->bgp->nodes) {
queue_free(instance->bgp->nodes);
}
u_free(instance->bgp);
instance->bgp = NULL;
}
void route_bgp_new_conn(struct ETCP_CONN* conn) {
void route_bgp_new_conn(struct ETCP_CONN* conn)
{
if (!conn) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn is NULL");
return;
@@ -275,7 +298,6 @@ void route_bgp_new_conn(struct ETCP_CONN* conn) {
}
struct ROUTE_BGP* bgp = conn->instance->bgp;
struct ROUTE_TABLE* rt = conn->instance->rt;
// === 1. Проверяем, уже есть ли это соединение в списке ===
bool already_exists = false;
@@ -292,11 +314,11 @@ void route_bgp_new_conn(struct ETCP_CONN* conn) {
// === 2. Если нет — добавляем (только один раз) ===
if (!already_exists) {
struct ll_entry* item_entry = queue_entry_new(sizeof(struct ROUTE_BGP_CONN_ITEM));
if (!item_entry) return;
if (!item_entry) {
return;
}
((struct ROUTE_BGP_CONN_ITEM*)item_entry->data)->conn = conn;
queue_data_put(bgp->senders_list, item_entry);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "New connection added to senders_list");
}
@@ -304,7 +326,8 @@ void route_bgp_new_conn(struct ETCP_CONN* conn) {
route_bgp_send_table_request(bgp, conn);
}
void route_bgp_remove_conn(struct ETCP_CONN* conn) {
void route_bgp_remove_conn(struct ETCP_CONN* conn)
{
if (!conn) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: conn is NULL");
return;
@@ -314,8 +337,9 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) {
return;
}
// SAFETY: проверяем что conn ещё есть в senders_list
struct ROUTE_BGP* bgp = conn->instance->bgp;
// SAFETY: проверяем что conn ещё есть в senders_list
bool found_in_list = false;
struct ll_entry* e = bgp->senders_list->head;
while (e) {
@@ -326,13 +350,14 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) {
}
e = e->next;
}
if (!found_in_list) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: conn already removed or not in list, skipping");
return;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: peer=%016llx", (unsigned long long)conn->peer_node_id);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: peer=%016llx",
(unsigned long long)conn->peer_node_id);
struct ROUTE_TABLE* rt = conn->instance->rt;
@@ -341,7 +366,7 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) {
bool need_withdraw = false;
struct ll_entry* node_entry = bgp->nodes ? bgp->nodes->head : NULL;
while (node_entry) {
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)node_entry->data;
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)node_entry;
if (route_bgp_remove_path(nq, conn) == 1) {
need_withdraw = true;
if (rt) {
@@ -364,37 +389,96 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) {
}
if (need_withdraw) {
route_bgp_send_withdraw(bgp, conn->peer_node_id);
route_bgp_broadcast_withdraw(bgp, conn->peer_node_id, conn->instance->node_id, NULL);
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Connection removed, paths updated");
}
/* ================================================
* NEW NODEINFO BASED IMPLEMENTATION
* ================================================ */
struct NODEINFO_Q* route_bgp_get_node(struct ROUTE_BGP* bgp, uint64_t node_id) {
if (!bgp || !bgp->nodes) return NULL;
struct NODEINFO_Q* route_bgp_get_node(struct ROUTE_BGP* bgp, uint64_t node_id)
{
if (!bgp || !bgp->nodes) {
return NULL;
}
uint64_t key = htobe64(node_id);
struct ll_entry* e = queue_find_data_by_index(bgp->nodes, &key, 8);
return e ? (struct NODEINFO_Q*)e->data : NULL;
return e ? (struct NODEINFO_Q*)e : NULL;
}
int route_bgp_add_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn) {
if (!nq || !conn) return -1;
DEBUG_TRACE(DEBUG_CATEGORY_BGP, "Added path for node %016llx via conn %s",
(unsigned long long)nq->node.node_id, conn->log_name);
int route_bgp_add_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count)
{
if (!nq || !conn || hop_count > MAX_HOPS || !hop_list) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "add_path: invalid args");
return -1;
}
if (!nq->paths) {
nq->paths = queue_new(conn->instance->ua, 32, "node_paths");
if (!nq->paths) return -1;
}
size_t hop_size = hop_count * 8;
size_t path_size = sizeof(struct NODEINFO_PATH) - sizeof(struct ll_entry) + hop_size;
struct ll_entry* pe = queue_entry_new(path_size);
if (!pe) return -1;
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)pe;
path->conn = conn;
path->hop_count = hop_count;
uint64_t* stored = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH));
memcpy(stored, hop_list, hop_size);
queue_data_put(nq->paths, pe);
DEBUG_TRACE(DEBUG_CATEGORY_BGP, "Added path for node %016llx via conn %s with %d hops", (unsigned long long)nq->node.node_id, conn->log_name, hop_count);
return 0;
}
int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn) {
if (!nq || !conn || !nq->paths) return -1;
int route_bgp_remove_path_by_hop(struct NODEINFO_Q* nq, uint64_t wd_source) {
if (!nq || !nq->paths) return 0;
int removed = 0;
struct ll_entry* e = nq->paths->head;
while (e) {
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e;
// parse hoplist in dyn after hop_count (after fixed PATH)
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH));
bool has_wd = false;
for (uint8_t i = 0; i < path->hop_count; i++) {
if (hop[i] == wd_source) {
has_wd = true;
break;
}
}
if (has_wd) {
struct ll_entry* next = e->next;
queue_remove_data(nq->paths, e);
queue_entry_free(e);
removed++;
e = next;
continue;
}
e = e->next;
}
if (removed > 0 && nq->paths && queue_entry_count(nq->paths) == 0) {
queue_free(nq->paths);
nq->paths = NULL;
return 1; // unreachable
}
return removed;
}
int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn)
{
if (!nq || !conn || !nq->paths) {
return -1;
}
// Remove conn from paths queue
struct ll_entry* e = nq->paths->head;
while (e) {
if (e->data == (void*)conn) {
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e;
if (path->conn == conn) {
queue_remove_data(nq->paths, e);
queue_entry_free(e);
break;
@@ -403,8 +487,7 @@ int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn) {
}
int remaining = nq->paths ? queue_entry_count(nq->paths) : 0;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Removed path for node %016llx via %s, remaining paths: %d",
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Removed path for node %016llx via %s, remaining paths: %d",
(unsigned long long)nq->node.node_id, conn->log_name, remaining);
// If no paths left - node is unreachable
@@ -415,20 +498,22 @@ int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn) {
}
return 1; // signal that node became unreachable
}
return 0;
}
int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from,
const uint8_t* data, size_t len) {
if (!bgp || !from || len < sizeof(struct BGP_NODEINFO_PACKET)) return -1;
int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from,
const uint8_t* data, size_t len)
{
if (!bgp || !from || len < sizeof(struct BGP_NODEINFO_PACKET)) {
return -1;
}
struct BGP_NODEINFO_PACKET* pkt = (struct BGP_NODEINFO_PACKET*)data;
struct NODEINFO* ni = &pkt->node;
uint64_t node_id = be64toh(ni->node_id);
if (ni->hop_count >= MAX_HOPS) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "NODEINFO from %s dropped: too many hops (%d)",
DEBUG_WARN(DEBUG_CATEGORY_BGP, "NODEINFO from %s dropped: too many hops (%d)",
from->log_name, ni->hop_count);
return -1;
}
@@ -437,97 +522,158 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from,
uint8_t new_ver = ni->ver;
if (existing && existing->last_ver >= new_ver) {
DEBUG_TRACE(DEBUG_CATEGORY_BGP, "NODEINFO from %s ignored (old ver %d <= %d)",
DEBUG_TRACE(DEBUG_CATEGORY_BGP, "NODEINFO from %s ignored (old ver %d <= %d)",
from->log_name, new_ver, existing->last_ver);
return 0;
}
if (!existing) {
struct ll_entry* entry = queue_entry_new(sizeof(struct NODEINFO_Q));
if (!entry) return -1;
existing = (struct NODEINFO_Q*)entry->data;
size_t dyn = len - sizeof(struct BGP_NODEINFO_PACKET) + 8;
struct ll_entry* entry = queue_entry_new(sizeof(struct NODEINFO_Q) + dyn);
if (!entry) {
return -1;
}
existing = (struct NODEINFO_Q*)entry;
existing->paths = queue_new(bgp->instance->ua, 32, "node_paths");
queue_data_put(bgp->nodes, entry);
queue_data_put_with_index(bgp->nodes, entry, offsetof(struct NODEINFO_Q, node.node_id), 8);
}
memcpy(&existing->node, ni, sizeof(struct NODEINFO));
existing->last_ver = new_ver;
route_bgp_add_path(existing, from);
uint8_t* dyn_dest = (uint8_t*)&existing->node + sizeof(struct NODEINFO);
const uint8_t* dyn_src = data + sizeof(struct BGP_NODEINFO_PACKET);
size_t dyn_size = len - sizeof(struct BGP_NODEINFO_PACKET);
memcpy(dyn_dest, dyn_src, dyn_size);
uint8_t* hop_dest = dyn_dest + dyn_size;
uint64_t sender = htobe64(from->peer_node_id);
memcpy(hop_dest, &sender, 8);
existing->node.hop_count = ni->hop_count + 1;
if (ni->hop_count > 0) {
route_bgp_add_path(existing, from, (uint64_t*)hop_dest, existing->node.hop_count);
}
if (bgp->instance->rt) {
route_insert(bgp->instance->rt, existing);
}
// Пересылаем дальше (увеличиваем hop_count)
if (ni->hop_count < MAX_HOPS - 1) {
ni->hop_count++;
route_bgp_broadcast_nodeinfo(bgp, from);
ni->hop_count--; // возвращаем назад
ni->hop_count--;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Processed NODEINFO from %s (node=%016llx, ver=%d, paths=%d)",
from->log_name, (unsigned long long)node_id, new_ver,
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Processed NODEINFO from %s (node=%016llx,ver=%d,paths=%d)",
from->log_name, (unsigned long long)node_id, new_ver,
existing->paths ? queue_entry_count(existing->paths) : 0);
return 0;
}
int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, const uint8_t* data, size_t len) {
if (!bgp || len < sizeof(struct BGP_WITHDRAW_PACKET)) return -1;
int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len) {
if (!bgp || len < sizeof(struct BGP_WITHDRAW_PACKET)) {
return -1;
}
struct BGP_WITHDRAW_PACKET* wp = (struct BGP_WITHDRAW_PACKET*)data;
uint64_t node_id = be64toh(wp->node_id);
uint64_t wd_source = be64toh(wp->wd_source);
struct NODEINFO_Q* nq = route_bgp_get_node(bgp, node_id);
if (nq) {
if (!nq) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "node not found");
return 0;
}
int ret=route_bgp_remove_path_by_hop(nq, wd_source);
if (ret>0) {
if (bgp->instance && bgp->instance->rt) {
route_delete(bgp->instance->rt, nq);
}
if (nq->paths) {
queue_free(nq->paths);
}
// TODO: remove from nodes queue
uint64_t key = htobe64(node_id);
struct ll_entry* entry = queue_find_data_by_index(bgp->nodes, &key, 8);
if (entry) {
queue_remove_data(bgp->nodes, entry);
queue_entry_free(entry);
}
nq->dirty = 1;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Removed node %016llx after WITHDRAW", (unsigned long long)node_id);
route_bgp_broadcast_withdraw(bgp, node_id, wd_source, sender);
}
route_bgp_broadcast_withdraw(bgp, node_id, NULL);
return 0;
}
void route_bgp_send_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
if (!bgp || !conn || !bgp->my_nodeinfo) return;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending NODEINFO to %s", conn->log_name);
struct ll_entry* entry = queue_entry_new(0);
if (!entry) return;
entry->dgram = u_malloc(bgp->my_nodeinfo_size);
if (!entry->dgram) {
queue_entry_free(entry);
/**
* @brief Отправка NODEINFO-пакета (всегда отправляем local_node)
* Сигнатура соответствует объявлению в route_bgp.h
*/
void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn)
{
if (!node || !conn) {
return;
}
memcpy(entry->dgram, bgp->my_nodeinfo, bgp->my_nodeinfo_size);
entry->len = bgp->my_nodeinfo_size;
etcp_send(conn, entry);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending NODEINFO to %s", conn->log_name);
size_t nl = node->node.node_name_len;
size_t s4 = node->node.local_v4_sockets;
size_t s6 = node->node.local_v6_sockets;
size_t sub4 = node->node.local_v4_subnets;
size_t sub6 = node->node.local_v6_subnets;
size_t t = node->node.tranzit_nodes;
size_t h = node->node.hop_count;
size_t dyn = nl +
s4 * sizeof(struct NODEINFO_IPV4_SOCKET) +
s6 * sizeof(struct NODEINFO_IPV6_SOCKET) +
sub4 * sizeof(struct NODEINFO_IPV4_SUBNET) +
sub6 * sizeof(struct NODEINFO_IPV6_SUBNET) +
t * 8 + h * 8;
size_t ps = sizeof(struct BGP_NODEINFO_PACKET) + dyn;
uint8_t* p = u_malloc(ps);
if (!p) {
return;
}
p[0] = ETCP_ID_ROUTE_ENTRY;
p[1] = ROUTE_SUBCMD_NODEINFO;
memcpy(p + 2, &node->node, sizeof(struct NODEINFO));
uint8_t* ds = (uint8_t*)&node->node + sizeof(struct NODEINFO);
memcpy(p + sizeof(struct BGP_NODEINFO_PACKET), ds, dyn);
struct ll_entry* e = queue_entry_new(0);
if (!e) {
u_free(p);
return;
}
e->dgram = p;
e->len = ps;
etcp_send(conn, e);
}
void route_bgp_broadcast_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* exclude) {
if (!bgp) return;
if (!bgp) {
return;
}
DEBUG_TRACE(DEBUG_CATEGORY_BGP, "Broadcasting NODEINFO");
struct ll_entry* e = bgp->senders_list ? bgp->senders_list->head : NULL;
while (e) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data;
if (item->conn && item->conn != exclude) {
route_bgp_send_nodeinfo(bgp, item->conn);
route_bgp_send_nodeinfo(bgp->local_node, item->conn);
}
e = e->next;
}
}
void route_bgp_send_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id) {
if (!bgp) return;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending WITHDRAW for node %016llx", (unsigned long long)node_id);
}
+81 -11
View File
@@ -35,7 +35,8 @@ struct BGP_NODEINFO_PACKET {
struct BGP_WITHDRAW_PACKET {
uint8_t cmd;
uint8_t subcmd;
uint64_t node_id;
uint64_t node_id; // удаляемый узел (который стал недоступен)
uint64_t wd_source; // узел который инициировал withdraw (при удалении он должен быть в hoplist или = current node_id)
} __attribute__((packed));
/**
@@ -53,27 +54,96 @@ struct ROUTE_BGP_CONN_ITEM {
struct ROUTE_BGP {
struct UTUN_INSTANCE* instance;
struct BGP_NODEINFO_PACKET* my_nodeinfo; // собранный пакет для отправки
uint16_t my_nodeinfo_size;
struct ll_queue* senders_list; // список активных соединений
struct ll_queue* nodes; // NODEINFO_Q с hash-таблицей по node_id
struct ll_queue* senders_list;
struct ll_queue* nodes;
struct NODEINFO_Q* local_node;
};
/**
* @brief Инициализирует модуль BGP маршрутизации.
*
* Создает очереди, local_node из подсетей конфига, привязывает к ETCP_ID_ROUTE_ENTRY,
* устанавливает коллбеки new_conn для on_up/on_down.
*
* @param instance экземпляр utun с node_id и конфигом
* @return ROUTE_BGP или NULL при ошибке
*/
struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance);
/**
* @brief Освобождает ресурсы BGP (очереди, local_node, снимает привязку ETCP).
*
* @param instance экземпляр utun
*/
void route_bgp_destroy(struct UTUN_INSTANCE* instance);
/**
* @brief Добавляет conn в senders_list (если нет), отправляет запрос таблицы (nodeinfo).
*
* Вызывается при ETCP on_up.
*/
void route_bgp_new_conn(struct ETCP_CONN* conn);
/**
* @brief Удаляет conn из senders_list, очищает paths во всех nodes, отправляет withdraw если node unreachable.
*
* Вызывается при ETCP on_down.
*/
void route_bgp_remove_conn(struct ETCP_CONN* conn);
/* Новые функции для работы с NODEINFO */
int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from,
const uint8_t* data, size_t len);
int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, const uint8_t* data, size_t len);
void route_bgp_send_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn);
/**
* @brief Обрабатывает пакет NODEINFO.
*
* Проверка версии, обновление или создание NODEINFO_Q, добавление пути,
* вставка в роутинг, broadcast если не max hops.
*
* @return 0 при успехе
*/
int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, const uint8_t* data, size_t len);
/**
* @brief Обрабатывает WITHDRAW.
*
* Удаляет node из роутинга и nodes, broadcast withdraw.
*
* @return 0 при успехе
*/
int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len);
/**
* @brief Отправляет NODEINFO пакет одному conn (всегда local_node).
*/
void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn);
/**
* @brief Рассылает local_node NODEINFO всем senders_list кроме exclude.
*/
void route_bgp_broadcast_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* exclude);
/**
* @brief Отправляет WITHDRAW для node_id (вызывает broadcast_withdraw).
*/
void route_bgp_send_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id);
/**
* @brief Поиск NODEINFO_Q по node_id через hash в nodes queue.
*
* @return node или NULL
*/
struct NODEINFO_Q* route_bgp_get_node(struct ROUTE_BGP* bgp, uint64_t node_id);
int route_bgp_add_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn);
/**
* @brief Добавляет путь (conn) в paths узла.
*
* @return 0 при успехе
*/
int route_bgp_add_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count);
/**
* @brief Удаляет conn из paths узла.
*
* @return 1 если путей не осталось (unreachable)
*/
int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn);
#endif // ROUTE_BGP_H
+24 -7
View File
@@ -1,9 +1,26 @@
Ключевые изменения в понимании
tranzit_nodes — это динамический список лучших транзитных узлов для данного node.
При conn down:
Находим узел, связанный с этим соединением.
Удаляем конкретный путь (этот транзитный узел) из списка tranzit_nodes.
Если после удаления tranzit_nodes стало пусто (нет активных путей) → узел считается недоступным → route_delete() + отправка WITHDRAW.
При получении NODEINFO — добавляем информацию о транзитных узлах (их может быть несколько).
При получении WITHDRAW — удаляем узел/маршруты и распространяем дальше.
paths
route_bgp_process_nodeinfo(bgp, from_conn, data, entry->len):
проверяет текущую версию nodeinfo, если совпадает - только bgp_update local nodelist
если версия новая или нет узла - spread:
bgp_update local nodelist
realloc: добавляет next hop: hoplist += prev_node_id, hop_count++
bgp_spread
1. функция распространения маршрута
bgp_spread(struct ROUTE_BGP bgp, struct NODEINFO* n)
send to:
- все подключения, если не найден uid подключения в hoplist
bgp_update local nodelist:
- обновляем саму node
- удалеям conn где lash hop=prev_node_id
- добавляем новый conn с новым hoplist
2. withdraw:
bgp_withdraw(struct ROUTE_BGP bgp, uint64_t node_to_del, uint64_t wd_source) - wd_source это узел который захотел withdraw.
- находим у себя node to del. удаляем если в hoplist найден wd_node (или мы = wd_node)
если удалили - распространяем по всем линкам с этими же аргументами
+3 -3
View File
@@ -138,7 +138,7 @@ void route_table_destroy(struct ROUTE_TABLE *table) {
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "route_table_destroy: count=%zu", table->count);
// v_node_info — внешний объект (BGP_NODEINFO_Q), память им не управляем
// v_node_info — внешний объект (NODEINFO_Q), память им не управляем
u_free(table->dynamic_subnets);
u_free(table->local_subnets);
u_free(table->entries);
@@ -147,7 +147,7 @@ void route_table_destroy(struct ROUTE_TABLE *table) {
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing table destroyed");
}
bool route_insert(struct ROUTE_TABLE *table, struct BGP_NODEINFO_Q *node) {
bool route_insert(struct ROUTE_TABLE *table, struct NODEINFO_Q *node) {
if (!table || !node) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_insert: invalid arguments");
return false;
@@ -218,7 +218,7 @@ bool route_insert(struct ROUTE_TABLE *table, struct BGP_NODEINFO_Q *node) {
return true;
}
void route_delete(struct ROUTE_TABLE *table, struct BGP_NODEINFO_Q *node) {
void route_delete(struct ROUTE_TABLE *table, struct NODEINFO_Q *node) {
if (!table || !node) return;
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "route_delete: removing all routes for node_info=%p", (void*)node);
+4 -3
View File
@@ -10,6 +10,7 @@
struct ETCP_CONNECTIONS;
struct ROUTE_TABLE;
struct ROUTE_ENTRY;
struct NODEINFO_Q;
/**
* @brief Флаги узла
@@ -28,7 +29,7 @@ typedef enum {
struct ROUTE_ENTRY {
uint32_t network; // Сетевой адрес (big-endian)
uint8_t prefix_length; // Длина префикса подсети
struct BGP_NODEINFO_Q* v_node_info; // узел владелец этих маршрутов. null если - локальный маршрут.
struct NODEINFO_Q* v_node_info; // узел владелец этих маршрутов. null если - локальный маршрут.
};
/**
@@ -73,7 +74,7 @@ void route_table_destroy(struct ROUTE_TABLE *table);
*
* @return true если вставка/обновление успешно
*/
bool route_insert(struct ROUTE_TABLE *table, struct BGP_NODEINFO_Q *node);
bool route_insert(struct ROUTE_TABLE *table, struct NODEINFO_Q *node);
/**
* @brief Удаляет все записи из таблицы маршрутизации для указанного узла
@@ -81,7 +82,7 @@ bool route_insert(struct ROUTE_TABLE *table, struct BGP_NODEINFO_Q *node);
* @param table Указатель на таблицу маршрутизации
* @param node узел, все маршруты которого нужно удалить
*/
void route_delete(struct ROUTE_TABLE *table, struct BGP_NODEINFO_Q *node);
void route_delete(struct ROUTE_TABLE *table, struct NODEINFO_Q *node);
/**
* @brief Выполняет поиск маршрута для заданного IP-адреса
+69 -96
View File
@@ -12,103 +12,7 @@
#include "route_bgp.h"
#include "etcp_debug.h"
// Build MY_NODEINFO packet for this instance
int route_bgp_build_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp) {
if (!instance || !bgp) return -1;
// Count IPv4 sockets
int v4_socket_count = 0;
struct ETCP_SOCKET* sock = instance->etcp_sockets;
while (sock) {
if (sock->local_addr.ss_family == AF_INET) {
v4_socket_count++;
}
sock = sock->next;
}
// Count IPv4 routes (my_subnets)
int v4_route_count = 0;
struct CFG_ROUTE_ENTRY* subnet = instance->config->my_subnets;
while (subnet) {
if (subnet->ip.family == AF_INET) {
v4_route_count++;
}
subnet = subnet->next;
}
// Get name length
size_t name_len = strlen(instance->name);
// Calculate total size
size_t pkt_size = sizeof(struct BGP_NODEINFO_PACKET)
+ name_len
+ v4_socket_count * sizeof(struct NODEINFO_IPV4_SOCKET)
+ v4_route_count * sizeof(struct NODEINFO_IPV4_SUBNET);
// Allocate
struct BGP_NODEINFO_PACKET* pkt = u_malloc(pkt_size);
if (!pkt) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_build_my_nodeinfo: malloc failed");
return -1;
}
// Fill fixed fields
pkt->cmd = ETCP_ID_ROUTE_ENTRY;
pkt->subcmd = ROUTE_SUBCMD_NODEINFO;
pkt->node.node_id = htobe64(instance->node_id);
pkt->node.ver = bgp->my_nodeinfo ? bgp->my_nodeinfo->node.ver + 1 : 1;
memcpy(pkt->node.public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE);
pkt->node.node_name_len = (uint8_t)name_len;
pkt->node.local_v4_sockets = (uint8_t)v4_socket_count;
pkt->node.local_v6_sockets = 0;
pkt->node.local_v4_subnets = (uint8_t)v4_route_count;
pkt->node.local_v6_subnets = 0;
pkt->node.tranzit_nodes = 0;
pkt->node.hop_count = 0;
// Fill variable data
uint8_t* ptr = (uint8_t*)pkt + sizeof(struct BGP_NODEINFO_PACKET);
// Name
if (name_len > 0) {
memcpy(ptr, instance->name, name_len);
ptr += name_len;
}
// IPv4 sockets
struct NODEINFO_IPV4_SOCKET* sock_arr = (struct NODEINFO_IPV4_SOCKET*)ptr;
sock = instance->etcp_sockets;
while (sock) {
if (sock->local_addr.ss_family == AF_INET) {
struct sockaddr_in* in = (struct sockaddr_in*)&sock->local_addr;
memcpy(sock_arr->addr, &in->sin_addr, 4);
sock_arr->port = in->sin_port;
sock_arr++;
}
sock = sock->next;
}
ptr = (uint8_t*)sock_arr;
// IPv4 routes
struct NODEINFO_IPV4_SUBNET* route_arr = (struct NODEINFO_IPV4_SUBNET*)ptr;
subnet = instance->config->my_subnets;
while (subnet) {
if (subnet->ip.family == AF_INET) {
memcpy(route_arr->addr, &subnet->ip.addr.v4, 4);
route_arr->prefix_length = subnet->netmask;
route_arr++;
}
subnet = subnet->next;
}
bgp->my_nodeinfo = pkt;
bgp->my_nodeinfo_size = pkt_size;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Built my_nodeinfo: name='%s', v4_sockets=%d, v4_routes=%d",
instance->name, v4_socket_count, v4_route_count);
return 0;
}
/**
* @brief Получает указатель на массив IPv4-подсетей узла (без malloc/копирования).
@@ -153,3 +57,72 @@ int get_node_routes(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SUBNET *
(unsigned)info->local_v4_subnets, (void*)node);
return (int)info->local_v4_subnets;
}
int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp) {
if (!instance || !bgp) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_update_my_nodeinfo: invalid args");
return -1;
}
if (!bgp->local_node) {
int vc = 0;
struct CFG_ROUTE_ENTRY* s = instance->config->my_subnets;
while (s) {
if (s->ip.family == AF_INET) vc++;
s = s->next;
}
size_t d = vc * sizeof(struct NODEINFO_IPV4_SUBNET);
bgp->local_node = u_calloc(1, sizeof(struct NODEINFO_Q) + d);
if (!bgp->local_node) return -1;
bgp->local_node->node.node_id = htobe64(instance->node_id);
bgp->local_node->node.hop_count = 0;
bgp->local_node->node.ver = 1;
bgp->local_node->dirty = 1;
bgp->local_node->last_ver = 1;
bgp->local_node->node.local_v4_subnets = vc;
}
int vc = 0;
struct CFG_ROUTE_ENTRY* s = instance->config->my_subnets;
while (s) {
if (s->ip.family == AF_INET) vc++;
s = s->next;
}
int changed = (vc != (int)bgp->local_node->node.local_v4_subnets);
if (!changed && vc > 0) {
uint8_t* current = (uint8_t*)&bgp->local_node->node + sizeof(struct NODEINFO);
struct NODEINFO_IPV4_SUBNET* ra = (struct NODEINFO_IPV4_SUBNET*)current;
s = instance->config->my_subnets;
bool same = true;
while (s) {
if (s->ip.family == AF_INET) {
if (memcmp(ra->addr, &s->ip.addr.v4, 4) != 0 || ra->prefix_length != s->netmask) {
same = false;
break;
}
ra++;
}
s = s->next;
}
changed = !same;
}
if (changed) {
uint8_t oldv = bgp->local_node->node.ver;
bgp->local_node->node.ver = ((oldv + 1) % 255) + 1;
bgp->local_node->node.local_v4_subnets = vc;
bgp->local_node->dirty = 1;
bgp->local_node->last_ver = bgp->local_node->node.ver;
uint8_t* dp = (uint8_t*)&bgp->local_node->node + sizeof(struct NODEINFO);
struct NODEINFO_IPV4_SUBNET* ra = (struct NODEINFO_IPV4_SUBNET*)dp;
s = instance->config->my_subnets;
while (s) {
if (s->ip.family == AF_INET) {
memcpy(ra->addr, &s->ip.addr.v4, 4);
ra->prefix_length = s->netmask;
ra++;
}
s = s->next;
}
} else {
bgp->local_node->last_ver = bgp->local_node->node.ver;
}
return vc;
}
+17 -7
View File
@@ -2,9 +2,12 @@
#define ROUTE_NODE_H
#include <stdint.h>
#include <stddef.h>
#include "../lib/ll_queue.h"
#include "secure_channel.h"
struct ROUTE_BGP;
/**
* @brief Информация о узле
*/
@@ -48,25 +51,32 @@ struct NODEINFO_TRANZIT_NODE {
uint16_t link_q; // меньше - лучше (потери + 1/BW)
} __attribute__((packed));
struct NODEINFO_PATH {
struct ll_entry ll;
struct ETCP_CONN* conn;
uint8_t hop_count; // hop list: маршрут этого path
} __attribute__((packed));
struct NODEINFO_Q {
struct ll_entry ll;
struct NODEINFO node; // KEY = node_id (offset=0 len=8)
struct ll_queue* paths; // список ETCP_CONN* через которые узел доступен
uint32_t last_ver; // последняя обработанная версия NODEINFO
struct ll_queue* paths;
uint8_t dirty;
uint8_t last_ver;
struct NODEINFO node; // Всегда в конце структуры - динамически расширяемый блок
} __attribute__((packed));
/**
* @brief Создаёт/обновляет nodeinfo для собственного узла
*
*
* Собирает данные из локальных структур и упаковывает к структуру (оптимизированную для передачи по сети)
*
*
* @param instance Указатель на UTUN_INSTANCE (с него сбоираем все данные)
* @param bgp здесь будет обновлен struct NODEINFO
* @param bgp Указатель на ROUTE_BGP (для доступа к my_nodeinfo и instance)
* @return количество подсетей (>= 0) или -1 при ошибке
*/
int route_bgp_build_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp);
int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp);
/**
* @brief Получает указатель на массив IPv4-подсетей узла (без malloc/копирования).
+1 -22
View File
@@ -75,28 +75,7 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
}
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing module created");
// Add local subnets from config as static routes
struct CFG_ROUTE_ENTRY* subnet = config->my_subnets;
while (subnet) {
struct ROUTE_ENTRY entry = {0};
entry.network = ntohl(subnet->ip.addr.v4.s_addr);
entry.prefix_length = subnet->netmask;
entry.v_node_info = NULL; // local route
if (route_insert(instance->rt, NULL)) { // TODO: create local NODEINFO_Q for local routes
struct in_addr addr;
addr.s_addr = htonl(entry.network);
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Added local route: %s/%d",
ip_to_str(&addr, AF_INET).str, entry.prefix_length);
} else {
struct in_addr addr;
addr.s_addr = htonl(entry.network);
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Failed to add local route: %s/%d (skipping)",
ip_to_str(&addr, AF_INET).str, entry.prefix_length);
}
subnet = subnet->next;
}
if(instance->bgp&&instance->bgp->local_node){if(route_insert(instance->rt,instance->bgp->local_node)){DEBUG_INFO(DEBUG_CATEGORY_ROUTING,"Added local routes from local_node");}else{DEBUG_WARN(DEBUG_CATEGORY_ROUTING,"Failed to add local routes");}}
// Initialize TUN device if enabled
if (g_tun_init_enabled) {