VOL-911: ADTRAN OLT, remove unused FrameIO/legacy Packet in-out logic

Change-Id: Ibac7cfe08daa41b4e48a9835cb2f10fc1cfebd33
diff --git a/voltha/adapters/adtran_olt/README.md b/voltha/adapters/adtran_olt/README.md
index 5ec8732..73fc9ed 100644
--- a/voltha/adapters/adtran_olt/README.md
+++ b/voltha/adapters/adtran_olt/README.md
@@ -15,6 +15,7 @@
 |  -z   | --zmq_port       | 5656    | ZeroMQ OMCI Proxy Port |
 |  -M   | --multicast_vlan | 4000    | Multicast VLANs (comma-delimeted) |
 |  -v   | --untagged_vlan  | 4092    | VLAN wrapper for untagged ONU frames |
+|  -Z   | --pio_port       | 5657    | PIO Service ZeroMQ Port |
 
 For example, if your Adtran OLT is address 10.17.174.193 with the default TCP ports and
 NETCONF credentials of admin/admin and REST credentials of ADMIN/ADMIN, the command line
@@ -28,8 +29,9 @@
     preprovision_olt -t adtran_olt -i 10.17.174.193 -- --nc_username admin --nc_password admin --rc_username ADMIN --rc_password ADMIN
 ```
 
-Currently the Adtran Device Adapter will enable all PON ports on startup and attempt to activate any discovered ONUs.
-This behaviour will change once PON Management is fully supported.
+Currently the Adtran Device Adapter supports xPON provisioning and to enable PON ports, or activate ONUs, you
+must use the appropriate commands. In the VOLTHA v2.0 release (Q4 2018?), the xPON provisioning will be removed
+from VOLTHA and replaced with Technology Profiles.
 
 ## REST Based Pre-Provisioning
 In addition to CLI provisioning, the Adtran OLT Device Adapter can also be provisioned though the
@@ -38,9 +40,9 @@
 ```bash
 VOLTHA_IP=localhost
 OLT_IP=10.17.174.228
-REST_PORT=`docker inspect compose_chameleon_1 | jq -r '.[0].NetworkSettings.Ports["8881/tcp"][0].HostPort'`
+REST_PORT=`curl -s http://localhost:8500/v1/catalog/service/voltha-envoy-8443 | jq -r '.[0].ServicePort'`
     
-curl -k -s -X POST https://${VOLTHA_IP}:${REST_PORT}/api/v1/local/devices \
+curl -k -s -X POST https://${VOLTHA_IP}:${REST_PORT}/api/v1/devices \
  --header 'Content-Type: application/json' --header 'Accept: application/json' \
  -d "{\"type\": \"adtran_olt\",\"ipv4_address\": \"${OLT_IP}\",\"extra_args\": \"-u admin -p admin -U ADMIN -P ADMIN\"}" \
 | jq '.' | tee /tmp/adtn-olt.json
@@ -48,10 +50,8 @@
 This will not only pre-provision the OLT, but it will also return the created VOLTHA Device ID for use other commands.
 The output is also shown on the console as well:
 
-```bash
-REST_PORT=`docker inspect compose_chameleon_1 | jq -r '.[0].NetworkSettings.Ports["8881/tcp"][0].HostPort'`
-    
-curl -k -s -X POST https://${VOLTHA_IP}:${REST_PORT}/api/v1/local/devices \
+```bash    
+curl -k -s -X POST https://${VOLTHA_IP}:${REST_PORT}/api/v1/devices \
   --header 'Content-Type: application/json' --header 'Accept: application/json' \
   -d "{\"type\": \"adtran_olt\",\"ipv4_address\": \"${OLT_IP}\",\"extra_args\": \"-u admin -p admin -U ADMIN -P ADMIN\"}" \
 | jq '.' | tee /tmp/adtn-olt.json
@@ -86,19 +86,19 @@
 curl -k -s -X POST https://${VOLTHA_IP}:${REST_PORT}/api/v1/local/devices/${DEVICE_ID}/enable
 ```
 ### Other REST APIs
-A full list of URLs supported by VOLTHA can be obtained from the swagger API pointing
-your favorite Internet Browser at: **https://${VOLTHA_IP}:${REST_PORT}/#**
-
 To list out any devices, you can use the following command:
 
 ```bash
