VOL-710: ADTRAN_ONU: Move default flow into an OpenOMCI Task

Change-Id: I075052a3e35fb6e38da10c53dddcd1b3d21c8bc9
diff --git a/voltha/adapters/adtran_onu/adtran_onu_handler.py b/voltha/adapters/adtran_onu/adtran_onu_handler.py
index 8e7282f..e6598a3 100644
--- a/voltha/adapters/adtran_onu/adtran_onu_handler.py
+++ b/voltha/adapters/adtran_onu/adtran_onu_handler.py
@@ -939,7 +939,7 @@
             # If the PON has already synchronized, add the logical port now
             # since we know we have been activated
 
-            if self._pon is not None and self._pon.connected:
+            if self._pon is not None and self.openomci.connected:
                 uni_port.add_logical_port(ofp_port_no, subscriber_vlan=subscriber_vlan)
 
         # TODO: Next is just for debugging to see what this call returns after
diff --git a/voltha/adapters/adtran_onu/omci/adtn_mib_download_task.py b/voltha/adapters/adtran_onu/omci/adtn_mib_download_task.py
index a6d6d5c..b6fb650 100644
--- a/voltha/adapters/adtran_onu/omci/adtn_mib_download_task.py
+++ b/voltha/adapters/adtran_onu/omci/adtn_mib_download_task.py
@@ -14,11 +14,26 @@
 # limitations under the License.
 #
 from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks, returnValue, TimeoutError, failure
+from voltha.extensions.omci.omci_me import *
 from voltha.extensions.omci.tasks.task import Task
-from twisted.internet.defer import inlineCallbacks, TimeoutError, failure
-from voltha.extensions.omci.omci_me import OntDataFrame
 from voltha.extensions.omci.omci_defs import *
 
+OP = EntityOperations
+RC = ReasonCodes
+
+
+class MibDownloadFailure(Exception):
+    """
+    This error is raised by default when the download fails
+    """
+
+
+class MibResourcesFailure(Exception):
+    """
+    This error is raised by when one or more resources required is not available
+    """
+
 
 class AdtnMibDownloadTask(Task):
     """
@@ -36,10 +51,13 @@
     Currently, the only service tech profiles expected by v2.0 will be for AT&T
     residential data service and DT residential data service.
     """
-    task_priority = Task.DEFAULT_PRIORITY
+    task_priority = Task.DEFAULT_PRIORITY + 10
+    default_tpid = 0x8100
+    default_gem_payload = 1518
+
     name = "ADTRAN MIB Download Example Task"
 
-    def __init__(self, omci_agent, device_id):
+    def __init__(self, omci_agent, handler):
         """
         Class initialization
 
@@ -48,10 +66,38 @@
         """
         super(AdtnMibDownloadTask, self).__init__(AdtnMibDownloadTask.name,
                                                   omci_agent,
-                                                  device_id,
+                                                  handler.device_id,
                                                   priority=AdtnMibDownloadTask.task_priority)
+        self._handler = handler
+        self._onu_device = omci_agent.get_device(handler.device_id)
         self._local_deferred = None
 
+        # Frame size
+        self._max_gem_payload = AdtnMibDownloadTask.default_gem_payload
+
+        # Port numbers
+        self._pon_port_num = 0
+        self._uni_port_num = 0  # TODO Both port numbers are the same, is this correct?  See MacBridgePortConfigurationDataFrame
+
+        self._vlan_tcis_1 = 0x900
+        self._input_tpid = AdtnMibDownloadTask.default_tpid
+        self._output_tpid = AdtnMibDownloadTask.default_tpid
+
+        device = self._handler.adapter_agent.get_device(self.device_id)
+        self._cvid = device.vlan
+
+        # Entity IDs. IDs with values can probably be most anything for most ONUs,
+        #             IDs set to None are discovered/set
+
+        self._mac_bridge_service_profile_entity_id = 0x100
+        self._ieee_mapper_service_profile_entity_id = 0x100
+        self._mac_bridge_port_ani_entity_id = 0x100
+        self._gal_enet_profile_entity_id = 0x100
+
+        # Next to are specific
+        self._ethernet_uni_entity_id = self._handler.uni_ports[0].entity_id
+        self._vlan_config_entity_id = self._vlan_tcis_1
+
     def cancel_deferred(self):
         super(AdtnMibDownloadTask, self).cancel_deferred()
 
@@ -78,445 +124,459 @@
         self.cancel_deferred()
         super(AdtnMibDownloadTask, self).stop()
 
+    def check_status_and_state(self, results, operation=''):
+        """
+        Check the results of an OMCI response.  An exception is thrown
+        if the task was cancelled or an error was detected.
+
+        :param results: (OmciFrame) OMCI Response frame
+        :param operation: (str) what operation was being performed
+        :return: True if successful, False if the entity existed (already created)
+        """
+        if not self.running:
+            raise MibDownloadFailure('Download Task was cancelled')
+
+        omci_msg = results.fields['omci_message'].fields
+        status = omci_msg['success_code']
+        error_mask = omci_msg.get('parameter_error_attributes_mask', 'n/a')
+        failed_mask = omci_msg.get('failed_attributes_mask', 'n/a')
+        unsupported_mask = omci_msg.get('unsupported_attributes_mask', 'n/a')
+
+        self.log.debug(operation, status=status, error_mask=error_mask,
+                       failed_mask=failed_mask, unsupported_mask=unsupported_mask)
+
+        if status == RC.Success:
+            return True
+
+        elif status == RC.InstanceExists:
+            return False
+
+        raise MibDownloadFailure('{} failed with a status of {}, error_mask: {}, failed_mask: {}, unsupported_mask: {}'
+                                 .format(operation, status, error_mask, failed_mask, unsupported_mask))
+
     @inlineCallbacks
     def perform_mib_download(self):
         """
-        Send the commands
+        Send the commands to minimally configure the PON, Bridge, and
+        UNI ports for this device. The application of any service flows
+        and other characteristics are done as needed.
         """
         self.log.info('perform-download')
 
