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 clear 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 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(id, slcore_id, 0), 322 "Disabling valid service and core failed"); 323 TEST_ASSERT_EQUAL(0, rte_service_lcore_stop(slcore_id), 324 "Failed to stop service lcore"); 325 326 wait_slcore_inactive(slcore_id); 327 328 TEST_ASSERT_EQUAL(0, rte_service_lcore_may_be_active(slcore_id), 329 "Service lcore not stopped after waiting."); 330 331 TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_calls, &attr_value), 332 "Valid attr_get() call didn't return success"); 333 TEST_ASSERT_EQUAL(1, (attr_value > 0), 334 "attr_get() call didn't get call count (zero)"); 335 336 TEST_ASSERT_EQUAL(0, rte_service_attr_reset_all(id), 337 "Valid attr_reset_all() return success"); 338 339 TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_id, &attr_value), 340 "Valid attr_get() call didn't return success"); 341 TEST_ASSERT_EQUAL(0, attr_value, 342 "attr_get() call didn't set correct cycles (zero)"); 343 /* ensure call count > zero */ 344 TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_calls, &attr_value), 345 "Valid attr_get() call didn't return success"); 346 TEST_ASSERT_EQUAL(0, (attr_value > 0), 347 "attr_get() call didn't get call count (zero)"); 348 349 return unregister_all(); 350 } 351 352 /* verify service lcore attr get */ 353 static int 354 service_lcore_attr_get(void) 355 { 356 /* ensure all services unregistered so cycle counts are zero */ 357 unregister_all(); 358 359 struct rte_service_spec service; 360 memset(&service, 0, sizeof(struct rte_service_spec)); 361 service.callback = dummy_cb; 362 snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME); 363 service.capabilities |= RTE_SERVICE_CAP_MT_SAFE; 364 uint32_t id; 365 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id), 366 "Register of service failed"); 367 rte_service_component_runstate_set(id, 1); 368 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(id, 1), 369 "Error: Service start returned non-zero"); 370 rte_service_set_stats_enable(id, 1); 371 372 uint64_t lcore_attr_value = 0xdead; 373 uint32_t lcore_attr_id = UINT32_MAX; 374 375 /* check error return values */ 376 TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_attr_get(UINT32_MAX, 377 lcore_attr_id, &lcore_attr_value), 378 "Invalid lcore_id didn't return -EINVAL"); 379 TEST_ASSERT_EQUAL(-ENOTSUP, rte_service_lcore_attr_get(rte_lcore_id(), 380 lcore_attr_id, &lcore_attr_value), 381 "Non-service core didn't return -ENOTSUP"); 382 383 /* Start service core to increment loop count */ 384 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 385 "Service core add did not return zero"); 386 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(id, slcore_id, 1), 387 "Enabling valid service and core failed"); 388 /* Ensure service is not active before starting */ 389 TEST_ASSERT_EQUAL(0, rte_service_lcore_may_be_active(slcore_id), 390 "Not-active service core reported as active"); 391 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id), 392 "Starting service core failed"); 393 394 /* wait for the service lcore to run */ 395 rte_delay_ms(200); 396 397 lcore_attr_id = RTE_SERVICE_LCORE_ATTR_LOOPS; 398 TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_get(slcore_id, 399 lcore_attr_id, &lcore_attr_value), 400 "Valid lcore_attr_get() call didn't return success"); 401 int loops_gt_zero = lcore_attr_value > 0; 402 TEST_ASSERT_EQUAL(1, loops_gt_zero, 403 "lcore_attr_get() failed to get loops " 404 "(expected > zero)"); 405 406 lcore_attr_id++; // invalid lcore attr id 407 TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_attr_get(slcore_id, 408 lcore_attr_id, &lcore_attr_value), 409 "Invalid lcore attr didn't return -EINVAL"); 410 411 /* Ensure service is active */ 412 TEST_ASSERT_EQUAL(1, rte_service_lcore_may_be_active(slcore_id), 413 "Active service core reported as not-active"); 414 415 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(id, slcore_id, 0), 416 "Disabling valid service and core failed"); 417 TEST_ASSERT_EQUAL(0, rte_service_lcore_stop(slcore_id), 418 "Failed to stop service lcore"); 419 420 wait_slcore_inactive(slcore_id); 421 422 TEST_ASSERT_EQUAL(0, rte_service_lcore_may_be_active(slcore_id), 423 "Service lcore not stopped after waiting."); 424 425 TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_reset_all(slcore_id), 426 "Valid lcore_attr_reset_all() didn't return success"); 427 428 lcore_attr_id = RTE_SERVICE_LCORE_ATTR_LOOPS; 429 TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_get(slcore_id, 430 lcore_attr_id, &lcore_attr_value), 431 "Valid lcore_attr_get() call didn't return success"); 432 TEST_ASSERT_EQUAL(0, lcore_attr_value, 433 "lcore_attr_get() didn't get correct loop count " 434 "(zero)"); 435 436 return unregister_all(); 437 } 438 439 /* verify service dump */ 440 static int 441 service_dump(void) 442 { 443 const uint32_t sid = 0; 444 rte_service_set_stats_enable(sid, 1); 445 rte_service_dump(stdout, 0); 446 rte_service_set_stats_enable(sid, 0); 447 rte_service_dump(stdout, 0); 448 return unregister_all(); 449 } 450 451 /* start and stop a service */ 452 static int 453 service_start_stop(void) 454 { 455 const uint32_t sid = 0; 456 457 /* runstate_get() returns if service is running and slcore is mapped */ 458 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 459 "Service core add did not return zero"); 460 int ret = rte_service_map_lcore_set(sid, slcore_id, 1); 461 TEST_ASSERT_EQUAL(0, ret, 462 "Enabling service core, expected 0 got %d", ret); 463 464 TEST_ASSERT_EQUAL(0, rte_service_runstate_get(sid), 465 "Error: Service should be stopped"); 466 467 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 468 "Error: Service stopped returned non-zero"); 469 470 TEST_ASSERT_EQUAL(0, rte_service_runstate_get(sid), 471 "Error: Service is running - should be stopped"); 472 473 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 474 "Error: Service start returned non-zero"); 475 476 TEST_ASSERT_EQUAL(1, rte_service_runstate_get(sid), 477 "Error: Service is not running"); 478 479 return unregister_all(); 480 } 481 482 483 static int 484 service_remote_launch_func(void *arg) 485 { 486 RTE_SET_USED(arg); 487 service_remote_launch_flag = 1; 488 return 0; 489 } 490 491 /* enable and disable a lcore for a service */ 492 static int 493 service_lcore_en_dis_able(void) 494 { 495 const uint32_t sid = 0; 496 497 /* expected failure cases */ 498 TEST_ASSERT_EQUAL(-EINVAL, rte_service_map_lcore_set(sid, 100000, 1), 499 "Enable on invalid core did not fail"); 500 TEST_ASSERT_EQUAL(-EINVAL, rte_service_map_lcore_set(sid, 100000, 0), 501 "Disable on invalid core did not fail"); 502 503 /* add service core to allow enabling */ 504 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 505 "Add service core failed when not in use before"); 506 507 /* valid enable */ 508 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1), 509 "Enabling valid service and core failed"); 510 TEST_ASSERT_EQUAL(1, rte_service_map_lcore_get(sid, slcore_id), 511 "Enabled core returned not-enabled"); 512 513 /* valid disable */ 514 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 0), 515 "Disabling valid service and lcore failed"); 516 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_get(sid, slcore_id), 517 "Disabled core returned enabled"); 518 519 /* call remote_launch to verify that app can launch ex-service lcore */ 520 service_remote_launch_flag = 0; 521 rte_eal_wait_lcore(slcore_id); 522 int ret = rte_eal_remote_launch(service_remote_launch_func, NULL, 523 slcore_id); 524 TEST_ASSERT_EQUAL(0, ret, "Ex-service core remote launch failed."); 525 rte_eal_wait_lcore(slcore_id); 526 TEST_ASSERT_EQUAL(1, service_remote_launch_flag, 527 "Ex-service core function call had no effect."); 528 529 return unregister_all(); 530 } 531 532 static int 533 service_lcore_running_check(void) 534 { 535 uint64_t tick = service_tick; 536 rte_delay_ms(SERVICE_DELAY * 100); 537 /* if (tick != service_tick) we know the lcore as polled the service */ 538 return tick != service_tick; 539 } 540 541 static int 542 service_lcore_add_del(void) 543 { 544 if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) || 545 !rte_lcore_is_enabled(2) || !rte_lcore_is_enabled(3)) 546 return TEST_SKIPPED; 547 548 /* check initial count */ 549 TEST_ASSERT_EQUAL(0, rte_service_lcore_count(), 550 "Service lcore count has value before adding a lcore"); 551 552 /* check service lcore add */ 553 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 554 "Add service core failed when not in use before"); 555 TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_add(slcore_id), 556 "Add service core failed to refuse in-use lcore"); 557 558 /* check count */ 559 TEST_ASSERT_EQUAL(1, rte_service_lcore_count(), 560 "Service core count not equal to one"); 561 562 /* retrieve core list, checking lcore ids */ 563 const uint32_t size = 4; 564 uint32_t service_core_ids[size]; 565 int32_t n = rte_service_lcore_list(service_core_ids, size); 566 TEST_ASSERT_EQUAL(1, n, "Service core list return should equal 1"); 567 TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0], 568 "Service core list lcore must equal slcore_id"); 569 570 /* recheck count, add more cores, and check count */ 571 TEST_ASSERT_EQUAL(1, rte_service_lcore_count(), 572 "Service core count not equal to one"); 573 uint32_t slcore_1 = rte_get_next_lcore(/* start core */ -1, 574 /* skip main */ 1, 575 /* wrap */ 0); 576 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_1), 577 "Service core add did not return zero"); 578 uint32_t slcore_2 = rte_get_next_lcore(/* start core */ slcore_1, 579 /* skip main */ 1, 580 /* wrap */ 0); 581 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_2), 582 "Service core add did not return zero"); 583 584 uint32_t count = rte_service_lcore_count(); 585 const uint32_t cores_at_this_point = 3; 586 TEST_ASSERT_EQUAL(cores_at_this_point, count, 587 "Service core count %d, expected %d", count, 588 cores_at_this_point); 589 590 /* check longer service core list */ 591 n = rte_service_lcore_list(service_core_ids, size); 592 TEST_ASSERT_EQUAL(3, n, "Service core list return should equal 3"); 593 TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0], 594 "Service core list[0] lcore must equal 1"); 595 TEST_ASSERT_EQUAL(slcore_1, service_core_ids[1], 596 "Service core list[1] lcore must equal 2"); 597 TEST_ASSERT_EQUAL(slcore_2, service_core_ids[2], 598 "Service core list[2] lcore must equal 3"); 599 600 /* recheck count, remove lcores, check remaining lcore_id is correct */ 601 TEST_ASSERT_EQUAL(3, rte_service_lcore_count(), 602 "Service core count not equal to three"); 603 TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_1), 604 "Service core add did not return zero"); 605 TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_2), 606 "Service core add did not return zero"); 607 TEST_ASSERT_EQUAL(1, rte_service_lcore_count(), 608 "Service core count not equal to one"); 609 n = rte_service_lcore_list(service_core_ids, size); 610 TEST_ASSERT_EQUAL(1, n, "Service core list return should equal one"); 611 TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0], 612 "Service core list[0] lcore must equal %d", 613 slcore_id); 614 615 return unregister_all(); 616 } 617 618 static int 619 service_threaded_test(int mt_safe) 620 { 621 unregister_all(); 622 623 /* add next 2 cores */ 624 uint32_t slcore_1 = rte_get_next_lcore(/* start core */ -1, 625 /* skip main */ 1, 626 /* wrap */ 0); 627 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_1), 628 "mt safe lcore add fail"); 629 uint32_t slcore_2 = rte_get_next_lcore(/* start core */ slcore_1, 630 /* skip main */ 1, 631 /* wrap */ 0); 632 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_2), 633 "mt safe lcore add fail"); 634 635 /* Use locks to verify that two threads are in the same function 636 * at the same time. These are passed to the unit tests through 637 * the callback userdata parameter. 638 */ 639 uint32_t test_params[2]; 640 memset(test_params, 0, sizeof(uint32_t) * 2); 641 642 /* register MT safe service. */ 643 struct rte_service_spec service; 644 memset(&service, 0, sizeof(struct rte_service_spec)); 645 service.callback_userdata = test_params; 646 snprintf(service.name, sizeof(service.name), MT_SAFE_SERVICE_NAME); 647 648 if (mt_safe) { 649 service.callback = dummy_mt_safe_cb; 650 service.capabilities |= RTE_SERVICE_CAP_MT_SAFE; 651 } else 652 service.callback = dummy_mt_unsafe_cb; 653 654 uint32_t id; 655 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id), 656 "Register of MT SAFE service failed"); 657 658 const uint32_t sid = 0; 659 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 660 "Starting valid service failed"); 661 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_1, 1), 662 "Failed to enable lcore 1 on mt safe service"); 663 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_2, 1), 664 "Failed to enable lcore 2 on mt safe service"); 665 rte_service_lcore_start(slcore_1); 666 rte_service_lcore_start(slcore_2); 667 668 /* wait for the worker threads to run */ 669 rte_delay_ms(500); 670 rte_service_lcore_stop(slcore_1); 671 rte_service_lcore_stop(slcore_2); 672 673 TEST_ASSERT_EQUAL(0, test_params[1], 674 "Service run with component runstate = 0"); 675 676 /* enable backend runstate: the service should run after this */ 677 rte_service_component_runstate_set(id, 1); 678 679 /* initialize to pass, see callback comment for details */ 680 if (!mt_safe) 681 test_params[1] = 1; 682 683 /* wait for lcores before start() */ 684 rte_eal_wait_lcore(slcore_1); 685 rte_eal_wait_lcore(slcore_2); 686 687 rte_service_lcore_start(slcore_1); 688 rte_service_lcore_start(slcore_2); 689 690 /* wait for the worker threads to run */ 691 rte_delay_ms(500); 692 rte_service_lcore_stop(slcore_1); 693 rte_service_lcore_stop(slcore_2); 694 695 TEST_ASSERT_EQUAL(1, test_params[1], 696 "MT Safe service not run by two cores concurrently"); 697 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 698 "Failed to stop MT Safe service"); 699 700 rte_eal_wait_lcore(slcore_1); 701 rte_eal_wait_lcore(slcore_2); 702 unregister_all(); 703 704 /* return the value of the callback pass_test variable to caller */ 705 return test_params[1]; 706 } 707 708 /* tests an MT SAFE service with two cores. The callback function ensures that 709 * two threads access the callback concurrently. 710 */ 711 static int 712 service_mt_safe_poll(void) 713 { 714 int mt_safe = 1; 715 716 if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) || 717 !rte_lcore_is_enabled(2)) 718 return TEST_SKIPPED; 719 720 TEST_ASSERT_EQUAL(1, service_threaded_test(mt_safe), 721 "Error: MT Safe service not run by two cores concurrently"); 722 return TEST_SUCCESS; 723 } 724 725 /* tests a NON mt safe service with two cores, the callback is serialized 726 * using the CAS. 727 */ 728 static int 729 service_mt_unsafe_poll(void) 730 { 731 int mt_safe = 0; 732 733 if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) || 734 !rte_lcore_is_enabled(2)) 735 return TEST_SKIPPED; 736 737 TEST_ASSERT_EQUAL(1, service_threaded_test(mt_safe), 738 "Error: NON MT Safe service run by two cores concurrently"); 739 return TEST_SUCCESS; 740 } 741 742 static int32_t 743 delay_as_a_mt_safe_service(void *args) 744 { 745 RTE_SET_USED(args); 746 uint32_t *params = args; 747 748 /* retrieve done flag and lock to add/sub */ 749 uint32_t *done = ¶ms[0]; 750 uint32_t *lock = ¶ms[1]; 751 752 while (!*done) { 753 __atomic_add_fetch(lock, 1, __ATOMIC_RELAXED); 754 rte_delay_us(500); 755 if (__atomic_load_n(lock, __ATOMIC_RELAXED) > 1) 756 /* pass: second core has simultaneously incremented */ 757 *done = 1; 758 __atomic_sub_fetch(lock, 1, __ATOMIC_RELAXED); 759 } 760 761 return 0; 762 } 763 764 static int32_t 765 delay_as_a_service(void *args) 766 { 767 uint32_t *done = (uint32_t *)args; 768 while (!*done) 769 rte_delay_ms(5); 770 return 0; 771 } 772 773 static int 774 service_run_on_app_core_func(void *arg) 775 { 776 uint32_t *delay_service_id = (uint32_t *)arg; 777 return rte_service_run_iter_on_app_lcore(*delay_service_id, 1); 778 } 779 780 static int 781 service_app_lcore_poll_impl(const int mt_safe) 782 { 783 uint32_t params[2] = {0}; 784 785 struct rte_service_spec service; 786 memset(&service, 0, sizeof(struct rte_service_spec)); 787 snprintf(service.name, sizeof(service.name), MT_SAFE_SERVICE_NAME); 788 if (mt_safe) { 789 service.callback = delay_as_a_mt_safe_service; 790 service.callback_userdata = params; 791 service.capabilities |= RTE_SERVICE_CAP_MT_SAFE; 792 } else { 793 service.callback = delay_as_a_service; 794 service.callback_userdata = ¶ms; 795 } 796 797 uint32_t id; 798 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id), 799 "Register of app lcore delay service failed"); 800 801 rte_service_component_runstate_set(id, 1); 802 rte_service_runstate_set(id, 1); 803 804 uint32_t app_core2 = rte_get_next_lcore(slcore_id, 1, 1); 805 rte_eal_wait_lcore(app_core2); 806 int app_core2_ret = rte_eal_remote_launch(service_run_on_app_core_func, 807 &id, app_core2); 808 809 rte_delay_ms(100); 810 811 int app_core1_ret = service_run_on_app_core_func(&id); 812 813 /* flag done, then wait for the spawned 2nd core to return */ 814 params[0] = 1; 815 rte_eal_mp_wait_lcore(); 816 817 /* core two gets launched first - and should hold the service lock */ 818 TEST_ASSERT_EQUAL(0, app_core2_ret, 819 "App core2 : run service didn't return zero"); 820 821 if (mt_safe) { 822 /* mt safe should have both cores return 0 for success */ 823 TEST_ASSERT_EQUAL(0, app_core1_ret, 824 "MT Safe: App core1 didn't return 0"); 825 } else { 826 /* core one attempts to run later - should be blocked */ 827 TEST_ASSERT_EQUAL(-EBUSY, app_core1_ret, 828 "MT Unsafe: App core1 didn't return -EBUSY"); 829 } 830 831 /* Performance test: call in a loop, and measure tsc() */ 832 const uint32_t perf_iters = (1 << 12); 833 uint64_t start = rte_rdtsc(); 834 uint32_t i; 835 for (i = 0; i < perf_iters; i++) { 836 int err = service_run_on_app_core_func(&id); 837 TEST_ASSERT_EQUAL(0, err, "perf test: returned run failure"); 838 } 839 uint64_t end = rte_rdtsc(); 840 printf("perf test for %s: %0.1f cycles per call\n", mt_safe ? 841 "MT Safe" : "MT Unsafe", (end - start)/(float)perf_iters); 842 843 unregister_all(); 844 return TEST_SUCCESS; 845 } 846 847 static int 848 service_app_lcore_mt_safe(void) 849 { 850 const int mt_safe = 1; 851 return service_app_lcore_poll_impl(mt_safe); 852 } 853 854 static int 855 service_app_lcore_mt_unsafe(void) 856 { 857 const int mt_safe = 0; 858 return service_app_lcore_poll_impl(mt_safe); 859 } 860 861 /* start and stop a service core - ensuring it goes back to sleep */ 862 static int 863 service_lcore_start_stop(void) 864 { 865 /* start service core and service, create mapping so tick() runs */ 866 const uint32_t sid = 0; 867 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 868 "Starting valid service failed"); 869 TEST_ASSERT_EQUAL(-EINVAL, rte_service_map_lcore_set(sid, slcore_id, 1), 870 "Enabling valid service on non-service core must fail"); 871 872 /* core start */ 873 TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_start(slcore_id), 874 "Service core start without add should return EINVAL"); 875 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 876 "Service core add did not return zero"); 877 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1), 878 "Enabling valid service on valid core failed"); 879 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id), 880 "Service core start after add failed"); 881 TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_start(slcore_id), 882 "Service core expected as running but was stopped"); 883 884 /* ensures core really is running the service function */ 885 TEST_ASSERT_EQUAL(1, service_lcore_running_check(), 886 "Service core expected to poll service but it didn't"); 887 888 /* core stop */ 889 TEST_ASSERT_EQUAL(-EBUSY, rte_service_lcore_stop(slcore_id), 890 "Service core running a service should return -EBUSY"); 891 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 892 "Stopping valid service failed"); 893 TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_stop(100000), 894 "Invalid Service core stop should return -EINVAL"); 895 TEST_ASSERT_EQUAL(0, rte_service_lcore_stop(slcore_id), 896 "Service core stop expected to return 0"); 897 TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_stop(slcore_id), 898 "Already stopped service core should return -EALREADY"); 899 900 /* ensure service is not longer running */ 901 TEST_ASSERT_EQUAL(0, service_lcore_running_check(), 902 "Service core expected to poll service but it didn't"); 903 904 TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_id), 905 "Service core del did not return zero"); 906 907 return unregister_all(); 908 } 909 910 /* stop a service and wait for it to become inactive */ 911 static int 912 service_may_be_active(void) 913 { 914 const uint32_t sid = 0; 915 int i; 916 917 /* expected failure cases */ 918 TEST_ASSERT_EQUAL(-EINVAL, rte_service_may_be_active(10000), 919 "Invalid service may be active check did not fail"); 920 921 /* start the service */ 922 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 923 "Starting valid service failed"); 924 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 925 "Add service core failed when not in use before"); 926 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1), 927 "Enabling valid service on valid core failed"); 928 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id), 929 "Service core start after add failed"); 930 931 /* ensures core really is running the service function */ 932 TEST_ASSERT_EQUAL(1, service_lcore_running_check(), 933 "Service core expected to poll service but it didn't"); 934 935 /* stop the service */ 936 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 937 "Error: Service stop returned non-zero"); 938 939 /* give the service 100ms to stop running */ 940 for (i = 0; i < 100; i++) { 941 if (!rte_service_may_be_active(sid)) 942 break; 943 rte_delay_ms(SERVICE_DELAY); 944 } 945 946 TEST_ASSERT_EQUAL(0, rte_service_may_be_active(sid), 947 "Error: Service not stopped after 100ms"); 948 949 return unregister_all(); 950 } 951 952 /* check service may be active when service is running on a second lcore */ 953 static int 954 service_active_two_cores(void) 955 { 956 if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) || 957 !rte_lcore_is_enabled(2)) 958 return TEST_SKIPPED; 959 960 const uint32_t sid = 0; 961 int i; 962 963 uint32_t lcore = rte_get_next_lcore(/* start core */ -1, 964 /* skip main */ 1, 965 /* wrap */ 0); 966 uint32_t slcore = rte_get_next_lcore(/* start core */ lcore, 967 /* skip main */ 1, 968 /* wrap */ 0); 969 970 /* start the service on the second available lcore */ 971 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 972 "Starting valid service failed"); 973 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore), 974 "Add service core failed when not in use before"); 975 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore, 1), 976 "Enabling valid service on valid core failed"); 977 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore), 978 "Service core start after add failed"); 979 980 /* ensures core really is running the service function */ 981 TEST_ASSERT_EQUAL(1, service_lcore_running_check(), 982 "Service core expected to poll service but it didn't"); 983 984 /* ensures that service may be active reports running state */ 985 TEST_ASSERT_EQUAL(1, rte_service_may_be_active(sid), 986 "Service may be active did not report running state"); 987 988 /* stop the service */ 989 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 990 "Error: Service stop returned non-zero"); 991 992 /* give the service 100ms to stop running */ 993 for (i = 0; i < 100; i++) { 994 if (!rte_service_may_be_active(sid)) 995 break; 996 rte_delay_ms(SERVICE_DELAY); 997 } 998 999 TEST_ASSERT_EQUAL(0, rte_service_may_be_active(sid), 1000 "Error: Service not stopped after 100ms"); 1001 1002 return unregister_all(); 1003 } 1004 1005 static struct unit_test_suite service_tests = { 1006 .suite_name = "service core test suite", 1007 .setup = testsuite_setup, 1008 .teardown = testsuite_teardown, 1009 .unit_test_cases = { 1010 TEST_CASE_ST(dummy_register, NULL, unregister_all), 1011 TEST_CASE_ST(dummy_register, NULL, service_name), 1012 TEST_CASE_ST(dummy_register, NULL, service_get_by_name), 1013 TEST_CASE_ST(dummy_register, NULL, service_dump), 1014 TEST_CASE_ST(dummy_register, NULL, service_attr_get), 1015 TEST_CASE_ST(dummy_register, NULL, service_lcore_attr_get), 1016 TEST_CASE_ST(dummy_register, NULL, service_probe_capability), 1017 TEST_CASE_ST(dummy_register, NULL, service_start_stop), 1018 TEST_CASE_ST(dummy_register, NULL, service_lcore_add_del), 1019 TEST_CASE_ST(dummy_register, NULL, service_lcore_start_stop), 1020 TEST_CASE_ST(dummy_register, NULL, service_lcore_en_dis_able), 1021 TEST_CASE_ST(dummy_register, NULL, service_mt_unsafe_poll), 1022 TEST_CASE_ST(dummy_register, NULL, service_mt_safe_poll), 1023 TEST_CASE_ST(dummy_register, NULL, service_app_lcore_mt_safe), 1024 TEST_CASE_ST(dummy_register, NULL, service_app_lcore_mt_unsafe), 1025 TEST_CASE_ST(dummy_register, NULL, service_may_be_active), 1026 TEST_CASE_ST(dummy_register, NULL, service_active_two_cores), 1027 TEST_CASES_END() /**< NULL terminate unit test array */ 1028 } 1029 }; 1030 1031 static int 1032 test_service_common(void) 1033 { 1034 return unit_test_suite_runner(&service_tests); 1035 } 1036 1037 REGISTER_TEST_COMMAND(service_autotest, test_service_common); 1038