@@ -206,6 +206,10 @@ struct peer {
206206	// Pool size 
207207	uint8_t  pool_size ;
208208	uint8_t  pool_start ;
209+ 
210+ 	struct  {
211+ 		sd_event_source  * source ;
212+ 	} routing_table_polling ;
209213};
210214
211215struct  msg_type_support  {
@@ -241,6 +245,9 @@ struct ctx {
241245	// Timeout in usecs for a MCTP response 
242246	uint64_t  mctp_timeout ;
243247
248+ 	// Interval in usecs between routing table requests 
249+ 	uint64_t  routing_table_polling_interval ;
250+ 
244251	// Next IID to use 
245252	uint8_t  iid ;
246253
@@ -276,6 +283,7 @@ static int publish_peer(struct peer *peer);
276283static  int  unpublish_peer (struct  peer  * peer );
277284static  int  peer_route_update (struct  peer  * peer , uint16_t  type );
278285static  int  peer_neigh_update (struct  peer  * peer , uint16_t  type );
286+ static  int  peer_routing_table_polling_enable (struct  peer  * peer );
279287
280288static  int  add_interface_local (struct  ctx  * ctx , int  ifindex );
281289static  int  del_interface (struct  link  * link );
@@ -815,6 +823,10 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
815823		if  (link_data -> discovery .flag  !=  DISCOVERY_UNSUPPORTED ) {
816824			link_data -> discovery .flag  =  DISCOVERY_DISCOVERED ;
817825		}
826+ 		rc  =  peer_routing_table_polling_enable (peer );
827+ 		if  (rc ) {
828+ 			warnx ("failed to setup routing table polling for bus owner" );
829+ 		}
818830		resp -> status  = 
819831			SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_ACCEPTED ) |
820832			SET_MCTP_EID_ALLOCATION_STATUS (MCTP_SET_EID_POOL_NONE );
@@ -1909,6 +1921,8 @@ static int remove_peer(struct peer *peer)
19091921		sd_event_source_unref (peer -> recovery .source );
19101922	}
19111923
1924+ 	sd_event_source_disable_unref (peer -> routing_table_polling .source );
1925+ 
19121926	n -> peers [peer -> eid ] =  NULL ;
19131927	free (peer -> message_types );
19141928	free (peer -> uuid );
@@ -2291,6 +2305,62 @@ static int query_get_endpoint_id(struct ctx *ctx, const dest_phys *dest,
22912305	return  rc ;
22922306}
22932307
2308+ static  int  query_get_routing_table (struct  ctx  * ctx , struct  peer  * peer ,
2309+ 				   uint8_t  handle ,
2310+ 				   struct  get_routing_table_entry  * * entries ,
2311+ 				   size_t  * entries_count , uint8_t  * next_handle )
2312+ {
2313+ 	struct  sockaddr_mctp_ext  addr ;
2314+ 	struct  mctp_ctrl_cmd_get_routing_table  req  =  { 0  };
2315+ 	struct  mctp_ctrl_resp_get_routing_table  * resp  =  NULL ;
2316+ 	uint8_t  * buf  =  NULL ;
2317+ 	size_t  buf_size ;
2318+ 	uint8_t  iid ;
2319+ 	int  rc ;
2320+ 
2321+ 	iid  =  mctp_next_iid (ctx );
2322+ 
2323+ 	req .ctrl_hdr .rq_dgram_inst  =  RQDI_REQ  | iid ;
2324+ 	req .ctrl_hdr .command_code  =  MCTP_CTRL_CMD_GET_ROUTING_TABLE_ENTRIES ;
2325+ 
2326+ 	req .entry_handle  =  handle ;
2327+ 
2328+ 	rc  =  endpoint_query_peer (peer , MCTP_CTRL_HDR_MSG_TYPE , & req ,
2329+ 				 sizeof (req ), & buf , & buf_size , & addr );
2330+ 	if  (rc  <  0 )
2331+ 		goto out ;
2332+ 
2333+ 	rc  =  mctp_ctrl_validate_response (
2334+ 		buf , buf_size , sizeof (* resp ), peer_tostr_short (peer ), iid ,
2335+ 		MCTP_CTRL_CMD_GET_ROUTING_TABLE_ENTRIES );
2336+ 	if  (rc )
2337+ 		goto out ;
2338+ 
2339+ 	resp  =  (void  * )buf ;
2340+ 
2341+ 	* next_handle  =  resp -> next_entry_handle ;
2342+ 	* entries_count  =  resp -> number_of_entries ;
2343+ 	if  (* entries_count  ==  0 ) {
2344+ 		* entries  =  NULL ;
2345+ 		goto out ;
2346+ 	}
2347+ 
2348+ 	* entries  =  malloc (resp -> number_of_entries  * 
2349+ 				  sizeof (struct  get_routing_table_entry ) + 
2350+ 			  1024 );
2351+ 	if  (* entries  ==  NULL ) {
2352+ 		rc  =  - ENOMEM ;
2353+ 		goto out ;
2354+ 	}
2355+ 
2356+ 	memcpy (* entries , resp  +  1 ,
2357+ 	       resp -> number_of_entries  * 
2358+ 		       sizeof (struct  get_routing_table_entry ));
2359+ out :
2360+ 	free (buf );
2361+ 	return  rc ;
2362+ }
2363+ 
22942364/* Returns 0, and ret_peer associated with the endpoint. 
22952365 * Returns 0, ret_peer=NULL if the endpoint successfully replies "not yet assigned". 
22962366 * Returns negative error code on failure. 
@@ -3347,6 +3417,107 @@ static int method_endpoint_set_mtu(sd_bus_message *call, void *data,
33473417	return  rc ;
33483418}
33493419
3420+ static  int  peer_routing_table_polling_callback (sd_event_source  * source ,
3421+ 					       uint64_t  time , void  * userdata )
3422+ {
3423+ 	struct  peer  * peer  =  userdata ;
3424+ 	struct  peer  * remote_peer  =  NULL ;
3425+ 	struct  get_routing_table_entry  * entry  =  NULL ;
3426+ 	size_t  entries_count  =  0 ;
3427+ 	uint8_t  handle  =  0x00 ;
3428+ 	size_t  i ;
3429+ 	int  rc ;
3430+ 
3431+ 	assert (peer -> routing_table_polling .source  ==  source );
3432+ 
3433+ 	while  (handle  !=  0xFF ) {
3434+ 		rc  =  query_get_routing_table (peer -> ctx , peer , handle , & entry ,
3435+ 					     & entries_count , & handle );
3436+ 		if  (rc  <  0 ) {
3437+ 			warnx ("failed to fetch routing table from peer %s" ,
3438+ 			      peer_tostr (peer ));
3439+ 			return  0 ;
3440+ 		}
3441+ 		dfree (entry );
3442+ 
3443+ 		for  (i  =  0 ; i  <  entries_count ;
3444+ 		     i ++ , entry  =  MCTP_GET_ROUTING_TABLE_MSG_NEXT (entry )) {
3445+ 			// Add Bridge/Endpoint to routing table 
3446+ 
3447+ 			switch  (GET_ROUTING_ENTRY_TYPE (entry -> entry_type )) {
3448+ 			case  MCTP_ROUTING_ENTRY_ENDPOINT :
3449+ 			case  MCTP_ROUTING_ENTRY_BRIDGE :
3450+ 			case  MCTP_ROUTING_ENTRY_BRIDGE_AND_ENDPOINTS :
3451+ 				rc  =  add_peer (peer -> ctx , & peer -> phys ,
3452+ 					      entry -> starting_eid , peer -> net ,
3453+ 					      & remote_peer , true);
3454+ 				if  (rc  ==  - EEXIST ) {
3455+ 					continue ;
3456+ 				} else  if  (rc  <  0 ) {
3457+ 					warnx ("failed to add new peer: %s" ,
3458+ 					      strerror (- rc ));
3459+ 					continue ;
3460+ 				}
3461+ 
3462+ 				rc  =  setup_added_peer (remote_peer );
3463+ 				if  (rc  <  0 ) {
3464+ 					warnx ("failed to set up new peer: %s" ,
3465+ 					      strerror (- rc ));
3466+ 					continue ;
3467+ 				}
3468+ 
3469+ 				// TODO: port? 
3470+ 
3471+ 				break ;
3472+ 			};
3473+ 
3474+ 			// For bridge, enable routing table polling recursively 
3475+ 
3476+ 			switch  (GET_ROUTING_ENTRY_TYPE (entry -> entry_type )) {
3477+ 			case  MCTP_ROUTING_ENTRY_BRIDGE :
3478+ 			case  MCTP_ROUTING_ENTRY_BRIDGE_AND_ENDPOINTS :
3479+ 				rc  =  peer_routing_table_polling_enable (
3480+ 					remote_peer );
3481+ 				if  (rc  <  0 ) {
3482+ 					warnx ("failed to enable routing table polling on bridge: %s" ,
3483+ 					      strerror (- rc ));
3484+ 					continue ;
3485+ 				}
3486+ 
3487+ 				break ;
3488+ 			}
3489+ 		}
3490+ 	}
3491+ 
3492+ 	// rearm timer 
3493+ 	rc  =  mctp_ops .sd_event .source_set_time_relative (
3494+ 		source , peer -> ctx -> routing_table_polling_interval );
3495+ 	if  (rc ) {
3496+ 		warn ("failed to rearm timer" );
3497+ 	}
3498+ 
3499+ 	return  0 ;
3500+ }
3501+ 
3502+ static  int  peer_routing_table_polling_enable (struct  peer  * peer )
3503+ {
3504+ 	int  rc  =  0 ;
3505+ 
3506+ 	if  (peer -> routing_table_polling .source  !=  NULL ) {
3507+ 		return  0 ;
3508+ 	}
3509+ 
3510+ 	rc  =  mctp_ops .sd_event .add_time_relative (
3511+ 		peer -> ctx -> event , & peer -> routing_table_polling .source ,
3512+ 		CLOCK_MONOTONIC , peer -> ctx -> routing_table_polling_interval , 0 ,
3513+ 		peer_routing_table_polling_callback , peer );
3514+ 
3515+ 	rc  =  sd_event_source_set_enabled (peer -> routing_table_polling .source ,
3516+ 					 SD_EVENT_ON );
3517+ 
3518+ 	return  rc ;
3519+ }
3520+ 
33503521static  int  method_net_learn_endpoint (sd_bus_message  * call , void  * data ,
33513522				     sd_bus_error  * berr )
33523523{
@@ -4798,6 +4969,16 @@ static int parse_config_mctp(struct ctx *ctx, toml_table_t *mctp_tab)
47984969		ctx -> mctp_timeout  =  i  *  1000 ;
47994970	}
48004971
4972+ 	val  =  toml_int_in (mctp_tab , "routing_table_polling_interval_ms" );
4973+ 	if  (val .ok ) {
4974+ 		int64_t  i  =  val .u .i ;
4975+ 		if  (i  <= 0  ||  i  >  100  *  1000 ) {
4976+ 			warnx ("invalid routing_table_polling_interval_ms value" );
4977+ 			return  -1 ;
4978+ 		}
4979+ 		ctx -> routing_table_polling_interval  =  i  *  1000 ;
4980+ 	}
4981+ 
48014982	val  =  toml_string_in (mctp_tab , "uuid" );
48024983	if  (val .ok ) {
48034984		rc  =  sd_id128_from_string (val .u .s , (void  * )& ctx -> uuid );
@@ -4974,6 +5155,7 @@ static void setup_config_defaults(struct ctx *ctx)
49745155{
49755156	ctx -> mctp_timeout  =  250000 ; // 250ms 
49765157	ctx -> default_role  =  ENDPOINT_ROLE_BUS_OWNER ;
5158+ 	ctx -> routing_table_polling_interval  =  1000000 ; // 1s 
49775159	ctx -> max_pool_size  =  15 ;
49785160	ctx -> dyn_eid_min  =  eid_alloc_min ;
49795161	ctx -> dyn_eid_max  =  eid_alloc_max ;
0 commit comments