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