power: fix frequency list buffer validation
[dpdk.git] / examples / qos_sched / cfg_file.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <rte_string_fns.h>
10 #include <rte_sched.h>
11
12 #include "cfg_file.h"
13 #include "main.h"
14
15
16 /** when we resize a file structure, how many extra entries
17  * for new sections do we add in */
18 #define CFG_ALLOC_SECTION_BATCH 8
19 /** when we resize a section structure, how many extra entries
20  * for new entries do we add in */
21 #define CFG_ALLOC_ENTRY_BATCH 16
22
23 int
24 cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params)
25 {
26         const char *entry;
27         int j;
28
29         if (!cfg || !port_params)
30                 return -1;
31
32         entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead");
33         if (entry)
34                 port_params->frame_overhead = (uint32_t)atoi(entry);
35
36         entry = rte_cfgfile_get_entry(cfg, "port", "number of subports per port");
37         if (entry)
38                 port_params->n_subports_per_port = (uint32_t)atoi(entry);
39
40         entry = rte_cfgfile_get_entry(cfg, "port", "number of pipes per subport");
41         if (entry)
42                 port_params->n_pipes_per_subport = (uint32_t)atoi(entry);
43
44         entry = rte_cfgfile_get_entry(cfg, "port", "queue sizes");
45         if (entry) {
46                 char *next;
47
48                 for(j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
49                         port_params->qsize[j] = (uint16_t)strtol(entry, &next, 10);
50                         if (next == NULL)
51                                 break;
52                         entry = next;
53                 }
54         }
55
56 #ifdef RTE_SCHED_RED
57         for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
58                 char str[32];
59
60                 /* Parse WRED min thresholds */
61                 snprintf(str, sizeof(str), "tc %d wred min", j);
62                 entry = rte_cfgfile_get_entry(cfg, "red", str);
63                 if (entry) {
64                         char *next;
65                         int k;
66                         /* for each packet colour (green, yellow, red) */
67                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
68                                 port_params->red_params[j][k].min_th
69                                         = (uint16_t)strtol(entry, &next, 10);
70                                 if (next == NULL)
71                                         break;
72                                 entry = next;
73                         }
74                 }
75
76                 /* Parse WRED max thresholds */
77                 snprintf(str, sizeof(str), "tc %d wred max", j);
78                 entry = rte_cfgfile_get_entry(cfg, "red", str);
79                 if (entry) {
80                         char *next;
81                         int k;
82                         /* for each packet colour (green, yellow, red) */
83                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
84                                 port_params->red_params[j][k].max_th
85                                         = (uint16_t)strtol(entry, &next, 10);
86                                 if (next == NULL)
87                                         break;
88                                 entry = next;
89                         }
90                 }
91
92                 /* Parse WRED inverse mark probabilities */
93                 snprintf(str, sizeof(str), "tc %d wred inv prob", j);
94                 entry = rte_cfgfile_get_entry(cfg, "red", str);
95                 if (entry) {
96                         char *next;
97                         int k;
98                         /* for each packet colour (green, yellow, red) */
99                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
100                                 port_params->red_params[j][k].maxp_inv
101                                         = (uint8_t)strtol(entry, &next, 10);
102
103                                 if (next == NULL)
104                                         break;
105                                 entry = next;
106                         }
107                 }
108
109                 /* Parse WRED EWMA filter weights */
110                 snprintf(str, sizeof(str), "tc %d wred weight", j);
111                 entry = rte_cfgfile_get_entry(cfg, "red", str);
112                 if (entry) {
113                         char *next;
114                         int k;
115                         /* for each packet colour (green, yellow, red) */
116                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
117                                 port_params->red_params[j][k].wq_log2
118                                         = (uint8_t)strtol(entry, &next, 10);
119                                 if (next == NULL)
120                                         break;
121                                 entry = next;
122                         }
123                 }
124         }
125 #endif /* RTE_SCHED_RED */
126
127         return 0;
128 }
129
130 int
131 cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params)
132 {
133         int i, j;
134         char *next;
135         const char *entry;
136         int profiles;
137
138         if (!cfg || !pipe_params)
139                 return -1;
140
141         profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1);
142         port_params.n_pipe_profiles = profiles;
143
144         for (j = 0; j < profiles; j++) {
145                 char pipe_name[32];
146                 snprintf(pipe_name, sizeof(pipe_name), "pipe profile %d", j);
147
148                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb rate");
149                 if (entry)
150                         pipe_params[j].tb_rate = (uint32_t)atoi(entry);
151
152                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb size");
153                 if (entry)
154                         pipe_params[j].tb_size = (uint32_t)atoi(entry);
155
156                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc period");
157                 if (entry)
158                         pipe_params[j].tc_period = (uint32_t)atoi(entry);
159
160                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 rate");
161                 if (entry)
162                         pipe_params[j].tc_rate[0] = (uint32_t)atoi(entry);
163
164                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 rate");
165                 if (entry)
166                         pipe_params[j].tc_rate[1] = (uint32_t)atoi(entry);
167
168                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 rate");
169                 if (entry)
170                         pipe_params[j].tc_rate[2] = (uint32_t)atoi(entry);
171
172                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 rate");
173                 if (entry)
174                         pipe_params[j].tc_rate[3] = (uint32_t)atoi(entry);
175
176 #ifdef RTE_SCHED_SUBPORT_TC_OV
177                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 oversubscription weight");
178                 if (entry)
179                         pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry);
180 #endif
181
182                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 wrr weights");
183                 if (entry) {
184                         for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
185                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*0 + i] =
186                                         (uint8_t)strtol(entry, &next, 10);
187                                 if (next == NULL)
188                                         break;
189                                 entry = next;
190                         }
191                 }
192                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 wrr weights");
193                 if (entry) {
194                         for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
195                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*1 + i] =
196                                         (uint8_t)strtol(entry, &next, 10);
197                                 if (next == NULL)
198                                         break;
199                                 entry = next;
200                         }
201                 }
202                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 wrr weights");
203                 if (entry) {
204                         for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
205                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*2 + i] =
206                                         (uint8_t)strtol(entry, &next, 10);
207                                 if (next == NULL)
208                                         break;
209                                 entry = next;
210                         }
211                 }
212                 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 wrr weights");
213                 if (entry) {
214                         for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
215                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*3 + i] =
216                                         (uint8_t)strtol(entry, &next, 10);
217                                 if (next == NULL)
218                                         break;
219                                 entry = next;
220                         }
221                 }
222         }
223         return 0;
224 }
225
226 int
227 cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params)
228 {
229         const char *entry;
230         int i, j, k;
231
232         if (!cfg || !subport_params)
233                 return -1;
234
235         memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile));
236
237         for (i = 0; i < MAX_SCHED_SUBPORTS; i++) {
238                 char sec_name[CFG_NAME_LEN];
239                 snprintf(sec_name, sizeof(sec_name), "subport %d", i);
240
241                 if (rte_cfgfile_has_section(cfg, sec_name)) {
242                         entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate");
243                         if (entry)
244                                 subport_params[i].tb_rate = (uint32_t)atoi(entry);
245
246                         entry = rte_cfgfile_get_entry(cfg, sec_name, "tb size");
247                         if (entry)
248                                 subport_params[i].tb_size = (uint32_t)atoi(entry);
249
250                         entry = rte_cfgfile_get_entry(cfg, sec_name, "tc period");
251                         if (entry)
252                                 subport_params[i].tc_period = (uint32_t)atoi(entry);
253
254                         entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 0 rate");
255                         if (entry)
256                                 subport_params[i].tc_rate[0] = (uint32_t)atoi(entry);
257
258                         entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 1 rate");
259                         if (entry)
260                                 subport_params[i].tc_rate[1] = (uint32_t)atoi(entry);
261
262                         entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 2 rate");
263                         if (entry)
264                                 subport_params[i].tc_rate[2] = (uint32_t)atoi(entry);
265
266                         entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 3 rate");
267                         if (entry)
268                                 subport_params[i].tc_rate[3] = (uint32_t)atoi(entry);
269
270                         int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name);
271                         struct rte_cfgfile_entry entries[n_entries];
272
273                         rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries);
274
275                         for (j = 0; j < n_entries; j++) {
276                                 if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) {
277                                         int profile;
278                                         char *tokens[2] = {NULL, NULL};
279                                         int n_tokens;
280                                         int begin, end;
281
282                                         profile = atoi(entries[j].value);
283                                         n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")],
284                                                         strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-');
285
286                                         begin =  atoi(tokens[0]);
287                                         if (n_tokens == 2)
288                                                 end = atoi(tokens[1]);
289                                         else
290                                                 end = begin;
291
292                                         if (end >= MAX_SCHED_PIPES || begin > end)
293                                                 return -1;
294
295                                         for (k = begin; k <= end; k++) {
296                                                 char profile_name[CFG_NAME_LEN];
297
298                                                 snprintf(profile_name, sizeof(profile_name),
299                                                                 "pipe profile %d", profile);
300                                                 if (rte_cfgfile_has_section(cfg, profile_name))
301                                                         app_pipe_to_profile[i][k] = profile;
302                                                 else
303                                                         rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n",
304                                                                         entries[j].value);
305
306                                         }
307                                 }
308                         }
309                 }
310         }
311
312         return 0;
313 }