Microsemi adapter updated

Change-Id: I841d7e1d6570fc8b8a8f59b680597d7cfa297539
diff --git a/voltha/adapters/microsemi_olt/APIProxy.py b/voltha/adapters/microsemi_olt/APIProxy.py
index ff9f466..1c92f0e 100644
--- a/voltha/adapters/microsemi_olt/APIProxy.py
+++ b/voltha/adapters/microsemi_olt/APIProxy.py
@@ -21,15 +21,19 @@
 from scapy.automaton import ATMT
 
 from voltha.adapters.microsemi_olt.BaseOltAutomaton import BaseOltAutomaton
-from voltha.adapters.microsemi_olt.PAS5211 import PAS5211MsgSendFrame, PAS5211MsgSendFrameResponse, \
-    PAS5211EventFrameReceived
+from voltha.adapters.microsemi_olt.PAS5211 import PAS5211MsgSendFrame, PAS5211MsgGetOltVersionResponse, PAS5211MsgSendFrameResponse, \
+    PAS5211EventFrameReceived, PAS5211MsgHeader, PAS5211SetVlanGenConfigResponse
+
+from voltha.extensions.omci.omci_frame import OmciFrame
 
 log = structlog.get_logger()
 
+
 class APIProxy(BaseOltAutomaton):
 
     proxy_address = None
     msg = None
+    opcode = None
 
     def parse_args(self, debug=0, store=0, **kwargs):
         self.adaptor_agent = kwargs.pop('adapter_agent')
@@ -38,6 +42,37 @@
 
         BaseOltAutomaton.parse_args(self, debug=debug, store=store, **kwargs)
 
+    def restart(self, *args, **kargs):
+        self.msg = kargs.pop('msg')
+        super(APIProxy, self).restart()
+
+    def master_filter(self, pkt):
+
+        if not super(APIProxy, self).master_filter(pkt):
+            return False
+
+        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
+
+        # if OmciFrame in pkt:
+        #     # if pkt[OmciFrame].message_type in (16, 17):
+        #     return False
+
+
+        if PAS5211MsgHeader in pkt:
+            if PAS5211MsgGetOltVersionResponse not in pkt:
+                if pkt[PAS5211MsgHeader].channel_id == self.proxy_address.channel_id:
+                    if pkt[PAS5211MsgHeader].onu_id == self.proxy_address.onu_id:
+                        if OmciFrame not in pkt:
+                            rcv_opcode = pkt[PAS5211MsgHeader].opcode & 0xFF
+                            if rcv_opcode == self.opcode:
+                                return True
+
+        return False
+
     """
     States
     """
@@ -53,19 +88,26 @@
     @ATMT.state(error=1)
     def error(self, msg):
         log.error(msg)
+        raise self.end()
+
 
     @ATMT.state(final=1)
     def end(self):
-        pass
+        log.debug('api-msg-end')
+        # pass
 
     """
     Utils
     """
 
     def px(self, pkt):
-        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)
+        
+        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, 
+            onu_session_id=self.proxy_address.onu_session_id)
 
     """
     Transitions
@@ -73,21 +115,26 @@
 
     @ATMT.condition(send_msg)
     def send_api_msg(self):
+        log.debug('send-api-msg')
         self.opcode = self.msg.opcode & 0xFF
         self.send(self.px(self.msg))
         raise self.wait_response()
 
     # Transitions from wait_event
-    @ATMT.timeout(wait_response, 3)
+    @ATMT.timeout(wait_response, 10)
     def timeout_wait_response(self):
-        raise self.error("No OMCI event for {}".format(self.proxy_address))
+        log.debug('api-proxy-timeout')
+        # Send empty packet...
+        self.adaptor_agent.receive_proxied_message(self.proxy_address, dict());
+        raise self.error("No API event for {}".format(self.proxy_address))
 
     @ATMT.receive_condition(wait_response)
     def wait_for_response(self, pkt):
-        if PAS5211EventFrameReceived in pkt:
-            rcv_opcode = pkt.opcode & 0xFF
-            if rcv_opcode == self.opcode:
-                # FIXME we may need to verify the transaction id
-                #  to make sure we have the right packet
-                self.adaptor_agent.recieve_proxied_message(self.proxy_address,pkt)
-                raise self.end()
+        if PAS5211MsgHeader in pkt: # and not isinstance(pkt, OmciFrame):
+            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 70dd42f..47bc6e0 100644
--- a/voltha/adapters/microsemi_olt/ActivationWatcher.py
+++ b/voltha/adapters/microsemi_olt/ActivationWatcher.py
@@ -15,6 +15,9 @@
 #
 from struct import pack, unpack
 
+from twisted.internet import reactor
+from twisted.internet.defer import DeferredQueue, inlineCallbacks, returnValue
+
 from scapy.automaton import ATMT
 import structlog
 from voltha.adapters.microsemi_olt.BaseOltAutomaton import BaseOltAutomaton
@@ -25,31 +28,44 @@
     PAS5211MsgGetDbaMode, PAS5211MsgGetDbaModeResponse, PAS5211MsgSendDbaAlgorithmMsg, \
     PAS5211MsgSendDbaAlgorithmMsgResponse, PAS5211EventDbaAlgorithm, PAS5211MsgSetPortIdConfig, \
     PAS5211MsgSetPortIdConfigResponse, PAS5211MsgGetOnuIdByPortId, PAS5211MsgGetOnuIdByPortIdResponse, \
-    PAS5211SetVlanUplinkConfiguration, PAS5211SetVlanUplinkConfigurationResponse, PAS5211MsgSetOnuAllocIdResponse
+    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, \
     PMC_OFAL_MAX_BI_DIRECTIONAL_FLOW_PER_ONU, PMC_OFAL_START_FLOW_ID_BASE, PON_DBA_MODE_RUNNING, \
     PYTHAGORAS_UPDATE_AID_SLA, SLA_be_bw_gros, SLA_gr_bw_gros, SLA_gr_bw_fine, SLA_be_bw_fine, PYTHAGORAS_DBA_DATA_COS, \
     PYTHAGORAS_DBA_STATUS_REPORT_NSR, PYTHAGORAS_SET_SLA_RESP_SIZE, PON_PORT_TYPE_GEM, PON_PORT_DESTINATION_CNI0, \
-    PON_FALSE, PON_DISABLE
+    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
 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 twisted.internet import reactor
+
+from voltha.protos.events_pb2 import AlarmEvent, AlarmEventType, \
+    AlarmEventSeverity, AlarmEventState, AlarmEventCategory, AlarmEventCategory
+
 log = structlog.get_logger()
 _verbose = False
 
 ALLOC_ID = 1000
 
+
 def alloc_id(onu_id):
     for i in range(0, PMC_OFAL_MAX_BI_DIRECTIONAL_FLOW_PER_ONU):
         alloc_id = PMC_OFAL_START_FLOW_ID_BASE + \
-                   (onu_id * PMC_OFAL_MAX_BI_DIRECTIONAL_FLOW_PER_ONU) + i
+            (onu_id * PMC_OFAL_MAX_BI_DIRECTIONAL_FLOW_PER_ONU) + i
         yield alloc_id
 
+
 def hexstring(string):
     return ":".join("{:02x}".format(ord(c)) for c in string)
 
+
 class ActivationManager(BaseOltAutomaton):
 
     onu_id = None
@@ -59,14 +75,17 @@
     channel_id = None
     alloc_id = None
     vendor = None
+    olt_adapter = None
 
-    def parse_args(self, debug=0, store=0, **kwargs):
+    def parse_args(self, debug=0, store=0,**kwargs):
         self.onu_id = kwargs.pop('onu_id')
         self.serial_number = kwargs.pop('serial_number')
         self.onu_session_id = kwargs.pop('onu_session_id')
         self.port_id = self.onu_id
         self.channel_id = kwargs.pop('channel_id')
         self.alloc_id = alloc_id(self.onu_id)
+        self.activation_watcher = kwargs.pop('activation_watcher')
+        self.olt_adapter = kwargs.pop('olt_adapter')
 
         if self.onu_id is None or self.serial_number is None or \
                 self.onu_session_id is None or self.channel_id is None:
@@ -75,6 +94,37 @@
         BaseOltAutomaton.parse_args(self, debug=debug, store=store, **kwargs)
 
     """
+        Master filter: Do not allow PAS5211MsgGetOltVersionResponse
+    """
+
+    def master_filter(self, pkt):
+
+        if not super(ActivationManager, self).master_filter(pkt):
+            return False
+    
+
+        if OmciFrame in pkt:
+            if pkt[OmciFrame].message_type in (16, 17):
+                return False
+
+        if PAS5211MsgGetOltVersionResponse not in pkt:
+            if PAS5211MsgHeader in pkt:
+                if pkt[PAS5211MsgHeader].channel_id == self.channel_id:
+                    return True
+        
+        return False
+
+    def create_default_data_flow_olt_config(self):
+        # PAS_set_onu_alloc_id
+        # PYTHAGORAS_set_SLA
+        # PAS_map_port_id_to_alloc_id
+        # PAS_set_vlan_uplink_configuration
+        pass
+
+    # def register_activation_watcher(self, activation_watcher):
+    #     self.activation_watcher = activation_watcher
+
+    """
     States
     """
 
@@ -118,33 +168,16 @@
     def wait_dba_mode(self):
         pass
 
-    @ATMT.state()
-    def wait_send_dba_alg_msg(self):
-        pass
-
-    @ATMT.state()
-    def wait_dba_alg_event(self):
-        pass
-
-    @ATMT.state()
-    def wait_set_port_id_config(self):
-        pass
-
-    @ATMT.state()
-    def wait_get_onu_id_by_port_id(self):
-        pass
-
-    @ATMT.state()
-    def wait_set_vlan_uplink_config(self):
-        pass
-
     @ATMT.state(final=1)
     def end(self):
-        pass
+        log.debug("activation-manager-end")
+        self.activation_watcher.next_activation()
 
+    
     @ATMT.state(error=1)
     def error(self, msg):
         log.error(msg)
+        raise self.end()
 
     """
     Utility Methods
@@ -155,17 +188,25 @@
                       onu_id=self.onu_id, onu_session_id=self.onu_session_id)
 
     def detect_onu(self):
-        log.info("Activated {} ONT".format(self.vendor))
         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)
+
             self.device.onu_detected(
-                parent_port_no=self.channel_id,
+                parent_port_no=parent_port,
                 child_device_type='%s_onu' % self.vendor.lower(),
                 onu_id=self.onu_id,
                 serial_number=hexstring(self.serial_number),
-                onu_session_id=self.onu_session_id
+                onu_session_id=self.onu_session_id,
+                channel_id=self.channel_id
             )
+
         except Exception as e:
-            print e
+            log.exception('failed', e=e)
+            raise e
 
     """
     Transitions
@@ -174,31 +215,38 @@
     # Transition from got_activation_event
     @ATMT.condition(got_activation_event)
     def send_get_activation_auth_mode(self):
+        log.debug('PAS5211MsgGetActivationAuthMode, channel_id={}'.format(self.channel_id))
         auth_mode = PAS5211MsgGetActivationAuthMode()
-        self.send(self.p(auth_mode))
+        self.send(self.p(auth_mode, channel_id=self.channel_id))
         raise self.wait_get_auth_mode()
 
     # 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)))
+            .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_get_auth_mode)
     def wait_for_get_auth_mode(self, pkt):
+        log.debug('wait_for_get_auth_mode')
         if PAS5211MsgGetActivationAuthModeResponse in pkt:
+            log.debug('PAS5211MsgGetActivationAuthModeResponse')
+            pkt = pkt[PAS5211MsgGetActivationAuthModeResponse]
             if pkt.mode == PON_ACTIVATION_AUTH_AUTO:
                 raise self.got_auth_mode()
             else:
                 # TODO There may be something that can be done here.
                 # See line 2497 of PAS_onu_mode_change_thread.c
-                log.error('Got unknown auth mode {}; dropping activation event'.format(pkt.mode))
+                log.error(
+                    'Got unknown auth mode {}; dropping activation event'.format(pkt.mode))
                 raise self.end()
 
     # Transitions from got auth_mode
     @ATMT.condition(got_auth_mode)
     def send_omci_port_id(self):
-        omci_port_id = PAS5211MsgSetOnuOmciPortId(port_id=self.port_id, activate=PON_ENABLE)
+        log.debug('send_omci_port_id')
+        omci_port_id = PAS5211MsgSetOnuOmciPortId(
+            port_id=self.port_id, activate=PON_ENABLE)
         self.send(self.px(omci_port_id))
         raise self.wait_omci_port_id()
 
@@ -206,34 +254,32 @@
     @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)))
+            .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_omci_port_id)
     def wait_for_omci_port_id(self, pkt):
-        if pkt.opcode == PAS5211MsgSetOnuOmciPortIdResponse.opcode and \
-                pkt.onu_id == self.onu_id and pkt.onu_session_id == self.onu_session_id and \
-                pkt.channel_id == self.channel_id:
-            raise self.got_omci_port_id()
+        log.debug('wait_for_omci_port_id')
+        if PAS5211MsgSetOnuOmciPortIdResponse in pkt:
+            log.debug('PAS5211MsgSetOnuOmciPortIdResponse')
+            msg_header = pkt[PAS5211MsgHeader]
+            if msg_header.opcode == PAS5211MsgSetOnuOmciPortIdResponse.opcode and \
+                    msg_header.onu_id == self.onu_id and msg_header.onu_session_id == self.onu_session_id and \
+                    msg_header.channel_id == self.channel_id:
+                raise self.got_omci_port_id()
 
     # Transitions from got_omci_port_id
     @ATMT.condition(got_omci_port_id)
     def send_omci_identity_frame(self):
-        # attr_mask |= OMCI_ATTR_BIT(OMCI_CIRCUIT_PACK_ATTR_VENDOR_ID);
-        #message.attributes_mask = 2048
+        log.debug('send_omci_identity_frame')
 
-        # Entity_id
-        # equip_ind = OMCI_CIRCUIT_PACK_INTEGRATED_EQUIPMENT;
-        # slot_id = 257;
-        # entity_instance = ((equip_ind<<8) | slot_id
-        message = OmciGet(entity_class=CircuitPack.class_id, entity_id = 257,
+        message = OmciGet(entity_class=CircuitPack.class_id, entity_id=257,
                           attributes_mask=2048)
-        #TODO fix transaction id
+        # TODO fix transaction id
         frame = OmciFrame(transaction_id=0, message_type=OmciGet.message_id,
                           omci_message=message)
         omci_frame = PAS5211MsgSendFrame(port_type=PON_PORT_PON, port_id=self.port_id,
                                          management_frame=PON_ENABLE, frame=frame)
 
-
         self.send(self.px(omci_frame))
 
         raise self.wait_send_frame()
@@ -242,195 +288,183 @@
     @ATMT.timeout(wait_send_frame, 3)
     def timeout_send_frame(self):
         raise self.error('Could not send omci to OLT {}; dropping activation event for {}'
-                   .format(self.target, hexstring(self.serial_number)))
+                         .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_send_frame)
     def wait_for_send_frame(self, pkt):
+        log.debug('wait_for_send_frame')
         if PAS5211MsgSendFrameResponse in pkt:
+            log.debug('PAS5211MsgSendFrameResponse')
             raise self.wait_omci_get()
 
     # Transitions from wait_omci_get
     @ATMT.timeout(wait_omci_get, 3)
-    def timeout_send_frame(self):
+    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)))
+            .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_omci_get)
     def wait_for_omci_get(self, pkt):
+        log.debug('wait_for_omci_get')
         if OmciGetResponse in pkt:
+            log.debug('OmciGetResponse')
             self.allocId = self.alloc_id.next()
-            self.vendor = pkt['OmciGetResponse'].data['vendor_id']
+            #self.vendor = pkt['OmciGetResponse'].data['vendor_id']
+            self.vendor = pkt[OmciGetResponse].data['vendor_id']
+            log.debug('wait_for_omci_get vendor_id:' + self.vendor)
             l_obj_status = PAS5211MsgGetLogicalObjectStatus(
-                            type=PON_LOGICAL_OBJECT_TYPE_ALLOC_ID,
-                            value=self.allocId)
-            self.send(self.px(l_obj_status))
+                type=PON_LOGICAL_OBJECT_TYPE_ALLOC_ID,
+                value=self.allocId)
+            self.send(self.p(l_obj_status, channel_id=self.channel_id))
             raise self.wait_logical_object_status()
 
     # 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)))
+            .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_logical_object_status)
     def wait_for_logical_object_status(self, pkt):
+        log.debug('wait_for_logical_object_status')
         if PAS5211MsgGetLogicalObjectStatusResponse in pkt:
-            if pkt.type == PON_LOGICAL_OBJECT_TYPE_ALLOC_ID:
+            pkt = pkt[PAS5211MsgGetLogicalObjectStatusResponse]
+            log.debug('PAS5211MsgGetLogicalObjectStatusResponse pkt.type=' + str(pkt.type) + ' pkt.return_value=' + str(
+                pkt.return_value))
+            if pkt.type == PON_LOGICAL_OBJECT_TYPE_ALLOC_ID:  # PASCOMM_GPON_api_parser.c line:11994
                 if pkt.return_value == 0:
+                    log.debug(
+                        'PAS5211MsgGetLogicalObjectStatusResponse (pkt.return_value == 0)')
                     # alloc-id not set
                     set_alloc_id = PAS5211MsgSetOnuAllocId(
-                                    alloc_id=self.allocId,
-                                    allocate=PON_ENABLE
-                                )
-                    self.onu_id = -1
+                        alloc_id=self.allocId,
+                        allocate=PON_ENABLE
+                    )
+                    # self.onu_id = -1
                     self.port_id = self.allocId
                     self.send(self.px(set_alloc_id))
                     raise self.wait_set_alloc_id()
                 else:
+                    log.debug(
+                        'PAS5211MsgGetLogicalObjectStatusResponse (pkt.return_value != 0)')
                     l_obj_status = PAS5211MsgGetLogicalObjectStatus(
                         type=PON_LOGICAL_OBJECT_TYPE_ONU_ID_BY_ALLOC_ID,
                         value=self.allocId)
                     self.send(self.px(l_obj_status))
                     raise self.wait_logical_object_status()
             elif pkt.type == PON_LOGICAL_OBJECT_TYPE_ONU_ID_BY_ALLOC_ID:
+                log.debug(
+                    'PAS5211MsgGetLogicalObjectStatusResponse (pkt.type == PON_LOGICAL_OBJECT_TYPE_ALLOC_ID)')
                 # That's your onu id.
                 self.onu_id = pkt.return_value
                 # FIXME Need to iterate to get the port id as
                 # in PMC_OFAL_flow_db.c line 656
-                # UPDATE PORT_ID
                 set_alloc_id = PAS5211MsgSetOnuAllocId(
                     alloc_id=self.allocId,
                     allocate=PON_ENABLE
                 )
                 self.send(self.px(set_alloc_id))
-                raise self.wait_for_set_alloc_id() #FIXME are we done? probably not but check
+                raise self.wait_set_alloc_id()  #  are we done? probably not but check
 
     # 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 {}'
-                   .format(self.target, hexstring(self.serial_number)))
+                         .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_set_alloc_id)
     def wait_for_set_alloc_id(self, pkt):
+        log.debug('wait_for_set_alloc_id')
         if PAS5211MsgSetOnuAllocIdResponse in pkt:
-            self.send(self.px(PAS5211MsgGetDbaMode()))
+            self.send(self.p(PAS5211MsgGetDbaMode(),
+                             channel_id=self.channel_id))
             raise self.wait_dba_mode()
 
-    # Transitions from wait for dba mode (See Pythagoras_api.c line 344 & PMC_OFAL.c 2062)
+    # Transitions from wait for dba mode (See Pythagoras_api.c line 344 &
+    # 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 {}'
-                   .format(self.target, hexstring(self.serial_number)))
-
+                         .format(self.target, hexstring(self.serial_number)))
 
     @ATMT.receive_condition(wait_dba_mode)
     def wait_for_dba_mode(self, pkt):
         if PAS5211MsgGetDbaModeResponse in pkt:
+            pkt = pkt[PAS5211MsgGetDbaModeResponse]
             if pkt.dba_mode != PON_DBA_MODE_RUNNING:
                 raise self.error('DBA is not running; dropping activation event for {}'
-                           .format(hexstring(self.serial_number)))
-
-            data = pack('<LLHHBBBB', PYTHAGORAS_UPDATE_AID_SLA,
-                        self.allocId, 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)
-
-            send_dba_alg = PAS5211MsgSendDbaAlgorithmMsg(data=data)
-            self.send(self.px(send_dba_alg))
-            raise self.wait_send_dba_alg_msg()
-
-    # Transitions from wait_send_dba_alg_msg
-    @ATMT.timeout(wait_send_dba_alg_msg, 3)
-    def timeout_wait_for_send_dba_alg_msg(self):
-        raise self.error('Unable to set dba alg params for {}; dropping activation event for {}'
-                         .format(self.target, hexstring(self.serial_number)))
-
-    @ATMT.receive_condition(wait_send_dba_alg_msg)
-    def wait_for_send_dba_alg_msg(self, pkt):
-        if PAS5211MsgSendDbaAlgorithmMsgResponse in pkt:
-            raise self.wait_dba_alg_event()
-
-    # Transitions from wait_dba_alg_event
-    @ATMT.timeout(wait_dba_alg_event, 3)
-    def timeout_wait_for_send_dba_alg_event(self):
-        raise self.error('DBA params ont set for {}; dropping activation event for {}'
-                         .format(self.target, hexstring(self.serial_number)))
-
-    @ATMT.receive_condition(wait_dba_alg_event)
-    def wait_for_send_dba_alg_event(self, pkt):
-        if PAS5211EventDbaAlgorithm in pkt:
-            if pkt.size < PYTHAGORAS_SET_SLA_RESP_SIZE:
-                raise self.error('DBA Event message too small for {}, dropping activation event for {}'
-                                 .format(self.target, hexstring(self.serial_number)))
-
-            (_, aid, _) = unpack('<LLH',pkt.data)
-            if aid == self.allocId:
-                # All is well moving on.
-                # There is some more shit at PYTHAGORAS.c line 395 but fuck it.
-                set_port_id_config = PAS5211MsgSetPortIdConfig(
-                    port_id=self.port_id,
-                    activate=PON_ENABLE,
-                    alloc_id=self.allocId,
-                    type=PON_PORT_TYPE_GEM,
-                    destination=PON_PORT_DESTINATION_CNI0
-                )
-                self.send(self.px(set_port_id_config))
-                raise self.wait_set_port_id_config()
-
-    # Transitions from wait_set_port_id_config
-    @ATMT.timeout(wait_set_port_id_config, 3)
-    def timeout_wait_set_port_id_config(self):
-        raise self.error('Could not set port id config for {}; dropping activation event for {}'
-                         .format(self.target, hexstring(self.serial_number)))
-
-    @ATMT.receive_condition(wait_set_port_id_config)
-    def wait_for_set_port_id_config(self, pkt):
-        if PAS5211MsgSetPortIdConfigResponse in pkt:
-            get_onu_id = PAS5211MsgGetOnuIdByPortId(
-                port_id=self.port_id
-            )
-            self.send(self.px(get_onu_id))
-            raise self.wait_get_onu_id_by_port_id()
-
-    # Transistions from wait_get_onu_id_by_port_id
-    @ATMT.timeout(wait_get_onu_id_by_port_id, 3)
-    def timeout_wait_get_onu_id_by_port_id(self):
-        raise self.error('Could not get onu id for {}; dropping activation event for {}'
-                         .format(self.target, hexstring(self.serial_number)))
-
-    @ATMT.receive_condition(wait_get_onu_id_by_port_id)
-    def wait_for_get_onu_id_by_port_id(self, pkt):
-        if PAS5211MsgGetOnuIdByPortIdResponse in pkt:
-            self.onu_id = pkt['PAS5211MsgGetOnuIdByPortIdResponse'].onu_id
-            # There may be more things to do here. but traces indicate that no.
-            # see PAS.c line 977 and onwards.
-            set_vlan_uplink_config = PAS5211SetVlanUplinkConfiguration(
-                port_id=self.port_id,
-                pvid_config_enabled=PON_FALSE,
-                min_cos=0,
-                max_cos=7,
-                de_bit=PON_DISABLE
-            )
-            self.send(self.px(set_vlan_uplink_config))
-            raise self.wait_set_vlan_uplink_config()
-
-    # Transitions from wait_set_vlan_uplink_config
-    @ATMT.timeout(wait_set_vlan_uplink_config, 3)
-    def timeout_wait_set_vlan_uplink_config(self):
-        raise self.error('Could not set vlan uplink config for {}; dropping activation event for {}'
-                                 .format(self.target, hexstring(self.serial_number)))
-
-    @ATMT.receive_condition(wait_set_vlan_uplink_config)
-    def wait_for_set_vlan_uplink_config(self, pkt):
-        if PAS5211SetVlanUplinkConfigurationResponse in pkt:
-            # YAY we made it.
-            # TODO update OLT with CNI port
+                                 .format(hexstring(self.serial_number)))
             self.detect_onu()
             raise self.end()
 
-
+   
 class ActivationWatcher(BaseOltAutomaton):
+    """
+        Master filter: Do not allow PAS5211MsgGetOltVersionResponse
+    """
+
+    pending_activation_events = []
+    activation_lock = False
+    olt_adapter = None
+
+    def master_filter(self, pkt):
+        if not super(ActivationWatcher, self).master_filter(pkt):
+            return False
+
+        if PAS5211EventOnuActivation in pkt:
+            return True
+
+        elif PAS5211EventOnuDeactivation in pkt:
+            return True
+
+        elif PAS5211EventAlarmNotification in pkt:
+            return True
+
+        return False
+
+
+    # Callback from activation manager
+    def next_activation(self):
+        log.debug("next-activation")
+        if self.pending_activation_events:
+            self.activation_lock=True
+            # Retrieve last element from list
+            pkt = self.pending_activation_events.pop()
+            self.activate_onu(pkt)
+        else:
+            self.activation_lock = False
+
+    def parse_args(self, debug=0, store=0,**kwargs):
+        self.olt_adapter = kwargs.pop('olt_adapter')
+        BaseOltAutomaton.parse_args(self, **kwargs)
+
+    def activate_onu(self, pkt):
+        log.debug("activate-onu")
+        msg_header = pkt[PAS5211MsgHeader]
+        msg = pkt[PAS5211EventOnuActivation]
+        log.debug('{} activated'.format(hexstring(msg.serial_number)))
+        onu_activation = ActivationManager(iface=self.iface, target=self.target, comm=self.comm,
+                                           onu_id=msg_header.onu_id, serial_number=msg.serial_number,
+                                           onu_session_id=msg_header.onu_session_id,
+                                           channel_id=msg_header.channel_id, device=self.device, activation_watcher=self, olt_adapter=self.olt_adapter)
+
+        onu_activation.runbg()
+
+    def deactivate_onu(self, pkt):
+        log.debug("deactivate-onu")
+        msg_header = pkt[PAS5211MsgHeader]
+        try:
+            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(
+                msg_header.channel_id, msg_header.onu_id, msg_header.onu_session_id))
+        except Exception as e:
+            log.exception('deactivate-onu failed', e=e)
 
     """
     States
