[ovs-dev] [ovn-controller-vtep V6 3/7] ovn-controller-vtep: Add gateway module.

Alex Wang alexw at nicira.com
Mon Aug 10 02:50:43 UTC 2015


This commit adds the gateway module to ovn-controller-vtep.  The
module will register the physical switches to ovnsb as chassis and
constantly update the "vtep_logical_switches" column in Chassis table.

Limitation (Recorded in TODO file):

- Do not support reading multiple tunnel ips of physical switch.

Signed-off-by: Alex Wang <alexw at nicira.com>

---
V5->V6:
- simplify the chassis entry check as suggested by Russell.
- fix memory leak and double free pointed out by Russell.

V4->V5:
- rebase on top of master.
- adopt Russell's review suggestions, greatly simplify the code.

V3->V4:
- rebase to master.

V2->V3:
- since ovn-sb schema changes (removal of Gateway table), the gateway
  module code needs to be adapted.
- rebase to master.

PATCH->V2:
- split into separate commit.
- can register all physical switches controlled by vtep database.
---
 ovn/TODO                                           |    6 +
 ovn/controller-vtep/automake.mk                    |    2 +
 ovn/controller-vtep/gateway.c                      |  222 ++++++++++++++++++++
 .../{ovn-controller-vtep.h => gateway.h}           |   19 +-
 ovn/controller-vtep/ovn-controller-vtep.c          |   31 ++-
 ovn/controller-vtep/ovn-controller-vtep.h          |   20 ++
 tests/ovn-controller-vtep.at                       |  151 +++++++++++++
 7 files changed, 435 insertions(+), 16 deletions(-)
 create mode 100644 ovn/controller-vtep/gateway.c
 copy ovn/controller-vtep/{ovn-controller-vtep.h => gateway.h} (65%)

diff --git a/ovn/TODO b/ovn/TODO
index 509e5d0..356b3ba 100644
--- a/ovn/TODO
+++ b/ovn/TODO
@@ -74,3 +74,9 @@
    Epstein et al., "What's the Difference? Efficient Set
    Reconciliation Without Prior Context".  (I'm not yet aware of
    previous non-academic use of this technique.)
+
+** Support multiple tunnel encapsulations in Chassis.
+
+   So far, both ovn-controller and ovn-controller-vtep only allow
+   chassis to have one tunnel encapsulation entry.  We should extend
+   the implementation to support multiple tunnel encapsulations.
diff --git a/ovn/controller-vtep/automake.mk b/ovn/controller-vtep/automake.mk
index 7adda15..514cafa 100644
--- a/ovn/controller-vtep/automake.mk
+++ b/ovn/controller-vtep/automake.mk
@@ -1,5 +1,7 @@
 bin_PROGRAMS += ovn/controller-vtep/ovn-controller-vtep
 ovn_controller_vtep_ovn_controller_vtep_SOURCES = \
+	ovn/controller-vtep/gateway.c \
+	ovn/controller-vtep/gateway.h \
 	ovn/controller-vtep/ovn-controller-vtep.c \
 	ovn/controller-vtep/ovn-controller-vtep.h
 ovn_controller_vtep_ovn_controller_vtep_LDADD = ovn/lib/libovn.la lib/libopenvswitch.la vtep/libvtep.la
