Browse Source
- Replaced old BGP_ROUTE_PACKET with NODEINFO packets - Added paths list to NODEINFO_Q for multi-path routing - Implemented process_nodeinfo, process_withdraw, add/remove_path - Updated routing.c to use v_node_info->paths - Fixed type inconsistencies and includes across route_* files - Hash size for nodes queue increased to 256 - Version increment logic in build_my_nodeinfo Branch: feature/nodeinfo-routingfeature/nodeinfo-routing
4 changed files with 342 additions and 7 deletions
@ -0,0 +1,155 @@
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <stdint.h> |
||||
|
||||
#include "../lib/ll_queue.h" |
||||
#include "../lib/debug_config.h" |
||||
#include "../lib/mem.h" |
||||
#include "utun_instance.h" |
||||
#include "etcp.h" |
||||
#include "config_parser.h" |
||||
#include "route_node.h" |
||||
#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/копирования). |
||||
*
|
||||
* Функция вычисляет смещение внутри динамической части BGP_NODEINFO_Q |
||||
* и возвращает прямой указатель на массив struct BGP_NODEINFO_IPV4_SUBNET. |
||||
*
|
||||
* @param node Указатель на BGP_NODEINFO_Q |
||||
* @param out_subnets [out] сюда будет записан указатель на первый элемент массива |
||||
* (NULL если подсетей нет) |
||||
* @return количество подсетей (>= 0) или -1 при ошибке |
||||
*/ |
||||
int get_node_routes(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SUBNET **out_subnets) { |
||||
if (!node || !out_subnets) { |
||||
return -1; |
||||
} |
||||
|
||||
*out_subnets = NULL; |
||||
|
||||
const struct NODEINFO *info = &node->node; |
||||
|
||||
if (info->local_v4_subnets == 0) { |
||||
return 0; // успех, но нет подсетей
|
||||
} |
||||
|
||||
// Начало динамических полей сразу после фиксированной части NODEINFO
|
||||
const uint8_t *dynamic = (const uint8_t *)&node->node + sizeof(struct NODEINFO); |
||||
|
||||
// 1. Пропускаем node_name
|
||||
dynamic += info->node_name_len; |
||||
|
||||
// 2. Пропускаем local_v4_sockets
|
||||
dynamic += info->local_v4_sockets * sizeof(struct NODEINFO_IPV4_SOCKET); |
||||
|
||||
// 3. Пропускаем local_v6_sockets
|
||||
dynamic += info->local_v6_sockets * sizeof(struct NODEINFO_IPV6_SOCKET); |
||||
|
||||
// Теперь dynamic указывает точно на начало массива NODEINFO_IPV4_SUBNET
|
||||
*out_subnets = (const struct NODEINFO_IPV4_SUBNET *)dynamic; |
||||
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "get_node_routes: returned %u IPv4 subnets from node %p", |
||||
(unsigned)info->local_v4_subnets, (void*)node); |
||||
return (int)info->local_v4_subnets; |
||||
} |
||||
@ -0,0 +1,84 @@
|
||||
#ifndef ROUTE_NODE_H |
||||
#define ROUTE_NODE_H |
||||
|
||||
#include <stdint.h> |
||||
#include "../lib/ll_queue.h" |
||||
#include "secure_channel.h" |
||||
|
||||
/**
|
||||
* @brief Информация о узле |
||||
*/ |
||||
struct NODEINFO { |
||||
uint64_t node_id; // (big-endian)
|
||||
uint8_t ver; // версия пакета (циклический счетчик чтобы быстро сравнивать с локальной копией - были ли обновления)
|
||||
uint8_t public_key[SC_PUBKEY_SIZE]; // node pubkey
|
||||
uint8_t node_name_len; // размер в байтах (без null терминации)
|
||||
uint8_t local_v4_sockets; // NODEINFO_IPV4_SOCKET число локальных ipv4 сокетов узла (для direct incoming connections)
|
||||
uint8_t local_v6_sockets; // NODEINFO_IPV6_SOCKET число локальных ipv6 сокетов узла (для direct incoming connections) (пока 0)
|
||||
uint8_t local_v4_subnets; // NODEINFO_IPV4_SUBNET число локальных ipv4 подсетей узла
|
||||
uint8_t local_v6_subnets; // NODEINFO_IPV6_SUBNET число локальных ipv6 подсетей узла (пока 0)
|
||||
uint8_t tranzit_nodes; // NODEINFO_TRANZIT_NODE лучшие транзитные узлы для этой ноды (минимальный пинг / лучшее качество каналов. выбирается/обновляется узлом)
|
||||
uint8_t hop_count; // hop list: маршрут по которому распространялся этот NODEINFO_PACKET. для избежания зацикливаний при распространении по узлам. каждый узел при передаче инкрементирует и добавляет в конец свой node_id.
|
||||
// далее идут динамическип поля по порядку следования полей в этой структуре: char node_name[node_name_len], сокеты, роуты, tranzit nodes, hop list (блоки описаны структурами ниже). hop list - это массив node_id[hop_count].
|
||||
} __attribute__((packed)); |
||||
|
||||
struct NODEINFO_IPV4_SOCKET { |
||||
uint8_t addr[4];// network byte order
|
||||
uint16_t port; |
||||
} __attribute__((packed)); |
||||
|
||||
struct NODEINFO_IPV6_SOCKET { |
||||
uint8_t addr[16]; |
||||
uint16_t port; |
||||
} __attribute__((packed)); |
||||
|
||||
struct NODEINFO_IPV4_SUBNET { |
||||
uint8_t addr[4];// network byte order
|
||||
uint8_t prefix_length; |
||||
} __attribute__((packed)); |
||||
|
||||
struct NODEINFO_IPV6_SUBNET { |
||||
uint8_t addr[16]; |
||||
uint8_t prefix_length; |
||||
} __attribute__((packed)); |
||||
|
||||
struct NODEINFO_TRANZIT_NODE { |
||||
uint64_t node_id; // (big-endian)
|
||||
uint16_t rtt; // x0.1 ms (измеренный удаленным узлом RTT до транзитного узла)
|
||||
uint16_t link_q; // меньше - лучше (потери + 1/BW)
|
||||
} __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
|
||||
} __attribute__((packed)); |
||||
|
||||
|
||||
/**
|
||||
* @brief Создаёт/обновляет nodeinfo для собственного узла |
||||
*
|
||||
* Собирает данные из локальных структур и упаковывает к структуру (оптимизированную для передачи по сети) |
||||
*
|
||||
* @param instance Указатель на UTUN_INSTANCE (с него сбоираем все данные) |
||||
* @param bgp здесь будет обновлен struct NODEINFO |
||||
* @return количество подсетей (>= 0) или -1 при ошибке |
||||
*/ |
||||
int route_bgp_build_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp); |
||||
|
||||
/**
|
||||
* @brief Получает указатель на массив IPv4-подсетей узла (без malloc/копирования). |
||||
*
|
||||
* Функция вычисляет смещение внутри динамической части NODEINFO_Q |
||||
* и возвращает прямой указатель на массив struct NODEINFO_IPV4_SUBNET. |
||||
*
|
||||
* @param node Указатель на NODEINFO_Q |
||||
* @param out_subnets [out] сюда будет записан указатель на первый элемент массива |
||||
* (NULL если подсетей нет) |
||||
* @return количество подсетей (>= 0) или -1 при ошибке |
||||
*/ |
||||
int get_node_routes(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SUBNET **out_subnets); |
||||
|
||||
#endif // ROUTE_NODE_H
|
||||
Loading…
Reference in new issue