xref: /openbmc/libmctp/core.c (revision ac1cd9dc)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 
3 #include <assert.h>
4 #include <errno.h>
5 #include <stdarg.h>
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #undef pr_fmt
13 #define pr_fmt(fmt) "core: " fmt
14 
15 #include "libmctp.h"
16 #include "libmctp-alloc.h"
17 #include "libmctp-log.h"
18 #include "libmctp-cmds.h"
19 #include "range.h"
20 
21 /* Internal data structures */
22 
23 enum mctp_bus_state {
24 	mctp_bus_state_constructed = 0,
25 	mctp_bus_state_tx_enabled,
26 	mctp_bus_state_tx_disabled,
27 };
28 
29 struct mctp_bus {
30 	mctp_eid_t eid;
31 	struct mctp_binding *binding;
32 	enum mctp_bus_state state;
33 
34 	struct mctp_pktbuf *tx_queue_head;
35 	struct mctp_pktbuf *tx_queue_tail;
36 
37 	/* todo: routing */
38 };
39 
40 struct mctp_msg_ctx {
41 	uint8_t		src;
42 	uint8_t		dest;
43 	uint8_t		tag;
44 	uint8_t		last_seq;
45 	void		*buf;
46 	size_t		buf_size;
47 	size_t		buf_alloc_size;
48 };
49 
50 struct mctp {
51 	int			n_busses;
52 	struct mctp_bus		*busses;
53 
54 	/* Message RX callback */
55 	mctp_rx_fn		message_rx;
56 	void			*message_rx_data;
57 
58 	/* Message reassembly.
59 	 * @todo: flexible context count
60 	 */
61 	struct mctp_msg_ctx	msg_ctxs[16];
62 
63 	enum {
64 		ROUTE_ENDPOINT,
65 		ROUTE_BRIDGE,
66 	}			route_policy;
67 	size_t max_message_size;
68 };
69 
70 #ifndef BUILD_ASSERT
71 #define BUILD_ASSERT(x) \
72 	do { (void)sizeof(char[0-(!(x))]); } while (0)
73 #endif
74 
75 #ifndef ARRAY_SIZE
76 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
77 #endif
78 
79 /* 64kb should be sufficient for a single message. Applications
80  * requiring higher sizes can override by setting max_message_size.*/
81 #ifndef MCTP_MAX_MESSAGE_SIZE
82 #define MCTP_MAX_MESSAGE_SIZE 65536
83 #endif
84 
85 static int mctp_message_tx_on_bus(struct mctp_bus *bus, mctp_eid_t src,
86 				  mctp_eid_t dest, void *msg, size_t msg_len);
87 
88 struct mctp_pktbuf *mctp_pktbuf_alloc(struct mctp_binding *binding, size_t len)
89 {
90 	struct mctp_pktbuf *buf;
91 	size_t size;
92 
93 	size = binding->pkt_size + binding->pkt_header + binding->pkt_trailer;
94 
95 	/* todo: pools */
96 	buf = __mctp_alloc(sizeof(*buf) + size);
97 
98 	buf->size = size;
99 	buf->start = binding->pkt_header;
100 	buf->end = buf->start + len;
101 	buf->mctp_hdr_off = buf->start;
102 	buf->next = NULL;
103 
104 	return buf;
105 }
106 
107 void mctp_pktbuf_free(struct mctp_pktbuf *pkt)
108 {
109 	__mctp_free(pkt);
110 }
111 
112 struct mctp_hdr *mctp_pktbuf_hdr(struct mctp_pktbuf *pkt)
113 {
114 	return (void *)pkt->data + pkt->mctp_hdr_off;
115 }
116 
117 void *mctp_pktbuf_data(struct mctp_pktbuf *pkt)
118 {
119 	return (void *)pkt->data + pkt->mctp_hdr_off + sizeof(struct mctp_hdr);
120 }
121 
122 size_t mctp_pktbuf_size(struct mctp_pktbuf *pkt)
123 {
124 	return pkt->end - pkt->start;
125 }
126 
127 void *mctp_pktbuf_alloc_start(struct mctp_pktbuf *pkt, size_t size)
128 {
129 	assert(size <= pkt->start);
130 	pkt->start -= size;
131 	return pkt->data + pkt->start;
132 }
133 
134 void *mctp_pktbuf_alloc_end(struct mctp_pktbuf *pkt, size_t size)
135 {
136 	void *buf;
137 
138 	assert(size <= (pkt->size - pkt->end));
139 	buf = pkt->data + pkt->end;
140 	pkt->end += size;
141 	return buf;
142 }
143 
144 int mctp_pktbuf_push(struct mctp_pktbuf *pkt, void *data, size_t len)
145 {
146 	void *p;
147 
148 	if (pkt->end + len > pkt->size)
149 		return -1;
150 
151 	p = pkt->data + pkt->end;
152 
153 	pkt->end += len;
154 	memcpy(p, data, len);
155 
156 	return 0;
157 }
158 
159 void *mctp_pktbuf_pop(struct mctp_pktbuf *pkt, size_t len)
160 {
161 	if (len > mctp_pktbuf_size(pkt))
162 		return NULL;
163 
164 	pkt->end -= len;
165 	return pkt->data + pkt->end;
166 }
167 
168 /* Message reassembly */
169 static struct mctp_msg_ctx *mctp_msg_ctx_lookup(struct mctp *mctp,
170 		uint8_t src, uint8_t dest, uint8_t tag)
171 {
172 	unsigned int i;
173 
174 	/* @todo: better lookup, if we add support for more outstanding
175 	 * message contexts */
176 	for (i = 0; i < ARRAY_SIZE(mctp->msg_ctxs); i++) {
177 		struct mctp_msg_ctx *ctx = &mctp->msg_ctxs[i];
178 		if (ctx->src == src && ctx->dest == dest && ctx->tag == tag)
179 			return ctx;
180 	}
181 
182 	return NULL;
183 }
184 
185 static struct mctp_msg_ctx *mctp_msg_ctx_create(struct mctp *mctp,
186 		uint8_t src, uint8_t dest, uint8_t tag)
187 {
188 	struct mctp_msg_ctx *ctx = NULL;
189 	unsigned int i;
190 
191 	for (i = 0; i < ARRAY_SIZE(mctp->msg_ctxs); i++) {
192 		struct mctp_msg_ctx *tmp = &mctp->msg_ctxs[i];
193 		if (!tmp->src) {
194 			ctx = tmp;
195 			break;
196 		}
197 	}
198 
199 	if (!ctx)
200 		return NULL;
201 
202 	ctx->src = src;
203 	ctx->dest = dest;
204 	ctx->tag = tag;
205 	ctx->buf_size = 0;
206 
207 	return ctx;
208 }
209 
210 static void mctp_msg_ctx_drop(struct mctp_msg_ctx *ctx)
211 {
212 	ctx->src = 0;
213 }
214 
215 static void mctp_msg_ctx_reset(struct mctp_msg_ctx *ctx)
216 {
217 	ctx->buf_size = 0;
218 }
219 
220 static int mctp_msg_ctx_add_pkt(struct mctp_msg_ctx *ctx,
221 		struct mctp_pktbuf *pkt, size_t max_size)
222 {
223 	size_t len;
224 
225 	len = mctp_pktbuf_size(pkt) - sizeof(struct mctp_hdr);
226 
227 	if (ctx->buf_size + len > ctx->buf_alloc_size) {
228 		size_t new_alloc_size;
229 		void *lbuf;
230 
231 		/* @todo: finer-grained allocation */
232 		if (!ctx->buf_alloc_size) {
233 			new_alloc_size = MAX(len, 4096UL);
234 		} else {
235 			new_alloc_size = ctx->buf_alloc_size * 2;
236 		}
237 
238 		/* Don't allow heap to grow beyond a limit */
239 		if (new_alloc_size > max_size)
240 			return -1;
241 
242 
243 		lbuf = __mctp_realloc(ctx->buf, new_alloc_size);
244 		if (lbuf) {
245 			ctx->buf = lbuf;
246 			ctx->buf_alloc_size = new_alloc_size;
247 		} else {
248 			__mctp_free(ctx->buf);
249 			return -1;
250 		}
251 	}
252 
253 	memcpy(ctx->buf + ctx->buf_size, mctp_pktbuf_data(pkt), len);
254 	ctx->buf_size += len;
255 
256 	return 0;
257 }
258 
259 /* Core API functions */
260 struct mctp *mctp_init(void)
261 {
262 	struct mctp *mctp;
263 
264 	mctp = __mctp_alloc(sizeof(*mctp));
265 
266 	if(!mctp)
267 		return NULL;
268 
269 	memset(mctp, 0, sizeof(*mctp));
270 	mctp->max_message_size = MCTP_MAX_MESSAGE_SIZE;
271 
272 	return mctp;
273 }
274 
275 void mctp_set_max_message_size(struct mctp *mctp, size_t message_size)
276 {
277 	mctp->max_message_size = message_size;
278 }
279 
280 static void mctp_bus_destroy(struct mctp_bus *bus)
281 {
282 	while (bus->tx_queue_head) {
283 		struct mctp_pktbuf *curr = bus->tx_queue_head;
284 
285 		bus->tx_queue_head = curr->next;
286 		mctp_pktbuf_free(curr);
287 	}
288 }
289 
290 void mctp_destroy(struct mctp *mctp)
291 {
292 	size_t i;
293 
294 	/* Cleanup message assembly contexts */
295 	BUILD_ASSERT(ARRAY_SIZE(mctp->msg_ctxs) < SIZE_MAX);
296 	for (i = 0; i < ARRAY_SIZE(mctp->msg_ctxs); i++) {
297 		struct mctp_msg_ctx *tmp = &mctp->msg_ctxs[i];
298 		if (tmp->buf)
299 			__mctp_free(tmp->buf);
300 	}
301 
302 	while (mctp->n_busses--)
303 		mctp_bus_destroy(&mctp->busses[mctp->n_busses]);
304 
305 	__mctp_free(mctp->busses);
306 	__mctp_free(mctp);
307 }
308 
309 int mctp_set_rx_all(struct mctp *mctp, mctp_rx_fn fn, void *data)
310 {
311 	mctp->message_rx = fn;
312 	mctp->message_rx_data = data;
313 	return 0;
314 }
315 
316 static struct mctp_bus *find_bus_for_eid(struct mctp *mctp,
317 		mctp_eid_t dest __attribute__((unused)))
318 {
319 	/* for now, just use the first bus. For full routing support,
320 	 * we will need a table of neighbours */
321 	return &mctp->busses[0];
322 }
323 
324 int mctp_register_bus(struct mctp *mctp,
325 		struct mctp_binding *binding,
326 		mctp_eid_t eid)
327 {
328 	int rc = 0;
329 
330 	/* todo: multiple busses */
331 	assert(mctp->n_busses == 0);
332 	mctp->n_busses = 1;
333 
334 	mctp->busses = __mctp_alloc(sizeof(struct mctp_bus));
335 	if (!mctp->busses)
336 		return -ENOMEM;
337 
338 	memset(mctp->busses, 0, sizeof(struct mctp_bus));
339 	mctp->busses[0].binding = binding;
340 	mctp->busses[0].eid = eid;
341 	binding->bus = &mctp->busses[0];
342 	binding->mctp = mctp;
343 	mctp->route_policy = ROUTE_ENDPOINT;
344 
345 	if (binding->start) {
346 		rc = binding->start(binding);
347 		if (rc < 0) {
348 			mctp_prerr("Failed to start binding: %d", rc);
349 			binding->bus = NULL;
350 			__mctp_free(mctp->busses);
351 			mctp->busses = NULL;
352 			mctp->n_busses = 0;
353 		}
354 	}
355 
356 	return rc;
357 }
358 
359 int mctp_bridge_busses(struct mctp *mctp,
360 		struct mctp_binding *b1, struct mctp_binding *b2)
361 {
362 	int rc = 0;
363 
364 	assert(mctp->n_busses == 0);
365 	mctp->busses = __mctp_alloc(2 * sizeof(struct mctp_bus));
366 	if (!mctp->busses)
367 		return -ENOMEM;
368 	memset(mctp->busses, 0, 2 * sizeof(struct mctp_bus));
369 	mctp->n_busses = 2;
370 	mctp->busses[0].binding = b1;
371 	b1->bus = &mctp->busses[0];
372 	b1->mctp = mctp;
373 	mctp->busses[1].binding = b2;
374 	b2->bus = &mctp->busses[1];
375 	b2->mctp = mctp;
376 
377 	mctp->route_policy = ROUTE_BRIDGE;
378 
379 	if (b1->start) {
380 		rc = b1->start(b1);
381 		if (rc < 0) {
382 			mctp_prerr("Failed to start bridged bus %s: %d",
383 				   b1->name, rc);
384 			goto done;
385 		}
386 	}
387 
388 	if (b2->start) {
389 		rc = b2->start(b2);
390 		if (rc < 0) {
391 			mctp_prerr("Failed to start bridged bus %s: %d",
392 				   b2->name, rc);
393 			goto done;
394 		}
395 	}
396 
397 done:
398 	return rc;
399 }
400 
401 static inline bool mctp_ctrl_cmd_is_transport(struct mctp_ctrl_msg_hdr *hdr)
402 {
403 	return ((hdr->command_code >= MCTP_CTRL_CMD_FIRST_TRANSPORT) &&
404 		(hdr->command_code <= MCTP_CTRL_CMD_LAST_TRANSPORT));
405 }
406 
407 static bool mctp_ctrl_handle_msg(struct mctp_bus *bus, mctp_eid_t src,
408 				 void *buffer, size_t length)
409 {
410 	struct mctp_ctrl_msg_hdr *msg_hdr = buffer;
411 
412 	/*
413 	 * Control message is received. If a transport control message handler
414 	 * is provided, it will called. If there is no dedicated handler, this
415 	 * function returns false and data can be handled by the generic
416 	 * message handler. The transport control message handler will be
417 	 * provided with messages in the command range 0xF0 - 0xFF.
418 	 */
419 	if (mctp_ctrl_cmd_is_transport(msg_hdr)) {
420 		if (bus->binding->control_rx != NULL) {
421 			/* MCTP bus binding handler */
422 			bus->binding->control_rx(src,
423 						 bus->binding->control_rx_data,
424 						 buffer, length);
425 			return true;
426 		}
427 	}
428 
429 	/*
430 	 * Command was not handled, due to lack of specific callback.
431 	 * It will be passed to regular message_rx handler.
432 	 */
433 	return false;
434 }
435 
436 static inline bool mctp_rx_dest_is_local(struct mctp_bus *bus, mctp_eid_t dest)
437 {
438 	return dest == bus->eid || dest == MCTP_EID_NULL ||
439 	       dest == MCTP_EID_BROADCAST;
440 }
441 
442 static inline bool mctp_ctrl_cmd_is_request(struct mctp_ctrl_msg_hdr *hdr)
443 {
444 	return hdr->ic_msg_type == MCTP_CTRL_HDR_MSG_TYPE &&
445 	       hdr->rq_dgram_inst & MCTP_CTRL_HDR_FLAG_REQUEST;
446 }
447 
448 /*
449  * Receive the complete MCTP message and route it.
450  * Asserts:
451  *     'buf' is not NULL.
452  */
453 static void mctp_rx(struct mctp *mctp, struct mctp_bus *bus, mctp_eid_t src,
454 		    mctp_eid_t dest, void *buf, size_t len)
455 {
456 	assert(buf != NULL);
457 
458 	if (mctp->route_policy == ROUTE_ENDPOINT &&
459 	    mctp_rx_dest_is_local(bus, dest)) {
460 		/* Handle MCTP Control Messages: */
461 		if (len >= sizeof(struct mctp_ctrl_msg_hdr)) {
462 			struct mctp_ctrl_msg_hdr *msg_hdr = buf;
463 
464 			/*
465 			 * Identify if this is a control request message.
466 			 * See DSP0236 v1.3.0 sec. 11.5.
467 			 */
468 			if (mctp_ctrl_cmd_is_request(msg_hdr)) {
469 				bool handled;
470 				handled = mctp_ctrl_handle_msg(bus, src, buf,
471 							       len);
472 				if (handled)
473 					return;
474 			}
475 		}
476 		if (mctp->message_rx)
477 			mctp->message_rx(src, mctp->message_rx_data, buf, len);
478 	}
479 
480 	if (mctp->route_policy == ROUTE_BRIDGE) {
481 		int i;
482 
483 		for (i = 0; i < mctp->n_busses; i++) {
484 			struct mctp_bus *dest_bus = &mctp->busses[i];
485 			if (dest_bus == bus)
486 				continue;
487 
488 			mctp_message_tx_on_bus(dest_bus, src, dest, buf, len);
489 		}
490 
491 	}
492 }
493 
494 void mctp_bus_rx(struct mctp_binding *binding, struct mctp_pktbuf *pkt)
495 {
496 	struct mctp_bus *bus = binding->bus;
497 	struct mctp *mctp = binding->mctp;
498 	uint8_t flags, exp_seq, seq, tag;
499 	struct mctp_msg_ctx *ctx;
500 	struct mctp_hdr *hdr;
501 	size_t len;
502 	void *p;
503 	int rc;
504 
505 	assert(bus);
506 
507 	/* Drop packet if it was smaller than mctp hdr size */
508 	if (mctp_pktbuf_size(pkt) <= sizeof(struct mctp_hdr))
509 		goto out;
510 
511 	hdr = mctp_pktbuf_hdr(pkt);
512 
513 	/* small optimisation: don't bother reassembly if we're going to
514 	 * drop the packet in mctp_rx anyway */
515 	if (mctp->route_policy == ROUTE_ENDPOINT && hdr->dest != bus->eid)
516 		goto out;
517 
518 	flags = hdr->flags_seq_tag & (MCTP_HDR_FLAG_SOM | MCTP_HDR_FLAG_EOM);
519 	tag = (hdr->flags_seq_tag >> MCTP_HDR_TAG_SHIFT) & MCTP_HDR_TAG_MASK;
520 	seq = (hdr->flags_seq_tag >> MCTP_HDR_SEQ_SHIFT) & MCTP_HDR_SEQ_MASK;
521 
522 	switch (flags) {
523 	case MCTP_HDR_FLAG_SOM | MCTP_HDR_FLAG_EOM:
524 		/* single-packet message - send straight up to rx function,
525 		 * no need to create a message context */
526 		len = pkt->end - pkt->mctp_hdr_off - sizeof(struct mctp_hdr);
527 		p = pkt->data + pkt->mctp_hdr_off + sizeof(struct mctp_hdr);
528 		mctp_rx(mctp, bus, hdr->src, hdr->dest, p, len);
529 		break;
530 
531 	case MCTP_HDR_FLAG_SOM:
532 		/* start of a new message - start the new context for
533 		 * future message reception. If an existing context is
534 		 * already present, drop it. */
535 		ctx = mctp_msg_ctx_lookup(mctp, hdr->src, hdr->dest, tag);
536 		if (ctx) {
537 			mctp_msg_ctx_reset(ctx);
538 		} else {
539 			ctx = mctp_msg_ctx_create(mctp,
540 					hdr->src, hdr->dest, tag);
541 		}
542 
543 		rc = mctp_msg_ctx_add_pkt(ctx, pkt, mctp->max_message_size);
544 		if (rc) {
545 			mctp_msg_ctx_drop(ctx);
546 		} else {
547 			ctx->last_seq = seq;
548 		}
549 
550 		break;
551 
552 	case MCTP_HDR_FLAG_EOM:
553 		ctx = mctp_msg_ctx_lookup(mctp, hdr->src, hdr->dest, tag);
554 		if (!ctx)
555 			goto out;
556 
557 		exp_seq = (ctx->last_seq + 1) % 4;
558 
559 		if (exp_seq != seq) {
560 			mctp_prdebug(
561 				"Sequence number %d does not match expected %d",
562 				seq, exp_seq);
563 			mctp_msg_ctx_drop(ctx);
564 			goto out;
565 		}
566 
567 		rc = mctp_msg_ctx_add_pkt(ctx, pkt, mctp->max_message_size);
568 		if (!rc)
569 			mctp_rx(mctp, bus, ctx->src, ctx->dest,
570 					ctx->buf, ctx->buf_size);
571 
572 		mctp_msg_ctx_drop(ctx);
573 		break;
574 
575 	case 0:
576 		/* Neither SOM nor EOM */
577 		ctx = mctp_msg_ctx_lookup(mctp, hdr->src,hdr->dest, tag);
578 		if (!ctx)
579 			goto out;
580 
581 		exp_seq = (ctx->last_seq + 1) % 4;
582 		if (exp_seq != seq) {
583 			mctp_prdebug(
584 				"Sequence number %d does not match expected %d",
585 				seq, exp_seq);
586 			mctp_msg_ctx_drop(ctx);
587 			goto out;
588 		}
589 
590 		rc = mctp_msg_ctx_add_pkt(ctx, pkt, mctp->max_message_size);
591 		if (rc) {
592 			mctp_msg_ctx_drop(ctx);
593 			goto out;
594 		}
595 		ctx->last_seq = seq;
596 
597 		break;
598 	}
599 out:
600 	mctp_pktbuf_free(pkt);
601 }
602 
603 static int mctp_packet_tx(struct mctp_bus *bus,
604 		struct mctp_pktbuf *pkt)
605 {
606 	if (bus->state != mctp_bus_state_tx_enabled)
607 		return -1;
608 
609 	return bus->binding->tx(bus->binding, pkt);
610 }
611 
612 static void mctp_send_tx_queue(struct mctp_bus *bus)
613 {
614 	struct mctp_pktbuf *pkt;
615 
616 	while ((pkt = bus->tx_queue_head)) {
617 		int rc;
618 
619 		rc = mctp_packet_tx(bus, pkt);
620 		if (rc)
621 			break;
622 
623 		bus->tx_queue_head = pkt->next;
624 		mctp_pktbuf_free(pkt);
625 	}
626 
627 	if (!bus->tx_queue_head)
628 		bus->tx_queue_tail = NULL;
629 
630 }
631 
632 void mctp_binding_set_tx_enabled(struct mctp_binding *binding, bool enable)
633 {
634 	struct mctp_bus *bus = binding->bus;
635 
636 	switch(bus->state) {
637 	case mctp_bus_state_constructed:
638 		if (!enable)
639 			return;
640 
641 		if (binding->pkt_size < MCTP_PACKET_SIZE(MCTP_BTU)) {
642 			mctp_prerr("Cannot start %s binding with invalid MTU: %zu",
643 				   binding->name,
644 				   MCTP_BODY_SIZE(binding->pkt_size));
645 			return;
646 		}
647 
648 		bus->state = mctp_bus_state_tx_enabled;
649 		mctp_prinfo("%s binding started", binding->name);
650 		return;
651 	case mctp_bus_state_tx_enabled:
652 		if (enable)
653 			return;
654 
655 		bus->state = mctp_bus_state_tx_disabled;
656 		mctp_prdebug("%s binding Tx disabled", binding->name);
657 		return;
658 	case mctp_bus_state_tx_disabled:
659 		if (!enable)
660 			return;
661 
662 		bus->state = mctp_bus_state_tx_enabled;
663 		mctp_prdebug("%s binding Tx enabled", binding->name);
664 		mctp_send_tx_queue(bus);
665 		return;
666 	}
667 }
668 
669 static int mctp_message_tx_on_bus(struct mctp_bus *bus, mctp_eid_t src,
670 				  mctp_eid_t dest, void *msg, size_t msg_len)
671 {
672 	size_t max_payload_len, payload_len, p;
673 	struct mctp_pktbuf *pkt;
674 	struct mctp_hdr *hdr;
675 	int i;
676 
677 	if (bus->state == mctp_bus_state_constructed)
678 		return -ENXIO;
679 
680 	max_payload_len = MCTP_BODY_SIZE(bus->binding->pkt_size);
681 
682 	{
683 		const bool valid_mtu = max_payload_len >= MCTP_BTU;
684 		assert(valid_mtu);
685 		if (!valid_mtu)
686 			return -EINVAL;
687 	}
688 
689 	mctp_prdebug("%s: Generating packets for transmission of %zu byte message from %hhu to %hhu",
690 		     __func__, msg_len, src, dest);
691 
692 	/* queue up packets, each of max MCTP_MTU size */
693 	for (p = 0, i = 0; p < msg_len; i++) {
694 		payload_len = msg_len - p;
695 		if (payload_len > max_payload_len)
696 			payload_len = max_payload_len;
697 
698 		pkt = mctp_pktbuf_alloc(bus->binding,
699 				payload_len + sizeof(*hdr));
700 		hdr = mctp_pktbuf_hdr(pkt);
701 
702 		/* todo: tags */
703 		hdr->ver = bus->binding->version & 0xf;
704 		hdr->dest = dest;
705 		hdr->src = src;
706 		hdr->flags_seq_tag = MCTP_HDR_FLAG_TO |
707 			(0 << MCTP_HDR_TAG_SHIFT);
708 
709 		if (i == 0)
710 			hdr->flags_seq_tag |= MCTP_HDR_FLAG_SOM;
711 		if (p + payload_len >= msg_len)
712 			hdr->flags_seq_tag |= MCTP_HDR_FLAG_EOM;
713 		hdr->flags_seq_tag |=
714 			(i & MCTP_HDR_SEQ_MASK) << MCTP_HDR_SEQ_SHIFT;
715 
716 		memcpy(mctp_pktbuf_data(pkt), msg + p, payload_len);
717 
718 		/* add to tx queue */
719 		if (bus->tx_queue_tail)
720 			bus->tx_queue_tail->next = pkt;
721 		else
722 			bus->tx_queue_head = pkt;
723 		bus->tx_queue_tail = pkt;
724 
725 		p += payload_len;
726 	}
727 
728 	mctp_prdebug("%s: Enqueued %d packets", __func__, i);
729 
730 	mctp_send_tx_queue(bus);
731 
732 	return 0;
733 }
734 
735 int mctp_message_tx(struct mctp *mctp, mctp_eid_t eid,
736 		void *msg, size_t msg_len)
737 {
738 	struct mctp_bus *bus;
739 
740 	bus = find_bus_for_eid(mctp, eid);
741 	return mctp_message_tx_on_bus(bus, bus->eid, eid, msg, msg_len);
742 }
743