@@ -448,10 +482,97 @@
     @ATMT.receive_condition(wait_onu_activation_event)
     def wait_for_onu_activation_event(self, pkt):
         if PAS5211EventOnuActivation in pkt:
-            log.info('{} activated'.format(hexstring(pkt.serial_number)))
-            onu_activation = ActivationManager(iface=self.iface, target=self.target, comm=self.comm,
-                                               onu_id=pkt.onu_id, serial_number=pkt.serial_number,
-                                               onu_session_id=pkt.onu_session_id,
-                                               channel_id=pkt.channel_id, device=self.device)
-            onu_activation.runbg()
-            raise self.wait_onu_activation_event()
+            log.debug('PAS5211EventOnuActivation Received')
+
+            self.pending_activation_events.append(pkt)
+
+            if not self.activation_lock:
+                self.next_activation()
+
+        elif PAS5211EventOnuDeactivation in pkt:
+            log.debug('PAS5211EventOnuDeactivation Received')
+            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))
+            try:
+                self.process_alarm(pkt)
+            except Exception as e:
+                log.exception('Error at process_alarm', e=e)
+        else:
+            pass
+
+        raise self.wait_onu_activation_event()
+
+
+    #Method to parse alarm and send it to DeviceManager
+    def process_alarm(self, pkt):
+        log.debug('[Process_alarm] Starting')
+        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,
+            type=AlarmEventType.EQUIPMENT,
+            # category=AlarmEventCategory.OLT,
+            # severity=AlarmEventSeverity.INDETERMINATE,
+            # state=AlarmEventState.RAISED,
+            context=ctx
+        )
+
+        #Define especific alarm parameters
+        if code == PON_ALARM_LOS:
+            alarm['description'] = 'Loss of signal: OLT does not receive transmissions in the upstream'
+        elif code == PON_ALARM_LOSI:
+            alarm['description'] = 'Loss of signal for ONUi: no signal from the ONU when expected'
+        elif code == PON_ALARM_DOWI:
+            alarm['description'] = 'Loss of signal for ONUi: no signal from the ONU when expected'
+        elif code == PON_ALARM_LOFI:
+            alarm['description'] = 'Loss of frame of ONUi: no valid optical signal is received from the ONU'
+        elif code == PON_ALARM_RDII:
+            alarm['description'] = 'Remote Defect Indication of ONUi: OLT transmissions is received with defect at the ONUi'
+        elif code == PON_ALARM_LOAMI:
+            alarm['description'] = 'Loss of PLOAM for ONUi: 3 messages of ONU are missing after OLT sends PLOAMu request'
+        elif code == PON_ALARM_LCDGI:
+            alarm['description'] = 'Loss of GEM channel delineation: GEM fragment delineation of ONUi is lost'
+        elif code == PON_ALARM_LOAI:
+            alarm['description'] = 'Loss of acknowledge with ONUi: OLT does not receive ack from ONUi'
+        elif code == PON_ALARM_SDI:
+            alarm['description'] = 'Signal Degraded of ONUi: raised when the upstream BER of ONUi goes below certain level'
+        elif code == PON_ALARM_SFI:
+            alarm['description'] = 'Signal Fail of ONUi: raised when the upstream of ONUi becomes greater than some level'
+        elif code == PON_ALARM_PEE:
+            alarm['description'] = 'Physical Equipment Error of ONUi: raised when the OLT receives a PEE message from the ONU'
+        elif code == PON_ALARM_DGI:
+            alarm['description'] = 'Dying Gasp of ONUi: raised when the OLT receives DG message from ONUi'
+        elif code == PON_ALARM_LOKI:
+            alarm['description'] = 'Loss of key synch with ONUi: Key transmission from ONU fails 3 times'
+        elif code == PON_ALARM_TIWI:
+            alarm['description'] = 'Transmission interference warning: raised when the drift of ONU transmissions exceeds specified threshold'
+        elif code == PON_ALARM_TIA:
+            alarm['description'] = 'Transmission Interference Alarm: an ONU turns on its laser at another ONUs time'
+        else:
+            log.error('Error, unsupported OLT Alarm {} received from OLT device'.format(code, self.device))
+            alarm['description'] = ''
+
+        log.debug('[Process_alarm] Send alarm to DeviceManager')
+        log.warn('Alarm: '+alarm['description']+' from '+alarm['id'])
+
+        self.device.publish_alarm(alarm)
diff --git a/voltha/adapters/microsemi_olt/DeviceManager.py b/voltha/adapters/microsemi_olt/DeviceManager.py
index d9499d5..c11119b 100644
--- a/voltha/adapters/microsemi_olt/DeviceManager.py
+++ b/voltha/adapters/microsemi_olt/DeviceManager.py
@@ -16,7 +16,7 @@
 from uuid import uuid4
 import structlog
 
-from voltha.adapters.microsemi_olt.PAS5211 import CHANNELS
+from voltha.adapters.microsemi_olt.PAS5211 import CHANNELS, PORTS
 from voltha.protos.common_pb2 import ConnectStatus, OperStatus, AdminState
 from voltha.protos.device_pb2 import Device, Port, Image
 from voltha.protos.logical_device_pb2 import LogicalDevice, LogicalPort
@@ -25,6 +25,7 @@
 
 log = structlog.get_logger()
 
+
 def mac_str_to_tuple(mac):
     """
     Convert 'xx:xx:xx:xx:xx:xx' MAC address string to a tuple of integers.
@@ -32,6 +33,7 @@
     """
     return tuple(int(d, 16) for d in mac.split(':'))
 
+
 class DeviceManager(object):
 
     def __init__(self, device, adapter_agent):
@@ -55,13 +57,13 @@
         # active, standby etc. Choose the active or running software
         # below. See simulated_olt for example implementation
         self.device.images.image.extend([
-                                          Image(version="0.0.1")
-                                        ])
+            Image(version="0.0.1")
+        ])
         self.device.serial_number = self.device.mac_address
         self.device.oper_status = ConnectStatus.REACHABLE
-        self.adapter_agent.update_device(self.device)
+        # self.adapter_agent.update_device(self.device)
 
-        for i in CHANNELS:
+        for i in PORTS:
             self.adapter_agent.add_port(self.device.id, Port(
                 port_no=i,
                 label='PON port',
@@ -70,8 +72,15 @@
                 oper_status=OperStatus.ACTIVE
             ))
 
+        self.create_logical_device()
+        self.add_upstream_port(129)
+        self.add_logical_upstream_port(129)
+
+        self.device.parent_id = self.logical_device.id
+        self.adapter_agent.update_device(self.device)
+
     def create_logical_device(self):
-        log.info('create-logical-device')
+        log.debug('create-logical-device')
         # then shortly after we create the logical device with one port
         # that will correspond to the NNI port
         ld = LogicalDevice(
@@ -94,7 +103,41 @@
             root_device_id=self.device.id
         )
 
-        self.logical_device = self.adapter_agent.create_logical_device(ld)
+        self.logical_device = self.adapter_agent.create_logical_device(ld, dpid=self.device.mac_address)
+
+    def add_upstream_port(self, port):
+        nni_port = Port(
+            port_no=port,
+            label='NNI',
+            type=Port.ETHERNET_NNI,
+            admin_state=AdminState.ENABLED,
+            oper_status=OperStatus.ACTIVE
+        )
+        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(
+            id='nni',
+            ofp_port=ofp_port(
+                port_no=port,
+                # hw_addr=mac_str_to_tuple(self.device.serial_number)[2:8],
+                hw_addr=mac_str_to_tuple('00:00:00:00:00:%02x' % port),
+                name='nni',
+                config=0,
+                state=OFPPS_LIVE,
+                curr=cap,
+                advertised=cap,
+                peer=cap,
+                curr_speed=OFPPF_10GB_FD,
+                max_speed=OFPPF_10GB_FD
+            ),
+            device_id=self.device.id,
+            device_port_no=port,
+            root_port=True
+        ))
 
     def add_port(self, port):
         self.adapter_agent.add_port(self.device.id, port)
@@ -119,27 +162,62 @@
                                             logical_port)
 
     def onu_detected(self, parent_port_no=None,
-                        child_device_type=None,
-                        onu_id=None,
-                        serial_number=None,
-                        onu_session_id=None):
-        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(
+                     child_device_type=None,
+                     onu_id=None,
+                     serial_number=None,
+                     onu_session_id=None,
+                     channel_id=None):
+        log.debug('onu-detected') 
+        try:
+            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)
+        except Exception as e:
+            log.exception('onu-detected-failed', e=e) 
+            raise e
+
+    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(
                 device_id=self.device.id,
-                channel_id=parent_port_no, # happens to be the channel id as well
+                channel_id=channel_id,
                 onu_id=onu_id,
                 onu_session_id=onu_session_id
-            ),
-            admin_state=AdminState.ENABLED,
-            vlan=0
-        )
+            ))
+            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:
+            log.debug("ONU {} cannot be deactivated".format(onu_id))
 
     def activate(self):
-        self.device = self.adapter_agent.get_device(self.device.id)
-        self.device.parent_id = self.logical_device.id
+        # self.device = self.adapter_agent.get_device(self.device.id)
+        # self.device.parent_id = self.logical_device.id
         self.device.oper_status = OperStatus.ACTIVE
         self.adapter_agent.update_device(self.device)
+
+
+    def publish_alarm(self, alarm):
+        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"]
+        )
+        self.adapter_agent.submit_alarm(self.device.id, new_alarm)
+        log.debug("[publish_alarm]")
\ No newline at end of file
diff --git a/voltha/adapters/microsemi_olt/OMCIProxy.py b/voltha/adapters/microsemi_olt/OMCIProxy.py
index 58efaf6..670b247 100644
--- a/voltha/adapters/microsemi_olt/OMCIProxy.py
+++ b/voltha/adapters/microsemi_olt/OMCIProxy.py
@@ -26,6 +26,14 @@
 from voltha.adapters.microsemi_olt.PAS5211_constants import PON_ENABLE, PON_TRUE
 from voltha.adapters.microsemi_olt.PAS5211_constants import PON_PORT_PON
 
+from voltha.adapters.microsemi_olt.PAS5211 import PAS5211MsgHeader, PAS5211MsgGetOltVersionResponse, PAS5211MsgGetOltVersionResponse
+
+from voltha.extensions.omci.omci_messages import OmciMibResetResponse
+
+from voltha.extensions.omci.omci_frame import OmciFrame
+
+import sys, gc
+
 log = structlog.get_logger()
 
 
@@ -40,6 +48,34 @@
         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()
+
+
+    def master_filter(self, pkt):
+        if not super(OMCIProxy, self).master_filter(pkt):
+            return False
+
+        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
+
+        if PAS5211MsgHeader in pkt:
+            if PAS5211MsgGetOltVersionResponse not in pkt:
+                if pkt[PAS5211MsgHeader].channel_id == self.proxy_address.channel_id:
+                    if pkt[PAS5211MsgHeader].onu_id == self.proxy_address.onu_id:
+                        # OMCI response
+                        if OmciFrame in pkt:
+                            if pkt[OmciFrame].message_type not in (16, 17):
+                                return True
+                        # # SendFrameResponse corresponding to OMCI PAS request
+                        elif PAS5211MsgSendFrameResponse in pkt:
+                            return True
+        return False
 
     """
     States
@@ -60,10 +96,12 @@
     @ATMT.state(error=1)
     def error(self, msg):
         log.error(msg)
+        raise self.end()
 
     @ATMT.state(final=1)
     def end(self):
-        pass
+        log.debug('omci-msg-end')
+        # pass
 
     """
     Utils
@@ -80,17 +118,19 @@
 
     @ATMT.condition(got_omci_msg)
     def send_omci_msg(self):
-        log.debug('send-omci-msg')
+        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)
-        to_send.show()
         self.send(to_send)
         raise self.wait_send_response()
 
     # Transitions from wait_send_response
-    @ATMT.timeout(wait_send_response, 3)
+    @ATMT.timeout(wait_send_response, 10)
     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))
 
     @ATMT.receive_condition(wait_send_response)
@@ -99,15 +139,25 @@
             raise self.wait_event()
 
     # Transitions from wait_event
-    @ATMT.timeout(wait_event, 3)
+    @ATMT.timeout(wait_event, 20)
     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))
 
     @ATMT.receive_condition(wait_event)
     def wait_for_event(self, pkt):
         if PAS5211EventFrameReceived in pkt:
+            log.debug("PAS5211EventFrameReceived")
             # FIXME we may need to verify the transaction id
             #  to make sure we have the right packet
-            self.adaptor_agent.recieve_proxied_message(self.proxy_address,
-                                                       pkt['PAS5211EventFrameReceived'])
+            # pkt.show()
+            # pkt['PAS5211EventFrameReceived'].show()
+            log.debug("rcv-omci-msg", proxy_address=self.proxy_address)
+            self.adaptor_agent.receive_proxied_message(self.proxy_address, pkt)
             raise self.end()
