X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=examples%2Fip_pipeline%2Fconfig_parse.c;fp=examples%2Fip_pipeline%2Fconfig_parse.c;h=0adca98f04c394781a21f1700e88f523ef254c1c;hb=8b25d1ad5d2264bdfc2818c7bda74ee2697df6db;hp=e5efd03ea6ab5056b9813b67e7473fe02c8c9ba3;hpb=97f17497d162afdb82c8704bf097f0fee3724b2e;p=deb_dpdk.git diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c index e5efd03e..0adca98f 100644 --- a/examples/ip_pipeline/config_parse.c +++ b/examples/ip_pipeline/config_parse.c @@ -1,4 +1,4 @@ -/*- +/*- * BSD LICENSE * * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. @@ -30,6 +30,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include #include #include @@ -80,6 +81,11 @@ static const struct app_link_params link_params_default = { .tcp_local_q = 0, .udp_local_q = 0, .sctp_local_q = 0, + .rss_qs = {0}, + .n_rss_qs = 0, + .rss_proto_ipv4 = ETH_RSS_IPV4, + .rss_proto_ipv6 = ETH_RSS_IPV6, + .rss_proto_l2 = 0, .state = 0, .ip = 0, .depth = 0, @@ -103,6 +109,13 @@ static const struct app_link_params link_params_default = { .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */ .split_hdr_size = 0, /* Header split buffer size */ }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_key_len = 40, + .rss_hf = 0, + }, + }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, @@ -176,6 +189,20 @@ struct app_pktq_tm_params default_tm_params = { .burst_write = 32, }; +struct app_pktq_kni_params default_kni_params = { + .parsed = 0, + .socket_id = 0, + .core_id = 0, + .hyper_th_id = 0, + .force_bind = 0, + + .mempool_id = 0, + .burst_read = 32, + .burst_write = 32, + .dropless = 0, + .n_retries = 0, +}; + struct app_pktq_source_params default_source_params = { .parsed = 0, .mempool_id = 0, @@ -229,306 +256,136 @@ app_print_usage(char *prgname) rte_exit(0, app_usage, prgname, app_params_default.config_file); } -#define skip_white_spaces(pos) \ -({ \ - __typeof__(pos) _p = (pos); \ - for ( ; isspace(*_p); _p++); \ - _p; \ +#define APP_PARAM_ADD(set, key) \ +({ \ + ssize_t pos = APP_PARAM_FIND(set, key); \ + ssize_t size = RTE_DIM(set); \ + \ + if (pos < 0) { \ + for (pos = 0; pos < size; pos++) { \ + if (!APP_PARAM_VALID(&((set)[pos]))) \ + break; \ + } \ + \ + APP_CHECK((pos < size), \ + "Parse error: size of %s is limited to %u elements",\ + #set, (uint32_t) size); \ + \ + (set)[pos].name = strdup(key); \ + APP_CHECK(((set)[pos].name), \ + "Parse error: no free memory"); \ + } \ + pos; \ }) -#define PARSER_PARAM_ADD_CHECK(result, params_array, section_name) \ -do { \ - APP_CHECK((result != -EINVAL), \ - "Parse error: no free memory"); \ - APP_CHECK((result != -ENOMEM), \ - "Parse error: too many \"%s\" sections", section_name); \ - APP_CHECK(((result >= 0) && (params_array)[result].parsed == 0),\ - "Parse error: duplicate \"%s\" section", section_name); \ - APP_CHECK((result >= 0), \ - "Parse error in section \"%s\"", section_name); \ -} while (0) - -int -parser_read_arg_bool(const char *p) -{ - p = skip_white_spaces(p); - int result = -EINVAL; - - if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) || - ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) { - p += 3; - result = 1; - } - - if (((p[0] == 'o') && (p[1] == 'n')) || - ((p[0] == 'O') && (p[1] == 'N'))) { - p += 2; - result = 1; - } +#define APP_PARAM_ADD_LINK_FOR_RXQ(app, rxq_name) \ +({ \ + char link_name[APP_PARAM_NAME_SIZE]; \ + ssize_t link_param_pos; \ + uint32_t link_id, queue_id; \ + \ + sscanf((rxq_name), "RXQ%" SCNu32 ".%" SCNu32, &link_id, &queue_id);\ + sprintf(link_name, "LINK%" PRIu32, link_id); \ + link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ + link_param_pos; \ +}) - if (((p[0] == 'n') && (p[1] == 'o')) || - ((p[0] == 'N') && (p[1] == 'O'))) { - p += 2; - result = 0; - } +#define APP_PARAM_ADD_LINK_FOR_TXQ(app, txq_name) \ +({ \ + char link_name[APP_PARAM_NAME_SIZE]; \ + ssize_t link_param_pos; \ + uint32_t link_id, queue_id; \ + \ + sscanf((txq_name), "TXQ%" SCNu32 ".%" SCNu32, &link_id, &queue_id);\ + sprintf(link_name, "LINK%" PRIu32, link_id); \ + link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ + link_param_pos; \ +}) - if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) || - ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) { - p += 3; - result = 0; - } +#define APP_PARAM_ADD_LINK_FOR_TM(app, tm_name) \ +({ \ + char link_name[APP_PARAM_NAME_SIZE]; \ + ssize_t link_param_pos; \ + uint32_t link_id; \ + \ + sscanf((tm_name), "TM%" SCNu32, &link_id); \ + sprintf(link_name, "LINK%" PRIu32, link_id); \ + link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ + link_param_pos; \ +}) - p = skip_white_spaces(p); +#define APP_PARAM_ADD_LINK_FOR_KNI(app, kni_name) \ +({ \ + char link_name[APP_PARAM_NAME_SIZE]; \ + ssize_t link_param_pos; \ + uint32_t link_id; \ + \ + sscanf((kni_name), "KNI%" SCNu32, &link_id); \ + sprintf(link_name, "LINK%" PRIu32, link_id); \ + link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ + link_param_pos; \ +}) - if (p[0] != '\0') - return -EINVAL; +#define PARSE_CHECK_DUPLICATE_SECTION(obj) \ +do { \ + APP_CHECK(((obj)->parsed == 0), \ + "Parse error: duplicate \"%s\" section", (obj)->name); \ + (obj)->parsed++; \ +} while (0) - return result; -} +#define PARSE_CHECK_DUPLICATE_SECTION_EAL(obj) \ +do { \ + APP_CHECK(((obj)->parsed == 0), \ + "Parse error: duplicate \"%s\" section", "EAL"); \ + (obj)->parsed++; \ +} while (0) #define PARSE_ERROR(exp, section, entry) \ -APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"\n", section, entry) +APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"", section, entry) #define PARSE_ERROR_MESSAGE(exp, section, entry, message) \ -APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": %s\n", \ +APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": %s", \ section, entry, message) +#define PARSE_ERROR_NO_ELEMENTS(exp, section, entry) \ +APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \ + "no elements detected", \ + section, entry) + +#define PARSE_ERROR_TOO_MANY_ELEMENTS(exp, section, entry, max) \ +APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \ + "maximum number of elements allowed is %u", \ + section, entry, max) + +#define PARSE_ERROR_INVALID_ELEMENT(exp, section, entry, value) \ +APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \ + "Invalid element value \"%s\"", \ + section, entry, value) #define PARSE_ERROR_MALLOC(exp) \ -APP_CHECK(exp, "Parse error: no free memory\n") +APP_CHECK(exp, "Parse error: no free memory") #define PARSE_ERROR_SECTION(exp, section) \ APP_CHECK(exp, "Parse error in section \"%s\"", section) #define PARSE_ERROR_SECTION_NO_ENTRIES(exp, section) \ -APP_CHECK(exp, "Parse error in section \"%s\": no entries\n", section) +APP_CHECK(exp, "Parse error in section \"%s\": no entries", section) #define PARSE_WARNING_IGNORED(exp, section, entry) \ do \ if (!(exp)) \ fprintf(stderr, "Parse warning in section \"%s\": " \ - "entry \"%s\" is ignored\n", section, entry); \ + "entry \"%s\" is ignored", section, entry); \ while (0) #define PARSE_ERROR_INVALID(exp, section, entry) \ -APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"\n",\ +APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"",\ section, entry) #define PARSE_ERROR_DUPLICATE(exp, section, entry) \ -APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"\n",\ +APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"", \ section, entry) -int -parser_read_uint64(uint64_t *value, const char *p) -{ - char *next; - uint64_t val; - - p = skip_white_spaces(p); - if (!isdigit(*p)) - return -EINVAL; - - val = strtoul(p, &next, 10); - if (p == next) - return -EINVAL; - - p = next; - switch (*p) { - case 'T': - val *= 1024ULL; - /* fall through */ - case 'G': - val *= 1024ULL; - /* fall through */ - case 'M': - val *= 1024ULL; - /* fall through */ - case 'k': - case 'K': - val *= 1024ULL; - p++; - break; - } - - p = skip_white_spaces(p); - if (*p != '\0') - return -EINVAL; - - *value = val; - return 0; -} - -int -parser_read_uint32(uint32_t *value, const char *p) -{ - uint64_t val = 0; - int ret = parser_read_uint64(&val, p); - - if (ret < 0) - return ret; - - if (val > UINT32_MAX) - return -ERANGE; - - *value = val; - return 0; -} - -int -parse_pipeline_core(uint32_t *socket, - uint32_t *core, - uint32_t *ht, - const char *entry) -{ - size_t num_len; - char num[8]; - - uint32_t s = 0, c = 0, h = 0, val; - uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0; - const char *next = skip_white_spaces(entry); - char type; - - /* Expect or [sX][cY][h]. At least one parameter is required. */ - while (*next != '\0') { - /* If everything parsed nothing should left */ - if (s_parsed && c_parsed && h_parsed) - return -EINVAL; - - type = *next; - switch (type) { - case 's': - case 'S': - if (s_parsed || c_parsed || h_parsed) - return -EINVAL; - s_parsed = 1; - next++; - break; - case 'c': - case 'C': - if (c_parsed || h_parsed) - return -EINVAL; - c_parsed = 1; - next++; - break; - case 'h': - case 'H': - if (h_parsed) - return -EINVAL; - h_parsed = 1; - next++; - break; - default: - /* If it start from digit it must be only core id. */ - if (!isdigit(*next) || s_parsed || c_parsed || h_parsed) - return -EINVAL; - - type = 'C'; - } - - for (num_len = 0; *next != '\0'; next++, num_len++) { - if (num_len == RTE_DIM(num)) - return -EINVAL; - - if (!isdigit(*next)) - break; - - num[num_len] = *next; - } - - if (num_len == 0 && type != 'h' && type != 'H') - return -EINVAL; - - if (num_len != 0 && (type == 'h' || type == 'H')) - return -EINVAL; - - num[num_len] = '\0'; - val = strtol(num, NULL, 10); - - h = 0; - switch (type) { - case 's': - case 'S': - s = val; - break; - case 'c': - case 'C': - c = val; - break; - case 'h': - case 'H': - h = 1; - break; - } - } - - *socket = s; - *core = c; - *ht = h; - return 0; -} - -static uint32_t -get_hex_val(char c) -{ - switch (c) { - case '0': case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - return c - '0'; - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - return c - 'A' + 10; - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - return c - 'a' + 10; - default: - return 0; - } -} - -int -parse_hex_string(char *src, uint8_t *dst, uint32_t *size) -{ - char *c; - uint32_t len, i; - - /* Check input parameters */ - if ((src == NULL) || - (dst == NULL) || - (size == NULL) || - (*size == 0)) - return -1; - - len = strlen(src); - if (((len & 3) != 0) || - (len > (*size) * 2)) - return -1; - *size = len / 2; - - for (c = src; *c != 0; c++) { - if ((((*c) >= '0') && ((*c) <= '9')) || - (((*c) >= 'A') && ((*c) <= 'F')) || - (((*c) >= 'a') && ((*c) <= 'f'))) - continue; - - return -1; - } - - /* Convert chars to bytes */ - for (i = 0; i < *size; i++) - dst[i] = get_hex_val(src[2 * i]) * 16 + - get_hex_val(src[2 * i + 1]); - - return 0; -} - -static size_t -skip_digits(const char *src) -{ - size_t i; - - for (i = 0; isdigit(src[i]); i++); - - return i; -} - static int validate_name(const char *name, const char *prefix, int num) { @@ -584,6 +441,8 @@ parse_eal(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); + PARSE_CHECK_DUPLICATE_SECTION_EAL(p); + for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *entry = &entries[i]; @@ -963,413 +822,162 @@ parse_eal(struct app_params *app, free(entries); } -static int -parse_pipeline_pcap_source(struct app_params *app, - struct app_pipeline_params *p, - const char *file_name, const char *cp_size) -{ - const char *next = NULL; - char *end; - uint32_t i; - int parse_file = 0; - - if (file_name && !cp_size) { - next = file_name; - parse_file = 1; /* parse file path */ - } else if (cp_size && !file_name) { - next = cp_size; - parse_file = 0; /* parse copy size */ - } else - return -EINVAL; - - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; - - if (p->n_pktq_in == 0) - return -EINVAL; - - i = 0; - while (*next != '\0') { - uint32_t id; - - if (i >= p->n_pktq_in) - return -EINVAL; - - id = p->pktq_in[i].id; - - end = strchr(next, ' '); - if (!end) - name_len = strlen(next); - else - name_len = end - next; - - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; - - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; - - if (parse_file) { - app->source_params[id].file_name = strdup(name); - if (app->source_params[id].file_name == NULL) - return -ENOMEM; - } else { - if (parser_read_uint32( - &app->source_params[id].n_bytes_per_pkt, - name) != 0) { - if (app->source_params[id]. - file_name != NULL) - free(app->source_params[id]. - file_name); - return -EINVAL; - } - } - - i++; - - if (i == p->n_pktq_in) - return 0; - } - - return -EINVAL; -} - -static int -parse_pipeline_pcap_sink(struct app_params *app, - struct app_pipeline_params *p, - const char *file_name, const char *n_pkts_to_dump) -{ - const char *next = NULL; - char *end; - uint32_t i; - int parse_file = 0; - - if (file_name && !n_pkts_to_dump) { - next = file_name; - parse_file = 1; /* parse file path */ - } else if (n_pkts_to_dump && !file_name) { - next = n_pkts_to_dump; - parse_file = 0; /* parse copy size */ - } else - return -EINVAL; - - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; - - if (p->n_pktq_out == 0) - return -EINVAL; - - i = 0; - while (*next != '\0') { - uint32_t id; - - if (i >= p->n_pktq_out) - return -EINVAL; - - id = p->pktq_out[i].id; - - end = strchr(next, ' '); - if (!end) - name_len = strlen(next); - else - name_len = end - next; - - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; - - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; - - if (parse_file) { - app->sink_params[id].file_name = strdup(name); - if (app->sink_params[id].file_name == NULL) - return -ENOMEM; - } else { - if (parser_read_uint32( - &app->sink_params[id].n_pkts_to_dump, - name) != 0) { - if (app->sink_params[id].file_name != - NULL) - free(app->sink_params[id]. - file_name); - return -EINVAL; - } - } - - i++; - - if (i == p->n_pktq_out) - return 0; - } - - return -EINVAL; -} - -static int +static void parse_pipeline_pktq_in(struct app_params *app, struct app_pipeline_params *p, - const char *value) + char *value) { - const char *next = value; - char *end; - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; + p->n_pktq_in = 0; - while (*next != '\0') { + while (1) { enum app_pktq_in_type type; int id; - char *end_space; - char *end_tab; + char *name = strtok_r(value, PARSE_DELIMITER, &value); - next = skip_white_spaces(next); - if (!next) + if (name == NULL) break; - end_space = strchr(next, ' '); - end_tab = strchr(next, ' '); - - if (end_space && (!end_tab)) - end = end_space; - else if ((!end_space) && end_tab) - end = end_tab; - else if (end_space && end_tab) - end = RTE_MIN(end_space, end_tab); - else - end = NULL; - - if (!end) - name_len = strlen(next); - else - name_len = end - next; - - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; - - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; + PARSE_ERROR_TOO_MANY_ELEMENTS( + (p->n_pktq_in < RTE_DIM(p->pktq_in)), + p->name, "pktq_in", (uint32_t)RTE_DIM(p->pktq_in)); if (validate_name(name, "RXQ", 2) == 0) { type = APP_PKTQ_IN_HWQ; id = APP_PARAM_ADD(app->hwq_in_params, name); + APP_PARAM_ADD_LINK_FOR_RXQ(app, name); } else if (validate_name(name, "SWQ", 1) == 0) { type = APP_PKTQ_IN_SWQ; id = APP_PARAM_ADD(app->swq_params, name); } else if (validate_name(name, "TM", 1) == 0) { type = APP_PKTQ_IN_TM; id = APP_PARAM_ADD(app->tm_params, name); + APP_PARAM_ADD_LINK_FOR_TM(app, name); + } else if (validate_name(name, "KNI", 1) == 0) { + type = APP_PKTQ_IN_KNI; + id = APP_PARAM_ADD(app->kni_params, name); + APP_PARAM_ADD_LINK_FOR_KNI(app, name); } else if (validate_name(name, "SOURCE", 1) == 0) { type = APP_PKTQ_IN_SOURCE; id = APP_PARAM_ADD(app->source_params, name); } else - return -EINVAL; - - if (id < 0) - return id; + PARSE_ERROR_INVALID_ELEMENT(0, + p->name, "pktq_in", name); p->pktq_in[p->n_pktq_in].type = type; p->pktq_in[p->n_pktq_in].id = (uint32_t) id; p->n_pktq_in++; } - return 0; + PARSE_ERROR_NO_ELEMENTS((p->n_pktq_in > 0), p->name, "pktq_in"); } -static int +static void parse_pipeline_pktq_out(struct app_params *app, struct app_pipeline_params *p, - const char *value) + char *value) { - const char *next = value; - char *end; - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; + p->n_pktq_out = 0; - while (*next != '\0') { + while (1) { enum app_pktq_out_type type; int id; - char *end_space; - char *end_tab; + char *name = strtok_r(value, PARSE_DELIMITER, &value); - next = skip_white_spaces(next); - if (!next) + if (name == NULL) break; - end_space = strchr(next, ' '); - end_tab = strchr(next, ' '); - - if (end_space && (!end_tab)) - end = end_space; - else if ((!end_space) && end_tab) - end = end_tab; - else if (end_space && end_tab) - end = RTE_MIN(end_space, end_tab); - else - end = NULL; - - if (!end) - name_len = strlen(next); - else - name_len = end - next; - - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; + PARSE_ERROR_TOO_MANY_ELEMENTS( + (p->n_pktq_out < RTE_DIM(p->pktq_out)), + p->name, "pktq_out", (uint32_t)RTE_DIM(p->pktq_out)); - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; if (validate_name(name, "TXQ", 2) == 0) { type = APP_PKTQ_OUT_HWQ; id = APP_PARAM_ADD(app->hwq_out_params, name); + APP_PARAM_ADD_LINK_FOR_TXQ(app, name); } else if (validate_name(name, "SWQ", 1) == 0) { type = APP_PKTQ_OUT_SWQ; id = APP_PARAM_ADD(app->swq_params, name); } else if (validate_name(name, "TM", 1) == 0) { type = APP_PKTQ_OUT_TM; id = APP_PARAM_ADD(app->tm_params, name); + APP_PARAM_ADD_LINK_FOR_TM(app, name); + } else if (validate_name(name, "KNI", 1) == 0) { + type = APP_PKTQ_OUT_KNI; + id = APP_PARAM_ADD(app->kni_params, name); + APP_PARAM_ADD_LINK_FOR_KNI(app, name); } else if (validate_name(name, "SINK", 1) == 0) { type = APP_PKTQ_OUT_SINK; id = APP_PARAM_ADD(app->sink_params, name); } else - return -EINVAL; - - if (id < 0) - return id; + PARSE_ERROR_INVALID_ELEMENT(0, + p->name, "pktq_out", name); p->pktq_out[p->n_pktq_out].type = type; p->pktq_out[p->n_pktq_out].id = id; p->n_pktq_out++; } - return 0; + PARSE_ERROR_NO_ELEMENTS((p->n_pktq_out > 0), p->name, "pktq_out"); } -static int +static void parse_pipeline_msgq_in(struct app_params *app, struct app_pipeline_params *p, - const char *value) + char *value) { - const char *next = value; - char *end; - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; - ssize_t idx; - - while (*next != '\0') { - char *end_space; - char *end_tab; - - next = skip_white_spaces(next); - if (!next) - break; + p->n_msgq_in = 0; - end_space = strchr(next, ' '); - end_tab = strchr(next, ' '); + while (1) { + int idx; + char *name = strtok_r(value, PARSE_DELIMITER, &value); - if (end_space && (!end_tab)) - end = end_space; - else if ((!end_space) && end_tab) - end = end_tab; - else if (end_space && end_tab) - end = RTE_MIN(end_space, end_tab); - else - end = NULL; - - if (!end) - name_len = strlen(next); - else - name_len = end - next; - - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; + if (name == NULL) + break; - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; + PARSE_ERROR_TOO_MANY_ELEMENTS( + (p->n_msgq_in < RTE_DIM(p->msgq_in)), + p->name, "msgq_in", (uint32_t)(RTE_DIM(p->msgq_in))); - if (validate_name(name, "MSGQ", 1) != 0) - return -EINVAL; + PARSE_ERROR_INVALID_ELEMENT( + (validate_name(name, "MSGQ", 1) == 0), + p->name, "msgq_in", name); idx = APP_PARAM_ADD(app->msgq_params, name); - if (idx < 0) - return idx; - p->msgq_in[p->n_msgq_in] = idx; p->n_msgq_in++; } - return 0; + PARSE_ERROR_NO_ELEMENTS((p->n_msgq_in > 0), p->name, "msgq_in"); } -static int +static void parse_pipeline_msgq_out(struct app_params *app, struct app_pipeline_params *p, - const char *value) + char *value) { - const char *next = value; - char *end; - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; - ssize_t idx; - - while (*next != '\0') { - char *end_space; - char *end_tab; - - next = skip_white_spaces(next); - if (!next) - break; - - end_space = strchr(next, ' '); - end_tab = strchr(next, ' '); + p->n_msgq_out = 0; - if (end_space && (!end_tab)) - end = end_space; - else if ((!end_space) && end_tab) - end = end_tab; - else if (end_space && end_tab) - end = RTE_MIN(end_space, end_tab); - else - end = NULL; - - if (!end) - name_len = strlen(next); - else - name_len = end - next; + while (1) { + int idx; + char *name = strtok_r(value, PARSE_DELIMITER, &value); - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; + if (name == NULL) + break; - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; + PARSE_ERROR_TOO_MANY_ELEMENTS( + (p->n_msgq_out < RTE_DIM(p->msgq_out)), + p->name, "msgq_out", (uint32_t)RTE_DIM(p->msgq_out)); - if (validate_name(name, "MSGQ", 1) != 0) - return -EINVAL; + PARSE_ERROR_INVALID_ELEMENT( + (validate_name(name, "MSGQ", 1) == 0), + p->name, "msgq_out", name); idx = APP_PARAM_ADD(app->msgq_params, name); - if (idx < 0) - return idx; - p->msgq_out[p->n_msgq_out] = idx; p->n_msgq_out++; } - return 0; + PARSE_ERROR_NO_ELEMENTS((p->n_msgq_out > 0), p->name, "msgq_out"); } static void @@ -1392,9 +1000,8 @@ parse_pipeline(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->pipeline_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->pipeline_params, section_name); - param = &app->pipeline_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -1421,38 +1028,26 @@ parse_pipeline(struct app_params *app, } if (strcmp(ent->name, "pktq_in") == 0) { - int status = parse_pipeline_pktq_in(app, param, - ent->value); + parse_pipeline_pktq_in(app, param, ent->value); - PARSE_ERROR((status == 0), section_name, - ent->name); continue; } if (strcmp(ent->name, "pktq_out") == 0) { - int status = parse_pipeline_pktq_out(app, param, - ent->value); + parse_pipeline_pktq_out(app, param, ent->value); - PARSE_ERROR((status == 0), section_name, - ent->name); continue; } if (strcmp(ent->name, "msgq_in") == 0) { - int status = parse_pipeline_msgq_in(app, param, - ent->value); + parse_pipeline_msgq_in(app, param, ent->value); - PARSE_ERROR((status == 0), section_name, - ent->name); continue; } if (strcmp(ent->name, "msgq_out") == 0) { - int status = parse_pipeline_msgq_out(app, param, - ent->value); + parse_pipeline_msgq_out(app, param, ent->value); - PARSE_ERROR((status == 0), section_name, - ent->name); continue; } @@ -1466,66 +1061,6 @@ parse_pipeline(struct app_params *app, continue; } - if (strcmp(ent->name, "pcap_file_rd") == 0) { - int status; - -#ifndef RTE_PORT_PCAP - PARSE_ERROR_INVALID(0, section_name, ent->name); -#endif - - status = parse_pipeline_pcap_source(app, - param, ent->value, NULL); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "pcap_bytes_rd_per_pkt") == 0) { - int status; - -#ifndef RTE_PORT_PCAP - PARSE_ERROR_INVALID(0, section_name, ent->name); -#endif - - status = parse_pipeline_pcap_source(app, - param, NULL, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "pcap_file_wr") == 0) { - int status; - -#ifndef RTE_PORT_PCAP - PARSE_ERROR_INVALID(0, section_name, ent->name); -#endif - - status = parse_pipeline_pcap_sink(app, param, - ent->value, NULL); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "pcap_n_pkt_wr") == 0) { - int status; - -#ifndef RTE_PORT_PCAP - PARSE_ERROR_INVALID(0, section_name, ent->name); -#endif - - status = parse_pipeline_pcap_sink(app, param, - NULL, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - /* pipeline type specific items */ APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS), "Parse error in section \"%s\": too many " @@ -1541,17 +1076,13 @@ parse_pipeline(struct app_params *app, param->n_args++; } - param->parsed = 1; - snprintf(name, sizeof(name), "MSGQ-REQ-%s", section_name); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; param->msgq_in[param->n_msgq_in++] = param_idx; snprintf(name, sizeof(name), "MSGQ-RSP-%s", section_name); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; param->msgq_out[param->n_msgq_out++] = param_idx; @@ -1560,7 +1091,6 @@ parse_pipeline(struct app_params *app, param->core_id, (param->hyper_th_id) ? "h" : ""); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; snprintf(name, sizeof(name), "MSGQ-RSP-CORE-s%" PRIu32 "c%" PRIu32 "%s", @@ -1568,7 +1098,6 @@ parse_pipeline(struct app_params *app, param->core_id, (param->hyper_th_id) ? "h" : ""); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; free(entries); @@ -1592,57 +1121,197 @@ parse_mempool(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); - param_idx = APP_PARAM_ADD(app->mempool_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->mempool_params, section_name); + param_idx = APP_PARAM_ADD(app->mempool_params, section_name); + param = &app->mempool_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); + + for (i = 0; i < n_entries; i++) { + struct rte_cfgfile_entry *ent = &entries[i]; + + if (strcmp(ent->name, "buffer_size") == 0) { + int status = parser_read_uint32( + ¶m->buffer_size, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "pool_size") == 0) { + int status = parser_read_uint32( + ¶m->pool_size, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "cache_size") == 0) { + int status = parser_read_uint32( + ¶m->cache_size, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "cpu") == 0) { + int status = parser_read_uint32( + ¶m->cpu_socket_id, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); + } + + free(entries); +} + +static int +parse_link_rss_qs(struct app_link_params *p, + char *value) +{ + p->n_rss_qs = 0; + + while (1) { + char *token = strtok_r(value, PARSE_DELIMITER, &value); + + if (token == NULL) + break; + + if (p->n_rss_qs == RTE_DIM(p->rss_qs)) + return -ENOMEM; + + if (parser_read_uint32(&p->rss_qs[p->n_rss_qs++], token)) + return -EINVAL; + } + + return 0; +} + +static int +parse_link_rss_proto_ipv4(struct app_link_params *p, + char *value) +{ + uint64_t mask = 0; + + while (1) { + char *token = strtok_r(value, PARSE_DELIMITER, &value); + + if (token == NULL) + break; + + if (strcmp(token, "IP") == 0) { + mask |= ETH_RSS_IPV4; + continue; + } + if (strcmp(token, "FRAG") == 0) { + mask |= ETH_RSS_FRAG_IPV4; + continue; + } + if (strcmp(token, "TCP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV4_TCP; + continue; + } + if (strcmp(token, "UDP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV4_UDP; + continue; + } + if (strcmp(token, "SCTP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV4_SCTP; + continue; + } + if (strcmp(token, "OTHER") == 0) { + mask |= ETH_RSS_NONFRAG_IPV4_OTHER; + continue; + } + return -EINVAL; + } + + p->rss_proto_ipv4 = mask; + return 0; +} - param = &app->mempool_params[param_idx]; +static int +parse_link_rss_proto_ipv6(struct app_link_params *p, + char *value) +{ + uint64_t mask = 0; - for (i = 0; i < n_entries; i++) { - struct rte_cfgfile_entry *ent = &entries[i]; + while (1) { + char *token = strtok_r(value, PARSE_DELIMITER, &value); - if (strcmp(ent->name, "buffer_size") == 0) { - int status = parser_read_uint32( - ¶m->buffer_size, ent->value); + if (token == NULL) + break; - PARSE_ERROR((status == 0), section_name, - ent->name); + if (strcmp(token, "IP") == 0) { + mask |= ETH_RSS_IPV6; continue; } - - if (strcmp(ent->name, "pool_size") == 0) { - int status = parser_read_uint32( - ¶m->pool_size, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); + if (strcmp(token, "FRAG") == 0) { + mask |= ETH_RSS_FRAG_IPV6; continue; } - - if (strcmp(ent->name, "cache_size") == 0) { - int status = parser_read_uint32( - ¶m->cache_size, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); + if (strcmp(token, "TCP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV6_TCP; + continue; + } + if (strcmp(token, "UDP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV6_UDP; + continue; + } + if (strcmp(token, "SCTP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV6_SCTP; + continue; + } + if (strcmp(token, "OTHER") == 0) { + mask |= ETH_RSS_NONFRAG_IPV6_OTHER; + continue; + } + if (strcmp(token, "IP_EX") == 0) { + mask |= ETH_RSS_IPV6_EX; continue; } + if (strcmp(token, "TCP_EX") == 0) { + mask |= ETH_RSS_IPV6_TCP_EX; + continue; + } + if (strcmp(token, "UDP_EX") == 0) { + mask |= ETH_RSS_IPV6_UDP_EX; + continue; + } + return -EINVAL; + } - if (strcmp(ent->name, "cpu") == 0) { - int status = parser_read_uint32( - ¶m->cpu_socket_id, ent->value); + p->rss_proto_ipv6 = mask; + return 0; +} - PARSE_ERROR((status == 0), section_name, - ent->name); +static int +parse_link_rss_proto_l2(struct app_link_params *p, + char *value) +{ + uint64_t mask = 0; + + while (1) { + char *token = strtok_r(value, PARSE_DELIMITER, &value); + + if (token == NULL) + break; + + if (strcmp(token, "L2") == 0) { + mask |= ETH_RSS_L2_PAYLOAD; continue; } - - /* unrecognized */ - PARSE_ERROR_INVALID(0, section_name, ent->name); + return -EINVAL; } - param->parsed = 1; - - free(entries); + p->rss_proto_l2 = mask; + return 0; } static void @@ -1653,6 +1322,10 @@ parse_link(struct app_params *app, struct app_link_params *param; struct rte_cfgfile_entry *entries; int n_entries, i; + int rss_qs_present = 0; + int rss_proto_ipv4_present = 0; + int rss_proto_ipv6_present = 0; + int rss_proto_l2_present = 0; int pci_bdf_present = 0; ssize_t param_idx; @@ -1665,9 +1338,8 @@ parse_link(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->link_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->link_params, section_name); - param = &app->link_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -1707,7 +1379,6 @@ parse_link(struct app_params *app, continue; } - if (strcmp(ent->name, "tcp_local_q") == 0) { int status = parser_read_uint32( ¶m->tcp_local_q, ent->value); @@ -1735,6 +1406,44 @@ parse_link(struct app_params *app, continue; } + if (strcmp(ent->name, "rss_qs") == 0) { + int status = parse_link_rss_qs(param, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + rss_qs_present = 1; + continue; + } + + if (strcmp(ent->name, "rss_proto_ipv4") == 0) { + int status = + parse_link_rss_proto_ipv4(param, ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + rss_proto_ipv4_present = 1; + continue; + } + + if (strcmp(ent->name, "rss_proto_ipv6") == 0) { + int status = + parse_link_rss_proto_ipv6(param, ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + rss_proto_ipv6_present = 1; + continue; + } + + if (strcmp(ent->name, "rss_proto_l2") == 0) { + int status = parse_link_rss_proto_l2(param, ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + rss_proto_l2_present = 1; + continue; + } + if (strcmp(ent->name, "pci_bdf") == 0) { PARSE_ERROR_DUPLICATE((pci_bdf_present == 0), section_name, ent->name); @@ -1760,7 +1469,28 @@ parse_link(struct app_params *app, "this entry is mandatory (port_mask is not " "provided)"); - param->parsed = 1; + if (rss_proto_ipv4_present) + PARSE_ERROR_MESSAGE((rss_qs_present), + section_name, "rss_proto_ipv4", + "entry not allowed (rss_qs entry is not provided)"); + if (rss_proto_ipv6_present) + PARSE_ERROR_MESSAGE((rss_qs_present), + section_name, "rss_proto_ipv6", + "entry not allowed (rss_qs entry is not provided)"); + if (rss_proto_l2_present) + PARSE_ERROR_MESSAGE((rss_qs_present), + section_name, "rss_proto_l2", + "entry not allowed (rss_qs entry is not provided)"); + if (rss_proto_ipv4_present | + rss_proto_ipv6_present | + rss_proto_l2_present){ + if (rss_proto_ipv4_present == 0) + param->rss_proto_ipv4 = 0; + if (rss_proto_ipv6_present == 0) + param->rss_proto_ipv6 = 0; + if (rss_proto_l2_present == 0) + param->rss_proto_l2 = 0; + } free(entries); } @@ -1784,9 +1514,10 @@ parse_rxq(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->hwq_in_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_in_params, section_name); - param = &app->hwq_in_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); + + APP_PARAM_ADD_LINK_FOR_RXQ(app, section_name); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -1798,10 +1529,8 @@ parse_rxq(struct app_params *app, PARSE_ERROR((status == 0), section_name, ent->name); - idx = APP_PARAM_ADD(app->mempool_params, - ent->value); - PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, - section_name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); param->mempool_id = idx; continue; } @@ -1828,8 +1557,6 @@ parse_rxq(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -1852,9 +1579,10 @@ parse_txq(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->hwq_out_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_out_params, section_name); - param = &app->hwq_out_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); + + APP_PARAM_ADD_LINK_FOR_TXQ(app, section_name); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -1887,12 +1615,19 @@ parse_txq(struct app_params *app, continue; } + if (strcmp(ent->name, "n_retries") == 0) { + int status = parser_read_uint64(¶m->n_retries, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + /* unrecognized */ PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -1920,9 +1655,8 @@ parse_swq(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->swq_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->swq_params, section_name); - param = &app->swq_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2050,11 +1784,9 @@ parse_swq(struct app_params *app, PARSE_ERROR((status == 0), section_name, ent->name); - idx = APP_PARAM_ADD(app->mempool_params, - ent->value); - PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, - section_name); + idx = APP_PARAM_ADD(app->mempool_params, ent->value); param->mempool_direct_id = idx; + mempool_direct_present = 1; continue; } @@ -2066,11 +1798,10 @@ parse_swq(struct app_params *app, PARSE_ERROR((status == 0), section_name, ent->name); - idx = APP_PARAM_ADD(app->mempool_params, - ent->value); - PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, - section_name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); param->mempool_indirect_id = idx; + mempool_indirect_present = 1; continue; } @@ -2079,32 +1810,30 @@ parse_swq(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - APP_CHECK(((mtu_present) && + APP_CHECK(((mtu_present == 0) || ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), "Parse error in section \"%s\": IPv4/IPv6 fragmentation " "is off, therefore entry \"mtu\" is not allowed", section_name); - APP_CHECK(((metadata_size_present) && + APP_CHECK(((metadata_size_present == 0) || ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), "Parse error in section \"%s\": IPv4/IPv6 fragmentation " "is off, therefore entry \"metadata_size\" is " "not allowed", section_name); - APP_CHECK(((mempool_direct_present) && + APP_CHECK(((mempool_direct_present == 0) || ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), "Parse error in section \"%s\": IPv4/IPv6 fragmentation " "is off, therefore entry \"mempool_direct\" is " "not allowed", section_name); - APP_CHECK(((mempool_indirect_present) && + APP_CHECK(((mempool_indirect_present == 0) || ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), "Parse error in section \"%s\": IPv4/IPv6 fragmentation " "is off, therefore entry \"mempool_indirect\" is " "not allowed", section_name); - param->parsed = 1; - free(entries); } @@ -2127,9 +1856,10 @@ parse_tm(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->tm_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->tm_params, section_name); - param = &app->tm_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); + + APP_PARAM_ADD_LINK_FOR_TM(app, section_name); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2162,7 +1892,101 @@ parse_tm(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; + free(entries); +} + +static void +parse_kni(struct app_params *app, + const char *section_name, + struct rte_cfgfile *cfg) +{ + struct app_pktq_kni_params *param; + struct rte_cfgfile_entry *entries; + int n_entries, i; + ssize_t param_idx; + + n_entries = rte_cfgfile_section_num_entries(cfg, section_name); + PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); + + entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); + PARSE_ERROR_MALLOC(entries != NULL); + + rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); + + param_idx = APP_PARAM_ADD(app->kni_params, section_name); + param = &app->kni_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); + + APP_PARAM_ADD_LINK_FOR_KNI(app, section_name); + + for (i = 0; i < n_entries; i++) { + struct rte_cfgfile_entry *ent = &entries[i]; + + if (strcmp(ent->name, "core") == 0) { + int status = parse_pipeline_core( + ¶m->socket_id, + ¶m->core_id, + ¶m->hyper_th_id, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + param->force_bind = 1; + continue; + } + + if (strcmp(ent->name, "mempool") == 0) { + int status = validate_name(ent->value, + "MEMPOOL", 1); + ssize_t idx; + + PARSE_ERROR((status == 0), section_name, + ent->name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); + param->mempool_id = idx; + continue; + } + + if (strcmp(ent->name, "burst_read") == 0) { + int status = parser_read_uint32(¶m->burst_read, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "burst_write") == 0) { + int status = parser_read_uint32(¶m->burst_write, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "dropless") == 0) { + int status = parser_read_arg_bool(ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + param->dropless = status; + continue; + } + + if (strcmp(ent->name, "n_retries") == 0) { + int status = parser_read_uint64(¶m->n_retries, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); + } free(entries); } @@ -2188,9 +2012,8 @@ parse_source(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->source_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->source_params, section_name); - param = &app->source_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2202,10 +2025,8 @@ parse_source(struct app_params *app, PARSE_ERROR((status == 0), section_name, ent->name); - idx = APP_PARAM_ADD(app->mempool_params, - ent->value); - PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, - section_name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); param->mempool_id = idx; continue; } @@ -2219,7 +2040,7 @@ parse_source(struct app_params *app, continue; } - if (strcmp(ent->name, "pcap_file_rd")) { + if (strcmp(ent->name, "pcap_file_rd") == 0) { PARSE_ERROR_DUPLICATE((pcap_file_present == 0), section_name, ent->name); @@ -2251,8 +2072,6 @@ parse_source(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -2277,14 +2096,13 @@ parse_sink(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->sink_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->sink_params, section_name); - param = &app->sink_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - if (strcmp(ent->name, "pcap_file_wr")) { + if (strcmp(ent->name, "pcap_file_wr") == 0) { PARSE_ERROR_DUPLICATE((pcap_file_present == 0), section_name, ent->name); @@ -2295,7 +2113,7 @@ parse_sink(struct app_params *app, continue; } - if (strcmp(ent->name, "pcap_n_pkt_wr")) { + if (strcmp(ent->name, "pcap_n_pkt_wr") == 0) { int status; PARSE_ERROR_DUPLICATE((pcap_n_pkt_present == 0), @@ -2314,8 +2132,6 @@ parse_sink(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -2338,9 +2154,8 @@ parse_msgq_req_pipeline(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->msgq_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); - param = &app->msgq_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2358,7 +2173,6 @@ parse_msgq_req_pipeline(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; free(entries); } @@ -2381,9 +2195,8 @@ parse_msgq_rsp_pipeline(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->msgq_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); - param = &app->msgq_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2401,8 +2214,6 @@ parse_msgq_rsp_pipeline(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -2425,9 +2236,8 @@ parse_msgq(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->msgq_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); - param = &app->msgq_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2454,8 +2264,6 @@ parse_msgq(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -2478,6 +2286,7 @@ static const struct config_section cfg_file_scheme[] = { {"TXQ", 2, parse_txq}, {"SWQ", 1, parse_swq}, {"TM", 1, parse_tm}, + {"KNI", 1, parse_kni}, {"SOURCE", 1, parse_source}, {"SINK", 1, parse_sink}, {"MSGQ-REQ-PIPELINE", 1, parse_msgq_req_pipeline}, @@ -2488,10 +2297,7 @@ static const struct config_section cfg_file_scheme[] = { static void create_implicit_mempools(struct app_params *app) { - ssize_t idx; - - idx = APP_PARAM_ADD(app->mempool_params, "MEMPOOL0"); - PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, "start-up"); + APP_PARAM_ADD(app->mempool_params, "MEMPOOL0"); } static void @@ -2510,7 +2316,6 @@ create_implicit_links_from_port_mask(struct app_params *app, snprintf(name, sizeof(name), "LINK%" PRIu32, link_id); idx = APP_PARAM_ADD(app->link_params, name); - PARSER_PARAM_ADD_CHECK(idx, app->link_params, name); app->link_params[idx].pmd_id = pmd_id; link_id++; @@ -2525,6 +2330,11 @@ assign_link_pmd_id_from_pci_bdf(struct app_params *app) for (i = 0; i < app->n_links; i++) { struct app_link_params *link = &app->link_params[i]; + APP_CHECK((strlen(link->pci_bdf)), + "Parse error: %s pci_bdf is not configured " + "(port_mask is not provided)", + link->name); + link->pmd_id = i; } } @@ -2615,28 +2425,12 @@ app_config_parse(struct app_params *app, const char *file_name) APP_PARAM_COUNT(app->hwq_out_params, app->n_pktq_hwq_out); APP_PARAM_COUNT(app->swq_params, app->n_pktq_swq); APP_PARAM_COUNT(app->tm_params, app->n_pktq_tm); + APP_PARAM_COUNT(app->kni_params, app->n_pktq_kni); APP_PARAM_COUNT(app->source_params, app->n_pktq_source); APP_PARAM_COUNT(app->sink_params, app->n_pktq_sink); APP_PARAM_COUNT(app->msgq_params, app->n_msgq); APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines); -#ifdef RTE_PORT_PCAP - for (i = 0; i < (int)app->n_pktq_source; i++) { - struct app_pktq_source_params *p = &app->source_params[i]; - - APP_CHECK((p->file_name), "Parse error: missing " - "mandatory field \"pcap_file_rd\" for \"%s\"", - p->name); - } -#else - for (i = 0; i < (int)app->n_pktq_source; i++) { - struct app_pktq_source_params *p = &app->source_params[i]; - - APP_CHECK((!p->file_name), "Parse error: invalid field " - "\"pcap_file_rd\" for \"%s\"", p->name); - } -#endif - if (app->port_mask == 0) assign_link_pmd_id_from_pci_bdf(app); @@ -2803,6 +2597,84 @@ save_links_params(struct app_params *app, FILE *f) fprintf(f, "%s = %" PRIu32 "\n", "sctp_local_q", p->sctp_local_q); + if (p->n_rss_qs) { + uint32_t j; + + /* rss_qs */ + fprintf(f, "rss_qs = "); + for (j = 0; j < p->n_rss_qs; j++) + fprintf(f, "%" PRIu32 " ", p->rss_qs[j]); + fputc('\n', f); + + /* rss_proto_ipv4 */ + if (p->rss_proto_ipv4) { + fprintf(f, "rss_proto_ipv4 = "); + if (p->rss_proto_ipv4 & ETH_RSS_IPV4) + fprintf(f, "IP "); + if (p->rss_proto_ipv4 & ETH_RSS_FRAG_IPV4) + fprintf(f, "FRAG "); + if (p->rss_proto_ipv4 & + ETH_RSS_NONFRAG_IPV4_TCP) + fprintf(f, "TCP "); + if (p->rss_proto_ipv4 & + ETH_RSS_NONFRAG_IPV4_UDP) + fprintf(f, "UDP "); + if (p->rss_proto_ipv4 & + ETH_RSS_NONFRAG_IPV4_SCTP) + fprintf(f, "SCTP "); + if (p->rss_proto_ipv4 & + ETH_RSS_NONFRAG_IPV4_OTHER) + fprintf(f, "OTHER "); + fprintf(f, "\n"); + } else + fprintf(f, "; rss_proto_ipv4 = \n"); + + /* rss_proto_ipv6 */ + if (p->rss_proto_ipv6) { + fprintf(f, "rss_proto_ipv6 = "); + if (p->rss_proto_ipv6 & ETH_RSS_IPV6) + fprintf(f, "IP "); + if (p->rss_proto_ipv6 & ETH_RSS_FRAG_IPV6) + fprintf(f, "FRAG "); + if (p->rss_proto_ipv6 & + ETH_RSS_NONFRAG_IPV6_TCP) + fprintf(f, "TCP "); + if (p->rss_proto_ipv6 & + ETH_RSS_NONFRAG_IPV6_UDP) + fprintf(f, "UDP "); + if (p->rss_proto_ipv6 & + ETH_RSS_NONFRAG_IPV6_SCTP) + fprintf(f, "SCTP "); + if (p->rss_proto_ipv6 & + ETH_RSS_NONFRAG_IPV6_OTHER) + fprintf(f, "OTHER "); + if (p->rss_proto_ipv6 & ETH_RSS_IPV6_EX) + fprintf(f, "IP_EX "); + if (p->rss_proto_ipv6 & + ETH_RSS_IPV6_TCP_EX) + fprintf(f, "TCP_EX "); + if (p->rss_proto_ipv6 & + ETH_RSS_IPV6_UDP_EX) + fprintf(f, "UDP_EX "); + fprintf(f, "\n"); + } else + fprintf(f, "; rss_proto_ipv6 = \n"); + + /* rss_proto_l2 */ + if (p->rss_proto_l2) { + fprintf(f, "rss_proto_l2 = "); + if (p->rss_proto_l2 & ETH_RSS_L2_PAYLOAD) + fprintf(f, "L2 "); + fprintf(f, "\n"); + } else + fprintf(f, "; rss_proto_l2 = \n"); + } else { + fprintf(f, "; rss_qs = \n"); + fprintf(f, "; rss_proto_ipv4 = \n"); + fprintf(f, "; rss_proto_ipv6 = \n"); + fprintf(f, "; rss_proto_l2 = \n"); + } + if (strlen(p->pci_bdf)) fprintf(f, "%s = %s\n", "pci_bdf", p->pci_bdf); @@ -2851,6 +2723,7 @@ save_txq_params(struct app_params *app, FILE *f) fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no"); + fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries); fputc('\n', f); } @@ -2915,6 +2788,53 @@ save_tm_params(struct app_params *app, FILE *f) } } +static void +save_kni_params(struct app_params *app, FILE *f) +{ + struct app_pktq_kni_params *p; + size_t i, count; + + count = RTE_DIM(app->kni_params); + for (i = 0; i < count; i++) { + p = &app->kni_params[i]; + if (!APP_PARAM_VALID(p)) + continue; + + /* section name */ + fprintf(f, "[%s]\n", p->name); + + /* core */ + if (p->force_bind) { + fprintf(f, "; force_bind = 1\n"); + fprintf(f, "core = s%" PRIu32 "c%" PRIu32 "%s\n", + p->socket_id, + p->core_id, + (p->hyper_th_id) ? "h" : ""); + } else + fprintf(f, "; force_bind = 0\n"); + + /* mempool */ + fprintf(f, "%s = %s\n", "mempool", + app->mempool_params[p->mempool_id].name); + + /* burst_read */ + fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read); + + /* burst_write */ + fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write); + + /* dropless */ + fprintf(f, "%s = %s\n", + "dropless", + p->dropless ? "yes" : "no"); + + /* n_retries */ + fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries); + + fputc('\n', f); + } +} + static void save_source_params(struct app_params *app, FILE *f) { @@ -3022,6 +2942,9 @@ save_pipeline_params(struct app_params *app, FILE *f) case APP_PKTQ_IN_TM: name = app->tm_params[pp->id].name; break; + case APP_PKTQ_IN_KNI: + name = app->kni_params[pp->id].name; + break; case APP_PKTQ_IN_SOURCE: name = app->source_params[pp->id].name; break; @@ -3056,6 +2979,9 @@ save_pipeline_params(struct app_params *app, FILE *f) case APP_PKTQ_OUT_TM: name = app->tm_params[pp->id].name; break; + case APP_PKTQ_OUT_KNI: + name = app->kni_params[pp->id].name; + break; case APP_PKTQ_OUT_SINK: name = app->sink_params[pp->id].name; break; @@ -3141,6 +3067,7 @@ app_config_save(struct app_params *app, const char *file_name) save_txq_params(app, file); save_swq_params(app, file); save_tm_params(app, file); + save_kni_params(app, file); save_source_params(app, file); save_sink_params(app, file); save_msgq_params(app, file); @@ -3156,6 +3083,10 @@ app_config_init(struct app_params *app) memcpy(app, &app_params_default, sizeof(struct app_params)); + /* configure default_source_params */ + default_source_params.file_name = strdup("./config/packets.pcap"); + PARSE_ERROR_MALLOC(default_source_params.file_name != NULL); + for (i = 0; i < RTE_DIM(app->mempool_params); i++) memcpy(&app->mempool_params[i], &mempool_params_default, @@ -3186,6 +3117,11 @@ app_config_init(struct app_params *app) &default_tm_params, sizeof(default_tm_params)); + for (i = 0; i < RTE_DIM(app->kni_params); i++) + memcpy(&app->kni_params[i], + &default_kni_params, + sizeof(default_kni_params)); + for (i = 0; i < RTE_DIM(app->source_params); i++) memcpy(&app->source_params[i], &default_source_params,