VOL-2395: Authentication happens on a wrong UNI port after deleting subscribers

- Use TP ID in deriving VlanTaggingFilterDataFrame ME entity ID
- Set TCONT initial value based on omcc version
- Bug fixes on the TP delete path.
- Bump pyvoltha version to 2.3.5

Change-Id: Id3dbec5cf56b6f4bc12b085cfe1b7106b5f254d2
diff --git a/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py b/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
index 0712ccc..94b555b 100644
--- a/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
+++ b/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
@@ -175,6 +175,10 @@
     def pon_port(self):
         return self._pon
 
+    @property
+    def onu_omci_device(self):
+        return self._onu_omci_device
+
     def receive_message(self, msg):
         if self.omci_cc is not None:
             self.omci_cc.receive_message(msg)
@@ -428,7 +432,8 @@
                               uni_id=uni_id)
                 filter_info = self._queued_vlan_filter_task[uni_id]
                 reactor.callLater(0, self._add_vlan_filter_task, filter_info.get("device"),
-                                  uni_id, filter_info.get("uni_port"), filter_info.get("set_vlan_vid"))
+                                  uni_id, filter_info.get("uni_port"), filter_info.get("set_vlan_vid"),
+                                  filter_info.get("tp_id"))
                 # Now remove the entry from the dictionary
                 self._queued_vlan_filter_task[uni_id].clear()
                 self.log.debug("executed-queued-vlan-filter-task",
@@ -627,7 +632,7 @@
                 yield self.core_proxy.device_reason_update(self.device_id, 'tech-profile-config-delete-success')
 
             @inlineCallbacks
-            def failure(_reason, _uni_id, _tp_table_id, _tcont, _gem_port):
+            def failure(_reason):
                 self.log.warn('tech-profile-delete-failure-retrying',
                               _reason=_reason)
                 yield self.core_proxy.device_reason_update(self.device_id,
@@ -638,6 +643,13 @@
 
             self.log.info('deleting-tech-profile-configuration')
 
+            if tcont is None and gem_port is None:
+                if alloc_id is not None:
+                    self.log.error("tcont-info-corresponding-to-alloc-id-not-found", alloc_id=alloc_id)
+                if gem_port_id is not None:
+                    self.log.error("gem-port-info-corresponding-to-gem-port-id-not-found", gem_port_id=gem_port_id)
+                return
+
             self._tp_service_specific_task[uni_id][tp_path] = \
                 BrcmTpDeleteTask(self.omci_agent, self, uni_id, tp_table_id,
                                  tcont=tcont, gem_port=gem_port)
@@ -695,6 +707,15 @@
 
             self.log.debug('bulk-flow-update', device_id=device.id, flow=flow)
             try:
+                write_metadata = fd.get_write_metadata(flow)
+                if write_metadata is None:
+                    self.log.error("do-not-process-flow-without-write-metadata")
+                    return
+
+                # extract tp id from flow
+                tp_id = (write_metadata >> 32) & 0xFFFF
+                self.log.info("tp-id-in-flow", tp_id=tp_id)
+
                 _in_port = fd.get_in_port(flow)
                 assert _in_port is not None
 
@@ -814,30 +835,30 @@
                 if _set_vlan_vid is None or _set_vlan_vid == 0:
                     self.log.warn('ignoring-flow-that-does-not-set-vlanid')
                 else:
-                    self.log.info('set-vlanid', uni_id=uni_id, uni_port=uni_port, set_vlan_vid=_set_vlan_vid)
-                    self._add_vlan_filter_task(device, uni_id, uni_port, _set_vlan_vid)
+                    self.log.info('set-vlanid', uni_id=uni_id, uni_port=uni_port, set_vlan_vid=_set_vlan_vid, tp_id=tp_id)
+                    self._add_vlan_filter_task(device, uni_id, uni_port, _set_vlan_vid, tp_id)
             except Exception as e:
                 self.log.exception('failed-to-install-flow', e=e, flow=flow)
 
-    def _add_vlan_filter_task(self, device, uni_id, uni_port, _set_vlan_vid):
+    def _add_vlan_filter_task(self, device, uni_id, uni_port, _set_vlan_vid, tp_id):
         assert uni_port is not None
         if uni_id in self._tech_profile_download_done and self._tech_profile_download_done[uni_id] != {}:
             @inlineCallbacks
             def success(_results):
-                self.log.info('vlan-tagging-success', uni_port=uni_port, vlan=_set_vlan_vid)
+                self.log.info('vlan-tagging-success', uni_port=uni_port, vlan=_set_vlan_vid, tp_id=tp_id)
                 yield self.core_proxy.device_reason_update(self.device_id, 'omci-flows-pushed')
                 self._vlan_filter_task = None
 
             @inlineCallbacks
             def failure(_reason):
-                self.log.warn('vlan-tagging-failure', uni_port=uni_port, vlan=_set_vlan_vid)
+                self.log.warn('vlan-tagging-failure', uni_port=uni_port, vlan=_set_vlan_vid, tp_id=tp_id)
                 yield self.core_proxy.device_reason_update(self.device_id, 'omci-flows-failed-retrying')
                 self._vlan_filter_task = reactor.callLater(_STARTUP_RETRY_WAIT,
                                                            self._add_vlan_filter_task, device, uni_port.port_number,
-                                                           uni_port, _set_vlan_vid)
+                                                           uni_port, _set_vlan_vid, tp_id)
 
             self.log.info('setting-vlan-tag')
-            self._vlan_filter_task = BrcmVlanFilterTask(self.omci_agent, self, uni_port, _set_vlan_vid)
+            self._vlan_filter_task = BrcmVlanFilterTask(self.omci_agent, self, uni_port, _set_vlan_vid, tp_id)
             self._deferred = self._onu_omci_device.task_runner.queue_task(self._vlan_filter_task)
             self._deferred.addCallbacks(success, failure)
         else:
@@ -846,7 +867,8 @@
             self._queued_vlan_filter_task[uni_id] = {"device": device,
                                                      "uni_id": uni_id,
                                                      "uni_port": uni_port,
-                                                     "set_vlan_vid": _set_vlan_vid}
+                                                     "set_vlan_vid": _set_vlan_vid,
+                                                     "tp_id": tp_id}
 
     def get_tx_id(self):
         self.log.debug('get-tx-id')
