@@ -140,6 +140,8 @@ struct link {
140140 struct ctx * ctx ;
141141};
142142
143+ struct vdm_type_support ;
144+
143145struct peer {
144146 uint32_t net ;
145147 mctp_eid_t eid ;
@@ -177,6 +179,9 @@ struct peer {
177179 uint8_t * message_types ;
178180 size_t num_message_types ;
179181
182+ struct vdm_type_support * vdm_types ;
183+ size_t num_vdm_types ;
184+
180185 // From Get Endpoint ID
181186 uint8_t endpoint_type ;
182187 uint8_t medium_spec ;
@@ -2013,6 +2018,7 @@ static int remove_peer(struct peer *peer)
20132018
20142019 n -> peers [peer -> eid ] = NULL ;
20152020 free (peer -> message_types );
2021+ free (peer -> vdm_types );
20162022 free (peer -> uuid );
20172023
20182024 for (idx = 0 ; idx < ctx -> num_peers ; idx ++ ) {
@@ -2055,6 +2061,7 @@ static void free_peers(struct ctx *ctx)
20552061 for (size_t i = 0 ; i < ctx -> num_peers ; i ++ ) {
20562062 struct peer * peer = ctx -> peers [i ];
20572063 free (peer -> message_types );
2064+ free (peer -> vdm_types );
20582065 free (peer -> uuid );
20592066 free (peer -> path );
20602067 sd_bus_slot_unref (peer -> slot_obmc_endpoint );
@@ -2512,6 +2519,116 @@ static int query_get_peer_msgtypes(struct peer *peer)
25122519 return rc ;
25132520}
25142521
2522+ static int query_get_peer_vdm_types (struct peer * peer )
2523+ {
2524+ struct mctp_ctrl_resp_get_vdm_support * resp = NULL ;
2525+ struct vdm_type_support * cur_vdm_type , * new_vdm ;
2526+ struct mctp_ctrl_cmd_get_vdm_support req ;
2527+ size_t buf_size , expect_size , new_size ;
2528+ struct sockaddr_mctp_ext addr ;
2529+ uint8_t * buf = NULL ;
2530+ uint16_t * cmd_set ;
2531+ uint8_t iid ;
2532+ int rc ;
2533+
2534+ peer -> num_vdm_types = 0 ;
2535+ free (peer -> vdm_types );
2536+ peer -> vdm_types = NULL ;
2537+
2538+ req .ctrl_hdr .command_code = MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT ;
2539+ req .vendor_id_set_selector = 0 ;
2540+
2541+ while (req .vendor_id_set_selector !=
2542+ MCTP_GET_VDM_SUPPORT_NO_MORE_CAP_SET ) {
2543+ iid = mctp_next_iid (peer -> ctx );
2544+
2545+ mctp_ctrl_msg_hdr_init_req (
2546+ & req .ctrl_hdr , iid ,
2547+ MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT );
2548+ rc = endpoint_query_peer (peer , MCTP_CTRL_HDR_MSG_TYPE , & req ,
2549+ sizeof (req ), & buf , & buf_size , & addr );
2550+ if (rc < 0 )
2551+ goto out ;
2552+
2553+ /* Check for minimum length of PCIe VDM*/
2554+ expect_size = sizeof (* resp );
2555+ rc = mctp_ctrl_validate_response (
2556+ buf , buf_size , expect_size , peer_tostr_short (peer ), iid ,
2557+ MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT );
2558+ if (rc )
2559+ goto out ;
2560+
2561+ resp = (void * )buf ;
2562+ if (resp -> vendor_id_format !=
2563+ MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID &&
2564+ resp -> vendor_id_format !=
2565+ MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
2566+ warnx ("%s: bad vendor_id_format 0x%02x dest %s" ,
2567+ __func__ , resp -> vendor_id_format ,
2568+ peer_tostr (peer ));
2569+ rc = - ENOMSG ;
2570+ goto out ;
2571+ }
2572+
2573+ if (resp -> vendor_id_format ==
2574+ MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
2575+ /* Accomodate 2 bytes for IANA VID */
2576+ expect_size += sizeof (uint16_t );
2577+ }
2578+
2579+ if (buf_size != expect_size ) {
2580+ warnx ("%s: bad reply length. got %zu, expected %zu dest %s" ,
2581+ __func__ , buf_size , expect_size ,
2582+ peer_tostr (peer ));
2583+ rc = - ENOMSG ;
2584+ goto out ;
2585+ }
2586+
2587+ new_size = (peer -> num_vdm_types + 1 ) *
2588+ sizeof (struct vdm_type_support );
2589+ new_vdm = realloc (peer -> vdm_types , new_size );
2590+ if (!new_vdm ) {
2591+ rc = - ENOMEM ;
2592+ goto out ;
2593+ }
2594+ peer -> vdm_types = new_vdm ;
2595+ cur_vdm_type = peer -> vdm_types + peer -> num_vdm_types ;
2596+ cur_vdm_type -> format = resp -> vendor_id_format ;
2597+
2598+ if (resp -> vendor_id_format ==
2599+ MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
2600+ cur_vdm_type -> vendor_id .iana =
2601+ be32toh (resp -> vendor_id_data_iana );
2602+ } else {
2603+ cur_vdm_type -> vendor_id .pcie =
2604+ be16toh (resp -> vendor_id_data_pcie );
2605+ }
2606+ // Assume IANA and adjust if PCIE
2607+ cmd_set = (uint16_t * )(resp + 1 );
2608+ if (resp -> vendor_id_format ==
2609+ MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) {
2610+ cmd_set -- ;
2611+ }
2612+ cur_vdm_type -> cmd_set = be16toh (* cmd_set );
2613+ peer -> num_vdm_types ++ ;
2614+
2615+ /* Use the next selector from the response. 0xFF indicates no more entries */
2616+ req .vendor_id_set_selector = resp -> vendor_id_set_selector ;
2617+ free (buf );
2618+ buf = NULL ;
2619+ }
2620+ rc = 0 ;
2621+
2622+ out :
2623+ free (buf );
2624+ if (rc < 0 ) {
2625+ free (peer -> vdm_types );
2626+ peer -> vdm_types = NULL ;
2627+ peer -> num_vdm_types = 0 ;
2628+ }
2629+ return rc ;
2630+ }
2631+
25152632static int peer_set_uuid (struct peer * peer , const uint8_t uuid [16 ])
25162633{
25172634 if (!peer -> uuid ) {
@@ -2946,6 +3063,7 @@ static int method_learn_endpoint(sd_bus_message *call, void *data,
29463063static int query_peer_properties (struct peer * peer )
29473064{
29483065 const unsigned int max_retries = 4 ;
3066+ bool supports_vdm = false;
29493067 int rc ;
29503068
29513069 for (unsigned int i = 0 ; i < max_retries ; i ++ ) {
@@ -2974,6 +3092,39 @@ static int query_peer_properties(struct peer *peer)
29743092 }
29753093 }
29763094
3095+ for (unsigned int i = 0 ; i < peer -> num_message_types ; i ++ ) {
3096+ if (peer -> message_types [i ] ==
3097+ MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ||
3098+ peer -> message_types [i ] ==
3099+ MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) {
3100+ supports_vdm = true;
3101+ break ;
3102+ }
3103+ }
3104+
3105+ for (unsigned int i = 0 ; supports_vdm && i < max_retries ; i ++ ) {
3106+ rc = query_get_peer_vdm_types (peer );
3107+ // Success
3108+ if (rc == 0 )
3109+ break ;
3110+
3111+ // On timeout, retry
3112+ if (rc == - ETIMEDOUT ) {
3113+ if (peer -> ctx -> verbose )
3114+ warnx ("Retrying to get vendor message types for %s. Attempt %u" ,
3115+ peer_tostr (peer ), i + 1 );
3116+ rc = 0 ;
3117+ continue ;
3118+ }
3119+
3120+ if (rc < 0 ) {
3121+ warnx ("Error getting vendor message types for %s. Ignoring error %d %s" ,
3122+ peer_tostr (peer ), rc , strerror (- rc ));
3123+ rc = 0 ;
3124+ break ;
3125+ }
3126+ }
3127+
29773128 for (unsigned int i = 0 ; i < max_retries ; i ++ ) {
29783129 rc = query_get_peer_uuid (peer );
29793130
@@ -3866,6 +4017,42 @@ static int bus_endpoint_get_prop(sd_bus *bus, const char *path,
38664017 rc = sd_bus_message_append_array (reply , 'y' ,
38674018 peer -> message_types ,
38684019 peer -> num_message_types );
4020+ } else if (strcmp (property , "VendorDefinedMessageTypes" ) == 0 ) {
4021+ rc = sd_bus_message_open_container (reply , 'a' , "(yvu)" );
4022+ if (rc < 0 )
4023+ return rc ;
4024+
4025+ for (size_t i = 0 ; i < peer -> num_vdm_types ; i ++ ) {
4026+ struct vdm_type_support * vdm = & peer -> vdm_types [i ];
4027+ rc = sd_bus_message_open_container (reply , 'r' , "yvu" );
4028+ if (rc < 0 )
4029+ return rc ;
4030+
4031+ rc = sd_bus_message_append (reply , "y" , vdm -> format );
4032+ if (rc < 0 )
4033+ return rc ;
4034+
4035+ if (vdm -> format == VID_FORMAT_PCIE ) {
4036+ rc = sd_bus_message_append (reply , "v" , "q" ,
4037+ vdm -> vendor_id .pcie );
4038+ } else {
4039+ rc = sd_bus_message_append (reply , "v" , "u" ,
4040+ vdm -> vendor_id .iana );
4041+ }
4042+ if (rc < 0 )
4043+ return rc ;
4044+
4045+ rc = sd_bus_message_append (reply , "u" ,
4046+ (uint32_t )vdm -> cmd_set );
4047+ if (rc < 0 )
4048+ return rc ;
4049+
4050+ rc = sd_bus_message_close_container (reply );
4051+ if (rc < 0 )
4052+ return rc ;
4053+ }
4054+
4055+ rc = sd_bus_message_close_container (reply );
38694056 } else if (strcmp (property , "UUID" ) == 0 && peer -> uuid ) {
38704057 const char * s = dfree (bytes_to_uuid (peer -> uuid ));
38714058 rc = sd_bus_message_append (reply , "s" , s );
@@ -4055,6 +4242,11 @@ static const sd_bus_vtable bus_endpoint_obmc_vtable[] = {
40554242 bus_endpoint_get_prop ,
40564243 0 ,
40574244 SD_BUS_VTABLE_PROPERTY_CONST ),
4245+ SD_BUS_PROPERTY ("VendorDefinedMessageTypes" ,
4246+ "a(yvu)" ,
4247+ bus_endpoint_get_prop ,
4248+ 0 ,
4249+ SD_BUS_VTABLE_PROPERTY_CONST ),
40584250 SD_BUS_VTABLE_END
40594251};
40604252
0 commit comments