@@ -126,7 +126,6 @@ enum discovery_state {
126126};
127127
128128struct link {
129- enum discovery_state discovered ;
130129 bool published ;
131130 int ifindex ;
132131 enum endpoint_role role ;
@@ -135,6 +134,14 @@ struct link {
135134 sd_bus_slot * slot_iface ;
136135 sd_bus_slot * slot_busowner ;
137136
137+ struct {
138+ enum discovery_state flag ;
139+ sd_event_source * notify_source ;
140+ dest_phys notify_dest ;
141+ uint64_t notify_retry_delay ;
142+ uint8_t notify_retries_left ;
143+ } discovery ;
144+
138145 struct ctx * ctx ;
139146};
140147
@@ -793,8 +800,8 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
793800 warnx ("ERR: cannot add bus owner to object lists" );
794801 }
795802
796- if (link_data -> discovered != DISCOVERY_UNSUPPORTED ) {
797- link_data -> discovered = DISCOVERY_DISCOVERED ;
803+ if (link_data -> discovery . flag != DISCOVERY_UNSUPPORTED ) {
804+ link_data -> discovery . flag = DISCOVERY_DISCOVERED ;
798805 }
799806 resp -> status =
800807 SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_ACCEPTED ) |
@@ -805,13 +812,13 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
805812 return reply_message (ctx , sd , resp , resp_len , addr );
806813
807814 case MCTP_SET_EID_DISCOVERED :
808- if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
815+ if (link_data -> discovery . flag == DISCOVERY_UNSUPPORTED ) {
809816 resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
810817 resp_len = sizeof (struct mctp_ctrl_resp );
811818 return reply_message (ctx , sd , resp , resp_len , addr );
812819 }
813820
814- link_data -> discovered = DISCOVERY_DISCOVERED ;
821+ link_data -> discovery . flag = DISCOVERY_DISCOVERED ;
815822 resp -> status =
816823 SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_REJECTED ) |
817824 SET_MCTP_EID_ALLOCATION_STATUS (MCTP_SET_EID_POOL_NONE );
@@ -1009,16 +1016,16 @@ static int handle_control_prepare_endpoint_discovery(
10091016 resp = (void * )resp ;
10101017 mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , * req );
10111018
1012- if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
1019+ if (link_data -> discovery . flag == DISCOVERY_UNSUPPORTED ) {
10131020 warnx ("received prepare for discovery request to unsupported interface %d" ,
10141021 addr -> smctp_ifindex );
10151022 resp -> completion_code = MCTP_CTRL_CC_ERROR_UNSUPPORTED_CMD ;
10161023 return reply_message_phys (ctx , sd , resp ,
10171024 sizeof (struct mctp_ctrl_resp ), addr );
10181025 }
10191026
1020- if (link_data -> discovered == DISCOVERY_DISCOVERED ) {
1021- link_data -> discovered = DISCOVERY_UNDISCOVERED ;
1027+ if (link_data -> discovery . flag == DISCOVERY_DISCOVERED ) {
1028+ link_data -> discovery . flag = DISCOVERY_UNDISCOVERED ;
10221029 warnx ("clear discovered flag of interface %d" ,
10231030 addr -> smctp_ifindex );
10241031 }
@@ -1053,13 +1060,13 @@ handle_control_endpoint_discovery(struct ctx *ctx, int sd,
10531060 return 0 ;
10541061 }
10551062
1056- if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
1063+ if (link_data -> discovery . flag == DISCOVERY_UNSUPPORTED ) {
10571064 resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
10581065 return reply_message (ctx , sd , resp ,
10591066 sizeof (struct mctp_ctrl_resp ), addr );
10601067 }
10611068
1062- if (link_data -> discovered == DISCOVERY_DISCOVERED ) {
1069+ if (link_data -> discovery . flag == DISCOVERY_DISCOVERED ) {
10631070 // if we are already discovered (i.e, assigned an EID), then no reply
10641071 return 0 ;
10651072 }
@@ -3460,6 +3467,81 @@ static int bus_link_get_prop(sd_bus *bus, const char *path,
34603467 return rc ;
34613468}
34623469
3470+ static int query_discovery_notify (struct link * link )
3471+ {
3472+ struct mctp_ctrl_cmd_discovery_notify req = { 0 };
3473+ struct mctp_ctrl_resp_discovery_notify * resp ;
3474+ struct sockaddr_mctp_ext resp_addr ;
3475+ size_t buf_size ;
3476+ uint8_t * buf ;
3477+ int rc ;
3478+
3479+ mctp_ctrl_msg_hdr_init_req (& req .ctrl_hdr , mctp_next_iid (link -> ctx ),
3480+ MCTP_CTRL_CMD_DISCOVERY_NOTIFY );
3481+
3482+ rc = endpoint_query_phys (link -> ctx , & link -> discovery .notify_dest ,
3483+ MCTP_CTRL_HDR_MSG_TYPE , & req , sizeof (req ),
3484+ & buf , & buf_size , & resp_addr );
3485+ if (rc < 0 )
3486+ goto free_buf ;
3487+
3488+ if (buf_size != sizeof (* resp )) {
3489+ warnx ("%s: wrong reply length %zu bytes. dest %s" , __func__ ,
3490+ buf_size , dest_phys_tostr (& link -> discovery .notify_dest ));
3491+ rc = - ENOMSG ;
3492+ goto free_buf ;
3493+ }
3494+
3495+ resp = (void * )buf ;
3496+ if (resp -> completion_code != 0 ) {
3497+ warnx ("Failure completion code 0x%02x from %s" ,
3498+ resp -> completion_code ,
3499+ dest_phys_tostr (& link -> discovery .notify_dest ));
3500+ rc = - ECONNREFUSED ;
3501+ goto free_buf ;
3502+ }
3503+
3504+ free_buf :
3505+ free (buf );
3506+ return rc ;
3507+ }
3508+
3509+ static int link_discovery_notify_callback (sd_event_source * source ,
3510+ uint64_t time , void * userdata )
3511+ {
3512+ struct link * link = userdata ;
3513+ struct ctx * ctx = link -> ctx ;
3514+ int rc ;
3515+
3516+ // sanity check
3517+ assert (link -> discovery .notify_source == source );
3518+
3519+ // Discovery notify succeeded
3520+ if (link -> discovery .flag == DISCOVERY_DISCOVERED ) {
3521+ sd_event_source_disable_unref (source );
3522+ link -> discovery .notify_source = NULL ;
3523+ return 0 ;
3524+ }
3525+
3526+ rc = query_discovery_notify (link );
3527+ if (rc < 0 ) {
3528+ if (ctx -> verbose ) {
3529+ warnx ("failed to send discovery notify at retry %d: %s" ,
3530+ link -> discovery .notify_retries_left ,
3531+ strerror (- rc ));
3532+ }
3533+ }
3534+ link -> discovery .notify_retries_left -= 1 ;
3535+ if (link -> discovery .notify_retries_left == 0 ) {
3536+ warnx ("failed to send discovery notify after all retries" );
3537+ sd_event_source_disable_unref (source );
3538+ } else {
3539+ sd_event_source_set_time_relative (
3540+ source , link -> discovery .notify_retry_delay );
3541+ }
3542+ return 0 ;
3543+ }
3544+
34633545static int bus_link_set_prop (sd_bus * bus , const char * path ,
34643546 const char * interface , const char * property ,
34653547 sd_bus_message * value , void * userdata ,
@@ -4279,7 +4361,7 @@ static int add_interface(struct ctx *ctx, int ifindex)
42794361 if (!link )
42804362 return - ENOMEM ;
42814363
4282- link -> discovered = DISCOVERY_UNSUPPORTED ;
4364+ link -> discovery . flag = DISCOVERY_UNSUPPORTED ;
42834365 link -> published = false;
42844366 link -> ifindex = ifindex ;
42854367 link -> ctx = ctx ;
@@ -4309,7 +4391,29 @@ static int add_interface(struct ctx *ctx, int ifindex)
43094391 }
43104392
43114393 if (phys_binding == MCTP_PHYS_BINDING_PCIE_VDM ) {
4312- link -> discovered = DISCOVERY_UNDISCOVERED ;
4394+ link -> discovery .flag = DISCOVERY_UNDISCOVERED ;
4395+ // TODO: These numbers are respectively MN1 and MT4, specified in DSP0239
4396+ // control message timing.
4397+ //
4398+ // Might need to extract these to macros like MCTP_I2C_TSYM_* in this file,
4399+ // or a commit to actually centralize those timing at one place, now that
4400+ // we have support for detecting link binding type.
4401+ link -> discovery .notify_retries_left = 2 ;
4402+ link -> discovery .notify_retry_delay = 5000000 ;
4403+
4404+ // For PCIe-VDM, we want an all zeroes address for Route-to-Root-Complex.
4405+ mctp_nl_hwaddr_len_byindex (
4406+ ctx -> nl , ifindex ,
4407+ & link -> discovery .notify_dest .hwaddr_len );
4408+ memset (link -> discovery .notify_dest .hwaddr , 0 ,
4409+ link -> discovery .notify_dest .hwaddr_len );
4410+ link -> discovery .notify_dest .ifindex = ifindex ;
4411+
4412+ sd_event_add_time_relative (ctx -> event ,
4413+ & link -> discovery .notify_source ,
4414+ CLOCK_MONOTONIC , 0 , 0 ,
4415+ link_discovery_notify_callback ,
4416+ link );
43134417 }
43144418
43154419 link -> published = true;
0 commit comments