-        # if not self.enabled:
-        #     returnValue('not-enabled')
-        #
-        # device = self._handler.adapter_agent.get_device(self._handler.device_id)
-        #
-        # def resources_available():
-        #     return (device.vlan > 0 and
-        #             len(self._handler.uni_ports) > 0 and
-        #             len(self._handler.pon_port.tconts) and
-        #             len(self._handler.pon_port.gem_ports))
-        #
-        # if not self._bridge_initialized and resources_available():
-        #     device.reason = 'Performing OMCI Download'
-        #     self._handler.adapter_agent.update_device(device)
-        #
-        #     omci = self.omci_cc
-        #
-        #     #############################################
-        #     #  All our variables here
-        #     #  TODO: Move elsewhere in future version of this software
-        #     #  TODO: Make as many entity IDs dynamic/discovered as possible
-        #
-        #     frame = None
-        #     gal_enet_profile_entity_id = 0x100
-        #     ieee_mapper_service_profile_entity_id = 0x100
-        #     mac_bridge_service_profile_entity_id = 0x100
-        #     mac_bridge_port_ani_entity_id = 0x100
-        #     ethernet_uni_entity_id = 0x101  # TODO: This can be retrieved from the UNI-G instance_id
-        #     vlan_tcis_1 = 0x900
-        #     vlan_config_entity_id = vlan_tcis_1
-        #     cvid = device.vlan
-        #
-        #     try:
-        #         ################################################################################
-        #         # TCONTS
-        #         #
-        #         #  EntityID will be referenced by:
-        #         #            - GemPortNetworkCtp
-        #         #  References:
-        #         #            - ONU created TCONT (created on ONU startup)
-        #
-        #         omci_dev = self._onu_omci_device
-        #         tcont_idents = omci_dev.query_mib(Tcont.class_id)
-        #         self.log.debug('tcont-idents', tcont_idents=tcont_idents)
-        #
-        #         for tcont in self._handler.pon_port.tconts.itervalues():
-        #             free_entity_id = next((k for k, v in tcont_idents.items()
-        #                                    if isinstance(k, int) and
-        #                                    v.get('attributes', {}).get('alloc_id', 0) == 0xFFFF), None)
-        #             if free_entity_id is None:
-        #                 self.log.error('no-available-tconts')
-        #                 break
-        #
-        #             yield tcont.add_to_hardware(omci, free_entity_id)
-        #
-        #         ################################################################################
-        #         # GEMS  (GemPortNetworkCtp and GemInterworkingTp)
-        #         #
-        #         #  For both of these MEs, the entity_id is the GEM Port ID. The entity id of the
-        #         #  GemInterworkingTp ME could be different since it has an attribute to specify
-        #         #  the GemPortNetworkCtp entity id.
-        #         #
-        #         #  TODO: In the GEM Port routine to add, it has a hardcoded upstream TM ID of 0x8000
-        #         #        for the GemPortNetworkCtp ME
-        #         #
-        #         #  GemPortNetworkCtp
-        #         #    EntityID will be referenced by:
-        #         #              - GemInterworkingTp
-        #         #    References:
-        #         #              - TCONT
-        #         #              - Hardcoded upstream TM Entity ID
-        #         #              - (Possibly in Future) Upstream Traffic descriptor profile pointer
-        #         #
-        #         #  GemInterworkingTp
-        #         #    EntityID will be referenced by:
-        #         #              - Ieee8021pMapperServiceProfile
-        #         #    References:
-        #         #              - GemPortNetworkCtp
-        #         #              - Ieee8021pMapperServiceProfile
-        #         #              - GalEthernetProfile
-        #         #
-        #         for gem_port in self._handler.pon_port.gem_ports.itervalues():
-        #             tcont = gem_port.tcont
-        #             if tcont is None:
-        #                 self.log.error('unknown-tcont-reference', gem_id=gem_port.gem_id)
-        #                 continue
-        #
-        #             yield gem_port.add_to_hardware(omci,
-        #                                            tcont.entity_id,
-        #                                            ieee_mapper_service_profile_entity_id,
-        #                                            gal_enet_profile_entity_id)
-        #
-        #         ########################################################################################
-        #         # Create GalEthernetProfile - Once per ONU/PON interface
-        #         #
-        #         #  EntityID will be referenced by:
-        #         #            - GemInterworkingTp
-        #         #  References:
-        #         #            - Nothing
-        #
-        #         frame = GalEthernetProfileFrame(gal_enet_profile_entity_id,
-        #                                         max_gem_payload_size=1518).create()  # Max GEM Payload size
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-        #         self.log.debug('create-gal-ethernet-profile', status=status, error_mask=error_mask)
-        #
-        #         ################################################################################
-        #         # MAC Bridge Service Profile - Once per UNI
-        #         #
-        #         #  EntityID will be referenced by:
-        #         #            - MAC Bridge Port Configuration Data
-        #         #  References:
-        #         #            - Nothing
-        #
-        #         attributes = {
-        #             'spanning_tree_ind': False,
-        #             #  TODO: CB: see if we need or can use any of the following...
-        #             # 'learning_ind': True,
-        #             # 'priority': 0x8000,
-        #             # 'max_age': 20 * 256,
-        #             # 'hello_time': 2 * 256,
-        #             # 'forward_delay': 15 * 256,
-        #             # 'unknown_mac_address_discard': True
-        #         }
-        #         frame = MacBridgeServiceProfileFrame(mac_bridge_service_profile_entity_id,
-        #                                              attributes).create()
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-        #         self.log.debug('create-mac-bridge-service-profile', status=status, error_mask=error_mask)
-        #
-        #         ################################################################################
-        #         # IEEE 802.1 Mapper Service config - Once per PON
-        #         #
-        #         #  EntityID will be referenced by:
-        #         #            - MAC Bridge Port Configuration Data for the PON port
-        #         #  References:
-        #         #            - Nothing at this point. When a GEM port is created, this entity will
-        #         #              be updated to reference the GEM Interworking TP
-        #
-        #         frame = Ieee8021pMapperServiceProfileFrame(ieee_mapper_service_profile_entity_id).create()
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-        #         self.log.debug('create-8021p-mapper-service-profile', status=status, error_mask=error_mask)
-        #
-        #         ################################################################################
-        #         # Create MAC Bridge Port Configuration Data for the PON port via IEEE 802.1
-        #         # mapper service. Upon receipt by the ONU, the ONU will create an instance
-        #         # of the following before returning the response.
-        #         #
-        #         #     - MAC bridge port designation data
-        #         #     - MAC bridge port filter table data
-        #         #     - MAC bridge port bridge table data
-        #         #
-        #         #  EntityID will be referenced by:
-        #         #            - Implicitly by the VLAN tagging filter data
-        #         #  References:
-        #         #            - MAC Bridge Service Profile (the bridge)
-        #         #            - IEEE 802.1p mapper service profile for PON port
-        #
-        #         frame = MacBridgePortConfigurationDataFrame(
-        #             mac_bridge_port_ani_entity_id,  # Entity ID
-        #             bridge_id_pointer=mac_bridge_service_profile_entity_id,  # Bridge Entity ID
-        #             # TODO: The PORT number for this port and the UNI port are the same. Is this correct?
-        #             port_num=0,  # Port ID
-        #             tp_type=3,  # TP Type (IEEE 802.1p mapper service)
-        #             tp_pointer=ieee_mapper_service_profile_entity_id  # TP ID, 8021p mapper ID
-        #         ).create()
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-        #         self.log.debug('create-mac-bridge-port-configuration-data-part-1', status=status, error_mask=error_mask)
-        #
-        #         ################################################################################
-        #         # MAC Bridge Port config
-        #         # This configuration is for Ethernet UNI
-        #         #
-        #         #  EntityID will be referenced by:
-        #         #            - Nothing
-        #         #  References:
-        #         #            - MAC Bridge Service Profile (the bridge)
-        #         #            - PPTP Ethernet UNI
-        #
-        #         frame = MacBridgePortConfigurationDataFrame(
-        #             0x000,  # Entity ID - This is read-only/set-by-create !!!
-        #             bridge_id_pointer=mac_bridge_service_profile_entity_id,  # Bridge Entity ID
-        #             port_num=0,  # Port ID
-        #             tp_type=1,  # PPTP Ethernet UNI
-        #             tp_pointer=ethernet_uni_entity_id  # TP ID, 8021p mapper Id
-        #         ).create()
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-        #         self.log.debug('create-mac-bridge-port-configuration-data-part-2', status=status, error_mask=error_mask)
-        #
-        #         ################################################################################
-        #         # VLAN Tagging Filter config
-        #         #
-        #         #  EntityID will be referenced by:
-        #         #            - Nothing
-        #         #  References:
-        #         #            - MacBridgePortConfigurationData for the ANI/PON side
-        #         #
-        #         # Set anything, this request will not be used when using Extended Vlan
-        #
-        #         frame = VlanTaggingFilterDataFrame(
-        #             mac_bridge_port_ani_entity_id,  # Entity ID
-        #             vlan_tcis=[vlan_tcis_1],  # VLAN IDs
-        #             forward_operation=0x10
-        #         ).create()
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-        #         self.log.debug('create-vlan-tagging-filter-data', status=status, error_mask=error_mask)
-        #
-        #         ################################################################################
-        #         # Update the IEEE 802.1p Mapper Service Profile config
-        #         #
-        #         #  EntityID was created prior to this call. This is a set
-        #         #
-        #         #  References:
-        #         #            - Gem Interwork TPs are set here
-        #         #
-        #         # TODO: All p-bits currently go to the one and only GEMPORT ID for now
-        #         gem_ports = self._handler.pon_port.gem_ports
-        #         gem_entity_ids = [gem_port.entity_id for _, gem_port in self._gem_ports.items()] \
-        #             if len(self._gem_ports) else [OmciNullPointer]
-        #
-        #         frame = Ieee8021pMapperServiceProfileFrame(
-        #             ieee_mapper_service_profile_entity_id,  # 802.1p mapper Service Mapper Profile ID
-        #             interwork_tp_pointers=gem_entity_ids  # Interworking TP IDs
-        #         ).set()
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         failed_attributes_mask = results.fields['omci_message'].fields['failed_attributes_mask']
-        #         unsupported_attributes_mask = results.fields['omci_message'].fields['unsupported_attributes_mask']
-        #         self.log.debug('set-8021p-mapper-service-profile', status=status,
-        #                        failed_attributes_mask=failed_attributes_mask,
-        #                        unsupported_attributes_mask=unsupported_attributes_mask)
-        #
-        #         ################################################################################
-        #         #  Unlock UNI
-        #         #
-        #         #  EntityID will be referenced by:
-        #         #            - MAC bridge port configuration data for the UNI side
-        #         #  References:
-        #         #            - Nothing
-        #
-        #         attributes = dict(
-        #             administrative_state=0  # 0 - Unlock
-        #         )
-        #         frame = PptpEthernetUniFrame(
-        #             ethernet_uni_entity_id,  # Entity ID
-        #             attributes=attributes  # See above
-        #         ).set()
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         failed_attributes_mask = results.fields['omci_message'].fields['failed_attributes_mask']
-        #         unsupported_attributes_mask = results.fields['omci_message'].fields['unsupported_attributes_mask']
-        #         self.log.debug('set-pptp-ethernet-uni', status=status,
-        #                        failed_attributes_mask=failed_attributes_mask,
-        #                        unsupported_attributes_mask=unsupported_attributes_mask)
-        #
-        #         ################################################################################
-        #         # Create Extended VLAN Tagging Operation config
-        #         #
-        #         #  EntityID relates to the VLAN TCIS
-        #         #  References:
-        #         #            - VLAN TCIS from previously created VLAN Tagging filter data
-        #         #            - PPTP Ethernet UNI
-        #         #
-        #         # TODO: add entry here for additional UNI interfaces
-        #
-        #         attributes = dict(
-        #             association_type=2,  # Assoc Type, PPTP Ethernet UNI
-        #             associated_me_pointer=ethernet_uni_entity_id  # Assoc ME, PPTP Entity Id
-        #         )
-        #
-        #         frame = ExtendedVlanTaggingOperationConfigurationDataFrame(
-        #             vlan_config_entity_id,
-        #             attributes=attributes
-        #         ).create()
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-        #         self.log.debug('create-extended-vlan-tagging-operation-configuration-data', status=status,
-        #                        error_mask=error_mask)
-        #
-        #         ################################################################################
-        #         # Update Extended VLAN Tagging Operation Config Data
-        #         #
-        #         # Specifies the TPIDs in use and that operations in the downstream direction are
-        #         # inverse to the operations in the upstream direction
-        #         # TODO: Downstream mode may need to be modified once we work more on the flow rules
-        #
-        #         attributes = dict(
-        #             input_tpid=0x8100,  # input TPID
-        #             output_tpid=0x8100,  # output TPID
-        #             downstream_mode=0,  # inverse of upstream
-        #         )
-        #         frame = ExtendedVlanTaggingOperationConfigurationDataFrame(
-        #             vlan_config_entity_id,
-        #             attributes=attributes
-        #         ).set()
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         failed_attributes_mask = results.fields['omci_message'].fields['failed_attributes_mask']
-        #         unsupported_attributes_mask = results.fields['omci_message'].fields['unsupported_attributes_mask']
-        #         self.log.debug('set-extended-vlan-tagging-operation-configuration-data', status=status,
-        #                        failed_attributes_mask=failed_attributes_mask,
-        #                        unsupported_attributes_mask=unsupported_attributes_mask)
-        #
-        #         ################################################################################
-        #         # Update Extended VLAN Tagging Operation Config Data
-        #         #
-        #         # parameters: Entity Id ( 0x900), Filter Inner Vlan Id(0x1000-4096,do not filter on Inner vid,
-        #         #             Treatment Inner Vlan Id : 2
-        #
-        #         attributes = dict(
-        #             received_frame_vlan_tagging_operation_table=
-        #             VlanTaggingOperation(
-        #                 filter_outer_priority=15,  # This entry is not a double-tag rule
-        #                 filter_outer_vid=4096,  # Do not filter on the outer VID value
-        #                 filter_outer_tpid_de=0,  # Do not filter on the outer TPID field
-        #
-        #                 filter_inner_priority=15,  # This is a no-tag rule, ignore all other VLAN tag filter fields
-        #                 filter_inner_vid=0x1000,  # Do not filter on the inner VID
-        #                 filter_inner_tpid_de=0,  # Do not filter on inner TPID field
-        #                 filter_ether_type=0,  # Do not filter on EtherType
-        #
-        #                 treatment_tags_to_remove=0,  # Remove 0 tags
-        #                 treatment_outer_priority=15,  # Do not add an outer tag
-        #                 treatment_outer_vid=0,  # n/a
-        #                 treatment_outer_tpid_de=0,  # n/a
-        #
-        #                 treatment_inner_priority=0,  # Add an inner tag and insert this value as the priority
-        #                 treatment_inner_vid=cvid,  # use this value as the VID in the inner VLAN tag
-        #                 treatment_inner_tpid_de=4  # set TPID = 0x8100
-        #             )
-        #         )
-        #         frame = ExtendedVlanTaggingOperationConfigurationDataFrame(
-        #             vlan_config_entity_id,  # Entity ID       BP: Oldvalue 0x202
-        #             attributes=attributes  # See above
-        #         ).set()
-        #         results = yield omci.send(frame)
-        #
-        #         status = results.fields['omci_message'].fields['success_code']
-        #         failed_attributes_mask = results.fields['omci_message'].fields['failed_attributes_mask']
-        #         unsupported_attributes_mask = results.fields['omci_message'].fields['unsupported_attributes_mask']
-        #         self.log.debug('set-extended-vlan-tagging-operation-configuration-data-untagged', status=status,
-        #                        failed_attributes_mask=failed_attributes_mask,
-        #                        unsupported_attributes_mask=unsupported_attributes_mask)
-        #
-        #         # BP: This is for AT&T RG's
-        #         #
-        #         #   TODO: CB: NOTE: TRY THIS ONCE OTHER SEQUENCES WORK
-        #         #
-        #         # Set AR - ExtendedVlanTaggingOperationConfigData
-        #         #          514 - RxVlanTaggingOperationTable - add VLAN <cvid> to priority tagged pkts - c-vid
-        #         # results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_single_tag(
-        #         #                                 0x900,  # Entity ID
-        #         #                                 8,      # Filter Inner Priority, do not filter on Inner Priority
-        #         #                                 0,    # Filter Inner VID, this will be 0 in CORD
-        #         #                                 0,      # Filter Inner TPID DE
-        #         #                                 1,      # Treatment tags, number of tags to remove
-        #         #                                 8,      # Treatment inner priority, copy Inner Priority
-        #         #                                 2)   # Treatment inner VID, this will be 2 in CORD
-        #
-        #         # Set AR - ExtendedVlanTaggingOperationConfigData
-        #         #          514 - RxVlanTaggingOperationTable - add VLAN <cvid> to priority tagged pkts - c-vid
-        #         # results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_single_tag(
-        #         #                                 0x200,  # Entity ID
-        #         #                                 8,      # Filter Inner Priority
-        #         #                                 0,      # Filter Inner VID
-        #         #                                 0,      # Filter Inner TPID DE
-        #         #                                 1,      # Treatment tags to remove
-        #         #                                 8,      # Treatment inner priority
-        #         #                                 cvid)   # Treatment inner VID
-        #         #
-        #         # Set AR - ExtendedVlanTaggingOperationConfigData
-        #         #          514 - RxVlanTaggingOperationTable - add VLAN <cvid> to untagged pkts - c-vid
-        #         # results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_untagged(
-        #         #                                0x100,   # Entity ID            BP: Oldvalue 0x202
-        #         #                                0x1000,  # Filter Inner VID     BP: Oldvalue 0x1000
-        #         #                                cvid)    # Treatment inner VID  BP: cvid
-        #
-        #         # success = results.fields['omci_message'].fields['success_code'] == 0
-        #         # error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-        #
-        #         ###############################################################################
-        #         # If here, we are done
-        #         self._bridge_initialized = True
-        #         device.reason = ''
-        #         self._handler.adapter_agent.update_device(device)
-        #
-        #     except TimeoutError as e:
-        #         self.log.warn('rx-timeout', frame=frame)
-        #         self._deferred = reactor.callLater(_STARTUP_RETRY_WAIT,
-        #                                            self.resync_omci_settings)
-        #         returnValue('retry-pending')
-        #
-        #     except Exception as e:
-        #         self.log.exception('omci-setup', e=e)
-        #         device.reason = 'OMCI setup sequence failure: ' + e.message
-        #         self._handler.adapter_agent.update_device(device)
-        #
-        #         # Try again later
-        #         self._deferred = reactor.callLater(_STARTUP_RETRY_WAIT,
-        #                                            self.resync_omci_settings)
-        # else:
-        #     self._deferred = reactor.callLater(_STARTUP_RETRY_WAIT,
-        #                                        self.resync_omci_settings)
+        device = self._handler.adapter_agent.get_device(self.device_id)
 
