@@ -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_tries_left ;
143+ } discovery ;
144+
138145 struct ctx * ctx ;
139146};
140147
@@ -805,8 +812,8 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
805812 warnx ("ERR: cannot add bus owner to object lists" );
806813 }
807814
808- if (link_data -> discovered != DISCOVERY_UNSUPPORTED ) {
809- link_data -> discovered = DISCOVERY_DISCOVERED ;
815+ if (link_data -> discovery . flag != DISCOVERY_UNSUPPORTED ) {
816+ link_data -> discovery . flag = DISCOVERY_DISCOVERED ;
810817 }
811818 resp -> status =
812819 SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_ACCEPTED ) |
@@ -817,13 +824,13 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
817824 return reply_message (ctx , sd , resp , resp_len , addr );
818825
819826 case MCTP_SET_EID_DISCOVERED :
820- if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
827+ if (link_data -> discovery . flag == DISCOVERY_UNSUPPORTED ) {
821828 resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
822829 resp_len = sizeof (struct mctp_ctrl_resp );
823830 return reply_message (ctx , sd , resp , resp_len , addr );
824831 }
825832
826- link_data -> discovered = DISCOVERY_DISCOVERED ;
833+ link_data -> discovery . flag = DISCOVERY_DISCOVERED ;
827834 resp -> status =
828835 SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_REJECTED ) |
829836 SET_MCTP_EID_ALLOCATION_STATUS (MCTP_SET_EID_POOL_NONE );
@@ -1061,16 +1068,16 @@ static int handle_control_prepare_endpoint_discovery(
10611068 resp = (void * )resp ;
10621069 mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , * req );
10631070
1064- if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
1071+ if (link_data -> discovery . flag == DISCOVERY_UNSUPPORTED ) {
10651072 warnx ("received prepare for discovery request to unsupported interface %d" ,
10661073 addr -> smctp_ifindex );
10671074 resp -> completion_code = MCTP_CTRL_CC_ERROR_UNSUPPORTED_CMD ;
10681075 return reply_message_phys (ctx , sd , resp ,
10691076 sizeof (struct mctp_ctrl_resp ), addr );
10701077 }
10711078
1072- if (link_data -> discovered == DISCOVERY_DISCOVERED ) {
1073- link_data -> discovered = DISCOVERY_UNDISCOVERED ;
1079+ if (link_data -> discovery . flag == DISCOVERY_DISCOVERED ) {
1080+ link_data -> discovery . flag = DISCOVERY_UNDISCOVERED ;
10741081 warnx ("clear discovered flag of interface %d" ,
10751082 addr -> smctp_ifindex );
10761083 }
@@ -1105,13 +1112,13 @@ handle_control_endpoint_discovery(struct ctx *ctx, int sd,
11051112 return 0 ;
11061113 }
11071114
1108- if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
1115+ if (link_data -> discovery . flag == DISCOVERY_UNSUPPORTED ) {
11091116 resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
11101117 return reply_message (ctx , sd , resp ,
11111118 sizeof (struct mctp_ctrl_resp ), addr );
11121119 }
11131120
1114- if (link_data -> discovered == DISCOVERY_DISCOVERED ) {
1121+ if (link_data -> discovery . flag == DISCOVERY_DISCOVERED ) {
11151122 // if we are already discovered (i.e, assigned an EID), then no reply
11161123 return 0 ;
11171124 }
@@ -3632,6 +3639,88 @@ static int bus_link_get_prop(sd_bus *bus, const char *path,
36323639 return rc ;
36333640}
36343641
3642+ static int query_discovery_notify (struct link * link )
3643+ {
3644+ struct mctp_ctrl_cmd_discovery_notify req = { 0 };
3645+ struct mctp_ctrl_resp_discovery_notify * resp ;
3646+ struct sockaddr_mctp_ext resp_addr ;
3647+ size_t buf_size ;
3648+ uint8_t * buf ;
3649+ int rc ;
3650+
3651+ mctp_ctrl_msg_hdr_init_req (& req .ctrl_hdr , mctp_next_iid (link -> ctx ),
3652+ MCTP_CTRL_CMD_DISCOVERY_NOTIFY );
3653+
3654+ rc = endpoint_query_phys (link -> ctx , & link -> discovery .notify_dest ,
3655+ MCTP_CTRL_HDR_MSG_TYPE , & req , sizeof (req ),
3656+ & buf , & buf_size , & resp_addr );
3657+ if (rc < 0 )
3658+ goto free_buf ;
3659+
3660+ if (buf_size != sizeof (* resp )) {
3661+ warnx ("%s: wrong reply length %zu bytes. dest %s" , __func__ ,
3662+ buf_size , dest_phys_tostr (& link -> discovery .notify_dest ));
3663+ rc = - ENOMSG ;
3664+ goto free_buf ;
3665+ }
3666+
3667+ resp = (void * )buf ;
3668+ if (resp -> completion_code != 0 ) {
3669+ warnx ("Failure completion code 0x%02x from %s" ,
3670+ resp -> completion_code ,
3671+ dest_phys_tostr (& link -> discovery .notify_dest ));
3672+ rc = - ECONNREFUSED ;
3673+ goto free_buf ;
3674+ }
3675+
3676+ free_buf :
3677+ free (buf );
3678+ return rc ;
3679+ }
3680+
3681+ static int link_discovery_notify_callback (sd_event_source * source ,
3682+ uint64_t time , void * userdata )
3683+ {
3684+ struct link * link = userdata ;
3685+ struct ctx * ctx = link -> ctx ;
3686+ int rc ;
3687+
3688+ // sanity check
3689+ assert (link -> discovery .notify_source == source );
3690+
3691+ // Discovery notify succeeded
3692+ if (link -> discovery .flag == DISCOVERY_DISCOVERED )
3693+ goto disarm ;
3694+
3695+ rc = query_discovery_notify (link );
3696+ if (rc < 0 ) {
3697+ if (ctx -> verbose ) {
3698+ warnx ("failed to send discovery notify at retry %d: %s" ,
3699+ link -> discovery .notify_tries_left , strerror (- rc ));
3700+ }
3701+ }
3702+
3703+ link -> discovery .notify_tries_left -= 1 ;
3704+ if (link -> discovery .notify_tries_left == 0 ) {
3705+ warnx ("failed to send discovery notify after all retries" );
3706+ goto disarm ;
3707+ }
3708+
3709+ rc = mctp_ops .sd_event .source_set_time_relative (
3710+ source , link -> discovery .notify_retry_delay );
3711+ if (rc < 0 ) {
3712+ warnx ("failed to rearm discovery notify timer" );
3713+ goto disarm ;
3714+ }
3715+
3716+ return 0 ;
3717+
3718+ disarm :
3719+ sd_event_source_disable_unref (source );
3720+ link -> discovery .notify_source = NULL ;
3721+ return 0 ;
3722+ }
3723+
36353724static int bus_link_set_prop (sd_bus * bus , const char * path ,
36363725 const char * interface , const char * property ,
36373726 sd_bus_message * value , void * userdata ,
@@ -4469,7 +4558,7 @@ static int add_interface(struct ctx *ctx, int ifindex)
44694558 if (!link )
44704559 return - ENOMEM ;
44714560
4472- link -> discovered = DISCOVERY_UNSUPPORTED ;
4561+ link -> discovery . flag = DISCOVERY_UNSUPPORTED ;
44734562 link -> published = false;
44744563 link -> ifindex = ifindex ;
44754564 link -> ctx = ctx ;
@@ -4499,7 +4588,42 @@ static int add_interface(struct ctx *ctx, int ifindex)
44994588 }
45004589
45014590 if (phys_binding == MCTP_PHYS_BINDING_PCIE_VDM ) {
4502- link -> discovered = DISCOVERY_UNDISCOVERED ;
4591+ link -> discovery .flag = DISCOVERY_UNDISCOVERED ;
4592+ // TODO: These numbers are respectively MN1 and MT4, specified in DSP0239
4593+ // control message timing.
4594+ //
4595+ // Might need to extract these to macros like MCTP_I2C_TSYM_* in this file,
4596+ // or a commit to actually centralize those timing at one place, now that
4597+ // we have support for detecting link binding type.
4598+ link -> discovery .notify_tries_left = 3 ;
4599+ link -> discovery .notify_retry_delay = 5000000 ;
4600+
4601+ // For PCIe-VDM, we want an all zeroes address for Route-to-Root-Complex.
4602+ rc = mctp_nl_hwaddr_len_byindex (
4603+ ctx -> nl , ifindex ,
4604+ & link -> discovery .notify_dest .hwaddr_len );
4605+ if (rc < 0 ) {
4606+ warnx ("Can't find hwaddr_len by index %d" , ifindex );
4607+ return - ENOENT ;
4608+ }
4609+
4610+ memset (link -> discovery .notify_dest .hwaddr , 0 ,
4611+ link -> discovery .notify_dest .hwaddr_len );
4612+ link -> discovery .notify_dest .ifindex = ifindex ;
4613+
4614+ rc = mctp_ops .sd_event .add_time_relative (
4615+ ctx -> event , & link -> discovery .notify_source ,
4616+ CLOCK_MONOTONIC , 0 , 0 , link_discovery_notify_callback ,
4617+ link );
4618+ if (rc >= 0 ) {
4619+ rc = sd_event_source_set_enabled (
4620+ link -> discovery .notify_source , SD_EVENT_ON );
4621+ }
4622+ if (rc < 0 ) {
4623+ warnx ("Failed to arm discovery notify timer" );
4624+ sd_event_source_disable_unref (
4625+ link -> discovery .notify_source );
4626+ }
45034627 }
45044628
45054629 link -> published = true;
0 commit comments