When the option is set to a comma separated list of chassis names, OVN
will attempt to bind the port at any number of other locations in
addition to the main chassis.
This is useful in live migration scenarios where it's important to
prepare the environment for workloads to move to, avoiding costly flow
configuration at the moment of the final port binding location change.
This may also be useful in port mirroring scenarios.
Corresponding database fields (pb->additional_chassis,
pb->requested_additional_chassis, pb->additional_encap) are introduced
as part of the patch. These are similar to fields designed to track the
main chassis (->chassis, ->requested_chassis, ->encap). But because we
support any number of additional chassis, these fields are lists.
Signed-off-by: Ihar Hrachyshka
---
NEWS | 1 +
controller/binding.c | 294 ---
controller/lport.c | 46 ---
controller/lport.h | 11 +-
northd/northd.c | 62 ++---
northd/ovn-northd.c | 4 +-
ovn-nb.xml | 20 ++-
ovn-sb.ovsschema | 17 ++-
ovn-sb.xml | 63 --
tests/ovn.at | 218
10 files changed, 632 insertions(+), 104 deletions(-)
diff --git a/NEWS b/NEWS
index f18a7d766..856d683f3 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ Post v22.03.0
explicitly request routers to reply to any ARP/ND request for a VIP
(when set to "all") and only for reachable VIPs (when set to "reachable"
or by default).
+ - Support list of chassis for Logical_Switch_Port:options:requested-chassis.
OVN v22.03.0 - 11 Mar 2022
--
diff --git a/controller/binding.c b/controller/binding.c
index 6bdbe9912..066eec9a5 100644
--- a/controller/binding.c
+++ b/controller/binding.c
@@ -930,6 +930,130 @@ claimed_lport_set_up(const struct sbrec_port_binding *pb,
}
}
+typedef void (*set_func)(const struct sbrec_port_binding *pb,
+ const struct sbrec_encap *);
+
+static bool
+update_port_encap_if_needed(const struct sbrec_port_binding *pb,
+const struct sbrec_chassis *chassis_rec,
+const struct ovsrec_interface *iface_rec,
+bool sb_readonly)
+{
+const struct sbrec_encap *encap_rec =
+sbrec_get_port_encap(chassis_rec, iface_rec);
+if ((encap_rec && pb->encap != encap_rec) ||
+(!encap_rec && pb->encap)) {
+if (sb_readonly) {
+return false;
+}
+sbrec_port_binding_set_encap(pb, encap_rec);
+}
+return true;
+}
+
+static void
+append_additional_encap(const struct sbrec_port_binding *pb,
+const struct sbrec_encap *encap)
+{
+struct sbrec_encap **additional_encap = xmalloc(
+(pb->n_additional_encap + 1) * (sizeof *additional_encap));
+memcpy(additional_encap, pb->additional_encap,
+ pb->n_additional_encap * (sizeof *additional_encap));
+additional_encap[pb->n_additional_encap] = (struct sbrec_encap *) encap;
+sbrec_port_binding_set_additional_encap(
+pb, additional_encap, pb->n_additional_encap + 1);
+free(additional_encap);
+}
+
+static void
+remove_additional_encap_for_chassis(const struct sbrec_port_binding *pb,
+const struct sbrec_chassis *chassis_rec)
+{
+struct sbrec_encap **additional_encap = xmalloc(
+pb->n_additional_encap * (sizeof *additional_encap));
+
+int idx = 0;
+for (int i = 0; i < pb->n_additional_encap; i++) {
+if (!strcmp(pb->additional_encap[i]->chassis_name,
+chassis_rec->name)) {
+continue;
+}
+additional_encap[idx++] = pb->additional_encap[i];
+}
+sbrec_port_binding_set_additional_encap(pb, additional_encap, idx);
+free(additional_encap);
+}
+
+static bool
+update_port_additional_encap_if_needed(
+const struct sbrec_port_binding *pb,
+const struct sbrec_chassis *chassis_rec,
+const struct ovsrec_interface *iface_rec,
+bool sb_readonly)
+{
+const struct sbrec_encap *encap_rec =
+sbrec_get_port_encap(chassis_rec, iface_rec);
+if (encap_rec) {
+for (int i = 0; i < pb->n_additional_encap; i++) {
+if (pb->additional_encap[i] == encap_rec) {
+return true;
+}
+}
+if (sb_readonly) {
+return false;
+}
+append_additional_encap(pb, encap_rec);
+}
+return true;
+}
+
+static bool
+is_additional_chassis(const struct sbrec_port_binding *pb,
+ const struct sbrec_chassis *chassis_rec)
+{
+for (int i = 0; i < pb->n_additional_chassis; i++) {
+if (pb->additional_chassis[i] == chassis_rec) {
+return true;
+}
+}
+return false;
+}
+
+static void
+append_additional_chassis(const struct sbrec_port_binding *pb,
+ cons