Skip to content

Commit 0d4a51d

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 <[email protected]> Signed-off-by: PavanKumarIntel <[email protected]>
1 parent 236330c commit 0d4a51d

File tree

3 files changed

+316
-2
lines changed

3 files changed

+316
-2
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: 232 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,16 @@ struct msg_type_support {
208208
sd_bus_track *source_peer;
209209
};
210210

211+
struct vdm_type_support {
212+
uint8_t vid_format;
213+
union {
214+
uint16_t pcie;
215+
uint32_t iana;
216+
} vendor_id;
217+
uint16_t cmd_set;
218+
sd_bus_track *source_peer;
219+
};
220+
211221
struct ctx {
212222
sd_event *event;
213223
sd_bus *bus;
@@ -243,6 +253,9 @@ struct ctx {
243253
struct msg_type_support *supported_msg_types;
244254
size_t num_supported_msg_types;
245255

256+
struct vdm_type_support *supported_vdm_types;
257+
size_t num_supported_vdm_types;
258+
246259
// Verbose logging
247260
bool verbose;
248261

@@ -999,6 +1012,83 @@ static int handle_control_get_message_type_support(
9991012
return rc;
10001013
}
10011014

1015+
static int
1016+
handle_control_get_vdm_type_support(struct ctx *ctx, int sd,
1017+
const struct sockaddr_mctp_ext *addr,
1018+
const uint8_t *buf, const size_t buf_size)
1019+
{
1020+
size_t resp_len, max_rsp_len, vdm_count, vid_size_left;
1021+
struct mctp_ctrl_resp_get_vdm_support *resp = NULL;
1022+
struct mctp_ctrl_cmd_get_vdm_support *req = NULL;
1023+
struct vdm_type_support *cur_vdm;
1024+
uint8_t *resp_buf;
1025+
int rc;
1026+
1027+
if (buf_size < sizeof(*req)) {
1028+
warnx("short Get Message Type Support message");
1029+
return -ENOMSG;
1030+
}
1031+
1032+
req = (void *)buf;
1033+
vdm_count = ctx->num_supported_vdm_types;
1034+
// Allocate space for 32 bit VID + 16 bit cmd set
1035+
max_rsp_len = sizeof(*resp) + sizeof(uint16_t);
1036+
resp_buf = malloc(max_rsp_len);
1037+
if (!resp_buf) {
1038+
warnx("Failed to allocate response buffer");
1039+
return -ENOMEM;
1040+
}
1041+
resp = (void *)resp_buf;
1042+
mctp_ctrl_msg_hdr_init_resp(&resp->ctrl_hdr, req->ctrl_hdr);
1043+
1044+
if (vdm_count == 0) {
1045+
if (ctx->verbose) {
1046+
warnx("Get VDM Type Support but no VDMs registered");
1047+
}
1048+
resp_len = sizeof(struct mctp_ctrl_resp);
1049+
resp->completion_code = MCTP_CTRL_CC_ERROR;
1050+
} else if (req->vendor_id_set_selector >= vdm_count) {
1051+
if (ctx->verbose) {
1052+
warnx("Get VDM Type Support selector %u out of range (max %zu)",
1053+
req->vendor_id_set_selector, vdm_count);
1054+
}
1055+
resp_len = sizeof(struct mctp_ctrl_resp);
1056+
resp->completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA;
1057+
} else {
1058+
cur_vdm =
1059+
&ctx->supported_vdm_types[req->vendor_id_set_selector];
1060+
vid_size_left = (cur_vdm->vid_format ==
1061+
MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID) ?
1062+
sizeof(uint16_t) :
1063+
0;
1064+
resp_len = max_rsp_len - vid_size_left;
1065+
1066+
resp->completion_code = MCTP_CTRL_CC_SUCCESS;
1067+
resp->vendor_id_set_selector =
1068+
req->vendor_id_set_selector == (vdm_count - 1) ?
1069+
MCTP_GET_VDM_SUPPORT_NO_MORE_CAP_SET :
1070+
req->vendor_id_set_selector + 1;
1071+
resp->vendor_id_format = cur_vdm->vid_format;
1072+
uint8_t *out_ptr = (uint8_t *)(resp + 1);
1073+
out_ptr -= vid_size_left;
1074+
1075+
if (cur_vdm->vid_format ==
1076+
MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID) {
1077+
resp->vendor_id_data_pcie =
1078+
htobe16(cur_vdm->vendor_id.pcie);
1079+
} else {
1080+
resp->vendor_id_data_iana =
1081+
htobe32(cur_vdm->vendor_id.iana);
1082+
}
1083+
uint16_t *cmd_type_ptr = (uint16_t *)out_ptr;
1084+
*cmd_type_ptr = htobe16(cur_vdm->cmd_set);
1085+
}
1086+
1087+
rc = reply_message(ctx, sd, resp, resp_len, addr);
1088+
free(resp_buf);
1089+
return rc;
1090+
}
1091+
10021092
static int
10031093
handle_control_resolve_endpoint_id(struct ctx *ctx, int sd,
10041094
const struct sockaddr_mctp_ext *addr,
@@ -1202,6 +1292,10 @@ static int cb_listen_control_msg(sd_event_source *s, int sd, uint32_t revents,
12021292
rc = handle_control_get_message_type_support(ctx, sd, &addr,
12031293
buf, buf_size);
12041294
break;
1295+
case MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT:
1296+
rc = handle_control_get_vdm_type_support(ctx, sd, &addr, buf,
1297+
buf_size);
1298+
break;
12051299
case MCTP_CTRL_CMD_RESOLVE_ENDPOINT_ID:
12061300
rc = handle_control_resolve_endpoint_id(ctx, sd, &addr, buf,
12071301
buf_size);
@@ -3420,6 +3514,33 @@ static int on_dbus_peer_removed(sd_bus_track *track, void *userdata)
34203514
return 0;
34213515
}
34223516

3517+
static int on_dbus_peer_removed_vdm_type(sd_bus_track *track, void *userdata)
3518+
{
3519+
struct ctx *ctx = userdata;
3520+
size_t i;
3521+
3522+
for (i = 0; i < ctx->num_supported_vdm_types; i++) {
3523+
struct vdm_type_support *vdm_type =
3524+
&ctx->supported_vdm_types[i];
3525+
3526+
if (vdm_type->source_peer != track)
3527+
continue;
3528+
if (ctx->verbose) {
3529+
warnx("Removing VDM type support entry vid_format %d cmd_set 0x%04x",
3530+
vdm_type->vid_format, vdm_type->cmd_set);
3531+
}
3532+
if (i != ctx->num_supported_vdm_types - 1) {
3533+
*vdm_type = ctx->supported_vdm_types
3534+
[ctx->num_supported_vdm_types - 1];
3535+
}
3536+
ctx->num_supported_vdm_types--;
3537+
break;
3538+
}
3539+
3540+
sd_bus_track_unref(track);
3541+
return 0;
3542+
}
3543+
34233544
static int method_register_type_support(sd_bus_message *call, void *data,
34243545
sd_bus_error *berr)
34253546
{
@@ -3439,15 +3560,13 @@ static int method_register_type_support(sd_bus_message *call, void *data,
34393560
goto err;
34403561

34413562
if (versions_len == 0) {
3442-
warnx("No versions provided for message type %d", msg_type);
34433563
return sd_bus_error_setf(
34443564
berr, SD_BUS_ERROR_INVALID_ARGS,
34453565
"No versions provided for message type %d", msg_type);
34463566
}
34473567

34483568
for (i = 0; i < ctx->num_supported_msg_types; i++) {
34493569
if (ctx->supported_msg_types[i].msg_type == msg_type) {
3450-
warnx("Message type %d already registered", msg_type);
34513570
return sd_bus_error_setf(
34523571
berr, SD_BUS_ERROR_INVALID_ARGS,
34533572
"Message type %d already registered", msg_type);
@@ -3506,6 +3625,104 @@ static int method_register_type_support(sd_bus_message *call, void *data,
35063625
return rc;
35073626
}
35083627

3628+
static int method_register_vdm_type_support(sd_bus_message *call, void *data,
3629+
sd_bus_error *berr)
3630+
{
3631+
struct vdm_type_support new_vdm, *cur_vdm_type, *new_vdm_types_arr;
3632+
struct ctx *ctx = data;
3633+
uint16_t vid_pcie;
3634+
uint32_t vid_iana;
3635+
int rc;
3636+
3637+
rc = sd_bus_message_read(call, "y", &new_vdm.vid_format);
3638+
if (rc < 0)
3639+
goto err;
3640+
3641+
if (new_vdm.vid_format != MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID &&
3642+
new_vdm.vid_format != MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID) {
3643+
return sd_bus_error_setf(berr, SD_BUS_ERROR_INVALID_ARGS,
3644+
"Unsupported VID format: %d",
3645+
new_vdm.vid_format);
3646+
}
3647+
3648+
if (new_vdm.vid_format == MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID) {
3649+
rc = sd_bus_message_read(call, "v", "q", &vid_pcie);
3650+
if (rc < 0)
3651+
goto err;
3652+
new_vdm.vendor_id.pcie = vid_pcie;
3653+
} else if (new_vdm.vid_format == MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID) {
3654+
rc = sd_bus_message_read(call, "v", "u", &vid_iana);
3655+
if (rc < 0)
3656+
goto err;
3657+
new_vdm.vendor_id.iana = vid_iana;
3658+
}
3659+
3660+
rc = sd_bus_message_read(call, "q", &new_vdm.cmd_set);
3661+
if (rc < 0)
3662+
goto err;
3663+
3664+
// Check for duplicates
3665+
for (size_t i = 0; i < ctx->num_supported_vdm_types; i++) {
3666+
if (ctx->supported_vdm_types[i].vid_format !=
3667+
new_vdm.vid_format)
3668+
continue;
3669+
3670+
if (ctx->supported_vdm_types[i].cmd_set != new_vdm.cmd_set)
3671+
continue;
3672+
3673+
bool vid_matches = false;
3674+
if (new_vdm.vid_format == MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID) {
3675+
vid_matches =
3676+
(ctx->supported_vdm_types[i].vendor_id.pcie ==
3677+
new_vdm.vendor_id.pcie);
3678+
} else {
3679+
vid_matches =
3680+
(ctx->supported_vdm_types[i].vendor_id.iana ==
3681+
new_vdm.vendor_id.iana);
3682+
}
3683+
3684+
if (vid_matches) {
3685+
return sd_bus_error_setf(berr,
3686+
SD_BUS_ERROR_INVALID_ARGS,
3687+
"VDM type already registered");
3688+
}
3689+
}
3690+
3691+
new_vdm_types_arr = realloc(ctx->supported_vdm_types,
3692+
(ctx->num_supported_vdm_types + 1) *
3693+
sizeof(struct vdm_type_support));
3694+
if (!new_vdm_types_arr)
3695+
return sd_bus_error_setf(
3696+
berr, SD_BUS_ERROR_NO_MEMORY,
3697+
"Failed to allocate memory for VDM types");
3698+
ctx->supported_vdm_types = new_vdm_types_arr;
3699+
3700+
cur_vdm_type = &ctx->supported_vdm_types[ctx->num_supported_vdm_types];
3701+
memcpy(cur_vdm_type, &new_vdm, sizeof(struct vdm_type_support));
3702+
3703+
// Track peer
3704+
rc = sd_bus_track_new(ctx->bus, &cur_vdm_type->source_peer,
3705+
on_dbus_peer_removed_vdm_type, ctx);
3706+
if (rc < 0)
3707+
goto track_err;
3708+
3709+
rc = sd_bus_track_add_sender(cur_vdm_type->source_peer, call);
3710+
if (rc < 0)
3711+
goto track_err;
3712+
3713+
ctx->num_supported_vdm_types++;
3714+
return sd_bus_reply_method_return(call, "");
3715+
3716+
track_err:
3717+
sd_bus_track_unref(cur_vdm_type->source_peer);
3718+
set_berr(ctx, rc, berr);
3719+
return rc;
3720+
3721+
err:
3722+
set_berr(ctx, rc, berr);
3723+
return rc;
3724+
}
3725+
35093726
// clang-format off
35103727
static const sd_bus_vtable bus_link_owner_vtable[] = {
35113728
SD_BUS_VTABLE_START(0),
@@ -3868,6 +4085,13 @@ static const sd_bus_vtable mctp_base_vtable[] = {
38684085
SD_BUS_NO_RESULT,
38694086
method_register_type_support,
38704087
0),
4088+
SD_BUS_METHOD_WITH_ARGS("RegisterVDMTypeSupport",
4089+
SD_BUS_ARGS("y", format,
4090+
"v", format_data,
4091+
"q", vendor_subtype),
4092+
SD_BUS_NO_RESULT,
4093+
method_register_vdm_type_support,
4094+
0),
38714095
SD_BUS_VTABLE_END,
38724096
};
38734097
// clang-format on
@@ -4823,6 +5047,9 @@ static void setup_ctrl_cmd_defaults(struct ctx *ctx)
48235047
ctx->supported_msg_types = NULL;
48245048
ctx->num_supported_msg_types = 0;
48255049

5050+
ctx->supported_vdm_types = NULL;
5051+
ctx->num_supported_vdm_types = 0;
5052+
48265053
// Default to supporting only control messages
48275054
ctx->supported_msg_types = malloc(sizeof(struct msg_type_support));
48285055
if (!ctx->supported_msg_types) {
@@ -4868,6 +5095,9 @@ static void free_ctrl_cmd_defaults(struct ctx *ctx)
48685095
free(ctx->supported_msg_types[i].versions);
48695096
}
48705097
free(ctx->supported_msg_types);
5098+
free(ctx->supported_vdm_types);
5099+
ctx->supported_vdm_types = NULL;
5100+
ctx->num_supported_vdm_types = 0;
48715101
}
48725102

48735103
static int endpoint_send_allocate_endpoint_ids(

0 commit comments

Comments
 (0)