Update to latest tef code

Change-Id: If881f4abde96d8c3aecd3b3129bdadee88587e29
diff --git a/voltha/adapters/microsemi_olt/APIProxy.py b/voltha/adapters/microsemi_olt/APIProxy.py
index 1c92f0e..7defc9c 100644
--- a/voltha/adapters/microsemi_olt/APIProxy.py
+++ b/voltha/adapters/microsemi_olt/APIProxy.py
@@ -101,12 +101,12 @@
     """
 
     def px(self, pkt):
-        
+
         if not self.proxy_address.channel_id:
             self.proxy_address.channel_id = 0
 
-        return self.p(pkt, channel_id=self.proxy_address.channel_id, 
-            onu_id=self.proxy_address.onu_id, 
+        return self.p(pkt, channel_id=self.proxy_address.channel_id,
+            onu_id=self.proxy_address.onu_id,
             onu_session_id=self.proxy_address.onu_session_id)
 
     """
@@ -134,7 +134,7 @@
             log.debug("adaptor-rcv", adaptor=self.adaptor_agent)
             self.adaptor_agent.receive_proxied_message(self.proxy_address, pkt['PAS5211MsgHeader'])
             raise self.end()
- 
+
     def __del__(self):
         log.debug("APIProxy deleted")
         super(APIProxy, self).__del__()
\ No newline at end of file
diff --git a/voltha/adapters/microsemi_olt/ActivationWatcher.py b/voltha/adapters/microsemi_olt/ActivationWatcher.py
index 47bc6e0..a0cd345 100644
--- a/voltha/adapters/microsemi_olt/ActivationWatcher.py
+++ b/voltha/adapters/microsemi_olt/ActivationWatcher.py
@@ -30,6 +30,7 @@
     PAS5211MsgSetPortIdConfigResponse, PAS5211MsgGetOnuIdByPortId, PAS5211MsgGetOnuIdByPortIdResponse, \
     PAS5211SetVlanUplinkConfiguration, PAS5211SetVlanUplinkConfigurationResponse, PAS5211MsgSetOnuAllocIdResponse, \
     PAS5211MsgHeader, PAS5211MsgGetOltVersionResponse, PAS5211EventOnuDeactivation, PAS5211EventAlarmNotification
+
     #PAS5211EventAlarmNotification, PAS5211EventOnuDeactivation
 from voltha.adapters.microsemi_olt.PAS5211_constants import PON_ACTIVATION_AUTH_AUTO, PON_ENABLE, PON_PORT_PON, \
     PON_LOGICAL_OBJECT_TYPE_ALLOC_ID, PON_LOGICAL_OBJECT_TYPE_ONU_ID_BY_ALLOC_ID, PON_TRUE, \
@@ -39,10 +40,16 @@
     PON_FALSE, PON_DISABLE, PON_ALARM_LOS, PASCOMM_RETRIES, \
     PON_ALARM_LOSI, PON_ALARM_DOWI, PON_ALARM_LOFI, PON_ALARM_RDII, PON_ALARM_LOAMI, PON_ALARM_LCDGI, \
     PON_ALARM_LOAI, PON_ALARM_SDI, PON_ALARM_SFI, PON_ALARM_PEE, PON_ALARM_DGI, PON_ALARM_LOKI, PON_ALARM_TIWI, \
-    PON_ALARM_TIA, PON_ALARM_AUTH_FAILED_IN_REGISTRATION_ID_MODE, PON_ALARM_SUFI
+    PON_ALARM_TIA, PON_ALARM_AUTH_FAILED_IN_REGISTRATION_ID_MODE, PON_ALARM_SUFI,\
+    PON_DOWNSTREAM_PLOAM_MESSAGE_ENCRYPTED_PORT_ID, PON_DOWNSTREAM_PLOAM_MESSAGE_ASSIGN_ALLOC_ID, \
+    PON_DOWNSTREAM_PLOAM_MESSAGE_CONFIGURE_PORT_ID, PON_DOWNSTREAM_PLOAM_MESSAGE_BER_INTERVAL, \
+    PON_DOWNSTREAM_PLOAM_MESSAGE_KEY_SWITCHING, PON_ALARM_SDI_RAISE, PON_ALARM_SDI_CLEAR, \
+    PON_ALARM_RAISE, PON_ALARM_CLEAR
+
 from voltha.extensions.omci.omci_entities import CircuitPack
 from voltha.extensions.omci.omci_frame import OmciFrame
-from voltha.extensions.omci.omci_messages import OmciGet, OmciGetResponse
+from voltha.extensions.omci.omci_messages import OmciGet, OmciGetResponse, OmciAlarmNotification
+
 
 from twisted.internet import reactor
 
@@ -52,8 +59,7 @@
 log = structlog.get_logger()
 _verbose = False
 
-ALLOC_ID = 1000
-
+MAX_RETRIES = 10
 
 def alloc_id(onu_id):
     for i in range(0, PMC_OFAL_MAX_BI_DIRECTIONAL_FLOW_PER_ONU):
@@ -76,6 +82,7 @@
     alloc_id = None
     vendor = None
     olt_adapter = None
+    retries = 0
 
     def parse_args(self, debug=0, store=0,**kwargs):
         self.onu_id = kwargs.pop('onu_id')
@@ -101,7 +108,7 @@
 
         if not super(ActivationManager, self).master_filter(pkt):
             return False
-    
+
 
         if OmciFrame in pkt:
             if pkt[OmciFrame].message_type in (16, 17):
@@ -111,7 +118,7 @@
             if PAS5211MsgHeader in pkt:
                 if pkt[PAS5211MsgHeader].channel_id == self.channel_id:
                     return True
-        
+
         return False
 
     def create_default_data_flow_olt_config(self):
@@ -173,7 +180,7 @@
         log.debug("activation-manager-end")
         self.activation_watcher.next_activation()
 
-    
+
     @ATMT.state(error=1)
     def error(self, msg):
         log.error(msg)
@@ -191,7 +198,7 @@
         try:
             log.info("Activated {} ONT, channel_id={}, onu_id={}, session_id={}, serial={} ".format(
                 self.vendor, self.channel_id, self.onu_id, self.onu_session_id, hexstring(self.serial_number)))
-            
+
             parent_port = self.channel_id * 32 + (self.onu_id + 1)
             self.olt_adapter.add_onu_info(parent_port, self.onu_id, self.onu_session_id)
 
@@ -205,8 +212,8 @@
             )
 
         except Exception as e:
-            log.exception('failed', e=e)
-            raise e
+            log.exception('detect-onu-failed', e=e)
+            # raise e
 
     """
     Transitions
@@ -223,8 +230,12 @@
     # Transitions from wait_get_auth_mode
     @ATMT.timeout(wait_get_auth_mode, 3)
     def timeout_get_auth_mode(self):
-        raise self.error('Could not get auth mode for OLT {}; dropping activation event for {}'
-            .format(self.target, hexstring(self.serial_number)))
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_get_activation_auth_mode()
+        else:
+            raise self.error('Could not get auth mode for OLT {}; dropping activation event for {}'
+                .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_get_auth_mode)
     def wait_for_get_auth_mode(self, pkt):
@@ -253,8 +264,12 @@
     # Transitions from wait_omci_port_id
     @ATMT.timeout(wait_omci_port_id, 3)
     def timeout_omci_port_id(self):
-        raise self.error('Could not set omci port id for OLT {}; dropping activation event for {}'
-            .format(self.target, hexstring(self.serial_number)))
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_omci_port_id()
+        else:
+            raise self.error('Could not set omci port id for OLT {}; dropping activation event for {}'
+                .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_omci_port_id)
     def wait_for_omci_port_id(self, pkt):
@@ -287,7 +302,11 @@
     # Transitions from wait_send_frame
     @ATMT.timeout(wait_send_frame, 3)
     def timeout_send_frame(self):
-        raise self.error('Could not send omci to OLT {}; dropping activation event for {}'
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_omci_identity_frame()
+        else:
+            raise self.error('Could not send omci to OLT {}; dropping activation event for {}'
                          .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_send_frame)
@@ -300,8 +319,12 @@
     # Transitions from wait_omci_get
     @ATMT.timeout(wait_omci_get, 3)
     def timeout_omci_get(self):
-        raise self.error('Did not receive omci get event from OLT {}; dropping activation event for {}'
-            .format(self.target, hexstring(self.serial_number)))
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_omci_identity_frame()
+        else:
+            raise self.error('Did not receive omci get event from OLT {}; dropping activation event for {}'
+                .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_omci_get)
     def wait_for_omci_get(self, pkt):
@@ -321,8 +344,15 @@
     # Transitions from wait_logical_object_status
     @ATMT.timeout(wait_logical_object_status, 3)
     def timeout_logical_object_status(self):
-        raise self.error('Did not receive info about alloc id status for {}; dropping activation event for {}'
-            .format(self.target, hexstring(self.serial_number)))
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            l_obj_status = PAS5211MsgGetLogicalObjectStatus(
+                type=PON_LOGICAL_OBJECT_TYPE_ALLOC_ID,
+                value=self.allocId)
+            self.send(self.p(l_obj_status, channel_id=self.channel_id))
+        else:
+            raise self.error('Did not receive info about alloc id status for {}; dropping activation event for {}'
+                .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_logical_object_status)
     def wait_for_logical_object_status(self, pkt):
@@ -369,7 +399,15 @@
     # Transitions from wait_set_alloc_id
     @ATMT.timeout(wait_set_alloc_id, 3)
     def timeout_set_alloc_id(self):
-        raise self.error('Was not able to set alloc id for {}; dropping activation event for {}'
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            set_alloc_id = PAS5211MsgSetOnuAllocId(
+                    alloc_id=self.allocId,
+                    allocate=PON_ENABLE
+                )
+            self.send(self.px(set_alloc_id))
+        else:
+            raise self.error('Was not able to set alloc id for {}; dropping activation event for {}'
                          .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_set_alloc_id)
@@ -384,7 +422,12 @@
     # PMC_OFAL.c 2062)
     @ATMT.timeout(wait_dba_mode, 3)
     def timeout_wait_dba_mode(self):
-        raise self.error('Did not get DBA mode for {}; dropping activation event for {}'
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send(self.p(PAS5211MsgGetDbaMode(),
+                             channel_id=self.channel_id))
+        else:
+            raise self.error('Did not get DBA mode for {}; dropping activation event for {}'
                          .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_dba_mode)
@@ -397,7 +440,7 @@
             self.detect_onu()
             raise self.end()
 
-   
+
 class ActivationWatcher(BaseOltAutomaton):
     """
         Master filter: Do not allow PAS5211MsgGetOltVersionResponse
