/* Validate/create pattern. */
PATTERN,
+ ITEM_PARAM_IS,
+ ITEM_PARAM_SPEC,
+ ITEM_PARAM_LAST,
+ ITEM_PARAM_MASK,
ITEM_NEXT,
ITEM_END,
ITEM_VOID,
uint16_t port; /**< Current port ID (for completions). */
uint32_t objdata; /**< Object-specific data. */
void *object; /**< Address of current object for relative offsets. */
+ void *objmask; /**< Object a full mask must be written to. */
};
/** Token argument. */
ZERO,
};
+__rte_unused
+static const enum index item_param[] = {
+ ITEM_PARAM_IS,
+ ITEM_PARAM_SPEC,
+ ITEM_PARAM_LAST,
+ ITEM_PARAM_MASK,
+ ZERO,
+};
+
static const enum index next_item[] = {
ITEM_END,
ITEM_VOID,
static int parse_vc(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
+static int parse_vc_spec(struct context *, const struct token *,
+ const char *, unsigned int, void *, unsigned int);
static int parse_destroy(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
.next = NEXT(next_item),
.call = parse_vc,
},
+ [ITEM_PARAM_IS] = {
+ .name = "is",
+ .help = "match value perfectly (with full bit-mask)",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_SPEC] = {
+ .name = "spec",
+ .help = "match value according to configured bit-mask",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_LAST] = {
+ .name = "last",
+ .help = "specify upper bound to establish a range",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_MASK] = {
+ .name = "mask",
+ .help = "specify bit-mask with relevant bits set to one",
+ .call = parse_vc_spec,
+ },
[ITEM_NEXT] = {
.name = "/",
.help = "specify next pattern item",
memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
ctx->objdata = 0;
ctx->object = out;
+ ctx->objmask = NULL;
return len;
}
out->command = ctx->curr;
ctx->objdata = 0;
ctx->object = out;
+ ctx->objmask = NULL;
out->args.vc.data = (uint8_t *)out + size;
return len;
}
ctx->objdata = 0;
ctx->object = &out->args.vc.attr;
+ ctx->objmask = NULL;
switch (ctx->curr) {
case GROUP:
case PRIORITY:
(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
sizeof(double));
ctx->object = out->args.vc.pattern;
+ ctx->objmask = NULL;
return len;
case ACTIONS:
out->args.vc.actions =
out->args.vc.pattern_n),
sizeof(double));
ctx->object = out->args.vc.actions;
+ ctx->objmask = NULL;
return len;
default:
if (!token->priv)
};
++out->args.vc.pattern_n;
ctx->object = item;
+ ctx->objmask = NULL;
} else {
const struct parse_action_priv *priv = token->priv;
struct rte_flow_action *action =
};
++out->args.vc.actions_n;
ctx->object = action;
+ ctx->objmask = NULL;
}
memset(data, 0, data_size);
out->args.vc.data = data;
return len;
}
+/** Parse pattern item parameter type. */
+static int
+parse_vc_spec(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_item *item;
+ uint32_t data_size;
+ int index;
+ int objmask = 0;
+
+ (void)size;
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Parse parameter types. */
+ switch (ctx->curr) {
+ case ITEM_PARAM_IS:
+ index = 0;
+ objmask = 1;
+ break;
+ case ITEM_PARAM_SPEC:
+ index = 0;
+ break;
+ case ITEM_PARAM_LAST:
+ index = 1;
+ break;
+ case ITEM_PARAM_MASK:
+ index = 2;
+ break;
+ default:
+ return -1;
+ }
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->args.vc.pattern_n)
+ return -1;
+ item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
+ data_size = ctx->objdata / 3; /* spec, last, mask */
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data + (data_size * index);
+ if (objmask) {
+ ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
+ item->mask = ctx->objmask;
+ } else
+ ctx->objmask = NULL;
+ /* Update relevant item pointer. */
+ *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
+ ctx->object;
+ return len;
+}
+
/** Parse tokens for destroy command. */
static int
parse_destroy(struct context *ctx, const struct token *token,
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 -1;
ctx->objdata = 0;
ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
+ ctx->objmask = NULL;
return len;
}
out->command = ctx->curr;
ctx->objdata = 0;
ctx->object = out;
+ ctx->objmask = NULL;
}
return len;
}
out->command = ctx->curr;
ctx->objdata = 0;
ctx->object = out;
+ ctx->objmask = NULL;
}
return len;
}
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 -1;
ctx->objdata = 0;
ctx->object = out->args.list.group + out->args.list.group_n++;
+ ctx->objmask = NULL;
return len;
}
return len;
buf = (uint8_t *)ctx->object + arg->offset;
size = arg->size;
+objmask:
switch (size) {
case sizeof(uint8_t):
*(uint8_t *)buf = u;
default:
goto error;
}
+ if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
+ u = -1;
+ buf = (uint8_t *)ctx->objmask + arg->offset;
+ goto objmask;
+ }
return len;
error:
push_args(ctx, arg);
else {
ctx->objdata = 0;
ctx->object = out;
+ ctx->objmask = NULL;
size = sizeof(*out);
}
ret = parse_int(ctx, token, str, len, out, size);
ctx->port = 0;
ctx->objdata = 0;
ctx->object = NULL;
+ ctx->objmask = NULL;
}
/** Parse a token (cmdline API). */