[ovs-dev] [ovn-controller-vtep V3 5/7] ovn-controller-vtep: Add gateway module.

Alex Wang alexw at nicira.com
Tue Jul 14 03:22:41 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 "logical_switches" column in Chassis table.

Limitation:

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

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

---
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/controller-vtep/automake.mk                    |    2 +
 ovn/controller-vtep/gateway.c                      |  281 ++++++++++++++++++++
 .../{ovn-controller-vtep.h => gateway.h}           |   15 +-
 ovn/controller-vtep/ovn-controller-vtep.c          |    3 +
 ovn/controller-vtep/ovn-controller-vtep.h          |   18 ++
 tests/ovn-controller-vtep.at                       |  151 +++++++++++
 6 files changed, 461 insertions(+), 9 deletions(-)
 create mode 100644 ovn/controller-vtep/gateway.c
 copy ovn/controller-vtep/{ovn-controller-vtep.h => gateway.h} (72%)

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..54a5b63
--- /dev/null
+++ b/ovn/controller-vtep/gateway.c
@@ -0,0 +1,281 @@
+/* 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/hash.h"
+#include "lib/hmap.h"
+#include "lib/poll-loop.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 logical switches that
+ * are associated with the physical switch, and updates the corresponding
+ * chassis's 'logical_switches' column.
+ *
+ */
+
+/* Global revalidation sequence number, incremented at each call to
+ * 'revalidate_gateway()'. */
+static uint64_t gw_reval_seq;
+
+/* Represents a chassis added by the gateway module.  The 'reval_seq'
+ * is increment each time a chassis is revalidated.  Chassis whose 'reval_seq'
+ * not equal to 'gw_reval_seq' will be removed. */
+struct gw_chassis {
+    struct hmap_node hmap_node; /* In 'gw_chassis'. */
+    char *name;                 /* Name of the Chassis. */
+    uint64_t reval_seq;         /* Chassis revalidation sequence number. */
+};
+
+/* Contains all chassis created by the gateway module. */
+static struct hmap gw_chassis_map = HMAP_INITIALIZER(&gw_chassis_map);
+
+/* Searchs 'gw_chassis_map' for chassis 'name' and returns the pointer.
+ * Returns NULL, if the chassis is not found. */
+static struct gw_chassis *
+get_gw_chassis(const char *name)
+{
+    struct gw_chassis *gw_chassis;
+
+    HMAP_FOR_EACH_WITH_HASH (gw_chassis, hmap_node, hash_string(name, 0),
+                             &gw_chassis_map) {
+        if (!strcmp(gw_chassis->name, name)) {
+            return gw_chassis;
+        }
+    }
+
+    return NULL;
+}
+
+/* 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;
+
+    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;
+    struct ovsdb_idl_txn *txn;
+    struct gw_chassis *iter, *next;
+    int retval;
+
+    /* Increments the global revalidation sequence number. */
+    gw_reval_seq++;
+
+    txn = ovsdb_idl_txn_create(ctx->ovnsb_idl);
+    ovsdb_idl_txn_add_comment(txn, "ovn-controller-vtep: updating vtep chassis");
+
+    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
+        const struct sbrec_chassis *chassis_rec;
+        struct gw_chassis *gw_chassis;
+        const char *encap_ip;
+
+        encap_ip = pswitch->n_tunnel_ips ? pswitch->tunnel_ips[0] : "";
+        gw_chassis = get_gw_chassis(pswitch->name);
+        chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
+        if (gw_chassis && !chassis_rec) {
+            VLOG_WARN("Chassis for VTEP physical switch (%s) disappears, "
+                      "maybe deleted by ovn-sbctl, adding it back",
+                      pswitch->name);
+            create_chassis_rec(txn, pswitch->name, encap_ip);
+        } else if (!gw_chassis && chassis_rec) {
+            VLOG_WARN("Chassis for new VTEP physical switch (%s) has already "
+                      "been added, maybe by ovn-sbctl", pswitch->name);
+            if (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);
+                VLOG_WARN("Skip adding chassis for physical switch (%s)",
+                          pswitch->name);
+                continue;
+            }
+            gw_chassis = xmalloc(sizeof *gw_chassis);
+            gw_chassis->name = xstrdup(pswitch->name);
+            hmap_insert(&gw_chassis_map, &gw_chassis->hmap_node,
+                        hash_string(gw_chassis->name, 0));
+        } else if (gw_chassis && chassis_rec) {
+            /* 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 {
+            /* Creates a new chassis for the VTEP physical switch and a new
+             * gw_chassis record. */
+            create_chassis_rec(txn, pswitch->name, encap_ip);
+            gw_chassis = xmalloc(sizeof *gw_chassis);
+            gw_chassis->name = xstrdup(pswitch->name);
+            hmap_insert(&gw_chassis_map, &gw_chassis->hmap_node,
+                        hash_string(gw_chassis->name, 0));
+        }
+        /* Updates the 'gw_chassis's revalidation seq number to prevent
+         * it from being garbage collected. */
+        gw_chassis->reval_seq = gw_reval_seq;
+    }
+
+    /* For 'gw_chassis' in 'gw_chassis_map' whose reval_seq is not
+     * 'gw_reval_seq', it means the corresponding physical switch no
+     * longer exist.  So, garbage collects them. */
+    HMAP_FOR_EACH_SAFE (iter, next, hmap_node, &gw_chassis_map) {
+        if (iter->reval_seq != 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);
+            }
+            hmap_remove(&gw_chassis_map, &iter->hmap_node);
+            free(iter->name);
+            free(iter);
+        }
+    }
+
+    retval = ovsdb_idl_txn_commit_block(txn);
+    if (retval != TXN_SUCCESS && retval != TXN_UNCHANGED) {
+        VLOG_INFO("Problem registering chassis: %s",
+                  ovsdb_idl_txn_status_to_string(retval));
+        poll_immediate_wake();
+    }
+    ovsdb_idl_txn_destroy(txn);
+}
+
+/* Updates the logical switches in the Chassis table based on vtep database
+ * configuration. */
+static void
+update_logical_switches(struct controller_vtep_ctx *ctx)
+{
+    const struct vteprec_physical_switch *pswitch;
+    struct ovsdb_idl_txn *txn;
+    int retval;
+
+    txn = ovsdb_idl_txn_create(ctx->ovnsb_idl);
+    ovsdb_idl_txn_add_comment(txn, "ovn-controller-vtep: "
+                              "updating 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 smap lswitches = SMAP_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 *ls;
+
+                ls = port->value_vlan_bindings[j];
+                /* If not already in 'lswitches', adds the logical switch
+                 * to logical port map.  The logical port is defined as
+                 * {pswitch->name}_{ls->name}. */
+                if (!smap_get(&lswitches, ls->name)) {
+                    char *lport = xasprintf("%s_%s", pswitch->name, ls->name);
+
+                    smap_add(&lswitches, ls->name, lport);
+                    free(lport);
+                }
+            }
+        }
+        sbrec_chassis_set_logical_switches(chassis_rec, &lswitches);
+        smap_destroy(&lswitches);
+    }
+
+    retval = ovsdb_idl_txn_commit_block(txn);
+    if (retval != TXN_SUCCESS && retval != TXN_UNCHANGED) {
+        VLOG_INFO("Problem updating chassis's logical_switches: %s",
+                  ovsdb_idl_txn_status_to_string(retval));
+        poll_immediate_wake();
+    }
+    ovsdb_idl_txn_destroy(txn);
+}
+
+
+void
+gateway_run(struct controller_vtep_ctx *ctx)
+{
+    revalidate_gateway(ctx);
+    update_logical_switches(ctx);
+}
+
+/* Destroys the chassis table entries of the vtep physical switches. */
+void
+gateway_destroy(struct controller_vtep_ctx *ctx)
+{
+    int retval = TXN_TRY_AGAIN;
+
+    ovs_assert(ctx->ovnsb_idl);
+    while (retval != TXN_SUCCESS && retval != TXN_UNCHANGED) {
+        const struct vteprec_physical_switch *pswitch;
+        struct ovsdb_idl_txn *txn = ovsdb_idl_txn_create(ctx->ovnsb_idl);
+
+        ovsdb_idl_txn_add_comment(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;
+            }
+            sbrec_chassis_delete(chassis_rec);
+        }
+        retval = ovsdb_idl_txn_commit_block(txn);
+        if (retval == TXN_ERROR) {
+            VLOG_INFO("Problem unregistering chassis: %s",
+                      ovsdb_idl_txn_status_to_string(retval));
+        }
+        ovsdb_idl_txn_destroy(txn);
+    }
+}
diff --git a/ovn/controller-vtep/ovn-controller-vtep.h b/ovn/controller-vtep/gateway.h
similarity index 72%
copy from ovn/controller-vtep/ovn-controller-vtep.h
copy to ovn/controller-vtep/gateway.h
index 121a9e3..edc895e 100644
--- a/ovn/controller-vtep/ovn-controller-vtep.h
+++ b/ovn/controller-vtep/gateway.h
@@ -13,15 +13,12 @@
  * limitations under the License.
  */
 
