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