TestMain.test_tracepath()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 33
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 25
nop 2
dl 0
loc 33
ccs 17
cts 17
cp 1
crap 1
rs 9.28
c 0
b 0
f 0
1
"""Module to test the main napp file."""
2 1
import asyncio
3 1
import pytest
4 1
from unittest.mock import patch, MagicMock
5
6 1
from kytos.core.interface import Interface
7 1
from kytos.lib.helpers import (
8
    get_interface_mock,
9
    get_switch_mock,
10
    get_controller_mock,
11
    get_link_mock,
12
    get_test_client,
13
)
14 1
from kytos.core.rest_api import HTTPException
15
16
17
# pylint: disable=too-many-public-methods, too-many-lines
18 1
class TestMain:
19
    """Test the Main class."""
20
21 1
    def setup_method(self):
22
        """Execute steps before each tests."""
23
        # The decorator run_on_thread is patched, so methods that listen
24
        # for events do not run on threads while tested.
25
        # Decorators have to be patched before the methods that are
26
        # decorated with them are imported.
27 1
        patch("kytos.core.helpers.run_on_thread", lambda x: x).start()
28
        # pylint: disable=import-outside-toplevel
29 1
        from napps.amlight.sdntrace_cp.main import Main
30
31 1
        controller = get_controller_mock()
32 1
        self.napp = Main(controller)
33
34 1
        sw1 = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
35 1
        intf_sw1 = get_interface_mock("eth1", 1, sw1)
36 1
        intf_sw1.link = None
37 1
        sw1.get_interface_by_port_no.return_value = intf_sw1
38 1
        sw2 = get_switch_mock("00:00:00:00:00:00:00:02", 0x04)
39 1
        intf_sw2 = get_interface_mock("eth1", 1, sw2)
40 1
        intf_sw2.link = None
41 1
        sw2.get_interface_by_port_no.return_value = intf_sw2
42 1
        self.napp.controller.switches = {sw1.dpid: sw1, sw2.dpid: sw2}
43 1
        self.api_client = get_test_client(controller, self.napp)
44 1
        self.base_endpoint = "amlight/sdntrace_cp/v1"
45 1
        self.trace_endpoint = f"{self.base_endpoint}/trace"
46 1
        self.traces_endpoint = f"{self.base_endpoint}/traces"
47
48 1
    @patch("napps.amlight.sdntrace_cp.main.Main.match_and_apply")
49 1
    def test_trace_step(self, mock_flow_match):
50
        """Test trace_step success result."""
51 1
        mock_flow_match.return_value = ["1"], ["entries"], 1
52 1
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
53
54 1
        mock_interface = Interface("interface A", 1, MagicMock())
55 1
        mock_interface.address = "00:00:00:00:00:00:00:01"
56
57 1
        iface1 = get_interface_mock(
58
            "", 1, get_switch_mock("00:00:00:00:00:00:00:01")
59
        )
60 1
        iface2 = get_interface_mock(
61
            "", 2, get_switch_mock("00:00:00:00:00:00:00:02")
62
        )
63 1
        mock_interface.link = get_link_mock(iface1, iface2)
64 1
        mock_interface.link.endpoint_a.port_number = 1
65 1
        mock_interface.link.endpoint_a.port_number = 2
66
67
        # Patch for utils.find_endpoint
68 1
        switch.get_interface_by_port_no.return_value = mock_interface
69
70 1
        entries = MagicMock()
71
72 1
        stored_flows = {
73
            "flow": {
74
                "table_id": 0,
75
                "cookie": 84114964,
76
                "hard_timeout": 0,
77
                "idle_timeout": 0,
78
                "priority": 10,
79
            },
80
            "flow_id": 1,
81
            "state": "installed",
82
            "switch": "00:00:00:00:00:00:00:01",
83
        }
84
85 1
        stored_flows_arg = {
86
            "00:00:00:00:00:00:00:01": [stored_flows]
87
        }
88
89 1
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
90
91 1
        mock_flow_match.assert_called_once()
92 1
        assert result == {
93
                    "dpid": "00:00:00:00:00:00:00:01",
94
                    "in_port": 2,
95
                    "out_port": 1,
96
                    "entries": ["entries"],
97
                }
98
99 1
    @patch("napps.amlight.sdntrace_cp.main.Main.match_and_apply")
100 1
    def test_trace_step__no_endpoint(self, mock_flow_match):
101
        """Test trace_step without endpoints available for switch/port."""
102 1
        mock_flow_match.return_value = ["1"], ["entries"], 1
103 1
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
104
105 1
        mock_interface = Interface("interface A", 1, MagicMock())
106 1
        mock_interface.address = "00:00:00:00:00:00:00:01"
107 1
        mock_interface.link = None
108
109
        # Patch for utils.find_endpoint
110 1
        switch.get_interface_by_port_no.return_value = mock_interface
111
112 1
        entries = MagicMock()
113
114 1
        stored_flows = {
115
            "flow": {
116
                "table_id": 0,
117
                "cookie": 84114964,
118
                "hard_timeout": 0,
119
                "idle_timeout": 0,
120
                "priority": 10,
121
            },
122
            "flow_id": 1,
123
            "state": "installed",
124
            "switch": "00:00:00:00:00:00:00:01",
125
        }
126
127 1
        stored_flows_arg = {
128
            "00:00:00:00:00:00:00:01": [stored_flows]
129
        }
130
131 1
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
132
133 1
        mock_flow_match.assert_called_once()
134 1
        assert result == {"entries": ["entries"], "out_port": 1}
135
136 1
    def test_trace_step__no_flow(self):
137
        """Test trace_step without flows for the switch."""
138 1
        switch = get_switch_mock("00:00:00:00:00:00:00:01")
139 1
        entries = MagicMock()
140
141 1
        stored_flows = {
142
            "flow": {
143
                "table_id": 0,
144
                "cookie": 84114964,
145
                "hard_timeout": 0,
146
                "idle_timeout": 0,
147
                "priority": 10,
148
            },
149
            "flow_id": 1,
150
            "state": "installed",
151
            "switch": "00:00:00:00:00:00:00:01",
152
        }
153
154 1
        stored_flows_arg = {
155
            "00:00:00:00:00:00:00:01": [stored_flows]
156
        }
157
158 1
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
159 1
        assert result is None
160
161 1
    @patch("napps.amlight.sdntrace_cp.main.Main.trace_step")
162 1
    def test_tracepath(self, mock_trace_step):
163
        """Test tracepath with success result."""
164 1
        eth = {"dl_vlan": 100}
165 1
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
166 1
        switch = {"switch": dpid, "eth": eth}
167 1
        entries = {"trace": switch}
168 1
        mock_trace_step.return_value = {
169
            "dpid": "00:00:00:00:00:00:00:02",
170
            "in_port": 2,
171
            "out_port": 3,
172
            "entries": entries,
173
        }
174
175 1
        stored_flows_arg = {
176
            "00:00:00:00:00:00:00:01": [],
177
            "00:00:00:00:00:00:00:02": [],
178
        }
179
180 1
        result = self.napp.tracepath(
181
                                        entries["trace"]["switch"],
182
                                        stored_flows_arg
183
                                    )
184
185 1
        assert result[0]["in"]["dpid"] == "00:00:00:00:00:00:00:01"
186 1
        assert result[0]["in"]["port"] == 1
187 1
        assert result[0]["in"]["type"] == "starting"
188 1
        assert result[0]["out"]["port"] == 3
189
190 1
        assert result[1]["in"]["dpid"] == "00:00:00:00:00:00:00:02"
