[ovs-dev] [PATCH 1/3] dpctl: Fix error handling and reporting regressions.
Ben Pfaff
blp at nicira.com
Wed Apr 15 18:19:34 UTC 2015
Fixes multiple weaknesses in dpctl error reporting:
* dpctl_set_if() didn't stop processing or report to the caller
attempts to change a port type or number.
* dpctl_set_if() didn't report the specifics when netdev_set_config()
reported an error setting port configuration (which can happen even
it returns 0).
* The unixctl handler didn't report errors encountered during command
processing through the JSON-RPC error mechanism, which meant that
ovs-appctl's return code wasn't useful (as ovs-dpctl's return code
is useful) for detecting errors in command execution.
At least the first of these is a regression from OVS 2.3.x.
A followup commit will add tests.
Reported-by: Kevin Lo <kevlo at FreeBSD.org>
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
lib/dpctl.c | 34 +++++++++++++++++++++++-----------
1 file changed, 23 insertions(+), 11 deletions(-)
diff --git a/lib/dpctl.c b/lib/dpctl.c
index 4c4d1c3..a9a56ff 100644
--- a/lib/dpctl.c
+++ b/lib/dpctl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -382,12 +382,14 @@ dpctl_set_if(int argc, const char *argv[], struct dpctl_params *dpctl_p)
"%s: can't change type from %s to %s",
name, type, value);
error = EINVAL;
+ goto next_destroy_args;
}
} else if (!strcmp(key, "port_no")) {
if (port_no != u32_to_odp(atoi(value))) {
dpctl_error(dpctl_p, 0, "%s: can't change port number from"
" %"PRIu32" to %d", name, port_no, atoi(value));
error = EINVAL;
+ goto next_destroy_args;
}
} else if (value[0] == '\0') {
smap_remove(&args, key);
@@ -397,7 +399,13 @@ dpctl_set_if(int argc, const char *argv[], struct dpctl_params *dpctl_p)
}
/* Update configuration. */
- error = netdev_set_config(netdev, &args, NULL);
+ char *err_s = NULL;
+ error = netdev_set_config(netdev, &args, &err_s);
+ if (err_s || error) {
+ dpctl_error(dpctl_p, error,
+ err_s ? err_s : "Error updating configuration");
+ free(err_s);
+ }
if (error) {
goto next_destroy_args;
}
@@ -1567,7 +1575,7 @@ dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[],
{
struct ds ds = DS_EMPTY_INITIALIZER;
struct dpctl_params dpctl_p;
- bool opt_parse_err = false;
+ bool error = false;
dpctl_command_handler *handler = (dpctl_command_handler *) aux;
@@ -1579,7 +1587,7 @@ dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[],
/* Parse options (like getopt). Unfortunately it does
* not seem a good idea to call getopt_long() here, since it uses global
* variables */
- while (argc > 1 && !opt_parse_err) {
+ while (argc > 1 && !error) {
const char *arg = argv[1];
if (!strncmp(arg, "--", 2)) {
/* Long option */
@@ -1593,13 +1601,13 @@ dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[],
dpctl_p.verbosity++;
} else {
ds_put_format(&ds, "Unrecognized option %s", argv[1]);
- opt_parse_err = true;
+ error = true;
}
} else if (arg[0] == '-' && arg[1] != '\0') {
/* Short option[s] */
const char *opt = &arg[1];
- while (*opt && !opt_parse_err) {
+ while (*opt && !error) {
switch (*opt) {
case 'm':
dpctl_p.verbosity++;
@@ -1609,7 +1617,7 @@ dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[],
break;
default:
ds_put_format(&ds, "Unrecognized option -%c", *opt);
- opt_parse_err = true;
+ error = true;
break;
}
opt++;
@@ -1619,22 +1627,26 @@ dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[],
break;
}
- if (opt_parse_err) {
+ if (error) {
break;
}
argv++;
argc--;
}
- if (!opt_parse_err) {
+ if (!error) {
dpctl_p.is_appctl = true;
dpctl_p.output = dpctl_unixctl_print;
dpctl_p.aux = &ds;
- handler(argc, argv, &dpctl_p);
+ error = handler(argc, argv, &dpctl_p) != 0;
}
- unixctl_command_reply(conn, ds_cstr(&ds));
+ if (error) {
+ unixctl_command_reply_error(conn, ds_cstr(&ds));
+ } else {
+ unixctl_command_reply(conn, ds_cstr(&ds));
+ }
ds_destroy(&ds);
}
--
2.1.3
More information about the dev
mailing list