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(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params) 147 { 148 const char *entry; 149 int i, j, k; 150 151 if (!cfg || !subport_params) 152 return -1; 153 154 memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); 155 memset(active_queues, 0, sizeof(active_queues)); 156 n_active_queues = 0; 157 158 #ifdef RTE_SCHED_RED 159 char sec_name[CFG_NAME_LEN]; 160 struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; 161 162 snprintf(sec_name, sizeof(sec_name), "red"); 163 164 if (rte_cfgfile_has_section(cfg, sec_name)) { 165 166 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { 167 char str[32]; 168 169 /* Parse WRED min thresholds */ 170 snprintf(str, sizeof(str), "tc %d wred min", i); 171 entry = rte_cfgfile_get_entry(cfg, sec_name, str); 172 if (entry) { 173 char *next; 174 /* for each packet colour (green, yellow, red) */ 175 for (j = 0; j < RTE_COLORS; j++) { 176 red_params[i][j].min_th 177 = (uint16_t)strtol(entry, &next, 10); 178 if (next == NULL) 179 break; 180 entry = next; 181 } 182 } 183 184 /* Parse WRED max thresholds */ 185 snprintf(str, sizeof(str), "tc %d wred max", i); 186 entry = rte_cfgfile_get_entry(cfg, "red", str); 187 if (entry) { 188 char *next; 189 /* for each packet colour (green, yellow, red) */ 190 for (j = 0; j < RTE_COLORS; j++) { 191 red_params[i][j].max_th 192 = (uint16_t)strtol(entry, &next, 10); 193 if (next == NULL) 194 break; 195 entry = next; 196 } 197 } 198 199 /* Parse WRED inverse mark probabilities */ 200 snprintf(str, sizeof(str), "tc %d wred inv prob", i); 201 entry = rte_cfgfile_get_entry(cfg, "red", str); 202 if (entry) { 203 char *next; 204 /* for each packet colour (green, yellow, red) */ 205 for (j = 0; j < RTE_COLORS; j++) { 206 red_params[i][j].maxp_inv 207 = (uint8_t)strtol(entry, &next, 10); 208 209 if (next == NULL) 210 break; 211 entry = next; 212 } 213 } 214 215 /* Parse WRED EWMA filter weights */ 216 snprintf(str, sizeof(str), "tc %d wred weight", i); 217 entry = rte_cfgfile_get_entry(cfg, "red", str); 218 if (entry) { 219 char *next; 220 /* for each packet colour (green, yellow, red) */ 221 for (j = 0; j < RTE_COLORS; j++) { 222 red_params[i][j].wq_log2 223 = (uint8_t)strtol(entry, &next, 10); 224 if (next == NULL) 225 break; 226 entry = next; 227 } 228 } 229 } 230 } 231 #endif /* RTE_SCHED_RED */ 232 233 for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { 234 char sec_name[CFG_NAME_LEN]; 235 snprintf(sec_name, sizeof(sec_name), "subport %d", i); 236 237 if (rte_cfgfile_has_section(cfg, sec_name)) { 238 entry = rte_cfgfile_get_entry(cfg, sec_name, 239 "number of pipes per subport"); 240 if (entry) 241 subport_params[i].n_pipes_per_subport_enabled = 242 (uint32_t)atoi(entry); 243 244 entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); 245 if (entry) { 246 char *next; 247 248 for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { 249 subport_params[i].qsize[j] = 250 (uint16_t)strtol(entry, &next, 10); 251 if (subport_params[i].qsize[j] != 0) { 252 active_queues[n_active_queues] = j; 253 n_active_queues++; 254 } 255 if (next == NULL) 256 break; 257 entry = next; 258 } 259 260 subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] = 261 (uint16_t)strtol(entry, &next, 10); 262 263 for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { 264 active_queues[n_active_queues] = 265 RTE_SCHED_TRAFFIC_CLASS_BE + j; 266 n_active_queues++; 267 } 268 } 269 270 entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); 271 if (entry) 272 subport_params[i].tb_rate = (uint64_t)atoi(entry); 273 274 entry = rte_cfgfile_get_entry(cfg, sec_name, "tb size"); 275 if (entry) 276 subport_params[i].tb_size = (uint64_t)atoi(entry); 277 278 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc period"); 279 if (entry) 280 subport_params[i].tc_period = (uint64_t)atoi(entry); 281 282 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 0 rate"); 283 if (entry) 284 subport_params[i].tc_rate[0] = (uint64_t)atoi(entry); 285 286 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 1 rate"); 287 if (entry) 288 subport_params[i].tc_rate[1] = (uint64_t)atoi(entry); 289 290 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 2 rate"); 291 if (entry) 292 subport_params[i].tc_rate[2] = (uint64_t)atoi(entry); 293 294 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 3 rate"); 295 if (entry) 296 subport_params[i].tc_rate[3] = (uint64_t)atoi(entry); 297 298 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 4 rate"); 299 if (entry) 300 subport_params[i].tc_rate[4] = (uint64_t)atoi(entry); 301 302 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 5 rate"); 303 if (entry) 304 subport_params[i].tc_rate[5] = (uint64_t)atoi(entry); 305 306 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 6 rate"); 307 if (entry) 308 subport_params[i].tc_rate[6] = (uint64_t)atoi(entry); 309 310 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 7 rate"); 311 if (entry) 312 subport_params[i].tc_rate[7] = (uint64_t)atoi(entry); 313 314 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 8 rate"); 315 if (entry) 316 subport_params[i].tc_rate[8] = (uint64_t)atoi(entry); 317 318 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 9 rate"); 319 if (entry) 320 subport_params[i].tc_rate[9] = (uint64_t)atoi(entry); 321 322 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 10 rate"); 323 if (entry) 324 subport_params[i].tc_rate[10] = (uint64_t)atoi(entry); 325 326 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 11 rate"); 327 if (entry) 328 subport_params[i].tc_rate[11] = (uint64_t)atoi(entry); 329 330 entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 12 rate"); 331 if (entry) 332 subport_params[i].tc_rate[12] = (uint64_t)atoi(entry); 333 334 int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name); 335 struct rte_cfgfile_entry entries[n_entries]; 336 337 rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries); 338 339 for (j = 0; j < n_entries; j++) { 340 if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) { 341 int profile; 342 char *tokens[2] = {NULL, NULL}; 343 int n_tokens; 344 int begin, end; 345 346 profile = atoi(entries[j].value); 347 n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")], 348 strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-'); 349 350 begin = atoi(tokens[0]); 351 if (n_tokens == 2) 352 end = atoi(tokens[1]); 353 else 354 end = begin; 355 356 if (end >= MAX_SCHED_PIPES || begin > end) 357 return -1; 358 359 for (k = begin; k <= end; k++) { 360 char profile_name[CFG_NAME_LEN]; 361 362 snprintf(profile_name, sizeof(profile_name), 363 "pipe profile %d", profile); 364 if (rte_cfgfile_has_section(cfg, profile_name)) 365 app_pipe_to_profile[i][k] = profile; 366 else 367 rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n", 368 entries[j].value); 369 370 } 371 } 372 } 373 #ifdef RTE_SCHED_RED 374 for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { 375 for (k = 0; k < RTE_COLORS; k++) { 376 subport_params[i].red_params[j][k].min_th = 377 red_params[j][k].min_th; 378 subport_params[i].red_params[j][k].max_th = 379 red_params[j][k].max_th; 380 subport_params[i].red_params[j][k].maxp_inv = 381 red_params[j][k].maxp_inv; 382 subport_params[i].red_params[j][k].wq_log2 = 383 red_params[j][k].wq_log2; 384 } 385 } 386 #endif 387 } 388 } 389 390 return 0; 391 } 392