1)Integrating the Edgecore interface configuration with xpon modules in voltha.
2)VOL-255 - Registration and activation of ONU in ASFvolt16 adapter.
3)Add debug print in device state machine when no operation for state change.
3)When ONU is added using XPON command, with admin state down, the admin state of the ONU is DISABLED. Changed the admin state to PREPROVISIONED.
4)Handling of indication as per BAL 2.4 changes.

Change-Id: I49186881a2e006e7075fecf1a1523c256a697069
diff --git a/voltha/adapters/asfvolt16_olt/asfvolt16_device_handler.py b/voltha/adapters/asfvolt16_olt/asfvolt16_device_handler.py
index 462fe37..60ca65e 100644
--- a/voltha/adapters/asfvolt16_olt/asfvolt16_device_handler.py
+++ b/voltha/adapters/asfvolt16_olt/asfvolt16_device_handler.py
@@ -20,8 +20,11 @@
 
 from uuid import uuid4
 from common.frameio.frameio import BpfProgramFilter
+from twisted.internet import reactor
+from scapy.packet import Packet
 from voltha.protos.common_pb2 import OperStatus, ConnectStatus
-from voltha.protos.device_pb2 import Port
+from voltha.protos.device_pb2 import DeviceType, DeviceTypes, Port, Device, \
+    PmConfigs, PmConfig, PmGroupConfig
 from voltha.protos.common_pb2 import AdminState
 from voltha.protos.logical_device_pb2 import LogicalPort, LogicalDevice
 from voltha.protos.openflow_13_pb2 import OFPPS_LIVE, OFPPF_FIBER, \
@@ -30,17 +33,15 @@
 from voltha.core.logical_device_agent import mac_str_to_tuple
 from voltha.adapters.asfvolt16_olt.bal import Bal
 from voltha.adapters.device_handler import OltDeviceHandler
+from voltha.protos.bbf_fiber_base_pb2 import \
+    ChannelgroupConfig, ChannelpartitionConfig, ChannelpairConfig, \
+    ChannelterminationConfig, OntaniConfig, VOntaniConfig, VEnetConfig
 
 # TODO: VLAN ID needs to come from some sort of configuration.
 PACKET_IN_VLAN = 4091
 is_inband_frame = BpfProgramFilter('(ether[14:2] & 0xfff) = 0x{:03x}'.format(
     PACKET_IN_VLAN))
 
-#TODO: hardcoded NNI port ID to be removed once port enumeration is supported.
-nni_port_no = 1
-
-# TODO - hardcoded OLT ID to be removed once multiple OLT devices is supported.
-olt_id = 1
 
 class Asfvolt16Handler(OltDeviceHandler):
     def __init__(self, adapter, device_id):
@@ -74,9 +75,11 @@
             device.model = 'ASFvOLT16'
             device.serial_number = device.host_and_port
             self.adapter_agent.update_device(device)
