#
# Copyright 2017 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""
Maple OLT/ONU adapter.
"""
from uuid import uuid4

import arrow
import binascii
from scapy.layers.l2 import Ether, Dot1Q
from twisted.internet import reactor
from twisted.internet.protocol import ReconnectingClientFactory
from twisted.spread import pb
from twisted.internet.defer import inlineCallbacks, returnValue, DeferredQueue
from zope.interface import implementer

from common.frameio.frameio import BpfProgramFilter, hexify

from voltha.adapters.interface import IAdapterInterface
from voltha.core.logical_device_agent import mac_str_to_tuple
import voltha.core.flow_decomposer as fd
from voltha.protos import third_party
from voltha.protos.adapter_pb2 import Adapter
from voltha.protos.adapter_pb2 import AdapterConfig
from voltha.protos.common_pb2 import LogLevel, OperStatus, ConnectStatus, \
    AdminState
from voltha.protos.device_pb2 import DeviceType, DeviceTypes, Port, Device, \
PmConfigs, PmConfig, PmGroupConfig
from voltha.protos.health_pb2 import HealthStatus
from google.protobuf.empty_pb2 import Empty
from voltha.protos.events_pb2 import KpiEvent, MetricValuePairs
from voltha.protos.events_pb2 import KpiEventType
from voltha.protos.events_pb2 import AlarmEvent, AlarmEventType, \
    AlarmEventSeverity, AlarmEventState, AlarmEventCategory

from voltha.protos.logical_device_pb2 import LogicalPort, LogicalDevice
from voltha.protos.openflow_13_pb2 import OFPPS_LIVE, OFPPF_FIBER, \
    OFPPF_1GB_FD, OFPC_GROUP_STATS, OFPC_PORT_STATS, OFPC_TABLE_STATS, \
    OFPC_FLOW_STATS, OFPP_CONTROLLER, OFPXMC_OPENFLOW_BASIC, \
    ofp_switch_features, ofp_desc, ofp_port
from voltha.registry import registry
from voltha.extensions.omci.omci import *

_ = third_party
log = structlog.get_logger()

PACKET_IN_VLAN = 4091
is_inband_frame = BpfProgramFilter('(ether[14:2] & 0xfff) = 0x{:03x}'.format(
    PACKET_IN_VLAN))


class MapleOltPmMetrics:
    class Metrics:
        def __init__(self, config, value=0, is_group=False):
            self.config = config
            self.value = value
            self.is_group = is_group

    def __init__(self,device):
        self.pm_names = {'tx_64','tx_65_127', 'tx_128_255', 'tx_256_511',
                        'tx_512_1023', 'tx_1024_1518', 'tx_1519_9k', 'rx_64',
                        'rx_65_127', 'rx_128_255', 'rx_256_511', 'rx_512_1023',
                        'rx_1024_1518', 'rx_1519_9k', 'tx_pkts', 'rx_pkts',
                         'tx_bytes', 'rx_bytes'}
        self.pm_group_names = {'nni'}
        self.device = device
        self.id = device.id
        self.default_freq = 150
        self.pon_metrics = dict()
        self.nni_metrics = dict()
        for m in self.pm_names:
            self.pon_metrics[m] = \
                    self.Metrics(config = PmConfig(name=m,
                                                   type=PmConfig.COUNTER,
                                                   enabled=True), value = 0)
            self.nni_metrics[m] = \
                    self.Metrics(config = PmConfig(name=m,
                                                   type=PmConfig.COUNTER,
                                                   enabled=True), value = 0)
        self.pm_group_metrics = dict()
        for m in self.pm_group_names:
            self.pm_group_metrics[m] = \
                    self.Metrics(config = PmGroupConfig(group_name=m,
                                                        group_freq=self.default_freq,
                                                        enabled=True),
                                                        is_group = True)
        for m in sorted(self.nni_metrics):
            pm=self.nni_metrics[m]
            self.pm_group_metrics['nni'].config.metrics.extend([PmConfig(
                                                          name=pm.config.name,
                                                          type=pm.config.type,
                                                          enabled=pm.config.enabled)])

    @inlineCallbacks
    def configure_pm_collection_freq(self, freq, remote):
        log.info('configuring-pm-collection-freq',
                      freq=freq)
        try:
            data = yield remote.callRemote('set_stats_collection_interval', 0,
                                           freq)
            log.info('configured-pm-collection-freq', data=data)
        except Exception as e:
            log.exception('configure-pm-collection-freq', exc=str(e))

    def enable_pm_collection(self, pm_group, remote):
        if pm_group == 'nni':
            self.configure_pm_collection_freq(self.default_freq/10, remote)

    def disable_pm_collection(self, pm_group, remote):
        if pm_group == 'nni':
            self.configure_pm_collection_freq(0, remote)

    def update(self, device, pm_config, remote):
        if self.default_freq != pm_config.default_freq:
            self.default_freq = pm_config.default_freq

        if pm_config.grouped is True:
            for m in pm_config.groups:
                self.pm_group_metrics[m.group_name].config.enabled = m.enabled
                if m.enabled is True:
                    self.enable_pm_collection(m.group_name, remote)
                else:
                    self.disable_pm_collection(m.group_name, remote)

        else:
            for m in pm_config.metrics:
                self.pon_metrics[m.name].config.enabled = m.enabled
                self.nni_metrics[m.name].config.enabled = m.enabled

    def make_proto(self):
        pm_config = PmConfigs(
            id=self.id,
            default_freq=self.default_freq,
            grouped = True,
            freq_override = False)
        for m in self.pm_group_names:
            pm_config.groups.extend([self.pm_group_metrics[m].config])

        return pm_config


class MapleOltRxHandler(pb.Root):
    def __init__(self, device_id, adapter, onu_queue):
        self.device_id = device_id
        self.adapter = adapter
        self.onu_discovered_queue = onu_queue
        self.adapter_agent = adapter.adapter_agent
        self.adapter_name = adapter.name
        # registry('main').get_args().external_host_address
        self.pb_server_ip = '192.168.24.20'
        self.pb_server_port = 24497
        self.pb_server_factory = pb.PBServerFactory(self)
        # start PB server
        self.listen_port = reactor.listenTCP(self.pb_server_port,
                                             self.pb_server_factory)
        self.omci_rx_queue = DeferredQueue()
        log.info('PB-server-started-on-port', port=self.pb_server_port)

    def get_ip(self):
        return self.pb_server_ip

    def get_port(self):
        return self.pb_server_port

    def get_host(self):
        return self.listen_port.getHost()

    def remote_echo(self, pkt_type, pon, onu, port, crc_ok, msg_size, msg_data):
        log.info('received-omci-msg',
                 pkt_type=pkt_type,
                 pon_id=pon,
                 onu_id=onu,
                 port_id=port,
                 crc_ok=crc_ok,
                 msg_size=msg_size,
                 msg_data=hexify(msg_data))
        self.omci_rx_queue.put((onu, msg_data))

    def receive_omci_msg(self):
        return self.omci_rx_queue.get()

    def remote_report_stats(self, _object, key, stats_data):
        log.info('received-stats-msg',
                 object=_object,
                 key=key,
                 stats=stats_data)

        prefix = 'voltha.{}.{}'.format(self.adapter_name, self.device_id)

        try:
            ts = arrow.utcnow().timestamp

            prefixes = {
                prefix + '.nni': MetricValuePairs(metrics=stats_data)
                }

            kpi_event = KpiEvent(
                type=KpiEventType.slice,
                ts=ts,
                prefixes=prefixes
            )

            self.adapter_agent.submit_kpis(kpi_event)

        except Exception as e:
            log.exception('failed-to-submit-kpis', e=e)

    def remote_report_event(self, _object, key, event, event_data=None):
        def _convert_serial_data(data):
            b = bytearray()
            b.extend(data)

            return binascii.hexlify(b)

        log.info('received-event-msg',
                 object=_object,
                 key=key,
                 event_str=event,
                 event_data=event_data)

        if _object == 'device':
            # key: {'device_id': <int>}
            # event: 'state-changed'
            #     event_data: {'state_change_successful': <False|True>,
            #                  'new_state': <str> ('active-working'|'inactive')}
            pass
        elif _object == 'nni':
            # key: {'device_id': <int>, 'nni': <int>}
            pass
        elif _object == 'pon_ni':
            # key: {'device_id': <int>, 'pon_ni': <int>}
            # event: 'state-changed'
            #     event_data: {'state_change_successful': <False|True>,
            #                  'new_state': <str> ('active-working'|'inactive')}
            #
            # event: 'onu-discovered'
            #     event_data: {'serial_num_vendor_id': <str>
            #                  'serial_num_vendor_specific': <str>
            #                  'ranging_time': <int>
            #                  'onu_id': <int>
            #                  'us_line_rate': <int> (0=2.5G, 1=10G)
            #                  'ds_pon_id': <int>
            #                  'us_pon_id': <int>
            #                  'tuning_granularity': <int>
            #                  'step_tuning_time': <int>
            #                  'attenuation': <int>
            #                  'power_levelling_caps': <int>}
            if 'onu-discovered' == event and event_data is not None:
                event_data['_device_id'] = key['device_id'] if 'device_id' in key else None
                event_data['_pon_id'] = key['pon_id'] if 'pon_id' in key else None
                event_data['_vendor_id'] = _convert_serial_data(event_data['serial_num_vendor_id']) \
                    if 'serial_num_vendor_id' in event_data else None
                event_data['_vendor_specific'] = _convert_serial_data(event_data['serial_num_vendor_specific']) \
                    if 'serial_num_vendor_specific' in event_data else None

                self.onu_discovered_queue.put(event_data)
                log.info('onu-discovered-event-added-to-queue', event_data=event_data)

        elif _object == 'onu':
            # key: {'device_id': <int>, 'pon_ni': <int>, 'onu_id': <int>}
            # event: 'activation-completed'
            #     event_data: {'activation_successful': <False|True>,
            #                  act_fail_reason': <str>}
            #
            # event: 'deactivation-completed'
            #     event_data: {'deactivation_successful': <False|True>}
            #
            # event: 'ranging-completed'
            #     event_data: {'ranging_successful': <False|True>,
            #                  'ranging_fail_reason': <str>,
            #                  'eqd': <int>,
            #                  'number_of_ploams': <int>,
            #                  'power_level': <int>}
            #
            # event: 'enable-completed'
            #     event_data: {'serial_num-vendor_id': <str>
            #                  'serial_num-vendor_specific: <str>}
            #
            # event: 'disable-completed'
            #     event_data: {'serial_num-vendor_id': <str>
            #                  'serial_num-vendor_specific: <str>}
            event_dict = {'event':event, 'event_data':event_data}

            # Get child_device from onu_id
            child_device = self.adapter_agent.get_child_device(self.device_id, onu_id=key['onu_id'])
            assert child_device is not None

            # Send the event message to the ONU adapter
            self.adapter_agent.publish_inter_adapter_message(child_device.id, event_dict)

        elif _object == 'alloc_id':
            # key: {'device_id': <int>, 'pon_ni': <int>, 'onu_id': <int>, 'alloc_id': ,<int>}
            pass
        elif _object == 'gem_port':
            # key: {'device_id': <int>, 'pon_ni': <int>, 'onu_id': <int>, 'gem_port': ,<int>}
            pass
        elif _object == 'trx':
            # key: {'device_id': <int>, 'pon_ni': <int>}
            pass
        elif _object == 'flow_map':
            # key: {'device_id': <int>, 'pon_ni': <int>}
            pass

    def remote_report_alarm(self, _object, key, alarm, status, priority,
                            alarm_data=None):
        log.info('received-alarm-msg',
                 object=_object,
                 key=key,
                 alarm=alarm,
                 status=status,
                 priority=priority,
                 alarm_data=alarm_data)

        id = 'voltha.{}.{}.{}'.format(self.adapter_name, self.device_id, _object)
        description = '{} Alarm - {} - {}'.format(_object.upper(), alarm.upper(),
                                                  'Raised' if status else 'Cleared')

        if priority == 'low':
            severity = AlarmEventSeverity.MINOR
        elif priority == 'medium':
            severity = AlarmEventSeverity.MAJOR
        elif priority == 'high':
            severity = AlarmEventSeverity.CRITICAL
        else:
            severity = AlarmEventSeverity.INDETERMINATE

        try:
            ts = arrow.utcnow().timestamp

            alarm_event = self.adapter_agent.create_alarm(
                id=id,
                resource_id=str(key),
                type=AlarmEventType.EQUIPMENT,
                category=AlarmEventCategory.PON,
                severity=severity,
                state=AlarmEventState.RAISED if status else AlarmEventState.CLEARED,
                description=description,
                context=alarm_data,
                raised_ts = ts)

            self.adapter_agent.submit_alarm(self.device_id, alarm_event)

        except Exception as e:
            log.exception('failed-to-submit-alarm', e=e)

        # take action based on alarm type, only pon_ni and onu objects report alarms
        if object == 'pon_ni':
            # key: {'device_id': <int>, 'pon_ni': <int>}
            # alarm: 'los'
            # status: <False|True>
            pass
        elif object == 'onu':
            # key: {'device_id': <int>, 'pon_ni': <int>, 'onu_id': <int>}
            # alarm: <'los'|'lob'|'lopc_miss'|'los_mic_err'|'dow'|'sf'|'sd'|'suf'|'df'|'tiw'|'looc'|'dg'>
            # status: <False|True>
            pass

@implementer(IAdapterInterface)
class MapleOltAdapter(object):
    name = 'maple_olt'

    supported_device_types = [
        DeviceType(
            id=name,
            adapter=name,
            accepts_bulk_flow_update=True
        )
    ]

    def __init__(self, adapter_agent, config):
        self.adapter_agent = adapter_agent
        self.config = config
        self.descriptor = Adapter(
            id=self.name,
            vendor='Voltha project',
            version='0.4',
            config=AdapterConfig(log_level=LogLevel.INFO)
        )
        self.devices_handlers = dict()  # device_id -> MapleOltHandler()
        self.logical_device_id_to_root_device_id = dict()

        # register for adapter messages
        self.adapter_agent.register_for_inter_adapter_messages()

    def start(self):
        log.debug('starting')
        log.info('started')

    def stop(self):
        log.debug('stopping')
        log.info('stopped')

    def adapter_descriptor(self):
        return self.descriptor

    def device_types(self):
        return DeviceTypes(items=self.supported_device_types)

    def health(self):
        return HealthStatus(state=HealthStatus.HealthState.HEALTHY)

    def change_master_state(self, master):
        raise NotImplementedError()

    def update_pm_config(self, device, pm_config):
        log.info("adapter-update-pm-config", device=device, pm_config=pm_config)
        handler = self.devices_handlers[device.id]
        handler.update_pm_metrics(device, pm_config)

    def adopt_device(self, device):
        log.info("adopt-device", device=device)
        self.devices_handlers[device.id] = MapleOltHandler(self, device.id)
        reactor.callLater(0, self.devices_handlers[device.id].activate, device)
        return device

    def abandon_device(self, device):
        raise NotImplementedError()

    def disable_device(self, device):
        raise NotImplementedError()

    def reenable_device(self, device):
        raise NotImplementedError()

    def reboot_device(self, device):
        raise NotImplementedError()

    def delete_device(self, device):
        raise NotImplementedError()

    def get_device_details(self, device):
        raise NotImplementedError()

    def update_flows_bulk(self, device, flows, groups):
        log.info('bulk-flow-update', device_id=device.id,
                 flows=flows, groups=groups)
        assert len(groups.items) == 0, "Cannot yet deal with groups"
        handler = self.devices_handlers[device.id]
        return handler.update_flow_table(flows.items, device)

    def update_flows_incrementally(self, device, flow_changes, group_changes):
        raise NotImplementedError()

    def send_proxied_message(self, proxy_address, msg):
        log.info('send-proxied-message', proxy_address=proxy_address, msg=msg)
        handler = self.devices_handlers[proxy_address.device_id]
        handler.send_proxied_message(proxy_address, msg)

    def receive_proxied_message(self, proxy_address, msg):
        raise NotImplementedError()

    def receive_packet_out(self, logical_device_id, egress_port_no, msg):
        def ldi_to_di(ldi):
            di = self.logical_device_id_to_root_device_id.get(ldi)
            if di is None:
                logical_device = self.adapter_agent.get_logical_device(ldi)
                di = logical_device.root_device_id
                self.logical_device_id_to_root_device_id[ldi] = di
            return di

        device_id = ldi_to_di(logical_device_id)
        handler = self.devices_handlers[device_id]
        handler.packet_out(egress_port_no, msg)

    def receive_inter_adapter_message(self, msg):
        pass

class MaplePBClientFactory(pb.PBClientFactory, ReconnectingClientFactory):
    channel = None
    maxDelay = 60
    initialDelay = 15

    def clientConnectionMade(self, broker):
        log.info('pb-client-connection-made')
        pb.PBClientFactory.clientConnectionMade(self, broker)
        ReconnectingClientFactory.resetDelay(self)

    def clientConnectionLost(self, connector, reason, reconnecting=0):
        log.info('pb-client-connection-lost')
        pb.PBClientFactory.clientConnectionLost(self, connector, reason,
                                                reconnecting=1)
        ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
        log.info('pb-client-connection-lost-retrying')

    def clientConnectionFailed(self, connector, reason):
        log.info('pb-client-connection-failed')
        pb.PBClientFactory.clientConnectionFailed(self, connector, reason)
        ReconnectingClientFactory.clientConnectionFailed(self, connector,
                                                         reason)
        log.info('pb-client-connection-failed-retrying')

    def disconnect(self, stopTrying=0):
        if stopTrying:
            ReconnectingClientFactory.stopTrying(self)
        pb.PBClientFactory.disconnect(self)

    def channel_disconnected(self, channel):
        log.info('pb-channel-disconnected', channel=channel)
        self.disconnect()

    @inlineCallbacks
    def getChannel(self):
        if self.channel is None:
            try:
                self.channel = yield self.getRootObject()
                self.channel.notifyOnDisconnect(self.channel_disconnected)
            except Exception as e:
                log.info('pb-client-failed-to-get-channel', exc=str(e))
                self.channel = None
        returnValue(self.channel)


class MapleOltHandler(object):
    def __init__(self, adapter, device_id):
        self.adapter = adapter
        self.adapter_agent = adapter.adapter_agent
        self.device_id = device_id
        self.log = structlog.get_logger(device_id=device_id)
        self.io_port = None
        self.logical_device_id = None
        self.interface = registry('main').get_args().interface
        self.pbc_factory = MaplePBClientFactory()
        self.pbc_port = 24498
        self.tx_id = 0
        self.onu_discovered_queue = DeferredQueue()
        self.rx_handler = MapleOltRxHandler(self.device_id, self.adapter, self.onu_discovered_queue)
        self.heartbeat_count = 0
        self.heartbeat_miss = 0
        self.heartbeat_interval = 1
        self.heartbeat_failed_limit = 3
        self.command_timeout = 5
        self.pm_metrics = None
        self.onus = {}

    def __del__(self):
        if self.io_port is not None:
            registry('frameio').close_port(self.io_port)

    def get_channel(self):
        return self.pbc_factory.getChannel()

    def get_proxy_channel_id_from_onu(self, onu_id):
        return onu_id << 4

    def get_onu_from_channel_id(self, channel_id):
        return channel_id >> 4

    def get_tunnel_tag_from_onu(self, onu):
        return 1024 + (onu * 16)

    def get_onu_from_tunnel_tag(self, tunnel_tag):
        return (tunnel_tag - 1024) / 16

    def get_new_onu_id(self, vendor, vendor_specific):
        onu_id = None
        for i in range(0, 63):
            if i not in self.onus:
                onu_id = i
                break

        if onu_id is not None:
            self.onus[onu_id] = {'onu_id': onu_id,
                                 'vendor': vendor,
                                 'vendor_specific': vendor_specific}
        return onu_id

    def onu_exists(self, onu_id):
        if onu_id in self.onus:
            self.log.info('onu-exists',
                          onu_id=onu_id,
                          vendor=self.onus[onu_id]['vendor'],
                          vendor_specific=self.onus[onu_id]['vendor_specific'])
            return self.onus[onu_id]['vendor'], self.onus[onu_id]['vendor_specific']
        else:
            self.log.info('onu-does-not-exist', onu_id=onu_id)
            return None, None

    def onu_serial_exists(self, sn_vendor, sn_vendor_specific):
        for key, value in self.onus.iteritems():
            if sn_vendor in value.itervalues() and sn_vendor_specific in value.itervalues():
                self.log.info('onu-serial-number-exists',
                              onu_id=value['onu_id'],
                              vendor=sn_vendor,
                              vendor_specific=sn_vendor_specific,
                              onus=self.onus)
                return value['onu_id']

        self.log.info('onu-serial-number-does-not-exist',
                      vendor=sn_vendor,
                      vendor_specific=sn_vendor_specific,
                      onus=self.onus)
        return None

    @inlineCallbacks
    def send_set_remote(self):
        srv_ip = self.rx_handler.get_ip()
        srv_port = self.rx_handler.get_port()
        self.log.info('setting-remote-ip-port', ip=srv_ip, port=srv_port)

        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('set_remote', srv_ip, srv_port)
            self.log.info('set-remote', data=data, ip=srv_ip, port=srv_port)
        except Exception as e:
            self.log.info('set-remote-exception', exc=str(e))

    @inlineCallbacks
    def send_config_classifier(self, olt_no, etype, ip_proto=None,
                               dst_port=None):
        self.log.info('configuring-classifier',
                      olt=olt_no,
                      etype=etype,
                      ip_proto=ip_proto,
                      dst_port=dst_port)
        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('config_classifier',
                                           olt_no,
                                           etype,
                                           ip_proto,
                                           dst_port)
            self.log.info('configured-classifier', data=data)
        except Exception as e:
            self.log.info('config-classifier-exception', exc=str(e))

    @inlineCallbacks
    def send_config_acflow(self, olt_no, onu_no, etype, ip_proto=None,
                           dst_port=None):
        self.log.info('configuring-acflow',
                      olt=olt_no,
                      onu=onu_no,
                      etype=etype,
                      ip_proto=ip_proto,
                      dst_port=dst_port)
        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('config_acflow',
                                           olt_no,
                                           onu_no,
                                           etype,
                                           ip_proto,
                                           dst_port)

            self.log.info('configured-acflow', data=data)
        except Exception as e:
            self.log.info('config-acflow-exception', exc=str(e))

    @inlineCallbacks
    def send_connect_olt(self, olt_no):
        self.log.info('connecting-to-olt', olt=olt_no)
        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('connect_olt', olt_no)
            self.log.info('connected-to-olt', data=data)
        except Exception as e:
            self.log.info('connect-olt-exception', exc=str(e))

    @inlineCallbacks
    def send_activate_olt(self, olt_no):
        self.log.info('activating-olt', olt=olt_no)
        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('activate_olt', olt_no)
            self.log.info('activated-olt', data=data)
        except Exception as e:
            self.log.info('activate-olt-exception', exc=str(e))

    @inlineCallbacks
    def send_create_onu(self, olt_no, onu_no, serial_no, vendor_no):
        self.log.info('creating-onu',
                      olt=olt_no,
                      onu=onu_no,
                      serial=serial_no,
                      vendor=vendor_no)
        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('create_onu',
                                           olt_no,
                                           onu_no,
                                           serial_no,
                                           vendor_no)
            self.log.info('created-onu', data=data)
        except Exception as e:
            self.log.info('create-onu-exception', exc=str(e))

    @inlineCallbacks
    def send_configure_alloc_id(self, olt_no, onu_no, alloc_id):
        self.log.info('configuring-alloc-id',
                      olt=olt_no,
                      onu=onu_no,
                      alloc_id=alloc_id)
        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('configure_alloc_id',
                                           olt_no,
                                           onu_no,
                                           alloc_id)
            self.log.info('configured-alloc-id', data=data)
        except Exception as e:
            self.log.info('configure-alloc-id-exception', exc=str(e))

    @inlineCallbacks
    def send_configure_unicast_gem(self, olt_no, onu_no, uni_gem):
        self.log.info('configuring-unicast-gem',
                      olt=olt_no,
                      onu=onu_no,
                      unicast_gem_port=uni_gem)
        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('configure_unicast_gem',
                                           olt_no,
                                           onu_no,
                                           uni_gem)
            self.log.info('configured-unicast-gem', data=data)
        except Exception as e:
            self.log.info('configure-unicast-gem-exception', exc=str(e))

    @inlineCallbacks
    def send_configure_multicast_gem(self, olt_no, onu_no, multi_gem):
        self.log.info('configuring-multicast-gem',
                      olt=olt_no,
                      onu=onu_no,
                      multicast_gem_port=multi_gem)
        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('configure_multicast_gem',
                                           olt_no,
                                           onu_no,
                                           multi_gem)
            self.log.info('configured-multicast-gem', data=data)
        except Exception as e:
            self.log.info('configure-multicast-gem-exception', exc=str(e))

    @inlineCallbacks
    def send_configure_onu(self, olt_no, onu_no, alloc_id, uni_gem, multi_gem):
        self.log.info('configuring-onu',
                      olt=olt_no,
                      onu=onu_no,
                      alloc_id=alloc_id,
                      unicast_gem_port=uni_gem,
                      multicast_gem_port=multi_gem)
        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('configure_onu',
                                           olt_no,
                                           onu_no,
                                           alloc_id,
                                           uni_gem,
                                           multi_gem)
            self.log.info('configured-onu', data=data)
        except Exception as e:
            self.log.info('configure-onu-exception', exc=str(e))

    @inlineCallbacks
    def send_activate_onu(self, olt_no, onu_no):
        self.log.info('activating-onu', olt=olt_no, onu=onu_no)
        try:
            remote = yield self.get_channel()
            data = yield remote.callRemote('activate_onu', olt_no, onu_no)
            self.log.info('activated-onu', data=data)
        except Exception as e:
            self.log.info('activate-onu-exception', exc=str(e))


    @inlineCallbacks
    def heartbeat(self, device_id, state='run'):
        """Heartbeat OLT hardware

        Call PB remote method 'heartbeat' to verify connectivity to OLT
        hardware. If heartbeat missed self.heartbeat_failed_limit times OLT
        adapter is set FAILED/UNREACHABLE.
        No further action from VOLTHA core is expected as result of heartbeat
        failure. Heartbeat continues following failure and once connectivity is
        restored adapter state will be set to ACTIVE/REACHABLE

        Arguments:
        device_id: adapter device id
        state: desired state (stop, start, run)
        """

        self.log.debug('olt-heartbeat', device=device_id, state=state,
                       count=self.heartbeat_count)

        def add_timeout(d, duration):
            return reactor.callLater(duration, d.cancel)

        def cancel_timeout(t):
            if t.active():
                t.cancel()
                self.log.debug('olt-heartbeat-timeout-cancelled')

        def heartbeat_alarm(device_id, status, heartbeat_misses=0):
            try:
                ts = arrow.utcnow().timestamp

                alarm_data = {'heartbeats_missed':str(heartbeat_misses)}

                alarm_event = self.adapter_agent.create_alarm(
                    id='voltha.{}.{}.olt'.format(self.adapter.name, device_id),
                    resource_id='olt',
                    type=AlarmEventType.EQUIPMENT,
                    category=AlarmEventCategory.PON,
                    severity=AlarmEventSeverity.CRITICAL,
                    state=AlarmEventState.RAISED if status else
                        AlarmEventState.CLEARED,
                    description='OLT Alarm - Heartbeat - {}'.format('Raised'
                                                                    if status
                                                                    else 'Cleared'),
                    context=alarm_data,
                    raised_ts = ts)

                self.adapter_agent.submit_alarm(device_id, alarm_event)

            except Exception as e:
                log.exception('failed-to-submit-alarm', e=e)

        if state == 'stop':
            return

        if state == 'start':
            self.heartbeat_count = 0
            self.heartbeat_miss = 0

        try:
            d = self.get_channel()
            timeout = add_timeout(d, self.command_timeout)
            remote = yield d
            cancel_timeout(timeout)

            d = remote.callRemote('heartbeat', self.heartbeat_count)
            timeout = add_timeout(d, self.command_timeout)
            data = yield d
            cancel_timeout(timeout)
        except Exception as e:
            data = -1
            self.log.info('olt-heartbeat-exception', data=data,
                          count=self.heartbeat_miss, exc=str(e))

        if data != self.heartbeat_count:
            # something is not right
            self.heartbeat_miss += 1
            self.log.info('olt-heartbeat-miss', data=data,
                          count=self.heartbeat_count, miss=self.heartbeat_miss)
        else:
            if self.heartbeat_miss > 0:
                self.heartbeat_miss = 0
                _device = self.adapter_agent.get_device(device_id)
                _device.connect_status = ConnectStatus.REACHABLE
                _device.oper_status = OperStatus.ACTIVE
                _device.reason = ''
                self.adapter_agent.update_device(_device)
                heartbeat_alarm(device_id, 0)

        _device = self.adapter_agent.get_device(device_id)
        if (self.heartbeat_miss >= self.heartbeat_failed_limit) and \
           (_device.connect_status == ConnectStatus.REACHABLE):
            self.log.info('olt-heartbeat-failed', data=data,
                          count=self.heartbeat_miss)
            _device = self.adapter_agent.get_device(device_id)
            _device.connect_status = ConnectStatus.UNREACHABLE
            _device.oper_status = OperStatus.FAILED
            _device.reason = 'Lost connectivity to OLT'
            self.adapter_agent.update_device(_device)
            heartbeat_alarm(device_id, 1, self.heartbeat_miss)

        self.heartbeat_count += 1
        reactor.callLater(self.heartbeat_interval, self.heartbeat, device_id)

    @inlineCallbacks
    def arrive_onu(self):
        self.log.info('arrive-onu waiting')
        _data = yield self.onu_discovered_queue.get()

        ok_to_arrive = False
        olt_id = _data['_device_id']
        pon_id = _data['_pon_id']
        onu_id = self.onu_serial_exists(_data['_vendor_id'], _data['_vendor_specific'])
        self.log.info('arrive-onu-detected', olt_id=olt_id, pon_ni=pon_id, onu_data=_data, onus=self.onus)

        if _data['onu_id'] == 65535:
            if onu_id is not None:
                self.log.info('onu-activation-already-in-progress',
                              vendor=_data['_vendor_id'],
                              vendor_specific=_data['_vendor_specific'],
                              onus=self.onus)
            else:
                onu_id = self.get_new_onu_id(_data['_vendor_id'],
                                             _data['_vendor_specific'])
                self.log.info('assigned-onu-id',
                              onu_id=onu_id,
                              vendor=_data['_vendor_id'],
                              vendor_specific=_data['_vendor_specific'],
                              onus=self.onus)
                ok_to_arrive = True
        else:
            vendor_id, vendor_specific = self.onu_exists(_data['onu_id'])
            if vendor_id is not None and vendor_id == _data['_vendor_id'] and \
               vendor_specific is not None and vendor_specific == _data['_vendor_specific']:
                onu_id = _data['onu_id']
                self.log.info('re-discovered-existing-onu',
                              onu_id=onu_id,
                              vendor=_data['_vendor_id'],
                              vendor_specific=_data['_vendor_specific'])
                ok_to_arrive = True
            else:
                self.log.info('onu-id-serial-number-mismatch-detected',
                              onu_id=onu_id,
                              vendor_id=vendor_id,
                              new_vendor_id=_data['_vendor_id'],
                              vendor_specific=vendor_specific,
                              new_vendor_specific=_data['_vendor_specific'])

        if onu_id is not None and ok_to_arrive:
            self.log.info('arriving-onu', onu_id=onu_id)
            tunnel_tag = self.get_tunnel_tag_from_onu(onu_id)
            yield self.send_create_onu(pon_id,
                                       onu_id,
                                       _data['_vendor_id'],
                                       _data['_vendor_specific'])
            yield self.send_configure_alloc_id(pon_id, onu_id, tunnel_tag)
            yield self.send_configure_unicast_gem(pon_id, onu_id, tunnel_tag)
            yield self.send_configure_multicast_gem(pon_id, onu_id, 4000)
            yield self.send_activate_onu(pon_id, onu_id)

            self.adapter_agent.child_device_detected(
                parent_device_id=self.device_id,
                parent_port_no=100,
                child_device_type='broadcom_onu',
                proxy_address=Device.ProxyAddress(
                    device_id=self.device_id,
                    channel_id=self.get_proxy_channel_id_from_onu(onu_id),  # c-vid
                    onu_id=onu_id,
                    onu_session_id=tunnel_tag  # tunnel_tag/gem_port, alloc_id
                ),
                vlan=tunnel_tag,
                serial_number=_data['_vendor_specific']
            )

        reactor.callLater(1, self.arrive_onu)

    @inlineCallbacks
    def activate(self, device):
        self.log.info('activating-olt', device=device)

        while self.onu_discovered_queue.pending:
            _ = yield self.onu_discovered_queue.get()

        if self.logical_device_id is None:
            if not device.ipv4_address:
                device.oper_status = OperStatus.FAILED
                device.reason = 'No ipv4_address field provided'
                self.adapter_agent.update_device(device)
                return

            device.root = True
            device.vendor = 'Broadcom'
            device.model = 'bcm68620'
            device.serial_number = device.ipv4_address
            self.adapter_agent.update_device(device)

            nni_port = Port(
                port_no=1,
                label='NNI facing Ethernet port',
                type=Port.ETHERNET_NNI,
                admin_state=AdminState.ENABLED,
                oper_status=OperStatus.ACTIVE
            )
            self.adapter_agent.add_port(device.id, nni_port)
            self.adapter_agent.add_port(device.id, Port(
                port_no=100,
                label='PON port',
                type=Port.PON_OLT,
                admin_state=AdminState.ENABLED,
                oper_status=OperStatus.ACTIVE
            ))

            ld = LogicalDevice(
                # not setting id and datapth_id will let the adapter
                # agent pick id
                desc=ofp_desc(
                    mfr_desc='cord project',
                    hw_desc='n/a',
                    sw_desc='logical device for Maple-based PON',
                    serial_num=uuid4().hex,
                    dp_desc='n/a'
                ),
                switch_features=ofp_switch_features(
                    n_buffers=256,  # TODO fake for now
                    n_tables=2,  # TODO ditto
                    capabilities=(  # TODO and ditto
                        OFPC_FLOW_STATS
                        | OFPC_TABLE_STATS
                        | OFPC_PORT_STATS
                        | OFPC_GROUP_STATS
                    )
                ),
                root_device_id=device.id
            )
            ld_initialized = self.adapter_agent.create_logical_device(ld)
            cap = OFPPF_1GB_FD | OFPPF_FIBER
            self.adapter_agent.add_logical_port(ld_initialized.id, LogicalPort(
                id='nni',
                ofp_port=ofp_port(
                    port_no=0,  # is 0 OK?
                    hw_addr=mac_str_to_tuple('00:00:00:00:00:%02x' % 129),
                    name='nni',
                    config=0,
                    state=OFPPS_LIVE,
                    curr=cap,
                    advertised=cap,
                    peer=cap,
                    curr_speed=OFPPF_1GB_FD,
                    max_speed=OFPPF_1GB_FD
                ),
                device_id=device.id,
                device_port_no=nni_port.port_no,
                root_port=True
            ))

            device = self.adapter_agent.get_device(device.id)
            device.parent_id = ld_initialized.id
            device.connect_status = ConnectStatus.UNREACHABLE
            device.oper_status = OperStatus.ACTIVATING
            self.adapter_agent.update_device(device)
            self.logical_device_id = ld_initialized.id

        device = self.adapter_agent.get_device(device.id)
        self.log.info('initiating-connection-to-olt',
                      device_id=device.id,
                      ipv4=device.ipv4_address,
                      port=self.pbc_port)
        try:
            reactor.connectTCP(device.ipv4_address, self.pbc_port, self.pbc_factory)
            device.connect_status = ConnectStatus.REACHABLE
            device.oper_status = OperStatus.ACTIVE
            device.reason = ''
            self.adapter_agent.update_device(device)
        except Exception as e:
            self.log.info('get-channel-exception', exc=str(e))
            device = self.adapter_agent.get_device(device.id)
            device.oper_status = OperStatus.FAILED
            device.reason = 'Failed to connect to OLT'
            self.adapter_agent.update_device(device)
            self.pbc_factory.stopTrying()
            reactor.callLater(5, self.activate, device)
            return

        device = self.adapter_agent.get_device(device.id)
        self.log.info('connected-to-olt',
                       device_id=device.id,
                       ipv4=device.ipv4_address,
                       port=self.pbc_port)

        reactor.callLater(0, self.heartbeat, device.id, state='start')

        yield self.send_set_remote()
        yield self.send_connect_olt(0)
        yield self.send_activate_olt(0)

        # Open the frameio port to receive in-band packet_in messages
        self.log.info('registering-frameio')
        self.io_port = registry('frameio').open_port(
            self.interface, self.rcv_io, is_inband_frame)

        # Finally set the initial PM configuration for this device
        # TODO: if arrive_onu not working, the following PM stuff was commented out during testing
        self.pm_metrics=MapleOltPmMetrics(device)
        pm_config = self.pm_metrics.make_proto()
        log.info("initial-pm-config", pm_config=pm_config)
        self.adapter_agent.update_device_pm_config(pm_config,init=True)

        # Apply the PM configuration
        self.update_pm_metrics(device, pm_config)

        reactor.callLater(1, self.arrive_onu)

        self.log.info('olt-activated', device=device)

    def rcv_io(self, port, frame):
        self.log.info('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)

    @inlineCallbacks
    def update_flow_table(self, flows, device):
        self.log.info('bulk-flow-update', device_id=device.id, flows=flows)

        def is_downstream(port):
            return not is_upstream(port)

        def is_upstream(port):
            return port == 100  # Need a better way


        for flow in flows:
            _type = None
            _ip_proto = None
            _port = None
            _vlan_vid = None
            _udp_dst = None
            _udp_src = None
            _ipv4_dst = None
            _ipv4_src = None
            _metadata = None
            _output = None
            _push_tpid = None
            _field = None

            try:
                _in_port = fd.get_in_port(flow)
                assert _in_port is not None

                if is_downstream(_in_port):
                    self.log.info('downstream-flow')
                elif is_upstream(_in_port):
                    self.log.info('upstream-flow')
                else:
                    raise Exception('port should be 1 or 2 by our convention')

                _out_port = fd.get_out_port(flow)  # may be None
                self.log.info('out-port', out_port=_out_port)

                for field in fd.get_ofb_fields(flow):

                    if field.type == fd.ETH_TYPE:
                        _type = field.eth_type
                        self.log.info('field-type-eth-type',
                                      eth_type=_type)

                    elif field.type == fd.IP_PROTO:
                        _ip_proto = field.ip_proto
                        self.log.info('field-type-ip-proto',
                                      ip_proto=_ip_proto)

                    elif field.type == fd.IN_PORT:
                        _port = field.port
                        self.log.info('field-type-in-port',
                                      in_port=_port)

                    elif field.type == fd.VLAN_VID:
                        _vlan_vid = field.vlan_vid & 0xfff
                        self.log.info('field-type-vlan-vid',
                                      vlan=_vlan_vid)

                    elif field.type == fd.VLAN_PCP:
                        _vlan_pcp = field.vlan_pcp
                        self.log.info('field-type-vlan-pcp',
                                      pcp=_vlan_pcp)

                    elif field.type == fd.UDP_DST:
                        _udp_dst = field.udp_dst
                        self.log.info('field-type-udp-dst',
                                      udp_dst=_udp_dst)

                    elif field.type == fd.UDP_SRC:
                        _udp_src = field.udp_src
                        self.log.info('field-type-udp-src',
                                      udp_src=_udp_src)

                    elif field.type == fd.IPV4_DST:
                        _ipv4_dst = field.ipv4_dst
                        self.log.info('field-type-ipv4-dst',
                                      ipv4_dst=_ipv4_dst)

                    elif field.type == fd.IPV4_SRC:
                        _ipv4_src = field.ipv4_src
                        self.log.info('field-type-ipv4-src',
                                      ipv4_dst=_ipv4_src)

                    elif field.type == fd.METADATA:
                        _metadata = field.table_metadata
                        self.log.info('field-type-metadata',
                                      metadata=_metadata)

                    else:
                        raise NotImplementedError('field.type={}'.format(
                            field.type))

                for action in fd.get_actions(flow):

                    if action.type == fd.OUTPUT:
                        _output = action.output.port
                        self.log.info('action-type-output',
                                      output=_output, in_port=_in_port)

                    elif action.type == fd.POP_VLAN:
                        self.log.info('action-type-pop-vlan',
                                      in_port=_in_port)

                    elif action.type == fd.PUSH_VLAN:
                        _push_tpid = action.push.ethertype
                        log.info('action-type-push-vlan',
                                 push_tpid=_push_tpid, in_port=_in_port)
                        if action.push.ethertype != 0x8100:
                            self.log.error('unhandled-tpid',
                                           ethertype=action.push.ethertype)

                    elif action.type == fd.SET_FIELD:
                        _field = action.set_field.field.ofb_field
                        assert (action.set_field.field.oxm_class ==
                                OFPXMC_OPENFLOW_BASIC)
                        self.log.info('action-type-set-field',
                                      field=_field, in_port=_in_port)
                        if _field.type == fd.VLAN_VID:
                            self.log.info('set-field-type-vlan-vid',
                                          vlan_vid=_field.vlan_vid & 0xfff)
                        else:
                            self.log.error('unsupported-action-set-field-type',
                                           field_type=_field.type)
                    else:
                        log.error('unsupported-action-type',
                                  action_type=action.type, in_port=_in_port)

                if is_upstream(_in_port) and \
                        (_type == 0x888e or
                        (_type == 0x800 and (_ip_proto == 2 or _ip_proto == 17))):
                    yield self.send_config_classifier(0, _type, _ip_proto, _udp_dst)
                    yield self.send_config_acflow(0, _in_port, _type, _ip_proto, _udp_dst)



            except Exception as e:
                log.exception('failed-to-install-flow', e=e, flow=flow)



    @inlineCallbacks
    def send_proxied_message(self, proxy_address, msg):
        if isinstance(msg, Packet):
            msg = str(msg)

        self.log.info('send-proxied-message',
                      proxy_address=proxy_address.channel_id,
                      msg=msg)

        try:
            remote = yield self.get_channel()
            yield remote.callRemote("send_omci",
                                    0,
                                    0,
                                    self.get_onu_from_channel_id(proxy_address.channel_id),
                                    msg)
            onu, rmsg = yield self.rx_handler.receive_omci_msg()
            self.adapter_agent.receive_proxied_message(proxy_address, rmsg)
        except Exception as e:
            self.log.info('send-proxied_message-exception', exc=str(e))

    def packet_out(self, egress_port, msg):
        self.log.info('sending-packet-out',
                      egress_port=egress_port,
                      msg=hexify(msg))

        pkt = Ether(msg)
        out_pkt = (
            Ether(src=pkt.src, dst=pkt.dst) /
            Dot1Q(vlan=4091) /
            Dot1Q(vlan=egress_port, type=pkt.type) /
            pkt.payload
        )
        self.io_port.send(str(out_pkt))

    @inlineCallbacks
    def update_pm_metrics(self, device, pm_config):
        self.log.info('update-pm-metrics', device_id=device.id,
                      pm_config=pm_config)
        remote = yield self.get_channel()
        self.pm_metrics.update(device, pm_config, remote)
