1fe939687SNatalie Samsonov /* SPDX-License-Identifier: BSD-3-Clause 2fe939687SNatalie Samsonov * Copyright(c) 2017 Marvell International Ltd. 3fe939687SNatalie Samsonov * Copyright(c) 2017 Semihalf. 4fe939687SNatalie Samsonov * All rights reserved. 5fe939687SNatalie Samsonov */ 6fe939687SNatalie Samsonov 7fe939687SNatalie Samsonov #include <stdint.h> 8fe939687SNatalie Samsonov #include <stdlib.h> 9fe939687SNatalie Samsonov #include <string.h> 10fe939687SNatalie Samsonov 11fe939687SNatalie Samsonov #include <rte_common.h> 12fe939687SNatalie Samsonov #include <rte_cfgfile.h> 13fe939687SNatalie Samsonov #include <rte_log.h> 14fe939687SNatalie Samsonov #include <rte_lcore.h> 15fe939687SNatalie Samsonov #include <rte_malloc.h> 16fe939687SNatalie Samsonov #include <rte_string_fns.h> 17fe939687SNatalie Samsonov 18fe939687SNatalie Samsonov #include "mrvl_qos.h" 19fe939687SNatalie Samsonov 20fe939687SNatalie Samsonov /* Parsing tokens. Defined conveniently, so that any correction is easy. */ 21fe939687SNatalie Samsonov #define MRVL_TOK_DEFAULT "default" 22c2b5ae61SLiron Himi #define MRVL_TOK_DSA_MODE "dsa_mode" 236000b5beSDana Vardi #define MRVL_TOK_START_HDR "start_hdr" 246000b5beSDana Vardi #define MRVL_TOK_START_HDR_NONE "none" 256000b5beSDana Vardi #define MRVL_TOK_START_HDR_DSA "dsa" 2621aa25e0SDana Vardi #define MRVL_TOK_START_HDR_CUSTOM "custom" 276000b5beSDana Vardi #define MRVL_TOK_START_HDR_EXT_DSA "ext_dsa" 28fe939687SNatalie Samsonov #define MRVL_TOK_DEFAULT_TC "default_tc" 29fe939687SNatalie Samsonov #define MRVL_TOK_DSCP "dscp" 30fe939687SNatalie Samsonov #define MRVL_TOK_MAPPING_PRIORITY "mapping_priority" 31fe939687SNatalie Samsonov #define MRVL_TOK_IP "ip" 32fe939687SNatalie Samsonov #define MRVL_TOK_IP_VLAN "ip/vlan" 33fe939687SNatalie Samsonov #define MRVL_TOK_PCP "pcp" 34fe939687SNatalie Samsonov #define MRVL_TOK_PORT "port" 35fe939687SNatalie Samsonov #define MRVL_TOK_RXQ "rxq" 36fe939687SNatalie Samsonov #define MRVL_TOK_TC "tc" 37fe939687SNatalie Samsonov #define MRVL_TOK_TXQ "txq" 38fe939687SNatalie Samsonov #define MRVL_TOK_VLAN "vlan" 39fe939687SNatalie Samsonov #define MRVL_TOK_VLAN_IP "vlan/ip" 403e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF "parser udf" 41fe939687SNatalie Samsonov 42fe939687SNatalie Samsonov /* egress specific configuration tokens */ 43fe939687SNatalie Samsonov #define MRVL_TOK_BURST_SIZE "burst_size" 44fe939687SNatalie Samsonov #define MRVL_TOK_RATE_LIMIT "rate_limit" 45fe939687SNatalie Samsonov #define MRVL_TOK_RATE_LIMIT_ENABLE "rate_limit_enable" 46fe939687SNatalie Samsonov #define MRVL_TOK_SCHED_MODE "sched_mode" 47fe939687SNatalie Samsonov #define MRVL_TOK_SCHED_MODE_SP "sp" 48fe939687SNatalie Samsonov #define MRVL_TOK_SCHED_MODE_WRR "wrr" 49fe939687SNatalie Samsonov #define MRVL_TOK_WRR_WEIGHT "wrr_weight" 50fe939687SNatalie Samsonov 51fe939687SNatalie Samsonov /* policer specific configuration tokens */ 52e97d8874STomasz Duszynski #define MRVL_TOK_PLCR "policer" 53e97d8874STomasz Duszynski #define MRVL_TOK_PLCR_DEFAULT "default_policer" 54fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_UNIT "token_unit" 55fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_UNIT_BYTES "bytes" 56fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_UNIT_PACKETS "packets" 57fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_COLOR "color_mode" 58fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_COLOR_BLIND "blind" 59fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_COLOR_AWARE "aware" 60fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_CIR "cir" 61fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_CBS "cbs" 62fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_EBS "ebs" 63fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_DEFAULT_COLOR "default_color" 64fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_DEFAULT_COLOR_GREEN "green" 65fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_DEFAULT_COLOR_YELLOW "yellow" 66fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_DEFAULT_COLOR_RED "red" 67fe939687SNatalie Samsonov 683e09b2a7SLiron Himi /* parser udf specific configuration tokens */ 693e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_PROTO "proto" 703e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_FIELD "field" 713e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_KEY "key" 723e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_MASK "mask" 733e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_OFFSET "offset" 743e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_PROTO_ETH "eth" 753e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_FIELD_ETH_TYPE "type" 763e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_PROTO_UDP "udp" 773e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_FIELD_UDP_DPORT "dport" 783e09b2a7SLiron Himi 79ef08031fSDana Vardi /* parser forward bad frames tokens */ 80ef08031fSDana Vardi #define MRVL_TOK_FWD_BAD_FRAMES "forward_bad_frames" 813e09b2a7SLiron Himi 824b86050aSDana Vardi /* parse fill bpool buffers tokens */ 834b86050aSDana Vardi #define MRVL_TOK_FILL_BPOOL_BUFFS "fill_bpool_buffs" 844b86050aSDana Vardi 85fe939687SNatalie Samsonov /** Number of tokens in range a-b = 2. */ 86fe939687SNatalie Samsonov #define MAX_RNG_TOKENS 2 87fe939687SNatalie Samsonov 88fe939687SNatalie Samsonov /** Maximum possible value of PCP. */ 89fe939687SNatalie Samsonov #define MAX_PCP 7 90fe939687SNatalie Samsonov 91fe939687SNatalie Samsonov /** Maximum possible value of DSCP. */ 92fe939687SNatalie Samsonov #define MAX_DSCP 63 93fe939687SNatalie Samsonov 94d7eb4fb2SLiron Himi /** Global configuration. */ 95d7eb4fb2SLiron Himi struct mrvl_cfg *mrvl_cfg; 96fe939687SNatalie Samsonov 97fe939687SNatalie Samsonov /** 98fe939687SNatalie Samsonov * Read out-queue configuration from file. 99fe939687SNatalie Samsonov * 100fe939687SNatalie Samsonov * @param file Path to the configuration file. 101fe939687SNatalie Samsonov * @param port Port number. 102fe939687SNatalie Samsonov * @param outq Out queue number. 103d7eb4fb2SLiron Himi * @param cfg Pointer to the Marvell configuration structure. 104fe939687SNatalie Samsonov * @returns 0 in case of success, negative value otherwise. 105fe939687SNatalie Samsonov */ 106fe939687SNatalie Samsonov static int 107fe939687SNatalie Samsonov get_outq_cfg(struct rte_cfgfile *file, int port, int outq, 108d7eb4fb2SLiron Himi struct mrvl_cfg *cfg) 109fe939687SNatalie Samsonov { 110fe939687SNatalie Samsonov char sec_name[32]; 111fe939687SNatalie Samsonov const char *entry; 112fe939687SNatalie Samsonov uint32_t val; 113fe939687SNatalie Samsonov 114fe939687SNatalie Samsonov snprintf(sec_name, sizeof(sec_name), "%s %d %s %d", 115fe939687SNatalie Samsonov MRVL_TOK_PORT, port, MRVL_TOK_TXQ, outq); 116fe939687SNatalie Samsonov 117fe939687SNatalie Samsonov /* Skip non-existing */ 118fe939687SNatalie Samsonov if (rte_cfgfile_num_sections(file, sec_name, strlen(sec_name)) <= 0) 119fe939687SNatalie Samsonov return 0; 120fe939687SNatalie Samsonov 121fe939687SNatalie Samsonov /* Read scheduling mode */ 122fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_SCHED_MODE); 123fe939687SNatalie Samsonov if (entry) { 124fe939687SNatalie Samsonov if (!strncmp(entry, MRVL_TOK_SCHED_MODE_SP, 125fe939687SNatalie Samsonov strlen(MRVL_TOK_SCHED_MODE_SP))) { 126fe939687SNatalie Samsonov cfg->port[port].outq[outq].sched_mode = 127fe939687SNatalie Samsonov PP2_PPIO_SCHED_M_SP; 128fe939687SNatalie Samsonov } else if (!strncmp(entry, MRVL_TOK_SCHED_MODE_WRR, 129fe939687SNatalie Samsonov strlen(MRVL_TOK_SCHED_MODE_WRR))) { 130fe939687SNatalie Samsonov cfg->port[port].outq[outq].sched_mode = 131fe939687SNatalie Samsonov PP2_PPIO_SCHED_M_WRR; 132fe939687SNatalie Samsonov } else { 133acab7d58STomasz Duszynski MRVL_LOG(ERR, "Unknown token: %s", entry); 134fe939687SNatalie Samsonov return -1; 135fe939687SNatalie Samsonov } 136fe939687SNatalie Samsonov } 137fe939687SNatalie Samsonov 138fe939687SNatalie Samsonov /* Read wrr weight */ 139fe939687SNatalie Samsonov if (cfg->port[port].outq[outq].sched_mode == PP2_PPIO_SCHED_M_WRR) { 140fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, 141fe939687SNatalie Samsonov MRVL_TOK_WRR_WEIGHT); 142fe939687SNatalie Samsonov if (entry) { 143fe939687SNatalie Samsonov if (get_val_securely(entry, &val) < 0) 144fe939687SNatalie Samsonov return -1; 145fe939687SNatalie Samsonov cfg->port[port].outq[outq].weight = val; 146fe939687SNatalie Samsonov } 147fe939687SNatalie Samsonov } 148fe939687SNatalie Samsonov 149fe939687SNatalie Samsonov /* 150fe939687SNatalie Samsonov * There's no point in setting rate limiting for specific outq as 151fe939687SNatalie Samsonov * global port rate limiting has priority. 152fe939687SNatalie Samsonov */ 153fe939687SNatalie Samsonov if (cfg->port[port].rate_limit_enable) { 154acab7d58STomasz Duszynski MRVL_LOG(WARNING, "Port %d rate limiting already enabled", 155fe939687SNatalie Samsonov port); 156fe939687SNatalie Samsonov return 0; 157fe939687SNatalie Samsonov } 158fe939687SNatalie Samsonov 159fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, 160fe939687SNatalie Samsonov MRVL_TOK_RATE_LIMIT_ENABLE); 161fe939687SNatalie Samsonov if (entry) { 162fe939687SNatalie Samsonov if (get_val_securely(entry, &val) < 0) 163fe939687SNatalie Samsonov return -1; 164fe939687SNatalie Samsonov cfg->port[port].outq[outq].rate_limit_enable = val; 165fe939687SNatalie Samsonov } 166fe939687SNatalie Samsonov 167fe939687SNatalie Samsonov if (!cfg->port[port].outq[outq].rate_limit_enable) 168fe939687SNatalie Samsonov return 0; 169fe939687SNatalie Samsonov 170fe939687SNatalie Samsonov /* Read CBS (in kB) */ 171fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_BURST_SIZE); 172fe939687SNatalie Samsonov if (entry) { 173fe939687SNatalie Samsonov if (get_val_securely(entry, &val) < 0) 174fe939687SNatalie Samsonov return -1; 175fe939687SNatalie Samsonov cfg->port[port].outq[outq].rate_limit_params.cbs = val; 176fe939687SNatalie Samsonov } 177fe939687SNatalie Samsonov 178fe939687SNatalie Samsonov /* Read CIR (in kbps) */ 179fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_RATE_LIMIT); 180fe939687SNatalie Samsonov if (entry) { 181fe939687SNatalie Samsonov if (get_val_securely(entry, &val) < 0) 182fe939687SNatalie Samsonov return -1; 183fe939687SNatalie Samsonov cfg->port[port].outq[outq].rate_limit_params.cir = val; 184fe939687SNatalie Samsonov } 185fe939687SNatalie Samsonov 186fe939687SNatalie Samsonov return 0; 187fe939687SNatalie Samsonov } 188fe939687SNatalie Samsonov 189fe939687SNatalie Samsonov /** 190fe939687SNatalie Samsonov * Gets multiple-entry values and places them in table. 191fe939687SNatalie Samsonov * 192fe939687SNatalie Samsonov * Entry can be anything, e.g. "1 2-3 5 6 7-9". This needs to be converted to 193fe939687SNatalie Samsonov * table entries, respectively: {1, 2, 3, 5, 6, 7, 8, 9}. 194fe939687SNatalie Samsonov * As all result table's elements are always 1-byte long, we 195fe939687SNatalie Samsonov * won't overcomplicate the function, but we'll keep API generic, 196fe939687SNatalie Samsonov * check if someone hasn't changed element size and make it simple 197fe939687SNatalie Samsonov * to extend to other sizes. 198fe939687SNatalie Samsonov * 199fe939687SNatalie Samsonov * This function is purely utilitary, it does not print any error, only returns 200fe939687SNatalie Samsonov * different error numbers. 201fe939687SNatalie Samsonov * 202fe939687SNatalie Samsonov * @param entry[in] Values string to parse. 203fe939687SNatalie Samsonov * @param tab[out] Results table. 204fe939687SNatalie Samsonov * @param elem_sz[in] Element size (in bytes). 205fe939687SNatalie Samsonov * @param max_elems[in] Number of results table elements available. 206fe939687SNatalie Samsonov * @param max val[in] Maximum value allowed. 207fe939687SNatalie Samsonov * @returns Number of correctly parsed elements in case of success. 208fe939687SNatalie Samsonov * @retval -1 Wrong element size. 209fe939687SNatalie Samsonov * @retval -2 More tokens than result table allows. 210fe939687SNatalie Samsonov * @retval -3 Wrong range syntax. 211fe939687SNatalie Samsonov * @retval -4 Wrong range values. 212fe939687SNatalie Samsonov * @retval -5 Maximum value exceeded. 213fe939687SNatalie Samsonov */ 214fe939687SNatalie Samsonov static int 215fe939687SNatalie Samsonov get_entry_values(const char *entry, uint8_t *tab, 216fe939687SNatalie Samsonov size_t elem_sz, uint8_t max_elems, uint8_t max_val) 217fe939687SNatalie Samsonov { 218fe939687SNatalie Samsonov /* There should not be more tokens than max elements. 219fe939687SNatalie Samsonov * Add 1 for error trap. 220fe939687SNatalie Samsonov */ 221fe939687SNatalie Samsonov char *tokens[max_elems + 1]; 222fe939687SNatalie Samsonov 223fe939687SNatalie Samsonov /* Begin, End + error trap = 3. */ 224fe939687SNatalie Samsonov char *rng_tokens[MAX_RNG_TOKENS + 1]; 225fe939687SNatalie Samsonov long beg, end; 226fe939687SNatalie Samsonov uint32_t token_val; 227fe939687SNatalie Samsonov int nb_tokens, nb_rng_tokens; 228fe939687SNatalie Samsonov int i; 229fe939687SNatalie Samsonov int values = 0; 230fe939687SNatalie Samsonov char val; 231fe939687SNatalie Samsonov char entry_cpy[CFG_VALUE_LEN]; 232fe939687SNatalie Samsonov 233fe939687SNatalie Samsonov if (elem_sz != 1) 234fe939687SNatalie Samsonov return -1; 235fe939687SNatalie Samsonov 236fe939687SNatalie Samsonov /* Copy the entry to safely use rte_strsplit(). */ 237c022cb40SBruce Richardson strlcpy(entry_cpy, entry, RTE_DIM(entry_cpy)); 238fe939687SNatalie Samsonov 239fe939687SNatalie Samsonov /* 240fe939687SNatalie Samsonov * If there are more tokens than array size, rte_strsplit will 241fe939687SNatalie Samsonov * not return error, just array size. 242fe939687SNatalie Samsonov */ 243fe939687SNatalie Samsonov nb_tokens = rte_strsplit(entry_cpy, strlen(entry_cpy), 244fe939687SNatalie Samsonov tokens, max_elems + 1, ' '); 245fe939687SNatalie Samsonov 246fe939687SNatalie Samsonov /* Quick check, will be refined later. */ 247fe939687SNatalie Samsonov if (nb_tokens > max_elems) 248fe939687SNatalie Samsonov return -2; 249fe939687SNatalie Samsonov 250fe939687SNatalie Samsonov for (i = 0; i < nb_tokens; ++i) { 251fe939687SNatalie Samsonov if (strchr(tokens[i], '-') != NULL) { 252fe939687SNatalie Samsonov /* 253fe939687SNatalie Samsonov * Split to begin and end tokens. 254fe939687SNatalie Samsonov * We want to catch error cases too, thus we leave 255fe939687SNatalie Samsonov * option for number of tokens to be more than 2. 256fe939687SNatalie Samsonov */ 257fe939687SNatalie Samsonov nb_rng_tokens = rte_strsplit(tokens[i], 258fe939687SNatalie Samsonov strlen(tokens[i]), rng_tokens, 259fe939687SNatalie Samsonov RTE_DIM(rng_tokens), '-'); 260fe939687SNatalie Samsonov if (nb_rng_tokens != 2) 261fe939687SNatalie Samsonov return -3; 262fe939687SNatalie Samsonov 263fe939687SNatalie Samsonov /* Range and sanity checks. */ 264fe939687SNatalie Samsonov if (get_val_securely(rng_tokens[0], &token_val) < 0) 265fe939687SNatalie Samsonov return -4; 266fe939687SNatalie Samsonov beg = (char)token_val; 267fe939687SNatalie Samsonov if (get_val_securely(rng_tokens[1], &token_val) < 0) 268fe939687SNatalie Samsonov return -4; 269fe939687SNatalie Samsonov end = (char)token_val; 270fe939687SNatalie Samsonov if (beg < 0 || beg > UCHAR_MAX || 271fe939687SNatalie Samsonov end < 0 || end > UCHAR_MAX || end < beg) 272fe939687SNatalie Samsonov return -4; 273fe939687SNatalie Samsonov 274fe939687SNatalie Samsonov for (val = beg; val <= end; ++val) { 275fe939687SNatalie Samsonov if (val > max_val) 276fe939687SNatalie Samsonov return -5; 277fe939687SNatalie Samsonov 278fe939687SNatalie Samsonov *tab = val; 279fe939687SNatalie Samsonov tab = RTE_PTR_ADD(tab, elem_sz); 280fe939687SNatalie Samsonov ++values; 281fe939687SNatalie Samsonov if (values >= max_elems) 282fe939687SNatalie Samsonov return -2; 283fe939687SNatalie Samsonov } 284fe939687SNatalie Samsonov } else { 285fe939687SNatalie Samsonov /* Single values. */ 286fe939687SNatalie Samsonov if (get_val_securely(tokens[i], &token_val) < 0) 287fe939687SNatalie Samsonov return -5; 288fe939687SNatalie Samsonov val = (char)token_val; 289fe939687SNatalie Samsonov if (val > max_val) 290fe939687SNatalie Samsonov return -5; 291fe939687SNatalie Samsonov 292fe939687SNatalie Samsonov *tab = val; 293fe939687SNatalie Samsonov tab = RTE_PTR_ADD(tab, elem_sz); 294fe939687SNatalie Samsonov ++values; 295fe939687SNatalie Samsonov if (values >= max_elems) 296fe939687SNatalie Samsonov return -2; 297fe939687SNatalie Samsonov } 298fe939687SNatalie Samsonov } 299fe939687SNatalie Samsonov 300fe939687SNatalie Samsonov return values; 301fe939687SNatalie Samsonov } 302fe939687SNatalie Samsonov 303fe939687SNatalie Samsonov /** 3047be78d02SJosh Soref * Parse Traffic Classes mapping configuration. 305fe939687SNatalie Samsonov * 306fe939687SNatalie Samsonov * @param file Config file handle. 307fe939687SNatalie Samsonov * @param port Which port to look for. 308fe939687SNatalie Samsonov * @param tc Which Traffic Class to look for. 309fe939687SNatalie Samsonov * @param cfg[out] Parsing results. 310fe939687SNatalie Samsonov * @returns 0 in case of success, negative value otherwise. 311fe939687SNatalie Samsonov */ 312fe939687SNatalie Samsonov static int 313fe939687SNatalie Samsonov parse_tc_cfg(struct rte_cfgfile *file, int port, int tc, 314d7eb4fb2SLiron Himi struct mrvl_cfg *cfg) 315fe939687SNatalie Samsonov { 316fe939687SNatalie Samsonov char sec_name[32]; 317fe939687SNatalie Samsonov const char *entry; 318fe939687SNatalie Samsonov int n; 319fe939687SNatalie Samsonov 320fe939687SNatalie Samsonov snprintf(sec_name, sizeof(sec_name), "%s %d %s %d", 321fe939687SNatalie Samsonov MRVL_TOK_PORT, port, MRVL_TOK_TC, tc); 322fe939687SNatalie Samsonov 323fe939687SNatalie Samsonov /* Skip non-existing */ 324fe939687SNatalie Samsonov if (rte_cfgfile_num_sections(file, sec_name, strlen(sec_name)) <= 0) 325fe939687SNatalie Samsonov return 0; 326fe939687SNatalie Samsonov 32741c60f74SDana Vardi cfg->port[port].use_qos_global_defaults = 0; 328fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_RXQ); 329fe939687SNatalie Samsonov if (entry) { 330fe939687SNatalie Samsonov n = get_entry_values(entry, 331fe939687SNatalie Samsonov cfg->port[port].tc[tc].inq, 332fe939687SNatalie Samsonov sizeof(cfg->port[port].tc[tc].inq[0]), 333fe939687SNatalie Samsonov RTE_DIM(cfg->port[port].tc[tc].inq), 334fe939687SNatalie Samsonov MRVL_PP2_RXQ_MAX); 335fe939687SNatalie Samsonov if (n < 0) { 336acab7d58STomasz Duszynski MRVL_LOG(ERR, "Error %d while parsing: %s", 337fe939687SNatalie Samsonov n, entry); 338fe939687SNatalie Samsonov return n; 339fe939687SNatalie Samsonov } 340fe939687SNatalie Samsonov cfg->port[port].tc[tc].inqs = n; 341fe939687SNatalie Samsonov } 342fe939687SNatalie Samsonov 343fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PCP); 344fe939687SNatalie Samsonov if (entry) { 345fe939687SNatalie Samsonov n = get_entry_values(entry, 346fe939687SNatalie Samsonov cfg->port[port].tc[tc].pcp, 347fe939687SNatalie Samsonov sizeof(cfg->port[port].tc[tc].pcp[0]), 348fe939687SNatalie Samsonov RTE_DIM(cfg->port[port].tc[tc].pcp), 349fe939687SNatalie Samsonov MAX_PCP); 350fe939687SNatalie Samsonov if (n < 0) { 351acab7d58STomasz Duszynski MRVL_LOG(ERR, "Error %d while parsing: %s", 352fe939687SNatalie Samsonov n, entry); 353fe939687SNatalie Samsonov return n; 354fe939687SNatalie Samsonov } 355fe939687SNatalie Samsonov cfg->port[port].tc[tc].pcps = n; 356fe939687SNatalie Samsonov } 357fe939687SNatalie Samsonov 358fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_DSCP); 359fe939687SNatalie Samsonov if (entry) { 360fe939687SNatalie Samsonov n = get_entry_values(entry, 361fe939687SNatalie Samsonov cfg->port[port].tc[tc].dscp, 362fe939687SNatalie Samsonov sizeof(cfg->port[port].tc[tc].dscp[0]), 363fe939687SNatalie Samsonov RTE_DIM(cfg->port[port].tc[tc].dscp), 364fe939687SNatalie Samsonov MAX_DSCP); 365fe939687SNatalie Samsonov if (n < 0) { 366acab7d58STomasz Duszynski MRVL_LOG(ERR, "Error %d while parsing: %s", 367fe939687SNatalie Samsonov n, entry); 368fe939687SNatalie Samsonov return n; 369fe939687SNatalie Samsonov } 370fe939687SNatalie Samsonov cfg->port[port].tc[tc].dscps = n; 371fe939687SNatalie Samsonov } 372fe939687SNatalie Samsonov 373e97d8874STomasz Duszynski if (!cfg->port[port].setup_policer) 374e97d8874STomasz Duszynski return 0; 375e97d8874STomasz Duszynski 376fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, 377fe939687SNatalie Samsonov MRVL_TOK_PLCR_DEFAULT_COLOR); 378fe939687SNatalie Samsonov if (entry) { 379fe939687SNatalie Samsonov if (!strncmp(entry, MRVL_TOK_PLCR_DEFAULT_COLOR_GREEN, 380fe939687SNatalie Samsonov sizeof(MRVL_TOK_PLCR_DEFAULT_COLOR_GREEN))) { 381fe939687SNatalie Samsonov cfg->port[port].tc[tc].color = PP2_PPIO_COLOR_GREEN; 382fe939687SNatalie Samsonov } else if (!strncmp(entry, MRVL_TOK_PLCR_DEFAULT_COLOR_YELLOW, 383fe939687SNatalie Samsonov sizeof(MRVL_TOK_PLCR_DEFAULT_COLOR_YELLOW))) { 384fe939687SNatalie Samsonov cfg->port[port].tc[tc].color = PP2_PPIO_COLOR_YELLOW; 385fe939687SNatalie Samsonov } else if (!strncmp(entry, MRVL_TOK_PLCR_DEFAULT_COLOR_RED, 386fe939687SNatalie Samsonov sizeof(MRVL_TOK_PLCR_DEFAULT_COLOR_RED))) { 387fe939687SNatalie Samsonov cfg->port[port].tc[tc].color = PP2_PPIO_COLOR_RED; 388fe939687SNatalie Samsonov } else { 389acab7d58STomasz Duszynski MRVL_LOG(ERR, "Error while parsing: %s", entry); 390fe939687SNatalie Samsonov return -1; 391fe939687SNatalie Samsonov } 392fe939687SNatalie Samsonov } 393fe939687SNatalie Samsonov 394fe939687SNatalie Samsonov return 0; 395fe939687SNatalie Samsonov } 396fe939687SNatalie Samsonov 397fe939687SNatalie Samsonov /** 398e97d8874STomasz Duszynski * Parse default port policer. 399e97d8874STomasz Duszynski * 400e97d8874STomasz Duszynski * @param file Config file handle. 401e97d8874STomasz Duszynski * @param sec_name Section name with policer configuration 402e97d8874STomasz Duszynski * @param port Port number. 403e97d8874STomasz Duszynski * @param cfg[out] Parsing results. 404e97d8874STomasz Duszynski * @returns 0 in case of success, negative value otherwise. 405e97d8874STomasz Duszynski */ 406e97d8874STomasz Duszynski static int 407e97d8874STomasz Duszynski parse_policer(struct rte_cfgfile *file, int port, const char *sec_name, 408d7eb4fb2SLiron Himi struct mrvl_cfg *cfg) 409e97d8874STomasz Duszynski { 410e97d8874STomasz Duszynski const char *entry; 411e97d8874STomasz Duszynski uint32_t val; 412e97d8874STomasz Duszynski 413e97d8874STomasz Duszynski /* Read policer token unit */ 414e97d8874STomasz Duszynski entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_UNIT); 415e97d8874STomasz Duszynski if (entry) { 416e97d8874STomasz Duszynski if (!strncmp(entry, MRVL_TOK_PLCR_UNIT_BYTES, 417e97d8874STomasz Duszynski sizeof(MRVL_TOK_PLCR_UNIT_BYTES))) { 418e97d8874STomasz Duszynski cfg->port[port].policer_params.token_unit = 419e97d8874STomasz Duszynski PP2_CLS_PLCR_BYTES_TOKEN_UNIT; 420e97d8874STomasz Duszynski } else if (!strncmp(entry, MRVL_TOK_PLCR_UNIT_PACKETS, 421e97d8874STomasz Duszynski sizeof(MRVL_TOK_PLCR_UNIT_PACKETS))) { 422e97d8874STomasz Duszynski cfg->port[port].policer_params.token_unit = 423e97d8874STomasz Duszynski PP2_CLS_PLCR_PACKETS_TOKEN_UNIT; 424e97d8874STomasz Duszynski } else { 425406aeb15SYuval Caduri MRVL_LOG(ERR, "Unknown token: %s", entry); 426e97d8874STomasz Duszynski return -1; 427e97d8874STomasz Duszynski } 428e97d8874STomasz Duszynski } 429e97d8874STomasz Duszynski 430e97d8874STomasz Duszynski /* Read policer color mode */ 431e97d8874STomasz Duszynski entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_COLOR); 432e97d8874STomasz Duszynski if (entry) { 433e97d8874STomasz Duszynski if (!strncmp(entry, MRVL_TOK_PLCR_COLOR_BLIND, 434e97d8874STomasz Duszynski sizeof(MRVL_TOK_PLCR_COLOR_BLIND))) { 435e97d8874STomasz Duszynski cfg->port[port].policer_params.color_mode = 436e97d8874STomasz Duszynski PP2_CLS_PLCR_COLOR_BLIND_MODE; 437e97d8874STomasz Duszynski } else if (!strncmp(entry, MRVL_TOK_PLCR_COLOR_AWARE, 438e97d8874STomasz Duszynski sizeof(MRVL_TOK_PLCR_COLOR_AWARE))) { 439e97d8874STomasz Duszynski cfg->port[port].policer_params.color_mode = 440e97d8874STomasz Duszynski PP2_CLS_PLCR_COLOR_AWARE_MODE; 441e97d8874STomasz Duszynski } else { 442406aeb15SYuval Caduri MRVL_LOG(ERR, "Error in parsing: %s", entry); 443e97d8874STomasz Duszynski return -1; 444e97d8874STomasz Duszynski } 445e97d8874STomasz Duszynski } 446e97d8874STomasz Duszynski 447e97d8874STomasz Duszynski /* Read policer cir */ 448e97d8874STomasz Duszynski entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_CIR); 449e97d8874STomasz Duszynski if (entry) { 450e97d8874STomasz Duszynski if (get_val_securely(entry, &val) < 0) 451e97d8874STomasz Duszynski return -1; 452e97d8874STomasz Duszynski cfg->port[port].policer_params.cir = val; 453e97d8874STomasz Duszynski } 454e97d8874STomasz Duszynski 455e97d8874STomasz Duszynski /* Read policer cbs */ 456e97d8874STomasz Duszynski entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_CBS); 457e97d8874STomasz Duszynski if (entry) { 458e97d8874STomasz Duszynski if (get_val_securely(entry, &val) < 0) 459e97d8874STomasz Duszynski return -1; 460e97d8874STomasz Duszynski cfg->port[port].policer_params.cbs = val; 461e97d8874STomasz Duszynski } 462e97d8874STomasz Duszynski 463e97d8874STomasz Duszynski /* Read policer ebs */ 464e97d8874STomasz Duszynski entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_EBS); 465e97d8874STomasz Duszynski if (entry) { 466e97d8874STomasz Duszynski if (get_val_securely(entry, &val) < 0) 467e97d8874STomasz Duszynski return -1; 468e97d8874STomasz Duszynski cfg->port[port].policer_params.ebs = val; 469e97d8874STomasz Duszynski } 470e97d8874STomasz Duszynski 471e97d8874STomasz Duszynski cfg->port[port].setup_policer = 1; 472e97d8874STomasz Duszynski 473e97d8874STomasz Duszynski return 0; 474e97d8874STomasz Duszynski } 475e97d8874STomasz Duszynski 476e97d8874STomasz Duszynski /** 4773e09b2a7SLiron Himi * Parse parser udf. 4783e09b2a7SLiron Himi * 4793e09b2a7SLiron Himi * @param file Config file handle. 4803e09b2a7SLiron Himi * @param sec_name section name 4813e09b2a7SLiron Himi * @param udf udf index 4823e09b2a7SLiron Himi * @param cfg[out] Parsing results. 4833e09b2a7SLiron Himi * @returns 0 in case of success, negative value otherwise. 4843e09b2a7SLiron Himi */ 4853e09b2a7SLiron Himi static int 4863e09b2a7SLiron Himi parse_udf(struct rte_cfgfile *file, const char *sec_name, int udf, 4873e09b2a7SLiron Himi struct mrvl_cfg *cfg) 4883e09b2a7SLiron Himi { 4893e09b2a7SLiron Himi struct pp2_parse_udf_params *udf_params; 4903e09b2a7SLiron Himi const char *entry, *entry_field; 4913e09b2a7SLiron Himi uint32_t val, i; 4923e09b2a7SLiron Himi uint8_t field_size; 4933e09b2a7SLiron Himi char malloc_name[32], tmp_arr[3]; 4943e09b2a7SLiron Himi /* field len in chars equal to '0x' + rest of data */ 4953e09b2a7SLiron Himi #define FIELD_LEN_IN_CHARS(field_size) (uint32_t)(2 + (field_size) * 2) 4963e09b2a7SLiron Himi 4973e09b2a7SLiron Himi udf_params = &cfg->pp2_cfg.prs_udfs.udfs[udf]; 4983e09b2a7SLiron Himi 4993e09b2a7SLiron Himi /* Read 'proto' field */ 5003e09b2a7SLiron Himi entry = rte_cfgfile_get_entry(file, sec_name, 5013e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_PROTO); 5023e09b2a7SLiron Himi if (!entry) { 503*8df71650SJerin Jacob MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set", udf, 5043e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_PROTO); 5053e09b2a7SLiron Himi return -1; 5063e09b2a7SLiron Himi } 5073e09b2a7SLiron Himi 5083e09b2a7SLiron Himi /* Read 'field' field */ 5093e09b2a7SLiron Himi entry_field = rte_cfgfile_get_entry(file, sec_name, 5103e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_FIELD); 5113e09b2a7SLiron Himi if (!entry_field) { 512*8df71650SJerin Jacob MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set", udf, 5133e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_FIELD); 5143e09b2a7SLiron Himi return -1; 5153e09b2a7SLiron Himi } 5163e09b2a7SLiron Himi 5173e09b2a7SLiron Himi if (!strncmp(entry, MRVL_TOK_PARSER_UDF_PROTO_ETH, 5183e09b2a7SLiron Himi sizeof(MRVL_TOK_PARSER_UDF_PROTO_ETH))) { 5193e09b2a7SLiron Himi udf_params->match_proto = MV_NET_PROTO_ETH; 5203e09b2a7SLiron Himi if (!strncmp(entry_field, MRVL_TOK_PARSER_UDF_FIELD_ETH_TYPE, 5213e09b2a7SLiron Himi sizeof(MRVL_TOK_PARSER_UDF_FIELD_ETH_TYPE))) { 5223e09b2a7SLiron Himi udf_params->match_field.eth = MV_NET_ETH_F_TYPE; 5233e09b2a7SLiron Himi field_size = 2; 5243e09b2a7SLiron Himi } else { 5253e09b2a7SLiron Himi MRVL_LOG(ERR, "UDF[%d]: mismatch between '%s' proto " 526*8df71650SJerin Jacob "and '%s' field", udf, 5273e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_PROTO_ETH, 5283e09b2a7SLiron Himi entry_field); 5293e09b2a7SLiron Himi return -1; 5303e09b2a7SLiron Himi } 5313e09b2a7SLiron Himi } else if (!strncmp(entry, MRVL_TOK_PARSER_UDF_PROTO_UDP, 5323e09b2a7SLiron Himi sizeof(MRVL_TOK_PARSER_UDF_PROTO_UDP))) { 5333e09b2a7SLiron Himi udf_params->match_proto = MV_NET_PROTO_UDP; 5343e09b2a7SLiron Himi if (!strncmp(entry_field, MRVL_TOK_PARSER_UDF_FIELD_UDP_DPORT, 5353e09b2a7SLiron Himi sizeof(MRVL_TOK_PARSER_UDF_FIELD_UDP_DPORT))) { 5363e09b2a7SLiron Himi udf_params->match_field.udp = MV_NET_UDP_F_DP; 5373e09b2a7SLiron Himi field_size = 2; 5383e09b2a7SLiron Himi } else { 5393e09b2a7SLiron Himi MRVL_LOG(ERR, "UDF[%d]: mismatch between '%s' proto " 540*8df71650SJerin Jacob "and '%s' field", udf, 5413e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_PROTO_UDP, 5423e09b2a7SLiron Himi entry_field); 5433e09b2a7SLiron Himi return -1; 5443e09b2a7SLiron Himi } 5453e09b2a7SLiron Himi } else { 546*8df71650SJerin Jacob MRVL_LOG(ERR, "UDF[%d]: Unsupported '%s' proto", udf, entry); 5473e09b2a7SLiron Himi return -1; 5483e09b2a7SLiron Himi } 5493e09b2a7SLiron Himi 5503e09b2a7SLiron Himi snprintf(malloc_name, sizeof(malloc_name), "mrvl_udf_%d_key", udf); 5513e09b2a7SLiron Himi udf_params->match_key = rte_zmalloc(malloc_name, field_size, 0); 5523e09b2a7SLiron Himi if (udf_params->match_key == NULL) { 553*8df71650SJerin Jacob MRVL_LOG(ERR, "Cannot allocate udf %d key", udf); 5543e09b2a7SLiron Himi return -1; 5553e09b2a7SLiron Himi } 5563e09b2a7SLiron Himi snprintf(malloc_name, sizeof(malloc_name), "mrvl_udf_%d_mask", udf); 5573e09b2a7SLiron Himi udf_params->match_mask = rte_zmalloc(malloc_name, field_size, 0); 5583e09b2a7SLiron Himi if (udf_params->match_mask == NULL) { 559*8df71650SJerin Jacob MRVL_LOG(ERR, "Cannot allocate udf %d mask", udf); 5603e09b2a7SLiron Himi return -1; 5613e09b2a7SLiron Himi } 5623e09b2a7SLiron Himi 5633e09b2a7SLiron Himi /* Read 'key' field */ 5643e09b2a7SLiron Himi entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PARSER_UDF_KEY); 5653e09b2a7SLiron Himi if (!entry) { 566*8df71650SJerin Jacob MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set", udf, 5673e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_KEY); 5683e09b2a7SLiron Himi return -1; 5693e09b2a7SLiron Himi } 5703e09b2a7SLiron Himi 5713e09b2a7SLiron Himi if (strncmp(entry, "0x", 2) != 0) { 572*8df71650SJerin Jacob MRVL_LOG(ERR, "UDF[%d]: '%s' field must start with '0x'", 5733e09b2a7SLiron Himi udf, MRVL_TOK_PARSER_UDF_KEY); 5743e09b2a7SLiron Himi return -EINVAL; 5753e09b2a7SLiron Himi } 5763e09b2a7SLiron Himi 5773e09b2a7SLiron Himi if (strlen(entry) != FIELD_LEN_IN_CHARS(field_size)) { 578*8df71650SJerin Jacob MRVL_LOG(ERR, "UDF[%d]: '%s' field's len must be %d", udf, 5793e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_KEY, 5803e09b2a7SLiron Himi FIELD_LEN_IN_CHARS(field_size)); 5813e09b2a7SLiron Himi return -EINVAL; 5823e09b2a7SLiron Himi } 5833e09b2a7SLiron Himi 5843e09b2a7SLiron Himi entry += 2; /* skip the '0x' */ 5853e09b2a7SLiron Himi for (i = 0; i < field_size; i++) { 5863e09b2a7SLiron Himi strncpy(tmp_arr, entry, 2); 5873e09b2a7SLiron Himi tmp_arr[2] = '\0'; 5883e09b2a7SLiron Himi if (get_val_securely8(tmp_arr, 16, 5893e09b2a7SLiron Himi &udf_params->match_key[i]) < 0) { 5903e09b2a7SLiron Himi MRVL_LOG(ERR, "UDF[%d]: '%s' field's value is not in " 591*8df71650SJerin Jacob "hex format", udf, MRVL_TOK_PARSER_UDF_KEY); 5923e09b2a7SLiron Himi return -EINVAL; 5933e09b2a7SLiron Himi } 5943e09b2a7SLiron Himi entry += 2; 5953e09b2a7SLiron Himi } 5963e09b2a7SLiron Himi 5973e09b2a7SLiron Himi /* Read 'mask' field */ 5983e09b2a7SLiron Himi entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PARSER_UDF_MASK); 5993e09b2a7SLiron Himi if (!entry) { 600*8df71650SJerin Jacob MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set", udf, 6013e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_MASK); 6023e09b2a7SLiron Himi return -1; 6033e09b2a7SLiron Himi } 6043e09b2a7SLiron Himi if (strncmp(entry, "0x", 2) != 0) { 605*8df71650SJerin Jacob MRVL_LOG(ERR, "UDF[%d]: '%s' field must start with '0x'", 6063e09b2a7SLiron Himi udf, MRVL_TOK_PARSER_UDF_MASK); 6073e09b2a7SLiron Himi return -EINVAL; 6083e09b2a7SLiron Himi } 6093e09b2a7SLiron Himi 6103e09b2a7SLiron Himi if (strlen(entry) != FIELD_LEN_IN_CHARS(field_size)) { 611*8df71650SJerin Jacob MRVL_LOG(ERR, "UDF[%d]: '%s' field's len must be %d", udf, 6123e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_MASK, 6133e09b2a7SLiron Himi FIELD_LEN_IN_CHARS(field_size)); 6143e09b2a7SLiron Himi return -EINVAL; 6153e09b2a7SLiron Himi } 6163e09b2a7SLiron Himi 6173e09b2a7SLiron Himi entry += 2; /* skip the '0x' */ 6183e09b2a7SLiron Himi for (i = 0; i < field_size; i++) { 6193e09b2a7SLiron Himi strncpy(tmp_arr, entry, 2); 6203e09b2a7SLiron Himi tmp_arr[2] = '\0'; 6213e09b2a7SLiron Himi if (get_val_securely8(tmp_arr, 16, 6223e09b2a7SLiron Himi &udf_params->match_mask[i]) < 0) { 6233e09b2a7SLiron Himi MRVL_LOG(ERR, "UDF[%d]: '%s' field's value is not in " 624*8df71650SJerin Jacob "hex format", udf, MRVL_TOK_PARSER_UDF_MASK); 6253e09b2a7SLiron Himi return -EINVAL; 6263e09b2a7SLiron Himi } 6273e09b2a7SLiron Himi entry += 2; 6283e09b2a7SLiron Himi } 6293e09b2a7SLiron Himi 6303e09b2a7SLiron Himi /* Read offset */ 6313e09b2a7SLiron Himi entry = rte_cfgfile_get_entry(file, sec_name, 6323e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_OFFSET); 6333e09b2a7SLiron Himi if (!entry) { 634*8df71650SJerin Jacob MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set", udf, 6353e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF_OFFSET); 6363e09b2a7SLiron Himi return -1; 6373e09b2a7SLiron Himi } 6383e09b2a7SLiron Himi if (get_val_securely(entry, &val) < 0) 6393e09b2a7SLiron Himi return -1; 6403e09b2a7SLiron Himi udf_params->offset = val; 6413e09b2a7SLiron Himi 6423e09b2a7SLiron Himi return 0; 6433e09b2a7SLiron Himi } 6443e09b2a7SLiron Himi 6453e09b2a7SLiron Himi /** 646d7eb4fb2SLiron Himi * Parse configuration - rte_kvargs_process handler. 647fe939687SNatalie Samsonov * 648fe939687SNatalie Samsonov * Opens configuration file and parses its content. 649fe939687SNatalie Samsonov * 650fe939687SNatalie Samsonov * @param key Unused. 651fe939687SNatalie Samsonov * @param path Path to config file. 652fe939687SNatalie Samsonov * @param extra_args Pointer to configuration structure. 653fe939687SNatalie Samsonov * @returns 0 in case of success, exits otherwise. 654fe939687SNatalie Samsonov */ 655fe939687SNatalie Samsonov int 656d7eb4fb2SLiron Himi mrvl_get_cfg(const char *key __rte_unused, const char *path, void *extra_args) 657fe939687SNatalie Samsonov { 658d7eb4fb2SLiron Himi struct mrvl_cfg **cfg = extra_args; 659fe939687SNatalie Samsonov struct rte_cfgfile *file = rte_cfgfile_load(path, 0); 660fe939687SNatalie Samsonov uint32_t val; 661fe939687SNatalie Samsonov int n, i, ret; 662fe939687SNatalie Samsonov const char *entry; 663fe939687SNatalie Samsonov char sec_name[32]; 664fe939687SNatalie Samsonov 665c2b5ae61SLiron Himi if (file == NULL) { 666*8df71650SJerin Jacob MRVL_LOG(ERR, "Cannot load configuration %s", path); 667c2b5ae61SLiron Himi return -1; 668c2b5ae61SLiron Himi } 669fe939687SNatalie Samsonov 670fe939687SNatalie Samsonov /* Create configuration. This is never accessed on the fast path, 671fe939687SNatalie Samsonov * so we can ignore socket. 672fe939687SNatalie Samsonov */ 673d7eb4fb2SLiron Himi *cfg = rte_zmalloc("mrvl_cfg", sizeof(struct mrvl_cfg), 0); 674c2b5ae61SLiron Himi if (*cfg == NULL) { 675*8df71650SJerin Jacob MRVL_LOG(ERR, "Cannot allocate configuration %s", path); 676c2b5ae61SLiron Himi return -1; 677c2b5ae61SLiron Himi } 678fe939687SNatalie Samsonov 6793e09b2a7SLiron Himi /* PP2 configuration */ 6803e09b2a7SLiron Himi n = rte_cfgfile_num_sections(file, MRVL_TOK_PARSER_UDF, 6813e09b2a7SLiron Himi sizeof(MRVL_TOK_PARSER_UDF) - 1); 6823e09b2a7SLiron Himi 6833e09b2a7SLiron Himi if (n && n > PP2_MAX_UDFS_SUPPORTED) { 684*8df71650SJerin Jacob MRVL_LOG(ERR, "found %d udf sections, but only %d are supported", 6853e09b2a7SLiron Himi n, PP2_MAX_UDFS_SUPPORTED); 6863e09b2a7SLiron Himi return -1; 6873e09b2a7SLiron Himi } 6883e09b2a7SLiron Himi (*cfg)->pp2_cfg.prs_udfs.num_udfs = n; 6893e09b2a7SLiron Himi for (i = 0; i < n; i++) { 6903e09b2a7SLiron Himi snprintf(sec_name, sizeof(sec_name), "%s %d", 6913e09b2a7SLiron Himi MRVL_TOK_PARSER_UDF, i); 6923e09b2a7SLiron Himi 6933e09b2a7SLiron Himi /* udf sections must be sequential. */ 6943e09b2a7SLiron Himi if (rte_cfgfile_num_sections(file, sec_name, 6953e09b2a7SLiron Himi strlen(sec_name)) <= 0) { 696*8df71650SJerin Jacob MRVL_LOG(ERR, "udf sections must be sequential (0 - %d)", 6973e09b2a7SLiron Himi PP2_MAX_UDFS_SUPPORTED - 1); 6983e09b2a7SLiron Himi return -1; 6993e09b2a7SLiron Himi } 7003e09b2a7SLiron Himi 7013e09b2a7SLiron Himi ret = parse_udf(file, sec_name, i, *cfg); 7023e09b2a7SLiron Himi if (ret) { 703*8df71650SJerin Jacob MRVL_LOG(ERR, "Error in parsing %s!", sec_name); 7043e09b2a7SLiron Himi return -1; 7053e09b2a7SLiron Himi } 7063e09b2a7SLiron Himi } 7073e09b2a7SLiron Himi 7083e09b2a7SLiron Himi /* PP2 Ports configuration */ 709fe939687SNatalie Samsonov n = rte_cfgfile_num_sections(file, MRVL_TOK_PORT, 710fe939687SNatalie Samsonov sizeof(MRVL_TOK_PORT) - 1); 711fe939687SNatalie Samsonov 712fe939687SNatalie Samsonov if (n == 0) { 713fe939687SNatalie Samsonov /* This is weird, but not bad. */ 714acab7d58STomasz Duszynski MRVL_LOG(WARNING, "Empty configuration file?"); 715fe939687SNatalie Samsonov return 0; 716fe939687SNatalie Samsonov } 717fe939687SNatalie Samsonov 718fe939687SNatalie Samsonov /* Use the number of ports given as vdev parameters. */ 719fe939687SNatalie Samsonov for (n = 0; n < (PP2_NUM_ETH_PPIO * PP2_NUM_PKT_PROC); ++n) { 720fe939687SNatalie Samsonov snprintf(sec_name, sizeof(sec_name), "%s %d %s", 721fe939687SNatalie Samsonov MRVL_TOK_PORT, n, MRVL_TOK_DEFAULT); 722fe939687SNatalie Samsonov 723406aeb15SYuval Caduri /* Use global defaults, unless an override occurs */ 72441c60f74SDana Vardi (*cfg)->port[n].use_qos_global_defaults = 1; 725406aeb15SYuval Caduri 7264b86050aSDana Vardi /* Set non-zero defaults before the decision to continue to next 7274b86050aSDana Vardi * port or to parse the port section in config file 7284b86050aSDana Vardi */ 7294b86050aSDana Vardi (*cfg)->port[n].fill_bpool_buffs = MRVL_BURST_SIZE; 7304b86050aSDana Vardi 731fe939687SNatalie Samsonov /* Skip ports non-existing in configuration. */ 732fe939687SNatalie Samsonov if (rte_cfgfile_num_sections(file, sec_name, 733fe939687SNatalie Samsonov strlen(sec_name)) <= 0) { 734fe939687SNatalie Samsonov continue; 735fe939687SNatalie Samsonov } 736fe939687SNatalie Samsonov 7376000b5beSDana Vardi /* MRVL_TOK_START_HDR replaces MRVL_TOK_DSA_MODE parameter. 7386000b5beSDana Vardi * MRVL_TOK_DSA_MODE will be supported for backward 7397be78d02SJosh Soref * compatibility. 7406000b5beSDana Vardi */ 7416000b5beSDana Vardi entry = rte_cfgfile_get_entry(file, sec_name, 7426000b5beSDana Vardi MRVL_TOK_START_HDR); 7436000b5beSDana Vardi /* if start_hsr is missing, check if dsa_mode exist instead */ 7446000b5beSDana Vardi if (entry == NULL) 745c2b5ae61SLiron Himi entry = rte_cfgfile_get_entry(file, sec_name, 746c2b5ae61SLiron Himi MRVL_TOK_DSA_MODE); 747c2b5ae61SLiron Himi if (entry) { 7486000b5beSDana Vardi if (!strncmp(entry, MRVL_TOK_START_HDR_NONE, 7496000b5beSDana Vardi sizeof(MRVL_TOK_START_HDR_NONE))) 750c2b5ae61SLiron Himi (*cfg)->port[n].eth_start_hdr = 751c2b5ae61SLiron Himi PP2_PPIO_HDR_ETH; 7526000b5beSDana Vardi else if (!strncmp(entry, MRVL_TOK_START_HDR_DSA, 7536000b5beSDana Vardi sizeof(MRVL_TOK_START_HDR_DSA))) 754c2b5ae61SLiron Himi (*cfg)->port[n].eth_start_hdr = 755c2b5ae61SLiron Himi PP2_PPIO_HDR_ETH_DSA; 75621aa25e0SDana Vardi else if (!strncmp(entry, MRVL_TOK_START_HDR_CUSTOM, 75721aa25e0SDana Vardi sizeof(MRVL_TOK_START_HDR_CUSTOM))) 75821aa25e0SDana Vardi (*cfg)->port[n].eth_start_hdr = 75921aa25e0SDana Vardi PP2_PPIO_HDR_ETH_CUSTOM; 7606000b5beSDana Vardi else if (!strncmp(entry, MRVL_TOK_START_HDR_EXT_DSA, 7616000b5beSDana Vardi sizeof(MRVL_TOK_START_HDR_EXT_DSA))) { 762c2b5ae61SLiron Himi (*cfg)->port[n].eth_start_hdr = 763c2b5ae61SLiron Himi PP2_PPIO_HDR_ETH_EXT_DSA; 764c2b5ae61SLiron Himi } else { 765c2b5ae61SLiron Himi MRVL_LOG(ERR, 766*8df71650SJerin Jacob "Error in parsing %s value (%s)!", 7676000b5beSDana Vardi MRVL_TOK_START_HDR, entry); 768c2b5ae61SLiron Himi return -1; 769c2b5ae61SLiron Himi } 770c2b5ae61SLiron Himi } else { 771c2b5ae61SLiron Himi (*cfg)->port[n].eth_start_hdr = PP2_PPIO_HDR_ETH; 772c2b5ae61SLiron Himi } 773c2b5ae61SLiron Himi 774fe939687SNatalie Samsonov /* 775fe939687SNatalie Samsonov * Read per-port rate limiting. Setting that will 776fe939687SNatalie Samsonov * disable per-queue rate limiting. 777fe939687SNatalie Samsonov */ 778fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, 779fe939687SNatalie Samsonov MRVL_TOK_RATE_LIMIT_ENABLE); 780fe939687SNatalie Samsonov if (entry) { 781fe939687SNatalie Samsonov if (get_val_securely(entry, &val) < 0) 782fe939687SNatalie Samsonov return -1; 783fe939687SNatalie Samsonov (*cfg)->port[n].rate_limit_enable = val; 784fe939687SNatalie Samsonov } 785fe939687SNatalie Samsonov 786fe939687SNatalie Samsonov if ((*cfg)->port[n].rate_limit_enable) { 787fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, 788fe939687SNatalie Samsonov MRVL_TOK_BURST_SIZE); 789fe939687SNatalie Samsonov if (entry) { 790fe939687SNatalie Samsonov if (get_val_securely(entry, &val) < 0) 791fe939687SNatalie Samsonov return -1; 792fe939687SNatalie Samsonov (*cfg)->port[n].rate_limit_params.cbs = val; 793fe939687SNatalie Samsonov } 794fe939687SNatalie Samsonov 795fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, 796fe939687SNatalie Samsonov MRVL_TOK_RATE_LIMIT); 797fe939687SNatalie Samsonov if (entry) { 798fe939687SNatalie Samsonov if (get_val_securely(entry, &val) < 0) 799fe939687SNatalie Samsonov return -1; 800fe939687SNatalie Samsonov (*cfg)->port[n].rate_limit_params.cir = val; 801fe939687SNatalie Samsonov } 802fe939687SNatalie Samsonov } 803fe939687SNatalie Samsonov 804fe939687SNatalie Samsonov entry = rte_cfgfile_get_entry(file, sec_name, 805fe939687SNatalie Samsonov MRVL_TOK_MAPPING_PRIORITY); 806fe939687SNatalie Samsonov if (entry) { 80741c60f74SDana Vardi (*cfg)->port[n].use_qos_global_defaults = 0; 808fe939687SNatalie Samsonov if (!strncmp(entry, MRVL_TOK_VLAN_IP, 809fe939687SNatalie Samsonov sizeof(MRVL_TOK_VLAN_IP))) 810fe939687SNatalie Samsonov (*cfg)->port[n].mapping_priority = 811fe939687SNatalie Samsonov PP2_CLS_QOS_TBL_VLAN_IP_PRI; 812fe939687SNatalie Samsonov else if (!strncmp(entry, MRVL_TOK_IP_VLAN, 813fe939687SNatalie Samsonov sizeof(MRVL_TOK_IP_VLAN))) 814fe939687SNatalie Samsonov (*cfg)->port[n].mapping_priority = 815fe939687SNatalie Samsonov PP2_CLS_QOS_TBL_IP_VLAN_PRI; 816fe939687SNatalie Samsonov else if (!strncmp(entry, MRVL_TOK_IP, 817fe939687SNatalie Samsonov sizeof(MRVL_TOK_IP))) 818fe939687SNatalie Samsonov (*cfg)->port[n].mapping_priority = 819fe939687SNatalie Samsonov PP2_CLS_QOS_TBL_IP_PRI; 820fe939687SNatalie Samsonov else if (!strncmp(entry, MRVL_TOK_VLAN, 821c2b5ae61SLiron Himi sizeof(MRVL_TOK_VLAN))) { 822fe939687SNatalie Samsonov (*cfg)->port[n].mapping_priority = 823fe939687SNatalie Samsonov PP2_CLS_QOS_TBL_VLAN_PRI; 824c2b5ae61SLiron Himi } else { 825c2b5ae61SLiron Himi MRVL_LOG(ERR, 826*8df71650SJerin Jacob "Error in parsing %s value (%s)!", 827fe939687SNatalie Samsonov MRVL_TOK_MAPPING_PRIORITY, entry); 828c2b5ae61SLiron Himi return -1; 829c2b5ae61SLiron Himi } 830fe939687SNatalie Samsonov } else { 831fe939687SNatalie Samsonov (*cfg)->port[n].mapping_priority = 83255e429acSLiron Himi PP2_CLS_QOS_TBL_NONE; 833fe939687SNatalie Samsonov } 834fe939687SNatalie Samsonov 835e97d8874STomasz Duszynski /* Parse policer configuration (if any) */ 836e97d8874STomasz Duszynski entry = rte_cfgfile_get_entry(file, sec_name, 837e97d8874STomasz Duszynski MRVL_TOK_PLCR_DEFAULT); 838e97d8874STomasz Duszynski if (entry) { 83941c60f74SDana Vardi (*cfg)->port[n].use_qos_global_defaults = 0; 840e97d8874STomasz Duszynski if (get_val_securely(entry, &val) < 0) 841e97d8874STomasz Duszynski return -1; 842e97d8874STomasz Duszynski 843e97d8874STomasz Duszynski snprintf(sec_name, sizeof(sec_name), "%s %d", 844e97d8874STomasz Duszynski MRVL_TOK_PLCR, val); 845e97d8874STomasz Duszynski ret = parse_policer(file, n, sec_name, *cfg); 846e97d8874STomasz Duszynski if (ret) 847e97d8874STomasz Duszynski return -1; 848e97d8874STomasz Duszynski } 849e97d8874STomasz Duszynski 850fe939687SNatalie Samsonov for (i = 0; i < MRVL_PP2_RXQ_MAX; ++i) { 851fe939687SNatalie Samsonov ret = get_outq_cfg(file, n, i, *cfg); 852c2b5ae61SLiron Himi if (ret < 0) { 853c2b5ae61SLiron Himi MRVL_LOG(ERR, 854*8df71650SJerin Jacob "Error %d parsing port %d outq %d!", 855fe939687SNatalie Samsonov ret, n, i); 856c2b5ae61SLiron Himi return -1; 857c2b5ae61SLiron Himi } 858fe939687SNatalie Samsonov } 859fe939687SNatalie Samsonov 860fe939687SNatalie Samsonov for (i = 0; i < MRVL_PP2_TC_MAX; ++i) { 861fe939687SNatalie Samsonov ret = parse_tc_cfg(file, n, i, *cfg); 862c2b5ae61SLiron Himi if (ret < 0) { 863c2b5ae61SLiron Himi MRVL_LOG(ERR, 864*8df71650SJerin Jacob "Error %d parsing port %d tc %d!", 865fe939687SNatalie Samsonov ret, n, i); 866c2b5ae61SLiron Himi return -1; 867c2b5ae61SLiron Himi } 868fe939687SNatalie Samsonov } 869406aeb15SYuval Caduri 870406aeb15SYuval Caduri entry = rte_cfgfile_get_entry(file, sec_name, 871406aeb15SYuval Caduri MRVL_TOK_DEFAULT_TC); 872406aeb15SYuval Caduri if (entry) { 873406aeb15SYuval Caduri if (get_val_securely(entry, &val) < 0 || 874406aeb15SYuval Caduri val > USHRT_MAX) 875406aeb15SYuval Caduri return -1; 876406aeb15SYuval Caduri (*cfg)->port[n].default_tc = (uint8_t)val; 877406aeb15SYuval Caduri } else { 87841c60f74SDana Vardi if ((*cfg)->port[n].use_qos_global_defaults == 0) { 879406aeb15SYuval Caduri MRVL_LOG(ERR, 880c2b5ae61SLiron Himi "Default Traffic Class required in " 881c2b5ae61SLiron Himi "custom configuration!"); 882406aeb15SYuval Caduri return -1; 883406aeb15SYuval Caduri } 884406aeb15SYuval Caduri } 885ef08031fSDana Vardi 886ef08031fSDana Vardi /* Parse forward bad frames option */ 887ef08031fSDana Vardi entry = rte_cfgfile_get_entry(file, sec_name, 888ef08031fSDana Vardi MRVL_TOK_FWD_BAD_FRAMES); 889ef08031fSDana Vardi if (entry) { 890ef08031fSDana Vardi if (get_val_securely(entry, &val) < 0) { 891ef08031fSDana Vardi MRVL_LOG(ERR, 892*8df71650SJerin Jacob "Error in parsing %s value (%s)!", 893ef08031fSDana Vardi MRVL_TOK_FWD_BAD_FRAMES, entry); 894ef08031fSDana Vardi return -1; 895ef08031fSDana Vardi } 896ef08031fSDana Vardi (*cfg)->port[n].forward_bad_frames = (uint8_t)val; 897ef08031fSDana Vardi } else { 898ef08031fSDana Vardi (*cfg)->port[n].forward_bad_frames = 0; 899ef08031fSDana Vardi } 9004b86050aSDana Vardi 9014b86050aSDana Vardi /* Parse fill bpool buffs option */ 9024b86050aSDana Vardi entry = rte_cfgfile_get_entry(file, sec_name, 9034b86050aSDana Vardi MRVL_TOK_FILL_BPOOL_BUFFS); 9044b86050aSDana Vardi if (entry) { 9054b86050aSDana Vardi if (get_val_securely(entry, &val) < 0) { 9064b86050aSDana Vardi MRVL_LOG(ERR, 907*8df71650SJerin Jacob "Error in parsing %s value (%s)!", 9084b86050aSDana Vardi MRVL_TOK_FILL_BPOOL_BUFFS, entry); 9094b86050aSDana Vardi return -1; 9104b86050aSDana Vardi } 9114b86050aSDana Vardi (*cfg)->port[n].fill_bpool_buffs = val; 9124b86050aSDana Vardi } 913fe939687SNatalie Samsonov } 914fe939687SNatalie Samsonov 915fe939687SNatalie Samsonov return 0; 916fe939687SNatalie Samsonov } 917fe939687SNatalie Samsonov 918fe939687SNatalie Samsonov /** 919fe939687SNatalie Samsonov * Setup Traffic Class. 920fe939687SNatalie Samsonov * 921fe939687SNatalie Samsonov * Fill in TC parameters in single MUSDK TC config entry. 922fe939687SNatalie Samsonov * @param param TC parameters entry. 923fe939687SNatalie Samsonov * @param inqs Number of MUSDK in-queues in this TC. 924fe939687SNatalie Samsonov * @param bpool Bpool for this TC. 925fe939687SNatalie Samsonov * @param color Default color for this TC. 926fe939687SNatalie Samsonov * @returns 0 in case of success, exits otherwise. 927fe939687SNatalie Samsonov */ 928fe939687SNatalie Samsonov static int 929fe939687SNatalie Samsonov setup_tc(struct pp2_ppio_tc_params *param, uint8_t inqs, 930fe939687SNatalie Samsonov struct pp2_bpool *bpool, enum pp2_ppio_color color) 931fe939687SNatalie Samsonov { 932fe939687SNatalie Samsonov struct pp2_ppio_inq_params *inq_params; 933fe939687SNatalie Samsonov 934fe939687SNatalie Samsonov param->pkt_offset = MRVL_PKT_OFFS; 935e04ec42aSTomasz Duszynski param->pools[0][0] = bpool; 93630d30720SLiron Himi param->pools[0][1] = dummy_pool[bpool->pp2_id]; 937fe939687SNatalie Samsonov param->default_color = color; 938fe939687SNatalie Samsonov 939fe939687SNatalie Samsonov inq_params = rte_zmalloc_socket("inq_params", 940fe939687SNatalie Samsonov inqs * sizeof(*inq_params), 941fe939687SNatalie Samsonov 0, rte_socket_id()); 942fe939687SNatalie Samsonov if (!inq_params) 943fe939687SNatalie Samsonov return -ENOMEM; 944fe939687SNatalie Samsonov 945fe939687SNatalie Samsonov param->num_in_qs = inqs; 946fe939687SNatalie Samsonov 947fe939687SNatalie Samsonov /* Release old config if necessary. */ 948fe939687SNatalie Samsonov rte_free(param->inqs_params); 949fe939687SNatalie Samsonov 950fe939687SNatalie Samsonov param->inqs_params = inq_params; 951fe939687SNatalie Samsonov 952fe939687SNatalie Samsonov return 0; 953fe939687SNatalie Samsonov } 954fe939687SNatalie Samsonov 955fe939687SNatalie Samsonov /** 956fe939687SNatalie Samsonov * Setup ingress policer. 957fe939687SNatalie Samsonov * 958fe939687SNatalie Samsonov * @param priv Port's private data. 959fe939687SNatalie Samsonov * @param params Pointer to the policer's configuration. 960e97d8874STomasz Duszynski * @param plcr_id Policer id. 961fe939687SNatalie Samsonov * @returns 0 in case of success, negative values otherwise. 962fe939687SNatalie Samsonov */ 963fe939687SNatalie Samsonov static int 964fe939687SNatalie Samsonov setup_policer(struct mrvl_priv *priv, struct pp2_cls_plcr_params *params) 965fe939687SNatalie Samsonov { 966fe939687SNatalie Samsonov char match[16]; 967fe939687SNatalie Samsonov int ret; 968fe939687SNatalie Samsonov 969e97d8874STomasz Duszynski /* 970e97d8874STomasz Duszynski * At this point no other policers are used which means 971e97d8874STomasz Duszynski * any policer can be picked up and used as a default one. 972e97d8874STomasz Duszynski * 973e97d8874STomasz Duszynski * Lets use 0th then. 974e97d8874STomasz Duszynski */ 975*8df71650SJerin Jacob sprintf(match, "policer-%d:%d", priv->pp_id, 0); 976fe939687SNatalie Samsonov params->match = match; 977fe939687SNatalie Samsonov 978e97d8874STomasz Duszynski ret = pp2_cls_plcr_init(params, &priv->default_policer); 979fe939687SNatalie Samsonov if (ret) { 980acab7d58STomasz Duszynski MRVL_LOG(ERR, "Failed to setup %s", match); 981fe939687SNatalie Samsonov return -1; 982fe939687SNatalie Samsonov } 983fe939687SNatalie Samsonov 984e97d8874STomasz Duszynski priv->ppio_params.inqs_params.plcr = priv->default_policer; 985e97d8874STomasz Duszynski priv->used_plcrs = BIT(0); 986fe939687SNatalie Samsonov 987fe939687SNatalie Samsonov return 0; 988fe939687SNatalie Samsonov } 989fe939687SNatalie Samsonov 990fe939687SNatalie Samsonov /** 991fe939687SNatalie Samsonov * Configure RX Queues in a given port. 992fe939687SNatalie Samsonov * 993fe939687SNatalie Samsonov * Sets up RX queues, their Traffic Classes and DPDK rxq->(TC,inq) mapping. 994fe939687SNatalie Samsonov * 995fe939687SNatalie Samsonov * @param priv Port's private data 996fe939687SNatalie Samsonov * @param portid DPDK port ID 997fe939687SNatalie Samsonov * @param max_queues Maximum number of queues to configure. 998fe939687SNatalie Samsonov * @returns 0 in case of success, negative value otherwise. 999fe939687SNatalie Samsonov */ 1000fe939687SNatalie Samsonov int 1001fe939687SNatalie Samsonov mrvl_configure_rxqs(struct mrvl_priv *priv, uint16_t portid, 1002fe939687SNatalie Samsonov uint16_t max_queues) 1003fe939687SNatalie Samsonov { 1004fe939687SNatalie Samsonov size_t i, tc; 1005fe939687SNatalie Samsonov 1006d7eb4fb2SLiron Himi if (mrvl_cfg == NULL || 100741c60f74SDana Vardi mrvl_cfg->port[portid].use_qos_global_defaults) { 1008fe939687SNatalie Samsonov /* 1009fe939687SNatalie Samsonov * No port configuration, use default: 1 TC, no QoS, 1010fe939687SNatalie Samsonov * TC color set to green. 1011fe939687SNatalie Samsonov */ 1012fe939687SNatalie Samsonov priv->ppio_params.inqs_params.num_tcs = 1; 1013fe939687SNatalie Samsonov setup_tc(&priv->ppio_params.inqs_params.tcs_params[0], 1014fe939687SNatalie Samsonov max_queues, priv->bpool, PP2_PPIO_COLOR_GREEN); 1015fe939687SNatalie Samsonov 1016fe939687SNatalie Samsonov /* Direct mapping of queues i.e. 0->0, 1->1 etc. */ 1017fe939687SNatalie Samsonov for (i = 0; i < max_queues; ++i) { 1018fe939687SNatalie Samsonov priv->rxq_map[i].tc = 0; 1019fe939687SNatalie Samsonov priv->rxq_map[i].inq = i; 1020fe939687SNatalie Samsonov } 1021fe939687SNatalie Samsonov return 0; 1022fe939687SNatalie Samsonov } 1023fe939687SNatalie Samsonov 1024fe939687SNatalie Samsonov /* We need only a subset of configuration. */ 1025d7eb4fb2SLiron Himi struct port_cfg *port_cfg = &mrvl_cfg->port[portid]; 1026fe939687SNatalie Samsonov 1027fe939687SNatalie Samsonov priv->qos_tbl_params.type = port_cfg->mapping_priority; 1028fe939687SNatalie Samsonov 1029fe939687SNatalie Samsonov /* 1030fe939687SNatalie Samsonov * We need to reverse mapping, from tc->pcp (better from usability 1031fe939687SNatalie Samsonov * point of view) to pcp->tc (configurable in MUSDK). 1032fe939687SNatalie Samsonov * First, set all map elements to "default". 1033fe939687SNatalie Samsonov */ 1034fe939687SNatalie Samsonov for (i = 0; i < RTE_DIM(priv->qos_tbl_params.pcp_cos_map); ++i) 1035fe939687SNatalie Samsonov priv->qos_tbl_params.pcp_cos_map[i].tc = port_cfg->default_tc; 1036fe939687SNatalie Samsonov 1037fe939687SNatalie Samsonov /* Then, fill in all known values. */ 1038fe939687SNatalie Samsonov for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) { 1039fe939687SNatalie Samsonov if (port_cfg->tc[tc].pcps > RTE_DIM(port_cfg->tc[0].pcp)) { 1040fe939687SNatalie Samsonov /* Better safe than sorry. */ 1041acab7d58STomasz Duszynski MRVL_LOG(ERR, 1042acab7d58STomasz Duszynski "Too many PCPs configured in TC %zu!", tc); 1043fe939687SNatalie Samsonov return -1; 1044fe939687SNatalie Samsonov } 1045fe939687SNatalie Samsonov for (i = 0; i < port_cfg->tc[tc].pcps; ++i) { 1046fe939687SNatalie Samsonov priv->qos_tbl_params.pcp_cos_map[ 1047fe939687SNatalie Samsonov port_cfg->tc[tc].pcp[i]].tc = tc; 1048fe939687SNatalie Samsonov } 1049fe939687SNatalie Samsonov } 1050fe939687SNatalie Samsonov 1051fe939687SNatalie Samsonov /* 1052fe939687SNatalie Samsonov * The same logic goes with DSCP. 1053fe939687SNatalie Samsonov * First, set all map elements to "default". 1054fe939687SNatalie Samsonov */ 1055fe939687SNatalie Samsonov for (i = 0; i < RTE_DIM(priv->qos_tbl_params.dscp_cos_map); ++i) 1056fe939687SNatalie Samsonov priv->qos_tbl_params.dscp_cos_map[i].tc = 1057fe939687SNatalie Samsonov port_cfg->default_tc; 1058fe939687SNatalie Samsonov 1059fe939687SNatalie Samsonov /* Fill in all known values. */ 1060fe939687SNatalie Samsonov for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) { 1061fe939687SNatalie Samsonov if (port_cfg->tc[tc].dscps > RTE_DIM(port_cfg->tc[0].dscp)) { 1062fe939687SNatalie Samsonov /* Better safe than sorry. */ 1063acab7d58STomasz Duszynski MRVL_LOG(ERR, 1064acab7d58STomasz Duszynski "Too many DSCPs configured in TC %zu!", tc); 1065fe939687SNatalie Samsonov return -1; 1066fe939687SNatalie Samsonov } 1067fe939687SNatalie Samsonov for (i = 0; i < port_cfg->tc[tc].dscps; ++i) { 1068fe939687SNatalie Samsonov priv->qos_tbl_params.dscp_cos_map[ 1069fe939687SNatalie Samsonov port_cfg->tc[tc].dscp[i]].tc = tc; 1070fe939687SNatalie Samsonov } 1071fe939687SNatalie Samsonov } 1072fe939687SNatalie Samsonov 1073fe939687SNatalie Samsonov /* 1074fe939687SNatalie Samsonov * Surprisingly, similar logic goes with queue mapping. 1075fe939687SNatalie Samsonov * We need only to store qid->tc mapping, 1076fe939687SNatalie Samsonov * to know TC when queue is read. 1077fe939687SNatalie Samsonov */ 1078fe939687SNatalie Samsonov for (i = 0; i < RTE_DIM(priv->rxq_map); ++i) 1079fe939687SNatalie Samsonov priv->rxq_map[i].tc = MRVL_UNKNOWN_TC; 1080fe939687SNatalie Samsonov 1081fe939687SNatalie Samsonov /* Set up DPDKq->(TC,inq) mapping. */ 1082fe939687SNatalie Samsonov for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) { 1083fe939687SNatalie Samsonov if (port_cfg->tc[tc].inqs > RTE_DIM(port_cfg->tc[0].inq)) { 1084fe939687SNatalie Samsonov /* Overflow. */ 1085acab7d58STomasz Duszynski MRVL_LOG(ERR, 1086acab7d58STomasz Duszynski "Too many RX queues configured per TC %zu!", 1087fe939687SNatalie Samsonov tc); 1088fe939687SNatalie Samsonov return -1; 1089fe939687SNatalie Samsonov } 1090fe939687SNatalie Samsonov for (i = 0; i < port_cfg->tc[tc].inqs; ++i) { 1091fe939687SNatalie Samsonov uint8_t idx = port_cfg->tc[tc].inq[i]; 1092fe939687SNatalie Samsonov 1093fe939687SNatalie Samsonov if (idx > RTE_DIM(priv->rxq_map)) { 1094acab7d58STomasz Duszynski MRVL_LOG(ERR, "Bad queue index %d!", idx); 1095fe939687SNatalie Samsonov return -1; 1096fe939687SNatalie Samsonov } 1097fe939687SNatalie Samsonov 1098fe939687SNatalie Samsonov priv->rxq_map[idx].tc = tc; 1099fe939687SNatalie Samsonov priv->rxq_map[idx].inq = i; 1100fe939687SNatalie Samsonov } 1101fe939687SNatalie Samsonov } 1102fe939687SNatalie Samsonov 1103fe939687SNatalie Samsonov /* 1104fe939687SNatalie Samsonov * Set up TC configuration. TCs need to be sequenced: 0, 1, 2 1105fe939687SNatalie Samsonov * with no gaps. Empty TC means end of processing. 1106fe939687SNatalie Samsonov */ 1107fe939687SNatalie Samsonov for (i = 0; i < MRVL_PP2_TC_MAX; ++i) { 1108fe939687SNatalie Samsonov if (port_cfg->tc[i].inqs == 0) 1109fe939687SNatalie Samsonov break; 1110fe939687SNatalie Samsonov setup_tc(&priv->ppio_params.inqs_params.tcs_params[i], 1111fe939687SNatalie Samsonov port_cfg->tc[i].inqs, 1112fe939687SNatalie Samsonov priv->bpool, port_cfg->tc[i].color); 1113fe939687SNatalie Samsonov } 1114fe939687SNatalie Samsonov 1115fe939687SNatalie Samsonov priv->ppio_params.inqs_params.num_tcs = i; 1116fe939687SNatalie Samsonov 1117e97d8874STomasz Duszynski if (port_cfg->setup_policer) 1118fe939687SNatalie Samsonov return setup_policer(priv, &port_cfg->policer_params); 1119fe939687SNatalie Samsonov 1120fe939687SNatalie Samsonov return 0; 1121fe939687SNatalie Samsonov } 1122fe939687SNatalie Samsonov 1123fe939687SNatalie Samsonov /** 1124fe939687SNatalie Samsonov * Configure TX Queues in a given port. 1125fe939687SNatalie Samsonov * 1126fe939687SNatalie Samsonov * Sets up TX queues egress scheduler and limiter. 1127fe939687SNatalie Samsonov * 1128fe939687SNatalie Samsonov * @param priv Port's private data 1129fe939687SNatalie Samsonov * @param portid DPDK port ID 1130fe939687SNatalie Samsonov * @param max_queues Maximum number of queues to configure. 1131fe939687SNatalie Samsonov * @returns 0 in case of success, negative value otherwise. 1132fe939687SNatalie Samsonov */ 1133fe939687SNatalie Samsonov int 1134fe939687SNatalie Samsonov mrvl_configure_txqs(struct mrvl_priv *priv, uint16_t portid, 1135fe939687SNatalie Samsonov uint16_t max_queues) 1136fe939687SNatalie Samsonov { 1137fe939687SNatalie Samsonov /* We need only a subset of configuration. */ 1138d7eb4fb2SLiron Himi struct port_cfg *port_cfg = &mrvl_cfg->port[portid]; 1139fe939687SNatalie Samsonov int i; 1140fe939687SNatalie Samsonov 1141d7eb4fb2SLiron Himi if (mrvl_cfg == NULL) 1142fe939687SNatalie Samsonov return 0; 1143fe939687SNatalie Samsonov 1144fe939687SNatalie Samsonov priv->ppio_params.rate_limit_enable = port_cfg->rate_limit_enable; 1145fe939687SNatalie Samsonov if (port_cfg->rate_limit_enable) 1146fe939687SNatalie Samsonov priv->ppio_params.rate_limit_params = 1147fe939687SNatalie Samsonov port_cfg->rate_limit_params; 1148fe939687SNatalie Samsonov 1149fe939687SNatalie Samsonov for (i = 0; i < max_queues; i++) { 1150fe939687SNatalie Samsonov struct pp2_ppio_outq_params *params = 1151fe939687SNatalie Samsonov &priv->ppio_params.outqs_params.outqs_params[i]; 1152fe939687SNatalie Samsonov 1153fe939687SNatalie Samsonov params->sched_mode = port_cfg->outq[i].sched_mode; 1154fe939687SNatalie Samsonov params->weight = port_cfg->outq[i].weight; 1155fe939687SNatalie Samsonov params->rate_limit_enable = port_cfg->outq[i].rate_limit_enable; 1156fe939687SNatalie Samsonov params->rate_limit_params = port_cfg->outq[i].rate_limit_params; 1157fe939687SNatalie Samsonov } 1158fe939687SNatalie Samsonov 1159fe939687SNatalie Samsonov return 0; 1160fe939687SNatalie Samsonov } 1161fe939687SNatalie Samsonov 1162fe939687SNatalie Samsonov /** 1163fe939687SNatalie Samsonov * Start QoS mapping. 1164fe939687SNatalie Samsonov * 1165fe939687SNatalie Samsonov * Finalize QoS table configuration and initialize it in SDK. It can be done 1166fe939687SNatalie Samsonov * only after port is started, so we have a valid ppio reference. 1167fe939687SNatalie Samsonov * 1168fe939687SNatalie Samsonov * @param priv Port's private (configuration) data. 1169fe939687SNatalie Samsonov * @returns 0 in case of success, exits otherwise. 1170fe939687SNatalie Samsonov */ 1171fe939687SNatalie Samsonov int 1172fe939687SNatalie Samsonov mrvl_start_qos_mapping(struct mrvl_priv *priv) 1173fe939687SNatalie Samsonov { 1174fe939687SNatalie Samsonov size_t i; 1175fe939687SNatalie Samsonov 117655e429acSLiron Himi if (priv->qos_tbl_params.type == PP2_CLS_QOS_TBL_NONE) 117755e429acSLiron Himi return 0; 117855e429acSLiron Himi 1179fe939687SNatalie Samsonov if (priv->ppio == NULL) { 1180acab7d58STomasz Duszynski MRVL_LOG(ERR, "ppio must not be NULL here!"); 1181fe939687SNatalie Samsonov return -1; 1182fe939687SNatalie Samsonov } 1183fe939687SNatalie Samsonov 1184fe939687SNatalie Samsonov for (i = 0; i < RTE_DIM(priv->qos_tbl_params.pcp_cos_map); ++i) 1185fe939687SNatalie Samsonov priv->qos_tbl_params.pcp_cos_map[i].ppio = priv->ppio; 1186fe939687SNatalie Samsonov 1187fe939687SNatalie Samsonov for (i = 0; i < RTE_DIM(priv->qos_tbl_params.dscp_cos_map); ++i) 1188fe939687SNatalie Samsonov priv->qos_tbl_params.dscp_cos_map[i].ppio = priv->ppio; 1189fe939687SNatalie Samsonov 1190fe939687SNatalie Samsonov /* Initialize Classifier QoS table. */ 1191fe939687SNatalie Samsonov 1192fe939687SNatalie Samsonov return pp2_cls_qos_tbl_init(&priv->qos_tbl_params, &priv->qos_tbl); 1193fe939687SNatalie Samsonov } 1194