diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c
index d7b175e..df5a2ae 100644
--- a/ovn/controller/binding.c
+++ b/ovn/controller/binding.c
@@ -295,67 +295,30 @@ consider_local_datapath(struct controller_ctx *ctx,
             /* Add child logical port to the set of all local ports. */
             sset_add(all_lports, binding_rec->logical_port);
         }
+
+        if (binding_rec->chassis != chassis_rec) {
+            return;
+        }
         add_local_datapath(local_datapaths, binding_rec);
         if (iface_rec && qos_map && ctx->ovs_idl_txn) {
             get_qos_params(binding_rec, qos_map);
         }
-        if (binding_rec->chassis == chassis_rec) {
-            return;
-        }
-        if (ctx->ovnsb_idl_txn) {
-            if (binding_rec->chassis) {
-                VLOG_INFO("Changing chassis for lport %s from %s to %s.",
-                          binding_rec->logical_port,
-                          binding_rec->chassis->name,
-                          chassis_rec->name);
-            } else {
-                VLOG_INFO("Claiming lport %s for this chassis.",
-                          binding_rec->logical_port);
-                for (int i = 0; i < binding_rec->n_mac; i++) {
-                    VLOG_INFO("Claiming %s", binding_rec->mac[i]);
-                }
-            }
-            sbrec_port_binding_set_chassis(binding_rec, chassis_rec);
-        }
     } else if (!strcmp(binding_rec->type, "l2gateway")) {
-        const char *chassis_id = smap_get(&binding_rec->options,
-                                          "l2gateway-chassis");
-        if (!chassis_id || strcmp(chassis_id, chassis_rec->name)) {
-            if (binding_rec->chassis == chassis_rec && ctx->ovnsb_idl_txn) {
-                VLOG_INFO("Releasing l2gateway port %s from this chassis.",
-                          binding_rec->logical_port);
-                sbrec_port_binding_set_chassis(binding_rec, NULL);
-            }
+        if (!binding_rec->chassis || strcmp(binding_rec->chassis->name,
+                                            chassis_rec->name)) {
             return;
         }
 
         sset_add(all_lports, binding_rec->logical_port);
         add_local_datapath(local_datapaths, binding_rec);
-        if (binding_rec->chassis == chassis_rec) {
-            return;
-        }
-
-        if (!strcmp(chassis_id, chassis_rec->name) && ctx->ovnsb_idl_txn) {
-            VLOG_INFO("Claiming l2gateway port %s for this chassis.",
-                      binding_rec->logical_port);
-            sbrec_port_binding_set_chassis(binding_rec, chassis_rec);
-        }
     } else if (!strcmp(binding_rec->type, "l3gateway")) {
         const char *chassis = smap_get(&binding_rec->options,
                                        "l3gateway-chassis");
-        if (!strcmp(chassis, chassis_rec->name) && ctx->ovnsb_idl_txn) {
+        if (chassis && !strcmp(chassis, chassis_rec->name)) {
             add_local_datapath(local_datapaths, binding_rec);
         }
     } else if (chassis_rec && binding_rec->chassis == chassis_rec) {
-        if (ctx->ovnsb_idl_txn) {
-            VLOG_INFO("Releasing lport %s from this chassis.",
-                      binding_rec->logical_port);
-            for (int i = 0; i < binding_rec->n_mac; i++) {
-                VLOG_INFO("Releasing %s", binding_rec->mac[i]);
-            }
-            sbrec_port_binding_set_chassis(binding_rec, NULL);
-            sset_find_and_delete(all_lports, binding_rec->logical_port);
-        }
+        sset_find_and_delete(all_lports, binding_rec->logical_port);
     } else if (!binding_rec->chassis
                && !strcmp(binding_rec->type, "localnet")) {
         /* Add all localnet ports to all_lports so that we allocate ct zones
@@ -387,7 +350,7 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
     }
 
     /* Run through each binding record to see if it is resident on this
-     * chassis and update the binding accordingly.  This includes both
+     * chassis and update the local datapath accordingly.  This includes both
      * directly connected logical ports and children of those ports. */
     SBREC_PORT_BINDING_FOR_EACH(binding_rec, ctx->ovnsb_idl) {
         consider_local_datapath(ctx, chassis_rec, binding_rec,
@@ -413,33 +376,8 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
 /* Returns true if the database is all cleaned up, false if more work is
  * required. */
 bool
-binding_cleanup(struct controller_ctx *ctx, const char *chassis_id)
+binding_cleanup(struct controller_ctx *ctx  OVS_UNUSED,
+                const char *chassis_id OVS_UNUSED)
 {
-    if (!ctx->ovnsb_idl_txn) {
-        return false;
-    }
-
-    if (!chassis_id) {
-        return true;
-    }
-
-    const struct sbrec_chassis *chassis_rec
-        = get_chassis(ctx->ovnsb_idl, chassis_id);
-    if (!chassis_rec) {
-        return true;
-    }
-
-    ovsdb_idl_txn_add_comment(
-        ctx->ovnsb_idl_txn,
-        "ovn-controller: removing all port bindings for '%s'", chassis_id);
-
-    const struct sbrec_port_binding *binding_rec;
-    bool any_changes = false;
-    SBREC_PORT_BINDING_FOR_EACH(binding_rec, ctx->ovnsb_idl) {
-        if (binding_rec->chassis == chassis_rec) {
-            sbrec_port_binding_set_chassis(binding_rec, NULL);
-            any_changes = true;
-        }
-    }
-    return !any_changes;
+    return true;
 }
diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c
index c5866b4..e98be7a 100644
--- a/ovn/controller/physical.c
+++ b/ovn/controller/physical.c
@@ -190,6 +190,13 @@ consider_port_binding(enum mf_field_id mff_ovn_geneve,
         return;
     }
 
+    /* binding->chassis should be set for VM (of VIF) interface port */
+    if (!binding->type[0] && !binding->chassis) {
+        /* This could happen in cases where ovn-northd has not updated the
+         * chassis column */
+        return;
+    }
+
     /* Find the OpenFlow port for the logical port, as 'ofport'.  This is
      * one of:
      *
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 437da9f..a625ba2 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -1346,7 +1346,8 @@ join_logical_ports(struct northd_context *ctx,
 
 static void
 ovn_port_update_sbrec(const struct ovn_port *op,
-                      struct hmap *chassis_qdisc_queues)
+                      struct hmap *chassis_qdisc_queues,
+                      struct ovsdb_idl *ovnsb_idl)
 {
     sbrec_port_binding_set_datapath(op->sb, op->od->sb);
     if (op->nbrp) {
@@ -1397,6 +1398,24 @@ ovn_port_update_sbrec(const struct ovn_port *op,
             sbrec_port_binding_set_options(op->sb, &options);
             smap_destroy(&options);
             sbrec_port_binding_set_type(op->sb, op->nbsp->type);
+
+            /* Set the chassis for the port binding if defined */
+            const char *chassis = NULL;
+            if (!strcmp(op->nbsp->type, "l2gateway")) {
+                chassis = smap_get(&op->nbsp->options, "l2gateway-chassis");
+            } else {
+                chassis = smap_get(&op->nbsp->options, "chassis");
+            }
+
+            if (chassis) {
+                const struct sbrec_chassis *chassis_rec = NULL;
+                SBREC_CHASSIS_FOR_EACH(chassis_rec, ovnsb_idl) {
+                    if (!strcmp(chassis_rec->name, chassis)) {
+                        break;
+                    }
+                }
+                sbrec_port_binding_set_chassis(op->sb, chassis_rec);
+            }
         } else {
             const char *chassis = NULL;
             if (op->peer && op->peer->od && op->peer->od->nbr) {
@@ -1418,6 +1437,13 @@ ovn_port_update_sbrec(const struct ovn_port *op,
             smap_add(&new, "peer", router_port);
             if (chassis) {
                 smap_add(&new, "l3gateway-chassis", chassis);
+                const struct sbrec_chassis *chassis_rec = NULL;
+                SBREC_CHASSIS_FOR_EACH(chassis_rec, ovnsb_idl) {
+                    if (!strcmp(chassis_rec->name, chassis)) {
+                        break;
+                    }
+                }
+                sbrec_port_binding_set_chassis(op->sb, chassis_rec);
             }
 
             const char *nat_addresses = smap_get(&op->nbsp->options,
@@ -1482,7 +1508,7 @@ build_ports(struct northd_context *ctx, struct hmap *datapaths,
         if (op->nbsp) {
             tag_alloc_create_new_tag(&tag_alloc_table, op->nbsp);
         }
-        ovn_port_update_sbrec(op, &chassis_qdisc_queues);
+        ovn_port_update_sbrec(op, &chassis_qdisc_queues, ctx->ovnsb_idl);
 
         add_tnlid(&op->od->port_tnlids, op->sb->tunnel_key);
         if (op->sb->tunnel_key > op->od->port_key_hint) {
@@ -1498,7 +1524,7 @@ build_ports(struct northd_context *ctx, struct hmap *datapaths,
         }
 
         op->sb = sbrec_port_binding_insert(ctx->ovnsb_txn);
-        ovn_port_update_sbrec(op, &chassis_qdisc_queues);
+        ovn_port_update_sbrec(op, &chassis_qdisc_queues, ctx->ovnsb_idl);
 
         sbrec_port_binding_set_logical_port(op->sb, op->key);
         sbrec_port_binding_set_tunnel_key(op->sb, tunnel_key);
@@ -4860,6 +4886,7 @@ main(int argc, char *argv[])
 
     ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis);
     ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_nb_cfg);
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_name);
 
     /* Main loop. */
     exiting = false;
diff --git a/ovn/ovn-architecture.7.xml b/ovn/ovn-architecture.7.xml
index 95cba98..cb3c496 100644
--- a/ovn/ovn-architecture.7.xml
+++ b/ovn/ovn-architecture.7.xml
@@ -430,7 +430,10 @@
       update the flow that delivers broadcast and multicast packets to include
       the new port.  It also creates a record in the <code>Binding</code> table
       and populates all its columns except the column that identifies the
-      <code>chassis</code>.
+      <code>chassis</code>. It populates the <code>chassis</code> column of
+      the <code>Binding</code> table if the <code>options:chassis</code> column
+      of the <code>Logical_Switch_Port</code> table is defined with a valid
+      chassis id.
     </li>
 
     <li>
@@ -456,12 +459,12 @@
     <li>
       On the hypervisor where the VM is powered on, <code>ovn-controller</code>
       notices <code>external_ids</code>:<code>iface-id</code> in the new
-      Interface. In response, in the OVN Southbound DB, it updates the
+      Interface. In response, in the OVN Southbound DB, it reads the
       <code>Binding</code> table's <code>chassis</code> column for the
       row that links the logical port from <code>external_ids</code>:<code>
-      iface-id</code> to the hypervisor. Afterward, <code>ovn-controller</code>
-      updates the local hypervisor's OpenFlow tables so that packets to and from
-      the VIF are properly handled.
+      iface-id</code> and matches with its own chassis id. If the match is
+      successful, <code>ovn-controller</code> updates the local hypervisor's
+      OpenFlow tables so that packets to and from the VIF are properly handled.
     </li>
 
     <li>
@@ -493,21 +496,6 @@
     </li>
 
     <li>
-      On the hypervisor where the VM was powered off,
-      <code>ovn-controller</code> notices that the VIF was deleted.  In
-      response, it removes the <code>Chassis</code> column content in the
-      <code>Binding</code> table for the logical port.
-    </li>
-
-    <li>
-      On every hypervisor, <code>ovn-controller</code> notices the empty
-      <code>Chassis</code> column in the <code>Binding</code> table's row
-      for the logical port.  This means that <code>ovn-controller</code> no
-      longer knows the physical location of the logical port, so each instance
-      updates its OpenFlow table to reflect that.
-    </li>
-
-    <li>
       Eventually, when the VIF (or its entire VM) is no longer needed by
       anyone, an administrator deletes the VIF using the CMS user interface or
       API.  The CMS updates its own configuration.
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index 49fbe00..35520d6 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -305,6 +305,14 @@
           If set, indicates the maximum burst size for data sent from this
           interface, in bits.
         </column>
+
+        <column name="options" key="chassis">
+          Optional. The chassis on which the logical port should be bound to.
+          <code>ovn-controller</code> running on the defined chassis will
+          associate this logical port to the interface present in the OVN
+          integration bridge (defined with logical port name in
+          <code>external_ids</code>:<code>iface-id</code>).
+        </column>
       </group>
     </group>
 
diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
index b61c0d5..07c53e8 100644
--- a/ovn/ovn-sb.xml
+++ b/ovn/ovn-sb.xml
@@ -1589,33 +1589,32 @@ tcp.flags = RST;
       For every <code>Logical_Switch_Port</code> record in
       <code>OVN_Northbound</code> database, <code>ovn-northd</code>
       creates a record in this table.  <code>ovn-northd</code> populates
-      and maintains every column except the <code>chassis</code> column,
-      which it leaves empty in new records.
+      and maintains every column.
     </p>
 
     <p>
-      <code>ovn-controller</code>/<code>ovn-controller-vtep</code>
-      populates the <code>chassis</code> column for the records that
-      identify the logical ports that are located on its hypervisor/gateway,
-      which <code>ovn-controller</code>/<code>ovn-controller-vtep</code> in
-      turn finds out by monitoring the local hypervisor's Open_vSwitch
-      database, which identifies logical ports via the conventions described
-      in <code>IntegrationGuide.rst</code>.  (The exceptions are for
-      <code>Port_Binding</code> records with <code>type</code> of
-      <code>l3gateway</code>, whose locations are identified by
-      <code>ovn-northd</code> via the <code>options:l3gateway-chassis</code>
-      column in this table.  <code>ovn-controller</code> is still responsible
-      to populate the <code>chassis</code> column.)
+      <code>ovn-controller</code> expects the <code>chassis</code> column
+      to be populated by <code>ovn-northd</code> or by the administrator
+      (using the <code>ovn-sbctl</code> utility).
     </p>
 
     <p>
-      When a chassis shuts down gracefully, it should clean up the
-      <code>chassis</code> column that it previously had populated.
+      <code>ovn-controller-vtep</code> populates the <code>chassis</code> column
+      for the records that identify the logical ports that are located on its hypervisor/gateway,
+      which <code>ovn-controller-vtep</code> in turn finds out by monitoring
+      the local hypervisor's Open_vSwitch database, which identifies logical
+      ports via the conventions described in <code>IntegrationGuide.rst</code>.
+    </p>
+
+    <p>
+      When a chassis shuts down gracefully, CMS via <code>ovn-northd</code>
+      should clean up <code>chassis</code> column for the logical ports hosted
+      in this chassis.
       (This is not critical because resources hosted on the chassis are equally
       unreachable regardless of whether their rows are present.)  To handle the
       case where a VM is shut down abruptly on one chassis, then brought up
       again on a different one,
-      <code>ovn-controller</code>/<code>ovn-controller-vtep</code> must
+      <code>ovn-northd</code>/<code>ovn-controller-vtep</code> must
       overwrite the <code>chassis</code> column with new information.
     </p>
 
@@ -1640,8 +1639,10 @@ tcp.flags = RST;
           <dt>(empty string)</dt>
           <dd>
             The physical location of the logical port.  To successfully identify a
-            chassis, this column must be a <ref table="Chassis"/> record.  This is
-            populated by <code>ovn-controller</code>.
+            chassis, this column must be a <ref table="Chassis"/> record.
+            This is populated by <code>ovn-northd</code> based on the value
+            of the <code>options:chassis</code> column in the
+            <ref table="Logical_Switch_Port"/> table if defined by CMS.
           </dd>
 
           <dt>vtep</dt>
@@ -1660,17 +1661,19 @@ tcp.flags = RST;
           <dt>l3gateway</dt>
           <dd>
             The physical location of the L3 gateway.  To successfully identify a
-            chassis, this column must be a <ref table="Chassis"/> record.  This is
-            populated by <code>ovn-controller</code> based on the value of
-            the <code>options:l3gateway-chassis</code> column in this table.
+            chassis, this column must be a <ref table="Chassis"/> record.
+            This is populated by <code>ovn-northd</code> based on the value
+            of the <code>options:chassis</code> column in the
+            <ref table="Logical_Switch_Port"/> table if defined by CMS.
           </dd>
 
           <dt>l2gateway</dt>
           <dd>
             The physical location of this L2 gateway.  To successfully identify a
             chassis, this column must be a <ref table="Chassis"/> record.
-            This is populated by <code>ovn-controller</code> based on the value
-            of the <code>options:l2gateway-chassis</code> column in this table.
+            This is populated by <code>ovn-northd</code> based on the value
+            of the <code>options:l2gateway-chassis</code> column in the
+            <ref table="Logical_Switch_Port"/> table if defined by CMS.
           </dd>
         </dl>
 
diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
index 8442431..abb173d 100644
--- a/tests/ovn-controller.at
+++ b/tests/ovn-controller.at
@@ -80,6 +80,8 @@ ovn-sbctl \
         type=localnet options:network_name=physnet1 \
     -- create Port_Binding datapath=@dp102 logical_port=localvif2 tunnel_key=2
 ovs-vsctl add-port br-int localvif2 -- set Interface localvif2 external_ids:iface-id=localvif2
+ovn-sbctl lsp-bind localvif2 hv
+
 check_patches \
     'br-int  patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
     'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
diff --git a/tests/ovn.at b/tests/ovn.at
index 6ae4247..4814861 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1028,6 +1028,7 @@ for i in 1 2 3; do
     for j in 1 2 3; do
         ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
         ovn-nbctl lsp-add lsw0 lp$i$j
+        ovn-nbctl lsp-set-options lp$i$j chassis=hv$i
         if test $j = 1; then
             ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
         else
@@ -1566,6 +1567,7 @@ for i in 1 2; do
         fi
 
         ovn-nbctl lsp-add $ls_name $lsp_name
+        ovn-nbctl lsp-set-options $lsp_name chassis=hv$i
         ovn-nbctl lsp-set-addresses $lsp_name f0:00:00:00:00:$i$j
         ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$j
 
@@ -1699,6 +1701,7 @@ as hv1
 ovs-vsctl add-br br-phys
 ovn_attach n1 br-phys 192.168.0.1
 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
+ovn-nbctl lsp-set-options lp1 chassis=hv1
 
 # Create hypervisor hv2 connected to n1
 sim_add hv2
@@ -1706,7 +1709,7 @@ as hv2
 ovs-vsctl add-br br-phys
 ovn_attach n1 br-phys 192.168.0.2
 ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
-
+ovn-nbctl lsp-set-options lp2 chassis=hv2
 
 # Start the vtep emulator with a leg in both networks
 sim_add vtep
@@ -1873,6 +1876,7 @@ as hv1
 ovs-vsctl add-br br-phys
 ovn_attach n1 br-phys 192.168.0.1
 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
+ovn-nbctl lsp-set-options lp1 chassis=hv1
 
 # Create hypervisor hv2 connected to n1
 sim_add hv2
@@ -1880,6 +1884,7 @@ as hv2
 ovs-vsctl add-br br-phys
 ovn_attach n1 br-phys 192.168.0.2
 ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
+ovn-nbctl lsp-set-options lp2 chassis=hv2
 
 # Create hypervisor hv_gw connected to n1 and n2
 # connect br-phys bridge to n1; connect hv-gw bridge to n2
@@ -2092,6 +2097,7 @@ for i in 1 2 3; do
                     options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
                     options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
                     ofport-request=$i$j$k
+            ovn-nbctl lsp-set-options lp$i$j$k chassis=hv$hv
         done
     done
 done
@@ -2430,6 +2436,7 @@ for i in 1 2 3; do
     for j in 1 2 3; do
         ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
         ovn-nbctl lsp-add lsw0 lp$i$j
+        ovn-nbctl lsp-set-options lp$i$j chassis=hv$i
         if test $j = 1; then
             ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
         elif test $j = 2; then
@@ -2839,6 +2846,7 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options ls1-lp1 chassis=hv1
 
 sim_add hv2
 as hv2
@@ -2849,6 +2857,7 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \
     options:tx_pcap=hv2/vif1-tx.pcap \
     options:rxq_pcap=hv2/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options ls2-lp1 chassis=hv2
 
 
 # Pre-populate the hypervisors' ARP tables so that we don't lose any
@@ -2945,13 +2954,14 @@ ovs-vsctl -- add-port br-int vif1 -- \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options ls1-lp1 chassis=hv1
 
 ovs-vsctl -- add-port br-int vif2 -- \
     set interface vif2 external-ids:iface-id=ls1-lp2 \
     options:tx_pcap=hv1/vif2-tx.pcap \
     options:rxq_pcap=hv1/vif2-rx.pcap \
     ofport-request=1
-
+ovn-nbctl lsp-set-options ls1-lp2 chassis=hv1
 
 # Allow some time for ovn-northd and ovn-controller to catch up.
 # XXX This should be more systematic.
@@ -3080,13 +3090,14 @@ ovs-vsctl -- add-port br-int vif1 -- \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options ls1-lp1 chassis=hv1
 
 ovs-vsctl -- add-port br-int vif2 -- \
     set interface vif2 external-ids:iface-id=ls2-lp1 \
     options:tx_pcap=hv1/vif2-tx.pcap \
     options:rxq_pcap=hv1/vif2-rx.pcap \
     ofport-request=1
-
+ovn-nbctl lsp-set-options ls2-lp1 chassis=hv1
 
 # Allow some time for ovn-northd and ovn-controller to catch up.
 # XXX This should be more systematic.
@@ -3217,12 +3228,14 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options foo1 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif2 -- \
     set interface hv1-vif2 external-ids:iface-id=alice1 \
     options:tx_pcap=hv1/vif2-tx.pcap \
     options:rxq_pcap=hv1/vif2-rx.pcap \
     ofport-request=2
+ovn-nbctl lsp-set-options alice1 chassis=hv1
 
 sim_add hv2
 as hv2
@@ -3233,6 +3246,7 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \
     options:tx_pcap=hv2/vif1-tx.pcap \
     options:rxq_pcap=hv2/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options bob1 chassis=hv2
 
 
 # Pre-populate the hypervisors' ARP tables so that we don't lose any
@@ -3333,6 +3347,7 @@ AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
 AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
 
 AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface localvif1 external_ids:iface-id=localvif1])
+ovn-nbctl lsp-set-options localvif1 chassis=hv
 
 # Wait for packet to be received.
 echo "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" > expected
@@ -3429,12 +3444,14 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options foo1 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif2 -- \
     set interface hv1-vif2 external-ids:iface-id=alice1 \
     options:tx_pcap=hv1/vif2-tx.pcap \
     options:rxq_pcap=hv1/vif2-rx.pcap \
     ofport-request=2
+ovn-nbctl lsp-set-options alice1 chassis=hv1
 
 sim_add hv2
 as hv2
@@ -3445,7 +3462,7 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \
     options:tx_pcap=hv2/vif1-tx.pcap \
     options:rxq_pcap=hv2/vif1-rx.pcap \
     ofport-request=1
-
+ovn-nbctl lsp-set-options bob1 chassis=hv2
 
 # Pre-populate the hypervisors' ARP tables so that we don't lose any
 # packets for ARP resolution (native tunneling doesn't queue packets
@@ -3568,24 +3585,28 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options ls1-lp1 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif2 -- \
     set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
     options:tx_pcap=hv1/vif2-tx.pcap \
     options:rxq_pcap=hv1/vif2-rx.pcap \
     ofport-request=2
+ovn-nbctl lsp-set-options ls1-lp2 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif3 -- \
     set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
     options:tx_pcap=hv1/vif3-tx.pcap \
     options:rxq_pcap=hv1/vif3-rx.pcap \
     ofport-request=3
+ovn-nbctl lsp-set-options ls2-lp1 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif4 -- \
     set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
     options:tx_pcap=hv1/vif4-tx.pcap \
     options:rxq_pcap=hv1/vif4-rx.pcap \
     ofport-request=4
+ovn-nbctl lsp-set-options ls2-lp2 chassis=hv1
 
 ovn_populate_arp
 
@@ -3840,30 +3861,35 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options ls1-lp1 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif2 -- \
     set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
     options:tx_pcap=hv1/vif2-tx.pcap \
     options:rxq_pcap=hv1/vif2-rx.pcap \
     ofport-request=2
+ovn-nbctl lsp-set-options ls1-lp2 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif3 -- \
     set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
     options:tx_pcap=hv1/vif3-tx.pcap \
     options:rxq_pcap=hv1/vif3-rx.pcap \
     ofport-request=3
+ovn-nbctl lsp-set-options ls2-lp1 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif4 -- \
     set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
     options:tx_pcap=hv1/vif4-tx.pcap \
     options:rxq_pcap=hv1/vif4-rx.pcap \
     ofport-request=4
+ovn-nbctl lsp-set-options ls2-lp2 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif5 -- \
     set interface hv1-vif5 external-ids:iface-id=ls1-lp3 \
     options:tx_pcap=hv1/vif5-tx.pcap \
     options:rxq_pcap=hv1/vif5-rx.pcap \
     ofport-request=5
+ovn-nbctl lsp-set-options ls1-lp3 chassis=hv1
 
 ovn_populate_arp
 
@@ -4078,7 +4104,6 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
 
-
 sim_add hv2
 as hv2
 ovs-vsctl add-br br-phys
@@ -4133,11 +4158,13 @@ R2 static_routes @lrt
 
 # Create logical port foo1 in foo
 ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
+-- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2" \
+-- lsp-set-options foo1 chassis=hv1
 
 # Create logical port alice1 in alice
 ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
+-- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2" \
+-- lsp-set-options alice1 chassis=hv2
 
 
 # Allow some time for ovn-northd and ovn-controller to catch up.
@@ -4273,13 +4300,14 @@ ovs-vsctl -- add-port br-int vif1 -- \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options ls1-lp1 chassis=hv1
 
 ovs-vsctl -- add-port br-int vif2 -- \
     set interface vif2 external-ids:iface-id=ls2-lp1 \
     options:tx_pcap=hv1/vif2-tx.pcap \
     options:rxq_pcap=hv1/vif2-rx.pcap \
     ofport-request=1
-
+ovn-nbctl lsp-set-options ls2-lp1 chassis=hv1
 
 # Allow some time for ovn-northd and ovn-controller to catch up.
 # XXX This should be more systematic.
@@ -4391,9 +4419,12 @@ as hv1 ovs-vsctl add-br br-phys
 as hv1 ovn_attach n1 br-phys 192.168.0.1
 
 as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1
+ovn-nbctl lsp-set-options lp1 chassis=hv1
+
 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
 
 as hv1 ovs-vsctl del-port br-int vif1
+ovn-nbctl lsp-set-options lp1 chassis=""
 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
 
 OVN_CLEANUP([hv1])
@@ -4446,11 +4477,13 @@ ovn-nbctl lsp-add ls1 lp1
 ovn-nbctl lsp-set-addresses lp1 unknown
 
 as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1
+ovn-nbctl lsp-set-options lp1 chassis=hv1
 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
 
 test_datapath_in_of_rules 1 "after port is bound"
 
 as hv1 ovs-vsctl del-port br-int vif1
+ovn-nbctl lsp-set-options lp1 chassis=""
 OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
 
 ovn-nbctl lsp-set-addresses lp1
@@ -4490,12 +4523,14 @@ ovn_attach n1 br-phys 192.168.0.2
 # Add vif1 to hv1 and lsw0, turn on l2 port security on vif1.
 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
 ovn-nbctl lsp-add lsw0 lp1
+ovn-nbctl lsp-set-options lp1 chassis=hv1
 ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:94:05:98 192.168.0.3 fd81:ce49:a948:0:f816:3eff:fe94:598"
 ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:94:05:98 192.168.0.3 fd81:ce49:a948:0:f816:3eff:fe94:598"
 
 # Add vif2 to hv1 and lsw0, turn on l2 port security on vif2.
 ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=hv1/vif2-tx.pcap options:rxq_pcap=hv1/vif2-rx.pcap ofport-request=2
 ovn-nbctl lsp-add lsw0 lp2
+ovn-nbctl lsp-set-options lp2 chassis=hv1
 ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:a1:f9:ae 192.168.0.4 fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
 ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:a1:f9:ae 192.168.0.4 fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
 
@@ -4776,18 +4811,21 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options foo1 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif2 -- \
     set interface hv1-vif2 external-ids:iface-id=foo2 \
     options:tx_pcap=hv1/vif2-tx.pcap \
     options:rxq_pcap=hv1/vif2-rx.pcap \
     ofport-request=2
+ovn-nbctl lsp-set-options foo2 chassis=hv1
 
 ovs-vsctl -- add-port br-int hv1-vif3 -- \
     set interface hv1-vif3 external-ids:iface-id=alice1 \
     options:tx_pcap=hv1/vif3-tx.pcap \
     options:rxq_pcap=hv1/vif3-rx.pcap \
     ofport-request=3
+ovn-nbctl lsp-set-options alice1 chassis=hv1
 
 # Allow some time for ovn-northd and ovn-controller to catch up.
 # XXX This should be more systematic.
@@ -4879,6 +4917,7 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options ls1-lp1 chassis=hv1
 
 ovn_populate_arp
 sleep 2
@@ -4997,11 +5036,14 @@ ovs-vsctl -- add-port br-int hv1-ls1lp2 -- \
     options:tx_pcap=hv1/ls1lp2-tx.pcap \
     options:rxq_pcap=hv1/ls1lp2-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options ls1lp2 chassis=hv1
+
 ovs-vsctl -- add-port br-int hv1-ls2lp2 -- \
     set interface hv1-ls2lp2 external-ids:iface-id=ls2lp2 \
     options:tx_pcap=hv1/ls2lp2-tx.pcap \
     options:rxq_pcap=hv1/ls2lp2-rx.pcap \
     ofport-request=2
+ovn-nbctl lsp-set-options ls2lp2 chassis=hv1
 
 # Allow some time for ovn-northd and ovn-controller to catch up.
 # XXX This should be more systematic.
@@ -5188,6 +5230,10 @@ for i in `seq 1 3`; do
     -- lsp-set-addresses bar$i "f0:00:0a:01:02:$i 172.16.1.$ip"
 done
 
+for i in foo1 bar1 bar2 bar3; do
+    ovn-nbctl lsp-set-options $i chassis=hv1
+done
+
 OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=0 | grep REG13 | wc -l` -eq 4])
 
 OVN_CLEANUP([hv1])
@@ -5343,6 +5389,7 @@ AT_CHECK([ovn-nbctl lsp-set-port-security localvif3 "f0:00:00:00:00:03"])
 # Bind the localvif1 to hv1.
 as hv1
 AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface localvif1 external_ids:iface-id=localvif1])
+ovn-nbctl lsp-set-options localvif1 chassis=hv1
 
 # On hv1, check that there are no flows outputting bcast to tunnel
 OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip | grep output | wc -l` -eq 0])
@@ -5353,6 +5400,7 @@ OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip | grep
 
 # Now bind vif2 on hv2.
 AT_CHECK([ovs-vsctl add-port br-int localvif2 -- set Interface localvif2 external_ids:iface-id=localvif2])
+ovn-nbctl lsp-set-options localvif2 chassis=hv2
 
 # At this point, the broadcast flow on vif2 should be deleted.
 # because, there is now a localnet vif bound (table=32 programming logic)
@@ -5363,6 +5411,7 @@ OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc
 
 # Now bind vif3 on hv2.
 AT_CHECK([ovs-vsctl add-port br-int localvif3 -- set Interface localvif3 external_ids:iface-id=localvif3])
+ovn-nbctl lsp-set-options localvif3 chassis=hv2
 
 # Verify that the local net patch port still exists on hv2
 OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc -l` -eq 1])
@@ -5397,6 +5446,8 @@ ovs-vsctl add-br br-phys
 ovn_attach n1 br-phys 192.168.0.1
 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=vif1-tx.pcap options:rxq_pcap=vif1-rx.pcap ofport-request=1
 ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=vif2-tx.pcap options:rxq_pcap=vif2-rx.pcap ofport-request=2
+ovn-nbctl lsp-set-options lp1 chassis=hv
+ovn-nbctl lsp-set-options lp2 chassis=hv
 
 AT_CAPTURE_FILE([trace])
 ovn_trace () {
@@ -5624,12 +5675,17 @@ ovs-vsctl -- add-port br-int vm1 -- \
     options:tx_pcap=hv1/vm1-tx.pcap \
     options:rxq_pcap=hv1/vm1-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options vm1 chassis=hv1
+ovn-nbctl lsp-set-options bar1 chassis=hv1
+ovn-nbctl lsp-set-options foo1 chassis=hv1
 
 ovs-vsctl -- add-port br-int bar3 -- \
     set interface bar3 external-ids:iface-id=bar3 \
     options:tx_pcap=hv1/bar3-tx.pcap \
     options:rxq_pcap=hv1/bar3-rx.pcap \
     ofport-request=2
+ovn-nbctl lsp-set-options bar3 chassis=hv1
+ovn-nbctl lsp-set-options bar3 chassis=hv1
 
 sim_add hv2
 as hv2
@@ -5640,12 +5696,18 @@ ovs-vsctl -- add-port br-int vm2 -- \
     options:tx_pcap=hv2/vm2-tx.pcap \
     options:rxq_pcap=hv2/vm2-rx.pcap \
     ofport-request=1
+ovn-nbctl lsp-set-options vm2 chassis=hv2
+ovn-nbctl lsp-set-options bar2 chassis=hv2
+ovn-nbctl lsp-set-options foo2 chassis=hv2
 
 # Pre-populate the hypervisors' ARP tables so that we don't lose any
 # packets for ARP resolution (native tunneling doesn't queue packets
 # for ARP resolution).
 ovn_populate_arp
 
+ovsdb-client dump unix:$ovs_base/ovn-sb/ovn-sb.sock
+ovsdb-client dump unix:$ovs_base/ovn-nb/ovn-nb.sock
+
 # Allow some time for ovn-northd and ovn-controller to catch up.
 # XXX This should be more systematic.
 sleep 1
@@ -5804,7 +5866,6 @@ ovs-vsctl -- add-port br-int hv3-vif1 -- \
     options:rxq_pcap=hv3/vif1-rx.pcap \
     ofport-request=1
 
-
 ovn-nbctl create Logical_Router name=R1
 ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
 ovn-nbctl create Logical_Router name=R3 options:chassis="hv3"
@@ -5876,6 +5937,11 @@ ovn-nbctl lsp-add alice alice1 \
 ovn-nbctl lsp-add bob bob1 \
 -- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
 
+ovn-nbctl lsp-set-options foo1 chassis=hv1
+ovn-nbctl lsp-set-options bar1 chassis=hv1
+ovn-nbctl lsp-set-options alice1 chassis=hv2
+ovn-nbctl lsp-set-options bob1 chassis=hv3
+
 # Pre-populate the hypervisors' ARP tables so that we don't lose any
 # packets for ARP resolution (native tunneling doesn't queue packets
 # for ARP resolution).
