xref: /openbmc/libmctp/tests/test_seq.c (revision 3ef47785)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 
3 #ifdef NDEBUG
4 #undef NDEBUG
5 #endif
6 
7 #include <assert.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 
12 #include "compiler.h"
13 #include "libmctp.h"
14 #include "test-utils.h"
15 
16 #ifndef ARRAY_SIZE
17 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
18 #endif
19 
20 struct test_ctx {
21 	struct mctp *mctp;
22 	struct mctp_binding_test *binding;
23 	int rx_count;
24 	uint8_t rx_data[4];
25 	size_t rx_len;
26 };
27 
28 static void test_rx(uint8_t eid __unused, bool tag_owner __unused,
29 		    uint8_t msg_tag __unused, void *data, void *msg, size_t len)
30 {
31 	struct test_ctx *ctx = data;
32 
33 	ctx->rx_count++;
34 
35 	/* append incoming message data to the existing rx_data */
36 	assert(len <= sizeof(ctx->rx_data));
37 	assert(ctx->rx_len + len <= sizeof(ctx->rx_data));
38 
39 	memcpy(ctx->rx_data + ctx->rx_len, msg, len);
40 	ctx->rx_len += len;
41 }
42 
43 #define SEQ(x) (x << MCTP_HDR_SEQ_SHIFT)
44 
45 struct test {
46 	int n_packets;
47 	uint8_t flags_seq_tags[4];
48 	int exp_rx_count;
49 	size_t exp_rx_len;
50 } tests[] = {
51 	{
52 		/* single packet */
53 		.n_packets = 1,
54 		.flags_seq_tags = {
55 			SEQ(1) | MCTP_HDR_FLAG_SOM | MCTP_HDR_FLAG_EOM,
56 		},
57 		.exp_rx_count = 1,
58 		.exp_rx_len = 1,
59 	},
60 	{
61 		/* two packets: one start, one end */
62 		.n_packets = 2,
63 		.flags_seq_tags = {
64 			SEQ(1) | MCTP_HDR_FLAG_SOM,
65 			SEQ(2) | MCTP_HDR_FLAG_EOM,
66 		},
67 		.exp_rx_count = 1,
68 		.exp_rx_len = 2,
69 	},
70 	{
71 		/* three packets: one start, one no flags, one end */
72 		.n_packets = 3,
73 		.flags_seq_tags = {
74 			SEQ(1) | MCTP_HDR_FLAG_SOM,
75 			SEQ(2),
76 			SEQ(3) | MCTP_HDR_FLAG_EOM,
77 		},
78 		.exp_rx_count = 1,
79 		.exp_rx_len = 3,
80 	},
81 	{
82 		/* two packets, wrapping sequence numbers */
83 		.n_packets = 2,
84 		.flags_seq_tags = {
85 			SEQ(3) | MCTP_HDR_FLAG_SOM,
86 			SEQ(0) | MCTP_HDR_FLAG_EOM,
87 		},
88 		.exp_rx_count = 1,
89 		.exp_rx_len = 2,
90 	},
91 	{
92 		/* two packets, invalid sequence number */
93 		.n_packets = 2,
94 		.flags_seq_tags = {
95 			SEQ(1) | MCTP_HDR_FLAG_SOM,
96 			SEQ(3) | MCTP_HDR_FLAG_EOM,
97 		},
98 		.exp_rx_count = 0,
99 		.exp_rx_len = 0,
100 	},
101 };
102 
103 static void run_one_test(struct test_ctx *ctx, struct test *test)
104 {
105 	const mctp_eid_t local_eid = 8;
106 	const mctp_eid_t remote_eid = 9;
107 	struct {
108 		struct mctp_hdr hdr;
109 		uint8_t payload[1];
110 	} pktbuf;
111 	int i;
112 
113 	ctx->rx_count = 0;
114 	ctx->rx_len = 0;
115 
116 	mctp_test_stack_init(&ctx->mctp, &ctx->binding, local_eid);
117 
118 	mctp_set_rx_all(ctx->mctp, test_rx, ctx);
119 
120 	for (i = 0; i < test->n_packets; i++) {
121 		memset(&pktbuf, 0, sizeof(pktbuf));
122 		pktbuf.hdr.dest = local_eid;
123 		pktbuf.hdr.src = remote_eid;
124 		pktbuf.hdr.flags_seq_tag = test->flags_seq_tags[i];
125 		pktbuf.payload[0] = i;
126 
127 		mctp_binding_test_rx_raw(ctx->binding, &pktbuf, sizeof(pktbuf));
128 	}
129 
130 	assert(ctx->rx_count == test->exp_rx_count);
131 	assert(ctx->rx_len == test->exp_rx_len);
132 
133 	/* ensure the payload data was reconstructed correctly */
134 	for (i = 0; i < (int)ctx->rx_len; i++)
135 		assert(ctx->rx_data[i] == i);
136 
137 	mctp_binding_test_destroy(ctx->binding);
138 	mctp_destroy(ctx->mctp);
139 }
140 
141 int main(void)
142 {
143 	struct test_ctx ctx;
144 	unsigned int i;
145 
146 	for (i = 0; i < ARRAY_SIZE(tests); i++)
147 		run_one_test(&ctx, &tests[i]);
148 
149 	return EXIT_SUCCESS;
150 }
151