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