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