xref: /openbmc/libmctp/tests/test_i2c.c (revision a3830d259a53269f7b9c8b46129e863ebed1b188)
1e5b941d9SMatt Johnston /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2e5b941d9SMatt Johnston 
3e5b941d9SMatt Johnston #if HAVE_CONFIG_H
4e5b941d9SMatt Johnston #include "config.h"
5e5b941d9SMatt Johnston #endif
6e5b941d9SMatt Johnston 
7e5b941d9SMatt Johnston #include "compiler.h"
8e5b941d9SMatt Johnston #include "range.h"
9e5b941d9SMatt Johnston #include "libmctp-log.h"
10e5b941d9SMatt Johnston #include "libmctp-i2c.h"
11e5b941d9SMatt Johnston #include "libmctp-sizes.h"
12e5b941d9SMatt Johnston #include "libmctp-alloc.h"
13e5b941d9SMatt Johnston 
14e5b941d9SMatt Johnston /* For access to mctp_bninding_i2c internals */
15e5b941d9SMatt Johnston #include "i2c-internal.h"
16e5b941d9SMatt Johnston 
17e5b941d9SMatt Johnston #ifdef NDEBUG
18e5b941d9SMatt Johnston #undef NDEBUG
19e5b941d9SMatt Johnston #endif
20e5b941d9SMatt Johnston 
21e5b941d9SMatt Johnston #include <assert.h>
22e5b941d9SMatt Johnston #include <errno.h>
23e5b941d9SMatt Johnston #include <fcntl.h>
24e5b941d9SMatt Johnston #include <stdbool.h>
25e5b941d9SMatt Johnston #include <stdio.h>
26e5b941d9SMatt Johnston #include <string.h>
27e5b941d9SMatt Johnston #include <unistd.h>
28e5b941d9SMatt Johnston #include <stdlib.h>
29e5b941d9SMatt Johnston 
30e5b941d9SMatt Johnston struct mctp_binding_serial_pipe {
31e5b941d9SMatt Johnston 	int ingress;
32e5b941d9SMatt Johnston 	int egress;
33e5b941d9SMatt Johnston 
34e5b941d9SMatt Johnston 	struct mctp_binding_serial *serial;
35e5b941d9SMatt Johnston };
36e5b941d9SMatt Johnston 
37e5b941d9SMatt Johnston // Sized to test fragmentation and >8 bit length
38e5b941d9SMatt Johnston #define TEST_MSG_LEN 300
39e5b941d9SMatt Johnston static uint8_t mctp_msg_src[TEST_MSG_LEN];
40e5b941d9SMatt Johnston 
41e5b941d9SMatt Johnston struct i2c_test {
42e5b941d9SMatt Johnston 	struct mctp_binding_i2c *i2c;
43e5b941d9SMatt Johnston 	struct mctp *mctp;
44e5b941d9SMatt Johnston 
45e5b941d9SMatt Johnston 	uint8_t rx_msg[TEST_MSG_LEN];
46e5b941d9SMatt Johnston 	size_t rx_len;
47e5b941d9SMatt Johnston 
48e5b941d9SMatt Johnston 	/* Physical addresses. These get set regardless of whether the packet
49e5b941d9SMatt Johnston 	 * is dropped by the stack (no match etc) */
50e5b941d9SMatt Johnston 	uint8_t last_rx_i2c_src;
51e5b941d9SMatt Johnston 	uint8_t last_tx_i2c_dst;
52e5b941d9SMatt Johnston };
53e5b941d9SMatt Johnston 
54e5b941d9SMatt Johnston static const uint8_t I2C_ADDR_A = 0x20;
55e5b941d9SMatt Johnston static const uint8_t I2C_ADDR_B = 0x21;
56e5b941d9SMatt Johnston static const uint8_t EID_A = 50;
57e5b941d9SMatt Johnston static const uint8_t EID_B = 51;
58e5b941d9SMatt Johnston 
test_i2c_tx(const void * buf,size_t len,void * ctx)59e5b941d9SMatt Johnston static int test_i2c_tx(const void *buf, size_t len, void *ctx)
60e5b941d9SMatt Johnston {
61e5b941d9SMatt Johnston 	struct i2c_test *test_pair = ctx;
62e5b941d9SMatt Johnston 	struct i2c_test *tx_test = &test_pair[0];
63e5b941d9SMatt Johnston 	struct i2c_test *rx_test = &test_pair[1];
64e5b941d9SMatt Johnston 
65e5b941d9SMatt Johnston 	mctp_prdebug("test_i2c_tx len %zu", len);
66e5b941d9SMatt Johnston 
67e5b941d9SMatt Johnston 	const struct mctp_i2c_hdr *hdr = buf;
68e5b941d9SMatt Johnston 	tx_test->last_tx_i2c_dst = hdr->dest >> 1;
69e5b941d9SMatt Johnston 	rx_test->last_rx_i2c_src = hdr->source >> 1;
70e5b941d9SMatt Johnston 
71e5b941d9SMatt Johnston 	mctp_i2c_rx(rx_test->i2c, buf, len);
72e5b941d9SMatt Johnston 	return 0;
73e5b941d9SMatt Johnston }
74e5b941d9SMatt Johnston 
test_i2c_rxmsg(uint8_t src_eid,bool tag_owner,uint8_t msg_tag,void * ctx,void * msg,size_t len)75e5b941d9SMatt Johnston static void test_i2c_rxmsg(uint8_t src_eid, bool tag_owner, uint8_t msg_tag,
76e5b941d9SMatt Johnston 			   void *ctx, void *msg, size_t len)
77e5b941d9SMatt Johnston {
78e5b941d9SMatt Johnston 	struct i2c_test *test_pair = ctx;
79e5b941d9SMatt Johnston 	// struct i2c_test *tx_test = &test_pair[0];
80e5b941d9SMatt Johnston 	struct i2c_test *rx_test = &test_pair[1];
81e5b941d9SMatt Johnston 
82e5b941d9SMatt Johnston 	mctp_prdebug("test_i2c_rx src %d len %zu tag %d owner %d", src_eid, len,
83e5b941d9SMatt Johnston 		     msg_tag, tag_owner);
84e5b941d9SMatt Johnston 
85e5b941d9SMatt Johnston 	// Must be cleared by previous test runs
86e5b941d9SMatt Johnston 	assert(rx_test->rx_len == 0);
87e5b941d9SMatt Johnston 	memcpy(rx_test->rx_msg, msg, len);
88e5b941d9SMatt Johnston 	rx_test->rx_len = len;
89e5b941d9SMatt Johnston }
90e5b941d9SMatt Johnston 
91e5b941d9SMatt Johnston /* Transmits a MCTP message and checks the received message matches */
run_tx_test(struct i2c_test * tx_test,uint8_t dest_eid,size_t tx_len,struct i2c_test * rx_test)92e5b941d9SMatt Johnston static void run_tx_test(struct i2c_test *tx_test, uint8_t dest_eid,
93e5b941d9SMatt Johnston 			size_t tx_len, struct i2c_test *rx_test)
94e5b941d9SMatt Johnston {
95e5b941d9SMatt Johnston 	int rc;
96e5b941d9SMatt Johnston 	const uint8_t msg_tag = 2;
97e5b941d9SMatt Johnston 	const bool tag_owner = false;
98e5b941d9SMatt Johnston 
99e5b941d9SMatt Johnston 	assert(tx_len <= sizeof(mctp_msg_src));
100e5b941d9SMatt Johnston 	rc = mctp_message_tx(tx_test->mctp, dest_eid, tag_owner, msg_tag,
101e5b941d9SMatt Johnston 			     mctp_msg_src, tx_len);
102e5b941d9SMatt Johnston 	assert(rc == 0);
103e5b941d9SMatt Johnston 
104e5b941d9SMatt Johnston 	while (!mctp_is_tx_ready(tx_test->mctp, dest_eid)) {
105e5b941d9SMatt Johnston 		mctp_i2c_tx_poll(tx_test->i2c);
106e5b941d9SMatt Johnston 	}
107e5b941d9SMatt Johnston 
108e5b941d9SMatt Johnston 	assert(rx_test->rx_len == tx_len);
109e5b941d9SMatt Johnston 	assert(memcmp(rx_test->rx_msg, mctp_msg_src, tx_len) == 0);
110e5b941d9SMatt Johnston 
111e5b941d9SMatt Johnston 	rx_test->rx_len = 0;
112e5b941d9SMatt Johnston }
113e5b941d9SMatt Johnston 
test_neigh_expiry(struct i2c_test * tx_test,struct i2c_test * rx_test)114e5b941d9SMatt Johnston static void test_neigh_expiry(struct i2c_test *tx_test,
115e5b941d9SMatt Johnston 			      struct i2c_test *rx_test)
116e5b941d9SMatt Johnston {
117e5b941d9SMatt Johnston 	const uint8_t msg_tag = 2;
118e5b941d9SMatt Johnston 	const bool tag_owner = true;
119e5b941d9SMatt Johnston 	const size_t msg_len = 5;
120e5b941d9SMatt Johnston 	int rc;
121e5b941d9SMatt Johnston 
122e5b941d9SMatt Johnston 	(void)rx_test;
123e5b941d9SMatt Johnston 
124e5b941d9SMatt Johnston 	/* Clear the tx neighbour table */
125e5b941d9SMatt Johnston 	memset(tx_test->i2c->neigh, 0x0, sizeof(tx_test->i2c->neigh));
126e5b941d9SMatt Johnston 
127e5b941d9SMatt Johnston 	/* Check that all EIDs fail */
128e5b941d9SMatt Johnston 	rx_test->rx_len = 0;
129e5b941d9SMatt Johnston 	for (size_t eid = 8; eid < 254; eid++) {
130e5b941d9SMatt Johnston 		mctp_message_tx(tx_test->mctp, eid, tag_owner, msg_tag,
131e5b941d9SMatt Johnston 				mctp_msg_src, msg_len);
132e5b941d9SMatt Johnston 		/* Not received */
133e5b941d9SMatt Johnston 		assert(rx_test->rx_len == 0);
134e5b941d9SMatt Johnston 	}
135e5b941d9SMatt Johnston 
136e5b941d9SMatt Johnston 	/* Add one entry */
137e5b941d9SMatt Johnston 	rc = mctp_i2c_set_neighbour(tx_test->i2c, EID_B,
138e5b941d9SMatt Johnston 				    rx_test->i2c->own_addr);
139e5b941d9SMatt Johnston 	assert(rc == 0);
140e5b941d9SMatt Johnston 	rx_test->rx_len = 0;
141e5b941d9SMatt Johnston 	mctp_message_tx(tx_test->mctp, EID_B, tag_owner, msg_tag, mctp_msg_src,
142e5b941d9SMatt Johnston 			msg_len);
143e5b941d9SMatt Johnston 	assert(rx_test->rx_len == msg_len);
144e5b941d9SMatt Johnston 	assert(tx_test->last_tx_i2c_dst == rx_test->i2c->own_addr);
145e5b941d9SMatt Johnston 
146e5b941d9SMatt Johnston 	/* Replace the entry */
147e5b941d9SMatt Johnston 	rx_test->i2c->own_addr++;
148e5b941d9SMatt Johnston 	rc = mctp_i2c_set_neighbour(tx_test->i2c, EID_B,
149e5b941d9SMatt Johnston 				    rx_test->i2c->own_addr);
150e5b941d9SMatt Johnston 	assert(rc == 0);
151e5b941d9SMatt Johnston 	rx_test->rx_len = 0;
152e5b941d9SMatt Johnston 	mctp_message_tx(tx_test->mctp, EID_B, tag_owner, msg_tag, mctp_msg_src,
153e5b941d9SMatt Johnston 			msg_len);
154e5b941d9SMatt Johnston 	assert(rc == 0);
155e5b941d9SMatt Johnston 	assert(rx_test->rx_len == msg_len);
156e5b941d9SMatt Johnston 	assert(tx_test->last_tx_i2c_dst == rx_test->i2c->own_addr);
157e5b941d9SMatt Johnston 
158e5b941d9SMatt Johnston 	/* Check only one entry is set */
159e5b941d9SMatt Johnston 	size_t count = 0;
160e5b941d9SMatt Johnston 	for (size_t i = 0; i < MCTP_I2C_NEIGH_COUNT; i++) {
161e5b941d9SMatt Johnston 		struct mctp_i2c_neigh *n = &tx_test->i2c->neigh[i];
162e5b941d9SMatt Johnston 		if (n->used) {
163e5b941d9SMatt Johnston 			assert(n->eid == EID_B);
164e5b941d9SMatt Johnston 			count++;
165e5b941d9SMatt Johnston 		}
166e5b941d9SMatt Johnston 	}
167e5b941d9SMatt Johnston 	assert(count == 1);
168e5b941d9SMatt Johnston 
169e5b941d9SMatt Johnston 	/* Ensure we can iterate without overflow.
170e5b941d9SMatt Johnston 	 * If MCTP_I2C_NEIGH_COUNT increases too large this test would need rethinking
171e5b941d9SMatt Johnston 	 * (and eviction may become impossible) */
172e5b941d9SMatt Johnston 	assert((int)EID_B + MCTP_I2C_NEIGH_COUNT < 254);
173e5b941d9SMatt Johnston 	assert((int)I2C_ADDR_B + MCTP_I2C_NEIGH_COUNT < 0x7f);
174e5b941d9SMatt Johnston 
175e5b941d9SMatt Johnston 	/* Fill entries. -1 because one was already filled. */
176e5b941d9SMatt Johnston 	for (size_t i = 0; i < MCTP_I2C_NEIGH_COUNT - 1; i++) {
177e5b941d9SMatt Johnston 		/* Unused addresses */
178e5b941d9SMatt Johnston 		uint8_t addr = rx_test->i2c->own_addr + i + 1;
179e5b941d9SMatt Johnston 		uint8_t eid = EID_B + i + 1;
180e5b941d9SMatt Johnston 		rc = mctp_i2c_set_neighbour(tx_test->i2c, eid, addr);
181e5b941d9SMatt Johnston 		assert(rc == 0);
182e5b941d9SMatt Johnston 	}
183e5b941d9SMatt Johnston 
184e5b941d9SMatt Johnston 	/* Check all are used */
185e5b941d9SMatt Johnston 	for (size_t i = 0; i < MCTP_I2C_NEIGH_COUNT; i++) {
186e5b941d9SMatt Johnston 		struct mctp_i2c_neigh *n = &tx_test->i2c->neigh[i];
187e5b941d9SMatt Johnston 		assert(n->used);
188e5b941d9SMatt Johnston 	}
189e5b941d9SMatt Johnston 
190e5b941d9SMatt Johnston 	/* Test eviction */
191e5b941d9SMatt Johnston 	{
192e5b941d9SMatt Johnston 		uint8_t addr =
193e5b941d9SMatt Johnston 			rx_test->i2c->own_addr + MCTP_I2C_NEIGH_COUNT + 1;
194e5b941d9SMatt Johnston 		uint8_t eid = EID_B + MCTP_I2C_NEIGH_COUNT + 1;
195e5b941d9SMatt Johnston 		rc = mctp_i2c_set_neighbour(tx_test->i2c, eid, addr);
196e5b941d9SMatt Johnston 		assert(rc == 0);
197e5b941d9SMatt Johnston 
198e5b941d9SMatt Johnston 		/* EID_B got evicted, send should fail */
199e5b941d9SMatt Johnston 		rx_test->rx_len = 0;
200e5b941d9SMatt Johnston 		mctp_message_tx(tx_test->mctp, EID_B, tag_owner, msg_tag,
201e5b941d9SMatt Johnston 				mctp_msg_src, msg_len);
202e5b941d9SMatt Johnston 		/* Not received */
203e5b941d9SMatt Johnston 		assert(rx_test->rx_len == 0);
204e5b941d9SMatt Johnston 	}
205e5b941d9SMatt Johnston 
206e5b941d9SMatt Johnston 	/* Add EID_B again */
207e5b941d9SMatt Johnston 	rc = mctp_i2c_set_neighbour(tx_test->i2c, EID_B,
208e5b941d9SMatt Johnston 				    rx_test->i2c->own_addr);
209e5b941d9SMatt Johnston 	assert(rc == 0);
210e5b941d9SMatt Johnston 	rx_test->rx_len = 0;
211e5b941d9SMatt Johnston 	mctp_message_tx(tx_test->mctp, EID_B, tag_owner, msg_tag, mctp_msg_src,
212e5b941d9SMatt Johnston 			msg_len);
213e5b941d9SMatt Johnston 	/* Is received */
214e5b941d9SMatt Johnston 	assert(rx_test->rx_len == msg_len);
215e5b941d9SMatt Johnston }
216e5b941d9SMatt Johnston 
main(void)217e5b941d9SMatt Johnston int main(void)
218e5b941d9SMatt Johnston {
219e5b941d9SMatt Johnston 	struct i2c_test scenario[2];
220e5b941d9SMatt Johnston 	struct i2c_test *tx_test = &scenario[0];
221e5b941d9SMatt Johnston 	struct i2c_test *rx_test = &scenario[1];
222e5b941d9SMatt Johnston 
223e5b941d9SMatt Johnston 	mctp_set_log_stdio(MCTP_LOG_DEBUG);
224e5b941d9SMatt Johnston 
225e5b941d9SMatt Johnston 	memset(scenario, 0x0, sizeof(scenario));
226e5b941d9SMatt Johnston 
227e5b941d9SMatt Johnston 	/* Setup a source buffer */
228e5b941d9SMatt Johnston 	for (size_t i = 0; i < sizeof(mctp_msg_src); i++) {
229e5b941d9SMatt Johnston 		mctp_msg_src[i] = i & 0xff;
230e5b941d9SMatt Johnston 	}
231e5b941d9SMatt Johnston 
232e5b941d9SMatt Johnston 	tx_test->mctp = mctp_init();
233e5b941d9SMatt Johnston 	assert(tx_test->mctp);
234e5b941d9SMatt Johnston 	tx_test->i2c = malloc(MCTP_SIZEOF_BINDING_I2C);
235e5b941d9SMatt Johnston 	assert(tx_test->i2c);
236e5b941d9SMatt Johnston 	rx_test->mctp = mctp_init();
237e5b941d9SMatt Johnston 	assert(rx_test->mctp);
238e5b941d9SMatt Johnston 	rx_test->i2c = malloc(MCTP_SIZEOF_BINDING_I2C);
239e5b941d9SMatt Johnston 	assert(rx_test->i2c);
240e5b941d9SMatt Johnston 
241e5b941d9SMatt Johnston 	/* TX side */
242e5b941d9SMatt Johnston 	mctp_i2c_setup(tx_test->i2c, I2C_ADDR_A, test_i2c_tx, scenario);
243e5b941d9SMatt Johnston 	mctp_register_bus(tx_test->mctp, mctp_binding_i2c_core(tx_test->i2c),
244e5b941d9SMatt Johnston 			  EID_A);
245e5b941d9SMatt Johnston 	mctp_set_rx_all(tx_test->mctp, NULL, NULL);
246e5b941d9SMatt Johnston 	mctp_i2c_set_neighbour(tx_test->i2c, EID_B, I2C_ADDR_B);
247e5b941d9SMatt Johnston 
248e5b941d9SMatt Johnston 	/* RX side */
249e5b941d9SMatt Johnston 	mctp_i2c_setup(rx_test->i2c, I2C_ADDR_B, NULL, NULL);
250e5b941d9SMatt Johnston 	mctp_register_bus(rx_test->mctp, mctp_binding_i2c_core(rx_test->i2c),
251e5b941d9SMatt Johnston 			  EID_B);
252e5b941d9SMatt Johnston 	mctp_set_rx_all(rx_test->mctp, test_i2c_rxmsg, scenario);
253e5b941d9SMatt Johnston 	// mctp_i2c_set_neighbour(rx_test->i2c, EID_A, I2C_ADDR_A);
254e5b941d9SMatt Johnston 
255e5b941d9SMatt Johnston 	/* Try all message sizes */
256e5b941d9SMatt Johnston 	for (size_t i = 1; i < sizeof(mctp_msg_src); i++) {
257e5b941d9SMatt Johnston 		run_tx_test(tx_test, EID_B, i, rx_test);
258e5b941d9SMatt Johnston 	}
259e5b941d9SMatt Johnston 
260e5b941d9SMatt Johnston 	test_neigh_expiry(tx_test, rx_test);
261e5b941d9SMatt Johnston 
262*a3830d25SMatt Johnston 	free(tx_test->i2c);
263*a3830d25SMatt Johnston 	free(rx_test->i2c);
264*a3830d25SMatt Johnston 	mctp_destroy(tx_test->mctp);
265*a3830d25SMatt Johnston 	mctp_destroy(rx_test->mctp);
266*a3830d25SMatt Johnston 
267e5b941d9SMatt Johnston 	return 0;
268e5b941d9SMatt Johnston }
269