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