191 1
        assert result[1]["in"]["port"] == 2
192 1
        assert result[1]["in"]["type"] == "intermediary"
193 1
        assert result[1]["out"]["port"] == 3
194
195 1
    @patch("napps.amlight.sdntrace_cp.main.Main.trace_step")
196 1
    def test_tracepath_loop(self, mock_trace_step):
197
        """Test tracepath with success result."""
198 1
        eth = {"dl_vlan": 100}
199 1
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
200 1
        switch = {"switch": dpid, "eth": eth}
201 1
        entries = {"trace": switch}
202 1
        mock_trace_step.return_value = {
203
            "dpid": "00:00:00:00:00:00:00:01",
204
            "in_port": 1,
205
            "out_port": 1,
206
            "entries": entries,
207
        }
208
209 1
        result = self.napp.tracepath(
210
                                        entries["trace"]["switch"],
211
                                        {}
212
                                    )
213 1
        assert len(result) == 2
214
        # input interface = output interface
215 1
        assert result[0]["in"]["type"] == "starting"
216 1
        assert result[1]["in"]["type"] == "loop"
217
218 1
    def test_has_loop(self):
219
        """Test has_loop to detect a tracepath with loop."""
220 1
        trace_result = [
221
            {
222
                "in": {
223
                    "dpid": "00:00:00:00:00:00:00:01",
224
                    "port": 2,
225
                },
226
                "out": {
227
                    "port": 1,
228
                },
229
            },
230
            {
231
                "in": {
232
                    "dpid": "00:00:00:00:00:00:00:03",
233
                    "port": 2,
234
                },
235
                "out": {
236
                    "port": 1,
237
                },
238
            },
239
            {
240
                "in": {
241
                    "dpid": "00:00:00:00:00:00:00:03",
242
                    "port": 3,
243
                },
244
                "out": {
245
                    "port": 1,
246
                },
247
            },
248
            {
249
                "in": {
250
                    "dpid": "00:00:00:00:00:00:00:03",
251
                    "port": 3,
252
                },
253
                "out": {
254
                    "port": 1,
255
                },
256
            },
257
        ]
258 1
        trace_step = {
259
            "dpid": "00:00:00:00:00:00:00:03",
260
            "port": 3,
261
        }
262
263 1
        result = self.napp.has_loop(trace_step, trace_result)
264 1
        assert result
265
266 1
    def test_has_loop__fail(self):
267
        """Test has_loop to detect a tracepath with loop."""
268 1
        trace_result = [
269
            {
270
                "in": {
271
                    "dpid": "00:00:00:00:00:00:00:01",
272
                    "port": 2,
273
                },
274
                "out": {
275
                    "port": 1,
276
                },
277
            },
278
            {
279
                "in": {
280
                    "dpid": "00:00:00:00:00:00:00:02",
281
                    "port": 2,
282
                },
283
                "out": {
284
                    "port": 1,
285
                },
286
            },
287
        ]
288 1
        trace_step = {
289
            "dpid": "00:00:00:00:00:00:00:03",
290
            "port": 2,
291
        }
292
293 1
        result = self.napp.has_loop(trace_step, trace_result)
294 1
        assert not result
295
296 1 View Code Duplication
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
297 1
    async def test_trace(self, mock_stored_flows):
298
        """Test trace rest call."""
299 1
        self.napp.controller.loop = asyncio.get_running_loop()
300 1
        payload = {
301
            "trace": {
302
                "switch": {
303
                    "dpid": "00:00:00:00:00:00:00:01",
304
                    "in_port": 1
305
                    },
306
                "eth": {"dl_vlan": 100},
307
            }
308
        }
309 1
        stored_flows = {
310
                "flow": {
311
                    "table_id": 0,
312
                    "cookie": 84114964,
313
                    "hard_timeout": 0,
314
                    "idle_timeout": 0,
315
                    "priority": 10,
316
                    "match": {"dl_vlan": 100, "in_port": 1},
317
                    "actions": [
318
                        {"action_type": "push_vlan"},
319
                        {"action_type": "set_vlan", "vlan_id": 200},
320
                        {"action_type": "output", "port": 2}
321
                    ],
322
                },
323
                "flow_id": 1,
324
                "state": "installed",
325
                "switch": "00:00:00:00:00:00:00:01",
326
        }
327 1
        mock_stored_flows.return_value = {
328
            "00:00:00:00:00:00:00:01": [stored_flows]
329
        }
330
331 1
        resp = await self.api_client.put(self.trace_endpoint, json=payload)
332 1
        assert resp.status_code == 200
333 1
        current_data = resp.json()
334 1
        result = current_data["result"]
335
336 1
        assert len(result) == 1
337 1
        assert result[0]["dpid"] == "00:00:00:00:00:00:00:01"
338 1
        assert result[0]["port"] == 1
339 1
        assert result[0]["type"] == "last"
340 1
        assert result[0]["vlan"] == 100
341 1
        assert result[0]["out"] == {"port": 2, "vlan": 200}
342
343 1 View Code Duplication
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
344 1
    async def test_trace_instructions(self, mock_stored_flows):
345
        """Test trace rest call with instructions."""
346 1
        self.napp.controller.loop = asyncio.get_running_loop()
347 1
        payload = {
348
            "trace": {
349
                "switch": {
350
                    "dpid": "00:00:00:00:00:00:00:01",
351
                    "in_port": 1
352
                    },
353
                "eth": {"dl_vlan": 100},
354
            }
355
        }
356 1
        stored_flows = {
357
                "flow": {
358
                    "table_id": 0,
359
                    "cookie": 84114964,
360
                    "hard_timeout": 0,
361
                    "idle_timeout": 0,
362
                    "priority": 10,
363
                    "match": {"dl_vlan": 100, "in_port": 1},
364
                    "instructions": [
365
                        {
366
                            "instruction_type": "apply_actions",
367
                            "actions": [
368
                                {"action_type": "push_vlan"},
369
                                {"action_type": "set_vlan", "vlan_id": 200},
370
                                {"action_type": "output", "port": 2}
371
                            ]
372
                        }
373
                    ]
374
                },
375
                "flow_id": 1,
376
                "state": "installed",
377
                "switch": "00:00:00:00:00:00:00:01",
378
        }
379 1
        mock_stored_flows.return_value = {
380
            "00:00:00:00:00:00:00:01": [stored_flows]
381
        }
382
383 1
        resp = await self.api_client.put(self.trace_endpoint, json=payload)
384 1
        assert resp.status_code == 200
385 1
        current_data = resp.json()
386 1
        result = current_data["result"]
387
388 1
        assert len(result) == 1
389 1
        assert result[0]["dpid"] == "00:00:00:00:00:00:00:01"
390 1
        assert result[0]["port"] == 1
391 1
        assert result[0]["type"] == "last"
392 1
        assert result[0]["vlan"] == 100
393 1
        assert result[0]["out"] == {"port": 2, "vlan": 200}
394
395 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
396 1
    async def test_instructions_no_match(self, mock_stored_flows):
397
        """Test a no match for trace rest call with instructions."""
398 1
        self.napp.controller.loop = asyncio.get_running_loop()
399 1
        payload = {
400
            "trace": {
401
                "switch": {
402
                    "dpid": "00:00:00:00:00:00:00:01",
403
                    "in_port": 1
404
                    },
405
                "eth": {"dl_vlan": 100},
406
            }
407
        }
