@@ -117,7 +117,14 @@ static const struct role roles[] = {
117117 },
118118};
119119
120+ enum discovery_state {
121+ DISCOVERY_UNSUPPORTED ,
122+ DISCOVERY_DISCOVERED ,
123+ DISCOVERY_UNDISCOVERED ,
124+ };
125+
120126struct link {
127+ enum discovery_state discovered ;
121128 bool published ;
122129 int ifindex ;
123130 enum endpoint_role role ;
@@ -777,6 +784,9 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
777784 warnx ("ERR: cannot add bus owner to object lists" );
778785 }
779786
787+ if (link_data -> discovered != DISCOVERY_UNSUPPORTED ) {
788+ link_data -> discovered = DISCOVERY_DISCOVERED ;
789+ }
780790 resp -> status =
781791 SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_ACCEPTED ) |
782792 SET_MCTP_EID_ALLOCATION_STATUS (MCTP_SET_EID_POOL_NONE );
@@ -786,6 +796,20 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
786796 return reply_message (ctx , sd , resp , resp_len , addr );
787797
788798 case MCTP_SET_EID_DISCOVERED :
799+ if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
800+ resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
801+ resp_len = sizeof (struct mctp_ctrl_resp );
802+ return reply_message (ctx , sd , resp , resp_len , addr );
803+ }
804+
805+ link_data -> discovered = DISCOVERY_DISCOVERED ;
806+ resp -> status =
807+ SET_MCTP_EID_ASSIGNMENT_STATUS (MCTP_SET_EID_REJECTED ) |
808+ SET_MCTP_EID_ALLOCATION_STATUS (MCTP_SET_EID_POOL_NONE );
809+ resp -> eid_set = req -> eid ;
810+ resp -> eid_pool_size = 0 ;
811+ return reply_message (ctx , sd , resp , resp_len , addr );
812+
789813 case MCTP_SET_EID_RESET :
790814 // unsupported
791815 resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
@@ -948,6 +972,97 @@ handle_control_resolve_endpoint_id(struct ctx *ctx, int sd,
948972 return reply_message (ctx , sd , resp , resp_len , addr );
949973}
950974
975+ static int handle_control_prepare_endpoint_discovery (
976+ struct ctx * ctx , int sd , const struct sockaddr_mctp_ext * addr ,
977+ const uint8_t * buf , const size_t buf_size )
978+ {
979+ struct mctp_ctrl_msg_hdr * req = NULL ;
980+ struct mctp_ctrl_resp_prepare_discovery respi = { 0 }, * resp = & respi ;
981+ struct link * link_data ;
982+
983+ if (buf_size < sizeof (* req )) {
984+ warnx ("short Prepare for Endpoint Discovery message" );
985+ return - ENOMSG ;
986+ }
987+
988+ link_data = mctp_nl_get_link_userdata (ctx -> nl , addr -> smctp_ifindex );
989+ if (!link_data ) {
990+ bug_warn ("unconfigured interface %d" , addr -> smctp_ifindex );
991+ return - ENOENT ;
992+ }
993+
994+ if (link_data -> role == ENDPOINT_ROLE_BUS_OWNER ) {
995+ // ignore message if we are bus owner
996+ return 0 ;
997+ }
998+
999+ req = (void * )buf ;
1000+ resp = (void * )resp ;
1001+ mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , * req );
1002+
1003+ if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
1004+ warnx ("received prepare for discovery request to unsupported interface %d" ,
1005+ addr -> smctp_ifindex );
1006+ resp -> completion_code = MCTP_CTRL_CC_ERROR_UNSUPPORTED_CMD ;
1007+ return reply_message_phys (ctx , sd , resp ,
1008+ sizeof (struct mctp_ctrl_resp ), addr );
1009+ }
1010+
1011+ if (link_data -> discovered == DISCOVERY_DISCOVERED ) {
1012+ link_data -> discovered = DISCOVERY_UNDISCOVERED ;
1013+ warnx ("clear discovered flag of interface %d" ,
1014+ addr -> smctp_ifindex );
1015+ }
1016+
1017+ // we need to send using physical addressing, no entry in routing table yet
1018+ resp -> completion_code = MCTP_CTRL_CC_SUCCESS ;
1019+ return reply_message_phys (ctx , sd , resp , sizeof (* resp ), addr );
1020+ }
1021+
1022+ static int
1023+ handle_control_endpoint_discovery (struct ctx * ctx , int sd ,
1024+ const struct sockaddr_mctp_ext * addr ,
1025+ const uint8_t * buf , const size_t buf_size )
1026+ {
1027+ struct mctp_ctrl_msg_hdr * req = NULL ;
1028+ struct mctp_ctrl_resp_endpoint_discovery respi = { 0 }, * resp = & respi ;
1029+ struct link * link_data ;
1030+
1031+ if (buf_size < sizeof (* req )) {
1032+ warnx ("short Endpoint Discovery message" );
1033+ return - ENOMSG ;
1034+ }
1035+
1036+ link_data = mctp_nl_get_link_userdata (ctx -> nl , addr -> smctp_ifindex );
1037+ if (!link_data ) {
1038+ bug_warn ("unconfigured interface %d" , addr -> smctp_ifindex );
1039+ return - ENOENT ;
1040+ }
1041+
1042+ if (link_data -> role == ENDPOINT_ROLE_BUS_OWNER ) {
1043+ // ignore message if we are bus owner
1044+ return 0 ;
1045+ }
1046+
1047+ if (link_data -> discovered == DISCOVERY_UNSUPPORTED ) {
1048+ resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
1049+ return reply_message (ctx , sd , resp ,
1050+ sizeof (struct mctp_ctrl_resp ), addr );
1051+ }
1052+
1053+ if (link_data -> discovered == DISCOVERY_DISCOVERED ) {
1054+ // if we are already discovered (i.e, assigned an EID), then no reply
1055+ return 0 ;
1056+ }
1057+
1058+ req = (void * )buf ;
1059+ resp = (void * )resp ;
1060+ mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , * req );
1061+
1062+ // we need to send using physical addressing, no entry in routing table yet
1063+ return reply_message_phys (ctx , sd , resp , sizeof (* resp ), addr );
1064+ }
1065+
9511066static int handle_control_unsupported (struct ctx * ctx , int sd ,
9521067 const struct sockaddr_mctp_ext * addr ,
9531068 const uint8_t * buf , const size_t buf_size )
@@ -1030,6 +1145,14 @@ static int cb_listen_control_msg(sd_event_source *s, int sd, uint32_t revents,
10301145 rc = handle_control_resolve_endpoint_id (ctx , sd , & addr , buf ,
10311146 buf_size );
10321147 break ;
1148+ case MCTP_CTRL_CMD_PREPARE_ENDPOINT_DISCOVERY :
1149+ rc = handle_control_prepare_endpoint_discovery (ctx , sd , & addr ,
1150+ buf , buf_size );
1151+ break ;
1152+ case MCTP_CTRL_CMD_ENDPOINT_DISCOVERY :
1153+ rc = handle_control_endpoint_discovery (ctx , sd , & addr , buf ,
1154+ buf_size );
1155+ break ;
10331156 default :
10341157 if (ctx -> verbose ) {
10351158 warnx ("Ignoring unsupported command code 0x%02x" ,
@@ -3905,10 +4028,14 @@ static int add_interface(struct ctx *ctx, int ifindex)
39054028 return - ENOENT ;
39064029 }
39074030
4031+ enum mctp_phys_binding phys_binding =
4032+ mctp_nl_phys_binding_byindex (ctx -> nl , ifindex );
4033+
39084034 struct link * link = calloc (1 , sizeof (* link ));
39094035 if (!link )
39104036 return - ENOMEM ;
39114037
4038+ link -> discovered = DISCOVERY_UNSUPPORTED ;
39124039 link -> published = false;
39134040 link -> ifindex = ifindex ;
39144041 link -> ctx = ctx ;
@@ -3937,6 +4064,11 @@ static int add_interface(struct ctx *ctx, int ifindex)
39374064 bus_link_owner_vtable , link );
39384065 }
39394066
4067+ if (phys_binding == MCTP_PHYS_BINDING_PCIE_VDM ||
4068+ phys_binding == MCTP_PHYS_BINDING_I3C ) {
4069+ link -> discovered = DISCOVERY_UNDISCOVERED ;
4070+ }
4071+
39404072 link -> published = true;
39414073 rc = emit_interface_added (link );
39424074 if (rc < 0 ) {
0 commit comments