@ -37,19 +37,47 @@
// Вспомогательные функции
// Вспомогательные функции
// ============================================================================
// ============================================================================
static struct TOPO_GROUP_CONN_ITEM * topo_group_peer ( const struct TOPO_GROUP * group , uint64_t peer_id ) {
for ( struct ll_entry * e = group & & group - > senders_list ? group - > senders_list - > head : NULL ; e ; e = e - > next ) {
struct TOPO_GROUP_CONN_ITEM * item = ( struct TOPO_GROUP_CONN_ITEM * ) e - > data ;
if ( item - > conn & & item - > conn - > peer_node_id = = peer_id ) return item ;
}
return NULL ;
}
int topo_group_peer_ready ( const struct TOPO_GROUP * group , uint64_t peer_id ) {
const struct TOPO_GROUP_CONN_ITEM * peer = topo_group_peer ( group , peer_id ) ;
return peer & & peer - > conn - > links_up & & peer - > table_received & & peer - > table_sent ;
}
static void topo_group_log_exchange ( struct TOPO_GROUP * group , struct TOPO_GROUP_CONN_ITEM * peer ) {
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " group exchange: group=%016llx peer=%016llx exchange=%016llx sent=%u received=%u ready=%d " ,
( unsigned long long ) group - > group_id , ( unsigned long long ) peer - > conn - > peer_node_id ,
( unsigned long long ) peer - > exchange_id , peer - > table_sent , peer - > table_received ,
topo_group_peer_ready ( group , peer - > conn - > peer_node_id ) ) ;
}
/* Шлёт пиру запрос полной таблицы узлов группы (REQUEST_TABLE). */
/* Шлёт пиру запрос полной таблицы узлов группы (REQUEST_TABLE). */
static void topo_group_send_table_request ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) {
static void topo_group_send_table_request ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) {
if ( ! group | | ! conn ) return ;
if ( ! group | | ! conn ) return ;
struct TOPO_GROUP_CONN_ITEM * peer = topo_group_peer ( group , conn - > peer_node_id ) ;
if ( ! peer | | peer - > conn ! = conn ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " table request without group peer " ) ; return ; }
if ( ! peer - > exchange_id & & ( random_bytes ( ( uint8_t * ) & peer - > exchange_id , sizeof ( peer - > exchange_id ) ) ! = 0 | | ! peer - > exchange_id ) ) {
peer - > exchange_id = 0 ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " cannot generate group exchange id group=%016llx " , ( unsigned long long ) group - > group_id ) ;
return ;
}
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " Sending table request to %s grp=%016llx " , conn - > log_name , ( unsigned long long ) group - > group_id ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " Sending table request to %s grp=%016llx " , conn - > log_name , ( unsigned long long ) group - > group_id ) ;
struct TOPOMSG_TABLE_REQ * req = u_calloc ( 1 , sizeof ( struct TOPOMSG_TABLE_REQ ) ) ;
struct TOPOMSG_TABLE_REQ * req = u_calloc ( 1 , sizeof ( struct TOPOMSG_TABLE_REQ ) ) ;
if ( ! req ) return ;
if ( ! req ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " table request allocation failed " ) ; return ; }
req - > cmd = ETCP_ID_TOPO_ENTRY ;
req - > cmd = ETCP_ID_TOPO_ENTRY ;
req - > subcmd = TOPO_SUBCMD_REQUEST_TABLE ;
req - > subcmd = TOPO_SUBCMD_REQUEST_TABLE ;
req - > group_id = group - > group_id ;
req - > group_id = group - > group_id ;
req - > exchange_id = peer - > exchange_id ;
struct ll_entry * e = queue_entry_new ( 0 ) ;
struct ll_entry * e = queue_entry_new ( 0 ) ;
if ( ! e ) { u_free ( req ) ; return ; }
if ( ! e ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " table request entry allocation failed " ) ; u_free ( req ) ; return ; }
e - > dgram = ( uint8_t * ) req ; e - > len = sizeof ( struct TOPOMSG_TABLE_REQ ) ;
e - > dgram = ( uint8_t * ) req ; e - > len = sizeof ( struct TOPOMSG_TABLE_REQ ) ;
if ( etcp_send ( conn , e ) ! = 0 ) { u_free ( req ) ; queue_entry_free ( e ) ; }
if ( etcp_send ( conn , e ) ! = 0 ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " cannot send table request " ) ; u_free ( req ) ; queue_entry_free ( e ) ; }
}
}
/* Запрашивает у пира членство в группе (JOIN_GROUP). */
/* Запрашивает у пира членство в группе (JOIN_GROUP). */
@ -82,32 +110,37 @@ static void topo_group_send_resync(struct ETCP_CONN* conn) {
}
}
/* Сигнализирует пиру об окончании начальной синхронизации таблицы. */
/* Сигнализирует пиру об окончании начальной синхронизации таблицы. */
static void topo_group_send_table_complete ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) {
static int topo_group_send_table_complete ( struct TOPO_GROUP * group , struct ETCP_CONN * conn , uint64_t exchange_id ) {
if ( ! group | | ! conn ) return ;
struct TOPOMSG_TABLE_REQ * req = u_calloc ( 1 , sizeof ( struct TOPOMSG_TABLE_REQ ) ) ;
struct TOPOMSG_TABLE_REQ * req = u_calloc ( 1 , sizeof ( struct TOPOMSG_TABLE_REQ ) ) ;
if ( ! req ) return ;
if ( ! req ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " table complete allocation failed " ) ; return - 1 ; }
req - > cmd = ETCP_ID_TOPO_ENTRY ;
req - > cmd = ETCP_ID_TOPO_ENTRY ;
req - > subcmd = TOPO_SUBCMD_TABLE_COMPLETE ;
req - > subcmd = TOPO_SUBCMD_TABLE_COMPLETE ;
req - > group_id = group - > group_id ;
req - > group_id = group - > group_id ;
req - > exchange_id = exchange_id ;
struct ll_entry * e = queue_entry_new ( 0 ) ;
struct ll_entry * e = queue_entry_new ( 0 ) ;
if ( ! e ) { u_free ( req ) ; return ; }
if ( ! e ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " table complete entry allocation failed " ) ; u_free ( req ) ; return - 1 ; }
e - > dgram = ( uint8_t * ) req ; e - > len = sizeof ( struct TOPOMSG_TABLE_REQ ) ;
e - > dgram = ( uint8_t * ) req ; e - > len = sizeof ( struct TOPOMSG_TABLE_REQ ) ;
if ( etcp_send ( conn , e ) ! = 0 ) { u_free ( req ) ; queue_entry_free ( e ) ; }
if ( etcp_send ( conn , e ) ! = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " cannot send table complete " ) ; u_free ( req ) ; queue_entry_free ( e ) ; return - 1 ;
}
return 0 ;
}
}
static int topo_group_add_to_senders ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) ;
static int topo_group_add_to_senders ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) ;
static bool topo_group_should_send_to ( const struct TOPO_GROUP_NODE * nq , uint64_t target_id ) ;
static bool topo_group_should_send_to ( const struct TOPO_GROUP_NODE * nq , uint64_t target_id ) ;
static void topo_group_send_full_table ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) ;
static int topo_group_send_full_table ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) ;
static void topo_group_handle_request_table ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) ;
static void topo_group_handle_request_table ( struct TOPO_GROUP * group , struct ETCP_CONN * conn , uint64_t exchange_id ) ;
static void topo_group_handle_join_group ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) ;
static void topo_group_handle_join_group ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) ;
static void topo_group_send_resync ( struct ETCP_CONN * conn ) ;
static void topo_group_send_resync ( struct ETCP_CONN * conn ) ;
static void topo_group_handle_resync ( struct UTUN_INSTANCE * instance , struct ETCP_CONN * conn ) ;
static void topo_group_handle_resync ( struct UTUN_INSTANCE * instance , struct ETCP_CONN * conn ) ;
/* Запоминает REQUEST_TABLE для группы, которой у нас ещё нет (CHAT-канал не загружен). */
/* Запоминает REQUEST_TABLE для группы, которой у нас ещё нет (CHAT-канал не загружен). */
static void topo_group_remember_table_req ( struct TOPO_GROUPS * g , uint64_t node_id , uint64_t group_id ) {
static void topo_group_remember_table_req ( struct TOPO_GROUPS * g , uint64_t node_id , uint64_t group_id , uint64_t exchange_id ) {
if ( ! g ) return ;
if ( ! g ) return ;
for ( int i = 0 ; i < g - > pending_table_req_count ; i + + )
for ( int i = 0 ; i < g - > pending_table_req_count ; i + + )
if ( g - > pending_table_reqs [ i ] . node_id = = node_id & & g - > pending_table_reqs [ i ] . group_id = = group_id ) return ;
if ( g - > pending_table_reqs [ i ] . node_id = = node_id & & g - > pending_table_reqs [ i ] . group_id = = group_id ) {
g - > pending_table_reqs [ i ] . exchange_id = exchange_id ; return ;
}
if ( g - > pending_table_req_count > = TOPO_MAX_PENDING_TABLE_REQS ) {
if ( g - > pending_table_req_count > = TOPO_MAX_PENDING_TABLE_REQS ) {
memmove ( g - > pending_table_reqs , g - > pending_table_reqs + 1 ,
memmove ( g - > pending_table_reqs , g - > pending_table_reqs + 1 ,
( TOPO_MAX_PENDING_TABLE_REQS - 1 ) * sizeof ( g - > pending_table_reqs [ 0 ] ) ) ;
( TOPO_MAX_PENDING_TABLE_REQS - 1 ) * sizeof ( g - > pending_table_reqs [ 0 ] ) ) ;
@ -115,6 +148,7 @@ static void topo_group_remember_table_req(struct TOPO_GROUPS* g, uint64_t node_i
}
}
g - > pending_table_reqs [ g - > pending_table_req_count ] . node_id = node_id ;
g - > pending_table_reqs [ g - > pending_table_req_count ] . node_id = node_id ;
g - > pending_table_reqs [ g - > pending_table_req_count ] . group_id = group_id ;
g - > pending_table_reqs [ g - > pending_table_req_count ] . group_id = group_id ;
g - > pending_table_reqs [ g - > pending_table_req_count ] . exchange_id = exchange_id ;
g - > pending_table_req_count + + ;
g - > pending_table_req_count + + ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " remembered table request node=%016llx grp=%016llx (group not created yet) " ,
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " remembered table request node=%016llx grp=%016llx (group not created yet) " ,
( unsigned long long ) node_id , ( unsigned long long ) group_id ) ;
( unsigned long long ) node_id , ( unsigned long long ) group_id ) ;
@ -133,7 +167,7 @@ static void topo_group_fulfill_table_reqs(struct TOPO_GROUPS* g, uint64_t group_
if ( conn & & conn - > links_up ) {
if ( conn & & conn - > links_up ) {
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " fulfilling remembered table request node=%016llx grp=%016llx " ,
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " fulfilling remembered table request node=%016llx grp=%016llx " ,
( unsigned long long ) req - > node_id , ( unsigned long long ) group_id ) ;
( unsigned long long ) req - > node_id , ( unsigned long long ) group_id ) ;
topo_group_handle_request_table ( group , conn ) ;
topo_group_handle_request_table ( group , conn , req - > exchange_id ) ;
}
}
}
}
g - > pending_table_req_count = w ;
g - > pending_table_req_count = w ;
@ -259,6 +293,13 @@ static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ;
}
}
if ( ( subcmd = = TOPO_SUBCMD_REQUEST_TABLE | | subcmd = = TOPO_SUBCMD_TABLE_COMPLETE ) & &
( entry - > len ! = sizeof ( struct TOPOMSG_TABLE_REQ ) | | ! ( ( struct TOPOMSG_TABLE_REQ * ) data ) - > exchange_id ) ) {
DEBUG_WARN ( DEBUG_CATEGORY_BGP , " invalid table control peer=%016llx cmd=%u length=%u " ,
( unsigned long long ) from_conn - > peer_node_id , subcmd , entry - > len ) ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ;
}
uint64_t pkt_group_id = 0 ;
uint64_t pkt_group_id = 0 ;
if ( subcmd = = TOPO_SUBCMD_NODEINFO & & entry - > len > = sizeof ( struct TOPOMSG_NODEINFO_PKT ) ) {
if ( subcmd = = TOPO_SUBCMD_NODEINFO & & entry - > len > = sizeof ( struct TOPOMSG_NODEINFO_PKT ) ) {
pkt_group_id = ( ( struct TOPOMSG_NODEINFO_PKT * ) data ) - > node . group_id ;
pkt_group_id = ( ( struct TOPOMSG_NODEINFO_PKT * ) data ) - > node . group_id ;
@ -278,7 +319,8 @@ static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
struct TOPO_GROUP * group = topo_groups_find ( instance - > topo_groups , pkt_group_id ) ;
struct TOPO_GROUP * group = topo_groups_find ( instance - > topo_groups , pkt_group_id ) ;
if ( ! group ) {
if ( ! group ) {
if ( subcmd = = TOPO_SUBCMD_REQUEST_TABLE )
if ( subcmd = = TOPO_SUBCMD_REQUEST_TABLE )
topo_group_remember_table_req ( instance - > topo_groups , from_conn - > peer_node_id , pkt_group_id ) ;
topo_group_remember_table_req ( instance - > topo_groups , from_conn - > peer_node_id , pkt_group_id ,
( ( struct TOPOMSG_TABLE_REQ * ) data ) - > exchange_id ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " BGP recv %s from %s: group %016llx not found, dropping " , group_subcmd_name ( subcmd ) , from_conn - > log_name , ( unsigned long long ) pkt_group_id ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " BGP recv %s from %s: group %016llx not found, dropping " , group_subcmd_name ( subcmd ) , from_conn - > log_name , ( unsigned long long ) pkt_group_id ) ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ;
}
}
@ -302,14 +344,25 @@ static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
if ( subcmd = = TOPO_SUBCMD_NODEINFO ) { nodeinfo_dump_log ( data , entry - > len ) ; topo_group_process_nodeinfo ( group , from_conn , data , entry - > len ) ; }
if ( subcmd = = TOPO_SUBCMD_NODEINFO ) { nodeinfo_dump_log ( data , entry - > len ) ; topo_group_process_nodeinfo ( group , from_conn , data , entry - > len ) ; }
else if ( subcmd = = TOPO_SUBCMD_WITHDRAW ) topo_group_process_withdraw ( group , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_WITHDRAW ) topo_group_process_withdraw ( group , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_REQUEST_TABLE ) topo_group_handle_request_table ( group , from_conn ) ;
else if ( subcmd = = TOPO_SUBCMD_REQUEST_TABLE )
topo_group_handle_request_table ( group , from_conn , ( ( struct TOPOMSG_TABLE_REQ * ) data ) - > exchange_id ) ;
else if ( subcmd = = TOPO_SUBCMD_JOIN_GROUP ) topo_group_handle_join_group ( group , from_conn ) ;
else if ( subcmd = = TOPO_SUBCMD_JOIN_GROUP ) topo_group_handle_join_group ( group , from_conn ) ;
else if ( subcmd = = TOPO_SUBCMD_LEAVE_GROUP ) {
else if ( subcmd = = TOPO_SUBCMD_LEAVE_GROUP ) {
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " peer left group: peer=%016llx group=%016llx " ,
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " peer left group: peer=%016llx group=%016llx " ,
( unsigned long long ) from_conn - > peer_node_id , ( unsigned long long ) group - > group_id ) ;
( unsigned long long ) from_conn - > peer_node_id , ( unsigned long long ) group - > group_id ) ;
topo_group_remove_conn ( group , from_conn , TOPO_REMOVE_REMOTE_LEAVE ) ;
topo_group_remove_conn ( group , from_conn , TOPO_REMOVE_REMOTE_LEAVE ) ;
}
}
else if ( subcmd = = TOPO_SUBCMD_TABLE_COMPLETE ) { etcp_set_routing_exchange_state ( from_conn , 3 ) ; DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP sync complete with %s: %d nodes grp=%016llx " , from_conn - > log_name , queue_entry_count ( group - > nodes ) , ( unsigned long long ) group - > group_id ) ; }
else if ( subcmd = = TOPO_SUBCMD_TABLE_COMPLETE ) {
struct TOPO_GROUP_CONN_ITEM * peer = topo_group_peer ( group , from_conn - > peer_node_id ) ;
uint64_t id = ( ( struct TOPOMSG_TABLE_REQ * ) data ) - > exchange_id ;
if ( ! peer | | peer - > conn ! = from_conn | | peer - > exchange_id ! = id ) {
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " ignore stale TABLE_COMPLETE group=%016llx peer=%016llx exchange=%016llx " ,
( unsigned long long ) group - > group_id , ( unsigned long long ) from_conn - > peer_node_id , ( unsigned long long ) id ) ;
} else if ( ! peer - > table_received ) {
peer - > table_received = 1 ;
topo_group_log_exchange ( group , peer ) ;
}
}
else if ( subcmd = = TOPO_SUBCMD_ERR_GROUP_MISMATCH ) {
else if ( subcmd = = TOPO_SUBCMD_ERR_GROUP_MISMATCH ) {
if ( entry - > len > = sizeof ( struct TOPOMSG_ERR_GROUP_MISMATCH ) ) {
if ( entry - > len > = sizeof ( struct TOPOMSG_ERR_GROUP_MISMATCH ) ) {
struct TOPOMSG_ERR_GROUP_MISMATCH * err = ( struct TOPOMSG_ERR_GROUP_MISMATCH * ) data ;
struct TOPOMSG_ERR_GROUP_MISMATCH * err = ( struct TOPOMSG_ERR_GROUP_MISMATCH * ) data ;
@ -336,7 +389,9 @@ static void topo_group_conn_status(struct ETCP_CONN* conn, int status, void* arg
for ( struct ll_entry * e = groups - > group_list - > head ; e ; e = e - > next ) {
for ( struct ll_entry * e = groups - > group_list - > head ; e ; e = e - > next ) {
struct TOPO_GROUP * g = ( struct TOPO_GROUP * ) e ;
struct TOPO_GROUP * g = ( struct TOPO_GROUP * ) e ;
for ( struct ll_entry * se = g - > senders_list - > head ; se ; se = se - > next ) {
for ( struct ll_entry * se = g - > senders_list - > head ; se ; se = se - > next ) {
if ( ( ( struct TOPO_GROUP_CONN_ITEM * ) se - > data ) - > conn ! = conn ) continue ;
struct TOPO_GROUP_CONN_ITEM * peer = ( struct TOPO_GROUP_CONN_ITEM * ) se - > data ;
if ( peer - > conn ! = conn ) continue ;
peer - > exchange_id = 0 ; peer - > table_received = 0 ; peer - > table_sent = 0 ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP session resync: peer=%016llx group=%016llx " ,
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP session resync: peer=%016llx group=%016llx " ,
( unsigned long long ) conn - > peer_node_id , ( unsigned long long ) g - > group_id ) ;
( unsigned long long ) conn - > peer_node_id , ( unsigned long long ) g - > group_id ) ;
topo_group_send_join_group ( g , conn ) ; topo_group_send_table_request ( g , conn ) ;
topo_group_send_join_group ( g , conn ) ; topo_group_send_table_request ( g , conn ) ;
@ -1163,12 +1218,12 @@ int topo_group_process_withdraw(struct TOPO_GROUP* group, struct ETCP_CONN* send
}
}
/* Сериализует и шлёт NODEINFO узла конкретному пиру. */
/* Сериализует и шлёт NODEINFO узла конкретному пиру. */
void topo_group_send_nodeinfo ( struct TOPO_GROUP * group , struct TOPO_GROUP_NODE * node , struct ETCP_CONN * conn , uint16_t cumulative_rtt ) {
int topo_group_send_nodeinfo ( struct TOPO_GROUP * group , struct TOPO_GROUP_NODE * node , struct ETCP_CONN * conn , uint16_t cumulative_rtt ) {
if ( ! group | | ! node | | ! conn ) return ;
if ( ! group | | ! node | | ! conn ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " send_nodeinfo: invalid arguments " ) ; return - 1 ; }
size_t max_sz = sizeof ( struct TOPOMSG_NODEINFO_PKT ) + TOPO_NODE_WIRE_MAX_SIZE ;
size_t max_sz = sizeof ( struct TOPOMSG_NODEINFO_PKT ) + TOPO_NODE_WIRE_MAX_SIZE ;
uint8_t * p = u_malloc ( max_sz ) ;
uint8_t * p = u_malloc ( max_sz ) ;
if ( ! p ) return ;
if ( ! p ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " send_nodeinfo: allocation failed " ) ; return - 1 ; }
p [ 0 ] = ETCP_ID_TOPO_ENTRY ; p [ 1 ] = TOPO_SUBCMD_NODEINFO ;
p [ 0 ] = ETCP_ID_TOPO_ENTRY ; p [ 1 ] = TOPO_SUBCMD_NODEINFO ;
@ -1183,18 +1238,26 @@ void topo_group_send_nodeinfo(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE*
node - > paths ? queue_entry_count ( node - > paths ) : - 1 ,
node - > paths ? queue_entry_count ( node - > paths ) : - 1 ,
group - > nodes ? queue_entry_count ( group - > nodes ) : - 1 ) ;
group - > nodes ? queue_entry_count ( group - > nodes ) : - 1 ) ;
u_free ( p ) ;
u_free ( p ) ;
return ;
return - 1 ;
}
}
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " send_nodeinfo: node %016llx ver=%d grp=%016llx to conn=%p name='%s' " , ( unsigned long long ) node - > node_id , sni - > ver , ( unsigned long long ) group - > group_id , ( void * ) conn , conn - > log_name ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " send_nodeinfo: node %016llx ver=%d grp=%016llx to conn=%p name='%s' " , ( unsigned long long ) node - > node_id , sni - > ver , ( unsigned long long ) group - > group_id , ( void * ) conn , conn - > log_name ) ;
uint8_t sflags = ( group - > group_type = = TOPO_GROUP_TYPE_CHAT ) ? 0 : TOPO_FLAG_SEND_SUBNETS ;
uint8_t sflags = ( group - > group_type = = TOPO_GROUP_TYPE_CHAT ) ? 0 : TOPO_FLAG_SEND_SUBNETS ;
int ser_len = topo_node_serialize ( sni , node , group - > group_id , sflags , p + 2 , max_sz - 2 , cumulative_rtt ) ;
int ser_len = topo_node_serialize ( sni , node , group - > group_id , sflags , p + 2 , max_sz - 2 , cumulative_rtt ) ;
if ( ser_len < 0 ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " send_nodeinfo: serialize failed for node %016llx " , ( unsigned long long ) node - > node_id ) ; u_free ( p ) ; return ; }
if ( ser_len < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " send_nodeinfo: serialize failed for node %016llx " , ( unsigned long long ) node - > node_id ) ;
u_free ( p ) ; return - 1 ;
}
struct ll_entry * e = queue_entry_new ( 0 ) ;
struct ll_entry * e = queue_entry_new ( 0 ) ;
if ( ! e ) { u_free ( p ) ; return ; }
if ( ! e ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " send_nodeinfo: entry allocation failed " ) ; u_free ( p ) ; return - 1 ; }
e - > dgram = p ; e - > len = ( size_t ) ser_len + 2 ;
e - > dgram = p ; e - > len = ( size_t ) ser_len + 2 ;
if ( etcp_send ( conn , e ) ! = 0 ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " send_nodeinfo: etcp_send FAILED for node %016llx to %s " , ( unsigned long long ) node - > node_id , conn - > log_name ) ; u_free ( p ) ; queue_entry_free ( e ) ; }
if ( etcp_send ( conn , e ) ! = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " send_nodeinfo: etcp_send FAILED for node %016llx to %s " ,
( unsigned long long ) node - > node_id , conn - > log_name ) ;
u_free ( p ) ; queue_entry_free ( e ) ; return - 1 ;
}
return 0 ;
}
}
/* Добавляет conn в senders_list (дедуп), если его там ещё нет. */
/* Добавляет conn в senders_list (дедуп), если его там ещё нет. */
@ -1315,32 +1378,37 @@ int topo_group_leave_peer(struct TOPO_GROUP* group, struct NODE_CONN_DIRECT* han
}
}
/* Шлёт пиру полную таблицу узлов группы (все узлы, кроме достижимых через него). */
/* Шлёт пиру полную таблицу узлов группы (все узлы, кроме достижимых через него). */
static void topo_group_send_full_table ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) {
static int topo_group_send_full_table ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) {
if ( ! group | | ! conn ) return ;
uint64_t target = conn - > peer_node_id ;
uint64_t target = conn - > peer_node_id ;
struct ll_entry * e = group - > nodes ? group - > nodes - > head : NULL ;
struct ll_entry * e = group - > nodes ? group - > nodes - > head : NULL ;
while ( e ) {
while ( e ) {
struct TOPO_GROUP_NODE * nq = ( struct TOPO_GROUP_NODE * ) e ;
struct TOPO_GROUP_NODE * nq = ( struct TOPO_GROUP_NODE * ) e ;
if ( nq - > node_id = = group - > instance - > node_id ) { e = e - > next ; continue ; }
if ( nq - > node_id = = group - > instance - > node_id ) { e = e - > next ; continue ; }
if ( ! nq - > paths ) { DEBUG_WARN ( DEBUG_CATEGORY_BGP , " node has no paths " ) ; e = e - > next ; continue ; }
if ( ! nq - > paths ) { DEBUG_WARN ( DEBUG_CATEGORY_BGP , " node has no paths " ) ; e = e - > next ; continue ; }
if ( topo_group_should_send_to ( nq , target ) ) topo_group_send_nodeinfo ( group , nq , conn , topo_get_chain_rtt ( nq ) ) ;
if ( topo_group_should_send_to ( nq , target ) & & topo_group_send_nodeinfo ( group , nq , conn , topo_get_chain_rtt ( nq ) ) < 0 ) return - 1 ;
e = e - > next ;
e = e - > next ;
}
}
return 0 ;
}
}
/* Обрабатывает REQUEST_TABLE: шлёт свой nodeinfo + полную таблицу + TABLE_COMPLETE. */
/* Обрабатывает REQUEST_TABLE: шлёт свой nodeinfo + полную таблицу + TABLE_COMPLETE. */
static void topo_group_handle_request_table ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) {
static void topo_group_handle_request_table ( struct TOPO_GROUP * group , struct ETCP_CONN * conn , uint64_t exchange_id ) {
if ( ! group | | ! conn ) return ;
if ( ! group | | ! conn ) return ;
if ( ! topo_group_peer_allowed ( group , conn - > peer_node_id ) ) {
if ( ! topo_group_peer_allowed ( group , conn - > peer_node_id ) ) {
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " table request deferred: member unknown peer=%016llx group=%016llx " ,
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " table request deferred: member unknown peer=%016llx group=%016llx " ,
( unsigned long long ) conn - > peer_node_id , ( unsigned long long ) group - > group_id ) ;
( unsigned long long ) conn - > peer_node_id , ( unsigned long long ) group - > group_id ) ;
return ;
return ;
}
}
topo_group_send_nodeinfo ( group , group - > local_node , conn , 0 ) ;
if ( topo_group_send_nodeinfo ( group , group - > local_node , conn , 0 ) < 0 | | topo_group_send_full_table ( group , conn ) < 0 ) {
topo_group_send_full_table ( group , conn ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " table exchange incomplete group=%016llx peer=%016llx exchange=%016llx " ,
( unsigned long long ) group - > group_id , ( unsigned long long ) conn - > peer_node_id , ( unsigned long long ) exchange_id ) ;
return ;
}
/* senders_list заполняется только через topo_group_new_conn (add + BGP);
/* senders_list заполняется только через topo_group_new_conn (add + BGP);
з д е с ь н е д о б а в л я е м , и н а ч е new_conn ( н а JOIN_GROUP ) у п и р а е т с я в д е д у п и н е ш л ё т TABLE_REQ о б р а т н о . */
з д е с ь н е д о б а в л я е м , и н а ч е new_conn ( н а JOIN_GROUP ) у п и р а е т с я в д е д у п и н е ш л ё т TABLE_REQ о б р а т н о . */
topo_group_send_table_complete ( group , conn ) ;
if ( topo_group_send_table_complete ( group , conn , exchange_id ) < 0 ) return ;
struct TOPO_GROUP_CONN_ITEM * peer = topo_group_peer ( group , conn - > peer_node_id ) ;
if ( peer & & peer - > conn = = conn & & ! peer - > table_sent ) { peer - > table_sent = 1 ; topo_group_log_exchange ( group , peer ) ; }
}
}
/* Обрабатывает JOIN_GROUP: для UTUN — добавить запросившего и инициировать BGP обратно. */
/* Обрабатывает JOIN_GROUP: для UTUN — добавить запросившего и инициировать BGP обратно. */