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_SRC_EID 10 30 31 #ifndef ARRAY_SIZE 32 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 33 #endif 34 35 #define MAX_PAYLOAD_SIZE 50000 36 37 struct pktbuf { 38 struct mctp_hdr hdr; 39 uint8_t *payload; 40 }; 41 42 struct test_params { 43 bool seen; 44 size_t message_size; 45 uint8_t msg_tag; 46 bool tag_owner; 47 }; 48 49 static void rx_message(uint8_t eid __unused, bool tag_owner, uint8_t msg_tag, 50 void *data, void *msg __unused, size_t len) 51 { 52 struct test_params *param = (struct test_params *)data; 53 54 mctp_prdebug("MCTP message received: len %zd, tag %u", len, msg_tag); 55 56 param->seen = true; 57 param->message_size = len; 58 param->msg_tag = msg_tag; 59 param->tag_owner = tag_owner; 60 } 61 62 static uint8_t get_sequence() 63 { 64 static uint8_t pkt_seq = 0; 65 66 return (pkt_seq++ % 4); 67 } 68 69 static uint8_t get_tag() 70 { 71 static uint8_t tag = 0; 72 73 return (tag++ % 8); 74 } 75 76 /* 77 * receive_pktbuf bypasses all bindings and directly invokes mctp_bus_rx. 78 * This is necessary in order invoke test cases on the core functionality. 79 * The memory allocated for the mctp packet is capped at MCTP_BTU 80 * size, however, the mimiced rx pkt still retains the len parameter. 81 * This allows to mimic packets larger than a sane memory allocator can 82 * provide. 83 */ 84 static void receive_ptkbuf(struct mctp_binding_test *binding, 85 const struct pktbuf *pktbuf, size_t len) 86 { 87 size_t alloc_size = MIN((size_t)MCTP_BTU, len); 88 struct mctp_pktbuf *rx_pkt; 89 90 rx_pkt = __mctp_alloc(sizeof(*rx_pkt) + MCTP_PACKET_SIZE(alloc_size)); 91 assert(rx_pkt); 92 93 /* Preserve passed len parameter */ 94 rx_pkt->size = MCTP_PACKET_SIZE(len); 95 rx_pkt->start = 0; 96 rx_pkt->end = MCTP_PACKET_SIZE(len); 97 rx_pkt->mctp_hdr_off = 0; 98 rx_pkt->next = NULL; 99 memcpy(rx_pkt->data, &pktbuf->hdr, sizeof(pktbuf->hdr)); 100 memcpy(rx_pkt->data + sizeof(pktbuf->hdr), pktbuf->payload, alloc_size); 101 102 mctp_bus_rx((struct mctp_binding *)binding, rx_pkt); 103 } 104 105 static void receive_one_fragment(struct mctp_binding_test *binding, 106 uint8_t *payload, size_t fragment_size, 107 uint8_t flags_seq_tag, struct pktbuf *pktbuf) 108 { 109 pktbuf->hdr.flags_seq_tag = flags_seq_tag; 110 pktbuf->payload = payload; 111 receive_ptkbuf(binding, pktbuf, fragment_size); 112 } 113 114 static void receive_two_fragment_message(struct mctp_binding_test *binding, 115 uint8_t *payload, 116 size_t fragment1_size, 117 size_t fragment2_size, 118 struct pktbuf *pktbuf) 119 { 120 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag(); 121 uint8_t flags_seq_tag; 122 123 flags_seq_tag = MCTP_HDR_FLAG_SOM | 124 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 125 receive_one_fragment(binding, payload, fragment1_size, flags_seq_tag, 126 pktbuf); 127 128 flags_seq_tag = MCTP_HDR_FLAG_EOM | 129 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 130 receive_one_fragment(binding, payload + fragment1_size, fragment2_size, 131 flags_seq_tag, pktbuf); 132 } 133 134 static void mctp_core_test_simple_rx() 135 { 136 struct mctp *mctp = NULL; 137 struct mctp_binding_test *binding = NULL; 138 struct test_params test_param; 139 uint8_t test_payload[2 * MCTP_BTU]; 140 struct pktbuf pktbuf; 141 142 memset(test_payload, 0, sizeof(test_payload)); 143 test_param.seen = false; 144 test_param.message_size = 0; 145 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID); 146 mctp_set_rx_all(mctp, rx_message, &test_param); 147 memset(&pktbuf, 0, sizeof(pktbuf)); 148 pktbuf.hdr.dest = TEST_DEST_EID; 149 pktbuf.hdr.src = TEST_SRC_EID; 150 151 /* Receive 2 fragments of equal size */ 152 receive_two_fragment_message(binding, test_payload, MCTP_BTU, MCTP_BTU, 153 &pktbuf); 154 155 assert(test_param.seen); 156 assert(test_param.message_size == 2 * MCTP_BTU); 157 158 mctp_binding_test_destroy(binding); 159 mctp_destroy(mctp); 160 } 161 162 static void mctp_core_test_receive_equal_length_fragments() 163 { 164 struct mctp *mctp = NULL; 165 struct mctp_binding_test *binding = NULL; 166 struct test_params test_param; 167 static uint8_t test_payload[MAX_PAYLOAD_SIZE]; 168 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag(); 169 struct pktbuf pktbuf; 170 uint8_t flags_seq_tag; 171 172 memset(test_payload, 0, sizeof(test_payload)); 173 test_param.seen = false; 174 test_param.message_size = 0; 175 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID); 176 mctp_set_rx_all(mctp, rx_message, &test_param); 177 memset(&pktbuf, 0, sizeof(pktbuf)); 178 pktbuf.hdr.dest = TEST_DEST_EID; 179 pktbuf.hdr.src = TEST_SRC_EID; 180 181 /* Receive 3 fragments, each of size MCTP_BTU */ 182 flags_seq_tag = MCTP_HDR_FLAG_SOM | 183 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 184 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 185 &pktbuf); 186 187 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 188 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU, 189 flags_seq_tag, &pktbuf); 190 191 flags_seq_tag = MCTP_HDR_FLAG_EOM | 192 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 193 receive_one_fragment(binding, test_payload + (2 * MCTP_BTU), MCTP_BTU, 194 flags_seq_tag, &pktbuf); 195 196 assert(test_param.seen); 197 assert(test_param.message_size == 3 * MCTP_BTU); 198 199 mctp_binding_test_destroy(binding); 200 mctp_destroy(mctp); 201 } 202 203 static void mctp_core_test_receive_unexpected_smaller_middle_fragment() 204 { 205 struct mctp *mctp = NULL; 206 struct mctp_binding_test *binding = NULL; 207 struct test_params test_param; 208 static uint8_t test_payload[MAX_PAYLOAD_SIZE]; 209 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag(); 210 struct pktbuf pktbuf; 211 uint8_t flags_seq_tag; 212 213 memset(test_payload, 0, sizeof(test_payload)); 214 test_param.seen = false; 215 test_param.message_size = 0; 216 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID); 217 mctp_set_rx_all(mctp, rx_message, &test_param); 218 memset(&pktbuf, 0, sizeof(pktbuf)); 219 pktbuf.hdr.dest = TEST_DEST_EID; 220 pktbuf.hdr.src = TEST_SRC_EID; 221 222 /* Middle fragment with size MCTP_BTU - 1 */ 223 flags_seq_tag = MCTP_HDR_FLAG_SOM | 224 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 225 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 226 &pktbuf); 227 228 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 229 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU - 1, 230 flags_seq_tag, &pktbuf); 231 232 flags_seq_tag = MCTP_HDR_FLAG_EOM | 233 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 234 receive_one_fragment(binding, test_payload + (2 * MCTP_BTU), MCTP_BTU, 235 flags_seq_tag, &pktbuf); 236 237 assert(!test_param.seen); 238 239 mctp_binding_test_destroy(binding); 240 mctp_destroy(mctp); 241 } 242 243 static void mctp_core_test_receive_unexpected_bigger_middle_fragment() 244 { 245 struct mctp *mctp = NULL; 246 struct mctp_binding_test *binding = NULL; 247 struct test_params test_param; 248 static uint8_t test_payload[MAX_PAYLOAD_SIZE]; 249 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag(); 250 struct pktbuf pktbuf; 251 uint8_t flags_seq_tag; 252 253 memset(test_payload, 0, sizeof(test_payload)); 254 test_param.seen = false; 255 test_param.message_size = 0; 256 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID); 257 mctp_set_rx_all(mctp, rx_message, &test_param); 258 memset(&pktbuf, 0, sizeof(pktbuf)); 259 pktbuf.hdr.dest = TEST_DEST_EID; 260 pktbuf.hdr.src = TEST_SRC_EID; 261 262 /* Middle fragment with size MCTP_BTU + 1 */ 263 flags_seq_tag = MCTP_HDR_FLAG_SOM | 264 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 265 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 266 &pktbuf); 267 268 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 269 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU + 1, 270 flags_seq_tag, &pktbuf); 271 272 flags_seq_tag = MCTP_HDR_FLAG_EOM | 273 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 274 receive_one_fragment(binding, test_payload + (2 * MCTP_BTU), MCTP_BTU, 275 flags_seq_tag, &pktbuf); 276 277 assert(!test_param.seen); 278 279 mctp_binding_test_destroy(binding); 280 mctp_destroy(mctp); 281 } 282 283 static void mctp_core_test_receive_smaller_end_fragment() 284 { 285 struct mctp *mctp = NULL; 286 struct mctp_binding_test *binding = NULL; 287 struct test_params test_param; 288 static uint8_t test_payload[MAX_PAYLOAD_SIZE]; 289 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag(); 290 uint8_t end_frag_size = MCTP_BTU - 10; 291 struct pktbuf pktbuf; 292 uint8_t flags_seq_tag; 293 294 memset(test_payload, 0, sizeof(test_payload)); 295 test_param.seen = false; 296 test_param.message_size = 0; 297 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID); 298 mctp_set_rx_all(mctp, rx_message, &test_param); 299 memset(&pktbuf, 0, sizeof(pktbuf)); 300 pktbuf.hdr.dest = TEST_DEST_EID; 301 pktbuf.hdr.src = TEST_SRC_EID; 302 303 flags_seq_tag = MCTP_HDR_FLAG_SOM | 304 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 305 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 306 &pktbuf); 307 308 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 309 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU, 310 flags_seq_tag, &pktbuf); 311 312 flags_seq_tag = MCTP_HDR_FLAG_EOM | 313 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 314 receive_one_fragment(binding, test_payload + (2 * MCTP_BTU), 315 end_frag_size, flags_seq_tag, &pktbuf); 316 317 assert(test_param.seen); 318 assert(test_param.message_size == 319 (size_t)(2 * MCTP_BTU + end_frag_size)); 320 321 mctp_binding_test_destroy(binding); 322 mctp_destroy(mctp); 323 } 324 325 static void mctp_core_test_receive_bigger_end_fragment() 326 { 327 struct mctp *mctp = NULL; 328 struct mctp_binding_test *binding = NULL; 329 struct test_params test_param; 330 static uint8_t test_payload[MAX_PAYLOAD_SIZE]; 331 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag(); 332 uint8_t end_frag_size = MCTP_BTU + 10; 333 struct pktbuf pktbuf; 334 uint8_t flags_seq_tag; 335 336 memset(test_payload, 0, sizeof(test_payload)); 337 test_param.seen = false; 338 test_param.message_size = 0; 339 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID); 340 mctp_set_rx_all(mctp, rx_message, &test_param); 341 memset(&pktbuf, 0, sizeof(pktbuf)); 342 pktbuf.hdr.dest = TEST_DEST_EID; 343 pktbuf.hdr.src = TEST_SRC_EID; 344 345 flags_seq_tag = MCTP_HDR_FLAG_SOM | 346 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 347 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 348 &pktbuf); 349 350 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 351 receive_one_fragment(binding, test_payload + MCTP_BTU, MCTP_BTU, 352 flags_seq_tag, &pktbuf); 353 354 flags_seq_tag = MCTP_HDR_FLAG_EOM | 355 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 356 receive_one_fragment(binding, test_payload + (2 * MCTP_BTU), 357 end_frag_size, flags_seq_tag, &pktbuf); 358 359 assert(!test_param.seen); 360 361 mctp_binding_test_destroy(binding); 362 mctp_destroy(mctp); 363 } 364 365 static void mctp_core_test_drop_large_fragments() 366 { 367 struct mctp *mctp = NULL; 368 struct mctp_binding_test *binding = NULL; 369 struct test_params test_param; 370 static uint8_t test_payload[MAX_PAYLOAD_SIZE]; 371 struct pktbuf pktbuf; 372 373 memset(test_payload, 0, sizeof(test_payload)); 374 test_param.seen = false; 375 test_param.message_size = 0; 376 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID); 377 mctp_set_rx_all(mctp, rx_message, &test_param); 378 memset(&pktbuf, 0, sizeof(pktbuf)); 379 pktbuf.hdr.dest = TEST_DEST_EID; 380 pktbuf.hdr.src = TEST_SRC_EID; 381 382 /* Receive a large payload - first fragment with MCTP_BTU bytes, 383 * 2nd fragment of SIZE_MAX */ 384 385 receive_two_fragment_message(binding, test_payload, MCTP_BTU, 386 SIZE_MAX - sizeof(struct mctp_hdr), 387 &pktbuf); 388 389 assert(!test_param.seen); 390 391 mctp_binding_test_destroy(binding); 392 mctp_destroy(mctp); 393 } 394 395 static void mctp_core_test_exhaust_context_buffers() 396 { 397 struct mctp *mctp = NULL; 398 struct mctp_binding_test *binding = NULL; 399 struct test_params test_param; 400 static uint8_t test_payload[MAX_PAYLOAD_SIZE]; 401 uint8_t tag = MCTP_HDR_FLAG_TO | get_tag(); 402 uint8_t i = 0; 403 const uint8_t max_context_buffers = 16; 404 struct pktbuf pktbuf; 405 uint8_t flags_seq_tag; 406 407 memset(test_payload, 0, sizeof(test_payload)); 408 test_param.seen = false; 409 test_param.message_size = 0; 410 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID); 411 mctp_set_rx_all(mctp, rx_message, &test_param); 412 memset(&pktbuf, 0, sizeof(pktbuf)); 413 pktbuf.hdr.dest = TEST_DEST_EID; 414 pktbuf.hdr.src = TEST_SRC_EID; 415 416 /* Exhaust all 16 context buffers*/ 417 for (i = 0; i < max_context_buffers; i++) { 418 flags_seq_tag = MCTP_HDR_FLAG_SOM | 419 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 420 receive_one_fragment(binding, test_payload, MCTP_BTU, 421 flags_seq_tag, &pktbuf); 422 423 /* Change source EID so that different contexts are created */ 424 pktbuf.hdr.src++; 425 } 426 427 /* Send a full message from a different EID */ 428 pktbuf.hdr.src++; 429 receive_two_fragment_message(binding, test_payload, MCTP_BTU, MCTP_BTU, 430 &pktbuf); 431 432 /* Message assembly should fail */ 433 assert(!test_param.seen); 434 435 /* Complete message assembly for one of the messages */ 436 pktbuf.hdr.src -= max_context_buffers; 437 flags_seq_tag = MCTP_HDR_FLAG_EOM | 438 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | tag; 439 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 440 &pktbuf); 441 442 assert(test_param.seen); 443 assert(test_param.message_size == (2 * MCTP_BTU)); 444 445 mctp_binding_test_destroy(binding); 446 mctp_destroy(mctp); 447 } 448 449 static void mctp_core_test_rx_with_tag() 450 { 451 struct mctp *mctp = NULL; 452 struct mctp_binding_test *binding = NULL; 453 struct test_params test_param; 454 static uint8_t test_payload[MCTP_BTU]; 455 uint8_t tag = get_tag(); 456 struct pktbuf pktbuf; 457 uint8_t flags_seq_tag; 458 459 memset(test_payload, 0, sizeof(test_payload)); 460 test_param.seen = false; 461 test_param.message_size = 0; 462 test_param.msg_tag = 0; 463 test_param.tag_owner = false; 464 465 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID); 466 mctp_set_rx_all(mctp, rx_message, &test_param); 467 memset(&pktbuf, 0, sizeof(pktbuf)); 468 pktbuf.hdr.dest = TEST_DEST_EID; 469 pktbuf.hdr.src = TEST_SRC_EID; 470 471 /* Set tag and tag owner fields for a recieve packet */ 472 flags_seq_tag = MCTP_HDR_FLAG_SOM | MCTP_HDR_FLAG_EOM | 473 (1 << MCTP_HDR_TO_SHIFT) | tag; 474 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 475 &pktbuf); 476 477 assert(test_param.seen); 478 assert(test_param.message_size == (MCTP_BTU)); 479 assert(test_param.msg_tag == tag); 480 assert(test_param.tag_owner); 481 482 mctp_binding_test_destroy(binding); 483 mctp_destroy(mctp); 484 } 485 486 static void mctp_core_test_rx_with_tag_multifragment() 487 { 488 struct mctp *mctp = NULL; 489 struct mctp_binding_test *binding = NULL; 490 struct test_params test_param; 491 static uint8_t test_payload[MCTP_BTU]; 492 uint8_t tag = get_tag(); 493 struct pktbuf pktbuf; 494 uint8_t flags_seq_tag; 495 496 memset(test_payload, 0, sizeof(test_payload)); 497 test_param.seen = false; 498 test_param.message_size = 0; 499 test_param.msg_tag = 0; 500 test_param.tag_owner = false; 501 502 mctp_test_stack_init(&mctp, &binding, TEST_DEST_EID); 503 mctp_set_rx_all(mctp, rx_message, &test_param); 504 memset(&pktbuf, 0, sizeof(pktbuf)); 505 pktbuf.hdr.dest = TEST_DEST_EID; 506 pktbuf.hdr.src = TEST_SRC_EID; 507 508 /* Set tag and tag owner fields for a 3 fragment packet */ 509 flags_seq_tag = MCTP_HDR_FLAG_SOM | 510 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | 511 (1 << MCTP_HDR_TO_SHIFT) | tag; 512 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 513 &pktbuf); 514 515 flags_seq_tag = (get_sequence() << MCTP_HDR_SEQ_SHIFT) | 516 (1 << MCTP_HDR_TO_SHIFT) | tag; 517 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 518 &pktbuf); 519 520 flags_seq_tag = MCTP_HDR_FLAG_EOM | 521 (get_sequence() << MCTP_HDR_SEQ_SHIFT) | 522 (1 << MCTP_HDR_TO_SHIFT) | tag; 523 receive_one_fragment(binding, test_payload, MCTP_BTU, flags_seq_tag, 524 &pktbuf); 525 526 assert(test_param.seen); 527 assert(test_param.message_size == (3 * MCTP_BTU)); 528 assert(test_param.msg_tag == tag); 529 assert(test_param.tag_owner); 530 531 mctp_binding_test_destroy(binding); 532 mctp_destroy(mctp); 533 } 534 535 /* clang-format off */ 536 #define TEST_CASE(test) { #test, test } 537 static const struct { 538 const char *name; 539 void (*test)(void); 540 } mctp_core_tests[] = { 541 TEST_CASE(mctp_core_test_simple_rx), 542 TEST_CASE(mctp_core_test_receive_equal_length_fragments), 543 TEST_CASE(mctp_core_test_receive_unexpected_smaller_middle_fragment), 544 TEST_CASE(mctp_core_test_receive_unexpected_bigger_middle_fragment), 545 TEST_CASE(mctp_core_test_receive_smaller_end_fragment), 546 TEST_CASE(mctp_core_test_receive_bigger_end_fragment), 547 TEST_CASE(mctp_core_test_drop_large_fragments), 548 TEST_CASE(mctp_core_test_exhaust_context_buffers), 549 TEST_CASE(mctp_core_test_rx_with_tag), 550 TEST_CASE(mctp_core_test_rx_with_tag_multifragment), 551 }; 552 /* clang-format on */ 553 554 #ifndef BUILD_ASSERT 555 #define BUILD_ASSERT(x) \ 556 do { \ 557 (void)sizeof(char[0 - (!(x))]); \ 558 } while (0) 559 #endif 560 561 int main(void) 562 { 563 uint8_t i; 564 565 mctp_set_log_stdio(MCTP_LOG_DEBUG); 566 567 BUILD_ASSERT(ARRAY_SIZE(mctp_core_tests) < SIZE_MAX); 568 for (i = 0; i < ARRAY_SIZE(mctp_core_tests); i++) { 569 mctp_prlog(MCTP_LOG_DEBUG, "begin: %s", 570 mctp_core_tests[i].name); 571 mctp_core_tests[i].test(); 572 mctp_prlog(MCTP_LOG_DEBUG, "end: %s\n", 573 mctp_core_tests[i].name); 574 } 575 576 return 0; 577 } 578