+#ifndef OVN_GATEWAY_H
+#define OVN_GATEWAY_H 1
 
-#ifndef OVN_CONTROLLER_VTEP_H
-#define OVN_CONTROLLER_VTEP_H 1
+struct controller_vtep_ctx;
 
-#include "ovn/lib/ovn-sb-idl.h"
+void gateway_run(struct controller_vtep_ctx *);
+void gateway_destroy(struct controller_vtep_ctx *);
 
-struct controller_vtep_ctx {
-    struct ovsdb_idl *ovnsb_idl;
-    struct ovsdb_idl *vtep_idl;
-};
-
-#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 50d727f..dbc754b 100644
--- a/ovn/controller-vtep/ovn-controller-vtep.c
+++ b/ovn/controller-vtep/ovn-controller-vtep.c
@@ -38,6 +38,7 @@
 #include "unixctl.h"
 #include "util.h"
 
+#include "gateway.h"
 #include "ovn-controller-vtep.h"
 
 VLOG_DEFINE_THIS_MODULE(ovn_vtep);
@@ -121,6 +122,7 @@ main(int argc, char *argv[])
             break;
         }
 
+        gateway_run(&ctx);
         unixctl_server_run(unixctl);
 
         unixctl_server_wait(unixctl);
@@ -134,6 +136,7 @@ main(int argc, char *argv[])
     }
 
     unixctl_server_destroy(unixctl);
