|
|
|
|
@ -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); |
|
|
|
|
need_alloc=1; |
|
|
|
|
} |
|
|
|
|
} else need_alloc=1; |
|
|
|
|
|
|
|
|
|
memcpy(&existing->node, ni, sizeof(struct NODEINFO)); |
|
|
|
|
existing->last_ver = new_ver; |
|
|
|
|
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* 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); |
|
|
|
|
// 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++; |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
// 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 (ni->hop_count >= 0) { |
|
|
|
|
route_bgp_add_path(existing, from, (uint64_t*)hop_dest, existing->node.hop_count); |
|
|
|
|
if (bgp->instance->rt) { |
|
|
|
|
route_insert(bgp->instance->rt, nodeinfo1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (bgp->instance->rt) { |
|
|
|
|
route_insert(bgp->instance->rt, existing); |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
if (ni->hop_count < MAX_HOPS - 1) { |
|
|
|
|
ni->hop_count++; |
|
|
|
|
route_bgp_broadcast_nodeinfo(bgp, from); |
|
|
|
|
ni->hop_count--; |
|
|
|
|
} |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
|