+
+    def __del__(self):
+        log.debug("OMCIProxy deleted")
+        super(OMCIProxy, self).__del__()
diff --git a/voltha/adapters/microsemi_olt/OltInstallFlowStateMachine.py b/voltha/adapters/microsemi_olt/OltInstallFlowStateMachine.py
new file mode 100644
index 0000000..c5a945b
--- /dev/null
+++ b/voltha/adapters/microsemi_olt/OltInstallFlowStateMachine.py
@@ -0,0 +1,658 @@
+#
+# Copyright 2017 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License")
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+Handles sequence of messages that are used to send OMCI to the ONU
+"""
+import structlog
+from scapy.automaton import ATMT
+
+from voltha.adapters.microsemi_olt.BaseOltAutomaton import BaseOltAutomaton
+from voltha.adapters.microsemi_olt.PAS5211 import PAS5211MsgSendFrame, PAS5211MsgGetOltVersionResponse, PAS5211MsgSendFrameResponse, \
+    PAS5211EventFrameReceived, PAS5211MsgHeader, PAS5211SetVlanGenConfigResponse
+
+from voltha.extensions.omci.omci_frame import OmciFrame
+
+from voltha.adapters.microsemi_olt.PAS5211 import PAS5211GetOnuAllocs, PAS5211GetOnuAllocsResponse, PAS5211GetSnInfo, \
+    PAS5211GetSnInfoResponse, PAS5211GetOnusRange, PAS5211GetOnusRangeResponse, PAS5211MsgSetOnuOmciPortId, \
+    PAS5211MsgSetOnuOmciPortIdResponse, PAS5211MsgSetOnuAllocId, PAS5211MsgSetOnuAllocIdResponse, \
+    PAS5211SetSVlanAtConfig, PAS5211SetSVlanAtConfigResponse, PAS5211SetVlanDownConfig, \
+    PAS5211SetVlanDownConfigResponse, PAS5211SetDownVlanHandl, PAS5211SetDownVlanHandlResponse, \
+    PAS5211SetUplinkVlanHandl, PAS5211SetDownstreamPolicingConfigResponse, PAS5211SetDownstreamPolicingConfig, \
+    PAS5211SetPortIdPolicingConfig, PAS5211UnsetPortIdPolicingConfig, \
+    PAS5211MsgSendDbaAlgorithmMsg, PAS5211MsgSendDbaAlgorithmMsgResponse, \
+    PAS5211SetUpstreamPolicingConfigResponse, PAS5211SetUpstreamPolicingConfig, \
+    PAS5211MsgSetPortIdConfig, PAS5211MsgSetPortIdConfigResponse, \
+    PAS5211MsgGetOnuIdByPortId, PAS5211MsgGetOnuIdByPortIdResponse, \
+    PAS5211SetVlanUplinkConfiguration, PAS5211SetVlanUplinkConfigurationResponse, PAS5211SetUplinkVlanHandlResponse, PAS5211SetVlanGenConfig, PAS5211SetVlanGenConfigResponse, \
+    PAS5211GetPortIdDownstreamPolicingConfig, PAS5211GetPortIdDownstreamPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfig, \
+    PAS5211MsgHeader, PAS5211UnsetPortIdPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfigResponse, \
+    PAS5211SetPortIdPolicingConfigResponse
+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, \
+    PON_OUTPUT_VLAN_PRIO_HANDLE_DL_VLAN_TABLE, PON_DL_VLAN_SVLAN_REMOVE, PON_DL_VLAN_CVLAN_NO_CHANGE, \
+    PON_VLAN_DEST_DATAPATH, GEM_DIR_BIDIRECT, OMCI_MAC_BRIDGE_PCD_LANFCS_FORWARDED, \
+    OMCI_MAC_BRIDGE_PCD_ENCAP_METHOD_LLC, OMCI_8021P_MSP_UNMARKED_FRAME_TAG_FRAME, OMCI_8021P_MSP_TP_TYPE_NULL, \
+    OMCI_EX_VLAN_TAG_OCD_ASSOCIATION_TYPE_PPTP_ETH_UNI, OMCI_EX_VLAN_TAG_OCD_DS_MODE_US_INVERSE, PMC_UPSTREAM_PORT, \
+    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
+
+from struct import pack, unpack
+    
+log = structlog.get_logger()
+
+
+class OltInstallFlowStateMachine(BaseOltAutomaton):
+
+    onu_id = None
+    channel_id = None
+    port_id = None
+    onu_session_id = None
+    alloc_id = None
+    policy_id = None
+
+    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')
+        self.onu_session_id = kwargs.pop('onu_session_id')
+        self.alloc_id = kwargs.pop('alloc_id')
+        self.svlan_id = kwargs.pop('svlan_id')
+        self.cvlan_id = kwargs.pop('cvlan_id')
+        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):
+
+        if not super(OltInstallFlowStateMachine, self).master_filter(pkt):
+            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
+
+        return False
+
+    """
+    States
+    """
+
+    # Uplink states...
+    @ATMT.state(initial=1)
+    def send_msg(self):
+        log.debug('olt-flow-state-machine-start')
+
+    @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
+
+    # Downlink states...
+    @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
+
+
+    @ATMT.state(error=1)
+    def error(self, msg):
+        log.error(msg)
+        raise self.end()
+
+
+    @ATMT.state(final=1)
+    def end(self):
+        log.debug('olt-flow-state-machine-end')
+        # pass
+
+    """
+    Utils
+    """
+
+    def px(self, pkt):
+        return self.p(pkt, channel_id=self.channel_id, 
+                onu_id=self.onu_id, 
+                onu_session_id=self.onu_session_id)
+
+    """
+    Transitions
+    """
+
+    @ATMT.condition(send_msg)
+    def install_flow(self):
+        log.debug("install-flow")
+        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)
+    def timeout_wait_gen_vlan_uplink_configuration_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_set_port_id_configuration_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_get_onu_id_by_port_id_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_send_dba_algorithm_msg_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_set_svlan_at_configuration_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_set_vlan_uplink_configuration_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_set_uplink_vlan_handling_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_set_gen_vlan_downlink_configuration_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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())) 
+
+    @ATMT.timeout(wait_set_vlan_downlink_configuration_response, 10)
+    def timeout_wait_set_vlan_downlink_configuration_response(self):
+        #log.debug('api-proxy-timeout')
+        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):
+        #log.debug('api-proxy-response')
+        if PAS5211SetVlanDownConfigResponse in pkt:
+            log.debug('[RESPONSE] PAS5211SetVlanDownConfigResponse')
+            self.send_set_downlink_vlan_handling(self.device.device, self.cvlan_id, self.svlan_id, self.port_id)
+            raise self.wait_set_downlink_vlan_handling_response()
+        else:
+            log.debug('Unexpected pkt {}'.format(pkt.summary()))
+
+    @ATMT.timeout(wait_set_downlink_vlan_handling_response, 10)
+    def timeout_wait_set_downlink_vlan_handling_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_get_port_id_downlink_policing_response(self):
+        #log.debug('api-proxy-timeout')
+        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):
+        #log.debug('api-proxy-response')
+        if PAS5211GetPortIdDownstreamPolicingConfigResponse in pkt:
+            log.debug('[RESPONSE] PAS5211GetPortIdDownstreamPolicingConfigResponse')
+            if pkt[PAS5211GetPortIdDownstreamPolicingConfigResponse].ds_policing_config_id != PMC_OFAL_NO_POLICY:
+                self.policy_id = pkt[PAS5211GetPortIdDownstreamPolicingConfigResponse].ds_policing_config_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:
+                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_unset_port_id_downlink_policing_response, 10)
+    def timeout_wait_unset_port_id_downlink_policing_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_remove_downlink_policing_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_set_downlink_policing_response(self):
+        #log.debug('api-proxy-timeout')
+        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")
+        else:
+            log.debug('Unexpected pkt {}'.format(pkt.summary()))
+    
+    @ATMT.timeout(wait_set_port_id_policing_response, 10)
+    def timeout_wait_set_port_id_policing_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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,
+            port_id=port_id,
+            activate=activate,
+            alloc_id=alloc_id,
+            type=PON_PORT_TYPE_GEM,
+            destination=PON_PORT_DESTINATION_CNI0
+        )
+        self.send(self.px(msg))
+        log.debug("[SENT] PASS_set_port_id_configuration")
+
+    def send_get_onu_id_by_port_id(self, device, port_id):
+        msg = PAS5211MsgGetOnuIdByPortId(
+                # port_id=1000 + device.proxy_address.onu_id
+                port_id=port_id
+
+            )
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211MsgGetOnuIdByPortId")
+
+    def send_set_gen_vlan_uplink_configuration(self, device):
+        # transmit "vlan uplink configuration port-id 1001 min-cos 0 max-cos 7
+        # de-bit disable primary-tag-handling true"
+
+        msg = PAS5211SetVlanGenConfig(
+            direction=0,
+            extended_svlan_type=33024,
+            insertion_svlan_ethertype=33024,
+            extended_cvlan_type=33024,
+            insertion_cvlan_ethertype=33024,
+            pon_pcp_code=3,
+            cni_pcp_code=3,
+            reserved=0,
+        )
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211SetVlanGenConfig")
+
+    def send_set_gen_vlan_downlink_configuration(self, device):
+        # transmit "vlan uplink configuration port-id 1001 min-cos 0 max-cos 7
+        # de-bit disable primary-tag-handling true"
+
+        msg = PAS5211SetVlanGenConfig(
+            direction=1,
+            extended_svlan_type=33024,
+            insertion_svlan_ethertype=33024,
+            extended_cvlan_type=33024,
+            insertion_cvlan_ethertype=33024,
+            pon_pcp_code=3,
+            cni_pcp_code=3,
+            reserved=0,
+        )
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211SetVlanGenConfig")
+
+    def send_set_vlan_uplink_configuration(self, device, port_id):
+        # transmit "vlan uplink configuration port-id 1001 min-cos 0 max-cos 7
+        # de-bit disable primary-tag-handling true"
+
+        msg = PAS5211SetVlanUplinkConfiguration(
+            # port_id=(1000 + device.proxy_address.onu_id),
+            port_id = port_id,
+            pvid_config_enabled=PON_TRUE,
+            # Enables handling of primary tag in addition to the port-id at
+            # uplink frames
+            min_cos=0,  # The lower limit of the priority uplink frame from the specific Port Id can get
+            max_cos=7,  # The upper limit of the priority uplink frame from the specific Port Id can get
+            de_bit=PON_DISABLE  # Discard Eligibility (DE) enabled
+        )
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211SetVlanUplinkConfiguration")
+
+    def send_set_uplink_vlan_handling(self, device, port_id, cvlan_id, svlan_id):
+
+        # if (ul_vlan_key->primary_vid == PON_VLAN_UNUSED_TAG)
+        #    set_uplink_vlan_handling_msg.pvid_config_enabled = PON_FALSE;
+        # else
+        # {
+        #    set_uplink_vlan_handling_msg.pvid_config_enabled = PON_TRUE;
+        #    set_uplink_vlan_handling_msg.primary_vid      = ul_vlan_key->primary_vid;
+        # }
+        primary_vid = 0  # TODO change
+        # self.port_id = (1000 + device.proxy_address.onu_id)  # TODO change
+        if cvlan_id == PON_VLAN_UNUSED_TAG:
+            pvid_config_enabled = PON_FALSE
+        else:
+            pvid_config_enabled = PON_TRUE
+            primary_vid = cvlan_id
+
+        msg = PAS5211SetUplinkVlanHandl(
+            source_port_id=port_id,
+            primary_vid=primary_vid,  # The primary VLAN tag of the uplink frame
+            pvid_config_enabled=pvid_config_enabled,
+            svlan_tag_operation=PON_VLAN_CHANGE_TAG,
+            cvlan_tag_operation=PON_VLAN_DONT_CHANGE_TAG,  # Customer tag = new C-VLAN tag
+            new_svlan_tag=svlan_id,  # Service tag to be added or replace, not relevant
+            new_cvlan_tag=0,  # Customer tag to be added or replace, not relevant
+            destination=PON_VLAN_DEST_DATAPATH  # Frames go to the CNI
+        )
+
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211SetUplinkVlanHandl")
+
+    def send_set_svlan_at_configuration(self, device, svlan_id):
+
+        msg = PAS5211SetSVlanAtConfig(
+            svlan_id=svlan_id,  # 9
+            # 1 1:1 VLAN mode is used, no address table
+            forwarding_mode=PON_1_TO_1_VLAN_MODE,
+            use_svlan=PON_FALSE,  # Use S-VLAN as part of the address table key
+            use_cvlan=PON_FALSE,  # Use C-VLAN as part of the address table key
+            use_pbits=PON_FALSE,  # Use priority bits as part of the address table key
+            discard_unknown=PON_FALSE  # Forward frames
+        )
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211SetSVlanAtConfig")
+
+    def send_set_vlan_downlink_configuration(self, device, svlan_id):
+        msg = PAS5211SetVlanDownConfig(
+            svlan_id=svlan_id,  # 9
+            double_tag_handling=PON_TRUE,  # Enable handling according to double tag
+            vlan_priority_handling=PON_TRUE  # Use VLAN priority at the downlink VLAN table key
+        )
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211SetVlanDownConfig")
+
+    def send_get_port_id_downlink_policing(self, device, port_id):
+        msg = PAS5211GetPortIdDownstreamPolicingConfig(port_id=port_id)
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211GetPortIdDownstreamPolicingConfig")
+
+    def send_remove_downlink_policing(self, device, policy_id):
+        msg = PAS5211RemoveDownstreamPolicingConfig(
+            policing_config_id=policy_id,
+            reserved=0)
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211RemoveDownstreamPolicingConfig")
+
+    def send_unset_port_id_downlink_policing(self, device, dir, port_id):
+        msg = PAS5211UnsetPortIdPolicingConfig(direction=dir, port_id=port_id)
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211UnsetPortIdPolicingConfig")
+
+    def send_set_downlink_policing(self, device, bandwidth):
+        msg = PAS5211SetDownstreamPolicingConfig(
+            committed_bandwidth = SLA_gr_bw_gros*1024,
+            excessive_bandwidth = (bandwidth - SLA_gr_bw_gros)*1024,
+            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, 
+            policing_config_id=policy_id,
+            reserved=0)
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211SetPortIdPolicingConfig")
+
+    def send_send_dba_algorithm_msg(self, device, port_id, bandwidth):
+        alloc_id = []
+        mx_bw = []
+        gr_bw = []
+
+        data = pack('<LLHHBBBB', PYTHAGORAS_UPDATE_AID_SLA,
+            port_id, SLA_gr_bw_gros, bandwidth,
+            SLA_gr_bw_fine, SLA_be_bw_fine, PYTHAGORAS_DBA_DATA_COS,
+            PYTHAGORAS_DBA_STATUS_REPORT_NSR)
+
+        msg = PAS5211MsgSendDbaAlgorithmMsg(data= data)
+
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211MsgSendDbaAlgorithmMsg")
+
+    def send_set_downlink_vlan_handling(self, device, cvlan_id, svlan_id, port_id):
+        cvlan_tag = 0
+        svlan_tag = svlan_id
+        if cvlan_id == PON_VLAN_UNUSED_TAG:
+            double_tag_handling = PON_FALSE
+        else:
+            double_tag_handling = PON_TRUE
+            cvlan_tag = cvlan_id
+
+        input_priority = 0  # TODO: Extract value from somewhere
+
+        if input_priority == PON_VLAN_UNUSED_PRIORITY:
+            priority_handling = PON_FALSE
+        else:
+            priority_handling = PON_TRUE
+
+        output_priority = 0  # TODO: Extract value from somewhere
+
+        if output_priority == PON_VLAN_REPLACE_PRIORITY:
+            output_vlan_prio_handle = PON_OUTPUT_VLAN_PRIO_HANDLE_INCOMING_VLAN
+            output_priority = 0
+        elif output_priority == PON_VLAN_UNCHANGED_PRIORITY:
+            output_vlan_prio_handle = PON_OUTPUT_VLAN_PRIO_HANDLE_DONT_CHANGE
+            output_priority = 0
+        else:
+            output_vlan_prio_handle = PON_OUTPUT_VLAN_PRIO_HANDLE_DL_VLAN_TABLE
+
+        msg = PAS5211SetDownVlanHandl(
+            svlan_tag=svlan_tag,
+            cvlan_tag=cvlan_tag,  # Original downlink frame with this C-tag ID
+            double_tag_handling=PON_TRUE,
+            priority_handling=PON_FALSE,
+            input_priority=1,  # From traces # S-VLAN priority field
+            # Don't change original frame service tag
+            svlan_tag_operation=PON_DL_VLAN_SVLAN_REMOVE,
+            cvlan_tag_operation=PON_DL_VLAN_CVLAN_NO_CHANGE,  # Customer tag = new C-VLAN tag
+            # port_id=(1000 + device.proxy_address.onu_id),
+            port_id=port_id,
+            # GEM port-id destination of the downlink frame. It is used when
+            # the MAC destination address (DA) is a broadcast address
+            new_cvlan_tag=cvlan_tag,  # Same as cvlan_tag
+            # From traces PON_VLAN_DEST_DATAPATH,  # Frames go to the PON
+            destination=PON_VLAN_DEST_DATAPATH,
+            output_vlan_prio_handle=PON_OUTPUT_VLAN_PRIO_HANDLE_DONT_CHANGE,
+            output_priority=1  # New VLAN priority value
+        )
+        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
new file mode 100644
index 0000000..dfc5601
--- /dev/null
+++ b/voltha/adapters/microsemi_olt/OltReinstallFlowStateMachine.py
@@ -0,0 +1,78 @@
+#
+# Copyright 2017 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+Handles sequence of messages that are used to send OMCI to the ONU
+"""
+import structlog
+from scapy.automaton import ATMT
+
+from voltha.adapters.microsemi_olt.BaseOltAutomaton import BaseOltAutomaton
+from voltha.adapters.microsemi_olt.PAS5211 import PAS5211MsgSendFrame, PAS5211MsgGetOltVersionResponse, PAS5211MsgSendFrameResponse, \
+    PAS5211EventFrameReceived, PAS5211MsgHeader, PAS5211SetVlanGenConfigResponse
+
+from voltha.extensions.omci.omci_frame import OmciFrame
+
+from voltha.adapters.microsemi_olt.OltInstallFlowStateMachine import OltInstallFlowStateMachine
+from voltha.adapters.microsemi_olt.OltRemoveFlowStateMachine import OltRemoveFlowStateMachine
+
+from voltha.adapters.microsemi_olt.PAS5211 import PAS5211GetOnuAllocs, PAS5211GetOnuAllocsResponse, PAS5211GetSnInfo, \
+    PAS5211GetSnInfoResponse, PAS5211GetOnusRange, PAS5211GetOnusRangeResponse, PAS5211MsgSetOnuOmciPortId, \
+    PAS5211MsgSetOnuOmciPortIdResponse, PAS5211MsgSetOnuAllocId, PAS5211MsgSetOnuAllocIdResponse, \
+    PAS5211SetSVlanAtConfig, PAS5211SetSVlanAtConfigResponse, PAS5211SetVlanDownConfig, \
+    PAS5211SetVlanDownConfigResponse, PAS5211SetDownVlanHandl, PAS5211SetDownVlanHandlResponse, \
+    PAS5211SetUplinkVlanHandl, PAS5211SetDownstreamPolicingConfigResponse, PAS5211SetDownstreamPolicingConfig, \
+    PAS5211SetPortIdPolicingConfig, PAS5211UnsetPortIdPolicingConfig, \
+    PAS5211MsgSendDbaAlgorithmMsg, PAS5211MsgSendDbaAlgorithmMsgResponse, \
+    PAS5211SetUpstreamPolicingConfigResponse, PAS5211SetUpstreamPolicingConfig, \
+    PAS5211MsgSetPortIdConfig, PAS5211MsgSetPortIdConfigResponse, \
+    PAS5211MsgGetOnuIdByPortId, PAS5211MsgGetOnuIdByPortIdResponse, \
+    PAS5211SetVlanUplinkConfiguration, PAS5211SetVlanUplinkConfigurationResponse, PAS5211SetUplinkVlanHandlResponse, PAS5211SetVlanGenConfig, PAS5211SetVlanGenConfigResponse, \
+    PAS5211GetPortIdDownstreamPolicingConfig, PAS5211GetPortIdDownstreamPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfig, \
+    PAS5211MsgHeader, PAS5211UnsetPortIdPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfigResponse, \
+    PAS5211SetPortIdPolicingConfigResponse
+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, \
+    PON_OUTPUT_VLAN_PRIO_HANDLE_DL_VLAN_TABLE, PON_DL_VLAN_SVLAN_REMOVE, PON_DL_VLAN_CVLAN_NO_CHANGE, \
+    PON_VLAN_DEST_DATAPATH, GEM_DIR_BIDIRECT, OMCI_MAC_BRIDGE_PCD_LANFCS_FORWARDED, \
+    OMCI_MAC_BRIDGE_PCD_ENCAP_METHOD_LLC, OMCI_8021P_MSP_UNMARKED_FRAME_TAG_FRAME, OMCI_8021P_MSP_TP_TYPE_NULL, \
+    OMCI_EX_VLAN_TAG_OCD_ASSOCIATION_TYPE_PPTP_ETH_UNI, OMCI_EX_VLAN_TAG_OCD_DS_MODE_US_INVERSE, PMC_UPSTREAM_PORT, \
+    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()
+
+
+class OltReinstallFlowStateMachine(OltInstallFlowStateMachine):
+        
+    @ATMT.state()
+    def wait_set_port_id_configuration_response(self):
+        pass
+
+    @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: 
+            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)    
+            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
new file mode 100644
index 0000000..44bbe96
--- /dev/null
+++ b/voltha/adapters/microsemi_olt/OltRemoveFlowStateMachine.py
@@ -0,0 +1,222 @@
+#
+# Copyright 2017 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+Handles sequence of messages that are used to send OMCI to the ONU
+"""
+import structlog
+from scapy.automaton import ATMT
+
+from voltha.adapters.microsemi_olt.BaseOltAutomaton import BaseOltAutomaton
+from voltha.adapters.microsemi_olt.PAS5211 import PAS5211MsgSendFrame, PAS5211MsgGetOltVersionResponse, PAS5211MsgSendFrameResponse, \
+    PAS5211EventFrameReceived, PAS5211MsgHeader, PAS5211SetVlanGenConfigResponse
+
+from voltha.extensions.omci.omci_frame import OmciFrame
+
+from voltha.adapters.microsemi_olt.PAS5211 import PAS5211GetOnuAllocs, PAS5211GetOnuAllocsResponse, PAS5211GetSnInfo, \
+    PAS5211GetSnInfoResponse, PAS5211GetOnusRange, PAS5211GetOnusRangeResponse, PAS5211MsgSetOnuOmciPortId, \
+    PAS5211MsgSetOnuOmciPortIdResponse, PAS5211MsgSetOnuAllocId, PAS5211MsgSetOnuAllocIdResponse, \
+    PAS5211SetSVlanAtConfig, PAS5211SetSVlanAtConfigResponse, PAS5211SetVlanDownConfig, \
+    PAS5211SetVlanDownConfigResponse, PAS5211SetDownVlanHandl, PAS5211SetDownVlanHandlResponse, \
+    PAS5211SetUplinkVlanHandl, PAS5211SetDownstreamPolicingConfigResponse, PAS5211SetDownstreamPolicingConfig, \
+    PAS5211SetPortIdPolicingConfig, PAS5211UnsetPortIdPolicingConfig, \
+    PAS5211MsgSendDbaAlgorithmMsg, PAS5211MsgSendDbaAlgorithmMsgResponse, \
+    PAS5211SetUpstreamPolicingConfigResponse, PAS5211SetUpstreamPolicingConfig, \
+    PAS5211MsgSetPortIdConfig, PAS5211MsgSetPortIdConfigResponse, \
+    PAS5211MsgGetOnuIdByPortId, PAS5211MsgGetOnuIdByPortIdResponse, \
+    PAS5211SetVlanUplinkConfiguration, PAS5211SetVlanUplinkConfigurationResponse, PAS5211SetUplinkVlanHandlResponse, PAS5211SetVlanGenConfig, PAS5211SetVlanGenConfigResponse, \
+    PAS5211GetPortIdDownstreamPolicingConfig, PAS5211GetPortIdDownstreamPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfig, \
+    PAS5211MsgHeader, PAS5211UnsetPortIdPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfigResponse, \
+    PAS5211SetPortIdPolicingConfigResponse
+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, \
+    PON_OUTPUT_VLAN_PRIO_HANDLE_DL_VLAN_TABLE, PON_DL_VLAN_SVLAN_REMOVE, PON_DL_VLAN_CVLAN_NO_CHANGE, \
+    PON_VLAN_DEST_DATAPATH, GEM_DIR_BIDIRECT, OMCI_MAC_BRIDGE_PCD_LANFCS_FORWARDED, \
+    OMCI_MAC_BRIDGE_PCD_ENCAP_METHOD_LLC, OMCI_8021P_MSP_UNMARKED_FRAME_TAG_FRAME, OMCI_8021P_MSP_TP_TYPE_NULL, \
+    OMCI_EX_VLAN_TAG_OCD_ASSOCIATION_TYPE_PPTP_ETH_UNI, OMCI_EX_VLAN_TAG_OCD_DS_MODE_US_INVERSE, PMC_UPSTREAM_PORT, \
+    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()
+
+
+class OltRemoveFlowStateMachine(BaseOltAutomaton):
+
+    onu_id = None
+    channel_id = None
+    port_id = None
+    onu_session_id = None
+    alloc_id = None
+    policy_id = None
+
+    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')
+        self.onu_session_id = kwargs.pop('onu_session_id')
+        self.alloc_id = kwargs.pop('alloc_id')
+
+        BaseOltAutomaton.parse_args(self, debug=debug, store=store, **kwargs)
+
+
+    def master_filter(self, pkt):
+
+        if not super(OltRemoveFlowStateMachine, self).master_filter(pkt):
+            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
+
+        return False
+
+    """
+    States
+    """
+
+    # Uplink states...
+    @ATMT.state(initial=1)
+    def send_msg(self):
+        log.debug('olt-flow-state-machine-start')
+
+    @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_unset_port_id_downlink_policing_response(self):
+        pass
+
+
+    @ATMT.state(error=1)
+    def error(self, msg):
+        log.error(msg)
+        raise self.end()
+
+
+    @ATMT.state(final=1)
+    def end(self):
+        log.debug('olt-flow-state-machine-end')
+        # pass
+
+    """
+    Utils
+    """
+
+    def px(self, pkt):
+        return self.p(pkt, channel_id=self.channel_id, 
+            onu_id=self.onu_id, 
+            onu_session_id=self.onu_session_id)
+
+    """
+    Transitions
+    """
+
+    @ATMT.condition(send_msg)
+    def remove_flow(self):
+        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")
+
+    @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:
+            log.debug('[RESPONSE] PAS5211MsgGetOnuIdByPortIdResponse')
+            self.send_unset_port_id_downlink_policing(self.device.device, 1, self.port_id)
+            raise self.wait_unset_port_id_downlink_policing_response()
+        else:
+            log.debug('Unexpected pkt {}'.format(pkt.summary()))
+
+    @ATMT.timeout(wait_unset_port_id_downlink_policing_response, 10)
+    def timeout_wait_unset_port_id_downlink_policing_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            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)
+    def timeout_wait_set_port_id_configuration_response(self):
+        #log.debug('api-proxy-timeout')
+        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: 
+            log.debug('[RESPONSE] PAS5211MsgSetPortIdConfigResponse')
+            self.end()
+        else:
+            log.debug('Unexpected pkt {}'.format(pkt.summary()))
+
+
+
+    """ -   -   -   -   -   -   -   create_double_vlan_flow_olt_config   -   -   -   -   -   -   - """
+
+
+    def send_set_port_id_configuration(self, device, activate, port_id, alloc_id):
+        msg = PAS5211MsgSetPortIdConfig(
+            # port_id=1000 + device.proxy_address.onu_id,
+            port_id=port_id,
+            activate=activate,
+            alloc_id=alloc_id,
+            type=PON_PORT_TYPE_GEM,
+            destination=PON_PORT_DESTINATION_CNI0
+        )
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211MsgSetPortIdConfig")
+
+    def send_get_onu_id_by_port_id(self, device, port_id):
+        msg = PAS5211MsgGetOnuIdByPortId(
+                # port_id=1000 + device.proxy_address.onu_id
+                port_id=port_id
+
+            )
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211MsgGetOnuIdByPortId")
+
+
+    def send_unset_port_id_downlink_policing(self, device, dir, port_id):
+        msg = PAS5211UnsetPortIdPolicingConfig(direction=dir, port_id=port_id)
+        self.send(self.px(msg))
+        log.debug("[SENT] PAS5211UnsetPortIdPolicingConfig")
+
+
+    """ -   -   -   -   -   -   -  END create_double_vlan_flow_olt_config   -   -   -   -   -   -   - """
diff --git a/voltha/adapters/microsemi_olt/OltStateMachine.py b/voltha/adapters/microsemi_olt/OltStateMachine.py
index 4a43332..57a2d57 100644
--- a/voltha/adapters/microsemi_olt/OltStateMachine.py
+++ b/voltha/adapters/microsemi_olt/OltStateMachine.py
@@ -19,17 +19,19 @@
 from voltha.adapters.microsemi_olt.PAS5211 import PAS5211MsgGetProtocolVersion, PAS5211MsgGetOltVersion, \
     PAS5211MsgGetOltVersionResponse, PAS5211MsgGetProtocolVersionResponse, \
     SnrBurstDelay, RngBurstDelay, GeneralOpticsParams, ResetValues, ResetTimingCtrl, PreambleParams, \
-    PAS5211MsgSetOltOpticsResponse, CHANNELS, PAS5211MsgSetOpticsIoControlResponse, PAS5211MsgGetGeneralParamResponse, PAS5211MsgAddOltChannel, \
+    PAS5211MsgSetOltOpticsResponse, CHANNELS, PAS5211MsgSetOpticsIoControlResponse, PAS5211MsgGetGeneralParamResponse, \
+    PAS5211MsgAddOltChannel, \
     PAS5211MsgAddOltChannelResponse, PAS5211MsgSetAlarmConfigResponse, PAS5211MsgGetDbaMode, \
     PAS5211MsgGetDbaModeResponse, PAS5211MsgStartDbaAlgorithm, \
-    PAS5211MsgStartDbaAlgorithmResponse,  PAS5211MsgSetOltChannelActivationPeriod, \
-    PAS5211MsgSetOltChannelActivationPeriodResponse
-from voltha.adapters.microsemi_olt.PAS5211_constants import PON_OPTICS_VOLTAGE_IF_LVPECL, PON_ENABLE, PON_POLARITY_ACTIVE_HIGH, \
+    PAS5211MsgStartDbaAlgorithmResponse, PAS5211MsgSetOltChannelActivationPeriod, \
+    PAS5211MsgSetOltChannelActivationPeriodResponse, PAS5211MsgHeader, PAS5211Event, PAS5211EventAlarmNotification
+from voltha.adapters.microsemi_olt.PAS5211_constants import PON_OPTICS_VOLTAGE_IF_LVPECL, PON_ENABLE, \
+    PON_POLARITY_ACTIVE_HIGH, PASCOMM_RETRIES, \
     PON_SD_SOURCE_LASER_SD, PON_RESET_TYPE_DELAY_BASED, PON_DISABLE, PON_RESET_TYPE_NORMAL_START_BURST_BASED, \
-    PON_TX_ENABLE_DEFAULT, PON_ALARM_LOS,  PON_DBA_MODE_LOADED_NOT_RUNNING,  PON_DBA_MODE_RUNNING
+    PON_TX_ENABLE_DEFAULT, PON_ALARM_LOS, PON_DBA_MODE_LOADED_NOT_RUNNING, PON_DBA_MODE_RUNNING
 from voltha.adapters.microsemi_olt.PAS5211_utils import general_param, olt_optics_pkt, burst_timing, io_ctrl_optics, \
     alarm_config
-
+from voltha.extensions.omci.omci_frame import OmciFrame
 import structlog
 
 from voltha.protos.common_pb2 import ConnectStatus
@@ -38,17 +40,34 @@
 
 
 class OltStateMachine(BaseOltAutomaton):
-
     send_state = []
     dba_needs_start = False
+    retry = 10
 
     def check_channel_state(self):
         for i in CHANNELS:
-                if not self.send_state[i]:
-                    return False
+            if not self.send_state[i]:
+                return False
         self.send_state = []
         return True
 
+    def master_filter(self, pkt):
+
+        if not super(OltStateMachine, self).master_filter(pkt):
+            return False
+
+        if OmciFrame in pkt:
+            log.debug("OMCI-message-type: {}".format(pkt[OmciFrame].message_type))
+            return False
+        
+        if PAS5211Event in pkt:
+            return False
+
+        if PAS5211EventAlarmNotification in pkt:
+            return False
+
+        return True
+
     """
     States
     """
@@ -133,17 +152,18 @@
     def wait_activation(self):
         pass
 
-    @ATMT.state()
-    def initialized(self):
-        pass
-
-    @ATMT.state()
-    def wait_keepalive(self):
-        pass
+    @ATMT.state(final=1)
+    def end(self):
+        log.debug('OLT state machine ended')
+    #
+    # @ATMT.state()
+    # def wait_keepalive(self):
+    #     pass
 
     @ATMT.state(error=1)
-    def ERROR(self):
-        pass
+    def error(self):
+        raise self.end()
+        # pass
 
     """
     Transitions
