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
test_rx(uint8_t eid __unused,bool tag_owner __unused,uint8_t msg_tag __unused,void * data,void * msg,size_t len)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
run_one_test(struct test_ctx * ctx,struct test * test)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
main(void)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