xref: /dpdk/examples/l3fwd-power/perf_core.c (revision f30a1bbd63f494f5ba623582d7e9166c817794a4)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4 
5 #include <ctype.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 
10 #include <rte_common.h>
11 #include <rte_memory.h>
12 #include <rte_lcore.h>
13 #include <rte_power_cpufreq.h>
14 #include <rte_string_fns.h>
15 
16 #include "perf_core.h"
17 #include "main.h"
18 
19 
20 static uint16_t hp_lcores[RTE_MAX_LCORE];
21 static uint16_t nb_hp_lcores;
22 
23 struct __rte_cache_aligned perf_lcore_params {
24 	uint16_t port_id;
25 	uint16_t queue_id;
26 	uint8_t high_perf;
27 	uint32_t lcore_idx;
28 };
29 
30 static struct perf_lcore_params prf_lc_prms[MAX_LCORE_PARAMS];
31 static uint16_t nb_prf_lc_prms;
32 
33 static int
34 is_hp_core(unsigned int lcore)
35 {
36 	struct rte_power_core_capabilities caps;
37 	int ret;
38 
39 	/* do we have power management enabled? */
40 	if (rte_power_get_env() == PM_ENV_NOT_SET) {
41 		/* there's no power management, so just mark it as high perf */
42 		return 1;
43 	}
44 	ret = rte_power_get_capabilities(lcore, &caps);
45 	return ret == 0 && caps.turbo;
46 }
47 
48 int
49 update_lcore_params(void)
50 {
51 	uint8_t non_perf_lcores[RTE_MAX_LCORE];
52 	uint16_t nb_non_perf_lcores = 0;
53 	int i, j;
54 
55 	/* if perf-config option was not used do nothing */
56 	if (nb_prf_lc_prms == 0)
57 		return 0;
58 
59 	/* if high-perf-cores option was not used query every available core */
60 	if (nb_hp_lcores == 0) {
61 		for (i = 0; i < RTE_MAX_LCORE; i++) {
62 			if (rte_lcore_is_enabled(i) && is_hp_core(i)) {
63 				hp_lcores[nb_hp_lcores] = i;
64 				nb_hp_lcores++;
65 			}
66 		}
67 	}
68 
69 	/* create a list on non high performance cores*/
70 	for (i = 0; i < RTE_MAX_LCORE; i++) {
71 		if (rte_lcore_is_enabled(i)) {
72 			int hp = 0;
73 			for (j = 0; j < nb_hp_lcores; j++) {
74 				if (hp_lcores[j] == i) {
75 					hp = 1;
76 					break;
77 				}
78 			}
79 			if (!hp)
80 				non_perf_lcores[nb_non_perf_lcores++] = i;
81 		}
82 	}
83 
84 	/* update the lcore config */
85 	for (i = 0; i < nb_prf_lc_prms; i++) {
86 		int lcore = -1;
87 		if (prf_lc_prms[i].high_perf) {
88 			if (prf_lc_prms[i].lcore_idx < nb_hp_lcores)
89 				lcore = hp_lcores[prf_lc_prms[i].lcore_idx];
90 		} else {
91 			if (prf_lc_prms[i].lcore_idx < nb_non_perf_lcores)
92 				lcore =
93 				non_perf_lcores[prf_lc_prms[i].lcore_idx];
94 		}
95 
96 		if (lcore < 0) {
97 			printf("Performance cores configuration error\n");
98 			return -1;
99 		}
100 
101 		lcore_params_array[i].lcore_id = lcore;
102 		lcore_params_array[i].queue_id = prf_lc_prms[i].queue_id;
103 		lcore_params_array[i].port_id = prf_lc_prms[i].port_id;
104 	}
105 
106 	lcore_params = lcore_params_array;
107 	nb_lcore_params = nb_prf_lc_prms;
108 
109 	printf("Updated performance core configuration\n");
110 	for (i = 0; i < nb_prf_lc_prms; i++)
111 		printf("\t(%d,%d,%d)\n", lcore_params[i].port_id,
112 				lcore_params[i].queue_id,
113 				lcore_params[i].lcore_id);
114 
115 	return 0;
116 }
117 
118 int
119 parse_perf_config(const char *q_arg)
120 {
121 	char s[256];
122 	const char *p, *p0 = q_arg;
123 	char *end;
124 	enum fieldnames {
125 		FLD_PORT = 0,
126 		FLD_QUEUE,
127 		FLD_LCORE_HP,
128 		FLD_LCORE_IDX,
129 		_NUM_FLD
130 	};
131 	unsigned long int_fld[_NUM_FLD];
132 	char *str_fld[_NUM_FLD];
133 	int i;
134 	unsigned int size;
135 	unsigned int max_fld[_NUM_FLD] = {
136 		RTE_MAX_ETHPORTS,
137 		RTE_MAX_QUEUES_PER_PORT,
138 		255,
139 		RTE_MAX_LCORE
140 	};
141 
142 	nb_prf_lc_prms = 0;
143 
144 	while ((p = strchr(p0, '(')) != NULL) {
145 		++p;
146 		p0 = strchr(p, ')');
147 		if (p0 == NULL)
148 			return -1;
149 
150 		size = p0 - p;
151 		if (size >= sizeof(s))
152 			return -1;
153 
154 		snprintf(s, sizeof(s), "%.*s", size, p);
155 		if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') !=
156 								_NUM_FLD)
157 			return -1;
158 		for (i = 0; i < _NUM_FLD; i++) {
159 			errno = 0;
160 			int_fld[i] = strtoul(str_fld[i], &end, 0);
161 			if (errno != 0 || end == str_fld[i] || int_fld[i] > max_fld[i])
162 
163 				return -1;
164 		}
165 		if (nb_prf_lc_prms >= MAX_LCORE_PARAMS) {
166 			printf("exceeded max number of lcore params: %hu\n",
167 					nb_prf_lc_prms);
168 			return -1;
169 		}
170 		prf_lc_prms[nb_prf_lc_prms].port_id =
171 				(uint16_t)int_fld[FLD_PORT];
172 		prf_lc_prms[nb_prf_lc_prms].queue_id =
173 				(uint16_t)int_fld[FLD_QUEUE];
174 		prf_lc_prms[nb_prf_lc_prms].high_perf =
175 				!!(uint8_t)int_fld[FLD_LCORE_HP];
176 		prf_lc_prms[nb_prf_lc_prms].lcore_idx =
177 				(uint32_t)int_fld[FLD_LCORE_IDX];
178 		++nb_prf_lc_prms;
179 	}
180 
181 	return 0;
182 }
183 
184 int
185 parse_perf_core_list(const char *corelist)
186 {
187 	int i, idx = 0;
188 	unsigned int count = 0;
189 	char *end = NULL;
190 	int min, max;
191 
192 	if (corelist == NULL) {
193 		printf("invalid core list\n");
194 		return -1;
195 	}
196 
197 
198 	/* Remove all blank characters ahead and after */
199 	while (isblank(*corelist))
200 		corelist++;
201 	i = strlen(corelist);
202 	while ((i > 0) && isblank(corelist[i - 1]))
203 		i--;
204 
205 	/* Get list of cores */
206 	min = RTE_MAX_LCORE;
207 	do {
208 		while (isblank(*corelist))
209 			corelist++;
210 		if (*corelist == '\0')
211 			return -1;
212 		errno = 0;
213 		idx = strtoul(corelist, &end, 10);
214 		if (errno || end == NULL)
215 			return -1;
216 		while (isblank(*end))
217 			end++;
218 		if (*end == '-') {
219 			min = idx;
220 		} else if ((*end == ',') || (*end == '\0')) {
221 			max = idx;
222 			if (min == RTE_MAX_LCORE)
223 				min = idx;
224 			for (idx = min; idx <= max; idx++) {
225 				hp_lcores[count] = idx;
226 				count++;
227 			}
228 			min = RTE_MAX_LCORE;
229 		} else {
230 			printf("invalid core list\n");
231 			return -1;
232 		}
233 		corelist = end + 1;
234 	} while (*end != '\0');
235 
236 	if (count == 0) {
237 		printf("invalid core list\n");
238 		return -1;
239 	}
240 
241 	nb_hp_lcores = count;
242 
243 	printf("Configured %d high performance cores\n", nb_hp_lcores);
244 	for (i = 0; i < nb_hp_lcores; i++)
245 		printf("\tHigh performance core %d %d\n",
246 				i, hp_lcores[i]);
247 
248 	return 0;
249 }
250