ACTION_SAMPLE_INDEX_VALUE,
ACTION_SHARED,
SHARED_ACTION_ID2PTR,
+ ACTION_MODIFY_FIELD,
+ ACTION_MODIFY_FIELD_OP,
+ ACTION_MODIFY_FIELD_OP_VALUE,
+ ACTION_MODIFY_FIELD_DST_TYPE,
+ ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
+ ACTION_MODIFY_FIELD_DST_LEVEL,
+ ACTION_MODIFY_FIELD_DST_OFFSET,
+ ACTION_MODIFY_FIELD_SRC_TYPE,
+ ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
+ ACTION_MODIFY_FIELD_SRC_LEVEL,
+ ACTION_MODIFY_FIELD_SRC_OFFSET,
+ ACTION_MODIFY_FIELD_SRC_VALUE,
+ ACTION_MODIFY_FIELD_WIDTH,
};
/** Maximum size for pattern in struct rte_flow_item_raw. */
struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
+static const char *const modify_field_ops[] = {
+ "set", "add", "sub", NULL
+};
+
+static const char *const modify_field_ids[] = {
+ "start", "mac_dst", "mac_src",
+ "vlan_type", "vlan_id", "mac_type",
+ "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
+ "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
+ "tcp_port_src", "tcp_port_dst",
+ "tcp_seq_num", "tcp_ack_num", "tcp_flags",
+ "udp_port_src", "udp_port_dst",
+ "vxlan_vni", "geneve_vni", "gtp_teid",
+ "tag", "mark", "meta", "pointer", "value", NULL
+};
+
/** Maximum number of subsequent tokens and arguments on the stack. */
#define CTX_STACK_SIZE 16
ACTION_AGE,
ACTION_SAMPLE,
ACTION_SHARED,
+ ACTION_MODIFY_FIELD,
ZERO,
};
ZERO,
};
+static const enum index action_modify_field_dst[] = {
+ ACTION_MODIFY_FIELD_DST_LEVEL,
+ ACTION_MODIFY_FIELD_DST_OFFSET,
+ ACTION_MODIFY_FIELD_SRC_TYPE,
+ ZERO,
+};
+
+static const enum index action_modify_field_src[] = {
+ ACTION_MODIFY_FIELD_SRC_LEVEL,
+ ACTION_MODIFY_FIELD_SRC_OFFSET,
+ ACTION_MODIFY_FIELD_SRC_VALUE,
+ ACTION_MODIFY_FIELD_WIDTH,
+ ZERO,
+};
+
static int parse_set_raw_encap_decap(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
parse_vc_action_sample_index(struct context *ctx, const struct token *token,
const char *str, unsigned int len, void *buf,
unsigned int size);
+static int
+parse_vc_modify_field_op(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size);
+static int
+parse_vc_modify_field_id(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size);
static int parse_destroy(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
unsigned int, char *, unsigned int);
static int comp_set_sample_index(struct context *, const struct token *,
unsigned int, char *, unsigned int);
+static int comp_set_modify_field_op(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_set_modify_field_id(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
/** Token definitions. */
static const struct token token_list[] = {
.call = parse_vc_action_raw_decap_index,
.comp = comp_set_raw_index,
},
+ [ACTION_MODIFY_FIELD] = {
+ .name = "modify_field",
+ .help = "modify destination field with data from source field",
+ .priv = PRIV_ACTION(MODIFY_FIELD,
+ sizeof(struct rte_flow_action_modify_field)),
+ .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
+ .call = parse_vc,
+ },
+ [ACTION_MODIFY_FIELD_OP] = {
+ .name = "op",
+ .help = "operation type",
+ .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
+ NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_MODIFY_FIELD_OP_VALUE] = {
+ .name = "{operation}",
+ .help = "operation type value",
+ .call = parse_vc_modify_field_op,
+ .comp = comp_set_modify_field_op,
+ },
+ [ACTION_MODIFY_FIELD_DST_TYPE] = {
+ .name = "dst_type",
+ .help = "destination field type",
+ .next = NEXT(action_modify_field_dst,
+ NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
+ .name = "{dst_type}",
+ .help = "destination field type value",
+ .call = parse_vc_modify_field_id,
+ .comp = comp_set_modify_field_id,
+ },
+ [ACTION_MODIFY_FIELD_DST_LEVEL] = {
+ .name = "dst_level",
+ .help = "destination field level",
+ .next = NEXT(action_modify_field_dst, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+ dst.level)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_MODIFY_FIELD_DST_OFFSET] = {
+ .name = "dst_offset",
+ .help = "destination field bit offset",
+ .next = NEXT(action_modify_field_dst, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+ dst.offset)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_MODIFY_FIELD_SRC_TYPE] = {
+ .name = "src_type",
+ .help = "source field type",
+ .next = NEXT(action_modify_field_src,
+ NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
+ .name = "{src_type}",
+ .help = "source field type value",
+ .call = parse_vc_modify_field_id,
+ .comp = comp_set_modify_field_id,
+ },
+ [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
+ .name = "src_level",
+ .help = "source field level",
+ .next = NEXT(action_modify_field_src, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+ src.level)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
+ .name = "src_offset",
+ .help = "source field bit offset",
+ .next = NEXT(action_modify_field_src, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+ src.offset)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_MODIFY_FIELD_SRC_VALUE] = {
+ .name = "src_value",
+ .help = "source immediate value",
+ .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
+ NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+ src.value)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_MODIFY_FIELD_WIDTH] = {
+ .name = "width",
+ .help = "number of bits to copy",
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
+ NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+ width)),
+ .call = parse_vc_conf,
+ },
/* Top level command. */
[SET] = {
.name = "set",
return len;
}
+/** Parse operation for modify_field command. */
+static int
+parse_vc_modify_field_op(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct rte_flow_action_modify_field *action_modify_field;
+ unsigned int i;
+
+ (void)token;
+ (void)buf;
+ (void)size;
+ if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
+ return -1;
+ for (i = 0; modify_field_ops[i]; ++i)
+ if (!strcmp_partial(modify_field_ops[i], str, len))
+ break;
+ if (!modify_field_ops[i])
+ return -1;
+ if (!ctx->object)
+ return len;
+ action_modify_field = ctx->object;
+ action_modify_field->operation = (enum rte_flow_modify_op)i;
+ return len;
+}
+
+/** Parse id for modify_field command. */
+static int
+parse_vc_modify_field_id(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct rte_flow_action_modify_field *action_modify_field;
+ unsigned int i;
+
+ (void)token;
+ (void)buf;
+ (void)size;
+ if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
+ ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
+ return -1;
+ for (i = 0; modify_field_ids[i]; ++i)
+ if (!strcmp_partial(modify_field_ids[i], str, len))
+ break;
+ if (!modify_field_ids[i])
+ return -1;
+ if (!ctx->object)
+ return len;
+ action_modify_field = ctx->object;
+ if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
+ action_modify_field->dst.field = (enum rte_flow_field_id)i;
+ else
+ action_modify_field->src.field = (enum rte_flow_field_id)i;
+ return len;
+}
+
/** Parse tokens for destroy command. */
static int
parse_destroy(struct context *ctx, const struct token *token,
return nb;
}
+/** Complete operation for modify_field command. */
+static int
+comp_set_modify_field_op(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ uint16_t idx = 0;
+
+ RTE_SET_USED(ctx);
+ RTE_SET_USED(token);
+ for (idx = 0; modify_field_ops[idx]; ++idx)
+ ;
+ if (!buf)
+ return idx + 1;
+ if (ent < idx)
+ return strlcpy(buf, modify_field_ops[ent], size);
+ return -1;
+}
+
+/** Complete field id for modify_field command. */
+static int
+comp_set_modify_field_id(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ uint16_t idx = 0;
+
+ RTE_SET_USED(ctx);
+ RTE_SET_USED(token);
+ for (idx = 0; modify_field_ids[idx]; ++idx)
+ ;
+ if (!buf)
+ return idx + 1;
+ if (ent < idx)
+ return strlcpy(buf, modify_field_ids[ent], size);
+ return -1;
+}
+
/** Internal context. */
static struct context cmd_flow_context;