@@ -420,6 +463,9 @@
         elif PAS5211EventAlarmNotification in pkt:
             return True
 
+        elif OmciAlarmNotification in pkt:
+            return True
+
         return False
 
 
@@ -454,14 +500,14 @@
         log.debug("deactivate-onu")
         msg_header = pkt[PAS5211MsgHeader]
         try:
-            log.debug("Deactivating ONT, channel_id={}, onu_id={}, session_id={},".format(
+            log.debug("Deactivating ONT, channel_id={}, onu_id={}, session_id={}".format(
                 msg_header.channel_id, msg_header.onu_id, msg_header.onu_session_id))
 
             self.device.deactivate_onu(channel_id=msg_header.channel_id,
                                        onu_id=msg_header.onu_id,
                                        onu_session_id=msg_header.onu_session_id)
 
-            log.debug("Deactivated ONT, channel_id={}, onu_id={}, session_id={} ".format(
+            log.debug("Deactivated ONT, channel_id={}, onu_id={}, session_id={}".format(
                 msg_header.channel_id, msg_header.onu_id, msg_header.onu_session_id))
         except Exception as e:
             log.exception('deactivate-onu failed', e=e)
@@ -472,7 +518,11 @@
 
     @ATMT.state(initial=1)
     def wait_onu_activation_event(self):
-        pass
+        log.debug('activation-watcher-start')
+
+    @ATMT.state(final=1)
+    def end(self):
+        log.debug('activation-watcher-end')
 
     """
     Transitions
@@ -494,17 +544,21 @@
             self.deactivate_onu(pkt)
 
         elif PAS5211EventAlarmNotification in pkt:
-            log.debug('PAS5211EventAlarmNotification Received')
             msg = pkt[PAS5211EventAlarmNotification]
-            log.debug('alarm:info - code: {} '.format(msg.code))
-            log.debug(' alarm:info - parameter1: {}'.format(msg.parameter1))
-            log.debug(' alarm:info - parameter2 {}'.format(msg.parameter2))
-            log.debug(' alarm:info - parameter3 {}'.format(msg.parameter3))
-            log.debug(' alarm:info - parameter4 {}'.format(msg.parameter4))
+            log.debug('PAS5211EventAlarmNotification Received', code=msg.code, parameter1= msg.parameter1, parameter2= msg.parameter2,
+                parameter3= msg.parameter3, parameter4= msg.parameter4)
             try:
                 self.process_alarm(pkt)
             except Exception as e:
-                log.exception('Error at process_alarm', e=e)
+                log.exception('wait-for-onu-activation-alarm-event-error', e=e)
+
+        elif OmciAlarmNotification in pkt:
+            log.debug('OmciAlarmNotification Received')
+            try:
+                self.process_omci_alarm(pkt)
+            except Exception as e:
+                log.exception('wait-for-onu-activation-omci-alarm-event-error', e=e)
+
         else:
             pass
 
@@ -513,66 +567,126 @@
 
     #Method to parse alarm and send it to DeviceManager
     def process_alarm(self, pkt):
-        log.debug('[Process_alarm] Starting')
+        log.debug('proccess-alarm-start')
         msg_header = pkt[PAS5211MsgHeader]
         msg = pkt[PAS5211EventAlarmNotification]
         code = msg.code
+
         ctx = {
             'alarm_code': str(code),
-        } 
+        }
 
-        ctx = {}
-
-        #Define common alarm parameters
         alarm = dict(
-            #id=None,
-            resource_id='voltha.olt-onuid('+str(msg_header.onu_id)+')',
-            id='voltha.olt',
-            raised_ts=None,
-            changed_ts=None,
+            id='voltha.{}.{}.olt'.format(self.device.adapter_agent.adapter_name, self.device.device.id),
+            resource_id=self.device.device.id,
             type=AlarmEventType.EQUIPMENT,
-            # category=AlarmEventCategory.OLT,
-            # severity=AlarmEventSeverity.INDETERMINATE,
-            # state=AlarmEventState.RAISED,
+            category=AlarmEventCategory.OLT,
+            severity=AlarmEventSeverity.MAJOR,
             context=ctx
         )
 
-        #Define especific alarm parameters
+        if msg_header.onu_id >= 0:
+            ctx['onu_id'] = str(msg_header.onu_id)
+        if msg_header.channel_id >= 0:
+            ctx['channel_id'] = str(msg_header.channel_id)
+        if msg_header.onu_session_id >= 0:
+            ctx['onu_session_id'] = str(msg_header.onu_session_id)
+
         if code == PON_ALARM_LOS:
             alarm['description'] = 'Loss of signal: OLT does not receive transmissions in the upstream'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_LOSI:
             alarm['description'] = 'Loss of signal for ONUi: no signal from the ONU when expected'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_DOWI:
             alarm['description'] = 'Loss of signal for ONUi: no signal from the ONU when expected'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_LOFI:
             alarm['description'] = 'Loss of frame of ONUi: no valid optical signal is received from the ONU'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_RDII:
             alarm['description'] = 'Remote Defect Indication of ONUi: OLT transmissions is received with defect at the ONUi'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_LOAMI:
             alarm['description'] = 'Loss of PLOAM for ONUi: 3 messages of ONU are missing after OLT sends PLOAMu request'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_LCDGI:
             alarm['description'] = 'Loss of GEM channel delineation: GEM fragment delineation of ONUi is lost'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_LOAI:
             alarm['description'] = 'Loss of acknowledge with ONUi: OLT does not receive ack from ONUi'
+            if msg.parameter1 in (PON_DOWNSTREAM_PLOAM_MESSAGE_ENCRYPTED_PORT_ID, PON_DOWNSTREAM_PLOAM_MESSAGE_ASSIGN_ALLOC_ID,
+                        PON_DOWNSTREAM_PLOAM_MESSAGE_CONFIGURE_PORT_ID, PON_DOWNSTREAM_PLOAM_MESSAGE_BER_INTERVAL,
+                        PON_DOWNSTREAM_PLOAM_MESSAGE_KEY_SWITCHING):
+                ctx['downstream_ploam_message_id'] = str(msg.parameter1)
+                alarm['state'] = PON_ALARM_RAISE
+            else:
+                log.error('Error, ignored OLT Alarm {} from OLT device {} because Invalid PLOAM message id in OLT device'.format(code, self.device))
+                return
         elif code == PON_ALARM_SDI:
             alarm['description'] = 'Signal Degraded of ONUi: raised when the upstream BER of ONUi goes below certain level'
+            if msg.parameter1 in (PON_ALARM_SDI_RAISE, PON_ALARM_SDI_CLEAR):
+                ctx['onu_id'] = str(msg_header.onu_id)
+                ctx['parameter'] = str(msg.parameter1)
+                alarm['state'] = PON_ALARM_RAISE
+            else:
+                log.error('Error, ignored OLT Alarm {} from OLT device {} because Invalid parameter of alarm SDI'.format(code, self.device))
+                return
         elif code == PON_ALARM_SFI:
             alarm['description'] = 'Signal Fail of ONUi: raised when the upstream of ONUi becomes greater than some level'
+            alarm['state'] = msg.parameter1
         elif code == PON_ALARM_PEE:
             alarm['description'] = 'Physical Equipment Error of ONUi: raised when the OLT receives a PEE message from the ONU'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_DGI:
             alarm['description'] = 'Dying Gasp of ONUi: raised when the OLT receives DG message from ONUi'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_LOKI:
             alarm['description'] = 'Loss of key synch with ONUi: Key transmission from ONU fails 3 times'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_TIWI:
             alarm['description'] = 'Transmission interference warning: raised when the drift of ONU transmissions exceeds specified threshold'
+            alarm['state'] = msg.parameter2
         elif code == PON_ALARM_TIA:
             alarm['description'] = 'Transmission Interference Alarm: an ONU turns on its laser at another ONUs time'
+            alarm['state'] = msg.parameter2
         else:
-            log.error('Error, unsupported OLT Alarm {} received from OLT device'.format(code, self.device))
-            alarm['description'] = ''
+            log.error('Error, unsupported OLT Alarm {} received from OLT device {}'.format(code, self.device))
+            return
 
-        log.debug('[Process_alarm] Send alarm to DeviceManager')
-        log.warn('Alarm: '+alarm['description']+' from '+alarm['id'])
+        log.warn('Alarm', alarm=alarm)
+        self.device.publish_alarm(alarm)
+        log.debug('proccess-alarm-stop')
+
+
+    def process_omci_alarm(self, pkt):
+
+        log.debug('proccess-omci-alarm-start')
+        msg_header = pkt[PAS5211MsgHeader]
+        msg_omci_alarm = pkt[OmciAlarmNotification]
+
+        ctx = {
+            'entity_class': str(msg_omci_alarm.entity_class),
+            'entity_id': str(msg_omci_alarm.entity_id),
+            'alarm_bit_map': str(msg_omci_alarm.alarm_bit_map),
+            'alarm_sequence_number': str(msg_omci_alarm.alarm_sequence_number)
+        }
+
+        if msg_header.onu_id >= 0:
+            ctx['onu_id'] = str(msg_header.onu_id)
+        if msg_header.channel_id >= 0:
+            ctx['channel_id'] = str(msg_header.channel_id)
+        if msg_header.onu_session_id >= 0:
+            ctx['onu_session_id'] = str(msg_header.onu_session_id)
+
+        alarm = dict(
+            id='voltha.{}.{}.ont'.format(self.device.adapter_agent.adapter_name, self.device.device.id),
+            resource_id=self.device.device.id,
+            type=AlarmEventType.EQUIPMENT,
+            category=AlarmEventCategory.OLT,
+            context=ctx
+        )
 
         self.device.publish_alarm(alarm)
+        log.warn('Alarm', alarm=alarm)
+        log.debug('proccess-alarm-stop')
diff --git a/voltha/adapters/microsemi_olt/DeviceManager.py b/voltha/adapters/microsemi_olt/DeviceManager.py
index c11119b..646da82 100644
--- a/voltha/adapters/microsemi_olt/DeviceManager.py
+++ b/voltha/adapters/microsemi_olt/DeviceManager.py
@@ -23,6 +23,9 @@
 from voltha.protos.openflow_13_pb2 import ofp_desc, ofp_switch_features, OFPC_FLOW_STATS, OFPC_TABLE_STATS, \
     OFPC_PORT_STATS, OFPC_GROUP_STATS, ofp_port, OFPPS_LIVE, OFPPF_10GB_FD, OFPPF_FIBER
 
+from twisted.internet import reactor
+
+
 log = structlog.get_logger()
 
 
@@ -85,6 +88,7 @@
         # that will correspond to the NNI port
         ld = LogicalDevice(
             desc=ofp_desc(
+                mfr_desc=self.device.vendor,
                 hw_desc=self.device.hardware_version,
                 sw_desc=self.device.firmware_version,
                 serial_num=uuid4().hex,
@@ -102,9 +106,22 @@
             ),
             root_device_id=self.device.id
         )
-
         self.logical_device = self.adapter_agent.create_logical_device(ld, dpid=self.device.mac_address)
 
+    def delete_logical_device(self):
+        try:
+            log.debug('delete-logical-device')
+            self.adapter_agent.delete_logical_device(self.logical_device)
+        except Exception as e:
+            log.exception('delete-logical-device-failed', e=e)
+
+    def remove_all_logical_ports(self):
+        try:
+            log.debug('remove-logical-ports')
+            self.adapter_agent.remove_all_logical_ports(self.logical_device)
+        except Exception as e:
+            log.exception('delete-logical-device-failed', e=e)
+
     def add_upstream_port(self, port):
         nni_port = Port(
             port_no=port,
@@ -116,7 +133,7 @@
         self.adapter_agent.add_port(self.device.id, nni_port)
 
     def add_logical_upstream_port(self, port):
-    
+
         cap = OFPPF_10GB_FD | OFPPF_FIBER
 
         self.adapter_agent.add_logical_port(self.logical_device.id, LogicalPort(
@@ -167,9 +184,22 @@
                      serial_number=None,
                      onu_session_id=None,
                      channel_id=None):
-        log.debug('onu-detected') 
+        log.debug('onu-detected')
         try:
-            self.adapter_agent.child_device_detected(
+            # self.adapter_agent.child_device_detected(
+            #     parent_device_id=self.device.id,
+            #     parent_port_no=parent_port_no,
+            #     child_device_type=child_device_type,
+            #     serial_number=serial_number,
+            #     proxy_address=Device.ProxyAddress(
+            #         device_id=self.device.id,
+            #         channel_id=channel_id,  # happens to be the channel id as well
+            #         onu_id=onu_id,
+            #         onu_session_id=onu_session_id
+            #     ),
+            #     admin_state=AdminState.ENABLED,
+            #     vlan=0)
+            reactor.callLater(0, self.adapter_agent.child_device_detected,
                 parent_device_id=self.device.id,
                 parent_port_no=parent_port_no,
                 child_device_type=child_device_type,
@@ -182,10 +212,34 @@
                 ),
                 admin_state=AdminState.ENABLED,
                 vlan=0)
+
         except Exception as e:
-            log.exception('onu-detected-failed', e=e) 
+            log.exception('onu-detected-failed', e=e)
             raise e
 
+    def update_child_devices_state(self, oper_status=None,
+                                   connect_status=None,
+                                   admin_state=None):
+        try:
+            # self.adapter_agent.update_child_devices_state(self.device.id,
+            #                                         oper_status=oper_status,
+            #                                         connect_status=connect_status,
+            #                                         admin_state=admin_state)
+            reactor.callLater(0, self.adapter_agent.update_child_devices_state,
+                                                    self.device.id,
+                                                    oper_status=oper_status,
+                                                    connect_status=connect_status,
+                                                    admin_state=admin_state)
+        except Exception:
+            log.debug("Child ONUs from {} could not be updated".format(self.device.id))
+
+    def delete_all_child_devices(self):
+        try:
+            # self.adapter_agent.delete_all_child_devices(self.device.id)
+            reactor.callLater(0, self.adapter_agent.delete_all_child_devices, self.device.id)
+        except Exception:
+            log.debug("Child ONUs from {} cannot be removed".format(self.device.id))
+
     def deactivate_onu(self, onu_id=None, channel_id=None, onu_session_id=None):
         try:
             child_device = self.adapter_agent.get_child_device_with_proxy_address(Device.ProxyAddress(
@@ -194,11 +248,15 @@
                 onu_id=onu_id,
                 onu_session_id=onu_session_id
             ))
+            # self.adapter_agent.delete_child_device(self.device.id, child_device)
             if child_device:
-                # self.adapter_agent.update_child_device_state(child_device, admin_state=AdminState.DISABLED)
-                child_device.admin_state=AdminState.DISABLED
-                self.adapter_agent.update_device(child_device)
-        except KeyError:
+                child_device.admin_state = AdminState.DISABLED
+                # self.adapter_agent._make_up_to_date('/devices', child_device.id, child_device)
+                reactor.callLater(0, self.adapter_agent._make_up_to_date,
+                    '/devices', child_device.id, child_device)
+                #child_device.admin_state=AdminState.DISABLED
+                #self.adapter_agent.update_device(child_device)
+        except Exception:
             log.debug("ONU {} cannot be deactivated".format(onu_id))
 
     def activate(self):
@@ -209,15 +267,16 @@
 
 
     def publish_alarm(self, alarm):
+        log.debug("publish-alarm-start")
         new_alarm = self.adapter_agent.create_alarm(
-            # id = alarm["id"],
-            resource_id = alarm["resource_id"],
-            description = alarm["description"],
-            type = alarm["type"],
-            # category = alarm["category"],
-            # severity = alarm["severity"],
-            # state = alarm["state"],
-            context = alarm["context"]
+            id = alarm.get("id"),
+            resource_id = alarm.get("resource_id"),
+            description = alarm.get("description"),
+            type = alarm.get("type"),
+            category = alarm.get("category"),
+            severity = alarm.get("severity"),
+            state = alarm.get("state"),
+            context = alarm.get("context")
         )
         self.adapter_agent.submit_alarm(self.device.id, new_alarm)
-        log.debug("[publish_alarm]")
\ No newline at end of file
+        log.debug("publish-alarm-stop")
\ No newline at end of file
diff --git a/voltha/adapters/microsemi_olt/OMCIProxy.py b/voltha/adapters/microsemi_olt/OMCIProxy.py
index 670b247..2f6fe4c 100644
--- a/voltha/adapters/microsemi_olt/OMCIProxy.py
+++ b/voltha/adapters/microsemi_olt/OMCIProxy.py
@@ -36,11 +36,15 @@
 
 log = structlog.get_logger()
 
+MAX_RETRIES = 10
+
 
 class OMCIProxy(BaseOltAutomaton):
 
     proxy_address = None
     msg = None
+    retries = 0
+    to_send = None
 
     def parse_args(self, debug=0, store=0, **kwargs):
         self.adaptor_agent = kwargs.pop('adapter_agent')
@@ -48,7 +52,7 @@
         self.msg = kwargs.pop('msg')
 
         BaseOltAutomaton.parse_args(self, debug=debug, store=store, **kwargs)
-    
+
     def restart(self, *args, **kargs):
         self.msg = kargs.pop('msg')
         super(OMCIProxy, self).restart()
@@ -60,7 +64,7 @@
 
         if not self.proxy_address.channel_id:
             self.proxy_address.channel_id = 0
-        
+
         if not self.proxy_address.onu_id:
             self.proxy_address.onu_id = 0
 
@@ -72,6 +76,8 @@
                         if OmciFrame in pkt:
                             if pkt[OmciFrame].message_type not in (16, 17):
                                 return True
+                            else:
+                                log.debug('OmciAlarmNotification Received')
                         # # SendFrameResponse corresponding to OMCI PAS request
                         elif PAS5211MsgSendFrameResponse in pkt:
                             return True
@@ -121,8 +127,8 @@
         log.debug('send-omci-msg', proxy_address=self.proxy_address)
         send_frame = PAS5211MsgSendFrame(port_type=PON_PORT_PON, port_id=self.proxy_address.onu_id,
                                          management_frame=PON_TRUE, frame=self.msg)
-        to_send = self.px(send_frame)
-        self.send(to_send)
+        self.to_send = self.px(send_frame)
+        self.send(self.to_send)
         raise self.wait_send_response()
 
     # Transitions from wait_send_response
@@ -130,8 +136,13 @@
     def timeout_wait_send_response(self):
         log.debug('omci-proxy-timeout')
         # Send back empty packet...
-        self.adaptor_agent.receive_proxied_message(self.proxy_address, dict())
-        raise self.error("No ack for OMCI for {}".format(self.proxy_address))
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send(self.to_send)
+            raise self.wait_send_response()
+        else:
+            self.adaptor_agent.receive_proxied_message(self.proxy_address, dict())
+            raise self.error("No ack for OMCI for {}".format(self.proxy_address))
 
     @ATMT.receive_condition(wait_send_response)
     def wait_for_send_response(self, pkt):
@@ -143,8 +154,13 @@
     def timeout_wait_event(self):
         log.debug('omci-proxy-timeout')
         # Send back empty packet...
-        self.adaptor_agent.receive_proxied_message(self.proxy_address, dict())
-        raise self.error("No OMCI event for {}".format(self.proxy_address))
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send(self.to_send)
+            raise self.wait_send_response()
+        else:
+            self.adaptor_agent.receive_proxied_message(self.proxy_address, dict())
+            raise self.error("No ack for OMCI for {}".format(self.proxy_address))
 
     @ATMT.receive_condition(wait_event)
     def wait_for_event(self, pkt):
diff --git a/voltha/adapters/microsemi_olt/OltInstallFlowStateMachine.py b/voltha/adapters/microsemi_olt/OltInstallFlowStateMachine.py
index c5a945b..8a529bc 100644
--- a/voltha/adapters/microsemi_olt/OltInstallFlowStateMachine.py
+++ b/voltha/adapters/microsemi_olt/OltInstallFlowStateMachine.py
@@ -40,7 +40,7 @@
     PAS5211SetVlanUplinkConfiguration, PAS5211SetVlanUplinkConfigurationResponse, PAS5211SetUplinkVlanHandlResponse, PAS5211SetVlanGenConfig, PAS5211SetVlanGenConfigResponse, \
     PAS5211GetPortIdDownstreamPolicingConfig, PAS5211GetPortIdDownstreamPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfig, \
     PAS5211MsgHeader, PAS5211UnsetPortIdPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfigResponse, \
-    PAS5211SetPortIdPolicingConfigResponse
+    PAS5211SetPortIdPolicingConfigResponse, PAS5211EventAlarmNotification
 from voltha.adapters.microsemi_olt.PAS5211_constants import OMCI_GEM_IWTP_IW_OPT_8021P_MAPPER, PON_FALSE, \
     PON_1_TO_1_VLAN_MODE, PON_TRUE, PON_VLAN_UNUSED_TAG, PON_VLAN_UNUSED_PRIORITY, PON_VLAN_REPLACE_PRIORITY, \
     PON_OUTPUT_VLAN_PRIO_HANDLE_INCOMING_VLAN, PON_VLAN_UNCHANGED_PRIORITY, PON_OUTPUT_VLAN_PRIO_HANDLE_DONT_CHANGE, \
@@ -53,9 +53,13 @@
     PMC_OFAL_NO_POLICY, UPSTREAM, DOWNSTREAM
 
 from struct import pack, unpack
-    
+
+from voltha.adapters.microsemi_olt.OltRemoveFlowStateMachine import OltRemoveFlowStateMachine
+
 log = structlog.get_logger()
 
+MAX_RETRIES = 10
+TIMEOUT = 5
 
 class OltInstallFlowStateMachine(BaseOltAutomaton):
 
@@ -65,9 +69,10 @@
     onu_session_id = None
     alloc_id = None
     policy_id = None
+    retries = 0
 
     def parse_args(self, debug=0, store=0, **kwargs):
-        
+
         self.onu_id = kwargs.pop('onu_id')
         self.channel_id = kwargs.pop('channel_id')
         self.port_id = kwargs.pop('port_id')
@@ -78,7 +83,6 @@
         self.uplink_bandwidth = kwargs.pop('uplink_bandwidth')
         self.downlink_bandwidth = kwargs.pop('downlink_bandwidth')
 
-
         BaseOltAutomaton.parse_args(self, debug=debug, store=store, **kwargs)
 
     def master_filter(self, pkt):
@@ -87,13 +91,13 @@
             return False
 
         if PAS5211MsgHeader in pkt:
-            if PAS5211MsgGetOltVersionResponse not in pkt:
-                if pkt[PAS5211MsgHeader].channel_id == self.channel_id:
-                    if pkt[PAS5211MsgHeader].onu_id == self.onu_id:
-                        if OmciFrame not in pkt:
-                            if PAS5211MsgSendFrameResponse not in pkt:
-                                return True
-
+            if PAS5211EventAlarmNotification not in pkt:
+                if PAS5211MsgGetOltVersionResponse not in pkt:
+                    if pkt[PAS5211MsgHeader].channel_id == self.channel_id:
+                        if pkt[PAS5211MsgHeader].onu_id == self.onu_id:
+                            if OmciFrame not in pkt:
+                                if PAS5211MsgSendFrameResponse not in pkt:
+                                    return True
         return False
 
     """
@@ -108,27 +112,27 @@
     @ATMT.state()
     def wait_set_gen_vlan_uplink_configuration_response(self):
         pass
-    
+
     @ATMT.state()
     def wait_set_port_id_configuration_response(self):
         pass
-    
+
     @ATMT.state()
     def wait_get_onu_id_by_port_id_response(self):
         pass
-    
+
     @ATMT.state()
     def wait_send_dba_algorithm_msg_response(self):
         pass
-    
+
     @ATMT.state()
     def wait_set_svlan_at_configuration_response(self):
         pass
-    
+
     @ATMT.state()
     def wait_set_vlan_uplink_configuration_response(self):
         pass
-    
+
     @ATMT.state()
     def wait_set_uplink_vlan_handling_response(self):
         pass
@@ -137,31 +141,31 @@
     @ATMT.state()
     def wait_set_gen_vlan_downlink_configuration_response(self):
         pass
-            
+
     @ATMT.state()
     def wait_set_vlan_downlink_configuration_response(self):
         pass
-            
+
     @ATMT.state()
     def wait_set_downlink_vlan_handling_response(self):
         pass
-            
+
     @ATMT.state()
     def wait_get_port_id_downlink_policing_response(self):
         pass
-            
+
     @ATMT.state()
     def wait_unset_port_id_downlink_policing_response(self):
         pass
-            
+
     @ATMT.state()
     def wait_remove_downlink_policing_response(self):
         pass
-            
+
     @ATMT.state()
     def wait_set_downlink_policing_response(self):
         pass
-            
+
     @ATMT.state()
     def wait_set_port_id_policing_response(self):
         pass
@@ -170,8 +174,14 @@
     @ATMT.state(error=1)
     def error(self, msg):
         log.error(msg)
-        raise self.end()
+        # # If any error, we remove the flow...
+        # olt = OltRemoveFlowStateMachine(iface=self.iface, comm=self.comm,
+        #         target=self.target, device=self.device, onu_id=self.onu_id,
+        #         channel_id=self.channel_id, port_id=self.port_id, onu_session_id=self.onu_session_id,
+        #         alloc_id=self.alloc_id)
+        # olt.runbg()
 
+        raise self.end()
 
     @ATMT.state(final=1)
     def end(self):
@@ -183,8 +193,8 @@
     """
 
     def px(self, pkt):
-        return self.p(pkt, channel_id=self.channel_id, 
-                onu_id=self.onu_id, 
+        return self.p(pkt, channel_id=self.channel_id,
+                onu_id=self.onu_id,
                 onu_session_id=self.onu_session_id)
 
     """
@@ -197,131 +207,167 @@
         self.send_set_gen_vlan_uplink_configuration(self.device.device)
         raise self.wait_set_gen_vlan_uplink_configuration_response()
 
-    @ATMT.timeout(wait_set_gen_vlan_uplink_configuration_response, 10)
+    @ATMT.timeout(wait_set_gen_vlan_uplink_configuration_response, TIMEOUT)
     def timeout_wait_gen_vlan_uplink_configuration_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211SetVlanGenConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_gen_vlan_uplink_configuration(self.device.device)
+        else:
+            raise self.error("Timeout for message PAS5211SetVlanGenConfigResponse")
 
     @ATMT.receive_condition(wait_set_gen_vlan_uplink_configuration_response)
     def wait_for_set_gen_vlan_uplink_configuration_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211SetVlanGenConfigResponse in pkt: 
+        if PAS5211SetVlanGenConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211SetVlanGenConfigResponse')
             self.send_set_port_id_configuration(self.device.device, PON_ENABLE, self.port_id, self.alloc_id)
             raise self.wait_set_port_id_configuration_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_set_port_id_configuration_response, 10)
+    @ATMT.timeout(wait_set_port_id_configuration_response, TIMEOUT)
     def timeout_wait_set_port_id_configuration_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211MsgSetPortIdConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_port_id_configuration(self.device.device, PON_ENABLE, self.port_id, self.alloc_id)
+        else:
+            raise self.error("Timeout for message PAS5211MsgSetPortIdConfigResponse")
 
     @ATMT.receive_condition(wait_set_port_id_configuration_response)
     def wait_for_set_port_id_configuration_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211MsgSetPortIdConfigResponse in pkt: 
+        if PAS5211MsgSetPortIdConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211MsgSetPortIdConfigResponse')
             self.send_get_onu_id_by_port_id(self.device.device, self.port_id)
             raise self.wait_get_onu_id_by_port_id_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_get_onu_id_by_port_id_response, 10)
+    @ATMT.timeout(wait_get_onu_id_by_port_id_response, TIMEOUT)
     def timeout_wait_get_onu_id_by_port_id_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211MsgGetOnuIdByPortIdResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_get_onu_id_by_port_id(self.device.device, self.port_id)
+        else:
+            raise self.error("Timeout for message PAS5211MsgGetOnuIdByPortIdResponse")
 
     @ATMT.receive_condition(wait_get_onu_id_by_port_id_response)
     def wait_for_get_onu_id_by_port_id_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211MsgGetOnuIdByPortIdResponse in pkt: 
+        if PAS5211MsgGetOnuIdByPortIdResponse in pkt:
             log.debug('[RESPONSE] PAS5211MsgGetOnuIdByPortIdResponse')
             self.send_send_dba_algorithm_msg(self.device.device, self.port_id, self.uplink_bandwidth)
             raise self.wait_send_dba_algorithm_msg_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
-    
-    @ATMT.timeout(wait_send_dba_algorithm_msg_response, 10)
+
+    @ATMT.timeout(wait_send_dba_algorithm_msg_response, TIMEOUT)
     def timeout_wait_send_dba_algorithm_msg_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211MsgSendDbaAlgorithmMsgResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_send_dba_algorithm_msg(self.device.device, self.port_id, self.uplink_bandwidth)
+        else:
+            raise self.error("Timeout for message PAS5211MsgSendDbaAlgorithmMsgResponse")
 
     @ATMT.receive_condition(wait_send_dba_algorithm_msg_response)
     def wait_for_send_dba_algorithm_msg_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211MsgSendDbaAlgorithmMsgResponse in pkt: 
+        if PAS5211MsgSendDbaAlgorithmMsgResponse in pkt:
             log.debug('[RESPONSE] PAS5211MsgSendDbaAlgorithmMsgResponse')
             self.send_set_svlan_at_configuration(self.device.device, self.svlan_id)
             raise self.wait_set_svlan_at_configuration_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_set_svlan_at_configuration_response, 10)
+    @ATMT.timeout(wait_set_svlan_at_configuration_response, TIMEOUT)
     def timeout_wait_set_svlan_at_configuration_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211SetSVlanAtConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_svlan_at_configuration(self.device.device, self.svlan_id)
+        else:
+            raise self.error("Timeout for message PAS5211SetSVlanAtConfigResponse")
 
     @ATMT.receive_condition(wait_set_svlan_at_configuration_response)
     def wait_for_set_svlan_at_configuration_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211SetSVlanAtConfigResponse in pkt: 
+        if PAS5211SetSVlanAtConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211SetSVlanAtConfigResponse')
             self.send_set_vlan_uplink_configuration(self.device.device, self.port_id)
             raise self.wait_set_vlan_uplink_configuration_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
-    
-    @ATMT.timeout(wait_set_vlan_uplink_configuration_response, 10)
+
+    @ATMT.timeout(wait_set_vlan_uplink_configuration_response, TIMEOUT)
     def timeout_wait_set_vlan_uplink_configuration_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211SetVlanUplinkConfigurationResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_vlan_uplink_configuration(self.device.device, self.port_id)
+        else:
+            raise self.error("Timeout for message PAS5211SetVlanUplinkConfigurationResponse")
 
     @ATMT.receive_condition(wait_set_vlan_uplink_configuration_response)
     def wait_for_set_vlan_uplink_configuration_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211SetVlanUplinkConfigurationResponse in pkt: 
+        if PAS5211SetVlanUplinkConfigurationResponse in pkt:
             log.debug('[RESPONSE] PAS5211SetVlanUplinkConfigurationResponse')
             self.send_set_uplink_vlan_handling(self.device.device, self.port_id, self.cvlan_id, self.svlan_id)
             raise self.wait_set_uplink_vlan_handling_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    
-    @ATMT.timeout(wait_set_uplink_vlan_handling_response, 10)
+
+    @ATMT.timeout(wait_set_uplink_vlan_handling_response, TIMEOUT)
     def timeout_wait_set_uplink_vlan_handling_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211SetUplinkVlanHandlResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_uplink_vlan_handling(self.device.device, self.port_id, self.cvlan_id, self.svlan_id)
+        else:
+            raise self.error("Timeout for message PAS5211SetUplinkVlanHandlResponse")
 
     @ATMT.receive_condition(wait_set_uplink_vlan_handling_response)
     def wait_for_set_uplink_vlan_handling_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211SetUplinkVlanHandlResponse in pkt: 
+        if PAS5211SetUplinkVlanHandlResponse in pkt:
             log.debug('[RESPONSE] PAS5211SetUplinkVlanHandlResponse')
             self.send_set_gen_vlan_downlink_configuration(self.device.device)
             raise self.wait_set_gen_vlan_downlink_configuration_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_set_gen_vlan_downlink_configuration_response, 10)
