@@ -119,7 +119,14 @@ static const struct role roles[] = {
119119 },
120120};
121121
122+ enum discovery_state {
123+ DISCOVERY_UNSUPPORTED ,
124+ DISCOVERY_DISCOVERED ,
125+ DISCOVERY_UNDISCOVERED ,
126+ };
127+
122128struct link {
129+ enum discovery_state discovered ;
123130 bool published ;
124131 int ifindex ;
125132 enum endpoint_role role ;
@@ -786,6 +793,9 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
786793 warnx ("ERR: cannot add bus owner to object lists" );
787794 }
788795
796+ if (link_data -> discovered != DISCOVERY_UNSUPPORTED ) {
797+ link_data -> discovered = DISCOVERY_DISCOVERED ;
798+ }
789799 resp -> status =
790800 SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_ACCEPTED ) |
791801 SET_MCTP_EID_ALLOCATION_STATUS (MCTP_SET_EID_POOL_NONE );
@@ -795,6 +805,20 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
795805 return reply_message (ctx , sd , resp , resp_len , addr );
796806
797807 case MCTP_SET_EID_DISCOVERED :
808+ if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
809+ resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
810+ resp_len = sizeof (struct mctp_ctrl_resp );
811+ return reply_message (ctx , sd , resp , resp_len , addr );
812+ }
813+
814+ link_data -> discovered = DISCOVERY_DISCOVERED ;
815+ resp -> status =
816+ SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_REJECTED ) |
817+ SET_MCTP_EID_ALLOCATION_STATUS (MCTP_SET_EID_POOL_NONE );
818+ resp -> eid_set = req -> eid ;
819+ resp -> eid_pool_size = 0 ;
820+ return reply_message (ctx , sd , resp , resp_len , addr );
821+
798822 case MCTP_SET_EID_RESET :
799823 // unsupported
800824 resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
@@ -957,6 +981,97 @@ handle_control_resolve_endpoint_id(struct ctx *ctx, int sd,
957981 return reply_message (ctx , sd , resp , resp_len , addr );
958982}
959983
984+ static int handle_control_prepare_endpoint_discovery (
985+ struct ctx * ctx , int sd , const struct sockaddr_mctp_ext * addr ,
986+ const uint8_t * buf , const size_t buf_size )
987+ {
988+ struct mctp_ctrl_msg_hdr * req = NULL ;
989+ struct mctp_ctrl_resp_prepare_discovery respi = { 0 }, * resp = & respi ;
990+ struct link * link_data ;
991+
992+ if (buf_size < sizeof (* req )) {
993+ warnx ("short Prepare for Endpoint Discovery message" );
994+ return - ENOMSG ;
995+ }
996+
997+ link_data = mctp_nl_get_link_userdata (ctx -> nl , addr -> smctp_ifindex );
998+ if (!link_data ) {
999+ bug_warn ("unconfigured interface %d" , addr -> smctp_ifindex );
1000+ return - ENOENT ;
1001+ }
1002+
1003+ if (link_data -> role == ENDPOINT_ROLE_BUS_OWNER ) {
1004+ // ignore message if we are bus owner
1005+ return 0 ;
1006+ }
1007+
1008+ req = (void * )buf ;
1009+ resp = (void * )resp ;
1010+ mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , * req );
1011+
1012+ if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
1013+ warnx ("received prepare for discovery request to unsupported interface %d" ,
1014+ addr -> smctp_ifindex );
1015+ resp -> completion_code = MCTP_CTRL_CC_ERROR_UNSUPPORTED_CMD ;
1016+ return reply_message_phys (ctx , sd , resp ,
1017+ sizeof (struct mctp_ctrl_resp ), addr );
1018+ }
1019+
1020+ if (link_data -> discovered == DISCOVERY_DISCOVERED ) {
1021+ link_data -> discovered = DISCOVERY_UNDISCOVERED ;
1022+ warnx ("clear discovered flag of interface %d" ,
1023+ addr -> smctp_ifindex );
1024+ }
1025+
1026+ // we need to send using physical addressing, no entry in routing table yet
1027+ resp -> completion_code = MCTP_CTRL_CC_SUCCESS ;
1028+ return reply_message_phys (ctx , sd , resp , sizeof (* resp ), addr );
1029+ }
1030+
1031+ static int
1032+ handle_control_endpoint_discovery (struct ctx * ctx , int sd ,
1033+ const struct sockaddr_mctp_ext * addr ,
1034+ const uint8_t * buf , const size_t buf_size )
1035+ {
1036+ struct mctp_ctrl_msg_hdr * req = NULL ;
1037+ struct mctp_ctrl_resp_endpoint_discovery respi = { 0 }, * resp = & respi ;
1038+ struct link * link_data ;
1039+
1040+ if (buf_size < sizeof (* req )) {
1041+ warnx ("short Endpoint Discovery message" );
1042+ return - ENOMSG ;
1043+ }
1044+
1045+ link_data = mctp_nl_get_link_userdata (ctx -> nl , addr -> smctp_ifindex );
1046+ if (!link_data ) {
1047+ bug_warn ("unconfigured interface %d" , addr -> smctp_ifindex );
1048+ return - ENOENT ;
1049+ }
1050+
1051+ if (link_data -> role == ENDPOINT_ROLE_BUS_OWNER ) {
1052+ // ignore message if we are bus owner
1053+ return 0 ;
1054+ }
1055+
1056+ if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
1057+ resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
1058+ return reply_message (ctx , sd , resp ,
1059+ sizeof (struct mctp_ctrl_resp ), addr );
1060+ }
1061+
1062+ if (link_data -> discovered == DISCOVERY_DISCOVERED ) {
1063+ // if we are already discovered (i.e, assigned an EID), then no reply
1064+ return 0 ;
1065+ }
1066+
1067+ req = (void * )buf ;
1068+ resp = (void * )resp ;
1069+ mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , * req );
1070+
1071+ // we need to send using physical addressing, no entry in routing table yet
1072+ return reply_message_phys (ctx , sd , resp , sizeof (* resp ), addr );
1073+ }
1074+
9601075static int handle_control_unsupported (struct ctx * ctx , int sd ,
9611076 const struct sockaddr_mctp_ext * addr ,
9621077 const uint8_t * buf , const size_t buf_size )
@@ -1039,6 +1154,14 @@ static int cb_listen_control_msg(sd_event_source *s, int sd, uint32_t revents,
10391154 rc = handle_control_resolve_endpoint_id (ctx , sd , & addr , buf ,
10401155 buf_size );
10411156 break ;
1157+ case MCTP_CTRL_CMD_PREPARE_ENDPOINT_DISCOVERY :
1158+ rc = handle_control_prepare_endpoint_discovery (ctx , sd , & addr ,
1159+ buf , buf_size );
1160+ break ;
1161+ case MCTP_CTRL_CMD_ENDPOINT_DISCOVERY :
1162+ rc = handle_control_endpoint_discovery (ctx , sd , & addr , buf ,
1163+ buf_size );
1164+ break ;
10421165 default :
10431166 if (ctx -> verbose ) {
10441167 warnx ("Ignoring unsupported command code 0x%02x" ,
@@ -4150,10 +4273,13 @@ static int add_interface(struct ctx *ctx, int ifindex)
41504273 return - ENOENT ;
41514274 }
41524275
4276+ uint8_t phys_binding = mctp_nl_phys_binding_byindex (ctx -> nl , ifindex );
4277+
41534278 struct link * link = calloc (1 , sizeof (* link ));
41544279 if (!link )
41554280 return - ENOMEM ;
41564281
4282+ link -> discovered = DISCOVERY_UNSUPPORTED ;
41574283 link -> published = false;
41584284 link -> ifindex = ifindex ;
41594285 link -> ctx = ctx ;
@@ -4182,6 +4308,10 @@ static int add_interface(struct ctx *ctx, int ifindex)
41824308 bus_link_owner_vtable , link );
41834309 }
41844310
4311+ if (phys_binding == MCTP_PHYS_BINDING_PCIE_VDM ) {
4312+ link -> discovered = DISCOVERY_UNDISCOVERED ;
4313+ }
4314+
41854315 link -> published = true;
41864316 rc = emit_interface_added (link );
41874317 if (rc < 0 ) {
0 commit comments