Skip to content

Commit b79fdd2

Browse files
committed
GetMsgType : Take from config
GetMsgType response is hardcoded and always return only control message support. Read supported message types from config file and reply in control message Tested by sending GetMsgType and GetVersion from another EP Default responses for GetMsgType and GetVersion for type 0 5, 0, 1, 0 and 4, 0, 4, 241, 240, 255, 0, 241, 241, 255, 0, 241, 242, 255, 0, 241, 243, 241, 0 After calling busctl call au.com.codeconstruct.MCTP1 /au/com/codeconstruct/mctp1 au.com.codeconstruct.MCTP1 RegisterResponder yau 5 1 0xF1F2F3F4 Response for GetMsgType and GetVersion for type 5 5, 0, 2, 0, 5 and 4, 0, 1, 244, 243, 242, 241 Signed-off-by: Nidhin MS <[email protected]>
1 parent 0d13310 commit b79fdd2

File tree

2 files changed

+228
-32
lines changed

2 files changed

+228
-32
lines changed

docs/mctpd.md

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,39 @@ Service au.com.codeconstruct.MCTP1:
2525

2626
## Top-level object: `/au/com/codeconstruct/mctp1`
2727

28-
This object serves as the global MCTP daemon namespace; it doesn't contain
29-
much at present, but hosts two trees of MCTP objects:
28+
This object serves as the global MCTP daemon namespace.
29+
It hosts `au.com.codeconstruct.MCTP1` dbus interface to modify mctp properties like
30+
supported message types.
31+
```
32+
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
33+
au.com.codeconstruct.MCTP1 interface - - -
34+
.RegisterResponder method yau - -
35+
```
36+
37+
#### `.RegisterResponder`: `yau`
38+
39+
This method is used to add support for mctp message types other than control
40+
messages. Once called successfully subsequent response for get message type
41+
control command will include this new message type also. Also the versions
42+
passed to this method will be used to respond to get version control command.
43+
44+
`RegisterResponder <msg type> <versions>`
45+
46+
If message type is already registered then dbus call will fail
47+
48+
`<msg type>` Message type defined in DSP0239
49+
50+
`<versions>` Versions supported for this message type formatted as uint32 integers as
51+
specified in DSP0236
52+
53+
Example for PLDM type with two versions:
54+
55+
```shell
56+
busctl call au.com.codeconstruct.MCTP1 /au/com/codeconstruct/mctp1 \
57+
au.com.codeconstruct.MCTP1 RegisterResponder yau 1 2 0xF1F2F3F4 0xF0F0F0F1
58+
```
59+
60+
Also it hosts two trees of MCTP objects:
3061

3162
* Interfaces: Local hardware transport bindings that connect us to a MCTP bus
3263
* Endpoints: MCTP endpoints that `mctpd` knows about, both remote and local

src/mctpd.c

Lines changed: 195 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@ struct peer {
192192
} recovery;
193193
};
194194

