test_flow_builder_intra_evc   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 1066
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 700
dl 0
loc 1066
ccs 204
cts 204
cp 1
rs 9.9
c 0
b 0
f 0
wmc 13

5 Functions

Rating   Name   Duplication   Size   Complexity  
A test_flow_builder_default_table_groups() 0 3 1
B test_build_int_flows_intra_epl_inactive() 0 89 3
B test_build_int_flows_intra_evpl_diff_cvlans() 0 322 3
B test_build_int_flows_intra_evpl() 0 313 3
B test_build_int_flows_intra_epl() 0 311 3
1
"""Test flow_builder."""
2
3
# pylint: disable=too-many-lines
4
5 1
import pytest
6
7 1
from collections import defaultdict
8 1
from unittest.mock import MagicMock
9 1
from napps.kytos.telemetry_int.exceptions import FlowsNotFound
10 1
from napps.kytos.telemetry_int.managers.flow_builder import FlowBuilder
11 1
from napps.kytos.telemetry_int.managers.int import INTManager
12 1
from napps.kytos.telemetry_int.utils import get_cookie
13 1
from napps.kytos.telemetry_int.proxy_port import ProxyPort
14 1
from napps.kytos.telemetry_int import settings
15 1
from napps.kytos.telemetry_int.kytos_api_helper import _map_stored_flows_by_cookies
16 1
from kytos.lib.helpers import get_controller_mock, get_switch_mock, get_interface_mock
17 1
from kytos.core.common import EntityStatus
18
19
20 1
def test_flow_builder_default_table_groups() -> None:
21
    """test flow builder default table groups."""
22 1
    assert FlowBuilder().table_group == {"evpl": 2, "epl": 3, "evpl_vlan_range": 3}
23
24
25 1
def test_build_int_flows_intra_evpl(evcs_data, intra_evc_evpl_flows_data) -> None:
26
    """Test build INT flows intra EVPL.
27
28
                            +--------+
29
                            |        |
30
                         10 |      11|
31
                   +--------+--------v--+
32
                   |                    | 20
33
                1  |                    +-----+
34
     --------------+                    |     |
35
        (vlan 200) |                    |     |
36
                   |      sw1           |     |
37
               2   |                    |21   |
38
    ---------------+                    <-----+
39
        (vlan 200) |                    |
40
                   +--------------------+
41
    """
42 1
    controller = get_controller_mock()
43 1
    int_manager = INTManager(controller)
44 1
    get_proxy_port_or_raise = MagicMock()
45 1
    int_manager.get_proxy_port_or_raise = get_proxy_port_or_raise
46
47 1
    evc_id = "3766c105686749"
48 1
    dpid_a = "00:00:00:00:00:00:00:01"
49 1
    mock_switch_a = get_switch_mock(dpid_a, 0x04)
50 1
    mock_interface_a1 = get_interface_mock("s1-eth1", 1, mock_switch_a)
51 1
    mock_interface_a1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
52 1
    mock_interface_a10 = get_interface_mock("s1-eth10", 10, mock_switch_a)
53 1
    mock_interface_a1.metadata = {"proxy_port": mock_interface_a10.port_number}
54 1
    mock_interface_a10.status = EntityStatus.UP
55 1
    mock_interface_a11 = get_interface_mock("s1-eth11", 11, mock_switch_a)
56 1
    mock_interface_a11.status = EntityStatus.UP
57 1
    mock_interface_a10.metadata = {
58
        "looped": {
59
            "port_numbers": [
60
                mock_interface_a10.port_number,
61
                mock_interface_a11.port_number,
62
            ]
63
        }
64
    }
65
66 1
    mock_interface_z1 = get_interface_mock("s1-eth2", 1, mock_switch_a)
67 1
    mock_interface_z1.status = EntityStatus.UP
68 1
    mock_interface_z1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
69 1
    mock_interface_z20 = get_interface_mock("s1-eth20", 20, mock_switch_a)
70 1
    mock_interface_z1.metadata = {"proxy_port": mock_interface_z20.port_number}
71 1
    mock_interface_z20.status = EntityStatus.UP
72 1
    mock_interface_z21 = get_interface_mock("s1-eth21", 21, mock_switch_a)
73 1
    mock_interface_z21.status = EntityStatus.UP
74 1
    mock_interface_z20.metadata = {
75
        "looped": {
76
            "port_numbers": [
77
                mock_interface_z20.port_number,
78
                mock_interface_z21.port_number,
79
            ]
80
        }
81
    }
82
83 1
    mock_switch_a.get_interface_by_port_no = lambda port_no: {
84
        mock_interface_a10.port_number: mock_interface_a10,
85
        mock_interface_a11.port_number: mock_interface_a11,
86
        mock_interface_z20.port_number: mock_interface_z20,
87
        mock_interface_z21.port_number: mock_interface_z21,
88
    }[port_no]
89
90 1
    pp_a = ProxyPort(source=mock_interface_a10)
91 1
    assert pp_a.source == mock_interface_a10
92 1
    assert pp_a.destination == mock_interface_a11
93 1
    pp_z = ProxyPort(source=mock_interface_z20)
94 1
    assert pp_z.source == mock_interface_z20
95 1
    assert pp_z.destination == mock_interface_z21
