mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 09:58:01 +00:00
ovs-vsctl: Add commands "add-bond-iface" and "del-bond-iface".
It was not too hard to build these commands using the database commands, but a few people have asked for them over the years, so here they are. Signed-off-by: Ben Pfaff <blp@ovn.org> Tested-by: Yifeng Sun <pkusunyifeng@gmail.com> Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
This commit is contained in:
parent
8e98556b56
commit
ec5ef1cf55
1
NEWS
1
NEWS
@ -9,6 +9,7 @@ Post-v2.9.0
|
||||
* ovs-ofctl now accepts and display table names in place of numbers. By
|
||||
default it always accepts names and in interactive use it displays them;
|
||||
use --names or --no-names to override. See ovs-ofctl(8) for details.
|
||||
- ovs-vsctl: New commands "add-bond-iface" and "del-bond-iface".
|
||||
|
||||
|
||||
v2.9.0 - xx xxx xxxx
|
||||
|
@ -313,6 +313,66 @@ CHECK_IFACES([a], [a1], [a2], [a3])
|
||||
OVS_VSCTL_CLEANUP
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([add-bond-iface and del-bond-iface])
|
||||
AT_KEYWORDS([ovs-vsctl])
|
||||
OVS_VSCTL_SETUP
|
||||
|
||||
# Create 2-interface bond.
|
||||
AT_CHECK([RUN_OVS_VSCTL(
|
||||
[add-br a],
|
||||
[add-bond a bond0 a1 a2])])
|
||||
CHECK_BRIDGES([a, a, 0])
|
||||
CHECK_PORTS([a], [bond0])
|
||||
CHECK_IFACES([a], [a1], [a2])
|
||||
|
||||
# Add interface a3 to bond.
|
||||
AT_CHECK([RUN_OVS_VSCTL([add-bond-iface bond0 a3])])
|
||||
CHECK_BRIDGES([a, a, 0])
|
||||
CHECK_PORTS([a], [bond0])
|
||||
CHECK_IFACES([a], [a1], [a2], [a3])
|
||||
|
||||
# Delete interface a2 from bond.
|
||||
AT_CHECK([RUN_OVS_VSCTL([del-bond-iface bond0 a2])])
|
||||
CHECK_BRIDGES([a, a, 0])
|
||||
CHECK_PORTS([a], [bond0])
|
||||
CHECK_IFACES([a], [a1], [a3])
|
||||
|
||||
# Add interface a2 to bond.
|
||||
AT_CHECK([RUN_OVS_VSCTL([add-bond-iface bond0 a2])])
|
||||
CHECK_BRIDGES([a, a, 0])
|
||||
CHECK_PORTS([a], [bond0])
|
||||
CHECK_IFACES([a], [a1], [a2], [a3])
|
||||
|
||||
# Delete interface a2 from bond.
|
||||
AT_CHECK([RUN_OVS_VSCTL([del-bond-iface a2])])
|
||||
CHECK_BRIDGES([a, a, 0])
|
||||
CHECK_PORTS([a], [bond0])
|
||||
CHECK_IFACES([a], [a1], [a3])
|
||||
|
||||
AT_CHECK([RUN_OVS_VSCTL([--if-exists del-bond-iface bond0 a4])])
|
||||
AT_CHECK([RUN_OVS_VSCTL([del-bond-iface bond0 a4])], [1], [],
|
||||
[ovs-vsctl: no interface named a4
|
||||
])
|
||||
AT_CHECK([RUN_OVS_VSCTL([del-bond-iface a4])], [1], [],
|
||||
[ovs-vsctl: no interface named a4
|
||||
])
|
||||
AT_CHECK([RUN_OVS_VSCTL_TOGETHER([add-port a a4], [del-bond-iface bond0 a4])], [1], [],
|
||||
[ovs-vsctl: port bond0 does not have an interface a4
|
||||
])
|
||||
AT_CHECK([RUN_OVS_VSCTL([--may-exist add-bond-iface bond0 a3])])
|
||||
AT_CHECK([RUN_OVS_VSCTL_TOGETHER([add-bond a bond1 b1 b2 b3], [--may-exist add-bond-iface bond1 a3])], [1], [],
|
||||
[ovs-vsctl: "--may-exist add-bond-iface bond1 a3" but a3 is actually attached to port bond0
|
||||
])
|
||||
AT_CHECK([RUN_OVS_VSCTL([add-bond-iface bond0 a3])], [1], [],
|
||||
[ovs-vsctl: cannot create an interface named a3 because an interface named a3 already exists on bridge a
|
||||
])
|
||||
AT_CHECK([RUN_OVS_VSCTL_TOGETHER([del-bond-iface a1], [del-bond-iface a3])], [1], [],
|
||||
[ovs-vsctl: cannot delete last interface from port bond0
|
||||
])
|
||||
|
||||
OVS_VSCTL_CLEANUP
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([add-br a b, add-port a a1, add-port b b1, del-port a a1])
|
||||
AT_KEYWORDS([ovs-vsctl])
|
||||
OVS_VSCTL_SETUP
|
||||
|
@ -274,26 +274,6 @@ Without \fB\-\-may\-exist\fR, attempting to create a port that exists
|
||||
is an error. With \fB\-\-may\-exist\fR, this command does nothing if
|
||||
\fIport\fR already exists on \fIbridge\fR and is not a bonded port.
|
||||
.
|
||||
.IP "[\fB\-\-fake\-iface\fR] \fBadd\-bond \fIbridge port iface\fR\&... [\fIcolumn\fR[\fB:\fIkey\fR]\fR=\fIvalue\fR]\&...\fR"
|
||||
Creates on \fIbridge\fR a new port named \fIport\fR that bonds
|
||||
together the network devices given as each \fIiface\fR. At least two
|
||||
interfaces must be named. If the interfaces are DPDK enabled then
|
||||
the transaction will need to include operations to explicitly set the
|
||||
interface type to 'dpdk'.
|
||||
.IP
|
||||
Optional arguments set values of column in the Port record created by
|
||||
the command. The syntax is the same as that for the \fBset\fR command
|
||||
(see \fBDatabase Commands\fR below).
|
||||
.IP
|
||||
With \fB\-\-fake\-iface\fR, a fake interface with the name \fIport\fR is
|
||||
created. This should only be used for compatibility with legacy
|
||||
software that requires it.
|
||||
.IP
|
||||
Without \fB\-\-may\-exist\fR, attempting to create a port that exists
|
||||
is an error. With \fB\-\-may\-exist\fR, this command does nothing if
|
||||
\fIport\fR already exists on \fIbridge\fR and bonds together exactly
|
||||
the specified interfaces.
|
||||
.
|
||||
.IP "[\fB\-\-if\-exists\fR] \fBdel\-port \fR[\fIbridge\fR] \fIport\fR"
|
||||
Deletes \fIport\fR. If \fIbridge\fR is omitted, \fIport\fR is removed
|
||||
from whatever bridge contains it; if \fIbridge\fR is specified, it
|
||||
@ -318,6 +298,56 @@ no effect.
|
||||
Prints the name of the bridge that contains \fIport\fR on standard
|
||||
output.
|
||||
.
|
||||
.SS "Bond Commands"
|
||||
.
|
||||
These commands work with ports that have more than one interface,
|
||||
which Open vSwitch calls ``bonds.''
|
||||
.
|
||||
.IP "[\fB\-\-fake\-iface\fR] \fBadd\-bond \fIbridge port iface\fR\&... [\fIcolumn\fR[\fB:\fIkey\fR]\fR=\fIvalue\fR]\&...\fR"
|
||||
Creates on \fIbridge\fR a new port named \fIport\fR that bonds
|
||||
together the network devices given as each \fIiface\fR. At least two
|
||||
interfaces must be named. If the interfaces are DPDK enabled then
|
||||
the transaction will need to include operations to explicitly set the
|
||||
interface type to 'dpdk'.
|
||||
.IP
|
||||
Optional arguments set values of column in the Port record created by
|
||||
the command. The syntax is the same as that for the \fBset\fR command
|
||||
(see \fBDatabase Commands\fR below).
|
||||
.IP
|
||||
With \fB\-\-fake\-iface\fR, a fake interface with the name \fIport\fR is
|
||||
created. This should only be used for compatibility with legacy
|
||||
software that requires it.
|
||||
.IP
|
||||
Without \fB\-\-may\-exist\fR, attempting to create a port that exists
|
||||
is an error. With \fB\-\-may\-exist\fR, this command does nothing if
|
||||
\fIport\fR already exists on \fIbridge\fR and bonds together exactly
|
||||
the specified interfaces.
|
||||
.
|
||||
.IP "[\fB\-\-may\-exist\fR] \fBadd\-bond\-iface \fIbond iface\fR"
|
||||
Adds \fIiface\fR as a new bond interface to the existing port
|
||||
\fIbond\fR. If \fIbond\fR previously had only one port, this
|
||||
transforms it into a bond.
|
||||
.IP
|
||||
Without \fB\-\-may\-exist\fR, attempting to add an \fIiface\fR that is
|
||||
already part of \fIbond\fR is an error. With \fB\-\-may\-exist\fR,
|
||||
this command does nothing if \fIiface\fR is already part of
|
||||
\fIbond\fR. (It is still an error if \fIiface\fR is an interface of
|
||||
some other port or bond.)
|
||||
.
|
||||
.IP "[\fB\-\-if\-exists\fR] \fBdel\-bond\-iface\fR [\fIbond\fR] \fIiface\fR"
|
||||
Removes \fIiface\fR from its port. If \fIbond\fR is omitted,
|
||||
\fIiface\fR is removed from whatever port contains it; if \fIbond\fR
|
||||
is specified, it must be the port that contains \fIbond\fR.
|
||||
.IP
|
||||
If removing \fIiface\fR causes its port to have only a single
|
||||
interface, then that port transforms from a bond into an ordinary
|
||||
port. It is an error if \fIiface\fR is the only interface in its
|
||||
port.
|
||||
.IP
|
||||
Without \fB\-\-if\-exists\fR, attempting to delete an interface that
|
||||
does not exist is an error. With \fB\-\-if\-exists\fR, attempting to
|
||||
delete an interface that does not exist has no effect.
|
||||
.
|
||||
.SS "Interface Commands"
|
||||
.
|
||||
These commands examine the interfaces attached to an Open vSwitch
|
||||
|
@ -1636,6 +1636,71 @@ cmd_add_bond(struct ctl_context *ctx)
|
||||
&ctx->argv[n_ifaces + 3], ctx->argc - 3 - n_ifaces);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_add_bond_iface(struct ctl_context *ctx)
|
||||
{
|
||||
vsctl_context_populate_cache(ctx);
|
||||
|
||||
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
||||
bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
|
||||
struct vsctl_port *port = find_port(vsctl_ctx, ctx->argv[1], true);
|
||||
|
||||
const char *iface_name = ctx->argv[2];
|
||||
if (may_exist) {
|
||||
struct vsctl_iface *iface = find_iface(vsctl_ctx, iface_name, false);
|
||||
if (iface) {
|
||||
if (iface->port == port) {
|
||||
return;
|
||||
}
|
||||
char *command = vsctl_context_to_string(ctx);
|
||||
ctl_fatal("\"%s\" but %s is actually attached to port %s",
|
||||
command, iface_name, iface->port->port_cfg->name);
|
||||
}
|
||||
}
|
||||
check_conflicts(vsctl_ctx, iface_name,
|
||||
xasprintf("cannot create an interface named %s",
|
||||
iface_name));
|
||||
|
||||
struct ovsrec_interface *iface = ovsrec_interface_insert(ctx->txn);
|
||||
ovsrec_interface_set_name(iface, iface_name);
|
||||
ovsrec_port_update_interfaces_addvalue(port->port_cfg, iface);
|
||||
post_db_reload_expect_iface(iface);
|
||||
add_iface_to_cache(vsctl_ctx, port, iface);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_del_bond_iface(struct ctl_context *ctx)
|
||||
{
|
||||
vsctl_context_populate_cache(ctx);
|
||||
|
||||
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
||||
const char *iface_name = ctx->argv[ctx->argc - 1];
|
||||
bool must_exist = !shash_find(&ctx->options, "--if-exists");
|
||||
struct vsctl_iface *iface = find_iface(vsctl_ctx, iface_name, must_exist);
|
||||
if (!iface) {
|
||||
ovs_assert(!must_exist);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *port_name = ctx->argc > 2 ? ctx->argv[1] : NULL;
|
||||
if (port_name) {
|
||||
struct vsctl_port *port = find_port(vsctl_ctx, port_name, true);
|
||||
if (iface->port != port) {
|
||||
ctl_fatal("port %s does not have an interface %s",
|
||||
port_name, iface_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (ovs_list_is_short(&iface->port->ifaces)) {
|
||||
ctl_fatal("cannot delete last interface from port %s",
|
||||
iface->port->port_cfg->name);
|
||||
}
|
||||
|
||||
ovsrec_port_update_interfaces_delvalue(iface->port->port_cfg,
|
||||
iface->iface_cfg);
|
||||
del_cached_iface(vsctl_ctx, iface);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_del_port(struct ctl_context *ctx)
|
||||
{
|
||||
@ -2749,13 +2814,19 @@ static const struct ctl_command_syntax vsctl_commands[] = {
|
||||
RO},
|
||||
{"add-port", 2, INT_MAX, "BRIDGE NEW-PORT [COLUMN[:KEY]=VALUE]...",
|
||||
pre_get_info, cmd_add_port, NULL, "--may-exist", RW},
|
||||
{"add-bond", 4, INT_MAX,
|
||||
"BRIDGE NEW-BOND-PORT SYSIFACE... [COLUMN[:KEY]=VALUE]...", pre_get_info,
|
||||
cmd_add_bond, NULL, "--may-exist,--fake-iface", RW},
|
||||
{"del-port", 1, 2, "[BRIDGE] PORT|IFACE", pre_get_info, cmd_del_port, NULL,
|
||||
"--if-exists,--with-iface", RW},
|
||||
{"port-to-br", 1, 1, "PORT", pre_get_info, cmd_port_to_br, NULL, "", RO},
|
||||
|
||||
/* Bond commands. */
|
||||
{"add-bond", 4, INT_MAX,
|
||||
"BRIDGE BOND IFACE... [COLUMN[:KEY]=VALUE]...", pre_get_info,
|
||||
cmd_add_bond, NULL, "--may-exist,--fake-iface", RW},
|
||||
{"add-bond-iface", 2, 2, "BOND IFACE", pre_get_info, cmd_add_bond_iface,
|
||||
NULL, "--may-exist", RW},
|
||||
{"del-bond-iface", 1, 2, "[BOND] IFACE", pre_get_info, cmd_del_bond_iface,
|
||||
NULL, "--if-exists", RW},
|
||||
|
||||
/* Interface commands. */
|
||||
{"list-ifaces", 1, 1, "BRIDGE", pre_get_info, cmd_list_ifaces, NULL, "",
|
||||
RO},
|
||||
|
Loading…
x
Reference in New Issue
Block a user