@@ -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