app/testpmd: support GENEVE option item

The patch adds the GENEVE option rte flow item support to
command line interpreter. The flow command with GENEVE
option items looks like:

  flow create 0 ingress pattern eth / ipv4 / udp / geneve vni is 100 /
       geneve-opt class is 99 length is 1 type is 0 data is 0x669988 /
       end actions drop / end

The option length should be specified in 32-bit words, this
value specifies the length of the data pattern/mask arrays (should be
multiplied by sizeof(uint32_t) to be expressed in bytes. If match
on the length itself is not needed the mask should be set to zero, in
this case length is used to specify the pattern/mask array lengths only.

Signed-off-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
This commit is contained in:
Viacheslav Ovsiienko 2021-01-17 12:21:16 +02:00 committed by Ferruh Yigit
parent 2b4c72b4d1
commit 55c074f3ba
2 changed files with 102 additions and 6 deletions

View File

@ -283,6 +283,11 @@ enum index {
ITEM_ECPRI_MSG_IQ_DATA_PCID,
ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
ITEM_ECPRI_MSG_DLY_MSR_MSRID,
ITEM_GENEVE_OPT,
ITEM_GENEVE_OPT_CLASS,
ITEM_GENEVE_OPT_TYPE,
ITEM_GENEVE_OPT_LENGTH,
ITEM_GENEVE_OPT_DATA,
/* Validate/create actions. */
ACTIONS,
@ -413,6 +418,9 @@ enum index {
/** Maximum size for pattern in struct rte_flow_item_raw. */
#define ITEM_RAW_PATTERN_SIZE 40
/** Maximum size for GENEVE option data pattern in bytes. */
#define ITEM_GENEVE_OPT_DATA_SIZE 124
/** Storage size for struct rte_flow_item_raw including pattern. */
#define ITEM_RAW_SIZE \
(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
@ -428,7 +436,7 @@ struct action_rss_data {
};
/** Maximum data size in struct rte_flow_action_raw_encap. */
#define ACTION_RAW_ENCAP_MAX_DATA 128
#define ACTION_RAW_ENCAP_MAX_DATA 512
#define RAW_ENCAP_CONFS_MAX_NUM 8
/** Storage for struct rte_flow_action_raw_encap. */
@ -658,6 +666,16 @@ struct token {
.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
})
/** Static initializer for ARGS() to target a field with limits. */
#define ARGS_ENTRY_BOUNDED(s, f, i, a) \
(&(const struct arg){ \
.bounded = 1, \
.min = (i), \
.max = (a), \
.offset = offsetof(s, f), \
.size = sizeof(((s *)0)->f), \
})
/** Static initializer for ARGS() to target an arbitrary bit-mask. */
#define ARGS_ENTRY_MASK(s, f, m) \
(&(const struct arg){ \
@ -903,6 +921,7 @@ static const enum index next_item[] = {
ITEM_AH,
ITEM_PFCP,
ITEM_ECPRI,
ITEM_GENEVE_OPT,
END_SET,
ZERO,
};
@ -1244,6 +1263,15 @@ static const enum index item_ecpri_common_type[] = {
ZERO,
};
static const enum index item_geneve_opt[] = {
ITEM_GENEVE_OPT_CLASS,
ITEM_GENEVE_OPT_TYPE,
ITEM_GENEVE_OPT_LENGTH,
ITEM_GENEVE_OPT_DATA,
ITEM_NEXT,
ZERO,
};
static const enum index next_action[] = {
ACTION_END,
ACTION_VOID,
@ -3230,6 +3258,47 @@ static const struct token token_list[] = {
.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
hdr.type5.msr_id)),
},
[ITEM_GENEVE_OPT] = {
.name = "geneve-opt",
.help = "GENEVE header option",
.priv = PRIV_ITEM(GENEVE_OPT,
sizeof(struct rte_flow_item_geneve_opt) +
ITEM_GENEVE_OPT_DATA_SIZE),
.next = NEXT(item_geneve_opt),
.call = parse_vc,
},
[ITEM_GENEVE_OPT_CLASS] = {
.name = "class",
.help = "GENEVE option class",
.next = NEXT(item_geneve_opt, NEXT_ENTRY(UNSIGNED), item_param),
.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
option_class)),
},
[ITEM_GENEVE_OPT_TYPE] = {
.name = "type",
.help = "GENEVE option type",
.next = NEXT(item_geneve_opt, NEXT_ENTRY(UNSIGNED), item_param),
.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
option_type)),
},
[ITEM_GENEVE_OPT_LENGTH] = {
.name = "length",
.help = "GENEVE option data length (in 32b words)",
.next = NEXT(item_geneve_opt, NEXT_ENTRY(UNSIGNED), item_param),
.args = ARGS(ARGS_ENTRY_BOUNDED(
struct rte_flow_item_geneve_opt, option_len,
0, 31)),
},
[ITEM_GENEVE_OPT_DATA] = {
.name = "data",
.help = "GENEVE option data pattern",
.next = NEXT(item_geneve_opt, NEXT_ENTRY(HEX), item_param),
.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
ARGS_ENTRY_ARB(0, 0),
ARGS_ENTRY_ARB
(sizeof(struct rte_flow_item_geneve_opt),
ITEM_GENEVE_OPT_DATA_SIZE)),
},
/* Validate/create actions. */
[ACTIONS] = {
.name = "actions",
@ -6482,11 +6551,14 @@ parse_hex(struct context *ctx, const struct token *token,
ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
if (ret < 0)
goto error;
push_args(ctx, arg_len);
ret = parse_int(ctx, token, tmp, ret, NULL, 0);
if (ret < 0) {
pop_args(ctx);
goto error;
/* Save length if requested. */
if (arg_len->size) {
push_args(ctx, arg_len);
ret = parse_int(ctx, token, tmp, ret, NULL, 0);
if (ret < 0) {
pop_args(ctx);
goto error;
}
}
buf = (uint8_t *)ctx->object + arg_data->offset;
/* Output buffer is not necessarily NUL-terminated. */
@ -7486,6 +7558,9 @@ flow_item_default_mask(const struct rte_flow_item *item)
case RTE_FLOW_ITEM_TYPE_GENEVE:
mask = &rte_flow_item_geneve_mask;
break;
case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
mask = &rte_flow_item_geneve_opt_mask;
break;
case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
mask = &rte_flow_item_pppoe_proto_id_mask;
break;
@ -7600,6 +7675,7 @@ cmd_set_raw_parsed(const struct buffer *in)
data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
for (i = n - 1 ; i >= 0; --i) {
const struct rte_flow_item_gtp *gtp;
const struct rte_flow_item_geneve_opt *opt;
item = in->args.vc.pattern + i;
if (item->spec == NULL)
@ -7653,6 +7729,18 @@ cmd_set_raw_parsed(const struct buffer *in)
case RTE_FLOW_ITEM_TYPE_GENEVE:
size = sizeof(struct rte_geneve_hdr);
break;
case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
opt = (const struct rte_flow_item_geneve_opt *)
item->spec;
size = offsetof(struct rte_flow_item_geneve_opt, data);
if (opt->option_len && opt->data) {
*total_size += opt->option_len *
sizeof(uint32_t);
rte_memcpy(data_tail - (*total_size),
opt->data,
opt->option_len * sizeof(uint32_t));
}
break;
case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
size = sizeof(rte_be32_t);
proto = 0x73;

View File

@ -3680,6 +3680,14 @@ This section lists supported pattern items and their attributes, if any.
- ``vni {unsigned}``: virtual network identifier.
- ``protocol {unsigned}``: protocol type.
- ``geneve-opt``: match GENEVE header option.
- ``class {unsigned}``: GENEVE option class.
- ``type {unsigned}``: GENEVE option type.
- ``length {unsigned}``: GENEVE option length in 32-bit words.
- ``data {hex string}``: GENEVE option data, the length is defined by
``length`` field.
- ``vxlan-gpe``: match VXLAN-GPE header.
- ``vni {unsigned}``: VXLAN-GPE identifier.