408 1
        stored_flows = {
409
                "flow": {
410
                    "table_id": 0,
411
                    "cookie": 84114964,
412
                    "hard_timeout": 0,
413
                    "idle_timeout": 0,
414
                    "priority": 10,
415
                    "match": {"dl_vlan": 100, "in_port": 1},
416
                    "instructions": [
417
                        {
418
                            "instruction_type": "apply_actions",
419
                            "actions": [
420
                                {"action_type": "push_vlan"},
421
                                {"action_type": "set_vlan", "vlan_id": 200}
422
                            ]
423
                        }
424
                    ]
425
                },
426
                "flow_id": 1,
427
                "state": "installed",
428
                "switch": "00:00:00:00:00:00:00:01",
429
        }
430 1
        mock_stored_flows.return_value = {
431
            "00:00:00:00:00:00:00:01": [stored_flows]
432
        }
433
434 1
        resp = await self.api_client.put(self.trace_endpoint, json=payload)
435 1
        assert resp.status_code == 200
436 1
        current_data = resp.json()
437 1
        result = current_data["result"]
438 1
        assert result == []
439
440 1 View Code Duplication
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
441 1
    async def test_get_traces(self, mock_stored_flows):
442
        """Test traces rest call."""
443 1
        self.napp.controller.loop = asyncio.get_running_loop()
444 1
        payload = [{
445
            "trace": {
446
                "switch": {
447
                    "dpid": "00:00:00:00:00:00:00:01",
448
                    "in_port": 1
449
                    },
450
                "eth": {"dl_vlan": 100},
451
            }
452
        }]
453
454 1
        stored_flow = {
455
            "id": 1,
456
            "flow": {
457
                "table_id": 0,
458
                "cookie": 84114964,
459
                "hard_timeout": 0,
460
                "idle_timeout": 0,
461
                "priority": 10,
462
                "match": {"dl_vlan": 100, "in_port": 1},
463
                "actions": [
464
                    {"action_type": "pop_vlan"},
465
                    {"action_type": "output", "port": 2},
466
                ],
467
            }
468
        }
469
470 1
        mock_stored_flows.return_value = {
471
            "00:00:00:00:00:00:00:01": [stored_flow]
472
        }
473
474 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
475 1
        assert resp.status_code == 200
476 1
        current_data = resp.json()
477 1
        result1 = current_data["result"]
478
479 1
        assert len(result1) == 1
480 1
        assert len(result1[0]) == 1
