@@ -1000,8 +1000,9 @@ static int match_option_size(const char *prefix, size_t len,
/* Parses network data and adds info into nic
* Returns 1 if the input token does not match one of the keys
* or parsed values are not correct. Successful parse returns 0 */
-static int parse_nic_config(libxl_device_nic *nic, XLU_Config **config,
- char *token)
+static int parse_nic_config_token(XLU_Config **config,
+ char *token,
+ libxl_device_nic *nic)
{
char *endptr, *oparg;
int i;
@@ -1056,6 +1057,59 @@ static int parse_nic_config(libxl_device_nic *nic, XLU_Config **config,
return 0;
}
+static int parse_nic_config_one(XLU_Config **config,
+ const char *config_str,
+ libxl_device_nic *nic)
+{
+ char *buf = xstrdup(config_str);
+ char *p;
+ int ret;
+
+ set_default_nic_values(nic);
+
+ p = strtok(buf, ",");
+ if (!p) {
+ ret = 0;
+ goto out;
+ }
+
+ do {
+ while (*p == ' ')
+ p++;
+ ret = parse_nic_config_token(config, p, nic);
+ } while ((p = strtok(NULL, ",")) != NULL && ret == 0);
+
+out:
+ free(buf);
+
+ return ret;
+}
+
+static void parse_nic_config_multistring(XLU_Config **config,
+ int nspecs, const char *const *specs,
+ libxl_device_nic *nic)
+{
+ int i;
+
+ libxl_device_nic_init(nic);
+
+ if (!*config) {
+ *config = xlu_cfg_init(stderr, "command line");
+ if (!*config) { perror("xlu_cfg_init"); exit(-1); }
+ }
+
+ for (i = 0; i < nspecs; i++) {
+ if (parse_nic_config_one(config, specs[i], nic))
+ exit(EXIT_FAILURE);
+ }
+}
+
+static void parse_nic_config(XLU_Config **config, const char *buf,
+ libxl_device_nic *nic)
+{
+ parse_nic_config_multistring(config, 1, &buf, nic);
+}
+
static unsigned long parse_ulong(const char *str)
{
char *endptr;
@@ -1928,24 +1982,10 @@ static void parse_config_data(const char *config_source,
while ((buf = xlu_cfg_get_listitem (nics, d_config->num_nics))
!= NULL) {
libxl_device_nic *nic;
- char *buf2 = strdup(buf);
- char *p;
-
nic = ARRAY_EXTEND_INIT(d_config->nics,
d_config->num_nics,
libxl_device_nic_init);
- set_default_nic_values(nic);
-
- p = strtok(buf2, ",");
- if (!p)
- goto skip_nic;
- do {
- while (*p == ' ')
- p++;
- parse_nic_config(nic, &config, p);
- } while ((p = strtok(NULL, ",")) != NULL);
-skip_nic:
- free(buf2);
+ parse_nic_config(&config, buf, nic);
}
}
@@ -6532,12 +6572,10 @@ int main_networkattach(int argc, char **argv)
}
libxl_device_nic_init(&nic);
- set_default_nic_values(&nic);
- for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) {
- if (parse_nic_config(&nic, &config, *argv))
- return 1;
- }
+ optind++;
+ parse_nic_config_multistring(&config, argc-optind,
+ (const char* const*) argv + optind, &nic);
if (dryrun_only) {
char *json = libxl_device_nic_to_json(ctx, &nic);
The original parse_nic_config was in fact only parsing tokens. main_networkattach erroneously used it to parse raw config string, which led to xl network-attach not respecting network configuration syntax. Rework vif config parser: 1. Extract the snippet in parse_config_data to parse_nic_config_one. 2. Rename original parse_nic_config to parse_nic_config_token. 3. Provide _multistring variant. 4. Implement parse_nic_config with _multistring variant. 5. Use _multistring variant in main_networkattach. Finally the call chain becomes: parse_nic_config -> parse_nic_config_multistring -> parse_nic_config_one -> parse_nic_config_token. Some other less important changes: 1. Change prototypes of parse_nic_config functions to match block counterpart. 2. parse_nic_config will now exit if parsing failed. 3. main_networkattach doesn't call set_default_nic_values anymore. Signed-off-by: Wei Liu <wei.liu2@citrix.com> --- tools/libxl/xl_cmdimpl.c | 82 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 22 deletions(-)