| # |
| # 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. |
| # |
| from struct import pack, unpack |
| |
| from twisted.internet import reactor |
| from twisted.internet.defer import DeferredQueue, inlineCallbacks, returnValue |
| |
| from scapy.automaton import ATMT |
| import structlog |
| from voltha.adapters.microsemi_olt.BaseOltAutomaton import BaseOltAutomaton |
| from voltha.adapters.microsemi_olt.PAS5211 import PAS5211EventOnuActivation, PAS5211MsgGetActivationAuthMode, \ |
| PAS5211MsgGetActivationAuthModeResponse, PAS5211MsgSetOnuOmciPortId, \ |
| PAS5211MsgSetOnuOmciPortIdResponse, PAS5211MsgSendFrame, PAS5211MsgSendFrameResponse, \ |
| PAS5211MsgGetLogicalObjectStatus, PAS5211MsgGetLogicalObjectStatusResponse, PAS5211MsgSetOnuAllocId, \ |
| PAS5211MsgGetDbaMode, PAS5211MsgGetDbaModeResponse, PAS5211MsgSendDbaAlgorithmMsg, \ |
| PAS5211MsgSendDbaAlgorithmMsgResponse, PAS5211EventDbaAlgorithm, PAS5211MsgSetPortIdConfig, \ |
| PAS5211MsgSetPortIdConfigResponse, PAS5211MsgGetOnuIdByPortId, PAS5211MsgGetOnuIdByPortIdResponse, \ |
| PAS5211SetVlanUplinkConfiguration, PAS5211SetVlanUplinkConfigurationResponse, PAS5211MsgSetOnuAllocIdResponse, \ |
| PAS5211MsgHeader, PAS5211MsgGetOltVersionResponse, PAS5211EventOnuDeactivation, PAS5211EventAlarmNotification |
| |
| #PAS5211EventAlarmNotification, PAS5211EventOnuDeactivation |
| from voltha.adapters.microsemi_olt.PAS5211_constants import PON_ACTIVATION_AUTH_AUTO, PON_ENABLE, PON_PORT_PON, \ |
| PON_LOGICAL_OBJECT_TYPE_ALLOC_ID, PON_LOGICAL_OBJECT_TYPE_ONU_ID_BY_ALLOC_ID, PON_TRUE, \ |
| PMC_OFAL_MAX_BI_DIRECTIONAL_FLOW_PER_ONU, PMC_OFAL_START_FLOW_ID_BASE, PON_DBA_MODE_RUNNING, \ |
| PYTHAGORAS_UPDATE_AID_SLA, SLA_be_bw_gros, SLA_gr_bw_gros, SLA_gr_bw_fine, SLA_be_bw_fine, PYTHAGORAS_DBA_DATA_COS, \ |
| PYTHAGORAS_DBA_STATUS_REPORT_NSR, PYTHAGORAS_SET_SLA_RESP_SIZE, PON_PORT_TYPE_GEM, PON_PORT_DESTINATION_CNI0, \ |
| PON_FALSE, PON_DISABLE, PON_ALARM_LOS, PASCOMM_RETRIES, \ |
| PON_ALARM_LOSI, PON_ALARM_DOWI, PON_ALARM_LOFI, PON_ALARM_RDII, PON_ALARM_LOAMI, PON_ALARM_LCDGI, \ |
| PON_ALARM_LOAI, PON_ALARM_SDI, PON_ALARM_SFI, PON_ALARM_PEE, PON_ALARM_DGI, PON_ALARM_LOKI, PON_ALARM_TIWI, \ |
| PON_ALARM_TIA, PON_ALARM_AUTH_FAILED_IN_REGISTRATION_ID_MODE, PON_ALARM_SUFI,\ |
| PON_DOWNSTREAM_PLOAM_MESSAGE_ENCRYPTED_PORT_ID, PON_DOWNSTREAM_PLOAM_MESSAGE_ASSIGN_ALLOC_ID, \ |
| PON_DOWNSTREAM_PLOAM_MESSAGE_CONFIGURE_PORT_ID, PON_DOWNSTREAM_PLOAM_MESSAGE_BER_INTERVAL, \ |
| PON_DOWNSTREAM_PLOAM_MESSAGE_KEY_SWITCHING, PON_ALARM_SDI_RAISE, PON_ALARM_SDI_CLEAR, \ |
| PON_ALARM_RAISE, PON_ALARM_CLEAR |
| |
| from voltha.extensions.omci.omci_entities import CircuitPack |
| from voltha.extensions.omci.omci_frame import OmciFrame |
| from voltha.extensions.omci.omci_messages import OmciGet, OmciGetResponse, OmciAlarmNotification |
| |
| |
| from twisted.internet import reactor |
| |
| from voltha.protos.events_pb2 import AlarmEvent, AlarmEventType, \ |
| AlarmEventSeverity, AlarmEventState, AlarmEventCategory, AlarmEventCategory |
| |
| log = structlog.get_logger() |
| _verbose = False |
| |
| MAX_RETRIES = 10 |
| |
| def alloc_id(onu_id): |
| for i in range(0, PMC_OFAL_MAX_BI_DIRECTIONAL_FLOW_PER_ONU): |
| alloc_id = PMC_OFAL_START_FLOW_ID_BASE + \ |
| (onu_id * PMC_OFAL_MAX_BI_DIRECTIONAL_FLOW_PER_ONU) + i |
| yield alloc_id |
| |
| |
| def hexstring(string): |
| return ":".join("{:02x}".format(ord(c)) for c in string) |
| |
| |
| class ActivationManager(BaseOltAutomaton): |
| |
| onu_id = None |
| serial_number = None |
| onu_session_id = None |
| port_id = None |
| channel_id = None |
| alloc_id = None |
| vendor = None |
| olt_adapter = None |
| retries = 0 |
| |
| def parse_args(self, debug=0, store=0,**kwargs): |
| self.onu_id = kwargs.pop('onu_id') |
| self.serial_number = kwargs.pop('serial_number') |
| self.onu_session_id = kwargs.pop('onu_session_id') |
| self.port_id = self.onu_id |
| self.channel_id = kwargs.pop('channel_id') |
| self.alloc_id = alloc_id(self.onu_id) |
| self.activation_watcher = kwargs.pop('activation_watcher') |
| self.olt_adapter = kwargs.pop('olt_adapter') |
| |
| if self.onu_id is None or self.serial_number is None or \ |
| self.onu_session_id is None or self.channel_id is None: |
| raise ValueError('ONU is not well defined') |
| |
| BaseOltAutomaton.parse_args(self, debug=debug, store=store, **kwargs) |
| |
| """ |
| Master filter: Do not allow PAS5211MsgGetOltVersionResponse |
| """ |
| |
| def master_filter(self, pkt): |
| |
| if not super(ActivationManager, self).master_filter(pkt): |
| return False |
| |
| |
| if OmciFrame in pkt: |
| if pkt[OmciFrame].message_type in (16, 17): |
| return False |
| |
| if PAS5211MsgGetOltVersionResponse not in pkt: |
| if PAS5211MsgHeader in pkt: |
| if pkt[PAS5211MsgHeader].channel_id == self.channel_id: |
| return True |
| |
| return False |
| |
| def create_default_data_flow_olt_config(self): |
| # PAS_set_onu_alloc_id |
| # PYTHAGORAS_set_SLA |
| # PAS_map_port_id_to_alloc_id |
| # PAS_set_vlan_uplink_configuration |
| pass |
| |
| # def register_activation_watcher(self, activation_watcher): |
| # self.activation_watcher = activation_watcher |
| |
| """ |
| States |
| """ |
| |
| @ATMT.state(initial=1) |
| def got_activation_event(self): |
| pass |
| |
| @ATMT.state() |
| def wait_get_auth_mode(self): |
| pass |
| |
| @ATMT.state() |
| def got_auth_mode(self): |
| pass |
| |
| @ATMT.state() |
| def wait_omci_port_id(self): |
| pass |
| |
| @ATMT.state() |
| def got_omci_port_id(self): |
| pass |
| |
| @ATMT.state() |
| def wait_send_frame(self): |
| pass |
| |
| @ATMT.state() |
| def wait_omci_get(self): |
| pass |
| |
| @ATMT.state() |
| def wait_logical_object_status(self): |
| pass |
| |
| @ATMT.state() |
| def wait_set_alloc_id(self): |
| pass |
| |
| @ATMT.state() |
| def wait_dba_mode(self): |
| pass |
| |
| @ATMT.state(final=1) |
| def end(self): |
| log.debug("activation-manager-end") |
| self.activation_watcher.next_activation() |
| |
| |
| @ATMT.state(error=1) |
| def error(self, msg): |
| log.error(msg) |
| raise self.end() |
| |
| """ |
| Utility Methods |
| """ |
| |
| def px(self, pkt): |
| return self.p(pkt, channel_id=self.channel_id, |
| onu_id=self.onu_id, onu_session_id=self.onu_session_id) |
| |
| def detect_onu(self): |
| try: |
| log.info("Activated {} ONT, channel_id={}, onu_id={}, session_id={}, serial={} ".format( |
| self.vendor, self.channel_id, self.onu_id, self.onu_session_id, hexstring(self.serial_number))) |
| |
| parent_port = self.channel_id * 32 + (self.onu_id + 1) |
| self.olt_adapter.add_onu_info(parent_port, self.onu_id, self.onu_session_id) |
| |
| self.device.onu_detected( |
| parent_port_no=parent_port, |
| child_device_type='%s_onu' % self.vendor.lower(), |
| onu_id=self.onu_id, |
| serial_number=hexstring(self.serial_number), |
| onu_session_id=self.onu_session_id, |
| channel_id=self.channel_id |
| ) |
| |
| except Exception as e: |
| log.exception('detect-onu-failed', e=e) |
| # raise e |
| |
| """ |
| Transitions |
| """ |
| |
| # Transition from got_activation_event |
| @ATMT.condition(got_activation_event) |
| def send_get_activation_auth_mode(self): |
| log.debug('PAS5211MsgGetActivationAuthMode, channel_id={}'.format(self.channel_id)) |
| auth_mode = PAS5211MsgGetActivationAuthMode() |
| self.send(self.p(auth_mode, channel_id=self.channel_id)) |
| raise self.wait_get_auth_mode() |
| |
| # Transitions from wait_get_auth_mode |
| @ATMT.timeout(wait_get_auth_mode, 3) |
| def timeout_get_auth_mode(self): |
| if self.retries < MAX_RETRIES: |
| self.retries += 1 |
| self.send_get_activation_auth_mode() |
| else: |
| raise self.error('Could not get auth mode for OLT {}; dropping activation event for {}' |
| .format(self.target, hexstring(self.serial_number))) |
| |
| @ATMT.receive_condition(wait_get_auth_mode) |
| def wait_for_get_auth_mode(self, pkt): |
| log.debug('wait_for_get_auth_mode') |
| if PAS5211MsgGetActivationAuthModeResponse in pkt: |
| log.debug('PAS5211MsgGetActivationAuthModeResponse') |
| pkt = pkt[PAS5211MsgGetActivationAuthModeResponse] |
| if pkt.mode == PON_ACTIVATION_AUTH_AUTO: |
| raise self.got_auth_mode() |
| else: |
| # TODO There may be something that can be done here. |
| # See line 2497 of PAS_onu_mode_change_thread.c |
| log.error( |
| 'Got unknown auth mode {}; dropping activation event'.format(pkt.mode)) |
| raise self.end() |
| |
| # Transitions from got auth_mode |
| @ATMT.condition(got_auth_mode) |
| def send_omci_port_id(self): |
| log.debug('send_omci_port_id') |
| omci_port_id = PAS5211MsgSetOnuOmciPortId( |
| port_id=self.port_id, activate=PON_ENABLE) |
| self.send(self.px(omci_port_id)) |
| raise self.wait_omci_port_id() |
| |
| # Transitions from wait_omci_port_id |
| @ATMT.timeout(wait_omci_port_id, 3) |
| def timeout_omci_port_id(self): |
| if self.retries < MAX_RETRIES: |
| self.retries += 1 |
| self.send_omci_port_id() |
| else: |
| raise self.error('Could not set omci port id for OLT {}; dropping activation event for {}' |
| .format(self.target, hexstring(self.serial_number))) |
| |
| @ATMT.receive_condition(wait_omci_port_id) |
| def wait_for_omci_port_id(self, pkt): |
| log.debug('wait_for_omci_port_id') |
| if PAS5211MsgSetOnuOmciPortIdResponse in pkt: |
| log.debug('PAS5211MsgSetOnuOmciPortIdResponse') |
| msg_header = pkt[PAS5211MsgHeader] |
| if msg_header.opcode == PAS5211MsgSetOnuOmciPortIdResponse.opcode and \ |
| msg_header.onu_id == self.onu_id and msg_header.onu_session_id == self.onu_session_id and \ |
| msg_header.channel_id == self.channel_id: |
| raise self.got_omci_port_id() |
| |
| # Transitions from got_omci_port_id |
| @ATMT.condition(got_omci_port_id) |
| def send_omci_identity_frame(self): |
| log.debug('send_omci_identity_frame') |
| |
| message = OmciGet(entity_class=CircuitPack.class_id, entity_id=257, |
| attributes_mask=2048) |
| # TODO fix transaction id |
| frame = OmciFrame(transaction_id=0, message_type=OmciGet.message_id, |
| omci_message=message) |
| omci_frame = PAS5211MsgSendFrame(port_type=PON_PORT_PON, port_id=self.port_id, |
| management_frame=PON_ENABLE, frame=frame) |
| |
| self.send(self.px(omci_frame)) |
| |
| raise self.wait_send_frame() |
| |
| # Transitions from wait_send_frame |
| @ATMT.timeout(wait_send_frame, 3) |
| def timeout_send_frame(self): |
| if self.retries < MAX_RETRIES: |
| self.retries += 1 |
| self.send_omci_identity_frame() |
| else: |
| raise self.error('Could not send omci to OLT {}; dropping activation event for {}' |
| .format(self.target, hexstring(self.serial_number))) |
| |
| @ATMT.receive_condition(wait_send_frame) |
| def wait_for_send_frame(self, pkt): |
| log.debug('wait_for_send_frame') |
| if PAS5211MsgSendFrameResponse in pkt: |
| log.debug('PAS5211MsgSendFrameResponse') |
| raise self.wait_omci_get() |
| |
| # Transitions from wait_omci_get |
| @ATMT.timeout(wait_omci_get, 3) |
| def timeout_omci_get(self): |
| if self.retries < MAX_RETRIES: |
| self.retries += 1 |
| self.send_omci_identity_frame() |
| else: |
| raise self.error('Did not receive omci get event from OLT {}; dropping activation event for {}' |
| .format(self.target, hexstring(self.serial_number))) |
| |
| @ATMT.receive_condition(wait_omci_get) |
| def wait_for_omci_get(self, pkt): |
| log.debug('wait_for_omci_get') |
| if OmciGetResponse in pkt: |
| log.debug('OmciGetResponse') |
| self.allocId = self.alloc_id.next() |
| #self.vendor = pkt['OmciGetResponse'].data['vendor_id'] |
| self.vendor = pkt[OmciGetResponse].data['vendor_id'] |
| log.debug('wait_for_omci_get vendor_id:' + self.vendor) |
| l_obj_status = PAS5211MsgGetLogicalObjectStatus( |
| type=PON_LOGICAL_OBJECT_TYPE_ALLOC_ID, |
| value=self.allocId) |
| self.send(self.p(l_obj_status, channel_id=self.channel_id)) |
| raise self.wait_logical_object_status() |
| |
| # Transitions from wait_logical_object_status |
| @ATMT.timeout(wait_logical_object_status, 3) |
| def timeout_logical_object_status(self): |
| if self.retries < MAX_RETRIES: |
| self.retries += 1 |
| l_obj_status = PAS5211MsgGetLogicalObjectStatus( |
| type=PON_LOGICAL_OBJECT_TYPE_ALLOC_ID, |
| value=self.allocId) |
| self.send(self.p(l_obj_status, channel_id=self.channel_id)) |
| else: |
| raise self.error('Did not receive info about alloc id status for {}; dropping activation event for {}' |
| .format(self.target, hexstring(self.serial_number))) |
| |
| @ATMT.receive_condition(wait_logical_object_status) |
| def wait_for_logical_object_status(self, pkt): |
| log.debug('wait_for_logical_object_status') |
| if PAS5211MsgGetLogicalObjectStatusResponse in pkt: |
| pkt = pkt[PAS5211MsgGetLogicalObjectStatusResponse] |
| log.debug('PAS5211MsgGetLogicalObjectStatusResponse pkt.type=' + str(pkt.type) + ' pkt.return_value=' + str( |
| pkt.return_value)) |
| if pkt.type == PON_LOGICAL_OBJECT_TYPE_ALLOC_ID: # PASCOMM_GPON_api_parser.c line:11994 |
| if pkt.return_value == 0: |
| log.debug( |
| 'PAS5211MsgGetLogicalObjectStatusResponse (pkt.return_value == 0)') |
| # alloc-id not set |
| set_alloc_id = PAS5211MsgSetOnuAllocId( |
| alloc_id=self.allocId, |
| allocate=PON_ENABLE |
| ) |
| # self.onu_id = -1 |
| self.port_id = self.allocId |
| self.send(self.px(set_alloc_id)) |
| raise self.wait_set_alloc_id() |
| else: |
| log.debug( |
| 'PAS5211MsgGetLogicalObjectStatusResponse (pkt.return_value != 0)') |
| l_obj_status = PAS5211MsgGetLogicalObjectStatus( |
| type=PON_LOGICAL_OBJECT_TYPE_ONU_ID_BY_ALLOC_ID, |
| value=self.allocId) |
| self.send(self.px(l_obj_status)) |
| raise self.wait_logical_object_status() |
| elif pkt.type == PON_LOGICAL_OBJECT_TYPE_ONU_ID_BY_ALLOC_ID: |
| log.debug( |
| 'PAS5211MsgGetLogicalObjectStatusResponse (pkt.type == PON_LOGICAL_OBJECT_TYPE_ALLOC_ID)') |
| # That's your onu id. |
| self.onu_id = pkt.return_value |
| # FIXME Need to iterate to get the port id as |
| # in PMC_OFAL_flow_db.c line 656 |
| set_alloc_id = PAS5211MsgSetOnuAllocId( |
| alloc_id=self.allocId, |
| allocate=PON_ENABLE |
| ) |
| self.send(self.px(set_alloc_id)) |
| raise self.wait_set_alloc_id() # are we done? probably not but check |
| |
| # Transitions from wait_set_alloc_id |
| @ATMT.timeout(wait_set_alloc_id, 3) |
| def timeout_set_alloc_id(self): |
| if self.retries < MAX_RETRIES: |
| self.retries += 1 |
| set_alloc_id = PAS5211MsgSetOnuAllocId( |
| alloc_id=self.allocId, |
| allocate=PON_ENABLE |
| ) |
| self.send(self.px(set_alloc_id)) |
| else: |
| raise self.error('Was not able to set alloc id for {}; dropping activation event for {}' |
| .format(self.target, hexstring(self.serial_number))) |
| |
| @ATMT.receive_condition(wait_set_alloc_id) |
| def wait_for_set_alloc_id(self, pkt): |
| log.debug('wait_for_set_alloc_id') |
| if PAS5211MsgSetOnuAllocIdResponse in pkt: |
| self.send(self.p(PAS5211MsgGetDbaMode(), |
| channel_id=self.channel_id)) |
| raise self.wait_dba_mode() |
| |
| # Transitions from wait for dba mode (See Pythagoras_api.c line 344 & |
| # PMC_OFAL.c 2062) |
| @ATMT.timeout(wait_dba_mode, 3) |
| def timeout_wait_dba_mode(self): |
| if self.retries < MAX_RETRIES: |
| self.retries += 1 |
| self.send(self.p(PAS5211MsgGetDbaMode(), |
| channel_id=self.channel_id)) |
| else: |
| raise self.error('Did not get DBA mode for {}; dropping activation event for {}' |
| .format(self.target, hexstring(self.serial_number))) |
| |
| @ATMT.receive_condition(wait_dba_mode) |
| def wait_for_dba_mode(self, pkt): |
| if PAS5211MsgGetDbaModeResponse in pkt: |
| pkt = pkt[PAS5211MsgGetDbaModeResponse] |
| if pkt.dba_mode != PON_DBA_MODE_RUNNING: |
| raise self.error('DBA is not running; dropping activation event for {}' |
| .format(hexstring(self.serial_number))) |
| self.detect_onu() |
| raise self.end() |
| |
| |
| class ActivationWatcher(BaseOltAutomaton): |
| """ |
| Master filter: Do not allow PAS5211MsgGetOltVersionResponse |
| """ |
| |
| pending_activation_events = [] |
| activation_lock = False |
| olt_adapter = None |
| |
| def master_filter(self, pkt): |
| if not super(ActivationWatcher, self).master_filter(pkt): |
| return False |
| |
| if PAS5211EventOnuActivation in pkt: |
| return True |
| |
| elif PAS5211EventOnuDeactivation in pkt: |
| return True |
| |
| elif PAS5211EventAlarmNotification in pkt: |
| return True |
| |
| elif OmciAlarmNotification in pkt: |
| return True |
| |
| return False |
| |
| |
| # Callback from activation manager |
| def next_activation(self): |
| log.debug("next-activation") |
| if self.pending_activation_events: |
| self.activation_lock=True |
| # Retrieve last element from list |
| pkt = self.pending_activation_events.pop() |
| self.activate_onu(pkt) |
| else: |
| self.activation_lock = False |
| |
| def parse_args(self, debug=0, store=0,**kwargs): |
| self.olt_adapter = kwargs.pop('olt_adapter') |
| BaseOltAutomaton.parse_args(self, **kwargs) |
| |
| def activate_onu(self, pkt): |
| log.debug("activate-onu") |
| msg_header = pkt[PAS5211MsgHeader] |
| msg = pkt[PAS5211EventOnuActivation] |
| log.debug('{} activated'.format(hexstring(msg.serial_number))) |
| onu_activation = ActivationManager(iface=self.iface, target=self.target, comm=self.comm, |
| onu_id=msg_header.onu_id, serial_number=msg.serial_number, |
| onu_session_id=msg_header.onu_session_id, |
| channel_id=msg_header.channel_id, device=self.device, activation_watcher=self, olt_adapter=self.olt_adapter) |
| |
| onu_activation.runbg() |
| |
| def deactivate_onu(self, pkt): |
| log.debug("deactivate-onu") |
| msg_header = pkt[PAS5211MsgHeader] |
| try: |
| log.debug("Deactivating ONT, channel_id={}, onu_id={}, session_id={}".format( |
| msg_header.channel_id, msg_header.onu_id, msg_header.onu_session_id)) |
| |
| self.device.deactivate_onu(channel_id=msg_header.channel_id, |
| onu_id=msg_header.onu_id, |
| onu_session_id=msg_header.onu_session_id) |
| |
| log.debug("Deactivated ONT, channel_id={}, onu_id={}, session_id={}".format( |
| msg_header.channel_id, msg_header.onu_id, msg_header.onu_session_id)) |
| except Exception as e: |
| log.exception('deactivate-onu failed', e=e) |
| |
| """ |
| States |
| """ |
| |
| @ATMT.state(initial=1) |
| def wait_onu_activation_event(self): |
| log.debug('activation-watcher-start') |
| |
| @ATMT.state(final=1) |
| def end(self): |
| log.debug('activation-watcher-end') |
| |
| """ |
| Transitions |
| """ |
| |
| # Transitions from wait_onu_activation_event |
| @ATMT.receive_condition(wait_onu_activation_event) |
| def wait_for_onu_activation_event(self, pkt): |
| if PAS5211EventOnuActivation in pkt: |
| log.debug('PAS5211EventOnuActivation Received') |
| |
| self.pending_activation_events.append(pkt) |
| |
| if not self.activation_lock: |
| self.next_activation() |
| |
| elif PAS5211EventOnuDeactivation in pkt: |
| log.debug('PAS5211EventOnuDeactivation Received') |
| self.deactivate_onu(pkt) |
| |
| elif PAS5211EventAlarmNotification in pkt: |
| msg = pkt[PAS5211EventAlarmNotification] |
| log.debug('PAS5211EventAlarmNotification Received', code=msg.code, parameter1= msg.parameter1, parameter2= msg.parameter2, |
| parameter3= msg.parameter3, parameter4= msg.parameter4) |
| try: |
| self.process_alarm(pkt) |
| except Exception as e: |
| log.exception('wait-for-onu-activation-alarm-event-error', e=e) |
| |
| elif OmciAlarmNotification in pkt: |
| log.debug('OmciAlarmNotification Received') |
| try: |
| self.process_omci_alarm(pkt) |
| except Exception as e: |
| log.exception('wait-for-onu-activation-omci-alarm-event-error', e=e) |
| |
| else: |
| pass |
| |
| raise self.wait_onu_activation_event() |
| |
| |
| #Method to parse alarm and send it to DeviceManager |
| def process_alarm(self, pkt): |
| log.debug('proccess-alarm-start') |
| msg_header = pkt[PAS5211MsgHeader] |
| msg = pkt[PAS5211EventAlarmNotification] |
| code = msg.code |
| |
| ctx = { |
| 'alarm_code': str(code), |
| } |
| |
| alarm = dict( |
| id='voltha.{}.{}.olt'.format(self.device.adapter_agent.adapter_name, self.device.device.id), |
| resource_id=self.device.device.id, |
| type=AlarmEventType.EQUIPMENT, |
| category=AlarmEventCategory.OLT, |
| severity=AlarmEventSeverity.MAJOR, |
| context=ctx |
| ) |
| |
| if msg_header.onu_id >= 0: |
| ctx['onu_id'] = str(msg_header.onu_id) |
| if msg_header.channel_id >= 0: |
| ctx['channel_id'] = str(msg_header.channel_id) |
| if msg_header.onu_session_id >= 0: |
| ctx['onu_session_id'] = str(msg_header.onu_session_id) |
| |
| if code == PON_ALARM_LOS: |
| alarm['description'] = 'Loss of signal: OLT does not receive transmissions in the upstream' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_LOSI: |
| alarm['description'] = 'Loss of signal for ONUi: no signal from the ONU when expected' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_DOWI: |
| alarm['description'] = 'Loss of signal for ONUi: no signal from the ONU when expected' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_LOFI: |
| alarm['description'] = 'Loss of frame of ONUi: no valid optical signal is received from the ONU' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_RDII: |
| alarm['description'] = 'Remote Defect Indication of ONUi: OLT transmissions is received with defect at the ONUi' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_LOAMI: |
| alarm['description'] = 'Loss of PLOAM for ONUi: 3 messages of ONU are missing after OLT sends PLOAMu request' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_LCDGI: |
| alarm['description'] = 'Loss of GEM channel delineation: GEM fragment delineation of ONUi is lost' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_LOAI: |
| alarm['description'] = 'Loss of acknowledge with ONUi: OLT does not receive ack from ONUi' |
| if msg.parameter1 in (PON_DOWNSTREAM_PLOAM_MESSAGE_ENCRYPTED_PORT_ID, PON_DOWNSTREAM_PLOAM_MESSAGE_ASSIGN_ALLOC_ID, |
| PON_DOWNSTREAM_PLOAM_MESSAGE_CONFIGURE_PORT_ID, PON_DOWNSTREAM_PLOAM_MESSAGE_BER_INTERVAL, |
| PON_DOWNSTREAM_PLOAM_MESSAGE_KEY_SWITCHING): |
| ctx['downstream_ploam_message_id'] = str(msg.parameter1) |
| alarm['state'] = PON_ALARM_RAISE |
| else: |
| log.error('Error, ignored OLT Alarm {} from OLT device {} because Invalid PLOAM message id in OLT device'.format(code, self.device)) |
| return |
| elif code == PON_ALARM_SDI: |
| alarm['description'] = 'Signal Degraded of ONUi: raised when the upstream BER of ONUi goes below certain level' |
| if msg.parameter1 in (PON_ALARM_SDI_RAISE, PON_ALARM_SDI_CLEAR): |
| ctx['onu_id'] = str(msg_header.onu_id) |
| ctx['parameter'] = str(msg.parameter1) |
| alarm['state'] = PON_ALARM_RAISE |
| else: |
| log.error('Error, ignored OLT Alarm {} from OLT device {} because Invalid parameter of alarm SDI'.format(code, self.device)) |
| return |
| elif code == PON_ALARM_SFI: |
| alarm['description'] = 'Signal Fail of ONUi: raised when the upstream of ONUi becomes greater than some level' |
| alarm['state'] = msg.parameter1 |
| elif code == PON_ALARM_PEE: |
| alarm['description'] = 'Physical Equipment Error of ONUi: raised when the OLT receives a PEE message from the ONU' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_DGI: |
| alarm['description'] = 'Dying Gasp of ONUi: raised when the OLT receives DG message from ONUi' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_LOKI: |
| alarm['description'] = 'Loss of key synch with ONUi: Key transmission from ONU fails 3 times' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_TIWI: |
| alarm['description'] = 'Transmission interference warning: raised when the drift of ONU transmissions exceeds specified threshold' |
| alarm['state'] = msg.parameter2 |
| elif code == PON_ALARM_TIA: |
| alarm['description'] = 'Transmission Interference Alarm: an ONU turns on its laser at another ONUs time' |
| alarm['state'] = msg.parameter2 |
| else: |
| log.error('Error, unsupported OLT Alarm {} received from OLT device {}'.format(code, self.device)) |
| return |
| |
| log.warn('Alarm', alarm=alarm) |
| self.device.publish_alarm(alarm) |
| log.debug('proccess-alarm-stop') |
| |
| |
| def process_omci_alarm(self, pkt): |
| |
| log.debug('proccess-omci-alarm-start') |
| msg_header = pkt[PAS5211MsgHeader] |
| msg_omci_alarm = pkt[OmciAlarmNotification] |
| |
| ctx = { |
| 'entity_class': str(msg_omci_alarm.entity_class), |
| 'entity_id': str(msg_omci_alarm.entity_id), |
| 'alarm_bit_map': str(msg_omci_alarm.alarm_bit_map), |
| 'alarm_sequence_number': str(msg_omci_alarm.alarm_sequence_number) |
| } |
| |
| if msg_header.onu_id >= 0: |
| ctx['onu_id'] = str(msg_header.onu_id) |
| if msg_header.channel_id >= 0: |
| ctx['channel_id'] = str(msg_header.channel_id) |
| if msg_header.onu_session_id >= 0: |
| ctx['onu_session_id'] = str(msg_header.onu_session_id) |
| |
| alarm = dict( |
| id='voltha.{}.{}.ont'.format(self.device.adapter_agent.adapter_name, self.device.device.id), |
| resource_id=self.device.device.id, |
| type=AlarmEventType.EQUIPMENT, |
| category=AlarmEventCategory.OLT, |
| context=ctx |
| ) |
| |
| self.device.publish_alarm(alarm) |
| log.warn('Alarm', alarm=alarm) |
| log.debug('proccess-alarm-stop') |