-    
-            self.add_port(port_no=1, port_type=Port.ETHERNET_NNI)
-            self.logical_device_id = self.add_logical_device(device_id=device.id)
+
+            self.add_port(port_no=1, port_type=Port.ETHERNET_NNI,
+                          label='NNI facing Ethernet port')
+            self.logical_device_id = \
+                self.add_logical_device(device_id=device.id)
             self.add_logical_port(port_no=1,
                                   port_type=Port.ETHERNET_NNI,
                                   device_id=device.id,
@@ -93,19 +96,18 @@
         self.adapter_agent.update_device(device)
 
         # Open the frameio port to receive in-band packet_in messages
-        self.activate_io_port()
 
-    def add_port(self, port_no, port_type):
+    #        self.activate_io_port()
+
+    def add_port(self, port_no, port_type, label):
         self.log.info('adding-port', port_no=port_no, port_type=port_type)
         if port_type is Port.ETHERNET_NNI:
-            label='NNI facing Ethernet port'
-            oper_status=OperStatus.ACTIVE
+            oper_status = OperStatus.ACTIVE
         elif port_type is Port.PON_OLT:
-            label='PON port'
-            #To-Do The pon port status should be ACTIVATING.
-            #For now make the status as Active.
-            oper_status=OperStatus.ACTIVE
-        else :
+            # To-Do The pon port status should be ACTIVATING.
+            # For now make the status as Active.
+            oper_status = OperStatus.ACTIVE
+        else:
             self.log.erro('invalid-port-type', port_type=port_type)
             return
 
@@ -145,18 +147,20 @@
         ld_initialized = self.adapter_agent.create_logical_device(ld)
         return ld_initialized.id
 
-    def add_logical_port(self, port_no, port_type, device_id, logical_device_id):
-        self.log.info('adding-logical-port', port_no=port_no, port_type=port_type, device_id=device_id)
+    def add_logical_port(self, port_no, port_type,
+                         device_id, logical_device_id):
+        self.log.info('adding-logical-port', port_no=port_no,
+                      port_type=port_type, device_id=device_id)
         if port_type is Port.ETHERNET_NNI:
-            label='nni'
+            label = 'nni'
             cap = OFPPF_1GB_FD | OFPPF_FIBER
-            curr_speed=OFPPF_1GB_FD
-            max_speed=OFPPF_1GB_FD
+            curr_speed = OFPPF_1GB_FD
+            max_speed = OFPPF_1GB_FD
         else:
             self.log.erro('invalid-port-type', port_type=port_type)
             return
 
-        ofp=ofp_port(
+        ofp = ofp_port(
             port_no=0,  # is 0 OK?
             hw_addr=mac_str_to_tuple('00:00:00:00:00:%02x' % 129),
             name=label,
@@ -180,42 +184,141 @@
 
     def handle_access_term_ind(self, ind_info):
         device = self.adapter_agent.get_device(self.device_id)
-        if ind_info['actv_status'] == 'success':
+        if ind_info['activation_successful'] is True:
             self.log.info('successful access terminal Indication',
-                                  olt_id=self.olt_id)
+                          olt_id=self.olt_id)
             device.connect_status = ConnectStatus.REACHABLE
             device.oper_status = OperStatus.ACTIVE
             device.reason = 'OLT activated successfully'
             status = self.adapter_agent.update_device(device)
             self.log.info('OLT activation complete')
-            try:
-               #Here we have to add pon_port to OLT device.
-               #Since the create_interface is not called, below code is
-               #added to achive functionality.
-               #self.send_connect_olt(self.olt_id)
-               port_no = 100
-               self.add_port(port_no, port_type=Port.PON_OLT)
-               self.bal.activate_pon_port(self.olt_id, port_no);
-            except Exception as e:
-               return
         else:
             device.oper_status = OperStatus.FAILED
             device.reason = 'Failed to Intialize OLT'
             self.adapter_agent.update_device(device)
-            reactor.callLater(5, self.activate, device)
+            reactor.callLater(15, self.activate, device)
         return
 
-    def handle_subscriber_term_ind(self, ind_info):
-        self.log.info('To-DO Need to handle ONU Indication')
+    def handle_not_started_onu(self, child_device, ind_info):
+        if ind_info['_sub_group_type'] == 'onu_discovery':
+            self.log.info('Onu discovered', olt_id=self.olt_id,
+                          pon_ni=ind_info['_pon_id'], onu_data=ind_info)
+            #To-Do: Need to handle the ONUs, where the admin state is
+            #ENABLED and operation state is in Failed or Unkown
+            self.log.info('Not Yet handled', olt_id=self.olt_id,
+                          pon_ni=ind_info['_pon_id'], onu_data=ind_info)
+        else:
+            self.log.info('Invalid ONU event', olt_id=self.olt_id,
+                          pon_ni=ind_info['_pon_id'], onu_data=ind_info)
+
+    def handle_activating_onu(self, child_device, ind_info):
+        pon_id = ind_info['_pon_id']
+        self.log.info('Not handled Yet', olt_id=self.olt_id,
+                      pon_ni=pon_id, onu_data=ind_info)
+
+    def handle_activated_onu(self, child_device, ind_info):
+        pon_id = ind_info['_pon_id']
+        self.log.info('Not handled Yet', olt_id=self.olt_id,
+                      pon_ni=pon_id, onu_data=ind_info)
+
+    def handle_discovered_onu(self, child_device, ind_info):
+        pon_id = ind_info['_pon_id']
+        if ind_info['_sub_group_type'] == 'onu_discovery':
+            self.log.info('Activation is in progress', olt_id=self.olt_id,
+                          pon_ni=pon_id, onu_data=ind_info,
+                          onu_id=child_device.proxy_address.onu_id)
+
+        elif ind_info['_sub_group_type'] == 'sub_term_indication':
+            self.log.info('ONU activation is completed', olt_id=self.olt_id,
+                          pon_ni=pon_id, onu_data=ind_info)
+
+            msg = {'proxy_address': child_device.proxy_address,
+                   'event': 'activation-completed', 'event_data': ind_info}
+
+            # Send the event message to the ONU adapter
+            self.adapter_agent.publish_inter_adapter_message(child_device.id,
+                                                             msg)
+        else:
+            self.log.info('Invalid ONU event', olt_id=self.olt_id,
+                          pon_ni=ind_info['_pon_id'], onu_data=ind_info)
+
+    onu_handlers = {
+        OperStatus.UNKNOWN: handle_not_started_onu,
+        OperStatus.FAILED: handle_not_started_onu,
+        OperStatus.ACTIVATING: handle_activating_onu,
+        OperStatus.ACTIVE: handle_activated_onu,
+        OperStatus.DISCOVERED: handle_discovered_onu,
+    }
+
+    def handle_sub_term_ind(self, ind_info):
+        child_device = self.adapter_agent.get_child_device(
+            self.device_id,
+            serial_number=(ind_info['_vendor_id'] +
+                           ind_info['_vendor_specific']))
+        if child_device is None:
+            self.log.info('Onu is not configured', olt_id=self.olt_id,
+                          pon_ni=ind_info['_pon_id'], onu_data=ind_info)
+            return
+
+        handler = self.onu_handlers.get(child_device.oper_status)
+        if handler:
+            handler(self, child_device, ind_info)
 
     def send_proxied_message(self, proxy_address, msg):
+        if isinstance(msg, Packet):
+            msg = str(msg)
         try:
             self.bal.send_omci_request_message(proxy_address, msg)
         except Exception as e:
-            return
+            self.log.exception('', exc=str(e))
+        return
 
-def disable(self):
+    def create_interface(self, data):
+        try:
+            if isinstance(data, ChannelterminationConfig):
+                self.log.info('Activating PON port at OLT',
+                              pon_id=data.data.xgs_ponid)
+                self.add_port(port_no=data.data.xgs_ponid,
+                              port_type=Port.PON_OLT,
+                              label=data.name)
+                self.bal.activate_pon_port(self.olt_id, data.data.xgs_ponid)
+            if isinstance(data, VOntaniConfig):
+                serial_number = data.data.expected_serial_number
+                child_device = self.adapter_agent.get_child_device(
+                    self.device_id,
+                    serial_number=serial_number)
+                if child_device is None:
+                    self.log.info('Failed to find ONU Info',
+                                  serial_number=serial_number)
+                elif child_device.admin_state == AdminState.ENABLED:
+                    self.log.info('Activating ONU',
+                                  serial_number=serial_number,
+                                  onu_id=child_device.proxy_address.onu_id,
+                                  pon_id=child_device.parent_port_no)
+                    onu_info = dict()
+                    onu_info['pon_id'] = child_device.parent_port_no
+                    onu_info['onu_id'] = child_device.proxy_address.onu_id
+                    onu_info['vendor'] = child_device.vendor_id
+                    onu_info['vendor_specific'] = serial_number[4:]
+                    self.bal.activate_onu(onu_info)
+                else:
+                    self.log.info('Invalid ONU state to activate',
+                                  onu_id=child_device.proxy_address.onu_id,
+                                  serial_number=serial_number)
+        except Exception as e:
+            self.log.exception('', exc=str(e))
+        return
+
+    def update_interface(self, data):
+        self.log.info('Not Implemented yet')
+        return
+
+    def remove_interface(self, data):
+        self.log.info('Not Implemented yet')
+        return
+
+    def disable(self):
         super(Asfvolt16Handler, self).disable()
 
-def delete(self):
+    def delete(self):
         super(Asfvolt16Handler, self).delete()
diff --git a/voltha/adapters/asfvolt16_olt/asfvolt16_olt.py b/voltha/adapters/asfvolt16_olt/asfvolt16_olt.py
index 25b1b02..1aeaf7f 100644
--- a/voltha/adapters/asfvolt16_olt/asfvolt16_olt.py
+++ b/voltha/adapters/asfvolt16_olt/asfvolt16_olt.py
@@ -25,11 +25,12 @@
 
 log = structlog.get_logger()
 
+
 class Asfvolt16Adapter(OltAdapter):
     def __init__(self, adapter_agent, config):
         super(Asfvolt16Adapter, self).__init__(adapter_agent=adapter_agent,
                                                config=config,
-                                               device_handler_class = Asfvolt16Handler,
+                                               device_handler_class=Asfvolt16Handler,
                                                name='asfvolt16_olt',
                                                vendor='Edgecore',
                                                version='0.1',
diff --git a/voltha/adapters/asfvolt16_olt/asfvolt16_rx_handler.py b/voltha/adapters/asfvolt16_olt/asfvolt16_rx_handler.py
index 067d2fd..6722bc6 100644
--- a/voltha/adapters/asfvolt16_olt/asfvolt16_rx_handler.py
+++ b/voltha/adapters/asfvolt16_olt/asfvolt16_rx_handler.py
@@ -17,24 +17,16 @@
 """
 Asfvolt16 OLT adapter
 """
-
-import structlog
-from twisted.internet.defer import DeferredQueue
-import arrow
-import binascii
 from twisted.internet import reactor
 from common.utils.grpc_utils import twisted_async
-from google.protobuf import empty_pb2
 from voltha.adapters.asfvolt16_olt.protos import bal_indications_pb2
 from voltha.adapters.asfvolt16_olt.protos import bal_msg_type_pb2, \
-     bal_osmsg_pb2, bal_model_ids_pb2, bal_obj_pb2, bal_model_types_pb2, \
-     bal_errno_pb2, bal_pb2
-from voltha.adapters.device_handler import OltDeviceHandler
+    bal_osmsg_pb2, bal_model_ids_pb2, bal_obj_pb2, bal_model_types_pb2, \
+    bal_errno_pb2, bal_pb2
 from voltha.adapters.asfvolt16_olt.grpc_server import GrpcServer
+from voltha.protos.device_pb2 import Device
 
 
-#log = structlog.get_logger()
-
 class Asfvolt16RxHandler(object):
     def __init__(self, adapter, port, log):
         self.adapter = adapter
@@ -46,36 +38,147 @@
 
     def start(self):
         self.grpc_server = GrpcServer(self.grpc_server_port, self, self.log)
-        self.grpc_server.start(bal_indications_pb2.add_BalIndServicer_to_server, self)
+        self.grpc_server.start(
+            bal_indications_pb2.add_BalIndServicer_to_server, self)
 
     def stop(self):
         self.grpc_server.stop()
 
-    def process_flow_ind(self, bal_indication, device_id):
-        self.log.info('Flow indication is not implemented', device_id=device_id)
+    @twisted_async
+    def BalAccTermOperStsCngInd(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'access_terminal_indication'
+        ind_info['_sub_group_type'] = 'oper_state_change'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
 
-    def process_group_ind(self, bal_indication, device_id):
-        self.log.info('Group indication is not implemented', device_id=device_id)
+    @twisted_async
+    def BalAccTermInd(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Received access terminal Indication',
+                      device_id=device_id, obj_type=request.objType)
+        #     ind_info: {'_object_type': <str>
+        #                'actv_status': <str>}
+        ind_info = dict()
+        ind_info['_object_type'] = 'access_terminal_indication'
+        ind_info['_sub_group_type'] = 'access_terminal_indication'
+        if request.access_term_ind.data.admin_state == \
+                bal_model_types_pb2.BAL_STATE_UP:
+            ind_info['activation_successful'] = True
+        else:
+            ind_info['activation_successful'] = False
 
-    def process_interface_ind(self, bal_indication, device_id):
-        self.log.info('Inteface Ind received')
+        reactor.callLater(0,
+                          self.adapter.devices_handlers[device_id].handle_access_term_ind,
+                          ind_info)
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalFlowOperStsCng(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'flow_indication'
+        ind_info['_sub_group_type'] = 'oper_state_change'
+        ind_info['_object_type'] = request.objType
+        ind_info['_sub_group_type'] = request.sub_group
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalFlowInd(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'flow_indication'
+        ind_info['_sub_group_type'] = 'flow_indication'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalGroupInd(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'group_indication'
+        ind_info['_sub_group_type'] = 'group_indication'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalIfaceOperStsCng(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'interface_indication'
+        ind_info['_sub_group_type'] = 'oper_state_change'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalIfaceLos(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'interface_indication'
+        ind_info['_sub_group_type'] = 'loss_of_signal'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalIfaceInd(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Interface indication Received',
+                      device_id=device_id, obj_type=request.objType)
         self.log.info('Awaiting ONU discovery')
-        return
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
 
-    def process_packet_ind(self, bal_indication, device_id):
-        self.log.info('received omci msg')
-        proxy_address=Device.ProxyAddress(
-                      device_id=device_id,
-                      channel_id=bal_indication.balOmciResp.key.packet_send_dest.itu_omci_channel.sub_term_id,  
-                      onu_id=bal_indication.balOmciResp.key.packet_send_dest.itu_omci_channel.sub_term_id,
-                      onu_session_id=bal_indication.balOmciResp.key.packet_send_dest.itu_omci_channel.sub_term_id
-        )
-        self.adapter_agent.receive_proxied_message(proxy_address, bal_indication.balOmciRespInfo.data.pkt.val)
+    @twisted_async
+    def BalIfaceStat(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'interface_indication'
+        ind_info['_sub_group_type'] = 'stat_indication'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
 
-    def process_subscriber_term_ind(self, bal_indication, device_id):
-        onu_data = bal_indication.terminal_disc
-        self.log.info('Subscriber termination message received')
-        #     ind_info: {'object_type': <str>
+    @twisted_async
+    def BalSubsTermOperStsCng(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'sub_term_indication'
+        ind_info['_sub_group_type'] = 'oper_state_change'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalSubsTermDiscoveryInd(self, request, context):
+        #     ind_info: {'object_type': <int>
+        #                '_sub_group_type': <str>
         #                '_device_id': <str>
         #                '_pon_id' : <int>
         #                'onu_id' : <int>
@@ -83,67 +186,158 @@
         #                '__vendor_specific' : <str>
         #                'activation_successful':[True or False]}
 
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Subscriber terminal discovery Indication',
+                      device_id=device_id, obj_type=request.objType)
+        onu_data = request.terminal_disc
         ind_info = dict()
-        ind_info['object_type'] = 'subscriber_terminal'
+        ind_info['_object_type'] = 'sub_term_indication'
+        ind_info['_sub_group_type'] = 'onu_discovery'
         ind_info['_device_id'] = device_id
         ind_info['_pon_id'] = onu_data.key.intf_id
         ind_info['onu_id'] = onu_data.key.sub_term_id
-        ind_info['_vendor_id'] = '4252434D'
-        ind_info['_vendor_specific'] = onu_data.data.serial_number.vendor_specific
-
-        #if(bal_model_types_pb2.BAL_STATE_DOWN == onu_data.data.admin_state):
-        #    ind_info['activation_successful']=False
-        #elif(bal_model_types_pb2.BAL_STATE_UP == onu_data.data.admin_state):
-        #    ind_info['activation_successful']=True
+        ind_info['_vendor_id'] = onu_data.data.serial_number.vendor_id
+        ind_info['_vendor_specific'] = \
+            onu_data.data.serial_number.vendor_specific
         reactor.callLater(0,
-                          self.adapter.devices_handlers[device_id].handle_subscriber_term_ind, 
+                          self.adapter.devices_handlers[device_id].handle_sub_term_ind,
                           ind_info)
-
-    def process_queue_ind(self, bal_indication, device_id):
-        self.log.info('activating-olt', device_id=device_id)
-
-    def process_sched_ind(self, bal_indication, device_id):
-        self.log.info('activating-olt', device_id=device_id)
-
-    def process_access_term_ind(self, bal_indication, device_id):
-        self.log.info('Received access terminal Indication',
-                                  device_id=device_id)
-        #     ind_info: {'object_type': <str>
-        #                'actv_status': <str>}
-        ind_info = dict()
-        ind_info['object_type'] = 'access_terminal'
-        if bal_indication.access_term_ind.data.admin_state != bal_model_ids_pb2.BAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE:
-            ind_info['actv_status'] = 'failed'
-        else:
-            ind_info['actv_status'] = 'success'
-
-        reactor.callLater(0,
-                          self.adapter.devices_handlers[device_id].handle_access_term_ind,
-                          ind_info)
-
-    ind_handlers = {
-        bal_model_ids_pb2.BAL_OBJ_ID_ACCESS_TERMINAL : process_access_term_ind,
-        bal_model_ids_pb2.BAL_OBJ_ID_FLOW            : process_flow_ind,
-        bal_model_ids_pb2.BAL_OBJ_ID_GROUP           : process_group_ind,
-        bal_model_ids_pb2.BAL_OBJ_ID_INTERFACE       : process_interface_ind,
-        bal_model_ids_pb2.BAL_OBJ_ID_PACKET          : process_packet_ind,
-        bal_model_ids_pb2.BAL_OBJ_ID_SUBSCRIBER_TERMINAL : process_subscriber_term_ind,
-        bal_model_ids_pb2.BAL_OBJ_ID_TM_QUEUE        : process_queue_ind,
-        bal_model_ids_pb2.BAL_OBJ_ID_TM_SCHED        : process_sched_ind,
-    }
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
 
     @twisted_async
-    def BalIndInfo(self, request, context):
-        self.log.info('get-device-info')
-        self.log.info('received indication for object type',obj_type=request.objType)
+    def BalSubsTermAlarmInd(self, request, context):
         device_id = request.device_id.decode('unicode-escape')
-        try:
-            handler = self.ind_handlers.get(request.objType)
-            if handler:
-                handler(self, request, device_id)
-        except Exception as e:
-            self.log.exception('Invalid object type', e=e)
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'sub_term_indication'
+        ind_info['_sub_group_type'] = 'alarm_indication'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
 
+    @twisted_async
+    def BalSubsTermDgiInd(self, request, context):
+        self.log.info('Subscriber terminal Indication received')
+        #     ind_info: {'_object_type': <str>
+        #                '_device_id': <str>
+        #                '_pon_id' : <int>
+        #                'onu_id' : <int>
+        #                '_vendor_id' : <str>
+        #                '__vendor_specific' : <str>
+        #                'activation_successful':[True or False]}
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'sub_term_indication'
+        ind_info['_sub_group_type'] = 'dgi_indication'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalSubsTermInd(self, request, context):
+        #     ind_info: {'_object_type': <str>
+        #                '_sub_group_type': <str>
+        #                '_device_id': <str>
+        #                '_pon_id' : <int>
+        #                'onu_id' : <int>
+        #                '_vendor_id' : <str>
+        #                '__vendor_specific' : <str>
+        #                'activation_successful':[True or False]}
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Subscriber terminal indication received',
+                      device_id=device_id, obj_type=request.objType)
+        onu_data = request.terminal_ind
+        ind_info = dict()
+        ind_info['_object_type'] = 'sub_term_indication'
+        ind_info['_sub_group_type'] = 'sub_term_indication'
+        ind_info['_device_id'] = device_id
+        ind_info['_pon_id'] = onu_data.key.intf_id
+        ind_info['onu_id'] = onu_data.key.sub_term_id
+        ind_info['_vendor_id'] = onu_data.data.serial_number.vendor_id
+        ind_info['_vendor_specific'] = \
+            onu_data.data.serial_number.vendor_specific
+        if (bal_model_types_pb2.BAL_STATE_DOWN == onu_data.data.admin_state):
+            ind_info['activation_successful'] = False
+        elif (bal_model_types_pb2.BAL_STATE_UP == onu_data.data.admin_state):
+            ind_info['activation_successful'] = True
+
+        reactor.callLater(0,
+                          self.adapter.devices_handlers[device_id].handle_sub_term_ind,
+                          ind_info)
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalTmQueueIndInfo(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'tm_q_indication'
+        ind_info['_sub_group_type'] = 'tm_q_indication'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalTmSchedIndInfo(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'tm_sched_indication'
+        ind_info['_sub_group_type'] = 'tm_sched_indication'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalPktBearerChannelRxInd(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'packet_in_indication'
+        ind_info['_sub_group_type'] = 'bearer_message'
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalPktOmciChannelRxInd(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Received OMCI Messages',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'packet_in_indication'
+        ind_info['_sub_group_type'] = 'omci_message'
+        packet_data = request.balOmciResp.key.packet_send_dest
+        proxy_address = Device.ProxyAddress(
+            device_id=device_id,
+            channel_id=packet_data.itu_omci_channel.sub_term_id,
+            onu_id=packet_data.itu_omci_channel.sub_term_id,
+            onu_session_id=packet_data.itu_omci_channel.sub_term_id
+        )
+        self.adapter_agent.receive_proxied_message(proxy_address,
+                                                   request.balOmciResp.data.pkt.val)
+        bal_err = bal_pb2.BalErr()
+        bal_err.err = bal_errno_pb2.BAL_ERR_OK
+        return bal_err
+
+    @twisted_async
+    def BalPktIeeeOamChannelRxInd(self, request, context):
+        device_id = request.device_id.decode('unicode-escape')
+        self.log.info('Not implemented yet',
+                      device_id=device_id, obj_type=request.objType)
+        ind_info = dict()
+        ind_info['_object_type'] = 'packet_in_indication'
+        ind_info['_sub_group_type'] = 'ieee_oam_message'
         bal_err = bal_pb2.BalErr()
         bal_err.err = bal_errno_pb2.BAL_ERR_OK
         return bal_err
diff --git a/voltha/adapters/asfvolt16_olt/bal.py b/voltha/adapters/asfvolt16_olt/bal.py
index 2c5c861..95f389c 100644
--- a/voltha/adapters/asfvolt16_olt/bal.py
+++ b/voltha/adapters/asfvolt16_olt/bal.py
@@ -15,12 +15,11 @@
 #
 
 from twisted.internet.defer import inlineCallbacks
-
-from voltha.protos.common_pb2 import OperStatus, ConnectStatus
 from voltha.adapters.asfvolt16_olt.protos import bal_pb2, bal_obj_pb2, \
     bal_model_types_pb2, bal_model_ids_pb2
 from voltha.adapters.asfvolt16_olt.grpc_client import GrpcClient
 
+
 class Bal(object):
     def __init__(self, olt, log):
         self.log = log
@@ -48,51 +47,75 @@
 
     @inlineCallbacks
     def set_access_terminal_admin_state(self, admin_state):
-        #import pdb; pdb.set_trace()
-        self.log.info('setting-admin-state', admin_state=admin_state, device_id=self.device_id)
+        self.log.info('setting-admin-state',
+                      admin_state=admin_state, device_id=self.device_id)
         obj = bal_pb2.BalCfg()
         obj.device_id = self.device_id.encode('ascii', 'ignore')
         obj.hdr.obj_type = bal_model_ids_pb2.BAL_OBJ_ID_ACCESS_TERMINAL
         obj.cfg.key.access_term_id = 0
         obj.cfg.data.admin_state = admin_state
-	yield self.stub.BalCfgSet(obj)
+        yield self.stub.BalCfgSet(obj)
 
     @inlineCallbacks
     def activate_pon_port(self, olt_no, pon_port):
-        self.log.info('activating-pon-port in olt', olt=olt_no, pon_port=pon_port)
+        self.log.info('activating-pon-port in olt',
+                      olt=olt_no, pon_port=pon_port)
         try:
             obj = bal_pb2.BalCfg()
-            #Fill Header details
+            #            Fill Header details
             obj.device_id = self.device_id.encode('ascii', 'ignore')
             obj.hdr.obj_type = bal_model_ids_pb2.BAL_OBJ_ID_INTERFACE
-            #Fill Access Terminal Details
+            #            Fill Access Terminal Details
             obj.interface.key.intf_id = pon_port
             obj.interface.key.intf_type = bal_model_types_pb2.BAL_INTF_TYPE_PON
             obj.interface.data.admin_state = bal_model_types_pb2.BAL_STATE_UP
-	    yield self.stub.BalCfgSet(obj)
+            yield self.stub.BalCfgSet(obj)
         except Exception as e:
             self.log.info('activating-pon-port in olt-exception', exc=str(e))
         return
 
     @inlineCallbacks
     def send_omci_request_message(self, proxy_address, msg):
-        if isinstance(msg, Packet):
-            msg = str(msg)
-
         self.log.info('send_omci_request_message',
                       proxy_address=proxy_address.channel_id,
                       msg=msg)
         try:
             obj = bal_pb2.BalCfg()
-            #Fill Header details
+            #            Fill Header details
             obj.device_id = self.device_id.encode('ascii', 'ignore')
             obj.hdr.obj_type = bal_model_ids_pb2.BAL_OBJ_ID_PACKET
-            #Fill packet Details
-            obj.packet.key.packet_send_dest.type = bal_model_types_pb2.BAL_DEST_TYPE_ITU_OMCI_CHANNEL
-            obj.packet.key.packet_send_dest.itu_omci_channel.sub_term_id = proxy_address.channel_id
+            #            Fill packet Details
+            obj.packet.key.packet_send_dest.type = \
+                bal_model_types_pb2.BAL_DEST_TYPE_ITU_OMCI_CHANNEL
+            obj.packet.key.packet_send_dest.itu_omci_channel.sub_term_id = \
+                proxy_address.channel_id
             obj.packet.key.packet_send_dest.itu_omci_channel.int_id = 0
             obj.packet.data.pkt = msg
-	    yield self.stub.BalCfgSet(obj)
+            yield self.stub.BalCfgSet(obj)
         except Exception as e:
             self.log.info('send-proxied_message-exception', exc=str(e))
         return
+
+    @inlineCallbacks
+    def activate_onu(self, onu_info):
+        self.log.info('activating-ONU in olt',
+                      olt=self.olt.olt_id, onu_id=onu_info['onu_id'])
+        try:
+            obj = bal_pb2.BalCfg()
+            # Fill Header details
+            obj.device_id = self.device_id.encode('ascii', 'ignore')
+            obj.hdr.obj_type = bal_model_ids_pb2.BAL_OBJ_ID_SUBSCRIBER_TERMINAL
+            # Fill Access Terminal Details
+            obj.terminal.key.intf_id = onu_info['pon_id']
+            obj.terminal.key.sub_term_id = onu_info['onu_id']
+            obj.terminal.data.admin_state = bal_model_types_pb2.BAL_STATE_UP
+            obj.terminal.data.serial_number.vendor_id = onu_info['vendor']
+            obj.terminal.data.serial_number.vendor_specific = \
+                onu_info['vendor_specific']
+            obj.terminal.data.registration_id = \
+                '202020202020202020202020202020202020202020202020202020202020202020202020'
+            yield self.stub.BalCfgSet(obj)
+        except Exception as e:
+            self.log.info('activating-ONU-exception',
+                          onu_info['onu_id'], exc=str(e))
+        return
diff --git a/voltha/adapters/asfvolt16_olt/grpc_client.py b/voltha/adapters/asfvolt16_olt/grpc_client.py
index 41f46f6..aad69f1 100644
--- a/voltha/adapters/asfvolt16_olt/grpc_client.py
+++ b/voltha/adapters/asfvolt16_olt/grpc_client.py
@@ -17,6 +17,7 @@
 import grpc
 from grpc._channel import _Rendezvous
 
+
 class GrpcClient(object):
     def __init__(self, log):
         self.channel = None
diff --git a/voltha/adapters/asfvolt16_olt/protos/bal_indications.proto b/voltha/adapters/asfvolt16_olt/protos/bal_indications.proto
index 8dd5fc3..7cb1c35 100644
--- a/voltha/adapters/asfvolt16_olt/protos/bal_indications.proto
+++ b/voltha/adapters/asfvolt16_olt/protos/bal_indications.proto
@@ -22,6 +22,8 @@
 
 message BalIndications{
    BalObjId     objType = 1; //type of object for which the indications have been received
+   uint32       sub_group = 22; //Its a new parameter introduced by broadcom to indicate
+                                //type of an indication within the object Type.
    oneof u {
          BalAccessTerminalInd access_term_ind                        = 2;  // Access Terminal
          BalAccessTerminalOperStatusChange access_term_ind_op_state  = 3;  // Access Terminal Operational State Change
@@ -49,5 +51,23 @@
 service BalInd {
 
       //Handling of bal indications from the device
-      rpc BalIndInfo(BalIndications) returns(BalErr) {}
+      rpc BalAccTermInd(BalIndications) returns(BalErr) {}
+      rpc BalAccTermOperStsCngInd(BalIndications) returns(BalErr) {}
+      rpc BalFlowOperStsCng(BalIndications) returns(BalErr) {}
+      rpc BalFlowInd(BalIndications) returns(BalErr) {}
+      rpc BalGroupInd(BalIndications) returns(BalErr) {}
+      rpc BalIfaceOperStsCng(BalIndications) returns(BalErr) {}
+      rpc BalIfaceLos(BalIndications) returns(BalErr) {}
+      rpc BalIfaceInd(BalIndications) returns(BalErr) {}
+      rpc BalIfaceStat(BalIndications) returns(BalErr) {}
+      rpc BalSubsTermOperStsCng(BalIndications) returns(BalErr) {}
+      rpc BalSubsTermDiscoveryInd(BalIndications) returns(BalErr) {}
+      rpc BalSubsTermAlarmInd(BalIndications) returns(BalErr) {}
+      rpc BalSubsTermDgiInd(BalIndications) returns(BalErr) {}
+      rpc BalSubsTermInd(BalIndications) returns(BalErr) {}
+      rpc BalTmQueueIndInfo(BalIndications) returns(BalErr) {}
+      rpc BalTmSchedIndInfo(BalIndications) returns(BalErr) {}
+      rpc BalPktBearerChannelRxInd(BalIndications) returns(BalErr) {}
+      rpc BalPktOmciChannelRxInd(BalIndications) returns(BalErr) {}
+      rpc BalPktIeeeOamChannelRxInd(BalIndications) returns(BalErr) {}
 }
diff --git a/voltha/adapters/broadcom_onu/broadcom_onu.py b/voltha/adapters/broadcom_onu/broadcom_onu.py
index 86f82ad..968fc42 100644
--- a/voltha/adapters/broadcom_onu/broadcom_onu.py
+++ b/voltha/adapters/broadcom_onu/broadcom_onu.py
@@ -52,6 +52,7 @@
     supported_device_types = [
         DeviceType(
             id=name,
+            vendor_id='BRCM',
             adapter=name,
             accepts_bulk_flow_update=True
         )
@@ -173,20 +174,34 @@
         proxy_address = msg['proxy_address']
         assert proxy_address is not None
 
-        handler = self.devices_handlers[proxy_address.channel_id]
-        handler.event_messages.put(msg)
+        if proxy_address.channel_id in self.devices_handlers:
+            handler = self.devices_handlers[proxy_address.channel_id]
+            if handler is not None:
+                handler.event_messages.put(msg)
 
     def suppress_alarm(self, filter):
         raise NotImplementedError()
 
     def create_interface(self, device, data):
-        raise NotImplementedError()
+        log.info('create-interface', device_id=device.id)
+        if device.proxy_address.channel_id in self.devices_handlers:
+            handler = self.devices_handlers[device.proxy_address.channel_id]
+            if handler is not None:
+                handler.create_interface(data)
 
     def update_interface(self, device, data):
-        raise NotImplementedError()
+        log.info('update-interface', device_id=device.id)
+        if device.proxy_address.channel_id in self.devices_handlers:
+            handler = self.devices_handlers[device.proxy_address.channel_id]
+            if handler is not None:
+                handler.update_interface(data)
 
     def remove_interface(self, device, data):
-        raise NotImplementedError()
+        log.info('remove-interface', device_id=device.id)
+        if device.proxy_address.channel_id in self.devices_handlers:
+            handler = self.devices_handlers[device.proxy_address.channel_id]
+            if handler is not None:
+                handler.remove_interface(data)
 
     def receive_onu_detect_state(self, device_id, state):
         raise NotImplementedError()
@@ -1255,3 +1270,15 @@
         # TODO: add more entries here for other UNI ports
         self.send_create_mac_bridge_port_configuration_data(0x205, 0x201, 5, 1, 0x105)
         yield self.wait_for_response()
+
+    def create_interface(self, data):
+        self.log.info('Not Implemented yet')
+        return;
+
+    def update_interface(self, data):
+        self.log.info('Not Implemented yet')
+        return;
+
+    def remove_interface(self, data):
+        self.log.info('Not Implemented yet')
+        return;
diff --git a/voltha/adapters/device_handler.py b/voltha/adapters/device_handler.py
index 54f1106..15f11eb 100644
--- a/voltha/adapters/device_handler.py
+++ b/voltha/adapters/device_handler.py
@@ -45,6 +45,7 @@
         super(OltDeviceHandler, self).__init__(adapter, device_id)
         self.filter = None
         self.io_port = None
+        self.interface = registry('main').get_args().interface
 
     def __del__(self):
         if self.io_port is not None:
diff --git a/voltha/adapters/iadapter.py b/voltha/adapters/iadapter.py
index eda32f9..686a636 100644
--- a/voltha/adapters/iadapter.py
+++ b/voltha/adapters/iadapter.py
@@ -32,6 +32,7 @@
 
 log = structlog.get_logger()
 
+
 @implementer(IAdapterInterface)
 class IAdapter(object):
     def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version, device_type, vendor_id):
@@ -164,20 +165,35 @@
         raise NotImplementedError()
 
     def create_interface(self, device, data):
-        raise NotImplementedError()
+        log.info('create-interface', device_id=device.id)
+        if device.id in self.devices_handlers:
+            handler = self.devices_handlers[device.id]
+            if handler is not None:
+                handler.create_interface(data)
 
     def update_interface(self, device, data):
-        raise NotImplementedError()
+        log.info('update-interface', device_id=device.id)
+        if device.id in self.devices_handlers:
+            handler = self.devices_handlers[device.id]
+            if handler is not None:
+                handler.update_interface(data)
 
     def remove_interface(self, device, data):
-        raise NotImplementedError()
+        log.info('remove-interface', device_id=device.id)
+        if device.id in self.devices_handlers:
+            handler = self.devices_handlers[device.id]
+            if handler is not None:
+                handler.remove_interface(data)
 
     def receive_onu_detect_state(self, proxy_address, state):
         raise NotImplementedError()
 
+
 """
 OLT Adapter base class
 """
+
+
 class OltAdapter(IAdapter):
     def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version, device_type):
         super(OltAdapter, self).__init__(adapter_agent,
@@ -224,9 +240,12 @@
         handler = self.devices_handlers[device_id]
         handler.packet_out(egress_port_no, msg)
 
+
 """
 ONU Adapter base class
 """
+
+
 class OnuAdapter(IAdapter):
     def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version, device_type, vendor_id):
         super(OnuAdapter, self).__init__(adapter_agent,
diff --git a/voltha/core/adapter_agent.py b/voltha/core/adapter_agent.py
index 9fdc563..4c0b36c 100644
--- a/voltha/core/adapter_agent.py
+++ b/voltha/core/adapter_agent.py
@@ -621,6 +621,7 @@
         self._tx_event_subscriptions[topic] = self.event_bus.subscribe(
             topic, lambda t, m: self._send_proxied_message(proxy_address, m))
 
+
     def get_child_device_with_proxy_address(self, proxy_address):
         # Proxy address is defined as {parent id, channel_id}
         devices = self.root_proxy.get('/devices')
diff --git a/voltha/core/device_agent.py b/voltha/core/device_agent.py
index 64e5d69..224e8ec 100644
--- a/voltha/core/device_agent.py
+++ b/voltha/core/device_agent.py
@@ -281,10 +281,12 @@
                                    AdminState.UNKNOWN)
         new_admin_state = device.admin_state
         self.log.debug('device-admin-states', old_state=old_admin_state,
-                      new_state=new_admin_state, dry_run=dry_run)
+                       new_state=new_admin_state, dry_run=dry_run)
         transition_handler = self.admin_state_fsm.get(
             (old_admin_state, new_admin_state), None)
         if transition_handler is None:
+            self.log.debug('No Operation', old_state=old_admin_state,
+                           new_state=new_admin_state, dry_run=dry_run)
             pass  # no-op
         elif transition_handler is False:
             raise InvalidStateTransition('{} -> {}'.format(
diff --git a/voltha/core/xpon_agent.py b/voltha/core/xpon_agent.py
index 42b08db..3f8d94b 100644
--- a/voltha/core/xpon_agent.py
+++ b/voltha/core/xpon_agent.py
@@ -556,7 +556,7 @@
             vendor_id=vendor_id, proxy_address=proxy_address,
             root=True, serial_number=v_ont_ani.data.expected_serial_number,
             admin_state=AdminState.ENABLED if v_ont_ani.interface.enabled
-                                           else AdminState.DISABLED)
+                                           else AdminState.PREPROVISIONED)
         return
 
     def delete_onu_device(self, olt_device, onu_device):