Imported Upstream version 16.04
[deb_dpdk.git] / examples / qos_sched / cfg_file.c
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 }