blob: 71025195a8dde91a56eec38d77638e56e02c938d [file] [log] [blame]
Chip Boling67b674a2019-02-08 11:42:18 -06001#
2# Copyright 2017 the original author or authors.
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#
Zack Williams84a71e92019-11-15 09:00:19 -070016from __future__ import absolute_import
Chip Boling67b674a2019-02-08 11:42:18 -060017from pyvoltha.adapters.extensions.omci.omci_frame import OmciFrame
18from pyvoltha.adapters.extensions.omci.omci_defs import *
19from pyvoltha.adapters.extensions.omci.omci_entities import *
20from pyvoltha.adapters.extensions.omci.omci_messages import *
21
22# abbreviations
23OP = EntityOperations
24RC = ReasonCodes
25
26
27class MockOnu(object):
28 """
29 Minimal class that acts line an ONU. The Mock OLT handler will call into this
30 object with OMCI frames that it will respond to appropriately
31 """
32 def __init__(self, serial_number, adapter_agent, handler_id):
33 self.serial_number = serial_number
34 self._adapter_agent = adapter_agent # TODO: Remove any unused attributes
35 self._handler_id = handler_id
36 self.mib_data_sync = 0 # Assume at reboot!
37
38 # NOTE: when creating response frames, use the basic method of constructing
39 # these frames as the encoding created is unit-tested elsewhere
40 self._omci_response = {
41 OP.Get.value: {
42 CircuitPack.class_id: {
43 257: OmciFrame(transaction_id=0, # Will get replaced
44 message_type=OmciGetResponse.message_id,
45 omci_message=OmciGetResponse(
46 entity_class=CircuitPack.class_id,
47 entity_id=0,
48 success_code=RC.Success.value,
49 attributes_mask=CircuitPack.mask_for('number_of_ports'),
50 data=OmciMaskedData('value',
51 entity_class=CircuitPack.class_id,
52 attributes_mask=CircuitPack.mask_for('number_of_ports'))
53 ))
54 },
55 # Additional OMCI GET request responses here if needed
56 },
57 OP.GetNext.value: {},
58 OP.Create.value: {
59 # TODO: Create some OMCI CREATE request responses here.
60
61 # def send_create_gal_ethernet_profile(self,
62 # entity_id,
63 # max_gem_payload_size):
64 # frame = OmciFrame(
65 # transaction_id=self.get_tx_id(),
66 # message_type=OmciCreate.message_id,
67 # omci_message=OmciCreate(
68 # entity_class=GalEthernetProfile.class_id,
69 # entity_id=entity_id,
70 # data=dict(
71 # max_gem_payload_size=max_gem_payload_size
72 # )
73 # )
74 # )
75 # self.send_omci_message(frame)
76 },
77 OP.Set.value: {
78 # TODO: Create some OMCI SET request responses here.
79
80 # def send_set_admin_state(self,
81 # entity_id,
82 # admin_state):
83 # data = dict(
84 # administrative_state=admin_state
85 # )
86 # frame = OmciFrame(
87 # transaction_id=self.get_tx_id(),
88 # message_type=OmciSet.message_id,
89 # omci_message=OmciSet(
90 # entity_class=OntG.class_id,
91 # entity_id=entity_id,
92 # attributes_mask=OntG.mask_for(*data.keys()),
93 # data=data
94 # )
95 # )
96 # self.send_omci_message(frame)
97
98 },
99 OP.Delete.value: {
100 # TODO: Create some OMCI DELETE responses here.
101 },
102 OP.MibReset.value: {
103 OntData.class_id: {
104 0: OmciFrame(transaction_id=0, # Will get replaced
105 message_type=OmciMibResetResponse.message_id,
106 omci_message=OmciMibResetResponse(
107 entity_class=OntData.class_id,
108 entity_id=0,
109 success_code=RC.Success.value
110 ))
111 }
112 },
113 OP.MibUpload.value: {
114 OntData.class_id: {
115 0: OmciFrame(transaction_id=0, # Will get replaced
116 message_type=OmciMibUploadResponse.message_id,
117 omci_message=OmciMibUploadResponse(
118 entity_class=OntData.class_id,
119 entity_id=0,
120 number_of_commands=3 # Should match list size for MibUploadNext below
121 ))
122 }
123 },
124 # OP.MibUploadNext.value: {
125 # OntData.class_id: {
126 # 0: [
127 # OmciFrame(transaction_id=0,
128 # message_type=OmciMibUploadNextResponse.message_id,
129 # omci_message=OmciMibUploadNextResponse(
130 # entity_class=OntData.class_id,
131 # entity_id=0,
132 # object_entity_id=0, # TODO: Pick one
133 # object_attributes_mask=0, # TODO: Pick one
134 # object_data=None # TODO: Pick one
135 # )),
136 # OmciFrame(transaction_id=0,
137 # message_type=OmciMibUploadNextResponse.message_id,
138 # omci_message=OmciMibUploadNextResponse(
139 # entity_class=OntData.class_id,
140 # entity_id=0,
141 # object_entity_id=0, # TODO: Pick one
142 # object_attributes_mask=0, # TODO: Pick one
143 # object_data=None # TODO: Pick one
144 # )),
145 # OmciFrame(transaction_id=0,
146 # message_type=OmciMibUploadNextResponse.message_id,
147 # omci_message=OmciMibUploadNextResponse(
148 # entity_class=OntData.class_id,
149 # entity_id=0,
150 # object_entity_id=0, # TODO: Pick one
151 # object_attributes_mask=0, # TODO: Pick one
152 # object_data=None # TODO: Pick one
153 # )),
154 # ]
155 # }
156 # },
157 OP.Reboot.value: {
158 OntData.class_id: {
159 0: OmciFrame(transaction_id=0, # Will get replaced
160 message_type=OmciRebootResponse.message_id,
161 omci_message=OmciRebootResponse(
162 entity_class=OntG.class_id,
163 entity_id=0,
164 success_code=RC.Success.value
165 ))
166 }
167 },
168 }
169 # TODO: Support Autonomous ONU messages as well
170
171 def tearDown(self):
172 """Test case cleanup"""
173 pass
174
175 def _request_to_response_type(self, message_type):
176 return {
177 OP.Create.value: OmciCreateResponse,
178 OP.Delete.value: OmciDeleteResponse,
179 OP.Set.value: OmciSetResponse,
180 OP.Get.value: OmciGetResponse,
181 OP.GetNext.value: OmciGetNextResponse,
182 OP.MibUpload.value: OmciMibUploadResponse,
183 OP.MibUploadNext.value: OmciMibUploadNextResponse,
184 OP.MibReset.value: OmciMibResetResponse,
185 OP.Reboot.value: OmciRebootResponse,
186 }.get(message_type & 0x1F, None)
187
188 def rx_omci_frame(self, msg):
189 try:
190 frame = OmciFrame(msg.decode('hex'))
191 response = None
192 response_type = self._request_to_response_type(frame.fields['message_type'])
193 transaction_id = frame.fields['transaction_id']
194
195 omci_message = frame.fields.get('omci_message')
196
197 class_id = omci_message.fields.get('entity_class') \
198 if omci_message is not None else None
199 instance_id = omci_message.fields.get('entity_id') \
200 if omci_message is not None else None
201
202 # Look up hardcode responses based on class and instance ID. If found
203 # return the response, otherwise send back an error
204
205 if response_type is None:
206 status = RC.ProcessingError.value
207 elif class_id is None:
208 status = RC.UnknownEntity.value
209 elif instance_id is None:
210 status = RC.UnknownInstance.value
211 else:
212 status = RC.Success.value
213 try:
214 response_id = response_type.message_id & 0x1f
215 response = self._omci_response[response_id][class_id][instance_id]
216
217 if response_id == OP.MibUploadNext.value:
218 # Special case. Need to get requested entry
219 assert isinstance(response, list)
220 pass
221 pass
222 pass
223 pass
224
225 if isinstance(omci_message, OmciGetNext):
226 response = response[omci_message.fields['command_sequence_number']]
227
228 if isinstance(response, dict):
229 if response['failures'] > 0:
230 response['failures'] -= 1
231 return None
232 else: response = response['frame']
233
234 response.fields['transaction_id'] = transaction_id
235 if 'success_code' in response.fields['omci_message'].fields:
236 response.fields['omci_message'].fields['success_code'] = status
237
238 if status == RC.Success.value:
239 if response_type.message_id in [OmciCreateResponse.message_id,
240 OmciDeleteResponse.message_id,
241 OmciSetResponse.message_id]:
242 self.mib_data_sync += 1
243 if self.mib_data_sync > 255:
244 self.mib_data_sync = 1
245 elif response_type.message_id == OmciMibResetResponse.message_id:
246 self.mib_data_sync = 0
247
248 except KeyError as e:
249 bad_key = e.args[0]
250 if bad_key == class_id:
251 status = RC.UnknownEntity.value
252 elif bad_key == instance_id:
253 status = RC.UnknownInstance.value
254 else:
255 status = RC.ProcessingError.value
256
257 if status != RC.Success.value and \
258 response_type not in [OmciMibUploadResponse,
259 OmciMibUploadNextResponse]:
260 response = OmciFrame(transaction_id=transaction_id,
261 message_type=response_type.message_id,
262 omci_message=response_type(
263 entity_class=class_id,
264 entity_id=instance_id,
265 success_code=status
266 ))
267 return response
268
269 except Exception as e:
270 pass
271
272 @property
273 def proxy_address(self, device_id='1'):
274 if self._proxy_address is None:
275 self._proxy_address = Device.ProxyAddress(
276 device_id=device_id,
277 channel_group_id=1,
278 channel_id=1,
279 channel_termination="XGSPON",
280 onu_id=20,
281 onu_session_id=1)
282
283 return self._proxy_address
284