xref: /openbmc/docs/designs/pldm-stack.md (revision ed331697)
1# PLDM stack on OpenBMC
2
3Author: Deepak Kodihalli <dkodihal@linux.vnet.ibm.com> <dkodihal>
4
5Created: 2019-01-22
6
7## Problem Description
8
9On OpenBMC, in-band IPMI is currently the primary industry-standard means of
10communication between the BMC and the Host firmware. We've started hitting some
11inherent limitations of IPMI on OpenPOWER servers: a limited number of sensors,
12and a lack of a generic control mechanism (sensors are a generic monitoring
13mechanism) are the major ones. There is a need to improve upon the communication
14protocol, but at the same time inventing a custom protocol is undesirable.
15
16This design aims to employ Platform Level Data Model (PLDM), a standard
17application layer communication protocol defined by the DMTF. PLDM draws inputs
18from IPMI, but it overcomes most of the latter's limitations. PLDM is also
19designed to run on standard transport protocols, for e.g. MCTP (also designed by
20the DMTF). MCTP provides for a common transport layer over several physical
21channels, by defining hardware bindings. The solution of PLDM over MCTP also
22helps overcome some of the limitations of the hardware channels that IPMI uses.
23
24PLDM's purpose is to enable all sorts of "inside the box communication": BMC -
25Host, BMC - BMC, BMC - Network Controller and BMC - Other (for e.g. sensor)
26devices.
27
28## Background and References
29
30PLDM is designed to be an effective interface and data model that provides
31efficient access to low-level platform inventory, monitoring, control, event,
32and data/parameters transfer functions. For example, temperature, voltage, or
33fan sensors can have a PLDM representation that can be used to monitor and
34control the platform using a set of PLDM messages. PLDM defines data
35representations and commands that abstract the platform management hardware.
36
37PLDM groups commands under broader functions, and defines separate
38specifications for each of these functions (also called PLDM "Types"). The
39currently defined Types (and corresponding specs) are : PLDM base (with
40associated IDs and states specs), BIOS, FRU, Platform monitoring and control,
41Firmware Update and SMBIOS. All these specifications are available at:
42
43https://www.dmtf.org/standards/pmci
44
45Some of the reasons PLDM sounds promising (some of these are advantages over
46IPMI):
47
48- Common in-band communication protocol.
49
50- Already existing PLDM Type specifications that cover the most common
51  communication requirements. Up to 64 PLDM Types can be defined (the last one
52  is OEM). At the moment, 6 are defined. Each PLDM type can house up to 256 PLDM
53  commands.
54
55- PLDM sensors are 2 bytes in length.
56
57- PLDM introduces the concept of effecters - a control mechanism. Both sensors
58  and effecters are associated to entities (similar to IPMI, entities can be
59  physical or logical), where sensors are a mechanism for monitoring and
60  effecters are a mechanism for control. Effecters can be numeric or state
61  based. PLDM defines commonly used entities and their IDs, but there 8K slots
62  available to define OEM entities.
63
64- A very active PLDM related working group in the DMTF.
65
66The plan is to run PLDM over MCTP. MCTP is defined in a spec of its own, and a
67proposal on the MCTP design is in discussion already. There's going to be an
68intermediate PLDM over MCTP binding layer, which lets us send PLDM messages over
69MCTP. This is defined in a spec of its own, and the design for this binding will
70be proposed separately.
71
72## Requirements
73
74How different BMC applications make use of PLDM messages is outside the scope of
75this requirements doc. The requirements listed here are related to the PLDM
76protocol stack and the request/response model:
77
78- Marshalling and unmarshalling of PLDM messages, defined in various PLDM Type
79  specs, must be implemented. This can of course be staged based on the need of
80  specific Types and functions. Since this is just encoding and decoding PLDM
81  messages, this can be a library that could shared between the BMC, and other
82  firmware stacks. The specifics of each PLDM Type (such as FRU table
83  structures, sensor PDR structures, etc) are implemented by this lib.
84
85- Mapping PLDM concepts to native OpenBMC concepts must be implemented. For
86  e.g.: mapping PLDM sensors to phosphor-hwmon hosted D-Bus objects, mapping
87  PLDM FRU data to D-Bus objects hosted by phosphor-inventory-manager, etc. The
88  mapping shouldn't be restrictive to D-Bus alone (meaning it shouldn't be
89  necessary to put objects on the Bus just to serve PLDM requests, a problem
90  that exists with phosphor-host-ipmid today). Essentially these are platform
91  specific PLDM message handlers.
92
93- The BMC should be able to act as a PLDM responder as well as a PLDM requester.
94  As a PLDM requester, the BMC can monitor/control other devices. As a PLDM
95  responder, the BMC can react to PLDM messages directed to it via requesters in
96  the platform.
97
98- As a PLDM requester, the BMC must be able to discover other PLDM enabled
99  components in the platform.
100
101- As a PLDM requester, the BMC must be able to send simultaneous messages to
102  different responders.
103
104- As a PLDM requester, the BMC must be able to handle out of order responses.
105
106- As a PLDM responder, the BMC may simultaneously respond to messages from
107  different requesters, but the spec doesn't mandate this. In other words the
108  responder could be single-threaded.
109
110- It should be possible to plug-in OEM PLDM types/functions into the PLDM stack.
111
112- As a PLDM sensor monitoring daemon, the BMC must be able to enumerate and
113  monitor the static or self-described(with PDRs) PLDM sensors in satellite
114  Management Controller, on board device or PCIe add-on card.
115
116## Proposed Design
117
118This document covers the architectural, interface, and design details. It
119provides recommendations for implementations, but implementation details are
120outside the scope of this document.
121
122The design aims at having a single PLDM daemon serve both the requester and
123responder functions, and having transport specific endpoints to communicate on
124different channels.
125
126The design enables concurrency aspects of the requester and responder functions,
127but the goal is to employ asynchronous IO and event loops, instead of multiple
128threads, wherever possible.
129
130The following are high level structural elements of the design:
131
132### PLDM encode/decode libraries
133
134This library would take a PLDM message, decode it and extract the different
135fields of the message. Conversely, given a PLDM Type, command code, and the
136command's data fields, it would make a PLDM message. The thought is to design
137this as a common library, that can be used by the BMC and other firmware stacks,
138because it's the encode/decode and protocol piece (and not the handling of a
139message).
140
141### PLDM provider libraries
142
143These libraries would implement the platform specific handling of incoming PLDM
144requests (basically helping with the PLDM responder implementation, see next
145bullet point), so for instance they would query D-Bus objects (or even something
146like a JSON file) to fetch platform specific information to respond to the PLDM
147message. They would link with the encode/decode lib.
148
149It should be possible to plug-in a provider library, that lets someone add
150functionality for new PLDM (standard as well as OEM) Types. The libraries would
151implement a "register" API to plug-in handlers for specific PLDM messages.
152Something like:
153
154template <typename Handler, typename... args> auto register(uint8_t type,
155uint8_t command, Handler handler);
156
157This allows for providing a strongly-typed C++ handler registration scheme. It
158would also be possible to validate the parameters passed to the handler at
159compile time.
160
161### Request/Response Model
162
163The PLDM daemon links with the encode/decode and provider libs. The daemon would
164have to implement the following functions:
165
166#### Receiver/Responder
167
168The receiver wakes up on getting notified of incoming PLDM messages (via D-Bus
169signal or callback from the transport layer) from a remote PLDM device. If the
170message type is "Request" it would route them to a PLDM provider library. Via
171the library, asynchronous D-Bus calls (using sdbusplus-asio) would be made, so
172that the receiver can register a handler for the D-Bus response, instead of
173having to wait for the D-Bus response. This way it can go back to listening for
174incoming PLDM messages.
175
176In the D-Bus response handler, the receiver will send out the PLDM response
177message via the transport's send message API. If the transport's send message
178API blocks for a considerably long duration, then it would have to be run in a
179thread of it's own.
180
181If the incoming PLDM message is of type "Response", then the receiver emits a
182D-Bus signal pointing to the response message. Any time the message is too large
183to fit in a D-Bus payload, the message is written to a file, and a read-only
184file descriptor pointing to that file is contained in the D-Bus signal.
185
186#### Requester
187
188Designing the BMC as a PLDM requester is interesting. We haven't had this with
189IPMI, because the BMC was typically an IPMI server. PLDM requester functions
190will be spread across multiple OpenBMC applications (instead of a single big
191requester app) - based on the responder they're talking to and the high level
192function they implement. For example, there could be an app that lets the BMC
193upgrade firmware for other devices using PLDM - this would be a generic app in
194the sense that the same set of commands might have to be run irrespective of the
195device on the other side. There could also be an app that does fan control on a
196remote device, based on sensors from that device and algorithms specific to that
197device.
198
199##### Proposed requester design
200
201A requester app/flow comprises of the following :
202
203- Linkage with a PLDM encode/decode library, to be able to pack PLDM requests
204  and unpack PLDM responses.
205
206- A D-Bus API to generate a unique PLDM instance id. The id needs to be unique
207  across all outgoing PLDM messages (from potentially different processes). This
208  needs to be on D-Bus because the id needs to be unique across PLDM requester
209  app processes.
210
211- A requester client API that provides blocking and non-blocking functions to
212  transfer a PLDM request message and to receive the corresponding response
213  message, over MCTP (the blocking send() will return a PLDM response). This
214  will be a thin wrapper over the socket API provided by the mctp demux daemon.
215  This will provide APIs for common tasks so that the same may not be
216  re-implemented in each PLDM requester app. This set of API will be built into
217  the encode/decode library (so libpldm would house encode/decode APIs, and
218  based on a compile time flag, the requester APIs as well). A PLDM requester
219  app can choose to not use the client requester APIs, and instead can directly
220  talk to the MCTP demux daemon.
221
222##### Proposed requester design - flow diagrams
223
224a) With blocking API
225
226```
227+---------------+               +----------------+            +----------------+               +-----------------+
228|BMC requester/ |               |PLDM requester  |            |PLDM responder  |               |PLDM Daemon      |
229|client app     |               |lib (part of    |            |                |               |                 |
230|               |               |libpldm)        |            |                |               |                 |
231+-------+-------+               +-------+--------+            +--------+-------+               +---------+-------+
232        |                               |                              |                                 |
233        |App starts                     |                              |                                 |
234        |                               |                              |                                 |
235        +------------------------------->setup connection with         |                                 |
236        |init(non_block=false)          |MCTP daemon                   |                                 |
237        |                               |                              |                                 |
238        +<-------+return_code+----------+                              |                                 |
239        |                               |                              |                                 |
240        |                               |                              |                                 |
241        |                               |                              |                                 |
242        +------------------------------>+                              |                                 |
243        |encode_pldm_cmd(cmd code, args)|                              |                                 |
244        |                               |                              |                                 |
245        +<----+returns pldm_msg+--------+                              |                                 |
246        |                               |                              |                                 |
247        |                               |                              |                                 |
248        |----------------------------------------------------------------------------------------------->|
249        |DBus.getPLDMInstanceId()       |                              |                                 |
250        |                               |                              |                                 |
251        |<-------------------------returns PLDM instance id----------------------------------------------|
252        |                               |                              |                                 |
253        +------------------------------>+                              |                                 |
254        |send_msg(mctp_eids, pldm_msg)  +----------------------------->+                                 |
255        |                               |write msg to MCTP socket      |                                 |
256        |                               +----------------------------->+                                 |
257        |                               |call blocking recv() on socket|                                 |
258        |                               |                              |                                 |
259        |                               +<-+returns pldm_response+-----+                                 |
260        |                               |                              |                                 |
261        |                               +----+                         |                                 |
262        |                               |    | verify eids, instance id|                                 |
263        |                               +<---+                         |                                 |
264        |                               |                              |                                 |
265        +<--+returns pldm_response+-----+                              |                                 |
266        |                               |                              |                                 |
267        |                               |                              |                                 |
268        |                               |                              |                                 |
269        +------------------------------>+                              |                                 |
270        |decode_pldm_cmd(pldm_resp,     |                              |                                 |
271        |                output args)   |                              |                                 |
272        |                               |                              |                                 |
273        +------------------------------>+                              |                                 |
274        |close_connection()             |                              |                                 |
275        +                               +                              +                                 +
276```
277
278b) With non-blocking API
279
280```
281+---------------+               +----------------+            +----------------+             +---------------+
282|BMC requester/ |               |PLDM requester  |            |PLDM responder  |             |PLDM daemon    |
283|client app     |               |lib (part of    |            |                |             |               |
284|               |               |libpldm)        |            |                |             |               |
285+-------+-------+               +-------+--------+            +--------+-------+             +--------+------+
286        |                               |                              |                              |
287        |App starts                     |                              |                              |
288        |                               |                              |                              |
289        +------------------------------->setup connection with         |                              |
290        |init(non_block=true            |MCTP daemon                   |                              |
291        |     int* o_mctp_fd)           |                              |                              |
292        |                               |                              |                              |
293        +<-------+return_code+----------+                              |                              |
294        |                               |                              |                              |
295        |                               |                              |                              |
296        |                               |                              |                              |
297        +------------------------------>+                              |                              |
298        |encode_pldm_cmd(cmd code, args)|                              |                              |
299        |                               |                              |                              |
300        +<----+returns pldm_msg+--------+                              |                              |
301        |                               |                              |                              |
302        |-------------------------------------------------------------------------------------------->|
303        |DBus.getPLDMInstanceId()       |                              |                              |
304        |                               |                              |                              |
305        |<-------------------------returns PLDM instance id-------------------------------------------|
306        |                               |                              |                              |
307        |                               |                              |                              |
308        +------------------------------>+                              |                              |
309        |send_msg(eids, pldm_msg,       +----------------------------->+                              |
310        |         non_block=true)       |write msg to MCTP socket      |                              |
311        |                               +<---+return_code+-------------+                              |
312        +<-+returns rc, doesn't block+--+                              |                              |
313        |                               |                              |                              |
314        +------+                        |                              |                              |
315        |      |Add EPOLLIN on mctp_fd  |                              |                              |
316        |      |to self.event_loop      |                              |                              |
317        +<-----+                        |                              |                              |
318        |                               +                              |                              |
319        +<----------------------+PLDM response msg written to mctp_fd+-+                              |
320        |                               +                              |                              |
321        +------+EPOLLIN on mctp_fd      |                              |                              |
322        |      |received                |                              |                              |
323        |      |                        |                              |                              |
324        +<-----+                        |                              |                              |
325        |                               |                              |                              |
326        +------------------------------>+                              |                              |
327        |decode_pldm_cmd(pldm_response) |                              |                              |
328        |                               |                              |                              |
329        +------------------------------>+                              |                              |
330        |close_connection()             |                              |                              |
331        +                               +                              +                              +
332```
333
334##### Alternative to the proposed requester design
335
336a) Define D-Bus interfaces to send and receive PLDM messages :
337
338```
339method sendPLDM(uint8 mctp_eid, uint8 msg[])
340
341signal recvPLDM(uint8 mctp_eid, uint8 pldm_instance_id, uint8 msg[])
342```
343
344PLDM requester apps can then invoke the above applications. While this
345simplifies things for the user, it has two disadvantages :
346
347- the app implementing such an interface could be a single point of failure,
348  plus sending messages concurrently would be a challenge.
349- the message payload could be large (several pages), and copying the same for
350  D-Bus transfers might be undesirable.
351
352### Multiple transport channels
353
354The PLDM daemon might have to talk to remote PLDM devices via different
355channels. While a level of abstraction might be provided by MCTP, the PLDM
356daemon would have to implement a D-Bus interface to target a specific transport
357channel, so that requester apps on the BMC can send messages over that
358transport. Also, it should be possible to plug-in platform specific D-Bus
359objects that implement an interface to target a platform specific transport.
360
361### Processing PLDM FRU information sent down by the host firmware
362
363Note: while this is specific to the host BMC communication, most of this might
364apply to processing PLDM FRU information received from a device connected to the
365BMC as well.
366
367The requirement is for the BMC to consume PLDM FRU information received from the
368host firmware and then have the same exposed via Redfish. An example can be the
369host firmware sending down processor and core information via PLDM FRU commands,
370and the BMC making this information available via the Processor and
371ProcessorCollection schemas.
372
373This design is built around the pldmd and entity-manager applications on the
374BMC:
375
376- The pldmd asks the host firmware's PLDM stack for the host's FRU record table,
377  by sending it the PLDM GetFRURecordTable command. The pldmd should send this
378  command if the host indicates support for the PLDM FRU spec. The pldmd
379  receives a PLDM FRU record table from the host firmware (
380  www.dmtf.org/sites/default/files/standards/documents/DSP0257_1.0.0.pdf). The
381  daemon parses the FRU record table and hosts raw PLDM FRU information on
382  D-Bus. It will house the PLDM FRU properties for a certain FRU under an
383  xyz.openbmc_project.Inventory.Source.PLDM.FRU D-Bus interface, and house the
384  PLDM entity info extracted from the FRU record set PDR under an
385  xyz.openbmc_project.Source.PLDM.Entity interface.
386
387- Configurations can be written for entity-manager to probe an interface like
388  xyz.openbmc_project.Inventory.Source.PLDM.FRU, and create FRU inventory D-Bus
389  objects. Inventory interfaces from the xyz.openbmc_project. Inventory
390  namespace can be applied on these objects, by converting PLDM FRU property
391  values into xyz.openbmc_project.Invnetory.Decorator.Asset property values,
392  such as Part Number and Serial Number, in the entity manager configuration
393  file. Bmcweb can find these FRU inventory objects based on D-Bus interfaces,
394  as it does today.
395
396### MCTP endpoint discovery
397
398`pldmd` (PLDM daemon) utilizes the
399[MCTP D-Bus interfaces](https://github.com/openbmc/phosphor-dbus-interfaces/tree/master/yaml/xyz/openbmc_project/MCTP)
400to enumerate all MCTP endpoints in the system. The MCTP D-Bus interface
401implements the `SupportedMessageTypes` to have which Message type supported by
402each endpoint. `pldmd` watches the `InterfacesAdded` D-Bus signals from `mctpd`.
403It also matches the `InterfaceRemoved` D-Bus signals to find the removed
404endpoint EIDs from `mctpd`.
405
406### Terminus management and discovery
407
408`pldmd` will maintain a terminus table to manage the PLDM terminus in system.
409When `pldmd` received the updated EID table from MCTP D-Bus interface, `pldmd`
410should check if the EID support PLDM message type (0x01) and then adds the EID
411which is not in the terminus table yet. When the terminus EID is removed from
412MCTP D-Bus interface, `pldmd` should also clean up the removed endpoint from the
413terminus table.
414
415For each of terminus in the table, `pldmd` will go through the below steps:
416
417- Terminus initialization
418- Terminus discovery
419- Terminus monitor and control
420
421All of the added D-Bus object paths and D-Bus interfaces, Monitoring/Controlling
422tasks of the terminus will be removed when it is removed from the terminus
423table.
424
425#### Terminus initialization
426
427Each terminus in PLDM interface is identified by terminus ID (TID). This TID is
428an unique number `TID#`. When a new terminus is added to terminus table, `pldmd`
429should send `GetTID` to get the `TID#`. When the received `TID#` is already
430existing in TID pool, `pldmd` will call the `SetTID` command to assign a new TID
431for the terminus.
432
433Beside the `TID#`, terminus can also have `$TerminusName` or `$DeviceName` which
434can be encoded in the Terminus's `Entity Auxiliary Names PDR` (section 28.18 of
435DSP0248 1.2.1) or in the MCTP Entity-manager endpoint EID configuration file
436[Entity-Manager EID configuration](https://github.com/openbmc/entity-manager/blob/master/configurations/yosemite4_floatingfalls.json#L7).
437
438Because the `$TerminusName` will be included in the Terminus' sensors, effecters
439and states D-Bus object paths, so the EM EID configuration or Terminus's
440`Entity Auxiliary Names PDR` are recommended to be included for the Terminus
441support sensors, effecters or status. When the EM EID configuration is not
442available, the `Entity Auxiliary name PDR` should be added, so all sensors don't
443have the terminus number `TID#` in it anyhow.
444
445#### Teminus Discovery
446
447After the TID assignment steps, `pldmd` should go through `Terminus Discovery`
448steps:
449
450- Send `GetPLDMType` and `GetPLDMVersions` commands to the terminus to record
451  the supported PLDM type message/version.
452- If the terminus supports `GetPDRs` command type, `pldmd` will send that
453  command to get the terminus PDRs. Based on the retrieved PDRs, `pldmd` will
454  collect:
455
456  - The association between the entities in the system using
457    `Entity Association PDR` (section 28.17 of DSP0248 1.2.1).
458  - The entity names using `Entity Auxiliary Names PDR` (Section 28.18 of
459    DSP0248 1.2.1).
460  - The sensor/effecter/state info in the entities of terminus
461    sensors/effecter/state PDRs (section 28.4, 28.6, 28.8, 28.11, 28.14, 28.15,
462    28.25, etc. of DSP0248 1.2.1).
463  - The Fru info using FRU PDRs (section 28.22 of DSP0248 1.2.1).
464  - The other info using the others PDRs in section 28.x of DSP0248 1.2.1.
465
466  The above PDRs can also be configured in the JSON configuration files. When
467  the `PDR configuration` is available, the `pldmd` daemon will bypass `GetPDRs`
468  steps and read those files to collect that info. The template of the
469  configuration files can follow the current format of
470  [PDRs configuration files](https://github.com/openbmc/pldm/tree/master/configurations)
471
472  After this step, `pldmd` will have the list of `$sensorAuxNames` from the
473  Terminus's PDRs or the Terminus' EM JSON configuration files. This
474  `$sensorAuxNames` will be included in the PLDM Sensors D-Bus object paths in
475  `Sensor creating and monitor` section.
476
477- The `pldmd` then creates the Terminus inventory, sensors, effecters D-Bus
478  object paths.
479- At the final steps of `terminus discovery`, `pldmd` will send
480  `SetEventReceiver` notifies about the readiness of the BMC for the event
481  messages from the terminus.
482
483#### Terminus monitor and control
484
485After finishing the discovery steps, the daemon will start monitoring the
486sensors, response for the events from terminus and handle the terminus control
487action from the user.
488
489### Sensor creating and monitor
490
491To find out all sensors from PLDM terminus, `pldmd` should retrieve all the
492Sensor PDRs by PDR Repository commands (`GetPDRRepositoryInfo`, `GetPDR`) for
493the necessary parameters (e.g., `sensorID#`, `$SensorAuxName`, unit, etc.).
494`pldmd` can use libpldm encode/decode APIs
495(`encode_get_pdr_repository_info_req()`,
496`decode_get_pdr_repository_info_resp()`, `encode_get_pdr_req()`,
497`decode_get_pdr_resp()`) to build the commands message and then sends it to PLDM
498terminus.
499
500Regarding to the static device described in section 8.3.1 of DSP0248 1.2.1, the
501device uses PLDM for access only and doesn't support PDRs. The PDRs for the
502device needs to be encoded by Platform specific PDR JSON file by the platform
503developer. `pldmd` will generate these sensor PDRs encoded by JSON files and
504parse them as the same as the PDRs fetched by PLDM terminus.
505
506`pldmd` should expose the found PLDM sensor to D-Bus object path
507`/xyz/openbmc*project/sensors/<sensor_type>/SensorName`. The format of
508`sensorName` can be `$TerminusName_$SensorAuxName` or `$TerminusName_SensorID#`.
509`$SensorAuxName` will be included in the `sensorName` whenever they exist. For
510exposing sensor status to D-Bus, `pldmd` should implement following D-Bus
511interfaces to the D-Bus object path of PLDM sensor. The EM EID configuration or
512the Terminus' `Entity Auxiliary name PDR` will provide `$TerminusName`. And
513`$SensorAuxName` can be found in the EM EID sensor configuration or the sensor
514PDRs.
515
516- [xyz.openbmc_project.Sensor.Value](https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Sensor/Value.interface.yaml),
517  the interface exposes the sensor reading unit, value, Max/Min Value.
518
519- [xyz.openbmc_project.State.Decorator.OperationalStatus](https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/State/Decorator/OperationalStatus.interface.yaml),
520  the interface exposes the sensor status which is functional or not.
521
522After doing the discovery of PLDM sensors, `pldmd` should initialize all found
523sensors by necessary commands (e.g., `SetNumericSensorEnable`,
524`SetSensorThresholds`, `SetSensorHysteresis and `InitNumericSensor`) and then
525start to update the sensor status to D-bus objects by polling or async event
526method depending on the capability of PLDM terminus.
527
528`pldmd` should update the value property of `Sensor.Value` D-Bus interface after
529getting the response of `GetSensorReading` command successfully. If `pldmd`
530failed to get the response from PLDM terminus or the completion code returned by
531PLDM terminus is not `PLDM_SUCCESS`, the Functional property of
532`State.Decorator.OperationalStatus` D-Bus interface should be updated to false.
533
534#### Polling v.s. Async method
535
536For each terminus, `pldmd` maintains a list to poll the Terminus' sensors and
537exposes the status to D-Bus. `pldmd` has a polling timer with the configurable
538interval to update the PLDM sensors of the terminus periodically. The PLDM
539sensor in list has a `updateTime` which is initialized to the value of the
540defined `updateInterval` in sensor PDRs. Upon the polling timer timeout, the
541terminus' sensors will be read using `GetSensorReading` command. The read
542condition is the `elapsed time` from the `last read timestamp` to
543`current timestamp` is more than the sensor's `updateTime`. `pldmd` should have
544APIs to be paused and resumed by other task (e.g. pausing sensor polling during
545firmware updating to maximum bandwidth).
546
547To enable async event method for a sensor to update its status to `pldmd`,
548`pldmd` needs to implement the responder of `PlatformEventMessage` command
549described in 13.1 PLDM Event Message of
550[DSP0248 1.2.1](https://www.dmtf.org/sites/default/files/standards/documents/DSP0248_1.2.1.pdf).
551`pldmd` checks the response of `EventMessageSupported` command from PLDM
552terminus to identify if it can generate events. A PLDM sensor can work in event
553aync method if the `updateInterval` of all sensors in the same PLDM terminus are
554longer than final polling time. Before `pldmd` starts to receive async event
555from PLDM terminus, `pldmd` should remove the sensor from poll list and then
556send necessary commands (e.g., `EventMessageBufferSize` and `SetEventReceiver`)
557to PLDM terminus for the initialization.
558
559## Alternatives Considered
560
561Continue using IPMI, but start making more use of OEM extensions to suit the
562requirements of new platforms. However, given that the IPMI standard is no
563longer under active development, we would likely end up with a large amount of
564platform-specific customisations. This also does not solve the hardware channel
565issues in a standard manner. On OpenPOWER hardware at least, we've started to
566hit some of the limitations of IPMI (for example, we have need for >255
567sensors).
568
569## Impacts
570
571Development would be required to implement the PLDM protocol, the
572request/response model, and platform specific handling. Low level design is
573required to implement the protocol specifics of each of the PLDM Types. Such low
574level design is not included in this proposal.
575
576Design and development needs to involve the firmware stacks of management
577controllers and management devices of a platform management subsystem.
578
579## Testing
580
581Testing can be done without having to depend on the underlying transport layer.
582
583The responder function can be tested by mocking a requester and the transport
584layer: this would essentially test the protocol handling and platform specific
585handling. The requester function can be tested by mocking a responder: this
586would test the instance id handling and the send/receive functions.
587
588APIs from the shared libraries can be tested via fuzzing.
589
590The APIs to parse PDRs from PLDM terminus can be tested by a mocking responder.
591A sample JSON file is provided to test the APIs for mocking PDRs for static PLDM
592sensors.
593