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 | from unittest import TestCase, main |
| 18 | from nose.tools import assert_raises |
| 19 | from pyvoltha.adapters.extensions.omci.me_frame import * |
| 20 | from pyvoltha.adapters.extensions.omci.omci_me import * |
| 21 | from pyvoltha.adapters.extensions.omci.omci import * |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 22 | import codecs |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 23 | |
| 24 | |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 25 | def hexify(frame): |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 26 | """Return a hexadecimal string encoding of input buffer""" |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 27 | return codecs.encode(bytes(frame),'hex') |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 28 | |
| 29 | class TestSelectMeFrameGeneration(TestCase): |
| 30 | |
| 31 | def assertGeneratedFrameEquals(self, frame, ref): |
| 32 | assert isinstance(frame, Packet) |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 33 | serialized_hexified_frame = hexify(frame).upper() |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 34 | ref = ref.upper() |
| 35 | if serialized_hexified_frame != ref: |
| 36 | self.fail('Mismatch:\nReference:\n{}\nGenerated (bad):\n{}'.format( |
| 37 | ref, serialized_hexified_frame |
| 38 | )) |
| 39 | |
| 40 | def test_mib_reset_message_serialization(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 41 | ref = b'00004F0A000200000000000000000000' \ |
| 42 | b'00000000000000000000000000000000' \ |
| 43 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 44 | frame = OntDataFrame().mib_reset() |
| 45 | self.assertGeneratedFrameEquals(frame, ref) |
| 46 | |
| 47 | def test_create_gal_ethernet_profile(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 48 | ref = b'0000440A011000010030000000000000' \ |
| 49 | b'00000000000000000000000000000000' \ |
| 50 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 51 | frame = GalEthernetProfileFrame(1, max_gem_payload_size=48).create() |
| 52 | self.assertGeneratedFrameEquals(frame, ref) |
| 53 | |
| 54 | def test_set_tcont_1(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 55 | ref = b'0000480A010680008000040000000000' \ |
| 56 | b'00000000000000000000000000000000' \ |
| 57 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 58 | |
| 59 | frame = TcontFrame(0x8000, alloc_id=0x400).set() |
| 60 | self.assertGeneratedFrameEquals(frame, ref) |
| 61 | |
| 62 | def test_set_tcont_2(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 63 | ref = b'0000480A010680018000040100000000' \ |
| 64 | b'00000000000000000000000000000000' \ |
| 65 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 66 | |
| 67 | frame = TcontFrame(0x8001, alloc_id=0x401).set() |
| 68 | self.assertGeneratedFrameEquals(frame, ref) |
| 69 | |
| 70 | def test_create_8021p_mapper_service_profile(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 71 | ref = b'0000440A00828000ffffffffffffffff' \ |
| 72 | b'ffffffffffffffffffff000000000000' \ |
| 73 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 74 | frame = Ieee8021pMapperServiceProfileFrame(0x8000).create() |
| 75 | self.assertGeneratedFrameEquals(frame, ref) |
| 76 | |
| 77 | def test_create_mac_bridge_service_profile(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 78 | ref = b'0000440A002D02010001008000140002' \ |
| 79 | b'000f0001000000000000000000000000' \ |
| 80 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 81 | data = dict( |
| 82 | spanning_tree_ind=False, |
| 83 | learning_ind=True, |
| 84 | priority=0x8000, |
| 85 | max_age=20 * 256, |
| 86 | hello_time=2 * 256, |
| 87 | forward_delay=15 * 256, |
| 88 | unknown_mac_address_discard=True |
| 89 | ) |
| 90 | frame = MacBridgeServiceProfileFrame(0x201, attributes=data).create() |
| 91 | self.assertGeneratedFrameEquals(frame, ref) |
| 92 | |
| 93 | def test_create_gem_port_network_ctp(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 94 | ref = b'0000440A010C01000400800003010000' \ |
| 95 | b'00000000000000000000000000000000' \ |
| 96 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 97 | |
| 98 | data = dict( |
| 99 | port_id=0x400, |
| 100 | tcont_pointer=0x8000, |
| 101 | direction=3, |
| 102 | traffic_management_pointer_upstream=0x100 |
| 103 | ) |
| 104 | frame = GemPortNetworkCtpFrame(0x100, attributes=data).create() |
| 105 | self.assertGeneratedFrameEquals(frame, ref) |
| 106 | |
| 107 | # Also test direction as a string parameter |
| 108 | frame = GemPortNetworkCtpFrame(0x100, port_id=0x400, |
| 109 | tcont_id=0x8000, |
| 110 | direction='bi-directional', |
| 111 | upstream_tm=0x100).create() |
| 112 | self.assertGeneratedFrameEquals(frame, ref) |
| 113 | |
| 114 | def test_create_gem_inteworking_tp(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 115 | ref = b'0000440A010A80010100058000000000' \ |
| 116 | b'01000000000000000000000000000000' \ |
| 117 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 118 | frame = GemInterworkingTpFrame(0x8001, |
| 119 | gem_port_network_ctp_pointer=0x100, |
| 120 | interworking_option=5, |
| 121 | service_profile_pointer=0x8000, |
| 122 | interworking_tp_pointer=0x0, |
| 123 | gal_profile_pointer=0x1).create() |
| 124 | |
| 125 | self.assertGeneratedFrameEquals(frame, ref) |
| 126 | |
| 127 | def test_set_8021p_mapper_service_profile(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 128 | ref = b'0000480A008280007F80800100000000' \ |
| 129 | b'00000000000000000000000000000000' \ |
| 130 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 131 | ptrs = [0x8001, 0, 0, 0, 0, 0, 0, 0] |
| 132 | frame = Ieee8021pMapperServiceProfileFrame(0x8000, |
| 133 | interwork_tp_pointers=ptrs).set() |
| 134 | |
| 135 | self.assertGeneratedFrameEquals(frame, ref) |
| 136 | |
| 137 | ptrs = [0x8001, 0] |
| 138 | frame = Ieee8021pMapperServiceProfileFrame(0x8000, |
| 139 | interwork_tp_pointers=ptrs).set() |
| 140 | |
| 141 | self.assertGeneratedFrameEquals(frame, ref) |
| 142 | |
| 143 | def test_create_mac_bridge_port_configuration_data(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 144 | ref = b'0000440A002F21010201020380000000' \ |
| 145 | b'00000000000000000000000000000000' \ |
| 146 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 147 | |
| 148 | frame = MacBridgePortConfigurationDataFrame(0x2101, |
| 149 | bridge_id_pointer=0x201, |
| 150 | port_num=2, |
| 151 | tp_type=3, |
| 152 | tp_pointer=0x8000).create() |
| 153 | self.assertGeneratedFrameEquals(frame, ref) |
| 154 | |
| 155 | def test_create_vlan_tagging_filter_data(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 156 | ref = b'0000440A005421010400000000000000' \ |
| 157 | b'00000000000000000000000000000000' \ |
| 158 | b'100100000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 159 | frame = VlanTaggingFilterDataFrame(0x2101, |
| 160 | vlan_tcis=[0x400], |
| 161 | forward_operation=0x10).create() |
| 162 | self.assertGeneratedFrameEquals(frame, ref) |
| 163 | |
| 164 | def test_create_extended_vlan_tagging_operation_configuration_data(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 165 | ref = b'0000440A00AB02020A04010000000000' \ |
| 166 | b'00000000000000000000000000000000' \ |
| 167 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 168 | data = dict( |
| 169 | association_type=10, |
| 170 | associated_me_pointer=0x401 |
| 171 | ) |
| 172 | frame = \ |
| 173 | ExtendedVlanTaggingOperationConfigurationDataFrame(0x202, |
| 174 | attributes=data)\ |
| 175 | .create() |
| 176 | |
| 177 | self.assertGeneratedFrameEquals(frame, ref) |
| 178 | |
| 179 | def test_set_extended_vlan_tagging_operation_configuration_data(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 180 | ref = b'0000480A00AB02023800810081000000' \ |
| 181 | b'00000000000000000000000000000000' \ |
| 182 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 183 | data = dict( |
| 184 | input_tpid=0x8100, |
| 185 | output_tpid=0x8100, |
| 186 | downstream_mode=0, # inverse of upstream |
| 187 | ) |
| 188 | frame = \ |
| 189 | ExtendedVlanTaggingOperationConfigurationDataFrame(0x202, |
| 190 | attributes=data)\ |
| 191 | .set() |
| 192 | |
| 193 | self.assertGeneratedFrameEquals(frame, ref) |
| 194 | |
| 195 | def test_set_extended_vlan_tagging_1(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 196 | ref = b'0000480A00AB02020400f00000008200' \ |
| 197 | b'5000402f000000082004000000000000' \ |
| 198 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 199 | data = dict( |
| 200 | received_frame_vlan_tagging_operation_table=\ |
| 201 | VlanTaggingOperation( |
| 202 | filter_outer_priority=15, |
| 203 | filter_inner_priority=8, |
| 204 | filter_inner_vid=1024, |
| 205 | filter_inner_tpid_de=5, |
| 206 | filter_ether_type=0, |
| 207 | treatment_tags_to_remove=1, |
| 208 | pad3=2, |
| 209 | treatment_outer_priority=15, |
| 210 | treatment_inner_priority=8, |
| 211 | treatment_inner_vid=1024, |
| 212 | treatment_inner_tpid_de=4 |
| 213 | ) |
| 214 | ) |
| 215 | frame = \ |
| 216 | ExtendedVlanTaggingOperationConfigurationDataFrame(0x202, |
| 217 | attributes=data)\ |
| 218 | .set() |
| 219 | |
| 220 | self.assertGeneratedFrameEquals(frame, ref) |
| 221 | |
| 222 | def test_set_extended_vlan_tagging_2(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 223 | ref = b'0000480A00AB02020400F00000008200' \ |
| 224 | b'd000402f00000008200c000000000000' \ |
| 225 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 226 | data = dict( |
| 227 | received_frame_vlan_tagging_operation_table= |
| 228 | VlanTaggingOperation( |
| 229 | filter_outer_priority=15, |
| 230 | filter_inner_priority=8, |
| 231 | filter_inner_vid=1025, |
| 232 | filter_inner_tpid_de=5, |
| 233 | filter_ether_type=0, |
| 234 | treatment_tags_to_remove=1, |
| 235 | pad3=2, |
| 236 | treatment_outer_priority=15, |
| 237 | treatment_inner_priority=8, |
| 238 | treatment_inner_vid=1025, |
| 239 | treatment_inner_tpid_de=4 |
| 240 | ) |
| 241 | ) |
| 242 | |
| 243 | frame = \ |
| 244 | ExtendedVlanTaggingOperationConfigurationDataFrame(0x202, |
| 245 | attributes=data)\ |
| 246 | .set() |
| 247 | |
| 248 | self.assertGeneratedFrameEquals(frame, ref) |
| 249 | |
| 250 | def test_create_mac_bridge_port_configuration_data2(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 251 | ref = b'0000440A002F02010201010b04010000' \ |
| 252 | b'00000000000000000000000000000000' \ |
| 253 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 254 | data = dict( |
| 255 | bridge_id_pointer=0x201, |
| 256 | encapsulation_methods=0, |
| 257 | port_num=1, |
| 258 | port_priority=0, |
| 259 | port_path_cost=0, |
| 260 | port_spanning_tree_in=0, |
| 261 | lan_fcs_ind=0, |
| 262 | tp_type=11, |
| 263 | tp_pointer=0x401, |
| 264 | mac_learning_depth=0 |
| 265 | ) |
| 266 | frame = MacBridgePortConfigurationDataFrame(0x201, |
| 267 | attributes=data).create() |
| 268 | |
| 269 | self.assertGeneratedFrameEquals(frame, ref) |
| 270 | |
| 271 | def test_set_pptp_ethernet_uni_frame(self): |
Zack Williams | 84a71e9 | 2019-11-15 09:00:19 -0700 | [diff] [blame^] | 272 | ref = b'0000480A000B020109000005EE000000' \ |
| 273 | b'00000000000000000000000000000000' \ |
| 274 | b'000000000000000000000028' |
Chip Boling | 67b674a | 2019-02-08 11:42:18 -0600 | [diff] [blame] | 275 | data = dict( |
| 276 | administrative_state=0, # 0 - Unlock |
| 277 | max_frame_size=1518 # two-octet field |
| 278 | ) |
| 279 | frame = PptpEthernetUniFrame(0x201, |
| 280 | attributes=data).set() |
| 281 | |
| 282 | self.assertGeneratedFrameEquals(frame, ref) |
| 283 | |
| 284 | def test_constraint_errors(self): |
| 285 | self.assertTrue(True) # TODO Also test some attribute constraint failures |
| 286 | |
| 287 | def test_mib_upload_next(self): |
| 288 | # Test for VOL-649 error. SCAPY was only originally coded for a 'get' |
| 289 | # action (8-bit MIB Data Sync value) but MIB Upload Next commands have |
| 290 | # a 16-bit field. |
| 291 | # |
| 292 | # 255 and less always worked |
| 293 | OntDataFrame(sequence_number=0).mib_upload_next() |
| 294 | OntDataFrame(sequence_number=255).mib_upload_next() |
| 295 | # But not 256+ |
| 296 | OntDataFrame(sequence_number=256).mib_upload_next() |
| 297 | OntDataFrame(sequence_number=1000).mib_upload_next() |
| 298 | OntDataFrame(sequence_number=0xFFFE).mib_upload_next() |
| 299 | |
| 300 | # Also test the optional arguments for the other actions |
| 301 | OntDataFrame().get() |
| 302 | OntDataFrame(mib_data_sync=4).set() |
| 303 | OntDataFrame().mib_reset() |
| 304 | OntDataFrame().mib_upload() |
| 305 | # OntDataFrame(ignore_arc=True).get_all_alarms() Not yet coded |
| 306 | # OntDataFrame(ignore_arc=False).get_all_alarms() Not yet coded |
| 307 | |
| 308 | # Range/type checks |
| 309 | assert_raises(ValueError, OntDataFrame, mib_data_sync=-1) |
| 310 | assert_raises(ValueError, OntDataFrame, mib_data_sync=256) |
| 311 | assert_raises(ValueError, OntDataFrame, sequence_number=-1) |
| 312 | assert_raises(ValueError, OntDataFrame, sequence_number=0x10000) |
| 313 | assert_raises(TypeError, OntDataFrame, ignore_arc=123) |
| 314 | |
| 315 | |
| 316 | if __name__ == '__main__': |
| 317 | main() |
| 318 | |