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 > return 0; > @@ -99,7 +117,7 @@ parse_num_clients(const char *clients) > * on error. > */ > int > -parse_app_args(uint16_t max_ports, int argc, char *argv[]) > +parse_app_args(int argc, char *argv[]) > { > int option_index, opt; > char **argvopt = argv; > @@ -112,7 +130,7 @@ parse_app_args(uint16_t max_ports, int argc, char > *argv[]) > &option_index)) != EOF){ > switch (opt){ > case 'p': > - if (parse_portmask(max_ports, optarg) != 0){ > + if (parse_portmask(optarg) != 0) { > usage(); > return -1; > } > diff --git a/examples/multi_process/client_server_mp/mp_server/args.h > b/examples/multi_process/client_server_mp/mp_server/args.h > index 79c190a33a37..52c8cc86e6f0 100644 > --- a/examples/multi_process/client_server_mp/mp_server/args.h > +++ b/examples/multi_process/client_server_mp/mp_server/args.h > @@ -5,6 +5,6 @@ > #ifndef _ARGS_H_ > #define _ARGS_H_ > > -int parse_app_args(uint16_t max_ports, int argc, char *argv[]); > +int parse_app_args(int argc, char *argv[]); > > #endif /* ifndef _ARGS_H_ */ > diff --git a/examples/multi_process/client_server_mp/mp_server/init.c > b/examples/multi_process/client_server_mp/mp_server/init.c > index 3af5dc6994bf..1b0569937b51 100644 > --- a/examples/multi_process/client_server_mp/mp_server/init.c > +++ b/examples/multi_process/client_server_mp/mp_server/init.c > @@ -238,7 +238,7 @@ init(int argc, char *argv[]) { > int retval; > const struct rte_memzone *mz; > - uint16_t i, total_ports; > + uint16_t i; > > /* init EAL, parsing EAL args */ > retval = rte_eal_init(argc, argv); > @@ -247,9 +247,6 @@ init(int argc, char *argv[]) > argc -= retval; > argv += retval; > > - /* get total number of ports */ > - total_ports = rte_eth_dev_count_total(); > - > /* set up array for port data */ > mz = rte_memzone_reserve(MZ_PORT_INFO, sizeof(*ports), > rte_socket_id(), NO_FLAGS); > @@ -259,7 +256,7 @@ init(int argc, char *argv[]) > ports = mz->addr; > > /* parse additional, application arguments */ > - retval = parse_app_args(total_ports, argc, argv); > + retval = parse_app_args(argc, argv); > if (retval != 0) > return -1; > > -- > 2.20.1