96
97 1
    get_proxy_port_or_raise.side_effect = [pp_a, pp_z]
98 1
    evcs_data = {evc_id: evcs_data[evc_id]}
99 1
    evcs_data = int_manager._validate_map_enable_evcs(evcs_data)
100 1
    stored_flows = _map_stored_flows_by_cookies(intra_evc_evpl_flows_data)
101
102 1
    cookie = get_cookie(evc_id, settings.MEF_COOKIE_PREFIX)
103 1
    flows = FlowBuilder().build_int_flows(evcs_data, stored_flows)[cookie]
104
105 1
    n_expected_source_flows, n_expected_sink_flows = 3, 2
106 1
    assert len(flows) == (n_expected_source_flows + n_expected_sink_flows) * 2
107
108 1
    expected_uni_a_source_flows = [
109
        {
110
            "flow": {
111
                "owner": "telemetry_int",
112
                "cookie": int(0xA83766C105686749),
113
                "match": {"in_port": 1, "dl_vlan": 200, "dl_type": 2048, "nw_proto": 6},
114
                "table_id": 0,
115
                "table_group": "evpl",
116
                "priority": 20100,
117
                "idle_timeout": 0,
118
                "hard_timeout": 0,
119
                "instructions": [
120
                    {
121
                        "instruction_type": "apply_actions",
122
                        "actions": [{"action_type": "push_int"}],
123
                    },
124
                    {"instruction_type": "goto_table", "table_id": 2},
125
                ],
126
            }
127
        },
128
        {
129
            "flow": {
130
                "owner": "telemetry_int",
131
                "cookie": int(0xA83766C105686749),
132
                "match": {
133
                    "in_port": 1,
134
                    "dl_vlan": 200,
135
                    "dl_type": 2048,
136
                    "nw_proto": 17,
137
                },
138
                "table_id": 0,
139
                "table_group": "evpl",
140
                "priority": 20100,
141
                "idle_timeout": 0,
142
                "hard_timeout": 0,
143
                "instructions": [
144
                    {
145
                        "instruction_type": "apply_actions",
146
                        "actions": [{"action_type": "push_int"}],
147
                    },
148
                    {"instruction_type": "goto_table", "table_id": 2},
149
                ],
150
            }
151
        },
152
        {
153
            "flow": {
154
                "owner": "telemetry_int",
155
                "cookie": int(0xA83766C105686749),
156
                "match": {"in_port": 1, "dl_vlan": 200},
157
                "table_id": 2,
158
                "table_group": "evpl",
159
                "priority": 20000,
160
                "idle_timeout": 0,
161
                "hard_timeout": 0,
162
                "instructions": [
163
                    {
164
                        "instruction_type": "apply_actions",
165
                        "actions": [
166
                            {"action_type": "add_int_metadata"},
167
                            {"action_type": "set_vlan", "vlan_id": 200},
168
                            {"action_type": "output", "port": 20},
169
                        ],
170
                    }
171
                ],
172
            }
173
        },
174
    ]
175
176 1
    expected_uni_z_source_flows = [
177
        {
178
            "flow": {
179
                "owner": "telemetry_int",
180
                "cookie": int(0xA83766C105686749),
181
                "match": {"in_port": 2, "dl_vlan": 200, "dl_type": 2048, "nw_proto": 6},
182
                "table_id": 0,
183
                "table_group": "evpl",
184
                "priority": 20100,
185
                "idle_timeout": 0,
186
                "hard_timeout": 0,
187
                "instructions": [
188
                    {
189
                        "instruction_type": "apply_actions",
190
                        "actions": [{"action_type": "push_int"}],
191
                    },
192
                    {"instruction_type": "goto_table", "table_id": 2},
193
                ],
194
            }
195
        },
196
        {
197
            "flow": {
198
                "owner": "telemetry_int",
199
                "cookie": int(0xA83766C105686749),
200
                "match": {
201
                    "in_port": 2,
202
                    "dl_vlan": 200,
203
                    "dl_type": 2048,
204
                    "nw_proto": 17,
205
                },
206
                "table_id": 0,
207
                "table_group": "evpl",
208
                "priority": 20100,
209
                "idle_timeout": 0,
210
                "hard_timeout": 0,
211
                "instructions": [
212
                    {
213
                        "instruction_type": "apply_actions",
214
                        "actions": [{"action_type": "push_int"}],
215
                    },
216
                    {"instruction_type": "goto_table", "table_id": 2},
217
                ],
218
            }
219
        },
220
        {
221
            "flow": {
222
                "owner": "telemetry_int",
223
                "cookie": int(0xA83766C105686749),
224
                "match": {"in_port": 2, "dl_vlan": 200},
225
                "table_id": 2,
226
                "table_group": "evpl",
227
                "priority": 20000,
228
                "idle_timeout": 0,
229
                "hard_timeout": 0,
230
                "instructions": [
231
                    {
232
                        "instruction_type": "apply_actions",
233
                        "actions": [
234
                            {"action_type": "add_int_metadata"},
235
                            {"action_type": "set_vlan", "vlan_id": 200},
236
                            {"action_type": "output", "port": 10},
237
                        ],
238
                    }
239
                ],
240
            }
241
        },
242
    ]
