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 int 233 cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params) 234 { 235 const char *entry; 236 int i, j, k; 237 238 if (!cfg || !subport_params) 239 return -1; 240 241 memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); 242 memset(active_queues, 0, sizeof(active_queues)); 243 n_active_queues = 0; 244 245 #ifdef RTE_SCHED_RED 246 char sec_name[CFG_NAME_LEN]; 247 struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; 248 249 snprintf(sec_name, sizeof(sec_name), "red"); 250 251 if (rte_cfgfile_has_section(cfg, sec_name)) { 252 253 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { 254 char str[32]; 255 256 /* Parse WRED min thresholds */ 257 snprintf(str, sizeof(str), "tc %d wred min", i); 258 entry = rte_cfgfile_get_entry(cfg, sec_name, str); 259 if (entry) { 260 char *next; 261 /* for each packet colour (green, yellow, red) */ 262 for (j = 0; j < RTE_COLORS; j++) { 263 red_params[i][j].min_th 264 = (uint16_t)strtol(entry, &next, 10); 265 if (next == NULL) 266 break; 267 entry = next; 268 } 269 } 270 271 /* Parse WRED max thresholds */ 272 snprintf(str, sizeof(str), "tc %d wred max", i); 273 entry = rte_cfgfile_get_entry(cfg, "red", str); 274 if (entry) { 275 char *next; 276 /* for each packet colour (green, yellow, red) */ 277 for (j = 0; j < RTE_COLORS; j++) { 278 red_params[i][j].max_th 279 = (uint16_t)strtol(entry, &next, 10); 280 if (next == NULL) 281 break; 282 entry = next; 283 } 284 } 285 286 /* Parse WRED inverse mark probabilities */ 287 snprintf(str, sizeof(str), "tc %d wred inv prob", i); 288 entry = rte_cfgfile_get_entry(cfg, "red", str); 289 if (entry) { 290 char *next; 291 /* for each packet colour (green, yellow, red) */ 292 for (j = 0; j < RTE_COLORS; j++) { 293 red_params[i][j].maxp_inv 294 = (uint8_t)strtol(entry, &next, 10); 295 296 if (next == NULL) 297 break; 298 entry = next; 299 } 300 } 301 302 /* Parse WRED EWMA filter weights */ 303 snprintf(str, sizeof(str), "tc %d wred weight", 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 red_params[i][j].wq_log2 310 = (uint8_t)strtol(entry, &next, 10); 311 if (next == NULL) 312 break; 313 entry = next; 314 } 315 } 316 } 317 } 318 #endif /* RTE_SCHED_RED */ 319 320 for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { 321 char sec_name[CFG_NAME_LEN]; 322 snprintf(sec_name, sizeof(sec_name), "subport %d", i); 323 324 if (rte_cfgfile_has_section(cfg, sec_name)) { 325 entry = rte_cfgfile_get_entry(cfg, sec_name, 326 "number of pipes per subport"); 327 if (entry) 328 subport_params[i].n_pipes_per_subport_enabled = 329 (uint32_t)atoi(entry); 330 331 entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); 332 if (entry) { 333 char *next; 334 335 for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { 336 subport_params[i].qsize[j] = 337 (uint16_t)strtol(entry, &next, 10); 338 if (subport_params[i].qsize[j] != 0) { 339 active_queues[n_active_queues] = j; 340 n_active_queues++; 341 } 342 if (next == NULL) 343 break; 344 entry = next; 345 } 346 347 subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] = 348 (uint16_t)strtol(entry, &next, 10); 349 350 for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { 351 active_queues[n_active_queues] = 352 RTE_SCHED_TRAFFIC_CLASS_BE + j; 353 n_active_queues++; 354 } 355 } 356 357 int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name); 358 struct rte_cfgfile_entry entries[n_entries]; 359 360 rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries); 361 362 for (j = 0; j < n_entries; j++) { 363 if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) { 364 int profile; 365 char *tokens[2] = {NULL, NULL}; 366 int n_tokens; 367 int begin, end; 368 369 profile = atoi(entries[j].value); 370 n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")], 371 strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-'); 372 373 begin = atoi(tokens[0]); 374 if (n_tokens == 2) 375 end = atoi(tokens[1]); 376 else 377 end = begin; 378 379 if (end >= MAX_SCHED_PIPES || begin > end) 380 return -1; 381 382 for (k = begin; k <= end; k++) { 383 char profile_name[CFG_NAME_LEN]; 384 385 snprintf(profile_name, sizeof(profile_name), 386 "pipe profile %d", profile); 387 if (rte_cfgfile_has_section(cfg, profile_name)) 388 app_pipe_to_profile[i][k] = profile; 389 else 390 rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n", 391 entries[j].value); 392 393 } 394 } 395 } 396 #ifdef RTE_SCHED_RED 397 for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { 398 for (k = 0; k < RTE_COLORS; k++) { 399 subport_params[i].red_params[j][k].min_th = 400 red_params[j][k].min_th; 401 subport_params[i].red_params[j][k].max_th = 402 red_params[j][k].max_th; 403 subport_params[i].red_params[j][k].maxp_inv = 404 red_params[j][k].maxp_inv; 405 subport_params[i].red_params[j][k].wq_log2 = 406 red_params[j][k].wq_log2; 407 } 408 } 409 #endif 410 } 411 } 412 413 return 0; 414 } 415