-curl -k -s  https://${VOLTHA_IP}:${REST_PORT}/api/v1/local/devices | json_pp
+curl -k -s  https://${VOLTHA_IP}:${REST_PORT}/api/v1/devices | json_pp
+```
+
+Other API endpoints (beyond the /v1/ field above) can be listed with the following command
+
+```bash
+curl -k -s https://${VOLTHA_IP}:${REST_PORT}/api/v1 | json_pp
 ```
 
 # Tested OLT Device Driver versions
 
-The minimum version number of for the OLT software is: *_11971320F1-ML-2287_*
-The specific PON-Agent version number is: _*ngpon2_agent-4.0.37-1.545.702565*_
+The minimum version number of for the OLT software is: *_11971320F1-ML-3309_* or later
 
-At this time, the version numbers above are also the latest ones tested. Work on validating
-newer releases is currently underway.
diff --git a/voltha/adapters/adtran_olt/adtran_device_handler.py b/voltha/adapters/adtran_olt/adtran_device_handler.py
index 7437611..438cb62 100644
--- a/voltha/adapters/adtran_olt/adtran_device_handler.py
+++ b/voltha/adapters/adtran_olt/adtran_device_handler.py
@@ -16,13 +16,11 @@
 """
 import argparse
 import datetime
-import pprint
 import shlex
 import time
 
 import arrow
 import structlog
-import json
 from twisted.internet import reactor, defer
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python.failure import Failure
@@ -31,22 +29,15 @@
 from voltha.adapters.adtran_olt.net.adtran_rest import AdtranRestClient
 from voltha.protos import third_party
 from voltha.protos.common_pb2 import OperStatus, AdminState, ConnectStatus
-from voltha.protos.device_pb2 import Image
 from voltha.protos.logical_device_pb2 import LogicalDevice
 from voltha.protos.openflow_13_pb2 import ofp_desc, ofp_switch_features, OFPC_PORT_STATS, \
     OFPC_GROUP_STATS, OFPC_TABLE_STATS, OFPC_FLOW_STATS
-from voltha.registry import registry
 from alarms.adapter_alarms import AdapterAlarms
-from common.frameio.frameio import BpfProgramFilter
 from pki.olt_pm_metrics import OltPmMetrics
 from common.utils.asleep import asleep
-from scapy.layers.l2 import Ether, Dot1Q
-from scapy.layers.inet import Raw
 
 _ = third_party
 
-DEFAULT_PACKET_IN_VLAN = 4000
-DEFAULT_POC_3_MULTICAST_VLAN = 4050
 DEFAULT_MULTICAST_VLAN = 4000
 DEFAULT_UTILITY_VLAN = 4094
 DEFAULT_UNTAGGED_VLAN = DEFAULT_UTILITY_VLAN    # if RG does not send priority tagged frames
@@ -60,8 +51,6 @@
 _DEFAULT_NETCONF_PASSWORD = ""
 _DEFAULT_NETCONF_PORT = 830
 
-FIXED_ONU = False  # TODO: Deprecate this.  Enhanced ONU support
-
 
 class AdtranDeviceHandler(object):
     """
@@ -108,20 +97,15 @@
         self.adapter_agent = adapter.adapter_agent
         self.device_id = device_id
         self.log = structlog.get_logger(device_id=device_id)
-        self.startup = None  # Startup/reboot defeered
+        self.startup = None  # Startup/reboot deferred
         self.channel = None  # Proxy messaging channel with 'send' method
-        self.io_port = None
         self.logical_device_id = None
-        self.interface = registry('main').get_args().interface
         self.pm_metrics = None
         self.alarms = None
-        self.packet_in_vlan = DEFAULT_PACKET_IN_VLAN
         self.multicast_vlans = [DEFAULT_MULTICAST_VLAN]
         self.untagged_vlan = DEFAULT_UNTAGGED_VLAN
         self.utility_vlan = DEFAULT_UTILITY_VLAN
         self.default_mac_addr = '00:13:95:00:00:00'
-        self._is_inband_frame = None                    # TODO: Deprecate after PIO available
-        self.exception_gems = FIXED_ONU
         self._rest_support = None
 
         # Northbound and Southbound ports
@@ -169,7 +153,6 @@
 
         # Installed flows
         self._evcs = {}  # Flow ID/name -> FlowEntry
- 
 
     def _delete_logical_device(self):
         ldi, self.logical_device_id = self.logical_device_id, None
@@ -189,7 +172,6 @@
         if ldi in self.adapter.logical_device_id_to_root_device_id:
             del self.adapter.logical_device_id_to_root_device_id[ldi]
 
-
     def __del__(self):
         # Kill any startup or heartbeat defers
 
@@ -202,8 +184,6 @@
         if h is not None and not h.called:
             h.cancel()
 
-        self._deactivate_io_port()
-
         # Remove the logical device
         self._delete_logical_device()
 
@@ -282,20 +262,14 @@
                             help='VLAN for Untagged Frames from ONUs'),
         parser.add_argument('--utility_vlan', '-B', action='store',
                             default='{}'.format(DEFAULT_UTILITY_VLAN),
-                            help='VLAN for Untagged Frames from ONUs'),
-        parser.add_argument('--no_exception_gems', '-X', action='store_true', default=True,
-                            help='Native OpenFlow Packet-In/Out support')
+                            help='VLAN for Untagged Frames from ONUs')
+        parser.add_argument('--deprecated_option', '-X', action='store',
+                            default='not-used', help='Deprecated command')
         try:
             args = parser.parse_args(shlex.split(device.extra_args))
 
-            self.exception_gems = not args.no_exception_gems
-            if self.exception_gems:
-                self._is_inband_frame = BpfProgramFilter('(ether[14:2] & 0xfff) = 0x{:03x}'.
-                                                         format(self.packet_in_vlan))
-                self.multicast_vlans = [DEFAULT_POC_3_MULTICAST_VLAN]
-            else:
-                # May have multiple multicast VLANs
-                self.multicast_vlans = [int(vid.strip()) for vid in args.multicast_vlan.split(',')]
+            # May have multiple multicast VLANs
+            self.multicast_vlans = [int(vid.strip()) for vid in args.multicast_vlan.split(',')]
 
             self.netconf_username = args.nc_username
             self.netconf_password = args.nc_password
@@ -545,9 +519,6 @@
                 self.adapter_agent.update_device(device)
                 self.logical_device_id = ld_initialized.id
 
-                # finally, open the frameio port to receive in-band packet_in messages
-                self._activate_io_port()
-
                 # Start collecting stats from the device after a brief pause
                 reactor.callLater(10, self.start_kpi_collection, device.id)
 
@@ -862,9 +833,6 @@
         # Get the latest device reference
         device = self.adapter_agent.get_device(self.device_id)
 
-        # Deactivate in-band packets
-        self._deactivate_io_port()
-
         # Drop registration for ONU detection
         # self.adapter_agent.unregister_for_onu_detect_state(self.device.id)
 
@@ -1008,9 +976,6 @@
         # TODO:
         # 1) Restart health check / pings
 
-        # Activate in-band packets
-        self._activate_io_port()
-
         self.log.info('re-enabled', device_id=device.id)
 
         if done_deferred is not None:
@@ -1242,45 +1207,6 @@
 
         self.log.info('deleted', device_id=self.device_id)
 
-    def _activate_io_port(self):
-        if self.packet_in_vlan != 0 and self._is_inband_frame is not None and self.io_port is None:
-            self.log.info('registering-frameio')
-            self.io_port = registry('frameio').open_port(
-                self.interface, self._rcv_io, self._is_inband_frame)
-        else:
-            self.io_port = None
-
-    def _deactivate_io_port(self):
-        io, self.io_port = self.io_port, None
-
-        if io is not None:
-            registry('frameio').close_port(io)
-
-    def _rcv_io(self, port, frame):
-        self.log.debug('received', iface_name=port.iface_name, frame_len=len(frame))
-
-        pkt = Ether(frame)
-        if pkt.haslayer(Dot1Q):
-            outer_shim = pkt.getlayer(Dot1Q)
-
-            if isinstance(outer_shim.payload, Dot1Q):
-                inner_shim = outer_shim.payload
-                cvid = inner_shim.vlan
-                logical_port = cvid
-                popped_frame = (Ether(src=pkt.src, dst=pkt.dst, type=inner_shim.type) /
-                                inner_shim.payload)
-                kw = dict(
-                    logical_device_id=self.logical_device_id,
-                    logical_port_no=logical_port,
-                )
-                self.log.info('sending-packet-in', **kw)
-                self.adapter_agent.send_packet_in(
-                    packet=str(popped_frame), **kw)
-
-            elif pkt.haslayer(Raw):
-                raw_data = json.loads(pkt.getlayer(Raw).load)
-                self.alarms.send_alarm(self, raw_data)
-
     def packet_out(self, egress_port, msg):
         raise NotImplementedError('Overload in a derived class')
 
diff --git a/voltha/adapters/adtran_olt/adtran_olt.py b/voltha/adapters/adtran_olt/adtran_olt.py
index 30f6186..82015b8 100644
--- a/voltha/adapters/adtran_olt/adtran_olt.py
+++ b/voltha/adapters/adtran_olt/adtran_olt.py
@@ -51,7 +51,7 @@
         self.descriptor = Adapter(
             id=self.name,
             vendor='Adtran, Inc.',
-            version='0.14',
+            version='0.15',
             config=AdapterConfig(log_level=LogLevel.INFO)
         )
         log.debug('adtran_olt.__init__', adapter_agent=adapter_agent)
@@ -345,8 +345,8 @@
         :param groups: An  openflow_v13.Flows object
         :return: (Deferred or None)
         """
-        log.info('bulk-flow-update', device_id=device.id, flows=flows,
-                 groups=groups, num_flows=len(flows.items))
+        log.debug('bulk-flow-update', device_id=device.id, flows=flows,
+                  groups=groups, num_flows=len(flows.items))
         assert len(groups.items) == 0, "Cannot yet deal with groups"
 
         handler = self.devices_handlers.get(device.id)
@@ -556,7 +556,7 @@
         :param data: gemport data object
         :return: None
         """
-        log.info('create-gemport', data=data)
+        log.debug('create-gemport', data=data)
         handler = self.devices_handlers.get(device.id)
         if handler is not None:
             handler.xpon_create(data)
diff --git a/voltha/adapters/adtran_olt/adtran_olt_handler.py b/voltha/adapters/adtran_olt/adtran_olt_handler.py
index 1f21602..3b334e8 100644
--- a/voltha/adapters/adtran_olt/adtran_olt_handler.py
+++ b/voltha/adapters/adtran_olt/adtran_olt_handler.py
@@ -14,7 +14,6 @@
 
 import datetime
 import random
-import json
 import xmltodict
 
 from twisted.internet import reactor
@@ -687,7 +686,7 @@
         :param msg: actual message
         :return: None        """
 
-        if self.pio_port is not None or self.io_port is not None:
+        if self.pio_port is not None:
             from scapy.layers.l2 import Ether, Dot1Q
             from scapy.layers.inet import UDP
             from common.frameio.frameio import hexify
@@ -708,16 +707,7 @@
                 msg = ''.join(bytes)
                 pkt = Ether(msg)
 
-            if self.io_port is not None:
-                out_pkt = (
-                    Ether(src=pkt.src, dst=pkt.dst) /
-                    Dot1Q(vlan=self.packet_in_vlan) /
-                    Dot1Q(vlan=egress_port, type=pkt.type) /
-                    pkt.payload
-                )
-                self.io_port.send(str(out_pkt))
-
-            elif self._pio_agent is not None:
+            if self._pio_agent is not None:
                 port, ctag, vlan_id, evcmapname = FlowEntry.get_packetout_info(self.device_id, egress_port)
                 exceptiontype = None
                 if pkt.type == FlowEntry.EtherType.EAPOL:
@@ -942,7 +932,7 @@
             else:
                 self.log.debug('pon-invalid-or-disabled', pon_id=pon_id)
 
-    def get_onu_vid(self, onu_id):  # TODO: Deprecate this with packet-in/out support
+    def get_onu_vid(self, onu_id):  # TODO: Deprecate this when packet-in/out is supportted and UNI ports on the OLT
         if ATT_NETWORK:
             return (onu_id * 120) + 2
 
@@ -1017,10 +1007,6 @@
             return None, None, None
 
         if flow_entry.flow_direction == FlowEntry.FlowDirection.UPSTREAM:
-            if self.exception_gems:             # FIXED_ONU
-                ingress_port = vid
-                return ingress_port, vid, vid   # TODO: Needs work
-
             # Upstream ACLs will have VID=Logical_port until VOL-460 is addressed
             # but User data flows have the correct VID / C-Tag.
             if flow_entry.is_acl_flow:
@@ -1150,7 +1136,9 @@
 
         self._update_download_status(request, download)
 
-        if request.state != ImageDownload.DOWNLOAD_STARTED:
+        if request.state not in [ImageDownload.DOWNLOAD_STARTED,
+                                 ImageDownload.DOWNLOAD_SUCCEEDED,
+                                 ImageDownload.DOWNLOAD_FAILED]:
             # restore admin state to enabled
             device.admin_state = AdminState.ENABLED
             self.adapter_agent.update_device(device)
@@ -1420,7 +1408,8 @@
     def on_vont_ani_modify(self, vont_ani, update, diffs):
         valid_keys = ['enabled',
                       'expected-serial-number',
-                      'upstream-channel-speed'
+                      'upstream-channel-speed',
+                      'expected-registration-id',
                       ]  # Modify of these keys supported
 
         invalid_key = next((key for key in diffs.keys() if key not in valid_keys), None)
@@ -1441,6 +1430,9 @@
             elif k == 'upstream-channel-speed':
                 for onu in onus:
                     onu.upstream_channel_speed = update[k]
+            elif k == 'expected-registration-id':
+                for onu in onus:
+                    onu.password = update[k].encode('base64')
         return update
 
     def on_vont_ani_delete(self, vont_ani):
diff --git a/voltha/adapters/adtran_olt/alarms/adapter_alarms.py b/voltha/adapters/adtran_olt/alarms/adapter_alarms.py
index 0e2df7c..d74f726 100644
--- a/voltha/adapters/adtran_olt/alarms/adapter_alarms.py
+++ b/voltha/adapters/adtran_olt/alarms/adapter_alarms.py
@@ -72,7 +72,7 @@
             alarm_event = self.adapter.adapter_agent.create_alarm(
                 id=alarm_data.get('id', 'voltha.{}.{}.olt'.format(self.adapter.name,
                                                                   self.device_id)),
-                resource_id=self.device_id,
+                resource_id=str(alarm_data.get('resource_id', self.device_id)),
                 description="{}.{} - {}".format(self.adapter.name, self.device_id,
                                                 alarm_data.get('description')),
                 type=alarm_data.get('type'),
@@ -91,17 +91,20 @@
 class AlarmBase(object):
     def __init__(self, handler, object_type, alarm,
                  alarm_category,
+                 resource_id=None,
                  alarm_type=AlarmEventType.EQUIPMENT,
                  alarm_severity=AlarmEventSeverity.CRITICAL):
+
         self._handler = handler
         self._object_type = object_type
         self._alarm = alarm
         self._alarm_category = alarm_category
         self._alarm_type = alarm_type
         self._alarm_severity = alarm_severity
+        self._resource_id = resource_id
 
     def get_alarm_data(self, status):
-        return {
+        data = {
             'ts': arrow.utcnow().timestamp,
             'description': self._handler.alarms.format_description(self._object_type,
                                                                    self._alarm,
@@ -112,6 +115,9 @@
             'severity': self._alarm_severity,
             'state': AlarmEventState.RAISED if status else AlarmEventState.CLEARED
         }
+        if self._resource_id is not None:
+            data['resource_id'] = self._resource_id
+        return data
 
     def get_context_data(self):
         return {}   # You should override this if needed
diff --git a/voltha/adapters/adtran_olt/alarms/onu_active_alarm.py b/voltha/adapters/adtran_olt/alarms/onu_active_alarm.py
new file mode 100644
index 0000000..61e6825
--- /dev/null
+++ b/voltha/adapters/adtran_olt/alarms/onu_active_alarm.py
@@ -0,0 +1,49 @@
+# Copyright 2017-present Adtran, Inc.
+#
+# 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.
+
+from adapter_alarms import AlarmBase
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+
+
+class OnuActiveAlarm(AlarmBase):
+    def __init__(self, handler, pon_id, serial_number, reg_id):
+        super(OnuActiveAlarm, self).__init__(handler, 'ONU',
+                                             alarm='ONU_ACTIVATED',
+                                             alarm_category=AlarmEventCategory.PON,
+                                             resource_id=pon_id,
+                                             alarm_type=AlarmEventType.EQUIPMENT,
+                                             alarm_severity=AlarmEventSeverity.CRITICAL)
+        self._pon_id = pon_id
+        self._serial_number = serial_number
+        self._device_id = handler.device_id
+        device = handler.adapter_agent.get_device(handler.device_id)
+        self._olt_serial_number = device.serial_number
+        self._host = device.ipv4_address
+        self._datapath_id = device.parent_id
+        self._reg_id = reg_id
+
+    def get_context_data(self):
+        return {
+            'pon-id': self._pon_id,
+            'serial-number': self._serial_number,
+            'host': self._host,
+            'olt_serial_number': self._olt_serial_number,
+            'datapath_id': self._datapath_id,
+            'device_id' : self._device_id,
+            'registration_id' : self._reg_id
+        }
+
+    def clear_alarm(self):
+        raise NotImplementedError('ONU Active Alarms are auto-clear')
+
diff --git a/voltha/adapters/adtran_olt/alarms/onu_discovery_alarm.py b/voltha/adapters/adtran_olt/alarms/onu_discovery_alarm.py
index 8e992f2..c9dd527 100644
--- a/voltha/adapters/adtran_olt/alarms/onu_discovery_alarm.py
+++ b/voltha/adapters/adtran_olt/alarms/onu_discovery_alarm.py
@@ -19,9 +19,10 @@
     def __init__(self, handler, pon_id, serial_number):
         super(OnuDiscoveryAlarm, self).__init__(handler, 'ONU Discovery',
                                                 alarm='Discovery',
-                                                alarm_category=AlarmEventCategory.ONT,
-                                                alarm_type=AlarmEventType.COMMUNICATION,
-                                                alarm_severity=AlarmEventSeverity.MAJOR)
+                                                alarm_category=AlarmEventCategory.PON,
+                                                resource_id=pon_id,
+                                                alarm_type=AlarmEventType.EQUIPMENT,
+                                                alarm_severity=AlarmEventSeverity.CRITICAL)
         self._pon_id = pon_id
         self._serial_number = serial_number
 
diff --git a/voltha/adapters/adtran_olt/codec/olt_state.py b/voltha/adapters/adtran_olt/codec/olt_state.py
index 4e6d6bd..4103a1d 100644
--- a/voltha/adapters/adtran_olt/codec/olt_state.py
+++ b/voltha/adapters/adtran_olt/codec/olt_state.py
@@ -83,8 +83,8 @@
 
         @staticmethod
         def decode(pon_list):
-            log.info('Decoding PON List:{}{}'.format(os.linesep,
-                                                     pprint.PrettyPrinter().pformat(pon_list)))
+            # log.debug('Decoding PON List:{}{}'.format(os.linesep,
+            #                                           pprint.PrettyPrinter().pformat(pon_list)))
             pons = {}
             for pon_data in pon_list:
                 pon = OltState.Pon(pon_data)
@@ -197,8 +197,8 @@
 
             @staticmethod
             def decode(onu_list):
-                log.debug('onus:{}{}'.format(os.linesep,
-                                             pprint.PrettyPrinter().pformat(onu_list)))
+                # log.debug('onus:{}{}'.format(os.linesep,
+                #                              pprint.PrettyPrinter().pformat(onu_list)))
                 onus = {}
                 for onu_data in onu_list:
                     onu = OltState.Pon.Onu(onu_data)
@@ -237,7 +237,6 @@
                 """Distance to ONU"""
                 return self._packet.get('fiber-length', 0)
 
-
         class Gem(object):
             """
             Provides decode of onu list for a PON port
@@ -254,8 +253,8 @@
 
             @staticmethod
             def decode(gem_list):
-                log.debug('gems:{}{}'.format(os.linesep,
-                                             pprint.PrettyPrinter().pformat(gem_list)))
+                # log.debug('gems:{}{}'.format(os.linesep,
+                #                              pprint.PrettyPrinter().pformat(gem_list)))
                 gems = {}
                 for gem_data in gem_list:
                     gem = OltState.Pon.Gem(gem_data)
diff --git a/voltha/adapters/adtran_olt/flow/acl.py b/voltha/adapters/adtran_olt/flow/acl.py
index b2dc21f..10063bd 100644
--- a/voltha/adapters/adtran_olt/flow/acl.py
+++ b/voltha/adapters/adtran_olt/flow/acl.py
@@ -314,7 +314,7 @@
           </access-lists>
         </filter>
         """
-        log.info('query', xml=get_xml, regex=regex_)
+        log.debug('query', xml=get_xml, regex=regex_)
 
         def request_failed(results, operation):
             log.error('{}-failed'.format(operation), results=results)
diff --git a/voltha/adapters/adtran_olt/flow/evc.py b/voltha/adapters/adtran_olt/flow/evc.py
index ebd1f7f..4260c66 100644
--- a/voltha/adapters/adtran_olt/flow/evc.py
+++ b/voltha/adapters/adtran_olt/flow/evc.py
@@ -421,7 +421,7 @@
           </evcs>
         </filter>
         """
-        log.info('query', xml=get_xml, regex=regex_)
+        log.debug('query', xml=get_xml, regex=regex_)
 
         def request_failed(results, operation):
             log.error('{}-failed'.format(operation), results=results)
diff --git a/voltha/adapters/adtran_olt/flow/evc_map.py b/voltha/adapters/adtran_olt/flow/evc_map.py
index f873271..40892aa 100644
--- a/voltha/adapters/adtran_olt/flow/evc_map.py
+++ b/voltha/adapters/adtran_olt/flow/evc_map.py
@@ -528,51 +528,49 @@
         try:
             del self._flows[flow.flow_id]
 
-            if not flow.handler.exception_gems:  # ! FIXED_ONU
-                # Remove any ACLs
+            # Remove any ACLs
+            acl_name = ACL.flow_to_name(flow)
+            acl = None
 
-                acl_name = ACL.flow_to_name(flow)
-                acl = None
+            # if not yet installed just remove it from list
+            if acl_name in self._new_acls:
+                del self._new_acls[acl_name]
+            else:
+                acl = self._existing_acls[acl_name]
+            if acl is not None:
+                # Remove ACL from EVC-MAP entry
 
-                # if not yet installed just remove it from list
-                if acl_name in self._new_acls:
-                    del self._new_acls[acl_name]
-                else:
-                    acl = self._existing_acls[acl_name]
-                if acl is not None:
-                    # Remove ACL from EVC-MAP entry
+                try:
+                    map_xml = self._ingress_remove_acl_xml(self._gem_ids_and_vid, acl)
+                    log.debug('remove', xml=map_xml, name=acl.name)
+                    results = yield self._handler.netconf_client.edit_config(map_xml)
+                    if results.ok:
+                        del self._existing_acls[acl.name]
 
-                    try:
-                        map_xml = self._ingress_remove_acl_xml(self._gem_ids_and_vid, acl)
-                        log.debug('remove', xml=map_xml, name=acl.name)
-                        results = yield self._handler.netconf_client.edit_config(map_xml)
-                        if results.ok:
-                            del self._existing_acls[acl.name]
+                    # Scan EVC to see if it needs to move back to the Utility
+                    # or Untagged EVC from a user data EVC
+                    if self._evc and not self._evc.service_evc and\
+                        len(self._flows) > 0 and\
+                        all(f.is_acl_flow for f in self._flows.itervalues()):
 
-                        # Scan EVC to see if it needs to move back to the Utility
-                        # or Untagged EVC from a user data EVC
-                        if self._evc and not self._evc.service_evc and\
-                            len(self._flows) > 0 and\
-                            all(f.is_acl_flow for f in self._flows.itervalues()):
+                        self._evc.remove_evc_map(self)
+                        first_flow = self._flows.itervalues().next()
+                        self._evc = first_flow.get_utility_evc(None, True)
+                        self._evc.add_evc_map(self)
+                        log.debug('moved-acl-flows-to-utility-evc', newevcname=self._evc.name)
 
-                            self._evc.remove_evc_map(self)
-                            first_flow = self._flows.itervalues().next()
-                            self._evc = first_flow.get_utility_evc(None, True)
-                            self._evc.add_evc_map(self)
-                            log.debug('moved-acl-flows-to-utility-evc', newevcname=self._evc.name)
+                        self._needs_update = True
+                        self._evc.schedule_install()
 
-                            self._needs_update = True
-                            self._evc.schedule_install()
+                except Exception as e:
+                    log.exception('acl-remove-from-evc', e=e)
 
-                    except Exception as e:
-                        log.exception('acl-remove-from-evc', e=e)
+                # Remove ACL itself
+                try:
+                    yield acl.remove()
 
-                    # Remove ACL itself
-                    try:
-                        yield acl.remove()
-
-                    except Exception as e:
-                        log.exception('acl-remove', e=e)
+                except Exception as e:
+                    log.exception('acl-remove', e=e)
 
         except Exception as e:
             log.exception('remove-failed', e=e)
@@ -648,15 +646,10 @@
 
             if pon_port is not None:
                 self._pon_id = pon_port.pon_id
-                exception_gems = self._needs_acl_support and flow.handler.exception_gems  # FIXED_ONU
                 untagged_gem = flow.eth_type == FlowEntry.EtherType.EAPOL and\
                     flow.handler.untagged_vlan != flow.handler.utility_vlan
                 self._gem_ids_and_vid = pon_port.gem_ids(flow.logical_port, untagged_gem,
-                                                         exception_gems,   # FIXED_ONU
                                                          flow.is_multicast_flow)
-                # FIXED_ONU
-                if exception_gems and self._eth_type != FlowEntry.EtherType.EAPOL:
-                    self._gem_ids_and_vid = dict()
 
     def _decode(self, evc):
         from evc import EVC
@@ -710,15 +703,15 @@
         evc.switching_method = EVC.SwitchingMethod.DOUBLE_TAGGED  # \
         #     if self._c_tag is not None else EVC.SwitchingMethod.SINGLE_TAGGED
 
-        if not flow.handler.exception_gems:  # ! FIXED_ONU
-            try:
-                acl = ACL.create(flow)
-                if acl.name not in self._new_acls:
-                    self._new_acls[acl.name] = acl
+        try:
+            acl = ACL.create(flow)
+            if acl.name not in self._new_acls:
+                self._new_acls[acl.name] = acl
 
-            except Exception as e:
-                log.exception('ACL-decoding', e=e)
-                return False
+        except Exception as e:
+            log.exception('ACL-decoding', e=e)
+            return False
+
         return True
 
     # Bulk operations
diff --git a/voltha/adapters/adtran_olt/flow/flow_entry.py b/voltha/adapters/adtran_olt/flow/flow_entry.py
index 7575be8..c578190 100644
--- a/voltha/adapters/adtran_olt/flow/flow_entry.py
+++ b/voltha/adapters/adtran_olt/flow/flow_entry.py
@@ -310,9 +310,6 @@
                 if flow.signature in sig_map_map:
                     # Found an explicity matching existing EVC-MAP. Add flow to this EVC-MAP
                     flow.evc_map = sig_map_map[flow.signature].add_flow(flow, downstream_flow.evc)
-                elif flow.handler.exception_gems:       # FIXED_ONU
-                    # Create a new MAP
-                    flow.evc_map = EVCMap.create_ingress_map(flow, downstream_flow.evc)
                 else:
                     # May need to create a MAP or search for an existing ACL/user EVC-Map
                     upstream_flow_table = _existing_upstream_flow_entries[flow.device_id]
@@ -338,7 +335,7 @@
         return UtilityEVC.create(self, use_default_vlan_id)
 
     @property
-    def _needs_acl_support(self):    # FIXED_ONU- maybe
+    def _needs_acl_support(self):
         if self.ipv4_dst is not None:  # In case MCAST downstream has ACL on it
             return False
 
@@ -364,41 +361,40 @@
                                                                FlowEntry.FlowDirection.OTHER)
 
             # Modify flow entry for newer utility/untagged VLAN support
-            if not self.handler.exception_gems:         # ! FIXED_ONU
-                # New Packet In/Out support
-                if self._flow_direction == FlowEntry.FlowDirection.DOWNSTREAM and\
-                   self.vlan_id in (FlowEntry.LEGACY_CONTROL_VLAN,
-                                    self.handler.untagged_vlan):
-                    # May be for to controller flow downstream (no ethType) or multicast (ethType = IP)
-                    if self.eth_type is None or self._needs_acl_support:
-                        self._is_multicast = False
-                        self._is_acl_flow = True
-                        if self.inner_vid is not None:
-                            logical_port, subscriber_vlan, untagged_vlan = \
-                                self._handler.get_onu_port_and_vlans(self)
-                            self.inner_vid = subscriber_vlan
-                            self.vlan_id = self.handler.utility_vlan
-                        else:
-                            self.vlan_id = self.handler.untagged_vlan
-                elif self._flow_direction == FlowEntry.FlowDirection.UPSTREAM:
-                    try:
-                        # TODO: Need to support flow retry if the ONU is not yet activated   !!!!
-                        # Get the correct logical port and subscriber VLAN for this UNI
-                        self._logical_port, self.vlan_id, untagged_vlan = \
+            # New Packet In/Out support
+            if self._flow_direction == FlowEntry.FlowDirection.DOWNSTREAM and\
+               self.vlan_id in (FlowEntry.LEGACY_CONTROL_VLAN,
+                                self.handler.untagged_vlan):
+                # May be for to controller flow downstream (no ethType) or multicast (ethType = IP)
+                if self.eth_type is None or self._needs_acl_support:
+                    self._is_multicast = False
+                    self._is_acl_flow = True
+                    if self.inner_vid is not None:
+                        logical_port, subscriber_vlan, untagged_vlan = \
                             self._handler.get_onu_port_and_vlans(self)
+                        self.inner_vid = subscriber_vlan
+                        self.vlan_id = self.handler.utility_vlan
+                    else:
+                        self.vlan_id = self.handler.untagged_vlan
+            elif self._flow_direction == FlowEntry.FlowDirection.UPSTREAM:
+                try:
+                    # TODO: Need to support flow retry if the ONU is not yet activated   !!!!
+                    # Get the correct logical port and subscriber VLAN for this UNI
+                    self._logical_port, self.vlan_id, untagged_vlan = \
+                        self._handler.get_onu_port_and_vlans(self)
 
-                        if self._needs_acl_support:
-                            self._is_acl_flow = True
-                            if self.eth_type == FlowEntry.EtherType.EAPOL and \
-                                    self.handler.untagged_vlan != self.handler.utility_vlan:
-                                self.vlan_id = None
-                                self.push_vlan_id[0] = self.handler.untagged_vlan
-                            else:
-                                self.push_vlan_id[0] = self.handler.utility_vlan
+                    if self._needs_acl_support:
+                        self._is_acl_flow = True
+                        if self.eth_type == FlowEntry.EtherType.EAPOL and \
+                                self.handler.untagged_vlan != self.handler.utility_vlan:
+                            self.vlan_id = None
+                            self.push_vlan_id[0] = self.handler.untagged_vlan
+                        else:
+                            self.push_vlan_id[0] = self.handler.utility_vlan
 
-                    except Exception as e:
-                        # TODO: Need to support flow retry if the ONU is not yet activated   !!!!
-                        log.exception('tag-fixup', e=e)
+                except Exception as e:
+                    # TODO: Need to support flow retry if the ONU is not yet activated   !!!!
+                    log.exception('tag-fixup', e=e)
 
         # Create a signature that will help locate related flow entries on a device.
         # These are not exact, just ones that may be put together to make an EVC. The
@@ -699,7 +695,6 @@
         if device_id in _existing_upstream_flow_entries:
             del _existing_upstream_flow_entries[device_id]
 
-
     @staticmethod
     def get_packetout_info(device_id, logical_port):
         """
@@ -726,12 +721,11 @@
                 if len(gem_ids_and_vid) > 0:
                     for onu_id, gem_ids_with_vid in gem_ids_and_vid.iteritems():
                         log.debug('get-packetout-info', onu_id=onu_id, 
-                                   gem_ids_with_vid=gem_ids_with_vid)
+                                  gem_ids_with_vid=gem_ids_with_vid)
                         if len(gem_ids_with_vid) > 0:
                             gem_ids = gem_ids_with_vid[0]
                             ctag = gem_ids_with_vid[1]
                             gem_id = gem_ids[0]     # TODO: always grab fist in list
                             return flow_entry.in_port, ctag, Onu.gem_id_to_gvid(gem_id), \
                                    evc_map.get_evcmap_name(onu_id, gem_id)
-        return  None, None, None, None
-
+        return None, None, None, None
diff --git a/voltha/adapters/adtran_olt/flow/untagged_evc.py b/voltha/adapters/adtran_olt/flow/untagged_evc.py
index 98f267a..c51459f 100644
--- a/voltha/adapters/adtran_olt/flow/untagged_evc.py
+++ b/voltha/adapters/adtran_olt/flow/untagged_evc.py
@@ -85,10 +85,6 @@
             return None
 
     @property
-    def flow_entry(self):
-        return self._flow
-
-    @property
     def downstream_flows(self):
         return frozenset(self._downstream_flows)
 
@@ -113,7 +109,6 @@
         if evc_table is None:
             return defer.succeed('NOP')
 
-
         # Remove flow reference
         if self._flow.flow_id in self._downstream_flows:
             self._downstream_flows.discard(self._flow.flow_id)
@@ -148,7 +143,6 @@
         except Exception as e:
             log.exception('removal', e=e)
 
-
     def reflow(self, reflow_maps=True):
         pass    # TODO: Implement or use base class?
 
diff --git a/voltha/adapters/adtran_olt/flow/utility_evc.py b/voltha/adapters/adtran_olt/flow/utility_evc.py
index 2317b2a..a028f96 100644
--- a/voltha/adapters/adtran_olt/flow/utility_evc.py
+++ b/voltha/adapters/adtran_olt/flow/utility_evc.py
@@ -82,10 +82,6 @@
             return None
 
     @property
-    def flow_entry(self):
-        return self._flow
-
-    @property
     def downstream_flows(self):
         return frozenset(self._downstream_flows)
 
diff --git a/voltha/adapters/adtran_olt/net/rcmd.py b/voltha/adapters/adtran_olt/net/rcmd.py
index e46a9c1..3062b4c 100644
--- a/voltha/adapters/adtran_olt/net/rcmd.py
+++ b/voltha/adapters/adtran_olt/net/rcmd.py
@@ -68,7 +68,8 @@
 
         def connectionLost(self, reason):
             log.debug('connection-lost')
-            self.finished.callback(None)
+            if not self.finished.called:
+                self.finished.callback(reason)
 
     class PermissiveKnownHosts(KnownHostsFile):
         def verifyHostKey(self, ui, hostname, ip, key):
diff --git a/voltha/adapters/adtran_olt/nni_port.py b/voltha/adapters/adtran_olt/nni_port.py
index fac91de..83f113a 100644
--- a/voltha/adapters/adtran_olt/nni_port.py
+++ b/voltha/adapters/adtran_olt/nni_port.py
@@ -94,7 +94,7 @@
         :return: VOLTHA Port object
         """
         self.log.debug('get-port-status-update', port=self._port_no,
-            label=self._label)
+                       label=self._label)
         if self._port is None:
             self._port = Port(port_no=self._port_no,
                               label=self._label,
@@ -106,7 +106,7 @@
            self._port.oper_status != self._oper_status:
 
             self.log.debug('get-port-status-update', admin_state=self._admin_state,
-                oper_status = self._oper_status)
+                           oper_status = self._oper_status)
             self._port.admin_state = self._admin_state
             self._port.oper_status = self._oper_status
 
@@ -129,7 +129,7 @@
     def _update_adapter_agent(self):
         # adapter_agent add_port also does an update of port status
         self.log.debug('update-adapter-agent', admin_state=self._admin_state,
-            oper_status=self._oper_status)
+                       oper_status=self._oper_status)
         self.adapter_agent.add_port(self.olt.device_id, self.get_port())
 
     def get_logical_port(self):
@@ -260,7 +260,7 @@
     def sync_hardware(self):
         if self.state == AdtnPort.State.RUNNING or self.state == AdtnPort.State.STOPPED:
             def read_config(results):
-                self.log.debug('read-config', results=results)
+                #self.log.debug('read-config', results=results)
                 try:
                     result_dict = xmltodict.parse(results.data_xml)
                     interfaces = result_dict['data']['interfaces']
@@ -320,7 +320,7 @@
     def _update_statistics(self):
         if self.state == AdtnPort.State.RUNNING:
             def read_state(results):
-                self.log.debug('read-state', results=results)
+                # self.log.debug('read-state', results=results)
                 try:
                     result_dict = xmltodict.parse(results.data_xml)
                     entry = result_dict['data']['interfaces-state']['interface']
diff --git a/voltha/adapters/adtran_olt/onu.py b/voltha/adapters/adtran_olt/onu.py
index bb31b61..4ec2cb3 100644
--- a/voltha/adapters/adtran_olt/onu.py
+++ b/voltha/adapters/adtran_olt/onu.py
@@ -74,6 +74,7 @@
         self._expedite_count = 0
         self._resync_flows = False
         self._sync_deferred = None     # For sync of ONT config to hardware
+        self._password = None
 
         if onu_info['venet'] is not None:
             port_no, subscriber_vlan, self.untagged_vlan = Onu.decode_venet(onu_info['venet'],
@@ -195,6 +196,30 @@
             self._upstream_channel_speed = value
 
     @property
+    def password(self):
+        """
+        Get password.  Base 64 format
+        """
+        return self._password
+
+    @password.setter
+    def password(self, value):
+        """
+        Set the password
+        :param value: (str) base 64 encoded value
+        """
+        if self._password is None and value is not None:
+            self._password = value
+            # reg_id = value.decode('base64')
+            reg_id = (value.decode('base64')).rstrip('\00').lstrip('\00')
+            # Must remove any non-printable characters
+            reg_id = ''.join([i if ord(i) < 127 and ord(i) > 31 else '_' for i in reg_id])
+            # Generate alarm here for regID
+            from alarms.onu_active_alarm import OnuActiveAlarm
+            self.log.info('onu-Active-Alarm', serial_number=self._serial_number_string)
+            OnuActiveAlarm(self._olt, self._pon_id, self._serial_number_string, reg_id).raise_alarm()
+
+    @property
     def enabled(self):
         return self._enabled
 
@@ -380,8 +405,6 @@
 
         for _, gem_port in gem_ports.items():
             try:
-                gem_port.pon_id = self.pon_id
-                gem_port.onu_id = self.onu_id if self.onu_id is not None else -1
                 yield self.add_gem_port(gem_port, reflow=reflow)
 
             except Exception as e:
@@ -747,6 +770,7 @@
                                                        self._pon_id,
                                                        self._onu_id)
         except RestInvalidResponseCode as e:
+            results = None
             if e.code != 404:
                 self.log.exception('tcont-delete', e=e)
 
@@ -759,19 +783,15 @@
     def gem_port(self, gem_id):
         return self._gem_ports.get(gem_id)
 
-    def gem_ids(self, untagged_gem, exception_gems):  # FIXED_ONU
+    def gem_ids(self, untagged_gem):
         """Get all GEM Port IDs used by this ONU"""
-        if exception_gems:
+        if untagged_gem:
             gem_ids = sorted([gem_id for gem_id, gem in self._gem_ports.items()
-                             if gem.exception and not gem.multicast])
-            return gem_ids
-        elif untagged_gem:
-            gem_ids = sorted([gem_id for gem_id, gem in self._gem_ports.items()
-                             if gem.untagged and not gem.exception and not gem.multicast])
+                             if gem.untagged and not gem.multicast])
             return gem_ids
         else:
             return sorted([gem_id for gem_id, gem in self._gem_ports.items()
-                          if not gem.multicast and not gem.exception and not gem.untagged])
+                          if not gem.multicast and not gem.untagged])
 
     @inlineCallbacks
     def add_gem_port(self, gem_port, reflow=False):
@@ -788,6 +808,8 @@
         if not reflow and gem_port.gem_id in self._gem_ports:
             returnValue('nop')
 
+        gem_port.pon_id = self.pon_id
+        gem_port.onu_id = self.onu_id if self.onu_id is not None else -1
         self.log.info('add', gem_port=gem_port, reflow=reflow)
         self._gem_ports[gem_port.gem_id] = gem_port
 
diff --git a/voltha/adapters/adtran_olt/pki/olt_pm_metrics.py b/voltha/adapters/adtran_olt/pki/olt_pm_metrics.py
index 38e6477..2d1fdf6 100644
--- a/voltha/adapters/adtran_olt/pki/olt_pm_metrics.py
+++ b/voltha/adapters/adtran_olt/pki/olt_pm_metrics.py
@@ -211,7 +211,7 @@
                     port_metrics['pon.{}.onu.{}'.format(port.pon_id, onu.onu_id)] = \
                         self.collect_onu_metrics(onu)
                     for gem in onu.gem_ports:
-                        if gem.multicast or gem.exception:
+                        if gem.multicast:
                             continue
 
                         port_metrics['pon.{}.onu.{}.gem.{}'.format(port.pon_id,
diff --git a/voltha/adapters/adtran_olt/pon_port.py b/voltha/adapters/adtran_olt/pon_port.py
index e3d0e48..dd2c3df 100644
--- a/voltha/adapters/adtran_olt/pon_port.py
+++ b/voltha/adapters/adtran_olt/pon_port.py
@@ -25,9 +25,14 @@
 from codec.olt_config import OltConfig
 from onu import Onu
 from alarms.onu_los_alarm import OnuLosAlarm
-from voltha.protos.common_pb2 import OperStatus, AdminState
+from voltha.protos.common_pb2 import AdminState
 from voltha.protos.device_pb2 import Port
 
+try:
+    from alarms.onu_discovery_alarm2 import OnuDiscoveryAlarm
+except ImportError:
+    from alarms.onu_discovery_alarm import OnuDiscoveryAlarm
+
 
 class PonPort(AdtnPort):
     """
@@ -418,10 +423,6 @@
         Set the PON Port to a known good state on initial port startup.  Actual
         PON 'Start' is done elsewhere
         """
-        #if self.state != AdtnPort.State.INITIAL:
-        #    self.log.error('reset-ignored', state=self.state)
-        #    returnValue('Ignored')
-
         initial_port_state = AdminState.DISABLED
         self.log.info('reset', initial_state=initial_port_state)
 
@@ -468,7 +469,7 @@
 
         returnValue('Reset complete')
 
-    def gem_ids(self, logical_port, untagged_gem, exception_gems, multicast_gems):  # FIXED_ONU
+    def gem_ids(self, logical_port, untagged_gem, multicast_gems=False):
         """
         Get all GEM Port IDs used on a given PON
 
@@ -476,7 +477,6 @@
                           on PON, if Multicast, VID for Multicast, or None for all
                           Multicast GEMPorts
         :param untagged_gem: (boolean) Select from special purpose untagged GEM Port
-        :param exception_gems: (boolean) Select from special purpose ACL GEM Port
         :param multicast_gems: (boolean) Select from available Multicast GEM Ports
         :return: (dict) data_gem -> key -> onu-id, value -> tuple(sorted list of GEM Port IDs, onu_vid)
                         mcast_gem-> key -> mcast-vid, value -> GEM Port IDs
@@ -492,7 +492,7 @@
         else:
             for onu_id, onu in self._onu_by_id.iteritems():
                 if logical_port is None or logical_port == onu.logical_port:
-                    gem_ids[onu_id] = (onu.gem_ids(untagged_gem, exception_gems),
+                    gem_ids[onu_id] = (onu.gem_ids(untagged_gem),
                                        onu.onu_vid if not untagged_gem
                                        else self.olt.untagged_vlan)
         return gem_ids
@@ -710,6 +710,7 @@
                 onu.equalization_delay = onu_status.equalization_delay
                 onu.equalization_delay = onu_status.equalization_delay
                 onu.fiber_length = onu_status.fiber_length
+                onu.password = onu_status.reported_password
 
     def _update_gem_status(self, gems):
         for gem_id, gem_status in gems.iteritems():
@@ -779,15 +780,15 @@
                         vont_info = next(info for _, info in gpon_info['vont-anis'].items()
                                          if info.get('expected-serial-number') == serial_number)
 
-                        ont_info = next(info for _, info in gpon_info['ont-anis'].items()
-                                        if info.get('name') == vont_info['name'])
+                        # ont_info = next(info for _, info in gpon_info['ont-anis'].items()
+                        #                 if info.get('name') == vont_info['name'])
 
                         vont_ani = vont_info['data']
                         onu_id = vont_info['onu-id']
                         enabled = vont_info['enabled']
                         channel_speed = vont_info['upstream-channel-speed']
-                        xpon_name = ont_info['name']
-                        upstream_fec_enabled = ont_info.get('upstream-fec', False)
+                        xpon_name = vont_info['name']
+                        upstream_fec_enabled = True   # TODO: ont_info.get('upstream-fec', False)
 
                         tconts = {key: val for key, val in gpon_info['tconts'].iteritems()
                                   if val.vont_ani == vont_info['name']}
@@ -850,7 +851,6 @@
         onu_info = self._get_onu_info(serial_number)
 
         if onu_info is None:
-            from alarms.onu_discovery_alarm import OnuDiscoveryAlarm
             self.log.info('onu-lookup-failure', serial_number=serial_number_64)
             OnuDiscoveryAlarm(self.olt, self.pon_id, serial_number).raise_alarm()
             returnValue('new-onu')
diff --git a/voltha/adapters/adtran_olt/xpon/adtran_xpon.py b/voltha/adapters/adtran_olt/xpon/adtran_xpon.py
index ef07b1a..8c92c9b 100644
--- a/voltha/adapters/adtran_olt/xpon/adtran_xpon.py
+++ b/voltha/adapters/adtran_olt/xpon/adtran_xpon.py
@@ -147,6 +147,7 @@
                 'enabled': interface.enabled,
                 'onu-id': inst_data.onu_id,
                 'expected-serial-number': inst_data.expected_serial_number,
+                'expected-registration-id': inst_data.expected_registration_id,
                 'preferred-channel-pair': inst_data.preferred_chanpair,
                 'channel-partition': inst_data.parent_ref,
                 'upstream-channel-speed': inst_data.upstream_channel_speed,
diff --git a/voltha/adapters/adtran_olt/xpon/gem_port.py b/voltha/adapters/adtran_olt/xpon/gem_port.py
index ada51f9..4801a7f 100644
--- a/voltha/adapters/adtran_olt/xpon/gem_port.py
+++ b/voltha/adapters/adtran_olt/xpon/gem_port.py
@@ -25,7 +25,6 @@
                  traffic_class=None,
                  intf_ref=None,
                  untagged=False,
-                 exception=False,        # FIXED_ONU
                  name=None,
                  handler=None):
         self.name = name
@@ -38,7 +37,6 @@
         self._omci_transport = omci_transport
         self.multicast = multicast
         self.untagged = untagged
-        self.exception = exception        # FIXED_ONU
         self._handler = handler
 
         # TODO: Make this a base class and derive OLT and ONU specific classes from it
diff --git a/voltha/adapters/adtran_olt/xpon/olt_gem_port.py b/voltha/adapters/adtran_olt/xpon/olt_gem_port.py
index a23e5fb..c5b72a1 100644
--- a/voltha/adapters/adtran_olt/xpon/olt_gem_port.py
+++ b/voltha/adapters/adtran_olt/xpon/olt_gem_port.py
@@ -34,7 +34,6 @@
                  traffic_class=None,
                  intf_ref=None,
                  untagged=False,
-                 exception=False,  # FIXED_ONU
                  name=None,
                  handler=None,
                  is_mock=False):
@@ -46,22 +45,12 @@
                                          traffic_class=traffic_class,
                                          intf_ref=intf_ref,
                                          untagged=untagged,
-                                         exception=exception,
                                          name=name,
                                          handler=handler)
         self._is_mock = is_mock
 
     @staticmethod
     def create(handler, gem_port):
-        if handler.exception_gems:
-            exception = gem_port['gemport-id'] in [2180, 2186, 2192,         # FIXED_ONU
-                                                   2198, 2204, 2210,
-                                                   2216, 2222, 2228,
-                                                   2234, 2240, 2246,
-                                                   2252, 2258]
-        else:
-            exception = False         # FIXED_ONU
-
         mcast = gem_port['gemport-id'] in [4095]    # TODO: Perform proper lookup
         untagged = 'untagged' in gem_port['name'].lower()
         # TODO: Use next once real BBF mcast available.
@@ -77,8 +66,7 @@
                           intf_ref=gem_port.get(port_ref),
                           handler=handler,
                           multicast=mcast,
-                          untagged=untagged,
-                          exception=exception)    # FIXED_ONU
+                          untagged=untagged)
 
     @property
     def encryption(self):
diff --git a/voltha/adapters/adtran_olt/xpon/olt_tcont.py b/voltha/adapters/adtran_olt/xpon/olt_tcont.py
index 95fd8cc..3156d50 100644
--- a/voltha/adapters/adtran_olt/xpon/olt_tcont.py
+++ b/voltha/adapters/adtran_olt/xpon/olt_tcont.py
@@ -56,7 +56,7 @@
         # For TCONT, only leaf is the key. So only post needed
         try:
             results = yield session.request('POST', uri, data=data, name=name,
-                                            suppress_error=True)
+                                            suppress_error=False)
         except:
             results = None