Skip to content

Commit ac5a06b

Browse files
mctpd: support discovery requests
This adds support for the Discovered flag and discovery requests, as described in DSP0236 12.14 Prepare for Endpoint Discovery and 12.15 Endpoint Discovery. Signed-off-by: Khang D Nguyen <khangng@os.amperecomputing.com>
1 parent 45707fa commit ac5a06b

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

src/mctpd.c

Lines changed: 95 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;
@@ -776,6 +777,7 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
776777
warnx("ERR: cannot add bus owner to object lists");
777778
}
778779

780+
link_data->discovered = true;
779781
resp->status =
780782
SET_MCTP_EID_ASSIGNMENT_STATUS(MCTP_SET_EID_ACCEPTED) |
781783
SET_MCTP_EID_ALLOCATION_STATUS(MCTP_SET_EID_POOL_NONE);
@@ -785,6 +787,14 @@ static int handle_control_set_endpoint_id(struct ctx *ctx, int sd,
785787
return reply_message(ctx, sd, resp, resp_len, addr);
786788

787789
case MCTP_SET_EID_DISCOVERED:
790+
link_data->discovered = true;
791+
resp->status =
792+
SET_MCTP_EID_ASSIGNMENT_STATUS(MCTP_SET_EID_REJECTED) |
793+
SET_MCTP_EID_ALLOCATION_STATUS(MCTP_SET_EID_POOL_NONE);
794+
resp->eid_set = req->eid;
795+
resp->eid_pool_size = 0;
796+
return reply_message(ctx, sd, resp, resp_len, addr);
797+
788798
case MCTP_SET_EID_RESET:
789799
// unsupported
790800
resp->completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA;
@@ -947,6 +957,82 @@ handle_control_resolve_endpoint_id(struct ctx *ctx, int sd,
947957
return reply_message(ctx, sd, resp, resp_len, addr);
948958
}
949959

960+
static int handle_control_prepare_endpoint_discovery(
961+
struct ctx *ctx, int sd, const struct sockaddr_mctp_ext *addr,
962+
const uint8_t *buf, const size_t buf_size)
963+
{
964+
struct mctp_ctrl_msg_hdr *req = NULL;
965+
struct mctp_ctrl_resp_prepare_discovery respi = { 0 }, *resp = &respi;
966+
struct link *link_data;
967+
968+
if (buf_size < sizeof(*req)) {
969+
warnx("short Prepare for Endpoint Discovery message");
970+
return -ENOMSG;
971+
}
972+
973+
link_data = mctp_nl_get_link_userdata(ctx->nl, addr->smctp_ifindex);
974+
if (!link_data) {
975+
bug_warn("unconfigured interface %d", addr->smctp_ifindex);
976+
return -ENOENT;
977+
}
978+
979+
if (link_data->role == ENDPOINT_ROLE_BUS_OWNER) {
980+
// ignore message if we are bus owner
981+
return 0;
982+
}
983+
984+
req = (void *)buf;
985+
resp = (void *)resp;
986+
mctp_ctrl_msg_hdr_init_resp(&resp->ctrl_hdr, *req);
987+
988+
if (link_data->discovered) {
989+
link_data->discovered = false;
990+
warnx("clear discovered flag of interface %d",
991+
addr->smctp_ifindex);
992+
}
993+
994+
// we need to send using physical addressing, no entry in routing table yet
995+
return reply_message_phys(ctx, sd, resp, sizeof(*resp), addr);
996+
}
997+
998+
static int
999+
handle_control_endpoint_discovery(struct ctx *ctx, int sd,
1000+
const struct sockaddr_mctp_ext *addr,
1001+
const uint8_t *buf, const size_t buf_size)
1002+
{
1003+
struct mctp_ctrl_msg_hdr *req = NULL;
1004+
struct mctp_ctrl_resp_endpoint_discovery respi = { 0 }, *resp = &respi;
1005+
struct link *link_data;
1006+
1007+
if (buf_size < sizeof(*req)) {
1008+
warnx("short Endpoint Discovery message");
1009+
return -ENOMSG;
1010+
}
1011+
1012+
link_data = mctp_nl_get_link_userdata(ctx->nl, addr->smctp_ifindex);
1013+
if (!link_data) {
1014+
bug_warn("unconfigured interface %d", addr->smctp_ifindex);
1015+
return -ENOENT;
1016+
}
1017+
1018+
if (link_data->role == ENDPOINT_ROLE_BUS_OWNER) {
1019+
// ignore message if we are bus owner
1020+
return 0;
1021+
}
1022+
1023+
if (link_data->discovered) {
1024+
// if we are already discovered (i.e, assigned an EID), then no reply
1025+
return 0;
1026+
}
1027+
1028+
req = (void *)buf;
1029+
resp = (void *)resp;
1030+
mctp_ctrl_msg_hdr_init_resp(&resp->ctrl_hdr, *req);
1031+
1032+
// we need to send using physical addressing, no entry in routing table yet
1033+
return reply_message_phys(ctx, sd, resp, sizeof(*resp), addr);
1034+
}
1035+
9501036
static int handle_control_unsupported(struct ctx *ctx, int sd,
9511037
const struct sockaddr_mctp_ext *addr,
9521038
const uint8_t *buf, const size_t buf_size)
@@ -1029,6 +1115,14 @@ static int cb_listen_control_msg(sd_event_source *s, int sd, uint32_t revents,
10291115
rc = handle_control_resolve_endpoint_id(ctx, sd, &addr, buf,
10301116
buf_size);
10311117
break;
1118+
case MCTP_CTRL_CMD_PREPARE_ENDPOINT_DISCOVERY:
1119+
rc = handle_control_prepare_endpoint_discovery(ctx, sd, &addr,
1120+
buf, buf_size);
1121+
break;
1122+
case MCTP_CTRL_CMD_ENDPOINT_DISCOVERY:
1123+
rc = handle_control_endpoint_discovery(ctx, sd, &addr, buf,
1124+
buf_size);
1125+
break;
10321126
default:
10331127
if (ctx->verbose) {
10341128
warnx("Ignoring unsupported command code 0x%02x",
@@ -3902,6 +3996,7 @@ static int add_interface(struct ctx *ctx, int ifindex)
39023996
if (!link)
39033997
return -ENOMEM;
39043998

3999+
link->discovered = false;
39054000
link->published = false;
39064001
link->ifindex = ifindex;
39074002
link->ctx = ctx;

tests/test_mctpd_endpoint.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,31 @@ async def test_accept_multiple_set_eids_for_single_interface(dbus, mctpd):
101101

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

0 commit comments

Comments
 (0)