#
# Copyright 2018 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.
#
import copy
from twisted.internet import reactor
import grpc
from google.protobuf.json_format import MessageToDict
import hashlib
from simplejson import dumps
from twisted.internet.defer import inlineCallbacks, returnValue

from voltha_protos.openflow_13_pb2 import OFPXMC_OPENFLOW_BASIC, \
    ofp_flow_stats, OFPMT_OXM, Flows, FlowGroups, OFPXMT_OFB_IN_PORT, \
    OFPXMT_OFB_VLAN_VID
from voltha_protos.device_pb2 import Port
import pyvoltha.common.openflow.utils as fd
from voltha_protos import openolt_pb2
from voltha_protos.inter_container_pb2 import SwitchCapability, PortCapability, \
    InterAdapterMessageType, InterAdapterOmciMessage, InterAdapterTechProfileDownloadMessage

from pyvoltha.common.tech_profile.tech_profile import DEFAULT_TECH_PROFILE_TABLE_ID

# Flow categories
HSIA_FLOW = "HSIA_FLOW"

EAP_ETH_TYPE = 0x888e
LLDP_ETH_TYPE = 0x88cc

IGMP_PROTO = 2

# FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
DEFAULT_MGMT_VLAN = 4091

# Openolt Flow
UPSTREAM = "upstream"
DOWNSTREAM = "downstream"
PACKET_TAG_TYPE = "pkt_tag_type"
UNTAGGED = "untagged"
SINGLE_TAG = "single_tag"
DOUBLE_TAG = "double_tag"

# Classifier
ETH_TYPE = 'eth_type'
TPID = 'tpid'
IP_PROTO = 'ip_proto'
IN_PORT = 'in_port'
VLAN_VID = 'vlan_vid'
VLAN_PCP = 'vlan_pcp'
UDP_DST = 'udp_dst'
UDP_SRC = 'udp_src'
IPV4_DST = 'ipv4_dst'
IPV4_SRC = 'ipv4_src'
METADATA = 'metadata'
TUNNEL_ID = 'tunnel_id'
OUTPUT = 'output'
# Action
POP_VLAN = 'pop_vlan'
PUSH_VLAN = 'push_vlan'
TRAP_TO_HOST = 'trap_to_host'


