[dpdk-dev] [PATCH] app/testpmd: fix support of hex string parser for flow API

Zhao1, Wei wei.zhao1 at intel.com
Mon Mar 18 09:49:17 CET 2019


Hi,  Konstantin

> -----Original Message-----
> From: Ananyev, Konstantin
> Sent: Friday, March 15, 2019 5:45 PM
> To: Zhao1, Wei <wei.zhao1 at intel.com>; dev at dpdk.org
> Cc: stable at dpdk.org; Zhang, Qi Z <qi.z.zhang at intel.com>;
> adrien.mazarguil at 6wind.com; Zhao1, Wei <wei.zhao1 at intel.com>
> Subject: RE: [dpdk-dev] [PATCH] app/testpmd: fix support of hex string
> parser for flow API
> 
> Hi Wei,
> 
> >
> > There is need for users to set configuration of HEX number for RSS
> > key. The key byte should be pass down as hex number not as char
> > string. This patch enable cmdline flow parse HEX number, in order to
> > not using string which pass ASIC number.
> >
> > Fixes: f4d623f96119 ("app/testpmd: fix missing RSS fields in flow
> > action")
> > Cc: stable at dpdk.org
> >
> > Signed-off-by: Wei Zhao <wei.zhao1 at intel.com>
> > ---
> >  app/test-pmd/cmdline_flow.c | 141
> > +++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 140 insertions(+), 1 deletion(-)
> >
> > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> > index 36659a6..2445731 100644
> > --- a/app/test-pmd/cmdline_flow.c
> > +++ b/app/test-pmd/cmdline_flow.c
> > @@ -35,6 +35,7 @@ enum index {
> >  	PREFIX,
> >  	BOOLEAN,
> >  	STRING,
> > +	HEX,
> >  	MAC_ADDR,
> >  	IPV4_ADDR,
> >  	IPV6_ADDR,
> > @@ -1122,6 +1123,9 @@ static int parse_boolean(struct context *, const
> > struct token *,  static int parse_string(struct context *, const struct token *,
> >  			const char *, unsigned int,
> >  			void *, unsigned int);
> > +static int parse_hex(struct context *ctx, const struct token *token,
> > +			const char *str, unsigned int len,
> > +			void *buf, unsigned int size);
> >  static int parse_mac_addr(struct context *, const struct token *,
> >  			  const char *, unsigned int,
> >  			  void *, unsigned int);
> > @@ -1198,6 +1202,13 @@ static const struct token token_list[] = {
> >  		.call = parse_string,
> >  		.comp = comp_none,
> >  	},
> > +	[HEX] = {
> > +		.name = "{hex}",
> > +		.type = "HEX",
> > +		.help = "fixed string",
> > +		.call = parse_hex,
> > +		.comp = comp_none,
> > +	},
> >  	[MAC_ADDR] = {
> >  		.name = "{MAC address}",
> >  		.type = "MAC-48",
> > @@ -1544,7 +1555,7 @@ static const struct token token_list[] = {
> >  		.name = "pattern",
> >  		.help = "byte string to look for",
> >  		.next = NEXT(item_raw,
> > -			     NEXT_ENTRY(STRING),
> > +			     NEXT_ENTRY(HEX),
> >  			     NEXT_ENTRY(ITEM_PARAM_IS,
> >  					ITEM_PARAM_SPEC,
> >  					ITEM_PARAM_MASK)),
> > @@ -4475,6 +4486,134 @@ parse_string(struct context *ctx, const struct
> token *token,
> >  	return -1;
> >  }
> >
> > +static uint32_t
> > +get_hex_val(char c)
> > +{
> > +	switch (c) {
> > +	case '0': case '1': case '2': case '3': case '4': case '5':
> > +	case '6': case '7': case '8': case '9':
> > +		return c - '0';
> > +	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
> > +		return c - 'A' + 10;
> > +	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
> > +		return c - 'a' + 10;
> > +	default:
> > +		return 0;
> > +	}
> > +}
> > +
> > +static int
> > +parse_hex_string(const char *src, uint8_t *dst, uint32_t *size) {
> > +	const char *c;
> > +	uint32_t i;
> > +
> > +	/* Check input parameters */
> > +	if ((src == NULL) ||
> > +		(dst == NULL) ||
> > +		(size == NULL) ||
> > +		(*size == 0))
> > +		return -1;
> > +	if ((*size & 1) != 0)
> > +		return -1;
> > +
> > +	for (c = src, i = 0; i < *size; c++, i++) {
> > +		if ((((*c) >= '0') && ((*c) <= '9')) ||
> > +			(((*c) >= 'A') && ((*c) <= 'F')) ||
> > +			(((*c) >= 'a') && ((*c) <= 'f')))
> > +			continue;
> > +
> > +		return -1;
> > +	}
> > +	*size = *size / 2;
> > +
> > +	/* Convert chars to bytes */
> > +	for (i = 0; i < *size; i++)
> > +		dst[i] = get_hex_val(src[2 * i]) * 16 +
> > +			get_hex_val(src[2 * i + 1]);
> > +
> > +	return 0;
> > +}
> 
> What's wrong with strtoul() and friends?
> Why you need to write your own version?
> Konstantin


I have try to use strtoul(), but it do not work, because 
I want to pars char byte on bye one, not the long string by one time, and also 
RSS KEY can be as long as 100 byte long for i40e,   but strtoul() return only 64 bit long.
app\test-eventdev and examples\ip_pipeline , drivers\net\softnic also use get_hex_val(), so I will it also.


> 
> > +
> > +static int
> > +parse_hex(struct context *ctx, const struct token *token,
> > +		const char *str, unsigned int len,
> > +		void *buf, unsigned int size)
> > +{
> > +	const struct arg *arg_data = pop_args(ctx);
> > +	const struct arg *arg_len = pop_args(ctx);
> > +	const struct arg *arg_addr = pop_args(ctx);
> > +	char tmp[16]; /* Ought to be enough. */
> > +	int ret;
> > +	unsigned int hexlen = len;
> > +	uint8_t hex_tmp[16];
> > +
> > +	/* Arguments are expected. */
> > +	if (!arg_data)
> > +		return -1;
> > +	if (!arg_len) {
> > +		push_args(ctx, arg_data);
> > +		return -1;
> > +	}
> > +	if (!arg_addr) {
> > +		push_args(ctx, arg_len);
> > +		push_args(ctx, arg_data);
> > +		return -1;
> > +	}
> > +	size = arg_data->size;
> > +	/* Bit-mask fill is not supported. */
> > +	if (arg_data->mask || size < len)
> > +		goto error;
> > +	if (!ctx->object)
> > +		return len;
> > +
> > +	/* translate bytes string to array. */
> > +	if (str[0] == '0' && ((str[1] == 'x') ||
> > +			(str[1] == 'X'))) {
> > +		str += 2;
> > +		hexlen -= 2;
> > +	}
> > +	parse_hex_string(str, hex_tmp, &hexlen);
> > +	/* Let parse_int() fill length information first. */
> > +	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
> > +	if (ret < 0)
> > +		goto error;
> > +	push_args(ctx, arg_len);
> > +	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
> > +	if (ret < 0) {
> > +		pop_args(ctx);
> > +		goto error;
> > +	}
> > +	buf = (uint8_t *)ctx->object + arg_data->offset;
> > +	/* Output buffer is not necessarily NUL-terminated. */
> > +	memcpy(buf, hex_tmp, hexlen);
> > +	memset((uint8_t *)buf + len, 0x00, size - hexlen);
> > +	if (ctx->objmask)
> > +		memset((uint8_t *)ctx->objmask + arg_data->offset,
> > +					0xff, hexlen);
> > +	/* Save address if requested. */
> > +	if (arg_addr->size) {
> > +		memcpy((uint8_t *)ctx->object + arg_addr->offset,
> > +		       (void *[]){
> > +			(uint8_t *)ctx->object + arg_data->offset
> > +		       },
> > +		       arg_addr->size);
> > +		if (ctx->objmask)
> > +			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
> > +			       (void *[]){
> > +				(uint8_t *)ctx->objmask + arg_data->offset
> > +			       },
> > +			       arg_addr->size);
> > +	}
> > +	return len;
> > +error:
> > +	push_args(ctx, arg_addr);
> > +	push_args(ctx, arg_len);
> > +	push_args(ctx, arg_data);
> > +	return -1;
> > +
> > +}
> > +
> >  /**
> >   * Parse a MAC address.
> >   *
> > --
> > 2.7.5



More information about the dev mailing list