diff mbox

[ovs-dev,1/2] ovn-controller: Remove chassis creation code

Message ID 07dc4308-759e-2569-4978-1e7a39b05bfd@redhat.com
State Deferred
Headers show

Commit Message

Numan Siddique Nov. 11, 2016, 3:23 p.m. UTC
With this patch ovn-controller will not create a chassis row in the
OVN SB DB and will not modify the Chassis table row for the chassis.
Instead it expects the chassis row to be created externally.

Signed-off-by: Numan Siddique <nusiddiq@redhat.com>
---
 ovn/controller/chassis.c            | 195 +++++++++---------------------------
 ovn/controller/ovn-controller.8.xml |  60 -----------
 ovn/ovn-sb.xml                      |  65 ++++++------
 ovn/utilities/ovn-sbctl.c           |  15 +--
 tests/ofproto-macros.at             |   1 +
 tests/ovn-controller.at             |  35 +++----
 tutorial/ovs-sandbox                |   1 +
 7 files changed, 107 insertions(+), 265 deletions(-)
diff mbox

Patch

diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c
index 70cd159..42bbd6e 100644
--- a/ovn/controller/chassis.c
+++ b/ovn/controller/chassis.c
@@ -44,41 +44,17 @@  chassis_register_ovs_idl(struct ovsdb_idl *ovs_idl)
 }
 
 static const char *
-pop_tunnel_name(uint32_t *type)
-{
-    if (*type & GENEVE) {
-        *type &= ~GENEVE;
-        return "geneve";
-    } else if (*type & STT) {
-        *type &= ~STT;
-        return "stt";
-    } else if (*type & VXLAN) {
-        *type &= ~VXLAN;
-        return "vxlan";
-    }
-
-    OVS_NOT_REACHED();
-}
-
-static const char *
 get_bridge_mappings(const struct smap *ext_ids)
 {
     return smap_get_def(ext_ids, "ovn-bridge-mappings", "");
 }
 