class OpenOltFlowMgr(object):

    def __init__(self, core_proxy, adapter_proxy, log, stub, device_id, logical_device_id,
                 platform, resource_mgr):
        self.core_proxy = core_proxy
        self.adapter_proxy = adapter_proxy
        self.log = log
        self.stub = stub
        self.device_id = device_id
        self.logical_device_id = logical_device_id
        self.nni_intf_id = None
        self.platform = platform
        self.resource_mgr = resource_mgr
        self.tech_profile = dict()
        self._populate_tech_profile_per_pon_port()
        self.retry_add_flow_list = []

    def add_flow(self, flow):
        self.log.debug('add flow', flow=flow)
        classifier_info = dict()
        action_info = dict()

        for field in fd.get_ofb_fields(flow):
            if field.type == fd.ETH_TYPE:
                classifier_info[ETH_TYPE] = field.eth_type
                self.log.debug('field-type-eth-type',
                               eth_type=classifier_info[ETH_TYPE])
            elif field.type == fd.IP_PROTO:
                classifier_info[IP_PROTO] = field.ip_proto
                self.log.debug('field-type-ip-proto',
                               ip_proto=classifier_info[IP_PROTO])
            elif field.type == fd.IN_PORT:
                classifier_info[IN_PORT] = field.port
                self.log.debug('field-type-in-port',
                               in_port=classifier_info[IN_PORT])
            elif field.type == fd.VLAN_VID:
                classifier_info[VLAN_VID] = field.vlan_vid & 0xfff
                self.log.debug('field-type-vlan-vid',
                               vlan=classifier_info[VLAN_VID])
            elif field.type == fd.VLAN_PCP:
                classifier_info[VLAN_PCP] = field.vlan_pcp
                self.log.debug('field-type-vlan-pcp',
                               pcp=classifier_info[VLAN_PCP])
            elif field.type == fd.UDP_DST:
                classifier_info[UDP_DST] = field.udp_dst
                self.log.debug('field-type-udp-dst',
                               udp_dst=classifier_info[UDP_DST])
            elif field.type == fd.UDP_SRC:
                classifier_info[UDP_SRC] = field.udp_src
                self.log.debug('field-type-udp-src',
                               udp_src=classifier_info[UDP_SRC])
            elif field.type == fd.IPV4_DST:
                classifier_info[IPV4_DST] = field.ipv4_dst
                self.log.debug('field-type-ipv4-dst',
                               ipv4_dst=classifier_info[IPV4_DST])
            elif field.type == fd.IPV4_SRC:
                classifier_info[IPV4_SRC] = field.ipv4_src
                self.log.debug('field-type-ipv4-src',
                               ipv4_dst=classifier_info[IPV4_SRC])
            elif field.type == fd.METADATA:
                classifier_info[METADATA] = field.table_metadata
                self.log.debug('field-type-metadata',
                               metadata=classifier_info[METADATA])
            elif field.type == fd.TUNNEL_ID:
                classifier_info[TUNNEL_ID] = field.tunnel_id
                self.log.debug('field-type-tunnel-id',
                               tunnel_id=classifier_info[TUNNEL_ID])
            else:
                raise NotImplementedError('field.type={}'.format(
                    field.type))

        for action in fd.get_actions(flow):
            if action.type == fd.OUTPUT:
                action_info[OUTPUT] = action.output.port
                self.log.debug('action-type-output',
                               output=action_info[OUTPUT],
                               in_port=classifier_info[IN_PORT])
            elif action.type == fd.POP_VLAN:
                action_info[POP_VLAN] = True
                self.log.debug('action-type-pop-vlan',
                               in_port=classifier_info[IN_PORT])
            elif action.type == fd.PUSH_VLAN:
                action_info[PUSH_VLAN] = True
                action_info[TPID] = action.push.ethertype
                self.log.debug('action-type-push-vlan',
                               push_tpid=action_info[TPID], in_port=classifier_info[IN_PORT])
                if action.push.ethertype != 0x8100:
                    self.log.error('unhandled-tpid',
                                   ethertype=action.push.ethertype)
            elif action.type == fd.SET_FIELD:
                # action_info['action_type'] = 'set_field'
                _field = action.set_field.field.ofb_field
                assert (action.set_field.field.oxm_class ==
                        OFPXMC_OPENFLOW_BASIC)
                self.log.debug('action-type-set-field',
                               field=_field, in_port=classifier_info[IN_PORT])
                if _field.type == fd.VLAN_VID:
                    self.log.debug('set-field-type-vlan-vid',
                                   vlan_vid=_field.vlan_vid & 0xfff)
                    action_info[VLAN_VID] = (_field.vlan_vid & 0xfff)
                else:
                    self.log.error('unsupported-action-set-field-type',
                                   field_type=_field.type)
            else:
                self.log.error('unsupported-action-type',
                               action_type=action.type, in_port=classifier_info[IN_PORT])

        # controller bound trap flows.
        if self.platform.is_controller(action_info[OUTPUT]):
            # trap from pon port.  figure out uni port from tunnel id and set as in port
            if self.platform.intf_id_to_port_type_name(classifier_info[IN_PORT]) == Port.PON_OLT:
                if fd.get_child_port_from_tunnelid(flow) is not None:
                    classifier_info[IN_PORT] = fd.get_child_port_from_tunnelid(flow)
                    self.log.debug('pon-to-controller-flow-port-in-tunnelid', new_in_port=classifier_info[IN_PORT])
                else:
                    self.log.debug('pon-to-controller-flow-NO-PORT-in-tunnelid', in_port=classifier_info[IN_PORT],
                                   out_port=action_info[OUTPUT])
            # TODO NEW CORE: trap from nni port.
            else:
                self.log.warn('nni-to-controller-trap-unsupported', flow=flow)
        else:
            # do not operate on the private decomposer vlan. neither onu nor agg switch adds it.
            # cannot do anything with this flow
            if VLAN_VID in classifier_info and classifier_info[VLAN_VID] == 4000:
                self.log.debug('skipping-private-vlan', in_port=classifier_info[IN_PORT],
                               out_port=action_info[OUTPUT])
                return

            # downstream nni port to pon port.  figure out uni port from tunnel id and set as out port
            if self.platform.intf_id_to_port_type_name(action_info[OUTPUT]) == Port.PON_OLT:
                if fd.get_child_port_from_tunnelid(flow) is not None:
                    action_info[OUTPUT] = fd.get_child_port_from_tunnelid(flow)
                    self.log.debug('downstream-pon-port-flow-port-in-tunnelid', new_out_port=action_info[OUTPUT])
                else:
                    self.log.debug('downstream-pon-port-flow-NO-PORT-in-tunnelid', in_port=classifier_info[IN_PORT],
                                   out_port=action_info[OUTPUT])
                    return

            # upstream pon port to nni port.  figure out uni port from tunnel id and set as in port
            if self.platform.intf_id_to_port_type_name(classifier_info[IN_PORT]) == Port.PON_OLT:
                if fd.get_child_port_from_tunnelid(flow) is not None:
                    classifier_info[IN_PORT] = fd.get_child_port_from_tunnelid(flow)
                    self.log.debug('upstream-pon-port-flow-port-in-tunnelid', new_in_port=classifier_info[IN_PORT])
                else:
                    self.log.debug('upstream-pon-port-flow-NO-PORT-in-tunnelid', in_port=classifier_info[IN_PORT],
                                   out_port=action_info[OUTPUT])
                    return

        self.log.debug('flow-ports', classifier_inport=classifier_info[IN_PORT], action_output=action_info[OUTPUT])
        (port_no, intf_id, onu_id, uni_id) = self.platform.extract_access_from_flow(
            classifier_info[IN_PORT], action_info[OUTPUT])

        self.log.debug('extracted-flow-ports', port_no=port_no, intf_id=intf_id, onu_id=onu_id, uni_id=uni_id)

        # TODO NEW CORE: this needs to be broken into onu type flows that need these ID, and NNI flows that do not
        self.divide_and_add_flow(intf_id, onu_id, uni_id, port_no, classifier_info,
                                            action_info, flow)

    def _clear_flow_id_from_rm(self, flow, flow_id, flow_direction):
        uni_port_no = None
        child_device_id = None
        if flow_direction == UPSTREAM:
            for field in fd.get_ofb_fields(flow):
                if field.type == fd.IN_PORT:
                    is_uni, child_device_id = self._is_uni_port(field.port)
                    if is_uni:
                        uni_port_no = field.port
        elif flow_direction == DOWNSTREAM:
            for field in fd.get_ofb_fields(flow):
                if field.type == fd.METADATA:
                    uni_port = field.table_metadata & 0xFFFFFFFF
                    is_uni, child_device_id = self._is_uni_port(uni_port)
                    if is_uni:
                        uni_port_no = field.port

            if uni_port_no is None:
                for action in fd.get_actions(flow):
                    if action.type == fd.OUTPUT:
                        is_uni, child_device_id = \
                            self._is_uni_port(action.output.port)
                        if is_uni:
                            uni_port_no = action.output.port

        if child_device_id:
            child_device = self.adapter_agent.get_device(child_device_id)
            pon_intf = child_device.proxy_address.channel_id
            onu_id = child_device.proxy_address.onu_id
            uni_id = self.platform.uni_id_from_port_num(uni_port_no) if uni_port_no is not None else None
            flows = self.resource_mgr.get_flow_id_info(pon_intf, onu_id, uni_id, flow_id)
            assert (isinstance(flows, list))
            self.log.debug("retrieved-flows", flows=flows)
            for idx in range(len(flows)):
                if flow_direction == flows[idx]['flow_type']:
                    flows.pop(idx)
                    self.update_flow_info_to_kv_store(pon_intf, onu_id, uni_id, flow_id, flows)
                    if len(flows) > 0:
                        # There are still flows referencing the same flow_id.
                        # So the flow should not be freed yet.
                        # For ex: Case of HSIA where same flow is shared
                        # between DS and US.
                        return

            self.resource_mgr.free_flow_id_for_uni(pon_intf, onu_id, uni_id, flow_id)
        else:
            self.log.error("invalid-info", uni_port_no=uni_port_no,
                           child_device_id=child_device_id)

    def retry_add_flow(self, flow):
        self.log.debug("retry-add-flow")
        if flow.id in self.retry_add_flow_list:
            self.retry_add_flow_list.remove(flow.id)
        self.add_flow(flow)

    def remove_flow(self, flow):
        self.log.debug('trying to remove flows from logical flow :',
                       logical_flow=flow)
        device_flows_to_remove = []
        device_flows = self.flows_proxy.get('/').items
        for f in device_flows:
            if f.cookie == flow.id:
                device_flows_to_remove.append(f)

        for f in device_flows_to_remove:
            (id, direction) = self.decode_stored_id(f.id)
            flow_to_remove = openolt_pb2.Flow(flow_id=id, flow_type=direction)
            try:
                self.stub.FlowRemove(flow_to_remove)
            except grpc.RpcError as grpc_e:
                if grpc_e.code() == grpc.StatusCode.NOT_FOUND:
                    self.log.debug('This flow does not exist on the switch, '
                                   'normal after an OLT reboot',
                                   flow=flow_to_remove)
                else:
                    raise grpc_e

            # once we have successfully deleted the flow on the device
            # release the flow_id on resource pool and also clear any
            # data associated with the flow_id on KV store.
            self._clear_flow_id_from_rm(f, id, direction)
            self.log.debug('flow removed from device', flow=f,
                           flow_key=flow_to_remove)

    def get_tp_path(self, intf_id, uni):
        # FIXME Should get Table id form the flow, as of now hardcoded to
        # DEFAULT_TECH_PROFILE_TABLE_ID (64)
        # 'tp_path' contains the suffix part of the tech_profile_instance path.
        # The prefix to the 'tp_path' should be set to \
        # TechProfile.KV_STORE_TECH_PROFILE_PATH_PREFIX by the ONU adapter.
        return self.tech_profile[intf_id]. \
            get_tp_path(DEFAULT_TECH_PROFILE_TABLE_ID,
                        uni)

    def delete_tech_profile_instance(self, intf_id, onu_id, uni_id):
        # Remove the TP instance associated with the ONU
        ofp_port_name = self._get_ofp_port_name(intf_id, onu_id, uni_id)
        tp_path = self.get_tp_path(intf_id, ofp_port_name)
        return self.tech_profile[intf_id].delete_tech_profile_instance(tp_path)

    @inlineCallbacks
    def divide_and_add_flow(self, intf_id, onu_id, uni_id, port_no, classifier,
                            action, flow):

        self.log.debug('sorting flow', intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, port_no=port_no,
                       classifier=classifier, action=action)

        uni = self.get_uni_port_path(intf_id, onu_id, uni_id)

        # TODO: if there is no onu_id then the flows pushed are NNI based and belows flow pushes need to be refactored
        if (onu_id > 0):
            alloc_id, gem_ports = self.create_tcont_gemport(intf_id, onu_id, uni_id,
                                                            uni, port_no, flow.table_id)
            if alloc_id is None or gem_ports is None:
                self.log.error("alloc-id-gem-ports-unavailable", alloc_id=alloc_id, gem_ports=gem_ports)
                return

            self.log.debug('Generated required alloc and gemport ids', alloc_id=alloc_id, gemports=gem_ports)
        else:
            alloc_id = -1
            gem_ports = []
            self.log.error('cannot-generate-alloc-gem-id-for-flow', intf_id=intf_id, onu_id=onu_id, uni_id=uni_id)

        # TODO: if there are no usable onu, uni, alloc, or gem id, then the below flows are erroneous. this needs a refactor
        # Flows can't be added specific to gemport unless p-bits are received.
        # Hence adding flows for all gemports
        for gemport_id in gem_ports:
            if IP_PROTO in classifier:
                if classifier[IP_PROTO] == 17:
                    self.log.debug('dhcp flow add')
                    self.add_dhcp_trap(intf_id, onu_id, uni_id, port_no, classifier,
                                       action, flow, alloc_id, gemport_id)
                elif classifier[IP_PROTO] == 2:
                    self.log.warn('igmp flow add ignored, not implemented yet')
                else:
                    self.log.warn("Invalid-Classifier-to-handle",
                                  classifier=classifier,
                                  action=action)
            elif ETH_TYPE in classifier:
                if classifier[ETH_TYPE] == EAP_ETH_TYPE:
                    self.log.debug('eapol flow add')
                    self.add_eapol_flow(intf_id, onu_id, uni_id, port_no, flow, alloc_id,
                                        gemport_id)

                    # TODO NEW CORE: Skip trying to add subsequent eap capture for subscriber vlan
                    #  (later attempts at re-eap)
                    #vlan_id = self.get_subscriber_vlan(fd.get_in_port(flow))
                    #if vlan_id is not None:
                    #    self.add_eapol_flow(
                    #        intf_id, onu_id, uni_id, port_no, flow, alloc_id, gemport_id,
                    #        vlan_id=vlan_id)
                    parent_port_no = self.platform.intf_id_to_port_no(intf_id, Port.PON_OLT)

                    self.log.debug('get-child-device', intf_id=intf_id, onu_id=onu_id,
                                   parent_port_no=parent_port_no, device_id=self.device_id)

                    onu_device = yield self.core_proxy.get_child_device(self.device_id,
                                                                     onu_id=int(onu_id),
                                                                     parent_port_no=int(parent_port_no))
                    tp_path = self.get_tp_path(intf_id, uni)

                    tech_msg = InterAdapterTechProfileDownloadMessage(uni_id=uni_id, path=tp_path)

                    self.log.debug('Load-tech-profile-request-to-brcm-handler',
                                   onu_device=onu_device, tp_path=tp_path, tech_msg=tech_msg)

                    # Send the tech profile event to the onu adapter
                    yield self.adapter_proxy.send_inter_adapter_message(
                        msg=tech_msg,
                        type=InterAdapterMessageType.TECH_PROFILE_DOWNLOAD_REQUEST,
                        from_adapter="openolt",
                        to_adapter=onu_device.type,
                        to_device_id=onu_device.id
                    )

                if classifier[ETH_TYPE] == LLDP_ETH_TYPE:
                    self.log.debug('lldp flow add')
                    nni_intf_id = yield self.get_nni_intf_id()
                    self.add_lldp_flow(flow, port_no, nni_intf_id)

            elif PUSH_VLAN in action:
                self.add_upstream_data_flow(intf_id, onu_id, uni_id, port_no, classifier,
                                            action, flow, alloc_id, gemport_id)
            elif POP_VLAN in action:
                self.add_downstream_data_flow(intf_id, onu_id, uni_id, port_no, classifier,
                                              action, flow, alloc_id, gemport_id)
            else:
                self.log.debug('Invalid-flow-type-to-handle',
                               classifier=classifier,
                               action=action, flow=flow)

    def get_uni_port_path(self, intf_id, onu_id, uni_id):
        value = 'pon-{}/onu-{}/uni-{}'.format(intf_id, onu_id, uni_id)
        return value

    def create_tcont_gemport(self, intf_id, onu_id, uni_id, uni, port_no, table_id):
        alloc_id, gem_port_ids = None, None
        pon_intf_onu_id = (intf_id, onu_id)

        # If we already have allocated alloc_id and gem_ports earlier, render them
        alloc_id = \
            self.resource_mgr.get_current_alloc_ids_for_onu(pon_intf_onu_id)
        gem_port_ids = \
            self.resource_mgr.get_current_gemport_ids_for_onu(pon_intf_onu_id)
        if alloc_id is not None and gem_port_ids is not None:
            return alloc_id, gem_port_ids

        try:
            # FIXME: If table id is <= 63 using 64 as table id
            if table_id < DEFAULT_TECH_PROFILE_TABLE_ID:
                table_id = DEFAULT_TECH_PROFILE_TABLE_ID

            # Check tech profile instance already exists for derived port name
            tech_profile_instance = self.tech_profile[intf_id]. \
                get_tech_profile_instance(table_id, uni)
            self.log.debug('Get-tech-profile-instance-status', tech_profile_instance=tech_profile_instance)

            if tech_profile_instance is None:
                # create tech profile instance
                tech_profile_instance = self.tech_profile[intf_id]. \
                    create_tech_profile_instance(table_id, uni,
                                                 intf_id)
                if tech_profile_instance is None:
                    raise Exception('Tech-profile-instance-creation-failed')
            else:
                self.log.debug(
                    'Tech-profile-instance-already-exist-for-given port-name',
                    table_id=table_id, intf_id=intf_id, uni=uni)

            # upstream scheduler
            us_scheduler = self.tech_profile[intf_id].get_us_scheduler(
                tech_profile_instance)
            # downstream scheduler
            ds_scheduler = self.tech_profile[intf_id].get_ds_scheduler(
                tech_profile_instance)
            # create Tcont
            tconts = self.tech_profile[intf_id].get_tconts(tech_profile_instance,
                                                           us_scheduler,
                                                           ds_scheduler)

            self.stub.CreateTconts(openolt_pb2.Tconts(intf_id=intf_id,
                                                      onu_id=onu_id,
                                                      uni_id=uni_id,
                                                      port_no=port_no,
                                                      tconts=tconts))

            # Fetch alloc id and gemports from tech profile instance
            alloc_id = tech_profile_instance.us_scheduler.alloc_id
            gem_port_ids = []
            for i in range(len(
                    tech_profile_instance.upstream_gem_port_attribute_list)):
                gem_port_ids.append(
                    tech_profile_instance.upstream_gem_port_attribute_list[i].
                    gemport_id)
        except BaseException as e:
            self.log.exception(exception=e)

        # Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store
        pon_intf_onu_id = (intf_id, onu_id, uni_id)
        self.resource_mgr.resource_mgrs[intf_id].update_alloc_ids_for_onu(
            pon_intf_onu_id,
            list([alloc_id])
        )
        self.resource_mgr.resource_mgrs[intf_id].update_gemport_ids_for_onu(
            pon_intf_onu_id,
            gem_port_ids
        )

        self.resource_mgr.update_gemports_ponport_to_onu_map_on_kv_store(
            gem_port_ids, intf_id, onu_id, uni_id
        )

        return alloc_id, gem_port_ids

    def add_upstream_data_flow(self, intf_id, onu_id, uni_id, port_no, uplink_classifier,
                               uplink_action, logical_flow, alloc_id,
                               gemport_id):

        uplink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG

        self.add_hsia_flow(intf_id, onu_id, uni_id, port_no, uplink_classifier,
                           uplink_action, UPSTREAM,
                           logical_flow, alloc_id, gemport_id)

        # Secondary EAP on the subscriber vlan
        (eap_active, eap_logical_flow) = self.is_eap_enabled(intf_id, onu_id, uni_id)
        if eap_active:
            self.add_eapol_flow(intf_id, onu_id, uni_id, port_no, eap_logical_flow, alloc_id,
                                gemport_id, vlan_id=uplink_classifier[VLAN_VID])

    def add_downstream_data_flow(self, intf_id, onu_id, uni_id, port_no, downlink_classifier,
                                 downlink_action, flow, alloc_id, gemport_id):
        downlink_classifier[PACKET_TAG_TYPE] = DOUBLE_TAG
        # Needed ???? It should be already there
        downlink_action[POP_VLAN] = True
        downlink_action[VLAN_VID] = downlink_classifier[VLAN_VID]

        self.add_hsia_flow(intf_id, onu_id, uni_id, port_no, downlink_classifier,
                           downlink_action, DOWNSTREAM,
                           flow, alloc_id, gemport_id)

    @inlineCallbacks
    def add_hsia_flow(self, intf_id, onu_id, uni_id, port_no, classifier, action,
                      direction, logical_flow, alloc_id, gemport_id):

        self.log.debug('add hisa flow', flow=logical_flow, port_no=port_no,
                       intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, gemport_id=gemport_id,
                       alloc_id=alloc_id)

        flow_store_cookie = self._get_flow_store_cookie(classifier,
                                                        gemport_id)

        self.log.debug('flow-store-cookie-classifer-action', flow_store_cookie=flow_store_cookie, classifier=classifier,
                       action=action)

        # One of the OLT platform (Broadcom BAL) requires that symmetric
        # flows require the same flow_id to be used across UL and DL.
        # Since HSIA flow is the only symmetric flow currently, we need to
        # re-use the flow_id across both direction. The 'flow_category'
        # takes priority over flow_cookie to find any available HSIA_FLOW
        # id for the ONU.
        flow_id = self.resource_mgr.get_flow_id(intf_id, onu_id, uni_id,
                                                flow_store_cookie,
                                                HSIA_FLOW)
        if flow_id is None:
            self.log.error("hsia-flow-unavailable")
            return

        self.log.debug('flow-id', flow_id=flow_id)

        network_intf_id = yield self.get_nni_intf_id()

        flow = openolt_pb2.Flow(
            access_intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, flow_id=flow_id,
            flow_type=direction, alloc_id=alloc_id, network_intf_id=network_intf_id,
            gemport_id=gemport_id,
            classifier=self.mk_classifier(classifier),
            action=self.mk_action(action),
            priority=logical_flow.priority,
            port_no=port_no,
            cookie=logical_flow.cookie)

        self.log.debug('openolt-agent-flow', hsia_flow=flow)

        if self.add_flow_to_device(flow, logical_flow):
            self.log.debug('added-hsia-openolt-agent-flow', hsia_flow=flow, logical_flow=logical_flow)
            flow_info = self._get_flow_info_as_json_blob(flow,
                                                         flow_store_cookie,
                                                         HSIA_FLOW)
            self.update_flow_info_to_kv_store(flow.access_intf_id,
                                              flow.onu_id, flow.uni_id,
                                              flow.flow_id, flow_info)

    @inlineCallbacks
    def add_dhcp_trap(self, intf_id, onu_id, uni_id, port_no, classifier, action, logical_flow,
                      alloc_id, gemport_id):

        self.log.debug('add dhcp upstream trap', classifier=classifier,
                       intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, action=action)

        action.clear()
        action[TRAP_TO_HOST] = True
        classifier[UDP_SRC] = 68
        classifier[UDP_DST] = 67
        classifier[PACKET_TAG_TYPE] = SINGLE_TAG
        classifier.pop(VLAN_VID, None)

        flow_store_cookie = self._get_flow_store_cookie(classifier,
                                                        gemport_id)

        self.log.debug('flow-store-cookie-classifer-action', flow_store_cookie=flow_store_cookie, classifier=classifier,
                       action=action)

        flow_id = self.resource_mgr.get_flow_id(
            intf_id, onu_id, uni_id, flow_store_cookie
        )

        self.log.debug('flow-id', flow_id=flow_id)

        network_intf_id = yield self.get_nni_intf_id()

        dhcp_flow = openolt_pb2.Flow(
            onu_id=onu_id, uni_id=uni_id, flow_id=flow_id, flow_type=UPSTREAM,
            access_intf_id=intf_id, gemport_id=gemport_id,
            alloc_id=alloc_id, network_intf_id=network_intf_id,
            priority=logical_flow.priority,
            classifier=self.mk_classifier(classifier),
            action=self.mk_action(action),
            port_no=port_no,
            cookie=logical_flow.cookie)

        self.log.debug('openolt-agent-flow', dhcp_flow=dhcp_flow)

        if self.add_flow_to_device(dhcp_flow, logical_flow):
            self.log.debug('added-dhcp-openolt-agent-flow', dhcp_flow=dhcp_flow, logical_flow=logical_flow)
            flow_info = self._get_flow_info_as_json_blob(dhcp_flow, flow_store_cookie)
            self.update_flow_info_to_kv_store(dhcp_flow.access_intf_id,
                                              dhcp_flow.onu_id,
                                              dhcp_flow.uni_id,
                                              dhcp_flow.flow_id,
                                              flow_info)

    @inlineCallbacks
    def add_eapol_flow(self, intf_id, onu_id, uni_id, port_no, logical_flow, alloc_id,
                       gemport_id, vlan_id=DEFAULT_MGMT_VLAN):

        self.log.debug('add eapol upstream trap', flow=logical_flow, port_no=port_no,
                       intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, gemport_id=gemport_id,
                       alloc_id=alloc_id, vlan_id=vlan_id)

        uplink_classifier = dict()
        uplink_classifier[ETH_TYPE] = EAP_ETH_TYPE
        uplink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG
        uplink_classifier[VLAN_VID] = vlan_id

        uplink_action = dict()
        uplink_action[TRAP_TO_HOST] = True

        flow_store_cookie = self._get_flow_store_cookie(uplink_classifier,
                                                        gemport_id)

        self.log.debug('flow-store-cookie-classifier-action', flow_store_cookie=flow_store_cookie, uplink_classifier=uplink_classifier,
                       uplink_action=uplink_action)

        # Add Upstream EAPOL Flow.
        uplink_flow_id = self.resource_mgr.get_flow_id(
            intf_id, onu_id, uni_id, flow_store_cookie
        )

        self.log.debug('flow-id', uplink_flow_id=uplink_flow_id)

        network_intf_id = yield self.get_nni_intf_id()

        upstream_flow = openolt_pb2.Flow(
            access_intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, flow_id=uplink_flow_id,
            flow_type=UPSTREAM, alloc_id=alloc_id, network_intf_id=network_intf_id,
            gemport_id=gemport_id,
            classifier=self.mk_classifier(uplink_classifier),
            action=self.mk_action(uplink_action),
            priority=logical_flow.priority,
            port_no=port_no,
            cookie=logical_flow.cookie)

        self.log.debug('openolt-agent-flow', upstream_flow=upstream_flow)

        logical_flow = copy.deepcopy(logical_flow)
        logical_flow.match.oxm_fields.extend(fd.mk_oxm_fields([fd.vlan_vid(
            vlan_id | 0x1000)]))
        logical_flow.match.type = OFPMT_OXM

        if self.add_flow_to_device(upstream_flow, logical_flow):
            self.log.debug('added-eapol-openolt-agent-flow', upstream_flow=upstream_flow, logical_flow=logical_flow)
            flow_info = self._get_flow_info_as_json_blob(upstream_flow,
                                                         flow_store_cookie)
            self.update_flow_info_to_kv_store(upstream_flow.access_intf_id,
                                              upstream_flow.onu_id,
                                              upstream_flow.uni_id,
                                              upstream_flow.flow_id,
                                              flow_info)

        if vlan_id == DEFAULT_MGMT_VLAN:
            # Add Downstream EAPOL Flow, Only for first EAP flow (BAL
            # requirement)
            # On one of the platforms (Broadcom BAL), when same DL classifier
            # vlan was used across multiple ONUs, eapol flow re-adds after
            # flow delete (cases of onu reboot/disable) fails.
            # In order to generate unique vlan, a combination of intf_id
            # onu_id and uni_id is used.
            # uni_id defaults to 0, so add 1 to it.
            special_vlan_downstream_flow = 4090 - intf_id * onu_id * (uni_id+1)
            # Assert that we do not generate invalid vlans under no condition
            assert (special_vlan_downstream_flow >= 2), 'invalid-vlan-generated'
            self.log.warn('generating-special-downstream-vlan-for-bal', special_vlan_downstream_flow=special_vlan_downstream_flow)

            downlink_classifier = dict()
            downlink_classifier[PACKET_TAG_TYPE] = SINGLE_TAG
            downlink_classifier[VLAN_VID] = special_vlan_downstream_flow

            downlink_action = dict()
            downlink_action[PUSH_VLAN] = True
            downlink_action[VLAN_VID] = vlan_id


            flow_store_cookie = self._get_flow_store_cookie(downlink_classifier,
                                                            gemport_id)

            self.log.debug('flow-store-cookie-classifier-action', flow_store_cookie=flow_store_cookie, downlink_classifier=downlink_classifier,
                           downlink_action=downlink_action)

            downlink_flow_id = self.resource_mgr.get_flow_id(
                intf_id, onu_id, uni_id, flow_store_cookie
            )

            self.log.debug('flow-id', downlink_flow_id=downlink_flow_id)

            downstream_flow = openolt_pb2.Flow(
                access_intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, flow_id=downlink_flow_id,
                flow_type=DOWNSTREAM, alloc_id=alloc_id, network_intf_id=network_intf_id,
                gemport_id=gemport_id,
                classifier=self.mk_classifier(downlink_classifier),
                action=self.mk_action(downlink_action),
                priority=logical_flow.priority,
                port_no=port_no,
                cookie=logical_flow.cookie)

            self.log.debug('openolt-agent-flow', downstream_flow=downstream_flow)

            try:
                downstream_logical_flow = ofp_flow_stats(
                    id=logical_flow.id, cookie=logical_flow.cookie,
                    table_id=logical_flow.table_id, priority=logical_flow.priority,
                    flags=logical_flow.flags)

                downstream_logical_flow.match.oxm_fields.extend(fd.mk_oxm_fields([
                    fd.in_port(fd.get_out_port(logical_flow)),
                    fd.vlan_vid(special_vlan_downstream_flow | 0x1000)]))
                downstream_logical_flow.match.type = OFPMT_OXM

                downstream_logical_flow.instructions.extend(
                    fd.mk_instructions_from_actions([fd.output(
                        self.platform.mk_uni_port_num(intf_id, onu_id, uni_id))]))
            except Exception as e:
                self.log.exception("unexpected-error-building-downstream-logical-flow", intf_id=intf_id, onu_id=onu_id,
                                   uni_id=uni_id, e=e, downstream_flow=downstream_flow)

            if self.add_flow_to_device(downstream_flow, downstream_logical_flow):
                self.log.debug('added-eapol-openolt-agent-flow', downstream_flow=downstream_flow,
                               downstream_logical_flow=downstream_logical_flow)
                flow_info = self._get_flow_info_as_json_blob(downstream_flow,
                                                             flow_store_cookie)
                self.update_flow_info_to_kv_store(downstream_flow.access_intf_id,
                                                  downstream_flow.onu_id,
                                                  downstream_flow.uni_id,
                                                  downstream_flow.flow_id,
                                                  flow_info)

    def repush_all_different_flows(self):
        # Check if the device is supposed to have flows, if so add them
        # Recover static flows after a reboot
        logical_flows = self.logical_flows_proxy.get('/').items
        devices_flows = self.flows_proxy.get('/').items
        logical_flows_ids_provisioned = [f.cookie for f in devices_flows]
        for logical_flow in logical_flows:
            try:
                if logical_flow.id not in logical_flows_ids_provisioned:
                    self.add_flow(logical_flow)
            except Exception as e:
                self.log.exception('Problem reading this flow', e=e)

    def reset_flows(self):
        self.flows_proxy.update('/', Flows())

    """ Add a downstream LLDP trap flow on the NNI interface
    """

    def add_lldp_flow(self, logical_flow, port_no, network_intf_id=0):

        self.log.debug('add lldp trap flow', flow=logical_flow, port_no=port_no,
                       network_intf_id=network_intf_id)

        classifier = dict()
        classifier[ETH_TYPE] = LLDP_ETH_TYPE
        classifier[PACKET_TAG_TYPE] = UNTAGGED
        action = dict()
        action[TRAP_TO_HOST] = True

        # LLDP flow is installed to trap LLDP packets on the NNI port.
        # We manage flow_id resource pool on per PON port basis.
        # Since this situation is tricky, as a hack, we pass the NNI port
        # index (network_intf_id) as PON port Index for the flow_id resource
        # pool. Also, there is no ONU Id available for trapping LLDP packets
        # on NNI port, use onu_id as -1 (invalid)
        # ****************** CAVEAT *******************
        # This logic works if the NNI Port Id falls within the same valid
        # range of PON Port Ids. If this doesn't work for some OLT Vendor
        # we need to have a re-look at this.
        # *********************************************
        onu_id = -1
        uni_id = -1
        flow_store_cookie = self._get_flow_store_cookie(classifier)
        flow_id = self.resource_mgr.get_flow_id(network_intf_id, onu_id, uni_id,
                                                flow_store_cookie)

        self.log.debug('flow-store-cookie-classifier-action', flow_store_cookie=flow_store_cookie, classifier=classifier,
                       action=action)

        downstream_flow = openolt_pb2.Flow(
            access_intf_id=-1,  # access_intf_id not required
            onu_id=onu_id, # onu_id not required
            uni_id=uni_id, # uni_id not used
            flow_id=flow_id,
            flow_type=DOWNSTREAM,
            network_intf_id=network_intf_id,
            gemport_id=-1,  # gemport_id not required
            classifier=self.mk_classifier(classifier),
            action=self.mk_action(action),
            priority=logical_flow.priority,
            port_no=port_no,
            cookie=logical_flow.cookie)

        self.log.debug('openolt-agent-flow', downstream_flow=downstream_flow)

        if self.add_flow_to_device(downstream_flow, logical_flow):
            self.log.debug('added-lldp-openolt-agent-flow', downstream_flow=downstream_flow)
            self.update_flow_info_to_kv_store(network_intf_id, onu_id, uni_id,
                                              flow_id, downstream_flow)

    def mk_classifier(self, classifier_info):

        classifier = openolt_pb2.Classifier()

        if ETH_TYPE in classifier_info:
            classifier.eth_type = classifier_info[ETH_TYPE]
        if IP_PROTO in classifier_info:
            classifier.ip_proto = classifier_info[IP_PROTO]
        if VLAN_VID in classifier_info:
            classifier.o_vid = classifier_info[VLAN_VID]
        if METADATA in classifier_info:
            classifier.i_vid = classifier_info[METADATA]
        if VLAN_PCP in classifier_info:
            classifier.o_pbits = classifier_info[VLAN_PCP]
        if UDP_SRC in classifier_info:
            classifier.src_port = classifier_info[UDP_SRC]
        if UDP_DST in classifier_info:
            classifier.dst_port = classifier_info[UDP_DST]
        if IPV4_DST in classifier_info:
            classifier.dst_ip = classifier_info[IPV4_DST]
        if IPV4_SRC in classifier_info:
            classifier.src_ip = classifier_info[IPV4_SRC]
        if PACKET_TAG_TYPE in classifier_info:
            if classifier_info[PACKET_TAG_TYPE] == SINGLE_TAG:
                classifier.pkt_tag_type = SINGLE_TAG
            elif classifier_info[PACKET_TAG_TYPE] == DOUBLE_TAG:
                classifier.pkt_tag_type = DOUBLE_TAG
            elif classifier_info[PACKET_TAG_TYPE] == UNTAGGED:
                classifier.pkt_tag_type = UNTAGGED
            else:
                classifier.pkt_tag_type = 'none'

        return classifier

    def mk_action(self, action_info):
        action = openolt_pb2.Action()

        if POP_VLAN in action_info:
            action.o_vid = action_info[VLAN_VID]
            action.cmd.remove_outer_tag = True
        elif PUSH_VLAN in action_info:
            action.o_vid = action_info[VLAN_VID]
            action.cmd.add_outer_tag = True
        elif TRAP_TO_HOST in action_info:
            action.cmd.trap_to_host = True
        else:
            self.log.info('Invalid-action-field', action_info=action_info)
            return
        return action

    def is_eap_enabled(self, intf_id, onu_id, uni_id):
        flows = self.logical_flows_proxy.get('/').items

        for flow in flows:
            eap_flow = False
            eap_intf_id = None
            eap_onu_id = None
            eap_uni_id = None
            for field in fd.get_ofb_fields(flow):
                if field.type == fd.ETH_TYPE:
                    if field.eth_type == EAP_ETH_TYPE:
                        eap_flow = True
                if field.type == fd.IN_PORT:
                    eap_intf_id = self.platform.intf_id_from_uni_port_num(
                        field.port)
                    eap_onu_id = self.platform.onu_id_from_port_num(field.port)
                    eap_uni_id = self.platform.uni_id_from_port_num(field.port)

            if eap_flow:
                self.log.debug('eap flow detected', onu_id=onu_id, uni_id=uni_id,
                               intf_id=intf_id, eap_intf_id=eap_intf_id,
                               eap_onu_id=eap_onu_id,
                               eap_uni_id=eap_uni_id)
            if eap_flow and intf_id == eap_intf_id and onu_id == eap_onu_id and uni_id == eap_uni_id:
                return True, flow

        return False, None

    def get_subscriber_vlan(self, port):
        self.log.debug('looking from subscriber flow for port', port=port)

        flows = self.logical_flows_proxy.get('/').items
        for flow in flows:
            in_port = fd.get_in_port(flow)
            out_port = fd.get_out_port(flow)
            if in_port == port and out_port is not None and \
                    self.platform.intf_id_to_port_type_name(out_port) \
                    == Port.ETHERNET_NNI:
                fields = fd.get_ofb_fields(flow)
                self.log.debug('subscriber flow found', fields=fields)
                for field in fields:
                    if field.type == OFPXMT_OFB_VLAN_VID:
                        self.log.debug('subscriber vlan found',
                                       vlan_id=field.vlan_vid)
                        return field.vlan_vid & 0x0fff
        self.log.debug('No subscriber flow found', port=port)
        return None

    def add_flow_to_device(self, flow, logical_flow):
        self.log.debug('pushing flow to device', flow=flow)
        try:
            self.stub.FlowAdd(flow)
        except grpc.RpcError as grpc_e:
            if grpc_e.code() == grpc.StatusCode.ALREADY_EXISTS:
                self.log.warn('flow already exists', e=grpc_e, flow=flow)
            else:
                self.log.error('failed to add flow',
                               logical_flow=logical_flow, flow=flow,
                               grpc_error=grpc_e)
            return False
        except Exception as f:
            self.log.exception("unexpected-openolt-agent-error", flow=flow, logical_flow=logical_flow, f=f)
        else:
            # TODO NEW CORE: Should not need. Core keeps track of logical flows. no need to keep track.  verify, especially olt reboot!
            # self.register_flow(logical_flow, flow)
            return True

    def update_flow_info_to_kv_store(self, intf_id, onu_id, uni_id, flow_id, flow):
        self.log.debug("update-flow-info", intf_id=intf_id, onu_id=onu_id, uni_id=uni_id, flow_id=flow_id, flow=flow)
        self.resource_mgr.update_flow_id_info_for_uni(intf_id, onu_id, uni_id,
                                                      flow_id, flow)

    def register_flow(self, logical_flow, device_flow):
        self.log.debug('registering flow in device',
                       logical_flow=logical_flow, device_flow=device_flow)
        stored_flow = copy.deepcopy(logical_flow)
        stored_flow.id = self.generate_stored_id(device_flow.flow_id,
                                                 device_flow.flow_type)
        self.log.debug('generated device flow id', id=stored_flow.id,
                       flow_id=device_flow.flow_id,
                       direction=device_flow.flow_type)
        stored_flow.cookie = logical_flow.id
        flows = self.flows_proxy.get('/')
        flows.items.extend([stored_flow])
        self.flows_proxy.update('/', flows)

    def find_next_flow(self, flow):
        table_id = fd.get_goto_table_id(flow)
        metadata = 0
        # Prior to ONOS 1.13.5, Metadata contained the UNI output port number. In
        # 1.13.5 and later, the lower 32-bits is the output port number and the
        # upper 32-bits is the inner-vid we are looking for. Use just the lower 32
        # bits.  Allows this code to work with pre- and post-1.13.5 ONOS OltPipeline

        for field in fd.get_ofb_fields(flow):
            if field.type == fd.METADATA:
                metadata = field.table_metadata & 0xFFFFFFFF
        if table_id is None:
            return None
        flows = self.logical_flows_proxy.get('/').items
        next_flows = []
        for f in flows:
            if f.table_id == table_id:
                # FIXME
                if fd.get_in_port(f) == fd.get_in_port(flow) and \
                        fd.get_out_port(f) == metadata:
                    next_flows.append(f)

        if len(next_flows) == 0:
            self.log.warning('no next flow found, it may be a timing issue',
                             flow=flow, number_of_flows=len(flows))
            if flow.id in self.retry_add_flow_list:
                self.log.debug('flow is already in retry list', flow_id=flow.id)
            else:
                self.retry_add_flow_list.append(flow.id)
                reactor.callLater(5, self.retry_add_flow, flow)
            return None

        next_flows.sort(key=lambda f: f.priority, reverse=True)

        return next_flows[0]

    def update_children_flows(self, device_rules_map):

        for device_id, (flows, groups) in device_rules_map.iteritems():
            if device_id != self.device_id:
                self.root_proxy.update('/devices/{}/flows'.format(device_id),
                                       Flows(items=flows.values()))
                self.root_proxy.update('/devices/{}/flow_groups'.format(
                    device_id), FlowGroups(items=groups.values()))

    def clear_flows_and_scheduler_for_logical_port(self, child_device, logical_port):
        ofp_port_name = logical_port.ofp_port.name
        port_no = logical_port.ofp_port.port_no
        pon_port = child_device.proxy_address.channel_id
        onu_id = child_device.proxy_address.onu_id
        uni_id = self.platform.uni_id_from_port_num(logical_port)

        # TODO: The DEFAULT_TECH_PROFILE_ID is assumed. Right way to do,
        # is probably to maintain a list of Tech-profile table IDs associated
        # with the UNI logical_port. This way, when the logical port is deleted,
        # all the associated tech-profile configuration with the UNI logical_port
        # can be cleared.
        tech_profile_instance = self.tech_profile[pon_port]. \
            get_tech_profile_instance(
            DEFAULT_TECH_PROFILE_TABLE_ID,
            ofp_port_name)
        flow_ids = self.resource_mgr.get_current_flow_ids_for_uni(pon_port, onu_id, uni_id)
        self.log.debug("outstanding-flows-to-be-cleared", flow_ids=flow_ids)
        for flow_id in flow_ids:
            flow_infos = self.resource_mgr.get_flow_id_info(pon_port, onu_id, uni_id, flow_id)
            for flow_info in flow_infos:
                direction = flow_info['flow_type']
                flow_to_remove = openolt_pb2.Flow(flow_id=flow_id,
                                                  flow_type=direction)
                try:
                    self.stub.FlowRemove(flow_to_remove)
                except grpc.RpcError as grpc_e:
                    if grpc_e.code() == grpc.StatusCode.NOT_FOUND:
                        self.log.debug('This flow does not exist on the switch, '
                                       'normal after an OLT reboot',
                                       flow=flow_to_remove)
                    else:
                        raise grpc_e

                self.resource_mgr.free_flow_id_for_uni(pon_port, onu_id, uni_id, flow_id)

        try:
            tconts = self.tech_profile[pon_port].get_tconts(tech_profile_instance)
            self.stub.RemoveTconts(openolt_pb2.Tconts(intf_id=pon_port,
                                                      onu_id=onu_id,
                                                      uni_id=uni_id,
                                                      port_no=port_no,
                                                      tconts=tconts))
        except grpc.RpcError as grpc_e:
            self.log.error('error-removing-tcont-scheduler-queues',
                           err=grpc_e)

    def generate_stored_id(self, flow_id, direction):
        if direction == UPSTREAM:
            self.log.debug('upstream flow, shifting id')
            return 0x1 << 15 | flow_id
        elif direction == DOWNSTREAM:
            self.log.debug('downstream flow, not shifting id')
            return flow_id
        else:
            self.log.warn('Unrecognized direction', direction=direction)
            return flow_id

    def decode_stored_id(self, id):
        if id >> 15 == 0x1:
            return id & 0x7fff, UPSTREAM
        else:
            return id, DOWNSTREAM

    def _populate_tech_profile_per_pon_port(self):
        for arange in self.resource_mgr.device_info.ranges:
            for intf_id in arange.intf_ids:
                self.tech_profile[intf_id] = \
                    self.resource_mgr.resource_mgrs[intf_id].tech_profile

        # Make sure we have as many tech_profiles as there are pon ports on
        # the device
        assert len(self.tech_profile) == self.resource_mgr.device_info.pon_ports

    def _get_flow_info_as_json_blob(self, flow, flow_store_cookie,
                                    flow_category=None):
        json_blob = MessageToDict(message=flow,
                                  preserving_proto_field_name=True)
        self.log.debug("flow-info", json_blob=json_blob)
        json_blob['flow_store_cookie'] = flow_store_cookie
        if flow_category is not None:
            json_blob['flow_category'] = flow_category
        flow_info = self.resource_mgr.get_flow_id_info(flow.access_intf_id,
                                                       flow.onu_id, flow.uni_id, flow.flow_id)

        if flow_info is None:
            flow_info = list()
            flow_info.append(json_blob)
        else:
            assert (isinstance(flow_info, list))
            flow_info.append(json_blob)

        return flow_info

    @staticmethod
    def _get_flow_store_cookie(classifier, gem_port=None):
        assert isinstance(classifier, dict)
        # We need unique flows per gem_port
        if gem_port is not None:
            to_hash = dumps(classifier, sort_keys=True) + str(gem_port)
        else:
            to_hash = dumps(classifier, sort_keys=True)
        return hashlib.md5(to_hash).hexdigest()[:12]

    @inlineCallbacks
    def get_nni_intf_id(self):
        if self.nni_intf_id is not None:
            returnValue(self.nni_intf_id)

        port_list = yield self.core_proxy.get_ports(self.device_id, Port.ETHERNET_NNI)
        self.log.debug("nni-ports-list", port_list=port_list)

        # TODO: Hardcoded only first NNI
        port = port_list.items[0]

        self.log.debug("nni-port", port=port)
        self.nni_intf_id = self.platform.intf_id_from_nni_port_num(port.port_no)

        self.log.debug("nni-intf-d ", port=port.port_no, nni_intf_id=self.nni_intf_id)
        returnValue(self.nni_intf_id)
