159f3a8acSGregory Etelson /* SPDX-License-Identifier: BSD-3-Clause
259f3a8acSGregory Etelson * Copyright (c) 2021 NVIDIA Corporation & Affiliates
359f3a8acSGregory Etelson */
459f3a8acSGregory Etelson
559f3a8acSGregory Etelson #include <stddef.h>
659f3a8acSGregory Etelson #include <stdint.h>
759f3a8acSGregory Etelson #include <stdio.h>
8*1bcb7ba9SDavid Marchand #include <stdlib.h>
959f3a8acSGregory Etelson #include <errno.h>
1059f3a8acSGregory Etelson #include <string.h>
1159f3a8acSGregory Etelson
1259f3a8acSGregory Etelson #include <rte_common.h>
1359f3a8acSGregory Etelson #include <rte_ethdev.h>
1459f3a8acSGregory Etelson #include <cmdline_parse.h>
1559f3a8acSGregory Etelson #include <cmdline_parse_string.h>
1659f3a8acSGregory Etelson #include <cmdline_parse_num.h>
1759f3a8acSGregory Etelson #include <rte_flow.h>
1859f3a8acSGregory Etelson
1959f3a8acSGregory Etelson #include "testpmd.h"
2059f3a8acSGregory Etelson
2159f3a8acSGregory Etelson struct flex_item *flex_items[RTE_MAX_ETHPORTS][FLEX_MAX_PARSERS_NUM];
2259f3a8acSGregory Etelson struct flex_pattern flex_patterns[FLEX_MAX_PATTERNS_NUM];
2359f3a8acSGregory Etelson
248bc3c062SGregory Etelson #ifdef RTE_HAS_JANSSON
258bc3c062SGregory Etelson
2659f3a8acSGregory Etelson static struct flex_item *
flex_parser_fetch(uint16_t port_id,uint16_t flex_id)2759f3a8acSGregory Etelson flex_parser_fetch(uint16_t port_id, uint16_t flex_id)
2859f3a8acSGregory Etelson {
2959f3a8acSGregory Etelson if (port_id >= RTE_MAX_ETHPORTS) {
3059f3a8acSGregory Etelson printf("Invalid port_id: %u\n", port_id);
3159f3a8acSGregory Etelson return FLEX_PARSER_ERR;
3259f3a8acSGregory Etelson }
3359f3a8acSGregory Etelson if (flex_id >= FLEX_MAX_PARSERS_NUM) {
3459f3a8acSGregory Etelson printf("Invalid flex item flex_id: %u\n", flex_id);
3559f3a8acSGregory Etelson return FLEX_PARSER_ERR;
3659f3a8acSGregory Etelson }
3759f3a8acSGregory Etelson return flex_items[port_id][flex_id];
3859f3a8acSGregory Etelson }
3959f3a8acSGregory Etelson
402d3d8401SGregory Etelson static __rte_always_inline bool
match_strkey(const char * key,const char * pattern)412d3d8401SGregory Etelson match_strkey(const char *key, const char *pattern)
4259f3a8acSGregory Etelson {
432d3d8401SGregory Etelson return strncmp(key, pattern, strlen(key)) == 0;
4459f3a8acSGregory Etelson }
4559f3a8acSGregory Etelson
4659f3a8acSGregory Etelson static int
flex_tunnel_parse(json_t * jtun,enum rte_flow_item_flex_tunnel_mode * tunnel)4759f3a8acSGregory Etelson flex_tunnel_parse(json_t *jtun, enum rte_flow_item_flex_tunnel_mode *tunnel)
4859f3a8acSGregory Etelson {
4959f3a8acSGregory Etelson int tun = -1;
5059f3a8acSGregory Etelson
5159f3a8acSGregory Etelson if (json_is_integer(jtun))
5259f3a8acSGregory Etelson tun = (int)json_integer_value(jtun);
5359f3a8acSGregory Etelson else if (json_is_real(jtun))
5459f3a8acSGregory Etelson tun = (int)json_real_value(jtun);
5559f3a8acSGregory Etelson else if (json_is_string(jtun)) {
5659f3a8acSGregory Etelson const char *mode = json_string_value(jtun);
5759f3a8acSGregory Etelson
5859f3a8acSGregory Etelson if (match_strkey(mode, "FLEX_TUNNEL_MODE_SINGLE"))
5959f3a8acSGregory Etelson tun = FLEX_TUNNEL_MODE_SINGLE;
6059f3a8acSGregory Etelson else if (match_strkey(mode, "FLEX_TUNNEL_MODE_OUTER"))
6159f3a8acSGregory Etelson tun = FLEX_TUNNEL_MODE_OUTER;
6259f3a8acSGregory Etelson else if (match_strkey(mode, "FLEX_TUNNEL_MODE_INNER"))
6359f3a8acSGregory Etelson tun = FLEX_TUNNEL_MODE_INNER;
6459f3a8acSGregory Etelson else if (match_strkey(mode, "FLEX_TUNNEL_MODE_MULTI"))
6559f3a8acSGregory Etelson tun = FLEX_TUNNEL_MODE_MULTI;
6659f3a8acSGregory Etelson else if (match_strkey(mode, "FLEX_TUNNEL_MODE_TUNNEL"))
6759f3a8acSGregory Etelson tun = FLEX_TUNNEL_MODE_TUNNEL;
6859f3a8acSGregory Etelson else
6959f3a8acSGregory Etelson return -EINVAL;
7059f3a8acSGregory Etelson } else
7159f3a8acSGregory Etelson return -EINVAL;
7259f3a8acSGregory Etelson *tunnel = (enum rte_flow_item_flex_tunnel_mode)tun;
7359f3a8acSGregory Etelson return 0;
7459f3a8acSGregory Etelson }
7559f3a8acSGregory Etelson
7659f3a8acSGregory Etelson static int
flex_field_parse(json_t * jfld,struct rte_flow_item_flex_field * fld)7759f3a8acSGregory Etelson flex_field_parse(json_t *jfld, struct rte_flow_item_flex_field *fld)
7859f3a8acSGregory Etelson {
7959f3a8acSGregory Etelson const char *key;
8059f3a8acSGregory Etelson json_t *je;
8159f3a8acSGregory Etelson
8259f3a8acSGregory Etelson #define FLEX_FIELD_GET(fm, t) \
8359f3a8acSGregory Etelson do { \
8459f3a8acSGregory Etelson if (!strncmp(key, # fm, strlen(# fm))) { \
8559f3a8acSGregory Etelson if (json_is_real(je)) \
8659f3a8acSGregory Etelson fld->fm = (t) json_real_value(je); \
8759f3a8acSGregory Etelson else if (json_is_integer(je)) \
8859f3a8acSGregory Etelson fld->fm = (t) json_integer_value(je); \
8959f3a8acSGregory Etelson else \
9059f3a8acSGregory Etelson return -EINVAL; \
9159f3a8acSGregory Etelson } \
9259f3a8acSGregory Etelson } while (0)
9359f3a8acSGregory Etelson
9459f3a8acSGregory Etelson json_object_foreach(jfld, key, je) {
9559f3a8acSGregory Etelson FLEX_FIELD_GET(field_size, uint32_t);
9659f3a8acSGregory Etelson FLEX_FIELD_GET(field_base, int32_t);
9759f3a8acSGregory Etelson FLEX_FIELD_GET(offset_base, uint32_t);
9859f3a8acSGregory Etelson FLEX_FIELD_GET(offset_mask, uint32_t);
9959f3a8acSGregory Etelson FLEX_FIELD_GET(offset_shift, int32_t);
10059f3a8acSGregory Etelson FLEX_FIELD_GET(field_id, uint16_t);
10159f3a8acSGregory Etelson if (match_strkey(key, "field_mode")) {
10259f3a8acSGregory Etelson const char *mode;
10359f3a8acSGregory Etelson if (!json_is_string(je))
10459f3a8acSGregory Etelson return -EINVAL;
10559f3a8acSGregory Etelson mode = json_string_value(je);
10659f3a8acSGregory Etelson if (match_strkey(mode, "FIELD_MODE_DUMMY"))
10759f3a8acSGregory Etelson fld->field_mode = FIELD_MODE_DUMMY;
10859f3a8acSGregory Etelson else if (match_strkey(mode, "FIELD_MODE_FIXED"))
10959f3a8acSGregory Etelson fld->field_mode = FIELD_MODE_FIXED;
11059f3a8acSGregory Etelson else if (match_strkey(mode, "FIELD_MODE_OFFSET"))
11159f3a8acSGregory Etelson fld->field_mode = FIELD_MODE_OFFSET;
11259f3a8acSGregory Etelson else if (match_strkey(mode, "FIELD_MODE_BITMASK"))
11359f3a8acSGregory Etelson fld->field_mode = FIELD_MODE_BITMASK;
11459f3a8acSGregory Etelson else
11559f3a8acSGregory Etelson return -EINVAL;
11659f3a8acSGregory Etelson }
11759f3a8acSGregory Etelson }
11859f3a8acSGregory Etelson return 0;
11959f3a8acSGregory Etelson }
12059f3a8acSGregory Etelson
12159f3a8acSGregory Etelson enum flex_link_type {
12259f3a8acSGregory Etelson FLEX_LINK_IN = 0,
12359f3a8acSGregory Etelson FLEX_LINK_OUT = 1
12459f3a8acSGregory Etelson };
12559f3a8acSGregory Etelson
12659f3a8acSGregory Etelson static int
flex_link_item_parse(const char * src,struct rte_flow_item * item)12759f3a8acSGregory Etelson flex_link_item_parse(const char *src, struct rte_flow_item *item)
12859f3a8acSGregory Etelson {
12959f3a8acSGregory Etelson #define FLEX_PARSE_DATA_SIZE 1024
13059f3a8acSGregory Etelson
13159f3a8acSGregory Etelson int ret;
13259f3a8acSGregory Etelson uint8_t *ptr, data[FLEX_PARSE_DATA_SIZE] = {0,};
13359f3a8acSGregory Etelson char flow_rule[256];
13459f3a8acSGregory Etelson struct rte_flow_attr *attr;
13559f3a8acSGregory Etelson struct rte_flow_item *pattern;
13659f3a8acSGregory Etelson struct rte_flow_action *actions;
13759f3a8acSGregory Etelson
138fc547a92SGregory Etelson sprintf(flow_rule,
139fc547a92SGregory Etelson "flow create 0 pattern %s / end actions drop / end", src);
14059f3a8acSGregory Etelson src = flow_rule;
14159f3a8acSGregory Etelson ret = flow_parse(src, (void *)data, sizeof(data),
14259f3a8acSGregory Etelson &attr, &pattern, &actions);
14359f3a8acSGregory Etelson if (ret)
14459f3a8acSGregory Etelson return ret;
14559f3a8acSGregory Etelson item->type = pattern->type;
14659f3a8acSGregory Etelson if (pattern->spec) {
14759f3a8acSGregory Etelson ptr = (void *)(uintptr_t)item->spec;
14859f3a8acSGregory Etelson memcpy(ptr, pattern->spec, FLEX_MAX_FLOW_PATTERN_LENGTH);
14959f3a8acSGregory Etelson } else {
15059f3a8acSGregory Etelson item->spec = NULL;
15159f3a8acSGregory Etelson }
15259f3a8acSGregory Etelson if (pattern->mask) {
15359f3a8acSGregory Etelson ptr = (void *)(uintptr_t)item->mask;
15459f3a8acSGregory Etelson memcpy(ptr, pattern->mask, FLEX_MAX_FLOW_PATTERN_LENGTH);
15559f3a8acSGregory Etelson } else {
15659f3a8acSGregory Etelson item->mask = NULL;
15759f3a8acSGregory Etelson }
15859f3a8acSGregory Etelson if (pattern->last) {
15959f3a8acSGregory Etelson ptr = (void *)(uintptr_t)item->last;
16059f3a8acSGregory Etelson memcpy(ptr, pattern->last, FLEX_MAX_FLOW_PATTERN_LENGTH);
16159f3a8acSGregory Etelson } else {
16259f3a8acSGregory Etelson item->last = NULL;
16359f3a8acSGregory Etelson }
16459f3a8acSGregory Etelson return 0;
16559f3a8acSGregory Etelson }
16659f3a8acSGregory Etelson
16759f3a8acSGregory Etelson static int
flex_link_parse(json_t * jobj,struct rte_flow_item_flex_link * link,enum flex_link_type link_type)16859f3a8acSGregory Etelson flex_link_parse(json_t *jobj, struct rte_flow_item_flex_link *link,
16959f3a8acSGregory Etelson enum flex_link_type link_type)
17059f3a8acSGregory Etelson {
17159f3a8acSGregory Etelson const char *key;
17259f3a8acSGregory Etelson json_t *je;
17359f3a8acSGregory Etelson int ret;
17459f3a8acSGregory Etelson json_object_foreach(jobj, key, je) {
17559f3a8acSGregory Etelson if (match_strkey(key, "item")) {
17659f3a8acSGregory Etelson if (!json_is_string(je))
17759f3a8acSGregory Etelson return -EINVAL;
17859f3a8acSGregory Etelson ret = flex_link_item_parse(json_string_value(je),
17959f3a8acSGregory Etelson &link->item);
18059f3a8acSGregory Etelson if (ret)
18159f3a8acSGregory Etelson return -EINVAL;
18259f3a8acSGregory Etelson if (link_type == FLEX_LINK_IN) {
18359f3a8acSGregory Etelson if (!link->item.spec || !link->item.mask)
18459f3a8acSGregory Etelson return -EINVAL;
18559f3a8acSGregory Etelson if (link->item.last)
18659f3a8acSGregory Etelson return -EINVAL;
18759f3a8acSGregory Etelson }
18859f3a8acSGregory Etelson }
18959f3a8acSGregory Etelson if (match_strkey(key, "next")) {
19059f3a8acSGregory Etelson if (json_is_integer(je))
19159f3a8acSGregory Etelson link->next = (typeof(link->next))
19259f3a8acSGregory Etelson json_integer_value(je);
19359f3a8acSGregory Etelson else if (json_is_real(je))
19459f3a8acSGregory Etelson link->next = (typeof(link->next))
19559f3a8acSGregory Etelson json_real_value(je);
19659f3a8acSGregory Etelson else
19759f3a8acSGregory Etelson return -EINVAL;
19859f3a8acSGregory Etelson }
19959f3a8acSGregory Etelson }
20059f3a8acSGregory Etelson return 0;
20159f3a8acSGregory Etelson }
20259f3a8acSGregory Etelson
flex_item_config(json_t * jroot,struct rte_flow_item_flex_conf * flex_conf)20359f3a8acSGregory Etelson static int flex_item_config(json_t *jroot,
20459f3a8acSGregory Etelson struct rte_flow_item_flex_conf *flex_conf)
20559f3a8acSGregory Etelson {
20659f3a8acSGregory Etelson const char *key;
20759f3a8acSGregory Etelson json_t *jobj = NULL;
20859f3a8acSGregory Etelson int ret = 0;
20959f3a8acSGregory Etelson
21059f3a8acSGregory Etelson json_object_foreach(jroot, key, jobj) {
21159f3a8acSGregory Etelson if (match_strkey(key, "tunnel")) {
21259f3a8acSGregory Etelson ret = flex_tunnel_parse(jobj, &flex_conf->tunnel);
21359f3a8acSGregory Etelson if (ret) {
21459f3a8acSGregory Etelson printf("Can't parse tunnel value\n");
21559f3a8acSGregory Etelson goto out;
21659f3a8acSGregory Etelson }
21759f3a8acSGregory Etelson } else if (match_strkey(key, "next_header")) {
21859f3a8acSGregory Etelson ret = flex_field_parse(jobj, &flex_conf->next_header);
21959f3a8acSGregory Etelson if (ret) {
22059f3a8acSGregory Etelson printf("Can't parse next_header field\n");
22159f3a8acSGregory Etelson goto out;
22259f3a8acSGregory Etelson }
22359f3a8acSGregory Etelson } else if (match_strkey(key, "next_protocol")) {
22459f3a8acSGregory Etelson ret = flex_field_parse(jobj,
22559f3a8acSGregory Etelson &flex_conf->next_protocol);
22659f3a8acSGregory Etelson if (ret) {
22759f3a8acSGregory Etelson printf("Can't parse next_protocol field\n");
22859f3a8acSGregory Etelson goto out;
22959f3a8acSGregory Etelson }
23059f3a8acSGregory Etelson } else if (match_strkey(key, "sample_data")) {
23159f3a8acSGregory Etelson json_t *ji;
23259f3a8acSGregory Etelson uint32_t i, size = json_array_size(jobj);
23359f3a8acSGregory Etelson for (i = 0; i < size; i++) {
23459f3a8acSGregory Etelson ji = json_array_get(jobj, i);
23559f3a8acSGregory Etelson ret = flex_field_parse
23659f3a8acSGregory Etelson (ji, flex_conf->sample_data + i);
23759f3a8acSGregory Etelson if (ret) {
23859f3a8acSGregory Etelson printf("Can't parse sample_data field(s)\n");
23959f3a8acSGregory Etelson goto out;
24059f3a8acSGregory Etelson }
24159f3a8acSGregory Etelson }
24259f3a8acSGregory Etelson flex_conf->nb_samples = size;
24359f3a8acSGregory Etelson } else if (match_strkey(key, "input_link")) {
24459f3a8acSGregory Etelson json_t *ji;
24559f3a8acSGregory Etelson uint32_t i, size = json_array_size(jobj);
24659f3a8acSGregory Etelson for (i = 0; i < size; i++) {
24759f3a8acSGregory Etelson ji = json_array_get(jobj, i);
24859f3a8acSGregory Etelson ret = flex_link_parse(ji,
24959f3a8acSGregory Etelson flex_conf->input_link + i,
25059f3a8acSGregory Etelson FLEX_LINK_IN);
25159f3a8acSGregory Etelson if (ret) {
25259f3a8acSGregory Etelson printf("Can't parse input_link(s)\n");
25359f3a8acSGregory Etelson goto out;
25459f3a8acSGregory Etelson }
25559f3a8acSGregory Etelson }
25659f3a8acSGregory Etelson flex_conf->nb_inputs = size;
25759f3a8acSGregory Etelson } else if (match_strkey(key, "output_link")) {
25859f3a8acSGregory Etelson json_t *ji;
25959f3a8acSGregory Etelson uint32_t i, size = json_array_size(jobj);
26059f3a8acSGregory Etelson for (i = 0; i < size; i++) {
26159f3a8acSGregory Etelson ji = json_array_get(jobj, i);
26259f3a8acSGregory Etelson ret = flex_link_parse
26359f3a8acSGregory Etelson (ji, flex_conf->output_link + i,
26459f3a8acSGregory Etelson FLEX_LINK_OUT);
26559f3a8acSGregory Etelson if (ret) {
26659f3a8acSGregory Etelson printf("Can't parse output_link(s)\n");
26759f3a8acSGregory Etelson goto out;
26859f3a8acSGregory Etelson }
26959f3a8acSGregory Etelson }
27059f3a8acSGregory Etelson flex_conf->nb_outputs = size;
27159f3a8acSGregory Etelson }
27259f3a8acSGregory Etelson }
27359f3a8acSGregory Etelson out:
27459f3a8acSGregory Etelson return ret;
27559f3a8acSGregory Etelson }
27659f3a8acSGregory Etelson
27759f3a8acSGregory Etelson static struct flex_item *
flex_item_init(void)27859f3a8acSGregory Etelson flex_item_init(void)
27959f3a8acSGregory Etelson {
28059f3a8acSGregory Etelson size_t base_size, samples_size, links_size, spec_size;
28159f3a8acSGregory Etelson struct rte_flow_item_flex_conf *conf;
28259f3a8acSGregory Etelson struct flex_item *fp;
28359f3a8acSGregory Etelson uint8_t (*pattern)[FLEX_MAX_FLOW_PATTERN_LENGTH];
28459f3a8acSGregory Etelson int i;
28559f3a8acSGregory Etelson
28659f3a8acSGregory Etelson base_size = RTE_ALIGN(sizeof(*conf), sizeof(uintptr_t));
28759f3a8acSGregory Etelson samples_size = RTE_ALIGN(FLEX_ITEM_MAX_SAMPLES_NUM *
28859f3a8acSGregory Etelson sizeof(conf->sample_data[0]),
28959f3a8acSGregory Etelson sizeof(uintptr_t));
29059f3a8acSGregory Etelson links_size = RTE_ALIGN(FLEX_ITEM_MAX_LINKS_NUM *
29159f3a8acSGregory Etelson sizeof(conf->input_link[0]),
29259f3a8acSGregory Etelson sizeof(uintptr_t));
29359f3a8acSGregory Etelson /* spec & mask for all input links */
29459f3a8acSGregory Etelson spec_size = 2 * FLEX_MAX_FLOW_PATTERN_LENGTH * FLEX_ITEM_MAX_LINKS_NUM;
29559f3a8acSGregory Etelson fp = calloc(1, base_size + samples_size + 2 * links_size + spec_size);
29659f3a8acSGregory Etelson if (fp == NULL) {
29759f3a8acSGregory Etelson printf("Can't allocate memory for flex item\n");
29859f3a8acSGregory Etelson return NULL;
29959f3a8acSGregory Etelson }
30059f3a8acSGregory Etelson conf = &fp->flex_conf;
30159f3a8acSGregory Etelson conf->sample_data = (typeof(conf->sample_data))
30259f3a8acSGregory Etelson ((uint8_t *)fp + base_size);
30359f3a8acSGregory Etelson conf->input_link = (typeof(conf->input_link))
30459f3a8acSGregory Etelson ((uint8_t *)conf->sample_data + samples_size);
30559f3a8acSGregory Etelson conf->output_link = (typeof(conf->output_link))
30659f3a8acSGregory Etelson ((uint8_t *)conf->input_link + links_size);
30759f3a8acSGregory Etelson pattern = (typeof(pattern))((uint8_t *)conf->output_link + links_size);
30859f3a8acSGregory Etelson for (i = 0; i < FLEX_ITEM_MAX_LINKS_NUM; i++) {
30959f3a8acSGregory Etelson struct rte_flow_item_flex_link *in = conf->input_link + i;
31059f3a8acSGregory Etelson in->item.spec = pattern++;
31159f3a8acSGregory Etelson in->item.mask = pattern++;
31259f3a8acSGregory Etelson }
31359f3a8acSGregory Etelson return fp;
31459f3a8acSGregory Etelson }
31559f3a8acSGregory Etelson
31659f3a8acSGregory Etelson static int
flex_item_build_config(struct flex_item * fp,const char * filename)31759f3a8acSGregory Etelson flex_item_build_config(struct flex_item *fp, const char *filename)
31859f3a8acSGregory Etelson {
31959f3a8acSGregory Etelson int ret;
32059f3a8acSGregory Etelson json_error_t json_error;
32159f3a8acSGregory Etelson json_t *jroot = json_load_file(filename, 0, &json_error);
32259f3a8acSGregory Etelson
32359f3a8acSGregory Etelson if (!jroot) {
32459f3a8acSGregory Etelson printf("Bad JSON file \"%s\": %s\n", filename, json_error.text);
32559f3a8acSGregory Etelson return -1;
32659f3a8acSGregory Etelson }
32759f3a8acSGregory Etelson ret = flex_item_config(jroot, &fp->flex_conf);
32859f3a8acSGregory Etelson json_decref(jroot);
32959f3a8acSGregory Etelson return ret;
33059f3a8acSGregory Etelson }
33159f3a8acSGregory Etelson
33259f3a8acSGregory Etelson void
flex_item_create(portid_t port_id,uint16_t flex_id,const char * filename)33359f3a8acSGregory Etelson flex_item_create(portid_t port_id, uint16_t flex_id, const char *filename)
33459f3a8acSGregory Etelson {
33559f3a8acSGregory Etelson struct rte_flow_error flow_error;
33659f3a8acSGregory Etelson struct flex_item *fp = flex_parser_fetch(port_id, flex_id);
33759f3a8acSGregory Etelson int ret;
33859f3a8acSGregory Etelson
33959f3a8acSGregory Etelson if (fp == FLEX_PARSER_ERR) {
34059f3a8acSGregory Etelson printf("Bad parameters: port_id=%u flex_id=%u\n",
34159f3a8acSGregory Etelson port_id, flex_id);
34259f3a8acSGregory Etelson return;
34359f3a8acSGregory Etelson }
34459f3a8acSGregory Etelson if (fp) {
34559f3a8acSGregory Etelson printf("port-%u: flex item #%u is already in use\n",
34659f3a8acSGregory Etelson port_id, flex_id);
34759f3a8acSGregory Etelson return;
34859f3a8acSGregory Etelson }
34959f3a8acSGregory Etelson fp = flex_item_init();
35059f3a8acSGregory Etelson if (!fp) {
35159f3a8acSGregory Etelson printf("Could not allocate flex item\n");
35259f3a8acSGregory Etelson goto out;
35359f3a8acSGregory Etelson }
35459f3a8acSGregory Etelson ret = flex_item_build_config(fp, filename);
35559f3a8acSGregory Etelson if (ret)
35659f3a8acSGregory Etelson goto out;
35759f3a8acSGregory Etelson fp->flex_handle = rte_flow_flex_item_create(port_id,
35859f3a8acSGregory Etelson &fp->flex_conf,
35959f3a8acSGregory Etelson &flow_error);
36059f3a8acSGregory Etelson if (fp->flex_handle) {
36159f3a8acSGregory Etelson flex_items[port_id][flex_id] = fp;
36259f3a8acSGregory Etelson printf("port-%u: created flex item #%u\n", port_id, flex_id);
36359f3a8acSGregory Etelson fp = NULL;
36459f3a8acSGregory Etelson } else {
36559f3a8acSGregory Etelson printf("port-%u: flex item #%u creation failed: %s\n",
36659f3a8acSGregory Etelson port_id, flex_id,
36759f3a8acSGregory Etelson flow_error.message ? flow_error.message : "");
36859f3a8acSGregory Etelson }
36959f3a8acSGregory Etelson out:
37059f3a8acSGregory Etelson free(fp);
37159f3a8acSGregory Etelson }
37259f3a8acSGregory Etelson
37359f3a8acSGregory Etelson void
flex_item_destroy(portid_t port_id,uint16_t flex_id)3742d3d8401SGregory Etelson flex_item_destroy(portid_t port_id, uint16_t flex_id)
3752d3d8401SGregory Etelson {
3762d3d8401SGregory Etelson int ret;
3772d3d8401SGregory Etelson struct rte_flow_error error;
3782d3d8401SGregory Etelson struct flex_item *fp = flex_parser_fetch(port_id, flex_id);
3792d3d8401SGregory Etelson if (fp == FLEX_PARSER_ERR) {
3802d3d8401SGregory Etelson printf("Bad parameters: port_id=%u flex_id=%u\n",
3812d3d8401SGregory Etelson port_id, flex_id);
3822d3d8401SGregory Etelson return;
3832d3d8401SGregory Etelson }
3842d3d8401SGregory Etelson if (!fp)
3852d3d8401SGregory Etelson return;
3862d3d8401SGregory Etelson ret = rte_flow_flex_item_release(port_id, fp->flex_handle, &error);
3872d3d8401SGregory Etelson if (!ret) {
3882d3d8401SGregory Etelson free(fp);
3892d3d8401SGregory Etelson flex_items[port_id][flex_id] = NULL;
3902d3d8401SGregory Etelson printf("port-%u: released flex item #%u\n",
3912d3d8401SGregory Etelson port_id, flex_id);
3922d3d8401SGregory Etelson
3932d3d8401SGregory Etelson } else {
3942d3d8401SGregory Etelson printf("port-%u: cannot release flex item #%u: %s\n",
3952d3d8401SGregory Etelson port_id, flex_id, error.message);
3962d3d8401SGregory Etelson }
3972d3d8401SGregory Etelson }
3982d3d8401SGregory Etelson
3998bc3c062SGregory Etelson #else /* RTE_HAS_JANSSON */
flex_item_create(__rte_unused portid_t port_id,__rte_unused uint16_t flex_id,__rte_unused const char * filename)4008bc3c062SGregory Etelson void flex_item_create(__rte_unused portid_t port_id,
4018bc3c062SGregory Etelson __rte_unused uint16_t flex_id,
4028bc3c062SGregory Etelson __rte_unused const char *filename)
4038bc3c062SGregory Etelson {
4048bc3c062SGregory Etelson printf("cannot create flex item - no JSON library configured\n");
4058bc3c062SGregory Etelson }
4068bc3c062SGregory Etelson
4078bc3c062SGregory Etelson void
flex_item_destroy(__rte_unused portid_t port_id,__rte_unused uint16_t flex_id)4088bc3c062SGregory Etelson flex_item_destroy(__rte_unused portid_t port_id, __rte_unused uint16_t flex_id)
4098bc3c062SGregory Etelson {
4108bc3c062SGregory Etelson
4118bc3c062SGregory Etelson }
4128bc3c062SGregory Etelson
4138bc3c062SGregory Etelson #endif /* RTE_HAS_JANSSON */
4148bc3c062SGregory Etelson
4152d3d8401SGregory Etelson void
port_flex_item_flush(portid_t port_id)41659f3a8acSGregory Etelson port_flex_item_flush(portid_t port_id)
41759f3a8acSGregory Etelson {
41859f3a8acSGregory Etelson uint16_t i;
41959f3a8acSGregory Etelson
42059f3a8acSGregory Etelson for (i = 0; i < FLEX_MAX_PARSERS_NUM; i++) {
4212d3d8401SGregory Etelson if (flex_items[port_id][i] != NULL) {
42259f3a8acSGregory Etelson flex_item_destroy(port_id, i);
42359f3a8acSGregory Etelson flex_items[port_id][i] = NULL;
42459f3a8acSGregory Etelson }
42559f3a8acSGregory Etelson }
4262d3d8401SGregory Etelson }
42759f3a8acSGregory Etelson
42859f3a8acSGregory Etelson struct flex_pattern_set {
42959f3a8acSGregory Etelson cmdline_fixed_string_t set, flex_pattern;
43059f3a8acSGregory Etelson cmdline_fixed_string_t is_spec, mask;
43159f3a8acSGregory Etelson cmdline_fixed_string_t spec_data, mask_data;
43259f3a8acSGregory Etelson uint16_t id;
43359f3a8acSGregory Etelson };
43459f3a8acSGregory Etelson
43559f3a8acSGregory Etelson static cmdline_parse_token_string_t flex_pattern_set_token =
43659f3a8acSGregory Etelson TOKEN_STRING_INITIALIZER(struct flex_pattern_set, set, "set");
43759f3a8acSGregory Etelson static cmdline_parse_token_string_t flex_pattern_token =
43859f3a8acSGregory Etelson TOKEN_STRING_INITIALIZER(struct flex_pattern_set,
43959f3a8acSGregory Etelson flex_pattern, "flex_pattern");
44059f3a8acSGregory Etelson static cmdline_parse_token_string_t flex_pattern_is_token =
44159f3a8acSGregory Etelson TOKEN_STRING_INITIALIZER(struct flex_pattern_set,
44259f3a8acSGregory Etelson is_spec, "is");
44359f3a8acSGregory Etelson static cmdline_parse_token_string_t flex_pattern_spec_token =
44459f3a8acSGregory Etelson TOKEN_STRING_INITIALIZER(struct flex_pattern_set,
44559f3a8acSGregory Etelson is_spec, "spec");
44659f3a8acSGregory Etelson static cmdline_parse_token_string_t flex_pattern_mask_token =
44759f3a8acSGregory Etelson TOKEN_STRING_INITIALIZER(struct flex_pattern_set, mask, "mask");
44859f3a8acSGregory Etelson static cmdline_parse_token_string_t flex_pattern_spec_data_token =
44959f3a8acSGregory Etelson TOKEN_STRING_INITIALIZER(struct flex_pattern_set, spec_data, NULL);
45059f3a8acSGregory Etelson static cmdline_parse_token_string_t flex_pattern_mask_data_token =
45159f3a8acSGregory Etelson TOKEN_STRING_INITIALIZER(struct flex_pattern_set, mask_data, NULL);
45259f3a8acSGregory Etelson static cmdline_parse_token_num_t flex_pattern_id_token =
45359f3a8acSGregory Etelson TOKEN_NUM_INITIALIZER(struct flex_pattern_set, id, RTE_UINT16);
45459f3a8acSGregory Etelson
45559f3a8acSGregory Etelson /*
45659f3a8acSGregory Etelson * flex pattern data - spec or mask is a string representation of byte array
45759f3a8acSGregory Etelson * in hexadecimal format. Each byte in data string must have 2 characters:
45859f3a8acSGregory Etelson * 0x15 - "15"
45959f3a8acSGregory Etelson * 0x1 - "01"
46059f3a8acSGregory Etelson * Bytes in data array are in network order.
46159f3a8acSGregory Etelson */
46259f3a8acSGregory Etelson static uint32_t
flex_pattern_data(const char * str,uint8_t * data)46359f3a8acSGregory Etelson flex_pattern_data(const char *str, uint8_t *data)
46459f3a8acSGregory Etelson {
46559f3a8acSGregory Etelson uint32_t i, len = strlen(str);
46659f3a8acSGregory Etelson char b[3], *endptr;
46759f3a8acSGregory Etelson
46859f3a8acSGregory Etelson if (len & 01)
46959f3a8acSGregory Etelson return 0;
47059f3a8acSGregory Etelson len /= 2;
47159f3a8acSGregory Etelson if (len >= FLEX_MAX_FLOW_PATTERN_LENGTH)
47259f3a8acSGregory Etelson return 0;
47359f3a8acSGregory Etelson for (i = 0, b[2] = '\0'; i < len; i++) {
47459f3a8acSGregory Etelson b[0] = str[2 * i];
47559f3a8acSGregory Etelson b[1] = str[2 * i + 1];
47659f3a8acSGregory Etelson data[i] = strtoul(b, &endptr, 16);
47759f3a8acSGregory Etelson if (endptr != &b[2])
47859f3a8acSGregory Etelson return 0;
47959f3a8acSGregory Etelson }
48059f3a8acSGregory Etelson return len;
48159f3a8acSGregory Etelson }
48259f3a8acSGregory Etelson
48359f3a8acSGregory Etelson static void
flex_pattern_parsed_fn(void * parsed_result,__rte_unused struct cmdline * cl,__rte_unused void * data)48459f3a8acSGregory Etelson flex_pattern_parsed_fn(void *parsed_result,
48559f3a8acSGregory Etelson __rte_unused struct cmdline *cl,
48659f3a8acSGregory Etelson __rte_unused void *data)
48759f3a8acSGregory Etelson {
48859f3a8acSGregory Etelson struct flex_pattern_set *res = parsed_result;
48959f3a8acSGregory Etelson struct flex_pattern *fp;
49059f3a8acSGregory Etelson bool full_spec;
49159f3a8acSGregory Etelson
49259f3a8acSGregory Etelson if (res->id >= FLEX_MAX_PATTERNS_NUM) {
49359f3a8acSGregory Etelson printf("Bad flex pattern id\n");
49459f3a8acSGregory Etelson return;
49559f3a8acSGregory Etelson }
49659f3a8acSGregory Etelson fp = flex_patterns + res->id;
49759f3a8acSGregory Etelson memset(fp->spec_pattern, 0, sizeof(fp->spec_pattern));
49859f3a8acSGregory Etelson memset(fp->mask_pattern, 0, sizeof(fp->mask_pattern));
49959f3a8acSGregory Etelson fp->spec.length = flex_pattern_data(res->spec_data, fp->spec_pattern);
50059f3a8acSGregory Etelson if (!fp->spec.length) {
50159f3a8acSGregory Etelson printf("Bad flex pattern spec\n");
50259f3a8acSGregory Etelson return;
50359f3a8acSGregory Etelson }
50459f3a8acSGregory Etelson full_spec = strncmp(res->is_spec, "spec", strlen("spec")) == 0;
50559f3a8acSGregory Etelson if (full_spec) {
50659f3a8acSGregory Etelson fp->mask.length = flex_pattern_data(res->mask_data,
50759f3a8acSGregory Etelson fp->mask_pattern);
50859f3a8acSGregory Etelson if (!fp->mask.length) {
50959f3a8acSGregory Etelson printf("Bad flex pattern mask\n");
51059f3a8acSGregory Etelson return;
51159f3a8acSGregory Etelson }
51259f3a8acSGregory Etelson } else {
51359f3a8acSGregory Etelson memset(fp->mask_pattern, 0xFF, fp->spec.length);
51459f3a8acSGregory Etelson fp->mask.length = fp->spec.length;
51559f3a8acSGregory Etelson }
51659f3a8acSGregory Etelson if (fp->mask.length != fp->spec.length) {
51759f3a8acSGregory Etelson printf("Spec length do not match mask length\n");
51859f3a8acSGregory Etelson return;
51959f3a8acSGregory Etelson }
52059f3a8acSGregory Etelson fp->spec.pattern = fp->spec_pattern;
52159f3a8acSGregory Etelson fp->mask.pattern = fp->mask_pattern;
52259f3a8acSGregory Etelson printf("created pattern #%u\n", res->id);
52359f3a8acSGregory Etelson }
52459f3a8acSGregory Etelson
52559f3a8acSGregory Etelson cmdline_parse_inst_t cmd_set_flex_is_pattern = {
52659f3a8acSGregory Etelson .f = flex_pattern_parsed_fn,
52759f3a8acSGregory Etelson .data = NULL,
52859f3a8acSGregory Etelson .help_str = "set flex_pattern <id> is <spec_data>",
52959f3a8acSGregory Etelson .tokens = {
53059f3a8acSGregory Etelson (void *)&flex_pattern_set_token,
53159f3a8acSGregory Etelson (void *)&flex_pattern_token,
53259f3a8acSGregory Etelson (void *)&flex_pattern_id_token,
53359f3a8acSGregory Etelson (void *)&flex_pattern_is_token,
53459f3a8acSGregory Etelson (void *)&flex_pattern_spec_data_token,
53559f3a8acSGregory Etelson NULL,
53659f3a8acSGregory Etelson }
53759f3a8acSGregory Etelson };
53859f3a8acSGregory Etelson
53959f3a8acSGregory Etelson cmdline_parse_inst_t cmd_set_flex_spec_pattern = {
54059f3a8acSGregory Etelson .f = flex_pattern_parsed_fn,
54159f3a8acSGregory Etelson .data = NULL,
54259f3a8acSGregory Etelson .help_str = "set flex_pattern <id> spec <spec_data> mask <mask_data>",
54359f3a8acSGregory Etelson .tokens = {
54459f3a8acSGregory Etelson (void *)&flex_pattern_set_token,
54559f3a8acSGregory Etelson (void *)&flex_pattern_token,
54659f3a8acSGregory Etelson (void *)&flex_pattern_id_token,
54759f3a8acSGregory Etelson (void *)&flex_pattern_spec_token,
54859f3a8acSGregory Etelson (void *)&flex_pattern_spec_data_token,
54959f3a8acSGregory Etelson (void *)&flex_pattern_mask_token,
55059f3a8acSGregory Etelson (void *)&flex_pattern_mask_data_token,
55159f3a8acSGregory Etelson NULL,
55259f3a8acSGregory Etelson }
55359f3a8acSGregory Etelson };
554