VOL-927: ADTRAN-OLT: Fix for flow setup race condition
Change-Id: I9367bd01cf41617252e211e9353ad10b8f57e719
diff --git a/voltha/adapters/adtran_olt/adtran_olt.py b/voltha/adapters/adtran_olt/adtran_olt.py
index 82015b8..9b846f0 100644
--- a/voltha/adapters/adtran_olt/adtran_olt.py
+++ b/voltha/adapters/adtran_olt/adtran_olt.py
@@ -51,7 +51,7 @@
self.descriptor = Adapter(
id=self.name,
vendor='Adtran, Inc.',
- version='0.15',
+ version='0.16',
config=AdapterConfig(log_level=LogLevel.INFO)
)
log.debug('adtran_olt.__init__', adapter_agent=adapter_agent)
diff --git a/voltha/adapters/adtran_olt/flow/evc.py b/voltha/adapters/adtran_olt/flow/evc.py
index 4260c66..0a762fc 100644
--- a/voltha/adapters/adtran_olt/flow/evc.py
+++ b/voltha/adapters/adtran_olt/flow/evc.py
@@ -209,7 +209,7 @@
Get all EVC Maps that reference this EVC
:return: list of EVCMap
"""
- return list(self._evc_maps.values())
+ return list(self._evc_maps.values()) if self._evc_maps is not None else []
@property
def evc_map_names(self):
@@ -217,11 +217,12 @@
Get all EVC Map names that reference this EVC
:return: list of EVCMap names
"""
- return list(self._evc_maps.keys())
+ return list(self._evc_maps.keys()) if self._evc_maps is not None else []
def add_evc_map(self, evc_map):
- if self._evc_maps is not None:
- self._evc_maps[evc_map.name] = evc_map
+ if self._evc_maps is None:
+ self._evc_maps = {}
+ self._evc_maps[evc_map.name] = evc_map
def remove_evc_map(self, evc_map):
if self._evc_maps is not None and evc_map.name in self._evc_maps:
diff --git a/voltha/adapters/adtran_olt/flow/evc_map.py b/voltha/adapters/adtran_olt/flow/evc_map.py
index 40892aa..239113e 100644
--- a/voltha/adapters/adtran_olt/flow/evc_map.py
+++ b/voltha/adapters/adtran_olt/flow/evc_map.py
@@ -231,7 +231,7 @@
# self._udp_src = None
return xml
- def _ingress_install_xml(self, onu_s_gem_ids_and_vid, acl_list):
+ def _ingress_install_xml(self, onu_s_gem_ids_and_vid, acl_list, create):
from ..onu import Onu
if len(acl_list):
@@ -247,7 +247,7 @@
else onu_or_vlan_id
for gem_id in gem_ids_and_vid[0]:
- xml += '<evc-map>'
+ xml += '<evc-map{}>'.format('' if not create else ' xc:operation="create"')
xml += '<name>{}.{}.{}</name>'.format(self.name, ident, gem_id)
xml += '<ce-vlan-id>{}</ce-vlan-id>'.format(Onu.gem_id_to_gvid(gem_id))
@@ -326,12 +326,12 @@
if not self._installed or self._needs_update:
try:
self._cancel_deferred()
- map_xml = self._ingress_install_xml(self._gem_ids_and_vid, work_acls.values()) \
+ map_xml = self._ingress_install_xml(self._gem_ids_and_vid, work_acls.values(),
+ not self._installed) \
if self._is_ingress_map else self._egress_install_xml()
log.debug('install', xml=map_xml, name=self.name)
results = yield self._handler.netconf_client.edit_config(map_xml)
- was_installed = self._installed
self._installed = results.ok
self._needs_update = results.ok
self.status = '' if results.ok else results.error
@@ -466,6 +466,7 @@
log.debug('find-matching-ingress-flow', logical_port=flow.logical_port, flow=flow.output)
candidate_flows = [f for f in upstream_flow_table.itervalues() if
+ f.in_port == flow.in_port and
f.logical_port == flow.logical_port and
f.output == flow.output and
f.evc_map is not None] # This weeds out this flow
diff --git a/voltha/adapters/adtran_olt/pon_port.py b/voltha/adapters/adtran_olt/pon_port.py
index dd2c3df..d0281ca 100644
--- a/voltha/adapters/adtran_olt/pon_port.py
+++ b/voltha/adapters/adtran_olt/pon_port.py
@@ -293,7 +293,7 @@
Update the port status and state in the core
"""
self.log.debug('update-adapter-agent', admin_state=self._admin_state,
- oper_status=self._oper_status)
+ oper_status=self._oper_status)
# because the core does not provide methods for updating admin
# and oper status per port, we need to copy any existing port
@@ -305,7 +305,7 @@
# copy current Port info
if agent_port is not None:
- self._port = agent_port;
+ self._port = agent_port
# set new states
self._port.admin_state = self._admin_state
@@ -836,8 +836,8 @@
# Hold off ONU activation until at least one GEM Port is defined.
self.log.debug('onu-info', gem_ports=gem_ports)
- return onu_info
- # return onu_info if len(gem_ports) > 0 else None
+ # return onu_info
+ return onu_info if len(gem_ports) > 0 and venet is not None else None
except Exception as e:
self.log.exception('get-onu-info', e=e)
diff --git a/voltha/adapters/adtran_onu/adtran_onu.py b/voltha/adapters/adtran_onu/adtran_onu.py
index b9e8c2f..1f76dfb 100755
--- a/voltha/adapters/adtran_onu/adtran_onu.py
+++ b/voltha/adapters/adtran_onu/adtran_onu.py
@@ -22,13 +22,15 @@
from voltha.adapters.iadapter import OnuAdapter
from voltha.protos import third_party
from adtran_onu_handler import AdtranOnuHandler
+from voltha.extensions.omci.openomci_agent import OpenOMCIAgent, OpenOmciAgentDefaults
+from voltha.extensions.omci.database.mib_db_dict import MibDbVolatileDict
from twisted.internet import reactor
+from copy import deepcopy
_ = third_party
class AdtranOnuAdapter(OnuAdapter):
-
def __init__(self, adapter_agent, config):
self.log = structlog.get_logger()
super(AdtranOnuAdapter, self).__init__(adapter_agent=adapter_agent,
@@ -36,9 +38,31 @@
device_handler_class=AdtranOnuHandler,
name='adtran_onu',
vendor='Adtran, Inc.',
- version='0.7',
+ version='0.9',
device_type='adtran_onu',
vendor_id='ADTN')
+ # Customize OpenOMCI for Adtran ONUs
+ self.adtran_omci = deepcopy(OpenOmciAgentDefaults)
+
+ # TODO: Continue to customize adtran_omci here as needed
+
+ self._omci_agent = OpenOMCIAgent(self.adapter_agent.core,
+ support_classes=self.adtran_omci)
+
+ @property
+ def omci_agent(self):
+ return self._omci_agent
+
+ def start(self):
+ super(AdtranOnuAdapter, self).start()
+ self._omci_agent.start()
+
+ def stop(self):
+ omci, self._omci_agent = self._omci_agent, None
+ if omci is not None:
+ omci.stop()
+
+ super(AdtranOnuAdapter, self).stop()
def suppress_alarm(self, filter):
raise NotImplementedError()
diff --git a/voltha/adapters/adtran_onu/adtran_onu_handler.py b/voltha/adapters/adtran_onu/adtran_onu_handler.py
index 86a70d5..bba4872 100644
--- a/voltha/adapters/adtran_onu/adtran_onu_handler.py
+++ b/voltha/adapters/adtran_onu/adtran_onu_handler.py
@@ -32,9 +32,7 @@
from voltha.protos import third_party
from voltha.protos.common_pb2 import OperStatus, ConnectStatus
-from voltha.protos.device_pb2 import Image
from common.utils.indexpool import IndexPool
-from voltha.extensions.omci.openomci_agent import OpenOMCIAgent
from voltha.extensions.omci.omci_me import *
_ = third_party
@@ -67,11 +65,6 @@
self._deferred = None
self._event_deferred = None
- # TODO: Remove next two lines if/when OpenOMCI is in the core or a container
- # in order to support multiple ONUs per instance
- self._omci_agent = OpenOMCIAgent(self.adapter_agent.core)
- self._omci_agent.start()
-
self._port_number_pool = IndexPool(_MAXIMUM_PORT, 1)
self._olt_created = False # True if deprecated method of OLT creating DA is used
@@ -135,7 +128,7 @@
@property
def omci_agent(self):
- return self._omci_agent
+ return self.adapter.omci_agent
@property
def omci(self):
@@ -589,6 +582,9 @@
device.reason = 'reboot in progress'
self.adapter_agent.update_device(device)
+ # Disable OpenOMCI
+ self.pon_port.enabled = False
+
self._deferred = reactor.callLater(_ONU_REBOOT_MIN,
self._finish_reboot,
previous_oper_status,
@@ -609,6 +605,10 @@
# real OLT the operational state should be the state the device is
# after a reboot.
# Get the latest device reference
+
+ # Restart OpenOMCI
+ self.pon_port.enabled = True
+
device = self.adapter_agent.get_device(self.device_id)
device.oper_status = previous_oper_status
@@ -782,9 +782,8 @@
self._pon.delete()
# OpenOMCI cleanup
- if self._omci_agent is not None:
- self._omci_agent.remove_device(self.device_id, cleanup=True)
- self._omci_agent = None
+ if self.omci_agent is not None:
+ self.omci_agent.remove_device(self.device_id, cleanup=True)
def _check_for_mock_config(self, data):
# Check for MOCK configuration
diff --git a/voltha/adapters/adtran_onu/onu_gem_port.py b/voltha/adapters/adtran_onu/onu_gem_port.py
index 9d5bc61..0cff8ac 100644
--- a/voltha/adapters/adtran_onu/onu_gem_port.py
+++ b/voltha/adapters/adtran_onu/onu_gem_port.py
@@ -15,7 +15,7 @@
import structlog
from voltha.adapters.adtran_olt.xpon.gem_port import GemPort
-from twisted.internet.defer import inlineCallbacks, returnValue, succeed
+from twisted.internet.defer import inlineCallbacks, returnValue
from voltha.extensions.omci.omci_me import GemPortNetworkCtpFrame, GemInterworkingTpFrame
@@ -31,7 +31,6 @@
traffic_class=None,
intf_ref=None,
untagged=False,
- exception=False, # FIXED_ONU
name=None,
handler=None,
is_mock=False):
@@ -43,7 +42,6 @@
traffic_class=traffic_class,
intf_ref=intf_ref,
untagged=untagged,
- exception=exception,
name=name,
handler=handler)
self._is_mock = is_mock
diff --git a/voltha/adapters/adtran_onu/onu_pm_metrics.py b/voltha/adapters/adtran_onu/onu_pm_metrics.py
index 52e1fc7..d4aa5f6 100644
--- a/voltha/adapters/adtran_onu/onu_pm_metrics.py
+++ b/voltha/adapters/adtran_onu/onu_pm_metrics.py
@@ -32,6 +32,7 @@
('rx_alarm_overflow', PmConfig.COUNTER), # Autonomous ONU generated alarm message overflows
('rx_avc_overflow', PmConfig.COUNTER), # Autonomous ONU generated AVC message overflows
('rx_onu_discards', PmConfig.COUNTER), # Autonomous ONU message unknown type discards
+ ('rx_unknown_me', PmConfig.COUNTER), # Managed Entities without a decode definition
('rx_timeouts', PmConfig.COUNTER),
('consecutive_errors', PmConfig.COUNTER),
('reply_min', PmConfig.GUAGE), # Milliseconds
diff --git a/voltha/adapters/adtran_onu/pon_port.py b/voltha/adapters/adtran_onu/pon_port.py
index 40dee83..63c410e 100644
--- a/voltha/adapters/adtran_onu/pon_port.py
+++ b/voltha/adapters/adtran_onu/pon_port.py
@@ -58,7 +58,8 @@
self._onu_omci_device = handler.omci_agent.add_device(handler.device_id,
handler.adapter_agent,
- onu_custom_me_entities())
+ onu_custom_me_entities(),
+ support_classes=handler.adapter.adtran_omci)
# TODO: Add stats, alarm reference, ...
def __str__(self):
@@ -97,6 +98,8 @@
self._admin_state = AdminState.DISABLED
self._oper_status = OperStatus.UNKNOWN
self._update_adapter_agent()
+
+ self._dev_info_loaded = False
# TODO: stop h/w sync
pass
@@ -495,13 +498,12 @@
# -
# TODO: All p-bits currently go to the one and only GEMPORT ID for now
- gem_entity_ids = []
- for gem_port in self._gem_ports.itervalues():
- gem_entity_ids.append(gem_port.entity_id)
+ gem_entity_ids = [gem_port.entity_id for _, gem_port in self._gem_ports.items()] \
+ if len(self._gem_ports) else [OmciNullPointer]
frame = Ieee8021pMapperServiceProfileFrame(
- ieee_mapper_service_profile_entity_id, # 802.1p mapper Service Mapper Profile ID
- interwork_tp_pointers=gem_entity_ids # Interworking TP IDs BP: oldvalue self.gemid
+ ieee_mapper_service_profile_entity_id, # 802.1p mapper Service Mapper Profile ID
+ interwork_tp_pointers=gem_entity_ids # Interworking TP IDs BP: oldvalue self.gemid
).set()
results = yield omci.send(frame)
@@ -811,7 +813,7 @@
in_sync = msg[IN_SYNC_KEY]
if in_sync:
- # Only call this once as well
+ # Only call this once as well (after PON enable)
bus = self._onu_omci_device.event_bus
bus.unsubscribe(self._in_sync_subscription)
self._in_sync_subscription = None