+    @ATMT.timeout(wait_set_gen_vlan_downlink_configuration_response, TIMEOUT)
     def timeout_wait_set_gen_vlan_downlink_configuration_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211SetVlanGenConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_gen_vlan_downlink_configuration(self.device.device)
+        else:
+            raise self.error("Timeout for message PAS5211SetVlanGenConfigResponse")
 
     @ATMT.receive_condition(wait_set_gen_vlan_downlink_configuration_response)
     def wait_for_set_gen_vlan_downlink_configuration_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211SetVlanGenConfigResponse in pkt: 
+        if PAS5211SetVlanGenConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211SetVlanGenConfigResponse')
             self.send_set_vlan_downlink_configuration(self.device.device, self.svlan_id)
             raise self.wait_set_vlan_downlink_configuration_response()
         else:
-            log.debug('Unexpected pkt {}'.format(pkt.summary())) 
+            log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_set_vlan_downlink_configuration_response, 10)
+    @ATMT.timeout(wait_set_vlan_downlink_configuration_response, TIMEOUT)
     def timeout_wait_set_vlan_downlink_configuration_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211SetVlanDownConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_vlan_downlink_configuration(self.device.device, self.svlan_id)
+        else:
+            raise self.error("Timeout for message PAS5211SetVlanDownConfigResponse")
 
     @ATMT.receive_condition(wait_set_vlan_downlink_configuration_response)
     def wait_for_set_vlan_downlink_configuration_response(self, pkt):
