X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Ffailsafe%2Ffailsafe_args.c;h=cfc83e365d13e6f5a88b99ffb3c6bc03bbcdfc86;hb=9df0826a42e890006c77861c74b79907f33b8201;hp=bde8f2dee5ede6c9b119725f4a67c1d13904af1f;hpb=a46f8d584eb88feb2a05ca3459d4a00b7d7654aa;p=dpdk.git diff --git a/drivers/net/failsafe/failsafe_args.c b/drivers/net/failsafe/failsafe_args.c index bde8f2dee5..cfc83e365d 100644 --- a/drivers/net/failsafe/failsafe_args.c +++ b/drivers/net/failsafe/failsafe_args.c @@ -32,7 +32,9 @@ */ #include +#include +#include #include #include #include @@ -45,9 +47,11 @@ 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; const char *pmd_failsafe_init_parameters[] = { + PMD_FAILSAFE_HOTPLUG_POLL_KVARG, PMD_FAILSAFE_MAC_KVARG, NULL, }; @@ -94,6 +98,68 @@ fs_parse_device(struct sub_device *sdev, char *args) return 0; } +static void +fs_sanitize_cmdline(char *args) +{ + char *nl; + + nl = strrchr(args, '\n'); + if (nl) + nl[0] = '\0'; +} + +static int +fs_execute_cmd(struct sub_device *sdev, char *cmdline) +{ + FILE *fp; + /* store possible newline as well */ + char output[DEVARGS_MAXLEN + 1]; + size_t len; + int ret; + + RTE_ASSERT(cmdline != NULL || sdev->cmdline != NULL); + if (sdev->cmdline == NULL) { + size_t i; + + len = strlen(cmdline) + 1; + sdev->cmdline = calloc(1, len); + if (sdev->cmdline == NULL) { + ERROR("Command line allocation failed"); + return -ENOMEM; + } + snprintf(sdev->cmdline, len, "%s", cmdline); + /* 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); + fp = popen(sdev->cmdline, "r"); + if (fp == NULL) { + ret = -errno; + ERROR("popen: %s", strerror(errno)); + return ret; + } + /* We only read one line */ + if (fgets(output, sizeof(output) - 1, fp) == NULL) { + DEBUG("Could not read command output"); + ret = -ENODEV; + goto ret_pclose; + } + fs_sanitize_cmdline(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: + if (pclose(fp) == -1) + ERROR("pclose: %s", strerror(errno)); + return ret; +} + static int fs_parse_device_param(struct rte_eth_dev *dev, const char *param, uint8_t head) @@ -128,6 +194,14 @@ fs_parse_device_param(struct rte_eth_dev *dev, const char *param, ret = fs_parse_device(sdev, args); if (ret) goto free_args; + } else if (strncmp(param, "exec", 4) == 0) { + ret = fs_execute_cmd(sdev, args); + if (ret == -ENODEV) { + DEBUG("Reading device info from command line failed"); + ret = 0; + } + if (ret) + goto free_args; } else { ERROR("Unrecognized device type: %.*s", (int)b, param); return -EINVAL; @@ -202,10 +276,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; @@ -220,6 +301,24 @@ out: return 0; } +static int +fs_get_u64_arg(const char *key __rte_unused, + const char *value, void *out) +{ + uint64_t *u64 = out; + char *endptr = NULL; + + if ((value == NULL) || (out == NULL)) + return -EINVAL; + errno = 0; + *u64 = strtoull(value, &endptr, 0); + if (errno != 0) + return -errno; + if (endptr == value) + return -1; + return 0; +} + static int fs_get_mac_addr_arg(const char *key __rte_unused, const char *value, void *out) @@ -271,6 +370,16 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) PMD_FAILSAFE_PARAM_STRING); return -1; } + /* PLUG_IN event poll timer */ + arg_count = rte_kvargs_count(kvlist, + PMD_FAILSAFE_HOTPLUG_POLL_KVARG); + if (arg_count == 1) { + ret = rte_kvargs_process(kvlist, + PMD_FAILSAFE_HOTPLUG_POLL_KVARG, + &fs_get_u64_arg, &hotplug_poll); + if (ret < 0) + goto free_kvlist; + } /* MAC addr */ arg_count = rte_kvargs_count(kvlist, PMD_FAILSAFE_MAC_KVARG); @@ -281,9 +390,11 @@ 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; } } + PRIV(dev)->state = DEV_PARSED; free_kvlist: rte_kvargs_free(kvlist); return ret; @@ -296,6 +407,8 @@ failsafe_args_free(struct rte_eth_dev *dev) uint8_t i; FOREACH_SUBDEV(sdev, i, dev) { + rte_free(sdev->cmdline); + sdev->cmdline = NULL; free(sdev->devargs.args); sdev->devargs.args = NULL; } @@ -310,7 +423,8 @@ fs_count_device(struct rte_eth_dev *dev, const char *param, while (param[b] != '(' && param[b] != '\0') b++; - if (strncmp(param, "dev", b) != 0) { + if (strncmp(param, "dev", b) != 0 && + strncmp(param, "exec", b) != 0) { ERROR("Unrecognized device type: %.*s", (int)b, param); return -EINVAL; } @@ -325,3 +439,34 @@ failsafe_args_count_subdevice(struct rte_eth_dev *dev, return fs_parse_sub_devices(fs_count_device, 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) +{ + struct sub_device *sdev; + uint8_t i; + int ret = 0; + + FOREACH_SUBDEV(sdev, i, dev) { + if (sdev->state >= DEV_PARSED) + continue; + if (sdev->cmdline) + ret = fs_execute_cmd(sdev, sdev->cmdline); + else + ret = fs_parse_sub_device(sdev); + if (ret == 0) + sdev->state = DEV_PARSED; + } + return 0; +}