243
244 1
    expected_uni_a_sink_flows = [
245
        {
246
            "flow": {
247
                "owner": "telemetry_int",
248
                "cookie": int(0xA83766C105686749),
249
                "match": {"in_port": 11, "dl_vlan": 200},
250
                "table_id": 0,
251
                "table_group": "evpl",
252
                "priority": 20000,
253
                "idle_timeout": 0,
254
                "hard_timeout": 0,
255
                "instructions": [
256
                    {
257
                        "instruction_type": "apply_actions",
258
                        "actions": [{"action_type": "send_report"}],
259
                    },
260
                    {"instruction_type": "goto_table", "table_id": 2},
261
                ],
262
            },
263
        },
264
        {
265
            "flow": {
266
                "owner": "telemetry_int",
267
                "cookie": int(0xA83766C105686749),
268
                "match": {"in_port": 11, "dl_vlan": 200},
269
                "table_id": 2,
270
                "table_group": "evpl",
271
                "priority": 20000,
272
                "idle_timeout": 0,
273
                "hard_timeout": 0,
274
                "instructions": [
275
                    {
276
                        "instruction_type": "apply_actions",
277
                        "actions": [
278
                            {"action_type": "pop_int"},
279
                            {"action_type": "output", "port": 1},
280
                        ],
281
                    }
282
                ],
283
            },
284
        },
285
    ]
286 1
    expected_uni_z_sink_flows = [
287
        {
288
            "flow": {
289
                "owner": "telemetry_int",
290
                "cookie": int(0xA83766C105686749),
291
                "match": {"in_port": 21, "dl_vlan": 200},
292
                "table_id": 0,
293
                "table_group": "evpl",
294
                "priority": 20000,
295
                "idle_timeout": 0,
296
                "hard_timeout": 0,
297
                "instructions": [
298
                    {
299
                        "instruction_type": "apply_actions",
300
                        "actions": [{"action_type": "send_report"}],
301
                    },
302
                    {"instruction_type": "goto_table", "table_id": 2},
303
                ],
304
            },
305
        },
306
        {
307
            "flow": {
308
                "owner": "telemetry_int",
309
                "cookie": int(0xA83766C105686749),
310
                "match": {"in_port": 21, "dl_vlan": 200},
311
                "table_id": 2,
312
                "table_group": "evpl",
313
                "priority": 20000,
314
                "idle_timeout": 0,
315
                "hard_timeout": 0,
316
                "instructions": [
317
                    {
318
                        "instruction_type": "apply_actions",
319
                        "actions": [
320
                            {"action_type": "pop_int"},
321
                            {"action_type": "output", "port": 2},
322
                        ],
323
                    }
324
                ],
325
            },
326
        },
327
    ]
328
329 1
    expected_flows = (
330
        expected_uni_a_source_flows
331
        + expected_uni_z_source_flows
332
        + expected_uni_z_sink_flows
333
        + expected_uni_a_sink_flows
334
    )
335
336 1
    for i, flow in enumerate(flows):
337 1
        assert (i, flow["flow"]) == (i, expected_flows[i]["flow"])
338
339
340 1
def test_build_int_flows_intra_evpl_diff_cvlans(
341
    evcs_data, intra_evc_evpl_flows_data
342
) -> None:
343
    """Test build INT flows intra EVPL different cvlans.
344
345
                            +--------+
346
                            |        |
347
                         10 |      11|
348
                   +--------+--------v--+
349
                   |                    | 20
350
                1  |                    +-----+
351
     --------------+                    |     |
352
        (vlan 100) |                    |     |
353
                   |      sw1           |     |
354
               2   |                    |21   |
355
    ---------------+                    <-----+
356
        (vlan 200) |                    |
357
                   +--------------------+
358
    """
359
360 1
    dpid = "00:00:00:00:00:00:00:01"
361
362
    # adapt conftest data accordingly since it was captured with c-vlans 200/200
363 1
    intra_evc_evpl_flows_data[dpid][0]["flow"]["match"]["dl_vlan"] = 100
364 1
    intra_evc_evpl_flows_data[dpid][1]["flow"]["actions"][0]["vlan_id"] = 100
365
366 1
    controller = get_controller_mock()
367 1
    int_manager = INTManager(controller)
368 1
    get_proxy_port_or_raise = MagicMock()
369 1
    int_manager.get_proxy_port_or_raise = get_proxy_port_or_raise
370
371 1
    evc_id = "3766c105686749"
372 1
    dpid_a = "00:00:00:00:00:00:00:01"
373 1
    mock_switch_a = get_switch_mock(dpid_a, 0x04)
374 1
    mock_interface_a1 = get_interface_mock("s1-eth1", 1, mock_switch_a)
375 1
    mock_interface_a1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
376 1
    mock_interface_a10 = get_interface_mock("s1-eth10", 10, mock_switch_a)
377 1
    mock_interface_a1.metadata = {"proxy_port": mock_interface_a10.port_number}
378 1
    mock_interface_a10.status = EntityStatus.UP
379 1
    mock_interface_a11 = get_interface_mock("s1-eth11", 11, mock_switch_a)
380 1
    mock_interface_a11.status = EntityStatus.UP
381 1
    mock_interface_a10.metadata = {
382
        "looped": {
383
            "port_numbers": [
384
                mock_interface_a10.port_number,
385
                mock_interface_a11.port_number,
386
            ]
387
        }
388
    }
