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 /* check initial count */ 506 TEST_ASSERT_EQUAL(0, rte_service_lcore_count(), 507 "Service lcore count has value before adding a lcore"); 508 509 /* check service lcore add */ 510 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 511 "Add service core failed when not in use before"); 512 TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_add(slcore_id), 513 "Add service core failed to refuse in-use lcore"); 514 515 /* check count */ 516 TEST_ASSERT_EQUAL(1, rte_service_lcore_count(), 517 "Service core count not equal to one"); 518 519 /* retrieve core list, checking lcore ids */ 520 const uint32_t size = 4; 521 uint32_t service_core_ids[size]; 522 int32_t n = rte_service_lcore_list(service_core_ids, size); 523 TEST_ASSERT_EQUAL(1, n, "Service core list return should equal 1"); 524 TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0], 525 "Service core list lcore must equal slcore_id"); 526 527 /* recheck count, add more cores, and check count */ 528 TEST_ASSERT_EQUAL(1, rte_service_lcore_count(), 529 "Service core count not equal to one"); 530 uint32_t slcore_1 = rte_get_next_lcore(/* start core */ -1, 531 /* skip master */ 1, 532 /* wrap */ 0); 533 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_1), 534 "Service core add did not return zero"); 535 uint32_t slcore_2 = rte_get_next_lcore(/* start core */ slcore_1, 536 /* skip master */ 1, 537 /* wrap */ 0); 538 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_2), 539 "Service core add did not return zero"); 540 541 uint32_t count = rte_service_lcore_count(); 542 const uint32_t cores_at_this_point = 3; 543 TEST_ASSERT_EQUAL(cores_at_this_point, count, 544 "Service core count %d, expected %d", count, 545 cores_at_this_point); 546 547 /* check longer service core list */ 548 n = rte_service_lcore_list(service_core_ids, size); 549 TEST_ASSERT_EQUAL(3, n, "Service core list return should equal 3"); 550 TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0], 551 "Service core list[0] lcore must equal 1"); 552 TEST_ASSERT_EQUAL(slcore_1, service_core_ids[1], 553 "Service core list[1] lcore must equal 2"); 554 TEST_ASSERT_EQUAL(slcore_2, service_core_ids[2], 555 "Service core list[2] lcore must equal 3"); 556 557 /* recheck count, remove lcores, check remaining lcore_id is correct */ 558 TEST_ASSERT_EQUAL(3, rte_service_lcore_count(), 559 "Service core count not equal to three"); 560 TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_1), 561 "Service core add did not return zero"); 562 TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_2), 563 "Service core add did not return zero"); 564 TEST_ASSERT_EQUAL(1, rte_service_lcore_count(), 565 "Service core count not equal to one"); 566 n = rte_service_lcore_list(service_core_ids, size); 567 TEST_ASSERT_EQUAL(1, n, "Service core list return should equal one"); 568 TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0], 569 "Service core list[0] lcore must equal %d", 570 slcore_id); 571 572 return unregister_all(); 573 } 574 575 static int 576 service_threaded_test(int mt_safe) 577 { 578 unregister_all(); 579 580 /* add next 2 cores */ 581 uint32_t slcore_1 = rte_get_next_lcore(/* start core */ -1, 582 /* skip master */ 1, 583 /* wrap */ 0); 584 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_1), 585 "mt safe lcore add fail"); 586 uint32_t slcore_2 = rte_get_next_lcore(/* start core */ slcore_1, 587 /* skip master */ 1, 588 /* wrap */ 0); 589 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_2), 590 "mt safe lcore add fail"); 591 592 /* Use atomic locks to verify that two threads are in the same function 593 * at the same time. These are passed to the unit tests through the 594 * callback userdata parameter 595 */ 596 uint32_t test_params[2]; 597 memset(test_params, 0, sizeof(uint32_t) * 2); 598 599 /* register MT safe service. */ 600 struct rte_service_spec service; 601 memset(&service, 0, sizeof(struct rte_service_spec)); 602 service.callback_userdata = test_params; 603 snprintf(service.name, sizeof(service.name), MT_SAFE_SERVICE_NAME); 604 605 if (mt_safe) { 606 service.callback = dummy_mt_safe_cb; 607 service.capabilities |= RTE_SERVICE_CAP_MT_SAFE; 608 } else 609 service.callback = dummy_mt_unsafe_cb; 610 611 uint32_t id; 612 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id), 613 "Register of MT SAFE service failed"); 614 615 const uint32_t sid = 0; 616 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 617 "Starting valid service failed"); 618 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_1, 1), 619 "Failed to enable lcore 1 on mt safe service"); 620 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_2, 1), 621 "Failed to enable lcore 2 on mt safe service"); 622 rte_service_lcore_start(slcore_1); 623 rte_service_lcore_start(slcore_2); 624 625 /* wait for the worker threads to run */ 626 rte_delay_ms(500); 627 rte_service_lcore_stop(slcore_1); 628 rte_service_lcore_stop(slcore_2); 629 630 TEST_ASSERT_EQUAL(0, test_params[1], 631 "Service run with component runstate = 0"); 632 633 /* enable backend runstate: the service should run after this */ 634 rte_service_component_runstate_set(id, 1); 635 636 /* initialize to pass, see callback comment for details */ 637 if (!mt_safe) 638 test_params[1] = 1; 639 640 /* wait for lcores before start() */ 641 rte_eal_wait_lcore(slcore_1); 642 rte_eal_wait_lcore(slcore_2); 643 644 rte_service_lcore_start(slcore_1); 645 rte_service_lcore_start(slcore_2); 646 647 /* wait for the worker threads to run */ 648 rte_delay_ms(500); 649 rte_service_lcore_stop(slcore_1); 650 rte_service_lcore_stop(slcore_2); 651 652 TEST_ASSERT_EQUAL(1, test_params[1], 653 "MT Safe service not run by two cores concurrently"); 654 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 655 "Failed to stop MT Safe service"); 656 657 rte_eal_wait_lcore(slcore_1); 658 rte_eal_wait_lcore(slcore_2); 659 unregister_all(); 660 661 /* return the value of the callback pass_test variable to caller */ 662 return test_params[1]; 663 } 664 665 /* tests an MT SAFE service with two cores. The callback function ensures that 666 * two threads access the callback concurrently. 667 */ 668 static int 669 service_mt_safe_poll(void) 670 { 671 int mt_safe = 1; 672 TEST_ASSERT_EQUAL(1, service_threaded_test(mt_safe), 673 "Error: MT Safe service not run by two cores concurrently"); 674 return TEST_SUCCESS; 675 } 676 677 /* tests a NON mt safe service with two cores, the callback is serialized 678 * using the atomic cmpset. 679 */ 680 static int 681 service_mt_unsafe_poll(void) 682 { 683 int mt_safe = 0; 684 TEST_ASSERT_EQUAL(1, service_threaded_test(mt_safe), 685 "Error: NON MT Safe service run by two cores concurrently"); 686 return TEST_SUCCESS; 687 } 688 689 static int32_t 690 delay_as_a_mt_safe_service(void *args) 691 { 692 RTE_SET_USED(args); 693 uint32_t *params = args; 694 695 /* retrieve done flag and atomic lock to inc/dec */ 696 uint32_t *done = ¶ms[0]; 697 rte_atomic32_t *lock = (rte_atomic32_t *)¶ms[1]; 698 699 while (!*done) { 700 rte_atomic32_inc(lock); 701 rte_delay_us(500); 702 if (rte_atomic32_read(lock) > 1) 703 /* pass: second core has simultaneously incremented */ 704 *done = 1; 705 rte_atomic32_dec(lock); 706 } 707 708 return 0; 709 } 710 711 static int32_t 712 delay_as_a_service(void *args) 713 { 714 uint32_t *done = (uint32_t *)args; 715 while (!*done) 716 rte_delay_ms(5); 717 return 0; 718 } 719 720 static int 721 service_run_on_app_core_func(void *arg) 722 { 723 uint32_t *delay_service_id = (uint32_t *)arg; 724 return rte_service_run_iter_on_app_lcore(*delay_service_id, 1); 725 } 726 727 static int 728 service_app_lcore_poll_impl(const int mt_safe) 729 { 730 uint32_t params[2] = {0}; 731 732 struct rte_service_spec service; 733 memset(&service, 0, sizeof(struct rte_service_spec)); 734 snprintf(service.name, sizeof(service.name), MT_SAFE_SERVICE_NAME); 735 if (mt_safe) { 736 service.callback = delay_as_a_mt_safe_service; 737 service.callback_userdata = params; 738 service.capabilities |= RTE_SERVICE_CAP_MT_SAFE; 739 } else { 740 service.callback = delay_as_a_service; 741 service.callback_userdata = ¶ms; 742 } 743 744 uint32_t id; 745 TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id), 746 "Register of app lcore delay service failed"); 747 748 rte_service_component_runstate_set(id, 1); 749 rte_service_runstate_set(id, 1); 750 751 uint32_t app_core2 = rte_get_next_lcore(slcore_id, 1, 1); 752 rte_eal_wait_lcore(app_core2); 753 int app_core2_ret = rte_eal_remote_launch(service_run_on_app_core_func, 754 &id, app_core2); 755 756 rte_delay_ms(100); 757 758 int app_core1_ret = service_run_on_app_core_func(&id); 759 760 /* flag done, then wait for the spawned 2nd core to return */ 761 params[0] = 1; 762 rte_eal_mp_wait_lcore(); 763 764 /* core two gets launched first - and should hold the service lock */ 765 TEST_ASSERT_EQUAL(0, app_core2_ret, 766 "App core2 : run service didn't return zero"); 767 768 if (mt_safe) { 769 /* mt safe should have both cores return 0 for success */ 770 TEST_ASSERT_EQUAL(0, app_core1_ret, 771 "MT Safe: App core1 didn't return 0"); 772 } else { 773 /* core one attempts to run later - should be blocked */ 774 TEST_ASSERT_EQUAL(-EBUSY, app_core1_ret, 775 "MT Unsafe: App core1 didn't return -EBUSY"); 776 } 777 778 unregister_all(); 779 780 return TEST_SUCCESS; 781 } 782 783 static int 784 service_app_lcore_mt_safe(void) 785 { 786 const int mt_safe = 1; 787 return service_app_lcore_poll_impl(mt_safe); 788 } 789 790 static int 791 service_app_lcore_mt_unsafe(void) 792 { 793 const int mt_safe = 0; 794 return service_app_lcore_poll_impl(mt_safe); 795 } 796 797 /* start and stop a service core - ensuring it goes back to sleep */ 798 static int 799 service_lcore_start_stop(void) 800 { 801 /* start service core and service, create mapping so tick() runs */ 802 const uint32_t sid = 0; 803 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 804 "Starting valid service failed"); 805 TEST_ASSERT_EQUAL(-EINVAL, rte_service_map_lcore_set(sid, slcore_id, 1), 806 "Enabling valid service on non-service core must fail"); 807 808 /* core start */ 809 TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_start(slcore_id), 810 "Service core start without add should return EINVAL"); 811 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 812 "Service core add did not return zero"); 813 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1), 814 "Enabling valid service on valid core failed"); 815 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id), 816 "Service core start after add failed"); 817 TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_start(slcore_id), 818 "Service core expected as running but was stopped"); 819 820 /* ensures core really is running the service function */ 821 TEST_ASSERT_EQUAL(1, service_lcore_running_check(), 822 "Service core expected to poll service but it didn't"); 823 824 /* core stop */ 825 TEST_ASSERT_EQUAL(-EBUSY, rte_service_lcore_stop(slcore_id), 826 "Service core running a service should return -EBUSY"); 827 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 828 "Stopping valid service failed"); 829 TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_stop(100000), 830 "Invalid Service core stop should return -EINVAL"); 831 TEST_ASSERT_EQUAL(0, rte_service_lcore_stop(slcore_id), 832 "Service core stop expected to return 0"); 833 TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_stop(slcore_id), 834 "Already stopped service core should return -EALREADY"); 835 836 /* ensure service is not longer running */ 837 TEST_ASSERT_EQUAL(0, service_lcore_running_check(), 838 "Service core expected to poll service but it didn't"); 839 840 TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_id), 841 "Service core del did not return zero"); 842 843 return unregister_all(); 844 } 845 846 /* stop a service and wait for it to become inactive */ 847 static int 848 service_may_be_active(void) 849 { 850 const uint32_t sid = 0; 851 int i; 852 853 /* expected failure cases */ 854 TEST_ASSERT_EQUAL(-EINVAL, rte_service_may_be_active(10000), 855 "Invalid service may be active check did not fail"); 856 857 /* start the service */ 858 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1), 859 "Starting valid service failed"); 860 TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id), 861 "Add service core failed when not in use before"); 862 TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1), 863 "Enabling valid service on valid core failed"); 864 TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id), 865 "Service core start after add failed"); 866 867 /* ensures core really is running the service function */ 868 TEST_ASSERT_EQUAL(1, service_lcore_running_check(), 869 "Service core expected to poll service but it didn't"); 870 871 /* stop the service */ 872 TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0), 873 "Error: Service stop returned non-zero"); 874 875 /* give the service 100ms to stop running */ 876 for (i = 0; i < 100; i++) { 877 if (!rte_service_may_be_active(sid)) 878 break; 879 rte_delay_ms(SERVICE_DELAY); 880 } 881 882 TEST_ASSERT_EQUAL(0, rte_service_may_be_active(sid), 883 "Error: Service not stopped after 100ms"); 884 885 return unregister_all(); 886 } 887 888 static struct unit_test_suite service_tests = { 889 .suite_name = "service core test suite", 890 .setup = testsuite_setup, 891 .teardown = testsuite_teardown, 892 .unit_test_cases = { 893 TEST_CASE_ST(dummy_register, NULL, unregister_all), 894 TEST_CASE_ST(dummy_register, NULL, service_name), 895 TEST_CASE_ST(dummy_register, NULL, service_get_by_name), 896 TEST_CASE_ST(dummy_register, NULL, service_dump), 897 TEST_CASE_ST(dummy_register, NULL, service_attr_get), 898 TEST_CASE_ST(dummy_register, NULL, service_lcore_attr_get), 899 TEST_CASE_ST(dummy_register, NULL, service_probe_capability), 900 TEST_CASE_ST(dummy_register, NULL, service_start_stop), 901 TEST_CASE_ST(dummy_register, NULL, service_lcore_add_del), 902 TEST_CASE_ST(dummy_register, NULL, service_lcore_start_stop), 903 TEST_CASE_ST(dummy_register, NULL, service_lcore_en_dis_able), 904 TEST_CASE_ST(dummy_register, NULL, service_mt_unsafe_poll), 905 TEST_CASE_ST(dummy_register, NULL, service_mt_safe_poll), 906 TEST_CASE_ST(dummy_register, NULL, service_app_lcore_mt_safe), 907 TEST_CASE_ST(dummy_register, NULL, service_app_lcore_mt_unsafe), 908 TEST_CASE_ST(dummy_register, NULL, service_may_be_active), 909 TEST_CASES_END() /**< NULL terminate unit test array */ 910 } 911 }; 912 913 static int 914 test_service_common(void) 915 { 916 return unit_test_suite_runner(&service_tests); 917 } 918 919 REGISTER_TEST_COMMAND(service_autotest, test_service_common); 920