1# OpenBMC platform communication channel: MCTP & PLDM in userspace 2 3Author: Jeremy Kerr <jk@ozlabs.org> <jk> 4 5Please refer to the [mctp.md](MCTP Overview) document for general 6MCTP design description, background and requirements. 7 8This document describes a userspace implementation of MCTP 9infrastructure, allowing a straightforward mechanism of supporting MCTP 10messaging within an OpenBMC system. 11 12## Proposed Design 13 14The MCTP core specification just provides the packetisation, routing and 15addressing mechanisms. The actual transmit/receive of those packets is 16up to the hardware binding of the MCTP transport. 17 18For OpenBMC, we would introduce a MCTP daemon, which implements the transport 19over a configurable hardware channel (eg., Serial UART, I2C or PCIe), and 20provides a socket-based interface for other processes to send and 21receive complete MCTP messages. This daemon is responsible for the 22packetisation and routing of MCTP messages from external endpoints, and 23handling the forwarding these messages to and from individual handler 24applications. This includes handling local MCTP-stack configuration, 25like local EID assignments. 26 27This daemon has a few components: 28 29 1) the core MCTP stack 30 31 2) one or more binding implementations (eg, MCTP-over-serial), which 32 interact with the hardware channel(s). 33 34 3) an interface to handler applications over a unix-domain socket. 35 36The proposed implementation here is to produce an MCTP "library" which 37provides the packetisation and routing functions, between: 38 39 - an "upper" messaging transmit/receive interface, for tx/rx of a full 40 message to a specific endpoint (ie, (1) above) 41 42 - a "lower" hardware binding for transmit/receive of individual 43 packets, providing a method for the core to tx/rx each packet to 44 hardware, and defines the parameters of the common packetisation 45 code (ie. (2) above). 46 47The lower interface would be plugged in to one of a number of 48hardware-specific binding implementations. Most of these would be 49included in the library source tree, but others can be plugged-in too, 50perhaps where the physical layer implementation does not make sense to 51include in the platform-agnostic library. 52 53The reason for a library is to allow the same MCTP implementation to be 54used in both OpenBMC and host firmware; the library should be 55bidirectional. To allow this, the library would be written in portable C 56(structured in a way that can be compiled as "extern C" in C++ 57codebases), and be able to be configured to suit those runtime 58environments (for example, POSIX IO may not be available on all 59platforms; we should be able to compile the library to suit). The 60licence for the library should also allow this re-use; a dual Apache & 61GPLv2+ licence may be best. 62 63These "lower" binding implementations may have very different methods of 64transferring packets to the physical layer. For example, a serial 65binding implementation for running on a Linux environment may be 66implemented through read()/write() syscalls to a PTY device. An I2C 67binding for use in low-level host firmware environments may interact 68directly with hardware registers to perform packet transfers. 69 70The application-specific handlers implement the actual functionality 71provided over the MCTP channel, and connect to the central daemon over a 72UNIX domain socket. Each of these would register with the MCTP daemon to 73receive MCTP messages of a certain type, and would transmit MCTP 74messages of that same type. 75 76The daemon's sockets to these handlers is configured for non-blocking 77IO, to allow the daemon to be decoupled from any blocking behaviour of 78handlers. The daemon would use a message queue to enable message 79reception/transmission to a blocked daemon, but this would be of a 80limited size. Handlers whose sockets exceed this queue would be 81disconnected from the daemon. 82 83One design intention of the multiplexer daemon is to allow a future 84kernel-based MCTP implementation without requiring major structural 85changes to handler applications. The socket-based interface facilitates 86this, as the unix-domain socket interface could be fairly easily swapped 87out with a new kernel-based socket type. 88 89MCTP is intended to be an optional component of OpenBMC. Platforms using 90OpenBMC are free to adopt it as they see fit. 91 92### Demultiplexer daemon interface 93 94MCTP handlers (ie, clients of the demultiplexer) connect using a 95unix-domain socket, at the abstract socket address: 96 97 \0mctp-demux 98 99The socket type used should be `SOCK_SEQPACKET`. 100 101Once connected, the client sends a single byte message, indicating what 102type of MCTP messages should be forwarded to the client. Types must be 103greater than zero. 104 105Subsequent messages sent over the socket are MCTP messages sent/received 106by the demultiplexer, that match the specified MCTP message type. 107Clients should use the send/recv syscalls to interact with the socket. 108 109Each message has a fixed small header: 110 111 `uint8_t eid` 112 113For messages coming from the demux daemon, this indicates the source EID 114of the outgoing MCTP message. For messages going to the demux daemon, 115this indicates the destination EID. 116 117The rest of the message data is the complete MCTP message, including 118MCTP message type field. 119 120The daemon does not provide a facility for clients to specify or 121retrieve values for the tag field in individual MCTP packets. 122 123 124## Alternatives Considered 125 126In terms of an MCTP daemon structure, an alternative is to have the 127MCTP implementation contained within a single process, using the libmctp 128API directly for passing messages from the core code to 129application-level handlers. The drawback of this approach is that this 130single process needs to implement all possible functionality that is 131available over MCTP, which may be quite a disjoint set. This would 132likely lead to unnecessary restrictions on the implementation of those 133application-level handlers (programming language, frameworks used, etc). 134Also, this single-process approach would likely need more significant 135modifications if/when MCTP protocol support is moved to the kernel. 136 137The interface between the demultiplexer daemon and clients is currently 138defined as a socket-based interface. However, an alternative here would 139be to pass MCTP messages over dbus instead. The reason for the choice of 140sockets rather than dbus is that the former allows a direct transition 141to a kernel-based socket API when suitable. 142 143## Testing 144 145For the core MCTP library, we are able to run tests there in complete 146isolation (I have already been able to run a prototype MCTP stack 147through the afl fuzzer) to ensure that the core transport protocol 148works. 149 150For MCTP hardware bindings, we would develop channel-specific tests that 151would be run in CI on both host and BMC. 152 153For the OpenBMC MCTP daemon implementation, testing models would depend 154on the structure we adopt in the design section. 155