X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Ffailsafe%2Ffailsafe_args.c;h=707490b94c4ee22411a046d837f5d5c7784fd4c8;hb=8d4659e70fc081ab220e44552af194900d720d2e;hp=ec3db553f1ae65ceefea0c3dd821246644264cf2;hpb=a0194d828100ecf549763d1a80f08cc61275840f;p=dpdk.git diff --git a/drivers/net/failsafe/failsafe_args.c b/drivers/net/failsafe/failsafe_args.c index ec3db553f1..707490b94c 100644 --- a/drivers/net/failsafe/failsafe_args.c +++ b/drivers/net/failsafe/failsafe_args.c @@ -1,56 +1,31 @@ -/*- - * BSD LICENSE - * - * Copyright 2017 6WIND S.A. - * Copyright 2017 Mellanox. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of 6WIND S.A. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2017 6WIND S.A. + * Copyright 2017 Mellanox Technologies, Ltd */ +#include +#include +#include #include +#include #include #include #include #include #include +#include #include "failsafe_private.h" -#define DEVARGS_MAXLEN 4096 - /* Callback used when a new device is found in devargs */ typedef int (parse_cb)(struct rte_eth_dev *dev, const char *params, uint8_t head); -uint64_t hotplug_poll = FAILSAFE_HOTPLUG_DEFAULT_TIMEOUT_MS; -int mac_from_arg = 0; +uint64_t failsafe_hotplug_poll = FAILSAFE_HOTPLUG_DEFAULT_TIMEOUT_MS; +int failsafe_mac_from_arg; -const char *pmd_failsafe_init_parameters[] = { +static const char * const pmd_failsafe_init_parameters[] = { PMD_FAILSAFE_HOTPLUG_POLL_KVARG, PMD_FAILSAFE_MAC_KVARG, NULL, @@ -88,7 +63,7 @@ fs_parse_device(struct sub_device *sdev, char *args) d = &sdev->devargs; DEBUG("%s", args); - ret = rte_eal_devargs_parse(args, d); + ret = rte_devargs_parse(d, args); if (ret) { DEBUG("devargs parsing failed with code %d", ret); return ret; @@ -101,10 +76,11 @@ fs_parse_device(struct sub_device *sdev, char *args) static void fs_sanitize_cmdline(char *args) { - size_t len; + char *nl; - len = strnlen(args, DEVARGS_MAXLEN); - args[len - 1] = '\0'; + nl = strrchr(args, '\n'); + if (nl) + nl[0] = '\0'; } static int @@ -114,7 +90,6 @@ fs_execute_cmd(struct sub_device *sdev, char *cmdline) /* store possible newline as well */ char output[DEVARGS_MAXLEN + 1]; size_t len; - int old_err; int ret; RTE_ASSERT(cmdline != NULL || sdev->cmdline != NULL); @@ -127,43 +102,100 @@ fs_execute_cmd(struct sub_device *sdev, char *cmdline) ERROR("Command line allocation failed"); return -ENOMEM; } - snprintf(sdev->cmdline, len, "%s", cmdline); + strlcpy(sdev->cmdline, cmdline, len); /* Replace all commas in the command line by spaces */ for (i = 0; i < len; i++) if (sdev->cmdline[i] == ',') sdev->cmdline[i] = ' '; } DEBUG("'%s'", sdev->cmdline); - old_err = errno; fp = popen(sdev->cmdline, "r"); if (fp == NULL) { - ret = errno; + ret = -errno; ERROR("popen: %s", strerror(errno)); - errno = old_err; return ret; } /* We only read one line */ if (fgets(output, sizeof(output) - 1, fp) == NULL) { DEBUG("Could not read command output"); - return -ENODEV; + ret = -ENODEV; + goto ret_pclose; } fs_sanitize_cmdline(output); - ret = fs_parse_device(sdev, output); - if (ret) { - ERROR("Parsing device '%s' failed", output); + if (output[0] == '\0') { + ret = -ENODEV; goto ret_pclose; } + ret = fs_parse_device(sdev, output); + if (ret) + ERROR("Parsing device '%s' failed", output); ret_pclose: - ret = pclose(fp); - if (ret) { - ret = errno; + if (pclose(fp) == -1) ERROR("pclose: %s", strerror(errno)); - errno = old_err; - return ret; - } return ret; } +static int +fs_read_fd(struct sub_device *sdev, char *fd_str) +{ + FILE *fp = NULL; + int fd = -1; + /* store possible newline as well */ + char output[DEVARGS_MAXLEN + 1]; + int err = -ENODEV; + int oflags; + int lcount; + + RTE_ASSERT(fd_str != NULL || sdev->fd_str != NULL); + if (sdev->fd_str == NULL) { + sdev->fd_str = strdup(fd_str); + if (sdev->fd_str == NULL) { + ERROR("Command line allocation failed"); + return -ENOMEM; + } + } + errno = 0; + fd = strtol(fd_str, &fd_str, 0); + if (errno || *fd_str || fd < 0) { + ERROR("Parsing FD number failed"); + goto error; + } + /* Fiddle with copy of file descriptor */ + fd = dup(fd); + if (fd == -1) + goto error; + oflags = fcntl(fd, F_GETFL); + if (oflags == -1) + goto error; + if (fcntl(fd, F_SETFL, oflags | O_NONBLOCK) == -1) + goto error; + fp = fdopen(fd, "r"); + if (fp == NULL) + goto error; + fd = -1; + /* Only take the last line into account */ + lcount = 0; + while (fgets(output, sizeof(output), fp)) + ++lcount; + if (lcount == 0) + goto error; + else if (ferror(fp) && errno != EAGAIN) + goto error; + /* Line must end with a newline character */ + fs_sanitize_cmdline(output); + if (output[0] == '\0') + goto error; + err = fs_parse_device(sdev, output); + if (err) + ERROR("Parsing device '%s' failed", output); +error: + if (fp) + fclose(fp); + if (fd != -1) + close(fd); + return err; +} + static int fs_parse_device_param(struct rte_eth_dev *dev, const char *param, uint8_t head) @@ -206,6 +238,14 @@ fs_parse_device_param(struct rte_eth_dev *dev, const char *param, } if (ret) goto free_args; + } else if (strncmp(param, "fd(", 3) == 0) { + ret = fs_read_fd(sdev, args); + if (ret == -ENODEV) { + DEBUG("Reading device info from FD failed"); + ret = 0; + } + if (ret) + goto free_args; } else { ERROR("Unrecognized device type: %.*s", (int)b, param); return -EINVAL; @@ -280,10 +320,17 @@ fs_remove_sub_devices_definition(char params[DEVARGS_MAXLEN]) ERROR("Invalid parameter"); return -EINVAL; } - if (params[b] == ',' || params[b] == '\0') - i += snprintf(&buffer[i], b - a + 1, "%s", ¶ms[a]); - if (params[b] == '(') { + if (params[b] == ',' || params[b] == '\0') { + size_t len = b - a; + + if (i > 0) + len += 1; + snprintf(&buffer[i], len + 1, "%s%s", + i ? "," : "", ¶ms[a]); + i += len; + } else if (params[b] == '(') { size_t start = b; + b += closing_paren(¶ms[b]); if (b == start) return -EINVAL; @@ -294,7 +341,7 @@ fs_remove_sub_devices_definition(char params[DEVARGS_MAXLEN]) a = b + 1; } out: - snprintf(params, DEVARGS_MAXLEN, "%s", buffer); + strlcpy(params, buffer, DEVARGS_MAXLEN); return 0; } @@ -320,16 +367,12 @@ static int fs_get_mac_addr_arg(const char *key __rte_unused, const char *value, void *out) { - struct ether_addr *ea = out; - int ret; + struct rte_ether_addr *ea = out; if ((value == NULL) || (out == NULL)) return -EINVAL; - ret = sscanf(value, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", - &ea->addr_bytes[0], &ea->addr_bytes[1], - &ea->addr_bytes[2], &ea->addr_bytes[3], - &ea->addr_bytes[4], &ea->addr_bytes[5]); - return ret != ETHER_ADDR_LEN; + + return rte_ether_unformat_addr(value, ea); } int @@ -346,7 +389,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) ret = 0; priv->subs_tx = FAILSAFE_MAX_ETHPORTS; /* default parameters */ - n = snprintf(mut_params, sizeof(mut_params), "%s", params); + n = strlcpy(mut_params, params, sizeof(mut_params)); if (n >= sizeof(mut_params)) { ERROR("Parameter string too long (>=%zu)", sizeof(mut_params)); @@ -373,7 +416,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) if (arg_count == 1) { ret = rte_kvargs_process(kvlist, PMD_FAILSAFE_HOTPLUG_POLL_KVARG, - &fs_get_u64_arg, &hotplug_poll); + &fs_get_u64_arg, &failsafe_hotplug_poll); if (ret < 0) goto free_kvlist; } @@ -387,7 +430,8 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) &dev->data->mac_addrs[0]); if (ret < 0) goto free_kvlist; - mac_from_arg = 1; + + failsafe_mac_from_arg = 1; } } PRIV(dev)->state = DEV_PARSED; @@ -403,8 +447,10 @@ failsafe_args_free(struct rte_eth_dev *dev) uint8_t i; FOREACH_SUBDEV(sdev, i, dev) { - rte_free(sdev->cmdline); + free(sdev->cmdline); sdev->cmdline = NULL; + free(sdev->fd_str); + sdev->fd_str = NULL; free(sdev->devargs.args); sdev->devargs.args = NULL; } @@ -420,7 +466,8 @@ fs_count_device(struct rte_eth_dev *dev, const char *param, param[b] != '\0') b++; if (strncmp(param, "dev", b) != 0 && - strncmp(param, "exec", b) != 0) { + strncmp(param, "exec", b) != 0 && + strncmp(param, "fd(", b) != 0) { ERROR("Unrecognized device type: %.*s", (int)b, param); return -EINVAL; } @@ -436,6 +483,17 @@ failsafe_args_count_subdevice(struct rte_eth_dev *dev, dev, params); } +static int +fs_parse_sub_device(struct sub_device *sdev) +{ + struct rte_devargs *da; + char devstr[DEVARGS_MAXLEN] = ""; + + da = &sdev->devargs; + snprintf(devstr, sizeof(devstr), "%s,%s", da->name, da->args); + return fs_parse_device(sdev, devstr); +} + int failsafe_args_parse_subs(struct rte_eth_dev *dev) { @@ -448,6 +506,10 @@ failsafe_args_parse_subs(struct rte_eth_dev *dev) continue; if (sdev->cmdline) ret = fs_execute_cmd(sdev, sdev->cmdline); + else if (sdev->fd_str) + ret = fs_read_fd(sdev, sdev->fd_str); + else + ret = fs_parse_sub_device(sdev); if (ret == 0) sdev->state = DEV_PARSED; }