Browse Source

topo_group: узлы меняются только по BGP (NODEINFO/WITHDRAW), удаление по link down через BGP-коллбэк

v2
evgeny 4 weeks ago
parent
commit
1a88ea88a8
  1. 67
      src/routing_layer/topo_group.c

67
src/routing_layer/topo_group.c

@ -213,45 +213,6 @@ static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
// Init / Destroy / New / Remove conn
// ============================================================================
/* Создать TOPO_GROUP_NODE (если нет) + прямой путь через conn (hop=1). Без BGP.
Используется из topo_group_new_conn (add + init BGP) и из приёма TABLE_REQ (входящий запросил BGP). */
static void topo_group_conn_add_path(struct TOPO_GROUP* group, struct ETCP_CONN* conn, uint64_t node_id) {
if (!group || !conn || !node_id || node_id == group->instance->node_id) return;
/* узел в реестре — иначе загрузить из БД (nodes + node_addresses), чтобы форвардинг мог сериализовать */
{ struct TOPO_GROUPS* groups = group->instance->topo_groups;
struct TOPO_NODE* ni = topo_node_registry_find(groups, node_id);
if (!ni) {
sqlite3* db = group->instance->topo_sqlite_db;
ni = db ? topo_node_sqlite_node_load(db, groups, node_id) : NULL;
if (ni) ni = topo_node_registry_store(groups, ni);
}
}
struct TOPO_GROUP_NODE* nq = topo_node_find_by_id(group, node_id);
if (nq && nq->paths) {
struct ll_entry* pe = nq->paths->head;
while (pe) { if (((struct TOPO_NODEPATH*)pe)->conn == conn) return; pe = pe->next; }
}
if (!nq) {
struct ll_entry* qe = queue_entry_new(sizeof(struct TOPO_GROUP_NODE));
if (!qe) return;
nq = (struct TOPO_GROUP_NODE*)qe;
memset((uint8_t*)nq + sizeof(struct ll_entry), 0, sizeof(*nq) - sizeof(struct ll_entry));
nq->node_id = node_id;
queue_data_put_with_index(group->nodes, &nq->ll);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "node added to group: node=%016llx grp=%016llx type=%u ch=%s (direct)",
(unsigned long long)node_id, (unsigned long long)group->group_id, group->group_type, group->channel_id);
}
uint64_t hop[1] = { node_id };
topo_group_add_path(nq, conn, hop, 1, 0);
nq->conn_presence |= NCONN_DIRECT;
nq->conn_up |= NCONN_DIRECT;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "conn_add_path: node=0x%016llx grp=%016llx ch=%s conn=%s",
(unsigned long long)node_id, (unsigned long long)group->group_id, group->channel_id, conn->log_name);
}
static void topo_group_conn_status(struct ETCP_CONN* conn, int status, void* arg) {
struct TOPO_GROUPS* groups = (struct TOPO_GROUPS*)arg;
if (!conn || !groups) return;
@ -551,21 +512,9 @@ void topo_group_new_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!conn->instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "conn->instance is NULL"); return; }
if (!conn->instance->rt) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "conn->instance->rt is NULL"); return; }
topo_recovery_cancel_for_node(group, conn->peer_node_id);
/* создать узел + прямой путь (сразу, не дожидаясь NODEINFO; дедуп внутри по conn).
Делаем ДО проверки senders_list: conn может уже быть в senders_list (через handle_request_table),
но узел ещё не создан (входящий JOIN_GROUP). */
topo_group_conn_add_path(group, conn, conn->peer_node_id);
{ struct TOPO_GROUP_NODE* peer_nq = topo_node_find_by_id(group, conn->peer_node_id);
if (peer_nq) {
peer_nq->connectivity.last_ping_time = get_time_tb();
if (conn->instance->topo_sqlite_db) topo_node_sqlite_nodeinfo_updated(conn->instance->topo_sqlite_db, conn->peer_node_id);
}
}
/* дедуп: тот же conn стреляет ETCP_CONN_STATUS_UP дважды (UDP-линк, затем TCP-линк).
* Если conn уже в senders_list — не слать повторно TABLE_REQ и не задваивать active_conn_count. */
* Если conn уже в senders_list — повторно не обрабатываем, иначе active_conn_count
* задваивается и переподключение никогда не стартует. */
{ struct ll_entry* se = group->senders_list ? group->senders_list->head : NULL;
while (se) {
if (((struct TOPO_GROUP_CONN_ITEM*)se->data)->conn == conn) {
@ -576,6 +525,15 @@ void topo_group_new_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
}
}
topo_recovery_cancel_for_node(group, conn->peer_node_id);
struct TOPO_GROUP_NODE* peer_nq = topo_node_find_by_id(group, conn->peer_node_id);
if (peer_nq) {
peer_nq->connectivity.last_ping_time = get_time_tb();
peer_nq->conn_presence |= NCONN_DIRECT;
peer_nq->conn_up |= NCONN_DIRECT;
if (conn->instance->topo_sqlite_db) topo_node_sqlite_nodeinfo_updated(conn->instance->topo_sqlite_db, conn->peer_node_id);
}
topo_group_add_to_senders(group, conn);
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "topo_group_new_conn: peer=%016llx group=%016llx type=%d ch=%s", (unsigned long long)conn->peer_node_id, (unsigned long long)group->group_id, group->group_type, group->channel_id);
@ -625,6 +583,9 @@ void topo_group_remove_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
uint64_t wd_src = (key == conn->peer_node_id) ? conn->instance->node_id : conn->peer_node_id;
topo_group_broadcast_withdraw(group, key, wd_src, NULL);
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Removed node %016llx after link down", (unsigned long long)key);
{ struct topo_node_cbk_entry* c = group->node_cbks;
while (c) { c->fn(group, key, TOPO_NODE_EVENT_REMOVE, c->arg); c = c->next; }
}
} else {
nq->conn_up &= ~NCONN_DIRECT;
{ int has_direct = 0; struct ll_entry* pe2 = nq->paths ? nq->paths->head : NULL;

Loading…
Cancel
Save