-/* Returns this chassis's Chassis record, if it is available and is currently
- * amenable to a transaction. */
+/* Returns this chassis's Chassis record */
 const struct sbrec_chassis *
 chassis_run(struct controller_ctx *ctx, const char *chassis_id,
             const struct ovsrec_bridge *br_int)
 {
-    if (!ctx->ovnsb_idl_txn) {
-        return NULL;
-    }
-
     const struct ovsrec_open_vswitch *cfg;
-    const char *encap_type, *encap_ip;
-    static bool inited = false;
 
     cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
     if (!cfg) {
@@ -86,147 +62,68 @@  chassis_run(struct controller_ctx *ctx, const char *chassis_id,
         return NULL;
     }
 
-    encap_type = smap_get(&cfg->external_ids, "ovn-encap-type");
-    encap_ip = smap_get(&cfg->external_ids, "ovn-encap-ip");
-    if (!encap_type || !encap_ip) {
-        VLOG_INFO("Need to specify an encap type and ip");
+    const struct sbrec_chassis *chassis_rec
+        = get_chassis(ctx->ovnsb_idl, chassis_id);
+
+    if (!chassis_rec) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+        VLOG_WARN_RL(&rl, "No chassis row defined for chassis '%s'.",
+                     chassis_id);
         return NULL;
     }
 
-    char *tokstr = xstrdup(encap_type);
-    char *save_ptr = NULL;
-    char *token;
-    uint32_t req_tunnels = 0;
-    for (token = strtok_r(tokstr, ",", &save_ptr); token != NULL;
-         token = strtok_r(NULL, ",", &save_ptr)) {
-        uint32_t type = get_tunnel_type(token);
-        if (!type) {
-            VLOG_INFO("Unknown tunnel type: %s", token);
-        }
-        req_tunnels |= type;
+    uint32_t cur_tunnels = 0;
+    for (int i = 0; i < chassis_rec->n_encaps; i++) {
+        cur_tunnels |= get_tunnel_type(chassis_rec->encaps[i]->type);
     }
-    free(tokstr);
 
-    const char *hostname = smap_get_def(&cfg->external_ids, "hostname", "");
-    char hostname_[HOST_NAME_MAX + 1];
-    if (!hostname[0]) {
-        if (gethostname(hostname_, sizeof hostname_)) {
-            hostname_[0] = '\0';
-        }
-        hostname = hostname_;
+    if (!cur_tunnels) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+        VLOG_WARN_RL(&rl, "Invalid or no encap params for chassis '%s'.",
+                     chassis_id);
+        return NULL;
     }
 
-    const char *bridge_mappings = get_bridge_mappings(&cfg->external_ids);
-    const char *datapath_type =
-        br_int && br_int->datapath_type ? br_int->datapath_type : "";
-
-    struct ds iface_types = DS_EMPTY_INITIALIZER;
-    ds_put_cstr(&iface_types, "");
-    for (int j = 0; j < cfg->n_iface_types; j++) {
-        ds_put_format(&iface_types, "%s,", cfg->iface_types[j]);
+    if (!chassis_rec->hostname[0]) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+        VLOG_WARN_RL(&rl, "No hostname defined for chassis '%s'.",
+                     chassis_id);
+        return NULL;
     }
-    ds_chomp(&iface_types, ',');
-    const char *iface_types_str = ds_cstr(&iface_types);
-
-    const struct sbrec_chassis *chassis_rec
-        = get_chassis(ctx->ovnsb_idl, chassis_id);
-
-    if (chassis_rec) {
-        if (strcmp(hostname, chassis_rec->hostname)) {
-            sbrec_chassis_set_hostname(chassis_rec, hostname);
-        }
-
-        /* Determine new values for Chassis external-ids. */
-        const char *chassis_bridge_mappings
-            = get_bridge_mappings(&chassis_rec->external_ids);
-        const char *chassis_datapath_type
-            = smap_get_def(&chassis_rec->external_ids, "datapath-type", "");
-        const char *chassis_iface_types
-            = smap_get_def(&chassis_rec->external_ids, "iface-types", "");
-
-        /* If any of the external-ids should change, update them. */
-        if (strcmp(bridge_mappings, chassis_bridge_mappings) ||
-            strcmp(datapath_type, chassis_datapath_type) ||
-            strcmp(iface_types_str, chassis_iface_types)) {
-            struct smap new_ids;
-            smap_clone(&new_ids, &chassis_rec->external_ids);
-            smap_replace(&new_ids, "ovn-bridge-mappings", bridge_mappings);
-            smap_replace(&new_ids, "datapath-type", datapath_type);
-            smap_replace(&new_ids, "iface-types", iface_types_str);
-            sbrec_chassis_verify_external_ids(chassis_rec);
-            sbrec_chassis_set_external_ids(chassis_rec, &new_ids);
-            smap_destroy(&new_ids);
-        }
 
-        /* Compare desired tunnels against those currently in the database. */
-        uint32_t cur_tunnels = 0;
-        bool same = true;
-        for (int i = 0; i < chassis_rec->n_encaps; i++) {
-            cur_tunnels |= get_tunnel_type(chassis_rec->encaps[i]->type);
-            same = same && !strcmp(chassis_rec->encaps[i]->ip, encap_ip);
-
-            same = same && smap_get_bool(&chassis_rec->encaps[i]->options,
-                                         "csum", false);
-        }
-        same = same && req_tunnels == cur_tunnels;
-
-        if (same) {
-            /* Nothing changed. */
-            inited = true;
-            ds_destroy(&iface_types);
-            return chassis_rec;
-        } else if (!inited) {
-            struct ds cur_encaps = DS_EMPTY_INITIALIZER;
-            for (int i = 0; i < chassis_rec->n_encaps; i++) {
-                ds_put_format(&cur_encaps, "%s,",
-                              chassis_rec->encaps[i]->type);
-            }
-            ds_chomp(&cur_encaps, ',');
-
-            VLOG_WARN("Chassis config changing on startup, make sure "
-                      "multiple chassis are not configured : %s/%s->%s/%s",
-                      ds_cstr(&cur_encaps),
-                      chassis_rec->encaps[0]->ip,
-                      encap_type, encap_ip);
-            ds_destroy(&cur_encaps);
+    const struct sbrec_chassis *cr;
+    SBREC_CHASSIS_FOR_EACH(cr, ctx->ovnsb_idl) {
+        if (strcmp(chassis_rec->name, cr->name) &&
+            !strcmp(chassis_rec->hostname, cr->hostname)) {
+            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+            VLOG_WARN_RL(&rl, "hostname defined for this chassis '%s' is "
+                         "same as other chassis '%s'", chassis_id, cr->name);
+            return NULL;
         }
     }
 
-    ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
-                              "ovn-controller: registering chassis '%s'",
-                              chassis_id);
-
-    if (!chassis_rec) {
-        struct smap ext_ids = SMAP_INITIALIZER(&ext_ids);
-        smap_add(&ext_ids, "ovn-bridge-mappings", bridge_mappings);
-        smap_add(&ext_ids, "datapath-type", datapath_type);
-        smap_add(&ext_ids, "iface-types", iface_types_str);
-        chassis_rec = sbrec_chassis_insert(ctx->ovnsb_idl_txn);
-        sbrec_chassis_set_name(chassis_rec, chassis_id);
-        sbrec_chassis_set_hostname(chassis_rec, hostname);
-        sbrec_chassis_set_external_ids(chassis_rec, &ext_ids);
-        smap_destroy(&ext_ids);
-    }
-
-    ds_destroy(&iface_types);
-    int n_encaps = count_1bits(req_tunnels);
-    struct sbrec_encap **encaps = xmalloc(n_encaps * sizeof *encaps);
-    const struct smap options = SMAP_CONST1(&options, "csum", "true");
-
-    for (int i = 0; i < n_encaps; i++) {
-        const char *type = pop_tunnel_name(&req_tunnels);
+    const char *bridge_mappings = get_bridge_mappings(&cfg->external_ids);
+    const char *datapath_type =
+        br_int && br_int->datapath_type ? br_int->datapath_type : "";
 
-        encaps[i] = sbrec_encap_insert(ctx->ovnsb_idl_txn);
+    const char *chassis_bridge_mappings
+        = get_bridge_mappings(&chassis_rec->external_ids);
+    const char *chassis_datapath_type
+        = smap_get_def(&chassis_rec->external_ids, "datapath-type", "");
 
-        sbrec_encap_set_type(encaps[i], type);
-        sbrec_encap_set_ip(encaps[i], encap_ip);
-        sbrec_encap_set_options(encaps[i], &options);
+    if (strcmp(bridge_mappings, chassis_bridge_mappings)) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+        VLOG_WARN_RL(&rl, "bridge_mappings configuration mismatch. Defined -,"
+                  " %s, Expected - %s", chassis_bridge_mappings,
+                  bridge_mappings);
     }
 
-    sbrec_chassis_set_encaps(chassis_rec, encaps, n_encaps);
-    free(encaps);
+    if (strcmp(datapath_type, chassis_datapath_type)) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+        VLOG_WARN_RL(&rl, "datapath_type configuration mismatch. Defined - %s,"
+                  " Expected - %s", chassis_datapath_type, datapath_type);
+    }
 
-    inited = true;
     return chassis_rec;
 }
 
diff --git a/ovn/controller/ovn-controller.8.xml b/ovn/controller/ovn-controller.8.xml
index 5f51cb1..9ad5d4f 100644
--- a/ovn/controller/ovn-controller.8.xml
+++ b/ovn/controller/ovn-controller.8.xml
@@ -75,12 +75,6 @@ 
       table of the local OVS instance:
     </p>
     <dl>
-      <dt><code>external_ids:system-id</code></dt>
-      <dd>The chassis name to use in the Chassis table.</dd>
-
-      <dt><code>external_ids:hostname</code></dt>
-      <dd>The hostname to use in the Chassis table.</dd>
-
       <dt><code>external_ids:ovn-bridge</code></dt>
       <dd>
         The integration bridge to which logical ports are attached.  The
@@ -117,36 +111,6 @@ 
         </p>
       </dd>
 
-      <dt><code>external_ids:ovn-encap-type</code></dt>
-      <dd>
-        <p>
-          The encapsulation type that a chassis should use to connect to
-          this node.  Multiple encapsulation types may be specified with
-          a comma-separated list.  Each listed encapsulation type will
-          be paired with <code>ovn-encap-ip</code>.
-        </p>
-
-        <p>
-          Supported tunnel types for connecting hypervisors
-          are <code>geneve</code> and <code>stt</code>.  Gateways may
-          use <code>geneve</code>, <code>vxlan</code>, or
-          <code>stt</code>.
-        </p>
-
-        <p>
-          Due to the limited amount of metadata in <code>vxlan</code>,
-          the capabilities and performance of connected gateways will be
-          reduced versus other tunnel formats.
-        </p>
-      </dd>
-
-      <dt><code>external_ids:ovn-encap-ip</code></dt>
-      <dd>
-        The IP address that a chassis should use to connect to this node
-        using encapsulation types specified by
-        <code>external_ids:ovn-encap-type</code>.
-      </dd>
-
       <dt><code>external_ids:ovn-bridge-mappings</code></dt>
       <dd>
         A list of key-value pairs that map a physical network name to a local
@@ -156,30 +120,6 @@ 
       </dd>
     </dl>
 
-    <p>
-      <code>ovn-controller</code> reads the following values from the
-      <code>Open_vSwitch</code> database of the local OVS instance:
-    </p>
-
-    <dl>
-      <dt><code>datapath-type</code> from <ref table="Bridge" db="Open_vSwitch"/> table</dt>
-      <dd>
-        This value is read from local OVS integration bridge row of
-        <ref table="Bridge" db="Open_vSwitch"/> table and populated in
-        <ref key="datapath-type" table="Chassis" column="external_ids"
-        db="OVN_Southbound"/> of the <ref table="Chassis" db="OVN_Southbound"/>
-        table in the OVN_Southbound database.
-      </dd>
-
-      <dt><code>iface-types</code> from <ref table="Open_vSwitch" db="Open_vSwitch"/> table</dt>
-      <dd>
-        This value is populated in <ref key="iface-types" table="Chassis"
-        column="external_ids" db="OVN_Southbound"/> of the
-        <ref table="Chassis" db="OVN_Southbound"/> table in the OVN_Southbound
-        database.
-      </dd>
-    </dl>
-
     <h1>Open vSwitch Database Usage</h1>
 
     <p>
diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
index 45c473c..b61c0d5 100644
--- a/ovn/ovn-sb.xml
+++ b/ovn/ovn-sb.xml
@@ -175,36 +175,33 @@ 
   <table name="Chassis" title="Physical Network Hypervisor and Gateway Information">
     <p>
       Each row in this table represents a hypervisor or gateway (a chassis) in
-      the physical network (PN).  Each chassis, via
-      <code>ovn-controller</code>/<code>ovn-controller-vtep</code>, adds
-      and updates its own row, and keeps a copy of the remaining rows to
-      determine how to reach other hypervisors.
+      the physical network (PN). <code>ovn-controller</code> running on each
+      chassis expects the row pertaining to it to be added by an
+      Administrator. Unless <code>ovn-controller</code> finds its row
+      in this table, it will not translate the logical flows to OF flows.
+      <code>ovn-controller-vtep</code>, adds
+      and updates its own row. Each chassis keeps a copy of the remaining rows
+      to determine how to reach other hypervisors.
     </p>
 
     <p>
-      When a chassis shuts down gracefully, it should remove its own row.
-      (This is not critical because resources hosted on the chassis are equally
-      unreachable regardless of whether the row is present.)  If a chassis
-      shuts down permanently without removing its row, some kind of manual or
-      automatic cleanup is eventually needed; we can devise a process for that
-      as necessary.
+      When a chassis shuts down gracefully, Administrator should remove
+      the corresponding row. (This is not critical because resources hosted on
+      the chassis are equally unreachable regardless of whether the row is
+      present.).
     </p>
 
     <column name="name">
       OVN does not prescribe a particular format for chassis names.
-      ovn-controller populates this column using <ref key="system-id"
-      table="Open_vSwitch" column="external_ids" db="Open_vSwitch"/>
-      in the Open_vSwitch database's <ref table="Open_vSwitch"
-      db="Open_vSwitch"/> table.  ovn-controller-vtep populates this
-      column with <ref table="Physical_Switch" column="name"
-      db="hardware_vtep"/> in the hardware_vtep database's
+      ovn-controller-vtep populates this column with
+      <ref table="Physical_Switch" column="name" db="hardware_vtep"/> in the
+      hardware_vtep database's
       <ref table="Physical_Switch" db="hardware_vtep"/> table.
     </column>
 
     <column name="hostname">
-      The hostname of the chassis, if applicable.  ovn-controller will populate
-      this column with the hostname of the host it is running on.
-      ovn-controller-vtep will leave this column empty.
+      The hostname of the chassis, if applicable. ovn-controller-vtep will
+      leave this column empty.
     </column>
 
     <column name="nb_cfg">
@@ -215,26 +212,28 @@ 
     </column>
 
     <column name="external_ids" key="ovn-bridge-mappings">
-      <code>ovn-controller</code> populates this key with the set of bridge
-      mappings it has been configured to use.  Other applications should treat
-      this key as read-only.  See <code>ovn-controller</code>(8) for more
-      information.
+      <code>ovn-controller</code> expects this key to be populated with the set
+      of bridge mappings it has been configured to use. Other applications
+      could read this value to know the bridge mappings configued on this
+      chassis.
     </column>
 
     <column name="external_ids" key="datapath-type">
-      <code>ovn-controller</code> populates this key with the datapath type
-      configured in the <ref table="Bridge" column="datapath_type"/> column of
-      the Open_vSwitch database's <ref table="Bridge" db="Open_vSwitch"/>
-      table.  Other applications should treat this key as read-only. See
-      <code>ovn-controller</code>(8) for more information.
+      <code>ovn-controller</code> expects this key to be populated with the
+      datapath type configured in the
+      <ref table="Bridge" column="datapath_type"/> column of the Open_vSwitch
+      database's <ref table="Bridge" db="Open_vSwitch"/>
+      table. Other applications could read this value to know the datapath
+      type supported by this chassis.
     </column>
 
     <column name="external_ids" key="iface-types">
-      <code>ovn-controller</code> populates this key with the interface types
-      configured in the <ref table="Open_vSwitch" column="iface_types"/> column
-      of the Open_vSwitch database's <ref table="Open_vSwitch"
-      db="Open_vSwitch"/> table.  Other applications should treat this key as
-      read-only. See <code>ovn-controller</code>(8) for more information.
+      <code>ovn-controller</code> expects this key to be populated with the
+      interface types configured in the
+      <ref table="Open_vSwitch" column="iface_types"/> column of the
+      Open_vSwitch database's <ref table="Open_vSwitch"
+      db="Open_vSwitch"/> table.  Other applications could read this value to
+      know the interface types supported by this chassis.
     </column>
 
     <group title="Common Columns">
diff --git a/ovn/utilities/ovn-sbctl.c b/ovn/utilities/ovn-sbctl.c
index 0763b79..02d40c5 100644
--- a/ovn/utilities/ovn-sbctl.c
+++ b/ovn/utilities/ovn-sbctl.c
@@ -295,9 +295,10 @@  General commands:\n\
   show                        print overview of database contents\n\
 \n\
 Chassis commands:\n\
-  chassis-add CHASSIS ENCAP-TYPE ENCAP-IP  create a new chassis named\n\
-                                           CHASSIS with ENCAP-TYPE tunnels\n\
-                                           and ENCAP-IP\n\
+  chassis-add CHASSIS ENCAP-TYPE ENCAP-IP [HOSTNAME] create a new chassis\n\
+                                                     named CHASSIS with\n\
+                                                     ENCAP-TYPE tunnels and\n\
+                                                     ENCAP-IP\n\
   chassis-del CHASSIS         delete CHASSIS and all of its encaps\n\
                               and gateway_ports\n\
 \n\
@@ -563,7 +564,9 @@  cmd_chassis_add(struct ctl_context *ctx)
     sbrec_chassis_set_name(ch, ch_name);
     sbrec_chassis_set_encaps(ch, encaps, n_encaps);
     free(encaps);
-
+    if (ctx->argc == 5) {
+        sbrec_chassis_set_hostname(ch, ctx->argv[4]);
+    }
     sbctl_context_invalidate_cache(ctx);
 }
 
@@ -1027,8 +1030,8 @@  static const struct ctl_command_syntax sbctl_commands[] = {
     { "init", 0, 0, "", NULL, sbctl_init, NULL, "", RW },
 
     /* Chassis commands. */
-    {"chassis-add", 3, 3, "CHASSIS ENCAP-TYPE ENCAP-IP", pre_get_info,
-     cmd_chassis_add, NULL, "--may-exist", RW},
+    {"chassis-add", 3, 4, "CHASSIS ENCAP-TYPE ENCAP-IP [HOSTNAME]",
+     pre_get_info, cmd_chassis_add, NULL, "--may-exist", RW},
     {"chassis-del", 1, 1, "CHASSIS", pre_get_info, cmd_chassis_del, NULL,
      "--if-exists", RW},
 
diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at
index 92ab9ab..dff6d89 100644
--- a/tests/ofproto-macros.at
+++ b/tests/ofproto-macros.at
@@ -258,6 +258,7 @@  ovn_attach() {
         -- add-br br-int \
         -- set bridge br-int fail-mode=secure other-config:disable-in-band=true \
         || return 1
+    ovn-sbctl chassis-add $sandbox geneve,vxlan $ip $sandbox
     start_daemon ovn-controller || return 1
 }
 
diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
index 60a6760..8442431 100644
--- a/tests/ovn-controller.at
+++ b/tests/ovn-controller.at
@@ -47,14 +47,12 @@  patch
 }
 
 # Make sure that the configured bridge mappings in the Open_vSwitch db
-# is mirrored into the Chassis record in the OVN_Southbound db.
+# is not mirrored into the Chassis record in the OVN_Southbound db as
+# ovn-controller doesn't write to the SB DB.
 check_bridge_mappings () {
-    local_mappings=$1
     sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
     chassis_mappings=$(ovn-sbctl get Chassis ${sysid} external_ids:ovn-bridge-mappings | sed -e 's/\"//g')
-    echo $local_mappings
-    echo $chassis_mappings
-    AT_CHECK([test "${local_mappings}" = "${chassis_mappings}"])
+    AT_CHECK([test "${chassis_mappings}" = ""])
 }
 
 # Initially there should be no patch ports.
@@ -129,6 +127,9 @@  on_exit 'kill `cat $ovs_base/ovn-sb/ovsdb-server-2.pid`'
 ovsdb-tool create $ovs_base/ovn-sb/ovn-sb1.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
 as ovn-sb ovsdb-server --detach --pidfile=$ovs_base/ovn-sb/ovsdb-server-2.pid --remote=punix:$ovs_base/ovn-sb/ovn-sb1.sock $ovs_base/ovn-sb/ovn-sb1.db \
    --unixctl=$ovs_base/ovn-sb/ovsdb-server-2.ctl
+ovn-sbctl --db=unix:$ovs_base/ovn-sb/ovn-sb1.sock init
+ovn-sbctl --db=unix:$ovs_base/ovn-sb/ovn-sb1.sock chassis-add hv geneve,vxlan 127.0.0.1 hv
+
 AT_CHECK([ovs-vsctl -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb1.sock])
 check_patches
 AT_CHECK([ovs-vsctl -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock])
@@ -152,8 +153,9 @@  OVS_APP_EXIT_AND_WAIT([ovsdb-server])
 
 AT_CLEANUP
 
-# Checks that ovn-controller populates datapath-type and iface-types
-# correctly in the Chassis external-ids column.
+# Checks that ovn-controller doesn't populates datapath-type and iface-types
+# in the Chassis external-ids column on its own as it cannot write to the
+# SB DB
 AT_SETUP([ovn-controller - Chassis external_ids])
 AT_KEYWORDS([ovn])
 ovn_init_db ovn-sb
@@ -171,40 +173,39 @@  ovn_attach n1 br-phys 192.168.0.1
 sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
 
 # Make sure that the datapath_type set in the Bridge table
-# is mirrored into the Chassis record in the OVN_Southbound db.
+# is not mirrored into the Chassis record in the OVN_Southbound db.
 check_datapath_type () {
-    datapath_type=$1
     chassis_datapath_type=$(ovn-sbctl get Chassis ${sysid} external_ids:datapath-type | sed -e 's/"//g') #"
-    test "${datapath_type}" = "${chassis_datapath_type}"
+    test "${datapath_type}" = ""
 }
 
-OVS_WAIT_UNTIL([check_datapath_type ""])
+OVS_WAIT_UNTIL([check_datapath_type])
 
 ovs-vsctl set Bridge br-int datapath-type=foo
-OVS_WAIT_UNTIL([check_datapath_type foo])
+OVS_WAIT_UNTIL([check_datapath_type])
 
 # Change "ovn-bridge-mappings" value. It should not change the "datapath-type".
 ovs-vsctl set Open_vSwitch . external_ids:ovn-bridge-mappings=foo-mapping
 check_datapath_type foo
 
 ovs-vsctl set Bridge br-int datapath-type=bar
-OVS_WAIT_UNTIL([check_datapath_type bar])
+OVS_WAIT_UNTIL([check_datapath_type])
 
 ovs-vsctl set Bridge br-int datapath-type=\"\"
-OVS_WAIT_UNTIL([check_datapath_type ""])
+OVS_WAIT_UNTIL([check_datapath_type])
 
 expected_iface_types=$(ovs-vsctl get Open_vSwitch . iface_types|sed 's/[[]][[ ]]//g')
 chassis_iface_types=$(ovn-sbctl get Chassis ${sysid} external_ids:iface-types | sed -e 's/\"//g')
 echo "chassis_iface_types = ${chassis_iface_types}"
-AT_CHECK([test "${expected_iface_types}" = "${chassis_iface_types}"])
+AT_CHECK([test "${expected_iface_types}" != "${chassis_iface_types}"])
 
 # Change the value of external_ids:iface-types using ovn-sbctl.
-# ovn-controller should again set it back to proper one.
+# ovn-controller should not modify it.
 ovn-sbctl set Chassis ${sysid} external_ids:iface-types="foo"
 OVS_WAIT_UNTIL([
     chassis_iface_types=$(ovn-sbctl get Chassis ${sysid} external_ids:iface-types | sed -e 's/\"//g')
     echo "chassis_iface_types = ${chassis_iface_types}"
-    test "${expected_iface_types}" = "${chassis_iface_types}"
+    test "${expected_iface_types}" != "${chassis_iface_types}"
 ])
 
 # Gracefully terminate daemons
diff --git a/tutorial/ovs-sandbox b/tutorial/ovs-sandbox
index 4372da4..e9d7342 100755
--- a/tutorial/ovs-sandbox
+++ b/tutorial/ovs-sandbox
@@ -369,6 +369,7 @@  if $ovn; then
     ovs-vsctl set open . external-ids:ovn-remote=unix:"$sandbox"/ovnsb_db.sock
     ovs-vsctl set open . external-ids:ovn-encap-type=geneve
     ovs-vsctl set open . external-ids:ovn-encap-ip=127.0.0.1
+    ovn-sbctl chassis-add 56b18105-5706-46ef-80c4-ff20979ab068 geneve,vxlan 127.0.0.1 sandbox
 
     ovn-nbctl init
     ovn-sbctl init