1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Intel Corporation 3 */ 4 5 #include <unistd.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <stdint.h> 9 #include <errno.h> 10 #include <sys/queue.h> 11 12 #include <rte_memory.h> 13 #include <rte_launch.h> 14 #include <rte_eal.h> 15 #include <rte_debug.h> 16 #include <rte_cycles.h> 17 18 /* allow application scheduling of the services */ 19 #include <rte_service.h> 20 21 /* Allow application registration of its own services. An application does not 22 * have to register services, but it can be useful if it wishes to run a 23 * function on a core that is otherwise in use as a service core. In this 24 * example, all services are dummy services registered by the sample app itself. 25 */ 26 #include <rte_service_component.h> 27 28 #define PROFILE_CORES_MAX 8 29 #define PROFILE_SERVICE_PER_CORE 5 30 31 /* dummy function to do "work" */ 32 static int32_t service_func(void *args) 33 { 34 RTE_SET_USED(args); 35 rte_delay_us(2000); 36 return 0; 37 } 38 39 static struct rte_service_spec services[] = { 40 {"service_1", service_func, NULL, 0, 0}, 41 {"service_2", service_func, NULL, 0, 0}, 42 {"service_3", service_func, NULL, 0, 0}, 43 {"service_4", service_func, NULL, 0, 0}, 44 {"service_5", service_func, NULL, 0, 0}, 45 }; 46 #define NUM_SERVICES RTE_DIM(services) 47 48 /* this struct holds the mapping of a particular core to all services */ 49 struct profile_for_core { 50 uint32_t mapped_services[PROFILE_SERVICE_PER_CORE]; 51 }; 52 53 /* struct that can be applied as the service core mapping. Items in this 54 * struct will be passed to the ordinary rte_service_* APIs to configure the 55 * service cores at runtime, based on the requirements. 56 * 57 * These profiles can be considered a "configuration" for the service cores, 58 * where switching profile just changes the number of cores and the mappings 59 * for each of them. As a result, the core requirements and performance of the 60 * application scales. 61 */ 62 struct profile { 63 char name[64]; 64 uint32_t num_cores; 65 struct profile_for_core cores[PROFILE_CORES_MAX]; 66 }; 67 68 static struct profile profiles[] = { 69 /* profile 0: high performance */ 70 { 71 .name = "High Performance", 72 .num_cores = 5, 73 .cores[0] = {.mapped_services = {1, 0, 0, 0, 0} }, 74 .cores[1] = {.mapped_services = {0, 1, 0, 0, 0} }, 75 .cores[2] = {.mapped_services = {0, 0, 1, 0, 0} }, 76 .cores[3] = {.mapped_services = {0, 0, 0, 1, 0} }, 77 .cores[4] = {.mapped_services = {0, 0, 0, 0, 1} }, 78 }, 79 /* profile 1: mid performance with single service priority */ 80 { 81 .name = "Mid-High Performance", 82 .num_cores = 3, 83 .cores[0] = {.mapped_services = {1, 1, 0, 0, 0} }, 84 .cores[1] = {.mapped_services = {0, 0, 1, 1, 0} }, 85 .cores[2] = {.mapped_services = {0, 0, 0, 0, 1} }, 86 .cores[3] = {.mapped_services = {0, 0, 0, 0, 0} }, 87 .cores[4] = {.mapped_services = {0, 0, 0, 0, 0} }, 88 }, 89 /* profile 2: mid performance with single service priority */ 90 { 91 .name = "Mid-Low Performance", 92 .num_cores = 2, 93 .cores[0] = {.mapped_services = {1, 1, 1, 0, 0} }, 94 .cores[1] = {.mapped_services = {1, 1, 0, 1, 1} }, 95 .cores[2] = {.mapped_services = {0, 0, 0, 0, 0} }, 96 .cores[3] = {.mapped_services = {0, 0, 0, 0, 0} }, 97 .cores[4] = {.mapped_services = {0, 0, 0, 0, 0} }, 98 }, 99 /* profile 3: scale down performance on single core */ 100 { 101 .name = "Scale down performance", 102 .num_cores = 1, 103 .cores[0] = {.mapped_services = {1, 1, 1, 1, 1} }, 104 .cores[1] = {.mapped_services = {0, 0, 0, 0, 0} }, 105 .cores[2] = {.mapped_services = {0, 0, 0, 0, 0} }, 106 .cores[3] = {.mapped_services = {0, 0, 0, 0, 0} }, 107 .cores[4] = {.mapped_services = {0, 0, 0, 0, 0} }, 108 }, 109 }; 110 #define NUM_PROFILES RTE_DIM(profiles) 111 112 static void 113 apply_profile(int profile_id) 114 { 115 uint32_t i; 116 uint32_t s; 117 int ret; 118 struct profile *p = &profiles[profile_id]; 119 const uint8_t core_off = 1; 120 121 for (i = 0; i < p->num_cores; i++) { 122 uint32_t core = i + core_off; 123 ret = rte_service_lcore_add(core); 124 if (ret && ret != -EALREADY) 125 printf("core %d added ret %d\n", core, ret); 126 127 ret = rte_service_lcore_start(core); 128 if (ret && ret != -EALREADY) 129 printf("core %d start ret %d\n", core, ret); 130 131 for (s = 0; s < NUM_SERVICES; s++) { 132 if (rte_service_map_lcore_set(s, core, 133 p->cores[i].mapped_services[s])) 134 printf("failed to map lcore %d\n", core); 135 } 136 } 137 138 for ( ; i < PROFILE_CORES_MAX; i++) { 139 uint32_t core = i + core_off; 140 for (s = 0; s < NUM_SERVICES; s++) { 141 ret = rte_service_map_lcore_set(s, core, 0); 142 if (ret && ret != -EINVAL) { 143 printf("%s %d: map lcore set = %d\n", __func__, 144 __LINE__, ret); 145 } 146 } 147 ret = rte_service_lcore_stop(core); 148 if (ret && ret != -EALREADY) { 149 printf("%s %d: lcore stop = %d\n", __func__, 150 __LINE__, ret); 151 } 152 ret = rte_service_lcore_del(core); 153 if (ret && ret != -EINVAL) { 154 printf("%s %d: lcore del = %d\n", __func__, 155 __LINE__, ret); 156 } 157 } 158 } 159 160 int 161 main(int argc, char **argv) 162 { 163 int ret; 164 165 ret = rte_eal_init(argc, argv); 166 if (ret < 0) 167 rte_panic("Cannot init EAL\n"); 168 169 uint32_t i; 170 for (i = 0; i < NUM_SERVICES; i++) { 171 services[i].callback_userdata = 0; 172 uint32_t id; 173 ret = rte_service_component_register(&services[i], &id); 174 if (ret) 175 rte_exit(-1, "service register() failed"); 176 177 /* set the service itself to be ready to run. In the case of 178 * ethdev, eventdev etc PMDs, this will be set when the 179 * appropriate configure or setup function is called. 180 */ 181 rte_service_component_runstate_set(id, 1); 182 183 /* Collect statistics for the service */ 184 rte_service_set_stats_enable(id, 1); 185 186 /* the application sets the service to be active. Note that the 187 * previous component_runstate_set() is the PMD indicating 188 * ready, while this function is the application setting the 189 * service to run. Applications can choose to not run a service 190 * by setting runstate to 0 at any time. 191 */ 192 ret = rte_service_runstate_set(id, 1); 193 if (ret) 194 return -ENOEXEC; 195 } 196 197 i = 0; 198 while (1) { 199 const char clr[] = { 27, '[', '2', 'J', '\0' }; 200 const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' }; 201 printf("%s%s", clr, topLeft); 202 203 apply_profile(i); 204 printf("\n==> Profile: %s\n\n", profiles[i].name); 205 206 sleep(1); 207 rte_service_dump(stdout, UINT32_MAX); 208 209 sleep(5); 210 rte_service_dump(stdout, UINT32_MAX); 211 212 i++; 213 if (i >= NUM_PROFILES) 214 i = 0; 215 } 216 217 return 0; 218 } 219