Prepare BGP paths before committing received node state
This commit is contained in:
1 parent
ab5c077600
commit
145dd1e5ab
2 files changed
+40
-25
No files matched your search
@@ -52,7 +52,7 @@ static int topo_tx_control(struct TOPO_GROUP_CONN_ITEM* peer, const void* data,
|
||||
static int topo_tx_node(struct TOPO_GROUP_CONN_ITEM* peer, uint64_t node_id);
|
||||
static int topo_tx_table(struct TOPO_GROUP_CONN_ITEM* peer);
|
||||
static int topo_control_wait(struct ETCP_CONN* conn, const void* data, size_t size);
|
||||
static void topo_group_routes_changed(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* node, int event);
|
||||
static int topo_group_routes_changed(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* node, int event);
|
||||
static void topo_group_prune_paths(struct TOPO_GROUP_CONN_ITEM* peer, int all);
|
||||
static void topo_exchange_watch(void* arg);
|
||||
static void topo_tx_fail(struct TOPO_GROUP_CONN_ITEM* peer);
|
||||
@@ -1191,8 +1191,9 @@ int topo_group_remove_path(struct TOPO_GROUP_NODE* nq, struct ETCP_CONN* conn) {
|
||||
}
|
||||
|
||||
/* Одна точка обновления доступности, потребителей и анонсов после изменения путей. */
|
||||
static void topo_group_routes_changed(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* node, int event) {
|
||||
static int topo_group_routes_changed(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* node, int event) {
|
||||
uint64_t id = node->node_id;
|
||||
int result = 0;
|
||||
struct TOPO_NODEPATH* best = topo_node_best_path(node);
|
||||
node->conn_presence &= ~(NCONN_BGP | NCONN_DIRECT);
|
||||
node->conn_up &= ~(NCONN_BGP | NCONN_DIRECT);
|
||||
@@ -1211,9 +1212,11 @@ static void topo_group_routes_changed(struct TOPO_GROUP* group, struct TOPO_GROU
|
||||
(unsigned long long)(best ? best->conn->peer_node_id : 0), best ? best->hop_count : 0);
|
||||
if (group->group_type != TOPO_GROUP_TYPE_CHAT && group->instance->rt) {
|
||||
route_delete(group->instance->rt, node);
|
||||
if (best && node->subnets && node->subnets->v4_subnets && !route_insert(group->instance->rt, node))
|
||||
if (best && node->subnets && node->subnets->v4_subnets && !route_insert(group->instance->rt, node)) {
|
||||
result = -1;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "BGP IPv4 routes rejected: group=%016llx node=%016llx; previous routes removed",
|
||||
(unsigned long long)group->group_id, (unsigned long long)id);
|
||||
}
|
||||
}
|
||||
topo_fire_nodeinfo_cbk(group->instance, group, node);
|
||||
if (!node->paths) {
|
||||
@@ -1226,6 +1229,7 @@ static void topo_group_routes_changed(struct TOPO_GROUP* group, struct TOPO_GROU
|
||||
topo_recovery_changed(group);
|
||||
conn_mgr_routes_changed(group->conn_mgr);
|
||||
multicast_routes_changed(group->instance);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* TABLE_COMPLETE подтверждает только NODEINFO текущего обмена. Сбой обмена
|
||||
@@ -1374,9 +1378,9 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from
|
||||
if (result < 0) return -1;
|
||||
struct TOPO_GROUP_CONN_ITEM* peer = topo_group_peer(group, from->peer_node_id);
|
||||
((struct TOPO_NODEPATH*)nodeinfo1->paths->tail)->exchange = peer ? peer->local_epoch : 0;
|
||||
topo_group_routes_changed(group, nodeinfo1, TOPO_NODE_EVENT_UPDATE);
|
||||
result = topo_group_routes_changed(group, nodeinfo1, TOPO_NODE_EVENT_UPDATE);
|
||||
topo_group_peer_progressed(group, from->peer_node_id);
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
uint64_t incoming_timestamp = new_ni->timestamp;
|
||||
if (!nodeinfo1) {
|
||||
@@ -1391,9 +1395,22 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from
|
||||
nodeinfo1 = (struct TOPO_GROUP_NODE*)qe;
|
||||
memset((uint8_t*)nodeinfo1 + sizeof(struct ll_entry), 0, sizeof(*nodeinfo1) - sizeof(struct ll_entry));
|
||||
}
|
||||
/* Подготовить новый путь до изменения записи/подсетей. OOM сохраняет прежний узел целиком. */
|
||||
uint64_t hop_list[MAX_HOPS];
|
||||
if (new_hop_count) memcpy(hop_list, new_hop_list, new_hop_count * sizeof(*hop_list));
|
||||
hop_list[new_hop_count] = from->peer_node_id;
|
||||
struct TOPO_GROUP_NODE prepared = {0};
|
||||
if (topo_group_add_path(&prepared, from, hop_list, new_hop_count + 1, incoming_cumulative_rtt) < 0) {
|
||||
topo_node_destroy(group->instance->topo_groups, new_ni);
|
||||
struct TOPO_GROUP_NODE rejected = { .subnets = new_subnets };
|
||||
topo_nodeq_free_group_fields(group->instance->topo_groups, &rejected);
|
||||
if (is_new_node) queue_entry_free(&nodeinfo1->ll);
|
||||
u_free(new_hop_list); return -1;
|
||||
}
|
||||
struct TOPO_NODE* stored = topo_node_registry_store(group->instance->topo_groups, new_ni);
|
||||
if (!stored) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "node registry update failed");
|
||||
topo_nodeq_clear_paths(&prepared);
|
||||
topo_node_destroy(group->instance->topo_groups, new_ni);
|
||||
struct TOPO_GROUP_NODE rejected = { .subnets = new_subnets };
|
||||
topo_nodeq_free_group_fields(group->instance->topo_groups, &rejected);
|
||||
@@ -1409,24 +1426,24 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "node added to group: node=%016llx grp=%016llx type=%u ch=%s (bgp)",
|
||||
(unsigned long long)node_id, (unsigned long long)group->group_id, group->group_type, group->channel_id);
|
||||
|
||||
nodeinfo1->paths = paths; nodeinfo1->last_ver = new_ver;
|
||||
/* Остальные соседи сохраняются; после store больше не нужны выделения памяти. */
|
||||
struct TOPO_NODEPATH* incoming = (struct TOPO_NODEPATH*)prepared.paths->head;
|
||||
struct TOPO_GROUP_CONN_ITEM* peer = topo_group_peer(group, from->peer_node_id);
|
||||
incoming->exchange = peer ? peer->local_epoch : 0;
|
||||
if (paths) {
|
||||
struct ll_entry* e;
|
||||
while ((e = queue_data_get(paths))) {
|
||||
if (((struct TOPO_NODEPATH*)e)->conn == from) queue_entry_free(e);
|
||||
else queue_data_put(prepared.paths, e);
|
||||
}
|
||||
queue_free(paths);
|
||||
}
|
||||
nodeinfo1->paths = prepared.paths; nodeinfo1->last_ver = new_ver;
|
||||
nodeinfo1->last_timestamp = incoming_timestamp;
|
||||
nodeinfo1->radio = (ni->flags & TOPO_FLAG_RADIO) ? 1 : 0;
|
||||
nodeinfo1->phone_status = ni->flags & (TOPO_FLAG_PHONE_KNOWN | TOPO_FLAG_PHONE_BUSY);
|
||||
|
||||
uint64_t hop_list[MAX_HOPS];
|
||||
if (new_hop_count > 0) memcpy(hop_list, new_hop_list, new_hop_count * 8);
|
||||
hop_list[new_hop_count] = from->peer_node_id;
|
||||
uint8_t extended_count = new_hop_count + 1;
|
||||
|
||||
u_free(new_hop_list);
|
||||
|
||||
if (topo_group_add_path(nodeinfo1, from, hop_list, extended_count, incoming_cumulative_rtt) < 0) {
|
||||
if (is_new_node) topo_nodeq_remove_node(group, nodeinfo1);
|
||||
return -1;
|
||||
}
|
||||
struct TOPO_GROUP_CONN_ITEM* peer = topo_group_peer(group, from->peer_node_id);
|
||||
((struct TOPO_NODEPATH*)nodeinfo1->paths->tail)->exchange = peer ? peer->local_epoch : 0;
|
||||
if (node_id != group->instance->node_id) {
|
||||
sqlite3* sdb = group->instance->topo_sqlite_db;
|
||||
if (sdb) {
|
||||
@@ -1448,12 +1465,9 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from
|
||||
if (group->instance->topo_groups->node_updated_cb)
|
||||
group->instance->topo_groups->node_updated_cb(group->instance, node_id, ni->public_key, ni->ed25519_public_key);
|
||||
|
||||
topo_group_routes_changed(group, nodeinfo1, is_new_node ? TOPO_NODE_EVENT_NEW : TOPO_NODE_EVENT_UPDATE);
|
||||
int result = topo_group_routes_changed(group, nodeinfo1, is_new_node ? TOPO_NODE_EVENT_NEW : TOPO_NODE_EVENT_UPDATE);
|
||||
|
||||
int socks_changed = 1;
|
||||
if (!is_new_node) socks_changed = 1;
|
||||
|
||||
if (node_id != group->instance->node_id && (is_new_node || socks_changed)) {
|
||||
if (node_id != group->instance->node_id) {
|
||||
struct TOPO_NODE* tni = topo_node_registry_find(group->instance->topo_groups, nodeinfo1->node_id);
|
||||
int v4a = tni ? topo_list_count((struct _topo_head*)tni->v4_addrs) : 0;
|
||||
int v6a = tni ? topo_list_count((struct _topo_head*)tni->v6_addrs) : 0;
|
||||
@@ -1464,7 +1478,7 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from
|
||||
topo_group_peer_progressed(group, from->peer_node_id);
|
||||
node_conn_direct_update_node(group->instance, node_id);
|
||||
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Обрабатывает WITHDRAW: удаляет узел/пути, чистит роутинг, форвардит withdraw. */
|
||||
|
||||
@@ -1102,7 +1102,8 @@ int topo_node_init_self(struct UTUN_INSTANCE* instance) {
|
||||
topo_node_destroy(instance->topo_groups, ni); return -1;
|
||||
}
|
||||
if (!topo_node_registry_store(instance->topo_groups, ni)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "cannot register local identity"); return -1;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "cannot register local identity");
|
||||
topo_node_destroy(instance->topo_groups, ni); return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user