@@ -148,6 +148,8 @@ struct link {
148148 struct ctx * ctx ;
149149};
150150
151+ struct vdm_type_support ;
152+
151153struct peer {
152154 uint32_t net ;
153155 mctp_eid_t eid ;
@@ -185,6 +187,9 @@ struct peer {
185187 uint8_t * message_types ;
186188 size_t num_message_types ;
187189
190+ struct vdm_type_support * vdm_types ;
191+ size_t num_vdm_types ;
192+
188193 // From Get Endpoint ID
189194 uint8_t endpoint_type ;
190195 uint8_t medium_spec ;
@@ -1060,8 +1065,9 @@ handle_control_get_vdm_type_support(struct ctx *ctx, int sd,
10601065 struct mctp_ctrl_resp_get_vdm_support * resp = NULL ;
10611066 struct mctp_ctrl_cmd_get_vdm_support * req = NULL ;
10621067 size_t resp_len , max_rsp_len , vdm_count ;
1068+ struct mctp_vdm_pcie_data * vdm_pcie ;
1069+ struct mctp_vdm_iana_data * vdm_iana ;
10631070 struct vdm_type_support * cur_vdm ;
1064- uint16_t * cmd_type_ptr ;
10651071 uint8_t * resp_buf ;
10661072 int rc ;
10671073
@@ -1073,15 +1079,14 @@ handle_control_get_vdm_type_support(struct ctx *ctx, int sd,
10731079 req = (void * )buf ;
10741080 vdm_count = ctx -> num_supported_vdm_types ;
10751081 // Allocate space for 32 bit VID + 16 bit cmd set
1076- max_rsp_len = sizeof (* resp ) + sizeof (uint16_t );
1082+ max_rsp_len = sizeof (* resp ) + sizeof (struct mctp_vdm_iana_data );
10771083 resp_len = max_rsp_len ;
10781084 resp_buf = malloc (max_rsp_len );
10791085 if (!resp_buf ) {
10801086 warnx ("Failed to allocate response buffer" );
10811087 return - ENOMEM ;
10821088 }
10831089 resp = (void * )resp_buf ;
1084- cmd_type_ptr = (uint16_t * )(resp + 1 );
10851090 mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , req -> ctrl_hdr );
10861091
10871092 if (req -> vendor_id_set_selector >= vdm_count ) {
@@ -1103,17 +1108,16 @@ handle_control_get_vdm_type_support(struct ctx *ctx, int sd,
11031108 resp -> vendor_id_format = cur_vdm -> format ;
11041109
11051110 if (cur_vdm -> format == VID_FORMAT_PCIE ) {
1106- // 4 bytes was reserved for VID, but PCIe VID uses only 2 bytes.
1107- cmd_type_ptr -- ;
1108- resp_len = max_rsp_len - sizeof (uint16_t );
1109- resp -> vendor_id_data_pcie =
1110- htobe16 (cur_vdm -> vendor_id .pcie );
1111+ vdm_pcie = (void * )(resp + 1 );
1112+ resp_len = sizeof (* resp ) + sizeof (struct mctp_vdm_pcie_data );
1113+ vdm_pcie -> vendor_id = htobe16 (cur_vdm -> vendor_id .pcie );
1114+ vdm_pcie -> cmd_set = htobe16 (cur_vdm -> cmd_set );
11111115 } else {
1112- resp -> vendor_id_data_iana =
1116+ vdm_iana = (void * )(resp + 1 );
1117+ vdm_iana -> enterprise_number =
11131118 htobe32 (cur_vdm -> vendor_id .iana );
1119+ vdm_iana -> cmd_set = htobe16 (cur_vdm -> cmd_set );
11141120 }
1115-
1116- * cmd_type_ptr = htobe16 (cur_vdm -> cmd_set );
11171121 }
11181122
11191123 rc = reply_message (ctx , sd , resp , resp_len , addr );
@@ -2085,6 +2089,7 @@ static int remove_peer(struct peer *peer)
20852089
20862090 n -> peers [peer -> eid ] = NULL ;
20872091 free (peer -> message_types );
2092+ free (peer -> vdm_types );
20882093 free (peer -> uuid );
20892094
20902095 for (idx = 0 ; idx < ctx -> num_peers ; idx ++ ) {
@@ -2127,6 +2132,7 @@ static void free_peers(struct ctx *ctx)
21272132 for (size_t i = 0 ; i < ctx -> num_peers ; i ++ ) {
21282133 struct peer * peer = ctx -> peers [i ];
21292134 free (peer -> message_types );
2135+ free (peer -> vdm_types );
21302136 free (peer -> uuid );
21312137 free (peer -> path );
21322138 free (peer -> bridge_ep_poll .sources );
@@ -2585,6 +2591,106 @@ static int query_get_peer_msgtypes(struct peer *peer)
25852591 return rc ;
25862592}
25872593
2594+ static int query_get_peer_vdm_types (struct peer * peer )
2595+ {
2596+ struct vdm_type_support * cur_vdm_type , * new_vdm , * vdm_types = NULL ;
2597+ size_t buf_size , expect_size , new_size , num_vdm_types = 0 ;
2598+ struct mctp_ctrl_resp_get_vdm_support * resp = NULL ;
2599+ struct mctp_ctrl_cmd_get_vdm_support req ;
2600+ struct mctp_vdm_pcie_data * vdm_pcie ;
2601+ struct mctp_vdm_iana_data * vdm_iana ;
2602+ struct sockaddr_mctp_ext addr ;
2603+ uint8_t iid , fmt , * buf = NULL ;
2604+ int rc ;
2605+
2606+ req .ctrl_hdr .command_code = MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT ;
2607+ req .vendor_id_set_selector = 0 ;
2608+
2609+ while (true) {
2610+ iid = mctp_next_iid (peer -> ctx );
2611+
2612+ mctp_ctrl_msg_hdr_init_req (
2613+ & req .ctrl_hdr , iid ,
2614+ MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT );
2615+ if (buf ) {
2616+ free (buf );
2617+ buf = NULL ;
2618+ }
2619+ rc = endpoint_query_peer (peer , MCTP_CTRL_HDR_MSG_TYPE , & req ,
2620+ sizeof (req ), & buf , & buf_size , & addr );
2621+ if (rc < 0 )
2622+ break ;
2623+
2624+ expect_size = sizeof (* resp );
2625+ rc = mctp_ctrl_validate_response (
2626+ buf , buf_size , expect_size , peer_tostr_short (peer ), iid ,
2627+ MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT );
2628+ if (rc )
2629+ break ;
2630+
2631+ resp = (void * )buf ;
2632+ fmt = resp -> vendor_id_format ;
2633+ if (fmt == MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) {
2634+ expect_size = sizeof (* resp ) +
2635+ sizeof (struct mctp_vdm_pcie_data );
2636+ } else if (fmt == MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
2637+ expect_size = sizeof (* resp ) +
2638+ sizeof (struct mctp_vdm_iana_data );
2639+ } else {
2640+ warnx ("%s: bad vendor_id_format 0x%02x dest %s" ,
2641+ __func__ , fmt , peer_tostr (peer ));
2642+ rc = - ENOMSG ;
2643+ break ;
2644+ }
2645+ if (buf_size != expect_size ) {
2646+ warnx ("%s: bad reply length. got %zu, expected %zu dest %s" ,
2647+ __func__ , buf_size , expect_size ,
2648+ peer_tostr (peer ));
2649+ rc = - ENOMSG ;
2650+ break ;
2651+ }
2652+
2653+ new_size =
2654+ (num_vdm_types + 1 ) * sizeof (struct vdm_type_support );
2655+ new_vdm = realloc (vdm_types , new_size );
2656+ if (!new_vdm ) {
2657+ rc = - ENOMEM ;
2658+ break ;
2659+ }
2660+ vdm_types = new_vdm ;
2661+ cur_vdm_type = vdm_types + num_vdm_types ;
2662+ cur_vdm_type -> format = fmt ;
2663+
2664+ if (fmt == MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
2665+ vdm_iana = (struct mctp_vdm_iana_data * )(resp + 1 );
2666+ cur_vdm_type -> vendor_id .iana =
2667+ be32toh (vdm_iana -> enterprise_number );
2668+ cur_vdm_type -> cmd_set = be16toh (vdm_iana -> cmd_set );
2669+ } else {
2670+ vdm_pcie = (struct mctp_vdm_pcie_data * )(resp + 1 );
2671+ cur_vdm_type -> vendor_id .pcie =
2672+ be16toh (vdm_pcie -> vendor_id );
2673+ cur_vdm_type -> cmd_set = be16toh (vdm_pcie -> cmd_set );
2674+ }
2675+ num_vdm_types ++ ;
2676+ if (resp -> vendor_id_set_selector ==
2677+ MCTP_GET_VDM_SUPPORT_NO_MORE_CAP_SET ) {
2678+ peer -> vdm_types = vdm_types ;
2679+ vdm_types = NULL ;
2680+ peer -> num_vdm_types = num_vdm_types ;
2681+ rc = 0 ;
2682+ break ;
2683+ }
2684+
2685+ /* Use the next selector from the response. 0xFF indicates no more entries */
2686+ req .vendor_id_set_selector = resp -> vendor_id_set_selector ;
2687+ }
2688+
2689+ free (buf );
2690+ free (vdm_types );
2691+ return rc ;
2692+ }
2693+
25882694static int peer_set_uuid (struct peer * peer , const uint8_t uuid [16 ])
25892695{
25902696 if (!peer -> uuid ) {
@@ -3019,6 +3125,7 @@ static int method_learn_endpoint(sd_bus_message *call, void *data,
30193125static int query_peer_properties (struct peer * peer )
30203126{
30213127 const unsigned int max_retries = 4 ;
3128+ bool supports_vdm = false;
30223129 int rc ;
30233130
30243131 for (unsigned int i = 0 ; i < max_retries ; i ++ ) {
@@ -3047,6 +3154,41 @@ static int query_peer_properties(struct peer *peer)
30473154 }
30483155 }
30493156
3157+ for (unsigned int i = 0 ; i < peer -> num_message_types ; i ++ ) {
3158+ if (peer -> message_types [i ] ==
3159+ MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ||
3160+ peer -> message_types [i ] ==
3161+ MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) {
3162+ supports_vdm = true;
3163+ break ;
3164+ }
3165+ }
3166+
3167+ if (supports_vdm ) {
3168+ for (unsigned int i = 0 ; i < max_retries ; i ++ ) {
3169+ rc = query_get_peer_vdm_types (peer );
3170+
3171+ if (rc == 0 )
3172+ break ;
3173+
3174+ // On timeout, retry
3175+ if (rc == - ETIMEDOUT ) {
3176+ if (peer -> ctx -> verbose )
3177+ warnx ("Retrying to get vendor message types for %s. Attempt %u" ,
3178+ peer_tostr (peer ), i + 1 );
3179+ rc = 0 ;
3180+ continue ;
3181+ }
3182+
3183+ if (rc < 0 ) {
3184+ warnx ("Error getting vendor message types for %s. Ignoring error %d %s" ,
3185+ peer_tostr (peer ), rc , strerror (- rc ));
3186+ rc = 0 ;
3187+ break ;
3188+ }
3189+ }
3190+ }
3191+
30503192 for (unsigned int i = 0 ; i < max_retries ; i ++ ) {
30513193 rc = query_get_peer_uuid (peer );
30523194
@@ -3939,6 +4081,41 @@ static int bus_endpoint_get_prop(sd_bus *bus, const char *path,
39394081 rc = sd_bus_message_append_array (reply , 'y' ,
39404082 peer -> message_types ,
39414083 peer -> num_message_types );
4084+ } else if (strcmp (property , "VendorDefinedMessageTypes" ) == 0 ) {
4085+ rc = sd_bus_message_open_container (reply , 'a' , "(yvq)" );
4086+ if (rc < 0 )
4087+ return rc ;
4088+
4089+ for (size_t i = 0 ; i < peer -> num_vdm_types ; i ++ ) {
4090+ struct vdm_type_support * vdm = & peer -> vdm_types [i ];
4091+ rc = sd_bus_message_open_container (reply , 'r' , "yvq" );
4092+ if (rc < 0 )
4093+ return rc ;
4094+
4095+ rc = sd_bus_message_append (reply , "y" , vdm -> format );
4096+ if (rc < 0 )
4097+ return rc ;
4098+
4099+ if (vdm -> format == VID_FORMAT_PCIE ) {
4100+ rc = sd_bus_message_append (reply , "v" , "q" ,
4101+ vdm -> vendor_id .pcie );
4102+ } else {
4103+ rc = sd_bus_message_append (reply , "v" , "u" ,
4104+ vdm -> vendor_id .iana );
4105+ }
4106+ if (rc < 0 )
4107+ return rc ;
4108+
4109+ rc = sd_bus_message_append (reply , "q" , vdm -> cmd_set );
4110+ if (rc < 0 )
4111+ return rc ;
4112+
4113+ rc = sd_bus_message_close_container (reply );
4114+ if (rc < 0 )
4115+ return rc ;
4116+ }
4117+
4118+ rc = sd_bus_message_close_container (reply );
39424119 } else if (strcmp (property , "UUID" ) == 0 && peer -> uuid ) {
39434120 const char * s = dfree (bytes_to_uuid (peer -> uuid ));
39444121 rc = sd_bus_message_append (reply , "s" , s );
@@ -4128,6 +4305,11 @@ static const sd_bus_vtable bus_endpoint_obmc_vtable[] = {
41284305 bus_endpoint_get_prop ,
41294306 0 ,
41304307 SD_BUS_VTABLE_PROPERTY_CONST ),
4308+ SD_BUS_PROPERTY ("VendorDefinedMessageTypes" ,
4309+ "a(yvq)" ,
4310+ bus_endpoint_get_prop ,
4311+ 0 ,
4312+ SD_BUS_VTABLE_PROPERTY_CONST ),
41314313 SD_BUS_VTABLE_END
41324314};
41334315
0 commit comments