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