-        self.deferred.callback("TODO: Done, what should we provide back that is of value?")
-        #
-        # except TimeoutError as e:
-        #     self.log.warn('download-timeout', e=e)
-        #     self.deferred.errback(failure.Failure(e))
-        #     # TODO: Recover any allocated objects (tconts, priority queues, ...)
-        # except Exception as e:
-        #     self.log.exception('download', e=e)
-        #     self.deferred.errback(failure.Failure(e))
-        #     TODO: Recover any allocated objects (tconts, priority queues, ...)
+        def resources_available():
+            return (device.vlan > 0 and
+                    len(self._handler.uni_ports) > 0 and
+                    len(self._handler.pon_port.tconts) and
+                    len(self._handler.pon_port.gem_ports))
+
+        if self._handler.enabled and resources_available():
+            device.reason = 'Performing OMCI Download'
+            self._handler.adapter_agent.update_device(device)
+
+            try:
+                # Lock the UNI ports to prevent any alarms during initial configuration
+                # of the ONU
+                yield self.enable_unis(self._handler.uni_ports, True)
+
+                # Provision the initial bridge configuration
+                yield self.perform_initial_bridge_setup()
+
+                # And not all the service specific work
+                yield self.perform_service_specific_steps()
+
+                # And re-enable the UNIs if needed
+                yield self.enable_unis(self._handler.uni_ports, False)
+
+                # If here, we are done
+                device = self._handler.adapter_agent.get_device(self.device_id)
+
+                device.reason = ''
+                self._handler.adapter_agent.update_device(device)
+                self.deferred.callback('TODO: What should we return to the caller?')
+
+            except TimeoutError as e:
+                self.deferred.errback(failure.Failure(e))
+
+        else:
+            # TODO: Provide better error reason, what was missing...
+            e = MibResourcesFailure('Required resources are not available')
+            self.deferred.errback(failure.Failure(e))
+
+    @inlineCallbacks
+    def perform_initial_bridge_setup(self):
+        omci_cc = self._onu_device.omci_cc
+        frame = None
+
+        try:
+            ################################################################################
+            # Common - PON and/or UNI                                                      #
+            ################################################################################
+            # MAC Bridge Service Profile
+            #
+            #  EntityID will be referenced by:
+            #            - MAC Bridge Port Configuration Data (PON & UNI)
+            #  References:
+            #            - Nothing
+
+            attributes = {
+                'spanning_tree_ind': False
+            }
+            frame = MacBridgeServiceProfileFrame(
+                self._mac_bridge_service_profile_entity_id,
+                attributes
+            ).create()
+            results = yield omci_cc.send(frame)
+            self.check_status_and_state(results, 'create-mac-bridge-service-profile')
+
+            ################################################################################
+            # PON Specific                                                                 #
+            ################################################################################
+            # IEEE 802.1 Mapper Service config - Once per PON
+            #
+            #  EntityID will be referenced by:
+            #            - MAC Bridge Port Configuration Data for the PON port
+            #  References:
+            #            - Nothing at this point. When a GEM port is created, this entity will
+            #              be updated to reference the GEM Interworking TP
+
+            frame = Ieee8021pMapperServiceProfileFrame(self._ieee_mapper_service_profile_entity_id).create()
+            results = yield omci_cc.send(frame)
+            self.check_status_and_state(results, 'create-8021p-mapper-service-profile')
+
+            ################################################################################
+            # Create MAC Bridge Port Configuration Data for the PON port via IEEE 802.1
+            # mapper service. Upon receipt by the ONU, the ONU will create an instance
+            # of the following before returning the response.
+            #
+            #     - MAC bridge port designation data
+            #     - MAC bridge port filter table data
+            #     - MAC bridge port bridge table data
+            #
+            #  EntityID will be referenced by:
+            #            - Implicitly by the VLAN tagging filter data
+            #  References:
+            #            - MAC Bridge Service Profile (the bridge)
+            #            - IEEE 802.1p mapper service profile for PON port
+
+            frame = MacBridgePortConfigurationDataFrame(
+                self._mac_bridge_port_ani_entity_id,                    # Entity ID
+                bridge_id_pointer=self._mac_bridge_service_profile_entity_id,  # Bridge Entity ID
+                # TODO: The PORT number for this port and the UNI port are the same. Is this correct?
+                port_num=self._pon_port_num,                            # Port ID
+                tp_type=3,                                              # TP Type (IEEE 802.1p mapper service)
+                tp_pointer=self._ieee_mapper_service_profile_entity_id  # TP ID, 8021p mapper ID
+            ).create()
+            results = yield omci_cc.send(frame)
+            self.check_status_and_state(results, 'create-mac-bridge-port-configuration-data-part-1')
+
+            ################################################################################
+            # VLAN Tagging Filter config
+            #
+            #  EntityID will be referenced by:
+            #            - Nothing
+            #  References:
+            #            - MacBridgePortConfigurationData for the ANI/PON side
+            #
+            # Set anything, this request will not be used when using Extended Vlan
+
+            frame = VlanTaggingFilterDataFrame(
+                self._mac_bridge_port_ani_entity_id,  # Entity ID
+                vlan_tcis=[self._vlan_tcis_1],        # VLAN IDs
+                forward_operation=0x10
+            ).create()
+            results = yield omci_cc.send(frame)
+            self.check_status_and_state(results, 'create-vlan-tagging-filter-data')
+
+            ########################################################################################
+            # Create GalEthernetProfile - Once per ONU/PON interface
+            #
+            #  EntityID will be referenced by:
+            #            - GemInterworkingTp
+            #  References:
+            #            - Nothing
+
+            frame = GalEthernetProfileFrame(
+                self._gal_enet_profile_entity_id,
+                max_gem_payload_size=self._max_gem_payload
+            ).create()
+            results = yield omci_cc.send(frame)
+            self.check_status_and_state(results, 'create-gal-ethernet-profile')
+
+            ################################################################################
+            # UNI Specific                                                                 #
+            ################################################################################
+            # MAC Bridge Port config
+            # This configuration is for Ethernet UNI
+            #
+            #  EntityID will be referenced by:
+            #            - Nothing
+            #  References:
+            #            - MAC Bridge Service Profile (the bridge)
+            #            - PPTP Ethernet UNI
+
+            frame = MacBridgePortConfigurationDataFrame(
+                0x000,                                   # Entity ID - This is read-only/set-by-create !!!
+                bridge_id_pointer=self._mac_bridge_service_profile_entity_id,  # Bridge Entity ID
+                port_num=self._uni_port_num,             # Port ID
+                tp_type=1,                               # PPTP Ethernet UNI
+                tp_pointer=self._ethernet_uni_entity_id  # TP ID, 8021p mapper Id
+            ).create()
+            results = yield omci_cc.send(frame)
+            self.check_status_and_state(results, 'create-mac-bridge-port-configuration-data-part-2')
+
+        except TimeoutError as e:
+            self.log.warn('rx-timeout-1', frame=frame)
+            raise
+
+        except Exception as e:
+            self.log.exception('omci-setup-1', e=e)
+            raise
+
+        returnValue(None)
+
+    @inlineCallbacks
+    def perform_service_specific_steps(self):
+        omci_cc = self._onu_device.omci_cc
+        frame = None
+
+        try:
+            ################################################################################
+            # TCONTS
+            #
+            #  EntityID will be referenced by:
+            #            - GemPortNetworkCtp
+            #  References:
+            #            - ONU created TCONT (created on ONU startup)
+
+            tcont_idents = self._onu_device.query_mib(Tcont.class_id)
+            self.log.debug('tcont-idents', tcont_idents=tcont_idents)
+
+            for tcont in self._handler.pon_port.tconts.itervalues():
+                free_entity_id = next((k for k, v in tcont_idents.items()
+                                       if isinstance(k, int) and
+                                       v.get('attributes', {}).get('alloc_id', 0) == 0xFFFF), None)
+                if free_entity_id is None:
+                    self.log.error('no-available-tconts')
+                    break
+                # TODO: Need to restore on failure.  Need to check status/results
+                yield tcont.add_to_hardware(omci_cc, free_entity_id)
+
+            ################################################################################
+            # GEMS  (GemPortNetworkCtp and GemInterworkingTp)
+            #
+            #  For both of these MEs, the entity_id is the GEM Port ID. The entity id of the
+            #  GemInterworkingTp ME could be different since it has an attribute to specify
+            #  the GemPortNetworkCtp entity id.
+            #
+            #  TODO: In the GEM Port routine to add, it has a hardcoded upstream TM ID of 0x8000
+            #        for the GemPortNetworkCtp ME
+            #
+            #  GemPortNetworkCtp
+            #    EntityID will be referenced by:
+            #              - GemInterworkingTp
+            #    References:
+            #              - TCONT
+            #              - Hardcoded upstream TM Entity ID
+            #              - (Possibly in Future) Upstream Traffic descriptor profile pointer
+            #
+            #  GemInterworkingTp
+            #    EntityID will be referenced by:
+            #              - Ieee8021pMapperServiceProfile
+            #    References:
+            #              - GemPortNetworkCtp
+            #              - Ieee8021pMapperServiceProfile
+            #              - GalEthernetProfile
+            #
+
+            for gem_port in self._handler.pon_port.gem_ports.itervalues():
+                tcont = gem_port.tcont
+                if tcont is None:
+                    self.log.error('unknown-tcont-reference', gem_id=gem_port.gem_id)
+                    continue
+                # TODO: Need to restore on failure.  Need to check status/results
+                yield gem_port.add_to_hardware(omci_cc,
+                                               tcont.entity_id,
+                                               self._ieee_mapper_service_profile_entity_id,
+                                               self._gal_enet_profile_entity_id)
+
+            ################################################################################
+            # Update the IEEE 802.1p Mapper Service Profile config
+            #
+            #  EntityID was created prior to this call. This is a set
+            #
+            #  References:
+            #            - Gem Interwork TPs are set here
+            #
+            # TODO: All p-bits currently go to the one and only GEMPORT ID for now
+            gem_ports = self._handler.pon_port.gem_ports
+            gem_entity_ids = [gem_port.entity_id for _, gem_port in gem_ports.items()] \
+                if len(gem_ports) else [OmciNullPointer]
+
+            frame = Ieee8021pMapperServiceProfileFrame(
+                self._ieee_mapper_service_profile_entity_id,  # 802.1p mapper Service Mapper Profile ID
+                interwork_tp_pointers=gem_entity_ids          # Interworking TP IDs
+            ).set()
+            results = yield omci_cc.send(frame)
+            self.check_status_and_state(results, 'set-8021p-mapper-service-profile')
+
+            ################################################################################
+            # Create Extended VLAN Tagging Operation config (PON-side)
+            #
+            #  EntityID relates to the VLAN TCIS
+            #  References:
+            #            - VLAN TCIS from previously created VLAN Tagging filter data
+            #            - PPTP Ethernet UNI
+            #
+            # TODO: add entry here for additional UNI interfaces
+
+            attributes = dict(
+                association_type=2,                                 # Assoc Type, PPTP Ethernet UNI
+                associated_me_pointer=self._ethernet_uni_entity_id  # Assoc ME, PPTP Entity Id
+            )
+
+            frame = ExtendedVlanTaggingOperationConfigurationDataFrame(
+                self._vlan_config_entity_id,
+                attributes=attributes
+            ).create()
+            results = yield omci_cc.send(frame)
+            self.check_status_and_state(results, 'create-extended-vlan-tagging-operation-configuration-data')
+
+            ################################################################################
+            # Update Extended VLAN Tagging Operation Config Data
+            #
+            # Specifies the TPIDs in use and that operations in the downstream direction are
+            # inverse to the operations in the upstream direction
+            # TODO: Downstream mode may need to be modified once we work more on the flow rules
+
+            attributes = dict(
+                input_tpid=self._input_tpid,    # input TPID
+                output_tpid=self._output_tpid,  # output TPID
+                downstream_mode=0,              # inverse of upstream
+            )
+            frame = ExtendedVlanTaggingOperationConfigurationDataFrame(
+                self._vlan_config_entity_id,
+                attributes=attributes
+            ).set()
+            results = yield omci_cc.send(frame)
+            self.check_status_and_state(results, 'set-extended-vlan-tagging-operation-configuration-data')
+
+            ################################################################################
+            # Update Extended VLAN Tagging Operation Config Data
+            #
+            # parameters: Entity Id ( 0x900), Filter Inner Vlan Id(0x1000-4096,do not filter on Inner vid,
+            #             Treatment Inner Vlan Id : 2
+
+            attributes = dict(
+                received_frame_vlan_tagging_operation_table=
+                VlanTaggingOperation(
+                    filter_outer_priority=15,  # This entry is not a double-tag rule
+                    filter_outer_vid=4096,     # Do not filter on the outer VID value
+                    filter_outer_tpid_de=0,    # Do not filter on the outer TPID field
+
+                    filter_inner_priority=15,  # This is a no-tag rule, ignore all other VLAN tag filter fields
+                    filter_inner_vid=0x1000,   # Do not filter on the inner VID
+                    filter_inner_tpid_de=0,    # Do not filter on inner TPID field
+
+                    filter_ether_type=0,         # Do not filter on EtherType
+                    treatment_tags_to_remove=0,  # Remove 0 tags
+
+                    treatment_outer_priority=15,  # Do not add an outer tag
+                    treatment_outer_vid=0,        # n/a
+                    treatment_outer_tpid_de=0,    # n/a
+
+                    treatment_inner_priority=0,      # Add an inner tag and insert this value as the priority
+                    treatment_inner_vid=self._cvid,  # use this value as the VID in the inner VLAN tag
+                    treatment_inner_tpid_de=4,       # set TPID
+                )
+            )
+            frame = ExtendedVlanTaggingOperationConfigurationDataFrame(
+                self._vlan_config_entity_id,  # Entity ID
+                attributes=attributes         # See above
+            ).set()
+            results = yield omci_cc.send(frame)
+            self.check_status_and_state(results, 'set-extended-vlan-tagging-operation-configuration-data-untagged')
+
+            ################################################################################
+            ################################################################################
+            ################################################################################
+            # BP: This is for AT&T RG's                #
+            #   TODO: CB: NOTE: TRY THIS ONCE OTHER SEQUENCES WORK
+            #
+            # Set AR - ExtendedVlanTaggingOperationConfigData
+            #          514 - RxVlanTaggingOperationTable - add VLAN <cvid> to priority tagged pkts - c-vid
+            # results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_single_tag(
+            #                                 0x900,  # Entity ID
+            #                                 8,      # Filter Inner Priority, do not filter on Inner Priority
+            #                                 0,    # Filter Inner VID, this will be 0 in CORD
+            #                                 0,      # Filter Inner TPID DE
+            #                                 1,      # Treatment tags, number of tags to remove
+            #                                 8,      # Treatment inner priority, copy Inner Priority
+            #                                 2)   # Treatment inner VID, this will be 2 in CORD
+            # Set AR - ExtendedVlanTaggingOperationConfigData
+            #          514 - RxVlanTaggingOperationTable - add VLAN <cvid> to priority tagged pkts - c-vid
+            # results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_single_tag(
+            #                                 0x200,  # Entity ID
+            #                                 8,      # Filter Inner Priority
+            #                                 0,      # Filter Inner VID
+            #                                 0,      # Filter Inner TPID DE
+            #                                 1,      # Treatment tags to remove
+            #                                 8,      # Treatment inner priority
+            #                                 cvid)   # Treatment inner VID
+            # Set AR - ExtendedVlanTaggingOperationConfigData
+            #          514 - RxVlanTaggingOperationTable - add VLAN <cvid> to untagged pkts - c-vid
+            # results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_untagged(
+            #                                0x100,   # Entity ID            BP: Oldvalue 0x202
+            #                                0x1000,  # Filter Inner VID     BP: Oldvalue 0x1000
+            #                                cvid)    # Treatment inner VID  BP: cvid
+            # success = results.fields['omci_message'].fields['success_code'] == 0
+            # error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
+
+            ###############################################################################
+
+        except TimeoutError as e:
+            self.log.warn('rx-timeout-2', frame=frame)
+            raise
+
+        except Exception as e:
+            self.log.exception('omci-setup-2', e=e)
+            raise
+
+        returnValue(None)
+
+    @inlineCallbacks
+    def enable_unis(self, unis, force_lock):
+        """
+        Lock or unlock one or more UNI ports
+
+        :param unis: (list) of UNI objects
+        :param force_lock: (boolean) If True, force lock regardless of enabled state
+        """
+        omci_cc = self._onu_device.omci_cc
+        frame = None
+
+        for uni in unis:
+            ################################################################################
+            #  Lock/Unlock UNI  -  0 to Unlock, 1 to lock
+            #
+            #  EntityID is referenced by:
+            #            - MAC bridge port configuration data for the UNI side
+            #  References:
+            #            - Nothing
+            try:
+                state = 1 if force_lock or not uni.enabled else 0
+                frame = PptpEthernetUniFrame(uni.entity_id,
+                                             attributes=dict(administrative_state=state)).set()
+                results = yield omci_cc.send(frame)
+                self.check_status_and_state(results, 'set-pptp-ethernet-uni-lock-restore')
+
+            except TimeoutError:
+                self.log.warn('rx-timeout', frame=frame)
+                raise
+
+            except Exception as e:
+                self.log.exception('omci-failure', e=e)
+                raise
+
+        returnValue(None)
diff --git a/voltha/adapters/adtran_onu/omci/omci.py b/voltha/adapters/adtran_onu/omci/omci.py
index ea7abaf..aa1e9c4 100644
--- a/voltha/adapters/adtran_onu/omci/omci.py
+++ b/voltha/adapters/adtran_onu/omci/omci.py
@@ -182,7 +182,14 @@
             uni_ports = len(uni_g) if uni_g is not None else 0
 
             assert pon_ports == 1, 'Expected one PON/ANI port, got {}'.format(pon_ports)
