Zack Williams | 41513bf | 2018-07-07 20:08:35 -0700 | [diff] [blame] | 1 | # Copyright 2017-present Open Networking Foundation |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | # you may not use this file except in compliance with the License. |
| 5 | # You may obtain a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 14 | |
| 15 | from unittest import main |
| 16 | |
| 17 | from mock import Mock |
| 18 | |
| 19 | from tests.utests.voltha.core.flow_helpers import FlowHelpers |
| 20 | from voltha.core import logical_device_agent |
| 21 | from voltha.core.flow_decomposer import * |
| 22 | from voltha.core.logical_device_agent import LogicalDeviceAgent |
| 23 | from voltha.protos.device_pb2 import Device, Port |
| 24 | from voltha.protos.logical_device_pb2 import LogicalDevice, LogicalPort |
| 25 | from voltha.protos.openflow_13_pb2 import Flows, FlowGroups |
| 26 | |
| 27 | |
| 28 | class test_multipon_logical_device_agent(FlowHelpers): |
| 29 | |
| 30 | def setup_mock_registry(self): |
| 31 | registry = Mock() |
| 32 | logical_device_agent.registry = registry |
| 33 | |
| 34 | def setUp(self): |
| 35 | self.setup_mock_registry() |
| 36 | |
| 37 | self.flows = Flows(items=[]) |
| 38 | self.groups = FlowGroups(items=[]) |
| 39 | self.ld_ports = [ |
| 40 | LogicalPort( |
| 41 | id='0', |
| 42 | device_id='olt', |
| 43 | device_port_no=0, |
| 44 | root_port=True, |
| 45 | ofp_port=ofp.ofp_port(port_no=0) |
| 46 | ), |
| 47 | LogicalPort( |
| 48 | id='101', |
| 49 | device_id='onu1', |
| 50 | device_port_no=0, |
| 51 | ofp_port=ofp.ofp_port(port_no=101) |
| 52 | ), |
| 53 | LogicalPort( |
| 54 | id='201', |
| 55 | device_id='onu2', |
| 56 | device_port_no=0, |
| 57 | ofp_port=ofp.ofp_port(port_no=201) |
| 58 | ) |
| 59 | ] |
| 60 | |
| 61 | self.devices = { |
| 62 | 'olt': Device( |
| 63 | id='olt', root=True, parent_id='id'), |
| 64 | 'onu1': Device( |
| 65 | id='onu1', parent_id='olt', parent_port_no=1, vlan=101), |
| 66 | 'onu2': Device( |
| 67 | id='onu2', parent_id='olt', parent_port_no=2, vlan=201), |
| 68 | } |
| 69 | |
| 70 | self.ports = { |
| 71 | 'olt': [ |
| 72 | Port(port_no=0, type=Port.ETHERNET_NNI, device_id='olt'), |
| 73 | Port(port_no=1, type=Port.PON_OLT, device_id='olt', |
| 74 | peers=[Port.PeerPort(device_id='onu1', port_no=1)]), |
| 75 | Port(port_no=2, type=Port.PON_OLT, device_id='olt', |
| 76 | peers=[Port.PeerPort(device_id='onu2', port_no=1)]) |
| 77 | ], |
| 78 | 'onu1': [ |
| 79 | Port(port_no=0, type=Port.ETHERNET_UNI, device_id='onu1'), |
| 80 | Port(port_no=1, type=Port.PON_ONU, device_id='onu1', |
| 81 | peers=[Port.PeerPort(device_id='olt', port_no=1)]) |
| 82 | ], |
| 83 | 'onu2': [ |
| 84 | Port(port_no=0, type=Port.ETHERNET_UNI, device_id='onu2'), |
| 85 | Port(port_no=1, type=Port.PON_ONU, device_id='onu2', |
| 86 | peers=[Port.PeerPort(device_id='olt', port_no=2)]) |
| 87 | ], |
| 88 | } |
| 89 | |
| 90 | self.device_flows = { |
| 91 | 'olt': Flows(), |
| 92 | 'onu1': Flows(), |
| 93 | 'onu2': Flows() |
| 94 | } |
| 95 | |
| 96 | self.device_groups = { |
| 97 | 'olt': FlowGroups(), |
| 98 | 'onu1': FlowGroups(), |
| 99 | 'onu2': FlowGroups() |
| 100 | } |
| 101 | |
| 102 | self.ld = LogicalDevice(id='id', root_device_id='olt') |
| 103 | |
| 104 | self.root_proxy = Mock() |
| 105 | def get_devices(path): |
| 106 | if path == '': |
| 107 | return self.devices.values() |
| 108 | if path.endswith('/ports'): |
| 109 | return self.ports[path[:-len('/ports')]] |
| 110 | elif path.find('/') == -1: |
| 111 | return self.devices[path] |
| 112 | else: |
| 113 | raise Exception( |
| 114 | 'Nothing to yield for path /devices/{}'.format(path)) |
| 115 | def update_devices(path, data): |
| 116 | if path.endswith('/flows'): |
| 117 | self.device_flows[path[:-len('/flows')]] = data |
| 118 | elif path.endswith('/flow_groups'): |
| 119 | self.device_groups[path[:-len('/flow_groups')]] = data |
| 120 | else: |
| 121 | raise NotImplementedError( |
| 122 | 'not handling path /devices/{}'.format(path)) |
| 123 | |
| 124 | self.root_proxy.get = lambda p: \ |
| 125 | get_devices(p[len('/devices/'):]) if p.startswith('/devices') \ |
| 126 | else None |
| 127 | self.root_proxy.update = lambda p, d: \ |
| 128 | update_devices(p[len('/devices/'):], d) \ |
| 129 | if p.startswith('/devices') \ |
| 130 | else None |
| 131 | self.ld_proxy = Mock() |
| 132 | self.ld_proxy.get = lambda p: \ |
| 133 | self.ld_ports if p == '/ports' else ( |
| 134 | self.ld if p == '/' else None |
| 135 | ) |
| 136 | |
| 137 | self.flows_proxy = Mock() |
| 138 | self.flows_proxy.get = lambda _: self.flows # always '/' path |
| 139 | def update_flows(_, flows): # always '/' path |
| 140 | self.flows = flows |
| 141 | self.flows_proxy.update = update_flows |
| 142 | |
| 143 | self.groups_proxy = Mock() |
| 144 | self.groups_proxy.get = lambda _: self.groups # always '/' path |
| 145 | def update_groups(_, groups): # always '/' path |
| 146 | self.groups = groups |
| 147 | self.groups_proxy.update = update_groups |
| 148 | |
| 149 | self.core = Mock() |
| 150 | self.core.get_proxy = lambda path: \ |
| 151 | self.root_proxy if path == '/' else ( |
| 152 | self.ld_proxy if path.endswith('id') else ( |
| 153 | self.flows_proxy if path.endswith('flows') else |
| 154 | self.groups_proxy |
| 155 | ) |
| 156 | ) |
| 157 | |
| 158 | self.lda = LogicalDeviceAgent(self.core, self.ld) |
| 159 | |
| 160 | def test_init(self): |
| 161 | pass # really just tests the setUp method |
| 162 | |
| 163 | # ~~~~~~~~~~~~~~~~~~~~ DEFAULT RULES AND ROUTES ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 164 | |
| 165 | def test_default_rules(self): |
| 166 | rules = self.lda.get_all_default_rules() |
| 167 | # no default olt downstream and no default group for each of 3 devs |
| 168 | self.assertEqual(len(rules['olt'][0]), 0) |
| 169 | self.assertEqual(len(rules['olt'][1]), 0) |
| 170 | self.assertEqual(len(rules['onu1'][0]), 3) |
| 171 | self.assertEqual(len(rules['onu1'][1]), 0) |
| 172 | self.assertEqual(len(rules['onu2'][0]), 3) |
| 173 | self.assertEqual(len(rules['onu2'][1]), 0) |
| 174 | |
| 175 | def test_routes(self): |
| 176 | self.lda.get_all_default_rules() # this will prepare the _routes |
| 177 | routes = self.lda._routes |
| 178 | self.assertEqual(len(routes), 4) |
| 179 | self.assertEqual(set(routes.keys()), |
| 180 | set([(0, 101), (0, 201), (101, 0), (201, 0)])) |
| 181 | |
| 182 | # verify all routes |
| 183 | route = routes[(0, 101)] |
| 184 | self.assertEqual(len(route), 2) |
| 185 | self.assertEqual(route[0].device, self.devices['olt']) |
| 186 | self.assertEqual(route[0].ingress_port, self.ports['olt'][0]) |
| 187 | self.assertEqual(route[0].egress_port, self.ports['olt'][1]) |
| 188 | self.assertEqual(route[1].device, self.devices['onu1']) |
| 189 | self.assertEqual(route[1].ingress_port, self.ports['onu1'][1]) |
| 190 | self.assertEqual(route[1].egress_port, self.ports['onu1'][0]) |
| 191 | |
| 192 | route = routes[(0, 201)] |
| 193 | self.assertEqual(len(route), 2) |
| 194 | self.assertEqual(route[0].device, self.devices['olt']) |
| 195 | self.assertEqual(route[0].ingress_port, self.ports['olt'][0]) |
| 196 | self.assertEqual(route[0].egress_port, self.ports['olt'][2]) |
| 197 | self.assertEqual(route[1].device, self.devices['onu2']) |
| 198 | self.assertEqual(route[1].ingress_port, self.ports['onu2'][1]) |
| 199 | self.assertEqual(route[1].egress_port, self.ports['onu2'][0]) |
| 200 | |
| 201 | route = routes[(101, 0)] |
| 202 | self.assertEqual(len(route), 2) |
| 203 | self.assertEqual(route[0].device, self.devices['onu1']) |
| 204 | self.assertEqual(route[0].ingress_port, self.ports['onu1'][0]) |
| 205 | self.assertEqual(route[0].egress_port, self.ports['onu1'][1]) |
| 206 | self.assertEqual(route[1].device, self.devices['olt']) |
| 207 | self.assertEqual(route[1].ingress_port, self.ports['olt'][1]) |
| 208 | self.assertEqual(route[1].egress_port, self.ports['olt'][0]) |
| 209 | |
| 210 | route = routes[(201, 0)] |
| 211 | self.assertEqual(len(route), 2) |
| 212 | self.assertEqual(route[0].device, self.devices['onu2']) |
| 213 | self.assertEqual(route[0].ingress_port, self.ports['onu2'][0]) |
| 214 | self.assertEqual(route[0].egress_port, self.ports['onu2'][1]) |
| 215 | self.assertEqual(route[1].device, self.devices['olt']) |
| 216 | self.assertEqual(route[1].ingress_port, self.ports['olt'][2]) |
| 217 | self.assertEqual(route[1].egress_port, self.ports['olt'][0]) |
| 218 | |
| 219 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~ FLOW DECOMP TESTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 220 | |
| 221 | def test_eapol_flow_decomp_case(self): |
| 222 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 223 | priority=1000, |
| 224 | match_fields=[in_port(201), eth_type(0x888e)], |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 225 | actions=[output(ofp.OFPP_CONTROLLER)], |
| 226 | meter_id=1, |
| 227 | metadata=32 |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 228 | )) |
| 229 | self.lda._flow_table_updated(self.flows) |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 230 | self.assertEqual(len(self.device_flows['olt'].items), 1) |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 231 | self.assertEqual(len(self.device_flows['onu1'].items), 3) |
Jonathan Hart | 5b43564 | 2018-08-20 08:50:05 -0700 | [diff] [blame] | 232 | self.assertEqual(len(self.device_flows['onu2'].items), 3) |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 233 | self.assertEqual(len(self.device_groups['olt'].items), 0) |
| 234 | self.assertEqual(len(self.device_groups['onu1'].items), 0) |
| 235 | self.assertEqual(len(self.device_groups['onu2'].items), 0) |
| 236 | |
| 237 | self.assertFlowsEqual(self.device_flows['olt'].items[0], mk_flow_stat( |
| 238 | priority=1000, |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 239 | match_fields=[in_port(2), eth_type(0x888e)], |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 240 | actions=[ |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 241 | output(2147483645) |
| 242 | ], |
| 243 | meter_id=1, |
| 244 | metadata=32 |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 245 | )) |
| 246 | |
| 247 | def test_multicast_group_with_one_subscriber(self): |
| 248 | self.lda.update_group_table(mk_multicast_group_mod( |
| 249 | group_id=2, |
| 250 | buckets=[ |
| 251 | ofp.ofp_bucket(actions=[ |
| 252 | pop_vlan(), |
| 253 | output(201) |
| 254 | ]), |
| 255 | ] |
| 256 | )) |
| 257 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 258 | priority=1000, |
| 259 | match_fields=[ |
| 260 | in_port(0), |
| 261 | eth_type(0x800), |
| 262 | vlan_vid(4096 + 140), |
| 263 | ipv4_dst(0xe60a0a0a) |
| 264 | ], |
| 265 | actions=[group(2)] |
| 266 | )) |
| 267 | self.lda._flow_table_updated(self.flows) |
| 268 | self.assertEqual(len(self.device_flows['olt'].items), 1) |
| 269 | self.assertEqual(len(self.device_flows['onu1'].items), 3) |
| 270 | self.assertEqual(len(self.device_flows['onu2'].items), 4) |
| 271 | self.assertEqual(len(self.device_groups['olt'].items), 0) |
| 272 | self.assertEqual(len(self.device_groups['onu1'].items), 0) |
| 273 | self.assertEqual(len(self.device_groups['onu2'].items), 0) |
| 274 | |
| 275 | self.assertFlowsEqual(self.device_flows['olt'].items[0], mk_flow_stat( |
| 276 | priority=1000, |
| 277 | match_fields=[in_port(0), eth_type(0x800), vlan_vid(4096 + 140), |
| 278 | ipv4_dst(0xe60a0a0a)], |
| 279 | actions=[ |
| 280 | pop_vlan(), |
Dimitris Benis | e95cf03 | 2018-08-30 00:27:51 +0300 | [diff] [blame] | 281 | output(1) |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 282 | ] |
| 283 | )) |
| 284 | self.assertFlowsEqual(self.device_flows['onu2'].items[3], mk_flow_stat( |
| 285 | priority=1000, |
| 286 | match_fields=[in_port(1), eth_type(0x800), ipv4_dst(0xe60a0a0a)], |
| 287 | actions=[ |
| 288 | output(0) |
| 289 | ] |
| 290 | )) |
| 291 | |
| 292 | def test_multicast_group_with_no_subscribers(self): |
| 293 | self.lda.update_group_table(mk_multicast_group_mod( |
| 294 | group_id=2, |
| 295 | buckets=[] # No subscribers |
| 296 | )) |
| 297 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 298 | priority=1000, |
| 299 | match_fields=[ |
| 300 | in_port(0), |
| 301 | eth_type(0x800), |
| 302 | vlan_vid(4096 + 140), |
| 303 | ipv4_dst(0xe60a0a0a) |
| 304 | ], |
| 305 | actions=[group(2)] |
| 306 | )) |
| 307 | self.lda._flow_table_updated(self.flows) |
Dimitris Benis | e95cf03 | 2018-08-30 00:27:51 +0300 | [diff] [blame] | 308 | self.assertEqual(len(self.device_flows['olt'].items), 0) |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 309 | self.assertEqual(len(self.device_flows['onu1'].items), 3) |
| 310 | self.assertEqual(len(self.device_flows['onu2'].items), 3) |
| 311 | self.assertEqual(len(self.device_flows['onu2'].items), 3) |
| 312 | self.assertEqual(len(self.device_groups['olt'].items), 0) |
| 313 | self.assertEqual(len(self.device_groups['onu1'].items), 0) |
| 314 | self.assertEqual(len(self.device_groups['onu2'].items), 0) |
| 315 | |
Dimitris Benis | e95cf03 | 2018-08-30 00:27:51 +0300 | [diff] [blame] | 316 | self.assertFlowNotInFlows(mk_flow_stat( |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 317 | priority=1000, |
| 318 | match_fields=[in_port(0), eth_type(0x800), vlan_vid(4096 + 140), |
| 319 | ipv4_dst(0xe60a0a0a)], |
| 320 | actions=[ |
| 321 | pop_vlan(), |
| 322 | output(2) |
| 323 | ] |
Dimitris Benis | e95cf03 | 2018-08-30 00:27:51 +0300 | [diff] [blame] | 324 | ), self.device_flows['olt']) |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 325 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ COMPLEX TESTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 326 | |
| 327 | def test_complex_flow_table_decomposition(self): |
| 328 | |
| 329 | # Various controller-bound rules |
| 330 | for _in_port in (101, 201): |
| 331 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 332 | priority=2000, |
| 333 | match_fields=[in_port(_in_port), eth_type(0x888e)], |
| 334 | actions=[ |
| 335 | push_vlan(0x8100), |
| 336 | set_field(vlan_vid(4096 + 4000)), |
| 337 | output(ofp.OFPP_CONTROLLER) |
| 338 | ] |
| 339 | )) |
| 340 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 341 | priority=1000, |
| 342 | match_fields=[in_port(_in_port), eth_type(0x800), ip_proto(2)], |
| 343 | actions=[output(ofp.OFPP_CONTROLLER)] |
| 344 | )) |
| 345 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 346 | priority=1000, |
| 347 | match_fields=[in_port(_in_port), eth_type(0x800), ip_proto(17), |
| 348 | udp_src(68), udp_dst(67)], |
| 349 | actions=[output(ofp.OFPP_CONTROLLER)] |
| 350 | )) |
| 351 | |
| 352 | # Multicast channels |
| 353 | mcast_setup = ( |
| 354 | (1, 0xe4010101, ()), |
| 355 | (2, 0xe4010102, (101,)), |
| 356 | (3, 0xe4010103, (201,)), |
| 357 | (4, 0xe4010104, (101, 201)), |
| 358 | ) |
| 359 | for group_id, mcast_addr, ports in mcast_setup: |
| 360 | self.lda.update_group_table(mk_multicast_group_mod( |
| 361 | group_id=group_id, |
| 362 | buckets=[ |
| 363 | ofp.ofp_bucket(actions=[ |
| 364 | pop_vlan(), |
| 365 | output(port) |
| 366 | ]) for port in ports |
| 367 | ])) |
| 368 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 369 | priority=1000, |
| 370 | match_fields=[ |
| 371 | in_port(0), |
| 372 | eth_type(0x800), |
| 373 | vlan_vid(4096 + 140), |
| 374 | ipv4_dst(mcast_addr) |
| 375 | ], |
| 376 | actions=[ |
| 377 | group(group_id) |
| 378 | ] |
| 379 | )) |
| 380 | |
| 381 | # Unicast channels for each subscriber |
| 382 | for port, c_vid in ((101, 101), (201, 201)): |
| 383 | |
| 384 | # Downstream flow 1 for nni to pon |
| 385 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 386 | priority=500, |
| 387 | match_fields=[ |
| 388 | in_port(0), |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 389 | vlan_vid(4096 + 1000) |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 390 | ], |
| 391 | actions=[pop_vlan()], |
| 392 | next_table_id=1 |
| 393 | )) |
| 394 | |
| 395 | # Downstream flow 2 |
| 396 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 397 | priority=500, |
| 398 | match_fields=[in_port(0), vlan_vid(4096 + c_vid)], |
| 399 | actions=[set_field(vlan_vid(4096 + 0)), output(port)] |
| 400 | )) |
| 401 | |
| 402 | # upstream flow 1 for the 0-tagged case |
| 403 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 404 | priority=500, |
| 405 | match_fields=[in_port(port), vlan_vid(4096 + 0)], |
| 406 | actions=[set_field(vlan_vid(4096 + c_vid))], |
| 407 | next_table_id=1 |
| 408 | )) |
| 409 | # ... and for the untagged case |
| 410 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 411 | priority=500, |
| 412 | match_fields=[in_port(port), vlan_vid(0)], |
| 413 | actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + c_vid))], |
| 414 | next_table_id=1 |
| 415 | )) |
| 416 | |
| 417 | # Upstream flow 2 for s-tag |
| 418 | self.lda.update_flow_table(mk_simple_flow_mod( |
| 419 | priority=500, |
| 420 | match_fields=[in_port(port), vlan_vid(4096 + c_vid)], |
| 421 | actions=[ |
| 422 | push_vlan(0x8100), |
| 423 | set_field(vlan_vid(4096 + 1000)), |
| 424 | output(0) |
| 425 | ] |
| 426 | )) |
| 427 | |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 428 | self.assertEqual(len(self.flows.items), 19) |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 429 | self.assertEqual(len(self.groups.items), 4) |
| 430 | |
| 431 | # trigger flow table decomposition |
| 432 | self.lda._flow_table_updated(self.flows) |
| 433 | |
| 434 | # now check device level flows |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 435 | self.assertEqual(len(self.device_flows['olt'].items), 10) |
Jonathan Hart | 5b43564 | 2018-08-20 08:50:05 -0700 | [diff] [blame] | 436 | self.assertEqual(len(self.device_flows['onu1'].items), 5) |
| 437 | self.assertEqual(len(self.device_flows['onu2'].items), 5) |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 438 | self.assertEqual(len(self.device_groups['olt'].items), 0) |
| 439 | self.assertEqual(len(self.device_groups['onu1'].items), 0) |
| 440 | self.assertEqual(len(self.device_groups['onu2'].items), 0) |
| 441 | |
| 442 | # Flows installed on the OLT |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 443 | self.assertFlowsEqual(self.device_flows['olt'].items[0], mk_flow_stat( |
| 444 | priority=2000, |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 445 | match_fields=[in_port(1), eth_type(0x888e)], |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 446 | actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 4000)), |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 447 | output(2147483645)] |
| 448 | )) |
| 449 | self.assertFlowsEqual(self.device_flows['olt'].items[1], mk_flow_stat( |
| 450 | priority=1000, |
| 451 | match_fields=[in_port(1), eth_type(0x800), ip_proto(2)], |
| 452 | actions=[output(2147483645)] |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 453 | )) |
| 454 | self.assertFlowsEqual(self.device_flows['olt'].items[2], mk_flow_stat( |
| 455 | priority=1000, |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 456 | match_fields=[in_port(1), eth_type(0x800), ip_proto(17), |
| 457 | udp_src(68), udp_dst(67)], |
| 458 | actions=[output(2147483645)] |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 459 | )) |
| 460 | self.assertFlowsEqual(self.device_flows['olt'].items[3], mk_flow_stat( |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 461 | priority=2000, |
| 462 | match_fields=[in_port(2), eth_type(0x888e)], |
| 463 | actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 4000)), |
| 464 | output(2147483645)] |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 465 | )) |
| 466 | self.assertFlowsEqual(self.device_flows['olt'].items[4], mk_flow_stat( |
| 467 | priority=1000, |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 468 | match_fields=[in_port(2), eth_type(0x800), ip_proto(2)], |
| 469 | actions=[output(2147483645)] |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 470 | )) |
| 471 | self.assertFlowsEqual(self.device_flows['olt'].items[5], mk_flow_stat( |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 472 | priority=1000, |
| 473 | match_fields=[in_port(2), eth_type(0x800), ip_proto(17), |
| 474 | udp_src(68), udp_dst(67)], |
| 475 | actions=[output(2147483645)] |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 476 | )) |
| 477 | self.assertFlowsEqual(self.device_flows['olt'].items[6], mk_flow_stat( |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 478 | priority=1000, |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 479 | match_fields=[in_port(0), eth_type(0x800), vlan_vid(4096 + 140), |
| 480 | ipv4_dst(0xE4010102)], |
| 481 | actions=[pop_vlan(), output(1)] |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 482 | )) |
| 483 | self.assertFlowsEqual(self.device_flows['olt'].items[9], mk_flow_stat( |
Gamze Abaka | 53cc0a2 | 2019-01-31 12:06:11 +0000 | [diff] [blame^] | 484 | priority=500, |
| 485 | match_fields=[in_port(0), vlan_vid(4096 + 1000)], |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 486 | actions=[pop_vlan(), output(2)] |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 487 | )) |
| 488 | |
| 489 | # Flows installed on the ONU1 |
| 490 | self.assertFlowsEqual(self.device_flows['onu1'].items[0], mk_flow_stat( |
| 491 | priority=500, |
| 492 | match_fields=[in_port(0), vlan_vid(4096 + 0)], |
| 493 | actions=[ |
| 494 | set_field(vlan_vid(4096 + 101)), output(1)] |
| 495 | )) |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 496 | self.assertFlowsEqual(self.device_flows['onu1'].items[2], mk_flow_stat( |
| 497 | priority=500, |
| 498 | match_fields=[in_port(1), vlan_vid(4096 + 101)], |
| 499 | actions=[set_field(vlan_vid(4096 + 0)), output(0)] |
| 500 | )) |
| 501 | self.assertFlowsEqual(self.device_flows['onu1'].items[1], mk_flow_stat( |
| 502 | priority=500, |
| 503 | match_fields=[in_port(0), vlan_vid(0)], |
| 504 | actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 101)), |
| 505 | output(1)] |
| 506 | )) |
| 507 | |
| 508 | # Flows installed on the ONU2 |
| 509 | self.assertFlowsEqual(self.device_flows['onu2'].items[0], mk_flow_stat( |
| 510 | priority=500, |
| 511 | match_fields=[in_port(0), vlan_vid(4096 + 0)], |
| 512 | actions=[ |
| 513 | set_field(vlan_vid(4096 + 201)), output(1)] |
| 514 | )) |
Chip Boling | 8be8384 | 2017-09-18 18:06:37 -0500 | [diff] [blame] | 515 | self.assertFlowsEqual(self.device_flows['onu2'].items[2], mk_flow_stat( |
| 516 | priority=500, |
| 517 | match_fields=[in_port(1), vlan_vid(4096 + 201)], |
| 518 | actions=[set_field(vlan_vid(4096 + 0)), output(0)] |
| 519 | )) |
| 520 | self.assertFlowsEqual(self.device_flows['onu2'].items[1], mk_flow_stat( |
| 521 | priority=500, |
| 522 | match_fields=[in_port(0), vlan_vid(0)], |
| 523 | actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 201)), |
| 524 | output(1)] |
| 525 | )) |
| 526 | |
| 527 | |
| 528 | if __name__ == '__main__': |
| 529 | main() |