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