From 238125dabb763ba55969dbf645b05f1ee65585c9 Mon Sep 17 00:00:00 2001 From: Khang Nguyen Date: Thu, 31 Aug 2023 15:08:06 +0700 Subject: [PATCH] mctpd: Add `NotifyDiscovery` D-Bus method This method sends a Discovery Notify to the PCIe Root Complex. Tested: busctl call xyz.openbmc_project.MCTP /xyz/openbmc_project/mctp \ au.com.CodeConstruct.MCTP NotifyDiscovery s mctppcie0 should work. However, the message may take a long time to return so the timeout may need to be increased. This is to be investigated. Signed-off-by: Khang Nguyen --- docs/mctpd.md | 23 +++++++++++++++++ src/mctpd.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/docs/mctpd.md b/docs/mctpd.md index 6333917..03a3ac3 100644 --- a/docs/mctpd.md +++ b/docs/mctpd.md @@ -51,6 +51,29 @@ Like SetupEndpoint but will not assign EIDs, will only query endpoints for a cur The `new` return value is set to `false` for an already known endpoint, or `true` when an endpoint's EID is newly discovered. +## `.NotifyDiscovery` + +This method is used to trigger the MCTP over PCIe-VDM discovery process on a +PCIe-VDM interface. + +This method sends a Discovery Notify message to the Root Complex on the PCIe bus +with null EID, null physical address and Route-To-Root-Complex PCIe-VDM routing +type. + +This method should only be used when `mctpd` is running on an endpoint. + +`NotifyDiscovery ` + +`` is an PCIe-VDM interface such as `mctppcie0`. + + +Example: + +```shell +busctl call xyz.openbmc_project.MCTP /xyz/openbmc_project/mctp \ + au.com.CodeConstruct.MCTP NotifyDiscovery s mctppcie0 +``` + ## Endpoint Methods Each endpoint object has methods to configure it, with `au.com.CodeConstruct.MCTP.Endpoint` diff --git a/src/mctpd.c b/src/mctpd.c index b89b01b..e2809d0 100644 --- a/src/mctpd.c +++ b/src/mctpd.c @@ -1832,6 +1832,66 @@ static int method_learn_endpoint(sd_bus_message *call, void *data, sd_bus_error return rc; } +static int method_notify_discovery(sd_bus_message *call, void *data, + sd_bus_error *berr) +{ + int rc; + const char *ifname = NULL; + dest_phys desti = { 0 }, *dest = &desti; + ctx *ctx = data; + struct mctp_ctrl_cmd_discovery_notify req = { 0 }; + struct mctp_ctrl_resp_discovery_notify *resp; + uint8_t *buf; + size_t buf_size; + struct sockaddr_mctp_ext resp_addr; + + rc = sd_bus_message_read(call, "s", &ifname); + if (rc < 0) + goto err; + + dest->hwaddr_len = 2; + dest->ifindex = mctp_nl_ifindex_byname(ctx->nl, ifname); + if (dest->ifindex <= 0) + return sd_bus_error_setf(berr, SD_BUS_ERROR_INVALID_ARGS, + "Unknown MCTP ifname '%s'", ifname); + + rc = validate_dest_phys(ctx, dest); + if (rc < 0) + return sd_bus_error_setf(berr, SD_BUS_ERROR_INVALID_ARGS, + "Bad physaddr"); + + req.ctrl_hdr.command_code = MCTP_CTRL_CMD_DISCOVERY_NOTIFY; + req.ctrl_hdr.rq_dgram_inst = RQDI_REQ; + + rc = endpoint_query_phys(ctx, dest, MCTP_CTRL_HDR_MSG_TYPE, &req, + sizeof(req), &buf, &buf_size, &resp_addr); + if (rc < 0) + goto free_buf; + + if (buf_size != sizeof(*resp)) { + warnx("%s: wrong reply length %zu bytes. dest %s", __func__, + buf_size, dest_phys_tostr(dest)); + rc = -ENOMSG; + goto free_buf; + } + resp = (void *)buf; + + if (resp->completion_code != 0) { + // TODO: make this a debug message? + warnx("Failure completion code 0x%02x from %s", + resp->completion_code, dest_phys_tostr(dest)); + rc = -ECONNREFUSED; + goto free_buf; + } + free(buf); + return sd_bus_reply_method_return(call, ""); +free_buf: + free(buf); +err: + set_berr(ctx, rc, berr); + return rc; +} + // Query various properties of a peer. // To be called when a new peer is discovered/assigned, once an EID is known // and routable. @@ -2274,6 +2334,14 @@ static const sd_bus_vtable bus_mctpd_vtable[] = { SD_BUS_PARAM(found), method_learn_endpoint, 0), + + SD_BUS_METHOD_WITH_NAMES("NotifyDiscovery", + "s", + SD_BUS_PARAM(ifname), + "",, + method_notify_discovery, + 0), + SD_BUS_VTABLE_END, };