Clarify group processing callbacks and failed route installation
This commit is contained in:
1 parent
56d513ed85
commit
7ebfddfc4b
2 files changed
+48
-50
No files matched your search
@@ -157,7 +157,8 @@ static void topo_group_peer_event(struct NODE_CONN_DIRECT* handle, enum ncd_even
|
||||
|
||||
int topo_group_peer_open(struct TOPO_GROUP* group, uint64_t node_id, struct TOPO_PEER_REQUEST** out) {
|
||||
if (out) *out = NULL;
|
||||
if (!group || !out || !node_id || !group->senders_list || group->stopping || !topo_group_peer_allowed(group, node_id)) {
|
||||
if (!group || !group->instance || !out || !node_id || node_id == group->instance->node_id ||
|
||||
!group->senders_list || group->stopping || !topo_group_peer_allowed(group, node_id)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "cannot request group peer=%016llx: invalid arguments, stopped group or unknown member",
|
||||
(unsigned long long)node_id); return -1;
|
||||
}
|
||||
@@ -352,38 +353,6 @@ static void nodeinfo_dump_log(const uint8_t* data, size_t len) {
|
||||
ni->local_v4_sockets, ni->local_v4_addrs, ni->hop_count);
|
||||
}
|
||||
|
||||
/* Форматирует NODEINFO в читаемую строку для лога (имя, подсети, адреса). */
|
||||
static char* nodeinfo_format(const uint8_t* data, size_t len) {
|
||||
if (!data || len < sizeof(struct TOPOMSG_NODEINFO_PKT)) return NULL;
|
||||
struct TOPOMSG_NODEINFO_PKT* pkt = (struct TOPOMSG_NODEINFO_PKT*)data;
|
||||
struct TOPOMSG_NODE* ni = &pkt->node;
|
||||
uint64_t node_id = ni->node_id;
|
||||
const uint8_t* dyn = data + sizeof(struct TOPOMSG_NODEINFO_PKT);
|
||||
size_t off = 0;
|
||||
char name_buf[64] = {0};
|
||||
size_t nl = ni->node_name_len;
|
||||
if (nl > 0 && nl < 63 && off + nl < len - sizeof(struct TOPOMSG_NODEINFO_PKT)) {
|
||||
memcpy(name_buf, dyn + off, nl); off += nl;
|
||||
}
|
||||
off += ni->local_v4_sockets * sizeof(struct TOPOMSG_SOCKMETA4);
|
||||
off += ni->local_v4_addrs * sizeof(struct TOPOMSG_ADDR4);
|
||||
off += ni->local_v6_sockets * sizeof(struct TOPOMSG_SOCKMETA6);
|
||||
off += ni->local_v6_addrs * sizeof(struct TOPOMSG_ADDR6);
|
||||
char subs_buf[512] = {0};
|
||||
if (ni->local_v4_subnets > 0) {
|
||||
const struct TOPOMSG_SUBNET4* subs = (const struct TOPOMSG_SUBNET4*)(dyn + off);
|
||||
size_t sl = 0;
|
||||
for (uint8_t i = 0; i < ni->local_v4_subnets && sl < 400; i++) {
|
||||
uint32_t addr = (subs[i].addr[0]<<24)|(subs[i].addr[1]<<16)|(subs[i].addr[2]<<8)|subs[i].addr[3];
|
||||
char tmp[64]; snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%u ",(addr>>24)&255,(addr>>16)&255,(addr>>8)&255,addr&255,subs[i].prefix_length);
|
||||
strcat(subs_buf,tmp); sl += strlen(tmp);
|
||||
}
|
||||
}
|
||||
int need = snprintf(NULL,0,"NODEINFO nid=%016llx ver=%u name=\"%s\" v4subs=\"%s\" v4s=%u v4a=%u hop=%u", (unsigned long long)node_id,(unsigned)ni->ver,name_buf,subs_buf,(unsigned)ni->local_v4_sockets,(unsigned)ni->local_v4_addrs,(unsigned)ni->hop_count);
|
||||
char* buf = u_malloc(need+1); if (!buf) return NULL;
|
||||
snprintf(buf,need+1,"NODEINFO nid=%016llx ver=%u name=\"%s\" v4subs=\"%s\" v4s=%u v4a=%u hop=%u", (unsigned long long)node_id,(unsigned)ni->ver,name_buf,subs_buf,(unsigned)ni->local_v4_sockets,(unsigned)ni->local_v4_addrs,(unsigned)ni->hop_count);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Читаемое имя sub-команды BGP для логов. */
|
||||
static const char* group_subcmd_name(uint8_t subcmd) {
|
||||
@@ -982,7 +951,10 @@ void topo_groups_set_node_updated_cb(struct TOPO_GROUPS* groups, topo_node_updat
|
||||
static int topo_group_begin_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn, int retain) {
|
||||
if (!group || !conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args"); return -1; }
|
||||
if (group->stopping) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "join on stopped group"); return -1; }
|
||||
if (!conn->instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "conn->instance is NULL"); return -1; }
|
||||
if (conn->instance != group->instance || !conn->links_up || conn->close_requested) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "group join needs a live transport of the same instance peer=%016llx group=%016llx",
|
||||
(unsigned long long)conn->peer_node_id, (unsigned long long)group->group_id); return -1;
|
||||
}
|
||||
if (!conn->instance->rt) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "conn->instance->rt is NULL"); return -1; }
|
||||
if (!topo_group_peer_allowed(group, conn->peer_node_id)) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "group connect deferred: member unknown peer=%016llx group=%016llx",
|
||||
@@ -1269,7 +1241,10 @@ static void topo_group_send_err_group_mismatch(struct TOPO_GROUP* group, struct
|
||||
|
||||
/* Обрабатывает NODEINFO: проверка подписи/версии, обновление узла, пути, роутинг, форвард. */
|
||||
int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from, const uint8_t* data, size_t len) {
|
||||
if (!group || !from || len < sizeof(struct TOPOMSG_NODEINFO_PKT)) return -1;
|
||||
if (!group || !group->instance || !from || from->instance != group->instance || !data ||
|
||||
len < sizeof(struct TOPOMSG_NODEINFO_PKT)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "invalid NODEINFO context or length=%zu", len); return -1;
|
||||
}
|
||||
|
||||
struct TOPOMSG_NODEINFO_PKT* pkt = (struct TOPOMSG_NODEINFO_PKT*)data;
|
||||
struct TOPOMSG_NODE* ni = &pkt->node;
|
||||
@@ -1483,7 +1458,7 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from
|
||||
|
||||
/* Обрабатывает WITHDRAW: удаляет узел/пути, чистит роутинг, форвардит withdraw. */
|
||||
int topo_group_process_withdraw(struct TOPO_GROUP* group, struct ETCP_CONN* sender, const uint8_t* data, size_t len) {
|
||||
if (!group || !sender || len != sizeof(struct TOPOMSG_WITHDRAW_PKT)) {
|
||||
if (!group || !group->instance || !sender || sender->instance != group->instance || !data || len != sizeof(struct TOPOMSG_WITHDRAW_PKT)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "invalid WITHDRAW len=%zu", len); return -1;
|
||||
}
|
||||
struct TOPOMSG_WITHDRAW_PKT* wp = (struct TOPOMSG_WITHDRAW_PKT*)data;
|
||||
@@ -1954,9 +1929,9 @@ void topo_group_remove_peer_ready_cbk(struct TOPO_GROUP* group, topo_peer_ready_
|
||||
}
|
||||
|
||||
void topo_group_add_node_cbk(struct TOPO_GROUP* group, topo_node_event_fn fn, void* arg) {
|
||||
if (!group || !fn) return;
|
||||
if (!group || !fn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "node subscription: invalid arguments"); return; }
|
||||
struct topo_node_cbk_entry* e = u_malloc(sizeof(*e));
|
||||
if (!e) return;
|
||||
if (!e) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "node subscription allocation failed"); return; }
|
||||
e->fn = fn; e->arg = arg;
|
||||
e->next = group->node_cbks;
|
||||
group->node_cbks = e;
|
||||
@@ -1980,9 +1955,9 @@ void topo_group_remove_node_cbk(struct TOPO_GROUP* group, topo_node_event_fn fn,
|
||||
|
||||
/* Регистрирует глобальный колбэк изменения nodeinfo (уровень инстанса). */
|
||||
void utun_add_nodeinfo_cbk(struct UTUN_INSTANCE* instance, nodeinfo_cbk_fn fn, void* arg) {
|
||||
if (!instance || !fn) return;
|
||||
if (!instance || !fn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "nodeinfo subscription: invalid arguments"); return; }
|
||||
struct nodeinfo_cbk_entry* e = u_malloc(sizeof(*e));
|
||||
if (!e) return;
|
||||
if (!e) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "nodeinfo subscription allocation failed"); return; }
|
||||
e->fn = fn; e->arg = arg;
|
||||
e->next = instance->nodeinfo_cbks;
|
||||
instance->nodeinfo_cbks = e;
|
||||
|
||||
@@ -76,6 +76,11 @@ typedef void (*topo_node_updated_fn)(struct UTUN_INSTANCE* inst, uint64_t node_i
|
||||
typedef void (*topo_node_event_fn)(struct TOPO_GROUP* group, uint64_t node_id,
|
||||
int event, void* arg);
|
||||
|
||||
/* Подписки принадлежат группе/instance; fn и arg заимствованы до remove/destroy.
|
||||
* Вызов синхронный, в uasync. Callback не удаляет группу/узел и не меняет список
|
||||
* подписчиков во время обхода; такие действия нужно отложить через uasync_call_soon.
|
||||
* Повторная регистрация создаёт ещё одну подписку; remove снимает первое совпадение. */
|
||||
|
||||
struct topo_node_cbk_entry {
|
||||
topo_node_event_fn fn;
|
||||
void* arg;
|
||||
@@ -300,12 +305,15 @@ struct TOPO_GROUP* topo_groups_get_default(struct TOPO_GROUPS* g);
|
||||
struct TOPO_GROUP* topo_groups_find(struct TOPO_GROUPS* g, uint64_t group_id);
|
||||
|
||||
/**
|
||||
* @brief Создаёт новую группу с указанным типом.
|
||||
* @brief Создаёт и регистрирует новую группу; существующий group_id — ошибка.
|
||||
* После регистрации присоединяет уже поднятые транспорты: CHAT — локальных мемберов,
|
||||
* UTUN — пиров, которыми владеет конфигурация. Для CHAT по group_autoconnect
|
||||
* (по умолчанию 1) включает подбор пиров. Ошибки этих попыток логируются отдельно.
|
||||
*
|
||||
* @param g контейнер групп
|
||||
* @param group_id уникальный идентификатор
|
||||
* @param group_type TOPO_GROUP_TYPE_UTUN или TOPO_GROUP_TYPE_CHAT
|
||||
* @param channel_id идентификатор канала для групп типа CHAT (может быть NULL)
|
||||
* @param channel_id локальный ключ таблиц CHAT; копируется до 63 байт, NULL оставляет пустой ключ
|
||||
* @return TOPO_GROUP с local_node, conn_mgr, broadcast и radio или NULL с полным откатом создания
|
||||
*/
|
||||
struct TOPO_GROUP* topo_groups_create_group(struct TOPO_GROUPS* g, uint64_t group_id, uint8_t group_type, const char* channel_id);
|
||||
@@ -320,7 +328,7 @@ struct TOPO_GROUP* topo_groups_create_group(struct TOPO_GROUPS* g, uint64_t grou
|
||||
void topo_groups_remove_group(struct TOPO_GROUPS* g, uint64_t group_id);
|
||||
|
||||
/**
|
||||
* @brief Присоединяет существующий транспорт к группе и начинает JOIN/ACCEPT.
|
||||
* @brief Присоединяет UP-транспорт того же instance к группе и начинает JOIN/ACCEPT.
|
||||
* Группа приобретает собственный NCD handle; повтор не сбрасывает сессию. 0/-1.
|
||||
* Для обычного инициатора используйте отменяемый topo_group_peer_open().
|
||||
*/
|
||||
@@ -345,7 +353,7 @@ enum topo_peer_phase { TOPO_PEER_FAILED, TOPO_PEER_CONNECTING, TOPO_PEER_SYNCING
|
||||
* Запрос остаётся валиден после удаления группы (phase=FAILED), caller обязан
|
||||
* закрыть его. Все операции выполняются в потоке единственного uasync.
|
||||
* progress — timebase последнего принятого NODEINFO/шага обмена, не polling time.
|
||||
* open: 0 = запрос создан в *out, -1 = ошибка. */
|
||||
* open: node_id ненулевой и не self; 0 = запрос создан в *out, -1 = ошибка (*out=NULL). */
|
||||
int topo_group_peer_open(struct TOPO_GROUP* group, uint64_t node_id, struct TOPO_PEER_REQUEST** out);
|
||||
/* Освободить свой запрос; после вызова request недействителен. NULL допустим. */
|
||||
void topo_group_peer_close(struct TOPO_PEER_REQUEST* request);
|
||||
@@ -373,10 +381,18 @@ void topo_group_remove_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn, en
|
||||
/**
|
||||
* @brief Обрабатывает пакет NODEINFO.
|
||||
*
|
||||
* Проверка подписи и timestamp, обновление TOPO_GROUP_NODE, добавление пути,
|
||||
* вставка в роутинг, broadcast если не max hops.
|
||||
* data/len — полный TOPOMSG_NODEINFO_PKT с динамическими секциями; память заимствована.
|
||||
* Диспетчер заранее проверяет поколения/членство сессии. Здесь проверяются длина,
|
||||
* group_id тела, тип, подпись, конфликт timestamp и цепочка; добавляется ID from.
|
||||
* Старый timestamp обновляет только путь. Для новой записи путь готовится до commit:
|
||||
* отказ памяти сохраняет прежние запись/подсети/пути. Входная цепочка < MAX_HOPS,
|
||||
* сохранённая после добавления соседа — 1..MAX_HOPS.
|
||||
* Изменения распространяются из актуального состояния с backpressure.
|
||||
* Для UTUN прежние IPv4-маршруты узла удаляются перед установкой нового набора.
|
||||
* Пересечение/OOM маршрутов оставляет новый набор неустановленным, возвращает -1
|
||||
* и запрещает READY; подписанная запись и групповые пути уже могут быть приняты.
|
||||
*
|
||||
* @return 0 при успехе
|
||||
* @return 0 при применении/игнорировании собственного объявления, -1 при ошибке
|
||||
*/
|
||||
int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from, const uint8_t* data, size_t len);
|
||||
/* Присоединить UP-транспорт; переданный handle остаётся у вызывающего. 0/-1. */
|
||||
@@ -387,15 +403,20 @@ int topo_group_leave_peer(struct TOPO_GROUP* group, struct NODE_CONN_DIRECT* han
|
||||
/**
|
||||
* @brief Обрабатывает WITHDRAW.
|
||||
*
|
||||
* Удаляет затронутые пути; узел удаляется только без оставшихся путей.
|
||||
* data/len — заимствованный полный TOPOMSG_WITHDRAW_PKT; поколения/членство
|
||||
* проверяет диспетчер. Удаляет только путь sender; узел удаляется без оставшихся путей.
|
||||
* Неизвестный узел/отсутствующий путь sender — успешный no-op.
|
||||
*
|
||||
* @return 0 при успехе
|
||||
* @return 0 при успехе, -1 при неверных аргументах/длине
|
||||
*/
|
||||
int topo_group_process_withdraw(struct TOPO_GROUP* group, struct ETCP_CONN* sender, const uint8_t* data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Планирует NODEINFO узла одному пиру с backpressure.
|
||||
* group/node/conn заимствованы на время вызова; очередь хранит только node_id.
|
||||
* Запись и RTT читаются при отправке; повторные изменения узла объединяются.
|
||||
* 0 — запланировано либо сессия ещё не ACCEPT, -1 — ошибка. Ошибка самой отложенной
|
||||
* отправки сбрасывает READY и перезапускает обмен по watchdog.
|
||||
*/
|
||||
int topo_group_send_nodeinfo(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* node, struct ETCP_CONN* conn);
|
||||
|
||||
@@ -414,7 +435,9 @@ struct ETCP_CONN* topo_group_find_conn_for_node(struct TOPO_GROUP* group, uint64
|
||||
/**
|
||||
* @brief Атомарно заменяет путь через conn; остальные соседи не затрагиваются.
|
||||
*
|
||||
* @return 0 при успехе
|
||||
* nq/conn/hop_list заимствованы; цепочка 1..MAX_HOPS копируется. Семантику и петли
|
||||
* проверяет вызывающий; функция проверяет размер и атомарно заменяет путь conn.
|
||||
* @return 0 при успехе, -1 при неверных аргументах/OOM
|
||||
*/
|
||||
int topo_group_add_path(struct TOPO_GROUP_NODE* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count, uint16_t cumulative_rtt);
|
||||
|
||||
|
||||
Reference in new issue
Block a user