@@ -333,25 +379,33 @@
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_set_downlink_vlan_handling_response, 10)
+    @ATMT.timeout(wait_set_downlink_vlan_handling_response, TIMEOUT)
     def timeout_wait_set_downlink_vlan_handling_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211SetDownVlanHandlResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_downlink_vlan_handling(self.device.device, self.cvlan_id, self.svlan_id, self.port_id)
+        else:
+            raise self.error("Timeout for message PAS5211SetDownVlanHandlResponse")
 
     @ATMT.receive_condition(wait_set_downlink_vlan_handling_response)
     def wait_for_set_downlink_vlan_handling_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211SetDownVlanHandlResponse in pkt: 
+        if PAS5211SetDownVlanHandlResponse in pkt:
             log.debug('[RESPONSE] PAS5211SetDownVlanHandlResponse')
             self.send_get_port_id_downlink_policing(self.device.device, self.port_id)
             raise self.wait_get_port_id_downlink_policing_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_get_port_id_downlink_policing_response, 10)
+    @ATMT.timeout(wait_get_port_id_downlink_policing_response, TIMEOUT)
     def timeout_wait_get_port_id_downlink_policing_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211GetPortIdDownstreamPolicingConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_get_port_id_downlink_policing(self.device.device, self.port_id)
