diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c
index dfe002b..ef8445f 100644
--- a/ovn/controller/binding.c
+++ b/ovn/controller/binding.c
@@ -460,7 +460,12 @@ is_our_chassis(const struct sbrec_chassis *chassis_rec,
     return our_chassis;
 }
 
-static void
+/* Updates 'binding_rec' and if the port binding is local also updates the
+ * local datapaths and ports.
+ * Updates and returns the array of local virtual ports that will require
+ * additional processing.
+ */
+static const struct sbrec_port_binding **
 consider_local_datapath(struct ovsdb_idl_txn *ovnsb_idl_txn,
                         struct ovsdb_idl_txn *ovs_idl_txn,
                         struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
@@ -473,7 +478,9 @@ consider_local_datapath(struct ovsdb_idl_txn *ovnsb_idl_txn,
                         struct hmap *local_datapaths,
                         struct shash *lport_to_iface,
                         struct sset *local_lports,
-                        struct sset *local_lport_ids)
+                        struct sset *local_lport_ids,
+                        const struct sbrec_port_binding **vpbs,
+                        size_t *n_vpbs, size_t *n_allocated_vpbs)
 {
     const struct ovsrec_interface *iface_rec
         = shash_find_data(lport_to_iface, binding_rec->logical_port);
@@ -572,22 +579,11 @@ consider_local_datapath(struct ovsdb_idl_txn *ovnsb_idl_txn,
             }
         } else if (binding_rec->chassis == chassis_rec) {
             if (!strcmp(binding_rec->type, "virtual")) {
-                /* pinctrl module takes care of binding the ports
-                 * of type 'virtual'.
-                 * Release such ports if their virtual parents are no
-                 * longer claimed by this chassis. */
-                const struct sbrec_port_binding *parent
-                    = lport_lookup_by_name(sbrec_port_binding_by_name,
-                                        binding_rec->virtual_parent);
-                if (!parent || parent->chassis != chassis_rec) {
-                    VLOG_INFO("Releasing lport %s from this chassis.",
-                            binding_rec->logical_port);
-                    if (binding_rec->encap) {
-                        sbrec_port_binding_set_encap(binding_rec, NULL);
-                    }
-                    sbrec_port_binding_set_chassis(binding_rec, NULL);
-                    sbrec_port_binding_set_virtual_parent(binding_rec, NULL);
+                if (*n_vpbs == *n_allocated_vpbs) {
+                    vpbs = x2nrealloc(vpbs, n_allocated_vpbs, sizeof *vpbs);
                 }
+                vpbs[(*n_vpbs)] = binding_rec;
+                (*n_vpbs)++;
             } else {
                 VLOG_INFO("Releasing lport %s from this chassis.",
                           binding_rec->logical_port);
@@ -606,6 +602,30 @@ consider_local_datapath(struct ovsdb_idl_txn *ovnsb_idl_txn,
                          vif_chassis);
         }
     }
+    return vpbs;
+}
+
+static void
+consider_local_virtual_port(struct ovsdb_idl_index *sbrec_port_binding_by_name,
+                            const struct sbrec_chassis *chassis_rec,
+                            const struct sbrec_port_binding *binding_rec)
+{
+    /* pinctrl module takes care of binding the ports of type 'virtual'.
+     * Release such ports if their virtual parents are no longer claimed by
+     * this chassis.
+     */
+    const struct sbrec_port_binding *parent =
+        lport_lookup_by_name(sbrec_port_binding_by_name,
+                             binding_rec->virtual_parent);
+    if (!parent || parent->chassis != chassis_rec) {
+        VLOG_INFO("Releasing lport %s from this chassis.",
+                  binding_rec->logical_port);
+        if (binding_rec->encap) {
+            sbrec_port_binding_set_encap(binding_rec, NULL);
+        }
+        sbrec_port_binding_set_chassis(binding_rec, NULL);
+        sbrec_port_binding_set_virtual_parent(binding_rec, NULL);
+    }
 }
 
 static void
@@ -662,20 +682,41 @@ binding_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
                             &egress_ifaces);
     }
 
+    /* Array to store pointers to local virtual ports. It is populated by
+     * consider_local_datapath.
+     */
+    const struct sbrec_port_binding **vpbs = NULL;
+    size_t n_vpbs = 0;
+    size_t n_allocated_vpbs = 0;
+
     /* Run through each binding record to see if it is resident on this
      * chassis and update the binding accordingly.  This includes both
-     * directly connected logical ports and children of those ports. */
+     * directly connected logical ports and children of those ports.
+     * Virtual ports are just added to vpbs array and will be processed
+     * later. This is special case for virtual ports is needed in order to
+     * make sure we update the virtual_parent port bindings first.
+     */
     SBREC_PORT_BINDING_TABLE_FOR_EACH (binding_rec, port_binding_table) {
-        consider_local_datapath(ovnsb_idl_txn, ovs_idl_txn,
-                                sbrec_datapath_binding_by_key,
-                                sbrec_port_binding_by_datapath,
-                                sbrec_port_binding_by_name,
-                                active_tunnels, chassis_rec, binding_rec,
-                                sset_is_empty(&egress_ifaces) ? NULL :
-                                &qos_map, local_datapaths, &lport_to_iface,
-                                local_lports, local_lport_ids);
-
-    }
+        vpbs =
+            consider_local_datapath(ovnsb_idl_txn, ovs_idl_txn,
+                                    sbrec_datapath_binding_by_key,
+                                    sbrec_port_binding_by_datapath,
+                                    sbrec_port_binding_by_name,
+                                    active_tunnels, chassis_rec, binding_rec,
+                                    sset_is_empty(&egress_ifaces) ? NULL :
+                                    &qos_map, local_datapaths, &lport_to_iface,
+                                    local_lports, local_lport_ids,
+                                    vpbs, &n_vpbs, &n_allocated_vpbs);
+    }
+
+    /* Now also update the virtual ports in case their parent ports were
+     * updated above.
+     */
+    for (size_t i = 0; i < n_vpbs; i++) {
+        consider_local_virtual_port(sbrec_port_binding_by_name, chassis_rec,
+                                    vpbs[i]);
+    }
+    free(vpbs);
 
     /* Run through each binding record to see if it is a localnet port
      * on local datapaths discovered from above loop, and update the