@@ -156,13 +176,13 @@
         raise self.wait_for_proto_version()
 
     # Transitions from wait_for_proto_version
-    @ATMT.timeout(wait_for_proto_version, 1)
+    @ATMT.timeout(wait_for_proto_version, 3)
     def timeout_proto(self):
-        log.info("Timed out waiting for proto version")
+        log.debug("Timed out waiting for proto version")
         self.retry -= 1
         if self.retry < 0:
-            log.debug("Too many retries, aborting.")
-            raise self.ERROR()
+            log.error("Too many retries, aborting.")
+            raise self.error()
         raise self.disconnected()
 
     @ATMT.receive_condition(wait_for_proto_version)
@@ -171,35 +191,41 @@
         if PAS5211MsgGetProtocolVersionResponse in pkt:
             raise self.got_proto_version()
         else:
-            log.error("Got garbage packet {}".format(pkt))
-            raise self.ERROR()
+            log.error("Got garbage packet: {}".format(pkt.summary()))
+            self.retry -= 1
+            if self.retry < 0:
+                log.error("Too many retries, aborting.")
+                raise self.error()
+            else:
+                raise self.wait_for_proto_version()
 
     # Transitions from got_proto_version
     @ATMT.condition(got_proto_version)
     def send_olt_version(self):
         self.send(self.p(PAS5211MsgGetOltVersion()))
+        log.debug("[SENT] PAS5211MsgGetOltVersion")
         raise self.wait_for_olt_version()
 
     # Transitions from waiting for olt version
-    @ATMT.timeout(wait_for_olt_version, 1)
+    @ATMT.timeout(wait_for_olt_version, 3)
     def timeout_olt(self):
         log.debug("Timed out waiting for olt version")
         self.retry -= 1
         if self.retry < 0:
-            log.debug("Too many retries, aborting.")
-            raise self.ERROR()
+            log.error("Too many retries, aborting.")
+            raise self.error()
         raise self.disconnected()
 
     @ATMT.receive_condition(wait_for_olt_version)
     def receive_olt_version(self, pkt):
         log.debug("Received proto version")
         if PAS5211MsgGetOltVersionResponse in pkt:
-            log.info("updating device")
+            log.debug("[RESPONSE] PAS5211MsgGetOltVersion")
             self.device.update_device_info_from_pkt(pkt)
             raise self.got_olt_version()
         else:
             log.error("Got garbage packet {}".format(pkt))
-            raise self.ERROR()
+            raise self.error()
 
     # Transitions from got_olt_version
     @ATMT.condition(got_olt_version)
@@ -212,7 +238,8 @@
         general_optics_param = GeneralOpticsParams(laser_reset_polarity=PON_POLARITY_ACTIVE_HIGH,
                                                    laser_sd_polarity=PON_POLARITY_ACTIVE_HIGH,
                                                    sd_source=PON_SD_SOURCE_LASER_SD, sd_hold_snr_ranging=PON_DISABLE,
-                                                   sd_hold_normal=PON_DISABLE, reset_type_snr_ranging=PON_RESET_TYPE_DELAY_BASED,
+                                                   sd_hold_normal=PON_DISABLE,
+                                                   reset_type_snr_ranging=PON_RESET_TYPE_DELAY_BASED,
                                                    reset_type_normal=PON_RESET_TYPE_NORMAL_START_BURST_BASED,
                                                    laser_reset_enable=PON_ENABLE)
 
@@ -221,21 +248,21 @@
                                                              laser_reset_d2=2,
                                                              laser_reset_d1=5),
                                 reset_snr_burst=ResetValues(bcdr_reset_d2=2,
-                                                             bcdr_reset_d1=9,
-                                                             laser_reset_d2=2,
-                                                             laser_reset_d1=1),
+                                                            bcdr_reset_d1=9,
+                                                            laser_reset_d2=2,
+                                                            laser_reset_d1=1),
                                 reset_rng_burst=ResetValues(bcdr_reset_d2=2,
-                                                             bcdr_reset_d1=9,
-                                                             laser_reset_d2=2,
-                                                             laser_reset_d1=1),
+                                                            bcdr_reset_d1=9,
+                                                            laser_reset_d2=2,
+                                                            laser_reset_d1=1),
                                 single_reset=ResetValues(bcdr_reset_d2=1,
-                                                             bcdr_reset_d1=1,
-                                                             laser_reset_d2=1,
-                                                             laser_reset_d1=1),
+                                                         bcdr_reset_d1=1,
+                                                         laser_reset_d2=1,
+                                                         laser_reset_d1=1),
                                 double_reset=ResetValues(bcdr_reset_d2=1,
-                                                             bcdr_reset_d1=1,
-                                                             laser_reset_d2=1,
-                                                             laser_reset_d1=1))
+                                                         bcdr_reset_d1=1,
+                                                         laser_reset_d2=1,
+                                                         laser_reset_d1=1))
 
         preamble = PreambleParams(correlation_preamble_length=8, preamble_length_snr_rng=119,
                                   guard_time_data_mode=32, type1_size_data=0,
@@ -245,15 +272,16 @@
                                   delimiter_byte3=131)
 
         olt_optics = olt_optics_pkt(PON_OPTICS_VOLTAGE_IF_LVPECL, burst=burst_timing(1, 1,
-                                                    snr_burst=snr_burst_delay,
-                                                    rng_burst=rng_burst_delay),
-                                 general=general_optics_param,
-                                 reset=reset,
-                                 preamble=preamble)
+                                                                                     snr_burst=snr_burst_delay,
+                                                                                     rng_burst=rng_burst_delay),
+                                    general=general_optics_param,
+                                    reset=reset,
+                                    preamble=preamble)
 
         for id in CHANNELS:
             self.send_state.append(False)
             self.send(self.p(olt_optics, channel_id=id))
+            log.debug("[SENT] PAS5211MsgSetOltOptics")
 
         raise self.wait_olt_optics()
 
@@ -261,11 +289,12 @@
     @ATMT.timeout(wait_olt_optics, 3)
     def olt_optics_timeout(self):
         log.error("Setting olt optics failed; disconnecting")
-        raise self.ERROR()
+        raise self.error()
 
     @ATMT.receive_condition(wait_olt_optics)
     def receive_set_optics_response(self, pkt):
         if PAS5211MsgSetOltOpticsResponse in pkt:
+            log.debug("[RESPONSE] PAS5211MsgSetOltOptics")
             self.send_state[pkt.channel_id] = True
             if self.check_channel_state():
                 raise self.got_olt_optics()
@@ -278,18 +307,22 @@
         pkt = io_ctrl_optics(1, 0, 6, 14)
         self.send_state.append(False)
         self.send(self.p(pkt, channel_id=0))
+        log.debug("[SENT] PAS5211MsgSetOpticsIoControl")
 
         pkt = io_ctrl_optics(3, 2, 7, 15)
         self.send_state.append(False)
         self.send(self.p(pkt, channel_id=1))