+        else:
+            raise self.error("Timeout for message PAS5211GetPortIdDownstreamPolicingConfigResponse")
 
     @ATMT.receive_condition(wait_get_port_id_downlink_policing_response)
     def wait_for_get_port_id_downlink_policing_response(self, pkt):
@@ -360,6 +414,7 @@
             log.debug('[RESPONSE] PAS5211GetPortIdDownstreamPolicingConfigResponse')
             if pkt[PAS5211GetPortIdDownstreamPolicingConfigResponse].ds_policing_config_id != PMC_OFAL_NO_POLICY:
                 self.policy_id = pkt[PAS5211GetPortIdDownstreamPolicingConfigResponse].ds_policing_config_id
+                log.debug('Policy id got: {}'.format(self.policy_id))
                 self.send_unset_port_id_downlink_policing(self.device.device, 1, self.port_id)
                 raise self.wait_unset_port_id_downlink_policing_response()
             else:
@@ -368,69 +423,84 @@
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_unset_port_id_downlink_policing_response, 10)
+    @ATMT.timeout(wait_unset_port_id_downlink_policing_response, TIMEOUT)
     def timeout_wait_unset_port_id_downlink_policing_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211UnsetPortIdPolicingConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_unset_port_id_downlink_policing(self.device.device, 1, self.port_id)
