Skip to content

Commit 8b12d0f

Browse files
PavanMarthaIntelJunYe1993
authored andcommitted
mctpd: add dbus method RegisterVDMTypeSupport
Add a new DBus method RegisterVDMTypeSupport to support vendor defined message support as responder Add a new control command handler for get vdm message Tested: Unit tests passed Tested by sending GetVDM command from another endpoint Signed-off-by: Nidhin MS <nidhin.ms@intel.com> Signed-off-by: PavanKumarIntel <pavanx.kumar.martha@intel.com>
1 parent 7f64651 commit 8b12d0f

File tree

3 files changed

+402
-1
lines changed

3 files changed

+402
-1
lines changed

docs/mctpd.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ the MCTP stack, such as supported message types.
3232
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
3333
au.com.codeconstruct.MCTP1 interface - - -
3434
.RegisterTypeSupport method yau - -
35+
.RegisterVDMTypeSupport method yvq - -
3536
```
3637

3738
#### `.RegisterTypeSupport`: `yau`
@@ -53,6 +54,28 @@ De-registration is automatic - the specified types (and versions) are registered
5354
for as long as the dbus sender remains attached to the message bus, and are
5455
unregistered on disconnect.
5556

57+
#### `.RegisterVDMTypeSupport`: `yvq`
58+
59+
This method is used to add support for MCTP Vendor Defined Message (VDM) types.
60+
Once called successfully, subsequent responses for Get Vendor Defined Message
61+
Support control commands will include this new VDM type.
62+
63+
`RegisterVDMTypeSupport <vid format> <vendor id> <command set type>`
64+
65+
If the VDM type is already registered, then dbus call will fail.
66+
67+
- `<vid format>` Vendor ID format:
68+
- `0x00` - PCI/PCIe Vendor ID (16-bit)
69+
- `0x01` - IANA Enterprise Number (32-bit)
70+
- `<vendor id>` Vendor identifier as a variant type:
71+
- For PCIe format: 16-bit unsigned integer (`q`)
72+
- For IANA format: 32-bit unsigned integer (`u`)
73+
- `<command set type>` Command set type (16-bit unsigned integer) as defined by the vendor
74+
75+
De-registration is automatic - the specified VDM types are registered for as
76+
long as the dbus sender remains attached to the message bus, and are
77+
removed when the sender disconnects.
78+
5679
Also it hosts two trees of MCTP objects:
5780

5881
* Interfaces: Local hardware transport bindings that connect us to a MCTP bus

src/mctpd.c

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,21 @@ struct msg_type_support {
208208
sd_bus_track *source_peer;
209209
};
210210

211+
enum vid_format {
212+
VID_FORMAT_PCIE = MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID,
213+
VID_FORMAT_IANA = MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID,
214+
};
215+
216+
struct vdm_type_support {
217+
enum vid_format format;
218+
union {
219+
uint16_t pcie;
220+
uint32_t iana;
221+
} vendor_id;
222+
uint16_t cmd_set;
223+
sd_bus_track *source_peer;
224+
};
225+
211226
struct ctx {
212227
sd_event *event;
213228
sd_bus *bus;
@@ -243,6 +258,9 @@ struct ctx {
243258
struct msg_type_support *supported_msg_types;
244259
size_t num_supported_msg_types;
245260

261+
struct vdm_type_support *supported_vdm_types;
262+
size_t num_supported_vdm_types;
263+
246264
// Verbose logging
247265
bool verbose;
248266

@@ -999,6 +1017,75 @@ static int handle_control_get_message_type_support(
9991017
return rc;
10001018
}
10011019

1020+
static int
1021+
handle_control_get_vdm_type_support(struct ctx *ctx, int sd,
1022+
const struct sockaddr_mctp_ext *addr,
1023+
const uint8_t *buf, const size_t buf_size)
1024+
{
1025+
struct mctp_ctrl_resp_get_vdm_support *resp = NULL;
1026+
struct mctp_ctrl_cmd_get_vdm_support *req = NULL;
1027+
size_t resp_len, max_rsp_len, vdm_count;
1028+
struct vdm_type_support *cur_vdm;
1029+
uint16_t *cmd_type_ptr;
1030+
uint8_t *resp_buf;
1031+
int rc;
1032+
1033+
if (buf_size < sizeof(*req)) {
1034+
warnx("short Get VDM Type Support message");
1035+
return -ENOMSG;
1036+
}
1037+
1038+
req = (void *)buf;
1039+
vdm_count = ctx->num_supported_vdm_types;
1040+
// Allocate space for 32 bit VID + 16 bit cmd set
1041+
max_rsp_len = sizeof(*resp) + sizeof(uint16_t);
1042+
resp_len = max_rsp_len;
1043+
resp_buf = malloc(max_rsp_len);
1044+
if (!resp_buf) {
1045+
warnx("Failed to allocate response buffer");
1046+
return -ENOMEM;
1047+
}
1048+
resp = (void *)resp_buf;
1049+
cmd_type_ptr = (uint16_t *)(resp + 1);
1050+
mctp_ctrl_msg_hdr_init_resp(&resp->ctrl_hdr, req->ctrl_hdr);
1051+
1052+
if (req->vendor_id_set_selector >= vdm_count) {
1053+
if (ctx->verbose) {
1054+
warnx("Get VDM Type Support selector %u out of range (max %zu)",
1055+
req->vendor_id_set_selector, vdm_count);
1056+
}
1057+
resp_len = sizeof(struct mctp_ctrl_resp);
1058+
resp->completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA;
1059+
} else {
1060+
cur_vdm =
1061+
&ctx->supported_vdm_types[req->vendor_id_set_selector];
1062+
resp->completion_code = MCTP_CTRL_CC_SUCCESS;
1063+
resp->vendor_id_set_selector = req->vendor_id_set_selector + 1;
1064+
if (req->vendor_id_set_selector == (vdm_count - 1)) {
1065+
resp->vendor_id_set_selector =
1066+
MCTP_GET_VDM_SUPPORT_NO_MORE_CAP_SET;
1067+
}
1068+
resp->vendor_id_format = cur_vdm->format;
1069+
1070+
if (cur_vdm->format == VID_FORMAT_PCIE) {
1071+
// 4 bytes was reserved for VID, but PCIe VID uses only 2 bytes.
1072+
cmd_type_ptr--;
1073+
resp_len = max_rsp_len - sizeof(uint16_t);
1074+
resp->vendor_id_data_pcie =
1075+
htobe16(cur_vdm->vendor_id.pcie);
1076+
} else {
1077+
resp->vendor_id_data_iana =
1078+
htobe32(cur_vdm->vendor_id.iana);
1079+
}
1080+
1081+
*cmd_type_ptr = htobe16(cur_vdm->cmd_set);
1082+
}
1083+
1084+
rc = reply_message(ctx, sd, resp, resp_len, addr);
1085+
free(resp_buf);
1086+
return rc;
1087+
}
1088+
10021089
static int
10031090
handle_control_resolve_endpoint_id(struct ctx *ctx, int sd,
10041091
const struct sockaddr_mctp_ext *addr,
@@ -1202,6 +1289,10 @@ static int cb_listen_control_msg(sd_event_source *s, int sd, uint32_t revents,
12021289
rc = handle_control_get_message_type_support(ctx, sd, &addr,
12031290
buf, buf_size);
12041291
break;
1292+
case MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT:
1293+
rc = handle_control_get_vdm_type_support(ctx, sd, &addr, buf,
1294+
buf_size);
1295+
break;
12051296
case MCTP_CTRL_CMD_RESOLVE_ENDPOINT_ID:
12061297
rc = handle_control_resolve_endpoint_id(ctx, sd, &addr, buf,
12071298
buf_size);
@@ -3456,6 +3547,33 @@ static int on_dbus_peer_removed(sd_bus_track *track, void *userdata)
34563547
return 0;
34573548
}
34583549

3550+
static int on_dbus_peer_removed_vdm_type(sd_bus_track *track, void *userdata)
3551+
{
3552+
struct ctx *ctx = userdata;
3553+
size_t i;
3554+
3555+
for (i = 0; i < ctx->num_supported_vdm_types; i++) {
3556+
struct vdm_type_support *vdm_type =
3557+
&ctx->supported_vdm_types[i];
3558+
3559+
if (vdm_type->source_peer != track)
3560+
continue;
3561+
if (ctx->verbose) {
3562+
warnx("Removing VDM type support entry format %d cmd_set 0x%04x",
3563+
vdm_type->format, vdm_type->cmd_set);
3564+
}
3565+
if (i != ctx->num_supported_vdm_types - 1) {
3566+
*vdm_type = ctx->supported_vdm_types
3567+
[ctx->num_supported_vdm_types - 1];
3568+
}
3569+
ctx->num_supported_vdm_types--;
3570+
break;
3571+
}
3572+
3573+
sd_bus_track_unref(track);
3574+
return 0;
3575+
}
3576+
34593577
static int method_register_type_support(sd_bus_message *call, void *data,
34603578
sd_bus_error *berr)
34613579
{
@@ -3542,6 +3660,121 @@ static int method_register_type_support(sd_bus_message *call, void *data,
35423660
return rc;
35433661
}
35443662

3663+
static int method_register_vdm_type_support(sd_bus_message *call, void *data,
3664+
sd_bus_error *berr)
3665+
{
3666+
struct vdm_type_support new_vdm, *cur_vdm_type, *new_vdm_types_arr;
3667+
const char *vid_type_str;
3668+
struct ctx *ctx = data;
3669+
uint8_t vid_format;
3670+
uint16_t vid_pcie;
3671+
uint32_t vid_iana;
3672+
int rc;
3673+
3674+
rc = sd_bus_message_read(call, "y", &vid_format);
3675+
if (rc < 0)
3676+
goto err;
3677+
new_vdm.format = vid_format;
3678+
3679+
rc = sd_bus_message_peek_type(call, NULL, &vid_type_str);
3680+
if (rc < 0) {
3681+
return sd_bus_error_setf(berr, SD_BUS_ERROR_INVALID_ARGS,
3682+
"Failed to read variant type");
3683+
}
3684+
3685+
if (new_vdm.format == VID_FORMAT_PCIE) {
3686+
if (strcmp(vid_type_str, "q") != 0) {
3687+
return sd_bus_error_setf(
3688+
berr, SD_BUS_ERROR_INVALID_ARGS,
3689+
"Expected format is PCIe but variant contains '%s'",
3690+
vid_type_str);
3691+
}
3692+
rc = sd_bus_message_read(call, "v", "q", &vid_pcie);
3693+
if (rc < 0)
3694+
goto err;
3695+
new_vdm.vendor_id.pcie = vid_pcie;
3696+
} else if (new_vdm.format == VID_FORMAT_IANA) {
3697+
if (strcmp(vid_type_str, "u") != 0) {
3698+
return sd_bus_error_setf(
3699+
berr, SD_BUS_ERROR_INVALID_ARGS,
3700+
"Expected format is IANA but variant contains '%s'",
3701+
vid_type_str);
3702+
}
3703+
rc = sd_bus_message_read(call, "v", "u", &vid_iana);
3704+
if (rc < 0)
3705+
goto err;
3706+
new_vdm.vendor_id.iana = vid_iana;
3707+
} else {
3708+
return sd_bus_error_setf(berr, SD_BUS_ERROR_INVALID_ARGS,
3709+
"Unsupported VID format: %d",
3710+
new_vdm.format);
3711+
}
3712+
3713+
rc = sd_bus_message_read(call, "q", &new_vdm.cmd_set);
3714+
if (rc < 0)
3715+
goto err;
3716+
3717+
// Check for duplicates
3718+
for (size_t i = 0; i < ctx->num_supported_vdm_types; i++) {
3719+
if (ctx->supported_vdm_types[i].format != new_vdm.format)
3720+
continue;
3721+
3722+
if (ctx->supported_vdm_types[i].cmd_set != new_vdm.cmd_set)
3723+
continue;
3724+
3725+
bool vid_matches = false;
3726+
if (new_vdm.format == VID_FORMAT_PCIE) {
3727+
vid_matches =
3728+
(ctx->supported_vdm_types[i].vendor_id.pcie ==
3729+
new_vdm.vendor_id.pcie);
3730+
} else {
3731+
vid_matches =
3732+
(ctx->supported_vdm_types[i].vendor_id.iana ==
3733+
new_vdm.vendor_id.iana);
3734+
}
3735+
3736+
if (vid_matches) {
3737+
return sd_bus_error_setf(berr,
3738+
SD_BUS_ERROR_INVALID_ARGS,
3739+
"VDM type already registered");
3740+
}
3741+
}
3742+
3743+
new_vdm_types_arr = realloc(ctx->supported_vdm_types,
3744+
(ctx->num_supported_vdm_types + 1) *
3745+
sizeof(struct vdm_type_support));
3746+
if (!new_vdm_types_arr)
3747+
return sd_bus_error_setf(
3748+
berr, SD_BUS_ERROR_NO_MEMORY,
3749+
"Failed to allocate memory for VDM types");
3750+
ctx->supported_vdm_types = new_vdm_types_arr;
3751+
3752+
cur_vdm_type = &ctx->supported_vdm_types[ctx->num_supported_vdm_types];
3753+
memcpy(cur_vdm_type, &new_vdm, sizeof(struct vdm_type_support));
3754+
3755+
// Track peer
3756+
rc = sd_bus_track_new(ctx->bus, &cur_vdm_type->source_peer,
3757+
on_dbus_peer_removed_vdm_type, ctx);
3758+
if (rc < 0)
3759+
goto track_err;
3760+
3761+
rc = sd_bus_track_add_sender(cur_vdm_type->source_peer, call);
3762+
if (rc < 0)
3763+
goto track_err;
3764+
3765+
ctx->num_supported_vdm_types++;
3766+
return sd_bus_reply_method_return(call, "");
3767+
3768+
track_err:
3769+
sd_bus_track_unref(cur_vdm_type->source_peer);
3770+
set_berr(ctx, rc, berr);
3771+
return rc;
3772+
3773+
err:
3774+
set_berr(ctx, rc, berr);
3775+
return rc;
3776+
}
3777+
35453778
// clang-format off
35463779
static const sd_bus_vtable bus_link_owner_vtable[] = {
35473780
SD_BUS_VTABLE_START(0),
@@ -3904,6 +4137,13 @@ static const sd_bus_vtable mctp_base_vtable[] = {
39044137
SD_BUS_NO_RESULT,
39054138
method_register_type_support,
39064139
0),
4140+
SD_BUS_METHOD_WITH_ARGS("RegisterVDMTypeSupport",
4141+
SD_BUS_ARGS("y", format,
4142+
"v", format_data,
4143+
"q", vendor_subtype),
4144+
SD_BUS_NO_RESULT,
4145+
method_register_vdm_type_support,
4146+
0),
39074147
SD_BUS_VTABLE_END,
39084148
};
39094149
// clang-format on
@@ -4859,6 +5099,9 @@ static void setup_ctrl_cmd_defaults(struct ctx *ctx)
48595099
ctx->supported_msg_types = NULL;
48605100
ctx->num_supported_msg_types = 0;
48615101

5102+
ctx->supported_vdm_types = NULL;
5103+
ctx->num_supported_vdm_types = 0;
5104+
48625105
// Default to supporting only control messages
48635106
ctx->supported_msg_types = malloc(sizeof(struct msg_type_support));
48645107
if (!ctx->supported_msg_types) {
@@ -4904,6 +5147,9 @@ static void free_ctrl_cmd_defaults(struct ctx *ctx)
49045147
free(ctx->supported_msg_types[i].versions);
49055148
}
49065149
free(ctx->supported_msg_types);
5150+
free(ctx->supported_vdm_types);
5151+
ctx->supported_vdm_types = NULL;
5152+
ctx->num_supported_vdm_types = 0;
49075153
}
49085154

49095155
static int endpoint_send_allocate_endpoint_ids(

0 commit comments

Comments
 (0)