Hi Nelio, Wednesday, May 2, 2018 5:43 PM, Nelio Laranjeiro: > Subject: [dpdk-stable] [PATCH] net/mlx5: fix: flow validation
The title is wrong the : after the fix should be removed. > > Item spec and last are wrongly compared to the NIC capability causing a > validation failure when the mask is null. > This validation function should only verify the user is not configuring > unsupported matching fields. > > Fixes: 2097d0d1e2cc ("net/mlx5: support basic flow items and actions") > Cc: sta...@dpdk.org > > Signed-off-by: Nelio Laranjeiro <nelio.laranje...@6wind.com> > --- > drivers/net/mlx5/mlx5_flow.c | 73 +++++++++++------------------------- > 1 file changed, 22 insertions(+), 51 deletions(-) > > diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c > index 129311d50..5d4995783 100644 > --- a/drivers/net/mlx5/mlx5_flow.c > +++ b/drivers/net/mlx5/mlx5_flow.c > @@ -555,60 +555,31 @@ static int > mlx5_flow_item_validate(const struct rte_flow_item *item, > const uint8_t *mask, unsigned int size) { > - if (!item->spec && (item->mask || item->last)) { > - rte_errno = EINVAL; > - return -rte_errno; > - } > - if (item->spec && !item->mask) { > - unsigned int i; > - const uint8_t *spec = item->spec; > - > - for (i = 0; i < size; ++i) > - if ((spec[i] | mask[i]) != mask[i]) { > - rte_errno = EINVAL; > - return -rte_errno; > - } > - } > - if (item->last && !item->mask) { > - unsigned int i; > - const uint8_t *spec = item->last; > - > - for (i = 0; i < size; ++i) > - if ((spec[i] | mask[i]) != mask[i]) { > - rte_errno = EINVAL; > - return -rte_errno; > - } > - } > - if (item->mask) { > - unsigned int i; > - const uint8_t *spec = item->spec; > - > - for (i = 0; i < size; ++i) > - if ((spec[i] | mask[i]) != mask[i]) { > - rte_errno = EINVAL; > - return -rte_errno; > - } > - } > - if (item->spec && item->last) { > - uint8_t spec[size]; > - uint8_t last[size]; > - const uint8_t *apply = mask; > - unsigned int i; > - int ret; > + unsigned int i; > + const uint8_t *spec = item->spec; > + const uint8_t *last = item->last; > + const uint8_t *m = item->mask ? item->mask : mask; > > - if (item->mask) > - apply = item->mask; > - for (i = 0; i < size; ++i) { > - spec[i] = ((const uint8_t *)item->spec)[i] & apply[i]; > - last[i] = ((const uint8_t *)item->last)[i] & apply[i]; > - } > - ret = memcmp(spec, last, size); > - if (ret != 0) { > - rte_errno = EINVAL; > - return -rte_errno; > - } > + if (!spec && (item->mask || last)) > + goto error; > + if (!spec) > + return 0; > + for (i = 0; i < size; i++) { I think inline comment which explains what each code section below verifies would much help. > + if (spec) > + if (((spec[i] & m[i]) | mask[i]) != mask[i]) > + goto error; Am wondering. Which the below check of m ... > + if (last) > + if ((((last[i] & m[i]) | mask[i]) != mask[i]) || > + ((spec[i] & m[i]) != (last[i] & m[i]))) > + goto error; > + if (m) > + if ((m[i] | mask[i]) != mask[i]) > + goto error; Do we really need to spec check? Meaning if above one passes it is guarantee m is contained in mask. And if so, then the spec check will always succeed. > } > return 0; > +error: > + rte_errno = ENOTSUP; > + return -rte_errno; > } > > /** > -- > 2.17.0