+        else:
+            raise self.error("Timeout for message PAS5211UnsetPortIdPolicingConfigResponse")
 
     @ATMT.receive_condition(wait_unset_port_id_downlink_policing_response)
     def wait_for_unset_port_id_downlink_policing_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211UnsetPortIdPolicingConfigResponse in pkt: 
+        if PAS5211UnsetPortIdPolicingConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211UnsetPortIdPolicingConfigResponse')
             self.send_remove_downlink_policing(self.device.device, self.policy_id)
             raise self.wait_remove_downlink_policing_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_remove_downlink_policing_response, 10)
+    @ATMT.timeout(wait_remove_downlink_policing_response, TIMEOUT)
     def timeout_wait_remove_downlink_policing_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211RemoveDownstreamPolicingConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_remove_downlink_policing(self.device.device, self.policy_id)
+        else:
+            raise self.error("Timeout for message PAS5211RemoveDownstreamPolicingConfigResponse")
 
     @ATMT.receive_condition(wait_remove_downlink_policing_response)
     def wait_for_remove_downlink_policing_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211RemoveDownstreamPolicingConfigResponse in pkt: 
+        if PAS5211RemoveDownstreamPolicingConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211RemoveDownstreamPolicingConfigResponse')
             self.send_set_downlink_policing(self.device.device, self.downlink_bandwidth)
             raise self.wait_set_downlink_policing_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_set_downlink_policing_response, 10)
+    @ATMT.timeout(wait_set_downlink_policing_response, TIMEOUT)
     def timeout_wait_set_downlink_policing_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211SetDownstreamPolicingConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_downlink_policing(self.device.device, self.downlink_bandwidth)
+        else:
+            raise self.error("Timeout for message PAS5211SetDownstreamPolicingConfigResponse")
 
     @ATMT.receive_condition(wait_set_downlink_policing_response)
     def wait_for_set_downlink_policing_response(self, pkt):
         #log.debug('api-proxy-response')
         if PAS5211SetDownstreamPolicingConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211SetDownstreamPolicingConfigResponse')
-            if pkt[PAS5211SetDownstreamPolicingConfigResponse].policing_config_id:
-                self.policy_id = pkt[PAS5211SetDownstreamPolicingConfigResponse].policing_config_id
-                self.send_set_port_id_policing(self.device.device, 1, self.port_id, self.policy_id)
-                raise self.wait_set_port_id_policing_response()
-            else:
-                raise self.error("Error setting downling policy")
+            # if pkt[PAS5211SetDownstreamPolicingConfigResponse].policing_config_id:
+            self.policy_id = pkt[PAS5211SetDownstreamPolicingConfigResponse].policing_config_id
+            log.debug('Policy id set: {}'.format(self.policy_id))
+            self.send_set_port_id_policing(self.device.device, 1, self.port_id, self.policy_id)
+            raise self.wait_set_port_id_policing_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
-    
-    @ATMT.timeout(wait_set_port_id_policing_response, 10)
+
+    @ATMT.timeout(wait_set_port_id_policing_response, TIMEOUT)
     def timeout_wait_set_port_id_policing_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211SetPortIdPolicingConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_port_id_policing(self.device.device, 1, self.port_id, self.policy_id)
+        else:
+            raise self.error("Timeout for message PAS5211SetPortIdPolicingConfigResponse")
 
     @ATMT.receive_condition(wait_set_port_id_policing_response)
     def wait_for_set_port_id_policing_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211SetPortIdPolicingConfigResponse in pkt: 
+        if PAS5211SetPortIdPolicingConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211SetPortIdPolicingConfigResponse')
             raise self.end()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
-    
+
     def send_set_port_id_configuration(self, device, activate, port_id, alloc_id):
         msg = PAS5211MsgSetPortIdConfig(
             # port_id=1000 + device.proxy_address.onu_id,
@@ -578,15 +648,15 @@
         msg = PAS5211SetDownstreamPolicingConfig(
             committed_bandwidth = SLA_gr_bw_gros*1024,
             excessive_bandwidth = (bandwidth - SLA_gr_bw_gros)*1024,
-            committed_burst_limit = 256, 
+            committed_burst_limit = 256,
             excessive_burst_limit = 256)
         self.send(self.px(msg))
         log.debug("[SENT] PAS5211SetDownstreamPolicingConfig")
-    
+
     def send_set_port_id_policing(self, device, dir, port_id, policy_id):
         msg = PAS5211SetPortIdPolicingConfig(
-            direction=dir, 
-            port_id=port_id, 
+            direction=dir,
+            port_id=port_id,
             policing_config_id=policy_id,
             reserved=0)
         self.send(self.px(msg))
@@ -655,4 +725,3 @@
         )
         self.send(self.px(msg))
         log.debug("[SENT] PAS5211SetDownVlanHandl")
-        
\ No newline at end of file
diff --git a/voltha/adapters/microsemi_olt/OltReinstallFlowStateMachine.py b/voltha/adapters/microsemi_olt/OltReinstallFlowStateMachine.py
index dfc5601..d14411e 100644
--- a/voltha/adapters/microsemi_olt/OltReinstallFlowStateMachine.py
+++ b/voltha/adapters/microsemi_olt/OltReinstallFlowStateMachine.py
@@ -54,12 +54,13 @@
     PON_DISABLE, PON_VLAN_CHANGE_TAG, PON_VLAN_DONT_CHANGE_TAG, PON_PORT_TYPE_GEM, PON_PORT_DESTINATION_CNI0, PON_ENABLE, SLA_gr_bw_gros, PYTHAGORAS_UPDATE_AID_SLA, \
     SLA_gr_bw_gros, SLA_be_bw_gros, SLA_gr_bw_fine, SLA_be_bw_fine, PYTHAGORAS_DBA_DATA_COS, PYTHAGORAS_DBA_STATUS_REPORT_NSR, \
     PMC_OFAL_NO_POLICY, UPSTREAM, DOWNSTREAM
-    
+
 log = structlog.get_logger()
 
+TIMEOUT = 5
 
-class OltReinstallFlowStateMachine(OltInstallFlowStateMachine):
-        
+class OltReinstallFlowStateMachine(OltRemoveFlowStateMachine):
+
     @ATMT.state()
     def wait_set_port_id_configuration_response(self):
         pass
@@ -67,12 +68,12 @@
     @ATMT.receive_condition(wait_set_port_id_configuration_response)
     def wait_for_set_port_id_configuration_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211MsgSetPortIdConfigResponse in pkt: 
