Skip to content

Commit

Permalink
ovn: support requested-chassis option for logical switch ports
Browse files Browse the repository at this point in the history
This patch adds support for a "requested-chassis" option for logical
switch ports. If set, the only chassis that will claim this port is the
chassis identfied by this option; if already bound by another chassis,
it will be released.

The primary benefit of this enhancement is allowing a CMS to prevent
"thrashing" in the southbound database during live migration by keeping
the original chassis from attempting to re-bind a port that is in the
process of migrating.

This would also allow (with some additional work) RBAC to be applied
to the Port_Binding table for additional security.

Signed-off-by: Lance Richardson <[email protected]>
Signed-off-by: Russell Bryant <[email protected]>
  • Loading branch information
hlrichardson authored and russellb committed Aug 21, 2017
1 parent 2e1fca6 commit 63d91af
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 1 deletion.
15 changes: 14 additions & 1 deletion ovn/controller/binding.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,12 @@ consider_local_datapath(struct controller_ctx *ctx,
}

if (ctx->ovnsb_idl_txn) {
if (our_chassis) {
const char *vif_chassis = smap_get(&binding_rec->options,
"requested-chassis");
bool can_bind = !vif_chassis || !vif_chassis[0] ||
!strcmp(vif_chassis, chassis_rec->name);

if (can_bind && our_chassis) {
if (binding_rec->chassis != chassis_rec) {
if (binding_rec->chassis) {
VLOG_INFO("Changing chassis for lport %s from %s to %s.",
Expand All @@ -461,6 +466,14 @@ consider_local_datapath(struct controller_ctx *ctx,
VLOG_INFO("Releasing lport %s from this chassis.",
binding_rec->logical_port);
sbrec_port_binding_set_chassis(binding_rec, NULL);
} else if (our_chassis) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
VLOG_INFO_RL(&rl,
"Not claiming lport %s, chassis %s "
"requested-chassis %s",
binding_rec->logical_port,
chassis_rec->name,
vif_chassis);
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions ovn/ovn-nb.xml
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,14 @@
(empty string)
</p>

<column name="options" key="requested-chassis">
If set, identifies a specific chassis (by name) that is allowed to
bind this port. Using this option will prevent thrashing between
two chassis trying to bind the same port during a live migration.
It can also prevent similar thrashing due to a mis-configuration,
if a port is accidentally created on more than one chassis.
</column>

<column name="options" key="qos_max_rate">
If set, indicates the maximum rate for data sent from this interface,
in bit/s. The traffic will be shaped according to this limit.
Expand Down
8 changes: 8 additions & 0 deletions ovn/ovn-sb.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2159,6 +2159,14 @@ tcp.flags = RST;
(empty string)
</p>

<column name="options" key="requested-chassis">
If set, identifies a specific chassis (by name) that is allowed to
bind this port. Using this option will prevent thrashing between
two chassis trying to bind the same port during a live migration.
It can also prevent similar thrashing due to a mis-configuration,
if a port is accidentally created on more than one chassis.
</column>

<column name="options" key="qos_max_rate">
If set, indicates the maximum rate for data sent from this interface,
in bit/s. The traffic will be shaped according to this limit.
Expand Down
59 changes: 59 additions & 0 deletions tests/ovn.at
Original file line number Diff line number Diff line change
Expand Up @@ -8281,3 +8281,62 @@ AT_CHECK([grep "Releasing lport" gw1/ovn-controller.log], [1], [])
OVN_CLEANUP([gw1],[gw2],[hv1])

AT_CLEANUP

AT_SETUP([ovn -- options:requested-chassis for logical port])
ovn_start

net_add n1

ovn-nbctl ls-add ls0
ovn-nbctl lsp-add ls0 lsp0

# create two hypervisors, each with one vif port
sim_add hv1
as hv1
ovs-vsctl add-br br-phys
ovn_attach n1 br-phys 192.168.0.11
ovs-vsctl -- add-port br-int hv1-vif0

sim_add hv2
as hv2
ovs-vsctl add-br br-phys
ovn_attach n1 br-phys 192.168.0.12
ovs-vsctl -- add-port br-int hv2-vif0

# Allow only chassis hv1 to bind logical port lsp0.
ovn-nbctl lsp-set-options lsp0 requested-chassis=hv1

# Allow some time for ovn-northd and ovn-controller to catch up.
ovn-nbctl --wait=hv --timeout=3 sync

# Retrieve hv1 and hv2 chassis UUIDs from southbound database
hv1_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv1)
hv2_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv2)

# (1) Chassis hv2 should not bind lsp0 when requested-chassis is hv1.
echo "verifying that hv2 does not bind lsp0 when hv2 physical/logical mapping is added"
as hv2
ovs-vsctl set interface hv2-vif0 external-ids:iface-id=lsp0

OVS_WAIT_UNTIL([test 1 = $(grep -c "Not claiming lport lsp0" hv2/ovn-controller.log)])
AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x], [0], [])

# (2) Chassis hv1 should bind lsp0 when physical to logical mapping exists on hv1.
echo "verifying that hv1 binds lsp0 when hv1 physical/logical mapping is added"
as hv1
ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0

OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0" hv1/ovn-controller.log)])
AT_CHECK([test $(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = "$hv1_uuid"], [0], [])

# (3) Chassis hv1 should release lsp0 binding and chassis hv2 should bind lsp0 when
# the requested chassis for lsp0 is changed from hv1 to hv2.
echo "verifying that lsp0 binding moves when requested-chassis is changed"

ovn-nbctl lsp-set-options lsp0 requested-chassis=hv2
OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from this chassis" hv1/ovn-controller.log)])
OVS_WAIT_UNTIL([test $(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = "$hv2_uuid"])

OVN_CLEANUP([hv1],[hv2])

AT_CLEANUP

0 comments on commit 63d91af

Please sign in to comment.