VOL-805: Add support for partially decoding unknowm Managed Entities (MEs)
Change-Id: I28f70d46ee5f0ed97adb8309e32c6331dcacdfc5
diff --git a/tests/utests/voltha/extensions/omci/mock/mock_onu_handler.py b/tests/utests/voltha/extensions/omci/mock/mock_onu_handler.py
index 243bb6e..1897354 100644
--- a/tests/utests/voltha/extensions/omci/mock/mock_onu_handler.py
+++ b/tests/utests/voltha/extensions/omci/mock/mock_onu_handler.py
@@ -16,6 +16,7 @@
from mock_adapter_agent import MockProxyAddress, MockDevice
from voltha.extensions.omci.omci_cc import *
+from voltha.extensions.omci.omci_entities import entity_id_to_class_map
class MockOnuHandler(MockDevice):
@@ -37,7 +38,7 @@
self._adapter_agent = adapter_agent
self.onu_mock = None
- self.omci_cc = OMCI_CC(adapter_agent, device_id)
+ self.omci_cc = OMCI_CC(adapter_agent, device_id, me_map=entity_id_to_class_map)
# Items that you can change to perform various test failures
diff --git a/tests/utests/voltha/extensions/omci/test_mib_db_ext.py b/tests/utests/voltha/extensions/omci/test_mib_db_ext.py
index f84a757..60dedef 100644
--- a/tests/utests/voltha/extensions/omci/test_mib_db_ext.py
+++ b/tests/utests/voltha/extensions/omci/test_mib_db_ext.py
@@ -18,6 +18,7 @@
from voltha.extensions.omci.database.mib_db_ext import *
from voltha.extensions.omci.database.mib_db_api import MODIFIED_KEY, CREATED_KEY,\
DEVICE_ID_KEY, MDS_KEY, LAST_SYNC_KEY
+from voltha.extensions.omci.omci_cc import UNKNOWN_CLASS_ATTRIBUTE_KEY
from mock.mock_adapter_agent import MockAdapterAgent, MockDevice
from nose.tools import raises, assert_raises
import time
@@ -514,6 +515,23 @@
self.assertTrue(all(data['received_frame_vlan_tagging_operation_table'][k] == table_as_dict[k]
for k in table_as_dict.keys()))
+ def test_unknown_me_serialization(self):
+ self.db.start()
+ self.db.add(_DEVICE_ID)
+
+ blob = '00010000000c0000000000000000000000000000000000000000'
+ class_id = 0xff78
+ inst_id = 0x101
+ attributes = {
+ UNKNOWN_CLASS_ATTRIBUTE_KEY: blob
+ }
+ self.db.set(_DEVICE_ID, class_id, inst_id, attributes)
+
+ data = self.db.query(_DEVICE_ID, class_id, inst_id, attributes.keys())
+ self.assertTrue(isinstance(UNKNOWN_CLASS_ATTRIBUTE_KEY, basestring))
+ self.assertTrue(all(isinstance(attributes[k], basestring) for k in attributes.keys()))
+ self.assertTrue(all(data[k] == attributes[k] for k in attributes.keys()))
+
if __name__ == '__main__':
main()
diff --git a/tests/utests/voltha/extensions/omci/test_omci.py b/tests/utests/voltha/extensions/omci/test_omci.py
index dd5108e..a702c88 100644
--- a/tests/utests/voltha/extensions/omci/test_omci.py
+++ b/tests/utests/voltha/extensions/omci/test_omci.py
@@ -1109,24 +1109,6 @@
"000000000000000000000028a6bc6e48",
"01042e0a00020000014904011800ffffffff0000000000000000000000000000"
"000000000000000000000028f747c739",
- "01062e0a00020000015b0002c00000001018aaaa000000000000000000000000"
- "0000000000000000000000288abbdf19",
- "01072e0a00020000015b00022000000000000000000000000000000000000000"
- "0000000000000000000000284dbaf3c9",
- "01082e0a00020000015b00021000000000000000000000000000000000000000"
- "0000000000000000000000289f8ea0a4",
- "01092e0a00020000015b00020800000000000000000000000000000000000000"
- "0000000000000000000000289c36f098",
- "010a2e0a00020000015b00020400000000000000000000000000000000000000"
- "000000000000000000000028d04565ce",
- "010b2e0a00020000015b00020200000000000000000000000000000000000000"
- "0000000000000000000000281fa624ed",
- "010c2e0a00020000015b00020100000000000000000000000000000000000000"
- "000000000000000000000028c5c1d814",
- "010d2e0a00020000015b00020010000000000000000000000000000000000000"
- "000000000000000000000028a469a9d5",
- "010e2e0a00020000015b00020008000000000000000000000000000000000000"
- "000000000000000000000028da4dc6f1",
]
mask = "%5s %9s %20s %9s %s"
print
diff --git a/tests/utests/voltha/extensions/omci/test_omci_cc.py b/tests/utests/voltha/extensions/omci/test_omci_cc.py
index 2152f04..2a7fc5f 100644
--- a/tests/utests/voltha/extensions/omci/test_omci_cc.py
+++ b/tests/utests/voltha/extensions/omci/test_omci_cc.py
@@ -20,6 +20,7 @@
from mock.mock_onu import MockOnu
from voltha.extensions.omci.omci_defs import *
from voltha.extensions.omci.omci_frame import *
+from voltha.extensions.omci.omci_cc import UNKNOWN_CLASS_ATTRIBUTE_KEY
DEFAULT_OLT_DEVICE_ID = 'default_olt_mock'
DEFAULT_ONU_DEVICE_ID = 'default_onu_mock'
@@ -31,6 +32,15 @@
RC = ReasonCodes
+def chunk(indexable, chunk_size):
+ for i in range(0, len(indexable), chunk_size):
+ yield indexable[i:i + chunk_size]
+
+
+def hex2raw(hex_string):
+ return ''.join(chr(int(byte, 16)) for byte in chunk(hex_string, 2))
+
+
class TestOmciCc(TestCase):
"""
Test the Open OMCI Communication channels
@@ -114,6 +124,7 @@
'rx_avc_overflow': omci_cc.rx_avc_overflow,
'rx_onu_discards': omci_cc.rx_onu_discards,
'rx_timeouts': omci_cc.rx_timeouts,
+ 'rx_unknown_me': omci_cc.rx_unknown_me,
'tx_errors': omci_cc.tx_errors,
'consecutive_errors': omci_cc.consecutive_errors,
'reply_min': omci_cc.reply_min,
@@ -145,6 +156,7 @@
self.assertEqual(omci_cc.rx_alarm_overflow, 0)
self.assertEqual(omci_cc.rx_avc_overflow, 0)
self.assertEqual(omci_cc.rx_onu_discards, 0)
+ self.assertEqual(omci_cc.rx_unknown_me, 0)
self.assertEqual(omci_cc.rx_timeouts, 0)
self.assertEqual(omci_cc.tx_errors, 0)
self.assertEqual(omci_cc.consecutive_errors, 0)
@@ -177,6 +189,27 @@
self.assertFalse(omci_cc.enabled)
self.assertIsNone(omci_cc._proxy_address)
+ def test_rx_discard_if_disabled(self):
+ # ME without a known decoder
+ self.setup_one_of_each()
+
+ omci_cc = self.onu_handler.omci_cc
+ omci_cc.enabled = False
+ snapshot = self._snapshot_stats()
+
+ msg = '00fc2e0a00020000ff780000e00000010000000c' \
+ '0000000000000000000000000000000000000000' \
+ '00000028105a86ef'
+
+ omci_cc.receive_message(hex2raw(msg))
+
+ # Note: No counter increments
+ self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames'])
+ self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me'])
+ self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid'])
+ self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames'])
+ self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid'])
+
def test_message_send_get(self):
# Various tests of sending an OMCI message and it either
# getting a response or send catching some errors of
@@ -202,6 +235,7 @@
# d.addCallback(self._check_stats, snapshot, 'rx_alarm_overflow', snapshot['rx_alarm_overflow'])
# d.addCallback(self._check_stats, snapshot, 'rx_avc_overflow', snapshot['rx_avc_overflow'])
# d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards'])
+ # d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me'])
# d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts'])
# d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors'])
# d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors)
@@ -233,6 +267,7 @@
# d.addCallback(self._check_stats, snapshot, 'rx_alarm_overflow', snapshot['rx_alarm_overflow'])
# d.addCallback(self._check_stats, snapshot, 'rx_avc_overflow', snapshot['rx_avc_overflow'])
# d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards'])
+ # d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me'])
# d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts'])
# d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors'])
# d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors)
@@ -271,6 +306,7 @@
# d.addCallback(self._check_stats, snapshot, 'rx_alarm_overflow', snapshot['rx_alarm_overflow'])
# d.addCallback(self._check_stats, snapshot, 'rx_avc_overflow', snapshot['rx_avc_overflow'])
# d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards'])
+ # d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me'])
# d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts'])
# d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors'])
# d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors)
@@ -302,6 +338,7 @@
# d.addCallback(self._check_stats, snapshot, 'rx_alarm_overflow', snapshot['rx_alarm_overflow'])
# d.addCallback(self._check_stats, snapshot, 'rx_avc_overflow', snapshot['rx_avc_overflow'])
# d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards'])
+ # d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me'])
# d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts'])
# d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors'])
# d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors)
@@ -330,6 +367,7 @@
d.addCallback(self._check_stats, snapshot, 'rx_alarm_overflow', snapshot['rx_alarm_overflow'])
d.addCallback(self._check_stats, snapshot, 'rx_avc_overflow', snapshot['rx_avc_overflow'])
d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards'])
+ d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me'])
d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts'])
d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors'])
d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors)
@@ -359,6 +397,7 @@
d.addCallback(self._check_stats, snapshot, 'rx_alarm_overflow', snapshot['rx_alarm_overflow'])
d.addCallback(self._check_stats, snapshot, 'rx_avc_overflow', snapshot['rx_avc_overflow'])
d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards'])
+ d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me'])
d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts'])
d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors'])
d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors)
@@ -388,6 +427,7 @@
# d.addCallback(self._check_stats, snapshot, 'rx_alarm_overflow', snapshot['rx_alarm_overflow'])
# d.addCallback(self._check_stats, snapshot, 'rx_avc_overflow', snapshot['rx_avc_overflow'])
# d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards'])
+ # d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me'])
# d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts'])
# d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors'])
# d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors)
@@ -413,6 +453,7 @@
d.addCallback(self._check_stats, snapshot, 'rx_alarm_overflow', snapshot['rx_alarm_overflow'])
d.addCallback(self._check_stats, snapshot, 'rx_avc_overflow', snapshot['rx_avc_overflow'])
d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards'])
+ d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me'])
d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts'])
d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors'])
d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors)
@@ -507,6 +548,68 @@
# todo: Test zero consecutive errors
# d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors)
+ def test_rx_unknown_me(self):
+ # ME without a known decoder
+ self.setup_one_of_each()
+
+ omci_cc = self.onu_handler.omci_cc
+ omci_cc.enabled = True
+ snapshot = self._snapshot_stats()
+
+ # This is the ID ------+
+ # v
+ msg = '00fc2e0a00020000ff780000e00000010000000c' \
+ '0000000000000000000000000000000000000000' \
+ '00000028'
+
+ omci_cc.receive_message(hex2raw(msg))
+
+ # Note: After successful frame decode, a lookup of the corresponding request by
+ # TID is performed. None should be found, so we should see the Rx Unknown TID
+ # increment.
+ self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames'])
+ self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me'] + 1)
+ self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid'] + 1)
+ self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames'])
+ self.assertEqual(omci_cc.consecutive_errors, 0)
+
+ def test_rx_decode_unknown_me(self):
+ # ME without a known decoder
+ self.setup_one_of_each()
+
+ omci_cc = self.onu_handler.omci_cc
+ omci_cc.enabled = True
+ snapshot = self._snapshot_stats()
+
+ # This is a MIB Upload Next Response. Where we would probably first see an
+ # unknown Class ID
+ #
+ # This is the ID ------+
+ # v
+ msg = '00fc2e0a00020000ff780001e000'
+ blob = '00010000000c0000000000000000000000000000000000000000'
+ msg += blob + '00000028'
+
+ # Dig into the internal method so we can get the returned frame
+ frame = omci_cc._decode_unknown_me(hex2raw(msg))
+
+ self.assertEqual(frame.fields['transaction_id'], 0x00fc)
+ self.assertEqual(frame.fields['message_type'], 0x2e)
+
+ omci_fields = frame.fields['omci_message'].fields
+
+ self.assertEqual(omci_fields['entity_class'], 0x0002)
+ self.assertEqual(omci_fields['entity_id'], 0x00)
+ self.assertEqual(omci_fields['object_entity_class'], 0x0ff78)
+ self.assertEqual(omci_fields['object_entity_id'], 0x01)
+ self.assertEqual(omci_fields['object_attributes_mask'], 0xe000)
+
+ data_fields = omci_fields['object_data']
+
+ decoded_blob = data_fields.get(UNKNOWN_CLASS_ATTRIBUTE_KEY)
+ self.assertIsNotNone(decoded_blob)
+ self.assertEqual(decoded_blob, blob)
+
def test_flush(self):
# Test flush of autonomous ONU queues
self.setup_one_of_each()
diff --git a/voltha/extensions/omci/database/mib_db_dict.py b/voltha/extensions/omci/database/mib_db_dict.py
index 58d81c2..663ce36 100644
--- a/voltha/extensions/omci/database/mib_db_dict.py
+++ b/voltha/extensions/omci/database/mib_db_dict.py
@@ -263,7 +263,7 @@
value = value.to_json()
# Other complex packet types may be a repeated list field (FieldListField)
- elif isinstance(value, list):
+ elif isinstance(value, (list, dict)):
value = json.dumps(value, separators=(',', ':'))
db_value = instance_db[ATTRIBUTES_KEY].get(attribute) \
diff --git a/voltha/extensions/omci/database/mib_db_ext.py b/voltha/extensions/omci/database/mib_db_ext.py
index c0eebab..c1b84dd 100644
--- a/voltha/extensions/omci/database/mib_db_ext.py
+++ b/voltha/extensions/omci/database/mib_db_ext.py
@@ -99,10 +99,16 @@
"""
try:
me_map = self._omci_agent.get_device(device_id).me_map
- entity = me_map[class_id]
- attr_index = entity.attribute_name_to_index_map[attr_name]
- eca = entity.attributes[attr_index]
- field = eca.field
+
+ if class_id in me_map:
+ entity = me_map[class_id]
+ attr_index = entity.attribute_name_to_index_map[attr_name]
+ eca = entity.attributes[attr_index]
+ field = eca.field
+ else:
+ # Here for auto-defined MEs (ones not defined in ME Map)
+ from voltha.extensions.omci.omci_cc import UNKNOWN_CLASS_ATTRIBUTE_KEY
+ field = StrFixedLenField(UNKNOWN_CLASS_ATTRIBUTE_KEY, None, 24)
if isinstance(field, StrFixedLenField):
# For StrFixedLenField, value is an str already (or possibly JSON encoded object)
@@ -156,10 +162,16 @@
"""
try:
me_map = self._omci_agent.get_device(device_id).me_map
- entity = me_map[class_id]
- attr_index = entity.attribute_name_to_index_map[attr_name]
- eca = entity.attributes[attr_index]
- field = eca.field
+
+ if class_id in me_map:
+ entity = me_map[class_id]
+ attr_index = entity.attribute_name_to_index_map[attr_name]
+ eca = entity.attributes[attr_index]
+ field = eca.field
+ else:
+ # Here for auto-defined MEs (ones not defined in ME Map)
+ from voltha.extensions.omci.omci_cc import UNKNOWN_CLASS_ATTRIBUTE_KEY
+ field = StrFixedLenField(UNKNOWN_CLASS_ATTRIBUTE_KEY, None, 24)
if isinstance(field, StrFixedLenField):
from scapy.base_classes import Packet_metaclass
diff --git a/voltha/extensions/omci/omci_cc.py b/voltha/extensions/omci/omci_cc.py
index 69f7646..c873ef3 100644
--- a/voltha/extensions/omci/omci_cc.py
+++ b/voltha/extensions/omci/omci_cc.py
@@ -40,6 +40,7 @@
CONNECTED_KEY = 'connected'
TX_REQUEST_KEY = 'tx-request'
RX_RESPONSE_KEY = 'rx-response'
+UNKNOWN_CLASS_ATTRIBUTE_KEY = 'voltha-unknown-blob'
class OmciCCRxEvents(IntEnum):
@@ -97,6 +98,7 @@
self._rx_avc_overflow = 0 # Autonomously generated ONU AVC rx overflow
self._rx_onu_discards = 0 # Autonomously generated ONU unknown message types
self._rx_timeouts = 0
+ self._rx_unknown_me = 0 # Number of managed entities Rx without a decode definition
self._tx_errors = 0 # Exceptions during tx request
self._consecutive_errors = 0 # Rx & Tx errors in a row, a good RX resets this to 0
self._reply_min = sys.maxint # Fastest successful tx -> rx
@@ -158,6 +160,10 @@
return self._rx_unknown_tid # Tx TID not found
@property
+ def rx_unknown_me(self):
+ return self._rx_unknown_me
+
+ @property
def rx_onu_frames(self):
return self._rx_onu_frames
@@ -347,9 +353,10 @@
except KeyError as e:
# Unknown, Unsupported, or vendor-specific ME. Key is the unknown classID
- # TODO: Can we create a temporary one to hold it so upload does not always fail on new ME's?
- self.log.exception('frame-decode-key-error', msg=hexlify(msg), e=e)
- return
+ self.log.debug('frame-decode-key-error', msg=hexlify(msg), e=e)
+ rx_frame = self._decode_unknown_me(msg)
+ self._rx_unknown_me += 1
+ rx_tid = rx_frame.fields.get('transaction_id')
except Exception as e:
self.log.exception('frame-decode', msg=hexlify(msg), e=e)
@@ -392,6 +399,64 @@
except Exception as e:
self.log.exception('rx-msg', e=e)
+ def _decode_unknown_me(self, msg):
+ """
+ Decode an ME for an unsupported class ID. This should only occur for a subset
+ of message types (Get, Set, MIB Upload Next, ...) and they should only be
+ responses as well.
+
+ There are some times below that are commented out. For VOLTHA 2.0, it is
+ expected that any get, set, create, delete for unique (often vendor) MEs
+ will be coded by the ONU utilizing it and supplied to OpenOMCI as a
+ vendor-specific ME during device initialization.
+
+ :param msg: (str) Binary data
+ :return: (OmciFrame) resulting frame
+ """
+ from struct import unpack
+
+ (tid, msg_type, framing) = unpack('!HBB', msg[0:4])
+
+ assert framing == 0xa, 'Only basic OMCI framing supported at this time'
+ msg = msg[4:]
+
+ # TODO: Commented out items below are future work (not expected for VOLTHA v2.0)
+ (msg_class, kwargs) = {
+ # OmciCreateResponse.message_id: (OmciCreateResponse, None),
+ # OmciDeleteResponse.message_id: (OmciDeleteResponse, None),
+ # OmciSetResponse.message_id: (OmciSetResponse, None),
+ # OmciGetResponse.message_id: (OmciGetResponse, None),
+ # OmciGetAllAlarmsNextResponse.message_id: (OmciGetAllAlarmsNextResponse, None),
+ OmciMibUploadNextResponse.message_id: (OmciMibUploadNextResponse,
+ {
+ 'entity_class': unpack('!H', msg[0:2])[0],
+ 'entity_id': unpack('!H', msg[2:4])[0],
+ 'object_entity_class': unpack('!H', msg[4:6])[0],
+ 'object_entity_id': unpack('!H', msg[6:8])[0],
+ 'object_attributes_mask': unpack('!H', msg[8:10])[0],
+ 'object_data': {
+ UNKNOWN_CLASS_ATTRIBUTE_KEY: hexlify(msg[10:-4])
+ },
+ }),
+ # OmciAlarmNotification.message_id: (OmciAlarmNotification, None),
+ # OmciAttributeValueChange.message_id: (OmciAttributeValueChange,
+ # {
+ # 'entity_class': unpack('!H', msg[0:2])[0],
+ # 'entity_id': unpack('!H', msg[2:4])[0],
+ # 'data': {
+ # UNKNOWN_CLASS_ATTRIBUTE_KEY: hexlify(msg[4:-8])
+ # },
+ # }),
+ # OmciTestResult.message_id: (OmciTestResult, None),
+ }.get(msg_type, None)
+
+ if msg_class is None:
+ raise TypeError('Unsupport Message Type for Unknown Decode: {}',
+ msg_type)
+
+ return OmciFrame(transaction_id=tid, message_type=msg_type,
+ omci_message=msg_class(**kwargs))
+
def _publish_rx_frame(self, tx_frame, rx_frame):
"""
Notify listeners of successful response frame
diff --git a/voltha/extensions/omci/omci_entities.py b/voltha/extensions/omci/omci_entities.py
index 1a29ecf..0e4f52d 100644
--- a/voltha/extensions/omci/omci_entities.py
+++ b/voltha/extensions/omci/omci_entities.py
@@ -1056,14 +1056,6 @@
mandatory_operations = {OP.Set, OP.Get, OP.GetNext}
notifications = {OP.AttributeValueChange}
-
-class Unknown347(EntityClass):
- class_id = 347
- attributes = [
-
- ]
-
-
# entity class lookup table from entity_class values
entity_classes_name_map = dict(
inspect.getmembers(sys.modules[__name__],
diff --git a/voltha/extensions/omci/tasks/mib_resync_task.py b/voltha/extensions/omci/tasks/mib_resync_task.py
index e39e96b..06b45ec 100644
--- a/voltha/extensions/omci/tasks/mib_resync_task.py
+++ b/voltha/extensions/omci/tasks/mib_resync_task.py
@@ -60,7 +60,8 @@
super(MibResyncTask, self).__init__(MibResyncTask.name,
omci_agent,
device_id,
- priority=MibResyncTask.task_priority)
+ priority=MibResyncTask.task_priority,
+ exclusive=False)
self._local_deferred = None
self._device = omci_agent.get_device(device_id)
self._db_active = MibDbVolatileDict(omci_agent)
@@ -360,8 +361,13 @@
# will only show up it the OpenOMCI (OLT-side) database if it changed and
# an AVC Notification was sourced by the ONU
# TODO: These could be calculated once at ONU startup (device add)
- ro_attrs = {attr.field.name for attr in me_map[cls_id].attributes
- if attr.access == ro_set}
+ if cls_id in me_map:
+ ro_attrs = {attr.field.name for attr in me_map[cls_id].attributes
+ if attr.access == ro_set}
+ else:
+ # Here if partially defined ME (not defined in ME Map)
+ from voltha.extensions.omci.omci_cc import UNKNOWN_CLASS_ATTRIBUTE_KEY
+ ro_attrs = {UNKNOWN_CLASS_ATTRIBUTE_KEY}
# Get set of common instance IDs
inst_ids = {inst_id for inst_id, _ in olt_cls.items()