481 1
        assert result1[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
482 1
        assert result1[0][0]["port"] == 1
483 1
        assert result1[0][0]["type"] == "last"
484 1
        assert result1[0][0]["vlan"] == 100
485 1
        assert result1[0][0]["out"] == {"port": 2}
486
487 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
488 1
    async def test_traces(self, mock_stored_flows):
489
        """Test traces rest call"""
490 1
        self.napp.controller.loop = asyncio.get_running_loop()
491 1
        payload = [
492
                    {
493
                        "trace": {
494
                            "switch": {
495
                                "dpid": "00:00:00:00:00:00:00:01",
496
                                "in_port": 1
497
                            },
498
                            "eth": {
499
                                "dl_vlan": 100
500
                            }
501
                        }
502
                    },
503
                    {
504
                        "trace": {
505
                            "switch": {
506
                                "dpid": "00:00:00:00:00:00:00:0a",
507
                                "in_port": 1
508
                            },
509
                            "eth": {
510
                                "dl_vlan": 100
511
                            }
512
                        }
513
                    },
514
                    {
515
                        "trace": {
516
                            "switch": {
517
                                "dpid": "00:00:00:00:00:00:00:02",
518
                                "in_port": 2
519
                            },
520
                            "eth": {
521
                                "dl_vlan": 100
522
                            }
523
                        }
524
                    }
525
                ]
526
527 1
        stored_flow = {
528
            "id": 1,
529
            "flow": {
530
                "table_id": 0,
531
                "cookie": 84114964,
532
                "hard_timeout": 0,
533
                "idle_timeout": 0,
534
                "priority": 10,
535
                "match": {"dl_vlan": 100, "in_port": 1},
536
                "actions": [{"action_type": "output", "port": 2}],
537
            }
538
        }
539
540 1
        mock_stored_flows.return_value = {
541
            "00:00:00:00:00:00:00:01": [stored_flow],
542
            "00:00:00:00:00:00:00:02": [stored_flow],
543
        }
544
545 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
546 1
        assert resp.status_code == 200
547 1
        current_data = resp.json()
548 1
        result = current_data["result"]
549 1
        assert len(result) == 3
550
551 1
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
552 1
        assert result[0][0]["port"] == 1
553 1
        assert result[0][0]["type"] == "last"
554 1
        assert result[0][0]["vlan"] == 100
555 1
        assert result[0][0]["out"] == {"port": 2, "vlan": 100}
556
557 1
        assert result[1][0]["dpid"] == "00:00:00:00:00:00:00:0a"
558 1
        assert result[1][0]["port"] == 1
559 1
        assert result[1][0]["type"] == "last"
560 1
        assert result[1][0]["vlan"] == 100
561 1
        assert result[1][0]["out"] is None
562
563 1
        assert len(result[2]) == 0
564
565 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
566 1
    async def test_traces_fail(self, mock_stored_flows):
567
        """Test traces with a failed dependency."""
568 1
        self.napp.controller.loop = asyncio.get_running_loop()
569 1
        mock_stored_flows.side_effect = HTTPException(424, "failed")
570 1
        payload = [{
571
            "trace": {
572
                "switch": {
573
                    "dpid": "00:00:00:00:00:00:00:01",
574
                    "in_port": 1
575
                    },
576
                "eth": {"dl_vlan": 100},
577
            }
578
        }]
579 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
580
        assert resp.status_code == 424
581
582 1 View Code Duplication
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
583 1
    async def test_traces_with_loop(self, mock_stored_flows):
584
        """Test traces rest call"""
585 1
        self.napp.controller.loop = asyncio.get_running_loop()
586 1
        payload = [
587
                    {
588
                        "trace": {
589
                            "switch": {
590
                                "dpid": "00:00:00:00:00:00:00:01",
591
                                "in_port": 1
592
                            },
593
                            "eth": {
594
                                "dl_vlan": 100
595
                            }
596
                        }
597
                    }
598
                ]
599
600 1
        stored_flow = {
601
            "id": 1,
602
            "flow": {
603
                "table_id": 0,
604
                "cookie": 84114964,
605
                "hard_timeout": 0,
606
                "idle_timeout": 0,
607
                "priority": 10,
608
                "match": {"dl_vlan": 100, "in_port": 1},
609
                "actions": [{"action_type": "output", "port": 1}],
610
            }
611
        }
612
613 1
        mock_stored_flows.return_value = {
614
            "00:00:00:00:00:00:00:01": [stored_flow],
615
        }
616
617 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
618 1
        assert resp.status_code == 200
619 1
        current_data = resp.json()
620 1
        result = current_data["result"]
621 1
        assert len(result) == 1
622 1
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
623 1
        assert result[0][0]["port"] == 1
624 1
        assert result[0][0]["type"] == "loop"
625 1
        assert result[0][0]["vlan"] == 100
626 1
        assert result[0][0]["out"] == {"port": 1, "vlan": 100}
627
628 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
629 1
    async def test_traces_no_action(self, mock_stored_flows):
630
        """Test traces rest call for two traces with different switches."""
631 1
        self.napp.controller.loop = asyncio.get_running_loop()
632 1
        payload = [
633
            {
634
                "trace": {
635
                    "switch": {
636
                        "dpid": "00:00:00:00:00:00:00:01",
637
                        "in_port": 1
638
                        },
639
                    "eth": {"dl_vlan": 100},
640
                }
641
            },
642
            {
643
                "trace": {
644
                    "switch": {
645
                        "dpid": "00:00:00:00:00:00:00:02",
646
                        "in_port": 1},
647
                    "eth": {"dl_vlan": 100},
648
                }
649
            }
650
        ]
651
652 1
        stored_flow1 = {
653
            "id": 1,
654
            "flow": {
655
                "table_id": 0,
656
                "cookie": 84114964,
657
                "hard_timeout": 0,
658
                "idle_timeout": 0,
659
                "priority": 10,
660
                "match": {"dl_vlan": 100, "in_port": 1}
661
            }
662
        }
663 1
        stored_flow2 = {
664
            "id": 1,
665
            "flow": {
666
                "table_id": 0,
667
                "cookie": 84114964,
668
                "hard_timeout": 0,
669
                "idle_timeout": 0,
670
                "priority": 10,
671
                "match": {"dl_vlan": 100, "in_port": 1},
672
                "actions": []
673
            }
674
        }
675
676 1
        mock_stored_flows.return_value = {
677
            "00:00:00:00:00:00:00:01": [stored_flow1],
678
            "00:00:00:00:00:00:00:02": [stored_flow2]
679
        }
680
681 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
682 1
        assert resp.status_code == 200
683 1
        current_data = resp.json()
684 1
        result = current_data["result"]
685 1
        assert len(result) == 2
686 1
        assert len(result[0]) == 0
687 1
        assert len(result[1]) == 0
688
689 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
690 1
    async def test_get_traces_untagged(self, mock_stored_flows):
691
        """Test traces rest call."""
692 1
        self.napp.controller.loop = asyncio.get_running_loop()
693 1
        payload = [{
694
            "trace": {
695
                "switch": {
696
                    "dpid": "00:00:00:00:00:00:00:01",
697
                    "in_port": 1
698
                    },
699
                "eth": {"dl_vlan": 10},
700
            }
701
        }, {
702
            "trace": {
703
                "switch": {
704
                    "dpid": "00:00:00:00:00:00:00:01",
705
                    "in_port": 1
706
                    }
707
            }
708
        }
709
        ]
710
711 1
        stored_flow1 = {
712
            "flow": {
713
                "match": {"dl_vlan": 0, "in_port": 1},
714
                "actions": [
715
                    {"action_type": "pop_vlan"},
716
                    {"action_type": "output", "port": 2},
717
                ],
718
            }
719
        }
720 1
        stored_flow2 = {
721
            "flow": {
722
                "match": {"in_port": 1},
723
                "actions": [
724
                    {"action_type": "pop_vlan"},
725
                    {"action_type": "output", "port": 3},
726
                ],
727
            }
728
        }
729 1
        stored_flow3 = {
730
            "flow": {
731
                "match": {"dl_vlan": 10, "in_port": 1},
732
                "actions": [
733
                    {"action_type": "pop_vlan"},
734
                    {"action_type": "output", "port": 1},
735
                ],
736
            }
737
        }
738 1
        mock_stored_flows.return_value = {
739
            "00:00:00:00:00:00:00:01": [
740
                stored_flow1,
741
                stored_flow2,
742
                stored_flow3
743
            ]
744
        }
745
746 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
747 1
        assert resp.status_code == 200
748 1
        current_data = resp.json()
749
750 1
        result = current_data["result"]
751 1
        assert result[0][0]["type"] == "last"
752 1
        assert result[0][0]["out"] == {"port": 3}
753 1
        assert result[1][0]["type"] == "last"
754 1
        assert result[1][0]["out"] == {"port": 2}
755
756 1
        mock_stored_flows.return_value = {
757
            "00:00:00:00:00:00:00:01": [
758
                stored_flow3,
759
                stored_flow2,
760
                stored_flow1
761
            ]
762
        }
763
764 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
765 1
        assert resp.status_code == 200
766 1
        current_data = resp.json()
767 1
        result = current_data["result"]
768 1
        assert result[0][0]["type"] == "loop"
769 1
        assert result[0][0]["out"] == {"port": 1}
770 1
        assert result[1][0]["type"] == "last"
771 1
        assert result[1][0]["out"] == {"port": 3}
772
773 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
774 1
    async def test_get_traces_any(self, mock_stored_flows):
775
        """Test traces rest call."""
776 1
        self.napp.controller.loop = asyncio.get_running_loop()
777 1
        payload = [{
778
            "trace": {
779
                "switch": {
780
                    "dpid": "00:00:00:00:00:00:00:01",
781
                    "in_port": 1
782
                    },
783
                "eth": {"dl_vlan": 10}
784
            }
785
        }, {
786
            "trace": {
787
                "switch": {
788
                    "dpid": "00:00:00:00:00:00:00:01",
789
                    "in_port": 1
790
                    }
791
            }
792
        }
793
        ]
794
795 1
        stored_flow1 = {
796
            "flow": {
797
                "match": {"dl_vlan": "4096/4096", "in_port": 1},
798
                "actions": [
799
                    {"action_type": "pop_vlan"},
800
                    {"action_type": "output", "port": 2},
801
                ],
802
            }
803
        }
804 1
        stored_flow2 = {
805
            "flow": {
806
                "match": {"dl_vlan": 10, "in_port": 1},
807
                "actions": [
808
                    {"action_type": "pop_vlan"},
809
                    {"action_type": "output", "port": 1},
810
                ],
811
            }
812
        }
813 1
        stored_flow3 = {
814
            "flow": {
815
                "match": {"dl_vlan": "10/10", "in_port": 1},
816
                "actions": [
817
                    {"action_type": "pop_vlan"},
818
                    {"action_type": "output", "port": 3},
819
                ],
820
            }
821
        }
822 1
        stored_flow4 = {
823
            "flow": {
824
                "match": {"dl_vlan": "20/10", "in_port": 1},
825
                "actions": [
826
                    {"action_type": "pop_vlan"},
827
                    {"action_type": "output", "port": 1},
828
                ],
829
            }
830
        }
831 1
        mock_stored_flows.return_value = {
832
            "00:00:00:00:00:00:00:01": [
833
                stored_flow1,
834
                stored_flow2,
835
                stored_flow3,
836
                stored_flow4
837
            ]
838
        }
839
840 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
841 1
        assert resp.status_code == 200
842 1
        current_data = resp.json()
843 1
        result = current_data["result"]
844 1
        assert result[0][0]["type"] == "last"
845 1
        assert result[0][0]["out"] == {"port": 2}
846 1
        assert len(result[1]) == 0
847
848 1
        mock_stored_flows.return_value = {
849
            "00:00:00:00:00:00:00:01": [
850
                stored_flow4,
851
                stored_flow3,
852
                stored_flow2,
853
                stored_flow1
854
            ]
855
        }
856
857 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
858 1
        assert resp.status_code == 200
859 1
        current_data = resp.json()
860 1
        result = current_data["result"]
861 1
        assert result[0][0]["type"] == "last"
862 1
        assert result[0][0]["out"] == {"port": 3}
863 1
        assert len(result[1]) == 0
864
865 1
    @pytest.mark.parametrize(
866
        "flow,args,match",
867
        [
868
            (
869
                {'flow': {'match': {'dl_vlan': 10}}},
870
                {'dl_vlan': [10]},
871
                {'flow': {'match': {'dl_vlan': 10}}},
872
            ),
873
            (
874
                {'flow': {'match': {'dl_vlan': 0}}},
875
                {},
876
                {'flow': {'match': {'dl_vlan': 0}}},
877
            ),
878
            (
879
                {'flow': {'match': {'dl_vlan': '10/10'}}},
880
                {'dl_vlan': [10]},
881
                {'flow': {'match': {'dl_vlan': '10/10'}}},
882
            ),
883
            (
884
                {'flow': {'match': {'dl_vlan': '10/10'}}},
885
                {'dl_vlan': [2]},
886
                False,
887
            ),
888
            (
889
                {'flow': {'match': {
890
                                    'nw_src': '192.168.20.21/10',
891
                                    'nw_dst': '192.168.20.21/32',
892
                                    'ipv6_src': '2002:db8::8a3f:362:7897/10',
893
                                    'ipv6_dst': '2002:db8::8a3f:362:7897/128',
894
                                    }
895
                          },
896
                 },
897
                {
898
                        'nw_src': '192.168.20.21',
899
                        'nw_dst': '192.168.20.21',
900
                        'ipv6_src': '2002:db8::8a3f:362:7897',
901
                        'ipv6_dst': '2002:db8::8a3f:362:7897',
902
                },
903
                {'flow': {'match': {
904
                                    'nw_src': '192.168.20.21/10',
905
                                    'nw_dst': '192.168.20.21/32',
906
                                    'ipv6_src': '2002:db8::8a3f:362:7897/10',
907
                                    'ipv6_dst': '2002:db8::8a3f:362:7897/128',
908
                                    }
909
                          }
910
                 },
911
            ),
912
            (
913
                {'flow': {'match': {'nw_src': '192.168.20.21'}}},
914
                {'nw_src': '192.168.20.30'},
915
                False,
916
            ),
917
            (
918
                {'flow': {'match': {'ipv6_src': '2002:db8::8a3f:362:7'}}},
919
                {'ipv6_src': '2002:db8::8a3f:362:7897'},
920
                False,
921
            ),
922
            (
923
                {'flow': {'match': {'in_port': 1, 'dl_vlan': '4096/4096'}}},
924
                {'in_port': 1, 'dl_vlan': [1]},
925
                {'flow': {'match': {'in_port': 1, 'dl_vlan': '4096/4096'}}},
926
            ),
927
            (
928
                {'flow': {'match': {'in_port': 1, 'dl_vlan': '4096/4096'}}},
929
                {'dl_vlan': [1]},
930
                False,
931
            ),
932
        ],
933
    )
934 1
    def test_do_match(self, flow, args, match):
935
        """Test do_match."""
936 1
        assert self.napp.do_match(flow, args, 0) == match
937
938 1
    def test_match_flows(self):
939
        """Test match_flows."""
940 1
        flow = {"flow": {"match": {"dl_vlan": "10/10", "in_port": 1}}}
941 1
        switch = get_switch_mock("00:00:00:00:00:00:00:01")
942 1
        stored_flows = {"00:00:00:00:00:00:00:01": [flow]}
943 1
        args = {"dl_vlan": [10], "in_port": 1}
944 1
        resp = self.napp.match_flows(switch, 0, args, stored_flows)
945 1
        assert resp == [flow]
946
947 1
        stored_flows = {}
948 1
        resp = self.napp.match_flows(switch, 0, args, stored_flows)
949 1
        assert not resp
950
951 1
    @pytest.mark.parametrize(
952
        "flow,args,resp",
953
        [
954
            (
955
                {"flow": {
956
                          "match": {"dl_vlan": "10/10", "in_port": 1},
957
                          "actions": [{'action_type': 'output', 'port': 1}]
958
                          }
959
                 },
960
                {"dl_vlan": [10], "in_port": 1},
961
                ({"flow": {
962
                            "match": {"dl_vlan": "10/10", "in_port": 1},
963
                            "actions": [{'action_type': 'output', 'port': 1}]
964
                            }
965
                  }, {"dl_vlan": [10], "in_port": 1}, 1),
966
            ),
967
            (
968
                {"flow": {
969
                          "match": {"dl_vlan": "10/10", "in_port": 1},
970
                          "actions": [{'action_type': 'push_vlan'}]
971
                          }
972
                 },
973
                {"dl_vlan": [10], "in_port": 1},
974
                ({"flow": {
975
                            "match": {"dl_vlan": "10/10", "in_port": 1},
976
                            "actions": [{'action_type': 'push_vlan'}]
977
                            }
978
                  }, {"dl_vlan": [10, 0], "in_port": 1}, None),
979
            ),
980
            (
981
                {"flow": {
982
                          "match": {"dl_vlan": "10/10", "in_port": 1},
983
                          "actions": [{'action_type': 'pop_vlan'}]
984
                          }
985
                 },
986
                {"dl_vlan": [10], "in_port": 1},
987
                ({"flow": {
988
                            "match": {"dl_vlan": "10/10", "in_port": 1},
989
                            "actions": [{'action_type': 'pop_vlan'}]
990
                            }
991
                  }, {"in_port": 1}, None),
992
            ),
993
            (
994
                {"flow": {
995
                          "match": {"dl_vlan": "10/10", "in_port": 1},
996
                          "actions": [{'action_type': 'set_vlan',
997
                                       'vlan_id': 2}]
998
                          }
999
                 },
1000
                {"dl_vlan": [10], "in_port": 1},
1001
                ({"flow": {
1002
                            "match": {"dl_vlan": "10/10", "in_port": 1},
1003
                            "actions": [{'action_type': 'set_vlan',
1004
                                         'vlan_id': 2}]
1005
                            }
1006
                  }, {"dl_vlan": [2], "in_port": 1}, None),
1007
            ),
1008
        ],
1009
    )
1010 1
    def test_match_and_apply(self, flow, args, resp):
1011
        """Test match_and_apply."""
1012 1
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
1013 1
        stored_flows = {"00:00:00:00:00:00:00:01": [flow]}
1014 1
        assert self.napp.match_and_apply(switch, args, stored_flows) == resp
1015
1016 1
        stored_flows = {}
1017 1
        resp = self.napp.match_and_apply(switch, args, stored_flows)
1018 1
        assert not resp[0]
1019 1
        assert not resp[2]
1020
1021 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
1022 1
    async def test_goto_table_1_switch(self, mock_stored_flows):
1023
        """Test match_and_apply with goto_table"""
1024 1
        self.napp.controller.loop = asyncio.get_running_loop()
1025
1026 1
        stored_flow1 = {
1027
            "flow": {
1028
                        "match": {
1029
                            "in_port": 1
1030
                        },
1031
                        "instructions": [
1032
                            {
1033
                                "instruction_type": "goto_table",
1034
                                "table_id": 1
1035
                            }
1036
                        ]
1037
                    }
1038
        }
1039 1
        stored_flow2 = {
1040
            "flow": {
1041
                        "table_id": 1,
1042
                        "match": {
1043
                            "in_port": 1
1044
                        },
1045
                        "instructions": [
1046
                            {
1047
                                "instruction_type": "apply_actions",
1048
                                "actions": [
1049
                                    {
1050
                                        "action_type": "output",
1051
                                        "port": 2
1052
                                    }
1053
                                ]
1054
                            }
1055
                        ]
1056
                    }
1057
        }
1058 1
        stored_flow3 = {
1059
            "flow": {
1060
                        "match": {
1061
                            "in_port": 2
1062
                        },
1063
                        "instructions": [
1064
                            {
1065
                                "instruction_type": "goto_table",
1066
                                "table_id": 2
1067
                            }
1068
                        ]
1069
                    }
1070
        }
1071 1
        stored_flow4 = {
1072
            "flow": {
1073
                        "table_id": 2,
1074
                        "match": {
1075
                            "in_port": 2
1076
                        },
1077
                        "instructions": [
1078
                            {
1079
                                "instruction_type": "apply_actions",
1080
                                "actions": [
1081
                                    {
1082
                                        "action_type": "output",
1083
                                        "port": 1
1084
                                    }
1085
                                ]
1086
                            }
1087
                        ]
1088
                    }
1089
        }
1090 1
        mock_stored_flows.return_value = {
1091
            "00:00:00:00:00:00:00:01": [
1092
                stored_flow1,
1093
                stored_flow2,
1094
                stored_flow4,
1095
                stored_flow3
1096
            ]
1097
        }
1098
1099 1
        payload = [{
1100
            "trace": {
1101
                "switch": {
1102
                    "dpid": "00:00:00:00:00:00:00:01",
1103
                    "in_port": 1
1104
                    }
1105
            }
1106
        }, {
1107
            "trace": {
1108
                "switch": {
1109
                    "dpid": "00:00:00:00:00:00:00:01",
1110
                    "in_port": 2
1111
                    }
1112
            }
1113
        }
1114
        ]
1115
1116 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1117 1
        assert resp.status_code == 200
1118 1
        current_data = resp.json()
1119 1
        result = current_data["result"]
1120 1
        result_t1 = result[0]
1121 1
        assert result_t1[0]['dpid'] == '00:00:00:00:00:00:00:01'
1122 1
        assert result_t1[0]['port'] == 1
1123 1
        assert result_t1[0]['type'] == 'last'
1124 1
        assert result_t1[0]['out']['port'] == 2
1125
1126 1
        result_t1 = result[1]
1127 1
        assert result_t1[0]['dpid'] == '00:00:00:00:00:00:00:01'
1128 1
        assert result_t1[0]['port'] == 2
1129 1
        assert result_t1[0]['type'] == 'last'
1130 1
        assert result_t1[0]['out']['port'] == 1
1131
1132 1
        mock_stored_flows.return_value = {
1133
            "00:00:00:00:00:00:00:01": [
1134
                stored_flow1,
1135
                stored_flow4
1136
            ]
1137
        }
1138
1139 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1140 1
        assert resp.status_code == 200
1141 1
        current_data = resp.json()
1142 1
        result = current_data["result"]
1143
1144 1
        assert len(result[0]) == 0
1145 1
        assert len(result[1]) == 0
1146
1147 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
1148 1
    async def test_fail_wrong_goto_table(self, mock_stored_flows):
1149
        """Test match_and_apply with goto_table"""
1150 1
        self.napp.controller.loop = asyncio.get_running_loop()
1151
1152 1
        stored_flow1 = {
1153
            "flow": {
1154
                        "match": {
1155
                            "in_port": 1
1156
                        },
1157
                        "instructions": [
1158
                            {
1159
                                "instruction_type": "goto_table",
1160
                                "table_id": 2
1161
                            }
1162
                        ]
1163
                    }
1164
        }
1165 1
        stored_flow2 = {
1166
            "flow": {
1167
                        "table_id": 2,
1168
                        "match": {
1169
                            "in_port": 1
1170
                        },
1171
                        "instructions": [
1172
                            {
1173
                                "instruction_type": "goto_table",
1174
                                "table_id": 1
1175
                            }
1176
                        ]
1177
                    }
1178
        }
1179 1
        mock_stored_flows.return_value = {
1180
            "00:00:00:00:00:00:00:01": [
1181
                stored_flow1,
1182
                stored_flow2
1183
            ]
1184
        }
1185
1186 1
        payload = [{
1187
            "trace": {
1188
                "switch": {
1189
                    "dpid": "00:00:00:00:00:00:00:01",
1190
                    "in_port": 1
1191
                    }
1192
            }
1193
        }
1194
        ]
1195
1196 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1197
        assert resp.status_code == 409
1198
1199 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
1200 1
    async def test_trace_goto_table_intra(self, mock_stored_flows):
1201
        """Test trace rest call.
1202
            Topology:
1203
                switches: {s1}
1204
                links:{
1205
                    s1-eth17 -- s1-eth18,
1206
                    s1-eth19 -- s1-eth20
1207
                }
1208
        """
1209 1
        self.napp.controller.loop = asyncio.get_running_loop()
1210
1211 1
        switch = self.napp.controller.switches["00:00:00:00:00:00:00:01"]
1212
1213 1
        mock_interface = Interface("interface A", 1, MagicMock())
1214
1215 1
        mock_stored_flows.return_value = {
1216
            "00:00:00:00:00:00:00:01": [
1217
                {"flow": {
1218
                    "match": {
1219
                        "in_port": 15,
1220
                        "dl_vlan": 201
1221
                        },
1222
                    "instructions": [{
1223
                        "instruction_type": "apply_actions",
1224
                        "actions": [{
1225
                            "action_type": "push_int"
1226
                        }]
1227
                        }, {
1228
                            "instruction_type": "goto_table",
1229
                            "table_id": 2
1230
                        }
1231
                    ],
1232
                    "table_id": 0,
1233
                    "table_group": "evpl",
1234
                    "priority": 20100,
1235
                    }, },
1236
                {"flow": {
1237
                    "match": {
1238
                        "in_port": 16,
1239
                        "dl_vlan": 200
1240
                        },
1241
                    "instructions": [{
1242
                        "instruction_type": "apply_actions",
1243
                        "actions": [{
1244
                            "action_type": "push_int"
1245
                        }]
1246
                        }, {
1247
                            "instruction_type": "goto_table",
1248
                            "table_id": 2
1249
                        }
1250
                    ],
1251
                    "table_id": 0,
1252
                    "table_group": "evpl",
1253
                    "priority": 20100,
1254
                    }, },
1255
                {"flow": {
1256
                    "match": {
1257
                        "in_port": 15,
1258
                        "dl_vlan": 201
1259
                        },
1260
                    "instructions": [{
1261
                        "instruction_type": "apply_actions",
1262
                        "actions": [{
1263
                            "action_type": "add_int_metadata"
1264
                        }, {
1265
                            "action_type": "output",
1266
                            "port": 19
1267
                        }]}
1268
                    ],
1269
                    "table_id": 2,
1270
                    "table_group": "base",
1271
                    "priority": 20000,
1272
                    }},
1273
                {"flow": {
1274
                    "match": {
1275
                        "in_port": 16,
1276
                        "dl_vlan": 200
1277
                        },
1278
                    "instructions": [{
1279
                        "instruction_type": "apply_actions",
1280
                        "actions": [{
1281
                            "action_type": "add_int_metadata"
1282
                        }, {
1283
                            "action_type": "output",
1284
                            "port": 17
1285
                        }]}
1286
                    ],
1287
                    "table_id": 2,
1288
                    "table_group": "base",
1289
                    "priority": 20000,
1290
                    }, },
1291
                {"flow": {
1292
                    "match": {
1293
                        "in_port": 20,
1294
                        "dl_vlan": 201
1295
                        },
1296
                    "instructions": [{
1297
                        "instruction_type": "apply_actions",
1298
                        "actions": [{
1299
                            "action_type": "send_report"
1300
                        }]},
1301
                        {
1302
                            "instruction_type": "goto_table",
1303
                            "table_id": 2
1304
                        }
1305
                    ],
1306
                    "table_id": 0,
1307
                    "table_group": "evpl",
1308
                    "priority": 20000,
1309
                    }, },
1310
                {"flow": {
1311
                    "match": {
1312
                        "in_port": 20,
1313
                        "dl_vlan": 201
1314
                        },
1315
                    "instructions": [{
1316
                        "instruction_type": "apply_actions",
1317
                        "actions": [{
1318
                            "action_type": "pop_int"
1319
                        }, {
1320
                            "action_type": "set_vlan",
1321
                            "vlan_id": 200
1322
                        }, {
1323
                            "action_type": "output",
1324
                            "port": 16
1325
                        }]}
1326
                    ],
1327
                    "table_id": 2,
1328
                    "table_group": "base",
1329
                    "priority": 20000,
1330
                    }, },
1331
                {"flow": {
1332
                    "match": {
1333
                        "in_port": 18,
1334
                        "dl_vlan": 200
1335
                        },
1336
                    "instructions": [{
1337
                        "instruction_type": "apply_actions",
1338
                        "actions": [{
1339
                            "action_type": "send_report"
1340
                        }]},
1341
                        {
1342
                            "instruction_type": "goto_table",
1343
                            "table_id": 2
1344
                        }
1345
                    ],
1346
                    "table_id": 0,
1347
                    "table_group": "evpl",
1348
                    "priority": 20000,
1349
                    }, },
1350
                {"flow": {
1351
                    "match": {
1352
                        "in_port": 18,
1353
                        "dl_vlan": 200
1354
                        },
1355
                    "instructions": [{
1356
                        "instruction_type": "apply_actions",
1357
                        "actions": [{
1358
                            "action_type": "pop_int"
1359
                        }, {
1360
                            "action_type": "set_vlan",
1361
                            "vlan_id": 201
1362
                        }, {
1363
                            "action_type": "output",
1364
                            "port": 15
1365
                        }]}
1366
                    ],
1367
                    "table_id": 2,
1368
                    "table_group": "base",
1369
                    "priority": 20000,
1370
                    }, },
1371
                ]}
1372 1
        payload = [
1373
            {"trace": {
1374
                "switch": {
1375
                    "dpid": "00:00:00:00:00:00:00:01",
1376
                    "in_port": 15
1377
                    },
1378
                "eth": {"dl_vlan": 201}
1379
                }}
1380
        ]
1381
1382 1
        iface1 = get_interface_mock("s1-eth11", 19, switch)
1383 1
        iface2 = get_interface_mock("s1-eth11", 20, switch)
1384 1
        mock_interface.link = get_link_mock(iface2, iface1)
1385
1386 1
        switch.get_interface_by_port_no.return_value = mock_interface
1387
1388 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1389 1
        assert resp.status_code == 200
1390 1
        current_data = resp.json()
1391 1
        result = current_data["result"][0]
1392
1393 1
        assert result[0]['dpid'] == '00:00:00:00:00:00:00:01'
1394 1
        assert result[0]['port'] == 15
1395 1
        assert result[0]['vlan'] == 201
1396
1397 1
        assert result[1]['port'] == 20
1398 1
        assert result[1]['out']['port'] == 16
1399 1
        assert result[1]['out']['vlan'] == 200
1400 1
        payload = [
1401
            {"trace": {
1402
                "switch": {
1403
                    "dpid": "00:00:00:00:00:00:00:01",
1404
                    "in_port": 16
1405
                    },
1406
                "eth": {"dl_vlan": 200}
1407
                }}
1408
        ]
1409
1410 1
        iface1 = get_interface_mock("s1-eth11", 17, switch)
1411 1
        iface2 = get_interface_mock("s1-eth11", 18, switch)
1412 1
        mock_interface.link = get_link_mock(iface2, iface1)
1413
1414 1
        switch.get_interface_by_port_no.return_value = mock_interface
1415
1416 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1417 1
        assert resp.status_code == 200
1418 1
        current_data = resp.json()
1419 1
        result = current_data["result"][0]
1420
1421 1
        assert result[0]['dpid'] == '00:00:00:00:00:00:00:01'
1422 1
        assert result[0]['port'] == 16
1423 1
        assert result[0]['vlan'] == 200
1424
1425 1
        assert result[1]['port'] == 18
1426 1
        assert result[1]['out']['port'] == 15
1427 1
        assert result[1]['out']['vlan'] == 201
1428
1429
    # pylint: disable=too-many-statements
1430 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
1431 1
    async def test_trace_goto_table_inter(self, mock_stored_flows):
1432
        """Test trace rest call.
1433
            Topology:
1434
                switches: {s1, s2}
1435
                links:{
1436
                    s1-eth17 -- s1-eth18,
1437
                    s1-eth11 -- s2-eth11,
1438
                    s2-eth25 -- s2-eth26
1439
                }
1440
        """
1441 1
        self.napp.controller.loop = asyncio.get_running_loop()
1442
1443 1
        switch1 = self.napp.controller.switches["00:00:00:00:00:00:00:01"]
1444 1
        switch2 = self.napp.controller.switches["00:00:00:00:00:00:00:02"]
1445
1446 1
        mock_interface1 = Interface("interface A", 1, MagicMock())
1447 1
        mock_interface2 = Interface("interface B", 1, MagicMock())
1448
1449 1
        mock_stored_flows.return_value = {
1450
            "00:00:00:00:00:00:00:01": [
1451
                {"flow": {
1452
                    "match": {
1453
                        "in_port": 15,
1454
                        "dl_vlan": 100
1455
                        },
1456
                    "instructions": [{
1457
                        "instruction_type": "apply_actions",
1458
                        "actions": [{
1459
                            "action_type": "push_int"
1460
                        }]
1461
                        }, {
1462
                            "instruction_type": "goto_table",
1463
                            "table_id": 2
1464
                        }
1465
                    ],
1466
                    "table_id": 0,
1467
                    "table_group": "evpl",
1468
                    "priority": 20100,
1469
                    }, },
1470
                {"flow": {
1471
                    "match": {
1472
                        "in_port": 15,
1473
                        "dl_vlan": 100
1474
                        },
1475
                    "instructions": [{
1476
                        "instruction_type": "apply_actions",
1477
                        "actions": [{
1478
                            "action_type": "add_int_metadata"
1479
                        }, {
1480
                            "action_type": "set_vlan",
1481
                            "vlan_id": 100
1482
                        }, {
1483
                            "action_type": "push_vlan",
1484
                            "tag_type": "s"
1485
                        }, {
1486
                            "action_type": "set_vlan",
1487
                            "vlan_id": 1
1488
                        }, {
1489
                            "action_type": "output",
1490
                            "port": 11
1491
                        }]}
1492
                    ],
1493
                    "table_id": 2,
1494
                    "table_group": "base",
1495
                    "priority": 20000,
1496
                    }},
1497
                {"flow": {
1498
                    "match": {
1499
                        "in_port": 11,
1500
                        "dl_vlan": 1
1501
                        },
1502
                    "instructions": [{
1503
                        "instruction_type": "apply_actions",
1504
                        "actions": [{
1505
                            "action_type": "add_int_metadata"
1506
                        }, {
1507
                            "action_type": "output",
1508
                            "port": 17
1509
                        }]}
1510
                    ],
1511
                    "table_id": 0,
1512
                    "table_group": "evpl",
1513
                    "priority": 20100,
1514
                    }},
1515
                {"flow": {
1516
                    "match": {
1517
                        "in_port": 18,
1518
                        "dl_vlan": 1
1519
                        },
1520
                    "instructions": [{
1521
                        "instruction_type": "apply_actions",
1522
                        "actions": [{
1523
                            "action_type": "send_report"
1524
                        }]},
1525
                        {
1526
                            "instruction_type": "goto_table",
1527
                            "table_id": 2
1528
                        }
1529
                    ],
1530
                    "table_id": 0,
1531
                    "table_group": "evpl",
1532
                    "priority": 20000,
1533
                    }, },
1534
                {"flow": {
1535
                    "match": {
1536
                        "in_port": 18,
1537
                        "dl_vlan": 1
1538
                        },
1539
                    "instructions": [{
1540
                        "instruction_type": "apply_actions",
1541
                        "actions": [{
1542
                            "action_type": "pop_int"
1543
                        }, {
1544
                            "action_type": "pop_vlan"
1545
                        }, {
1546
                            "action_type": "output",
1547
                            "port": 15
1548
                        }]}
1549
                    ],
1550
                    "table_id": 2,
1551
                    "table_group": "base",
1552
                    "priority": 20000,
1553
                    }, }
1554
            ],
1555
            "00:00:00:00:00:00:00:02": [
1556
                {"flow": {
1557
                    "match": {
1558
                        "in_port": 22,
1559
                        "dl_vlan": 100
1560
                        },
1561
                    "instructions": [{
1562
                        "instruction_type": "apply_actions",
1563
                        "actions": [{
1564
                            "action_type": "push_int"
1565
                        }]
1566
                        }, {
1567
                            "instruction_type": "goto_table",
1568
                            "table_id": 2
1569
                        }
1570
                    ],
1571
                    "table_id": 0,
1572
                    "table_group": "evpl",
1573
                    "priority": 20100,
1574
                    }, },
1575
                {"flow": {
1576
                    "match": {
1577
                        "in_port": 11,
1578
                        "dl_vlan": 1
1579
                        },
1580
                    "instructions": [{
1581
                        "instruction_type": "apply_actions",
1582
                        "actions": [{
1583
                            "action_type": "add_int_metadata"
1584
                        }, {
1585
                            "action_type": "output",
1586
                            "port": 25
1587
                        }]}
1588
                    ],
1589
                    "table_id": 0,
1590
                    "table_group": "evpl",
1591
                    "priority": 20100,
1592
                    }},
1593
                {"flow": {
1594
                    "match": {
1595
                        "in_port": 22,
1596
                        "dl_vlan": 100
1597
                        },
1598
                    "instructions": [{
1599
                        "instruction_type": "apply_actions",
1600
                        "actions": [{
1601
                            "action_type": "add_int_metadata"
1602
                        }, {
1603
                            "action_type": "set_vlan",
1604
                            "vlan_id": 100
1605
                        }, {
1606
                            "action_type": "push_vlan",
1607
                            "tag_type": "s"
1608
                        }, {
1609
                            "action_type": "set_vlan",
1610
                            "vlan_id": 1
1611
                        }, {
1612
                            "action_type": "output",
1613
                            "port": 11
1614
                        }]}
1615
                    ],
1616
                    "table_id": 2,
1617
                    "table_group": "base",
1618
                    "priority": 20000,
1619
                    }},
1620
                {"flow": {
1621
                    "match": {
1622
                        "in_port": 26,
1623
                        "dl_vlan": 1
1624
                        },
1625
                    "instructions": [{
1626
                        "instruction_type": "apply_actions",
1627
                        "actions": [{
1628
                            "action_type": "send_report"
1629
                        }]},
1630
                        {
1631
                            "instruction_type": "goto_table",
1632
                            "table_id": 2
1633
                        }
1634
                    ],
1635
                    "table_id": 0,
1636
                    "table_group": "evpl",
1637
                    "priority": 20000,
1638
                    }, },
1639
                {"flow": {
1640
                    "match": {
1641
                        "in_port": 26,
1642
                        "dl_vlan": 1
1643
                        },
1644
                    "instructions": [{
1645
                        "instruction_type": "apply_actions",
1646
                        "actions": [{
1647
                            "action_type": "pop_int"
1648
                        }, {
1649
                            "action_type": "pop_vlan"
1650
                        }, {
1651
                            "action_type": "output",
1652
                            "port": 22
1653
                        }]}
1654
                    ],
1655
                    "table_id": 2,
1656
                    "table_group": "base",
1657
                    "priority": 20000,
1658
                    }, }
1659
            ]
1660
        }
1661
1662 1
        iface1 = get_interface_mock("s1-eth11", 11, switch1)
1663 1
        iface2 = get_interface_mock("s2-eth11", 11, switch2)
1664 1
        iface3 = get_interface_mock("s2-eth25", 25, switch2)
1665 1
        iface4 = get_interface_mock("s2-eth26", 26, switch2)
1666 1
        mock_interface1.link = get_link_mock(iface2, iface1)
1667 1
        mock_interface2.link = get_link_mock(iface4, iface3)
1668
1669 1
        switch1.get_interface_by_port_no.return_value = mock_interface1
1670 1
        switch2.get_interface_by_port_no.return_value = mock_interface2
1671
1672 1
        payload = [
1673
            {"trace": {
1674
                "switch": {
1675
                    "dpid": "00:00:00:00:00:00:00:01",
1676
                    "in_port": 15
1677
                    },
1678
                "eth": {"dl_vlan": 100}
1679
                }}
1680
        ]
1681
1682 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1683 1
        assert resp.status_code == 200
1684 1
        result = resp.json()["result"][0]
1685
1686 1
        assert result[0]['dpid'] == '00:00:00:00:00:00:00:01'
1687 1
        assert result[0]['port'] == 15
1688 1
        assert result[0]['vlan'] == 100
1689
1690 1
        assert result[1]['dpid'] == '00:00:00:00:00:00:00:02'
1691 1
        assert result[1]['port'] == 11
1692 1
        assert result[1]['vlan'] == 1
1693
1694 1
        assert result[2]['dpid'] == '00:00:00:00:00:00:00:02'
1695 1
        assert result[2]['port'] == 26
1696 1
        assert result[2]['vlan'] == 1
1697 1
        assert result[2]['out']['port'] == 22
1698 1
        assert result[2]['out']['vlan'] == 100
1699
1700 1
        iface3 = get_interface_mock("s1-eth17", 17, switch1)
1701 1
        iface4 = get_interface_mock("s1-eth18", 18, switch1)
1702 1
        mock_interface1.link = get_link_mock(iface1, iface2)
1703 1
        mock_interface2.link = get_link_mock(iface4, iface3)
1704
1705 1
        switch1.get_interface_by_port_no.return_value = mock_interface2
1706 1
        switch2.get_interface_by_port_no.return_value = mock_interface1
1707
1708 1
        payload = [
1709
            {"trace": {
1710
                "switch": {
1711
                    "dpid": "00:00:00:00:00:00:00:02",
1712
                    "in_port": 22
1713
                    },
1714
                "eth": {"dl_vlan": 100}
1715
                }}
1716
        ]
1717
1718 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1719 1
        assert resp.status_code == 200
1720 1
        result = resp.json()["result"][0]
1721
1722 1
        assert result[0]['dpid'] == '00:00:00:00:00:00:00:02'
1723 1
        assert result[0]['port'] == 22
1724 1
        assert result[0]['vlan'] == 100
1725
1726 1
        assert result[1]['dpid'] == '00:00:00:00:00:00:00:01'
1727 1
        assert result[1]['port'] == 11
1728 1
        assert result[1]['vlan'] == 1
1729
1730 1
        assert result[2]['dpid'] == '00:00:00:00:00:00:00:01'
1731 1
        assert result[2]['port'] == 18
1732 1
        assert result[2]['vlan'] == 1
1733 1
        assert result[2]['out']['port'] == 15
1734
        assert result[2]['out']['vlan'] == 100
1735