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.mazarg...@6wind.com>
Acked-by: Olga Shern <ol...@mellanox.com>
---
 app/test-pmd/cmdline_flow.c | 59 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 07f895e..69887fc 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -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:
-- 
2.1.4

Reply via email to