blob: 435e5e4193240d769fcab2ce4a3a0a21b7c365d8 [file] [log] [blame]
Sumanth Bhat69f545f2021-05-18 09:16:43 +00001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2
3#define _GNU_SOURCE
4
5#ifdef NDEBUG
6#undef NDEBUG
7#endif
8
9#if HAVE_CONFIG_H
10#include "config.h"
11#endif
12
13#include <assert.h>
14#include <fcntl.h>
15#include <stdbool.h>
16#include <stdint.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21
Andrew Jeffery5ab78252022-02-17 21:04:59 +103022#include "compiler.h"
Sumanth Bhat69f545f2021-05-18 09:16:43 +000023#include "libmctp-alloc.h"
24#include "libmctp-log.h"
25#include "range.h"
26#include "test-utils.h"
27
John Chung133df7a2024-05-14 16:19:56 +080028#define TEST_DEST_EID 9
29#define TEST_DEST_NULL_EID 0
30#define TEST_DEST_BROADCAST_EID 255
31#define TEST_SRC_EID 10
Sumanth Bhat69f545f2021-05-18 09:16:43 +000032
33#ifndef ARRAY_SIZE
34#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
35#endif
36
Sumanth Bhat69f545f2021-05-18 09:16:43 +000037#define MAX_PAYLOAD_SIZE 50000
38
39struct pktbuf {
40 struct mctp_hdr hdr;
41 uint8_t *payload;
42};
43
44struct test_params {
45 bool seen;
46 size_t message_size;
Sumanth Bhatf39c3852022-01-10 17:04:10 +053047 uint8_t msg_tag;
48 bool tag_owner;
Sumanth Bhat69f545f2021-05-18 09:16:43 +000049};
50
Sumanth Bhatf39c3852022-01-10 17:04:10 +053051static void rx_message(uint8_t eid __unused, bool tag_owner, uint8_t msg_tag,
52 void *data, void *msg __unused, size_t len)
Sumanth Bhat69f545f2021-05-18 09:16:43 +000053{
54 struct test_params *param = (struct test_params *)data;
55
Sumanth Bhatf39c3852022-01-10 17:04:10 +053056 mctp_prdebug("MCTP message received: len %zd, tag %u", len, msg_tag);
Sumanth Bhat69f545f2021-05-18 09:16:43 +000057
58 param->seen = true;
59 param->message_size = len;
Sumanth Bhatf39c3852022-01-10 17:04:10 +053060 param->msg_tag = msg_tag;
61 param->tag_owner = tag_owner;
Sumanth Bhat69f545f2021-05-18 09:16:43 +000062}
63
64static uint8_t get_sequence()
65{
66 static uint8_t pkt_seq = 0;
67
68 return (pkt_seq++ % 4);
69}
70
71static uint8_t get_tag()
72{
73 static uint8_t tag = 0;
74
75 return (tag++ % 8);
76}
77
78/*
79 * receive_pktbuf bypasses all bindings and directly invokes mctp_bus_rx.
80 * This is necessary in order invoke test cases on the core functionality.
81 * The memory allocated for the mctp packet is capped at MCTP_BTU
82 * size, however, the mimiced rx pkt still retains the len parameter.
83 * This allows to mimic packets larger than a sane memory allocator can
84 * provide.
85 */
86static void receive_ptkbuf(struct mctp_binding_test *binding,
87 const struct pktbuf *pktbuf, size_t len)
88{
89 size_t alloc_size = MIN((size_t)MCTP_BTU, len);
90 struct mctp_pktbuf *rx_pkt;
91
92 rx_pkt = __mctp_alloc(sizeof(*rx_pkt) + MCTP_PACKET_SIZE(alloc_size));
93 assert(rx_pkt);
94
95 /* Preserve passed len parameter */
96 rx_pkt->size = MCTP_PACKET_SIZE(len);
97 rx_pkt->start = 0;
98 rx_pkt->end = MCTP_PACKET_SIZE(len);
99 rx_pkt->mctp_hdr_off = 0;
100 rx_pkt->next = NULL;
101 memcpy(rx_pkt->data, &pktbuf->hdr, sizeof(pktbuf->hdr));
102 memcpy(rx_pkt->data + sizeof(pktbuf->hdr), pktbuf->payload, alloc_size);
103
104 mctp_bus_rx((struct mctp_binding *)binding, rx_pkt);
105}
106
107static void receive_one_fragment(struct mctp_binding_test *binding,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930108 uint8_t *payload, size_t fragment_size,
109 uint8_t flags_seq_tag, struct pktbuf *pktbuf)
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000110{
111 pktbuf->hdr.flags_seq_tag = flags_seq_tag;
112 pktbuf->payload = payload;
113 receive_ptkbuf(binding, pktbuf, fragment_size);
114}
115
116static void receive_two_fragment_message(struct mctp_binding_test *binding,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930117 uint8_t *payload,
118 size_t fragment1_size,
119 size_t fragment2_size,
120 struct pktbuf *pktbuf)
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000121{
122 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag();
123 uint8_t flags_seq_tag;
124
125 flags_seq_tag = MCTP_HDR_FLAG_SOM |
126 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
127 receive_one_fragment(binding, payload, fragment1_size, flags_seq_tag,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930128 pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000129
130 flags_seq_tag = MCTP_HDR_FLAG_EOM |
131 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
132 receive_one_fragment(binding, payload + fragment1_size, fragment2_size,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930133 flags_seq_tag, pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000134}
135
136static void mctp_core_test_simple_rx()
137{
138 struct mctp *mctp = NULL;
139 struct mctp_binding_test *binding = NULL;
140 struct test_params test_param;
141 uint8_t test_payload[2 * MCTP_BTU];
142 struct pktbuf pktbuf;
143
144 memset(test_payload, 0, sizeof(test_payload));
145 test_param.seen = false;
146 test_param.message_size = 0;
147 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
148 mctp_set_rx_all(mctp, rx_message, &test_param);
149 memset(&pktbuf, 0, sizeof(pktbuf));
150 pktbuf.hdr.dest = TEST_DEST_EID;
151 pktbuf.hdr.src = TEST_SRC_EID;
152
153 /* Receive 2 fragments of equal size */
154 receive_two_fragment_message(binding, test_payload, MCTP_BTU, MCTP_BTU,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930155 &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000156
157 assert(test_param.seen);
158 assert(test_param.message_size == 2 * MCTP_BTU);
159
160 mctp_binding_test_destroy(binding);
161 mctp_destroy(mctp);
162}
163
164static void mctp_core_test_receive_equal_length_fragments()
165{
166 struct mctp *mctp = NULL;
167 struct mctp_binding_test *binding = NULL;
168 struct test_params test_param;
169 static uint8_t test_payload[MAX_PAYLOAD_SIZE];
170 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag();
171 struct pktbuf pktbuf;
172 uint8_t flags_seq_tag;
173
174 memset(test_payload, 0, sizeof(test_payload));
175 test_param.seen = false;
176 test_param.message_size = 0;
177 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
178 mctp_set_rx_all(mctp, rx_message, &test_param);
179 memset(&pktbuf, 0, sizeof(pktbuf));
180 pktbuf.hdr.dest = TEST_DEST_EID;
181 pktbuf.hdr.src = TEST_SRC_EID;
182
183 /* Receive 3 fragments, each of size MCTP_BTU */
184 flags_seq_tag = MCTP_HDR_FLAG_SOM |
185 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
186 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930187 &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000188
189 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
190 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930191 flags_seq_tag, &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000192
193 flags_seq_tag = MCTP_HDR_FLAG_EOM |
194 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
195 receive_one_fragment(binding, test_payload + (2 * MCTP_BTU), MCTP_BTU,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930196 flags_seq_tag, &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000197
198 assert(test_param.seen);
199 assert(test_param.message_size == 3 * MCTP_BTU);
200
201 mctp_binding_test_destroy(binding);
202 mctp_destroy(mctp);
203}
204
205static void mctp_core_test_receive_unexpected_smaller_middle_fragment()
206{
207 struct mctp *mctp = NULL;
208 struct mctp_binding_test *binding = NULL;
209 struct test_params test_param;
210 static uint8_t test_payload[MAX_PAYLOAD_SIZE];
211 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag();
212 struct pktbuf pktbuf;
213 uint8_t flags_seq_tag;
214
215 memset(test_payload, 0, sizeof(test_payload));
216 test_param.seen = false;
217 test_param.message_size = 0;
218 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
219 mctp_set_rx_all(mctp, rx_message, &test_param);
220 memset(&pktbuf, 0, sizeof(pktbuf));
221 pktbuf.hdr.dest = TEST_DEST_EID;
222 pktbuf.hdr.src = TEST_SRC_EID;
223
224 /* Middle fragment with size MCTP_BTU - 1 */
225 flags_seq_tag = MCTP_HDR_FLAG_SOM |
226 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
227 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930228 &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000229
230 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
231 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU - 1,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930232 flags_seq_tag, &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000233
234 flags_seq_tag = MCTP_HDR_FLAG_EOM |
235 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
236 receive_one_fragment(binding, test_payload + (2 * MCTP_BTU), MCTP_BTU,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930237 flags_seq_tag, &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000238
239 assert(!test_param.seen);
240
241 mctp_binding_test_destroy(binding);
242 mctp_destroy(mctp);
243}
244
245static void mctp_core_test_receive_unexpected_bigger_middle_fragment()
246{
247 struct mctp *mctp = NULL;
248 struct mctp_binding_test *binding = NULL;
249 struct test_params test_param;
250 static uint8_t test_payload[MAX_PAYLOAD_SIZE];
251 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag();
252 struct pktbuf pktbuf;
253 uint8_t flags_seq_tag;
254
255 memset(test_payload, 0, sizeof(test_payload));
256 test_param.seen = false;
257 test_param.message_size = 0;
258 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
259 mctp_set_rx_all(mctp, rx_message, &test_param);
260 memset(&pktbuf, 0, sizeof(pktbuf));
261 pktbuf.hdr.dest = TEST_DEST_EID;
262 pktbuf.hdr.src = TEST_SRC_EID;
263
264 /* Middle fragment with size MCTP_BTU + 1 */
265 flags_seq_tag = MCTP_HDR_FLAG_SOM |
266 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
267 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930268 &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000269
270 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
271 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU + 1,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930272 flags_seq_tag, &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000273
274 flags_seq_tag = MCTP_HDR_FLAG_EOM |
275 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
276 receive_one_fragment(binding, test_payload + (2 * MCTP_BTU), MCTP_BTU,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930277 flags_seq_tag, &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000278
279 assert(!test_param.seen);
280
281 mctp_binding_test_destroy(binding);
282 mctp_destroy(mctp);
283}
284
285static void mctp_core_test_receive_smaller_end_fragment()
286{
287 struct mctp *mctp = NULL;
288 struct mctp_binding_test *binding = NULL;
289 struct test_params test_param;
290 static uint8_t test_payload[MAX_PAYLOAD_SIZE];
291 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag();
292 uint8_t end_frag_size = MCTP_BTU - 10;
293 struct pktbuf pktbuf;
294 uint8_t flags_seq_tag;
295
296 memset(test_payload, 0, sizeof(test_payload));
297 test_param.seen = false;
298 test_param.message_size = 0;
299 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
300 mctp_set_rx_all(mctp, rx_message, &test_param);
301 memset(&pktbuf, 0, sizeof(pktbuf));
302 pktbuf.hdr.dest = TEST_DEST_EID;
303 pktbuf.hdr.src = TEST_SRC_EID;
304
305 flags_seq_tag = MCTP_HDR_FLAG_SOM |
306 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
307 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930308 &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000309
310 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
311 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930312 flags_seq_tag, &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000313
314 flags_seq_tag = MCTP_HDR_FLAG_EOM |
315 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
316 receive_one_fragment(binding, test_payload + (2 * MCTP_BTU),
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930317 end_frag_size, flags_seq_tag, &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000318
319 assert(test_param.seen);
320 assert(test_param.message_size ==
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930321 (size_t)(2 * MCTP_BTU + end_frag_size));
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000322
323 mctp_binding_test_destroy(binding);
324 mctp_destroy(mctp);
325}
326
327static void mctp_core_test_receive_bigger_end_fragment()
328{
329 struct mctp *mctp = NULL;
330 struct mctp_binding_test *binding = NULL;
331 struct test_params test_param;
332 static uint8_t test_payload[MAX_PAYLOAD_SIZE];
333 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag();
334 uint8_t end_frag_size = MCTP_BTU + 10;
335 struct pktbuf pktbuf;
336 uint8_t flags_seq_tag;
337
338 memset(test_payload, 0, sizeof(test_payload));
339 test_param.seen = false;
340 test_param.message_size = 0;
341 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
342 mctp_set_rx_all(mctp, rx_message, &test_param);
343 memset(&pktbuf, 0, sizeof(pktbuf));
344 pktbuf.hdr.dest = TEST_DEST_EID;
345 pktbuf.hdr.src = TEST_SRC_EID;
346
347 flags_seq_tag = MCTP_HDR_FLAG_SOM |
348 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
349 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930350 &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000351
352 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
353 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930354 flags_seq_tag, &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000355
356 flags_seq_tag = MCTP_HDR_FLAG_EOM |
357 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
358 receive_one_fragment(binding, test_payload + (2 * MCTP_BTU),
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930359 end_frag_size, flags_seq_tag, &pktbuf);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000360
361 assert(!test_param.seen);
362
363 mctp_binding_test_destroy(binding);
364 mctp_destroy(mctp);
365}
366
Sumanth Bhatbc79c242021-06-16 12:36:56 +0530367static void mctp_core_test_drop_large_fragments()
368{
369 struct mctp *mctp = NULL;
370 struct mctp_binding_test *binding = NULL;
371 struct test_params test_param;
372 static uint8_t test_payload[MAX_PAYLOAD_SIZE];
373 struct pktbuf pktbuf;
374
375 memset(test_payload, 0, sizeof(test_payload));
376 test_param.seen = false;
377 test_param.message_size = 0;
378 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
379 mctp_set_rx_all(mctp, rx_message, &test_param);
380 memset(&pktbuf, 0, sizeof(pktbuf));
381 pktbuf.hdr.dest = TEST_DEST_EID;
382 pktbuf.hdr.src = TEST_SRC_EID;
383
384 /* Receive a large payload - first fragment with MCTP_BTU bytes,
385 * 2nd fragment of SIZE_MAX */
386
387 receive_two_fragment_message(binding, test_payload, MCTP_BTU,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930388 SIZE_MAX - sizeof(struct mctp_hdr),
389 &pktbuf);
Sumanth Bhatbc79c242021-06-16 12:36:56 +0530390
391 assert(!test_param.seen);
392
393 mctp_binding_test_destroy(binding);
394 mctp_destroy(mctp);
395}
396
Sumanth Bhat34d4c962021-06-16 12:50:48 +0530397static void mctp_core_test_exhaust_context_buffers()
398{
399 struct mctp *mctp = NULL;
400 struct mctp_binding_test *binding = NULL;
401 struct test_params test_param;
402 static uint8_t test_payload[MAX_PAYLOAD_SIZE];
403 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag();
404 uint8_t i = 0;
405 const uint8_t max_context_buffers = 16;
406 struct pktbuf pktbuf;
407 uint8_t flags_seq_tag;
408
409 memset(test_payload, 0, sizeof(test_payload));
410 test_param.seen = false;
411 test_param.message_size = 0;
412 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
413 mctp_set_rx_all(mctp, rx_message, &test_param);
414 memset(&pktbuf, 0, sizeof(pktbuf));
415 pktbuf.hdr.dest = TEST_DEST_EID;
416 pktbuf.hdr.src = TEST_SRC_EID;
417
418 /* Exhaust all 16 context buffers*/
419 for (i = 0; i < max_context_buffers; i++) {
420 flags_seq_tag = MCTP_HDR_FLAG_SOM |
421 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
422 receive_one_fragment(binding, test_payload, MCTP_BTU,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930423 flags_seq_tag, &pktbuf);
Sumanth Bhat34d4c962021-06-16 12:50:48 +0530424
425 /* Change source EID so that different contexts are created */
426 pktbuf.hdr.src++;
427 }
428
429 /* Send a full message from a different EID */
430 pktbuf.hdr.src++;
431 receive_two_fragment_message(binding, test_payload, MCTP_BTU, MCTP_BTU,
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930432 &pktbuf);
Sumanth Bhat34d4c962021-06-16 12:50:48 +0530433
434 /* Message assembly should fail */
435 assert(!test_param.seen);
436
437 /* Complete message assembly for one of the messages */
438 pktbuf.hdr.src -= max_context_buffers;
439 flags_seq_tag = MCTP_HDR_FLAG_EOM |
440 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag;
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930441 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
442 &pktbuf);
Sumanth Bhat34d4c962021-06-16 12:50:48 +0530443
444 assert(test_param.seen);
445 assert(test_param.message_size == (2 * MCTP_BTU));
446
447 mctp_binding_test_destroy(binding);
448 mctp_destroy(mctp);
449}
450
Sumanth Bhatf39c3852022-01-10 17:04:10 +0530451static void mctp_core_test_rx_with_tag()
452{
453 struct mctp *mctp = NULL;
454 struct mctp_binding_test *binding = NULL;
455 struct test_params test_param;
456 static uint8_t test_payload[MCTP_BTU];
457 uint8_t tag = get_tag();
458 struct pktbuf pktbuf;
459 uint8_t flags_seq_tag;
460
461 memset(test_payload, 0, sizeof(test_payload));
462 test_param.seen = false;
463 test_param.message_size = 0;
464 test_param.msg_tag = 0;
465 test_param.tag_owner = false;
466
467 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
468 mctp_set_rx_all(mctp, rx_message, &test_param);
469 memset(&pktbuf, 0, sizeof(pktbuf));
470 pktbuf.hdr.dest = TEST_DEST_EID;
471 pktbuf.hdr.src = TEST_SRC_EID;
472
473 /* Set tag and tag owner fields for a recieve packet */
474 flags_seq_tag = MCTP_HDR_FLAG_SOM | MCTP_HDR_FLAG_EOM |
475 (1 << MCTP_HDR_TO_SHIFT) | tag;
476 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
477 &pktbuf);
478
479 assert(test_param.seen);
480 assert(test_param.message_size == (MCTP_BTU));
481 assert(test_param.msg_tag == tag);
482 assert(test_param.tag_owner);
483
484 mctp_binding_test_destroy(binding);
485 mctp_destroy(mctp);
486}
487
488static void mctp_core_test_rx_with_tag_multifragment()
489{
490 struct mctp *mctp = NULL;
491 struct mctp_binding_test *binding = NULL;
492 struct test_params test_param;
493 static uint8_t test_payload[MCTP_BTU];
494 uint8_t tag = get_tag();
495 struct pktbuf pktbuf;
496 uint8_t flags_seq_tag;
497
498 memset(test_payload, 0, sizeof(test_payload));
499 test_param.seen = false;
500 test_param.message_size = 0;
501 test_param.msg_tag = 0;
502 test_param.tag_owner = false;
503
504 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
505 mctp_set_rx_all(mctp, rx_message, &test_param);
506 memset(&pktbuf, 0, sizeof(pktbuf));
507 pktbuf.hdr.dest = TEST_DEST_EID;
508 pktbuf.hdr.src = TEST_SRC_EID;
509
510 /* Set tag and tag owner fields for a 3 fragment packet */
511 flags_seq_tag = MCTP_HDR_FLAG_SOM |
512 (get_sequence() << MCTP_HDR_SEQ_SHIFT) |
513 (1 << MCTP_HDR_TO_SHIFT) | tag;
514 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
515 &pktbuf);
516
517 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) |
518 (1 << MCTP_HDR_TO_SHIFT) | tag;
519 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
520 &pktbuf);
521
522 flags_seq_tag = MCTP_HDR_FLAG_EOM |
523 (get_sequence() << MCTP_HDR_SEQ_SHIFT) |
524 (1 << MCTP_HDR_TO_SHIFT) | tag;
525 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag,
526 &pktbuf);
527
528 assert(test_param.seen);
529 assert(test_param.message_size == (3 * MCTP_BTU));
530 assert(test_param.msg_tag == tag);
531 assert(test_param.tag_owner);
532
533 mctp_binding_test_destroy(binding);
534 mctp_destroy(mctp);
535}
536
John Chung133df7a2024-05-14 16:19:56 +0800537/*
538 * This test case covers null destination eid. MCTP
539 * daemon might query endpoint (i.e., Get Endpoint
540 * ID command) by physical address requests and
541 * destination eid as 0. Endpoint shall accept and
542 * handle this request.
543 */
544static void mctp_core_test_rx_with_null_dst_eid()
545{
546 struct mctp *mctp = NULL;
547 struct mctp_binding_test *binding = NULL;
548 struct test_params test_param;
549 uint8_t test_payload[2 * MCTP_BTU];
550 struct pktbuf pktbuf;
551
552 memset(test_payload, 0, sizeof(test_payload));
553 test_param.seen = false;
554 test_param.message_size = 0;
555 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
556 mctp_set_rx_all(mctp, rx_message, &test_param);
557 memset(&pktbuf, 0, sizeof(pktbuf));
558 pktbuf.hdr.dest = TEST_DEST_NULL_EID;
559 pktbuf.hdr.src = TEST_SRC_EID;
560
561 /* Receive 2 fragments of equal size */
562 receive_two_fragment_message(binding, test_payload, MCTP_BTU, MCTP_BTU,
563 &pktbuf);
564
565 assert(test_param.seen);
566 assert(test_param.message_size == 2 * MCTP_BTU);
567
568 mctp_binding_test_destroy(binding);
569 mctp_destroy(mctp);
570}
571
572/*
573 * This test case covers Broadcast Request message (i.e.,
574 * `Endpoint Discovery` command). Endpoint shall accept
575 * and handle this request.
576 */
577static void mctp_core_test_rx_with_broadcast_dst_eid()
578{
579 struct mctp *mctp = NULL;
580 struct mctp_binding_test *binding = NULL;
581 struct test_params test_param;
582 uint8_t test_payload[2 * MCTP_BTU];
583 struct pktbuf pktbuf;
584
585 memset(test_payload, 0, sizeof(test_payload));
586 test_param.seen = false;
587 test_param.message_size = 0;
588 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID);
589 mctp_set_rx_all(mctp, rx_message, &test_param);
590 memset(&pktbuf, 0, sizeof(pktbuf));
591 pktbuf.hdr.dest = TEST_DEST_BROADCAST_EID;
592 pktbuf.hdr.src = TEST_SRC_EID;
593
594 /* Receive 2 fragments of equal size */
595 receive_two_fragment_message(binding, test_payload, MCTP_BTU, MCTP_BTU,
596 &pktbuf);
597
598 assert(test_param.seen);
599 assert(test_param.message_size == 2 * MCTP_BTU);
600
601 mctp_binding_test_destroy(binding);
602 mctp_destroy(mctp);
603}
604
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000605/* clang-format off */
606#define TEST_CASE(test) { #test, test }
607static const struct {
608 const char *name;
609 void (*test)(void);
610} mctp_core_tests[] = {
611 TEST_CASE(mctp_core_test_simple_rx),
612 TEST_CASE(mctp_core_test_receive_equal_length_fragments),
613 TEST_CASE(mctp_core_test_receive_unexpected_smaller_middle_fragment),
614 TEST_CASE(mctp_core_test_receive_unexpected_bigger_middle_fragment),
615 TEST_CASE(mctp_core_test_receive_smaller_end_fragment),
616 TEST_CASE(mctp_core_test_receive_bigger_end_fragment),
Sumanth Bhatbc79c242021-06-16 12:36:56 +0530617 TEST_CASE(mctp_core_test_drop_large_fragments),
Sumanth Bhat34d4c962021-06-16 12:50:48 +0530618 TEST_CASE(mctp_core_test_exhaust_context_buffers),
Sumanth Bhatf39c3852022-01-10 17:04:10 +0530619 TEST_CASE(mctp_core_test_rx_with_tag),
620 TEST_CASE(mctp_core_test_rx_with_tag_multifragment),
John Chung133df7a2024-05-14 16:19:56 +0800621 TEST_CASE(mctp_core_test_rx_with_null_dst_eid),
622 TEST_CASE(mctp_core_test_rx_with_broadcast_dst_eid),
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000623};
624/* clang-format on */
625
626#ifndef BUILD_ASSERT
627#define BUILD_ASSERT(x) \
628 do { \
629 (void)sizeof(char[0 - (!(x))]); \
630 } while (0)
631#endif
632
633int main(void)
634{
635 uint8_t i;
636
637 mctp_set_log_stdio(MCTP_LOG_DEBUG);
638
639 BUILD_ASSERT(ARRAY_SIZE(mctp_core_tests) < SIZE_MAX);
640 for (i = 0; i < ARRAY_SIZE(mctp_core_tests); i++) {
641 mctp_prlog(MCTP_LOG_DEBUG, "begin: %s",
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930642 mctp_core_tests[i].name);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000643 mctp_core_tests[i].test();
644 mctp_prlog(MCTP_LOG_DEBUG, "end: %s\n",
Andrew Jeffery31b01e02022-09-30 14:12:32 +0930645 mctp_core_tests[i].name);
Sumanth Bhat69f545f2021-05-18 09:16:43 +0000646 }
647
648 return 0;
649}