195+
struct msg_type_support {
196+
uint8_t msg_type;
197+
uint32_t *versions;
198+
size_t num_versions;
199+
};
200+
195201
struct ctx {
196202
sd_event *event;
197203
sd_bus *bus;
@@ -219,6 +225,10 @@ struct ctx {
219225

220226
uint8_t uuid[16];
221227

228+
// Supported message types and their versions
229+
struct msg_type_support* supported_msg_types;
230+
size_t num_supported_msg_types;
231+
222232
// Verbose logging
223233
bool verbose;
224234
};
@@ -667,42 +677,64 @@ handle_control_get_version_support(struct ctx *ctx, int sd,
667677
struct mctp_ctrl_cmd_get_mctp_ver_support *req = NULL;
668678
struct mctp_ctrl_resp_get_mctp_ver_support *resp = NULL;
669679
uint32_t *versions = NULL;
670-
// space for 4 versions
671-
uint8_t respbuf[sizeof(*resp) + 4 * sizeof(*versions)];
680+
uint8_t *respbuf = NULL;
672681
size_t resp_len;
682+
ssize_t i, ver_idx = -1, ver_count = 0;
683+
int status;
673684

674685
if (buf_size < sizeof(struct mctp_ctrl_cmd_get_mctp_ver_support)) {
675686
warnx("short Get Version Support message");
676687
return -ENOMSG;
677688
}
678689

679690
req = (void *)buf;
680-
resp = (void *)respbuf;
681-
memset(resp, 0x0, sizeof(*resp));
682-
versions = (void *)(resp + 1);
683-
switch (req->msg_type_number) {
684-
case 0xff: // Base Protocol
685-
case 0x00: // Control protocol
686-
// from DSP0236 1.3.1 section 12.6.2. Big endian.
687-
versions[0] = htonl(0xF1F0FF00);
688-
versions[1] = htonl(0xF1F1FF00);
689-
versions[2] = htonl(0xF1F2FF00);
690-
versions[3] = htonl(0xF1F3F100);
691-
resp->number_of_entries = 4;
692-
resp->completion_code = MCTP_CTRL_CC_SUCCESS;
693-
resp_len = sizeof(*resp) + 4 * sizeof(*versions);
694-
break;
695-
default:
696-
// Unsupported message type
691+
if (req->msg_type_number == 0xFF) {
692+
// use same version for base spec and control protocol
693+
req->msg_type_number = 0;
694+
}
695+
for (i = 0; i < ctx->num_supported_msg_types; i++) {
696+
if (ctx->supported_msg_types[i].msg_type ==
697+
req->msg_type_number) {
698+
ver_idx = i;
699+
break;
700+
}
701+
}
702+
703+
if (ver_idx < 0) {
704+
respbuf = malloc(sizeof(struct mctp_ctrl_resp));
705+
if (!respbuf) {
706+
warnx("Failed to allocate response buffer");
707+
return -ENOMEM;
708+
}
709+
resp = (void *)respbuf;
710+
// Nobody registered yet as responder for this type
697711
resp->completion_code =
698712
MCTP_CTRL_CC_GET_MCTP_VER_SUPPORT_UNSUPPORTED_TYPE;
699-
resp_len = sizeof(*resp);
713+
resp_len = sizeof(struct mctp_ctrl_resp);
714+
} else {
715+
ver_count = ctx->supported_msg_types[ver_idx].num_versions;
716+
respbuf =
717+
malloc(sizeof(*resp) + (ver_count * sizeof(uint32_t)));
718+
if (!respbuf) {
719+
warnx("Failed to allocate response buffer for versions");
720+
return -ENOMEM;
721+
}
722+
resp = (void *)respbuf;
723+
resp->number_of_entries = ver_count;
724+
versions = (void *)(resp + 1);
725+
memcpy(versions, ctx->supported_msg_types[ver_idx].versions,
726+
ver_count * sizeof(uint32_t));
727+
resp->completion_code = MCTP_CTRL_CC_SUCCESS;
728+
resp_len = sizeof(*resp) + ver_count * sizeof(uint32_t);
700729
}
701730

702731
resp->ctrl_hdr.command_code = req->ctrl_hdr.command_code;
703732
resp->ctrl_hdr.rq_dgram_inst =
704733
(req->ctrl_hdr.rq_dgram_inst & IID_MASK) | RQDI_RESP;
705-
return reply_message(ctx, sd, resp, resp_len, addr);
734+
735+
status = reply_message(ctx, sd, resp, resp_len, addr);
736+
free(respbuf);
737+
return status;
706738
}
707739

708740
static int handle_control_get_endpoint_id(struct ctx *ctx, int sd,
@@ -761,28 +793,42 @@ static int handle_control_get_message_type_support(
761793
const uint8_t *buf, const size_t buf_size)
762794
{
763795
struct mctp_ctrl_cmd_get_msg_type_support *req = NULL;
764-
;
765796
struct mctp_ctrl_resp_get_msg_type_support *resp = NULL;
766-
uint8_t resp_buf[sizeof(*resp) + 1];
767-
size_t resp_len;
797+
uint8_t *resp_buf, *msg_types;
798+
size_t resp_len, type_count;
799+
size_t i;
768800

769801
if (buf_size < sizeof(*req)) {
770802
warnx("short Get Message Type Support message");
771803
return -ENOMSG;
772804
}
773805

774806
req = (void *)buf;
807+
type_count = ctx->num_supported_msg_types;
808+
// Allocate extra space for the message types
809+
resp_len = sizeof(*resp) + type_count;
810+
resp_buf = malloc(resp_len);
811+
if (!resp_buf) {
812+
warnx("Failed to allocate response buffer");
813+
return -ENOMEM;
814+
}
815+
775816
resp = (void *)resp_buf;
776-
resp->ctrl_hdr.command_code = req->ctrl_hdr.command_code;
777817
resp->ctrl_hdr.rq_dgram_inst =
778818
(req->ctrl_hdr.rq_dgram_inst & IID_MASK) | RQDI_RESP;
819+
resp->ctrl_hdr.command_code = req->ctrl_hdr.command_code;
820+
resp->completion_code = MCTP_CTRL_CC_SUCCESS;
779821

780-
// Only control messages supported
781-
resp->msg_type_count = 1;
782-
*((uint8_t *)(resp + 1)) = MCTP_CTRL_HDR_MSG_TYPE;
783-
resp_len = sizeof(*resp) + resp->msg_type_count;
822+
resp->msg_type_count = type_count;
823+
// Append message types after msg_type_count
824+
msg_types = (uint8_t *)(resp + 1);
825+
for (i = 0; i < type_count; i++) {
826+
msg_types[i] = ctx->supported_msg_types[i].msg_type;
827+
}
784828

785-
return reply_message(ctx, sd, resp, resp_len, addr);
829+
int result = reply_message(ctx, sd, resp, resp_len, addr);
830+
free(resp_buf);
831+
return result;
786832
}
787833

788834
static int
@@ -2829,6 +2875,71 @@ static int method_net_learn_endpoint(sd_bus_message *call, void *data,
28292875
return rc;
28302876
}
28312877

2878+
static int method_register_responder(sd_bus_message *call, void *data,
2879+
sd_bus_error *berr)
2880+
{
2881+
struct ctx *ctx = data;
2882+
uint8_t msg_type;
2883+
const uint32_t *versions = NULL;
2884+
size_t versions_len;
2885+
int rc, i;
2886+
2887+
rc = sd_bus_message_read(call, "y", &msg_type);
2888+
if (rc < 0)
2889+
goto err;
2890+
rc = sd_bus_message_read_array(call, 'u', (const void **)&versions,
2891+
&versions_len);
2892+
if (rc < 0)
2893+
goto err;
2894+
2895+
if (versions_len == 0) {
2896+
warnx("No versions provided for message type %d", msg_type);
2897+
return sd_bus_error_setf(
2898+
berr, SD_BUS_ERROR_INVALID_ARGS,
2899+
"No versions provided for message type %d", msg_type);
2900+
}
2901+
2902+
for (i = 0; i < ctx->num_supported_msg_types; i++) {
2903+
if (ctx->supported_msg_types[i].msg_type == msg_type) {
2904+
warnx("Message type %d already registered", msg_type);
2905+
return sd_bus_error_setf(
2906+
berr, SD_BUS_ERROR_INVALID_ARGS,
2907+
"Message type %d already registered", msg_type);
2908+
}
2909+
}
2910+
2911+
struct msg_type_support *msg_types =
2912+
realloc(ctx->supported_msg_types,
2913+
(ctx->num_supported_msg_types + 1) *
2914+
sizeof(struct msg_type_support));
2915+
if (!msg_types) {
2916+
goto oom_err;
2917+
}
2918+
ctx->supported_msg_types = msg_types;
2919+
ctx->supported_msg_types[ctx->num_supported_msg_types].msg_type =
2920+
msg_type;
2921+
ctx->supported_msg_types[ctx->num_supported_msg_types].num_versions =
2922+
versions_len / sizeof(uint32_t);
2923+
ctx->supported_msg_types[ctx->num_supported_msg_types].versions =
2924+
malloc(versions_len);
2925+
if (!ctx->supported_msg_types[ctx->num_supported_msg_types].versions) {
2926+
goto oom_err;
2927+
}
2928+
// Assume callers's responsibility to provide version in uint32 format from spec
2929+
memcpy(ctx->supported_msg_types[ctx->num_supported_msg_types].versions,
2930+
versions, versions_len);
2931+
2932+
ctx->num_supported_msg_types++;
2933+
2934+
return sd_bus_reply_method_return(call, "");
2935+
oom_err:
2936+
return sd_bus_error_setf(berr, SD_BUS_ERROR_NO_MEMORY,
2937+
"Failed to allocate memory");
2938+
err:
2939+
set_berr(ctx, rc, berr);
2940+
return rc;
2941+
}
2942+
28322943
// clang-format off
28332944
static const sd_bus_vtable bus_link_owner_vtable[] = {
28342945
SD_BUS_VTABLE_START(0),
@@ -3145,6 +3256,17 @@ static const sd_bus_vtable bus_network_vtable[] = {
31453256
SD_BUS_VTABLE_PROPERTY_CONST),
31463257
SD_BUS_VTABLE_END
31473258
};
3259+
3260+
static const sd_bus_vtable mctp_base_vtable[] = {
3261+
SD_BUS_VTABLE_START(0),
3262+
SD_BUS_METHOD_WITH_ARGS("RegisterResponder",
3263+
SD_BUS_ARGS("y", msg_type,
3264+
"au", versions),
3265+
SD_BUS_NO_RESULT,
3266+
method_register_responder,
3267+
0),
3268+
SD_BUS_VTABLE_END,
3269+
};
31483270
// clang-format on
31493271

31503272
static int emit_endpoint_added(const struct peer *peer)
@@ -3295,6 +3417,14 @@ static int setup_bus(struct ctx *ctx)
32953417
goto out;
32963418
}
32973419

3420+
rc = sd_bus_add_object_vtable(ctx->bus, NULL, MCTP_DBUS_PATH,
3421+
MCTP_DBUS_NAME,
3422+
mctp_base_vtable, ctx);
3423+
if (rc < 0) {
3424+
warnx("Adding MCTP base vtable failed: %s", strerror(-rc));
3425+
goto out;
3426+
}
3427+
32983428
rc = 0;
32993429
out:
33003430
return rc;
@@ -3994,6 +4124,33 @@ static int parse_config(struct ctx *ctx)
39944124
return rc;
39954125
}
39964126

4127+
static void setup_ctrl_cmd_defaults(struct ctx *ctx)
4128+
{
4129+
ctx->supported_msg_types = NULL;
4130+
ctx->num_supported_msg_types = 0;
4131+
4132+
// Default to supporting only control messages
4133+
ctx->supported_msg_types = malloc(sizeof(struct msg_type_support));
4134+
if (!ctx->supported_msg_types) {
4135+
warnx("Out of memory for supported message types");
4136+
return;
4137+
}
4138+
ctx->num_supported_msg_types = 1;
4139+
ctx->supported_msg_types[0].msg_type = MCTP_CTRL_HDR_MSG_TYPE;
4140+
4141+
ctx->supported_msg_types[0].versions = malloc(sizeof(uint32_t) * 4);
4142+
if (!ctx->supported_msg_types[0].versions) {
4143+
warnx("Out of memory for versions");
4144+
free(ctx->supported_msg_types);
4145+
return;
4146+
}
4147+
ctx->supported_msg_types[0].num_versions = 4;
4148+
ctx->supported_msg_types[0].versions[0] = htonl(0xF1F0FF00);
4149+
ctx->supported_msg_types[0].versions[1] = htonl(0xF1F1FF00);
4150+
ctx->supported_msg_types[0].versions[2] = htonl(0xF1F2FF00);
4151+
ctx->supported_msg_types[0].versions[3] = htonl(0xF1F3F100);
4152+
}
4153+
39974154
static void setup_config_defaults(struct ctx *ctx)
39984155
{
39994156
ctx->mctp_timeout = 250000; // 250ms
@@ -4002,7 +4159,13 @@ static void setup_config_defaults(struct ctx *ctx)
40024159

40034160
static void free_config(struct ctx *ctx)
40044161
{
4162+
int i;
4163+
40054164
free(ctx->config_filename);
4165+
for (i = 0; i < ctx->num_supported_msg_types; i++) {
4166+
free(ctx->supported_msg_types[i].versions);
4167+
}
4168+
free(ctx->supported_msg_types);
40064169
}
40074170

40084171
int main(int argc, char **argv)
@@ -4013,6 +4176,8 @@ int main(int argc, char **argv)
40134176
setlinebuf(stdout);
40144177

40154178
setup_config_defaults(ctx);
4179+
setup_ctrl_cmd_defaults(ctx);
4180+
40164181
mctp_ops_init();
40174182

40184183
rc = parse_args(ctx, argc, argv);

0 commit comments

Comments
 (0)