xref: /openbmc/docs/designs/mctp/mctp-userspace.md (revision b38b0a4c)
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