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 uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE]; 24 uint32_t n_active_queues; 25 26 struct rte_sched_cman_params cman_params; 27 28 int parse_u64(const char *entry, uint64_t *val) 29 { 30 char *endptr; 31 if (!entry || !val) 32 return -EINVAL; 33 34 errno = 0; 35 36 *val = strtoull(entry, &endptr, 0); 37 if (errno == EINVAL || errno == ERANGE || *endptr != '\0') 38 return -EINVAL; 39 40 return 0; 41 } 42 43 int 44 cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params) 45 { 46 const char *entry; 47 48 if (!cfg || !port_params) 49 return -1; 50 51 entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead"); 52 if (entry) 53 port_params->frame_overhead = (uint32_t)atoi(entry); 54 55 entry = rte_cfgfile_get_entry(cfg, "port", "number of subports per port"); 56 if (entry) 57 port_params->n_subports_per_port = (uint32_t)atoi(entry); 58 59 return 0; 60 } 61 62 int 63 cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params) 64 { 65 int i, j, ret = 0; 66 char *next; 67 const char *entry; 68 int profiles; 69 70 if (!cfg || !pipe_params) 71 return -1; 72 73 profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1); 74 subport_params[0].n_pipe_profiles = profiles; 75 76 for (j = 0; j < profiles; j++) { 77 char pipe_name[32]; 78 snprintf(pipe_name, sizeof(pipe_name), "pipe profile %d", j); 79 80 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb rate"); 81 ret = parse_u64(entry, &pipe_params[j].tb_rate); 82 if (ret) 83 return ret; 84 85 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb size"); 86 ret = parse_u64(entry, &pipe_params[j].tb_size); 87 if (ret) 88 return ret; 89 90 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc period"); 91 ret = parse_u64(entry, &pipe_params[j].tc_period); 92 if (ret) 93 return ret; 94 95 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 rate"); 96 ret = parse_u64(entry, &pipe_params[j].tc_rate[0]); 97 if (ret) 98 return ret; 99 100 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 rate"); 101 ret = parse_u64(entry, &pipe_params[j].tc_rate[1]); 102 if (ret) 103 return ret; 104 105 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 rate"); 106 ret = parse_u64(entry, &pipe_params[j].tc_rate[2]); 107 if (ret) 108 return ret; 109 110 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 rate"); 111 ret = parse_u64(entry, &pipe_params[j].tc_rate[3]); 112 if (ret) 113 return ret; 114 115 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 4 rate"); 116 ret = parse_u64(entry, &pipe_params[j].tc_rate[4]); 117 if (ret) 118 return ret; 119 120 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 5 rate"); 121 ret = parse_u64(entry, &pipe_params[j].tc_rate[5]); 122 if (ret) 123 return ret; 124 125 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 6 rate"); 126 ret = parse_u64(entry, &pipe_params[j].tc_rate[6]); 127 if (ret) 128 return ret; 129 130 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 7 rate"); 131 ret = parse_u64(entry, &pipe_params[j].tc_rate[7]); 132 if (ret) 133 return ret; 134 135 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 8 rate"); 136 ret = parse_u64(entry, &pipe_params[j].tc_rate[8]); 137 if (ret) 138 return ret; 139 140 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 9 rate"); 141 ret = parse_u64(entry, &pipe_params[j].tc_rate[9]); 142 if (ret) 143 return ret; 144 145 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 10 rate"); 146 ret = parse_u64(entry, &pipe_params[j].tc_rate[10]); 147 if (ret) 148 return ret; 149 150 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 11 rate"); 151 ret = parse_u64(entry, &pipe_params[j].tc_rate[11]); 152 if (ret) 153 return ret; 154 155 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 rate"); 156 ret = parse_u64(entry, &pipe_params[j].tc_rate[12]); 157 if (ret) 158 return ret; 159 160 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 oversubscription weight"); 161 if (entry) 162 pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry); 163 164 entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 wrr weights"); 165 if (entry) { 166 for (i = 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++) { 167 pipe_params[j].wrr_weights[i] = 168 (uint8_t)strtol(entry, &next, 10); 169 if (next == NULL) 170 break; 171 entry = next; 172 } 173 } 174 } 175 return 0; 176 } 177 178 int 179 cfg_load_subport_profile(struct rte_cfgfile *cfg, 180 struct rte_sched_subport_profile_params *subport_profile) 181 { 182 int i, ret = 0; 183 const char *entry; 184 int profiles; 185 186 if (!cfg || !subport_profile) 187 return -1; 188 189 profiles = rte_cfgfile_num_sections(cfg, "subport profile", 190 sizeof("subport profile") - 1); 191 port_params.n_subport_profiles = profiles; 192 193 for (i = 0; i < profiles; i++) { 194 char sec_name[32]; 195 snprintf(sec_name, sizeof(sec_name), "subport profile %d", i); 196 197 entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); 198 ret = parse_u64(entry, &subport_profile[i].tb_rate); 199 if (ret) 200 return ret; 201 202 entry = rte_cfgfile_get_entry(cfg, sec_name, "tb size"); 203 ret = parse_u64(entry, &subport_profile[i].tb_size); 204 if (ret) 205 return ret; 206 207 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc period"); 208 ret = parse_u64(entry, &subport_profile[i].tc_period); 209 if (ret) 210 return ret; 211 212 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 0 rate"); 213 ret = parse_u64(entry, &subport_profile[i].tc_rate[0]); 214 if (ret) 215 return ret; 216 217 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 1 rate"); 218 ret = parse_u64(entry, &subport_profile[i].tc_rate[1]); 219 if (ret) 220 return ret; 221 222 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 2 rate"); 223 ret = parse_u64(entry, &subport_profile[i].tc_rate[2]); 224 if (ret) 225 return ret; 226 227 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 3 rate"); 228 ret = parse_u64(entry, &subport_profile[i].tc_rate[3]); 229 if (ret) 230 return ret; 231 232 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 4 rate"); 233 ret = parse_u64(entry, &subport_profile[i].tc_rate[4]); 234 if (ret) 235 return ret; 236 237 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 5 rate"); 238 ret = parse_u64(entry, &subport_profile[i].tc_rate[5]); 239 if (ret) 240 return ret; 241 242 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 6 rate"); 243 ret = parse_u64(entry, &subport_profile[i].tc_rate[6]); 244 if (ret) 245 return ret; 246 247 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 7 rate"); 248 ret = parse_u64(entry, &subport_profile[i].tc_rate[7]); 249 if (ret) 250 return ret; 251 252 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 8 rate"); 253 ret = parse_u64(entry, &subport_profile[i].tc_rate[8]); 254 if (ret) 255 return ret; 256 257 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 9 rate"); 258 ret = parse_u64(entry, &subport_profile[i].tc_rate[9]); 259 if (ret) 260 return ret; 261 262 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 10 rate"); 263 ret = parse_u64(entry, &subport_profile[i].tc_rate[10]); 264 if (ret) 265 return ret; 266 267 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 11 rate"); 268 ret = parse_u64(entry, &subport_profile[i].tc_rate[11]); 269 if (ret) 270 return ret; 271 272 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 12 rate"); 273 ret = parse_u64(entry, &subport_profile[i].tc_rate[12]); 274 if (ret) 275 return ret; 276 } 277 278 return 0; 279 } 280 281 int 282 cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params) 283 { 284 bool cman_enabled = false; 285 const char *entry; 286 int i, j, k; 287 288 if (!cfg || !subport_params) 289 return -1; 290 291 memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); 292 memset(active_queues, 0, sizeof(active_queues)); 293 n_active_queues = 0; 294 295 if (rte_cfgfile_has_section(cfg, "red")) { 296 cman_params.cman_mode = RTE_SCHED_CMAN_RED; 297 cman_enabled = true; 298 299 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { 300 char str[32]; 301 302 /* Parse RED min thresholds */ 303 snprintf(str, sizeof(str), "tc %d red min", i); 304 entry = rte_cfgfile_get_entry(cfg, "red", str); 305 if (entry) { 306 char *next; 307 /* for each packet colour (green, yellow, red) */ 308 for (j = 0; j < RTE_COLORS; j++) { 309 cman_params.red_params[i][j].min_th 310 = (uint16_t)strtol(entry, &next, 10); 311 if (next == NULL) 312 break; 313 entry = next; 314 } 315 } 316 317 /* Parse RED max thresholds */ 318 snprintf(str, sizeof(str), "tc %d red max", i); 319 entry = rte_cfgfile_get_entry(cfg, "red", str); 320 if (entry) { 321 char *next; 322 /* for each packet colour (green, yellow, red) */ 323 for (j = 0; j < RTE_COLORS; j++) { 324 cman_params.red_params[i][j].max_th 325 = (uint16_t)strtol(entry, &next, 10); 326 if (next == NULL) 327 break; 328 entry = next; 329 } 330 } 331 332 /* Parse RED inverse mark probabilities */ 333 snprintf(str, sizeof(str), "tc %d red inv prob", i); 334 entry = rte_cfgfile_get_entry(cfg, "red", str); 335 if (entry) { 336 char *next; 337 /* for each packet colour (green, yellow, red) */ 338 for (j = 0; j < RTE_COLORS; j++) { 339 cman_params.red_params[i][j].maxp_inv 340 = (uint8_t)strtol(entry, &next, 10); 341 342 if (next == NULL) 343 break; 344 entry = next; 345 } 346 } 347 348 /* Parse RED EWMA filter weights */ 349 snprintf(str, sizeof(str), "tc %d red weight", i); 350 entry = rte_cfgfile_get_entry(cfg, "red", str); 351 if (entry) { 352 char *next; 353 /* for each packet colour (green, yellow, red) */ 354 for (j = 0; j < RTE_COLORS; j++) { 355 cman_params.red_params[i][j].wq_log2 356 = (uint8_t)strtol(entry, &next, 10); 357 if (next == NULL) 358 break; 359 entry = next; 360 } 361 } 362 } 363 } 364 365 if (rte_cfgfile_has_section(cfg, "pie")) { 366 cman_params.cman_mode = RTE_SCHED_CMAN_PIE; 367 cman_enabled = true; 368 369 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { 370 char str[32]; 371 372 /* Parse Queue Delay Ref value */ 373 snprintf(str, sizeof(str), "tc %d qdelay ref", i); 374 entry = rte_cfgfile_get_entry(cfg, "pie", str); 375 if (entry) 376 cman_params.pie_params[i].qdelay_ref = 377 (uint16_t) atoi(entry); 378 379 /* Parse Max Burst value */ 380 snprintf(str, sizeof(str), "tc %d max burst", i); 381 entry = rte_cfgfile_get_entry(cfg, "pie", str); 382 if (entry) 383 cman_params.pie_params[i].max_burst = 384 (uint16_t) atoi(entry); 385 386 /* Parse Update Interval Value */ 387 snprintf(str, sizeof(str), "tc %d update interval", i); 388 entry = rte_cfgfile_get_entry(cfg, "pie", str); 389 if (entry) 390 cman_params.pie_params[i].dp_update_interval = 391 (uint16_t) atoi(entry); 392 393 /* Parse Tailq Threshold Value */ 394 snprintf(str, sizeof(str), "tc %d tailq th", i); 395 entry = rte_cfgfile_get_entry(cfg, "pie", str); 396 if (entry) 397 cman_params.pie_params[i].tailq_th = 398 (uint16_t) atoi(entry); 399 400 } 401 } 402 403 for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { 404 char sec_name[CFG_NAME_LEN]; 405 snprintf(sec_name, sizeof(sec_name), "subport %d", i); 406 407 if (rte_cfgfile_has_section(cfg, sec_name)) { 408 entry = rte_cfgfile_get_entry(cfg, sec_name, 409 "number of pipes per subport"); 410 if (entry) 411 subport_params[i].n_pipes_per_subport_enabled = 412 (uint32_t)atoi(entry); 413 414 entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); 415 if (entry) { 416 char *next; 417 418 for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { 419 subport_params[i].qsize[j] = 420 (uint16_t)strtol(entry, &next, 10); 421 if (subport_params[i].qsize[j] != 0) { 422 active_queues[n_active_queues] = j; 423 n_active_queues++; 424 } 425 if (next == NULL) 426 break; 427 entry = next; 428 } 429 430 subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] = 431 (uint16_t)strtol(entry, &next, 10); 432 433 for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { 434 active_queues[n_active_queues] = 435 RTE_SCHED_TRAFFIC_CLASS_BE + j; 436 n_active_queues++; 437 } 438 } 439 440 int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name); 441 struct rte_cfgfile_entry entries[n_entries]; 442 443 rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries); 444 445 for (j = 0; j < n_entries; j++) { 446 if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) { 447 int profile; 448 char *tokens[2] = {NULL, NULL}; 449 int n_tokens; 450 int begin, end; 451 452 profile = atoi(entries[j].value); 453 n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")], 454 strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-'); 455 456 begin = atoi(tokens[0]); 457 if (n_tokens == 2) 458 end = atoi(tokens[1]); 459 else 460 end = begin; 461 462 if (end >= MAX_SCHED_PIPES || begin > end) 463 return -1; 464 465 for (k = begin; k <= end; k++) { 466 char profile_name[CFG_NAME_LEN]; 467 468 snprintf(profile_name, sizeof(profile_name), 469 "pipe profile %d", profile); 470 if (rte_cfgfile_has_section(cfg, profile_name)) 471 app_pipe_to_profile[i][k] = profile; 472 else 473 rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n", 474 entries[j].value); 475 476 } 477 } 478 } 479 if (cman_enabled) 480 subport_params[i].cman_params = &cman_params; 481 } 482 } 483 484 return 0; 485 } 486