diff --git a/ovn/controller-vtep/gateway.c b/ovn/controller-vtep/gateway.c
new file mode 100644
index 0000000..025aff8
--- /dev/null
+++ b/ovn/controller-vtep/gateway.c
@@ -0,0 +1,222 @@
+/* Copyright (c) 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.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+#include "gateway.h"
+
+#include "lib/poll-loop.h"
+#include "lib/simap.h"
+#include "lib/sset.h"
+#include "lib/util.h"
+#include "openvswitch/vlog.h"
+#include "ovn/lib/ovn-sb-idl.h"
+#include "vtep/vtep-idl.h"
+#include "ovn-controller-vtep.h"
+
+VLOG_DEFINE_THIS_MODULE(gateway);
+
+/*
+ * Registers the physical switches in vtep to ovnsb as chassis.  For each
+ * physical switch in the vtep database, finds all vtep logical switches that
+ * are associated with the physical switch, and updates the corresponding
+ * chassis's 'vtep_logical_switches' column.
+ *
+ */
+
+/* Global revalidation sequence number, incremented at each call to
+ * 'revalidate_gateway()'. */
+static unsigned int gw_reval_seq;
+
+/* Maps all chassis created by the gateway module to their own reval_seq. */
+static struct simap gw_chassis_map = SIMAP_INITIALIZER(&gw_chassis_map);
+
+/* Creates and returns a new instance of 'struct sbrec_chassis'. */
+static const struct sbrec_chassis *
+create_chassis_rec(struct ovsdb_idl_txn *txn, const char *name,
+                   const char *encap_ip)
+{
+    const struct sbrec_chassis *chassis_rec;
+    struct sbrec_encap *encap_rec;
+
+    VLOG_INFO("add Chassis row for VTEP physical switch (%s)", name);
+
+    chassis_rec = sbrec_chassis_insert(txn);
+    sbrec_chassis_set_name(chassis_rec, name);
+    encap_rec = sbrec_encap_insert(txn);
+    sbrec_encap_set_type(encap_rec, OVN_SB_ENCAP_TYPE);
+    sbrec_encap_set_ip(encap_rec, encap_ip);
+    sbrec_chassis_set_encaps(chassis_rec, &encap_rec, 1);
+
+    return chassis_rec;
+}
+
+/* Revalidates chassis in ovnsb against vtep database.  Creates chassis for
+ * new vtep physical switch.  And removes chassis which no longer have
+ * physical switch in vtep.
+ *
+ * xxx: Support multiple tunnel encaps.
+ *
+ * */
+static void
+revalidate_gateway(struct controller_vtep_ctx *ctx)
+{
+    const struct vteprec_physical_switch *pswitch;
+
+    /* Increments the global revalidation sequence number. */
+    gw_reval_seq++;
+
+    ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
+                              "ovn-controller-vtep: updating vtep chassis");
+
+    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
+        const struct sbrec_chassis *chassis_rec;
+        struct simap_node *gw_node;
+        const char *encap_ip;
+
+        encap_ip = pswitch->n_tunnel_ips ? pswitch->tunnel_ips[0] : "";
+        gw_node = simap_find(&gw_chassis_map, pswitch->name);
+        chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
+        if (chassis_rec) {
+            if (!gw_node &&
+                (strcmp(chassis_rec->encaps[0]->type, OVN_SB_ENCAP_TYPE)
+                 || strcmp(chassis_rec->encaps[0]->ip, encap_ip))) {
+                VLOG_WARN("Chassis config changing on startup, make sure "
+                          "multiple chassis are not configured : %s/%s->%s/%s",
+                          chassis_rec->encaps[0]->type,
+                          chassis_rec->encaps[0]->ip,
+                          OVN_SB_ENCAP_TYPE, encap_ip);
+            }
+            /* Updates chassis's encap if anything changed. */
+            if (strcmp(chassis_rec->encaps[0]->type, OVN_SB_ENCAP_TYPE)) {
+                VLOG_WARN("Chassis for VTEP physical switch (%s) can only have "
+                          "encap type \"%s\"", pswitch->name, OVN_SB_ENCAP_TYPE);
+                sbrec_encap_set_type(chassis_rec->encaps[0], OVN_SB_ENCAP_TYPE);
+            }
+            if (strcmp(chassis_rec->encaps[0]->ip, encap_ip)) {
+                sbrec_encap_set_ip(chassis_rec->encaps[0], encap_ip);
+            }
+        } else {
+            if (gw_node) {
+                VLOG_WARN("Chassis for VTEP physical switch (%s) disappears, "
+                          "maybe deleted by ovn-sbctl, adding it back",
+                          pswitch->name);
+            }
+            /* Creates a new chassis for the VTEP physical switch. */
+            create_chassis_rec(ctx->ovnsb_idl_txn, pswitch->name, encap_ip);
+        }
+        /* Updates or creates the simap node for 'pswitch->name'. */
+        simap_put(&gw_chassis_map, pswitch->name, gw_reval_seq);
+    }
+
+    struct simap_node *iter, *next;
+    /* For 'gw_node' in 'gw_chassis_map' whose data is not
+     * 'gw_reval_seq', it means the corresponding physical switch no
+     * longer exist.  So, garbage collects them. */
+    SIMAP_FOR_EACH_SAFE (iter, next, &gw_chassis_map) {
+        if (iter->data != gw_reval_seq) {
+            const struct sbrec_chassis *chassis_rec;
+
+            chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, iter->name);
+            if (chassis_rec) {
+                sbrec_chassis_delete(chassis_rec);
+            }
+            simap_delete(&gw_chassis_map, iter);
+        }
+    }
+}
+
+/* Updates the 'vtep_logical_switches' column in the Chassis table based
+ * on vtep database configuration. */
+static void
+update_vtep_logical_switches(struct controller_vtep_ctx *ctx)
+{
+    const struct vteprec_physical_switch *pswitch;
+
+    ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, "ovn-controller-vtep: "
+                              "updating chassis's vtep_logical_switches");
+
+    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
+        const struct sbrec_chassis *chassis_rec =
+            get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
+        struct sset lswitches = SSET_INITIALIZER(&lswitches);
+        size_t i;
+
+        for (i = 0; i < pswitch->n_ports; i++) {
+            const struct vteprec_physical_port *port = pswitch->ports[i];
+            size_t j;
+
+            for (j = 0; j < port->n_vlan_bindings; j++) {
+                const struct vteprec_logical_switch *vtep_lswitch;
+
+                vtep_lswitch = port->value_vlan_bindings[j];
+                /* If not already in 'lswitches', records it. */
+                if (!sset_find(&lswitches, vtep_lswitch->name)) {
+                    sset_add(&lswitches, vtep_lswitch->name);
+                }
+            }
+        }
+
+        const char **ls_arr = sset_array(&lswitches);
+        sbrec_chassis_set_vtep_logical_switches(chassis_rec, ls_arr,
+                                                sset_count(&lswitches));
+        free(ls_arr);
+        sset_destroy(&lswitches);
+    }
+}
+
+
+void
+gateway_run(struct controller_vtep_ctx *ctx)
+{
+    if (!ctx->ovnsb_idl_txn) {
+        return;
+    }
+
+    revalidate_gateway(ctx);
+    update_vtep_logical_switches(ctx);
+}
+
+/* Destroys the chassis table entries for vtep physical switches.
+ * Returns true when all done. */
+bool
+gateway_cleanup(struct controller_vtep_ctx *ctx)
+{
+    static bool simap_destroyed = false;
+    const struct vteprec_physical_switch *pswitch;
+
+    if (!ctx->ovnsb_idl_txn) {
+        return false;
+    }
+
+    bool all_done = true;
+    ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, "ovn-controller-vtep: "
+                              "unregistering vtep chassis");
+    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
+        const struct sbrec_chassis *chassis_rec;
+
+        chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
+        if (!chassis_rec) {
+            continue;
+        }
+        all_done = false;
+        sbrec_chassis_delete(chassis_rec);
+    }
+    if (!simap_destroyed) {
+        simap_destroy(&gw_chassis_map);
+        simap_destroyed = true;
+    }
+
+    return all_done;
+}
diff --git a/ovn/controller-vtep/ovn-controller-vtep.h b/ovn/controller-vtep/gateway.h
similarity index 65%
copy from ovn/controller-vtep/ovn-controller-vtep.h
copy to ovn/controller-vtep/gateway.h
index bb01eb9..0086191 100644
--- a/ovn/controller-vtep/ovn-controller-vtep.h
+++ b/ovn/controller-vtep/gateway.h
@@ -13,19 +13,14 @@
  * limitations under the License.
  */
 
