Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 1 | # |
| 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 | # |
| 16 | import binascii |
Chip Boling | ce2daf6 | 2019-02-12 13:53:39 -0600 | [diff] [blame] | 17 | from pyvoltha.adapters.common.frameio.frameio import hexify |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 18 | from twisted.python.failure import Failure |
| 19 | from unittest import TestCase, main, skip |
| 20 | from mock.mock_adapter_agent import MockAdapterAgent |
| 21 | from mock.mock_onu_handler import MockOnuHandler |
| 22 | from mock.mock_olt_handler import MockOltHandler |
| 23 | from mock.mock_onu import MockOnu |
| 24 | from pyvoltha.adapters.extensions.omci.omci_defs import * |
| 25 | from pyvoltha.adapters.extensions.omci.omci_frame import * |
| 26 | from pyvoltha.adapters.extensions.omci.omci_entities import * |
| 27 | from pyvoltha.adapters.extensions.omci.omci_me import ExtendedVlanTaggingOperationConfigurationDataFrame |
| 28 | from pyvoltha.adapters.extensions.omci.omci_cc import OMCI_CC, UNKNOWN_CLASS_ATTRIBUTE_KEY,\ |
| 29 | MAX_OMCI_REQUEST_AGE |
| 30 | |
| 31 | DEFAULT_OLT_DEVICE_ID = 'default_olt_mock' |
| 32 | DEFAULT_ONU_DEVICE_ID = 'default_onu_mock' |
| 33 | DEFAULT_PON_ID = 0 |
| 34 | DEFAULT_ONU_ID = 0 |
| 35 | DEFAULT_ONU_SN = 'TEST00000001' |
| 36 | |
| 37 | OP = EntityOperations |
| 38 | RC = ReasonCodes |
| 39 | |
| 40 | successful = False |
| 41 | error_reason = None |
| 42 | |
| 43 | |
| 44 | def chunk(indexable, chunk_size): |
| 45 | for i in range(0, len(indexable), chunk_size): |
| 46 | yield indexable[i:i + chunk_size] |
| 47 | |
| 48 | |
| 49 | def hex2raw(hex_string): |
| 50 | return ''.join(chr(int(byte, 16)) for byte in chunk(hex_string, 2)) |
| 51 | |
| 52 | |
| 53 | class TestOmciCc(TestCase): |
| 54 | """ |
| 55 | Test the Open OMCI Communication channels |
| 56 | |
| 57 | Note also added some testing of MockOnu behaviour since its behaviour during more |
| 58 | complicated unit/integration tests may be performed in the future. |
| 59 | """ |
| 60 | def setUp(self, let_msg_timeout=False): |
| 61 | self.adapter_agent = MockAdapterAgent() |
| 62 | |
| 63 | def tearDown(self): |
| 64 | if self.adapter_agent is not None: |
| 65 | self.adapter_agent.tearDown() |
| 66 | |
| 67 | def setup_mock_olt(self, device_id=DEFAULT_OLT_DEVICE_ID): |
| 68 | handler = MockOltHandler(self.adapter_agent, device_id) |
| 69 | self.adapter_agent.add_device(handler.device) |
| 70 | return handler |
| 71 | |
| 72 | def setup_mock_onu(self, parent_id=DEFAULT_OLT_DEVICE_ID, |
| 73 | device_id=DEFAULT_ONU_DEVICE_ID, |
| 74 | pon_id=DEFAULT_PON_ID, |
| 75 | onu_id=DEFAULT_ONU_ID, |
| 76 | serial_no=DEFAULT_ONU_SN): |
| 77 | handler = MockOnuHandler(self.adapter_agent, parent_id, device_id, pon_id, onu_id) |
| 78 | handler.serial_number = serial_no |
| 79 | onu = MockOnu(serial_no, self.adapter_agent, handler.device_id) \ |
| 80 | if serial_no is not None else None |
| 81 | handler.onu_mock = onu |
| 82 | return handler |
| 83 | |
| 84 | def setup_one_of_each(self, timeout_messages=False): |
| 85 | # Most tests will use at lease one or more OLT and ONU |
| 86 | self.olt_handler = self.setup_mock_olt() |
| 87 | self.onu_handler = self.setup_mock_onu(parent_id=self.olt_handler.device_id) |
| 88 | self.onu_device = self.onu_handler.onu_mock |
| 89 | self.adapter_agent.timeout_the_message = timeout_messages |
| 90 | |
| 91 | self.adapter_agent.add_child_device(self.olt_handler.device, |
| 92 | self.onu_handler.device) |
| 93 | |
| 94 | def _is_omci_frame(self, results, omci_msg_type): |
| 95 | assert isinstance(results, OmciFrame), 'Not OMCI Frame' |
| 96 | assert 'omci_message' in results.fields, 'Not OMCI Frame' |
| 97 | if omci_msg_type is not None: |
| 98 | assert isinstance(results.fields['omci_message'], omci_msg_type) |
| 99 | return results |
| 100 | |
| 101 | def _check_status(self, results, value): |
| 102 | if value is not None: assert results is not None, 'unexpected emtpy message' |
| 103 | status = results.fields['omci_message'].fields['success_code'] |
| 104 | assert status == value,\ |
| 105 | 'Unexpected Status Code. Got {}, Expected: {}'.format(status, value) |
| 106 | return results |
| 107 | |
| 108 | def _check_mib_sync(self, results, value): |
| 109 | assert self.onu_device.mib_data_sync == value, \ |
| 110 | 'Unexpected MIB DATA Sync value. Got {}, Expected: {}'.format( |
| 111 | self.onu_device.mib_data_sync, value) |
| 112 | return results |
| 113 | |
| 114 | def _check_stats(self, results, _, stat, expected): |
| 115 | snapshot = self._snapshot_stats() |
| 116 | assert snapshot[stat] == expected, \ |
| 117 | 'Invalid statistic "{}". Got {}, Expected: {}'.format(stat, |
| 118 | snapshot[stat], |
| 119 | expected) |
| 120 | return results |
| 121 | |
| 122 | def _check_value_equal(self, results, name, value, expected): |
| 123 | assert value == expected, \ |
| 124 | 'Value "{}" not equal. Got {}, Expected: {}'.format(name, value, |
| 125 | expected) |
| 126 | return results |
| 127 | |
| 128 | def _default_errback(self, failure): |
| 129 | from twisted.internet.defer import TimeoutError |
| 130 | assert isinstance(failure.type, type(TimeoutError)) |
| 131 | |
| 132 | def _snapshot_stats(self): |
| 133 | omci_cc = self.onu_handler.omci_cc |
| 134 | return { |
| 135 | 'tx_frames': omci_cc.tx_frames, |
| 136 | 'rx_frames': omci_cc.rx_frames, |
| 137 | 'rx_unknown_tid': omci_cc.rx_unknown_tid, |
| 138 | 'rx_onu_frames': omci_cc.rx_onu_frames, |
| 139 | 'rx_onu_discards': omci_cc.rx_onu_discards, |
| 140 | 'rx_timeouts': omci_cc.rx_timeouts, |
| 141 | 'rx_unknown_me': omci_cc.rx_unknown_me, |
| 142 | 'rx_late': omci_cc.rx_late, |
| 143 | 'tx_errors': omci_cc.tx_errors, |
| 144 | 'consecutive_errors': omci_cc.consecutive_errors, |
| 145 | 'reply_min': omci_cc.reply_min, |
| 146 | 'reply_max': omci_cc.reply_max, |
| 147 | 'reply_average': omci_cc.reply_average, |
| 148 | 'hp_tx_queue_len': omci_cc.hp_tx_queue_len, |
| 149 | 'lp_tx_queue_len': omci_cc.lp_tx_queue_len, |
| 150 | 'max_hp_tx_queue': omci_cc.max_hp_tx_queue, |
| 151 | 'max_lp_tx_queue': omci_cc._max_lp_tx_queue, |
| 152 | } |
| 153 | |
| 154 | def test_default_init(self): |
| 155 | self.setup_one_of_each() |
| 156 | # Test default construction of OMCI_CC as well as |
| 157 | # various other parameter settings |
| 158 | omci_cc = self.onu_handler.omci_cc |
| 159 | |
| 160 | # No device directly associated |
| 161 | self.assertIsNotNone(omci_cc._adapter_agent) |
| 162 | self.assertIsNone(omci_cc._proxy_address) |
| 163 | |
| 164 | # No outstanding requests |
| 165 | self.assertEqual(len(omci_cc._pending[OMCI_CC.LOW_PRIORITY]), 0) |
| 166 | self.assertEqual(len(omci_cc._pending[OMCI_CC.HIGH_PRIORITY]), 0) |
| 167 | |
| 168 | # No active requests |
| 169 | self.assertIsNone(omci_cc._tx_request[OMCI_CC.LOW_PRIORITY]) |
| 170 | self.assertIsNone(omci_cc._tx_request[OMCI_CC.HIGH_PRIORITY]) |
| 171 | |
| 172 | # Flags/properties |
| 173 | self.assertFalse(omci_cc.enabled) |
| 174 | |
| 175 | # Statistics |
| 176 | self.assertEqual(omci_cc.tx_frames, 0) |
| 177 | self.assertEqual(omci_cc.rx_frames, 0) |
| 178 | self.assertEqual(omci_cc.rx_unknown_tid, 0) |
| 179 | self.assertEqual(omci_cc.rx_onu_frames, 0) |
| 180 | self.assertEqual(omci_cc.rx_onu_discards, 0) |
| 181 | self.assertEqual(omci_cc.rx_unknown_me, 0) |
| 182 | self.assertEqual(omci_cc.rx_timeouts, 0) |
| 183 | self.assertEqual(omci_cc.rx_late, 0) |
| 184 | self.assertEqual(omci_cc.tx_errors, 0) |
| 185 | self.assertEqual(omci_cc.consecutive_errors, 0) |
| 186 | self.assertNotEquals(omci_cc.reply_min, 0.0) |
| 187 | self.assertEqual(omci_cc.reply_max, 0.0) |
| 188 | self.assertEqual(omci_cc.reply_average, 0.0) |
| 189 | self.assertEqual(omci_cc.lp_tx_queue_len, 0.0) |
| 190 | self.assertEqual(omci_cc.max_hp_tx_queue, 0.0) |
| 191 | self.assertEqual(omci_cc._max_hp_tx_queue, 0.0) |
| 192 | self.assertEqual(omci_cc._max_lp_tx_queue, 0.0) |
| 193 | |
| 194 | def test_enable_disable(self): |
| 195 | self.setup_one_of_each() |
| 196 | |
| 197 | # Test enable property |
| 198 | omci_cc = self.onu_handler.omci_cc |
| 199 | |
| 200 | # Initially disabled |
| 201 | self.assertFalse(omci_cc.enabled) |
| 202 | omci_cc.enabled = False |
| 203 | self.assertFalse(omci_cc.enabled) |
| 204 | |
| 205 | omci_cc.enabled = True |
| 206 | self.assertTrue(omci_cc.enabled) |
| 207 | self.assertIsNotNone(omci_cc._proxy_address) |
| 208 | self.assertEqual(len(omci_cc._pending[OMCI_CC.LOW_PRIORITY]), 0) |
| 209 | self.assertEqual(len(omci_cc._pending[OMCI_CC.HIGH_PRIORITY]), 0) |
| 210 | |
| 211 | omci_cc.enabled = True # Should be a NOP |
| 212 | self.assertTrue(omci_cc.enabled) |
| 213 | self.assertIsNotNone(omci_cc._proxy_address) |
| 214 | self.assertEqual(len(omci_cc._pending[OMCI_CC.LOW_PRIORITY]), 0) |
| 215 | self.assertEqual(len(omci_cc._pending[OMCI_CC.HIGH_PRIORITY]), 0) |
| 216 | |
| 217 | omci_cc.enabled = False |
| 218 | self.assertFalse(omci_cc.enabled) |
| 219 | self.assertIsNone(omci_cc._proxy_address) |
| 220 | |
| 221 | def test_rx_discard_if_disabled(self): |
| 222 | # ME without a known decoder |
| 223 | self.setup_one_of_each() |
| 224 | |
| 225 | omci_cc = self.onu_handler.omci_cc |
| 226 | omci_cc.enabled = False |
| 227 | snapshot = self._snapshot_stats() |
| 228 | |
| 229 | msg = '00fc2e0a00020000ff780000e00000010000000c' \ |
| 230 | '0000000000000000000000000000000000000000' \ |
| 231 | '00000028105a86ef' |
| 232 | |
| 233 | omci_cc.receive_message(hex2raw(msg)) |
| 234 | |
| 235 | # Note: No counter increments |
| 236 | self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames']) |
| 237 | self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me']) |
| 238 | self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid']) |
| 239 | self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames']) |
| 240 | |
| 241 | def test_message_send_get(self): |
| 242 | # Various tests of sending an OMCI message and it either |
| 243 | # getting a response or send catching some errors of |
| 244 | # importance |
| 245 | self.setup_one_of_each() |
| 246 | |
| 247 | omci_cc = self.onu_handler.omci_cc |
| 248 | omci_cc.enabled = True |
| 249 | snapshot = self._snapshot_stats() |
| 250 | mib_data_sync = self.onu_device.mib_data_sync |
| 251 | |
| 252 | # GET |
| 253 | # d = omci_cc.send() # TODO: Implement |
| 254 | # |
| 255 | # d.addCallbacks(self._is_omci_frame, self._default_errback) |
| 256 | # d.addCallback(self._check_status, RC.Success.value) |
| 257 | # d.addCallback(self._check_mib_sync, mib_data_sync) |
| 258 | # |
| 259 | # d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames'] + 1) |
| 260 | # d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames'] + 1) |
| 261 | # d.addCallback(self._check_stats, snapshot, 'rx_unknown_tid', snapshot['rx_unknown_tid']) |
| 262 | # d.addCallback(self._check_stats, snapshot, 'rx_onu_frames', snapshot['rx_onu_frames']) |
| 263 | # d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards']) |
| 264 | # d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me']) |
| 265 | # d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts']) |
| 266 | # d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors']) |
| 267 | # d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors) |
| 268 | |
| 269 | # return d |
| 270 | |
| 271 | def test_message_send_set(self): |
| 272 | # Various tests of sending an OMCI message and it either |
| 273 | # getting a response or send catching some errors of |
| 274 | # importance |
| 275 | self.setup_one_of_each() |
| 276 | |
| 277 | omci_cc = self.onu_handler.omci_cc |
| 278 | omci_cc.enabled = True |
| 279 | snapshot = self._snapshot_stats() |
| 280 | mib_data_sync = self.onu_device.mib_data_sync |
| 281 | |
| 282 | # SET |
| 283 | # d = omci_cc.send() # TODO: Implement |
| 284 | # |
| 285 | # d.addCallbacks(self._is_omci_frame, self._default_errback) |
| 286 | # d.addCallback(self._check_status, RC.Success.value) |
| 287 | # d.addCallback(self._check_mib_sync, mib_data_sync + 1 if mib_data_sync < 255 else 1) |
| 288 | # |
| 289 | # d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames'] + 1) |
| 290 | # d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames'] + 1) |
| 291 | # d.addCallback(self._check_stats, snapshot, 'rx_unknown_tid', snapshot['rx_unknown_tid']) |
| 292 | # d.addCallback(self._check_stats, snapshot, 'rx_onu_frames', snapshot['rx_onu_frames']) |
| 293 | # d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards']) |
| 294 | # d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me']) |
| 295 | # d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts']) |
| 296 | # d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors']) |
| 297 | # d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors) |
| 298 | |
| 299 | # return d |
| 300 | # |
| 301 | # # Also test mib_data_sync rollover. 255 -> 1 (zero reserved) |
| 302 | # |
| 303 | # self.onu_device.mib_data_sync = 255 |
| 304 | # # SET |
| 305 | # self.assertTrue(True) # TODO: Implement (copy previous one here) |
| 306 | # self.assertEqual(1, self.onu_device.mib_data_sync) |
| 307 | |
| 308 | def test_message_send_create(self): |
| 309 | # Various tests of sending an OMCI message and it either |
| 310 | # getting a response or send catching some errors of |
| 311 | # importance |
| 312 | self.setup_one_of_each() |
| 313 | |
| 314 | omci_cc = self.onu_handler.omci_cc |
| 315 | omci_cc.enabled = True |
| 316 | snapshot = self._snapshot_stats() |
| 317 | mib_data_sync = self.onu_device.mib_data_sync |
| 318 | |
| 319 | # Create |
| 320 | # d = omci_cc.send() # TODO: Implement |
| 321 | # |
| 322 | # d.addCallbacks(self._is_omci_frame, self._default_errback) |
| 323 | # d.addCallback(self._check_status, RC.Success.value) |
| 324 | # d.addCallback(self._check_mib_sync, mib_data_sync + 1 if mib_data_sync < 255 else 1) |
| 325 | # |
| 326 | # d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames'] + 1) |
| 327 | # d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames'] + 1) |
| 328 | # d.addCallback(self._check_stats, snapshot, 'rx_unknown_tid', snapshot['rx_unknown_tid']) |
| 329 | # d.addCallback(self._check_stats, snapshot, 'rx_onu_frames', snapshot['rx_onu_frames']) |
| 330 | # d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards']) |
| 331 | # d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me']) |
| 332 | # d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts']) |
| 333 | # d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors']) |
| 334 | # d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors) |
| 335 | |
| 336 | # return d |
| 337 | |
| 338 | def test_message_send_delete(self): |
| 339 | # Various tests of sending an OMCI message and it either |
| 340 | # getting a response or send catching some errors of |
| 341 | # importance |
| 342 | self.setup_one_of_each() |
| 343 | |
| 344 | omci_cc = self.onu_handler.omci_cc |
| 345 | omci_cc.enabled = True |
| 346 | snapshot = self._snapshot_stats() |
| 347 | mib_data_sync = self.onu_device.mib_data_sync |
| 348 | |
| 349 | # Delete |
| 350 | # d = omci_cc.send() # TODO: Implement |
| 351 | # |
| 352 | # d.addCallbacks(self._is_omci_frame, self._default_errback) |
| 353 | # d.addCallback(self._check_status, RC.Success.value) |
| 354 | # d.addCallback(self._check_mib_sync, mib_data_sync + 1 if mib_data_sync < 255 else 1) |
| 355 | # |
| 356 | # d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames'] + 1) |
| 357 | # d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames'] + 1) |
| 358 | # d.addCallback(self._check_stats, snapshot, 'rx_unknown_tid', snapshot['rx_unknown_tid']) |
| 359 | # d.addCallback(self._check_stats, snapshot, 'rx_onu_frames', snapshot['rx_onu_frames']) |
| 360 | # d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards']) |
| 361 | # d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me']) |
| 362 | # d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts']) |
| 363 | # d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors']) |
| 364 | # d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors) |
| 365 | |
| 366 | # return d |
| 367 | |
| 368 | def test_message_send_mib_reset(self): |
| 369 | self.setup_one_of_each() |
| 370 | |
| 371 | omci_cc = self.onu_handler.omci_cc |
| 372 | omci_cc.enabled = True |
| 373 | self.onu_device.mib_data_sync = 10 |
| 374 | snapshot = self._snapshot_stats() |
| 375 | |
| 376 | # Successful MIB Reset |
| 377 | d = omci_cc.send_mib_reset(timeout=1.0) |
| 378 | |
| 379 | d.addCallbacks(self._is_omci_frame, self._default_errback) |
| 380 | d.addCallback(self._check_status, RC.Success) |
| 381 | d.addCallback(self._check_mib_sync, 0) |
| 382 | |
| 383 | d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames'] + 1) |
| 384 | d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames'] + 1) |
| 385 | d.addCallback(self._check_stats, snapshot, 'rx_unknown_tid', snapshot['rx_unknown_tid']) |
| 386 | d.addCallback(self._check_stats, snapshot, 'rx_onu_frames', snapshot['rx_onu_frames']) |
| 387 | d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards']) |
| 388 | d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me']) |
| 389 | d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts']) |
| 390 | d.addCallback(self._check_stats, snapshot, 'rx_late', snapshot['rx_late']) |
| 391 | d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors']) |
| 392 | d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors) |
| 393 | return d |
| 394 | |
| 395 | def test_message_send_mib_upload(self): |
| 396 | self.setup_one_of_each() |
| 397 | |
| 398 | omci_cc = self.onu_handler.omci_cc |
| 399 | omci_cc.enabled = True |
| 400 | snapshot = self._snapshot_stats() |
| 401 | mib_data_sync = self.onu_device.mib_data_sync |
| 402 | |
| 403 | # MIB Upload |
| 404 | d = omci_cc.send_mib_upload(timeout=1.0) |
| 405 | |
| 406 | d.addCallbacks(self._is_omci_frame, self._default_errback) |
| 407 | d.addCallback(self._check_status, RC.Success) |
| 408 | d.addCallback(self._check_mib_sync, mib_data_sync) |
| 409 | |
| 410 | # TODO: MIB Upload Results specific tests here |
| 411 | |
| 412 | d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames'] + 1) |
| 413 | d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames'] + 1) |
| 414 | d.addCallback(self._check_stats, snapshot, 'rx_unknown_tid', snapshot['rx_unknown_tid']) |
| 415 | d.addCallback(self._check_stats, snapshot, 'rx_onu_frames', snapshot['rx_onu_frames']) |
| 416 | d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards']) |
| 417 | d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me']) |
| 418 | d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts']) |
| 419 | d.addCallback(self._check_stats, snapshot, 'rx_late', snapshot['rx_late']) |
| 420 | d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors']) |
| 421 | d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors) |
| 422 | return d |
| 423 | |
| 424 | def test_message_send_mib_upload_next(self): |
| 425 | self.setup_one_of_each() |
| 426 | |
| 427 | omci_cc = self.onu_handler.omci_cc |
| 428 | omci_cc.enabled = True |
| 429 | snapshot = self._snapshot_stats() |
| 430 | mib_data_sync = self.onu_device.mib_data_sync |
| 431 | |
| 432 | # # MIB Upload Next |
| 433 | # d = omci_cc.send_mib_upload_next(0, timeout=1.0) |
| 434 | # |
| 435 | # d.addCallbacks(self._is_omci_frame, self._default_errback) |
| 436 | # d.addCallback(self._check_status, RC.Success) |
| 437 | # d.addCallback(self._check_mib_sync, mib_data_sync) |
| 438 | # |
| 439 | # # TODO: MIB Upload Next Results specific tests here |
| 440 | # |
| 441 | # d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames'] + 1) |
| 442 | # d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames'] + 1) |
| 443 | # d.addCallback(self._check_stats, snapshot, 'rx_unknown_tid', snapshot['rx_unknown_tid']) |
| 444 | # d.addCallback(self._check_stats, snapshot, 'rx_onu_frames', snapshot['rx_onu_frames']) |
| 445 | # d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards']) |
| 446 | # d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me']) |
| 447 | # d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts']) |
| 448 | # d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors']) |
| 449 | # d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors) |
| 450 | # return d |
| 451 | |
| 452 | def test_message_send_no_timeout(self): |
| 453 | self.setup_one_of_each() |
| 454 | |
| 455 | omci_cc = self.onu_handler.omci_cc |
| 456 | omci_cc.enabled = True |
| 457 | self.onu_device.mib_data_sync = 10 |
| 458 | snapshot = self._snapshot_stats() |
| 459 | |
| 460 | d = omci_cc.send_mib_reset(timeout=0) |
| 461 | d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames'] + 1) |
| 462 | d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames']) |
| 463 | d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors']) |
| 464 | return d |
| 465 | |
| 466 | def test_message_send_bad_timeout(self): |
| 467 | self.setup_one_of_each() |
| 468 | |
| 469 | omci_cc = self.onu_handler.omci_cc |
| 470 | omci_cc.enabled = True |
| 471 | self.onu_device.mib_data_sync = 10 |
| 472 | snapshot = self._snapshot_stats() |
| 473 | |
| 474 | d = omci_cc.send_mib_reset(timeout=MAX_OMCI_REQUEST_AGE + 1) |
| 475 | d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames']) |
| 476 | d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames']) |
| 477 | d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors'] + 1) |
| 478 | return d |
| 479 | |
| 480 | def test_message_send_not_a_frame(self): |
| 481 | self.setup_one_of_each() |
| 482 | |
| 483 | omci_cc = self.onu_handler.omci_cc |
| 484 | omci_cc.enabled = True |
| 485 | self.onu_device.mib_data_sync = 10 |
| 486 | snapshot = self._snapshot_stats() |
| 487 | |
| 488 | d = omci_cc.send('hello world', timeout=1) |
| 489 | d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames']) |
| 490 | d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames']) |
| 491 | d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors'] + 1) |
| 492 | return d |
| 493 | |
| 494 | def test_message_send_reboot(self): |
| 495 | self.setup_one_of_each() |
| 496 | |
| 497 | omci_cc = self.onu_handler.omci_cc |
| 498 | omci_cc.enabled = True |
| 499 | snapshot = self._snapshot_stats() |
| 500 | |
| 501 | # ONU Reboot |
| 502 | d = omci_cc.send_reboot(timeout=1.0) |
| 503 | |
| 504 | d.addCallbacks(self._is_omci_frame, self._default_errback) |
| 505 | d.addCallback(self._check_status, RC.Success) |
| 506 | |
| 507 | d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames'] + 1) |
| 508 | d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames'] + 1) |
| 509 | d.addCallback(self._check_stats, snapshot, 'rx_unknown_tid', snapshot['rx_unknown_tid']) |
| 510 | d.addCallback(self._check_stats, snapshot, 'rx_onu_frames', snapshot['rx_onu_frames']) |
| 511 | d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards']) |
| 512 | d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me']) |
| 513 | d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts']) |
| 514 | d.addCallback(self._check_stats, snapshot, 'rx_late', snapshot['rx_late']) |
| 515 | d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors']) |
| 516 | d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors) |
| 517 | return d |
| 518 | |
| 519 | def test_message_send_with_omci_disabled(self): |
| 520 | self.setup_one_of_each() |
| 521 | |
| 522 | omci_cc = self.onu_handler.omci_cc |
| 523 | self.assertFalse(omci_cc.enabled) |
| 524 | |
| 525 | # Successful MIB Reset |
| 526 | d = omci_cc.send_mib_reset(timeout=1.0) |
| 527 | |
| 528 | def success_is_bad(_results): |
| 529 | assert False, 'This test should throw a failure/error' |
| 530 | |
| 531 | def fail_fast(_failure): |
| 532 | pass |
| 533 | return None |
| 534 | |
| 535 | d.addCallbacks(success_is_bad, fail_fast) |
| 536 | return d |
| 537 | |
| 538 | def test_message_send_get_with_latency(self): |
| 539 | # Various tests of sending an OMCI message and it either |
| 540 | # getting a response or send catching some errors of |
| 541 | # importance |
| 542 | self.setup_one_of_each() |
| 543 | self.olt_handler.latency = 0.500 # 1/2 second |
| 544 | |
| 545 | omci_cc = self.onu_handler.omci_cc |
| 546 | omci_cc.enabled = True |
| 547 | |
| 548 | # Successful MIB Reset |
| 549 | d = omci_cc.send_mib_reset(timeout=1.0) |
| 550 | |
| 551 | d.addCallbacks(self._is_omci_frame, self._default_errback) |
| 552 | d.addCallback(self._check_status, RC.Success) |
| 553 | |
| 554 | def check_latency_values(_): |
| 555 | self.assertGreaterEqual(omci_cc.reply_min, self.olt_handler.latency) |
| 556 | self.assertGreaterEqual(omci_cc.reply_max, self.olt_handler.latency) |
| 557 | self.assertGreaterEqual(omci_cc.reply_average, self.olt_handler.latency) |
| 558 | |
| 559 | d.addCallback(check_latency_values) |
| 560 | return d |
| 561 | |
| 562 | def test_message_failures(self): |
| 563 | # Various tests of sending an OMCI message and it fails |
| 564 | self.setup_one_of_each() |
| 565 | |
| 566 | omci_cc = self.onu_handler.omci_cc |
| 567 | omci_cc.enabled = True |
| 568 | snapshot = self._snapshot_stats() |
| 569 | |
| 570 | self.assertEqual(omci_cc.tx_frames, 0) |
| 571 | self.assertEqual(omci_cc.rx_frames, 0) |
| 572 | self.assertEqual(omci_cc.rx_unknown_tid, 0) |
| 573 | self.assertEqual(omci_cc.rx_timeouts, 0) |
| 574 | self.assertEqual(omci_cc.rx_late, 0) |
| 575 | self.assertEqual(omci_cc.tx_errors, 0) |
| 576 | |
| 577 | # # Class ID not found |
| 578 | # d = omci_cc.send_mib_reset(timeout=1.0) |
| 579 | # self.assertTrue(True) # TODO: Implement |
| 580 | # todo: Test non-zero consecutive errors |
| 581 | # |
| 582 | # # Instance ID not found |
| 583 | # d = omci_cc.send_mib_reset(timeout=1.0) |
| 584 | # self.assertTrue(True) # TODO: Implement |
| 585 | # todo: Test non-zero consecutive errors |
| 586 | # |
| 587 | # # PON is disabled |
| 588 | # d = omci_cc.send_mib_reset(timeout=1.0) |
| 589 | # self.assertTrue(True) # TODO: Implement |
| 590 | # todo: Test non-zero consecutive errors |
| 591 | # |
| 592 | # # ONU is disabled |
| 593 | # d = omci_cc.send_mib_reset(timeout=1.0) |
| 594 | # self.assertTrue(True) # TODO: Implement |
| 595 | # todo: Test non-zero consecutive errors |
| 596 | # |
| 597 | # # ONU is not activated |
| 598 | # d = omci_cc.send_mib_reset(timeout=1.0) |
| 599 | # self.assertTrue(True) # TODO: Implement |
| 600 | # todo: Test non-zero consecutive errors |
| 601 | |
| 602 | # TODO: make OLT send back an unknown TID ( |
| 603 | |
| 604 | # todo: Test non-zero consecutive errors |
| 605 | # todo: Send a good frame |
| 606 | # todo: Test zero consecutive errors |
| 607 | # d.addCallback(self._check_value_equal, 'consecutive_errors', 0, omci_cc.consecutive_errors) |
| 608 | |
| 609 | def test_rx_unknown_me(self): |
| 610 | # ME without a known decoder |
| 611 | self.setup_one_of_each() |
| 612 | |
| 613 | omci_cc = self.onu_handler.omci_cc |
| 614 | omci_cc.enabled = True |
| 615 | snapshot = self._snapshot_stats() |
| 616 | |
| 617 | # This is the ID ------+ |
| 618 | # v |
| 619 | msg = '00fc2e0a00020000ff780000e00000010000000c' \ |
| 620 | '0000000000000000000000000000000000000000' \ |
| 621 | '00000028' |
| 622 | |
| 623 | omci_cc.receive_message(hex2raw(msg)) |
| 624 | |
| 625 | # Note: After successful frame decode, a lookup of the corresponding request by |
| 626 | # TID is performed. None should be found, so we should see the Rx Unknown TID |
| 627 | # increment. |
William Kurkian | 16b767a | 2019-05-07 17:02:19 -0400 | [diff] [blame] | 628 | self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames'] + 1) |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 629 | self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me'] + 1) |
| 630 | self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid'] + 1) |
| 631 | self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames']) |
| 632 | self.assertEqual(omci_cc.consecutive_errors, 0) |
| 633 | |
| 634 | def test_rx_decode_unknown_me(self): |
| 635 | # ME without a known decoder |
| 636 | self.setup_one_of_each() |
| 637 | |
| 638 | omci_cc = self.onu_handler.omci_cc |
| 639 | omci_cc.enabled = True |
| 640 | snapshot = self._snapshot_stats() |
| 641 | |
| 642 | # This is a MIB Upload Next Response. Where we would probably first see an |
| 643 | # unknown Class ID |
| 644 | # |
| 645 | # This is the ID ------+ |
| 646 | # v |
| 647 | msg = '00fc2e0a00020000ff780001e000' |
| 648 | blob = '00010000000c0000000000000000000000000000000000000000' |
| 649 | msg += blob + '00000028' |
| 650 | |
| 651 | # Dig into the internal method so we can get the returned frame |
| 652 | frame = omci_cc._decode_unknown_me(hex2raw(msg)) |
| 653 | |
| 654 | self.assertEqual(frame.fields['transaction_id'], 0x00fc) |
| 655 | self.assertEqual(frame.fields['message_type'], 0x2e) |
| 656 | |
| 657 | omci_fields = frame.fields['omci_message'].fields |
| 658 | |
| 659 | self.assertEqual(omci_fields['entity_class'], 0x0002) |
| 660 | self.assertEqual(omci_fields['entity_id'], 0x00) |
| 661 | self.assertEqual(omci_fields['object_entity_class'], 0x0ff78) |
| 662 | self.assertEqual(omci_fields['object_entity_id'], 0x01) |
| 663 | self.assertEqual(omci_fields['object_attributes_mask'], 0xe000) |
| 664 | |
| 665 | data_fields = omci_fields['object_data'] |
| 666 | |
| 667 | decoded_blob = data_fields.get(UNKNOWN_CLASS_ATTRIBUTE_KEY) |
| 668 | self.assertIsNotNone(decoded_blob) |
| 669 | self.assertEqual(decoded_blob, blob) |
| 670 | |
William Kurkian | 16b767a | 2019-05-07 17:02:19 -0400 | [diff] [blame] | 671 | def test_rx_unknown_me_avc(self): |
| 672 | # ME without a known decoder but is and attribute value change |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 673 | self.setup_one_of_each() |
| 674 | |
| 675 | omci_cc = self.onu_handler.omci_cc |
| 676 | omci_cc.enabled = True |
| 677 | snapshot = self._snapshot_stats() |
| 678 | |
William Kurkian | 16b767a | 2019-05-07 17:02:19 -0400 | [diff] [blame] | 679 | msg = '0000110aff78000080000e000000' \ |
| 680 | '00000000000000000000000000000000000000000000000000000' \ |
| 681 | '00000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 682 | |
William Kurkian | 16b767a | 2019-05-07 17:02:19 -0400 | [diff] [blame] | 683 | omci_cc.receive_message(hex2raw(msg)) |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 684 | |
William Kurkian | 16b767a | 2019-05-07 17:02:19 -0400 | [diff] [blame] | 685 | # Blob decode should work and then it should be passed off to the |
| 686 | # ONU Autonomous frame processor |
| 687 | self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames']) |
| 688 | self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me'] + 1) |
| 689 | self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid']) |
| 690 | self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames'] + 1) |
| 691 | self.assertEqual(omci_cc.rx_onu_discards, snapshot['rx_onu_discards']) |
| 692 | self.assertEqual(omci_cc.consecutive_errors, 0) |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 693 | |
| 694 | def test_rx_discard_if_disabled(self): |
| 695 | # ME without a known decoder |
| 696 | self.setup_one_of_each() |
| 697 | |
| 698 | omci_cc = self.onu_handler.omci_cc |
| 699 | omci_cc.enabled = False |
| 700 | snapshot = self._snapshot_stats() |
| 701 | |
| 702 | msg = '00fc2e0a00020000ff780000e00000010000000c' \ |
| 703 | '0000000000000000000000000000000000000000' \ |
| 704 | '00000028105a86ef' |
| 705 | |
| 706 | omci_cc.receive_message(hex2raw(msg)) |
| 707 | |
| 708 | # Note: No counter increments |
| 709 | self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames']) |
| 710 | self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me']) |
| 711 | self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid']) |
| 712 | self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames']) |
| 713 | |
| 714 | def test_omci_alarm_decode(self): |
| 715 | """ |
| 716 | This test covers an issue discovered in Sept 2018 (JIRA-1213). It was |
| 717 | an exception during frame decode. |
| 718 | """ |
| 719 | self.setup_one_of_each() |
| 720 | |
| 721 | omci_cc = self.onu_handler.omci_cc |
| 722 | omci_cc.enabled = True |
| 723 | snapshot = self._snapshot_stats() |
| 724 | |
| 725 | # Frame from the JIRA issue |
| 726 | msg = '0000100a000b0102800000000000000000000000' \ |
| 727 | '0000000000000000000000000000000000000015' \ |
| 728 | '000000282d3ae0a6' |
| 729 | |
| 730 | _results = omci_cc.receive_message(hex2raw(msg)) |
| 731 | |
| 732 | self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames']) |
| 733 | self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me']) |
| 734 | self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid']) |
| 735 | self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames'] + 1) |
| 736 | self.assertEqual(omci_cc.rx_onu_discards, snapshot['rx_onu_discards']) |
| 737 | |
| 738 | def test_omci_avc_decode(self): |
| 739 | self.setup_one_of_each() |
| 740 | |
| 741 | omci_cc = self.onu_handler.omci_cc |
| 742 | omci_cc.enabled = True |
| 743 | snapshot = self._snapshot_stats() |
| 744 | |
| 745 | # Frame from the JIRA issue |
| 746 | msg = '0000110a0007000080004d4c2d33363236000000' \ |
| 747 | '0000000020202020202020202020202020202020' \ |
| 748 | '00000028' |
| 749 | |
| 750 | _results = omci_cc.receive_message(hex2raw(msg)) |
| 751 | |
| 752 | self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames']) |
| 753 | self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me']) |
| 754 | self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid']) |
| 755 | self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames'] + 1) |
| 756 | self.assertEqual(omci_cc.rx_onu_discards, snapshot['rx_onu_discards']) |
| 757 | |
| 758 | def test_omci_unknown_onu_decode(self): |
| 759 | self.setup_one_of_each() |
| 760 | |
| 761 | omci_cc = self.onu_handler.omci_cc |
| 762 | omci_cc.enabled = True |
| 763 | snapshot = self._snapshot_stats() |
| 764 | |
| 765 | # Frame from the JIRA issue |
| 766 | msg = '0000190a0007000080004d4c2d33363236000000' \ |
| 767 | '0000000020202020202020202020202020202020' \ |
| 768 | '00000028' |
| 769 | |
| 770 | _results = omci_cc.receive_message(hex2raw(msg)) |
| 771 | |
| 772 | self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames']) |
| 773 | self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me']) |
| 774 | self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid']) |
| 775 | self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames'] + 1) |
| 776 | self.assertEqual(omci_cc.rx_onu_discards, snapshot['rx_onu_discards'] + 1) |
| 777 | |
| 778 | def test_omci_bad_frame_decode(self): |
| 779 | self.setup_one_of_each() |
| 780 | |
| 781 | omci_cc = self.onu_handler.omci_cc |
| 782 | omci_cc.enabled = True |
| 783 | snapshot = self._snapshot_stats() |
| 784 | |
| 785 | # Frame from the JIRA issue |
| 786 | msg = '0020190a0007000080004d4c2d33363236000000' \ |
| 787 | '0000000000000028' |
| 788 | |
| 789 | _results = omci_cc.receive_message(hex2raw(msg)) |
| 790 | # NOTE: Currently do not increment any Rx Discard counters, just throw it away |
| 791 | self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames'] + 1) |
| 792 | self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me']) |
| 793 | self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid'] + 1) |
| 794 | self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames']) |
| 795 | self.assertEqual(omci_cc.rx_onu_discards, snapshot['rx_onu_discards']) |
| 796 | |
| 797 | def test_rx_decode_onu_g(self): |
| 798 | self.setup_one_of_each() |
| 799 | |
| 800 | omci_cc = self.onu_handler.omci_cc |
| 801 | omci_cc.enabled = True |
| 802 | snapshot = self._snapshot_stats() |
| 803 | |
| 804 | msg = '001e2e0a0002000001000000e000424657530000' \ |
| 805 | '0000000000000000000000324246575300107496' \ |
| 806 | '00000028e7fb4a91' |
| 807 | |
| 808 | omci_cc.receive_message(hex2raw(msg)) |
| 809 | |
| 810 | # Note: No counter increments |
| 811 | self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames'] + 1) |
| 812 | self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me']) |
| 813 | self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid'] + 1) |
| 814 | self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames']) |
| 815 | |
| 816 | def test_rx_decode_extvlantagging(self): |
| 817 | self.setup_one_of_each() |
| 818 | |
| 819 | omci_cc = self.onu_handler.omci_cc |
| 820 | omci_cc.enabled = True |
| 821 | snapshot = self._snapshot_stats() |
| 822 | |
| 823 | msg = '030a290a00ab0201000d00000000001031323334' \ |
| 824 | '3536373839303132333435363738393031323334' \ |
| 825 | '000000281166d283' |
| 826 | |
| 827 | omci_cc.receive_message(hex2raw(msg)) |
| 828 | |
| 829 | self.assertEqual(omci_cc.rx_frames, snapshot['rx_frames'] + 1) |
| 830 | self.assertEqual(omci_cc.rx_unknown_me, snapshot['rx_unknown_me']) |
| 831 | self.assertEqual(omci_cc.rx_unknown_tid, snapshot['rx_unknown_tid'] + 1) |
| 832 | self.assertEqual(omci_cc.rx_onu_frames, snapshot['rx_onu_frames']) |
| 833 | |
| 834 | def _check_vlan_tag_op(self, results, attr, expected): |
| 835 | omci_msg = results.fields['omci_message'] |
| 836 | data = omci_msg.fields['data'] |
| 837 | val = data[attr] |
| 838 | self.assertEqual(expected, val) |
| 839 | return results |
| 840 | |
| 841 | @skip('for unknown omci failure') |
| 842 | #@deferred() |
| 843 | def test_rx_table_get_extvlantagging(self): |
| 844 | self.setup_one_of_each() |
| 845 | |
| 846 | onu = self.onu_handler.onu_mock |
| 847 | entity_id = 1 |
| 848 | vlan_tag_op1 = VlanTaggingOperation( |
| 849 | filter_outer_priority=15, |
| 850 | filter_outer_vid=4096, |
| 851 | filter_outer_tpid_de=2, |
| 852 | filter_inner_priority=15, |
| 853 | filter_inner_vid=4096, |
| 854 | filter_inner_tpid_de=0, |
| 855 | filter_ether_type=0, |
| 856 | treatment_tags_to_remove=0, |
| 857 | treatment_outer_priority=15, |
| 858 | treatment_outer_vid=1234, |
| 859 | treatment_outer_tpid_de=0, |
| 860 | treatment_inner_priority=0, |
| 861 | treatment_inner_vid=4091, |
| 862 | treatment_inner_tpid_de=4, |
| 863 | ) |
| 864 | vlan_tag_op2 = VlanTaggingOperation( |
| 865 | filter_outer_priority=14, |
| 866 | filter_outer_vid=1234, |
| 867 | filter_outer_tpid_de=5, |
| 868 | filter_inner_priority=1, |
| 869 | filter_inner_vid=2345, |
| 870 | filter_inner_tpid_de=1, |
| 871 | filter_ether_type=0, |
| 872 | treatment_tags_to_remove=1, |
| 873 | treatment_outer_priority=15, |
| 874 | treatment_outer_vid=2222, |
| 875 | treatment_outer_tpid_de=1, |
| 876 | treatment_inner_priority=1, |
| 877 | treatment_inner_vid=3333, |
| 878 | treatment_inner_tpid_de=5, |
| 879 | ) |
| 880 | vlan_tag_op3 = VlanTaggingOperation( |
| 881 | filter_outer_priority=13, |
| 882 | filter_outer_vid=55, |
| 883 | filter_outer_tpid_de=1, |
| 884 | filter_inner_priority=7, |
| 885 | filter_inner_vid=4567, |
| 886 | filter_inner_tpid_de=1, |
| 887 | filter_ether_type=0, |
| 888 | treatment_tags_to_remove=1, |
| 889 | treatment_outer_priority=2, |
| 890 | treatment_outer_vid=1111, |
| 891 | treatment_outer_tpid_de=1, |
| 892 | treatment_inner_priority=1, |
| 893 | treatment_inner_vid=3131, |
| 894 | treatment_inner_tpid_de=5, |
| 895 | ) |
| 896 | tbl = [vlan_tag_op1, vlan_tag_op2, vlan_tag_op3] |
| 897 | tblstr = str(vlan_tag_op1) + str(vlan_tag_op2) + str(vlan_tag_op3) |
| 898 | |
| 899 | onu._omci_response[OP.Get.value][ExtendedVlanTaggingOperationConfigurationData.class_id] = { |
| 900 | entity_id: OmciFrame(transaction_id=0, |
| 901 | message_type=OmciGetResponse.message_id, |
| 902 | omci_message=OmciGetResponse( |
| 903 | entity_class=ExtendedVlanTaggingOperationConfigurationData.class_id, |
| 904 | entity_id=1, |
| 905 | success_code=RC.Success.value, |
| 906 | attributes_mask=ExtendedVlanTaggingOperationConfigurationData.mask_for( |
| 907 | 'received_frame_vlan_tagging_operation_table'), |
| 908 | data={'received_frame_vlan_tagging_operation_table': 16 * len(tbl)} |
| 909 | )) |
| 910 | } |
| 911 | |
| 912 | rsp1 = binascii.a2b_hex(hexify(tblstr[0:OmciTableField.PDU_SIZE])) |
| 913 | rsp2 = binascii.a2b_hex(hexify(tblstr[OmciTableField.PDU_SIZE:])) |
| 914 | onu._omci_response[OP.GetNext.value][ExtendedVlanTaggingOperationConfigurationData.class_id] = { |
| 915 | entity_id: {0: {'failures':2, |
| 916 | 'frame':OmciFrame(transaction_id=0, |
| 917 | message_type=OmciGetNextResponse.message_id, |
| 918 | omci_message=OmciGetNextResponse( |
| 919 | entity_class=ExtendedVlanTaggingOperationConfigurationData.class_id, |
| 920 | entity_id=1, |
| 921 | success_code=RC.Success.value, |
| 922 | attributes_mask=ExtendedVlanTaggingOperationConfigurationData.mask_for( |
| 923 | 'received_frame_vlan_tagging_operation_table'), |
| 924 | data={'received_frame_vlan_tagging_operation_table': rsp1 |
| 925 | } |
| 926 | ))}, |
| 927 | 1: OmciFrame(transaction_id=0, |
| 928 | message_type=OmciGetNextResponse.message_id, |
| 929 | omci_message=OmciGetNextResponse( |
| 930 | entity_class=ExtendedVlanTaggingOperationConfigurationData.class_id, |
| 931 | entity_id=1, |
| 932 | success_code=RC.Success.value, |
| 933 | attributes_mask=ExtendedVlanTaggingOperationConfigurationData.mask_for( |
| 934 | 'received_frame_vlan_tagging_operation_table'), |
| 935 | data={'received_frame_vlan_tagging_operation_table': rsp2 |
| 936 | } |
| 937 | )) |
| 938 | } |
| 939 | } |
| 940 | |
| 941 | omci_cc = self.onu_handler.omci_cc |
| 942 | omci_cc.enabled = True |
| 943 | |
| 944 | msg = ExtendedVlanTaggingOperationConfigurationDataFrame( |
| 945 | entity_id, |
| 946 | attributes={'received_frame_vlan_tagging_operation_table':True} |
| 947 | ) |
| 948 | |
| 949 | snapshot = self._snapshot_stats() |
| 950 | |
| 951 | frame = msg.get() |
| 952 | d = omci_cc.send(frame, timeout=5.0) |
| 953 | |
| 954 | d.addCallbacks(self._is_omci_frame, self._default_errback, [OmciGetResponse]) |
| 955 | d.addCallback(self._check_status, RC.Success) |
| 956 | |
| 957 | d.addCallback(self._check_stats, snapshot, 'tx_frames', snapshot['tx_frames'] + 5) |
| 958 | d.addCallback(self._check_stats, snapshot, 'rx_frames', snapshot['rx_frames'] + 3) |
| 959 | d.addCallback(self._check_stats, snapshot, 'rx_unknown_tid', snapshot['rx_unknown_tid']) |
| 960 | d.addCallback(self._check_stats, snapshot, 'rx_onu_frames', snapshot['rx_onu_frames']) |
| 961 | d.addCallback(self._check_stats, snapshot, 'rx_onu_discards', snapshot['rx_onu_discards']) |
| 962 | d.addCallback(self._check_stats, snapshot, 'rx_unknown_me', snapshot['rx_unknown_me']) |
| 963 | d.addCallback(self._check_stats, snapshot, 'rx_timeouts', snapshot['rx_timeouts'] + 2) |
| 964 | d.addCallback(self._check_stats, snapshot, 'rx_late', snapshot['rx_late']) |
| 965 | d.addCallback(self._check_stats, snapshot, 'tx_errors', snapshot['tx_errors']) |
| 966 | d.addCallback(self._check_stats, snapshot, 'consecutive_errors', 0) |
| 967 | d.addCallback(self._check_vlan_tag_op, 'received_frame_vlan_tagging_operation_table', tbl) |
| 968 | |
| 969 | return d |
| 970 | |
| 971 | ################################################################## |
| 972 | # Start of tests specific to new stop_and_wait changes |
| 973 | # |
| 974 | def test_message_send_low_priority(self): |
| 975 | # self.setup_one_of_each(timeout_messages=True) |
| 976 | self.setup_one_of_each() |
| 977 | |
| 978 | omci_cc = self.onu_handler.omci_cc |
| 979 | omci_cc.enabled = True |
| 980 | snapshot = self._snapshot_stats() |
| 981 | |
| 982 | # MIB Upload |
| 983 | d = omci_cc.send_mib_upload(timeout=1.0, high_priority=False) |
| 984 | d.addCallback(self._check_stats, snapshot, 'lp_tx_queue_len', snapshot['lp_tx_queue_len']) |
| 985 | d.addCallback(self._check_stats, snapshot, 'hp_tx_queue_len', snapshot['hp_tx_queue_len']) |
| 986 | d.addCallback(self._check_stats, snapshot, 'max_lp_tx_queue', snapshot['max_lp_tx_queue'] + 1) |
| 987 | d.addCallback(self._check_stats, snapshot, 'max_hp_tx_queue', snapshot['max_hp_tx_queue']) |
| 988 | |
| 989 | # Flush to get ready for next test (one frame queued) |
| 990 | omci_cc.flush() |
| 991 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 992 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 993 | |
| 994 | self.adapter_agent.timeout_the_message = True |
| 995 | omci_cc.send_mib_upload(timeout=1.0, high_priority=False) |
| 996 | omci_cc.send_mib_upload(timeout=1.0, high_priority=False) |
| 997 | |
| 998 | self.assertEqual(omci_cc.lp_tx_queue_len, 1) |
| 999 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1000 | self.assertEqual(omci_cc.max_lp_tx_queue, 1) |
| 1001 | self.assertEqual(omci_cc.max_hp_tx_queue, 0) |
| 1002 | |
| 1003 | # Flush to get ready for next test (two queued and new max) |
| 1004 | omci_cc.flush() |
| 1005 | omci_cc.send_mib_upload(timeout=1.0, high_priority=False) |
| 1006 | omci_cc.send_mib_upload(timeout=1.0, high_priority=False) |
| 1007 | omci_cc.send_mib_upload(timeout=1.0, high_priority=False) |
| 1008 | |
| 1009 | self.assertEqual(omci_cc.lp_tx_queue_len, 2) |
| 1010 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1011 | self.assertEqual(omci_cc.max_lp_tx_queue, 2) |
| 1012 | self.assertEqual(omci_cc.max_hp_tx_queue, 0) |
| 1013 | |
| 1014 | def test_message_send_high_priority(self): |
| 1015 | # self.setup_one_of_each(timeout_messages=True) |
| 1016 | self.setup_one_of_each() |
| 1017 | |
| 1018 | omci_cc = self.onu_handler.omci_cc |
| 1019 | omci_cc.enabled = True |
| 1020 | snapshot = self._snapshot_stats() |
| 1021 | |
| 1022 | # MIB Upload |
| 1023 | d = omci_cc.send_mib_upload(high_priority=True) |
| 1024 | d.addCallback(self._check_stats, snapshot, 'lp_tx_queue_len', snapshot['lp_tx_queue_len']) |
| 1025 | d.addCallback(self._check_stats, snapshot, 'hp_tx_queue_len', snapshot['hp_tx_queue_len']) |
| 1026 | d.addCallback(self._check_stats, snapshot, 'max_lp_tx_queue', snapshot['max_lp_tx_queue']) |
| 1027 | d.addCallback(self._check_stats, snapshot, 'max_hp_tx_queue', snapshot['max_hp_tx_queue'] + 1) |
| 1028 | |
| 1029 | # Flush to get ready for next test (one frame queued) |
| 1030 | omci_cc.flush() |
| 1031 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1032 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1033 | |
| 1034 | self.adapter_agent.timeout_the_message = True |
| 1035 | omci_cc.send_mib_upload(high_priority=True) |
| 1036 | omci_cc.send_mib_upload(high_priority=True) |
| 1037 | |
| 1038 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1039 | self.assertEqual(omci_cc.hp_tx_queue_len, 1) |
| 1040 | self.assertEqual(omci_cc.max_lp_tx_queue, 0) |
| 1041 | self.assertEqual(omci_cc.max_hp_tx_queue, 1) |
| 1042 | |
| 1043 | # Flush to get ready for next test (two queued and new max) |
| 1044 | omci_cc.flush() |
| 1045 | omci_cc.send_mib_upload(high_priority=True) |
| 1046 | omci_cc.send_mib_upload(high_priority=True) |
| 1047 | omci_cc.send_mib_upload(high_priority=True) |
| 1048 | |
| 1049 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1050 | self.assertEqual(omci_cc.hp_tx_queue_len, 2) |
| 1051 | self.assertEqual(omci_cc.max_lp_tx_queue, 0) |
| 1052 | self.assertEqual(omci_cc.max_hp_tx_queue, 2) |
| 1053 | |
| 1054 | def test_message_send_and_cancel(self): |
| 1055 | global error_reason |
| 1056 | global successful |
| 1057 | # Do not send messages to adapter_agent |
| 1058 | self.setup_one_of_each(timeout_messages=True) |
| 1059 | |
| 1060 | omci_cc = self.onu_handler.omci_cc |
| 1061 | omci_cc.enabled = True |
| 1062 | |
| 1063 | def success(_results): |
| 1064 | global successful |
| 1065 | successful = True |
| 1066 | |
| 1067 | def failure(reason): |
| 1068 | global error_reason |
| 1069 | error_reason = reason |
| 1070 | |
| 1071 | def notCalled(reason): |
| 1072 | assert isinstance(reason, Failure), 'Should not be called with success' |
| 1073 | |
| 1074 | # Cancel one that is actively being sent |
| 1075 | d = omci_cc.send_mib_upload(high_priority=False) |
| 1076 | d.addCallbacks(success, failure) |
| 1077 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1078 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1079 | |
| 1080 | d.cancel() |
| 1081 | self.assertIsInstance(error_reason, Failure) |
| 1082 | self.assertFalse(successful) |
| 1083 | self.assertTrue(d.called) |
| 1084 | |
| 1085 | self.assertEqual(omci_cc.max_lp_tx_queue, 1) |
| 1086 | self.assertEqual(omci_cc.max_hp_tx_queue, 0) |
| 1087 | |
| 1088 | # Flush to get ready for next test (one running, one queued, cancel the |
| 1089 | # running one, so queued runs) |
| 1090 | omci_cc.flush() |
| 1091 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1092 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1093 | |
| 1094 | error_reason = None |
| 1095 | d1 = omci_cc.send_mib_upload(high_priority=False) |
| 1096 | d2 = omci_cc.send_mib_upload(high_priority=False) |
| 1097 | d1.addCallbacks(success, failure) |
| 1098 | d2.addCallbacks(notCalled, notCalled) |
| 1099 | self.assertEqual(omci_cc.lp_tx_queue_len, 1) |
| 1100 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1101 | |
| 1102 | d1.cancel() |
| 1103 | self.assertIsInstance(error_reason, Failure) |
| 1104 | self.assertFalse(successful) |
| 1105 | self.assertTrue(d1.called) |
| 1106 | self.assertFalse(d2.called) |
| 1107 | |
| 1108 | self.assertEqual(omci_cc.max_lp_tx_queue, 1) |
| 1109 | self.assertEqual(omci_cc.max_hp_tx_queue, 0) |
| 1110 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1111 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1112 | |
| 1113 | # Flush to get ready for next test (one running, one queued, cancel the queued one) |
| 1114 | |
| 1115 | omci_cc.flush() |
| 1116 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1117 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1118 | |
| 1119 | error_reason = None |
| 1120 | d3 = omci_cc.send_mib_upload(timeout=55, high_priority=False) |
| 1121 | d4 = omci_cc.send_mib_upload(timeout=55, high_priority=False) |
| 1122 | d5 = omci_cc.send_mib_upload(timeout=55, high_priority=False) |
| 1123 | d3.addCallbacks(notCalled, notCalled) |
| 1124 | d4.addCallbacks(success, failure) |
| 1125 | d5.addCallbacks(notCalled, notCalled) |
| 1126 | self.assertEqual(omci_cc.lp_tx_queue_len, 2) |
| 1127 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1128 | |
| 1129 | d4.cancel() |
| 1130 | self.assertIsInstance(error_reason, Failure) |
| 1131 | self.assertFalse(successful) |
| 1132 | self.assertFalse(d3.called) |
| 1133 | self.assertTrue(d4.called) |
| 1134 | self.assertFalse(d5.called) |
| 1135 | |
| 1136 | def test_message_send_low_and_high_priority(self): |
| 1137 | self.setup_one_of_each(timeout_messages=True) |
| 1138 | |
| 1139 | omci_cc = self.onu_handler.omci_cc |
| 1140 | omci_cc.enabled = True |
| 1141 | |
| 1142 | omci_cc.send_mib_reset(high_priority=False) |
| 1143 | omci_cc.send_mib_reset(high_priority=True) |
| 1144 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1145 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1146 | |
| 1147 | omci_cc.flush() |
| 1148 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1149 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1150 | |
| 1151 | omci_cc.send_mib_reset(high_priority=False) |
| 1152 | omci_cc.send_mib_reset(high_priority=True) |
| 1153 | omci_cc.send_mib_reset(high_priority=False) |
| 1154 | omci_cc.send_mib_reset(high_priority=True) |
| 1155 | self.assertEqual(omci_cc.lp_tx_queue_len, 1) |
| 1156 | self.assertEqual(omci_cc.hp_tx_queue_len, 1) |
| 1157 | |
| 1158 | def test_no_sw_download_and_mib_upload_at_same_time(self): |
| 1159 | # Section B.2.3 of ITU G.988-2017 specifies that a MIB |
| 1160 | # upload or software download at a given priority level |
| 1161 | # is not allowed while a similar action in the other |
| 1162 | # priority level is in progress. Relates to possible memory |
| 1163 | # consumption/needs on the ONU. |
| 1164 | # |
| 1165 | # OMCI_CC only checks if the commands are currently in |
| 1166 | # progress. ONU should reject messages if the upload/download |
| 1167 | # is in progress (but not an active request is in progress). |
| 1168 | |
| 1169 | self.setup_one_of_each(timeout_messages=True) |
| 1170 | omci_cc = self.onu_handler.omci_cc |
| 1171 | omci_cc.enabled = True |
| 1172 | |
| 1173 | mib_upload_msgs = [omci_cc.send_mib_upload, |
| 1174 | # omci_cc.send_mib_upload_next |
| 1175 | ] |
| 1176 | sw_download_msgs = [omci_cc.send_start_software_download, |
| 1177 | # omci_cc.send_download_section, |
| 1178 | # omci_cc.send_end_software_download |
| 1179 | ] |
| 1180 | |
| 1181 | for upload in mib_upload_msgs: |
| 1182 | for download in sw_download_msgs: |
| 1183 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1184 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1185 | |
| 1186 | upload(high_priority=False) |
| 1187 | download(1, 1, 1, high_priority=True) # Should stall send-next 50mS |
| 1188 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1189 | self.assertEqual(omci_cc.hp_tx_queue_len, 1) |
| 1190 | |
| 1191 | omci_cc.flush() |
| 1192 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1193 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1194 | |
| 1195 | upload(high_priority=True) |
| 1196 | download(1, 1, 1, high_priority=False) # Should stall send-next 50mS |
| 1197 | self.assertEqual(omci_cc.lp_tx_queue_len, 1) |
| 1198 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1199 | |
| 1200 | omci_cc.flush() |
| 1201 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1202 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1203 | |
| 1204 | download(1, 1, 1, high_priority=False) |
| 1205 | upload(high_priority=True) # Should stall send-next 50mS |
| 1206 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1207 | self.assertEqual(omci_cc.hp_tx_queue_len, 1) |
| 1208 | |
| 1209 | omci_cc.flush() |
| 1210 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1211 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1212 | |
| 1213 | download(1, 1, 1, high_priority=True) |
| 1214 | upload(high_priority=False) # Should stall send-next 50mS) |
| 1215 | self.assertEqual(omci_cc.lp_tx_queue_len, 1) |
| 1216 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1217 | |
| 1218 | omci_cc.flush() |
| 1219 | self.assertEqual(omci_cc.lp_tx_queue_len, 0) |
| 1220 | self.assertEqual(omci_cc.hp_tx_queue_len, 0) |
| 1221 | |
| 1222 | # Some more ideas for tests that we could add |
| 1223 | # Send explicit tid that is not valid |
| 1224 | # - Look at top of 'Send' method and test all the error conditions could may hit |
| 1225 | |
| 1226 | # Send multiple and have the OLT proxy throw an exception. Should call errback and |
| 1227 | # schedule remainder in queue to still tx. |
| 1228 | |
| 1229 | # Send a frame and then inject a response and test the RX logic out, including late |
| 1230 | # rx and retries by the OMCI_CC transmitter. |
| 1231 | |
| 1232 | |
| 1233 | if __name__ == '__main__': |
| 1234 | main() |