@@ -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,17 @@ 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 ) +
1113+ sizeof (struct mctp_vdm_pcie_data );
1114+ vdm_pcie -> vendor_id = htobe16 ( cur_vdm -> vendor_id . pcie );
1115+ vdm_pcie -> cmd_set = htobe16 (cur_vdm -> cmd_set );
11111116 } else {
1112- resp -> vendor_id_data_iana =
1117+ vdm_iana = (void * )(resp + 1 );
1118+ vdm_iana -> enterprise_number =
11131119 htobe32 (cur_vdm -> vendor_id .iana );
1120+ vdm_iana -> cmd_set = htobe16 (cur_vdm -> cmd_set );
11141121 }
1115-
1116- * cmd_type_ptr = htobe16 (cur_vdm -> cmd_set );
11171122 }
11181123
11191124 rc = reply_message (ctx , sd , resp , resp_len , addr );
@@ -2085,6 +2090,7 @@ static int remove_peer(struct peer *peer)
20852090
20862091 n -> peers [peer -> eid ] = NULL ;
20872092 free (peer -> message_types );
2093+ free (peer -> vdm_types );
20882094 free (peer -> uuid );
20892095
20902096 for (idx = 0 ; idx < ctx -> num_peers ; idx ++ ) {
@@ -2127,6 +2133,7 @@ static void free_peers(struct ctx *ctx)
21272133 for (size_t i = 0 ; i < ctx -> num_peers ; i ++ ) {
21282134 struct peer * peer = ctx -> peers [i ];
21292135 free (peer -> message_types );
2136+ free (peer -> vdm_types );
21302137 free (peer -> uuid );
21312138 free (peer -> path );
21322139 free (peer -> bridge_ep_poll .sources );
@@ -2585,6 +2592,112 @@ static int query_get_peer_msgtypes(struct peer *peer)
25852592 return rc ;
25862593}
25872594
2595+ static int query_get_peer_vdm_types (struct peer * peer )
2596+ {
2597+ struct mctp_ctrl_resp_get_vdm_support * resp = NULL ;
2598+ struct vdm_type_support * cur_vdm_type , * new_vdm ;
2599+ struct vdm_type_support * vdm_types = NULL ;
2600+ struct mctp_ctrl_cmd_get_vdm_support req ;
2601+ size_t buf_size , expect_size , new_size ;
2602+ struct mctp_vdm_pcie_data * vdm_pcie ;
2603+ struct mctp_vdm_iana_data * vdm_iana ;
2604+ struct sockaddr_mctp_ext addr ;
2605+ size_t num_vdm_types = 0 ;
2606+ uint8_t * buf = NULL ;
2607+ uint8_t iid , fmt ;
2608+ int rc ;
2609+
2610+ req .ctrl_hdr .command_code = MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT ;
2611+ req .vendor_id_set_selector = 0 ;
2612+
2613+ while (true) {
2614+ iid = mctp_next_iid (peer -> ctx );
2615+
2616+ mctp_ctrl_msg_hdr_init_req (
2617+ & req .ctrl_hdr , iid ,
2618+ MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT );
2619+ if (buf ) {
2620+ free (buf );
2621+ buf = NULL ;
2622+ }
2623+ rc = endpoint_query_peer (peer , MCTP_CTRL_HDR_MSG_TYPE , & req ,
2624+ sizeof (req ), & buf , & buf_size , & addr );
2625+ if (rc < 0 )
2626+ break ;
2627+
2628+ /* Check for minimum length of PCIe VDM*/
2629+ expect_size = sizeof (* resp ) + sizeof (struct mctp_vdm_pcie_data );
2630+ rc = mctp_ctrl_validate_response (
2631+ buf , buf_size , expect_size , peer_tostr_short (peer ), iid ,
2632+ MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT );
2633+ if (rc )
2634+ break ;
2635+
2636+ resp = (void * )buf ;
2637+ fmt = resp -> vendor_id_format ;
2638+ if (fmt != MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID &&
2639+ fmt != MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
2640+ warnx ("%s: bad vendor_id_format 0x%02x dest %s" ,
2641+ __func__ , fmt , peer_tostr (peer ));
2642+ rc = - ENOMSG ;
2643+ break ;
2644+ }
2645+
2646+ if (fmt == MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
2647+ /* Accomodate 2 bytes for IANA VID */
2648+ expect_size = sizeof (* resp ) +
2649+ sizeof (struct mctp_vdm_iana_data );
2650+ }
2651+
2652+ if (buf_size != expect_size ) {
2653+ warnx ("%s: bad reply length. got %zu, expected %zu dest %s" ,
2654+ __func__ , buf_size , expect_size ,
2655+ peer_tostr (peer ));
2656+ rc = - ENOMSG ;
2657+ break ;
2658+ }
2659+
2660+ new_size =
2661+ (num_vdm_types + 1 ) * sizeof (struct vdm_type_support );
2662+ new_vdm = realloc (vdm_types , new_size );
2663+ if (!new_vdm ) {
2664+ rc = - ENOMEM ;
2665+ break ;
2666+ }
2667+ vdm_types = new_vdm ;
2668+ cur_vdm_type = vdm_types + num_vdm_types ;
2669+ cur_vdm_type -> format = fmt ;
2670+
2671+ if (fmt == MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
2672+ vdm_iana = (struct mctp_vdm_iana_data * )(resp + 1 );
2673+ cur_vdm_type -> vendor_id .iana =
2674+ be32toh (vdm_iana -> enterprise_number );
2675+ cur_vdm_type -> cmd_set = be16toh (vdm_iana -> cmd_set );
2676+ } else {
2677+ vdm_pcie = (struct mctp_vdm_pcie_data * )(resp + 1 );
2678+ cur_vdm_type -> vendor_id .pcie =
2679+ be16toh (vdm_pcie -> vendor_id );
2680+ cur_vdm_type -> cmd_set = be16toh (vdm_pcie -> cmd_set );
2681+ }
2682+ num_vdm_types ++ ;
2683+ if (resp -> vendor_id_set_selector ==
2684+ MCTP_GET_VDM_SUPPORT_NO_MORE_CAP_SET ) {
2685+ peer -> vdm_types = vdm_types ;
2686+ vdm_types = NULL ;
2687+ peer -> num_vdm_types = num_vdm_types ;
2688+ rc = 0 ;
2689+ break ;
2690+ }
2691+
2692+ /* Use the next selector from the response. 0xFF indicates no more entries */
2693+ req .vendor_id_set_selector = resp -> vendor_id_set_selector ;
2694+ }
2695+
2696+ free (buf );
2697+ free (vdm_types );
2698+ return rc ;
2699+ }
2700+
25882701static int peer_set_uuid (struct peer * peer , const uint8_t uuid [16 ])
25892702{
25902703 if (!peer -> uuid ) {
@@ -3019,6 +3132,7 @@ static int method_learn_endpoint(sd_bus_message *call, void *data,
30193132static int query_peer_properties (struct peer * peer )
30203133{
30213134 const unsigned int max_retries = 4 ;
3135+ bool supports_vdm = false;
30223136 int rc ;
30233137
30243138 for (unsigned int i = 0 ; i < max_retries ; i ++ ) {
@@ -3047,6 +3161,41 @@ static int query_peer_properties(struct peer *peer)
30473161 }
30483162 }
30493163
3164+ for (unsigned int i = 0 ; i < peer -> num_message_types ; i ++ ) {
3165+ if (peer -> message_types [i ] ==
3166+ MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ||
3167+ peer -> message_types [i ] ==
3168+ MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) {
3169+ supports_vdm = true;
3170+ break ;
3171+ }
3172+ }
3173+
3174+ if (supports_vdm ) {
3175+ for (unsigned int i = 0 ; i < max_retries ; i ++ ) {
3176+ rc = query_get_peer_vdm_types (peer );
3177+ // Success
3178+ if (rc == 0 )
3179+ break ;
3180+
3181+ // On timeout, retry
3182+ if (rc == - ETIMEDOUT ) {
3183+ if (peer -> ctx -> verbose )
3184+ warnx ("Retrying to get vendor message types for %s. Attempt %u" ,
3185+ peer_tostr (peer ), i + 1 );
3186+ rc = 0 ;
3187+ continue ;
3188+ }
3189+
3190+ if (rc < 0 ) {
3191+ warnx ("Error getting vendor message types for %s. Ignoring error %d %s" ,
3192+ peer_tostr (peer ), rc , strerror (- rc ));
3193+ rc = 0 ;
3194+ break ;
3195+ }
3196+ }
3197+ }
3198+
30503199 for (unsigned int i = 0 ; i < max_retries ; i ++ ) {
30513200 rc = query_get_peer_uuid (peer );
30523201
@@ -3939,6 +4088,42 @@ static int bus_endpoint_get_prop(sd_bus *bus, const char *path,
39394088 rc = sd_bus_message_append_array (reply , 'y' ,
39404089 peer -> message_types ,
39414090 peer -> num_message_types );
4091+ } else if (strcmp (property , "VendorDefinedMessageTypes" ) == 0 ) {
4092+ rc = sd_bus_message_open_container (reply , 'a' , "(yvu)" );
4093+ if (rc < 0 )
4094+ return rc ;
4095+
4096+ for (size_t i = 0 ; i < peer -> num_vdm_types ; i ++ ) {
4097+ struct vdm_type_support * vdm = & peer -> vdm_types [i ];
4098+ rc = sd_bus_message_open_container (reply , 'r' , "yvu" );
4099+ if (rc < 0 )
4100+ return rc ;
4101+
4102+ rc = sd_bus_message_append (reply , "y" , vdm -> format );
4103+ if (rc < 0 )
4104+ return rc ;
4105+
4106+ if (vdm -> format == VID_FORMAT_PCIE ) {
4107+ rc = sd_bus_message_append (reply , "v" , "q" ,
4108+ vdm -> vendor_id .pcie );
4109+ } else {
4110+ rc = sd_bus_message_append (reply , "v" , "u" ,
4111+ vdm -> vendor_id .iana );
4112+ }
4113+ if (rc < 0 )
4114+ return rc ;
4115+
4116+ rc = sd_bus_message_append (reply , "u" ,
4117+ (uint32_t )vdm -> cmd_set );
4118+ if (rc < 0 )
4119+ return rc ;
4120+
4121+ rc = sd_bus_message_close_container (reply );
4122+ if (rc < 0 )
4123+ return rc ;
4124+ }
4125+
4126+ rc = sd_bus_message_close_container (reply );
39424127 } else if (strcmp (property , "UUID" ) == 0 && peer -> uuid ) {
39434128 const char * s = dfree (bytes_to_uuid (peer -> uuid ));
39444129 rc = sd_bus_message_append (reply , "s" , s );
@@ -4128,6 +4313,11 @@ static const sd_bus_vtable bus_endpoint_obmc_vtable[] = {
41284313 bus_endpoint_get_prop ,
41294314 0 ,
41304315 SD_BUS_VTABLE_PROPERTY_CONST ),
4316+ SD_BUS_PROPERTY ("VendorDefinedMessageTypes" ,
4317+ "a(yvu)" ,
4318+ bus_endpoint_get_prop ,
4319+ 0 ,
4320+ SD_BUS_VTABLE_PROPERTY_CONST ),
41314321 SD_BUS_VTABLE_END
41324322};
41334323
0 commit comments