@ -3,16 +3,13 @@
# include "../lib/debug_config.h"
# include "../lib/debug_config.h"
# include "../lib/mem.h"
# include "../lib/mem.h"
# include "../lib/platform_compat.h"
# include "../lib/platform_compat.h"
# include "../lib/u_async.h"
# include <stdio.h>
# include <stdio.h>
# include <stdlib.h>
# include <stdlib.h>
# include <string.h>
# include <string.h>
# include <stdint.h>
# include <stdint.h>
# define INITIAL_CAPACITY 100
# define INITIAL_CAPACITY 100
# define CONN_INFO_INIT_SIZE 4 // было 2 — теперь чуть больше
# define CONN_INFO_INIT_SIZE 4
# define DEBUG_CATEGORY_ROUTING 1
// ============================================================================
// ============================================================================
// Вспомогательные функции (без изменений)
// Вспомогательные функции (без изменений)
@ -330,7 +327,11 @@ struct ROUTE_TABLE *route_table_create(void) {
}
}
void route_table_destroy ( struct ROUTE_TABLE * table ) {
void route_table_destroy ( struct ROUTE_TABLE * table ) {
if ( ! table ) return ;
if ( ! table ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ROUTING , " route_table_destroy: table is NULL " ) ;
return ;
}
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_table_destroy: count=%zu " , table - > count ) ;
// Правильно освобождаем NODE_CONNS_INFO с учётом ref_count
// Правильно освобождаем NODE_CONNS_INFO с учётом ref_count
// (один info может быть у нескольких префиксов)
// (один info может быть у нескольких префиксов)
@ -363,7 +364,16 @@ bool route_insert(struct ROUTE_TABLE *table,
uint64_t * hop_list ,
uint64_t * hop_list ,
uint8_t hop_count ) {
uint8_t hop_count ) {
if ( ! table | | ! entry ) return false ;
if ( ! table ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ROUTING , " route_insert: table is NULL " ) ;
return false ;
}
if ( ! entry ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ROUTING , " route_insert: entry is NULL " ) ;
return false ;
}
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_insert: network=%08X prefix=%d conn=%p node_id=%llu " ,
entry - > network , entry - > prefix_length , ( void * ) conn , ( unsigned long long ) node_id ) ;
// === 0. Loop prevention — ВСЕГДА (исправление проблемы #3) ===
// === 0. Loop prevention — ВСЕГДА (исправление проблемы #3) ===
if ( conn & & my_node_id & & hop_list & & hop_count > 0 ) {
if ( conn & & my_node_id & & hop_list & & hop_count > 0 ) {
@ -372,6 +382,7 @@ bool route_insert(struct ROUTE_TABLE *table,
char ip_str [ 16 ] ;
char ip_str [ 16 ] ;
ip_to_string ( entry - > network , ip_str ) ;
ip_to_string ( entry - > network , ip_str ) ;
DEBUG_WARN ( DEBUG_CATEGORY_ROUTING , " Loop detected: %s/%d " , ip_str , entry - > prefix_length ) ;
DEBUG_WARN ( DEBUG_CATEGORY_ROUTING , " Loop detected: %s/%d " , ip_str , entry - > prefix_length ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_insert: REJECTED (loop detected) " ) ;
return false ;
return false ;
}
}
}
}
@ -389,6 +400,7 @@ bool route_insert(struct ROUTE_TABLE *table,
char ip_str [ 16 ] ;
char ip_str [ 16 ] ;
ip_to_string ( entry - > network , ip_str ) ;
ip_to_string ( entry - > network , ip_str ) ;
DEBUG_WARN ( DEBUG_CATEGORY_ROUTING , " Route conflict (different owner): %s/%d " , ip_str , entry - > prefix_length ) ;
DEBUG_WARN ( DEBUG_CATEGORY_ROUTING , " Route conflict (different owner): %s/%d " , ip_str , entry - > prefix_length ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_insert: REJECTED (conflict) " ) ;
return false ;
return false ;
}
}
@ -397,6 +409,7 @@ bool route_insert(struct ROUTE_TABLE *table,
existing - > last_update = get_time_tb ( ) ;
existing - > last_update = get_time_tb ( ) ;
if ( table - > change_callback )
if ( table - > change_callback )
table - > change_callback ( table , existing , 1 , table - > change_callback_arg ) ;
table - > change_callback ( table , existing , 1 , table - > change_callback_arg ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_insert: UPDATED local route %08X/%d " , entry - > network , entry - > prefix_length ) ;
return true ;
return true ;
}
}
@ -404,7 +417,10 @@ bool route_insert(struct ROUTE_TABLE *table,
struct NODE_CONNS_INFO * info = existing - > conn_list ;
struct NODE_CONNS_INFO * info = existing - > conn_list ;
bool needs_reroute = false ; // не используется здесь, но нужен для сигнатуры
bool needs_reroute = false ; // не используется здесь, но нужен для сигнатуры
info = node_conns_info_add ( table , info , 0 , 0 , NULL , conn , hop_list , hop_count , & needs_reroute ) ;
info = node_conns_info_add ( table , info , 0 , 0 , NULL , conn , hop_list , hop_count , & needs_reroute ) ;
if ( ! info ) return false ;
if ( ! info ) {
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_insert: FAILED (node_conns_info_add) " ) ;
return false ;
}
existing - > conn_list = info ;
existing - > conn_list = info ;
existing - > last_update = get_time_tb ( ) ;
existing - > last_update = get_time_tb ( ) ;
@ -412,6 +428,8 @@ bool route_insert(struct ROUTE_TABLE *table,
if ( table - > change_callback )
if ( table - > change_callback )
table - > change_callback ( table , existing , 1 , table - > change_callback_arg ) ;
table - > change_callback ( table , existing , 1 , table - > change_callback_arg ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_insert: UPDATED learned route %08X/%d node_id=%llu " ,
entry - > network , entry - > prefix_length , ( unsigned long long ) node_id ) ;
return true ;
return true ;
}
}
@ -421,6 +439,7 @@ bool route_insert(struct ROUTE_TABLE *table,
char ip_str [ 16 ] ;
char ip_str [ 16 ] ;
ip_to_string ( entry - > network , ip_str ) ;
ip_to_string ( entry - > network , ip_str ) ;
DEBUG_WARN ( DEBUG_CATEGORY_ROUTING , " Route overlap rejected: %s/%d " , ip_str , entry - > prefix_length ) ;
DEBUG_WARN ( DEBUG_CATEGORY_ROUTING , " Route overlap rejected: %s/%d " , ip_str , entry - > prefix_length ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_insert: REJECTED (overlap) " ) ;
return false ;
return false ;
}
}
@ -428,7 +447,10 @@ bool route_insert(struct ROUTE_TABLE *table,
if ( table - > count > = table - > capacity ) {
if ( table - > count > = table - > capacity ) {
uint32_t new_cap = table - > capacity * 2 ;
uint32_t new_cap = table - > capacity * 2 ;
struct ROUTE_ENTRY * new_entries = u_realloc ( table - > entries , new_cap * sizeof ( struct ROUTE_ENTRY ) ) ;
struct ROUTE_ENTRY * new_entries = u_realloc ( table - > entries , new_cap * sizeof ( struct ROUTE_ENTRY ) ) ;
if ( ! new_entries ) return false ;
if ( ! new_entries ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ROUTING , " route_insert: realloc failed " ) ;
return false ;
}
table - > entries = new_entries ;
table - > entries = new_entries ;
table - > capacity = new_cap ;
table - > capacity = new_cap ;
}
}
@ -487,12 +509,22 @@ bool route_insert(struct ROUTE_TABLE *table,
conn ? " learned " : " local " , ip_str , entry - > prefix_length ,
conn ? " learned " : " local " , ip_str , entry - > prefix_length ,
( unsigned long long ) node_id ) ;
( unsigned long long ) node_id ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_insert: INSERTED %s %08X/%d " ,
conn ? " learned " : " local " , entry - > network , entry - > prefix_length ) ;
return true ;
return true ;
}
}
/* ====================== НОВАЯ ФУНКЦИЯ ====================== */
/* ====================== НОВАЯ ФУНКЦИЯ ====================== */
void route_remove_conn ( struct ROUTE_TABLE * table , struct ETCP_CONN * conn ) {
void route_remove_conn ( struct ROUTE_TABLE * table , struct ETCP_CONN * conn ) {
if ( ! table | | ! conn ) return ;
if ( ! table ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ROUTING , " route_remove_conn: table is NULL " ) ;
return ;
}
if ( ! conn ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ROUTING , " route_remove_conn: conn is NULL " ) ;
return ;
}
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_remove_conn: conn=%p " , ( void * ) conn ) ;
struct NODE_CONNS_INFO * affected [ 512 ] ;
struct NODE_CONNS_INFO * affected [ 512 ] ;
bool needs_reroute [ 512 ] = { 0 } ;
bool needs_reroute [ 512 ] = { 0 } ;
@ -556,22 +588,38 @@ void route_remove_conn(struct ROUTE_TABLE *table, struct ETCP_CONN *conn) {
}
}
DEBUG_INFO ( DEBUG_CATEGORY_ROUTING , " route_remove_conn: processed %zu nodes " , aff_count ) ;
DEBUG_INFO ( DEBUG_CATEGORY_ROUTING , " route_remove_conn: processed %zu nodes " , aff_count ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_remove_conn: DONE " ) ;
}
}
/* ====================== НОВАЯ ФУНКЦИЯ ДЛЯ WITHDRAW ====================== */
/* ====================== НОВАЯ ФУНКЦИЯ ДЛЯ WITHDRAW ====================== */
bool route_remove_path ( struct ROUTE_TABLE * table ,
bool route_remove_path ( struct ROUTE_TABLE * table ,
struct ETCP_CONN * conn ,
struct ETCP_CONN * conn ,
uint64_t node_id ) {
uint64_t node_id ) {
if ( ! table | | ! conn ) return false ;
if ( ! table ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ROUTING , " route_remove_path: table is NULL " ) ;
return false ;
}
if ( ! conn ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ROUTING , " route_remove_path: conn is NULL " ) ;
return false ;
}
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_remove_path: node_id=%llu conn=%p " ,
( unsigned long long ) node_id , ( void * ) conn ) ;
struct NODE_CONNS_INFO * info = find_node_conns ( table , node_id ) ;
struct NODE_CONNS_INFO * info = find_node_conns ( table , node_id ) ;
if ( ! info ) return false ;
if ( ! info ) {
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_remove_path: node not found " ) ;
return false ;
}
bool was_preferred = node_conns_info_remove ( info , conn ) ;
bool was_preferred = node_conns_info_remove ( info , conn ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_remove_path: removed, was_preferred=%d remaining_conns=%d " ,
was_preferred , info - > conninfo_count ) ;
if ( info - > conninfo_count = = 0 ) {
if ( info - > conninfo_count = = 0 ) {
// Последний путь к узлу — полный withdraw
// Последний путь к узлу — полный withdraw
route_delete ( table , node_id ) ; // уже вызывает callback(2) и очищает память
route_delete ( table , node_id ) ; // уже вызывает callback(2) и очищает память
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_remove_path: WITHDRAW node_id=%llu " , ( unsigned long long ) node_id ) ;
return true ;
return true ;
} else if ( was_preferred ) {
} else if ( was_preferred ) {
// Изменился preferred_conn — уведомляем о reroute для всех префиксов этого узла
// Изменился preferred_conn — уведомляем о reroute для всех префиксов этого узла
@ -583,12 +631,17 @@ bool route_remove_path(struct ROUTE_TABLE *table,
table - > change_callback ( table , e , 1 , table - > change_callback_arg ) ;
table - > change_callback ( table , e , 1 , table - > change_callback_arg ) ;
}
}
}
}
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_remove_path: REROUTE node_id=%llu " , ( unsigned long long ) node_id ) ;
}
}
return false ;
return false ;
}
}
void route_delete ( struct ROUTE_TABLE * table , uint64_t node_id ) {
void route_delete ( struct ROUTE_TABLE * table , uint64_t node_id ) {
if ( ! table ) return ;
if ( ! table ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ROUTING , " route_delete: table is NULL " ) ;
return ;
}
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_delete: node_id=%llu " , ( unsigned long long ) node_id ) ;
size_t i = 0 ;
size_t i = 0 ;
while ( i < table - > count ) {
while ( i < table - > count ) {
@ -630,14 +683,22 @@ void route_delete(struct ROUTE_TABLE *table, uint64_t node_id) {
}
}
struct ROUTE_ENTRY * route_lookup ( struct ROUTE_TABLE * table , uint32_t dest_ip ) {
struct ROUTE_ENTRY * route_lookup ( struct ROUTE_TABLE * table , uint32_t dest_ip ) {
if ( ! table ) return NULL ;
if ( ! table ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ROUTING , " route_lookup: table is NULL " ) ;
return NULL ;
}
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_lookup: dest_ip=%08X " , dest_ip ) ;
struct ROUTE_ENTRY * result = binary_search_lpm ( table , dest_ip ) ;
struct ROUTE_ENTRY * result = binary_search_lpm ( table , dest_ip ) ;
if ( result ) {
if ( result ) {
table - > stats . routes_lookup_hits + + ;
table - > stats . routes_lookup_hits + + ;
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_lookup: FOUND %08X/%d node_id=%llu " ,
result - > network , result - > prefix_length ,
result - > conn_list ? ( unsigned long long ) result - > conn_list - > node_id : 0 ) ;
} else {
} else {
table - > stats . routes_lookup_misses + + ;
table - > stats . routes_lookup_misses + + ;
DEBUG_TRACE ( DEBUG_CATEGORY_ROUTING , " route_lookup: NOT FOUND " ) ;
}
}
return result ;
return result ;