+        log.debug("[SENT] PAS5211MsgSetOpticsIoControl")
 
         pkt = io_ctrl_optics(11, 10, 8, 16)
         self.send_state.append(False)
         self.send(self.p(pkt, channel_id=2))
+        log.debug("[SENT] PAS5211MsgSetOpticsIoControl")
 
         pkt = io_ctrl_optics(13, 12, 9, 17)
         self.send_state.append(False)
         self.send(self.p(pkt, channel_id=3))
+        log.debug("[SENT] PAS5211MsgSetOpticsIoControl")
 
         raise self.wait_olt_io_optics()
 
@@ -297,11 +330,12 @@
     @ATMT.timeout(wait_olt_io_optics, 3)
     def olt_io_optics_timeout(self):
         log.error("Setting olt io optics failed; disconnecting")
-        raise self.ERROR()
+        raise self.error()
 
     @ATMT.receive_condition(wait_olt_io_optics)
     def receive_io_optics_response(self, pkt):
         if PAS5211MsgSetOpticsIoControlResponse in pkt:
+            log.debug("[RESPONSE] PAS5211MsgSetOpticsIoControl")
             self.send_state[pkt.channel_id] = True
             if self.check_channel_state():
                 raise self.got_olt_io_optics()
@@ -314,6 +348,7 @@
         for id in CHANNELS:
             self.send_state.append(False)
             self.send(self.p(query, channel_id=id))
+            log.debug("[SENT] PAS5211MsgGetGeneralParam")
 
         raise self.wait_query_response()
 
@@ -321,11 +356,12 @@
     @ATMT.timeout(wait_query_response, 3)
     def query_timeout(self):
         log.error("Our queries have gone unanswered; disconnecting")
-        raise self.ERROR()
+        raise self.error()
 
     @ATMT.receive_condition(wait_query_response)
     def check_pon_tx_state(self, pkt):
         if PAS5211MsgGetGeneralParamResponse in pkt:
+            log.debug("[RESPONSE] PAS5211MsgGetGeneralParam")
             self.send_state[pkt.channel_id] = True
             if pkt.value == PON_ENABLE:
                 # TODO: we may want to do something here.
@@ -335,7 +371,7 @@
                     raise self.wait_query_response()
             else:
                 log.error("TX downstream is not enabled")
-                raise self.ERROR()
+                raise self.error()
 
     # Transitions from got_query_response
     @ATMT.condition(wait_query_response)
@@ -344,17 +380,19 @@
         for id in CHANNELS:
             self.send_state.append(False)
             self.send(self.p(olt_add, channel_id=id))
+            log.debug("[SENT] PAS5211MsgAddOltChannel")
         raise self.wait_olt_add()
 
     # Transitions from wait_olt_add
     @ATMT.timeout(wait_olt_add, 3)
     def olt_add_timeout(self):
         log.error("Cannot add olts; disconnecting")
-        raise self.ERROR()
+        raise self.error()
 
     @ATMT.receive_condition(wait_olt_add)
     def wait_for_olt_add(self, pkt):
         if PAS5211MsgAddOltChannelResponse in pkt:
+            log.debug("[RESPONSE] PAS5211MsgAddOltChannel")
             self.send_state[pkt.channel_id] = True
             if self.check_channel_state():
                 raise self.got_olt_add()
@@ -367,17 +405,19 @@
         for id in CHANNELS:
             self.send_state.append(False)
             self.send(self.p(alarm_msg, channel_id=id))
+            log.debug("[SENT] PAS5211MsgSetAlarmConfig")
         raise self.wait_alarm_set()
 
     # Transitions for wait_alarm_set
     @ATMT.timeout(wait_alarm_set, 3)
     def alarm_timeout(self):
         log.error("Couldn't set alarms; disconnecting")
-        raise self.ERROR()
+        raise self.error()
 
     @ATMT.receive_condition(wait_alarm_set)
     def wait_for_alarm_set(self, pkt):
         if PAS5211MsgSetAlarmConfigResponse in pkt:
+            log.debug("[RESPONSE] PAS5211MsgSetAlarmConfig")
             self.send_state[pkt.channel_id] = True
             if self.check_channel_state():
                 raise self.got_alarm_set()
@@ -390,19 +430,21 @@
         for id in CHANNELS:
             self.send_state.append(False)
             self.send(self.p(get_dba_mode, channel_id=id))
+            log.debug("[SENT] PAS5211MsgGetDbaMode")
+
         raise self.wait_dba_mode()
 
     # Transitions from wait_dba_mode
     @ATMT.timeout(wait_dba_mode, 3)
     def dba_timeout(self):
         log.error("No DBA information returned; disconnecting")
-        raise self.ERROR()
-
+        raise self.error()
 
     @ATMT.receive_condition(wait_dba_mode)
     def wait_for_dba_mode(self, pkt):
 
         if PAS5211MsgGetDbaModeResponse in pkt:
+            log.debug("[RESPONSE] PAS5211MsgGetDbaMode")
             # TODO: What do we do in case the DBA is not loaded.
             if pkt.dba_mode == PON_DBA_MODE_LOADED_NOT_RUNNING:
                 self.send_state[pkt.channel_id] = True
@@ -419,21 +461,24 @@
     # Transition from got_dba_mode
     @ATMT.condition(got_dba_mode)
     def send_start_dba(self):
-        dba_start = PAS5211MsgStartDbaAlgorithm(size=0, initialization_data=None)
+        dba_start = PAS5211MsgStartDbaAlgorithm(
+            size=0, initialization_data=None)
         for id in CHANNELS:
             self.send_state.append(False)
             self.send(self.p(dba_start, channel_id=id))
+            log.debug("[SENT] PAS5211MsgStartDbaAlgorithm")
         raise self.wait_dba_start()
 
     # Transitions from wait_dba_start
     @ATMT.timeout(wait_dba_start, 3)
-    def dba_timeout(self):
+    def dba_start_timeout(self):
         log.error("DBA has not started; disconnecting")
-        raise self.ERROR()
+        raise self.error()
 
     @ATMT.receive_condition(wait_dba_start)
     def wait_for_dba_start(self, pkt):
         if PAS5211MsgStartDbaAlgorithmResponse in pkt:
+            log.debug("[RESPONSE] PAS5211MsgStartDbaAlgorithm")
             self.send_state[pkt.channel_id] = True
             if self.check_channel_state():
                 raise self.got_dba_start()
@@ -442,45 +487,91 @@
     # Transitions from got_dba_start
     @ATMT.condition(got_dba_start)
     def send_activation_period(self):
-        activation = PAS5211MsgSetOltChannelActivationPeriod(activation_period=1000)
+        activation = PAS5211MsgSetOltChannelActivationPeriod(
+            activation_period=1000)
         for id in CHANNELS:
             self.send_state.append(False)
             self.send(self.p(activation, channel_id=id))
+            log.debug("[SENT] PAS5211MsgSetOltChannelActivationPeriod")
+
         raise self.wait_activation()
 
     # Transitions for wait_for_activation
     @ATMT.timeout(wait_activation, 3)
     def timeout_activation(self):
         log.error("No activation; disconnect")
-        raise self.ERROR()
+        raise self.error()
 
     @ATMT.receive_condition(wait_activation)
     def wait_for_activation(self, pkt):
         if PAS5211MsgSetOltChannelActivationPeriodResponse in pkt:
+            log.debug("[RESPONSE] PAS5211MsgSetOltChannelActivationPeriod")
             self.send_state[pkt.channel_id] = True
             if self.check_channel_state():
                 log.info("Ruby OLT at {} initialised".format(self.target))
-                self.device.create_logical_device()
+                # self.device.create_logical_device()
                 self.device.activate()
-                raise self.initialized()
+                # self.device.add_upstream_port(129)
+                # self.device.add_logical_upstream_port(129)
+                # keep_alive = KeepAlive(
+                #     iface=self.interface, comm=self.comm, target=self.target, device=self.device)
+                # keep_alive.run()
+                raise self.end()
         raise self.wait_activation()
 
-    # Keep alive loop
-    @ATMT.timeout(initialized, 1)
+
+class KeepAlive(BaseOltAutomaton):
+    """
+        Master filter: Only allow PAS5211MsgGetOltVersionResponse
+    """
+
+    def master_filter(self, pkt):
+        if not super(KeepAlive, self).master_filter(pkt):
+            return False
+
+        if PAS5211MsgGetOltVersionResponse in pkt:
+            return True
+
+        return False
+
+    """
+        States
+    """
+
+    @ATMT.state(initial=1)
+    def init_keepalive(self):
+        log.debug('init-keepalive')
+
+    @ATMT.state()
+    def wait_keepalive(self):
+        pass
+
+    @ATMT.state(error=1)
+    def error(self):
+        raise self.end()
+    
+    @ATMT.state(final=1)
+    def end(self):
+        log.debug('init-keepalive-end')
+
+    """
+        Transitions
+    """
+
+    # Send Keep Alive
+    @ATMT.condition(init_keepalive)
     def send_keepalive(self):
         self.send(self.p(PAS5211MsgGetOltVersion()))
-        raise self.wait_keepalive()
+        raise self.got_keepalive()
 
-    # Transitions from wait_keepalive
+    # Timeout
     @ATMT.timeout(wait_keepalive, 1)
     def timeout_keepalive(self):
         log.error("OLT not responding to keep alive; disconnecting")
-        raise self.ERROR()
+        raise self.error()
 
+    # Received Keep Alive
     @ATMT.receive_condition(wait_keepalive)