+    gateway_destroy(&ctx);
 
     ovsdb_idl_destroy(ctx.vtep_idl);
     ovsdb_idl_destroy(ctx.ovnsb_idl);
diff --git a/ovn/controller-vtep/ovn-controller-vtep.h b/ovn/controller-vtep/ovn-controller-vtep.h
index 121a9e3..f00d3c4 100644
--- a/ovn/controller-vtep/ovn-controller-vtep.h
+++ b/ovn/controller-vtep/ovn-controller-vtep.h
@@ -24,4 +24,22 @@ struct controller_vtep_ctx {
     struct ovsdb_idl *vtep_idl;
 };
 
+/* 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, 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..3065a6b 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 ovn-controller-vtep exit])
+   AT_CHECK([ovs-appctl -t ovsdb-server 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 del-chassis 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 -- br-vtep_lswitch0`"])
+AT_CHECK([ovn-sbctl --columns=logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
+{"lswitch0"="br-vtep_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 -- br-vtep_lswitch1`"])
+AT_CHECK([ovn-sbctl --columns=logical_switches list Chassis | cut -d ':' -f2 | tr -d ' '], [0], [dnl
+{"lswitch0"="br-vtep_lswitch0","lswitch1"="br-vtep_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=logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
+{"lswitch0"="br-vtep_lswitch0","lswitch1"="br-vtep_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=logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
+{"lswitch1"="br-vtep_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=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