blob: 04d3e8308706a9ac22d7b023ab1e829f7f3c8d0b [file] [log] [blame]
#
# Copyright 2017 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import structlog
from scapy.fields import ByteField, ThreeBytesField, StrFixedLenField, ConditionalField, IntField, Field
from scapy.fields import ShortField, BitField
from scapy.packet import Packet
from voltha.extensions.omci.omci_defs import AttributeAccess, OmciSectionDataSize
from voltha.extensions.omci.omci_fields import OmciTableField
import voltha.extensions.omci.omci_entities as omci_entities
log = structlog.get_logger()
class OmciData(Field):
__slots__ = Field.__slots__ + ['_entity_class']
def __init__(self, name, entity_class="entity_class"):
Field.__init__(self, name=name, default=None, fmt='s')
self._entity_class = entity_class
def addfield(self, pkt, s, val):
class_id = getattr(pkt, self._entity_class)
entity_class = omci_entities.entity_id_to_class_map.get(class_id)
for attribute in entity_class.attributes:
if AttributeAccess.SetByCreate not in attribute.access:
continue
if attribute.field.name == 'managed_entity_id':
continue
fld = attribute.field
s = fld.addfield(pkt, s, val.get(fld.name, fld.default))
return s
def getfield(self, pkt, s):
"""Extract an internal value from a string"""
class_id = getattr(pkt, self._entity_class)
entity_class = omci_entities.entity_id_to_class_map.get(class_id)
data = {}
for attribute in entity_class.attributes:
if AttributeAccess.SetByCreate not in attribute.access:
continue
if attribute.field.name == 'managed_entity_id':
continue
fld = attribute.field
s, value = fld.getfield(pkt, s)
data[fld.name] = value
return s, data
class OmciMaskedData(Field):
__slots__ = Field.__slots__ + ['_entity_class', '_attributes_mask']
def __init__(self, name, entity_class="entity_class",
attributes_mask="attributes_mask"):
Field.__init__(self, name=name, default=None, fmt='s')
self._entity_class = entity_class
self._attributes_mask = attributes_mask
def addfield(self, pkt, s, val):
class_id = getattr(pkt, self._entity_class)
attribute_mask = getattr(pkt, self._attributes_mask)
entity_class = omci_entities.entity_id_to_class_map.get(class_id)
indices = entity_class.attribute_indices_from_mask(attribute_mask)
for index in indices:
fld = entity_class.attributes[index].field
s = fld.addfield(pkt, s, val[fld.name])
return s
def getfield(self, pkt, s):
"""Extract an internal value from a string"""
class_id = getattr(pkt, self._entity_class)
attribute_mask = getattr(pkt, self._attributes_mask)
entity_class = omci_entities.entity_id_to_class_map[class_id]
indices = entity_class.attribute_indices_from_mask(attribute_mask)
data = {}
table_attribute_mask = 0
for index in indices:
try:
fld = entity_class.attributes[index].field
except IndexError, e:
log.error("attribute-decode-failure", attribute_index=index,
entity_class=entity_class, e=e)
continue
try:
s, value = fld.getfield(pkt, s)
except Exception, _e:
raise
if isinstance(pkt, OmciGetResponse) and isinstance(fld, OmciTableField):
data[fld.name + '_size'] = value
table_attribute_mask = table_attribute_mask | (1 << (15 - index))
else:
data[fld.name] = value
if table_attribute_mask:
data['table_attribute_mask'] = table_attribute_mask
return s, data
class OmciMessage(Packet):
name = "OmciMessage"
message_id = None # OMCI message_type value, filled by derived classes
fields_desc = []
class OmciCreate(OmciMessage):
name = "OmciCreate"
message_id = 0x44
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
OmciData("data")
]
class OmciCreateResponse(OmciMessage):
name = "OmciCreateResponse"
message_id = 0x24
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", None),
ByteField("success_code", 0),
ShortField("parameter_error_attributes_mask", None),
]
class OmciDelete(OmciMessage):
name = "OmciDelete"
message_id = 0x46
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", None),
]
class OmciDeleteResponse(OmciMessage):
name = "OmciDeleteResponse"
message_id = 0x26
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", None),
ByteField("success_code", 0),
]
class OmciSet(OmciMessage):
name = "OmciSet"
message_id = 0x48
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ShortField("attributes_mask", None),
OmciMaskedData("data")
]
class OmciSetResponse(OmciMessage):
name = "OmciSetResponse"
message_id = 0x28
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", None),
ByteField("success_code", 0),
ShortField("unsupported_attributes_mask", None),
ShortField("failed_attributes_mask", None),
]
class OmciGet(OmciMessage):
name = "OmciGet"
message_id = 0x49
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ShortField("attributes_mask", None)
]
class OmciGetResponse(OmciMessage):
name = "OmciGetResponse"
message_id = 0x29
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ByteField("success_code", 0),
ShortField("attributes_mask", None),
ConditionalField(
OmciMaskedData("data"), lambda pkt: pkt.success_code == 0)
]
class OmciGetAllAlarms(OmciMessage):
name = "OmciGetAllAlarms"
message_id = 0x4b
fields_desc = [
ShortField("entity_class", 2), # Always 2 (ONT data)
ShortField("entity_id", 0), # Always 0 (ONT instance)
ByteField("alarm_retrieval_mode", 0) # 0 or 1
]
class OmciGetAllAlarmsResponse(OmciMessage):
name = "OmciGetAllAlarmsResponse"
message_id = 0x2b
fields_desc = [
ShortField("entity_class", 2), # Always 2 (ONT data)
ShortField("entity_id", 0),
ShortField("number_of_commands", None)
]
class OmciGetAllAlarmsNext(OmciMessage):
name = "OmciGetAllAlarmsNext"
message_id = 0x4c
fields_desc = [
ShortField("entity_class", 2), # Always 2 (ONT data)
ShortField("entity_id", 0),
ShortField("command_sequence_number", None)
]
class OmciGetAllAlarmsNextResponse(OmciMessage):
name = "OmciGetAllAlarmsNextResponse"
message_id = 0x2c
fields_desc = [
ShortField("entity_class", 2), # Always 2 (ONT data)
ShortField("entity_id", 0),
ShortField("alarmed_entity_class", None),
ShortField("alarmed_entity_id", 0),
BitField("alarm_bit_map", None, 224)
]
class OmciMibUpload(OmciMessage):
name = "OmciMibUpload"
message_id = 0x4d
fields_desc = [
ShortField("entity_class", 2), # Always 2 (ONT data)
ShortField("entity_id", 0),
]
class OmciMibUploadResponse(OmciMessage):
name = "OmciMibUploadResponse"
message_id = 0x2d
fields_desc = [
ShortField("entity_class", 2), # Always 2 (ONT data)
ShortField("entity_id", 0),
ShortField("number_of_commands", None)
]
class OmciMibUploadNext(OmciMessage):
name = "OmciMibUploadNext"
message_id = 0x4e
fields_desc = [
ShortField("entity_class", 2), # Always 2 (ONT data)
ShortField("entity_id", 0),
ShortField("command_sequence_number", None)
]
class OmciMibUploadNextResponse(OmciMessage):
name = "OmciMibUploadNextResponse"
message_id = 0x2e
fields_desc = [
ShortField("entity_class", 2), # Always 2 (ONT data)
ShortField("entity_id", 0),
ShortField("object_entity_class", None),
ShortField("object_entity_id", 0),
ShortField("object_attributes_mask", None),
OmciMaskedData("object_data", entity_class='object_entity_class',
attributes_mask='object_attributes_mask')
]
class OmciMibReset(OmciMessage):
name = "OmciMibReset"
message_id = 0x4f
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0)
]
class OmciMibResetResponse(OmciMessage):
name = "OmciMibResetResponse"
message_id = 0x2f
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ByteField("success_code", 0)
]
class OmciAlarmNotification(OmciMessage):
name = "AlarmNotification"
message_id = 0x10
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
BitField("alarm_bit_map", 0, 224),
ThreeBytesField("zero_padding", 0),
ByteField("alarm_sequence_number", None)
]
class OmciAttributeValueChange(OmciMessage):
name = "AttributeValueChange"
message_id = 0x11
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ShortField("attributes_mask", None),
OmciMaskedData("data")
]
class OmciTestResult(OmciMessage):
name = "TestResult"
message_id = 0x1B
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0)
# ME Test specific message contents starts here
# TODO: Can this be coded easily with scapy?
]
class OmciReboot(OmciMessage):
name = "OmciOnuReboot"
message_id = 0x59
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ByteField("reboot_code", 0)
]
class OmciRebootResponse(OmciMessage):
name = "OmciOnuRebootResponse"
message_id = 0x39
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ByteField("success_code", 0)
]
class OmciGetNext(OmciMessage):
name = "OmciGetNext"
message_id = 0x5A
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ShortField("attributes_mask", None),
ShortField("command_sequence_number", None)
]
class OmciGetNextResponse(OmciMessage):
name = "OmciGetNextResponse"
message_id = 0x3A
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ByteField("success_code", 0),
ShortField("attributes_mask", None),
ConditionalField(OmciMaskedData("data"),
lambda pkt: pkt.success_code == 0)
]
class OmciSynchronizeTime(OmciMessage):
name = "OmciSynchronizeTime"
message_id = 0x58
fields_desc = [
ShortField("entity_class", 256), # OntG
ShortField("entity_id", 0),
ShortField("year", 0), # eg) 2018
ByteField("month", 0), # 1..12
ByteField("day", 0), # 1..31
ByteField("hour", 0), # 0..23
ByteField("minute", 0), # 0..59
ByteField("second", 0) # 0..59
]
class OmciSynchronizeTimeResponse(OmciMessage):
name = "OmciSynchronizeTimeResponse"
message_id = 0x38
fields_desc = [
ShortField("entity_class", 256), # OntG
ShortField("entity_id", 0),
ByteField("success_code", 0),
ConditionalField(ShortField("success_info", None),
lambda pkt: pkt.success_code == 0)
]
class OmciGetCurrentData(OmciMessage):
name = "OmciGetCurrentData"
message_id = 0x5C
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ShortField("attributes_mask", None),
]
class OmciGetCurrentDataResponse(OmciMessage):
name = "OmciGetCurrentDataResponse"
message_id = 0x3C
fields_desc = [
ShortField("entity_class", None),
ShortField("entity_id", 0),
ByteField("success_code", 0),
ShortField("attributes_mask", None),
ShortField("unsupported_attributes_mask", None),
ShortField("failed_attributes_mask", None),
ConditionalField(
OmciMaskedData("data"), lambda pkt: pkt.success_code == 0)
]
class OmciStartSoftwareDownload(OmciMessage):
name = "OmciStartSoftwareDownload"
message_id = 0x53
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
ByteField("window_size", 0),
IntField("image_size", 0),
ByteField("image_number", 1), # Always only 1 in parallel
ShortField("instance_id", None) # should be same as "entity_id"
]
class OmciStartSoftwareDownloadResponse(OmciMessage):
name = "OmciStartSoftwareDownloadResponse"
message_id = 0x33
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
ByteField("result", 0),
ByteField("window_size", 0),
ByteField("image_number", 1), # Always only 1 in parallel
ShortField("instance_id", None) # should be same as "entity_id"
]
class OmciEndSoftwareDownload(OmciMessage):
name = "OmciEndSoftwareDownload"
message_id = 0x55
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
IntField("crc32", 0),
IntField("image_size", 0),
ByteField("image_number", 1), # Always only 1 in parallel
ShortField("instance_id", None),# should be same as "entity_id"
]
class OmciEndSoftwareDownloadResponse(OmciMessage):
name = "OmciEndSoftwareDownload"
message_id = 0x35
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
ByteField("result", 0),
ByteField("image_number", 1), # Always only 1 in parallel
ShortField("instance_id", None),# should be same as "entity_id"
ByteField("result0", 0) # same as result
]
class OmciDownloadSection(OmciMessage):
name = "OmciDownloadSection"
message_id = 0x14
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
ByteField("section_number", 0), # Always only 1 in parallel
StrFixedLenField("data", 0, length=OmciSectionDataSize) # section data
]
class OmciDownloadSectionLast(OmciMessage):
name = "OmciDownloadSection"
message_id = 0x54
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
ByteField("section_number", 0), # Always only 1 in parallel
StrFixedLenField("data", 0, length=OmciSectionDataSize) # section data
]
class OmciDownloadSectionResponse(OmciMessage):
name = "OmciDownloadSectionResponse"
message_id = 0x34
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
ByteField("result", 0),
ByteField("section_number", 0), # Always only 1 in parallel
]
class OmciActivateImage(OmciMessage):
name = "OmciActivateImage"
message_id = 0x56
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
ByteField("activate_flag", 0) # Activate image unconditionally
]
class OmciActivateImageResponse(OmciMessage):
name = "OmciActivateImageResponse"
message_id = 0x36
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
ByteField("result", 0) # Activate image unconditionally
]
class OmciCommitImage(OmciMessage):
name = "OmciCommitImage"
message_id = 0x57
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
]
class OmciCommitImageResponse(OmciMessage):
name = "OmciCommitImageResponse"
message_id = 0x37
fields_desc = [
ShortField("entity_class", 7), # Always 7 (Software image)
ShortField("entity_id", None),
ByteField("result", 0) # Activate image unconditionally
]