-            assert uni_ports == 1, 'Expected one UNI port, got {}'.format(uni_ports)
+            assert uni_ports == len(self._handler.uni_ports), \
+                'Expected {} UNI port(s), got {}'.format(len(self._handler.uni_ports), uni_ports)
+
+            # Save entity_id for UNI ports
+            uni_entity_ids = uni_g.keys()
+            uni_entity_ids.sort()
+            for uni in self._handler.uni_ports:
+                uni.entity_id = uni_entity_ids.pop(0)
 
             self._total_tcont_count = ani_g.get('total-tcont-count')
             self._qos_flexibility = config.qos_configuration_flexibility or 0
@@ -219,7 +226,6 @@
 
             # Start MIB download  TODO: This will be replaced with a MIB Download task soon
             self._in_sync_reached = True
-            self._deferred = reactor.callLater(0, self.resync_omci_settings)
 
         except Exception as e:
             self.log.exception('device-info-load', e=e)
@@ -228,446 +234,7 @@
     def gem_or_tcont_added(self):
         if self._in_sync_reached:
             self._cancel_resync_deferred()
-            self._resync_deferred = reactor.callLater(_STARTUP_RETRY_WAIT,
-                                                      self.resync_omci_settings)
-
-    @inlineCallbacks
-    def resync_omci_settings(self):
-        #
-        # TODO: All of these steps below are being moved into an OpenOMCI Task.  !!!!
-        #
-        #  This will first be the AdtnMibDownloadTask task. As more ONUs are converted
-        #  to OpenOMCI, I am hoping to come up with a shared/generic version all can use
-        #
-        #  Note also that this sets up everything for the user right now. It will be refactored
-        #  once Service Tech Profiles are available.
-        #
-        self._cancel_resync_deferred()
-        self.log.debug('resync-omci-settings', initialized=self._bridge_initialized)
-
-        if not self.enabled:
-            returnValue('not-enabled')
-
-        device = self._handler.adapter_agent.get_device(self._handler.device_id)
-
-        def resources_available():
-            return (device.vlan > 0 and
-                    len(self._handler.uni_ports) > 0 and
-                    len(self._handler.pon_port.tconts) and
-                    len(self._handler.pon_port.gem_ports))
-
-        if not self._bridge_initialized and self._in_sync_reached and resources_available():
-            device.reason = 'Performing OMCI Download'
-            self._handler.adapter_agent.update_device(device)
-
-            omci = self.omci_cc
-
-            #############################################
-            #  All our variables here
-            #  TODO: Move elsewhere in future version of this software
-            #  TODO: Make as many entity IDs dynamic/discovered as possible
-
-            frame = None
-            gal_enet_profile_entity_id = 0x100
-            ieee_mapper_service_profile_entity_id = 0x100
-            mac_bridge_service_profile_entity_id = 0x100
-            mac_bridge_port_ani_entity_id = 0x100
-            ethernet_uni_entity_id = 0x101          # TODO: This can be retrieved from the UNI-G instance_id
-            vlan_tcis_1 = 0x900
-            vlan_config_entity_id = vlan_tcis_1
-            cvid = device.vlan
-
-            try:
-                ################################################################################
-                # TCONTS
-                #
-                #  EntityID will be referenced by:
-                #            - GemPortNetworkCtp
-                #  References:
-                #            - ONU created TCONT (created on ONU startup)
-
-                omci_dev = self._onu_omci_device
-                tcont_idents = omci_dev.query_mib(Tcont.class_id)
-                self.log.debug('tcont-idents', tcont_idents=tcont_idents)
-
-                for tcont in self._handler.pon_port.tconts.itervalues():
-                    free_entity_id = next((k for k, v in tcont_idents.items()
-                                          if isinstance(k, int) and
-                                           v.get('attributes', {}).get('alloc_id', 0) == 0xFFFF), None)
-                    if free_entity_id is None:
-                        self.log.error('no-available-tconts')
-                        break
-
-                    yield tcont.add_to_hardware(omci, free_entity_id)
-
-                ################################################################################
-                # GEMS  (GemPortNetworkCtp and GemInterworkingTp)
-                #
-                #  For both of these MEs, the entity_id is the GEM Port ID. The entity id of the
-                #  GemInterworkingTp ME could be different since it has an attribute to specify
-                #  the GemPortNetworkCtp entity id.
-                #
-                #  TODO: In the GEM Port routine to add, it has a hardcoded upstream TM ID of 0x8000
-                #        for the GemPortNetworkCtp ME
-                #
-                #  GemPortNetworkCtp
-                #    EntityID will be referenced by:
-                #              - GemInterworkingTp
-                #    References:
-                #              - TCONT
-                #              - Hardcoded upstream TM Entity ID
-                #              - (Possibly in Future) Upstream Traffic descriptor profile pointer
-                #
-                #  GemInterworkingTp
-                #    EntityID will be referenced by:
-                #              - Ieee8021pMapperServiceProfile
-                #    References:
-                #              - GemPortNetworkCtp
-                #              - Ieee8021pMapperServiceProfile
-                #              - GalEthernetProfile
-                #
-                for gem_port in self._handler.pon_port.gem_ports.itervalues():
-                    tcont = gem_port.tcont
-                    if tcont is None:
-                        self.log.error('unknown-tcont-reference', gem_id=gem_port.gem_id)
-                        continue
-
-                    yield gem_port.add_to_hardware(omci,
-                                                   tcont.entity_id,
-                                                   ieee_mapper_service_profile_entity_id,
-                                                   gal_enet_profile_entity_id)
-
-                ########################################################################################
-                # Create GalEthernetProfile - Once per ONU/PON interface
-                #
-                #  EntityID will be referenced by:
-                #            - GemInterworkingTp
-                #  References:
-                #            - Nothing
-
-                frame = GalEthernetProfileFrame(gal_enet_profile_entity_id,
-                                                max_gem_payload_size=1518).create()  # Max GEM Payload size
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-                self.log.debug('create-gal-ethernet-profile', status=status, error_mask=error_mask)
-
-                ################################################################################
-                # MAC Bridge Service Profile - Once per UNI
-                #
-                #  EntityID will be referenced by:
-                #            - MAC Bridge Port Configuration Data
-                #  References:
-                #            - Nothing
-
-                attributes = {
-                    'spanning_tree_ind': False,
-                    #  TODO: CB: see if we need or can use any of the following...
-                    # 'learning_ind': True,
-                    # 'priority': 0x8000,
-                    # 'max_age': 20 * 256,
-                    # 'hello_time': 2 * 256,
-                    # 'forward_delay': 15 * 256,
-                    # 'unknown_mac_address_discard': True
-                }
-                frame = MacBridgeServiceProfileFrame(mac_bridge_service_profile_entity_id,
-                                                     attributes).create()
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-                self.log.debug('create-mac-bridge-service-profile', status=status, error_mask=error_mask)
-
-                ################################################################################
-                # IEEE 802.1 Mapper Service config - Once per PON
-                #
-                #  EntityID will be referenced by:
-                #            - MAC Bridge Port Configuration Data for the PON port
-                #  References:
-                #            - Nothing at this point. When a GEM port is created, this entity will
-                #              be updated to reference the GEM Interworking TP
-
-                frame = Ieee8021pMapperServiceProfileFrame(ieee_mapper_service_profile_entity_id).create()
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-                self.log.debug('create-8021p-mapper-service-profile', status=status, error_mask=error_mask)
-
-                ################################################################################
-                # Create MAC Bridge Port Configuration Data for the PON port via IEEE 802.1
-                # mapper service. Upon receipt by the ONU, the ONU will create an instance
-                # of the following before returning the response.
-                #
-                #     - MAC bridge port designation data
-                #     - MAC bridge port filter table data
-                #     - MAC bridge port bridge table data
-                #
-                #  EntityID will be referenced by:
-                #            - Implicitly by the VLAN tagging filter data
-                #  References:
-                #            - MAC Bridge Service Profile (the bridge)
-                #            - IEEE 802.1p mapper service profile for PON port
-
-                frame = MacBridgePortConfigurationDataFrame(
-                    mac_bridge_port_ani_entity_id,                           # Entity ID
-                    bridge_id_pointer=mac_bridge_service_profile_entity_id,  # Bridge Entity ID
-                    # TODO: The PORT number for this port and the UNI port are the same. Is this correct?
-                    port_num=0,                                              # Port ID
-                    tp_type=3,                                               # TP Type (IEEE 802.1p mapper service)
-                    tp_pointer=ieee_mapper_service_profile_entity_id         # TP ID, 8021p mapper ID
-                ).create()
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-                self.log.debug('create-mac-bridge-port-configuration-data-part-1', status=status, error_mask=error_mask)
-
-                ################################################################################
-                # MAC Bridge Port config
-                # This configuration is for Ethernet UNI
-                #
-                #  EntityID will be referenced by:
-                #            - Nothing
-                #  References:
-                #            - MAC Bridge Service Profile (the bridge)
-                #            - PPTP Ethernet UNI
-
-                frame = MacBridgePortConfigurationDataFrame(
-                    0x000,                             # Entity ID - This is read-only/set-by-create !!!
-                    bridge_id_pointer=mac_bridge_service_profile_entity_id,  # Bridge Entity ID
-                    port_num=0,                        # Port ID
-                    tp_type=1,                         # PPTP Ethernet UNI
-                    tp_pointer=ethernet_uni_entity_id  # TP ID, 8021p mapper Id
-                ).create()
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-                self.log.debug('create-mac-bridge-port-configuration-data-part-2', status=status, error_mask=error_mask)
-
-                ################################################################################
-                # VLAN Tagging Filter config
-                #
-                #  EntityID will be referenced by:
-                #            - Nothing
-                #  References:
-                #            - MacBridgePortConfigurationData for the ANI/PON side
-                #
-                # Set anything, this request will not be used when using Extended Vlan
-
-                frame = VlanTaggingFilterDataFrame(
-                    mac_bridge_port_ani_entity_id,       # Entity ID
-                    vlan_tcis=[vlan_tcis_1],             # VLAN IDs
-                    forward_operation=0x10
-                ).create()
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-                self.log.debug('create-vlan-tagging-filter-data', status=status, error_mask=error_mask)
-
-                ################################################################################
-                # Update the IEEE 802.1p Mapper Service Profile config
-                #
-                #  EntityID was created prior to this call. This is a set
-                #
-                #  References:
-                #            - Gem Interwork TPs are set here
-                #
-                # TODO: All p-bits currently go to the one and only GEMPORT ID for now
-                gem_ports = self._handler.pon_port.gem_ports
-                gem_entity_ids = [gem_port.entity_id for _, gem_port in gem_ports.items()] \
-                    if len(gem_ports) else [OmciNullPointer]
-
-                frame = Ieee8021pMapperServiceProfileFrame(
-                    ieee_mapper_service_profile_entity_id,   # 802.1p mapper Service Mapper Profile ID
-                    interwork_tp_pointers=gem_entity_ids     # Interworking TP IDs
-                ).set()
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                failed_attributes_mask = results.fields['omci_message'].fields['failed_attributes_mask']
-                unsupported_attributes_mask = results.fields['omci_message'].fields['unsupported_attributes_mask']
-                self.log.debug('set-8021p-mapper-service-profile', status=status,
-                               failed_attributes_mask=failed_attributes_mask,
-                               unsupported_attributes_mask=unsupported_attributes_mask)
-
-                ################################################################################
-                #  Unlock UNI
-                #
-                #  EntityID will be referenced by:
-                #            - MAC bridge port configuration data for the UNI side
-                #  References:
-                #            - Nothing
-
-                attributes = dict(
-                    administrative_state=0  # 0 - Unlock
-                )
-                frame = PptpEthernetUniFrame(
-                    ethernet_uni_entity_id,  # Entity ID
-                    attributes=attributes    # See above
-                ).set()
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                failed_attributes_mask = results.fields['omci_message'].fields['failed_attributes_mask']
-                unsupported_attributes_mask = results.fields['omci_message'].fields['unsupported_attributes_mask']
-                self.log.debug('set-pptp-ethernet-uni', status=status,
-                               failed_attributes_mask=failed_attributes_mask,
-                               unsupported_attributes_mask=unsupported_attributes_mask)
-
-                ################################################################################
-                # Create Extended VLAN Tagging Operation config
-                #
-                #  EntityID relates to the VLAN TCIS
-                #  References:
-                #            - VLAN TCIS from previously created VLAN Tagging filter data
-                #            - PPTP Ethernet UNI
-                #
-                # TODO: add entry here for additional UNI interfaces
-
-                attributes = dict(
-                    association_type=2,                           # Assoc Type, PPTP Ethernet UNI
-                    associated_me_pointer=ethernet_uni_entity_id  # Assoc ME, PPTP Entity Id
-                )
-
-                frame = ExtendedVlanTaggingOperationConfigurationDataFrame(
-                    vlan_config_entity_id,
-                    attributes=attributes
-                ).create()
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-                self.log.debug('create-extended-vlan-tagging-operation-configuration-data', status=status, error_mask=error_mask)
-
-                ################################################################################
-                # Update Extended VLAN Tagging Operation Config Data
-                #
-                # Specifies the TPIDs in use and that operations in the downstream direction are
-                # inverse to the operations in the upstream direction
-                # TODO: Downstream mode may need to be modified once we work more on the flow rules
-
-                attributes = dict(
-                    input_tpid=0x8100,   # input TPID
-                    output_tpid=0x8100,  # output TPID
-                    downstream_mode=0,   # inverse of upstream
-                )
-                frame = ExtendedVlanTaggingOperationConfigurationDataFrame(
-                    vlan_config_entity_id,
-                    attributes=attributes
-                ).set()
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                failed_attributes_mask = results.fields['omci_message'].fields['failed_attributes_mask']
-                unsupported_attributes_mask = results.fields['omci_message'].fields['unsupported_attributes_mask']
-                self.log.debug('set-extended-vlan-tagging-operation-configuration-data', status=status,
-                               failed_attributes_mask=failed_attributes_mask,
-                               unsupported_attributes_mask=unsupported_attributes_mask)
-
-                ################################################################################
-                # Update Extended VLAN Tagging Operation Config Data
-                #
-                # parameters: Entity Id ( 0x900), Filter Inner Vlan Id(0x1000-4096,do not filter on Inner vid,
-                #             Treatment Inner Vlan Id : 2
-
-                attributes = dict(
-                    received_frame_vlan_tagging_operation_table=
-                    VlanTaggingOperation(
-                        filter_outer_priority=15,       # This entry is not a double-tag rule
-                        filter_outer_vid=4096,          # Do not filter on the outer VID value
-                        filter_outer_tpid_de=0,         # Do not filter on the outer TPID field
-
-                        filter_inner_priority=15,       # This is a no-tag rule, ignore all other VLAN tag filter fields
-                        filter_inner_vid=0x1000,        # Do not filter on the inner VID
-                        filter_inner_tpid_de=0,         # Do not filter on inner TPID field
-                        filter_ether_type=0,            # Do not filter on EtherType
-
-                        treatment_tags_to_remove=0,     # Remove 0 tags
-                        treatment_outer_priority=15,    # Do not add an outer tag
-                        treatment_outer_vid=0,          # n/a
-                        treatment_outer_tpid_de=0,      # n/a
-
-                        treatment_inner_priority=0,     # Add an inner tag and insert this value as the priority
-                        treatment_inner_vid=cvid,       # use this value as the VID in the inner VLAN tag
-                        treatment_inner_tpid_de=4       # set TPID = 0x8100
-                    )
-                )
-                frame = ExtendedVlanTaggingOperationConfigurationDataFrame(
-                    vlan_config_entity_id,    # Entity ID       BP: Oldvalue 0x202
-                    attributes=attributes     # See above
-                ).set()
-                results = yield omci.send(frame)
-
-                status = results.fields['omci_message'].fields['success_code']
-                failed_attributes_mask = results.fields['omci_message'].fields['failed_attributes_mask']
-                unsupported_attributes_mask = results.fields['omci_message'].fields['unsupported_attributes_mask']
-                self.log.debug('set-extended-vlan-tagging-operation-configuration-data-untagged', status=status,
-                               failed_attributes_mask=failed_attributes_mask,
-                               unsupported_attributes_mask=unsupported_attributes_mask)
-
-                # BP: This is for AT&T RG's
-                #
-                #   TODO: CB: NOTE: TRY THIS ONCE OTHER SEQUENCES WORK
-                #
-                # Set AR - ExtendedVlanTaggingOperationConfigData
-                #          514 - RxVlanTaggingOperationTable - add VLAN <cvid> to priority tagged pkts - c-vid
-                # results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_single_tag(
-                #                                 0x900,  # Entity ID
-                #                                 8,      # Filter Inner Priority, do not filter on Inner Priority
-                #                                 0,    # Filter Inner VID, this will be 0 in CORD
-                #                                 0,      # Filter Inner TPID DE
-                #                                 1,      # Treatment tags, number of tags to remove
-                #                                 8,      # Treatment inner priority, copy Inner Priority
-                #                                 2)   # Treatment inner VID, this will be 2 in CORD
-
-                # Set AR - ExtendedVlanTaggingOperationConfigData
-                #          514 - RxVlanTaggingOperationTable - add VLAN <cvid> to priority tagged pkts - c-vid
-                # results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_single_tag(
-                #                                 0x200,  # Entity ID
-                #                                 8,      # Filter Inner Priority
-                #                                 0,      # Filter Inner VID
-                #                                 0,      # Filter Inner TPID DE
-                #                                 1,      # Treatment tags to remove
-                #                                 8,      # Treatment inner priority
-                #                                 cvid)   # Treatment inner VID
-                #
-                # Set AR - ExtendedVlanTaggingOperationConfigData
-                #          514 - RxVlanTaggingOperationTable - add VLAN <cvid> to untagged pkts - c-vid
-                #results = yield omci.send_set_extended_vlan_tagging_operation_vlan_configuration_data_untagged(
-                #                                0x100,   # Entity ID            BP: Oldvalue 0x202
-                #                                0x1000,  # Filter Inner VID     BP: Oldvalue 0x1000
-                #                                cvid)    # Treatment inner VID  BP: cvid
-
-                # success = results.fields['omci_message'].fields['success_code'] == 0
-                # error_mask = results.fields['omci_message'].fields['parameter_error_attributes_mask']
-
-                ###############################################################################
-                # If here, we are done
-                self._bridge_initialized = True
-                device.reason = ''
-                self._handler.adapter_agent.update_device(device)
-
-            except TimeoutError as e:
-                self.log.warn('rx-timeout', frame=frame)
-                self._deferred = reactor.callLater(_STARTUP_RETRY_WAIT,
-                                                   self.resync_omci_settings)
-                returnValue('retry-pending')
-
-            except Exception as e:
-                self.log.exception('omci-setup', e=e)
-                device.reason = 'OMCI setup sequence failure: ' + e.message
-                self._handler.adapter_agent.update_device(device)
-
-                # Try again later
-                self._deferred = reactor.callLater(_STARTUP_RETRY_WAIT,
-                                                   self.resync_omci_settings)
-        else:
-            self._deferred = reactor.callLater(_STARTUP_RETRY_WAIT,
-                                               self.resync_omci_settings)
+            # TODO: Need to configure service here
 
     def _subscribe_to_events(self):
         from voltha.extensions.omci.onu_device_entry import OnuDeviceEvents, \
