LCOV - code coverage report
Current view: top level - app/test - test_service_cores.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 125 345 36.2 %
Date: 2024-02-14 00:53:57 Functions: 21 36 58.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 59 350 16.9 %

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

Generated by: LCOV version 1.14