@ -2,11 +2,9 @@
* @ file route_bgp . c
* @ file route_bgp . c
* @ brief BGP - like о б м е н м а р ш р у т а м и — и с п р а в л е н н а я в е р с и я п о д н о в у ю route_lib
* @ brief BGP - like о б м е н м а р ш р у т а м и — и с п р а в л е н н а я в е р с и я п о д н о в у ю route_lib
*/
*/
# include <stdlib.h>
# include <stdlib.h>
# include <string.h>
# include <string.h>
# include "../lib/platform_compat.h"
# include "../lib/platform_compat.h"
# include "route_node.h"
# include "route_node.h"
# include "route_lib.h"
# include "route_lib.h"
# include "route_bgp.h"
# include "route_bgp.h"
@ -19,84 +17,84 @@
# include "../lib/debug_config.h"
# include "../lib/debug_config.h"
# include "../lib/mem.h"
# include "../lib/mem.h"
// ============================================================================
// Вспомогательные функции
// ============================================================================
// ============================================================================
// ============================================================================
// Отправка (только preferred_conn + hop_list)
// Вспомогательные функции
// ============================================================================
// ============================================================================
/* Old route packet sending function removed - using NODEINFO only now */
static void route_bgp_send_table_request ( struct ROUTE_BGP * bgp , struct ETCP_CONN * conn )
{
if ( ! bgp | | ! conn ) {
static void route_bgp_send_table_request ( struct ROUTE_BGP * bgp , struct ETCP_CONN * conn ) {
return ;
if ( ! bgp | | ! conn ) return ;
}
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Sending table request to %s " , conn - > log_name ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Sending table request to %s " , conn - > log_name ) ;
route_bgp_send_nodeinfo ( bgp , conn ) ;
struct BGP_ROUTE_REQUEST * req = u_calloc ( 1 , sizeof ( struct BGP_ROUTE_REQUEST ) ) ;
if ( ! req ) return ;
req - > cmd = ETCP_ID_ROUTE_ENTRY ;
req - > subcmd = ROUTE_SUBCMD_REQUEST_TABLE ;
struct ll_entry * e = queue_entry_new ( 0 ) ;
if ( ! e ) {
u_free ( req ) ;
return ;
}
e - > dgram = ( uint8_t * ) req ;
e - > len = sizeof ( struct BGP_ROUTE_REQUEST ) ;
etcp_send ( conn , e ) ;
}
}
/* Old full table sending removed - now using NODEINFO */
/* Old full table sending removed - now using NODEINFO broadcast now */
// ============================================================================
// ============================================================================
// Broadcast / Withdraw
// Broadcast / Withdraw: node_id - удаляемый узел, wd_source - от кого получена команда удалить
// ============================================================================
// ============================================================================
/* Old broadcast route function removed - using NODEINFO broadcast now */
static void route_bgp_broadcast_withdraw ( struct ROUTE_BGP * bgp , uint64_t node_id , uint64_t wd_source , struct ETCP_CONN * exclude )
{
static void route_bgp_broadcast_withdraw ( struct ROUTE_BGP * bgp , uint64_t node_id ,
struct ETCP_CONN * exclude ) {
if ( ! bgp ) {
if ( ! bgp ) {
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_broadcast_withdraw: bgp is NULL" ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " bgp is NULL " ) ;
return ;
return ;
}
}
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route_bgp_broadcast_withdraw: node_id=%016llx exclude=%p " ,
struct NODEINFO_Q * nq = route_bgp_get_node ( bgp , node_id ) ;
( unsigned long long ) node_id , ( void * ) exclude ) ;
if ( ! nq ) {
DEBUG_WARN ( DEBUG_CATEGORY_BGP , " node not found " ) ;
return ;
}
if ( wd_source ! = 0 & & nq - > paths ) {
}
if ( nq - > paths & & queue_entry_count ( nq - > paths ) = = 0 ) {
if ( bgp - > instance & & bgp - > instance - > rt ) route_delete ( bgp - > instance - > rt , nq ) ;
nq - > dirty = 1 ;
}
struct BGP_WITHDRAW_PACKET * pkt = u_calloc ( 1 , sizeof ( struct BGP_WITHDRAW_PACKET ) ) ;
struct BGP_WITHDRAW_PACKET * pkt = u_calloc ( 1 , sizeof ( struct BGP_WITHDRAW_PACKET ) ) ;
if ( ! pkt ) return ;
if ( ! pkt ) return ;
pkt - > cmd = ETCP_ID_ROUTE_ENTRY ;
pkt - > cmd = ETCP_ID_ROUTE_ENTRY ;
pkt - > subcmd = ROUTE_SUBCMD_WITHDRAW ;
pkt - > subcmd = ROUTE_SUBCMD_WITHDRAW ;
pkt - > node_id = htobe64 ( node_id ) ;
pkt - > node_id = htobe64 ( node_id ) ;
pkt - > wd_source = htobe64 ( wd_source ) ;
struct ll_entry * send_entry = queue_entry_new ( 0 ) ;
struct ll_entry * e = bgp - > senders_list ? bgp - > senders_list - > head : NULL ;
if ( ! send_entry ) { u_free ( pkt ) ; return ; }
send_entry - > dgram = ( uint8_t * ) pkt ;
send_entry - > len = sizeof ( struct BGP_WITHDRAW_PACKET ) ;
struct ll_entry * e = bgp - > senders_list - > head ;
while ( e ) {
while ( e ) {
struct ROUTE_BGP_CONN_ITEM * item = ( struct ROUTE_BGP_CONN_ITEM * ) e - > data ;
struct ROUTE_BGP_CONN_ITEM * item = ( struct ROUTE_BGP_CONN_ITEM * ) e - > data ;
if ( item - > conn ! = exclude ) {
if ( item & & item - > conn & & item - > conn ! = exclude ) {
struct ll_entry * copy = queue_entry_new ( 0 ) ;
struct ll_entry * copy = queue_entry_new ( 0 ) ;
if ( copy ) {
if ( copy ) {
copy - > dgram = u_malloc ( send_entry - > len ) ;
copy - > dgram = u_malloc ( sizeof ( * pkt ) ) ;
memcpy ( copy - > dgram , send_entr y- > dgram , send_entry - > len ) ;
if ( copy - > dgram ) memcpy ( cop y- > dgram , pkt , sizeof ( * pkt ) ) ;
copy - > len = send_entry - > len ;
copy - > len = sizeof ( * pkt ) ;
etcp_send ( item - > conn , copy ) ;
etcp_send ( item - > conn , copy ) ;
}
}
}
}
e = e - > next ;
e = e - > next ;
}
}
queue_entry_free ( send_entry ) ;
u_free ( pkt ) ;
u_free ( pkt ) ;
}
}
// ============================================================================
// Callback на изменение таблицы (insert / update / delete)
// ============================================================================
/* Old route change callback removed - now using NODEINFO updates */
// ============================================================================
// ============================================================================
// Приём пакетов
// Приём пакетов
// ============================================================================
// ============================================================================
static void route_bgp_receive_cbk ( struct ETCP_CONN * from_conn , struct ll_entry * entry ) {
static void route_bgp_receive_cbk ( struct ETCP_CONN * from_conn , struct ll_entry * entry )
{
if ( ! from_conn | | ! entry | | entry - > len < 2 ) {
if ( ! from_conn | | ! entry | | entry - > len < 2 ) {
if ( entry ) {
if ( entry ) {
queue_dgram_free ( entry ) ;
queue_dgram_free ( entry ) ;
@ -130,10 +128,10 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
if ( subcmd = = ROUTE_SUBCMD_NODEINFO ) {
if ( subcmd = = ROUTE_SUBCMD_NODEINFO ) {
route_bgp_process_nodeinfo ( bgp , from_conn , data , entry - > len ) ;
route_bgp_process_nodeinfo ( bgp , from_conn , data , entry - > len ) ;
} else if ( subcmd = = ROUTE_SUBCMD_WITHDRAW ) {
} else if ( subcmd = = ROUTE_SUBCMD_WITHDRAW ) {
route_bgp_process_withdraw ( bgp , data , entry - > len ) ;
route_bgp_process_withdraw ( bgp , from_conn , data , entry - > len ) ;
} else if ( subcmd = = ROUTE_SUBCMD_REQUEST_TABLE ) {
} else if ( subcmd = = ROUTE_SUBCMD_REQUEST_TABLE ) {
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Received table request from %s " , from_conn - > log_name ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Received table request from %s " , from_conn - > log_name ) ;
route_bgp_send_nodeinfo ( bgp , from_conn ) ;
route_bgp_send_nodeinfo ( bgp - > local_node , from_conn ) ; /* всегда отправляем свой local_node */
}
}
queue_dgram_free ( entry ) ;
queue_dgram_free ( entry ) ;
@ -146,7 +144,8 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
// ============================================================================
// ============================================================================
// Callback для готовности ETCP соединения - отправляет маршруты
// Callback для готовности ETCP соединения - отправляет маршруты
static void route_bgp_on_conn_up ( struct ETCP_CONN * conn , void * arg ) {
static void route_bgp_on_conn_up ( struct ETCP_CONN * conn , void * arg )
{
( void ) arg ;
( void ) arg ;
if ( conn & & conn - > instance & & conn - > instance - > bgp ) {
if ( conn & & conn - > instance & & conn - > instance - > bgp ) {
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " BGP ON UP %s " , conn - > log_name ) ;
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " BGP ON UP %s " , conn - > log_name ) ;
@ -155,7 +154,8 @@ static void route_bgp_on_conn_up(struct ETCP_CONN* conn, void* arg) {
}
}
}
}
static void route_bgp_on_conn_down ( struct ETCP_CONN * conn , void * arg ) {
static void route_bgp_on_conn_down ( struct ETCP_CONN * conn , void * arg )
{
( void ) arg ;
( void ) arg ;
if ( conn & & conn - > instance & & conn - > instance - > bgp ) {
if ( conn & & conn - > instance & & conn - > instance - > bgp ) {
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " BGP ON DOWN %s " , conn - > log_name ) ;
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " BGP ON DOWN %s " , conn - > log_name ) ;
@ -165,7 +165,8 @@ static void route_bgp_on_conn_down(struct ETCP_CONN* conn, void* arg) {
}
}
// Callback для новых ETCP соединений - устанавливает ready callback
// Callback для новых ETCP соединений - устанавливает ready callback
static void route_bgp_etcp_conn_cbk ( struct ETCP_CONN * conn , void * arg ) {
static void route_bgp_etcp_conn_cbk ( struct ETCP_CONN * conn , void * arg )
{
( void ) arg ;
( void ) arg ;
if ( conn & & conn - > instance & & conn - > instance - > bgp ) {
if ( conn & & conn - > instance & & conn - > instance - > bgp ) {
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " BGP SET CBKS %s " , conn - > log_name ) ;
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " BGP SET CBKS %s " , conn - > log_name ) ;
@ -175,13 +176,15 @@ static void route_bgp_etcp_conn_cbk(struct ETCP_CONN* conn, void* arg) {
}
}
}
}
struct ROUTE_BGP * route_bgp_init ( struct UTUN_INSTANCE * instance ) {
struct ROUTE_BGP * route_bgp_init ( struct UTUN_INSTANCE * instance )
{
if ( ! instance ) {
if ( ! instance ) {
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_init: instance is NULL " ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_init: instance is NULL " ) ;
return NULL ;
return NULL ;
}
}
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route_bgp_init: node_id=%016llx " , ( unsigned long long ) instance - > node_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route_bgp_init: node_id=%016llx " ,
( unsigned long long ) instance - > node_id ) ;
struct ROUTE_BGP * bgp = u_calloc ( 1 , sizeof ( struct ROUTE_BGP ) ) ;
struct ROUTE_BGP * bgp = u_calloc ( 1 , sizeof ( struct ROUTE_BGP ) ) ;
if ( ! bgp ) {
if ( ! bgp ) {
@ -207,10 +210,27 @@ struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) {
return NULL ;
return NULL ;
}
}
// Build initial my_nodeinfo
int vc = 0 ;
if ( route_bgp_build_my_nodeinfo ( instance , bgp ) ! = 0 ) {
struct CFG_ROUTE_ENTRY * s = instance - > config - > my_subnets ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_init: build_my_nodeinfo failed " ) ;
while ( s ) {
if ( s - > ip . family = = AF_INET ) vc + + ;
s = s - > next ;
}
}
size_t d = vc * sizeof ( struct NODEINFO_IPV4_SUBNET ) ;
bgp - > local_node = u_calloc ( 1 , sizeof ( struct NODEINFO_Q ) + d ) ;
if ( ! bgp - > local_node ) {
queue_free ( bgp - > nodes ) ;
queue_free ( bgp - > senders_list ) ;
u_free ( bgp ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_init: local_node alloc failed " ) ;
return NULL ;
}
bgp - > local_node - > node . node_id = htobe64 ( instance - > node_id ) ;
bgp - > local_node - > node . hop_count = 0 ;
bgp - > local_node - > node . ver = 1 ;
bgp - > local_node - > dirty = 0 ;
route_bgp_update_my_nodeinfo ( instance , bgp ) ;
etcp_bind ( instance , ETCP_ID_ROUTE_ENTRY , route_bgp_receive_cbk ) ;
etcp_bind ( instance , ETCP_ID_ROUTE_ENTRY , route_bgp_receive_cbk ) ;
@ -221,7 +241,8 @@ struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) {
return bgp ;
return bgp ;
}
}
void route_bgp_destroy ( struct UTUN_INSTANCE * instance ) {
void route_bgp_destroy ( struct UTUN_INSTANCE * instance )
{
if ( ! instance ) {
if ( ! instance ) {
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_destroy: instance is NULL " ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_destroy: instance is NULL " ) ;
return ;
return ;
@ -231,32 +252,34 @@ void route_bgp_destroy(struct UTUN_INSTANCE* instance) {
return ;
return ;
}
}
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route_bgp_destroy: node_id=%016llx " , ( unsigned long long ) instance - > node_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route_bgp_destroy: node_id=%016llx " ,
( unsigned long long ) instance - > node_id ) ;
etcp_unbind ( instance , ETCP_ID_ROUTE_ENTRY ) ;
etcp_unbind ( instance , ETCP_ID_ROUTE_ENTRY ) ;
// очистка списка senders
struct ll_entry * e ;
struct ll_entry * e ;
while ( ( e = queue_data_get ( instance - > bgp - > senders_list ) ) ! = NULL ) {
while ( ( e = queue_data_get ( instance - > bgp - > senders_list ) ) ! = NULL ) {
queue_entry_free ( e ) ;
queue_entry_free ( e ) ;
}
}
queue_free ( instance - > bgp - > senders_list ) ;
queue_free ( instance - > bgp - > senders_list ) ;
// очистка nodes
if ( instance - > bgp - > local_node ) {
if ( instance - > bgp - > nodes ) {
if ( instance - > bgp - > local_node - > paths ) {
queue_free ( instance - > bgp - > nodes ) ;
queue_free ( instance - > bgp - > local_node - > paths ) ;
}
u_free ( instance - > bgp - > local_node ) ;
}
}
// Free my_nodeinfo
if ( instance - > bgp - > nodes ) {
if ( instance - > bgp - > my_nodeinfo ) {
queue_free ( instance - > bgp - > nodes ) ;
u_free ( instance - > bgp - > my_nodeinfo ) ;
}
}
u_free ( instance - > bgp ) ;
u_free ( instance - > bgp ) ;
instance - > bgp = NULL ;
instance - > bgp = NULL ;
}
}
void route_bgp_new_conn ( struct ETCP_CONN * conn ) {
void route_bgp_new_conn ( struct ETCP_CONN * conn )
{
if ( ! conn ) {
if ( ! conn ) {
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_new_conn: conn is NULL " ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_new_conn: conn is NULL " ) ;
return ;
return ;
@ -275,7 +298,6 @@ void route_bgp_new_conn(struct ETCP_CONN* conn) {
}
}
struct ROUTE_BGP * bgp = conn - > instance - > bgp ;
struct ROUTE_BGP * bgp = conn - > instance - > bgp ;
struct ROUTE_TABLE * rt = conn - > instance - > rt ;
// === 1. Проверяем, уже есть ли это соединение в списке ===
// === 1. Проверяем, уже есть ли это соединение в списке ===
bool already_exists = false ;
bool already_exists = false ;
@ -292,11 +314,11 @@ void route_bgp_new_conn(struct ETCP_CONN* conn) {
// === 2. Если нет — добавляем (только один раз) ===
// === 2. Если нет — добавляем (только один раз) ===
if ( ! already_exists ) {
if ( ! already_exists ) {
struct ll_entry * item_entry = queue_entry_new ( sizeof ( struct ROUTE_BGP_CONN_ITEM ) ) ;
struct ll_entry * item_entry = queue_entry_new ( sizeof ( struct ROUTE_BGP_CONN_ITEM ) ) ;
if ( ! item_entry ) return ;
if ( ! item_entry ) {
return ;
}
( ( struct ROUTE_BGP_CONN_ITEM * ) item_entry - > data ) - > conn = conn ;
( ( struct ROUTE_BGP_CONN_ITEM * ) item_entry - > data ) - > conn = conn ;
queue_data_put ( bgp - > senders_list , item_entry ) ;
queue_data_put ( bgp - > senders_list , item_entry ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " New connection added to senders_list " ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " New connection added to senders_list " ) ;
}
}
@ -304,7 +326,8 @@ void route_bgp_new_conn(struct ETCP_CONN* conn) {
route_bgp_send_table_request ( bgp , conn ) ;
route_bgp_send_table_request ( bgp , conn ) ;
}
}
void route_bgp_remove_conn ( struct ETCP_CONN * conn ) {
void route_bgp_remove_conn ( struct ETCP_CONN * conn )
{
if ( ! conn ) {
if ( ! conn ) {
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_remove_conn: conn is NULL " ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route_bgp_remove_conn: conn is NULL " ) ;
return ;
return ;
@ -314,8 +337,9 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) {
return ;
return ;
}
}
// SAFETY: проверяем что conn ещё есть в senders_list
struct ROUTE_BGP * bgp = conn - > instance - > bgp ;
struct ROUTE_BGP * bgp = conn - > instance - > bgp ;
// SAFETY: проверяем что conn ещё есть в senders_list
bool found_in_list = false ;
bool found_in_list = false ;
struct ll_entry * e = bgp - > senders_list - > head ;
struct ll_entry * e = bgp - > senders_list - > head ;
while ( e ) {
while ( e ) {
@ -332,7 +356,8 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) {
return ;
return ;
}
}
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route_bgp_remove_conn: peer=%016llx " , ( unsigned long long ) conn - > peer_node_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route_bgp_remove_conn: peer=%016llx " ,
( unsigned long long ) conn - > peer_node_id ) ;
struct ROUTE_TABLE * rt = conn - > instance - > rt ;
struct ROUTE_TABLE * rt = conn - > instance - > rt ;
@ -341,7 +366,7 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) {
bool need_withdraw = false ;
bool need_withdraw = false ;
struct ll_entry * node_entry = bgp - > nodes ? bgp - > nodes - > head : NULL ;
struct ll_entry * node_entry = bgp - > nodes ? bgp - > nodes - > head : NULL ;
while ( node_entry ) {
while ( node_entry ) {
struct NODEINFO_Q * nq = ( struct NODEINFO_Q * ) node_entry - > data ;
struct NODEINFO_Q * nq = ( struct NODEINFO_Q * ) node_entry ;
if ( route_bgp_remove_path ( nq , conn ) = = 1 ) {
if ( route_bgp_remove_path ( nq , conn ) = = 1 ) {
need_withdraw = true ;
need_withdraw = true ;
if ( rt ) {
if ( rt ) {
@ -364,37 +389,96 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) {
}
}
if ( need_withdraw ) {
if ( need_withdraw ) {
route_bgp_send _withdraw ( bgp , conn - > peer_node_id ) ;
route_bgp_broadcast _withdraw ( bgp , conn - > peer_node_id , conn - > instance - > node_id , NULL ) ;
}
}
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Connection removed, paths updated " ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Connection removed, paths updated " ) ;
}
}
/* ================================================
/* ================================================
* NEW NODEINFO BASED IMPLEMENTATION
* NEW NODEINFO BASED IMPLEMENTATION
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
struct NODEINFO_Q * route_bgp_get_node ( struct ROUTE_BGP * bgp , uint64_t node_id ) {
struct NODEINFO_Q * route_bgp_get_node ( struct ROUTE_BGP * bgp , uint64_t node_id )
if ( ! bgp | | ! bgp - > nodes ) return NULL ;
{
if ( ! bgp | | ! bgp - > nodes ) {
return NULL ;
}
uint64_t key = htobe64 ( node_id ) ;
uint64_t key = htobe64 ( node_id ) ;
struct ll_entry * e = queue_find_data_by_index ( bgp - > nodes , & key , 8 ) ;
struct ll_entry * e = queue_find_data_by_index ( bgp - > nodes , & key , 8 ) ;
return e ? ( struct NODEINFO_Q * ) e - > data : NULL ;
return e ? ( struct NODEINFO_Q * ) e : NULL ;
}
}
int route_bgp_add_path ( struct NODEINFO_Q * nq , struct ETCP_CONN * conn ) {
int route_bgp_add_path ( struct NODEINFO_Q * nq , struct ETCP_CONN * conn , uint64_t * hop_list , uint8_t hop_count )
if ( ! nq | | ! conn ) return - 1 ;
{
DEBUG_TRACE ( DEBUG_CATEGORY_BGP , " Added path for node %016llx via conn %s " ,
if ( ! nq | | ! conn | | hop_count > MAX_HOPS | | ! hop_list ) {
( unsigned long long ) nq - > node . node_id , conn - > log_name ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " add_path: invalid args " ) ;
return - 1 ;
}
if ( ! nq - > paths ) {
nq - > paths = queue_new ( conn - > instance - > ua , 32 , " node_paths " ) ;
if ( ! nq - > paths ) return - 1 ;
}
size_t hop_size = hop_count * 8 ;
size_t path_size = sizeof ( struct NODEINFO_PATH ) - sizeof ( struct ll_entry ) + hop_size ;
struct ll_entry * pe = queue_entry_new ( path_size ) ;
if ( ! pe ) return - 1 ;
struct NODEINFO_PATH * path = ( struct NODEINFO_PATH * ) pe ;
path - > conn = conn ;
path - > hop_count = hop_count ;
uint64_t * stored = ( uint64_t * ) ( ( uint8_t * ) path + sizeof ( struct NODEINFO_PATH ) ) ;
memcpy ( stored , hop_list , hop_size ) ;
queue_data_put ( nq - > paths , pe ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_BGP , " Added path for node %016llx via conn %s with %d hops " , ( unsigned long long ) nq - > node . node_id , conn - > log_name , hop_count ) ;
return 0 ;
return 0 ;
}
}
int route_bgp_remove_path ( struct NODEINFO_Q * nq , struct ETCP_CONN * conn ) {
int route_bgp_remove_path_by_hop ( struct NODEINFO_Q * nq , uint64_t wd_source ) {
if ( ! nq | | ! conn | | ! nq - > paths ) return - 1 ;
if ( ! nq | | ! nq - > paths ) return 0 ;
int removed = 0 ;
struct ll_entry * e = nq - > paths - > head ;
while ( e ) {
struct NODEINFO_PATH * path = ( struct NODEINFO_PATH * ) e ;
// parse hoplist in dyn after hop_count (after fixed PATH)
uint64_t * hop = ( uint64_t * ) ( ( uint8_t * ) path + sizeof ( struct NODEINFO_PATH ) ) ;
bool has_wd = false ;
for ( uint8_t i = 0 ; i < path - > hop_count ; i + + ) {
if ( hop [ i ] = = wd_source ) {
has_wd = true ;
break ;
}
}
if ( has_wd ) {
struct ll_entry * next = e - > next ;
queue_remove_data ( nq - > paths , e ) ;
queue_entry_free ( e ) ;
removed + + ;
e = next ;
continue ;
}
e = e - > next ;
}
if ( removed > 0 & & nq - > paths & & queue_entry_count ( nq - > paths ) = = 0 ) {
queue_free ( nq - > paths ) ;
nq - > paths = NULL ;
return 1 ; // unreachable
}
return removed ;
}
int route_bgp_remove_path ( struct NODEINFO_Q * nq , struct ETCP_CONN * conn )
{
if ( ! nq | | ! conn | | ! nq - > paths ) {
return - 1 ;
}
// Remove conn from paths queue
// Remove conn from paths queue
struct ll_entry * e = nq - > paths - > head ;
struct ll_entry * e = nq - > paths - > head ;
while ( e ) {
while ( e ) {
if ( e - > data = = ( void * ) conn ) {
struct NODEINFO_PATH * path = ( struct NODEINFO_PATH * ) e ;
if ( path - > conn = = conn ) {
queue_remove_data ( nq - > paths , e ) ;
queue_remove_data ( nq - > paths , e ) ;
queue_entry_free ( e ) ;
queue_entry_free ( e ) ;
break ;
break ;
@ -403,7 +487,6 @@ int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn) {
}
}
int remaining = nq - > paths ? queue_entry_count ( nq - > paths ) : 0 ;
int remaining = nq - > paths ? queue_entry_count ( nq - > paths ) : 0 ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Removed path for node %016llx via %s, remaining paths: %d " ,
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Removed path for node %016llx via %s, remaining paths: %d " ,
( unsigned long long ) nq - > node . node_id , conn - > log_name , remaining ) ;
( unsigned long long ) nq - > node . node_id , conn - > log_name , remaining ) ;
@ -415,13 +498,15 @@ int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn) {
}
}
return 1 ; // signal that node became unreachable
return 1 ; // signal that node became unreachable
}
}
return 0 ;
return 0 ;
}
}
int route_bgp_process_nodeinfo ( struct ROUTE_BGP * bgp , struct ETCP_CONN * from ,
int route_bgp_process_nodeinfo ( struct ROUTE_BGP * bgp , struct ETCP_CONN * from ,
const uint8_t * data , size_t len ) {
const uint8_t * data , size_t len )
if ( ! bgp | | ! from | | len < sizeof ( struct BGP_NODEINFO_PACKET ) ) return - 1 ;
{
if ( ! bgp | | ! from | | len < sizeof ( struct BGP_NODEINFO_PACKET ) ) {
return - 1 ;
}
struct BGP_NODEINFO_PACKET * pkt = ( struct BGP_NODEINFO_PACKET * ) data ;
struct BGP_NODEINFO_PACKET * pkt = ( struct BGP_NODEINFO_PACKET * ) data ;
struct NODEINFO * ni = & pkt - > node ;
struct NODEINFO * ni = & pkt - > node ;
@ -443,91 +528,152 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from,
}
}
if ( ! existing ) {
if ( ! existing ) {
struct ll_entry * entry = queue_entry_new ( sizeof ( struct NODEINFO_Q ) ) ;
size_t dyn = len - sizeof ( struct BGP_NODEINFO_PACKET ) + 8 ;
if ( ! entry ) return - 1 ;
struct ll_entry * entry = queue_entry_new ( sizeof ( struct NODEINFO_Q ) + dyn ) ;
existing = ( struct NODEINFO_Q * ) entry - > data ;
if ( ! entry ) {
return - 1 ;
}
existing = ( struct NODEINFO_Q * ) entry ;
existing - > paths = queue_new ( bgp - > instance - > ua , 32 , " node_paths " ) ;
existing - > paths = queue_new ( bgp - > instance - > ua , 32 , " node_paths " ) ;
queue_data_put ( bgp - > nodes , entry ) ;
queue_data_put_with_index ( bgp - > nodes , entry , offsetof ( struct NODEINFO_Q , node . node_id ) , 8 ) ;
}
}
memcpy ( & existing - > node , ni , sizeof ( struct NODEINFO ) ) ;
memcpy ( & existing - > node , ni , sizeof ( struct NODEINFO ) ) ;
existing - > last_ver = new_ver ;
existing - > last_ver = new_ver ;
route_bgp_add_path ( existing , from ) ;
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 ) ;
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 ;
if ( ni - > hop_count > 0 ) {
route_bgp_add_path ( existing , from , ( uint64_t * ) hop_dest , existing - > node . hop_count ) ;
}
if ( bgp - > instance - > rt ) {
if ( bgp - > instance - > rt ) {
route_insert ( bgp - > instance - > rt , existing ) ;
route_insert ( bgp - > instance - > rt , existing ) ;
}
}
// Пересылаем дальше (увеличиваем hop_count)
if ( ni - > hop_count < MAX_HOPS - 1 ) {
if ( ni - > hop_count < MAX_HOPS - 1 ) {
ni - > hop_count + + ;
ni - > hop_count + + ;
route_bgp_broadcast_nodeinfo ( bgp , from ) ;
route_bgp_broadcast_nodeinfo ( bgp , from ) ;
ni - > hop_count - - ; // возвращаем назад
ni - > hop_count - - ;
}
}
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Processed NODEINFO from %s (node=%016llx, ver=%d, paths=%d) " ,
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 ,
from - > log_name , ( unsigned long long ) node_id , new_ver ,
existing - > paths ? queue_entry_count ( existing - > paths ) : 0 ) ;
existing - > paths ? queue_entry_count ( existing - > paths ) : 0 ) ;
return 0 ;
return 0 ;
}
}
int route_bgp_process_withdraw ( struct ROUTE_BGP * bgp , const uint8_t * data , size_t len ) {
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 ;
struct BGP_WITHDRAW_PACKET * wp = ( struct BGP_WITHDRAW_PACKET * ) data ;
uint64_t node_id = be64toh ( wp - > node_id ) ;
uint64_t node_id = be64toh ( wp - > node_id ) ;
uint64_t wd_source = be64toh ( wp - > wd_source ) ;
struct NODEINFO_Q * nq = route_bgp_get_node ( bgp , node_id ) ;
struct NODEINFO_Q * nq = route_bgp_get_node ( bgp , node_id ) ;
if ( nq ) {
if ( ! nq ) {
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " node not found " ) ;
return 0 ;
}
int ret = route_bgp_remove_path_by_hop ( nq , wd_source ) ;
if ( ret > 0 ) {
if ( bgp - > instance & & bgp - > instance - > rt ) {
if ( bgp - > instance & & bgp - > instance - > rt ) {
route_delete ( bgp - > instance - > rt , nq ) ;
route_delete ( bgp - > instance - > rt , nq ) ;
}
}
if ( nq - > paths ) {
if ( nq - > paths ) {
queue_free ( nq - > paths ) ;
queue_free ( nq - > paths ) ;
}
}
// TODO: remove from nodes queue
uint64_t key = htobe64 ( node_id ) ;
struct ll_entry * entry = queue_find_data_by_index ( bgp - > nodes , & key , 8 ) ;
if ( entry ) {
queue_remove_data ( bgp - > nodes , entry ) ;
queue_entry_free ( entry ) ;
}
nq - > dirty = 1 ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Removed node %016llx after WITHDRAW " , ( unsigned long long ) node_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Removed node %016llx after WITHDRAW " , ( unsigned long long ) node_id ) ;
route_bgp_broadcast_withdraw ( bgp , node_id , wd_source , sender ) ;
}
}
route_bgp_broadcast_withdraw ( bgp , node_id , NULL ) ;
return 0 ;
return 0 ;
}
}
void route_bgp_send_nodeinfo ( struct ROUTE_BGP * bgp , struct ETCP_CONN * conn ) {
/**
if ( ! bgp | | ! conn | | ! bgp - > my_nodeinfo ) return ;
* @ brief О т п р а в к а NODEINFO - п а к е т а ( в с е г д а о т п р а в л я е м local_node )
* С и г н а т у р а с о о т в е т с т в у е т о б ъ я в л е н и ю в route_bgp . h
*/
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 ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Sending NODEINFO to %s " , conn - > log_name ) ;
struct ll_entry * entry = queue_entry_new ( 0 ) ;
size_t nl = node - > node . node_name_len ;
if ( ! entry ) return ;
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 ;
size_t ps = sizeof ( struct BGP_NODEINFO_PACKET ) + dyn ;
uint8_t * p = u_malloc ( ps ) ;
if ( ! p ) {
return ;
}
entry - > dgram = u_malloc ( bgp - > my_nodeinfo_size ) ;
p [ 0 ] = ETCP_ID_ROUTE_ENTRY ;
if ( ! entry - > dgram ) {
p [ 1 ] = ROUTE_SUBCMD_NODEINFO ;
queue_entry_free ( entry ) ;
memcpy ( p + 2 , & node - > node , sizeof ( struct NODEINFO ) ) ;
uint8_t * ds = ( uint8_t * ) & node - > node + sizeof ( struct NODEINFO ) ;
memcpy ( p + sizeof ( struct BGP_NODEINFO_PACKET ) , ds , dyn ) ;
struct ll_entry * e = queue_entry_new ( 0 ) ;
if ( ! e ) {
u_free ( p ) ;
return ;
return ;
}
}
memcpy ( entry - > dgram , bgp - > my_nodeinfo , bgp - > my_nodeinfo_size ) ;
entry - > len = bgp - > my_nodeinfo_size ;
etcp_send ( conn , entry ) ;
e - > dgram = p ;
e - > len = ps ;
etcp_send ( conn , e ) ;
}
}
void route_bgp_broadcast_nodeinfo ( struct ROUTE_BGP * bgp , struct ETCP_CONN * exclude ) {
void route_bgp_broadcast_nodeinfo ( struct ROUTE_BGP * bgp , struct ETCP_CONN * exclude ) {
if ( ! bgp ) return ;
if ( ! bgp ) {
return ;
}
DEBUG_TRACE ( DEBUG_CATEGORY_BGP , " Broadcasting NODEINFO " ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_BGP , " Broadcasting NODEINFO " ) ;
struct ll_entry * e = bgp - > senders_list ? bgp - > senders_list - > head : NULL ;
struct ll_entry * e = bgp - > senders_list ? bgp - > senders_list - > head : NULL ;
while ( e ) {
while ( e ) {
struct ROUTE_BGP_CONN_ITEM * item = ( struct ROUTE_BGP_CONN_ITEM * ) e - > data ;
struct ROUTE_BGP_CONN_ITEM * item = ( struct ROUTE_BGP_CONN_ITEM * ) e - > data ;
if ( item - > conn & & item - > conn ! = exclude ) {
if ( item - > conn & & item - > conn ! = exclude ) {
route_bgp_send_nodeinfo ( bgp , item - > conn ) ;
route_bgp_send_nodeinfo ( bgp - > local_node , item - > conn ) ;
}
}
e = e - > next ;
e = e - > next ;
}
}
}
}
void route_bgp_send_withdraw ( struct ROUTE_BGP * bgp , uint64_t node_id ) {
if ( ! bgp ) return ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Sending WITHDRAW for node %016llx " , ( unsigned long long ) node_id ) ;
}