+parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct action_raw_decap_data *action_raw_decap_data;
+ struct rte_flow_action *action;
+ const struct arg *arg;
+ struct buffer *out = buf;
+ int ret;
+ uint16_t idx;
+
+ RTE_SET_USED(token);
+ RTE_SET_USED(buf);
+ RTE_SET_USED(size);
+ arg = ARGS_ENTRY_ARB_BOUNDED
+ (offsetof(struct action_raw_decap_data, idx),
+ sizeof(((struct action_raw_decap_data *)0)->idx),
+ 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
+ if (push_args(ctx, arg))
+ return -1;
+ ret = parse_int(ctx, token, str, len, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ return -1;
+ }
+ if (!ctx->object)
+ return len;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ action_raw_decap_data = ctx->object;
+ idx = action_raw_decap_data->idx;
+ action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
+ action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
+ action->conf = &action_raw_decap_data->conf;
+ return len;
+}
+
+
+static int
+parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct action_raw_encap_data *action_raw_encap_data;
+ struct rte_flow_action *action;
+ const struct arg *arg;
+ struct buffer *out = buf;
+ int ret;
+ uint16_t idx;
+
+ RTE_SET_USED(token);
+ RTE_SET_USED(buf);
+ RTE_SET_USED(size);
+ if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
+ return -1;
+ arg = ARGS_ENTRY_ARB_BOUNDED
+ (offsetof(struct action_raw_encap_data, idx),
+ sizeof(((struct action_raw_encap_data *)0)->idx),
+ 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
+ if (push_args(ctx, arg))
+ return -1;
+ ret = parse_int(ctx, token, str, len, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ return -1;
+ }
+ if (!ctx->object)
+ return len;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ action_raw_encap_data = ctx->object;
+ idx = action_raw_encap_data->idx;
+ action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
+ action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
+ action_raw_encap_data->conf.preserve = NULL;
+ action->conf = &action_raw_encap_data->conf;
+ return len;
+}
+
+static int
+parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_raw_encap_data *action_raw_encap_data = NULL;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_raw_encap_data = ctx->object;
+ action_raw_encap_data->conf.data = raw_encap_confs[0].data;
+ action_raw_encap_data->conf.preserve = NULL;
+ action_raw_encap_data->conf.size = raw_encap_confs[0].size;
+ action->conf = &action_raw_encap_data->conf;
+ return ret;
+}
+
+static int
+parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_raw_decap_data *action_raw_decap_data = NULL;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_raw_decap_data = ctx->object;
+ action_raw_decap_data->conf.data = raw_decap_confs[0].data;
+ action_raw_decap_data->conf.size = raw_decap_confs[0].size;
+ action->conf = &action_raw_decap_data->conf;
+ return ret;
+}
+
+static int
+parse_vc_action_set_meta(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ ret = rte_flow_dynf_metadata_register();
+ if (ret < 0)
+ return -1;
+ return len;
+}
+
+static int
+parse_vc_action_sample(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_sample_data *action_sample_data = NULL;
+ static struct rte_flow_action end_action = {
+ RTE_FLOW_ACTION_TYPE_END, 0
+ };
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_sample_data = ctx->object;
+ action_sample_data->conf.actions = &end_action;
+ action->conf = &action_sample_data->conf;
+ return ret;
+}
+
+static int
+parse_vc_action_sample_index(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct action_sample_data *action_sample_data;
+ struct rte_flow_action *action;
+ const struct arg *arg;
+ struct buffer *out = buf;
+ int ret;
+ uint16_t idx;
+
+ RTE_SET_USED(token);
+ RTE_SET_USED(buf);
+ RTE_SET_USED(size);
+ if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
+ return -1;
+ arg = ARGS_ENTRY_ARB_BOUNDED
+ (offsetof(struct action_sample_data, idx),
+ sizeof(((struct action_sample_data *)0)->idx),
+ 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
+ if (push_args(ctx, arg))
+ return -1;
+ ret = parse_int(ctx, token, str, len, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ return -1;
+ }
+ if (!ctx->object)
+ return len;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ action_sample_data = ctx->object;
+ idx = action_sample_data->idx;
+ action_sample_data->conf.actions = raw_sample_confs[idx].data;
+ action->conf = &action_sample_data->conf;
+ 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 the conntrack update, not a rte_flow_action. */
+static int
+parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_modify_conntrack *ct_modify = NULL;
+
+ (void)size;
+ if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
+ ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
+ return -1;
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
+ if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
+ ct_modify->new_ct.is_original_dir =
+ conntrack_context.is_original_dir;
+ ct_modify->direction = 1;
+ } else {
+ uint32_t old_dir;
+
+ old_dir = ct_modify->new_ct.is_original_dir;
+ memcpy(&ct_modify->new_ct, &conntrack_context,
+ sizeof(conntrack_context));
+ ct_modify->new_ct.is_original_dir = old_dir;
+ ct_modify->state = 1;
+ }
+ return len;
+}
+
+/** Parse tokens for destroy command. */
+static int
+parse_destroy(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != DESTROY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.destroy.rule =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
+ sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse tokens for flush command. */
+static int
+parse_flush(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != FLUSH)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse tokens for dump command. */
+static int
+parse_dump(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != DUMP)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ }
+ switch (ctx->curr) {
+ case DUMP_ALL:
+ case DUMP_ONE:
+ out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ default:
+ return -1;
+ }
+}
+
+/** Parse tokens for query command. */
+static int
+parse_query(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != QUERY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse action names. */
+static int
+parse_action(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ const struct arg *arg = pop_args(ctx);
+ unsigned int i;
+
+ (void)size;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ /* Parse action name. */
+ for (i = 0; next_action[i]; ++i) {
+ const struct parse_action_priv *priv;
+
+ token = &token_list[next_action[i]];
+ if (strcmp_partial(token->name, str, len))
+ continue;
+ priv = token->priv;
+ if (!priv)
+ goto error;
+ if (out)
+ memcpy((uint8_t *)ctx->object + arg->offset,
+ &priv->type,
+ arg->size);
+ return len;
+ }
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/** Parse tokens for list command. */
+static int
+parse_list(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != LIST)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.list.group =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
+ sizeof(*out->args.list.group)) > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = out->args.list.group + out->args.list.group_n++;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse tokens for list all aged flows command. */
+static int
+parse_aged(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != AGED)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ if (ctx->curr == AGED_DESTROY)
+ out->args.aged.destroy = 1;
+ return len;
+}
+
+/** Parse tokens for isolate command. */
+static int
+parse_isolate(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != ISOLATE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse tokens for info/configure command. */
+static int
+parse_configure(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != INFO && ctx->curr != CONFIGURE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse tokens for template create command. */
+static int
+parse_template(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != PATTERN_TEMPLATE &&
+ ctx->curr != ACTIONS_TEMPLATE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.vc.data = (uint8_t *)out + size;
+ return len;
+ }
+ switch (ctx->curr) {
+ case PATTERN_TEMPLATE_CREATE:
+ out->args.vc.pattern =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ out->args.vc.pat_templ_id = UINT32_MAX;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ case PATTERN_TEMPLATE_EGRESS:
+ out->args.vc.attr.egress = 1;
+ return len;
+ case PATTERN_TEMPLATE_INGRESS:
+ out->args.vc.attr.ingress = 1;
+ return len;
+ case PATTERN_TEMPLATE_TRANSFER:
+ out->args.vc.attr.transfer = 1;
+ return len;
+ case ACTIONS_TEMPLATE_CREATE:
+ out->args.vc.act_templ_id = UINT32_MAX;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ case ACTIONS_TEMPLATE_SPEC:
+ out->args.vc.actions =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ ctx->object = out->args.vc.actions;
+ ctx->objmask = NULL;
+ return len;
+ case ACTIONS_TEMPLATE_MASK:
+ out->args.vc.masks =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)
+ (out->args.vc.actions +
+ out->args.vc.actions_n),
+ sizeof(double));
+ ctx->object = out->args.vc.masks;
+ ctx->objmask = NULL;
+ return len;
+ case ACTIONS_TEMPLATE_EGRESS:
+ out->args.vc.attr.egress = 1;
+ return len;
+ case ACTIONS_TEMPLATE_INGRESS:
+ out->args.vc.attr.ingress = 1;
+ return len;
+ case ACTIONS_TEMPLATE_TRANSFER:
+ out->args.vc.attr.transfer = 1;
+ return len;
+ default:
+ return -1;
+ }
+}
+
+/** Parse tokens for template destroy command. */
+static int
+parse_template_destroy(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ uint32_t *template_id;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command ||
+ out->command == PATTERN_TEMPLATE ||
+ out->command == ACTIONS_TEMPLATE) {
+ if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
+ ctx->curr != ACTIONS_TEMPLATE_DESTROY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.templ_destroy.template_id =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ template_id = out->args.templ_destroy.template_id
+ + out->args.templ_destroy.template_id_n++;
+ if ((uint8_t *)template_id > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = template_id;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse tokens for table create command. */
+static int
+parse_table(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ uint32_t *template_id;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != TABLE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ }
+ switch (ctx->curr) {
+ case TABLE_CREATE:
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.table.id = UINT32_MAX;
+ return len;
+ case TABLE_PATTERN_TEMPLATE:
+ out->args.table.pat_templ_id =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ template_id = out->args.table.pat_templ_id
+ + out->args.table.pat_templ_id_n++;
+ if ((uint8_t *)template_id > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = template_id;
+ ctx->objmask = NULL;
+ return len;
+ case TABLE_ACTIONS_TEMPLATE:
+ out->args.table.act_templ_id =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)
+ (out->args.table.pat_templ_id +
+ out->args.table.pat_templ_id_n),
+ sizeof(double));
+ template_id = out->args.table.act_templ_id
+ + out->args.table.act_templ_id_n++;
+ if ((uint8_t *)template_id > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = template_id;
+ ctx->objmask = NULL;
+ return len;
+ case TABLE_INGRESS:
+ out->args.table.attr.flow_attr.ingress = 1;
+ return len;
+ case TABLE_EGRESS:
+ out->args.table.attr.flow_attr.egress = 1;
+ return len;
+ case TABLE_TRANSFER:
+ out->args.table.attr.flow_attr.transfer = 1;
+ return len;
+ default:
+ return -1;
+ }
+}
+
+/** Parse tokens for table destroy command. */
+static int
+parse_table_destroy(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)