+        if PAS5211MsgSetPortIdConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211MsgSetPortIdConfigResponse')
             olt = OltInstallFlowStateMachine(iface=self.iface, comm=self.comm,
                     target=self.target, device=self.device, onu_id=self.onu_id,
                     channel_id=self.channel_id, port_id=self.port_id, onu_session_id=self.onu_session_id,
-                    alloc_id=self.alloc_id, svlan_id= self.svlan_id, cvlan_id=self.cvlan_id)    
+                    alloc_id=self.alloc_id, svlan_id= self.svlan_id, cvlan_id=self.cvlan_id)
             olt.runbg()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
diff --git a/voltha/adapters/microsemi_olt/OltRemoveFlowStateMachine.py b/voltha/adapters/microsemi_olt/OltRemoveFlowStateMachine.py
index 44bbe96..b143cb8 100644
--- a/voltha/adapters/microsemi_olt/OltRemoveFlowStateMachine.py
+++ b/voltha/adapters/microsemi_olt/OltRemoveFlowStateMachine.py
@@ -40,7 +40,7 @@
     PAS5211SetVlanUplinkConfiguration, PAS5211SetVlanUplinkConfigurationResponse, PAS5211SetUplinkVlanHandlResponse, PAS5211SetVlanGenConfig, PAS5211SetVlanGenConfigResponse, \
     PAS5211GetPortIdDownstreamPolicingConfig, PAS5211GetPortIdDownstreamPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfig, \
     PAS5211MsgHeader, PAS5211UnsetPortIdPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfigResponse, \
-    PAS5211SetPortIdPolicingConfigResponse
+    PAS5211SetPortIdPolicingConfigResponse, PAS5211EventAlarmNotification
 from voltha.adapters.microsemi_olt.PAS5211_constants import OMCI_GEM_IWTP_IW_OPT_8021P_MAPPER, PON_FALSE, \
     PON_1_TO_1_VLAN_MODE, PON_TRUE, PON_VLAN_UNUSED_TAG, PON_VLAN_UNUSED_PRIORITY, PON_VLAN_REPLACE_PRIORITY, \
     PON_OUTPUT_VLAN_PRIO_HANDLE_INCOMING_VLAN, PON_VLAN_UNCHANGED_PRIORITY, PON_OUTPUT_VLAN_PRIO_HANDLE_DONT_CHANGE, \
@@ -51,9 +51,11 @@
     PON_DISABLE, PON_VLAN_CHANGE_TAG, PON_VLAN_DONT_CHANGE_TAG, PON_PORT_TYPE_GEM, PON_PORT_DESTINATION_CNI0, PON_ENABLE, SLA_gr_bw_gros, PYTHAGORAS_UPDATE_AID_SLA, \
     SLA_gr_bw_gros, SLA_be_bw_gros, SLA_gr_bw_fine, SLA_be_bw_fine, PYTHAGORAS_DBA_DATA_COS, PYTHAGORAS_DBA_STATUS_REPORT_NSR, \
     PMC_OFAL_NO_POLICY, UPSTREAM, DOWNSTREAM
-    
+
 log = structlog.get_logger()
 
+MAX_RETRIES = 10
+TIMEOUT = 5
 
 class OltRemoveFlowStateMachine(BaseOltAutomaton):
 
@@ -63,9 +65,10 @@
     onu_session_id = None
     alloc_id = None
     policy_id = None
+    retries = 0
 
     def parse_args(self, debug=0, store=0, **kwargs):
-        
+
         self.onu_id = kwargs.pop('onu_id')
         self.channel_id = kwargs.pop('channel_id')
         self.port_id = kwargs.pop('port_id')
@@ -81,13 +84,13 @@
             return False
 
         if PAS5211MsgHeader in pkt:
-            if PAS5211MsgGetOltVersionResponse not in pkt:
-                if pkt[PAS5211MsgHeader].channel_id == self.channel_id:
-                    if pkt[PAS5211MsgHeader].onu_id == self.onu_id:
-                        if OmciFrame not in pkt:
-                            if PAS5211MsgSendFrameResponse not in pkt:
-                                return True
-
+            if PAS5211EventAlarmNotification not in pkt:
+                if PAS5211MsgGetOltVersionResponse not in pkt:
+                    if pkt[PAS5211MsgHeader].channel_id == self.channel_id:
+                        if pkt[PAS5211MsgHeader].onu_id == self.onu_id:
+                            if OmciFrame not in pkt:
+                                if PAS5211MsgSendFrameResponse not in pkt:
+                                    return True
         return False
 
     """
@@ -102,7 +105,7 @@
     @ATMT.state()
     def wait_set_port_id_configuration_response(self):
         pass
-    
+
     @ATMT.state()
     def wait_get_onu_id_by_port_id_response(self):
         pass
@@ -128,8 +131,8 @@
     """
 
     def px(self, pkt):