-    def wait_for_keepalive(self, pkt):
-        if PAS5211MsgGetOltVersionResponse in pkt:
-            raise self.initialized()
-
-
-
+    def got_keepalive(self, pkt):
+        log.debug('keepalive-received')
+        raise self.send_keepalive()
diff --git a/voltha/adapters/microsemi_olt/PAS5211.py b/voltha/adapters/microsemi_olt/PAS5211.py
index 947745b..3f642cf 100644
--- a/voltha/adapters/microsemi_olt/PAS5211.py
+++ b/voltha/adapters/microsemi_olt/PAS5211.py
@@ -20,7 +20,6 @@
 """
 import struct
 
-
 from scapy.fields import LEShortField, Field, LEIntField, LESignedIntField, FieldLenField, FieldListField, PacketField, \
     ByteField, StrFixedLenField, ConditionalField, StrField, MACField, LELongField, LenField, StrLenField
 from scapy.layers.l2 import DestMACField, ETHER_ANY, Ether
@@ -35,15 +34,18 @@
 """
 PAS5211 Constants
 """
-#TODO get range from olt_version message
-CHANNELS=range(0,4)
+# TODO get range from olt_version message
+CHANNELS = range(0, 4)
+PORTS = range(1, 129)
 
 
 class XLESignedIntField(Field):
     def __init__(self, name, default):
         Field.__init__(self, name, default, "<i")
+
     def randval(self):
         return RandSInt()
+
     def i2repr(self, pkt, x):
         return lhex(self.i2h(pkt, x))
 
@@ -83,7 +85,7 @@
 class PAS5211MsgGetProtocolVersion(PAS5211Msg):
     opcode = 2
     name = "PAS5211MsgGetProtocolVersion"
-    fields_desc = [ ]
+    fields_desc = []
 
 
 class PAS5211MsgGetProtocolVersionResponse(PAS5211Msg):
@@ -99,7 +101,7 @@
 class PAS5211MsgGetOltVersion(PAS5211Msg):
     opcode = 3
     name = "PAS5211MsgGetOltVersion"
-    fields_desc = [ ]
+    fields_desc = []
 
 
 class PAS5211MsgGetOltVersionResponse(PAS5211Msg):
@@ -127,7 +129,7 @@
 
 class SnrBurstDelay(Packet):
     name = "SnrBurstDelay"
-    fields_desc= [
+    fields_desc = [
         LEShortField("timer_delay", None),
         LEShortField("preamble_delay", None),
         LEShortField("delimiter_delay", None),
@@ -137,9 +139,10 @@
     def extract_padding(self, p):
         return "", p
 
+
 class RngBurstDelay(Packet):
     name = "SnrBurstDelay"
-    fields_desc= [
+    fields_desc = [
         LEShortField("timer_delay", None),
         LEShortField("preamble_delay", None),
         LEShortField("delimiter_delay", None)
@@ -165,7 +168,7 @@
 
 class GeneralOpticsParams(Packet):
     name = "GeneralOpticsParams"
-    fields_desc= [
+    fields_desc = [
         ByteField("laser_reset_polarity", None),
         ByteField("laser_sd_polarity", None),
         ByteField("sd_source", None),
@@ -278,7 +281,7 @@
 
 class PAS5211MsgSetOpticsIoControlResponse(PAS5211Msg):
     name = "PAS5211MsgSetOpticsIoControlResponse"
-    fields_desc = [ ]
+    fields_desc = []
 
     def extract_padding(self, p):
         return "", p
@@ -338,15 +341,13 @@
     fields_desc = []
 
 
-class  PAS5211MsgGetDbaModeResponse(PAS5211Msg):
+class PAS5211MsgGetDbaModeResponse(PAS5211Msg):
     name = "PAS5211MsgGetDbaModeResponse"
     fields_desc = [
         LEIntField("dba_mode", None),
     ]
 
 
-
-
 class PAS5211MsgAddOltChannel(PAS5211Msg):
     opcode = 4
     name = "PAS5211MsgAddOltChannel"
@@ -374,7 +375,6 @@
         LEIntField("parameter4", None)
     ]
 
-
 class PAS5211MsgSetOltChannelActivationPeriod(PAS5211Msg):
     opcode = 11
     name = "PAS5211MsgSetOltChannelActivationPeriod"
@@ -382,17 +382,14 @@
         LEIntField("activation_period", None)
     ]
 
-
 class PAS5211MsgSetOltChannelActivationPeriodResponse(PAS5211Msg):
     name = "PAS5211MsgSetOltChannelActivationPeriodResponse"
     fields_desc = []
 
-
 class PAS5211MsgSetAlarmConfigResponse(PAS5211Msg):
     name = "PAS5211MsgSetAlarmConfigResponse"
     fields_desc = []
 
-
 class PAS5211MsgSendCliCommand(PAS5211Msg):
     opcode = 15
     name = "PAS5211MsgSendCliCommand"
@@ -401,7 +398,6 @@
         StrField("command", "")
     ]
 
-
 class PAS5211MsgSwitchToInboundMode(PAS5211Msg):
     opcode = 0xec
     name = "PAS5211MsgSwitchToInboundMode"
@@ -414,9 +410,10 @@
     opcode = 145
     name = "PAS5211MsgGetActivationAuthMode"
     fields_desc = [
-        LEShortField("nothing", 0) # no idea why this is here
+        LEShortField("nothing", 0)  # no idea why this is here
     ]
 
+
 class PAS5211MsgGetActivationAuthModeResponse(PAS5211Msg):
     opcode = 10385
     name = "PAS5211MsgGetActivationAuthModeResponse"
@@ -425,6 +422,7 @@
         LEShortField("reserved", 0),
     ]
 
+
 class PAS5211MsgSetOnuOmciPortId(PAS5211Msg):
     opcode = 41
     name = "PAS5211MsgSetOnuOmciPortId"
@@ -470,14 +468,13 @@
     name = "PAS5211MsgSetOnuAllocIdResponse"
     fields_desc = []
 
-
 class PAS5211MsgSendDbaAlgorithmMsg(PAS5211Msg):
     opcode = 47
     name = "PAS5211MsgSendDbaAlgorithmMsg"
     fields_desc = [
-        #LEShortField("id", None),
+        # LEShortField("id", None),
         FieldLenField("size", None, fmt="<H", length_of="data"),
-        StrLenField("data", "", length_from=lambda x:x.size)
+        StrLenField("data", "", length_from=lambda x: x.size)
     ]
 
 class PAS5211MsgSendDbaAlgorithmMsgResponse(PAS5211Msg):
@@ -494,7 +491,7 @@
         LEShortField("alloc_id", None),
         LEIntField("type", None),
         LEIntField("destination", None),  # Is this the CNI port
-                                          # if yes then values are 0-11 (for ruby)
+        # if yes then values are 0-11 (for ruby)
         LEShortField("reserved", None)
     ]
 
@@ -503,7 +500,6 @@
     name = "PAS5211MsgSetPortIdConfigResponse"
     fields_desc = []
 
-
 class PAS5211MsgGetOnuIdByPortId(PAS5211Msg):
     opcode = 196
     name = "PAS5211MsgGetOnuIdByPortId"
@@ -512,7 +508,6 @@
         LEShortField("reserved", 0)
     ]
 
-
 class PAS5211MsgGetOnuIdByPortIdResponse(PAS5211Msg):
     opcode = 196
     name = "PAS5211MsgGetOnuIdByPortIdResponse"
@@ -521,7 +516,6 @@
         LEShortField("onu_id", None)
     ]
 
-
 class PAS5211SetVlanUplinkConfiguration(PAS5211Msg):
     opcode = 39
     name = "PAS5211SetVlanUplinkConfiguration"
@@ -534,21 +528,18 @@
         LEShortField("reserved", 0)
     ]
 
-
 class PAS5211SetVlanUplinkConfigurationResponse(PAS5211Msg):
     opcode = 10279
     name = "PAS5211SetVlanUplinkConfigurationResponse"
     fields_desc = []
 
-
 class PAS5211GetOnuAllocs(PAS5211Msg):
     opcode = 9
     name = "PAS5211GetOnuAllocs"
     fields_desc = [
-        LEShortField("nothing", None) # It's in the PMC code... so yeah.
+        LEShortField("nothing", None)  # It's in the PMC code... so yeah.
     ]
 
-
 class PAS5211GetOnuAllocsResponse(PAS5211Msg):
     opcode = 9
     name = "PAS5211GetOnuAllocsResponse"
@@ -557,7 +548,6 @@
         FieldListField("alloc_ids", None, LEShortField("alloc_id", None))
     ]
 
-
 class PAS5211GetSnInfo(PAS5211Msg):
     opcode = 7
     name = "PAS5211GetSnInfo"
@@ -565,7 +555,6 @@
         StrFixedLenField("serial_number", None, 8)
     ]
 
-
 class PAS5211GetSnInfoResponse(PAS5211Msg):
     opcode = 7
     name = "PAS5211GetSnInfoResponse"
@@ -578,7 +567,6 @@
         LEShortField("reserved", None)
     ]
 
-
 class PAS5211GetOnusRange(PAS5211Msg):
     opcode = 116
     name = "PAS5211GetOnusRange"
@@ -586,7 +574,6 @@
         LEShortField("nothing", None)
     ]
 
-
 class PAS5211GetOnusRangeResponse(PAS5211Msg):
     opcode = 116
     name = "PAS5211GetOnusRangeResponse"
@@ -605,7 +592,6 @@
         LEShortField("reserved", None)
     ]
 
-
 class PAS5211GetPortIdConfigResponse(PAS5211Msg):
     opcode = 19
     name = "PAS5211GetPortIdConfigResponse"
@@ -618,15 +604,6 @@
         LEShortField("reserved", None),
     ]
 
-# typedef struct
-# {
-#     short int          svlan_id;
-# 	PON_true_false_t   forwarding_mode;
-#     PON_true_false_t   use_svlan;
-#     PON_true_false_t   use_cvlan;
-#     PON_true_false_t   use_pbits;
-#     PON_true_false_t   discard_unknown;
-# } PASCOMM_msg_set_svlan_at_configuration_t;
 class PAS5211SetSVlanAtConfig(PAS5211Msg):
     opcode = 63
     name = "PAS5211SetSVlanAtConfig"
@@ -639,23 +616,11 @@
         LEShortField("discard_unknown", None),
     ]
 
-
 class PAS5211SetSVlanAtConfigResponse(PAS5211Msg):
     opcode = 63
     name = "PAS5211SetSVlanAtConfigResponse"
     fields_desc = []
 
-# typedef struct
-# {
-# 	PON_port_id_t              source_port_id;
-# 	PON_vlan_tag_t             primary_vid;
-#     PON_true_false_t           pvid_config_enabled; /* use_pvid */
-# 	PON_vlan_tag_operation_t   svlan_tag_operation;
-# 	PON_vlan_tag_operation_t   cvlan_tag_operation;
-# 	PON_vlan_tag_t             new_svlan_tag;
-# 	PON_vlan_tag_t             new_cvlan_tag;
-# 	PON_vlan_destination_t     destination;
-# } PASCOMM_msg_set_uplink_vlan_handling_t;
 
 class PAS5211SetUplinkVlanHandl(PAS5211Msg):
     opcode = 34
@@ -676,17 +641,6 @@
     name = "PAS5211SetUplinkVlanHandlResponse"
     fields_desc = []
 
-# typedef struct
-# {
-#     PON_pon_network_traffic_direction_t  direction;
-#     unsigned short                       extended_svlan_type;
-#     unsigned short 	                     insertion_svlan_ethertype;
-#     unsigned short                       extended_cvlan_type;
-#     unsigned short 	                     insertion_cvlan_ethertype;
-#     PON_pcp_scheme_t                     pon_pcp_code;
-#     PON_pcp_scheme_t                     cni_pcp_code;
-# 	unsigned short                       reserved;
-# } PASCOMM_msg_set_vlan_general_configuration_t;
 class PAS5211SetVlanGenConfig(PAS5211Msg):
     opcode = 43
     name = "PAS5211SetVlanGenConfig"
@@ -701,16 +655,52 @@
         LEShortField("reserved", None)
     ]
 
-
 class PAS5211SetVlanGenConfigResponse(PAS5211Msg):
     opcode = 43
     name = "PAS5211SetVlanGenConfigResponse"
     fields_desc = []
 
+
+class PAS5211SetVlanDownConfig(PAS5211Msg):
+    opcode = 32
+    name = "PAS5211SetVlanDownConfig"
+    fields_desc = [
+        LEShortField("svlan_id", None),
+        LEShortField("double_tag_handling", None),
+        LEShortField("vlan_priority_handling", None)
+    ]
+
+class PAS5211SetVlanDownConfigResponse(PAS5211Msg):
+    opcode = 32
+    name = "PAS5211SetVlanDownConfigResponse"
+    fields_desc = []
+
+class PAS5211SetDownVlanHandl(PAS5211Msg):
+    opcode = 27
+    name = "PAS5211SetDownVlanHandl"
+    fields_desc = [
+        LEShortField("svlan_tag", None),
+        LEShortField("cvlan_tag", None),
+        LEShortField("double_tag_handling", None),
+        LEShortField("priority_handling", None),
+        LEShortField("input_priority", None),
+        LEShortField("svlan_tag_operation", None),
+        LEShortField("cvlan_tag_operation", None),
+        LEShortField("port_id", None),
+        LEShortField("new_cvlan_tag", None),
+        LEShortField("destination", None),
+        LEShortField("output_vlan_prio_handle", None),
+        LEShortField("output_priority", None)
+    ]
+
+class PAS5211SetDownVlanHandlResponse(PAS5211Msg):
+    opcode = 27
+    name = "PAS5211SetDownVlanHandlResponse"
+    fields_desc = []
+
 class Frame(Packet):
     pass
 
-
 class PAS5211MsgSendFrame(PAS5211Msg):
     opcode = 42
     name = "PAS5211MsgSendFrame"
@@ -719,23 +709,20 @@
         LEShortField("port_type", PON_PORT_PON),
         LEShortField("port_id", 0),
         LEShortField("management_frame", PON_FALSE),
-        ConditionalField(PacketField("frame", None, Packet), lambda pkt: pkt.management_frame==PON_FALSE),
-        ConditionalField(PacketField("frame", None, OmciFrame), lambda pkt: pkt.management_frame==PON_TRUE)
+        ConditionalField(PacketField("frame", None, Packet), lambda pkt: pkt.management_frame == PON_FALSE),
+        ConditionalField(PacketField("frame", None, OmciFrame), lambda pkt: pkt.management_frame == PON_TRUE)
     ]
 
     def extract_padding(self, p):
         return "", p
 
-
 class PAS5211MsgSendFrameResponse(PAS5211Msg):
     name = "PAS5211MsgSendFrameResponse"
     fields_desc = []
 
-
 class PAS5211Event(PAS5211Msg):
     opcode = 12
 
-
 class PAS5211EventFrameReceived(PAS5211Event):
     name = "PAS5211EventFrameReceived"
     fields_desc = [
@@ -746,9 +733,9 @@
         LEShortField("classification_entity", None),
         LEShortField("l3_offset", None),
         LEShortField("l4_offset", None),
-        LEShortField("ignored", 0), # TODO these do receive values, but there is no code in PMC using it
-        ConditionalField(PacketField("frame", None, Packet), lambda pkt: pkt.management_frame==PON_FALSE),
-        ConditionalField(PacketField("frame", None, OmciFrame), lambda pkt: pkt.management_frame==PON_TRUE)
+        LEShortField("ignored", 0),  # TODO these do receive values, but there is no code in PMC using it
+        ConditionalField(PacketField("frame", None, Packet), lambda pkt: pkt.management_frame == PON_FALSE),
+        ConditionalField(PacketField("frame", None, OmciFrame), lambda pkt: pkt.management_frame == PON_TRUE)
     ]
 
 class PAS5211EventDbaAlgorithm(PAS5211Event):
@@ -758,20 +745,265 @@
         StrLenField("data", "", length_from=lambda x: x.size)
     ]
 
-
 class PAS5211EventOnuActivation(PAS5211Event):
     name = "PAS5211EventOnuActivation"
+    event_type = 1
     fields_desc = [
         StrFixedLenField("serial_number", None, length=8),
         LEIntField("equalization_period", None)
     ]
 
+class PAS5211EventOnuDeactivation(PAS5211Event):
+    name = "PAS5211EventOnuDeactivation"
+    event_type = 2
+    fields_desc = [
+        LEShortField("code", None)
+    ]
+
+class PAS5211EventLogMsg(PAS5211Event):
+    name = "PAS5211EventLogMsg"
+    event_type = 3
+    fields_desc = []
+
+class PAS5211EventFWGeneralPrint(PAS5211Event):
+    name = "PAS5211EventFWGeneralPrint"
+    event_type = 4
+    fields_desc = []
+
+class PAS5211EventFWTracePrint(PAS5211Event):
+    name = "PAS5211EventFWTracePrint"
+    event_type = 5
+    fields_desc = []
+
+class PAS5211EventStartEncryption(PAS5211Event):
+    name = "PAS5211EventStartEncryption"
+    event_type = 6
+    fields_desc = []
+
+class PAS5211EventStopEncryption(PAS5211Event):
+    name = "PAS5211EventStopEncryption"
+    event_type = 7
+    fields_desc = []
+
+class PAS5211EventUpdateEncryption(PAS5211Event):
+    name = "PAS5211EventUpdateEncryption"
+    event_type = 8
+    fields_desc = []
+
+class PAS5211EventAlarmNotification(PAS5211Event):
+    name = "PAS5211EventAlarmNotification"
+    event_type = 9
+    fields_desc = [
+        LEShortField("code", None),
+        LEIntField("parameter1", None),
+        LEIntField("parameter2", None),
+        LEIntField("parameter3", None),
+        LEIntField("parameter4", None)
+    ]
+
+class PAS5211EventDBAAlgorithmEvent(PAS5211Event):
+    name = "PAS5211EventDBAAlgorithmEvent"
+    event_type = 11
+    fields_desc = []
+
+class PAS5211EventOLTReset(PAS5211Event):
+    name = "PAS5211EventOLTReset"
+    event_type = 12
+    fields_desc = []
+
+class PAS5211EventOnuSleepMode(PAS5211Event):
+    name = "PAS5211EventOnuSleepMode"
+    event_type = 13
+    fields_desc = []
+
+class PAS5211EventAssignAllocId(PAS5211Event):
+    name = "PAS5211EventAssignAllocId"
+    event_type = 14
+    fields_desc = []
+
+class PAS5211EventConfigOMCIPort(PAS5211Event):
+    name = "PAS5211EventConfigOMCIPort"
+    event_type = 15
+    fields_desc = []
+
+class PAS5211EventPloamMessageReceived(PAS5211Event):
+    name = "PAS5211EventPloamMessageReceived"
+    event_type = 17
+    fields_desc = []
+
+class PAS5211EventLoadOLTBinaryCompleted(PAS5211Event):
+    name = "PAS5211EventLoadOLTBinaryCompleted"
+    event_type = 18
+    fields_desc = []
+
+class PAS5211EventMasterOLTFail(PAS5211Event):
+    name = "PAS5211EventMasterOLTFail"
+    event_type = 19
+    fields_desc = []
+
+class PAS5211EventRedundantSwitchOverStatus(PAS5211Event):
+    name = "PAS5211EventRedundantSwitchOverStatus"
+    event_type = 20
+    fields_desc = []
+
+class PAS5211EventSyncOLTData(PAS5211Event):
+    name = "PAS5211EventSyncOLTData"
+    event_type = 21
+    fields_desc = []
+
+class PAS5211EventEQDChange(PAS5211Event):
+    name = "PAS5211EventEQDChange"
+    event_type = 22
+    fields_desc = []
+
+class PAS5211EventXAUIStatusNotification(PAS5211Event):
+    name = "PAS5211EventXAUIStatusNotification"
+    event_type = 23
+    fields_desc = []
+
+class PAS5211EventUnauthenticatedONU(PAS5211Event):
+    name = "PAS5211EventUnauthenticatedONU"
+    event_type = 24
+    fields_desc = []
+
+class PAS5211EventFalseQFullReported(PAS5211Event):
+    name = "PAS5211EventFalseQFullReported"
+    event_type = 25
+    fields_desc = []
+
+class PAS5211EventOpticalModuleIndication(PAS5211Event):
+    name = "PAS5211EventOpticalModuleIndication"
+    event_type = 27
+    fields_desc = []
+
+class PAS5211EventActivationFailure(PAS5211Event):
+    name = "PAS5211EventActivationFailure"
+    event_type = 28
+    fields_desc = []
+
+class PAS5211EventBipError(PAS5211Event):
+    name = "PAS5211EventBipError"
+    event_type = 29
+    fields_desc = []
+
+class PAS5211EventREIError(PAS5211Event):
+    name = "PAS5211EventREIError"
+    event_type = 30
+    fields_desc = []
+
+class PAS5211EventRDNMultiONUFailure(PAS5211Event):
+    name = "PAS5211EventRDNMultiONUFailure"
+    event_type = 31
+    fields_desc = []
+
+class PAS5211EventUnexpectedSN(PAS5211Event):
+    name = "PAS5211EventUnexpectedSN"
+    event_type = 32
+    fields_desc = []
+
+class PAS5211EventRDNSwitchOverONUResult(PAS5211Event):
+    name = "PAS5211EventRDNSwitchOverONUResult"
+    event_type = 33
+    fields_desc = []
+
+class PAS5211EventGMacMalfucntionSuspected(PAS5211Event):
+    name = "PAS5211EventGMacMalfucntionSuspected"
+    event_type = 34
+    fields_desc = []
+
+
+class PAS5211GetPortIdDownstreamPolicingConfig(PAS5211Msg):
+    opcode = 82
+    name = "PAS5211GetPortIdDownstreamPolicingConfig"
+    fields_desc = [
+        LEShortField("port_id", None),
+        LEShortField("reserved", None)]
+
+class PAS5211GetPortIdDownstreamPolicingConfigResponse(PAS5211Msg):
+    opcode = 82
+    name = "PAS5211GetPortIdDownstreamPolicingConfigResponse"
+    fields_desc = [
+        LEIntField("committed_bandwidth", None),
+        LEIntField("excessive_bandwidth", None),
+        LEShortField("committed_burst_limit", None),
+        LEShortField("excessive_burst_limit", None),
+        LEShortField("ds_policing_config_id", None),
+        LEShortField("reserved", None)]
+
+class PAS5211RemoveDownstreamPolicingConfig(PAS5211Msg):
+    opcode = 76
+    name = "PAS5211RemoveDownstreamPolicingConfig"
+    fields_desc = [
+        LEShortField("policing_config_id", None),
+        LEShortField("reserved", None)]
+
+class PAS5211RemoveDownstreamPolicingConfigResponse(PAS5211Msg):
+    opcode = 76
+    name = "PAS5211RemoveDownstreamPolicingConfigResponse"
+    fields_desc = []
+
+class PAS5211SetPortIdPolicingConfig(PAS5211Msg):
+    opcode = 80
+    name = "PAS5211SetPortIdPolicingConfig"
+    fields_desc = [
+        LEShortField("direction", None),
+        LEShortField("port_id", None),
+        LEShortField("policing_config_id", None),
+        LEShortField("reserved", None)]
+
+class PAS5211SetPortIdPolicingConfigResponse(PAS5211Msg):
+    opcode = 80
+    name = "PAS5211SetPortIdPolicingConfigResponse"
+    fields_desc = []
+
+class PAS5211UnsetPortIdPolicingConfig(PAS5211Msg):
+    opcode = 81
+    name = "PAS5211UnsetSetPortIdPolicingConfig"
+    fields_desc = [
+        LEShortField("direction", None),
+        LEShortField("port_id", None)]
+
+class PAS5211UnsetPortIdPolicingConfigResponse(PAS5211Msg):
+    opcode = 81
+    name = "PAS5211UnsetSetPortIdPolicingConfigResponse"
+    fields_desc = []
+
+class PAS5211SetDownstreamPolicingConfig(PAS5211Msg):
+    opcode = 74
+    name = "PAS5211SetDownstreamPolicingConfig"
+    fields_desc = [
+        LEIntField("committed_bandwidth", None),
+        LEIntField("excessive_bandwidth", None),
+        LEShortField("committed_burst_limit", None),
+        LEShortField("excessive_burst_limit", None)]
+
+class PAS5211SetDownstreamPolicingConfigResponse(PAS5211Msg):
+    opcode = 74
+    name = "PAS5211SetDownstreamPolicingConfigResponse"
+    fields_desc = [
+        LEShortField("policing_config_id", None),
+        LEShortField("reserved", None)]
+
+class PAS5211SetUpstreamPolicingConfig(PAS5211Msg):
+    opcode = 77
+    name = "PAS5211SetUpstreamPolicingConfig"
+    fields_desc = [
+        LEIntField("bandwidth", None),
+        LEShortField("burst_limit", None),
+        LEShortField("reserved", None)]
+
+class PAS5211SetUpstreamPolicingConfigResponse(PAS5211Msg):
+    opcode = 77
+    name = "PAS5211SetDownstreamPolicingResponse"
+    fields_desc = [
+        LEShortField("policing_config_id", None),
+        LEShortField("reserved", None)]
 
 class PAS5211Dot3(Packet):
     name = "PAS5211Dot3"
-    fields_desc = [ DestMACField("dst"),
-                    MACField("src", ETHER_ANY),
-                    LenField("len", None, "H") ]
+    fields_desc = [DestMACField("dst"),
+                   MACField("src", ETHER_ANY),
+                   LenField("len", None, "H")]
 
     MIN_FRAME_SIZE = 60
 
@@ -789,6 +1021,7 @@
 This is needed in order to force scapy to use PAS5211Dot3
 instead of the default Dot3 that the Ether class uses.
 '''
+
 @classmethod
 def PAS_dispatch_hook(cls, _pkt=None, *args, **kargs):
     if _pkt and len(_pkt) >= 14:
@@ -799,7 +1032,6 @@
 Ether.dispatch_hook = PAS_dispatch_hook
 
 # bindings for messages received
-
 # fix for v2 of Microsemi OLT.
 bind_layers(Ether, PAS5211FrameHeader, type=0x0a00)
 
@@ -887,10 +1119,37 @@
 bind_layers(PAS5211MsgHeader, PAS5211SetVlanGenConfig, opcode=0x3000 | 43)
 bind_layers(PAS5211MsgHeader, PAS5211SetVlanGenConfigResponse, opcode=0x2800 | 43)
 
+bind_layers(PAS5211MsgHeader, PAS5211SetVlanDownConfig, opcode=0x3000 | 32)
+bind_layers(PAS5211MsgHeader, PAS5211SetVlanDownConfigResponse, opcode=0x2800 | 32)
+
+bind_layers(PAS5211MsgHeader, PAS5211SetDownVlanHandl, opcode=0x3000 | 27)
+bind_layers(PAS5211MsgHeader, PAS5211SetDownVlanHandlResponse, opcode=0x2800 | 27)
+
+bind_layers(PAS5211MsgHeader, PAS5211SetDownstreamPolicingConfig, opcode=0x3000 | 74)
+bind_layers(PAS5211MsgHeader, PAS5211SetDownstreamPolicingConfigResponse, opcode=0x2800 | 74)
+
+bind_layers(PAS5211MsgHeader, PAS5211SetUpstreamPolicingConfig, opcode=0x3000 | 77)
+bind_layers(PAS5211MsgHeader, PAS5211SetUpstreamPolicingConfigResponse, opcode=0x2800 | 77)
+
+bind_layers(PAS5211MsgHeader, PAS5211SetPortIdPolicingConfig, opcode=0x3000 | 80)
+bind_layers(PAS5211MsgHeader, PAS5211SetPortIdPolicingConfigResponse, opcode=0x2800 | 80)
+
+bind_layers(PAS5211MsgHeader, PAS5211UnsetPortIdPolicingConfig, opcode=0x3000 | 81)
+bind_layers(PAS5211MsgHeader, PAS5211UnsetPortIdPolicingConfigResponse, opcode=0x2800 | 81)
+
+bind_layers(PAS5211MsgHeader, PAS5211GetPortIdDownstreamPolicingConfig, opcode=0x3000 | 82)
+bind_layers(PAS5211MsgHeader, PAS5211GetPortIdDownstreamPolicingConfigResponse, opcode=0x2800 | 82)
+
+bind_layers(PAS5211MsgHeader, PAS5211RemoveDownstreamPolicingConfig, opcode=0x3000 | 76)
+bind_layers(PAS5211MsgHeader, PAS5211RemoveDownstreamPolicingConfigResponse, opcode=0x2800 | 76)
+
+
 # bindings for events received
 bind_layers(PAS5211MsgHeader, PAS5211EventOnuActivation, opcode=0x2800 | 12, event_type=1)
+bind_layers(PAS5211MsgHeader, PAS5211EventOnuDeactivation, opcode=0x2800 | 12, event_type=2)
 bind_layers(PAS5211MsgHeader, PAS5211EventFrameReceived, opcode=0x2800 | 12, event_type=10)
 bind_layers(PAS5211MsgHeader, PAS5211EventDbaAlgorithm, opcode=0x2800 | 12, event_type=11)
+bind_layers(PAS5211MsgHeader, PAS5211EventAlarmNotification, opcode=0x2800 | 12, event_type=9)
 bind_layers(PAS5211MsgHeader, PAS5211Event, opcode=0x2800 | 12)
 
 
@@ -918,10 +1177,21 @@
     from scapy.utils import rdpcap
     import sys
     import code
+
     packets = rdpcap(sys.argv[1])
     p = Display(packets)
 
-    def walk(index=0):
-        p.walk(index=index)
+    def walk(index=0, interactive=True, channel=-1):
+        if interactive is not True:
+            for packet in packets:
+                if PAS5211MsgHeader in packet:
+                    if PAS5211MsgGetOltVersion not in packet and PAS5211MsgGetOltVersionResponse not in packet:
+                        if channel is not -1:
+                            if packet[PAS5211MsgHeader].channel_id == channel:
+                                packet.show()
+                        else:
+                            packet.show()
+        else:
+            p.walk(index=index)
 
-    code.interact(local=locals())
\ No newline at end of file
+    code.interact(local=locals())
diff --git a/voltha/adapters/microsemi_olt/PAS5211_comm.py b/voltha/adapters/microsemi_olt/PAS5211_comm.py
index e7cc36d..bd9c8c0 100644
--- a/voltha/adapters/microsemi_olt/PAS5211_comm.py
+++ b/voltha/adapters/microsemi_olt/PAS5211_comm.py
@@ -20,7 +20,6 @@
 
 log = structlog.get_logger()
 
-
 def constructPAS5211Frames(msg, seq, src_mac, dst_mac, channel_id=-1,
                            onu_id=-1, onu_session_id=-1):
 
@@ -41,26 +40,23 @@
 
     return frame
 
-
 def sequence_generator(init):
     num = init
     while True:
         yield num
         num += 1
 
-
 def determine_src_mac(iface):
     if iface in netifaces.interfaces():
         return netifaces.ifaddresses(iface)[netifaces.AF_LINK][0]['addr']
     return None
 
-
 class PAS5211Communication(object):
     def __init__(self, dst_mac, init=0, iface = None):
         self.iface = iface
         self.dst_mac = dst_mac
-        self.seqgen = sequence_generator(init)
         self.src_mac = determine_src_mac(self.iface)
+        self.seqgen = sequence_generator(init)
 
     def frame(self, msg, channel_id=-1, onu_id=-1, onu_session_id=-1):
         return constructPAS5211Frames(msg, self.seqgen.next(), self.src_mac,
diff --git a/voltha/adapters/microsemi_olt/PAS5211_constants.py b/voltha/adapters/microsemi_olt/PAS5211_constants.py
index e70db40..9f7718f 100644
--- a/voltha/adapters/microsemi_olt/PAS5211_constants.py
+++ b/voltha/adapters/microsemi_olt/PAS5211_constants.py
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+from enum import Enum
 
 """
 PAS5211 Constants
