Skip to content

Commit 36a346c

Browse files
mctpd: add support for the Discovered flag
This adds support for the Discovered flag, described in DSP0236 12.14 Prepare for Endpoint Discovery and 12.15 Endpoint Discovery. Signed-off-by: Khang D Nguyen <[email protected]>
1 parent 521f10c commit 36a346c

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

src/mctpd.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ static const struct role roles[] = {
118118
};
119119

120120
struct link {
121+
bool discovered;
121122
bool published;
122123
int ifindex;
123124
enum endpoint_role role;
@@ -768,6 +769,7 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
768769
warnx("ERR: cannot add bus owner to object lists");
769770
}
770771

772+
link_data->discovered = true;
771773
SET_MCTP_EID_ASSIGNMENT_STATUS(resp->status,
772774
MCTP_SET_EID_ACCEPTED);
773775
SET_MCTP_EID_ALLOCATION_STATUS(resp->status,
@@ -778,6 +780,15 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
778780
return reply_message(ctx, sd, resp, resp_len, addr);
779781

780782
case MCTP_SET_EID_DISCOVERED:
783+
link_data->discovered = true;
784+
SET_MCTP_EID_ASSIGNMENT_STATUS(resp->status,
785+
MCTP_SET_EID_REJECTED);
786+
SET_MCTP_EID_ALLOCATION_STATUS(resp->status,
787+
MCTP_SET_EID_POOL_NONE);
788+
resp->eid_set = req->eid;
789+
resp->eid_pool_size = 0;
790+
return reply_message(ctx, sd, resp, resp_len, addr);
791+
781792
case MCTP_SET_EID_RESET:
782793
// unsupported
783794
resp->completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA;
@@ -938,6 +949,77 @@ handle_control_resolve_endpoint_id(struct ctx *ctx, int sd,
938949
return reply_message(ctx, sd, resp, resp_len, addr);
939950
}
940951

952+
static int handle_control_prepare_endpoint_discovery(
953+
struct ctx *ctx, int sd, const struct sockaddr_mctp_ext *addr,
954+
const uint8_t *buf, const size_t buf_size)
955+
{
956+
struct mctp_ctrl_msg_hdr *req = NULL;
957+
struct mctp_ctrl_resp_prepare_discovery respi = { 0 }, *resp = &respi;
958+
struct link *link_data;
959+
960+
if (buf_size < sizeof(*req)) {
961+
warnx("short Prepare for Endpoint Discovery message");
962+
return -ENOMSG;
963+
}
964+
965+
link_data = mctp_nl_get_link_userdata(ctx->nl, addr->smctp_ifindex);
966+
if (!link_data) {
967+
bug_warn("unconfigured interface %d", addr->smctp_ifindex);
968+
return -ENOENT;
969+
}
970+
971+
req = (void *)buf;
972+
resp = (void *)resp;
973+
mctp_ctrl_msg_hdr_init_resp(&resp->ctrl_hdr, *req);
974+
975+
if (link_data->discovered) {
976+
link_data->discovered = false;
977+
warnx("clear discovered flag of interface %d",
978+
addr->smctp_ifindex);
979+
}
980+
981+
// we need to send using physical addressing, no entry in routing table yet
982+
return reply_message_phys(ctx, sd, resp, sizeof(*resp), addr);
983+
}
984+
985+
static int
986+
handle_control_endpoint_discovery(struct ctx *ctx, int sd,
987+
const struct sockaddr_mctp_ext *addr,
988+
const uint8_t *buf, const size_t buf_size)
989+
{
990+
struct mctp_ctrl_msg_hdr *req = NULL;
991+
struct mctp_ctrl_resp_endpoint_discovery respi = { 0 }, *resp = &respi;
992+
struct link *link_data;
993+
994+
if (buf_size < sizeof(*req)) {
995+
warnx("short Endpoint Discovery message");
996+
return -ENOMSG;
997+
}
998+
999+
link_data = mctp_nl_get_link_userdata(ctx->nl, addr->smctp_ifindex);
1000+
if (!link_data) {
1001+
bug_warn("unconfigured interface %d", addr->smctp_ifindex);
1002+
return -ENOENT;
1003+
}
1004+
1005+
if (link_data->role == ENDPOINT_ROLE_BUS_OWNER) {
1006+
// ignore message if we are bus owner
1007+
return 0;
1008+
}
1009+
1010+
if (link_data->discovered) {
1011+
// if we are already discovered (i.e, assigned an EID), then no reply
1012+
return 0;
1013+
}
1014+
1015+
req = (void *)buf;
1016+
resp = (void *)resp;
1017+
mctp_ctrl_msg_hdr_init_resp(&resp->ctrl_hdr, *req);
1018+
1019+
// we need to send using physical addressing, no entry in routing table yet
1020+
return reply_message_phys(ctx, sd, resp, sizeof(*resp), addr);
1021+
}
1022+
9411023
static int handle_control_unsupported(struct ctx *ctx, int sd,
9421024
const struct sockaddr_mctp_ext *addr,
9431025
const uint8_t *buf, const size_t buf_size)
@@ -1020,6 +1102,14 @@ static int cb_listen_control_msg(sd_event_source *s, int sd, uint32_t revents,
10201102
rc = handle_control_resolve_endpoint_id(ctx, sd, &addr, buf,
10211103
buf_size);
10221104
break;
1105+
case MCTP_CTRL_CMD_PREPARE_ENDPOINT_DISCOVERY:
1106+
rc = handle_control_prepare_endpoint_discovery(ctx, sd, &addr,
1107+
buf, buf_size);
1108+
break;
1109+
case MCTP_CTRL_CMD_ENDPOINT_DISCOVERY:
1110+
rc = handle_control_endpoint_discovery(ctx, sd, &addr, buf,
1111+
buf_size);
1112+
break;
10231113
default:
10241114
if (ctx->verbose) {
10251115
warnx("Ignoring unsupported command code 0x%02x",
@@ -3880,6 +3970,7 @@ static int add_interface(struct ctx *ctx, int ifindex)
38803970
if (!link)
38813971
return -ENOMEM;
38823972

3973+
link->discovered = false;
38833974
link->published = false;
38843975
link->ifindex = ifindex;
38853976
link->ctx = ctx;

tests/test_mctpd_endpoint.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,30 @@ async def test_accept_multiple_set_eids_for_single_interface(dbus, mctpd):
9999

100100
# expect new EID on D-Bus
101101
assert await mctpd_mctp_endpoint_control_obj(dbus, f"/au/com/codeconstruct/mctp1/networks/1/endpoints/{0x66}")
102+
103+
104+
""" Test simple Discovery sequence """
105+
async def test_simple_discovery_sequence(dbus, mctpd):
106+
bo = mctpd.network.endpoints[0]
107+
108+
assert len(mctpd.system.addresses) == 0
109+
110+
# no EID yet
111+
rsp = await bo.send_control(mctpd.network.mctp_socket, MCTPControlCommand(True, 0, 0x02))
112+
assert rsp.hex(' ') == '00 02 00 00 02 00'
113+
114+
# BMC response to Prepare for Discovery
115+
rsp = await bo.send_control(mctpd.network.mctp_socket, MCTPControlCommand(True, 0, 0x0B))
116+
assert rsp.hex(' ') == '00 0b 00'
117+
118+
# BMC response to Endpoint Discovery
119+
rsp = await bo.send_control(mctpd.network.mctp_socket, MCTPControlCommand(True, 0, 0x0C))
120+
assert rsp.hex(' ') == '00 0c 00'
121+
122+
# set EID = 42
123+
rsp = await bo.send_control(mctpd.network.mctp_socket, MCTPControlCommand(True, 0, 0x01, bytes([0x00, 0x42])))
124+
assert rsp.hex(' ') == '00 01 00 00 42 00'
125+
126+
# BMC should contains two object paths: bus owner and itself
127+
assert await mctpd_mctp_endpoint_control_obj(dbus, "/au/com/codeconstruct/mctp1/networks/1/endpoints/8")
128+
assert await mctpd_mctp_endpoint_control_obj(dbus, f"/au/com/codeconstruct/mctp1/networks/1/endpoints/{0x42}")

0 commit comments

Comments
 (0)