@@ -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 }
@@ -3659,6 +3666,88 @@ static int bus_link_get_prop(sd_bus *bus, const char *path,
36593666 return rc ;
36603667}
36613668
3669+ static int query_discovery_notify (struct link * link )
3670+ {
3671+ struct mctp_ctrl_cmd_discovery_notify req = { 0 };
3672+ struct mctp_ctrl_resp_discovery_notify * resp ;
3673+ struct sockaddr_mctp_ext resp_addr ;
3674+ size_t buf_size ;
3675+ uint8_t * buf ;
3676+ int rc ;
3677+
3678+ mctp_ctrl_msg_hdr_init_req (& req .ctrl_hdr , mctp_next_iid (link -> ctx ),
3679+ MCTP_CTRL_CMD_DISCOVERY_NOTIFY );
3680+
3681+ rc = endpoint_query_phys (link -> ctx , & link -> discovery .notify_dest ,
3682+ MCTP_CTRL_HDR_MSG_TYPE , & req , sizeof (req ),
3683+ & buf , & buf_size , & resp_addr );
3684+ if (rc < 0 )
3685+ goto free_buf ;
3686+
3687+ if (buf_size != sizeof (* resp )) {
3688+ warnx ("%s: wrong reply length %zu bytes. dest %s" , __func__ ,
3689+ buf_size , dest_phys_tostr (& link -> discovery .notify_dest ));
3690+ rc = - ENOMSG ;
3691+ goto free_buf ;
3692+ }
3693+
3694+ resp = (void * )buf ;
3695+ if (resp -> completion_code != 0 ) {
3696+ warnx ("Failure completion code 0x%02x from %s" ,
3697+ resp -> completion_code ,
3698+ dest_phys_tostr (& link -> discovery .notify_dest ));
3699+ rc = - ECONNREFUSED ;
3700+ goto free_buf ;
3701+ }
3702+
3703+ free_buf :
3704+ free (buf );
3705+ return rc ;
3706+ }
3707+
3708+ static int link_discovery_notify_callback (sd_event_source * source ,
3709+ uint64_t time , void * userdata )
3710+ {
3711+ struct link * link = userdata ;
3712+ struct ctx * ctx = link -> ctx ;
3713+ int rc ;
3714+
3715+ // sanity check
3716+ assert (link -> discovery .notify_source == source );
3717+
3718+ // Discovery notify succeeded
3719+ if (link -> discovery .flag == DISCOVERY_DISCOVERED )
3720+ goto disarm ;
3721+
3722+ rc = query_discovery_notify (link );
3723+ if (rc < 0 ) {
3724+ if (ctx -> verbose ) {
3725+ warnx ("failed to send discovery notify at retry %d: %s" ,
3726+ link -> discovery .notify_tries_left , strerror (- rc ));
3727+ }
3728+ }
3729+
3730+ link -> discovery .notify_tries_left -= 1 ;
3731+ if (link -> discovery .notify_tries_left == 0 ) {
3732+ warnx ("failed to send discovery notify after all retries" );
3733+ goto disarm ;
3734+ }
3735+
3736+ rc = mctp_ops .sd_event .source_set_time_relative (
3737+ source , link -> discovery .notify_retry_delay );
3738+ if (rc < 0 ) {
3739+ warnx ("failed to rearm discovery notify timer" );
3740+ goto disarm ;
3741+ }
3742+
3743+ return 0 ;
3744+
3745+ disarm :
3746+ sd_event_source_disable_unref (source );
3747+ link -> discovery .notify_source = NULL ;
3748+ return 0 ;
3749+ }
3750+
36623751static int bus_link_set_prop (sd_bus * bus , const char * path ,
36633752 const char * interface , const char * property ,
36643753 sd_bus_message * value , void * userdata ,
@@ -4496,7 +4585,7 @@ static int add_interface(struct ctx *ctx, int ifindex)
44964585 if (!link )
44974586 return - ENOMEM ;
44984587
4499- link -> discovered = DISCOVERY_UNSUPPORTED ;
4588+ link -> discovery . flag = DISCOVERY_UNSUPPORTED ;
45004589 link -> published = false;
45014590 link -> ifindex = ifindex ;
45024591 link -> ctx = ctx ;
@@ -4526,7 +4615,42 @@ static int add_interface(struct ctx *ctx, int ifindex)
45264615 }
45274616
45284617 if (phys_binding == MCTP_PHYS_BINDING_PCIE_VDM ) {
4529- link -> discovered = DISCOVERY_UNDISCOVERED ;
4618+ link -> discovery .flag = DISCOVERY_UNDISCOVERED ;
4619+ // TODO: These numbers are respectively MN1 and MT4, specified in DSP0239
4620+ // control message timing.
4621+ //
4622+ // Might need to extract these to macros like MCTP_I2C_TSYM_* in this file,
4623+ // or a commit to actually centralize those timing at one place, now that
4624+ // we have support for detecting link binding type.
4625+ link -> discovery .notify_tries_left = 3 ;
4626+ link -> discovery .notify_retry_delay = 5000000 ;
4627+
4628+ // For PCIe-VDM, we want an all zeroes address for Route-to-Root-Complex.
4629+ rc = mctp_nl_hwaddr_len_byindex (
4630+ ctx -> nl , ifindex ,
4631+ & link -> discovery .notify_dest .hwaddr_len );
4632+ if (rc < 0 ) {
4633+ warnx ("Can't find hwaddr_len by index %d" , ifindex );
4634+ return - ENOENT ;
4635+ }
4636+
4637+ memset (link -> discovery .notify_dest .hwaddr , 0 ,
4638+ link -> discovery .notify_dest .hwaddr_len );
4639+ link -> discovery .notify_dest .ifindex = ifindex ;
4640+
4641+ rc = mctp_ops .sd_event .add_time_relative (
4642+ ctx -> event , & link -> discovery .notify_source ,
4643+ CLOCK_MONOTONIC , 0 , 0 , link_discovery_notify_callback ,
4644+ link );
4645+ if (rc >= 0 ) {
4646+ rc = sd_event_source_set_enabled (
4647+ link -> discovery .notify_source , SD_EVENT_ON );
4648+ }
4649+ if (rc < 0 ) {
4650+ warnx ("Failed to arm discovery notify timer" );
4651+ sd_event_source_disable_unref (
4652+ link -> discovery .notify_source );
4653+ }
45304654 }
45314655
45324656 link -> published = true;
0 commit comments