diff --git a/python/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py b/python/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
index 3e08584..c115159 100644
--- a/python/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
+++ b/python/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
@@ -41,7 +41,7 @@
     task_priority = 200
     name = "Broadcom VLAN Filter/Tagging Task"
 
-    def __init__(self, omci_agent, handler, uni_port, set_vlan_id, priority=task_priority):
+    def __init__(self, omci_agent, handler, uni_port, set_vlan_id, tp_id, priority=task_priority):
         """
         Class initialization
 
@@ -49,6 +49,7 @@
         :param handler: (BrcmOpenomciOnuHandler) ONU Device Handler Instance
         :param uni_port: (UniPort) Object instance representing the uni port and its settings
         :param set_vlan_id: (int) VLAN to filter for and set
+        :param tp_id: (int) TP ID for the flow
         :param priority: (int) OpenOMCI Task priority (0..255) 255 is the highest
         """
 
@@ -62,6 +63,7 @@
         self._device = omci_agent.get_device(handler.device_id)
         self._uni_port = uni_port
         self._set_vlan_id = set_vlan_id
+        self._tp_id = tp_id
         self._results = None
         self._local_deferred = None
         self._config = self._device.configuration
@@ -114,7 +116,7 @@
 
             # Delete bridge ani side vlan filter
             # TODO: check if its in our local mib first before blindly deleting
-            eid = self._mac_bridge_port_ani_entity_id + self._uni_port.entity_id  # Entity ID
+            eid = self._mac_bridge_port_ani_entity_id + self._uni_port.entity_id + self._tp_id  # Entity ID
             msg = VlanTaggingFilterDataFrame(eid)
             frame = msg.delete()
             self.log.debug('openomci-msg', omci_msg=msg)
diff --git a/python/adapters/brcm_openomci_onu/onu_tcont.py b/python/adapters/brcm_openomci_onu/onu_tcont.py
index 647746b..bc1f230 100644
--- a/python/adapters/brcm_openomci_onu/onu_tcont.py
+++ b/python/adapters/brcm_openomci_onu/onu_tcont.py
@@ -18,14 +18,25 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 from pyvoltha.adapters.extensions.omci.omci_me import TcontFrame
 from pyvoltha.adapters.extensions.omci.omci_defs import ReasonCodes
+from pyvoltha.adapters.extensions.omci.onu_configuration import OMCCVersion
 
 RC = ReasonCodes
 
 
 class OnuTCont(object):
+    G988_OMCC_VERSIONS = [OMCCVersion.G_988_2010_Base,
+                          OMCCVersion.G_988_2011_Amd_1_Base,
+                          OMCCVersion.G_988_2012_Amd_2_Base,
+                          OMCCVersion.G_988_2012_Base,
+                          OMCCVersion.G_988_2010,
+                          OMCCVersion.G_988_2011_Amd_1,
+                          OMCCVersion.G_988_2012_Amd_2,
+                          OMCCVersion.G_988_2012,
+                          OMCCVersion.G_988_2014_Amd_1]
     """
     Broadcom ONU specific implementation
     """
+
     def __init__(self, handler, uni_id, alloc_id, q_sched_policy, traffic_descriptor):
 
         self.log = structlog.get_logger(device_id=handler.device_id, uni_id=uni_id, alloc_id=alloc_id)
@@ -57,7 +68,6 @@
         self.log.debug('function-entry')
         return self._q_sched_policy
 
-
     @q_sched_policy.setter
     def q_sched_policy(self, q_sched_policy):
         sp = ('Null', 'WRR', 'StrictPriority')
@@ -87,7 +97,7 @@
         try:
             # FIXME: self.q_sched_policy seems to be READ-ONLY
             # Ideally the READ-ONLY or NOT attribute is available from ONU-2G ME
-            #msg = TcontFrame(self.entity_id, self.alloc_id, self.q_sched_policy)
+            # msg = TcontFrame(self.entity_id, self.alloc_id, self.q_sched_policy)
             msg = TcontFrame(self.entity_id, self.alloc_id)
             frame = msg.set()
             self.log.debug('openomci-msg', omci_msg=msg)
@@ -109,12 +119,18 @@
         # TODO: magic number, create a named variable
 
         try:
-            msg = TcontFrame(self.entity_id, 0xFF)
+            initial_alloc_id_value = 0xFF
+
+            onu_device = self._handler.onu_omci_device
+            omcc_version = onu_device.configuration.omcc_version
+            if omcc_version in OnuTCont.G988_OMCC_VERSIONS:
+                initial_alloc_id_value = 0xFFFF
+
+            msg = TcontFrame(self.entity_id, initial_alloc_id_value)
             frame = msg.set()
             self.log.debug('openomci-msg', omci_msg=msg)
             results = yield omci.send(frame)
             self.check_status_and_state(results, 'delete-tcont')
-
         except Exception as e:
             self.log.exception('tcont-delete', e=e)
             raise
diff --git a/python/requirements.txt b/python/requirements.txt
index cc93276..1a0c30a 100644
--- a/python/requirements.txt
+++ b/python/requirements.txt
@@ -1,2 +1,2 @@
 voltha-protos==2.1.2
-pyvoltha==2.3.3
+pyvoltha==2.3.5