alshabib | 2230237 | 2016-12-20 13:46:14 -0800 | [diff] [blame] | 1 | # |
Zsolt Haraszti | 3eb27a5 | 2017-01-03 21:56:48 -0800 | [diff] [blame] | 2 | # Copyright 2017 the original author or authors. |
alshabib | 2230237 | 2016-12-20 13:46:14 -0800 | [diff] [blame] | 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
| 15 | # |
| 16 | from scapy.automaton import ATMT |
alshabib | 2230237 | 2016-12-20 13:46:14 -0800 | [diff] [blame] | 17 | import structlog |
alshabib | 8b7e0ec | 2017-03-02 15:12:29 -0800 | [diff] [blame] | 18 | from voltha.adapters.microsemi_olt.BaseOltAutomaton import BaseOltAutomaton |
| 19 | from voltha.adapters.microsemi_olt.PAS5211 import PAS5211EventOnuActivation, PAS5211MsgGetActivationAuthMode, \ |
alshabib | 2230237 | 2016-12-20 13:46:14 -0800 | [diff] [blame] | 20 | PAS5211MsgGetActivationAuthModeResponse, PON_ACTIVATION_AUTH_AUTO, PON_ENABLE, PAS5211MsgSetOnuOmciPortId, \ |
| 21 | PAS5211MsgSetOnuOmciPortIdResponse, PAS5211MsgSendFrame, PON_PORT_PON, PAS5211MsgSendFrameResponse |
| 22 | from voltha.extensions.omci.omci_entities import CircuitPack |
| 23 | from voltha.extensions.omci.omci_frame import OmciFrame |
| 24 | from voltha.extensions.omci.omci_messages import OmciGet, OmciGetResponse |
| 25 | from voltha.protos.common_pb2 import AdminState |
| 26 | from voltha.protos.common_pb2 import OperStatus |
| 27 | from voltha.protos.device_pb2 import Port |
| 28 | |
| 29 | log = structlog.get_logger() |
| 30 | _verbose = False |
| 31 | |
| 32 | def hexstring(string): |
| 33 | return ":".join("{:02x}".format(ord(c)) for c in string) |
| 34 | |
| 35 | class ActivationManager(BaseOltAutomaton): |
| 36 | |
| 37 | onu_id = None |
| 38 | serial_number = None |
| 39 | onu_session_id = None |
| 40 | port_id = None |
| 41 | channel_id = None |
| 42 | |
| 43 | def parse_args(self, debug=0, store=0, **kwargs): |
| 44 | self.onu_id = kwargs.pop('onu_id') |
| 45 | self.serial_number = kwargs.pop('serial_number') |
| 46 | self.onu_session_id = kwargs.pop('onu_session_id') |
| 47 | self.port_id = self.onu_id |
| 48 | self.channel_id = kwargs.pop('channel_id') |
| 49 | |
| 50 | if self.onu_id is None or self.serial_number is None or \ |
| 51 | self.onu_session_id is None or self.channel_id is None: |
| 52 | raise ValueError('ONU is not well defined') |
| 53 | |
| 54 | BaseOltAutomaton.parse_args(self, debug=debug, store=store, **kwargs) |
| 55 | |
| 56 | """ |
| 57 | States |
| 58 | """ |
| 59 | |
| 60 | @ATMT.state(initial=1) |
| 61 | def got_activation_event(self): |
| 62 | pass |
| 63 | |
| 64 | @ATMT.state() |
| 65 | def wait_get_auth_mode(self): |
| 66 | pass |
| 67 | |
| 68 | @ATMT.state() |
| 69 | def got_auth_mode(self): |
| 70 | pass |
| 71 | |
| 72 | @ATMT.state() |
| 73 | def wait_omci_port_id(self): |
| 74 | pass |
| 75 | |
| 76 | @ATMT.state() |
| 77 | def got_omci_port_id(self): |
| 78 | pass |
| 79 | |
| 80 | @ATMT.state() |
| 81 | def wait_send_frame(self): |
| 82 | pass |
| 83 | |
| 84 | @ATMT.state() |
| 85 | def wait_omci_get(self): |
| 86 | pass |
| 87 | |
| 88 | @ATMT.state(final=1) |
| 89 | def end(self): |
| 90 | pass |
| 91 | |
| 92 | @ATMT.state(error=1) |
| 93 | def error(self): |
| 94 | pass |
| 95 | |
| 96 | """ |
| 97 | Utility Methods |
| 98 | """ |
| 99 | |
alshabib | 8b7e0ec | 2017-03-02 15:12:29 -0800 | [diff] [blame] | 100 | def create_port(self, vendor): |
alshabib | 2230237 | 2016-12-20 13:46:14 -0800 | [diff] [blame] | 101 | port = Port(port_no=self.port_id, |
| 102 | label="{} ONU".format(vendor), |
| 103 | type=Port.ETHERNET_UNI, |
| 104 | admin_state=AdminState.ENABLED, |
| 105 | oper_status=OperStatus.ACTIVE |
| 106 | ) |
| 107 | self.device.add_port(port) |
| 108 | |
| 109 | def px(self, pkt): |
| 110 | return self.p(pkt, channel_id=self.channel_id, |
| 111 | onu_id=self.onu_id, onu_session_id=self.onu_session_id) |
| 112 | |
| 113 | def error(self, msg): |
| 114 | log.error(msg) |
| 115 | raise self.error() |
| 116 | |
| 117 | """ |
| 118 | Transitions |
| 119 | """ |
| 120 | |
| 121 | # Transition from got_activation_event |
| 122 | @ATMT.condition(got_activation_event) |
| 123 | def send_get_activation_auth_mode(self): |
| 124 | auth_mode = PAS5211MsgGetActivationAuthMode() |
| 125 | self.send(self.p(auth_mode)) |
| 126 | raise self.wait_get_auth_mode() |
| 127 | |
| 128 | # Transitions from wait_get_auth_mode |
| 129 | @ATMT.timeout(wait_get_auth_mode, 3) |
| 130 | def timeout_get_auth_mode(self): |
| 131 | self.error('Could not get auth mode for OLT {}; dropping activation event for {}' |
| 132 | .format(self.target, hexstring(self.serial_number))) |
| 133 | |
| 134 | @ATMT.receive_condition(wait_get_auth_mode) |
| 135 | def wait_for_get_auth_mode(self, pkt): |
| 136 | if PAS5211MsgGetActivationAuthModeResponse in pkt: |
| 137 | if pkt.mode == PON_ACTIVATION_AUTH_AUTO: |
| 138 | raise self.got_auth_mode() |
| 139 | else: |
| 140 | # TODO There may be something that can be done here. |
| 141 | # See line 2497 of PAS_onu_mode_change_thread.c |
| 142 | log.error('Got unknown auth mode {}; dropping activation event'.format(pkt.mode)) |
| 143 | raise self.end() |
| 144 | |
| 145 | # Transitions from got auth_mode |
| 146 | @ATMT.condition(got_auth_mode) |
| 147 | def send_omci_port_id(self): |
| 148 | omci_port_id = PAS5211MsgSetOnuOmciPortId(port_id=self.port_id, activate=PON_ENABLE) |
| 149 | self.send(self.px(omci_port_id)) |
| 150 | raise self.wait_omci_port_id() |
| 151 | |
| 152 | # Transitions from wait_omci_port_id |
| 153 | @ATMT.timeout(wait_omci_port_id, 3) |
| 154 | def timeout_omci_port_id(self): |
| 155 | self.error('Could not set omci port id for OLT {}; dropping activation event for {}' |
| 156 | .format(self.target, hexstring(self.serial_number))) |
| 157 | |
| 158 | @ATMT.receive_condition(wait_omci_port_id) |
| 159 | def wait_for_omci_port_id(self, pkt): |
| 160 | if pkt.opcode == PAS5211MsgSetOnuOmciPortIdResponse.opcode and \ |
| 161 | pkt.onu_id == self.onu_id and pkt.onu_session_id == self.onu_session_id and \ |
| 162 | pkt.channel_id == self.channel_id: |
| 163 | raise self.got_omci_port_id() |
| 164 | |
| 165 | # Transitions from got_omci_port_id |
| 166 | @ATMT.condition(got_omci_port_id) |
| 167 | def send_omci_identity_frame(self): |
| 168 | # attr_mask |= OMCI_ATTR_BIT(OMCI_CIRCUIT_PACK_ATTR_VENDOR_ID); |
| 169 | #message.attributes_mask = 2048 |
| 170 | |
| 171 | # Entity_id |
| 172 | # equip_ind = OMCI_CIRCUIT_PACK_INTEGRATED_EQUIPMENT; |
| 173 | # slot_id = 257; |
| 174 | # entity_instance = ((equip_ind<<8) | slot_id |
| 175 | message = OmciGet(entity_class=CircuitPack.class_id, entity_id = 257, |
| 176 | attributes_mask=2048) |
| 177 | #TODO fix transaction id |
| 178 | frame = OmciFrame(transaction_id=0, message_type=OmciGet.message_id, |
| 179 | omci_message=message) |
| 180 | omci_frame = PAS5211MsgSendFrame(port_type=PON_PORT_PON, port_id=self.port_id, |
| 181 | management_frame=PON_ENABLE, frame=frame) |
| 182 | |
| 183 | self.send(self.px(omci_frame)) |
| 184 | |
| 185 | raise self.wait_send_frame() |
| 186 | |
| 187 | # Transitions from wait_send_frame |
| 188 | @ATMT.timeout(wait_send_frame, 3) |
| 189 | def timeout_send_frame(self): |
| 190 | self.error('Could not send omci to OLT {}; dropping activation event for {}' |
| 191 | .format(self.target, hexstring(self.serial_number))) |
| 192 | |
| 193 | @ATMT.receive_condition(wait_send_frame) |
| 194 | def wait_for_send_frame(self, pkt): |
alshabib | 8b7e0ec | 2017-03-02 15:12:29 -0800 | [diff] [blame] | 195 | if PAS5211MsgSendFrameResponse in pkt: |
alshabib | 2230237 | 2016-12-20 13:46:14 -0800 | [diff] [blame] | 196 | raise self.wait_omci_get() |
| 197 | |
| 198 | # Transitions from wait_omci_get |
| 199 | @ATMT.timeout(wait_omci_get, 3) |
| 200 | def timeout_send_frame(self): |
| 201 | self.error('Did not receive omci get event from OLT {}; dropping activation event for {}' |
| 202 | .format(self.target, hexstring(self.serial_number))) |
| 203 | |
| 204 | @ATMT.receive_condition(wait_omci_get) |
| 205 | def wait_for_omci_get(self, pkt): |
| 206 | if OmciGetResponse in pkt: |
alshabib | 8b7e0ec | 2017-03-02 15:12:29 -0800 | [diff] [blame] | 207 | vendor = pkt['OmciGetResponse'].data['vendor_id'] |
| 208 | log.info("Activated {} ONT".format(vendor)) |
| 209 | self.create_port(vendor) |
| 210 | |
| 211 | self.device.onu_detected( |
| 212 | parent_port_no=self.channel_id, |
| 213 | child_device_type='%s_onu' % vendor.lower(), |
| 214 | onu_id=self.port_id, |
| 215 | ) |
| 216 | |
alshabib | 2230237 | 2016-12-20 13:46:14 -0800 | [diff] [blame] | 217 | raise self.end() |
| 218 | |
| 219 | |
| 220 | class ActivationWatcher(BaseOltAutomaton): |
| 221 | |
| 222 | """ |
| 223 | States |
| 224 | """ |
| 225 | |
| 226 | @ATMT.state(initial=1) |
| 227 | def wait_onu_activation_event(self): |
| 228 | pass |
| 229 | |
| 230 | """ |
| 231 | Transitions |
| 232 | """ |
| 233 | |
| 234 | # Transitions from wait_onu_activation_event |
| 235 | @ATMT.receive_condition(wait_onu_activation_event) |
| 236 | def wait_for_onu_activation_event(self, pkt): |
| 237 | if PAS5211EventOnuActivation in pkt: |
| 238 | log.info('{} activated'.format(hexstring(pkt.serial_number))) |
| 239 | onu_activation = ActivationManager(iface=self.iface, target=self.target, comm=self.comm, |
| 240 | onu_id=pkt.onu_id, serial_number=pkt.serial_number, |
| 241 | onu_session_id=pkt.onu_session_id, |
| 242 | channel_id=pkt.channel_id, device=self.device) |
| 243 | onu_activation.runbg() |
| 244 | raise self.wait_onu_activation_event() |