blob: 04d3e8308706a9ac22d7b023ab1e829f7f3c8d0b [file] [log] [blame]
Chip Boling32aab302019-01-23 10:50: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#
16import structlog
17from scapy.fields import ByteField, ThreeBytesField, StrFixedLenField, ConditionalField, IntField, Field
18from scapy.fields import ShortField, BitField
19from scapy.packet import Packet
20
21from voltha.extensions.omci.omci_defs import AttributeAccess, OmciSectionDataSize
22from voltha.extensions.omci.omci_fields import OmciTableField
23import voltha.extensions.omci.omci_entities as omci_entities
24
25
26log = structlog.get_logger()
27
28
29class OmciData(Field):
30
31 __slots__ = Field.__slots__ + ['_entity_class']
32
33 def __init__(self, name, entity_class="entity_class"):
34 Field.__init__(self, name=name, default=None, fmt='s')
35 self._entity_class = entity_class
36
37 def addfield(self, pkt, s, val):
38 class_id = getattr(pkt, self._entity_class)
39 entity_class = omci_entities.entity_id_to_class_map.get(class_id)
40 for attribute in entity_class.attributes:
41 if AttributeAccess.SetByCreate not in attribute.access:
42 continue
43 if attribute.field.name == 'managed_entity_id':
44 continue
45 fld = attribute.field
46 s = fld.addfield(pkt, s, val.get(fld.name, fld.default))
47 return s
48
49 def getfield(self, pkt, s):
50 """Extract an internal value from a string"""
51 class_id = getattr(pkt, self._entity_class)
52 entity_class = omci_entities.entity_id_to_class_map.get(class_id)
53 data = {}
54 for attribute in entity_class.attributes:
55 if AttributeAccess.SetByCreate not in attribute.access:
56 continue
57 if attribute.field.name == 'managed_entity_id':
58 continue
59 fld = attribute.field
60 s, value = fld.getfield(pkt, s)
61 data[fld.name] = value
62 return s, data
63
64
65class OmciMaskedData(Field):
66
67 __slots__ = Field.__slots__ + ['_entity_class', '_attributes_mask']
68
69 def __init__(self, name, entity_class="entity_class",
70 attributes_mask="attributes_mask"):
71 Field.__init__(self, name=name, default=None, fmt='s')
72 self._entity_class = entity_class
73 self._attributes_mask = attributes_mask
74
75 def addfield(self, pkt, s, val):
76 class_id = getattr(pkt, self._entity_class)
77 attribute_mask = getattr(pkt, self._attributes_mask)
78 entity_class = omci_entities.entity_id_to_class_map.get(class_id)
79 indices = entity_class.attribute_indices_from_mask(attribute_mask)
80 for index in indices:
81 fld = entity_class.attributes[index].field
82 s = fld.addfield(pkt, s, val[fld.name])
83 return s
84
85 def getfield(self, pkt, s):
86 """Extract an internal value from a string"""
87 class_id = getattr(pkt, self._entity_class)
88 attribute_mask = getattr(pkt, self._attributes_mask)
89 entity_class = omci_entities.entity_id_to_class_map[class_id]
90 indices = entity_class.attribute_indices_from_mask(attribute_mask)
91 data = {}
92 table_attribute_mask = 0
93 for index in indices:
94 try:
95 fld = entity_class.attributes[index].field
96 except IndexError, e:
97 log.error("attribute-decode-failure", attribute_index=index,
98 entity_class=entity_class, e=e)
99 continue
100 try:
101 s, value = fld.getfield(pkt, s)
102 except Exception, _e:
103 raise
104 if isinstance(pkt, OmciGetResponse) and isinstance(fld, OmciTableField):
105 data[fld.name + '_size'] = value
106 table_attribute_mask = table_attribute_mask | (1 << (15 - index))
107 else:
108 data[fld.name] = value
109 if table_attribute_mask:
110 data['table_attribute_mask'] = table_attribute_mask
111 return s, data
112
113
114class OmciMessage(Packet):
115 name = "OmciMessage"
116 message_id = None # OMCI message_type value, filled by derived classes
117 fields_desc = []
118
119
120class OmciCreate(OmciMessage):
121 name = "OmciCreate"
122 message_id = 0x44
123 fields_desc = [
124 ShortField("entity_class", None),
125 ShortField("entity_id", 0),
126 OmciData("data")
127 ]
128
129
130class OmciCreateResponse(OmciMessage):
131 name = "OmciCreateResponse"
132 message_id = 0x24
133 fields_desc = [
134 ShortField("entity_class", None),
135 ShortField("entity_id", None),
136 ByteField("success_code", 0),
137 ShortField("parameter_error_attributes_mask", None),
138 ]
139
140
141class OmciDelete(OmciMessage):
142 name = "OmciDelete"
143 message_id = 0x46
144 fields_desc = [
145 ShortField("entity_class", None),
146 ShortField("entity_id", None),
147 ]
148
149
150class OmciDeleteResponse(OmciMessage):
151 name = "OmciDeleteResponse"
152 message_id = 0x26
153 fields_desc = [
154 ShortField("entity_class", None),
155 ShortField("entity_id", None),
156 ByteField("success_code", 0),
157 ]
158
159
160class OmciSet(OmciMessage):
161 name = "OmciSet"
162 message_id = 0x48
163 fields_desc = [
164 ShortField("entity_class", None),
165 ShortField("entity_id", 0),
166 ShortField("attributes_mask", None),
167 OmciMaskedData("data")
168 ]
169
170
171class OmciSetResponse(OmciMessage):
172 name = "OmciSetResponse"
173 message_id = 0x28
174 fields_desc = [
175 ShortField("entity_class", None),
176 ShortField("entity_id", None),
177 ByteField("success_code", 0),
178 ShortField("unsupported_attributes_mask", None),
179 ShortField("failed_attributes_mask", None),
180 ]
181
182
183class OmciGet(OmciMessage):
184 name = "OmciGet"
185 message_id = 0x49
186 fields_desc = [
187 ShortField("entity_class", None),
188 ShortField("entity_id", 0),
189 ShortField("attributes_mask", None)
190 ]
191
192
193class OmciGetResponse(OmciMessage):
194 name = "OmciGetResponse"
195 message_id = 0x29
196 fields_desc = [
197 ShortField("entity_class", None),
198 ShortField("entity_id", 0),
199 ByteField("success_code", 0),
200 ShortField("attributes_mask", None),
201 ConditionalField(
202 OmciMaskedData("data"), lambda pkt: pkt.success_code == 0)
203 ]
204
205
206class OmciGetAllAlarms(OmciMessage):
207 name = "OmciGetAllAlarms"
208 message_id = 0x4b
209 fields_desc = [
210 ShortField("entity_class", 2), # Always 2 (ONT data)
211 ShortField("entity_id", 0), # Always 0 (ONT instance)
212 ByteField("alarm_retrieval_mode", 0) # 0 or 1
213 ]
214
215
216class OmciGetAllAlarmsResponse(OmciMessage):
217 name = "OmciGetAllAlarmsResponse"
218 message_id = 0x2b
219 fields_desc = [
220 ShortField("entity_class", 2), # Always 2 (ONT data)
221 ShortField("entity_id", 0),
222 ShortField("number_of_commands", None)
223 ]
224
225
226class OmciGetAllAlarmsNext(OmciMessage):
227 name = "OmciGetAllAlarmsNext"
228 message_id = 0x4c
229 fields_desc = [
230 ShortField("entity_class", 2), # Always 2 (ONT data)
231 ShortField("entity_id", 0),
232 ShortField("command_sequence_number", None)
233 ]
234
235
236class OmciGetAllAlarmsNextResponse(OmciMessage):
237 name = "OmciGetAllAlarmsNextResponse"
238 message_id = 0x2c
239 fields_desc = [
240 ShortField("entity_class", 2), # Always 2 (ONT data)
241 ShortField("entity_id", 0),
242 ShortField("alarmed_entity_class", None),
243 ShortField("alarmed_entity_id", 0),
244 BitField("alarm_bit_map", None, 224)
245 ]
246
247
248class OmciMibUpload(OmciMessage):
249 name = "OmciMibUpload"
250 message_id = 0x4d
251 fields_desc = [
252 ShortField("entity_class", 2), # Always 2 (ONT data)
253 ShortField("entity_id", 0),
254 ]
255
256
257class OmciMibUploadResponse(OmciMessage):
258 name = "OmciMibUploadResponse"
259 message_id = 0x2d
260 fields_desc = [
261 ShortField("entity_class", 2), # Always 2 (ONT data)
262 ShortField("entity_id", 0),
263 ShortField("number_of_commands", None)
264 ]
265
266
267class OmciMibUploadNext(OmciMessage):
268 name = "OmciMibUploadNext"
269 message_id = 0x4e
270 fields_desc = [
271 ShortField("entity_class", 2), # Always 2 (ONT data)
272 ShortField("entity_id", 0),
273 ShortField("command_sequence_number", None)
274 ]
275
276
277class OmciMibUploadNextResponse(OmciMessage):
278 name = "OmciMibUploadNextResponse"
279 message_id = 0x2e
280 fields_desc = [
281 ShortField("entity_class", 2), # Always 2 (ONT data)
282 ShortField("entity_id", 0),
283 ShortField("object_entity_class", None),
284 ShortField("object_entity_id", 0),
285 ShortField("object_attributes_mask", None),
286 OmciMaskedData("object_data", entity_class='object_entity_class',
287 attributes_mask='object_attributes_mask')
288 ]
289
290
291class OmciMibReset(OmciMessage):
292 name = "OmciMibReset"
293 message_id = 0x4f
294 fields_desc = [
295 ShortField("entity_class", None),
296 ShortField("entity_id", 0)
297 ]
298
299
300class OmciMibResetResponse(OmciMessage):
301 name = "OmciMibResetResponse"
302 message_id = 0x2f
303 fields_desc = [
304 ShortField("entity_class", None),
305 ShortField("entity_id", 0),
306 ByteField("success_code", 0)
307 ]
308
309
310class OmciAlarmNotification(OmciMessage):
311 name = "AlarmNotification"
312 message_id = 0x10
313 fields_desc = [
314 ShortField("entity_class", None),
315 ShortField("entity_id", 0),
316 BitField("alarm_bit_map", 0, 224),
317 ThreeBytesField("zero_padding", 0),
318 ByteField("alarm_sequence_number", None)
319 ]
320
321
322class OmciAttributeValueChange(OmciMessage):
323 name = "AttributeValueChange"
324 message_id = 0x11
325 fields_desc = [
326 ShortField("entity_class", None),
327 ShortField("entity_id", 0),
328 ShortField("attributes_mask", None),
329 OmciMaskedData("data")
330 ]
331
332
333class OmciTestResult(OmciMessage):
334 name = "TestResult"
335 message_id = 0x1B
336 fields_desc = [
337 ShortField("entity_class", None),
338 ShortField("entity_id", 0)
339 # ME Test specific message contents starts here
340 # TODO: Can this be coded easily with scapy?
341 ]
342
343
344class OmciReboot(OmciMessage):
345 name = "OmciOnuReboot"
346 message_id = 0x59
347 fields_desc = [
348 ShortField("entity_class", None),
349 ShortField("entity_id", 0),
350 ByteField("reboot_code", 0)
351 ]
352
353
354class OmciRebootResponse(OmciMessage):
355 name = "OmciOnuRebootResponse"
356 message_id = 0x39
357 fields_desc = [
358 ShortField("entity_class", None),
359 ShortField("entity_id", 0),
360 ByteField("success_code", 0)
361 ]
362
363
364class OmciGetNext(OmciMessage):
365 name = "OmciGetNext"
366 message_id = 0x5A
367 fields_desc = [
368 ShortField("entity_class", None),
369 ShortField("entity_id", 0),
370 ShortField("attributes_mask", None),
371 ShortField("command_sequence_number", None)
372 ]
373
374
375class OmciGetNextResponse(OmciMessage):
376 name = "OmciGetNextResponse"
377 message_id = 0x3A
378 fields_desc = [
379 ShortField("entity_class", None),
380 ShortField("entity_id", 0),
381 ByteField("success_code", 0),
382 ShortField("attributes_mask", None),
383 ConditionalField(OmciMaskedData("data"),
384 lambda pkt: pkt.success_code == 0)
385 ]
386
387
388class OmciSynchronizeTime(OmciMessage):
389 name = "OmciSynchronizeTime"
390 message_id = 0x58
391 fields_desc = [
392 ShortField("entity_class", 256), # OntG
393 ShortField("entity_id", 0),
394 ShortField("year", 0), # eg) 2018
395 ByteField("month", 0), # 1..12
396 ByteField("day", 0), # 1..31
397 ByteField("hour", 0), # 0..23
398 ByteField("minute", 0), # 0..59
399 ByteField("second", 0) # 0..59
400 ]
401
402
403class OmciSynchronizeTimeResponse(OmciMessage):
404 name = "OmciSynchronizeTimeResponse"
405 message_id = 0x38
406 fields_desc = [
407 ShortField("entity_class", 256), # OntG
408 ShortField("entity_id", 0),
409 ByteField("success_code", 0),
410 ConditionalField(ShortField("success_info", None),
411 lambda pkt: pkt.success_code == 0)
412 ]
413
414
415class OmciGetCurrentData(OmciMessage):
416 name = "OmciGetCurrentData"
417 message_id = 0x5C
418 fields_desc = [
419 ShortField("entity_class", None),
420 ShortField("entity_id", 0),
421 ShortField("attributes_mask", None),
422 ]
423
424
425class OmciGetCurrentDataResponse(OmciMessage):
426 name = "OmciGetCurrentDataResponse"
427 message_id = 0x3C
428 fields_desc = [
429 ShortField("entity_class", None),
430 ShortField("entity_id", 0),
431 ByteField("success_code", 0),
432 ShortField("attributes_mask", None),
433 ShortField("unsupported_attributes_mask", None),
434 ShortField("failed_attributes_mask", None),
435 ConditionalField(
436 OmciMaskedData("data"), lambda pkt: pkt.success_code == 0)
437 ]
438
439class OmciStartSoftwareDownload(OmciMessage):
440 name = "OmciStartSoftwareDownload"
441 message_id = 0x53
442 fields_desc = [
443 ShortField("entity_class", 7), # Always 7 (Software image)
444 ShortField("entity_id", None),
445 ByteField("window_size", 0),
446 IntField("image_size", 0),
447 ByteField("image_number", 1), # Always only 1 in parallel
448 ShortField("instance_id", None) # should be same as "entity_id"
449 ]
450
451class OmciStartSoftwareDownloadResponse(OmciMessage):
452 name = "OmciStartSoftwareDownloadResponse"
453 message_id = 0x33
454 fields_desc = [
455 ShortField("entity_class", 7), # Always 7 (Software image)
456 ShortField("entity_id", None),
457 ByteField("result", 0),
458 ByteField("window_size", 0),
459 ByteField("image_number", 1), # Always only 1 in parallel
460 ShortField("instance_id", None) # should be same as "entity_id"
461 ]
462
463class OmciEndSoftwareDownload(OmciMessage):
464 name = "OmciEndSoftwareDownload"
465 message_id = 0x55
466 fields_desc = [
467 ShortField("entity_class", 7), # Always 7 (Software image)
468 ShortField("entity_id", None),
469 IntField("crc32", 0),
470 IntField("image_size", 0),
471 ByteField("image_number", 1), # Always only 1 in parallel
472 ShortField("instance_id", None),# should be same as "entity_id"
473 ]
474
475class OmciEndSoftwareDownloadResponse(OmciMessage):
476 name = "OmciEndSoftwareDownload"
477 message_id = 0x35
478 fields_desc = [
479 ShortField("entity_class", 7), # Always 7 (Software image)
480 ShortField("entity_id", None),
481 ByteField("result", 0),
482 ByteField("image_number", 1), # Always only 1 in parallel
483 ShortField("instance_id", None),# should be same as "entity_id"
484 ByteField("result0", 0) # same as result
485 ]
486
487class OmciDownloadSection(OmciMessage):
488 name = "OmciDownloadSection"
489 message_id = 0x14
490 fields_desc = [
491 ShortField("entity_class", 7), # Always 7 (Software image)
492 ShortField("entity_id", None),
493 ByteField("section_number", 0), # Always only 1 in parallel
494 StrFixedLenField("data", 0, length=OmciSectionDataSize) # section data
495 ]
496
497class OmciDownloadSectionLast(OmciMessage):
498 name = "OmciDownloadSection"
499 message_id = 0x54
500 fields_desc = [
501 ShortField("entity_class", 7), # Always 7 (Software image)
502 ShortField("entity_id", None),
503 ByteField("section_number", 0), # Always only 1 in parallel
504 StrFixedLenField("data", 0, length=OmciSectionDataSize) # section data
505 ]
506
507class OmciDownloadSectionResponse(OmciMessage):
508 name = "OmciDownloadSectionResponse"
509 message_id = 0x34
510 fields_desc = [
511 ShortField("entity_class", 7), # Always 7 (Software image)
512 ShortField("entity_id", None),
513 ByteField("result", 0),
514 ByteField("section_number", 0), # Always only 1 in parallel
515 ]
516
517class OmciActivateImage(OmciMessage):
518 name = "OmciActivateImage"
519 message_id = 0x56
520 fields_desc = [
521 ShortField("entity_class", 7), # Always 7 (Software image)
522 ShortField("entity_id", None),
523 ByteField("activate_flag", 0) # Activate image unconditionally
524 ]
525
526class OmciActivateImageResponse(OmciMessage):
527 name = "OmciActivateImageResponse"
528 message_id = 0x36
529 fields_desc = [
530 ShortField("entity_class", 7), # Always 7 (Software image)
531 ShortField("entity_id", None),
532 ByteField("result", 0) # Activate image unconditionally
533 ]
534
535class OmciCommitImage(OmciMessage):
536 name = "OmciCommitImage"
537 message_id = 0x57
538 fields_desc = [
539 ShortField("entity_class", 7), # Always 7 (Software image)
540 ShortField("entity_id", None),
541 ]
542
543class OmciCommitImageResponse(OmciMessage):
544 name = "OmciCommitImageResponse"
545 message_id = 0x37
546 fields_desc = [
547 ShortField("entity_class", 7), # Always 7 (Software image)
548 ShortField("entity_id", None),
549 ByteField("result", 0) # Activate image unconditionally
550 ]
551