VOL-1179 Support for Broadcom handler reconcile on vcore restart.
Change-Id: Iffeb7dbf1ff5e0ff18956c7addb2fb8a73374f25
diff --git a/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py b/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
index 4f95cb3..b4817e9 100644
--- a/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
+++ b/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
@@ -162,6 +162,7 @@
if self.omci_cc is not None:
self.omci_cc.receive_message(msg)
+ # Called once when the adapter creates the device/onu instance
def activate(self, device):
self.log.debug('function-entry', device=device)
@@ -182,31 +183,16 @@
device.oper_status = OperStatus.DISCOVERED
self.adapter_agent.update_device(device)
- self._pon = PonPort.create(self, self._pon_port_number)
- self.adapter_agent.add_port(device.id, self._pon.get_port())
-
- self.log.debug('added-pon-port-to-agent', pon=self._pon)
-
- parent_device = self.adapter_agent.get_device(device.parent_id)
- self.logical_device_id = parent_device.parent_id
-
- self.adapter_agent.update_device(device)
-
self.log.debug('set-device-discovered')
- # Create and start the OpenOMCI ONU Device Entry for this ONU
- self._onu_omci_device = self.omci_agent.add_device(self.device_id,
- self.adapter_agent,
- support_classes=self.adapter.broadcom_omci)
- # Port startup
- if self._pon is not None:
- self._pon.enabled = True
+ self._init_pon_state(device)
self.enabled = True
else:
self.log.info('onu-already-activated')
+ # Called once when the adapter needs to re-create device. usually on vcore restart
def reconcile(self, device):
self.log.debug('function-entry', device=device)
@@ -218,10 +204,44 @@
self.proxy_address = device.proxy_address
self.adapter_agent.register_for_proxied_messages(device.proxy_address)
- # TODO: Query ONU current status after reconcile and update.
- # To be addressed in future commits.
+ if self.enabled is not True:
+ self.log.info('reconciling-broadcom-onu-device')
- self.log.info('reconciling-broadcom-onu-device-ends')
+ self._init_pon_state(device)
+
+ # need to restart state machines on vcore restart. there is no indication to do it for us.
+ self._onu_omci_device.start()
+
+ # TODO: this is probably a bit heavy handed
+ # Force a reboot for now. We need indications to reflow to reassign tconts and gems given vcore went away
+ # This may not be necessary when mib resync actually works
+ reactor.callLater(1, self.reboot)
+
+ self.enabled = True
+ else:
+ self.log.info('onu-already-activated')
+
+
+ def _init_pon_state(self, device):
+ self.log.debug('function-entry', device=device)
+
+ self._pon = PonPort.create(self, self._pon_port_number)
+ self.adapter_agent.add_port(device.id, self._pon.get_port())
+
+ self.log.debug('added-pon-port-to-agent', pon=self._pon)
+
+ parent_device = self.adapter_agent.get_device(device.parent_id)
+ self.logical_device_id = parent_device.parent_id
+
+ self.adapter_agent.update_device(device)
+
+ # Create and start the OpenOMCI ONU Device Entry for this ONU
+ self._onu_omci_device = self.omci_agent.add_device(self.device_id,
+ self.adapter_agent,
+ support_classes=self.adapter.broadcom_omci)
+ # Port startup
+ if self._pon is not None:
+ self._pon.enabled = True
# TODO: move to UniPort
def update_logical_port(self, logical_device_id, port_id, state):
@@ -251,6 +271,8 @@
except AttributeError:
self.log.debug('parent-device-delete-child-not-implemented')
+ # Calling this assumes the onu is active/ready and had at least an initial mib downloaded. This gets called from
+ # flow decomposition that ultimately comes from onos
@inlineCallbacks
def update_flow_table(self, device, flows):
self.log.debug('function-entry', device=device, flows=flows)
@@ -394,6 +416,7 @@
_mac_bridge_service_profile_entity_id = 0x201
_mac_bridge_port_ani_entity_id = 0x2102 # TODO: can we just use the entity id from the anis list?
+ # TODO: Move this to a task
# Delete bridge ani side vlan filter
msg = VlanTaggingFilterDataFrame(_mac_bridge_port_ani_entity_id)
frame = msg.delete()
@@ -401,6 +424,7 @@
results = yield self.omci_cc.send(frame)
self.check_status_and_state(results, 'flow-delete-vlan-tagging-filter-data')
+ # TODO: Move this to a task
# Re-Create bridge ani side vlan filter
msg = VlanTaggingFilterDataFrame(
_mac_bridge_port_ani_entity_id, # Entity ID
@@ -439,6 +463,7 @@
treatment_inner_tpid_de=4
)
)
+ # TODO: Move this to a task
msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
_mac_bridge_service_profile_entity_id, # Bridge Entity ID
attributes=attributes # See above
@@ -474,6 +499,7 @@
treatment_inner_tpid_de=4, # set TPID
)
)
+ # TODO: Move this to a task
msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
_mac_bridge_service_profile_entity_id, # Bridge Entity ID
attributes=attributes # See above
@@ -494,6 +520,7 @@
# TODO: Actually conform to or create a proper interface.
# this and the other functions called from the olt arent very clear.
+ # Called each time there is an onu "up" indication from the olt handler
def create_interface(self, data):
self.log.debug('function-entry', data=data)
self._onu_indication = data
@@ -502,6 +529,8 @@
self._subscribe_to_events()
reactor.callLater(1, self._onu_omci_device.start)
+ # Currently called each time there is an onu "down" indication from the olt handler
+ # TODO: possibly other reasons to "update" from the olt?
def update_interface(self, data):
self.log.debug('function-entry', data=data)
oper_state = data.get('oper_state', None)
@@ -518,6 +547,7 @@
else:
self.log.debug('not-changing-openomci-statemachine')
+ # Not currently called by olt or anything else
def remove_interface(self, data):
self.log.debug('function-entry', data=data)
@@ -529,7 +559,7 @@
# TODO: im sure there is more to do here
-
+ # Called when there is an olt up indication, providing the gem port id chosen by the olt handler
def create_gemport(self, data):
self.log.debug('create-gemport', data=data)
gem_portdata = GemportsConfigData()
@@ -552,6 +582,7 @@
self.log.debug('pon-add-gemport', gem_port=gem_port)
+ # Not currently called. Would be called presumably from the olt handler
@inlineCallbacks
def remove_gemport(self, data):
self.log.debug('remove-gemport', data=data)
@@ -564,8 +595,7 @@
#TODO: Create a remove task that encompasses this
-
-
+ # Called when there is an olt up indication, providing the tcont id chosen by the olt handler
def create_tcont(self, tcont_data, traffic_descriptor_data):
self.log.debug('create-tcont', tcont_data=tcont_data, traffic_descriptor_data=traffic_descriptor_data)
tcontdata = TcontsConfigData()
@@ -598,6 +628,7 @@
else:
self.log.info('received-null-tcont-data', tcont=tcont.alloc_id)
+ # Not currently called. Would be called presumably from the olt handler
@inlineCallbacks
def remove_tcont(self, tcont_data, traffic_descriptor_data):
self.log.debug('remove-tcont', tcont_data=tcont_data, traffic_descriptor_data=traffic_descriptor_data)
@@ -608,13 +639,12 @@
# TODO: Create some omci task that encompases this what intended
-
+ # Not currently called. Would be called presumably from the olt handler
def create_multicast_gemport(self, data):
self.log.debug('function-entry', data=data)
# TODO: create objects and populate for later omci calls
-
@inlineCallbacks
def disable(self, device):
self.log.debug('function-entry', device=device)
@@ -654,7 +684,7 @@
self.log.info('reboot-device')
device = self.adapter_agent.get_device(self.device_id)
if device.connect_status != ConnectStatus.REACHABLE:
- self.log.error("device-unreacable")
+ self.log.error("device-unreachable")
returnValue(None)
def success(_results):
@@ -704,6 +734,8 @@
self.update_logical_port(logical_device_id, port_id, OFPPS_LIVE)
+ # Called just before openomci state machine is started. These listen for events from selected state machines,
+ # most importantly, mib in sync. Which ultimately leads to downloading the mib
def _subscribe_to_events(self):
self.log.debug('function-entry')
@@ -726,6 +758,7 @@
bus.unsubscribe(self._in_sync_subscription)
self._in_sync_subscription = None
+ # Called when the mib is in sync
def in_sync_handler(self, _topic, msg):
self.log.debug('function-entry', _topic=_topic, msg=msg)
if self._in_sync_subscription is not None:
@@ -750,6 +783,9 @@
if self._capabilities_subscription is not None:
self.log.debug('capabilities-handler-done')
+ # Mib is in sync, we can now query what we learned and actually start pushing ME (download) to the ONU.
+ # Currently uses a basic mib download task that create a bridge with a single gem port and uni, only allowing EAP
+ # Implement your own MibDownloadTask if you wish to setup something different by default
def _mib_in_sync(self):
self.log.debug('function-entry')
@@ -766,7 +802,7 @@
omci_dev = self._onu_omci_device
config = omci_dev.configuration
- # TODO: run this sooner somehow...
+ # TODO: run this sooner somehow. shouldnt have to wait for mib sync to push an initial download
# In Sync, we can register logical ports now. Ideally this could occur on
# the first time we received a successful (no timeout) OMCI Rx response.
try:
@@ -780,6 +816,8 @@
uni_g = config.uni_g_entities
pptp = config.pptp_entities
+ # Currently logging the ani and uni for information purposes. Actually act on the pptp as its ME ID
+ # is the most correct one to use in later tasks.
for key, value in ani_g.iteritems():
self.log.debug("discovered-ani", key=key, value=value)
@@ -865,6 +903,8 @@
self._mib_download_task = BrcmMibDownloadTask(self.omci_agent, self)
self._deferred = self._onu_omci_device.task_runner.queue_task(self._mib_download_task)
+ # Download an initial mib that creates simple bridge that can pass EAP. On success (above) finally set
+ # the device to active/reachable. This then opens up the handler to openflow pushes from outside
self.log.info('downloading-initial-mib-configuration')
self._mib_download_task = BrcmMibDownloadTask(self.omci_agent, self)
self._deferred = self._onu_omci_device.task_runner.queue_task(self._mib_download_task)