Skip to content

Commit 317225a

Browse files
PavanMarthaIntelmsnidhin
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 236330c commit 317225a

File tree

3 files changed

+401
-0
lines changed

3 files changed

+401
-0
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);
@@ -3420,6 +3511,33 @@ static int on_dbus_peer_removed(sd_bus_track *track, void *userdata)
34203511
return 0;
34213512
}
34223513

3514+
static int on_dbus_peer_removed_vdm_type(sd_bus_track *track, void *userdata)
3515+
{
3516+
struct ctx *ctx = userdata;
3517+
size_t i;
3518+
3519+
for (i = 0; i < ctx->num_supported_vdm_types; i++) {
3520+
struct vdm_type_support *vdm_type =
3521+
&ctx->supported_vdm_types[i];
3522+
3523+
if (vdm_type->source_peer != track)
3524+
continue;
3525+
if (ctx->verbose) {
3526+
warnx("Removing VDM type support entry format %d cmd_set 0x%04x",
3527+
vdm_type->format, vdm_type->cmd_set);
3528+
}
3529+
if (i != ctx->num_supported_vdm_types - 1) {
3530+
*vdm_type = ctx->supported_vdm_types
3531+
[ctx->num_supported_vdm_types - 1];
3532+
}
3533+
ctx->num_supported_vdm_types--;
3534+
break;
3535+
}
3536+
3537+
sd_bus_track_unref(track);
3538+
return 0;
3539+
}
3540+
34233541
static int method_register_type_support(sd_bus_message *call, void *data,
34243542
sd_bus_error *berr)
34253543
{
@@ -3506,6 +3624,121 @@ static int method_register_type_support(sd_bus_message *call, void *data,
35063624
return rc;
35073625
}
35083626

3627+
static int method_register_vdm_type_support(sd_bus_message *call, void *data,
3628+
sd_bus_error *berr)
3629+
{
3630+
struct vdm_type_support new_vdm, *cur_vdm_type, *new_vdm_types_arr;
3631+
const char *vid_type_str;
3632+
struct ctx *ctx = data;
3633+
uint8_t vid_format;
3634+
uint16_t vid_pcie;
3635+
uint32_t vid_iana;
3636+
int rc;
3637+
3638+
rc = sd_bus_message_read(call, "y", &vid_format);
3639+
if (rc < 0)
3640+
goto err;
3641+
new_vdm.format = vid_format;
3642+
3643+
rc = sd_bus_message_peek_type(call, NULL, &vid_type_str);
3644+
if (rc < 0) {
3645+
return sd_bus_error_setf(berr, SD_BUS_ERROR_INVALID_ARGS,
3646+
"Failed to read variant type");
3647+
}
3648+
3649+
if (new_vdm.format == VID_FORMAT_PCIE) {
3650+
if (strcmp(vid_type_str, "q") != 0) {
3651+
return sd_bus_error_setf(
3652+
berr, SD_BUS_ERROR_INVALID_ARGS,
3653+
"Expected format is PCIe but variant contains '%s'",
3654+
vid_type_str);
3655+
}
3656+
rc = sd_bus_message_read(call, "v", "q", &vid_pcie);
3657+
if (rc < 0)
3658+
goto err;
3659+
new_vdm.vendor_id.pcie = vid_pcie;
3660+
} else if (new_vdm.format == VID_FORMAT_IANA) {
3661+
if (strcmp(vid_type_str, "u") != 0) {
3662+
return sd_bus_error_setf(
3663+
berr, SD_BUS_ERROR_INVALID_ARGS,
3664+
"Expected format is IANA but variant contains '%s'",
3665+
vid_type_str);
3666+
}
3667+
rc = sd_bus_message_read(call, "v", "u", &vid_iana);
3668+
if (rc < 0)
3669+
goto err;
3670+
new_vdm.vendor_id.iana = vid_iana;
3671+
} else {
3672+
return sd_bus_error_setf(berr, SD_BUS_ERROR_INVALID_ARGS,
3673+
"Unsupported VID format: %d",
3674+
new_vdm.format);
3675+
}
3676+
3677+
rc = sd_bus_message_read(call, "q", &new_vdm.cmd_set);
3678+
if (rc < 0)
3679+
goto err;
3680+
3681+
// Check for duplicates
3682+
for (size_t i = 0; i < ctx->num_supported_vdm_types; i++) {
3683+
if (ctx->supported_vdm_types[i].format != new_vdm.format)
3684+
continue;
3685+
3686+
if (ctx->supported_vdm_types[i].cmd_set != new_vdm.cmd_set)
3687+
continue;
3688+
3689+
bool vid_matches = false;
3690+
if (new_vdm.format == VID_FORMAT_PCIE) {
3691+
vid_matches =
3692+
(ctx->supported_vdm_types[i].vendor_id.pcie ==
3693+
new_vdm.vendor_id.pcie);
3694+
} else {
3695+
vid_matches =
3696+
(ctx->supported_vdm_types[i].vendor_id.iana ==
3697+
new_vdm.vendor_id.iana);
3698+
}
3699+
3700+
if (vid_matches) {
3701+
return sd_bus_error_setf(berr,
3702+
SD_BUS_ERROR_INVALID_ARGS,
3703+
"VDM type already registered");
3704+
}
3705+
}
3706+
3707+
new_vdm_types_arr = realloc(ctx->supported_vdm_types,
3708+
(ctx->num_supported_vdm_types + 1) *
3709+
sizeof(struct vdm_type_support));
3710+
if (!new_vdm_types_arr)
3711+
return sd_bus_error_setf(
3712+
berr, SD_BUS_ERROR_NO_MEMORY,
3713+
"Failed to allocate memory for VDM types");
3714+
ctx->supported_vdm_types = new_vdm_types_arr;
3715+
3716+
cur_vdm_type = &ctx->supported_vdm_types[ctx->num_supported_vdm_types];
3717+
memcpy(cur_vdm_type, &new_vdm, sizeof(struct vdm_type_support));
3718+
3719+
// Track peer
3720+
rc = sd_bus_track_new(ctx->bus, &cur_vdm_type->source_peer,
3721+
on_dbus_peer_removed_vdm_type, ctx);
3722+
if (rc < 0)
3723+
goto track_err;
3724+
3725+
rc = sd_bus_track_add_sender(cur_vdm_type->source_peer, call);
3726+
if (rc < 0)
3727+
goto track_err;
3728+
3729+
ctx->num_supported_vdm_types++;
3730+
return sd_bus_reply_method_return(call, "");
3731+
3732+
track_err:
3733+
sd_bus_track_unref(cur_vdm_type->source_peer);
3734+
set_berr(ctx, rc, berr);
3735+
return rc;
3736+
3737+
err:
3738+
set_berr(ctx, rc, berr);
3739+
return rc;
3740+
}
3741+
35093742
// clang-format off
35103743
static const sd_bus_vtable bus_link_owner_vtable[] = {
35113744
SD_BUS_VTABLE_START(0),
@@ -3868,6 +4101,13 @@ static const sd_bus_vtable mctp_base_vtable[] = {
38684101
SD_BUS_NO_RESULT,
38694102
method_register_type_support,
38704103
0),
4104+
SD_BUS_METHOD_WITH_ARGS("RegisterVDMTypeSupport",
4105+
SD_BUS_ARGS("y", format,
4106+
"v", format_data,
4107+
"q", vendor_subtype),
4108+
SD_BUS_NO_RESULT,
4109+
method_register_vdm_type_support,
4110+
0),
38714111
SD_BUS_VTABLE_END,
38724112
};
38734113
// clang-format on
@@ -4823,6 +5063,9 @@ static void setup_ctrl_cmd_defaults(struct ctx *ctx)
48235063
ctx->supported_msg_types = NULL;
48245064
ctx->num_supported_msg_types = 0;
48255065

5066+
ctx->supported_vdm_types = NULL;
5067+
ctx->num_supported_vdm_types = 0;
5068+
48265069
// Default to supporting only control messages
48275070
ctx->supported_msg_types = malloc(sizeof(struct msg_type_support));
48285071
if (!ctx->supported_msg_types) {
@@ -4868,6 +5111,9 @@ static void free_ctrl_cmd_defaults(struct ctx *ctx)
48685111
free(ctx->supported_msg_types[i].versions);
48695112
}
48705113
free(ctx->supported_msg_types);
5114+
free(ctx->supported_vdm_types);
5115+
ctx->supported_vdm_types = NULL;
5116+
ctx->num_supported_vdm_types = 0;
48715117
}
48725118

48735119
static int endpoint_send_allocate_endpoint_ids(

0 commit comments

Comments
 (0)