+#ifndef OVN_GATEWAY_H
+#define OVN_GATEWAY_H 1
 
-#ifndef OVN_CONTROLLER_VTEP_H
-#define OVN_CONTROLLER_VTEP_H 1
+#include <stdbool.h>
 
-struct ovsdb_idl;
-struct ovsdb_idl_txn;
+struct controller_vtep_ctx;
 
-struct controller_vtep_ctx {
-    struct ovsdb_idl *ovnsb_idl;
-    struct ovsdb_idl_txn *ovnsb_idl_txn;
+void gateway_run(struct controller_vtep_ctx *);
+bool gateway_cleanup(struct controller_vtep_ctx *);
 
-    struct ovsdb_idl *vtep_idl;
-    struct ovsdb_idl_txn *vtep_idl_txn;
-};
-
-#endif /* ovn/ovn-controller-vtep.h */
+#endif /* ovn/controller-gw/gateway.h */
diff --git a/ovn/controller-vtep/ovn-controller-vtep.c b/ovn/controller-vtep/ovn-controller-vtep.c
index 21a92de..93a0458 100644
--- a/ovn/controller-vtep/ovn-controller-vtep.c
+++ b/ovn/controller-vtep/ovn-controller-vtep.c
@@ -21,8 +21,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "ovn-controller-vtep.h"
-
 #include "command-line.h"
 #include "compiler.h"
 #include "daemon.h"
