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