@@ -60,7 +61,6 @@
 def PON_EXT_GPIO_LINE(line):
     return line + 8
 
-# from enum PON_alarm_t
 PON_ALARM_SOFTWARE_ERROR = 0
 PON_ALARM_LOS = 1
 PON_ALARM_LOSI = 2
@@ -77,70 +77,72 @@
 PON_ALARM_LOKI = 13
 PON_ALARM_TIWI = 14
 PON_ALARM_TIA = 15
+PON_ALARM_AUTH_FAILED_IN_REGISTRATION_ID_MODE = 20
+PON_ALARM_SUFI = 21
+
 PON_ALARM_VIRTUAL_SCOPE_ONU_LASER_ALWAYS_ON = 16
 PON_ALARM_VIRTUAL_SCOPE_ONU_SIGNAL_DEGRADATION = 17
 PON_ALARM_VIRTUAL_SCOPE_ONU_EOL = 18
 PON_ALARM_VIRTUAL_SCOPE_ONU_EOL_DATABASE_IS_FULL = 19
-PON_ALARM_AUTH_FAILED_IN_REGISTRATION_ID_MODE = 20
-PON_ALARM_SUFI = 21
+
 PON_ALARM_LAST_ALARM = 22
 
 # from enum PON_general_parameters_type_t
-PON_COMBINED_LOSI_LOFI 		            = 1000
-PON_TX_ENABLE_DEFAULT 		            = 1001
+PON_COMBINED_LOSI_LOFI = 1000
+PON_TX_ENABLE_DEFAULT = 1001
 
 # Enable or disable False queue full event from DBA
-PON_FALSE_Q_FULL_EVENT_MODE             = 1002
+PON_FALSE_Q_FULL_EVENT_MODE = 1002
 
 # Set PID_AID_MISMATCH min silence period. 0 - disable, Else - period in secs
 PON_PID_AID_MISMATCH_MIN_SILENCE_PERIOD = 1003
 
 # Set if FW generate clear alarm. 0 - generate clear alarm, Else - don't
 # generate clear alarm
-PON_ENABLE_CLEAR_ALARM                  = 1004
+PON_ENABLE_CLEAR_ALARM = 1004
 
 # Enable or disabl send assign alloc id ploam. 0 - disable, 1 - enable
-PON_ASSIGN_ALLOC_ID_PLOAM               = 1005
+PON_ASSIGN_ALLOC_ID_PLOAM = 1005
 
 # BIP error polling period, 200 - 65000, 0 - Disabled, Recommended: 5000
 # (default)
-PON_BIP_ERR_POLLING_PERIOD_MS           = 1006
+PON_BIP_ERR_POLLING_PERIOD_MS = 1006
 
 # Ignore SN when decatived 0 - consider SN (deactivate the onu if received
 # same SN when activated (default)	1 - Ignore
-PON_IGNORE_SN_WHEN_ACTIVE		        = 1007
+PON_IGNORE_SN_WHEN_ACTIVE = 1007
 
 # 0xffffffff - Disabled (default). Any other value (0 - 0xfffe) indicates
 # that PA delay is enabled, with the specified delay value and included in
 # the US_OVERHEAD PLOAM
-PON_ONU_PRE_ASSIGNED_DELAY		        = 1008
+PON_ONU_PRE_ASSIGNED_DELAY = 1008
 
 # Enable or disable DS fragmentation, 0 disable, 1 enable
-PON_DS_FRAGMENTATION			        = 1009
+PON_DS_FRAGMENTATION = 1009
 
 # Set if fw report rei alarm when errors is 0, 0 disable (default), 1 enable
-PON_REI_ERRORS_REPORT_ALL		        = 1010
+PON_REI_ERRORS_REPORT_ALL = 1010
 
 # Set if igonre sfi deactivation, 0 disable (default), 1 enable
-PON_IGNORE_SFI_DEACTIVATION		        = 1011
+PON_IGNORE_SFI_DEACTIVATION = 1011
 
 # Allows to override the allocation overhead set by optic-params
 # configuration. This configuration is only allowed when the the pon channel
 # is disabled
-PON_OVERRIDE_ALLOCATION_OVERHEAD	    = 1012
+PON_OVERRIDE_ALLOCATION_OVERHEAD = 1012
 
 # Optics timeline offset, -128-127, : this parameter is very sensitive and
 # requires coordination with PMC
-PON_OPTICS_TIMELINE_OFFSET	            = 1013
+PON_OPTICS_TIMELINE_OFFSET = 1013
 
 # Last general meter
-PON_LAST_GENERAL_PARAMETER		        = PON_OPTICS_TIMELINE_OFFSET
+PON_LAST_GENERAL_PARAMETER = PON_OPTICS_TIMELINE_OFFSET
 
 # from enum PON_dba_mode_t
-PON_DBA_MODE_NOT_LOADED                 = 0
-PON_DBA_MODE_LOADED_NOT_RUNNING         = 1
-PON_DBA_MODE_RUNNING                    = 2
-PON_DBA_MODE_LAST                       = 3
+PON_DBA_MODE_NOT_LOADED = 0
+PON_DBA_MODE_LOADED_NOT_RUNNING = 1
+PON_DBA_MODE_RUNNING = 2
+PON_DBA_MODE_LAST = 3
 
 # from enum type typedef enum PON_port_frame_destination_t
 PON_PORT_PON = 0
@@ -157,86 +159,139 @@
 
 # from enum PON_olt_hw_classification_t
 
-PON_OLT_HW_CLASSIFICATION_PAUSE                    = 0
-PON_OLT_HW_CLASSIFICATION_LINK_CONSTRAINT          = 1
-PON_OLT_HW_CLASSIFICATION_IGMP                     = 2
-PON_OLT_HW_CLASSIFICATION_MPCP                     = 3
-PON_OLT_HW_CLASSIFICATION_OAM                      = 4
-PON_OLT_HW_CLASSIFICATION_802_1X                   = 5
-PON_OLT_HW_CLASSIFICATION_PPPOE_DISCOVERY          = 6
-PON_OLT_HW_CLASSIFICATION_PPPOE_SESSION            = 7
-PON_OLT_HW_CLASSIFICATION_DHCP_V4                  = 8
-PON_OLT_HW_CLASSIFICATION_PIM                      = 9
-PON_OLT_HW_CLASSIFICATION_DHCP_V6                  = 10
-PON_OLT_HW_CLASSIFICATION_ICMP_V4                  = 11
-PON_OLT_HW_CLASSIFICATION_MLD                      = 12
-PON_OLT_HW_CLASSIFICATION_ARP                      = 13
-PON_OLT_HW_CLASSIFICATION_CONF_DA                  = 14
-PON_OLT_HW_CLASSIFICATION_CONF_RULE                = 15
-PON_OLT_HW_CLASSIFICATION_DA_EQ_SA                 = 16
-PON_OLT_HW_CLASSIFICATION_DA_EQ_MAC                = 17
-PON_OLT_HW_CLASSIFICATION_DA_EQ_SEC_MAC            = 18
-PON_OLT_HW_CLASSIFICATION_SA_EQ_MAC                = 19
-PON_OLT_HW_CLASSIFICATION_SA_EQ_SEC_MAC            = 20
-PON_OLT_HW_CLASSIFICATION_ETHERNET_MANAGEMENT      = 100
-PON_OLT_HW_CLASSIFICATION_IPV4_LOCAL_MULTICAST     = 101
-PON_OLT_HW_CLASSIFICATION_IPV4_MANAGEMENT          = 102
-PON_OLT_HW_CLASSIFICATION_ALL_IPV4_MULTICAST       = 103
-PON_OLT_HW_CLASSIFICATION_IPV6_LOCAL_MULTICAST     = 104
-PON_OLT_HW_CLASSIFICATION_IPV6_MANAGEMENT          = 105
-PON_OLT_HW_CLASSIFICATION_ALL_IPV6_MULTICAST       = 106
-PON_OLT_HW_CLASSIFICATION_OTHER			           = 107
-PON_OLT_HW_CLASSIFICATION_LAST_RULE                = 108
+PON_OLT_HW_CLASSIFICATION_PAUSE = 0
+PON_OLT_HW_CLASSIFICATION_LINK_CONSTRAINT = 1
+PON_OLT_HW_CLASSIFICATION_IGMP = 2
+PON_OLT_HW_CLASSIFICATION_MPCP = 3
+PON_OLT_HW_CLASSIFICATION_OAM = 4
+PON_OLT_HW_CLASSIFICATION_802_1X = 5
+PON_OLT_HW_CLASSIFICATION_PPPOE_DISCOVERY = 6
+PON_OLT_HW_CLASSIFICATION_PPPOE_SESSION = 7
+PON_OLT_HW_CLASSIFICATION_DHCP_V4 = 8
+PON_OLT_HW_CLASSIFICATION_PIM  = 9
+PON_OLT_HW_CLASSIFICATION_DHCP_V6 = 10
+PON_OLT_HW_CLASSIFICATION_ICMP_V4 = 11
+PON_OLT_HW_CLASSIFICATION_MLD = 12
+PON_OLT_HW_CLASSIFICATION_ARP = 13
+PON_OLT_HW_CLASSIFICATION_CONF_DA = 14
+PON_OLT_HW_CLASSIFICATION_CONF_RULE = 15
+PON_OLT_HW_CLASSIFICATION_DA_EQ_SA = 16
+PON_OLT_HW_CLASSIFICATION_DA_EQ_MAC = 17
+PON_OLT_HW_CLASSIFICATION_DA_EQ_SEC_MAC = 18
+PON_OLT_HW_CLASSIFICATION_SA_EQ_MAC = 19
+PON_OLT_HW_CLASSIFICATION_SA_EQ_SEC_MAC = 20
+PON_OLT_HW_CLASSIFICATION_ETHERNET_MANAGEMENT = 100
+PON_OLT_HW_CLASSIFICATION_IPV4_LOCAL_MULTICAST = 101
+PON_OLT_HW_CLASSIFICATION_IPV4_MANAGEMENT = 102
+PON_OLT_HW_CLASSIFICATION_ALL_IPV4_MULTICAST  = 103
+PON_OLT_HW_CLASSIFICATION_IPV6_LOCAL_MULTICAST = 104
+PON_OLT_HW_CLASSIFICATION_IPV6_MANAGEMENT = 105
+PON_OLT_HW_CLASSIFICATION_ALL_IPV6_MULTICAST = 106
+PON_OLT_HW_CLASSIFICATION_OTHER	 = 107
+PON_OLT_HW_CLASSIFICATION_LAST_RULE  = 108
 
-PON_ACTIVATION_AUTH_AUTO 			  				= 0
+PON_ACTIVATION_AUTH_AUTO = 0
 PON_ACTIVATION_AUTH_HOST_CONTROLLED_SEPARATE_EVENTS = 1 # Host controlled: Separate events
-PON_ACTIVATION_AUTH_HOST_CONTROLLED_LUMPED_SN   	= 2 # Host controlled: Lumped-SN-Response
-PON_ACTIVATION_AUTH_REGISTRATION_ID_RAW   			= 3 # Registration-ID Raw
-PON_ACTIVATION_AUTH_REGISTRATION_ID_LEARN   		= 4  # Registration-ID Learn
+PON_ACTIVATION_AUTH_HOST_CONTROLLED_LUMPED_SN = 2 # Host controlled: Lumped-SN-Response
+PON_ACTIVATION_AUTH_REGISTRATION_ID_RAW = 3 # Registration-ID Raw
+PON_ACTIVATION_AUTH_REGISTRATION_ID_LEARN = 4  # Registration-ID Learn
 
-PON_LOGICAL_OBJECT_TYPE_ALLOC_ID	        = 0
+PON_LOGICAL_OBJECT_TYPE_ALLOC_ID = 0
 PON_LOGICAL_OBJECT_TYPE_ONU_ID_BY_ALLOC_ID  = 1
-PON_LOGICAL_OBJECT_TYPE_MAX			        = PON_LOGICAL_OBJECT_TYPE_ONU_ID_BY_ALLOC_ID
+PON_LOGICAL_OBJECT_TYPE_MAX	= PON_LOGICAL_OBJECT_TYPE_ONU_ID_BY_ALLOC_ID
 
+PMC_OFAL_MAX_BI_DIRECTIONAL_FLOW_PER_ONU = 16
+PMC_OFAL_START_FLOW_ID_BASE = 1000
 
-PMC_OFAL_MAX_BI_DIRECTIONAL_FLOW_PER_ONU    = 16
-PMC_OFAL_START_FLOW_ID_BASE                 = 1000
+PON_DL_VLAN_SVLAN_REMOVE = 3
+PON_DL_VLAN_CVLAN_NO_CHANGE = 0
+
+PON_VLAN_DONT_CHANGE_TAG = 0
+PON_VLAN_CHANGE_TAG = 1
+PON_VLAN_CHANGE_OTHER_TAG = 2
+PON_VLAN_CHANGE_REMOVE_TAG = 3
+
+PON_VLAN_UNUSED_TAG = -1
+PON_VLAN_DEST_DATAPATH = 1
+PON_VLAN_UNCHANGED_PRIORITY = -1
+PON_VLAN_REPLACE_PRIORITY = -2
+PON_VLAN_UNUSED_PRIORITY = -1
+
+PON_OUTPUT_VLAN_PRIO_HANDLE_DONT_CHANGE = 0
+PON_OUTPUT_VLAN_PRIO_HANDLE_INCOMING_VLAN = 1
+PON_OUTPUT_VLAN_PRIO_HANDLE_DL_VLAN_TABLE  = 2
+
+PON_N_TO_1_VLAN_MODE = 0
+PON_1_TO_1_VLAN_MODE = 1
 
 # OMCI
 
 OMCI_8021P_MSP_UNMARKED_FRAME_TAG_FRAME = 1
-OMCI_8021P_MSP_TP_TYPE_NULL             = 0
+OMCI_8021P_MSP_TP_TYPE_NULL = 0
 
 # GEM interworking option for MAC Bridge LAN
-OMCI_GEM_IWTP_IW_OPT_8021P_MAPPER                   = 5
+OMCI_GEM_IWTP_IW_OPT_8021P_MAPPER = 5
 #LLC frame encapsulation method
-OMCI_MAC_BRIDGE_PCD_ENCAP_METHOD_LLC                = 1
+OMCI_MAC_BRIDGE_PCD_ENCAP_METHOD_LLC = 1
 # Frame Check Sequence will forward
-OMCI_MAC_BRIDGE_PCD_LANFCS_FORWARDED                = 0
+OMCI_MAC_BRIDGE_PCD_LANFCS_FORWARDED = 0
 # in DS, perform the inverse of US operation
-OMCI_EX_VLAN_TAG_OCD_DS_MODE_US_INVERSE             = 0
+OMCI_EX_VLAN_TAG_OCD_DS_MODE_US_INVERSE = 0
 # Physical path termination point Ethernet UNI
-OMCI_EX_VLAN_TAG_OCD_ASSOCIATION_TYPE_PPTP_ETH_UNI  = 2
+OMCI_EX_VLAN_TAG_OCD_ASSOCIATION_TYPE_PPTP_ETH_UNI = 2
 
 # GEM Port Network CTP
 
 # Direction definitions
-GEM_DIR_BIDIRECT    = 3 # bi-directional
+GEM_DIR_BIDIRECT = 3 # bi-directional
 
+# PMC
+PMC_UPSTREAM_PORT = 129
 
 # SLA
 
-PYTHAGORAS_UPDATE_AID_SLA                   = 21
-
-PYTHAGORAS_DBA_DATA_COS                     = 0
-PYTHAGORAS_DBA_STATUS_REPORT_NSR            = 0
-
-PYTHAGORAS_SET_SLA_RESP_SIZE                = 10
+PYTHAGORAS_UPDATE_AID_SLA = 21
+PYTHAGORAS_DBA_DATA_COS = 0
+PYTHAGORAS_DBA_STATUS_REPORT_NSR = 0
+PYTHAGORAS_SET_SLA_RESP_SIZE = 10
 
 # Random values found in PMC code
-SLA_gr_bw_gros = 1;
-SLA_be_bw_gros = 10;
-SLA_gr_bw_fine = 0;
+SLA_gr_bw_gros = 30
+SLA_be_bw_gros = 300
+SLA_gr_bw_fine = 0
 SLA_be_bw_fine = 0
 
+PON_MAX_DS_POLICING_CONFIGURATION_INDEX = 255
+PMC_OFAL_NO_POLICY = PON_MAX_DS_POLICING_CONFIGURATION_INDEX+1
+
+#Enum classes to set alarm parameters
+
+class AlarmEventType(Enum):
+    COMMUNICATION = 0
+    ENVIRONMENT = 1
+    EQUIPTMENT = 2
+    SERVICE = 3
+    PROCESSING = 4
+    SECURITY = 5
+
+class AlarmEventCategory(Enum):
+    PON = 0
+
+class AlarmEventState(Enum):
+    RAISED = 1
+    CLEARED = 0
+
+class AlarmEventSeverity(Enum):
+    INDETERMINATE = 0
+    WARNING = 1
+    MINOR = 2
+    MAJOR = 3
+    CRITICAL = 4
+
+AlarmEventStateDefault = 1
+
+UPSTREAM = 1
+DOWNSTREAM = 2
+
+PASCOMM_RETRIES = 5
 
diff --git a/voltha/adapters/microsemi_olt/microsemi_olt.py b/voltha/adapters/microsemi_olt/microsemi_olt.py
index cf30317..b37b0b6 100644
--- a/voltha/adapters/microsemi_olt/microsemi_olt.py
+++ b/voltha/adapters/microsemi_olt/microsemi_olt.py
@@ -25,7 +25,10 @@
 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
 from voltha.adapters.microsemi_olt.PAS5211_comm import PAS5211Communication
 from voltha.extensions.omci.omci_frame import OmciFrame
 from voltha.extensions.omci.omci_messages import OmciMessage
@@ -35,9 +38,43 @@
 from voltha.protos.device_pb2 import DeviceTypes, DeviceType
 from voltha.protos.health_pb2 import HealthStatus
 from voltha.registry import registry
-
 from zope.interface import implementer
 