@@ -39,6 +37,9 @@
 #include "ovn/lib/ovn-sb-idl.h"
 #include "vtep/vtep-idl.h"
 
+#include "gateway.h"
+#include "ovn-controller-vtep.h"
+
 static unixctl_cb_func ovn_controller_vtep_exit;
 
 static void parse_options(int argc, char *argv[]);
@@ -86,13 +87,14 @@ main(int argc, char *argv[])
     /* Main loop. */
     exiting = false;
     while (!exiting) {
-        struct controller_vtep_ctx OVS_UNUSED ctx = {
+        struct controller_vtep_ctx ctx = {
             .vtep_idl = vtep_idl_loop.idl,
             .vtep_idl_txn = ovsdb_idl_loop_run(&vtep_idl_loop),
             .ovnsb_idl = ovnsb_idl_loop.idl,
             .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
         };
 
+        gateway_run(&ctx);
         unixctl_server_run(unixctl);
 
         unixctl_server_wait(unixctl);
@@ -104,8 +106,29 @@ main(int argc, char *argv[])
         poll_block();
     }
 
-    unixctl_server_destroy(unixctl);
+    /* It's time to exit.  Clean up the databases. */
+    bool done = false;
+    while (!done) {
+        struct controller_vtep_ctx ctx = {
+            .vtep_idl = vtep_idl_loop.idl,
+            .vtep_idl_txn = ovsdb_idl_loop_run(&vtep_idl_loop),
+            .ovnsb_idl = ovnsb_idl_loop.idl,
+            .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
+        };
 
+        /* Run all of the cleanup functions, even if one of them returns false.
+         * We're done if all of them return true. */
+        done = gateway_cleanup(&ctx);
+        if (done) {
+            poll_immediate_wake();
+        }
+
+        ovsdb_idl_loop_commit_and_wait(&vtep_idl_loop);
+        ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
+        poll_block();
+    }
+
+    unixctl_server_destroy(unixctl);
     ovsdb_idl_loop_destroy(&vtep_idl_loop);
     ovsdb_idl_loop_destroy(&ovnsb_idl_loop);
 
diff --git a/ovn/controller-vtep/ovn-controller-vtep.h b/ovn/controller-vtep/ovn-controller-vtep.h
index bb01eb9..435a730 100644
--- a/ovn/controller-vtep/ovn-controller-vtep.h
+++ b/ovn/controller-vtep/ovn-controller-vtep.h
@@ -17,6 +17,8 @@
 #ifndef OVN_CONTROLLER_VTEP_H
 #define OVN_CONTROLLER_VTEP_H 1
 
+#include "ovn/lib/ovn-sb-idl.h"
+
 struct ovsdb_idl;
 struct ovsdb_idl_txn;
 
@@ -28,4 +30,22 @@ struct controller_vtep_ctx {
     struct ovsdb_idl_txn *vtep_idl_txn;
 };
 
+/* VTEP needs what VTEP needs. */
+#define OVN_SB_ENCAP_TYPE "vxlan"
+#define VTEP_ENCAP_TYPE "vxlan_over_ipv4"
+
+static inline const struct sbrec_chassis *
+get_chassis_by_name(struct ovsdb_idl *ovnsb_idl, const char *chassis_id)
+{
+    const struct sbrec_chassis *chassis_rec;
+
+    SBREC_CHASSIS_FOR_EACH(chassis_rec, ovnsb_idl) {
+        if (!strcmp(chassis_rec->name, chassis_id)) {
+            break;
+        }
+    }
+
+    return chassis_rec;
+}
+
 #endif /* ovn/ovn-controller-vtep.h */
diff --git a/tests/ovn-controller-vtep.at b/tests/ovn-controller-vtep.at
index bcae89c..ed9cc50 100644
--- a/tests/ovn-controller-vtep.at
+++ b/tests/ovn-controller-vtep.at
@@ -1 +1,152 @@
 AT_BANNER([ovn_controller_vtep])
+
+# OVN_CONTROLLER_VTEP_START
+#
+# Starts the test with a setup with vtep device.
+#
+# Uses vtep-ovs to simulate the vtep switch 'br-vtep' with two physical ports
+# 'p0', 'p1'.
+#
+# Configures ovn-nb with a logical switch 'br-test'.
+#
+#
+m4_define([OVN_CONTROLLER_VTEP_START],
+  [OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+   OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+   OVS_DBDIR=`pwd`; export OVS_DBDIR
+   OVS_SYSCONFDIR=`pwd`; export OVS_SYSCONFDIR
+
+   dnl Create databases (ovn-nb, ovn-sb, vtep).
+   AT_CHECK([ovsdb-tool create vswitchd.db $abs_top_srcdir/vswitchd/vswitch.ovsschema])
+   for daemon in ovn-nb ovn-sb vtep; do
+      AT_CHECK([ovsdb-tool create $daemon.db $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
+   done
+
+   dnl Start ovsdb-server.
+   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file --remote=punix:$OVS_RUNDIR/db.sock vswitchd.db vtep.db ovn-nb.db ovn-sb.db], [0], [], [stderr])
+    ON_EXIT_UNQUOTED([kill `cat ovsdb-server.pid`])
+   AT_CHECK([[sed < stderr '
+/vlog|INFO|opened log file/d
+/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
+   AT_CAPTURE_FILE([ovsdb-server.log])
+
+   dnl Start ovs-vswitchd.
+   AT_CHECK([ovs-vswitchd --enable-dummy --disable-system --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif], [0], [], [stderr])
+   AT_CAPTURE_FILE([ovs-vswitchd.log])
+   ON_EXIT_UNQUOTED([kill `cat ovs-vswitchd.pid`])
+   AT_CHECK([[sed < stderr '
+/ovs_numa|INFO|Discovered /d
+/vlog|INFO|opened log file/d
+/vswitchd|INFO|ovs-vswitchd (Open vSwitch)/d
+/reconnect|INFO|/d
+/ofproto|INFO|using datapath ID/d
+/ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
+   AT_CHECK([ovs-vsctl -- add-br br-vtep \
+              -- set bridge br-vtep datapath-type=dummy other-config:datapath-id=fedcba9876543210 other-config:hwaddr=aa:55:aa:55:00:00 protocols=[[OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15]] fail-mode=secure \
+              -- add-port br-vtep p0 -- set Interface p0 type=dummy ofport_request=1 \
+              -- add-port br-vtep p1 -- set Interface p1 type=dummy ofport_request=2])
+
+   dnl Start ovs-vtep.
+   AT_CHECK([vtep-ctl add-ps br-vtep -- set Physical_Switch br-vtep tunnel_ips=1.2.3.4])
+   AT_CHECK([ovs-vtep --log-file=ovs-vtep.log --pidfile=ovs-vtep.pid --detach br-vtep \], [0], [], [stderr])
+   ON_EXIT_UNQUOTED([kill `cat ovs-vtep.pid`])
+   AT_CHECK([[sed < stderr '
+/vlog|INFO|opened log file/d']])
+   # waits until ovs-vtep starts up.
+   OVS_WAIT_UNTIL([test -n "`vtep-ctl show | grep Physical_Port`"])
+
+   dnl Start ovn-northd.
+   AT_CHECK([ovn-nbctl lswitch-add br-test])
+   AT_CHECK([ovn-northd --detach --pidfile --log-file --ovnnb-db=unix:$OVS_RUNDIR/db.sock --ovnsb-db=unix:$OVS_RUNDIR/db.sock], [0], [], [stderr])
+   ON_EXIT_UNQUOTED([kill `cat ovn-northd.pid`])
+   AT_CHECK([[sed < stderr '
+/vlog|INFO|opened log file/d']])
+   AT_CAPTURE_FILE([ovn-northd.log])
+
+   dnl Start ovn-controllger-vtep.
+   AT_CHECK([ovn-controller-vtep --detach --pidfile --log-file --vtep-db=unix:$OVS_RUNDIR/db.sock --ovnsb-db=unix:$OVS_RUNDIR/db.sock], [0], [], [stderr])
+   AT_CAPTURE_FILE([ovn-controller-vtep.log])
+   ON_EXIT_UNQUOTED([kill `cat ovn-controller-vtep.pid`])
+   AT_CHECK([[sed < stderr '
+/vlog|INFO|opened log file/d
+/reconnect|INFO|/d']])
+])
+
+# OVN_CONTROLLER_VTEP_STOP
+#
+# So many exits... Yeah, we started a lot daemons~
+#
+m4_define([OVN_CONTROLLER_VTEP_STOP],
+  [AT_CHECK([check_logs $1])
+   AT_CHECK([ovs-appctl -t ovs-vtep exit])
+   AT_CHECK([ovs-appctl -t ovn-northd exit])
+   AT_CHECK([ovs-appctl -t ovsdb-server exit])
+   AT_CHECK([ovs-appctl -t ovn-controller-vtep exit])
+   AT_CHECK([ovs-appctl -t ovs-vswitchd exit])])
+
+
+
+# tests chassis related updates.
+AT_SETUP([ovn-controller-vtep - test chassis])
+OVN_CONTROLLER_VTEP_START
+
+# verifies the initial ovn-sb db configuration.
+AT_CHECK([ovn-sbctl show], [0], [dnl
+Chassis br-vtep
+    Encap vxlan
+        ip: "1.2.3.4"
+])
+
+# deletes the chassis via ovn-sbctl and check that it is readded back
+# with the log.
+AT_CHECK([ovn-sbctl chassis-del br-vtep])
+OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
+AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log], [0], [dnl
+|WARN|Chassis for VTEP physical switch (br-vtep) disappears, maybe deleted by ovn-sbctl, adding it back
+])
+
+# changes the tunnel_ip on physical switch, watches the update of chassis's
+# encap.
+AT_CHECK([vtep-ctl set Physical_Switch br-vtep tunnel_ips=1.2.3.5])
+OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep 1\.2\.3\.5`"])
+AT_CHECK([ovn-sbctl --columns=ip list Encap | cut -d ':' -f2 | tr -d ' '], [0], [dnl
+"1.2.3.5"
+])
+
+# adds vlan_bindings to physical ports.
+AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0 -- bind-ls br-vtep p0 200 lswitch0 -- bind-ls br-vtep p1 300 lswitch0])
+OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep -- lswitch0`"])
+AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
+[["lswitch0"]]
+])
+
+# adds another logical switch and new vlan_bindings.
+AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 300 lswitch1])
+OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep -- lswitch1`"])
+AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' '], [0], [dnl
+[["lswitch0","lswitch1"]]
+])
+
+# unbinds one port from lswitch0, nothing should change.
+AT_CHECK([vtep-ctl unbind-ls br-vtep p0 200])
+OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=vlan_bindings list physical_port p0 | grep -- 200`"])
+AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
+[["lswitch0","lswitch1"]]
+])
+
+# unbinds all ports from lswitch0.
+AT_CHECK([vtep-ctl unbind-ls br-vtep p0 100 -- unbind-ls br-vtep p1 300])
+OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep -- br-vtep_lswitch0`"])
+AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
+[["lswitch1"]]
+])
+
+# unbinds all ports from lswitch1.
+AT_CHECK([vtep-ctl unbind-ls br-vtep p0 300])
+OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep -- br-vtep_lswitch1`"])
+AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' '], [0], [dnl
+[[]]
+])
+
+OVN_CONTROLLER_VTEP_STOP(["/Chassis for VTEP physical switch (br-vtep) disappears/d"])
+AT_CLEANUP
-- 
1.7.9.5




More information about the dev mailing list