From 10500639d5756986a587116ca1b8b42764f5ace2 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 17 Oct 2011 11:24:37 -0700 Subject: [PATCH] ovs-dpctl: Add new "set-if" command. I have found this useful for testing tunnel configuration. --- NEWS | 2 + utilities/ovs-dpctl.8.in | 13 ++++- utilities/ovs-dpctl.c | 101 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 113 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 2bd710bc..264581c2 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ Post-v1.2.0 information about all interfaces with CFM enabled. - If no argument is provided for "lacp/show", displays detailed information about all ports with LACP enabled. + - ovs-dpctl: + - New "set-if" command to modify a datapath port's configuration. - ovs-vswitchd: - The software switch now supports 255 OpenFlow tables, instead of just one. By default, only table 0 is consulted, but the diff --git a/utilities/ovs-dpctl.8.in b/utilities/ovs-dpctl.8.in index ee124484..bf7f97f6 100644 --- a/utilities/ovs-dpctl.8.in +++ b/utilities/ovs-dpctl.8.in @@ -34,11 +34,12 @@ default provider \fBsystem\fR is assumed. The following commands manage datapaths. . .TP -\fBadd\-dp \fIdp\fR [\fInetdev\fR...] +\fBadd\-dp \fIdp\fR [\fInetdev\fR[\fB,\fIoption\fR]...] Creates datapath \fIdp\fR, with a local port also named \fIdp\fR. This will fail if a network device \fIdp\fR already exists. .IP -If \fInetdev\fRs are specified, \fBovs\-dpctl\fR adds them to the datapath. +If \fInetdev\fRs are specified, \fBovs\-dpctl\fR adds them to the +new datapath, just as if \fBadd\-if\fR was specified. . .TP \fBdel\-dp \fIdp\fR @@ -68,6 +69,14 @@ Adds an arbitrary key-value option to the port's configuration. \fBovs\-vswitchd.conf.db\fR(5) documents the available port types and options. . +.IP "\fBset\-if \fIdp port\fR[\fB,\fIoption\fR]..." +Reconfigures each \fIport\fR in \fIdp\fR as specified. An +\fIoption\fR of the form \fIkey\fB=\fIvalue\fR adds the specified +key-value option to the port or overrides an existing key's value. An +\fIoption\fR of the form \fIkey\fB=\fR, that is, without a value, +deletes the key-value named \fIkey\fR. The type of a port cannot be +changed, so \fBtype=\fItype\fR is only allowed if \fItype\fR is the +port's existing type. .TP \fBdel\-if \fIdp netdev\fR... Removes each \fInetdev\fR from the list of network devices datapath diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c index d78fb317..499d4945 100644 --- a/utilities/ovs-dpctl.c +++ b/utilities/ovs-dpctl.c @@ -131,12 +131,16 @@ usage(void) " add-dp DP [IFACE...] add new datapath DP (with IFACEs)\n" " del-dp DP delete local datapath DP\n" " add-if DP IFACE... add each IFACE as a port on DP\n" + " set-if DP IFACE... reconfigure each IFACE within DP\n" " del-if DP IFACE... delete each IFACE from DP\n" " dump-dps display names of all datapaths\n" " show show basic info on all datapaths\n" " show DP... show basic info on each DP\n" " dump-flows DP display flows in DP\n" - " del-flows DP delete all flows from DP\n", + " del-flows DP delete all flows from DP\n" + "Each IFACE on add-dp, add-if, and set-if may be followed by\n" + "comma-separated options. See ovs-dpctl(8) for syntax, or the\n" + "Interface table in ovs-vswitchd.conf.db(5) for an options list.\n", program_name, program_name); vlog_usage(); printf("\nOther options:\n" @@ -234,6 +238,7 @@ do_add_if(int argc OVS_UNUSED, char *argv[]) if (!name) { ovs_error(0, "%s is not a valid network device name", argv[i]); + failure = true; continue; } @@ -287,6 +292,99 @@ next: } } +static void +do_set_if(int argc, char *argv[]) +{ + bool failure = false; + struct dpif *dpif; + int i; + + run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath"); + for (i = 2; i < argc; i++) { + struct netdev *netdev = NULL; + struct dpif_port dpif_port; + char *save_ptr = NULL; + char *type = NULL; + const char *name; + struct shash args; + char *option; + int error; + + name = strtok_r(argv[i], ",", &save_ptr); + if (!name) { + ovs_error(0, "%s is not a valid network device name", argv[i]); + failure = true; + continue; + } + + /* Get the port's type from the datapath. */ + error = dpif_port_query_by_name(dpif, name, &dpif_port); + if (error) { + ovs_error(error, "%s: failed to query port in %s", name, argv[1]); + goto next; + } + type = xstrdup(dpif_port.type); + dpif_port_destroy(&dpif_port); + + /* Retrieve its existing configuration. */ + error = netdev_open(name, type, &netdev); + if (error) { + ovs_error(error, "%s: failed to open network device", name); + goto next; + } + + shash_init(&args); + error = netdev_get_config(netdev, &args); + if (error) { + ovs_error(error, "%s: failed to fetch configuration", name); + goto next; + } + + /* Parse changes to configuration. */ + while ((option = strtok_r(NULL, ",", &save_ptr)) != NULL) { + char *save_ptr_2 = NULL; + char *key, *value; + + key = strtok_r(option, "=", &save_ptr_2); + value = strtok_r(NULL, "", &save_ptr_2); + if (!value) { + value = ""; + } + + if (!strcmp(key, "type")) { + if (strcmp(value, type)) { + ovs_error(0, "%s: can't change type from %s to %s", + name, type, value); + failure = true; + } + } else if (value[0] == '\0') { + free(shash_find_and_delete(&args, key)); + } else { + free(shash_replace(&args, key, xstrdup(value))); + } + } + + /* Update configuration. */ + error = netdev_set_config(netdev, &args); + smap_destroy(&args); + if (error) { + ovs_error(error, "%s: failed to configure network device", name); + goto next; + } + +next: + free(type); + netdev_close(netdev); + if (error) { + failure = true; + } + } + dpif_close(dpif); + if (failure) { + exit(EXIT_FAILURE); + } +} + static bool get_port_number(struct dpif *dpif, const char *name, uint16_t *port) { @@ -600,6 +698,7 @@ static const struct command all_commands[] = { { "del-dp", 1, 1, do_del_dp }, { "add-if", 2, INT_MAX, do_add_if }, { "del-if", 2, INT_MAX, do_del_if }, + { "set-if", 2, INT_MAX, do_set_if }, { "dump-dps", 0, 0, do_dump_dps }, { "show", 0, INT_MAX, do_show }, { "dump-flows", 1, 1, do_dump_flows }, -- 2.30.2