+import voltha.core.flow_decomposer as fd
+
+from voltha.protos.openflow_13_pb2 import OFPPF_1GB_FD, OFPPF_FIBER, ofp_port, OFPPS_LIVE, OFPXMC_OPENFLOW_BASIC
+
+from voltha.protos.openflow_13_pb2 import Flows, FlowGroups
+
+from voltha.adapters.microsemi_olt.PAS5211 import PAS5211GetOnuAllocs, PAS5211GetOnuAllocsResponse, PAS5211GetSnInfo, \
+    PAS5211GetSnInfoResponse, PAS5211GetOnusRange, PAS5211GetOnusRangeResponse, PAS5211MsgSetOnuOmciPortId, \
+    PAS5211MsgSetOnuOmciPortIdResponse, PAS5211MsgSetOnuAllocId, PAS5211MsgSetOnuAllocIdResponse, \
+    PAS5211SetSVlanAtConfig, PAS5211SetSVlanAtConfigResponse, PAS5211SetVlanDownConfig, \
+    PAS5211SetVlanDownConfigResponse, PAS5211SetDownVlanHandl, PAS5211SetDownVlanHandlResponse, \
+    PAS5211SetUplinkVlanHandl, PAS5211SetDownstreamPolicingConfigResponse, PAS5211SetDownstreamPolicingConfig, \
+    PAS5211SetPortIdPolicingConfig, PAS5211UnsetPortIdPolicingConfig, \
+    PAS5211MsgSendDbaAlgorithmMsg, PAS5211MsgSendDbaAlgorithmMsgResponse, \
+    PAS5211SetUpstreamPolicingConfigResponse, PAS5211SetUpstreamPolicingConfig, \
+    PAS5211MsgSetPortIdConfig, PAS5211MsgSetPortIdConfigResponse, \
+    PAS5211MsgGetOnuIdByPortId, PAS5211MsgGetOnuIdByPortIdResponse, \
+    PAS5211SetVlanUplinkConfiguration, PAS5211SetVlanUplinkConfigurationResponse, PAS5211SetUplinkVlanHandlResponse, PAS5211SetVlanGenConfig, PAS5211SetVlanGenConfigResponse, \
+    PAS5211GetPortIdDownstreamPolicingConfig, PAS5211GetPortIdDownstreamPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfig, \
+    PAS5211MsgHeader, PAS5211UnsetPortIdPolicingConfigResponse, PAS5211RemoveDownstreamPolicingConfigResponse, \
+    PAS5211SetPortIdPolicingConfigResponse
+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, \
+    PON_OUTPUT_VLAN_PRIO_HANDLE_DL_VLAN_TABLE, PON_DL_VLAN_SVLAN_REMOVE, PON_DL_VLAN_CVLAN_NO_CHANGE, \
+    PON_VLAN_DEST_DATAPATH, GEM_DIR_BIDIRECT, OMCI_MAC_BRIDGE_PCD_LANFCS_FORWARDED, \
+    OMCI_MAC_BRIDGE_PCD_ENCAP_METHOD_LLC, OMCI_8021P_MSP_UNMARKED_FRAME_TAG_FRAME, OMCI_8021P_MSP_TP_TYPE_NULL, \
+    OMCI_EX_VLAN_TAG_OCD_ASSOCIATION_TYPE_PPTP_ETH_UNI, OMCI_EX_VLAN_TAG_OCD_DS_MODE_US_INVERSE, PMC_UPSTREAM_PORT, \
+    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
+
+from twisted.internet import reactor
+from twisted.internet.defer import DeferredQueue, inlineCallbacks, returnValue
+
 log = structlog.get_logger()
 _ = third_party
 
@@ -58,25 +95,23 @@
     def __init__(self, adaptor_agent, config):
         self.adaptor_agent = adaptor_agent
         self.config = config
-        self.olts = {}
+        self.device_handlers = dict()
         self.descriptor = Adapter(
             id=self.name,
             vendor='Microsemi / Celestica',
-            version='0.1',
+            version='0.2',
             config=AdapterConfig(log_level=LogLevel.INFO)
         )
 
-        self.interface = registry('main').get_args().interface
-
     def start(self):
-        log.info('starting')
+        log.debug('starting')
         log.info('started')
         return self
 
     def stop(self):
         log.debug('stopping')
-        for target in self.olts.keys():
-            self._abandon(target)
+        for handler in self.device_handlers:
+            handler.stop()
         log.info('stopped')
         return self
 
@@ -93,23 +128,15 @@
         raise NotImplementedError()
 
     def adopt_device(self, device):
-        device_manager = DeviceManager(device, self.adaptor_agent)
-        target = device.mac_address
-        comm = PAS5211Communication(dst_mac=target, iface=self.interface)
-        olt = OltStateMachine(iface=self.interface, comm=comm,
-                              target=target, device=device_manager)
-        activation = ActivationWatcher(iface=self.interface, comm=comm,
-                                       target=target, device=device_manager)
-        reactor.callLater(0, self._init_olt, olt, activation)
-
-        log.info('adopted-device', device=device)
-        self.olts[target] = (olt, activation, comm)
+        log.debug('adopt-device', device=device)
+        self.device_handlers[device.id] = RubyAdapterHandler(self.adaptor_agent, self.config, self.descriptor)
+        reactor.callLater(0, self.device_handlers[device.id].activate, device)
 
     def reconcile_device(self, device):
         raise NotImplementedError()
 
     def abandon_device(self, device):
-        self._abandon(device.mac_address)
+        self.stop()
 
     def disable_device(self, device):
         raise NotImplementedError()
@@ -123,52 +150,6 @@
     def reboot_device(self, device):
         raise NotImplementedError()
 
-    def download_image(self, device, request):
-        raise NotImplementedError()
-
-    def get_image_download_status(self, device, request):
-        raise NotImplementedError()
-
-    def cancel_image_download(self, device, request):
-        raise NotImplementedError()
-
-    def activate_image_update(self, device, request):
-        raise NotImplementedError()
-
-    def revert_image_update(self, device, request):
-        raise NotImplementedError()
-
-    def self_test_device(self, device):
-        """
-        This is called to Self a device based on a NBI call.
-        :param device: A Voltha.Device object.
-        :return: Will return result of self test
-        """
-        log.info('self-test-device', device=device.id)
-        raise NotImplementedError()
-
-    def delete_device(self, device):
-        raise NotImplementedError()
-
-    def get_device_details(self, device):
-        raise NotImplementedError()
-
-    def update_flows_bulk(self, device, flows, groups):
-        log.debug('bulk-flow-update', device_id=device.id,
-                  flows=flows, groups=groups)
-
-    def create_interface(self, device, data):
-        raise NotImplementedError()
-
-    def update_interface(self, device, data):
-        raise NotImplementedError()
-
-    def remove_interface(self, device, data):
-        raise NotImplementedError()
-
-    def receive_onu_detect_state(self, device_id, state):
-        raise NotImplementedError()
-
     def create_tcont(self, device, tcont_data, traffic_descriptor_data):
         raise NotImplementedError()
 
@@ -205,39 +186,72 @@
     def remove_multicast_distribution_set(self, device, data):
         raise NotImplementedError()
 
+    def download_image(self, device, request):
+        raise NotImplementedError()
+
+    def get_image_download_status(self, device, request):
+        raise NotImplementedError()
+
+    def cancel_image_download(self, device, request):
+        raise NotImplementedError()
+
+    def activate_image_update(self, device, request):
+        raise NotImplementedError()
+
+    def revert_image_update(self, device, request):
+        raise NotImplementedError()
+
+    def self_test_device(self, device):
+        log.debug('self-test-device', device=device.id)
+        raise NotImplementedError()
+
+    def delete_device(self, device):
+        raise NotImplementedError()
+
+    def get_device_details(self, device):
+        raise NotImplementedError()
+
+    def update_flows_bulk(self, device, flows, groups):
+        try:
+            log.debug('olt-bulk-flow-update', device_id=device.id,
+                  flows=flows, groups=groups)
+
+            handler = self.device_handlers[device.id]
+            if handler:
+                handler.update_flow_table(device, flows)
+            else:
+                log.debug("No handler found for device {}".format(device.id))
+
+        except Exception as e:
+            log.exception('failed-olt-bulk-flow-update', e=e)
+
+
+    def create_interface(self, device, data):
+        raise NotImplementedError()
+
+    def update_interface(self, device, data):
+        raise NotImplementedError()
+
+    def remove_interface(self, device, data):
+        raise NotImplementedError()
+
+    def receive_onu_detect_state(self, device_id, state):
+        raise NotImplementedError()
+
     def send_proxied_message(self, proxy_address, msg):
+        log.debug("send-proxied-message-olt", proxy_address=proxy_address)
         device = self.adaptor_agent.get_device(proxy_address.device_id)
-        _, _, comm = self.olts[device.mac_address]
-        if isinstance(msg, OmciFrame):
-            log.info('send-omci-proxied-message', proxy_address=proxy_address, device=device)
-            # TODO make this more efficient
-            omci_proxy = OMCIProxy(proxy_address=proxy_address,
-                                   msg=msg,
-                                   adapter_agent=self.adaptor_agent,
-                                   target=device.mac_address,
-                                   comm=comm,
-                                   iface=self.interface)
-            omci_proxy.runbg()
-
-
-        else:
-            log.info('send-proxied-message', proxy_address=proxy_address)
-            api_proxy = APIProxy(proxy_address=proxy_address,
-                                 msg=msg,
-                                 adapter_agent=self.adaptor_agent,
-                                 target=device.mac_address,
-                                 comm=comm,
-                                 iface=self.interface)
-            api_proxy.runbg()
+        self.device_handlers[device.id].send_proxied_message(proxy_address, msg)
 
     def receive_proxied_message(self, proxy_address, msg):
+        log.debug("receive-proxied-message-olt-handler", proxy_address=proxy_address)
         raise NotImplementedError()
 
     def update_flows_incrementally(self, device, flow_changes, group_changes):
         raise NotImplementedError()
 
     def receive_packet_out(self, logical_device_id, egress_port_no, msg):
-        log.info('packet-out', logical_device_id=logical_device_id,
+        log.debug('packet-out', logical_device_id=logical_device_id,
                  egress_port_no=egress_port_no, msg_len=len(msg))
 
     def receive_inter_adapter_message(self, msg):
@@ -249,21 +263,289 @@
     def unsuppress_alarm(self, filter):
         raise NotImplementedError()
 
-    ##
-    # Private methods
-    ##
-    def _init_olt(self, olt, activation_watch):
+class RubyAdapterHandler(object):
+
+    name = "microsemi_olt"
+
+    supported_device_types = [
+        DeviceType(
+            id=name,
+            adapter=name,
+            accepts_bulk_flow_update=True
+        )
+    ]
+
+    def __init__(self, adaptor_agent, config, descriptor):
+        self.adaptor_agent = adaptor_agent
+        self.config = config
+        self.descriptor = descriptor
+        self.device = None
+        self.device_manager = None
+        self.comm = None
+        self.activation = None
+        self.olt = None
+        self.ports = dict()
+        self.last_iteration_ports = []
+        self.interface = registry('main').get_args().interface
+
+    def stop(self):
+        log.debug('stopping')
+        self._abandon(self.target)
+        log.info('stopped')
+        return self
+
+    def activate(self, device):
+        log.debug('activate-device', device=device)
+        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,
+                              target=self.target, device=self.device_manager)
+        activation = ActivationWatcher(iface=self.interface, comm=self.comm,
+                                target=self.target, device=self.device_manager, olt_adapter=self)
         olt.runbg()
-        activation_watch.runbg()
+        activation.runbg()
+
+        self.olt = olt
+
+    def abandon_device(self, device):
+        self._abandon(self.target)
+
+    def get_port_list(self, flows):
+        port_list = []
+        for flow in flows:
+            _in_port = fd.get_in_port(flow)
+            if _in_port not in (0, PMC_UPSTREAM_PORT):
+                if _in_port not in port_list:
+                    port_list.append(_in_port)
+                    log.debug('field-type-in-port', in_port=_in_port, port_list=port_list)
+        return port_list
+
+    def get_svlan(self, port, flows):
+        svlan_id = None
+        for flow in flows:
+            _in_port = fd.get_in_port(flow)
+            if _in_port == PMC_UPSTREAM_PORT:
+                log.debug('svlan-port-match')
+                metadata = fd.get_metadata(flow)
+                if metadata:
+                    if metadata == port:
+                        svlan_id = self.get_vlan(flow) & 0xfff
+                        log.debug('SVLAN found:{}'.format(svlan_id))
+
+        return svlan_id
+
+    def get_cvlan(self, svlan_id, port, flows):
+        cvlan_id = None
+        # Look for cvlan ...
+        for flow in flows:
+            _in_port = fd.get_in_port(flow)
+            if _in_port == port:
+                log.debug('cvlan-port-match')
+                for action in fd.get_actions(flow):
+                    if action.type == fd.SET_FIELD:
+                        vlan = action.set_field.field.ofb_field.vlan_vid & 0xfff
+                        if vlan == svlan_id:
+                            cvlan_id = self.get_vlan(flow) & 0xfff
+                            log.debug('CVLAN found:{}'.format(cvlan_id))
+        return cvlan_id
+
+    def get_uplink_bandwidth(self, cvlan_id, svlan_id, port, flows):
+        bandwidth = None
+        # Look for cvlan ...
+        for flow in flows:
+            _in_port = fd.get_in_port(flow)
+            if _in_port == port:
+                log.debug('uplink-bandwidth-port-match')
+                for action in fd.get_actions(flow):
+                    if action.type == fd.SET_FIELD:
+                        vlan = action.set_field.field.ofb_field.vlan_vid & 0xfff
+                        if vlan == svlan_id:
+                            bandwidth = fd.get_metadata(flow)
+                            if bandwidth:
+                                log.debug('Bandwidth found:{}'.format(bandwidth))
+        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
+
+    def update_flow_table(self, device, 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 ...
+            port_list = self.get_port_list(flows.items)
+
+            new_ports = set(port_list)-set(self.last_iteration_ports)
+            log.debug("new-ports", new_ports=new_ports)
+
+            disconnected_ports = set(self.last_iteration_ports)-set(port_list)
+            log.debug("disconnected-ports", disconnected_ports=disconnected_ports)
+
+            # For those new ports, check if we can proceed with flow installation...
+            for port in new_ports:
+                # Got svlan for that port ...
+                svlan_id = self.get_svlan(port, flows.items)
+
+                # ... look for the corresponding cvlan...
+                if svlan_id:
+                    cvlan_id = self.get_cvlan(svlan_id, port, flows.items)
+
+                # Both vlan found!
+                if svlan_id and cvlan_id:
+
+                    # Get bandwidths from flow info...
+                    uplink_bandwidth = self.get_uplink_bandwidth(cvlan_id, svlan_id, port, flows.items)
+                    if uplink_bandwidth == None:
+                        uplink_bandwidth = SLA_be_bw_gros
+
+                    downlink_bandwidth = self.get_downlink_bandwidth(cvlan_id, svlan_id, port, flows.items)
+                    if downlink_bandwidth == None:
+                        downlink_bandwidth = SLA_be_bw_gros
+
+                    onu_id = self.ports[port]['onu_id']
+                    onu_session_id = self.ports[port]['onu_session_id']
+                    port_id = 1000 + 16 * onu_id
+                    alloc_id = port_id
+                    channel_id= port / 32
+
+                    # Check if flow is already installed, if so, continue with next port
+                    if self.ports[port].get('cvlan') and self.ports[port].get('svlan'):
+                        if self.ports[port].get('svlan') == svlan_id:
+                            # Flow already installed
+                            if self.ports[port].get('cvlan') == cvlan_id:
+                                continue
+                            # We have new VLANs so we reinstall!
+                            else:
+                                self.reinstall_flows_sequence(device, onu_id, svlan_id, cvlan_id, port_id,
+                                    alloc_id, onu_session_id, channel_id, uplink_bandwidth, downlink_bandwidth)
+                        else:
+                            # New installation...
+                            self.install_flows_sequence(device, onu_id, svlan_id, cvlan_id, port_id,
+                                alloc_id, onu_session_id, channel_id, uplink_bandwidth, downlink_bandwidth)
+                    else:
+                        # New installation...
+                        self.install_flows_sequence(device, onu_id, svlan_id, cvlan_id, port_id,
+                            alloc_id, onu_session_id, channel_id, uplink_bandwidth, downlink_bandwidth)
+
+                    self.ports[port]['svlan'] = svlan_id
+                    self.ports[port]['cvlan'] = cvlan_id
+
+                else:
+                    # Finally, it is an incomplete port, so we remove from port list
+                    port_list.remove(port)
+
+            # For those ports without flows, uninstall them
+            for port in disconnected_ports:
+
+                onu_id = self.ports[port]['onu_id']
+                onu_session_id = self.ports[port]['onu_session_id']
+                port_id = 1000 + 16 * onu_id
+                alloc_id = port_id
+                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, 
+                        channel_id)
+                    self.ports[port]['svlan'] = None
+                    self.ports[port]['cvlan'] = None
+
+            self.last_iteration_ports = port_list
+
+        except Exception as e:
+            log.exception('failed-to-olt-update-flow-table', e=e)
+
+    def get_vlan(self, flow):
+        for field in fd.get_ofb_fields(flow):
+            if field.type == fd.VLAN_VID:
+                return field.vlan_vid
+        return None
+
+    def reinstall_flows_sequence(self, device, onu_id, svlan, cvlan, port_id,
+            alloc_id, onu_session_id, channel_id, uplink_bandwidth, downlink_bandwidth):
+        log.debug('init-flow-reinstallaton')
+        try:
+            olt = OltReinstallFlowStateMachine(iface=self.interface, comm=self.comm,
+                    target=self.target, device=self.device_manager, onu_id=onu_id,
+                    channel_id=channel_id, port_id=port_id, onu_session_id=onu_session_id,
+                    alloc_id=alloc_id, svlan_id=svlan, cvlan_id=cvlan,
+                    uplink_bandwidth=uplink_bandwidth, downlink_bandwidth=downlink_bandwidth)
+            olt.runbg()
+        except Exception as e:
+            log.exception('failed-to-launch-reinstall-flow', e=e)
+
+    def install_flows_sequence(self, device, onu_id, svlan, cvlan, port_id,
+            alloc_id, onu_session_id, channel_id, uplink_bandwidth, downlink_bandwidth):
+        log.debug('init-flow-installaton')
+        try:
+            olt = OltInstallFlowStateMachine(iface=self.interface, comm=self.comm,
+                    target=self.target, device=self.device_manager, onu_id=onu_id,
+                    channel_id=channel_id, port_id=port_id, onu_session_id=onu_session_id,
+                    alloc_id=alloc_id, svlan_id=svlan, cvlan_id=cvlan,
+                    uplink_bandwidth=uplink_bandwidth, downlink_bandwidth=downlink_bandwidth)
+            olt.runbg()
+        except Exception as e:
+            log.exception('failed-to-launch-install-flow', e=e)
+
+    def uninstall_flows_sequence(self, device, onu_id, port_id, alloc_id, onu_session_id,
+            channel_id):
+        log.debug('init-flow-deinstallaton')
+        try:
+            olt = OltRemoveFlowStateMachine(iface=self.interface, comm=self.comm,
+                    target=self.target, device=self.device_manager, onu_id=onu_id,
+                    channel_id=channel_id, port_id=port_id, onu_session_id=onu_session_id,
+                    alloc_id=alloc_id)
+            olt.runbg()
+        except Exception as e:
+            log.exception('failed-to-launch-deinstallaton-flow', e=e)
 
     def _abandon(self, target):
-        olt, activation, _ = self.olts[target]
-        olt.stop()
-        activation.stop()
-        del self.olts[target]
+        self.olt.stop()
+        self.activation.stop()
 
+    # Method exposed to Activation Watcher to get onu info from Activation
+    def add_onu_info(self, port, onu_id, onu_session_id):
+        existing_port = self.ports.get(port)
+        if existing_port:
+            existing_port['onu_id'] = onu_id
+            existing_port['onu_session_id'] = onu_session_id
+        else:
+            self.ports[port] = {'onu_id': onu_id, 'onu_session_id': onu_session_id}
 
+    def send_proxied_message(self, proxy_address, msg):
+        log.debug("send-proxied-message-olt-handler", proxy_address=proxy_address)
 
+        if isinstance(msg, OmciFrame):
+            omci_proxy = OMCIProxy(proxy_address=proxy_address,
+                                   msg=msg,
+                                   adapter_agent=self.adaptor_agent,
+                                   target=self.device.mac_address,
+                                   comm=self.comm,
+                                   iface=self.interface)
+            omci_proxy.runbg()
 
-
-
+        else:
+            api_proxy = APIProxy(proxy_address=proxy_address,
+                                 msg=msg,
+                                 adapter_agent=self.adaptor_agent,
+                                 target=self.device.mac_address,
+                                 comm=self.comm,
+                                 iface=self.interface)
+            api_proxy.runbg()
\ No newline at end of file