1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2021 NVIDIA Corporation & Affiliates
11 #include <rte_common.h>
12 #include <rte_ethdev.h>
13 #include <cmdline_parse.h>
14 #include <cmdline_parse_string.h>
15 #include <cmdline_parse_num.h>
20 struct flex_item *flex_items[RTE_MAX_ETHPORTS][FLEX_MAX_PARSERS_NUM];
21 struct flex_pattern flex_patterns[FLEX_MAX_PATTERNS_NUM];
23 #ifdef RTE_HAS_JANSSON
24 static __rte_always_inline bool
25 match_strkey(const char *key, const char *pattern)
27 return strncmp(key, pattern, strlen(key)) == 0;
30 static struct flex_item *
31 flex_parser_fetch(uint16_t port_id, uint16_t flex_id)
33 if (port_id >= RTE_MAX_ETHPORTS) {
34 printf("Invalid port_id: %u\n", port_id);
35 return FLEX_PARSER_ERR;
37 if (flex_id >= FLEX_MAX_PARSERS_NUM) {
38 printf("Invalid flex item flex_id: %u\n", flex_id);
39 return FLEX_PARSER_ERR;
41 return flex_items[port_id][flex_id];
45 flex_item_destroy(portid_t port_id, uint16_t flex_id)
48 struct rte_flow_error error;
49 struct flex_item *fp = flex_parser_fetch(port_id, flex_id);
50 if (fp == FLEX_PARSER_ERR) {
51 printf("Bad parameters: port_id=%u flex_id=%u\n",
57 ret = rte_flow_flex_item_release(port_id, fp->flex_handle, &error);
60 flex_items[port_id][flex_id] = NULL;
61 printf("port-%u: released flex item #%u\n",
65 printf("port-%u: cannot release flex item #%u: %s\n",
66 port_id, flex_id, error.message);
71 flex_tunnel_parse(json_t *jtun, enum rte_flow_item_flex_tunnel_mode *tunnel)
75 if (json_is_integer(jtun))
76 tun = (int)json_integer_value(jtun);
77 else if (json_is_real(jtun))
78 tun = (int)json_real_value(jtun);
79 else if (json_is_string(jtun)) {
80 const char *mode = json_string_value(jtun);
82 if (match_strkey(mode, "FLEX_TUNNEL_MODE_SINGLE"))
83 tun = FLEX_TUNNEL_MODE_SINGLE;
84 else if (match_strkey(mode, "FLEX_TUNNEL_MODE_OUTER"))
85 tun = FLEX_TUNNEL_MODE_OUTER;
86 else if (match_strkey(mode, "FLEX_TUNNEL_MODE_INNER"))
87 tun = FLEX_TUNNEL_MODE_INNER;
88 else if (match_strkey(mode, "FLEX_TUNNEL_MODE_MULTI"))
89 tun = FLEX_TUNNEL_MODE_MULTI;
90 else if (match_strkey(mode, "FLEX_TUNNEL_MODE_TUNNEL"))
91 tun = FLEX_TUNNEL_MODE_TUNNEL;
96 *tunnel = (enum rte_flow_item_flex_tunnel_mode)tun;
101 flex_field_parse(json_t *jfld, struct rte_flow_item_flex_field *fld)
106 #define FLEX_FIELD_GET(fm, t) \
108 if (!strncmp(key, # fm, strlen(# fm))) { \
109 if (json_is_real(je)) \
110 fld->fm = (t) json_real_value(je); \
111 else if (json_is_integer(je)) \
112 fld->fm = (t) json_integer_value(je); \
118 json_object_foreach(jfld, key, je) {
119 FLEX_FIELD_GET(field_size, uint32_t);
120 FLEX_FIELD_GET(field_base, int32_t);
121 FLEX_FIELD_GET(offset_base, uint32_t);
122 FLEX_FIELD_GET(offset_mask, uint32_t);
123 FLEX_FIELD_GET(offset_shift, int32_t);
124 FLEX_FIELD_GET(field_id, uint16_t);
125 if (match_strkey(key, "field_mode")) {
127 if (!json_is_string(je))
129 mode = json_string_value(je);
130 if (match_strkey(mode, "FIELD_MODE_DUMMY"))
131 fld->field_mode = FIELD_MODE_DUMMY;
132 else if (match_strkey(mode, "FIELD_MODE_FIXED"))
133 fld->field_mode = FIELD_MODE_FIXED;
134 else if (match_strkey(mode, "FIELD_MODE_OFFSET"))
135 fld->field_mode = FIELD_MODE_OFFSET;
136 else if (match_strkey(mode, "FIELD_MODE_BITMASK"))
137 fld->field_mode = FIELD_MODE_BITMASK;
145 enum flex_link_type {
151 flex_link_item_parse(const char *src, struct rte_flow_item *item)
153 #define FLEX_PARSE_DATA_SIZE 1024
156 uint8_t *ptr, data[FLEX_PARSE_DATA_SIZE] = {0,};
158 struct rte_flow_attr *attr;
159 struct rte_flow_item *pattern;
160 struct rte_flow_action *actions;
162 sprintf(flow_rule, "flow create 0 pattern %s / end", src);
164 ret = flow_parse(src, (void *)data, sizeof(data),
165 &attr, &pattern, &actions);
168 item->type = pattern->type;
170 ptr = (void *)(uintptr_t)item->spec;
171 memcpy(ptr, pattern->spec, FLEX_MAX_FLOW_PATTERN_LENGTH);
176 ptr = (void *)(uintptr_t)item->mask;
177 memcpy(ptr, pattern->mask, FLEX_MAX_FLOW_PATTERN_LENGTH);
182 ptr = (void *)(uintptr_t)item->last;
183 memcpy(ptr, pattern->last, FLEX_MAX_FLOW_PATTERN_LENGTH);
191 flex_link_parse(json_t *jobj, struct rte_flow_item_flex_link *link,
192 enum flex_link_type link_type)
197 json_object_foreach(jobj, key, je) {
198 if (match_strkey(key, "item")) {
199 if (!json_is_string(je))
201 ret = flex_link_item_parse(json_string_value(je),
205 if (link_type == FLEX_LINK_IN) {
206 if (!link->item.spec || !link->item.mask)
212 if (match_strkey(key, "next")) {
213 if (json_is_integer(je))
214 link->next = (typeof(link->next))
215 json_integer_value(je);
216 else if (json_is_real(je))
217 link->next = (typeof(link->next))
226 static int flex_item_config(json_t *jroot,
227 struct rte_flow_item_flex_conf *flex_conf)
233 json_object_foreach(jroot, key, jobj) {
234 if (match_strkey(key, "tunnel")) {
235 ret = flex_tunnel_parse(jobj, &flex_conf->tunnel);
237 printf("Can't parse tunnel value\n");
240 } else if (match_strkey(key, "next_header")) {
241 ret = flex_field_parse(jobj, &flex_conf->next_header);
243 printf("Can't parse next_header field\n");
246 } else if (match_strkey(key, "next_protocol")) {
247 ret = flex_field_parse(jobj,
248 &flex_conf->next_protocol);
250 printf("Can't parse next_protocol field\n");
253 } else if (match_strkey(key, "sample_data")) {
255 uint32_t i, size = json_array_size(jobj);
256 for (i = 0; i < size; i++) {
257 ji = json_array_get(jobj, i);
258 ret = flex_field_parse
259 (ji, flex_conf->sample_data + i);
261 printf("Can't parse sample_data field(s)\n");
265 flex_conf->nb_samples = size;
266 } else if (match_strkey(key, "input_link")) {
268 uint32_t i, size = json_array_size(jobj);
269 for (i = 0; i < size; i++) {
270 ji = json_array_get(jobj, i);
271 ret = flex_link_parse(ji,
272 flex_conf->input_link + i,
275 printf("Can't parse input_link(s)\n");
279 flex_conf->nb_inputs = size;
280 } else if (match_strkey(key, "output_link")) {
282 uint32_t i, size = json_array_size(jobj);
283 for (i = 0; i < size; i++) {
284 ji = json_array_get(jobj, i);
285 ret = flex_link_parse
286 (ji, flex_conf->output_link + i,
289 printf("Can't parse output_link(s)\n");
293 flex_conf->nb_outputs = size;
300 static struct flex_item *
303 size_t base_size, samples_size, links_size, spec_size;
304 struct rte_flow_item_flex_conf *conf;
305 struct flex_item *fp;
306 uint8_t (*pattern)[FLEX_MAX_FLOW_PATTERN_LENGTH];
309 base_size = RTE_ALIGN(sizeof(*conf), sizeof(uintptr_t));
310 samples_size = RTE_ALIGN(FLEX_ITEM_MAX_SAMPLES_NUM *
311 sizeof(conf->sample_data[0]),
313 links_size = RTE_ALIGN(FLEX_ITEM_MAX_LINKS_NUM *
314 sizeof(conf->input_link[0]),
316 /* spec & mask for all input links */
317 spec_size = 2 * FLEX_MAX_FLOW_PATTERN_LENGTH * FLEX_ITEM_MAX_LINKS_NUM;
318 fp = calloc(1, base_size + samples_size + 2 * links_size + spec_size);
320 printf("Can't allocate memory for flex item\n");
323 conf = &fp->flex_conf;
324 conf->sample_data = (typeof(conf->sample_data))
325 ((uint8_t *)fp + base_size);
326 conf->input_link = (typeof(conf->input_link))
327 ((uint8_t *)conf->sample_data + samples_size);
328 conf->output_link = (typeof(conf->output_link))
329 ((uint8_t *)conf->input_link + links_size);
330 pattern = (typeof(pattern))((uint8_t *)conf->output_link + links_size);
331 for (i = 0; i < FLEX_ITEM_MAX_LINKS_NUM; i++) {
332 struct rte_flow_item_flex_link *in = conf->input_link + i;
333 in->item.spec = pattern++;
334 in->item.mask = pattern++;
340 flex_item_build_config(struct flex_item *fp, const char *filename)
343 json_error_t json_error;
344 json_t *jroot = json_load_file(filename, 0, &json_error);
347 printf("Bad JSON file \"%s\": %s\n", filename, json_error.text);
350 ret = flex_item_config(jroot, &fp->flex_conf);
356 flex_item_create(portid_t port_id, uint16_t flex_id, const char *filename)
358 struct rte_flow_error flow_error;
359 struct flex_item *fp = flex_parser_fetch(port_id, flex_id);
362 if (fp == FLEX_PARSER_ERR) {
363 printf("Bad parameters: port_id=%u flex_id=%u\n",
368 printf("port-%u: flex item #%u is already in use\n",
372 fp = flex_item_init();
374 printf("Could not allocate flex item\n");
377 ret = flex_item_build_config(fp, filename);
380 fp->flex_handle = rte_flow_flex_item_create(port_id,
383 if (fp->flex_handle) {
384 flex_items[port_id][flex_id] = fp;
385 printf("port-%u: created flex item #%u\n", port_id, flex_id);
388 printf("port-%u: flex item #%u creation failed: %s\n",
390 flow_error.message ? flow_error.message : "");
397 #else /* RTE_HAS_JANSSON */
398 void flex_item_create(__rte_unused portid_t port_id,
399 __rte_unused uint16_t flex_id,
400 __rte_unused const char *filename)
402 printf("no JSON library\n");
405 void flex_item_destroy(__rte_unused portid_t port_id,
406 __rte_unused uint16_t flex_id)
408 printf("no JSON library\n");
410 #endif /* RTE_HAS_JANSSON */
413 port_flex_item_flush(portid_t port_id)
417 for (i = 0; i < FLEX_MAX_PARSERS_NUM; i++) {
418 flex_item_destroy(port_id, i);
419 flex_items[port_id][i] = NULL;
423 struct flex_pattern_set {
424 cmdline_fixed_string_t set, flex_pattern;
425 cmdline_fixed_string_t is_spec, mask;
426 cmdline_fixed_string_t spec_data, mask_data;
430 static cmdline_parse_token_string_t flex_pattern_set_token =
431 TOKEN_STRING_INITIALIZER(struct flex_pattern_set, set, "set");
432 static cmdline_parse_token_string_t flex_pattern_token =
433 TOKEN_STRING_INITIALIZER(struct flex_pattern_set,
434 flex_pattern, "flex_pattern");
435 static cmdline_parse_token_string_t flex_pattern_is_token =
436 TOKEN_STRING_INITIALIZER(struct flex_pattern_set,
438 static cmdline_parse_token_string_t flex_pattern_spec_token =
439 TOKEN_STRING_INITIALIZER(struct flex_pattern_set,
441 static cmdline_parse_token_string_t flex_pattern_mask_token =
442 TOKEN_STRING_INITIALIZER(struct flex_pattern_set, mask, "mask");
443 static cmdline_parse_token_string_t flex_pattern_spec_data_token =
444 TOKEN_STRING_INITIALIZER(struct flex_pattern_set, spec_data, NULL);
445 static cmdline_parse_token_string_t flex_pattern_mask_data_token =
446 TOKEN_STRING_INITIALIZER(struct flex_pattern_set, mask_data, NULL);
447 static cmdline_parse_token_num_t flex_pattern_id_token =
448 TOKEN_NUM_INITIALIZER(struct flex_pattern_set, id, RTE_UINT16);
451 * flex pattern data - spec or mask is a string representation of byte array
452 * in hexadecimal format. Each byte in data string must have 2 characters:
455 * Bytes in data array are in network order.
458 flex_pattern_data(const char *str, uint8_t *data)
460 uint32_t i, len = strlen(str);
466 if (len >= FLEX_MAX_FLOW_PATTERN_LENGTH)
468 for (i = 0, b[2] = '\0'; i < len; i++) {
470 b[1] = str[2 * i + 1];
471 data[i] = strtoul(b, &endptr, 16);
479 flex_pattern_parsed_fn(void *parsed_result,
480 __rte_unused struct cmdline *cl,
481 __rte_unused void *data)
483 struct flex_pattern_set *res = parsed_result;
484 struct flex_pattern *fp;
487 if (res->id >= FLEX_MAX_PATTERNS_NUM) {
488 printf("Bad flex pattern id\n");
491 fp = flex_patterns + res->id;
492 memset(fp->spec_pattern, 0, sizeof(fp->spec_pattern));
493 memset(fp->mask_pattern, 0, sizeof(fp->mask_pattern));
494 fp->spec.length = flex_pattern_data(res->spec_data, fp->spec_pattern);
495 if (!fp->spec.length) {
496 printf("Bad flex pattern spec\n");
499 full_spec = strncmp(res->is_spec, "spec", strlen("spec")) == 0;
501 fp->mask.length = flex_pattern_data(res->mask_data,
503 if (!fp->mask.length) {
504 printf("Bad flex pattern mask\n");
508 memset(fp->mask_pattern, 0xFF, fp->spec.length);
509 fp->mask.length = fp->spec.length;
511 if (fp->mask.length != fp->spec.length) {
512 printf("Spec length do not match mask length\n");
515 fp->spec.pattern = fp->spec_pattern;
516 fp->mask.pattern = fp->mask_pattern;
517 printf("created pattern #%u\n", res->id);
520 cmdline_parse_inst_t cmd_set_flex_is_pattern = {
521 .f = flex_pattern_parsed_fn,
523 .help_str = "set flex_pattern <id> is <spec_data>",
525 (void *)&flex_pattern_set_token,
526 (void *)&flex_pattern_token,
527 (void *)&flex_pattern_id_token,
528 (void *)&flex_pattern_is_token,
529 (void *)&flex_pattern_spec_data_token,
534 cmdline_parse_inst_t cmd_set_flex_spec_pattern = {
535 .f = flex_pattern_parsed_fn,
537 .help_str = "set flex_pattern <id> spec <spec_data> mask <mask_data>",
539 (void *)&flex_pattern_set_token,
540 (void *)&flex_pattern_token,
541 (void *)&flex_pattern_id_token,
542 (void *)&flex_pattern_spec_token,
543 (void *)&flex_pattern_spec_data_token,
544 (void *)&flex_pattern_mask_token,
545 (void *)&flex_pattern_mask_data_token,