1 /* 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 22 #include "compiler.h" 23 #include "libmctp-alloc.h" 24 #include "libmctp-log.h" 25 #include "range.h" 26 #include "test-utils.h" 27 28 #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 32 33 #ifndef ARRAY_SIZE 34 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 35 #endif 36 37 #define MAX_PAYLOAD_SIZE 50000 38 39 struct pktbuf { 40 struct mctp_hdr hdr; 41 uint8_t *payload; 42 }; 43 44 struct test_params { 45 bool seen; 46 size_t message_size; 47 uint8_t msg_tag; 48 bool tag_owner; 49 }; 50 51 static void rx_message(uint8_t eid __unused, bool tag_owner, uint8_t msg_tag, 52 void *data, void *msg __unused, size_t len) 53 { 54 struct test_params *param = (struct test_params *)data; 55 56 mctp_prdebug("MCTP message received: len %zd, tag %u", len, msg_tag); 57 58 param->seen = true; 59 param->message_size = len; 60 param->msg_tag = msg_tag; 61 param->tag_owner = tag_owner; 62 } 63 64 static uint8_t get_sequence() 65 { 66 static uint8_t pkt_seq = 0; 67 68 return (pkt_seq++ % 4); 69 } 70 71 static 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 */ 86 static 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 107 static void receive_one_fragment(struct mctp_binding_test *binding, 108 uint8_t *payload, size_t fragment_size, 109 uint8_t flags_seq_tag, struct pktbuf *pktbuf) 110 { 111 pktbuf->hdr.flags_seq_tag = flags_seq_tag; 112 pktbuf->payload = payload; 113 receive_ptkbuf(binding, pktbuf, fragment_size); 114 } 115 116 static void receive_two_fragment_message(struct mctp_binding_test *binding, 117 uint8_t *payload, 118 size_t fragment1_size, 119 size_t fragment2_size, 120 struct pktbuf *pktbuf) 121 { 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, 128 pktbuf); 129 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, 133 flags_seq_tag, pktbuf); 134 } 135 136 static 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, 155 &pktbuf); 156 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 164 static 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, 187 &pktbuf); 188 189 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 190 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU, 191 flags_seq_tag, &pktbuf); 192 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, 196 flags_seq_tag, &pktbuf); 197 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 205 static 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, 228 &pktbuf); 229 230 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 231 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU - 1, 232 flags_seq_tag, &pktbuf); 233 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, 237 flags_seq_tag, &pktbuf); 238 239 assert(!test_param.seen); 240 241 mctp_binding_test_destroy(binding); 242 mctp_destroy(mctp); 243 } 244 245 static 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, 268 &pktbuf); 269 270 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 271 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU + 1, 272 flags_seq_tag, &pktbuf); 273 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, 277 flags_seq_tag, &pktbuf); 278 279 assert(!test_param.seen); 280 281 mctp_binding_test_destroy(binding); 282 mctp_destroy(mctp); 283 } 284 285 static 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, 308 &pktbuf); 309 310 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 311 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU, 312 flags_seq_tag, &pktbuf); 313 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), 317 end_frag_size, flags_seq_tag, &pktbuf); 318 319 assert(test_param.seen); 320 assert(test_param.message_size == 321 (size_t)(2 * MCTP_BTU + end_frag_size)); 322 323 mctp_binding_test_destroy(binding); 324 mctp_destroy(mctp); 325 } 326 327 static 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, 350 &pktbuf); 351 352 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 353 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU, 354 flags_seq_tag, &pktbuf); 355 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), 359 end_frag_size, flags_seq_tag, &pktbuf); 360 361 assert(!test_param.seen); 362 363 mctp_binding_test_destroy(binding); 364 mctp_destroy(mctp); 365 } 366 367 static 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, 388 SIZE_MAX - sizeof(struct mctp_hdr), 389 &pktbuf); 390 391 assert(!test_param.seen); 392 393 mctp_binding_test_destroy(binding); 394 mctp_destroy(mctp); 395 } 396 397 static 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, 423 flags_seq_tag, &pktbuf); 424 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, 432 &pktbuf); 433 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; 441 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 442 &pktbuf); 443 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 451 static 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 488 static 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 537 /* 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 */ 544 static 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 */ 577 static 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 605 /* clang-format off */ 606 #define TEST_CASE(test) { #test, test } 607 static 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), 617 TEST_CASE(mctp_core_test_drop_large_fragments), 618 TEST_CASE(mctp_core_test_exhaust_context_buffers), 619 TEST_CASE(mctp_core_test_rx_with_tag), 620 TEST_CASE(mctp_core_test_rx_with_tag_multifragment), 621 TEST_CASE(mctp_core_test_rx_with_null_dst_eid), 622 TEST_CASE(mctp_core_test_rx_with_broadcast_dst_eid), 623 }; 624 /* clang-format on */ 625 626 int main(void) 627 { 628 uint8_t i; 629 630 mctp_set_log_stdio(MCTP_LOG_DEBUG); 631 632 static_assert(ARRAY_SIZE(mctp_core_tests) < SIZE_MAX, "size"); 633 for (i = 0; i < ARRAY_SIZE(mctp_core_tests); i++) { 634 mctp_prlog(MCTP_LOG_DEBUG, "begin: %s", 635 mctp_core_tests[i].name); 636 mctp_core_tests[i].test(); 637 mctp_prlog(MCTP_LOG_DEBUG, "end: %s\n", 638 mctp_core_tests[i].name); 639 } 640 641 return 0; 642 } 643