pldm design: elaborate the requester flow
Propose design for the BMC as a PLDM requester. Requirements for the
same are in the document already. This commit talks about two design
approaches, and recommends one of them.
Change-Id: I365ece91bef4c50b3780ed02345bc6f411c183c5
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/designs/pldm-stack.md b/designs/pldm-stack.md
index 2c21326..836a252 100644
--- a/designs/pldm-stack.md
+++ b/designs/pldm-stack.md
@@ -189,22 +189,154 @@
control on a remote device, based on sensors from that device and algorithms
specific to that device.
-The PLDM daemon would have to implement D-Bus interfaces to form the requester
-functions: a method to send a PLDM message over the underlying transport (again,
-this will have two versions: one that accepts a byte stream, and the other that
-accepts an fd, for large messages) and a signal to indicate a PLDM response from
-the remote PLDM device. The signal would comprise of the transport headers, PLDM
-headers, and the PLDM payload.
+##### Proposed requester design
-The typical flow for a requester app would be to send the PLDM message via the
-D-Bus API (the PLDM daemon would have to assign an instance id), and add a
-handler for the D-Bus signal containing the response. As this flow is
-asynchronous, the requester app can execute other scheduled work, if any, in its
-event loop, while it waits for the D-Bus signal containing the response. The
-D-Bus API to send a PLDM message to the remote PLDM device would call the
-underlying transport's send API. If that API blocks for too long, the call may
-have to run in a thread of it's own. The D-Bus signal containing a response
-message is emitted by the receiver (see above).
+A requester app/flow comprises of the following :
+
+- Linkage with a PLDM encode/decode library, to be able to pack PLDM requests
+ and unpack PLDM responses.
+
+- A D-Bus API to generate a unique PLDM instance id. The id needs to be unique
+ across all outgoing PLDM messages (from potentially different processes).
+ This needs to be on D-Bus because the id needs to be unique across PLDM
+ requester app processes.
+
+- A requester client API that provides blocking and non-blocking functions to
+ transfer a PLDM request message and to receive the corresponding response
+ message, over MCTP (the blocking send() will return a PLDM response).
+ This will be a thin wrapper over the socket API provided by the mctp demux
+ daemon. This will provide APIs for common tasks so that the same may not
+ be re-implemented in each PLDM requester app. This set of API will be built
+ into the encode/decode library (so libpldm would house encode/decode APIs, and
+ based on a compile time flag, the requester APIs as well). A PLDM requester
+ app can choose to not use the client requester APIs, and instead can directly
+ talk to the MCTP demux daemon.
+
+##### Proposed requester design - flow diagrams
+
+a) With blocking API
+
++---------------+ +----------------+ +----------------+ +-----------------+
+|BMC requester/ | |PLDM requester | |PLDM responder | |PLDM Daemon |
+|client app | |lib (part of | | | | |
+| | |libpldm) | | | | |
++-------+-------+ +-------+--------+ +--------+-------+ +---------+-------+
+ | | | |
+ |App starts | | |
+ | | | |
+ +------------------------------->setup connection with | |
+ |init(non_block=false) |MCTP daemon | |
+ | | | |
+ +<-------+return_code+----------+ | |
+ | | | |
+ | | | |
+ | | | |
+ +------------------------------>+ | |
+ |encode_pldm_cmd(cmd code, args)| | |
+ | | | |
+ +<----+returns pldm_msg+--------+ | |
+ | | | |
+ | | | |
+ |----------------------------------------------------------------------------------------------->|
+ |DBus.getPLDMInstanceId() | | |
+ | | | |
+ |<-------------------------returns PLDM instance id----------------------------------------------|
+ | | | |
+ +------------------------------>+ | |
+ |send_msg(mctp_eids, pldm_msg) +----------------------------->+ |
+ | |write msg to MCTP socket | |
+ | +----------------------------->+ |
+ | |call blocking recv() on socket| |
+ | | | |
+ | +<-+returns pldm_response+-----+ |
+ | | | |
+ | +----+ | |
+ | | | verify eids, instance id| |
+ | +<---+ | |
+ | | | |
+ +<--+returns pldm_response+-----+ | |
+ | | | |
+ | | | |
+ | | | |
+ +------------------------------>+ | |
+ |decode_pldm_cmd(pldm_resp, | | |
+ | output args) | | |
+ | | | |
+ +------------------------------>+ | |
+ |close_connection() | | |
+ + + + +
+
+
+b) With non-blocking API
+
++---------------+ +----------------+ +----------------+ +---------------+
+|BMC requester/ | |PLDM requester | |PLDM responder | |PLDM daemon |
+|client app | |lib (part of | | | | |
+| | |libpldm) | | | | |
++-------+-------+ +-------+--------+ +--------+-------+ +--------+------+
+ | | | |
+ |App starts | | |
+ | | | |
+ +------------------------------->setup connection with | |
+ |init(non_block=true |MCTP daemon | |
+ | int* o_mctp_fd) | | |
+ | | | |
+ +<-------+return_code+----------+ | |
+ | | | |
+ | | | |
+ | | | |
+ +------------------------------>+ | |
+ |encode_pldm_cmd(cmd code, args)| | |
+ | | | |
+ +<----+returns pldm_msg+--------+ | |
+ | | | |
+ |-------------------------------------------------------------------------------------------->|
+ |DBus.getPLDMInstanceId() | | |
+ | | | |
+ |<-------------------------returns PLDM instance id-------------------------------------------|
+ | | | |
+ | | | |
+ +------------------------------>+ | |
+ |send_msg(eids, pldm_msg, +----------------------------->+ |
+ | non_block=true) |write msg to MCTP socket | |
+ | +<---+return_code+-------------+ |
+ +<-+returns rc, doesn't block+--+ | |
+ | | | |
+ +------+ | | |
+ | |Add EPOLLIN on mctp_fd | | |
+ | |to self.event_loop | | |
+ +<-----+ | | |
+ | + | |
+ +<----------------------+PLDM response msg written to mctp_fd+-+ |
+ | + | |
+ +------+EPOLLIN on mctp_fd | | |
+ | |received | | |
+ | | | | |
+ +<-----+ | | |
+ | | | |
+ +------------------------------>+ | |
+ |decode_pldm_cmd(pldm_response) | | |
+ | | | |
+ +------------------------------>+ | |
+ |close_connection() | | |
+ + + + +
+
+##### Alternative to the proposed requester design
+
+a) Define D-Bus interfaces to send and receive PLDM messages :
+
+```
+method sendPLDM(uint8 mctp_eid, uint8 msg[])
+
+signal recvPLDM(uint8 mctp_eid, uint8 pldm_instance_id, uint8 msg[])
+```
+
+PLDM requester apps can then invoke the above applications. While this
+simplifies things for the user, it has two disadvantages :
+- the app implementing such an interface could be a single point of failure,
+ plus sending messages concurrently would be a challenge.
+- the message payload could be large (several pages), and copying the same for
+ D-Bus transfers might be undesirable.
### Multiple transport channels
The PLDM daemon might have to talk to remote PLDM devices via different