xref: /dpdk/examples/qos_sched/cfg_file.c (revision e76d7a768ce085c140e41f338f45d50118964ae3)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <rte_string_fns.h>
39 #include <rte_sched.h>
40 
41 #include "cfg_file.h"
42 #include "main.h"
43 
44 
45 /** when we resize a file structure, how many extra entries
46  * for new sections do we add in */
47 #define CFG_ALLOC_SECTION_BATCH 8
48 /** when we resize a section structure, how many extra entries
49  * for new entries do we add in */
50 #define CFG_ALLOC_ENTRY_BATCH 16
51 
52 int
53 cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params)
54 {
55 	const char *entry;
56 	int j;
57 
58 	if (!cfg || !port_params)
59 		return -1;
60 
61 	entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead");
62 	if (entry)
63 		port_params->frame_overhead = (uint32_t)atoi(entry);
64 
65 	entry = rte_cfgfile_get_entry(cfg, "port", "number of subports per port");
66 	if (entry)
67 		port_params->n_subports_per_port = (uint32_t)atoi(entry);
68 
69 	entry = rte_cfgfile_get_entry(cfg, "port", "number of pipes per subport");
70 	if (entry)
71 		port_params->n_pipes_per_subport = (uint32_t)atoi(entry);
72 
73 	entry = rte_cfgfile_get_entry(cfg, "port", "queue sizes");
74 	if (entry) {
75 		char *next;
76 
77 		for(j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
78 			port_params->qsize[j] = (uint16_t)strtol(entry, &next, 10);
79 			if (next == NULL)
80 				break;
81 			entry = next;
82 		}
83 	}
84 
85 #ifdef RTE_SCHED_RED
86 	for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
87 		char str[32];
88 
89 		/* Parse WRED min thresholds */
90 		snprintf(str, sizeof(str), "tc %d wred min", j);
91 		entry = rte_cfgfile_get_entry(cfg, "red", str);
92 		if (entry) {
93 			char *next;
94 			int k;
95 			/* for each packet colour (green, yellow, red) */
96 			for (k = 0; k < e_RTE_METER_COLORS; k++) {
97 				port_params->red_params[j][k].min_th
98 					= (uint16_t)strtol(entry, &next, 10);
99 				if (next == NULL)
100 					break;
101 				entry = next;
102 			}
103 		}
104 
105 		/* Parse WRED max thresholds */
106 		snprintf(str, sizeof(str), "tc %d wred max", j);
107 		entry = rte_cfgfile_get_entry(cfg, "red", str);
108 		if (entry) {
109 			char *next;
110 			int k;
111 			/* for each packet colour (green, yellow, red) */
112 			for (k = 0; k < e_RTE_METER_COLORS; k++) {
113 				port_params->red_params[j][k].max_th
114 					= (uint16_t)strtol(entry, &next, 10);
115 				if (next == NULL)
116 					break;
117 				entry = next;
118 			}
119 		}
120 
121 		/* Parse WRED inverse mark probabilities */
122 		snprintf(str, sizeof(str), "tc %d wred inv prob", j);
123 		entry = rte_cfgfile_get_entry(cfg, "red", str);
124 		if (entry) {
125 			char *next;
126 			int k;
127 			/* for each packet colour (green, yellow, red) */
128 			for (k = 0; k < e_RTE_METER_COLORS; k++) {
129 				port_params->red_params[j][k].maxp_inv
130 					= (uint8_t)strtol(entry, &next, 10);
131 
132 				if (next == NULL)
133 					break;
134 				entry = next;
135 			}
136 		}
137 
138 		/* Parse WRED EWMA filter weights */
139 		snprintf(str, sizeof(str), "tc %d wred weight", j);
140 		entry = rte_cfgfile_get_entry(cfg, "red", str);
141 		if (entry) {
142 			char *next;
143 			int k;
144 			/* for each packet colour (green, yellow, red) */
145 			for (k = 0; k < e_RTE_METER_COLORS; k++) {
146 				port_params->red_params[j][k].wq_log2
147 					= (uint8_t)strtol(entry, &next, 10);
148 				if (next == NULL)
149 					break;
150 				entry = next;
151 			}
152 		}
153 	}
154 #endif /* RTE_SCHED_RED */
155 
156 	return 0;
157 }
158 
159 int
160 cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params)
161 {
162 	int i, j;
163 	char *next;
164 	const char *entry;
165 	int profiles;
166 
167 	if (!cfg || !pipe_params)
168 		return -1;
169 
170 	profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1);
171 	port_params.n_pipe_profiles = profiles;
172 
173 	for (j = 0; j < profiles; j++) {
174 		char pipe_name[32];
175 		snprintf(pipe_name, sizeof(pipe_name), "pipe profile %d", j);
176 
177 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb rate");
178 		if (entry)
179 			pipe_params[j].tb_rate = (uint32_t)atoi(entry);
180 
181 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb size");
182 		if (entry)
183 			pipe_params[j].tb_size = (uint32_t)atoi(entry);
184 
185 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc period");
186 		if (entry)
187 			pipe_params[j].tc_period = (uint32_t)atoi(entry);
188 
189 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 rate");
190 		if (entry)
191 			pipe_params[j].tc_rate[0] = (uint32_t)atoi(entry);
192 
193 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 rate");
194 		if (entry)
195 			pipe_params[j].tc_rate[1] = (uint32_t)atoi(entry);
196 
197 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 rate");
198 		if (entry)
199 			pipe_params[j].tc_rate[2] = (uint32_t)atoi(entry);
200 
201 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 rate");
202 		if (entry)
203 			pipe_params[j].tc_rate[3] = (uint32_t)atoi(entry);
204 
205 #ifdef RTE_SCHED_SUBPORT_TC_OV
206 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 oversubscription weight");
207 		if (entry)
208 			pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry);
209 #endif
210 
211 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 wrr weights");
212 		if (entry) {
213 			for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
214 				pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*0 + i] =
215 					(uint8_t)strtol(entry, &next, 10);
216 				if (next == NULL)
217 					break;
218 				entry = next;
219 			}
220 		}
221 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 wrr weights");
222 		if (entry) {
223 			for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
224 				pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*1 + i] =
225 					(uint8_t)strtol(entry, &next, 10);
226 				if (next == NULL)
227 					break;
228 				entry = next;
229 			}
230 		}
231 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 wrr weights");
232 		if (entry) {
233 			for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
234 				pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*2 + i] =
235 					(uint8_t)strtol(entry, &next, 10);
236 				if (next == NULL)
237 					break;
238 				entry = next;
239 			}
240 		}
241 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 wrr weights");
242 		if (entry) {
243 			for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
244 				pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*3 + i] =
245 					(uint8_t)strtol(entry, &next, 10);
246 				if (next == NULL)
247 					break;
248 				entry = next;
249 			}
250 		}
251 	}
252 	return 0;
253 }
254 
255 int
256 cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params)
257 {
258 	const char *entry;
259 	int i, j, k;
260 
261 	if (!cfg || !subport_params)
262 		return -1;
263 
264 	memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile));
265 
266 	for (i = 0; i < MAX_SCHED_SUBPORTS; i++) {
267 		char sec_name[CFG_NAME_LEN];
268 		snprintf(sec_name, sizeof(sec_name), "subport %d", i);
269 
270 		if (rte_cfgfile_has_section(cfg, sec_name)) {
271 			entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate");
272 			if (entry)
273 				subport_params[i].tb_rate = (uint32_t)atoi(entry);
274 
275 			entry = rte_cfgfile_get_entry(cfg, sec_name, "tb size");
276 			if (entry)
277 				subport_params[i].tb_size = (uint32_t)atoi(entry);
278 
279 			entry = rte_cfgfile_get_entry(cfg, sec_name, "tc period");
280 			if (entry)
281 				subport_params[i].tc_period = (uint32_t)atoi(entry);
282 
283 			entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 0 rate");
284 			if (entry)
285 				subport_params[i].tc_rate[0] = (uint32_t)atoi(entry);
286 
287 			entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 1 rate");
288 			if (entry)
289 				subport_params[i].tc_rate[1] = (uint32_t)atoi(entry);
290 
291 			entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 2 rate");
292 			if (entry)
293 				subport_params[i].tc_rate[2] = (uint32_t)atoi(entry);
294 
295 			entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 3 rate");
296 			if (entry)
297 				subport_params[i].tc_rate[3] = (uint32_t)atoi(entry);
298 
299 			int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name);
300 			struct rte_cfgfile_entry entries[n_entries];
301 
302 			rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries);
303 
304 			for (j = 0; j < n_entries; j++) {
305 				if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) {
306 					int profile;
307 					char *tokens[2] = {NULL, NULL};
308 					int n_tokens;
309 					int begin, end;
310 
311 					profile = atoi(entries[j].value);
312 					n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")],
313 							strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-');
314 
315 					begin =  atoi(tokens[0]);
316 					if (n_tokens == 2)
317 						end = atoi(tokens[1]);
318 					else
319 						end = begin;
320 
321 					if (end >= MAX_SCHED_PIPES || begin > end)
322 						return -1;
323 
324 					for (k = begin; k <= end; k++) {
325 						char profile_name[CFG_NAME_LEN];
326 
327 						snprintf(profile_name, sizeof(profile_name),
328 								"pipe profile %d", profile);
329 						if (rte_cfgfile_has_section(cfg, profile_name))
330 							app_pipe_to_profile[i][k] = profile;
331 						else
332 							rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n",
333 									entries[j].value);
334 
335 					}
336 				}
337 			}
338 		}
339 	}
340 
341 	return 0;
342 }
343