blob: 7fe30cde3bcd9f68df1d36c4ee60cf9b905d7069 [file] [log] [blame]
alshabib22302372016-12-20 13:46:14 -08001#
Zsolt Haraszti3eb27a52017-01-03 21:56:48 -08002# Copyright 2017 the original author or authors.
alshabib22302372016-12-20 13:46:14 -08003#
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#
16from scapy.automaton import ATMT
alshabib22302372016-12-20 13:46:14 -080017import structlog
alshabib8b7e0ec2017-03-02 15:12:29 -080018from voltha.adapters.microsemi_olt.BaseOltAutomaton import BaseOltAutomaton
19from voltha.adapters.microsemi_olt.PAS5211 import PAS5211EventOnuActivation, PAS5211MsgGetActivationAuthMode, \
alshabib22302372016-12-20 13:46:14 -080020 PAS5211MsgGetActivationAuthModeResponse, PON_ACTIVATION_AUTH_AUTO, PON_ENABLE, PAS5211MsgSetOnuOmciPortId, \
21 PAS5211MsgSetOnuOmciPortIdResponse, PAS5211MsgSendFrame, PON_PORT_PON, PAS5211MsgSendFrameResponse
22from voltha.extensions.omci.omci_entities import CircuitPack
23from voltha.extensions.omci.omci_frame import OmciFrame
24from voltha.extensions.omci.omci_messages import OmciGet, OmciGetResponse
25from voltha.protos.common_pb2 import AdminState
26from voltha.protos.common_pb2 import OperStatus
27from voltha.protos.device_pb2 import Port
28
29log = structlog.get_logger()
30_verbose = False
31
32def hexstring(string):
33 return ":".join("{:02x}".format(ord(c)) for c in string)
34
35class 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
alshabib8b7e0ec2017-03-02 15:12:29 -0800100 def create_port(self, vendor):
alshabib22302372016-12-20 13:46:14 -0800101 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):
alshabib8b7e0ec2017-03-02 15:12:29 -0800195 if PAS5211MsgSendFrameResponse in pkt:
alshabib22302372016-12-20 13:46:14 -0800196 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:
alshabib8b7e0ec2017-03-02 15:12:29 -0800207 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
alshabib22302372016-12-20 13:46:14 -0800217 raise self.end()
218
219
220class 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()