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