blob: 5da57bf0b30c6ef36c6cab15d5a8d4a81fd2ffd7 [file] [log] [blame]
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -08001#
Zsolt Haraszti3eb27a52017-01-03 21:56:48 -08002# Copyright 2017 the original author or authors.
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -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#
Zsolt Haraszti578a46c2016-12-20 16:38:43 -080016import structlog
lcui33d6a8e2018-08-28 12:51:38 -070017from scapy.fields import ByteField, ThreeBytesField, StrFixedLenField, ConditionalField, IntField, Field
Chip Boling764e12f2018-01-20 15:52:43 -060018from scapy.fields import ShortField, BitField
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080019from scapy.packet import Packet
20
lcui33d6a8e2018-08-28 12:51:38 -070021from voltha.extensions.omci.omci_defs import AttributeAccess, OmciSectionDataSize
22from voltha.extensions.omci.omci_fields import OmciTableField
Chip Boling72bbcfe2018-02-14 14:27:59 -060023import voltha.extensions.omci.omci_entities as omci_entities
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080024
25
Zsolt Haraszti578a46c2016-12-20 16:38:43 -080026log = structlog.get_logger()
27
28
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080029class 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)
Chip Boling72bbcfe2018-02-14 14:27:59 -060039 entity_class = omci_entities.entity_id_to_class_map.get(class_id)
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080040 for attribute in entity_class.attributes:
Chip Boling72bbcfe2018-02-14 14:27:59 -060041 if AttributeAccess.SetByCreate not in attribute.access:
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080042 continue
Chip Boling72bbcfe2018-02-14 14:27:59 -060043 if attribute.field.name == 'managed_entity_id':
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080044 continue
Chip Boling72bbcfe2018-02-14 14:27:59 -060045 fld = attribute.field
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080046 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)
Chip Boling72bbcfe2018-02-14 14:27:59 -060052 entity_class = omci_entities.entity_id_to_class_map.get(class_id)
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080053 data = {}
54 for attribute in entity_class.attributes:
Chip Boling72bbcfe2018-02-14 14:27:59 -060055 if AttributeAccess.SetByCreate not in attribute.access:
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080056 continue
Chip Boling72bbcfe2018-02-14 14:27:59 -060057 if attribute.field.name == 'managed_entity_id':
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080058 continue
Chip Boling72bbcfe2018-02-14 14:27:59 -060059 fld = attribute.field
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080060 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)
Chip Boling72bbcfe2018-02-14 14:27:59 -060078 entity_class = omci_entities.entity_id_to_class_map.get(class_id)
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080079 indices = entity_class.attribute_indices_from_mask(attribute_mask)
80 for index in indices:
Chip Boling72bbcfe2018-02-14 14:27:59 -060081 fld = entity_class.attributes[index].field
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080082 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)
Chip Boling72bbcfe2018-02-14 14:27:59 -060089 entity_class = omci_entities.entity_id_to_class_map[class_id]
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080090 indices = entity_class.attribute_indices_from_mask(attribute_mask)
91 data = {}
Craig Lutgenaeb22b22018-11-13 10:05:45 -060092 table_attribute_mask = 0
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080093 for index in indices:
Zsolt Harasztie3ece3c2016-12-19 23:32:38 -080094 try:
Chip Boling72bbcfe2018-02-14 14:27:59 -060095 fld = entity_class.attributes[index].field
Zsolt Harasztie3ece3c2016-12-19 23:32:38 -080096 except IndexError, e:
Chip Boling72bbcfe2018-02-14 14:27:59 -060097 log.error("attribute-decode-failure", attribute_index=index,
98 entity_class=entity_class, e=e)
Zsolt Haraszti578a46c2016-12-20 16:38:43 -080099 continue
100 try:
101 s, value = fld.getfield(pkt, s)
Chip Bolingc0e4d3b2018-12-27 13:43:10 -0600102 except Exception, _e:
Zsolt Harasztie3ece3c2016-12-19 23:32:38 -0800103 raise
Craig Lutgenaeb22b22018-11-13 10:05:45 -0600104 if isinstance(pkt, OmciGetResponse) and isinstance(fld, OmciTableField):
105 data[fld.name + '_size'] = value
Chip Bolinga5e6aa32019-02-11 12:16:38 -0600106 table_attribute_mask = table_attribute_mask | (1 << (16 - index))
Craig Lutgenaeb22b22018-11-13 10:05:45 -0600107 else:
108 data[fld.name] = value
109 if table_attribute_mask:
110 data['table_attribute_mask'] = table_attribute_mask
Chip Boling72bbcfe2018-02-14 14:27:59 -0600111 return s, data
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -0800112
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(
Chip Bolinga5e6aa32019-02-11 12:16:38 -0600202 ShortField("unsupported_attributes_mask", 0),
203 lambda pkt: pkt.success_code == 9),
204 ConditionalField(
205 ShortField("failed_attributes_mask", 0),
206 lambda pkt: pkt.success_code == 9),
207 ConditionalField(
208 OmciMaskedData("data"),
209 lambda pkt: pkt.success_code == 0 or pkt.success_code == 9)
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -0800210 ]
211
212
213class OmciGetAllAlarms(OmciMessage):
214 name = "OmciGetAllAlarms"
215 message_id = 0x4b
216 fields_desc = [
217 ShortField("entity_class", 2), # Always 2 (ONT data)
218 ShortField("entity_id", 0), # Always 0 (ONT instance)
219 ByteField("alarm_retrieval_mode", 0) # 0 or 1
220 ]
221
222
223class OmciGetAllAlarmsResponse(OmciMessage):
224 name = "OmciGetAllAlarmsResponse"
225 message_id = 0x2b
226 fields_desc = [
227 ShortField("entity_class", 2), # Always 2 (ONT data)
228 ShortField("entity_id", 0),
229 ShortField("number_of_commands", None)
230 ]
231
232
233class OmciGetAllAlarmsNext(OmciMessage):
234 name = "OmciGetAllAlarmsNext"
235 message_id = 0x4c
236 fields_desc = [
237 ShortField("entity_class", 2), # Always 2 (ONT data)
238 ShortField("entity_id", 0),
239 ShortField("command_sequence_number", None)
240 ]
241
242
243class OmciGetAllAlarmsNextResponse(OmciMessage):
244 name = "OmciGetAllAlarmsNextResponse"
245 message_id = 0x2c
246 fields_desc = [
247 ShortField("entity_class", 2), # Always 2 (ONT data)
248 ShortField("entity_id", 0),
249 ShortField("alarmed_entity_class", None),
250 ShortField("alarmed_entity_id", 0),
jackwin35836dc4d2018-10-09 19:13:23 +0800251 BitField("alarm_bit_map", None, 224)
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -0800252 ]
253
254
255class OmciMibUpload(OmciMessage):
256 name = "OmciMibUpload"
257 message_id = 0x4d
258 fields_desc = [
259 ShortField("entity_class", 2), # Always 2 (ONT data)
260 ShortField("entity_id", 0),
261 ]
262
263
264class OmciMibUploadResponse(OmciMessage):
265 name = "OmciMibUploadResponse"
266 message_id = 0x2d
267 fields_desc = [
268 ShortField("entity_class", 2), # Always 2 (ONT data)
269 ShortField("entity_id", 0),
270 ShortField("number_of_commands", None)
271 ]
272
273
274class OmciMibUploadNext(OmciMessage):
275 name = "OmciMibUploadNext"
276 message_id = 0x4e
277 fields_desc = [
278 ShortField("entity_class", 2), # Always 2 (ONT data)
279 ShortField("entity_id", 0),
280 ShortField("command_sequence_number", None)
281 ]
282
283
284class OmciMibUploadNextResponse(OmciMessage):
285 name = "OmciMibUploadNextResponse"
286 message_id = 0x2e
287 fields_desc = [
288 ShortField("entity_class", 2), # Always 2 (ONT data)
289 ShortField("entity_id", 0),
290 ShortField("object_entity_class", None),
291 ShortField("object_entity_id", 0),
292 ShortField("object_attributes_mask", None),
Zsolt Harasztie3ece3c2016-12-19 23:32:38 -0800293 OmciMaskedData("object_data", entity_class='object_entity_class',
294 attributes_mask='object_attributes_mask')
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -0800295 ]
296
297
298class OmciMibReset(OmciMessage):
299 name = "OmciMibReset"
300 message_id = 0x4f
301 fields_desc = [
302 ShortField("entity_class", None),
303 ShortField("entity_id", 0)
304 ]
305
306
307class OmciMibResetResponse(OmciMessage):
308 name = "OmciMibResetResponse"
309 message_id = 0x2f
310 fields_desc = [
311 ShortField("entity_class", None),
312 ShortField("entity_id", 0),
313 ByteField("success_code", 0)
314 ]
Chip Boling764e12f2018-01-20 15:52:43 -0600315
316
317class OmciAlarmNotification(OmciMessage):
318 name = "AlarmNotification"
319 message_id = 0x10
320 fields_desc = [
321 ShortField("entity_class", None),
322 ShortField("entity_id", 0),
323 BitField("alarm_bit_map", 0, 224),
Chip Boling3186eb52018-11-02 14:28:01 -0500324 ThreeBytesField("zero_padding", 0),
Chip Boling764e12f2018-01-20 15:52:43 -0600325 ByteField("alarm_sequence_number", None)
326 ]
327
328
329class OmciAttributeValueChange(OmciMessage):
330 name = "AttributeValueChange"
331 message_id = 0x11
332 fields_desc = [
333 ShortField("entity_class", None),
334 ShortField("entity_id", 0),
335 ShortField("attributes_mask", None),
336 OmciMaskedData("data")
337 ]
338
339
340class OmciTestResult(OmciMessage):
341 name = "TestResult"
342 message_id = 0x1B
343 fields_desc = [
344 ShortField("entity_class", None),
345 ShortField("entity_id", 0)
346 # ME Test specific message contents starts here
347 # TODO: Can this be coded easily with scapy?
348 ]
Girish61687212018-01-08 12:48:58 +0530349
350
351class OmciReboot(OmciMessage):
352 name = "OmciOnuReboot"
353 message_id = 0x59
354 fields_desc = [
355 ShortField("entity_class", None),
356 ShortField("entity_id", 0),
357 ByteField("reboot_code", 0)
358 ]
359
360
361class OmciRebootResponse(OmciMessage):
362 name = "OmciOnuRebootResponse"
363 message_id = 0x39
364 fields_desc = [
365 ShortField("entity_class", None),
366 ShortField("entity_id", 0),
367 ByteField("success_code", 0)
368 ]
Chip Boling28155862018-06-07 11:13:39 -0500369
370
371class OmciGetNext(OmciMessage):
372 name = "OmciGetNext"
373 message_id = 0x5A
374 fields_desc = [
375 ShortField("entity_class", None),
376 ShortField("entity_id", 0),
377 ShortField("attributes_mask", None),
378 ShortField("command_sequence_number", None)
379 ]
380
381
382class OmciGetNextResponse(OmciMessage):
383 name = "OmciGetNextResponse"
384 message_id = 0x3A
385 fields_desc = [
386 ShortField("entity_class", None),
387 ShortField("entity_id", 0),
388 ByteField("success_code", 0),
389 ShortField("attributes_mask", None),
390 ConditionalField(OmciMaskedData("data"),
391 lambda pkt: pkt.success_code == 0)
392 ]
393
Chip Bolingac7b5622018-07-12 18:53:55 -0500394
395class OmciSynchronizeTime(OmciMessage):
396 name = "OmciSynchronizeTime"
397 message_id = 0x58
398 fields_desc = [
399 ShortField("entity_class", 256), # OntG
400 ShortField("entity_id", 0),
401 ShortField("year", 0), # eg) 2018
402 ByteField("month", 0), # 1..12
403 ByteField("day", 0), # 1..31
404 ByteField("hour", 0), # 0..23
405 ByteField("minute", 0), # 0..59
406 ByteField("second", 0) # 0..59
407 ]
408
409
410class OmciSynchronizeTimeResponse(OmciMessage):
411 name = "OmciSynchronizeTimeResponse"
412 message_id = 0x38
413 fields_desc = [
414 ShortField("entity_class", 256), # OntG
415 ShortField("entity_id", 0),
416 ByteField("success_code", 0),
417 ConditionalField(ShortField("success_info", None),
418 lambda pkt: pkt.success_code == 0)
419 ]
420
421
422class OmciGetCurrentData(OmciMessage):
423 name = "OmciGetCurrentData"
424 message_id = 0x5C
425 fields_desc = [
426 ShortField("entity_class", None),
427 ShortField("entity_id", 0),
428 ShortField("attributes_mask", None),
429 ]
430
431
432class OmciGetCurrentDataResponse(OmciMessage):
433 name = "OmciGetCurrentDataResponse"
434 message_id = 0x3C
435 fields_desc = [
436 ShortField("entity_class", None),
437 ShortField("entity_id", 0),
438 ByteField("success_code", 0),
439 ShortField("attributes_mask", None),
440 ShortField("unsupported_attributes_mask", None),
441 ShortField("failed_attributes_mask", None),
442 ConditionalField(
443 OmciMaskedData("data"), lambda pkt: pkt.success_code == 0)
444 ]
lcui33d6a8e2018-08-28 12:51:38 -0700445
446class OmciStartSoftwareDownload(OmciMessage):
447 name = "OmciStartSoftwareDownload"
448 message_id = 0x53
449 fields_desc = [
450 ShortField("entity_class", 7), # Always 7 (Software image)
451 ShortField("entity_id", None),
452 ByteField("window_size", 0),
453 IntField("image_size", 0),
454 ByteField("image_number", 1), # Always only 1 in parallel
455 ShortField("instance_id", None) # should be same as "entity_id"
456 ]
457
458class OmciStartSoftwareDownloadResponse(OmciMessage):
459 name = "OmciStartSoftwareDownloadResponse"
460 message_id = 0x33
461 fields_desc = [
462 ShortField("entity_class", 7), # Always 7 (Software image)
463 ShortField("entity_id", None),
464 ByteField("result", 0),
465 ByteField("window_size", 0),
466 ByteField("image_number", 1), # Always only 1 in parallel
467 ShortField("instance_id", None) # should be same as "entity_id"
468 ]
469
470class OmciEndSoftwareDownload(OmciMessage):
471 name = "OmciEndSoftwareDownload"
472 message_id = 0x55
473 fields_desc = [
474 ShortField("entity_class", 7), # Always 7 (Software image)
475 ShortField("entity_id", None),
476 IntField("crc32", 0),
477 IntField("image_size", 0),
478 ByteField("image_number", 1), # Always only 1 in parallel
479 ShortField("instance_id", None),# should be same as "entity_id"
480 ]
481
482class OmciEndSoftwareDownloadResponse(OmciMessage):
483 name = "OmciEndSoftwareDownload"
484 message_id = 0x35
485 fields_desc = [
486 ShortField("entity_class", 7), # Always 7 (Software image)
487 ShortField("entity_id", None),
488 ByteField("result", 0),
489 ByteField("image_number", 1), # Always only 1 in parallel
490 ShortField("instance_id", None),# should be same as "entity_id"
491 ByteField("result0", 0) # same as result
492 ]
493
494class OmciDownloadSection(OmciMessage):
495 name = "OmciDownloadSection"
496 message_id = 0x14
497 fields_desc = [
498 ShortField("entity_class", 7), # Always 7 (Software image)
499 ShortField("entity_id", None),
500 ByteField("section_number", 0), # Always only 1 in parallel
501 StrFixedLenField("data", 0, length=OmciSectionDataSize) # section data
502 ]
503
504class OmciDownloadSectionLast(OmciMessage):
505 name = "OmciDownloadSection"
506 message_id = 0x54
507 fields_desc = [
508 ShortField("entity_class", 7), # Always 7 (Software image)
509 ShortField("entity_id", None),
510 ByteField("section_number", 0), # Always only 1 in parallel
511 StrFixedLenField("data", 0, length=OmciSectionDataSize) # section data
512 ]
513
514class OmciDownloadSectionResponse(OmciMessage):
515 name = "OmciDownloadSectionResponse"
516 message_id = 0x34
517 fields_desc = [
518 ShortField("entity_class", 7), # Always 7 (Software image)
519 ShortField("entity_id", None),
520 ByteField("result", 0),
521 ByteField("section_number", 0), # Always only 1 in parallel
522 ]
523
524class OmciActivateImage(OmciMessage):
525 name = "OmciActivateImage"
526 message_id = 0x56
527 fields_desc = [
528 ShortField("entity_class", 7), # Always 7 (Software image)
529 ShortField("entity_id", None),
530 ByteField("activate_flag", 0) # Activate image unconditionally
531 ]
532
533class OmciActivateImageResponse(OmciMessage):
534 name = "OmciActivateImageResponse"
535 message_id = 0x36
536 fields_desc = [
537 ShortField("entity_class", 7), # Always 7 (Software image)
538 ShortField("entity_id", None),
539 ByteField("result", 0) # Activate image unconditionally
540 ]
541
542class OmciCommitImage(OmciMessage):
543 name = "OmciCommitImage"
544 message_id = 0x57
545 fields_desc = [
546 ShortField("entity_class", 7), # Always 7 (Software image)
547 ShortField("entity_id", None),
548 ]
549
550class OmciCommitImageResponse(OmciMessage):
551 name = "OmciCommitImageResponse"
552 message_id = 0x37
553 fields_desc = [
554 ShortField("entity_class", 7), # Always 7 (Software image)
555 ShortField("entity_id", None),
556 ByteField("result", 0) # Activate image unconditionally
557 ]
558