xref: /openbmc/libmctp/libmctp.h (revision 4a09e1dc48831f20e15b5fe76bf3011eaf587dd9)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 
3 #ifndef _LIBMCTP_H
4 #define _LIBMCTP_H
5 
6 #ifdef __cplusplus
7 extern "C" {
8 #endif
9 
10 #include <stdarg.h>
11 #include <stdbool.h>
12 #include <stdint.h>
13 #include <stddef.h>
14 
15 typedef uint8_t mctp_eid_t;
16 
17 /* Special Endpoint ID values */
18 #define MCTP_EID_NULL	   0
19 #define MCTP_EID_BROADCAST 0xff
20 
21 /* MCTP packet definitions */
22 struct mctp_hdr {
23 	uint8_t ver;
24 	uint8_t dest;
25 	uint8_t src;
26 	uint8_t flags_seq_tag;
27 };
28 
29 /* Definitions for flags_seq_tag field */
30 #define MCTP_HDR_FLAG_SOM  (1 << 7)
31 #define MCTP_HDR_FLAG_EOM  (1 << 6)
32 #define MCTP_HDR_FLAG_TO   (1 << 3)
33 #define MCTP_HDR_TO_SHIFT  (3)
34 #define MCTP_HDR_TO_MASK   (1)
35 #define MCTP_HDR_SEQ_SHIFT (4)
36 #define MCTP_HDR_SEQ_MASK  (0x3)
37 #define MCTP_HDR_TAG_SHIFT (0)
38 #define MCTP_HDR_TAG_MASK  (0x7)
39 
40 #define MCTP_MESSAGE_TO_SRC	      true
41 #define MCTP_MESSAGE_TO_DST	      false
42 #define MCTP_MESSAGE_CAPTURE_OUTGOING true
43 #define MCTP_MESSAGE_CAPTURE_INCOMING false
44 
45 /* Baseline Transmission Unit and packet size */
46 #define MCTP_BTU	       64
47 #define MCTP_PACKET_SIZE(unit) ((unit) + sizeof(struct mctp_hdr))
48 #define MCTP_BODY_SIZE(unit)   ((unit) - sizeof(struct mctp_hdr))
49 
50 /* packet buffers */
51 
52 struct mctp_pktbuf {
53 	size_t start, end, size;
54 	size_t mctp_hdr_off;
55 	bool alloc;
56 	unsigned char data[];
57 };
58 
59 #define MCTP_PKTBUF_SIZE(payload)                                              \
60 	(MCTP_PACKET_SIZE(payload) + sizeof(struct mctp_pktbuf))
61 
62 struct mctp;
63 struct mctp_bus;
64 struct mctp_binding;
65 
66 /* Initialise a mctp_pktbuf in static storage. Should not be freed.
67  * Storage must be sized to fit the binding,
68  * MCTP_PKTBUF_SIZE(binding->pkt_size + binding->pkt_header + binding->pkt_trailer) */
69 struct mctp_pktbuf *mctp_pktbuf_init(struct mctp_binding *binding,
70 				     void *storage);
71 /* Allocate and initialise a mctp_pktbuf. Should be freed with
72  * mctp_pktbuf_free */
73 struct mctp_pktbuf *mctp_pktbuf_alloc(struct mctp_binding *binding, size_t len);
74 void mctp_pktbuf_free(struct mctp_pktbuf *pkt);
75 struct mctp_hdr *mctp_pktbuf_hdr(struct mctp_pktbuf *pkt);
76 void *mctp_pktbuf_data(struct mctp_pktbuf *pkt);
77 size_t mctp_pktbuf_size(const struct mctp_pktbuf *pkt);
78 void *mctp_pktbuf_alloc_start(struct mctp_pktbuf *pkt, size_t size);
79 void *mctp_pktbuf_alloc_end(struct mctp_pktbuf *pkt, size_t size);
80 int mctp_pktbuf_push(struct mctp_pktbuf *pkt, const void *data, size_t len);
81 void *mctp_pktbuf_pop(struct mctp_pktbuf *pkt, size_t len);
82 
83 /* MCTP core */
84 
85 struct mctp *mctp_init(void);
86 void mctp_set_max_message_size(struct mctp *mctp, size_t message_size);
87 typedef void (*mctp_capture_fn)(struct mctp_pktbuf *pkt, bool outgoing,
88 				void *user);
89 void mctp_set_capture_handler(struct mctp *mctp, mctp_capture_fn fn,
90 			      void *user);
91 void mctp_destroy(struct mctp *mctp);
92 
93 /* Register a binding to the MCTP core, and creates a bus (populating
94  * binding->bus).
95  *
96  * If this function is called, the MCTP stack is initialised as an 'endpoint',
97  * and will deliver local packets to a RX callback - see `mctp_set_rx_all()`
98  * below.
99  */
100 int mctp_register_bus(struct mctp *mctp, struct mctp_binding *binding,
101 		      mctp_eid_t eid);
102 
103 void mctp_unregister_bus(struct mctp *mctp, struct mctp_binding *binding);
104 
105 /* Create a simple bidirectional bridge between busses.
106  *
107  * In this mode, the MCTP stack is initialised as a bridge. There is no EID
108  * defined, so no packets are considered local. Instead, all messages from one
109  * binding are forwarded to the other.
110  */
111 int mctp_bridge_busses(struct mctp *mctp, struct mctp_binding *b1,
112 		       struct mctp_binding *b2);
113 
114 typedef void (*mctp_rx_fn)(uint8_t src_eid, bool tag_owner, uint8_t msg_tag,
115 			   void *data, void *msg, size_t len);
116 
117 int mctp_set_rx_all(struct mctp *mctp, mctp_rx_fn fn, void *data);
118 
119 /* Transmit a message.
120  * @msg: The message buffer to send. Must be suitable for
121  * free(), or the custom mctp_set_alloc_ops() m_msg_free.
122  * The mctp stack will take ownership of the buffer
123  * and release it when message transmission is complete or fails.
124  *
125  * If an asynchronous binding is being used, it will return -EBUSY if
126  * a message is already pending for transmission (msg will be freed as usual).
127  * Asynchronous users can test mctp_is_tx_ready() prior to sending.
128  */
129 int mctp_message_tx_alloced(struct mctp *mctp, mctp_eid_t eid, bool tag_owner,
130 			    uint8_t msg_tag, void *msg, size_t msg_len);
131 
132 /* Transmit a message.
133  * @msg: The message buffer to send. Ownership of this buffer
134  * remains with the caller (a copy is made internally with __mctp_msg_alloc).
135  *
136  * If an asynchronous binding is being used, it will return -EBUSY if
137  * a message is already pending for transmission.
138  * Asynchronous users can test mctp_is_tx_ready() prior to sending.
139  *
140  * This is equivalent to duplicating `msg` then calling mctp_message_tx_alloc().
141  */
142 int mctp_message_tx(struct mctp *mctp, mctp_eid_t eid, bool tag_owner,
143 		    uint8_t msg_tag, const void *msg, size_t msg_len);
144 
145 bool mctp_is_tx_ready(struct mctp *mctp, mctp_eid_t eid);
146 
147 /* hardware bindings */
148 
149 /**
150  * @tx: Binding function to transmit one packet on the interface
151  * @tx_storage: A buffer for transmitting packets. Must be sized
152  * as MCTP_PKTBUF_SIZE(mtu).
153  *      Return:
154  *      * 0 - Success, pktbuf can be released
155  *	* -EMSGSIZE - Packet exceeds binding MTU, pktbuf must be dropped
156  *	* -EBUSY - Packet unable to be transmitted, pktbuf must be retained
157  */
158 struct mctp_binding {
159 	const char *name;
160 	uint8_t version;
161 	struct mctp_bus *bus;
162 	struct mctp *mctp;
163 	size_t pkt_size;
164 	size_t pkt_header;
165 	size_t pkt_trailer;
166 	void *tx_storage;
167 	int (*start)(struct mctp_binding *binding);
168 	int (*tx)(struct mctp_binding *binding, struct mctp_pktbuf *pkt);
169 	mctp_rx_fn control_rx;
170 	void *control_rx_data;
171 };
172 
173 void mctp_binding_set_tx_enabled(struct mctp_binding *binding, bool enable);
174 
175 /*
176  * Receive a packet from binding to core. Takes ownership of pkt, free()-ing it
177  * after use.
178  */
179 void mctp_bus_rx(struct mctp_binding *binding, struct mctp_pktbuf *pkt);
180 
181 /* environment-specific allocation */
182 void mctp_set_alloc_ops(void *(*m_alloc)(size_t), void (*m_free)(void *),
183 			void *(*m_msg_alloc)(size_t, void *),
184 			void (*m_msg_free)(void *, void *));
185 /* Gets/sets context that will be passed to custom m_msg_ ops */
186 void *mctp_get_alloc_ctx(struct mctp *mctp);
187 void mctp_set_alloc_ctx(struct mctp *mctp, void *ctx);
188 
189 /* environment-specific logging */
190 
191 void mctp_set_log_stdio(int level);
192 void mctp_set_log_syslog(void);
193 void mctp_set_log_custom(void (*fn)(int, const char *, va_list));
194 
195 /* these should match the syslog-standard LOG_* definitions, for
196  * easier use with syslog */
197 #define MCTP_LOG_ERR	 3
198 #define MCTP_LOG_WARNING 4
199 #define MCTP_LOG_NOTICE	 5
200 #define MCTP_LOG_INFO	 6
201 #define MCTP_LOG_DEBUG	 7
202 
203 #ifdef __cplusplus
204 }
205 #endif
206 
207 #endif /* _LIBMCTP_H */
208