@@ -751,7 +318,7 @@
                 # TODO: Handle failure, retry for now?
                 self._mib_download_deferred = reactor.callLater(_STARTUP_RETRY_WAIT,
                                                                 self.capabilties_handler)
-            self._mib_download_task = AdtnMibDownloadTask(self.omci_agent, self._handler.device_id)
+            self._mib_download_task = AdtnMibDownloadTask(self.omci_agent, self._handler)
             self._mib_download_deferred = self._onu_omci_device.task_runner.queue_task(self._mib_download_task)
             self._mib_download_deferred.addCallbacks(success, failure)
 
diff --git a/voltha/adapters/adtran_onu/uni_port.py b/voltha/adapters/adtran_onu/uni_port.py
index 9de2243..8663b38 100644
--- a/voltha/adapters/adtran_onu/uni_port.py
+++ b/voltha/adapters/adtran_onu/uni_port.py
@@ -39,6 +39,7 @@
         self._logical_port_number = None        # Set at time of logical port creation
         self._subscriber_vlan = subscriber_vlan
         self._untagged_vlan = untagged_vlan
+        self._entity_id = None                  # TODO: Use port number from UNI-G entity ID
 
         self._admin_state = AdminState.ENABLED
         self._oper_status = OperStatus.ACTIVE
@@ -109,6 +110,18 @@
         return self._port_number
 
     @property
+    def entity_id(self):
+        """
+        OMCI UNI_G entity ID for port
+        """
+        return self._entity_id
+
+    @entity_id.setter
+    def entity_id(self, value):
+        assert self._entity_id is None, 'Cannot reset the Entity ID'
+        self._entity_id = value
+
+    @property
     def subscriber_vlan(self):
         """
         Subscriber vlan assigned to this UNI