Evgeny 4 days ago
parent
commit
e47593cd77
  1. 163
      src/route_bgp.c
  2. 4
      src/route_bgp.h
  3. 13
      src/route_lib.c
  4. 2
      src/route_node.c
  5. 7
      src/route_node.h

163
src/route_bgp.c

@ -47,7 +47,7 @@ static char* nodeinfo_format(const uint8_t* data, size_t len) {
if (!data || len < sizeof(struct BGP_NODEINFO_PACKET)) return NULL;
struct BGP_NODEINFO_PACKET* pkt = (struct BGP_NODEINFO_PACKET*)data;
struct NODEINFO* ni = &pkt->node;
uint64_t node_id = be64toh(ni->node_id);
uint64_t node_id = ni->node_id;
const uint8_t* dyn = data + sizeof(struct BGP_NODEINFO_PACKET);
size_t off = 0;
char name_buf[64] = {0};
@ -101,8 +101,8 @@ static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id
if (!pkt) return;
pkt->cmd = ETCP_ID_ROUTE_ENTRY;
pkt->subcmd = ROUTE_SUBCMD_WITHDRAW;
pkt->node_id = htobe64(node_id);
pkt->wd_source = htobe64(wd_source);
pkt->node_id = node_id;
pkt->wd_source = wd_source;
struct ll_entry* e = bgp->senders_list ? bgp->senders_list->head : NULL;
while (e) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data;
@ -273,7 +273,7 @@ struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance)
return NULL;
}
bgp->local_node->node.node_id = htobe64(instance->node_id);
bgp->local_node->node.node_id = instance->node_id;
bgp->local_node->node.hop_count = 0;
bgp->local_node->node.ver = 1;
bgp->local_node->dirty = 0;
@ -453,13 +453,12 @@ struct NODEINFO_Q* route_bgp_get_node(struct ROUTE_BGP* bgp, uint64_t node_id)
return NULL;
}
uint64_t key = htobe64(node_id);
uint64_t key = node_id;
struct ll_entry* e = queue_find_data_by_index(bgp->nodes, &key, 8);
return e ? (struct NODEINFO_Q*)e : NULL;
}
int route_bgp_add_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count)
{
int route_bgp_add_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count) {
if (!nq || !conn || hop_count > MAX_HOPS || !hop_list) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "add_path: invalid args");
return -1;
@ -548,16 +547,28 @@ int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn)
return 0;
}
int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from,
const uint8_t* data, size_t len)
{
if (!bgp || !from || len < sizeof(struct BGP_NODEINFO_PACKET)) {
return -1;
}
int nodeinfo_dyn_size(struct NODEINFO* node) {
return node->node_name_len +
node->local_v4_sockets * sizeof(struct NODEINFO_IPV4_SOCKET) +
node->local_v6_sockets * sizeof(struct NODEINFO_IPV6_SOCKET) +
node->local_v4_subnets * sizeof(struct NODEINFO_IPV4_SUBNET) +
node->local_v6_subnets * sizeof(struct NODEINFO_IPV6_SUBNET) +
node->tranzit_nodes * 8 +
node->hop_count * 8;
}
int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, const uint8_t* data, size_t len) {
if (!bgp || !from || len < sizeof(struct BGP_NODEINFO_PACKET)) return -1;
struct BGP_NODEINFO_PACKET* pkt = (struct BGP_NODEINFO_PACKET*)data;
struct NODEINFO* ni = &pkt->node;
uint64_t node_id = be64toh(ni->node_id);
int dyn_size=nodeinfo_dyn_size(ni);
if (len!=dyn_size + sizeof(struct BGP_NODEINFO_PACKET)) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "Incorrect packet size (%s)",from->log_name);
return -1;
}
uint64_t node_id = ni->node_id;
if (ni->hop_count >= MAX_HOPS) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "NODEINFO from %s dropped: too many hops (%d)",
@ -565,68 +576,85 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from,
return -1;
}
struct NODEINFO_Q* existing = route_bgp_get_node(bgp, node_id);
struct NODEINFO_Q* nodeinfo1 = route_bgp_get_node(bgp, node_id);
uint8_t new_ver = ni->ver;
if (existing && existing->last_ver >= new_ver) {
if (nodeinfo1 && (int8_t)(nodeinfo1->last_ver-new_ver)>=0) {
DEBUG_TRACE(DEBUG_CATEGORY_BGP, "NODEINFO from %s ignored (old ver %d <= %d)",
from->log_name, new_ver, existing->last_ver);
from->log_name, new_ver, nodeinfo1->last_ver);
return 0;
}
int new_data_size=sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry) + dyn_size + 8;
struct ll_queue* paths=NULL;
int need_alloc=0;
if (nodeinfo1) {// remove old node
paths=nodeinfo1->paths;
if (nodeinfo1->ll.size < new_data_size) {
if (!existing) {
size_t dyn = len - sizeof(struct BGP_NODEINFO_PACKET) + 8;
struct ll_entry* entry = queue_entry_new(sizeof(struct NODEINFO_Q) + dyn);
if (!entry) {
return -1;
}
existing = (struct NODEINFO_Q*)entry;
existing->paths = queue_new(bgp->instance->ua, 0, "node_paths");
queue_data_put_with_index(bgp->nodes, entry, offsetof(struct NODEINFO_Q, node.node_id)-sizeof(struct ll_entry), 8);
}
memcpy(&existing->node, ni, sizeof(struct NODEINFO));
existing->last_ver = new_ver;
need_alloc=1;
}
} else need_alloc=1;
uint8_t* dyn_dest = (uint8_t*)&existing->node + sizeof(struct NODEINFO);
const uint8_t* dyn_src = data + sizeof(struct BGP_NODEINFO_PACKET);
size_t dyn_size = len - sizeof(struct BGP_NODEINFO_PACKET);
memcpy(dyn_dest, dyn_src, dyn_size);
if (need_alloc) {
if (nodeinfo1) {
queue_remove_data(bgp->nodes, &nodeinfo1->ll);
queue_entry_free(&nodeinfo1->ll);
}
nodeinfo1 = (struct NODEINFO_Q*)queue_entry_new(new_data_size);
paths = queue_new(bgp->instance->ua, 0, "node_paths");
memcpy(&nodeinfo1->node, ni, sizeof(struct NODEINFO) + dyn_size);
queue_data_put_with_index(bgp->nodes, &nodeinfo1->ll, offsetof(struct NODEINFO_Q, node.node_id)-sizeof(struct ll_entry), 8);
}
else memcpy(&nodeinfo1->node, ni, sizeof(struct NODEINFO) + dyn_size);
nodeinfo1->paths = paths;
nodeinfo1->last_ver = new_ver;
uint8_t* hop_dest = dyn_dest + dyn_size;
uint64_t sender = htobe64(from->peer_node_id);
memcpy(hop_dest, &sender, 8);
existing->node.hop_count = ni->hop_count + 1;
// add last hop
uint64_t* hop_list = (uint64_t*)((uint8_t*)&nodeinfo1->node + sizeof(struct NODEINFO) + dyn_size);
uint64_t sender = from->peer_node_id;
memcpy(hop_list, &sender, 8);
nodeinfo1->node.hop_count++;
if (ni->hop_count >= 0) {
route_bgp_add_path(existing, from, (uint64_t*)hop_dest, existing->node.hop_count);
}
// update node path
route_bgp_remove_path_by_hop(nodeinfo1, from->peer_node_id);
route_bgp_add_path(nodeinfo1, from, hop_list, nodeinfo1->node.hop_count);
if (bgp->instance->rt) {
route_insert(bgp->instance->rt, existing);
route_insert(bgp->instance->rt, nodeinfo1);
}
if (ni->hop_count < MAX_HOPS - 1) {
ni->hop_count++;
route_bgp_broadcast_nodeinfo(bgp, from);
ni->hop_count--;
int hop_count=nodeinfo1->node.hop_count;
// рассылаем по узлам которых нет в hop_list этой ноды (loop prevention)
struct ll_entry* e = bgp->senders_list ? bgp->senders_list->head : NULL;
while (e) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data;
if (item->conn) {
uint64_t id=item->conn->peer_node_id;
int found=0;
for (int i=0; i<hop_count; i++) if (hop_list[i]==id) found=1;
if (found==0) {
route_bgp_send_nodeinfo(nodeinfo1, item->conn);
}
else DEBUG_INFO(DEBUG_CATEGORY_BGP, "Skip send NODEINFO to node %016llx",id);
}
e = e->next;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Processed NODEINFO from %s (node=%016llx,ver=%d,paths=%d)",
from->log_name, (unsigned long long)node_id, new_ver,
existing->paths ? queue_entry_count(existing->paths) : 0);
nodeinfo1->paths ? queue_entry_count(nodeinfo1->paths) : 0);
return 0;
}
int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len) {
if (!bgp || len < sizeof(struct BGP_WITHDRAW_PACKET)) {
return -1;
}
if (!bgp || len < sizeof(struct BGP_WITHDRAW_PACKET)) return -1;
struct BGP_WITHDRAW_PACKET* wp = (struct BGP_WITHDRAW_PACKET*)data;
uint64_t node_id = be64toh(wp->node_id);
uint64_t wd_source = be64toh(wp->wd_source);
uint64_t node_id = wp->node_id;
uint64_t wd_source = wp->wd_source;
struct NODEINFO_Q* nq = route_bgp_get_node(bgp, node_id);
if (!nq) {
@ -641,7 +669,7 @@ int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender,
if (nq->paths) {
queue_free(nq->paths);
}
uint64_t key = htobe64(node_id);
uint64_t key = node_id;
struct ll_entry* entry = queue_find_data_by_index(bgp->nodes, &key, 8);
if (entry) {
queue_remove_data(bgp->nodes, entry);
@ -659,28 +687,14 @@ int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender,
* @brief Отправка NODEINFO-пакета (всегда отправляем local_node)
* Сигнатура соответствует объявлению в route_bgp.h
*/
void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn)
{
void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn) {
if (!node || !conn) {
return;
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending NODEINFO to %s", conn->log_name);
size_t nl = node->node.node_name_len;
size_t s4 = node->node.local_v4_sockets;
size_t s6 = node->node.local_v6_sockets;
size_t sub4 = node->node.local_v4_subnets;
size_t sub6 = node->node.local_v6_subnets;
size_t t = node->node.tranzit_nodes;
size_t h = node->node.hop_count;
size_t dyn = nl +
s4 * sizeof(struct NODEINFO_IPV4_SOCKET) +
s6 * sizeof(struct NODEINFO_IPV6_SOCKET) +
sub4 * sizeof(struct NODEINFO_IPV4_SUBNET) +
sub6 * sizeof(struct NODEINFO_IPV6_SUBNET) +
t * 8 + h * 8;
int dyn = nodeinfo_dyn_size(&node->node);
size_t ps = sizeof(struct BGP_NODEINFO_PACKET) + dyn;
@ -707,11 +721,9 @@ void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn)
etcp_send(conn, e);
}
void route_bgp_broadcast_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* exclude) {
if (!bgp) {
return;
}
/*
void route_bgp_broadcast_nodeinfo(struct ROUTE_BGP* bgp, struct NODEINFO_Q* node, struct ETCP_CONN* exclude) {
if (!bgp) return;
DEBUG_TRACE(DEBUG_CATEGORY_BGP, "Broadcasting NODEINFO");
@ -719,8 +731,9 @@ void route_bgp_broadcast_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* exclu
while (e) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data;
if (item->conn && item->conn != exclude) {
route_bgp_send_nodeinfo(bgp->local_node, item->conn);
route_bgp_send_nodeinfo(node, item->conn);
}
e = e->next;
}
}
*/

4
src/route_bgp.h

@ -116,9 +116,9 @@ int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender,
void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn);
/**
* @brief Рассылает local_node NODEINFO всем senders_list кроме exclude.
* @brief Рассылает node NODEINFO всем senders_list кроме exclude.
*/
void route_bgp_broadcast_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* exclude);
//void route_bgp_broadcast_nodeinfo(struct ROUTE_BGP* bgp, struct NODEINFO_Q* node, struct ETCP_CONN* exclude)
/**
* @brief Отправляет WITHDRAW для node_id (вызывает broadcast_withdraw).

13
src/route_lib.c

@ -1,12 +1,13 @@
#include "route_node.h"
#include "route_lib.h"
#include "etcp_debug.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
#include "../lib/platform_compat.h"
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "../lib/debug_config.h"
#include "../lib/mem.h"
#include "../lib/platform_compat.h"
#include "utun_instance.h"
#include "route_node.h"
#include "route_lib.h"
#include "etcp_debug.h"
#define INITIAL_CAPACITY 100

2
src/route_node.c

@ -78,7 +78,7 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
if (!bgp->local_node) {
bgp->local_node = u_calloc(1, sizeof(struct NODEINFO_Q) + dyn);
if (!bgp->local_node) return -1;
bgp->local_node->node.node_id = htobe64(instance->node_id);
bgp->local_node->node.node_id = instance->node_id;
bgp->local_node->node.hop_count = 0;
bgp->local_node->node.ver = 1;
bgp->local_node->dirty = 1;

7
src/route_node.h

@ -55,16 +55,15 @@ struct NODEINFO_PATH {
struct ll_entry ll;
struct ETCP_CONN* conn;
uint8_t hop_count; // hop list: маршрут этого path
} __attribute__((packed));
};// __attribute__((packed));
struct NODEINFO_Q {
struct ll_entry ll;
struct ll_queue* paths;
struct ll_queue* paths; // сюда помещаем struct NODEINFO_PATH
uint8_t dirty;
uint8_t last_ver;
struct NODEINFO node; // Всегда в конце структуры - динамически расширяемый блок
} __attribute__((packed));
};// __attribute__((packed));
/**

Loading…
Cancel
Save