[dpdk-dev,v2,16/25] app/testpmd: add rte_flow bit-field support
Checks
Commit Message
Several rte_flow structures expose bit-fields that cannot be set in a
generic fashion at byte level. Add bit-mask support to handle them.
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
app/test-pmd/cmdline_flow.c | 59 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
@@ -136,6 +136,7 @@ struct arg {
uint32_t sign:1; /**< Value is signed. */
uint32_t offset; /**< Relative offset from ctx->object. */
uint32_t size; /**< Field size. */
+ const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
};
/** Parser token definition. */
@@ -195,6 +196,13 @@ struct token {
.size = sizeof(((s *)0)->f), \
})
+/** Static initializer for ARGS() to target a bit-field. */
+#define ARGS_ENTRY_BF(s, f, b) \
+ (&(const struct arg){ \
+ .size = sizeof(s), \
+ .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
+ })
+
/** Static initializer for ARGS() to target a pointer. */
#define ARGS_ENTRY_PTR(s, f) \
(&(const struct arg){ \
@@ -623,6 +631,34 @@ push_args(struct context *ctx, const struct arg *arg)
return 0;
}
+/** Spread value into buffer according to bit-mask. */
+static size_t
+arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
+{
+ uint32_t i;
+ size_t len = 0;
+
+ /* Endian conversion is not supported on bit-fields. */
+ if (!arg->mask || arg->hton)
+ return 0;
+ for (i = 0; i != arg->size; ++i) {
+ unsigned int shift = 0;
+ uint8_t *buf = (uint8_t *)dst + i;
+
+ for (shift = 0; arg->mask[i] >> shift; ++shift) {
+ if (!(arg->mask[i] & (1 << shift)))
+ continue;
+ ++len;
+ if (!dst)
+ continue;
+ *buf &= ~(1 << shift);
+ *buf |= (val & 1) << shift;
+ val >>= 1;
+ }
+ }
+ return len;
+}
+
/**
* Parse a prefix length and generate a bit-mask.
*
@@ -649,6 +685,23 @@ parse_prefix(struct context *ctx, const struct token *token,
u = strtoumax(str, &end, 0);
if (errno || (size_t)(end - str) != len)
goto error;
+ if (arg->mask) {
+ uintmax_t v = 0;
+
+ extra = arg_entry_bf_fill(NULL, 0, arg);
+ if (u > extra)
+ goto error;
+ if (!ctx->object)
+ return len;
+ extra -= u;
+ while (u--)
+ (v <<= 1, v |= 1);
+ v <<= extra;
+ if (!arg_entry_bf_fill(ctx->object, v, arg) ||
+ !arg_entry_bf_fill(ctx->objmask, -1, arg))
+ goto error;
+ return len;
+ }
bytes = u / 8;
extra = u % 8;
size = arg->size;
@@ -1072,6 +1125,12 @@ parse_int(struct context *ctx, const struct token *token,
goto error;
if (!ctx->object)
return len;
+ if (arg->mask) {
+ if (!arg_entry_bf_fill(ctx->object, u, arg) ||
+ !arg_entry_bf_fill(ctx->objmask, -1, arg))
+ goto error;
+ return len;
+ }
buf = (uint8_t *)ctx->object + arg->offset;
size = arg->size;
objmask: