Browse Source

в процессе доработки роутинга (не рабочий комит)

nodeinfo-routing-update
jeka 4 weeks ago
parent
commit
7dd38d74c8
  1. 400
      src/route_bgp.c
  2. 32
      src/route_bgp.h
  3. 27
      src/route_bgp.txt

400
src/route_bgp.c

@ -34,8 +34,6 @@ static void route_bgp_on_route_change(struct ROUTE_TABLE* table,
static const char* route_type_to_str(route_type_t type) {
switch (type) {
case ROUTE_TYPE_STATIC: return "STATIC";
case ROUTE_TYPE_DYNAMIC: return "DYNAMIC";
case ROUTE_TYPE_LOCAL: return "LOCAL";
case ROUTE_TYPE_LEARNED: return "LEARNED";
default: return "UNKNOWN";
@ -48,6 +46,31 @@ static void format_ip(uint32_t ip, char* buffer) {
snprintf(buffer, 16, "%u.%u.%u.%u", b[3], b[2], b[1], b[0]);
}
/**
* @brief Рассылает маршрут всем соединениям (кроме exclude)
*/
static void route_bgp_broadcast_route(struct ROUTE_BGP* bgp, const struct ROUTE_ENTRY* route,
struct ETCP_CONN* exclude) {
if (!bgp || !route) return;
struct ll_entry* entry = bgp->senders_list->head;
int sent_count = 0;
while (entry) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)entry->data;
if (item->conn != exclude) {
route_bgp_send_route(bgp, item->conn, route);
sent_count++;
}
entry = entry->next;
}
char net_buf[16];
format_ip(route->network, net_buf);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Broadcasted route %s/%d to %d connections",
net_buf, route->prefix_length, sent_count);
}
/**
* @brief Колбэк для приема роутинг-пакетов от ETCP
*
@ -121,46 +144,41 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
// Вставляем в таблицу
char net_buf[16];
format_ip(route.network, net_buf);
size_t old_count = instance->rt->count;
if (route_table_insert(instance->rt, &route)) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Added learned route: %s/%d via node %016llx (hops=%d)",
net_buf, route.prefix_length,
(unsigned long long)route.destination_node_id,
route.metrics.hop_count);
struct ROUTE_BGP* bgp = instance->bgp;
if (instance->rt->count > old_count && !(route.flags & ROUTE_FLAG_ADVERTISED)) {
// Новый маршрут - распространяем всем кроме источника
route_bgp_broadcast_route(bgp, &route, from_conn);
// Устанавливаем флаг, чтобы не повторять
route.flags |= ROUTE_FLAG_ADVERTISED;
}
} else {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "Failed to insert route: %s/%d",
DEBUG_WARN(DEBUG_CATEGORY_BGP, "Failed to insert learned route: %s/%d",
net_buf, route.prefix_length);
}
break;
}
case ROUTE_SUBCMD_WITHDRAW: {
// Удаление маршрута (withdrawal)
uint32_t network = ntohl(pkt->network);
uint8_t prefix_length = pkt->prefix_length & 0x3F;
char w_net_buf[16];
format_ip(network, w_net_buf);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Processing route withdrawal: %s/%d from conn %p",
w_net_buf, prefix_length, (void*)from_conn);
if (route_table_delete_entry(instance->rt, network, prefix_length, from_conn)) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Route withdrawn successfully: %s/%d",
w_net_buf, prefix_length);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Withdrawn route: %s/%d from conn %p",
ip_buf, prefix_length, (void*)from_conn);
} else {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "Route to withdraw not found: %s/%d",
w_net_buf, prefix_length);
DEBUG_WARN(DEBUG_CATEGORY_BGP, "Withdraw failed: route %s/%d not found",
ip_buf, prefix_length);
}
break;
}
case ROUTE_SUBCMD_REQUEST: {
// Запрос полной таблицы - отправляем всё
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Full table request received from connection");
// Получаем bgp из instance (нужно добавить поле в instance)
// Пока просто игнорируем - таблица отправляется при new_conn
break;
}
default:
DEBUG_WARN(DEBUG_CATEGORY_BGP, "Unknown BGP subcommand: %d", pkt->subcmd);
break;
@ -171,281 +189,195 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
}
/**
* @brief Отправить withdraw (отзыв маршрута) через ETCP
* @brief Отправляет маршрут конкретному соединению
*/
static void route_bgp_send_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn,
const struct ROUTE_ENTRY* route)
{
if (!bgp || !conn || !route) {
static void route_bgp_send_route(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn,
const struct ROUTE_ENTRY* route) {
if (!bgp || !conn || !route) return;
// Создаем элемент для отправки
struct ll_entry* entry = queue_entry_new_from_pool(bgp->instance->pkt_pool);
if (!entry) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Failed to allocate entry for BGP send");
return;
}
// Создаем ETCP пакет
struct ll_entry* entry = ll_alloc_lldgram(sizeof(struct ROUTE_BGP_PACKET));
if (!entry) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Failed to allocate withdraw packet");
// Выделяем буфер для пакета
entry->dgram = u_malloc(BGP_PACKET_SIZE);
if (!entry->dgram) {
queue_entry_free(entry);
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Failed to allocate dgram for BGP send");
return;
}
entry->len = BGP_PACKET_SIZE;
entry->memlen = BGP_PACKET_SIZE;
struct ROUTE_BGP_PACKET* pkt = (struct ROUTE_BGP_PACKET*)entry->dgram;
memset(pkt, 0, BGP_PACKET_SIZE);
pkt->cmd = ETCP_ID_ROUTE_ENTRY;
pkt->subcmd = ROUTE_SUBCMD_WITHDRAW;
pkt->hop_count = 0;
pkt->prefix_length = route->prefix_length & 0x3F;
pkt->latency = 0;
pkt->endpoint_port = 0;
pkt->endpoint_ip = 0;
pkt->network = htonl(route->network);
pkt->bandwidth_kbps = 0;
pkt->node_id = route->destination_node_id;
pkt->subcmd = ROUTE_SUBCMD_ENTRY;
pkt->hop_count = route->metrics.hop_count;
pkt->prefix_length = route->prefix_length;
entry->len = sizeof(struct ROUTE_BGP_PACKET);
if (route->type == ROUTE_TYPE_LOCAL) {
pkt->prefix_length |= ROUTE_PREFIX_F_LOCAL;
}
char wd_net_buf[16];
format_ip(route->network, wd_net_buf);
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Sending withdraw: %s/%d to conn %p",
wd_net_buf, route->prefix_length, (void*)conn);
pkt->latency = route->metrics.latency_ms * 10; // ms -> x0.1 ms
pkt->bandwidth_kbps = htonl(route->metrics.bandwidth_kbps);
pkt->network = htonl(route->network);
pkt->endpoint_ip = htonl(route->endpoint_ip);
pkt->endpoint_port = htons(route->endpoint_port);
pkt->node_id = route->destination_node_id;
pkt->route_type = route->type;
// Отправляем через ETCP
if (etcp_send(conn, entry) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Failed to send withdraw via ETCP");
queue_dgram_free(entry);
queue_entry_free(entry);
DEBUG_WARN(DEBUG_CATEGORY_BGP, "Failed to send BGP route to conn %p", (void*)conn);
} else {
char net_buf[16];
format_ip(route->network, net_buf);
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Sent BGP route: %s/%d to conn %p",
net_buf, route->prefix_length, (void*)conn);
}
}
/**
* @brief Отправить withdraw для всех маршрутов через указанное соединение
* @brief Отправляет withdraw для конкретной подсети одному соединению
*/
static void route_bgp_send_withdraw_for_conn(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn)
{
if (!bgp || !conn || !bgp->instance->rt) {
static void route_bgp_send_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn,
uint32_t network, uint8_t prefix_length) {
if (!bgp || !conn) return;
struct ll_entry* entry = queue_entry_new_from_pool(bgp->instance->pkt_pool);
if (!entry) return;
entry->dgram = u_malloc(BGP_PACKET_SIZE);
if (!entry->dgram) {
queue_entry_free(entry);
return;
}
entry->len = BGP_PACKET_SIZE;
entry->memlen = BGP_PACKET_SIZE;
struct ROUTE_TABLE* rt = bgp->instance->rt;
struct ROUTE_BGP_PACKET* pkt = (struct ROUTE_BGP_PACKET*)entry->dgram;
memset(pkt, 0, BGP_PACKET_SIZE);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending withdraw for routes via conn %p to all peers", (void*)conn);
pkt->cmd = ETCP_ID_ROUTE_ENTRY;
pkt->subcmd = ROUTE_SUBCMD_WITHDRAW;
pkt->network = htonl(network);
pkt->prefix_length = prefix_length;
// Находим все маршруты через это соединение и отправляем withdraw
for (size_t i = 0; i < rt->count; i++) {
struct ROUTE_ENTRY* entry = &rt->entries[i];
if (entry->next_hop == conn && entry->type == ROUTE_TYPE_LEARNED) {
// Отправляем withdraw всем соединениям в senders_list
struct ll_entry* item_entry = bgp->senders_list->head;
while (item_entry) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)item_entry->data;
if (item->conn != conn) { // Не отправляем тому, кто прислал
route_bgp_send_withdraw(bgp, item->conn, entry);
}
item_entry = item_entry->next;
}
}
if (etcp_send(conn, entry) != 0) {
queue_dgram_free(entry);
queue_entry_free(entry);
}
}
/**
* @brief Колбэк при изменении таблицы маршрутизации
*
* Рассылает обновления всем соединениям в senders_list
* @brief Рассылает withdraw всем соединениям (кроме exclude)
*/
static void route_bgp_on_route_change(struct ROUTE_TABLE* table,
struct ROUTE_ENTRY* entry,
int action, void* arg)
{
struct ROUTE_BGP* bgp = (struct ROUTE_BGP*)arg;
if (!bgp || !entry) {
return;
}
// Не рассылаем локальные маршруты помеченные ROUTE_PREFIX_F_LOCAL
if (entry->type == ROUTE_TYPE_LOCAL && (entry->prefix_length & ROUTE_PREFIX_F_LOCAL)) {
return;
}
// Не рассылаем маршруты через которые мы их получили (чтобы избежать петель)
// Это делается в цикле ниже
char ch_net_buf[16];
format_ip(entry->network, ch_net_buf);
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Route change: action=%d, network=%s/%d, type=%d",
action, ch_net_buf, entry->prefix_length, entry->type);
static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint32_t network,
uint8_t prefix_length, struct ETCP_CONN* exclude) {
if (!bgp) return;
// Перебираем все соединения в senders_list
struct ll_entry* item_entry = bgp->senders_list->head;
while (item_entry) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)item_entry->data;
// Не отправляем тому, от кого пришел маршрут
if (entry->type == ROUTE_TYPE_LEARNED && entry->next_hop == item->conn) {
item_entry = item_entry->next;
continue;
}
if (action == 2) { // delete - отправить withdraw
route_bgp_send_withdraw(bgp, item->conn, entry);
} else { // insert (0) или update (1) - отправить маршрут
route_bgp_send_route(bgp, item->conn, entry);
struct ll_entry* entry = bgp->senders_list->head;
while (entry) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)entry->data;
if (item->conn != exclude) {
route_bgp_send_withdraw(bgp, item->conn, network, prefix_length);
}
item_entry = item_entry->next;
entry = entry->next;
}
}
/**
* @brief Отправить один маршрут через ETCP (вспомогательная функция для отправки одного пакета)
* @brief Отправляет withdraw для всех маршрутов через закрытое соединение
*/
static int route_bgp_send_route_single(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn,
const struct ROUTE_ENTRY* route,
uint32_t endpoint_ip, uint16_t endpoint_port)
{
struct ll_entry* entry = ll_alloc_lldgram(sizeof(struct ROUTE_BGP_PACKET));
if (!entry) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Failed to allocate packet");
return -1;
}
static void route_bgp_send_withdraw_for_conn(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
if (!bgp || !bgp->instance->rt) return;
struct ROUTE_BGP_PACKET* pkt = (struct ROUTE_BGP_PACKET*)entry->dgram;
pkt->cmd = ETCP_ID_ROUTE_ENTRY;
pkt->subcmd = ROUTE_SUBCMD_ENTRY;
pkt->hop_count = route->metrics.hop_count;
pkt->prefix_length = route->prefix_length;
struct ROUTE_ENTRY* routes = NULL;
size_t count = 0;
// Устанавливаем флаги
if (endpoint_ip && endpoint_port) {
pkt->prefix_length |= ROUTE_PREFIX_F_DIRECT;
}
// Если это локальный маршрут - отмечаем (не будет пересылаться дальше)
if (route->type == ROUTE_TYPE_LOCAL) {
pkt->prefix_length |= ROUTE_PREFIX_F_LOCAL;
// Получаем все маршруты (чтобы не итерать таблицу во время отправки)
for (size_t i = 0; i < bgp->instance->rt->count; i++) {
if (bgp->instance->rt->entries[i].next_hop == conn) {
count++;
}
}
pkt->latency = htons(route->metrics.latency_ms * 10); // ms -> x0.1 ms
pkt->endpoint_port = endpoint_port;
pkt->endpoint_ip = endpoint_ip;
pkt->network = htonl(route->network);
pkt->bandwidth_kbps = htonl(route->metrics.bandwidth_kbps);
pkt->node_id = bgp->instance->node_id; // Наш node_id
pkt->route_type = route->type;
if (count == 0) return;
entry->len = sizeof(struct ROUTE_BGP_PACKET);
char sr_net_buf[16];
char sr_ep_buf[16];
format_ip(route->network, sr_net_buf);
format_ip(ntohl(endpoint_ip), sr_ep_buf);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending route: %s/%d type=%s flags=0x%x "
"metrics{hops=%u lat=%u kbps=%u loss=%u metric=%u} "
"endpoint=%s:%u node_id=%016llx",
sr_net_buf, route->prefix_length,
route_type_to_str(route->type), route->flags,
route->metrics.hop_count, route->metrics.latency_ms,
route->metrics.bandwidth_kbps, route->metrics.packet_loss_rate,
route->metrics.metric,
sr_ep_buf, ntohs(endpoint_port),
(unsigned long long)route->destination_node_id);
routes = u_calloc(count, sizeof(struct ROUTE_ENTRY));
if (!routes) return;
// Отправляем через ETCP
if (etcp_send(conn, entry) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Failed to send route via ETCP");
queue_dgram_free(entry);
queue_entry_free(entry);
return -1;
size_t idx = 0;
for (size_t i = 0; i < bgp->instance->rt->count; i++) {
if (bgp->instance->rt->entries[i].next_hop == conn) {
routes[idx++] = bgp->instance->rt->entries[i];
}
}
return 0;
// Рассылаем withdraw для каждого
struct ll_entry* entry = bgp->senders_list->head;
while (entry) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)entry->data;
if (item->conn != conn) {
for (size_t i = 0; i < count; i++) {
route_bgp_send_withdraw(bgp, item->conn, routes[i].network, routes[i].prefix_length);
}
}
entry = entry->next;
}
u_free(routes);
}
/**
* @brief Отправить один маршрут через ETCP
* @brief Отправляет полную таблицу маршрутов конкретному соединению
*/
static void route_bgp_send_route(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn,
const struct ROUTE_ENTRY* route)
{
if (!bgp || !conn || !route) {
return;
}
// Пропускаем неактивные маршруты
if (!(route->flags & ROUTE_FLAG_ACTIVE)) {
return;
}
static void route_bgp_send_table_to_conn_internal(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
if (!bgp || !conn || !bgp->instance->rt) return;
// Пропускаем локальные маршруты если они не для анонса
if ((route->flags & ROUTE_FLAG_ADVERTISED) && (route->prefix_length & ROUTE_PREFIX_F_LOCAL)) {
return;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending full routing table to conn %p", (void*)conn);
// Для LOCAL маршрутов - отправляем с нескольких endpoints если есть PUBLIC или NAT серверы
if (route->type == ROUTE_TYPE_LOCAL && conn->links) {
// Сначала отправляем PUBLIC (приоритет), затем NAT
struct ETCP_LINK* link = conn->links;
int sent_any = 0;
// Первый проход - PUBLIC
while (link) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending routine: scanning conn type=%d init=%d", link->conn->type, link->initialized);
if (link->conn && link->conn->type == CFG_SERVER_TYPE_PUBLIC && link->initialized) {
struct sockaddr_in* sin = (struct sockaddr_in*)&link->conn->local_addr;
uint32_t ip = *(uint32_t*)&sin->sin_addr;
uint16_t port = sin->sin_port;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending routine [public]");
route_bgp_send_route_single(bgp, conn, route, ip, port);
sent_any = 1;
}
link = link->next;
}
// Второй проход - NAT
link = conn->links;
while (link) {
if (link->conn && link->conn->type == CFG_SERVER_TYPE_NAT && link->nat_ip && link->initialized) {
uint32_t ip = link->nat_ip;
uint16_t port = link->nat_port;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending routine [nat]");
route_bgp_send_route_single(bgp, conn, route, ip, port);
sent_any = 1;
}
link = link->next;
}
// Если нет PUBLIC и NAT - отправляем без endpoint (0.0.0.0:0)
if (!sent_any) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending routine [any]");
route_bgp_send_route_single(bgp, conn, route, 0, 0);
for (size_t i = 0; i < bgp->instance->rt->count; i++) {
const struct ROUTE_ENTRY* route = &bgp->instance->rt->entries[i];
if (route->type == ROUTE_TYPE_LOCAL ||
(route->type == ROUTE_TYPE_LEARNED && (route->flags & ROUTE_FLAG_ADVERTISED))) {
route_bgp_send_route(bgp, conn, route);
}
} else {
// Для LEARNED маршрутов - используем endpoint из route
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending routine [learned]");
route_bgp_send_route_single(bgp, conn, route,
htonl(route->endpoint_ip),
htons(route->endpoint_port));
}
}
/**
* @brief Отправить полную таблицу указанному соединению
* @brief Callback на изменение таблицы маршрутизации
*/
static void route_bgp_send_table_to_conn_internal(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn)
{
if (!bgp || !conn || !bgp->instance->rt) {
return;
}
struct ROUTE_TABLE* rt = bgp->instance->rt;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending full routing table (%zu routes) to connection",
rt->count);
static void route_bgp_on_route_change(struct ROUTE_TABLE* table,
struct ROUTE_ENTRY* entry,
int action, void* arg) {
struct ROUTE_BGP* bgp = (struct ROUTE_BGP*)arg;
if (!bgp || !entry) return;
// Отправляем все маршруты из таблицы
for (size_t i = 0; i < rt->count; i++) {
route_bgp_send_route(bgp, conn, &rt->entries[i]);
if (action == 0 || action == 1) { // insert or update
// Анонсируем только локальные и статические маршруты
if (entry->type == ROUTE_TYPE_LOCAL) {
route_bgp_broadcast_route(bgp, entry, NULL);
}
} else if (action == 2) { // delete
// Отправляем withdraw всем
route_bgp_broadcast_withdraw(bgp, entry->network, entry->prefix_length, NULL);
}
}
struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance)
{
/**
* @brief Инициализация BGP модуля
*/
struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) {
if (!instance) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Cannot init BGP: no instance");
return NULL;

32
src/route_bgp.h

@ -3,6 +3,7 @@
#include <stdint.h>
#include "../lib/ll_queue.h"
#include "route_lib.h"
// Forward declarations
struct UTUN_INSTANCE;
@ -13,28 +14,27 @@ struct ETCP_CONN;
// Sub-команды для маршрутных пакетов
#define ROUTE_SUBCMD_ENTRY 0x01 // Элемент таблицы
#define ROUTE_SUBCMD_WITHDRAW 0x02 // Отзыв маршрута
#define ROUTE_SUBCMD_REQUEST 0x03 // Запрос полной таблицы
// Флаги в prefix_length (2 старших бита)
#define ROUTE_PREFIX_F_DIRECT 0x40 // Можно подключиться напрямую
#define ROUTE_PREFIX_F_LOCAL 0x80 // Локальный маршрут (не пересылать)
#define ROUTE_SUBCMD_ENTRY_REROUTE 0x02 // old_node_id + элемент таблицы - когда найден альтернативный маршрут при WITHDRAW
#define ROUTE_SUBCMD_WITHDRAW 0x03 // Отзыв маршрута
#define ROUTE_SUBCMD_NODEINFO 0x04 // информация об узле для прямого подключения
/**
* @brief Пакет маршрутной информации (бинарный формат)
*/
struct ROUTE_BGP_PACKET {
struct PEER_INFO_ENTRY {
struct ROUTE_PEER_INFO;
}
struct BGP_ENTRY_PACKET {
uint8_t cmd; // ETCP_CMD_ROUTE (1)
uint8_t subcmd; // ROUTE_SUBCMD_ENTRY (1)
uint8_t hop_count; // Количество прыжков (инкриментирует получатель)
uint8_t prefix_length; // Длина префикса подсети + флаги (2 старших бита)
uint16_t latency; // Задержка (x0.1 ms)
uint16_t endpoint_port; // Порт для прямого подключения
uint32_t endpoint_ip; // IP для прямого подключения
uint32_t network; // Сетевой адрес (big-endian)
uint32_t bandwidth_kbps; // Пропускная способность
uint64_t node_id; // ID узла назначения
uint8_t route_type; // ROUTE_TYPE_LOCAL / LEARNED
struct ROUTE_PEER_INFO peer_info;
} __attribute__((packed));
struct BGP_NODEINFO_PACKET {
uint8_t cmd; // ETCP_CMD_ROUTE (1)
uint8_t subcmd; // ROUTE_SUBCMD_NODEINFO (4)
struct ROUTE_NODE_INFO node_info;
} __attribute__((packed));

27
src/route_bgp.txt

@ -38,4 +38,29 @@ subcmd:
удаленный узел считает свои хеши и сравнивает. где не совпало смотрит сколько записей.
если записей не много - передает эти записи.
если записей много - добавляет 4 бита к хеш таблице и строит субтаблицу для
если записей много - добавляет 4 бита к хеш таблице и строит субтаблицу для
Как работает роутинг:
1. типов маршрута бывает два: learned и local.
local - маршруты из конфига (my_subnet)
при инициализации они сразу добавляются в роутинг таблицу.
2. При установке подключения к новому узлу мы отправляем этому узлу полностью свою таблицу маршрутизации (local + learned узлы)
3. При получении маршрута мы смотрим есть ли такой маршрут уже в таблице. Если такоц маршрут есть - пропускаем. иначе добавляем/обновляем (стремимся получить маршрут с минимальным hop count).
Добавляем так:
инкрементируем hop_count
устанавливая etcp линк с которого приняли как next_hop.
рассылаем по всем активным линкам кроме линка с которого получили
4. При отключении от узла мы
Удаляем все маршруты узла
Рассылаем withdraw для узла hop_id.
Логика рассылки withdraw:
Если получен withdraw и next hop маршрутов узла = hop id - удаляем маршрут и распространяем withdraw дальше по доступным линкам.
А если next hop у нас другой - отправляем в ответ наш маршрут командой reoute (для распространения альтернативного найденного маршрута) в линк с которого пришел withdraw.
reroute содержит дополнительное поле - old_hop_id

Loading…
Cancel
Save