1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Intel Corporation 3 */ 4 5 #include <rte_common.h> 6 #include <rte_hexdump.h> 7 #include <rte_mbuf.h> 8 #include <rte_malloc.h> 9 #include <rte_memcpy.h> 10 #include <rte_cycles.h> 11 12 #include <rte_service.h> 13 #include <rte_service_component.h> 14 15 #include "test.h" 16 17 /* used as the service core ID */ 18 static uint32_t slcore_id; 19 /* used as timestamp to detect if a service core is running */ 20 static uint64_t service_tick; 21 /* used as a flag to check if a function was run */ 22 static uint32_t service_remote_launch_flag; 23 24 #define SERVICE_DELAY 1 25 26 #define DUMMY_SERVICE_NAME "dummy_service" 27 #define MT_SAFE_SERVICE_NAME "mt_safe_service" 28 29 static int 30 testsuite_setup(void) 31 { 32 slcore_id = rte_get_next_lcore(/* start core */ -1, 33 /* skip main */ 1, 34 /* wrap */ 0); 35 36 return TEST_SUCCESS; 37 } 38 39 static void 40 testsuite_teardown(void) 41 { 42 /* release service cores? */ 43 } 44 45 static int32_t dummy_cb(void *args) 46 { 47 RTE_SET_USED(args); 48 service_tick++; 49 rte_delay_ms(SERVICE_DELAY); 50 return 0; 51 } 52 53 static int32_t dummy_mt_unsafe_cb(void *args) 54 { 55 /* before running test, the initialization has set pass_test to 1. 56 * If the CAS in service-cores is working correctly, the code here 57 * should never fail to take the lock. If the lock *is* taken, fail the 58 * test, because two threads are concurrently in a non-MT safe callback. 59 */ 60 uint32_t *test_params = args; 61 uint32_t *lock = &test_params[0]; 62 uint32_t *pass_test = &test_params[1]; 63 uint32_t exp = 0; 64 int lock_taken = __atomic_compare_exchange_n(lock, &exp, 1, 0, 65 __ATOMIC_RELAXED, __ATOMIC_RELAXED); 66 if (lock_taken) { 67 /* delay with the lock held */ 68 rte_delay_ms(250); 69 __atomic_store_n(lock, 0, __ATOMIC_RELAXED); 70 } else { 71 /* 2nd thread will fail to take lock, so set pass flag */ 72 *pass_test = 0; 73 } 74 75 return 0; 76 } 77 78 79 static int32_t dummy_mt_safe_cb(void *args) 80 { 81 /* Atomic checks to ensure MT safe services allow > 1 thread to 82 * concurrently run the callback. The concept is as follows; 83 * 1) if lock is available, take the lock then delay 84 * 2) if first lock is taken, and a thread arrives in the CB, we know 85 * that 2 threads are running the callback at the same time: MT safe 86 */ 87 uint32_t *test_params = args; 88 uint32_t *lock = &test_params[0]; 89 uint32_t *pass_test = &test_params[1]; 90 uint32_t exp = 0; 91 int lock_taken = __atomic_compare_exchange_n(lock, &exp, 1, 0, 92 __ATOMIC_RELAXED, __ATOMIC_RELAXED); 93 if (lock_taken) { 94 /* delay with the lock held */ 95 rte_delay_ms(250); 96 __atomic_store_n(lock, 0, __ATOMIC_RELAXED); 97 } else { 98 /* 2nd thread will fail to take lock, so set pass flag */ 99 *pass_test = 1; 100 } 101 102 return 0; 103 } 104 105 /* unregister all services */ 106 static int 107 unregister_all(void) 108 { 109 uint32_t i; 110 111 TEST_ASSERT_EQUAL(-EINVAL, rte_service_component_unregister(1000), 112 "Unregistered invalid service id"); 113 114 uint32_t c = rte_service_get_count(); 115 for (i = 0; i < c; i++) { 116 TEST_ASSERT_EQUAL(0, rte_service_component_unregister(i), 117 "Error unregistering a valid service"); 118 } 119 120 rte_service_lcore_reset_all(); 121 rte_eal_mp_wait_lcore(); 122 123 return TEST_SUCCESS; 124 } 125 126 /* Wait until service lcore not active, or for 100x SERVICE_DELAY */ 127 static void 128 wait_slcore_inactive(uint32_t slcore_id) 129 { 130 int i; 131 132 for (i = 0; rte_service_lcore_may_be_active(slcore_id) == 1 && 133 i < 100; i++) 134 rte_delay_ms(SERVICE_DELAY); 135 } 136 137 /* register a single dummy service */ 138 static int 139 dummy_register(void) 140 { 141 /* make sure there are no remains from previous tests */ 142 unregister_all(); 143 144 struct rte_service_spec service; 145 memset(&service, 0, sizeof(struct rte_service_spec)); 146 147 TEST_ASSERT_EQUAL(-EINVAL, 148 rte_service_component_register(&service, NULL), 149 "Invalid callback"); 150 service.callback = dummy_cb; 151 152 TEST_ASSERT_EQUAL(-EINVAL, 153 rte_service_component_register(&service, NULL), 154 "Invalid name"); 155 snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME); 156 157 uint32_t id; 158 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id), 159 "Failed to register valid service"); 160 161 rte_service_component_runstate_set(id, 1); 162 163 return TEST_SUCCESS; 164 } 165 166 /* verify get_by_name() service lookup */ 167 static int 168 service_get_by_name(void) 169 { 170 unregister_all(); 171 172 uint32_t sid; 173 TEST_ASSERT_EQUAL(-ENODEV, 174 rte_service_get_by_name(DUMMY_SERVICE_NAME, &sid), 175 "get by name with invalid name should return -ENODEV"); 176 TEST_ASSERT_EQUAL(-EINVAL, 177 rte_service_get_by_name(DUMMY_SERVICE_NAME, 0x0), 178 "get by name with NULL ptr should return -ENODEV"); 179 180 /* register service */ 181 struct rte_service_spec service; 182 memset(&service, 0, sizeof(struct rte_service_spec)); 183 TEST_ASSERT_EQUAL(-EINVAL, 184 rte_service_component_register(&service, NULL), 185 "Invalid callback"); 186 service.callback = dummy_cb; 187 TEST_ASSERT_EQUAL(-EINVAL, 188 rte_service_component_register(&service, NULL), 189 "Invalid name"); 190 snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME); 191 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, NULL), 192 "Failed to register valid service"); 193 194 /* we unregistered all service, now registering 1, should be id 0 */ 195 uint32_t service_id_as_expected = 0; 196 TEST_ASSERT_EQUAL(0, rte_service_get_by_name(DUMMY_SERVICE_NAME, &sid), 197 "Service get_by_name should return 0 on valid inputs"); 198 TEST_ASSERT_EQUAL(service_id_as_expected, sid, 199 "Service get_by_name should equal expected id"); 200 201 unregister_all(); 202 203 /* ensure after unregister, get_by_name returns NULL */ 204 TEST_ASSERT_EQUAL(-ENODEV, 205 rte_service_get_by_name(DUMMY_SERVICE_NAME, &sid), 206 "get by name should return -ENODEV after unregister"); 207 208 return TEST_SUCCESS; 209 } 210 211 /* verify probe of capabilities */ 212 static int 213 service_probe_capability(void) 214 { 215 unregister_all(); 216 217 struct rte_service_spec service; 218 memset(&service, 0, sizeof(struct rte_service_spec)); 219 service.callback = dummy_cb; 220 snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME); 221 service.capabilities |= RTE_SERVICE_CAP_MT_SAFE; 222 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, NULL), 223 "Register of MT SAFE service failed"); 224 225 /* verify flag is enabled */ 226 const uint32_t sid = 0; 227 int32_t mt = rte_service_probe_capability(sid, RTE_SERVICE_CAP_MT_SAFE); 228 TEST_ASSERT_EQUAL(1, mt, "MT SAFE capability flag not set."); 229 230 231 unregister_all(); 232 233 memset(&service, 0, sizeof(struct rte_service_spec)); 234 service.callback = dummy_cb; 235 snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME); 236 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, NULL), 237 "Register of non-MT safe service failed"); 238 239 /* verify flag is enabled */ 240 mt = rte_service_probe_capability(sid, RTE_SERVICE_CAP_MT_SAFE); 241 TEST_ASSERT_EQUAL(0, mt, "MT SAFE cap flag set on non MT SAFE service"); 242 243 return unregister_all(); 244 } 245 246 /* verify the service name */ 247 static int 248 service_name(void) 249 { 250 const char *name = rte_service_get_name(0); 251 int equal = strcmp(name, DUMMY_SERVICE_NAME); 252 TEST_ASSERT_EQUAL(0, equal, "Error: Service name not correct"); 253 254 return unregister_all(); 255 } 256 257 /* verify service attr get */ 258 static int 259 service_attr_get(void) 260 { 261 /* ensure all services unregistered so cycle counts are zero */ 262 unregister_all(); 263 264 struct rte_service_spec service; 265 memset(&service, 0, sizeof(struct rte_service_spec)); 266 service.callback = dummy_cb; 267 snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME); 268 service.capabilities |= RTE_SERVICE_CAP_MT_SAFE; 269 uint32_t id; 270 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id), 271 "Register of service failed"); 272 rte_service_component_runstate_set(id, 1); 273 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(id, 1), 274 "Error: Service start returned non-zero"); 275 rte_service_set_stats_enable(id, 1); 276 277 uint32_t attr_id = UINT32_MAX; 278 uint64_t attr_value = 0xdead; 279 /* check error return values */ 280 TEST_ASSERT_EQUAL(-EINVAL, rte_service_attr_get(id, attr_id, 281 &attr_value), 282 "Invalid attr_id didn't return -EINVAL"); 283 284 attr_id = RTE_SERVICE_ATTR_CYCLES; 285 TEST_ASSERT_EQUAL(-EINVAL, rte_service_attr_get(UINT32_MAX, attr_id, 286 &attr_value), 287 "Invalid service id didn't return -EINVAL"); 288 289 TEST_ASSERT_EQUAL(-EINVAL, rte_service_attr_get(id, attr_id, NULL), 290 "Invalid attr_value pointer id didn't return -EINVAL"); 291 292 /* check correct (zero) return value and correct value (zero) */ 293 TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_id, &attr_value), 294 "Valid attr_get() call didn't return success"); 295 TEST_ASSERT_EQUAL(0, attr_value, 296 "attr_get() call didn't set correct cycles (zero)"); 297 /* check correct call count */ 298 const int attr_calls = RTE_SERVICE_ATTR_CALL_COUNT; 299 TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_calls, &attr_value), 300 "Valid attr_get() call didn't return success"); 301 TEST_ASSERT_EQUAL(0, attr_value, 302 "attr_get() call didn't get call count (zero)"); 303 304 /* Call service to increment cycle count */ 305 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 306 "Service core add did not return zero"); 307 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(id, slcore_id, 1), 308 "Enabling valid service and core failed"); 309 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id), 310 "Starting service core failed"); 311 312 /* wait for the service lcore to run */ 313 rte_delay_ms(200); 314 315 TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_id, &attr_value), 316 "Valid attr_get() call didn't return success"); 317 int cycles_gt_zero = attr_value > 0; 318 TEST_ASSERT_EQUAL(1, cycles_gt_zero, 319 "attr_get() failed to get cycles (expected > zero)"); 320 321 rte_service_lcore_stop(slcore_id); 322 323 wait_slcore_inactive(slcore_id); 324 325 TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_calls, &attr_value), 326 "Valid attr_get() call didn't return success"); 327 TEST_ASSERT_EQUAL(1, (attr_value > 0), 328 "attr_get() call didn't get call count (zero)"); 329 330 TEST_ASSERT_EQUAL(0, rte_service_attr_reset_all(id), 331 "Valid attr_reset_all() return success"); 332 333 TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_id, &attr_value), 334 "Valid attr_get() call didn't return success"); 335 TEST_ASSERT_EQUAL(0, attr_value, 336 "attr_get() call didn't set correct cycles (zero)"); 337 /* ensure call count > zero */ 338 TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_calls, &attr_value), 339 "Valid attr_get() call didn't return success"); 340 TEST_ASSERT_EQUAL(0, (attr_value > 0), 341 "attr_get() call didn't get call count (zero)"); 342 343 return unregister_all(); 344 } 345 346 /* verify service lcore attr get */ 347 static int 348 service_lcore_attr_get(void) 349 { 350 /* ensure all services unregistered so cycle counts are zero */ 351 unregister_all(); 352 353 struct rte_service_spec service; 354 memset(&service, 0, sizeof(struct rte_service_spec)); 355 service.callback = dummy_cb; 356 snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME); 357 service.capabilities |= RTE_SERVICE_CAP_MT_SAFE; 358 uint32_t id; 359 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id), 360 "Register of service failed"); 361 rte_service_component_runstate_set(id, 1); 362 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(id, 1), 363 "Error: Service start returned non-zero"); 364 rte_service_set_stats_enable(id, 1); 365 366 uint64_t lcore_attr_value = 0xdead; 367 uint32_t lcore_attr_id = UINT32_MAX; 368 369 /* check error return values */ 370 TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_attr_get(UINT32_MAX, 371 lcore_attr_id, &lcore_attr_value), 372 "Invalid lcore_id didn't return -EINVAL"); 373 TEST_ASSERT_EQUAL(-ENOTSUP, rte_service_lcore_attr_get(rte_lcore_id(), 374 lcore_attr_id, &lcore_attr_value), 375 "Non-service core didn't return -ENOTSUP"); 376 377 /* Start service core to increment loop count */ 378 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 379 "Service core add did not return zero"); 380 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(id, slcore_id, 1), 381 "Enabling valid service and core failed"); 382 /* Ensure service is not active before starting */ 383 TEST_ASSERT_EQUAL(0, rte_service_lcore_may_be_active(slcore_id), 384 "Not-active service core reported as active"); 385 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id), 386 "Starting service core failed"); 387 388 /* wait for the service lcore to run */ 389 rte_delay_ms(200); 390 391 lcore_attr_id = RTE_SERVICE_LCORE_ATTR_LOOPS; 392 TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_get(slcore_id, 393 lcore_attr_id, &lcore_attr_value), 394 "Valid lcore_attr_get() call didn't return success"); 395 int loops_gt_zero = lcore_attr_value > 0; 396 TEST_ASSERT_EQUAL(1, loops_gt_zero, 397 "lcore_attr_get() failed to get loops " 398 "(expected > zero)"); 399 400 lcore_attr_id++; // invalid lcore attr id 401 TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_attr_get(slcore_id, 402 lcore_attr_id, &lcore_attr_value), 403 "Invalid lcore attr didn't return -EINVAL"); 404 405 /* Ensure service is active */ 406 TEST_ASSERT_EQUAL(1, rte_service_lcore_may_be_active(slcore_id), 407 "Active service core reported as not-active"); 408 409 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(id, slcore_id, 0), 410 "Disabling valid service and core failed"); 411 TEST_ASSERT_EQUAL(0, rte_service_lcore_stop(slcore_id), 412 "Failed to stop service lcore"); 413 414 wait_slcore_inactive(slcore_id); 415 416 TEST_ASSERT_EQUAL(0, rte_service_lcore_may_be_active(slcore_id), 417 "Service lcore not stopped after waiting."); 418 419 TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_reset_all(slcore_id), 420 "Valid lcore_attr_reset_all() didn't return success"); 421 422 lcore_attr_id = RTE_SERVICE_LCORE_ATTR_LOOPS; 423 TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_get(slcore_id, 424 lcore_attr_id, &lcore_attr_value), 425 "Valid lcore_attr_get() call didn't return success"); 426 TEST_ASSERT_EQUAL(0, lcore_attr_value, 427 "lcore_attr_get() didn't get correct loop count " 428 "(zero)"); 429 430 return unregister_all(); 431 } 432 433 /* verify service dump */ 434 static int 435 service_dump(void) 436 { 437 const uint32_t sid = 0; 438 rte_service_set_stats_enable(sid, 1); 439 rte_service_dump(stdout, 0); 440 rte_service_set_stats_enable(sid, 0); 441 rte_service_dump(stdout, 0); 442 return unregister_all(); 443 } 444 445 /* start and stop a service */ 446 static int 447 service_start_stop(void) 448 { 449 const uint32_t sid = 0; 450 451 /* runstate_get() returns if service is running and slcore is mapped */ 452 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 453 "Service core add did not return zero"); 454 int ret = rte_service_map_lcore_set(sid, slcore_id, 1); 455 TEST_ASSERT_EQUAL(0, ret, 456 "Enabling service core, expected 0 got %d", ret); 457 458 TEST_ASSERT_EQUAL(0, rte_service_runstate_get(sid), 459 "Error: Service should be stopped"); 460 461 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 462 "Error: Service stopped returned non-zero"); 463 464 TEST_ASSERT_EQUAL(0, rte_service_runstate_get(sid), 465 "Error: Service is running - should be stopped"); 466 467 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 468 "Error: Service start returned non-zero"); 469 470 TEST_ASSERT_EQUAL(1, rte_service_runstate_get(sid), 471 "Error: Service is not running"); 472 473 return unregister_all(); 474 } 475 476 477 static int 478 service_remote_launch_func(void *arg) 479 { 480 RTE_SET_USED(arg); 481 service_remote_launch_flag = 1; 482 return 0; 483 } 484 485 /* enable and disable a lcore for a service */ 486 static int 487 service_lcore_en_dis_able(void) 488 { 489 const uint32_t sid = 0; 490 491 /* expected failure cases */ 492 TEST_ASSERT_EQUAL(-EINVAL, rte_service_map_lcore_set(sid, 100000, 1), 493 "Enable on invalid core did not fail"); 494 TEST_ASSERT_EQUAL(-EINVAL, rte_service_map_lcore_set(sid, 100000, 0), 495 "Disable on invalid core did not fail"); 496 497 /* add service core to allow enabling */ 498 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 499 "Add service core failed when not in use before"); 500 501 /* valid enable */ 502 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1), 503 "Enabling valid service and core failed"); 504 TEST_ASSERT_EQUAL(1, rte_service_map_lcore_get(sid, slcore_id), 505 "Enabled core returned not-enabled"); 506 507 /* valid disable */ 508 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 0), 509 "Disabling valid service and lcore failed"); 510 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_get(sid, slcore_id), 511 "Disabled core returned enabled"); 512 513 /* call remote_launch to verify that app can launch ex-service lcore */ 514 service_remote_launch_flag = 0; 515 rte_eal_wait_lcore(slcore_id); 516 int ret = rte_eal_remote_launch(service_remote_launch_func, NULL, 517 slcore_id); 518 TEST_ASSERT_EQUAL(0, ret, "Ex-service core remote launch failed."); 519 rte_eal_wait_lcore(slcore_id); 520 TEST_ASSERT_EQUAL(1, service_remote_launch_flag, 521 "Ex-service core function call had no effect."); 522 523 return unregister_all(); 524 } 525 526 static int 527 service_lcore_running_check(void) 528 { 529 uint64_t tick = service_tick; 530 rte_delay_ms(SERVICE_DELAY * 100); 531 /* if (tick != service_tick) we know the lcore as polled the service */ 532 return tick != service_tick; 533 } 534 535 static int 536 service_lcore_add_del(void) 537 { 538 if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) || 539 !rte_lcore_is_enabled(2) || !rte_lcore_is_enabled(3)) 540 return TEST_SKIPPED; 541 542 /* check initial count */ 543 TEST_ASSERT_EQUAL(0, rte_service_lcore_count(), 544 "Service lcore count has value before adding a lcore"); 545 546 /* check service lcore add */ 547 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 548 "Add service core failed when not in use before"); 549 TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_add(slcore_id), 550 "Add service core failed to refuse in-use lcore"); 551 552 /* check count */ 553 TEST_ASSERT_EQUAL(1, rte_service_lcore_count(), 554 "Service core count not equal to one"); 555 556 /* retrieve core list, checking lcore ids */ 557 const uint32_t size = 4; 558 uint32_t service_core_ids[size]; 559 int32_t n = rte_service_lcore_list(service_core_ids, size); 560 TEST_ASSERT_EQUAL(1, n, "Service core list return should equal 1"); 561 TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0], 562 "Service core list lcore must equal slcore_id"); 563 564 /* recheck count, add more cores, and check count */ 565 TEST_ASSERT_EQUAL(1, rte_service_lcore_count(), 566 "Service core count not equal to one"); 567 uint32_t slcore_1 = rte_get_next_lcore(/* start core */ -1, 568 /* skip main */ 1, 569 /* wrap */ 0); 570 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_1), 571 "Service core add did not return zero"); 572 uint32_t slcore_2 = rte_get_next_lcore(/* start core */ slcore_1, 573 /* skip main */ 1, 574 /* wrap */ 0); 575 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_2), 576 "Service core add did not return zero"); 577 578 uint32_t count = rte_service_lcore_count(); 579 const uint32_t cores_at_this_point = 3; 580 TEST_ASSERT_EQUAL(cores_at_this_point, count, 581 "Service core count %d, expected %d", count, 582 cores_at_this_point); 583 584 /* check longer service core list */ 585 n = rte_service_lcore_list(service_core_ids, size); 586 TEST_ASSERT_EQUAL(3, n, "Service core list return should equal 3"); 587 TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0], 588 "Service core list[0] lcore must equal 1"); 589 TEST_ASSERT_EQUAL(slcore_1, service_core_ids[1], 590 "Service core list[1] lcore must equal 2"); 591 TEST_ASSERT_EQUAL(slcore_2, service_core_ids[2], 592 "Service core list[2] lcore must equal 3"); 593 594 /* recheck count, remove lcores, check remaining lcore_id is correct */ 595 TEST_ASSERT_EQUAL(3, rte_service_lcore_count(), 596 "Service core count not equal to three"); 597 TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_1), 598 "Service core add did not return zero"); 599 TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_2), 600 "Service core add did not return zero"); 601 TEST_ASSERT_EQUAL(1, rte_service_lcore_count(), 602 "Service core count not equal to one"); 603 n = rte_service_lcore_list(service_core_ids, size); 604 TEST_ASSERT_EQUAL(1, n, "Service core list return should equal one"); 605 TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0], 606 "Service core list[0] lcore must equal %d", 607 slcore_id); 608 609 return unregister_all(); 610 } 611 612 static int 613 service_threaded_test(int mt_safe) 614 { 615 unregister_all(); 616 617 /* add next 2 cores */ 618 uint32_t slcore_1 = rte_get_next_lcore(/* start core */ -1, 619 /* skip main */ 1, 620 /* wrap */ 0); 621 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_1), 622 "mt safe lcore add fail"); 623 uint32_t slcore_2 = rte_get_next_lcore(/* start core */ slcore_1, 624 /* skip main */ 1, 625 /* wrap */ 0); 626 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_2), 627 "mt safe lcore add fail"); 628 629 /* Use locks to verify that two threads are in the same function 630 * at the same time. These are passed to the unit tests through 631 * the callback userdata parameter. 632 */ 633 uint32_t test_params[2]; 634 memset(test_params, 0, sizeof(uint32_t) * 2); 635 636 /* register MT safe service. */ 637 struct rte_service_spec service; 638 memset(&service, 0, sizeof(struct rte_service_spec)); 639 service.callback_userdata = test_params; 640 snprintf(service.name, sizeof(service.name), MT_SAFE_SERVICE_NAME); 641 642 if (mt_safe) { 643 service.callback = dummy_mt_safe_cb; 644 service.capabilities |= RTE_SERVICE_CAP_MT_SAFE; 645 } else 646 service.callback = dummy_mt_unsafe_cb; 647 648 uint32_t id; 649 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id), 650 "Register of MT SAFE service failed"); 651 652 const uint32_t sid = 0; 653 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 654 "Starting valid service failed"); 655 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_1, 1), 656 "Failed to enable lcore 1 on mt safe service"); 657 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_2, 1), 658 "Failed to enable lcore 2 on mt safe service"); 659 rte_service_lcore_start(slcore_1); 660 rte_service_lcore_start(slcore_2); 661 662 /* wait for the worker threads to run */ 663 rte_delay_ms(500); 664 rte_service_lcore_stop(slcore_1); 665 rte_service_lcore_stop(slcore_2); 666 667 TEST_ASSERT_EQUAL(0, test_params[1], 668 "Service run with component runstate = 0"); 669 670 /* enable backend runstate: the service should run after this */ 671 rte_service_component_runstate_set(id, 1); 672 673 /* initialize to pass, see callback comment for details */ 674 if (!mt_safe) 675 test_params[1] = 1; 676 677 /* wait for lcores before start() */ 678 rte_eal_wait_lcore(slcore_1); 679 rte_eal_wait_lcore(slcore_2); 680 681 rte_service_lcore_start(slcore_1); 682 rte_service_lcore_start(slcore_2); 683 684 /* wait for the worker threads to run */ 685 rte_delay_ms(500); 686 rte_service_lcore_stop(slcore_1); 687 rte_service_lcore_stop(slcore_2); 688 689 TEST_ASSERT_EQUAL(1, test_params[1], 690 "MT Safe service not run by two cores concurrently"); 691 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 692 "Failed to stop MT Safe service"); 693 694 rte_eal_wait_lcore(slcore_1); 695 rte_eal_wait_lcore(slcore_2); 696 unregister_all(); 697 698 /* return the value of the callback pass_test variable to caller */ 699 return test_params[1]; 700 } 701 702 /* tests an MT SAFE service with two cores. The callback function ensures that 703 * two threads access the callback concurrently. 704 */ 705 static int 706 service_mt_safe_poll(void) 707 { 708 int mt_safe = 1; 709 710 if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) || 711 !rte_lcore_is_enabled(2)) 712 return TEST_SKIPPED; 713 714 TEST_ASSERT_EQUAL(1, service_threaded_test(mt_safe), 715 "Error: MT Safe service not run by two cores concurrently"); 716 return TEST_SUCCESS; 717 } 718 719 /* tests a NON mt safe service with two cores, the callback is serialized 720 * using the CAS. 721 */ 722 static int 723 service_mt_unsafe_poll(void) 724 { 725 int mt_safe = 0; 726 727 if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) || 728 !rte_lcore_is_enabled(2)) 729 return TEST_SKIPPED; 730 731 TEST_ASSERT_EQUAL(1, service_threaded_test(mt_safe), 732 "Error: NON MT Safe service run by two cores concurrently"); 733 return TEST_SUCCESS; 734 } 735 736 static int32_t 737 delay_as_a_mt_safe_service(void *args) 738 { 739 RTE_SET_USED(args); 740 uint32_t *params = args; 741 742 /* retrieve done flag and lock to add/sub */ 743 uint32_t *done = ¶ms[0]; 744 uint32_t *lock = ¶ms[1]; 745 746 while (!*done) { 747 __atomic_add_fetch(lock, 1, __ATOMIC_RELAXED); 748 rte_delay_us(500); 749 if (__atomic_load_n(lock, __ATOMIC_RELAXED) > 1) 750 /* pass: second core has simultaneously incremented */ 751 *done = 1; 752 __atomic_sub_fetch(lock, 1, __ATOMIC_RELAXED); 753 } 754 755 return 0; 756 } 757 758 static int32_t 759 delay_as_a_service(void *args) 760 { 761 uint32_t *done = (uint32_t *)args; 762 while (!*done) 763 rte_delay_ms(5); 764 return 0; 765 } 766 767 static int 768 service_run_on_app_core_func(void *arg) 769 { 770 uint32_t *delay_service_id = (uint32_t *)arg; 771 return rte_service_run_iter_on_app_lcore(*delay_service_id, 1); 772 } 773 774 static int 775 service_app_lcore_poll_impl(const int mt_safe) 776 { 777 uint32_t params[2] = {0}; 778 779 struct rte_service_spec service; 780 memset(&service, 0, sizeof(struct rte_service_spec)); 781 snprintf(service.name, sizeof(service.name), MT_SAFE_SERVICE_NAME); 782 if (mt_safe) { 783 service.callback = delay_as_a_mt_safe_service; 784 service.callback_userdata = params; 785 service.capabilities |= RTE_SERVICE_CAP_MT_SAFE; 786 } else { 787 service.callback = delay_as_a_service; 788 service.callback_userdata = ¶ms; 789 } 790 791 uint32_t id; 792 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id), 793 "Register of app lcore delay service failed"); 794 795 rte_service_component_runstate_set(id, 1); 796 rte_service_runstate_set(id, 1); 797 798 uint32_t app_core2 = rte_get_next_lcore(slcore_id, 1, 1); 799 rte_eal_wait_lcore(app_core2); 800 int app_core2_ret = rte_eal_remote_launch(service_run_on_app_core_func, 801 &id, app_core2); 802 803 rte_delay_ms(100); 804 805 int app_core1_ret = service_run_on_app_core_func(&id); 806 807 /* flag done, then wait for the spawned 2nd core to return */ 808 params[0] = 1; 809 rte_eal_mp_wait_lcore(); 810 811 /* core two gets launched first - and should hold the service lock */ 812 TEST_ASSERT_EQUAL(0, app_core2_ret, 813 "App core2 : run service didn't return zero"); 814 815 if (mt_safe) { 816 /* mt safe should have both cores return 0 for success */ 817 TEST_ASSERT_EQUAL(0, app_core1_ret, 818 "MT Safe: App core1 didn't return 0"); 819 } else { 820 /* core one attempts to run later - should be blocked */ 821 TEST_ASSERT_EQUAL(-EBUSY, app_core1_ret, 822 "MT Unsafe: App core1 didn't return -EBUSY"); 823 } 824 825 /* Performance test: call in a loop, and measure tsc() */ 826 const uint32_t perf_iters = (1 << 12); 827 uint64_t start = rte_rdtsc(); 828 uint32_t i; 829 for (i = 0; i < perf_iters; i++) { 830 int err = service_run_on_app_core_func(&id); 831 TEST_ASSERT_EQUAL(0, err, "perf test: returned run failure"); 832 } 833 uint64_t end = rte_rdtsc(); 834 printf("perf test for %s: %0.1f cycles per call\n", mt_safe ? 835 "MT Safe" : "MT Unsafe", (end - start)/(float)perf_iters); 836 837 unregister_all(); 838 return TEST_SUCCESS; 839 } 840 841 static int 842 service_app_lcore_mt_safe(void) 843 { 844 const int mt_safe = 1; 845 return service_app_lcore_poll_impl(mt_safe); 846 } 847 848 static int 849 service_app_lcore_mt_unsafe(void) 850 { 851 const int mt_safe = 0; 852 return service_app_lcore_poll_impl(mt_safe); 853 } 854 855 /* start and stop a service core - ensuring it goes back to sleep */ 856 static int 857 service_lcore_start_stop(void) 858 { 859 /* start service core and service, create mapping so tick() runs */ 860 const uint32_t sid = 0; 861 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 862 "Starting valid service failed"); 863 TEST_ASSERT_EQUAL(-EINVAL, rte_service_map_lcore_set(sid, slcore_id, 1), 864 "Enabling valid service on non-service core must fail"); 865 866 /* core start */ 867 TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_start(slcore_id), 868 "Service core start without add should return EINVAL"); 869 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 870 "Service core add did not return zero"); 871 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1), 872 "Enabling valid service on valid core failed"); 873 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id), 874 "Service core start after add failed"); 875 TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_start(slcore_id), 876 "Service core expected as running but was stopped"); 877 878 /* ensures core really is running the service function */ 879 TEST_ASSERT_EQUAL(1, service_lcore_running_check(), 880 "Service core expected to poll service but it didn't"); 881 882 /* core stop */ 883 TEST_ASSERT_EQUAL(-EBUSY, rte_service_lcore_stop(slcore_id), 884 "Service core running a service should return -EBUSY"); 885 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 886 "Stopping valid service failed"); 887 TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_stop(100000), 888 "Invalid Service core stop should return -EINVAL"); 889 TEST_ASSERT_EQUAL(0, rte_service_lcore_stop(slcore_id), 890 "Service core stop expected to return 0"); 891 TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_stop(slcore_id), 892 "Already stopped service core should return -EALREADY"); 893 894 /* ensure service is not longer running */ 895 TEST_ASSERT_EQUAL(0, service_lcore_running_check(), 896 "Service core expected to poll service but it didn't"); 897 898 TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_id), 899 "Service core del did not return zero"); 900 901 return unregister_all(); 902 } 903 904 /* stop a service and wait for it to become inactive */ 905 static int 906 service_may_be_active(void) 907 { 908 const uint32_t sid = 0; 909 int i; 910 911 /* expected failure cases */ 912 TEST_ASSERT_EQUAL(-EINVAL, rte_service_may_be_active(10000), 913 "Invalid service may be active check did not fail"); 914 915 /* start the service */ 916 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 917 "Starting valid service failed"); 918 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 919 "Add service core failed when not in use before"); 920 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1), 921 "Enabling valid service on valid core failed"); 922 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id), 923 "Service core start after add failed"); 924 925 /* ensures core really is running the service function */ 926 TEST_ASSERT_EQUAL(1, service_lcore_running_check(), 927 "Service core expected to poll service but it didn't"); 928 929 /* stop the service */ 930 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 931 "Error: Service stop returned non-zero"); 932 933 /* give the service 100ms to stop running */ 934 for (i = 0; i < 100; i++) { 935 if (!rte_service_may_be_active(sid)) 936 break; 937 rte_delay_ms(SERVICE_DELAY); 938 } 939 940 TEST_ASSERT_EQUAL(0, rte_service_may_be_active(sid), 941 "Error: Service not stopped after 100ms"); 942 943 return unregister_all(); 944 } 945 946 /* check service may be active when service is running on a second lcore */ 947 static int 948 service_active_two_cores(void) 949 { 950 if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) || 951 !rte_lcore_is_enabled(2)) 952 return TEST_SKIPPED; 953 954 const uint32_t sid = 0; 955 int i; 956 957 uint32_t lcore = rte_get_next_lcore(/* start core */ -1, 958 /* skip main */ 1, 959 /* wrap */ 0); 960 uint32_t slcore = rte_get_next_lcore(/* start core */ lcore, 961 /* skip main */ 1, 962 /* wrap */ 0); 963 964 /* start the service on the second available lcore */ 965 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 966 "Starting valid service failed"); 967 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore), 968 "Add service core failed when not in use before"); 969 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore, 1), 970 "Enabling valid service on valid core failed"); 971 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore), 972 "Service core start after add failed"); 973 974 /* ensures core really is running the service function */ 975 TEST_ASSERT_EQUAL(1, service_lcore_running_check(), 976 "Service core expected to poll service but it didn't"); 977 978 /* ensures that service may be active reports running state */ 979 TEST_ASSERT_EQUAL(1, rte_service_may_be_active(sid), 980 "Service may be active did not report running state"); 981 982 /* stop the service */ 983 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 984 "Error: Service stop returned non-zero"); 985 986 /* give the service 100ms to stop running */ 987 for (i = 0; i < 100; i++) { 988 if (!rte_service_may_be_active(sid)) 989 break; 990 rte_delay_ms(SERVICE_DELAY); 991 } 992 993 TEST_ASSERT_EQUAL(0, rte_service_may_be_active(sid), 994 "Error: Service not stopped after 100ms"); 995 996 return unregister_all(); 997 } 998 999 static struct unit_test_suite service_tests = { 1000 .suite_name = "service core test suite", 1001 .setup = testsuite_setup, 1002 .teardown = testsuite_teardown, 1003 .unit_test_cases = { 1004 TEST_CASE_ST(dummy_register, NULL, unregister_all), 1005 TEST_CASE_ST(dummy_register, NULL, service_name), 1006 TEST_CASE_ST(dummy_register, NULL, service_get_by_name), 1007 TEST_CASE_ST(dummy_register, NULL, service_dump), 1008 TEST_CASE_ST(dummy_register, NULL, service_attr_get), 1009 TEST_CASE_ST(dummy_register, NULL, service_lcore_attr_get), 1010 TEST_CASE_ST(dummy_register, NULL, service_probe_capability), 1011 TEST_CASE_ST(dummy_register, NULL, service_start_stop), 1012 TEST_CASE_ST(dummy_register, NULL, service_lcore_add_del), 1013 TEST_CASE_ST(dummy_register, NULL, service_lcore_start_stop), 1014 TEST_CASE_ST(dummy_register, NULL, service_lcore_en_dis_able), 1015 TEST_CASE_ST(dummy_register, NULL, service_mt_unsafe_poll), 1016 TEST_CASE_ST(dummy_register, NULL, service_mt_safe_poll), 1017 TEST_CASE_ST(dummy_register, NULL, service_app_lcore_mt_safe), 1018 TEST_CASE_ST(dummy_register, NULL, service_app_lcore_mt_unsafe), 1019 TEST_CASE_ST(dummy_register, NULL, service_may_be_active), 1020 TEST_CASE_ST(dummy_register, NULL, service_active_two_cores), 1021 TEST_CASES_END() /**< NULL terminate unit test array */ 1022 } 1023 }; 1024 1025 static int 1026 test_service_common(void) 1027 { 1028 return unit_test_suite_runner(&service_tests); 1029 } 1030 1031 REGISTER_TEST_COMMAND(service_autotest, test_service_common); 1032