blob: b836199cb2ad1aff9577471b91afe7a6b76d5e9e [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
Chip Boling3186eb52018-11-02 14:28:01 -050017from scapy.fields import ByteField, ThreeBytesField, ConditionalField, 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
21from voltha.extensions.omci.omci_defs import AttributeAccess
Chip Boling72bbcfe2018-02-14 14:27:59 -060022import voltha.extensions.omci.omci_entities as omci_entities
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080023
24
Zsolt Haraszti578a46c2016-12-20 16:38:43 -080025log = structlog.get_logger()
26
27
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080028class OmciData(Field):
29
30 __slots__ = Field.__slots__ + ['_entity_class']
31
32 def __init__(self, name, entity_class="entity_class"):
33 Field.__init__(self, name=name, default=None, fmt='s')
34 self._entity_class = entity_class
35
36 def addfield(self, pkt, s, val):
37 class_id = getattr(pkt, self._entity_class)
Chip Boling72bbcfe2018-02-14 14:27:59 -060038 entity_class = omci_entities.entity_id_to_class_map.get(class_id)
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080039 for attribute in entity_class.attributes:
Chip Boling72bbcfe2018-02-14 14:27:59 -060040 if AttributeAccess.SetByCreate not in attribute.access:
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080041 continue
Chip Boling72bbcfe2018-02-14 14:27:59 -060042 if attribute.field.name == 'managed_entity_id':
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080043 continue
Chip Boling72bbcfe2018-02-14 14:27:59 -060044 fld = attribute.field
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080045 s = fld.addfield(pkt, s, val.get(fld.name, fld.default))
46 return s
47
48 def getfield(self, pkt, s):
49 """Extract an internal value from a string"""
50 class_id = getattr(pkt, self._entity_class)
Chip Boling72bbcfe2018-02-14 14:27:59 -060051 entity_class = omci_entities.entity_id_to_class_map.get(class_id)
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080052 data = {}
53 for attribute in entity_class.attributes:
Chip Boling72bbcfe2018-02-14 14:27:59 -060054 if AttributeAccess.SetByCreate not in attribute.access:
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080055 continue
Chip Boling72bbcfe2018-02-14 14:27:59 -060056 if attribute.field.name == 'managed_entity_id':
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080057 continue
Chip Boling72bbcfe2018-02-14 14:27:59 -060058 fld = attribute.field
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080059 s, value = fld.getfield(pkt, s)
60 data[fld.name] = value
61 return s, data
62
63
64class OmciMaskedData(Field):
65
66 __slots__ = Field.__slots__ + ['_entity_class', '_attributes_mask']
67
68 def __init__(self, name, entity_class="entity_class",
69 attributes_mask="attributes_mask"):
70 Field.__init__(self, name=name, default=None, fmt='s')
71 self._entity_class = entity_class
72 self._attributes_mask = attributes_mask
73
74 def addfield(self, pkt, s, val):
75 class_id = getattr(pkt, self._entity_class)
76 attribute_mask = getattr(pkt, self._attributes_mask)
Chip Boling72bbcfe2018-02-14 14:27:59 -060077 entity_class = omci_entities.entity_id_to_class_map.get(class_id)
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080078 indices = entity_class.attribute_indices_from_mask(attribute_mask)
79 for index in indices:
Chip Boling72bbcfe2018-02-14 14:27:59 -060080 fld = entity_class.attributes[index].field
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080081 s = fld.addfield(pkt, s, val[fld.name])
82 return s
83
84 def getfield(self, pkt, s):
85 """Extract an internal value from a string"""
86 class_id = getattr(pkt, self._entity_class)
87 attribute_mask = getattr(pkt, self._attributes_mask)
Chip Boling72bbcfe2018-02-14 14:27:59 -060088 entity_class = omci_entities.entity_id_to_class_map[class_id]
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -080089 indices = entity_class.attribute_indices_from_mask(attribute_mask)
90 data = {}
91 for index in indices:
Zsolt Harasztie3ece3c2016-12-19 23:32:38 -080092 try:
Chip Boling72bbcfe2018-02-14 14:27:59 -060093 fld = entity_class.attributes[index].field
Zsolt Harasztie3ece3c2016-12-19 23:32:38 -080094 except IndexError, e:
Chip Boling72bbcfe2018-02-14 14:27:59 -060095 log.error("attribute-decode-failure", attribute_index=index,
96 entity_class=entity_class, e=e)
Zsolt Haraszti578a46c2016-12-20 16:38:43 -080097 continue
98 try:
99 s, value = fld.getfield(pkt, s)
100 except Exception, e:
Zsolt Harasztie3ece3c2016-12-19 23:32:38 -0800101 raise
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -0800102 data[fld.name] = value
Chip Boling72bbcfe2018-02-14 14:27:59 -0600103 return s, data
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -0800104
105
106class OmciMessage(Packet):
107 name = "OmciMessage"
108 message_id = None # OMCI message_type value, filled by derived classes
109 fields_desc = []
110
111
112class OmciCreate(OmciMessage):
113 name = "OmciCreate"
114 message_id = 0x44
115 fields_desc = [
116 ShortField("entity_class", None),
117 ShortField("entity_id", 0),
118 OmciData("data")
119 ]
120
121
122class OmciCreateResponse(OmciMessage):
123 name = "OmciCreateResponse"
124 message_id = 0x24
125 fields_desc = [
126 ShortField("entity_class", None),
127 ShortField("entity_id", None),
128 ByteField("success_code", 0),
129 ShortField("parameter_error_attributes_mask", None),
130 ]
131
132
133class OmciDelete(OmciMessage):
134 name = "OmciDelete"
135 message_id = 0x46
136 fields_desc = [
137 ShortField("entity_class", None),
138 ShortField("entity_id", None),
139 ]
140
141
142class OmciDeleteResponse(OmciMessage):
143 name = "OmciDeleteResponse"
144 message_id = 0x26
145 fields_desc = [
146 ShortField("entity_class", None),
147 ShortField("entity_id", None),
148 ByteField("success_code", 0),
149 ]
150
151
152class OmciSet(OmciMessage):
153 name = "OmciSet"
154 message_id = 0x48
155 fields_desc = [
156 ShortField("entity_class", None),
157 ShortField("entity_id", 0),
158 ShortField("attributes_mask", None),
159 OmciMaskedData("data")
160 ]
161
162
163class OmciSetResponse(OmciMessage):
164 name = "OmciSetResponse"
165 message_id = 0x28
166 fields_desc = [
167 ShortField("entity_class", None),
168 ShortField("entity_id", None),
169 ByteField("success_code", 0),
170 ShortField("unsupported_attributes_mask", None),
171 ShortField("failed_attributes_mask", None),
172 ]
173
174
175class OmciGet(OmciMessage):
176 name = "OmciGet"
177 message_id = 0x49
178 fields_desc = [
179 ShortField("entity_class", None),
180 ShortField("entity_id", 0),
181 ShortField("attributes_mask", None)
182 ]
183
184
185class OmciGetResponse(OmciMessage):
186 name = "OmciGetResponse"
187 message_id = 0x29
188 fields_desc = [
189 ShortField("entity_class", None),
190 ShortField("entity_id", 0),
191 ByteField("success_code", 0),
192 ShortField("attributes_mask", None),
193 ConditionalField(
194 OmciMaskedData("data"), lambda pkt: pkt.success_code == 0)
195 ]
196
197
198class OmciGetAllAlarms(OmciMessage):
199 name = "OmciGetAllAlarms"
200 message_id = 0x4b
201 fields_desc = [
202 ShortField("entity_class", 2), # Always 2 (ONT data)
203 ShortField("entity_id", 0), # Always 0 (ONT instance)
204 ByteField("alarm_retrieval_mode", 0) # 0 or 1
205 ]
206
207
208class OmciGetAllAlarmsResponse(OmciMessage):
209 name = "OmciGetAllAlarmsResponse"
210 message_id = 0x2b
211 fields_desc = [
212 ShortField("entity_class", 2), # Always 2 (ONT data)
213 ShortField("entity_id", 0),
214 ShortField("number_of_commands", None)
215 ]
216
217
218class OmciGetAllAlarmsNext(OmciMessage):
219 name = "OmciGetAllAlarmsNext"
220 message_id = 0x4c
221 fields_desc = [
222 ShortField("entity_class", 2), # Always 2 (ONT data)
223 ShortField("entity_id", 0),
224 ShortField("command_sequence_number", None)
225 ]
226
227
228class OmciGetAllAlarmsNextResponse(OmciMessage):
229 name = "OmciGetAllAlarmsNextResponse"
230 message_id = 0x2c
231 fields_desc = [
232 ShortField("entity_class", 2), # Always 2 (ONT data)
233 ShortField("entity_id", 0),
234 ShortField("alarmed_entity_class", None),
235 ShortField("alarmed_entity_id", 0),
jackwin35836dc4d2018-10-09 19:13:23 +0800236 BitField("alarm_bit_map", None, 224)
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -0800237 ]
238
239
240class OmciMibUpload(OmciMessage):
241 name = "OmciMibUpload"
242 message_id = 0x4d
243 fields_desc = [
244 ShortField("entity_class", 2), # Always 2 (ONT data)
245 ShortField("entity_id", 0),
246 ]
247
248
249class OmciMibUploadResponse(OmciMessage):
250 name = "OmciMibUploadResponse"
251 message_id = 0x2d
252 fields_desc = [
253 ShortField("entity_class", 2), # Always 2 (ONT data)
254 ShortField("entity_id", 0),
255 ShortField("number_of_commands", None)
256 ]
257
258
259class OmciMibUploadNext(OmciMessage):
260 name = "OmciMibUploadNext"
261 message_id = 0x4e
262 fields_desc = [
263 ShortField("entity_class", 2), # Always 2 (ONT data)
264 ShortField("entity_id", 0),
265 ShortField("command_sequence_number", None)
266 ]
267
268
269class OmciMibUploadNextResponse(OmciMessage):
270 name = "OmciMibUploadNextResponse"
271 message_id = 0x2e
272 fields_desc = [
273 ShortField("entity_class", 2), # Always 2 (ONT data)
274 ShortField("entity_id", 0),
275 ShortField("object_entity_class", None),
276 ShortField("object_entity_id", 0),
277 ShortField("object_attributes_mask", None),
Zsolt Harasztie3ece3c2016-12-19 23:32:38 -0800278 OmciMaskedData("object_data", entity_class='object_entity_class',
279 attributes_mask='object_attributes_mask')
Zsolt Harasztie0acd8f2016-12-16 14:53:55 -0800280 ]
281
282
283class OmciMibReset(OmciMessage):
284 name = "OmciMibReset"
285 message_id = 0x4f
286 fields_desc = [
287 ShortField("entity_class", None),
288 ShortField("entity_id", 0)
289 ]
290
291
292class OmciMibResetResponse(OmciMessage):
293 name = "OmciMibResetResponse"
294 message_id = 0x2f
295 fields_desc = [
296 ShortField("entity_class", None),
297 ShortField("entity_id", 0),
298 ByteField("success_code", 0)
299 ]
Chip Boling764e12f2018-01-20 15:52:43 -0600300
301
302class OmciAlarmNotification(OmciMessage):
303 name = "AlarmNotification"
304 message_id = 0x10
305 fields_desc = [
306 ShortField("entity_class", None),
307 ShortField("entity_id", 0),
308 BitField("alarm_bit_map", 0, 224),
Chip Boling3186eb52018-11-02 14:28:01 -0500309 ThreeBytesField("zero_padding", 0),
Chip Boling764e12f2018-01-20 15:52:43 -0600310 ByteField("alarm_sequence_number", None)
311 ]
312
313
314class OmciAttributeValueChange(OmciMessage):
315 name = "AttributeValueChange"
316 message_id = 0x11
317 fields_desc = [
318 ShortField("entity_class", None),
319 ShortField("entity_id", 0),
320 ShortField("attributes_mask", None),
321 OmciMaskedData("data")
322 ]
323
324
325class OmciTestResult(OmciMessage):
326 name = "TestResult"
327 message_id = 0x1B
328 fields_desc = [
329 ShortField("entity_class", None),
330 ShortField("entity_id", 0)
331 # ME Test specific message contents starts here
332 # TODO: Can this be coded easily with scapy?
333 ]
Girish61687212018-01-08 12:48:58 +0530334
335
336class OmciReboot(OmciMessage):
337 name = "OmciOnuReboot"
338 message_id = 0x59
339 fields_desc = [
340 ShortField("entity_class", None),
341 ShortField("entity_id", 0),
342 ByteField("reboot_code", 0)
343 ]
344
345
346class OmciRebootResponse(OmciMessage):
347 name = "OmciOnuRebootResponse"
348 message_id = 0x39
349 fields_desc = [
350 ShortField("entity_class", None),
351 ShortField("entity_id", 0),
352 ByteField("success_code", 0)
353 ]
Chip Boling28155862018-06-07 11:13:39 -0500354
355
356class OmciGetNext(OmciMessage):
357 name = "OmciGetNext"
358 message_id = 0x5A
359 fields_desc = [
360 ShortField("entity_class", None),
361 ShortField("entity_id", 0),
362 ShortField("attributes_mask", None),
363 ShortField("command_sequence_number", None)
364 ]
365
366
367class OmciGetNextResponse(OmciMessage):
368 name = "OmciGetNextResponse"
369 message_id = 0x3A
370 fields_desc = [
371 ShortField("entity_class", None),
372 ShortField("entity_id", 0),
373 ByteField("success_code", 0),
374 ShortField("attributes_mask", None),
375 ConditionalField(OmciMaskedData("data"),
376 lambda pkt: pkt.success_code == 0)
377 ]
378
Chip Bolingac7b5622018-07-12 18:53:55 -0500379
380class OmciSynchronizeTime(OmciMessage):
381 name = "OmciSynchronizeTime"
382 message_id = 0x58
383 fields_desc = [
384 ShortField("entity_class", 256), # OntG
385 ShortField("entity_id", 0),
386 ShortField("year", 0), # eg) 2018
387 ByteField("month", 0), # 1..12
388 ByteField("day", 0), # 1..31
389 ByteField("hour", 0), # 0..23
390 ByteField("minute", 0), # 0..59
391 ByteField("second", 0) # 0..59
392 ]
393
394
395class OmciSynchronizeTimeResponse(OmciMessage):
396 name = "OmciSynchronizeTimeResponse"
397 message_id = 0x38
398 fields_desc = [
399 ShortField("entity_class", 256), # OntG
400 ShortField("entity_id", 0),
401 ByteField("success_code", 0),
402 ConditionalField(ShortField("success_info", None),
403 lambda pkt: pkt.success_code == 0)
404 ]
405
406
407class OmciGetCurrentData(OmciMessage):
408 name = "OmciGetCurrentData"
409 message_id = 0x5C
410 fields_desc = [
411 ShortField("entity_class", None),
412 ShortField("entity_id", 0),
413 ShortField("attributes_mask", None),
414 ]
415
416
417class OmciGetCurrentDataResponse(OmciMessage):
418 name = "OmciGetCurrentDataResponse"
419 message_id = 0x3C
420 fields_desc = [
421 ShortField("entity_class", None),
422 ShortField("entity_id", 0),
423 ByteField("success_code", 0),
424 ShortField("attributes_mask", None),
425 ShortField("unsupported_attributes_mask", None),
426 ShortField("failed_attributes_mask", None),
427 ConditionalField(
428 OmciMaskedData("data"), lambda pkt: pkt.success_code == 0)
429 ]