389
390 1
    mock_interface_z1 = get_interface_mock("s1-eth2", 1, mock_switch_a)
391 1
    mock_interface_z1.status = EntityStatus.UP
392 1
    mock_interface_z1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
393 1
    mock_interface_z20 = get_interface_mock("s1-eth20", 20, mock_switch_a)
394 1
    mock_interface_z1.metadata = {"proxy_port": mock_interface_z20.port_number}
395 1
    mock_interface_z20.status = EntityStatus.UP
396 1
    mock_interface_z21 = get_interface_mock("s1-eth21", 21, mock_switch_a)
397 1
    mock_interface_z21.status = EntityStatus.UP
398 1
    mock_interface_z20.metadata = {
399
        "looped": {
400
            "port_numbers": [
401
                mock_interface_z20.port_number,
402
                mock_interface_z21.port_number,
403
            ]
404
        }
405
    }
406
407 1
    mock_switch_a.get_interface_by_port_no = lambda port_no: {
408
        mock_interface_a10.port_number: mock_interface_a10,
409
        mock_interface_a11.port_number: mock_interface_a11,
410
        mock_interface_z20.port_number: mock_interface_z20,
411
        mock_interface_z21.port_number: mock_interface_z21,
412
    }[port_no]
413
414 1
    pp_a = ProxyPort(source=mock_interface_a10)
415 1
    assert pp_a.source == mock_interface_a10
416 1
    assert pp_a.destination == mock_interface_a11
417 1
    pp_z = ProxyPort(source=mock_interface_z20)
418 1
    assert pp_z.source == mock_interface_z20
419 1
    assert pp_z.destination == mock_interface_z21
420
421 1
    get_proxy_port_or_raise.side_effect = [pp_a, pp_z]
422 1
    evcs_data = {evc_id: evcs_data[evc_id]}
423 1
    evcs_data = int_manager._validate_map_enable_evcs(evcs_data)
424 1
    stored_flows = _map_stored_flows_by_cookies(intra_evc_evpl_flows_data)
425
426 1
    cookie = get_cookie(evc_id, settings.MEF_COOKIE_PREFIX)
427 1
    flows = FlowBuilder().build_int_flows(evcs_data, stored_flows)[cookie]
428
429 1
    n_expected_source_flows, n_expected_sink_flows = 3, 2
430 1
    assert len(flows) == (n_expected_source_flows + n_expected_sink_flows) * 2
431
432 1
    expected_uni_a_source_flows = [
433
        {
434
            "flow": {
435
                "owner": "telemetry_int",
436
                "cookie": int(0xA83766C105686749),
437
                "match": {"in_port": 1, "dl_vlan": 100, "dl_type": 2048, "nw_proto": 6},
438
                "table_id": 0,
439
                "table_group": "evpl",
440
                "priority": 20100,
441
                "idle_timeout": 0,
442
                "hard_timeout": 0,
443
                "instructions": [
444
                    {
445
                        "instruction_type": "apply_actions",
446
                        "actions": [{"action_type": "push_int"}],
447
                    },
448
                    {"instruction_type": "goto_table", "table_id": 2},
449
                ],
450
            }
451
        },
452
        {
453
            "flow": {
454
                "owner": "telemetry_int",
455
                "cookie": int(0xA83766C105686749),
456
                "match": {
457
                    "in_port": 1,
458
                    "dl_vlan": 100,
459
                    "dl_type": 2048,
460
                    "nw_proto": 17,
461
                },
462
                "table_id": 0,
463
                "table_group": "evpl",
464
                "priority": 20100,
465
                "idle_timeout": 0,
466
                "hard_timeout": 0,
467
                "instructions": [
468
                    {
469
                        "instruction_type": "apply_actions",
470
                        "actions": [{"action_type": "push_int"}],
471
                    },
472
                    {"instruction_type": "goto_table", "table_id": 2},
473
                ],
474
            }
475
        },
476
        {
477
            "flow": {
478
                "owner": "telemetry_int",
479
                "cookie": int(0xA83766C105686749),
480
                "match": {"in_port": 1, "dl_vlan": 100},
481
                "table_id": 2,
482
                "table_group": "evpl",
483
                "priority": 20000,
484
                "idle_timeout": 0,
485
                "hard_timeout": 0,
486
                "instructions": [
487
                    {
488
                        "instruction_type": "apply_actions",
489
                        "actions": [
490
                            {"action_type": "add_int_metadata"},
491
                            {"action_type": "set_vlan", "vlan_id": 200},
492
                            {"action_type": "output", "port": 20},
493
                        ],
494
                    }
495
                ],
496
            }
497
        },
498
    ]