-        return self.p(pkt, channel_id=self.channel_id, 
-            onu_id=self.onu_id, 
+        return self.p(pkt, channel_id=self.channel_id,
+            onu_id=self.onu_id,
             onu_session_id=self.onu_session_id)
 
     """
@@ -141,11 +144,13 @@
         self.send_get_onu_id_by_port_id(self.device.device, self.port_id)
         raise self.wait_get_onu_id_by_port_id_response()
 
-
-    @ATMT.timeout(wait_get_onu_id_by_port_id_response, 10)
     def timeout_wait_get_onu_id_by_port_id_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211MsgGetOnuIdByPortIdResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_get_onu_id_by_port_id(self.device.device, self.port_id)
+        else:
+            raise self.error("Timeout for message PAS5211MsgGetOnuIdByPortIdResponse")
 
     @ATMT.receive_condition(wait_get_onu_id_by_port_id_response)
     def wait_for_get_onu_id_by_port_id_response(self, pkt):
@@ -157,30 +162,38 @@
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_unset_port_id_downlink_policing_response, 10)
+    @ATMT.timeout(wait_unset_port_id_downlink_policing_response, TIMEOUT)
     def timeout_wait_unset_port_id_downlink_policing_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211UnsetPortIdPolicingConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_unset_port_id_downlink_policing(self.device.device, 1, self.port_id)
+        else:
+            raise self.error("Timeout for message PAS5211UnsetPortIdPolicingConfigResponse")
 
     @ATMT.receive_condition(wait_unset_port_id_downlink_policing_response)
     def wait_for_unset_port_id_downlink_policing_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211UnsetPortIdPolicingConfigResponse in pkt: 
+        if PAS5211UnsetPortIdPolicingConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211UnsetPortIdPolicingConfigResponse')
             self.send_set_port_id_configuration(self.device.device, PON_DISABLE, self.port_id, self.alloc_id)
             raise self.wait_set_port_id_configuration_response()
         else:
             log.debug('Unexpected pkt {}'.format(pkt.summary()))
 
-    @ATMT.timeout(wait_set_port_id_configuration_response, 10)
+    @ATMT.timeout(wait_set_port_id_configuration_response, TIMEOUT)
     def timeout_wait_set_port_id_configuration_response(self):
         #log.debug('api-proxy-timeout')
-        raise self.error("Timeout for message PAS5211MsgSetPortIdConfigResponse")
+        if self.retries < MAX_RETRIES:
+            self.retries += 1
+            self.send_set_port_id_configuration(self.device.device, PON_DISABLE, self.port_id, self.alloc_id)
+        else:
+            raise self.error("Timeout for message PAS5211MsgSetPortIdConfigResponse")
 
     @ATMT.receive_condition(wait_set_port_id_configuration_response)
     def wait_for_set_port_id_configuration_response(self, pkt):
         #log.debug('api-proxy-response')
-        if PAS5211MsgSetPortIdConfigResponse in pkt: 
+        if PAS5211MsgSetPortIdConfigResponse in pkt:
             log.debug('[RESPONSE] PAS5211MsgSetPortIdConfigResponse')
             self.end()
         else:
diff --git a/voltha/adapters/microsemi_olt/OltStateMachine.py b/voltha/adapters/microsemi_olt/OltStateMachine.py
index 57a2d57..a8f157e 100644
--- a/voltha/adapters/microsemi_olt/OltStateMachine.py
+++ b/voltha/adapters/microsemi_olt/OltStateMachine.py
@@ -59,7 +59,7 @@
         if OmciFrame in pkt:
             log.debug("OMCI-message-type: {}".format(pkt[OmciFrame].message_type))
             return False
-        
+
         if PAS5211Event in pkt:
             return False
 
@@ -224,7 +224,7 @@
             self.device.update_device_info_from_pkt(pkt)
             raise self.got_olt_version()
         else:
-            log.error("Got garbage packet {}".format(pkt))
+            log.error("Got garbage packet: {}".format(pkt.summary()))
             raise self.error()
 
     # Transitions from got_olt_version
@@ -549,7 +549,7 @@
     @ATMT.state(error=1)
     def error(self):
         raise self.end()
-    
+
     @ATMT.state(final=1)
     def end(self):
         log.debug('init-keepalive-end')
diff --git a/voltha/adapters/microsemi_olt/PAS5211_constants.py b/voltha/adapters/microsemi_olt/PAS5211_constants.py
index 9f7718f..eb23dbf 100644
--- a/voltha/adapters/microsemi_olt/PAS5211_constants.py
+++ b/voltha/adapters/microsemi_olt/PAS5211_constants.py
@@ -80,6 +80,17 @@
 PON_ALARM_AUTH_FAILED_IN_REGISTRATION_ID_MODE = 20
 PON_ALARM_SUFI = 21
 
+PON_DOWNSTREAM_PLOAM_MESSAGE_ENCRYPTED_PORT_ID=8,
+PON_DOWNSTREAM_PLOAM_MESSAGE_ASSIGN_ALLOC_ID=10,
+PON_DOWNSTREAM_PLOAM_MESSAGE_CONFIGURE_PORT_ID=14,
+PON_DOWNSTREAM_PLOAM_MESSAGE_BER_INTERVAL=18,
+PON_DOWNSTREAM_PLOAM_MESSAGE_KEY_SWITCHING=19
+
+PON_ALARM_SDI_RAISE=0,
+PON_ALARM_SDI_CLEAR=1
+PON_ALARM_RAISE=0
+PON_ALARM_CLEAR=1
+
 PON_ALARM_VIRTUAL_SCOPE_ONU_LASER_ALWAYS_ON = 16
 PON_ALARM_VIRTUAL_SCOPE_ONU_SIGNAL_DEGRADATION = 17
 PON_ALARM_VIRTUAL_SCOPE_ONU_EOL = 18
diff --git a/voltha/adapters/microsemi_olt/microsemi_olt.py b/voltha/adapters/microsemi_olt/microsemi_olt.py
index b37b0b6..2a0ebb7 100644
--- a/voltha/adapters/microsemi_olt/microsemi_olt.py
+++ b/voltha/adapters/microsemi_olt/microsemi_olt.py
@@ -25,7 +25,7 @@
 from voltha.adapters.microsemi_olt.ActivationWatcher import ActivationWatcher
 from voltha.adapters.microsemi_olt.DeviceManager import DeviceManager
 from voltha.adapters.microsemi_olt.OMCIProxy import OMCIProxy
-from voltha.adapters.microsemi_olt.OltStateMachine import OltStateMachine 
+from voltha.adapters.microsemi_olt.OltStateMachine import OltStateMachine
 from voltha.adapters.microsemi_olt.OltInstallFlowStateMachine import OltInstallFlowStateMachine
 from voltha.adapters.microsemi_olt.OltRemoveFlowStateMachine import OltRemoveFlowStateMachine
 from voltha.adapters.microsemi_olt.OltReinstallFlowStateMachine import OltReinstallFlowStateMachine
@@ -74,6 +74,8 @@
 
 from twisted.internet import reactor
 from twisted.internet.defer import DeferredQueue, inlineCallbacks, returnValue
+from voltha.protos.common_pb2 import OperStatus, AdminState, ConnectStatus
+
 
 log = structlog.get_logger()
 _ = third_party
@@ -148,7 +150,9 @@
         raise NotImplementedError()
 
     def reboot_device(self, device):
-        raise NotImplementedError()
+        log.debug('reboot-device', device=device)
+        device_handler = self.device_handlers[device.id]
+        reactor.callLater(0, device_handler.reboot_device, device)
 
     def create_tcont(self, device, tcont_data, traffic_descriptor_data):
         raise NotImplementedError()
@@ -287,6 +291,7 @@
         self.ports = dict()
         self.last_iteration_ports = []
         self.interface = registry('main').get_args().interface
+        self.flow_queue = DeferredQueue()
 
     def stop(self):
         log.debug('stopping')
@@ -296,19 +301,46 @@
 
     def activate(self, device):
         log.debug('activate-device', device=device)
+        self.last_iteration_ports = []
         self.device = device
         self.device_manager = DeviceManager(device, self.adaptor_agent)
         self.target = device.mac_address
         self.comm = PAS5211Communication(dst_mac=self.target, iface=self.interface)
 
-        olt = OltStateMachine(iface=self.interface, comm=self.comm,
+        self.olt = OltStateMachine(iface=self.interface, comm=self.comm,
                               target=self.target, device=self.device_manager)
-        activation = ActivationWatcher(iface=self.interface, comm=self.comm,
+        self.activation = ActivationWatcher(iface=self.interface, comm=self.comm,
                                 target=self.target, device=self.device_manager, olt_adapter=self)
-        olt.runbg()
-        activation.runbg()
 
-        self.olt = olt
+        reactor.callLater(0, self.wait_for_flow_events, device)
+
+        self.olt.runbg()
+        self.activation.runbg()
+
+    def reboot_device(self, device):
+        try:
+            log.debug('reboot-device', device=device)
+            # Stop ONUS ...
+            self.device_manager.update_child_devices_state(admin_state=AdminState.DISABLED)
+            # ... and then delete them!
+            self.device_manager.delete_all_child_devices
+            # Wait 10s to reboot OLT
+            reactor.callLater(10, self.reboot_olt, device)
+        except Exception as e:
+            log.exception('reboot-olt-exception', e=e)
+
+    def reboot_olt(self, device):
+        try:
+            # Stop OLT...
+            self.device_manager.delete_logical_device()
+            self.olt.stop()
+            self.activation.stop()
+            # ... and start again! ONUS will activate from events got from OLT
+            self.last_iteration_ports = []
+            self.ports.clear()
+            self.activate(device)
+        except Exception as e:
+            log.exception('reboot-olt-exception', e=e)
 
     def abandon_device(self, device):
         self._abandon(self.target)
@@ -369,30 +401,32 @@
         return bandwidth
 
     def get_downlink_bandwidth(self, cvlan_id, svlan_id, port, flows):
-        bandwidth = None
-        for flow in flows:
-            _in_port = fd.get_in_port(flow)
-            if _in_port == PMC_UPSTREAM_PORT:
-                log.debug('downlink-bandwidth-port-match')
-                if flow.table_id == 1:
-                    metadata = fd.get_metadata(flow)
-                    if metadata:
-                        if metadata == port:
-                            vlan = self.get_vlan(flow) & 0xfff
-                            if vlan == cvlan_id:
-                                bandwidth = fd.get_metadata(flow)
-                                log.debug('Bandwidth found:{}'.format(bandwidth))
-        return bandwidth
+        return None
 
     def update_flow_table(self, device, flows):
         try:
+            self.flow_queue.put({'flows':flows})
+        except Exception as e:
+            log.debug('flow-enqueue-exception', e=e)
+
+    @inlineCallbacks
+    def wait_for_flow_events(self, device):
+        log.debug('wait-for-flow-events', device=device)
+
+        event = yield self.flow_queue.get()
+        flows = event.get('flows')
+
+        try:
             cvlan_id = None
             svlan_id = None
 
-            log.debug('olt-update-flow-table', device_id=device.id, flows=flows)
-            # Look for in ports mentioned in flows received ...
+            log.debug('wait-for-flow-events-flow', device=device)
+
+            # Look for ports mentioned in flows received ...
             port_list = self.get_port_list(flows.items)
 
+            log.debug("list-ports", port_list=port_list)
+
             new_ports = set(port_list)-set(self.last_iteration_ports)
             log.debug("new-ports", new_ports=new_ports)
 
@@ -418,7 +452,10 @@
 
                     downlink_bandwidth = self.get_downlink_bandwidth(cvlan_id, svlan_id, port, flows.items)
                     if downlink_bandwidth == None:
-                        downlink_bandwidth = SLA_be_bw_gros
+                        if uplink_bandwidth == None:
+                            downlink_bandwidth = SLA_be_bw_gros
+                        else:
+                            downlink_bandwidth = uplink_bandwidth
 
                     onu_id = self.ports[port]['onu_id']
                     onu_session_id = self.ports[port]['onu_session_id']
@@ -450,7 +487,10 @@
 
                 else:
                     # Finally, it is an incomplete port, so we remove from port list
-                    port_list.remove(port)
+                    try:
+                        port_list.remove(port)
+                    except Exception as e:
+                        log.debug('remove-non-existing-port', e=e)
 
             # For those ports without flows, uninstall them
             for port in disconnected_ports:
@@ -462,16 +502,19 @@
                 channel_id= port / 32
 
                 if self.ports[port].get('cvlan') and self.ports[port].get('svlan'):
-                    self.uninstall_flows_sequence(device, onu_id, port_id, alloc_id, onu_session_id, 
+                    self.uninstall_flows_sequence(device, onu_id, port_id, alloc_id, onu_session_id,
                         channel_id)
                     self.ports[port]['svlan'] = None
                     self.ports[port]['cvlan'] = None
 
             self.last_iteration_ports = port_list
+            log.debug('last-iteration-ports', ports=self.last_iteration_ports)
 
         except Exception as e:
             log.exception('failed-to-olt-update-flow-table', e=e)
 
+        reactor.callLater(0, self.wait_for_flow_events, device)
+
     def get_vlan(self, flow):
         for field in fd.get_ofb_fields(flow):
             if field.type == fd.VLAN_VID: