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 28 if (!cfg || !port_params) 29 return -1; 30 31 entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead"); 32 if (entry) 33 port_params->frame_overhead = (uint32_t)atoi(entry); 34 35 entry = rte_cfgfile_get_entry(cfg, "port", "number of subports per port"); 36 if (entry) 37 port_params->n_subports_per_port = (uint32_t)atoi(entry); 38 39 return 0; 40 } 41 42 int 43 cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params) 44 { 45 int i, j; 46 char *next; 47 const char *entry; 48 int profiles; 49 50 if (!cfg || !pipe_params) 51 return -1; 52 53 profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1); 54 subport_params[0].n_pipe_profiles = profiles; 55 56 for (j = 0; j < profiles; j++) { 57 char pipe_name[32]; 58 snprintf(pipe_name, sizeof(pipe_name), "pipe profile %d", j); 59 60 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb rate"); 61 if (entry) 62 pipe_params[j].tb_rate = (uint64_t)atoi(entry); 63 64 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb size"); 65 if (entry) 66 pipe_params[j].tb_size = (uint64_t)atoi(entry); 67 68 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc period"); 69 if (entry) 70 pipe_params[j].tc_period = (uint64_t)atoi(entry); 71 72 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 rate"); 73 if (entry) 74 pipe_params[j].tc_rate[0] = (uint64_t)atoi(entry); 75 76 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 rate"); 77 if (entry) 78 pipe_params[j].tc_rate[1] = (uint64_t)atoi(entry); 79 80 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 rate"); 81 if (entry) 82 pipe_params[j].tc_rate[2] = (uint64_t)atoi(entry); 83 84 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 rate"); 85 if (entry) 86 pipe_params[j].tc_rate[3] = (uint64_t)atoi(entry); 87 88 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 4 rate"); 89 if (entry) 90 pipe_params[j].tc_rate[4] = (uint64_t)atoi(entry); 91 92 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 5 rate"); 93 if (entry) 94 pipe_params[j].tc_rate[5] = (uint64_t)atoi(entry); 95 96 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 6 rate"); 97 if (entry) 98 pipe_params[j].tc_rate[6] = (uint64_t)atoi(entry); 99 100 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 7 rate"); 101 if (entry) 102 pipe_params[j].tc_rate[7] = (uint64_t)atoi(entry); 103 104 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 8 rate"); 105 if (entry) 106 pipe_params[j].tc_rate[8] = (uint64_t)atoi(entry); 107 108 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 9 rate"); 109 if (entry) 110 pipe_params[j].tc_rate[9] = (uint64_t)atoi(entry); 111 112 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 10 rate"); 113 if (entry) 114 pipe_params[j].tc_rate[10] = (uint64_t)atoi(entry); 115 116 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 11 rate"); 117 if (entry) 118 pipe_params[j].tc_rate[11] = (uint64_t)atoi(entry); 119 120 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 rate"); 121 if (entry) 122 pipe_params[j].tc_rate[12] = (uint64_t)atoi(entry); 123 124 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 oversubscription weight"); 125 if (entry) 126 pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry); 127 128 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 wrr weights"); 129 if (entry) { 130 for (i = 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++) { 131 pipe_params[j].wrr_weights[i] = 132 (uint8_t)strtol(entry, &next, 10); 133 if (next == NULL) 134 break; 135 entry = next; 136 } 137 } 138 } 139 return 0; 140 } 141 142 int 143 cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params) 144 { 145 const char *entry; 146 int i, j, k; 147 148 if (!cfg || !subport_params) 149 return -1; 150 151 memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); 152 memset(active_queues, 0, sizeof(active_queues)); 153 n_active_queues = 0; 154 155 #ifdef RTE_SCHED_RED 156 char sec_name[CFG_NAME_LEN]; 157 struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; 158 159 snprintf(sec_name, sizeof(sec_name), "red"); 160 161 if (rte_cfgfile_has_section(cfg, sec_name)) { 162 163 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { 164 char str[32]; 165 166 /* Parse WRED min thresholds */ 167 snprintf(str, sizeof(str), "tc %d wred min", i); 168 entry = rte_cfgfile_get_entry(cfg, sec_name, str); 169 if (entry) { 170 char *next; 171 /* for each packet colour (green, yellow, red) */ 172 for (j = 0; j < RTE_COLORS; j++) { 173 red_params[i][j].min_th 174 = (uint16_t)strtol(entry, &next, 10); 175 if (next == NULL) 176 break; 177 entry = next; 178 } 179 } 180 181 /* Parse WRED max thresholds */ 182 snprintf(str, sizeof(str), "tc %d wred max", i); 183 entry = rte_cfgfile_get_entry(cfg, "red", str); 184 if (entry) { 185 char *next; 186 /* for each packet colour (green, yellow, red) */ 187 for (j = 0; j < RTE_COLORS; j++) { 188 red_params[i][j].max_th 189 = (uint16_t)strtol(entry, &next, 10); 190 if (next == NULL) 191 break; 192 entry = next; 193 } 194 } 195 196 /* Parse WRED inverse mark probabilities */ 197 snprintf(str, sizeof(str), "tc %d wred inv prob", i); 198 entry = rte_cfgfile_get_entry(cfg, "red", str); 199 if (entry) { 200 char *next; 201 /* for each packet colour (green, yellow, red) */ 202 for (j = 0; j < RTE_COLORS; j++) { 203 red_params[i][j].maxp_inv 204 = (uint8_t)strtol(entry, &next, 10); 205 206 if (next == NULL) 207 break; 208 entry = next; 209 } 210 } 211 212 /* Parse WRED EWMA filter weights */ 213 snprintf(str, sizeof(str), "tc %d wred weight", i); 214 entry = rte_cfgfile_get_entry(cfg, "red", str); 215 if (entry) { 216 char *next; 217 /* for each packet colour (green, yellow, red) */ 218 for (j = 0; j < RTE_COLORS; j++) { 219 red_params[i][j].wq_log2 220 = (uint8_t)strtol(entry, &next, 10); 221 if (next == NULL) 222 break; 223 entry = next; 224 } 225 } 226 } 227 } 228 #endif /* RTE_SCHED_RED */ 229 230 for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { 231 char sec_name[CFG_NAME_LEN]; 232 snprintf(sec_name, sizeof(sec_name), "subport %d", i); 233 234 if (rte_cfgfile_has_section(cfg, sec_name)) { 235 entry = rte_cfgfile_get_entry(cfg, sec_name, 236 "number of pipes per subport"); 237 if (entry) 238 subport_params[i].n_pipes_per_subport_enabled = 239 (uint32_t)atoi(entry); 240 241 entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); 242 if (entry) { 243 char *next; 244 245 for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { 246 subport_params[i].qsize[j] = 247 (uint16_t)strtol(entry, &next, 10); 248 if (subport_params[i].qsize[j] != 0) { 249 active_queues[n_active_queues] = j; 250 n_active_queues++; 251 } 252 if (next == NULL) 253 break; 254 entry = next; 255 } 256 257 subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] = 258 (uint16_t)strtol(entry, &next, 10); 259 260 for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { 261 active_queues[n_active_queues] = 262 RTE_SCHED_TRAFFIC_CLASS_BE + j; 263 n_active_queues++; 264 } 265 } 266 267 entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); 268 if (entry) 269 subport_params[i].tb_rate = (uint64_t)atoi(entry); 270 271 entry = rte_cfgfile_get_entry(cfg, sec_name, "tb size"); 272 if (entry) 273 subport_params[i].tb_size = (uint64_t)atoi(entry); 274 275 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc period"); 276 if (entry) 277 subport_params[i].tc_period = (uint64_t)atoi(entry); 278 279 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 0 rate"); 280 if (entry) 281 subport_params[i].tc_rate[0] = (uint64_t)atoi(entry); 282 283 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 1 rate"); 284 if (entry) 285 subport_params[i].tc_rate[1] = (uint64_t)atoi(entry); 286 287 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 2 rate"); 288 if (entry) 289 subport_params[i].tc_rate[2] = (uint64_t)atoi(entry); 290 291 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 3 rate"); 292 if (entry) 293 subport_params[i].tc_rate[3] = (uint64_t)atoi(entry); 294 295 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 4 rate"); 296 if (entry) 297 subport_params[i].tc_rate[4] = (uint64_t)atoi(entry); 298 299 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 5 rate"); 300 if (entry) 301 subport_params[i].tc_rate[5] = (uint64_t)atoi(entry); 302 303 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 6 rate"); 304 if (entry) 305 subport_params[i].tc_rate[6] = (uint64_t)atoi(entry); 306 307 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 7 rate"); 308 if (entry) 309 subport_params[i].tc_rate[7] = (uint64_t)atoi(entry); 310 311 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 8 rate"); 312 if (entry) 313 subport_params[i].tc_rate[8] = (uint64_t)atoi(entry); 314 315 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 9 rate"); 316 if (entry) 317 subport_params[i].tc_rate[9] = (uint64_t)atoi(entry); 318 319 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 10 rate"); 320 if (entry) 321 subport_params[i].tc_rate[10] = (uint64_t)atoi(entry); 322 323 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 11 rate"); 324 if (entry) 325 subport_params[i].tc_rate[11] = (uint64_t)atoi(entry); 326 327 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 12 rate"); 328 if (entry) 329 subport_params[i].tc_rate[12] = (uint64_t)atoi(entry); 330 331 int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name); 332 struct rte_cfgfile_entry entries[n_entries]; 333 334 rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries); 335 336 for (j = 0; j < n_entries; j++) { 337 if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) { 338 int profile; 339 char *tokens[2] = {NULL, NULL}; 340 int n_tokens; 341 int begin, end; 342 343 profile = atoi(entries[j].value); 344 n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")], 345 strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-'); 346 347 begin = atoi(tokens[0]); 348 if (n_tokens == 2) 349 end = atoi(tokens[1]); 350 else 351 end = begin; 352 353 if (end >= MAX_SCHED_PIPES || begin > end) 354 return -1; 355 356 for (k = begin; k <= end; k++) { 357 char profile_name[CFG_NAME_LEN]; 358 359 snprintf(profile_name, sizeof(profile_name), 360 "pipe profile %d", profile); 361 if (rte_cfgfile_has_section(cfg, profile_name)) 362 app_pipe_to_profile[i][k] = profile; 363 else 364 rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n", 365 entries[j].value); 366 367 } 368 } 369 } 370 #ifdef RTE_SCHED_RED 371 for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { 372 for (k = 0; k < RTE_COLORS; k++) { 373 subport_params[i].red_params[j][k].min_th = 374 red_params[j][k].min_th; 375 subport_params[i].red_params[j][k].max_th = 376 red_params[j][k].max_th; 377 subport_params[i].red_params[j][k].maxp_inv = 378 red_params[j][k].maxp_inv; 379 subport_params[i].red_params[j][k].wq_log2 = 380 red_params[j][k].wq_log2; 381 } 382 } 383 #endif 384 } 385 } 386 387 return 0; 388 } 389