499
500 1
    expected_uni_z_source_flows = [
501
        {
502
            "flow": {
503
                "owner": "telemetry_int",
504
                "cookie": int(0xA83766C105686749),
505
                "match": {"in_port": 2, "dl_vlan": 200, "dl_type": 2048, "nw_proto": 6},
506
                "table_id": 0,
507
                "table_group": "evpl",
508
                "priority": 20100,
509
                "idle_timeout": 0,
510
                "hard_timeout": 0,
511
                "instructions": [
512
                    {
513
                        "instruction_type": "apply_actions",
514
                        "actions": [{"action_type": "push_int"}],
515
                    },
516
                    {"instruction_type": "goto_table", "table_id": 2},
517
                ],
518
            }
519
        },
520
        {
521
            "flow": {
522
                "owner": "telemetry_int",
523
                "cookie": int(0xA83766C105686749),
524
                "match": {
525
                    "in_port": 2,
526
                    "dl_vlan": 200,
527
                    "dl_type": 2048,
528
                    "nw_proto": 17,
529
                },
530
                "table_id": 0,
531
                "table_group": "evpl",
532
                "priority": 20100,
533
                "idle_timeout": 0,
534
                "hard_timeout": 0,
535
                "instructions": [
536
                    {
537
                        "instruction_type": "apply_actions",
538
                        "actions": [{"action_type": "push_int"}],
539
                    },
540
                    {"instruction_type": "goto_table", "table_id": 2},
541
                ],
542
            }
543
        },
544
        {
545
            "flow": {
546
                "owner": "telemetry_int",
547
                "cookie": int(0xA83766C105686749),
548
                "match": {"in_port": 2, "dl_vlan": 200},
549
                "table_id": 2,
550
                "table_group": "evpl",
551
                "priority": 20000,
552
                "idle_timeout": 0,
553
                "hard_timeout": 0,
554
                "instructions": [
555
                    {
556
                        "instruction_type": "apply_actions",
557
                        "actions": [
558
                            {"action_type": "add_int_metadata"},
559
                            {"action_type": "set_vlan", "vlan_id": 100},
560
                            {"action_type": "output", "port": 10},
561
                        ],
562
                    }
563
                ],
564
            }
565
        },
566
    ]
567
568 1
    expected_uni_a_sink_flows = [
569
        {
570
            "flow": {
571
                "owner": "telemetry_int",
572
                "cookie": int(0xA83766C105686749),
573
                "match": {"in_port": 11, "dl_vlan": 100},
574
                "table_id": 0,
575
                "table_group": "evpl",
576
                "priority": 20000,
577
                "idle_timeout": 0,
578
                "hard_timeout": 0,
579
                "instructions": [
580
                    {
581
                        "instruction_type": "apply_actions",
582
                        "actions": [{"action_type": "send_report"}],
583
                    },
584
                    {"instruction_type": "goto_table", "table_id": 2},
585
                ],
586
            },
587
        },
588
        {
589
            "flow": {
590
                "owner": "telemetry_int",
591
                "cookie": int(0xA83766C105686749),
592
                "match": {"in_port": 11, "dl_vlan": 100},
593
                "table_id": 2,
594
                "table_group": "evpl",
595
                "priority": 20000,
596
                "idle_timeout": 0,
597
                "hard_timeout": 0,
598
                "instructions": [
599
                    {
600
                        "instruction_type": "apply_actions",
601
                        "actions": [
602
                            {"action_type": "pop_int"},
603
                            {"action_type": "output", "port": 1},
604
                        ],
605
                    }
606
                ],
607
            },
608
        },
609
    ]
610 1
    expected_uni_z_sink_flows = [
611
        {
612
            "flow": {
613
                "owner": "telemetry_int",
614
                "cookie": int(0xA83766C105686749),
615
                "match": {"in_port": 21, "dl_vlan": 200},
616
                "table_id": 0,
617
                "table_group": "evpl",
618
                "priority": 20000,
619
                "idle_timeout": 0,
620
                "hard_timeout": 0,
621
                "instructions": [
622
                    {
623
                        "instruction_type": "apply_actions",
624
                        "actions": [{"action_type": "send_report"}],
625
                    },
626
                    {"instruction_type": "goto_table", "table_id": 2},
627
                ],
628
            },
629
        },
630
        {
631
            "flow": {
632
                "owner": "telemetry_int",
633
                "cookie": int(0xA83766C105686749),
634
                "match": {"in_port": 21, "dl_vlan": 200},
635
                "table_id": 2,
636
                "table_group": "evpl",
637
                "priority": 20000,
638
                "idle_timeout": 0,
639
                "hard_timeout": 0,
640
                "instructions": [
641
                    {
642
                        "instruction_type": "apply_actions",
643
                        "actions": [
644
                            {"action_type": "pop_int"},
645
                            {"action_type": "output", "port": 2},
646
                        ],
647
                    }
648
                ],
649
            },
650
        },
651
    ]
652
653 1
    expected_flows = (
654
        expected_uni_a_source_flows
655
        + expected_uni_z_source_flows
656
        + expected_uni_z_sink_flows
657
        + expected_uni_a_sink_flows
658
    )
659
660 1
    for i, flow in enumerate(flows):
661 1
        assert (i, flow["flow"]) == (i, expected_flows[i]["flow"])
662
663
664 1
def test_build_int_flows_intra_epl(evcs_data, intra_evc_epl_flows_data) -> None:
665
    """Test build INT flows intra EPL.
666
667
                            +--------+
668
                            |        |
669
                         10 |      11|
670
                   +--------+--------v--+
671
                   |                    | 20
672
                1  |                    +-----+
673
     --------------+                    |     |
674
                   |                    |     |
675
                   |      sw1           |     |
676
               2   |                    |21   |
677
    ---------------+                    <-----+
678
                   |                    |
679
                   +--------------------+
680
    """
