xref: /openbmc/libmctp/tests/test_serial.c (revision a721c2d8)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 
3 #define _GNU_SOURCE
4 
5 #if HAVE_CONFIG_H
6 #include "config.h"
7 #endif
8 
9 #include "compiler.h"
10 #include "libmctp-log.h"
11 #include "libmctp-serial.h"
12 
13 #ifdef NDEBUG
14 #undef NDEBUG
15 #endif
16 
17 #include <assert.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24 
25 struct mctp_binding_serial_pipe {
26 	int ingress;
27 	int egress;
28 
29 	struct mctp_binding_serial *serial;
30 };
31 
32 static int mctp_binding_serial_pipe_tx(void *data, void *buf, size_t len)
33 {
34 	struct mctp_binding_serial_pipe *ctx = data;
35 	ssize_t rc;
36 
37 	rc = write(ctx->egress, buf, len);
38 	assert(rc >= 0);
39 	assert((size_t)rc == len);
40 
41 	return rc;
42 }
43 
44 uint8_t mctp_msg_src[2 * MCTP_BTU];
45 
46 static bool seen;
47 static bool received_tag_owner;
48 static uint8_t received_msg_tag;
49 
50 static void rx_message(uint8_t eid __unused, bool tag_owner, uint8_t msg_tag,
51 		       void *data __unused, void *msg, size_t len)
52 {
53 	uint8_t type;
54 
55 	type = *(uint8_t *)msg;
56 
57 	mctp_prdebug("MCTP message received: len %zd, type %d, tag %d", len,
58 		     type, msg_tag);
59 
60 	assert(sizeof(mctp_msg_src) == len);
61 	assert(!memcmp(mctp_msg_src, msg, len));
62 
63 	seen = true;
64 	received_msg_tag = msg_tag;
65 	received_tag_owner = tag_owner;
66 }
67 
68 struct serial_test {
69 	struct mctp_binding_serial_pipe binding;
70 	struct mctp *mctp;
71 };
72 
73 int main(void)
74 {
75 	struct serial_test scenario[2];
76 
77 	struct mctp_binding_serial_pipe *a;
78 	struct mctp_binding_serial_pipe *b;
79 	uint8_t msg_tag = 2;
80 	bool tag_owner = false;
81 	int p[2][2];
82 	int rc;
83 
84 	mctp_set_log_stdio(MCTP_LOG_DEBUG);
85 
86 	memset(&mctp_msg_src[0], 0x5a, MCTP_BTU);
87 	memset(&mctp_msg_src[MCTP_BTU], 0xa5, MCTP_BTU);
88 
89 	rc = pipe(p[0]);
90 	assert(!rc);
91 
92 	rc = pipe(p[1]);
93 	assert(!rc);
94 
95 	/* Instantiate the A side of the serial pipe */
96 	scenario[0].mctp = mctp_init();
97 	assert(scenario[0].mctp);
98 	scenario[0].binding.serial = mctp_serial_init();
99 	assert(scenario[0].binding.serial);
100 	a = &scenario[0].binding;
101 	a->ingress = p[0][0];
102 	a->egress = p[1][1];
103 	mctp_serial_open_fd(a->serial, a->ingress);
104 	mctp_serial_set_tx_fn(a->serial, mctp_binding_serial_pipe_tx, a);
105 	mctp_register_bus(scenario[0].mctp, mctp_binding_serial_core(a->serial),
106 			  8);
107 
108 	/* Instantiate the B side of the serial pipe */
109 	scenario[1].mctp = mctp_init();
110 	assert(scenario[1].mctp);
111 	mctp_set_rx_all(scenario[1].mctp, rx_message, NULL);
112 	scenario[1].binding.serial = mctp_serial_init();
113 	assert(scenario[1].binding.serial);
114 	b = &scenario[1].binding;
115 	b->ingress = p[1][0];
116 	b->egress = p[0][1];
117 	mctp_serial_open_fd(b->serial, b->ingress);
118 	mctp_serial_set_tx_fn(b->serial, mctp_binding_serial_pipe_tx, a);
119 	mctp_register_bus(scenario[1].mctp, mctp_binding_serial_core(b->serial),
120 			  9);
121 
122 	/* Transmit a message from A to B, with message tag */
123 	rc = mctp_message_tx(scenario[0].mctp, 9, tag_owner, msg_tag,
124 			     mctp_msg_src, sizeof(mctp_msg_src));
125 	assert(rc == 0);
126 
127 	/* Read the message at B from A */
128 	seen = false;
129 	received_tag_owner = true;
130 	received_msg_tag = 0;
131 	mctp_serial_read(b->serial);
132 	assert(seen);
133 	assert(received_tag_owner == tag_owner);
134 	assert(received_msg_tag == msg_tag);
135 
136 	mctp_serial_destroy(scenario[1].binding.serial);
137 	mctp_destroy(scenario[1].mctp);
138 	mctp_serial_destroy(scenario[0].binding.serial);
139 	mctp_destroy(scenario[0].mctp);
140 
141 	return 0;
142 }
143