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