681 1
    controller = get_controller_mock()
682 1
    int_manager = INTManager(controller)
683 1
    get_proxy_port_or_raise = MagicMock()
684 1
    int_manager.get_proxy_port_or_raise = get_proxy_port_or_raise
685
686 1
    evc_id = "3766c105686749"
687 1
    dpid_a = "00:00:00:00:00:00:00:01"
688 1
    mock_switch_a = get_switch_mock(dpid_a, 0x04)
689 1
    mock_interface_a1 = get_interface_mock("s1-eth1", 1, mock_switch_a)
690 1
    mock_interface_a1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
691 1
    mock_interface_a10 = get_interface_mock("s1-eth10", 10, mock_switch_a)
692 1
    mock_interface_a1.metadata = {"proxy_port": mock_interface_a10.port_number}
693 1
    mock_interface_a10.status = EntityStatus.UP
694 1
    mock_interface_a11 = get_interface_mock("s1-eth11", 11, mock_switch_a)
695 1
    mock_interface_a11.status = EntityStatus.UP
696 1
    mock_interface_a10.metadata = {
697
        "looped": {
698
            "port_numbers": [
699
                mock_interface_a10.port_number,
700
                mock_interface_a11.port_number,
701
            ]
702
        }
703
    }
704
705 1
    mock_interface_z1 = get_interface_mock("s1-eth2", 1, mock_switch_a)
706 1
    mock_interface_z1.status = EntityStatus.UP
707 1
    mock_interface_z1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
708 1
    mock_interface_z20 = get_interface_mock("s1-eth20", 20, mock_switch_a)
709 1
    mock_interface_z1.metadata = {"proxy_port": mock_interface_z20.port_number}
710 1
    mock_interface_z20.status = EntityStatus.UP
711 1
    mock_interface_z21 = get_interface_mock("s1-eth21", 21, mock_switch_a)
712 1
    mock_interface_z21.status = EntityStatus.UP
713 1
    mock_interface_z20.metadata = {
714
        "looped": {
715
            "port_numbers": [
716
                mock_interface_z20.port_number,
717
                mock_interface_z21.port_number,
718
            ]
719
        }
720
    }
721
722 1
    mock_switch_a.get_interface_by_port_no = lambda port_no: {
723
        mock_interface_a10.port_number: mock_interface_a10,
724
        mock_interface_a11.port_number: mock_interface_a11,
725
        mock_interface_z20.port_number: mock_interface_z20,
726
        mock_interface_z21.port_number: mock_interface_z21,
727
    }[port_no]
728
729 1
    pp_a = ProxyPort(source=mock_interface_a10)
730 1
    assert pp_a.source == mock_interface_a10
731 1
    assert pp_a.destination == mock_interface_a11
732 1
    pp_z = ProxyPort(source=mock_interface_z20)
733 1
    assert pp_z.source == mock_interface_z20
734 1
    assert pp_z.destination == mock_interface_z21
735
736 1
    get_proxy_port_or_raise.side_effect = [pp_a, pp_z]
737 1
    evcs_data[evc_id]["uni_a"].pop("tag")
738 1
    evcs_data[evc_id]["uni_z"].pop("tag")
739 1
    evcs_data = {evc_id: evcs_data[evc_id]}
740 1
    evcs_data = int_manager._validate_map_enable_evcs(evcs_data)
741 1
    stored_flows = _map_stored_flows_by_cookies(intra_evc_epl_flows_data)
742
743 1
    cookie = get_cookie(evc_id, settings.MEF_COOKIE_PREFIX)
744 1
    flows = FlowBuilder().build_int_flows(evcs_data, stored_flows)[cookie]
745
746 1
    n_expected_source_flows, n_expected_sink_flows = 3, 2
747 1
    assert len(flows) == (n_expected_source_flows + n_expected_sink_flows) * 2
748
749 1
    expected_uni_a_source_flows = [
750
        {
751
            "flow": {
752
                "owner": "telemetry_int",
753
                "cookie": int(0xA83766C105686749),
754
                "match": {"in_port": 1, "dl_type": 2048, "nw_proto": 6},
755
                "table_id": 0,
756
                "table_group": "epl",
757
                "priority": 10100,
758
                "idle_timeout": 0,
759
                "hard_timeout": 0,
760
                "instructions": [
761
                    {
762
                        "instruction_type": "apply_actions",
763
                        "actions": [{"action_type": "push_int"}],
764
                    },
765
                    {"instruction_type": "goto_table", "table_id": 3},
766
                ],
767
            }
768
        },
769
        {
770
            "flow": {
771
                "owner": "telemetry_int",
772
                "cookie": int(0xA83766C105686749),
773
                "match": {
774
                    "in_port": 1,
775
                    "dl_type": 2048,
776
                    "nw_proto": 17,
777
                },
778
                "table_id": 0,
779
                "table_group": "epl",
780
                "priority": 10100,
781
                "idle_timeout": 0,
782
                "hard_timeout": 0,
783
                "instructions": [
784
                    {
785
                        "instruction_type": "apply_actions",
786
                        "actions": [{"action_type": "push_int"}],
787
                    },
788
                    {"instruction_type": "goto_table", "table_id": 3},
789
                ],
790
            }
791
        },
792
        {
793
            "flow": {
794
                "owner": "telemetry_int",
795
                "cookie": int(0xA83766C105686749),
796
                "match": {"in_port": 1},
797
                "table_id": 3,
798
                "table_group": "epl",
799
                "priority": 10000,
800
                "idle_timeout": 0,
801
                "hard_timeout": 0,
802
                "instructions": [
803
                    {
804
                        "instruction_type": "apply_actions",
805
                        "actions": [
806
                            {"action_type": "add_int_metadata"},
807
                            {"action_type": "output", "port": 20},
808
                        ],
809
                    }
810
                ],
811
            }
812
        },
813
    ]
814
815 1
    expected_uni_z_source_flows = [
816
        {
817
            "flow": {
818
                "owner": "telemetry_int",
819
                "cookie": int(0xA83766C105686749),
820
                "match": {"in_port": 2, "dl_type": 2048, "nw_proto": 6},
821
                "table_id": 0,
822
                "table_group": "epl",
823
                "priority": 10100,
824
                "idle_timeout": 0,
825
                "hard_timeout": 0,
826
                "instructions": [
827
                    {
828
                        "instruction_type": "apply_actions",
829
                        "actions": [{"action_type": "push_int"}],
830
                    },
831
                    {"instruction_type": "goto_table", "table_id": 3},
832
                ],
833
            }
834
        },
835
        {
836
            "flow": {
837
                "owner": "telemetry_int",
838
                "cookie": int(0xA83766C105686749),
839
                "match": {
840
                    "in_port": 2,
841
                    "dl_type": 2048,
842
                    "nw_proto": 17,
843
                },
844
                "table_id": 0,
845
                "table_group": "epl",
846
                "priority": 10100,
847
                "idle_timeout": 0,
848
                "hard_timeout": 0,
849
                "instructions": [
850
                    {
851
                        "instruction_type": "apply_actions",
852
                        "actions": [{"action_type": "push_int"}],
853
                    },
854
                    {"instruction_type": "goto_table", "table_id": 3},
855
                ],
856
            }
857
        },
858
        {
859
            "flow": {
860
                "owner": "telemetry_int",
861
                "cookie": int(0xA83766C105686749),
862
                "match": {"in_port": 2},
863
                "table_id": 3,
864
                "table_group": "epl",
865
                "priority": 10000,
866
                "idle_timeout": 0,
867
                "hard_timeout": 0,
868
                "instructions": [
869
                    {
870
                        "instruction_type": "apply_actions",
871
                        "actions": [
872
                            {"action_type": "add_int_metadata"},
873
                            {"action_type": "output", "port": 10},
874
                        ],
875
                    }
876
                ],
877
            }
878
        },
879
    ]
880
881 1
    expected_uni_a_sink_flows = [
882
        {
883
            "flow": {
884
                "owner": "telemetry_int",
885
                "cookie": int(0xA83766C105686749),
886
                "match": {"in_port": 11},
887
                "table_id": 0,
888
                "table_group": "epl",
889
                "priority": 10000,
890
                "idle_timeout": 0,
891
                "hard_timeout": 0,
892
                "instructions": [
893
                    {
894
                        "instruction_type": "apply_actions",
895
                        "actions": [{"action_type": "send_report"}],
896
                    },
897
                    {"instruction_type": "goto_table", "table_id": 3},
898
                ],
899
            },
900
        },
901
        {
902
            "flow": {
903
                "owner": "telemetry_int",
904
                "cookie": int(0xA83766C105686749),
905
                "match": {"in_port": 11},
906
                "table_id": 3,
907
                "table_group": "epl",
908
                "priority": 10000,
909
                "idle_timeout": 0,
910
                "hard_timeout": 0,
911
                "instructions": [
912
                    {
913
                        "instruction_type": "apply_actions",
914
                        "actions": [
915
                            {"action_type": "pop_int"},
916
                            {"action_type": "output", "port": 1},
917
                        ],
918
                    }
919
                ],
920
            },
921
        },
922
    ]
923 1
    expected_uni_z_sink_flows = [
924
        {
925
            "flow": {
926
                "owner": "telemetry_int",
927
                "cookie": int(0xA83766C105686749),
928
                "match": {"in_port": 21},
929
                "table_id": 0,
930
                "table_group": "epl",
931
                "priority": 10000,
932
                "idle_timeout": 0,
933
                "hard_timeout": 0,
934
                "instructions": [
935
                    {
936
                        "instruction_type": "apply_actions",
937
                        "actions": [{"action_type": "send_report"}],
938
                    },
939
                    {"instruction_type": "goto_table", "table_id": 3},
940
                ],
941
            },
942
        },
943
        {
944
            "flow": {
945
                "owner": "telemetry_int",
946
                "cookie": int(0xA83766C105686749),
947
                "match": {"in_port": 21},
948
                "table_id": 3,
949
                "table_group": "epl",
950
                "priority": 10000,
951
                "idle_timeout": 0,
952
                "hard_timeout": 0,
953
                "instructions": [
954
                    {
955
                        "instruction_type": "apply_actions",
956
                        "actions": [
957
                            {"action_type": "pop_int"},
958
                            {"action_type": "output", "port": 2},
959
                        ],
960
                    }
961
                ],
962
            },
963
        },
964
    ]
