On Tue, 30 Jul 2019 09:21:02 +0000 Matan Azrad <ma...@mellanox.com> wrote:
> Hi Stephen > > From: Stephen Hemminger > > From: Stephen Hemminger <sthem...@microsoft.com> > > > > The mp_server incorrectly allows a port mask that included hidden ports and > > which later caused either lost packets or failed initialization. > > > > This fixes explicitly checking that each bit in portmask is a valid port > > before > > using it. > > > > Fixes: 5b7ba31148a8 ("ethdev: add port ownership") > > Signed-off-by: Stephen Hemminger <sthem...@microsoft.com> > > --- > > .../client_server_mp/mp_server/args.c | 46 +++++++++++++------ > > .../client_server_mp/mp_server/args.h | 2 +- > > .../client_server_mp/mp_server/init.c | 7 +-- > > 3 files changed, 35 insertions(+), 20 deletions(-) > > > > diff --git a/examples/multi_process/client_server_mp/mp_server/args.c > > b/examples/multi_process/client_server_mp/mp_server/args.c > > index b0d8d7665c85..c1ab12ad00d1 100644 > > --- a/examples/multi_process/client_server_mp/mp_server/args.c > > +++ b/examples/multi_process/client_server_mp/mp_server/args.c > > @@ -10,6 +10,7 @@ > > #include <errno.h> > > > > #include <rte_memory.h> > > +#include <rte_ethdev.h> > > #include <rte_string_fns.h> > > > > #include "common.h" > > @@ -34,6 +35,22 @@ usage(void) > > , progname); > > } > > > > +/** > > + * Check if port is present in the system > > + * It maybe owned by a device and should not be used. > > + */ > > +static int > > +port_is_present(uint16_t portid) > > +{ > > + uint16_t id; > > + > > + RTE_ETH_FOREACH_DEV(id) { > > + if (id == portid) > > + return 1; > > + } > > + return 0; > > +} > > + > > /** > > * The ports to be used by the application are passed in > > * the form of a bitmask. This function parses the bitmask @@ -41,31 +58,32 > > @@ usage(void) > > * array variable > > */ > > static int > > -parse_portmask(uint8_t max_ports, const char *portmask) > > +parse_portmask(const char *portmask) > > { > > char *end = NULL; > > unsigned long pm; > > - uint16_t count = 0; > > + uint16_t count; > > > > if (portmask == NULL || *portmask == '\0') > > return -1; > > > > /* convert parameter to a number and verify */ > > pm = strtoul(portmask, &end, 16); > > - if (end == NULL || *end != '\0' || pm == 0) > > + if (end == NULL || *end != '\0' || pm > UINT16_MAX || pm == 0) > > return -1; > > > > /* loop through bits of the mask and mark ports */ > > - while (pm != 0){ > > - if (pm & 0x01){ /* bit is set in mask, use port */ > > - if (count >= max_ports) > > - printf("WARNING: requested port %u not > > present" > > - " - ignoring\n", (unsigned)count); > > - else > > - ports->id[ports->num_ports++] = count; > > + for (count = 0; pm != 0; pm >>= 1, ++count) { > > + if ((pm & 0x1) == 0) > > + continue; > > + > > + if (!port_is_present(count)) { > > + printf("WARNING: requested port %u not present - > > ignoring\n", > > + count); > > + continue; > > } > > - pm = (pm >> 1); > > - count++; > > + > > + ports->id[ports->num_ports++] = count; > > } > > Why not just to do something like: > > RTE_ETH_FOREACH_DEV(id) { > If (pm & (1 << id)) { > pm &= ~(1 << id) > put in list > } > } > If (pm) > Warning > No real reason, was just trying to keep existing logic flow