965
966 1
    expected_flows = (
967
        expected_uni_a_source_flows
968
        + expected_uni_z_source_flows
969
        + expected_uni_z_sink_flows
970
        + expected_uni_a_sink_flows
971
    )
972
973 1
    for i, flow in enumerate(flows):
974 1
        assert (i, flow["flow"]) == (i, expected_flows[i]["flow"])
975
976
977 1
def test_build_int_flows_intra_epl_inactive(evcs_data) -> None:
978
    """Test build INT flows intra EPL inactive.
979
980
                            +--------+
981
                            |        |
982
                         10 |      11|
983
                   +--------+--------v--+
984
                   |                    | 20
985
                1  |                    +-----+
986
     --------------+                    |     |
987
                   |                    |     |
988
                   |      sw1           |     |
989
               2   |                    |21   |
990
    ---------------+                    <-----+
991
                   |                    |
992
                   +--------------------+
993
    """
994 1
    controller = get_controller_mock()
995 1
    int_manager = INTManager(controller)
996 1
    get_proxy_port_or_raise = MagicMock()
997 1
    int_manager.get_proxy_port_or_raise = get_proxy_port_or_raise
998
999 1
    evc_id = "3766c105686749"
1000 1
    dpid_a = "00:00:00:00:00:00:00:01"
1001 1
    mock_switch_a = get_switch_mock(dpid_a, 0x04)
1002 1
    mock_interface_a1 = get_interface_mock("s1-eth1", 1, mock_switch_a)
1003 1
    mock_interface_a1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
1004 1
    mock_interface_a10 = get_interface_mock("s1-eth10", 10, mock_switch_a)
1005 1
    mock_interface_a1.metadata = {"proxy_port": mock_interface_a10.port_number}
1006 1
    mock_interface_a10.status = EntityStatus.UP
1007 1
    mock_interface_a11 = get_interface_mock("s1-eth11", 11, mock_switch_a)
1008 1
    mock_interface_a11.status = EntityStatus.UP
1009 1
    mock_interface_a10.metadata = {
1010
        "looped": {
1011
            "port_numbers": [
1012
                mock_interface_a10.port_number,
1013
                mock_interface_a11.port_number,
1014
            ]
1015
        }
1016
    }
1017
1018 1
    mock_interface_z1 = get_interface_mock("s1-eth2", 1, mock_switch_a)
1019 1
    mock_interface_z1.status = EntityStatus.UP
1020 1
    mock_interface_z1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
1021 1
    mock_interface_z20 = get_interface_mock("s1-eth20", 20, mock_switch_a)
1022 1
    mock_interface_z1.metadata = {"proxy_port": mock_interface_z20.port_number}
1023 1
    mock_interface_z20.status = EntityStatus.UP
1024 1
    mock_interface_z21 = get_interface_mock("s1-eth21", 21, mock_switch_a)
1025 1
    mock_interface_z21.status = EntityStatus.UP
1026 1
    mock_interface_z20.metadata = {
1027
        "looped": {
1028
            "port_numbers": [
1029
                mock_interface_z20.port_number,
1030
                mock_interface_z21.port_number,
1031
            ]
1032
        }
1033
    }
1034
1035 1
    mock_switch_a.get_interface_by_port_no = lambda port_no: {
1036
        mock_interface_a10.port_number: mock_interface_a10,
1037
        mock_interface_a11.port_number: mock_interface_a11,
1038
        mock_interface_z20.port_number: mock_interface_z20,
1039
        mock_interface_z21.port_number: mock_interface_z21,
1040
    }[port_no]
1041
1042 1
    pp_a = ProxyPort(source=mock_interface_a10)
1043 1
    assert pp_a.source == mock_interface_a10
1044 1
    assert pp_a.destination == mock_interface_a11
1045 1
    pp_z = ProxyPort(source=mock_interface_z20)
1046 1
    assert pp_z.source == mock_interface_z20
1047 1
    assert pp_z.destination == mock_interface_z21
1048
1049 1
    get_proxy_port_or_raise.side_effect = [pp_a, pp_z]
1050 1
    evcs_data = {evc_id: evcs_data[evc_id]}
1051
1052
    # if it's an inactive EVC it shouldn't return any flows for this intra EPL
1053 1
    evcs_data[evc_id]["active"] = False
1054 1
    evcs_data = int_manager._validate_map_enable_evcs(evcs_data)
1055 1
    stored_flows = defaultdict(list)
1056 1
    cookie = get_cookie(evc_id, settings.MEF_COOKIE_PREFIX)
1057 1
    flows = FlowBuilder().build_int_flows(evcs_data, stored_flows)[cookie]
1058 1
    assert not flows
1059
1060
    # if it's active but there's no flows then it should raise FlowsNotFound
1061 1
    evcs_data[evc_id]["active"] = True
1062 1
    cookie = get_cookie(evc_id, settings.MEF_COOKIE_PREFIX)
1063 1
    with pytest.raises(FlowsNotFound):
1064 1
        int_manager._validate_evcs_stored_flows(
1065
            evcs_data, FlowBuilder().build_int_flows(evcs_data, stored_flows)
1066
        )
1067