misc: Fix python scripts shebang line
[vpp.git] / test / test_l2_flood.py
1 #!/usr/bin/env python3
2
3 import unittest
4 import socket
5
6 from framework import VppTestCase, VppTestRunner
7 from vpp_ip_route import VppIpRoute, VppRoutePath
8 from vpp_l2 import L2_PORT_TYPE, BRIDGE_FLAGS
9
10 from scapy.packet import Raw
11 from scapy.layers.l2 import Ether
12 from scapy.layers.inet import IP, UDP
13
14 NUM_PKTS = 67
15
16
17 class TestL2Flood(VppTestCase):
18     """ L2-flood """
19
20     @classmethod
21     def setUpClass(cls):
22         super(TestL2Flood, cls).setUpClass()
23
24     @classmethod
25     def tearDownClass(cls):
26         super(TestL2Flood, cls).tearDownClass()
27
28     def setUp(self):
29         super(TestL2Flood, self).setUp()
30
31         # 12 l2 interface and one l3
32         self.create_pg_interfaces(range(13))
33         self.create_bvi_interfaces(1)
34
35         for i in self.pg_interfaces:
36             i.admin_up()
37         for i in self.bvi_interfaces:
38             i.admin_up()
39
40         self.pg12.config_ip4()
41         self.pg12.resolve_arp()
42         self.bvi0.config_ip4()
43
44     def tearDown(self):
45         self.pg12.unconfig_ip4()
46         self.bvi0.unconfig_ip4()
47
48         for i in self.pg_interfaces:
49             i.admin_down()
50         for i in self.bvi_interfaces:
51             i.admin_down()
52         super(TestL2Flood, self).tearDown()
53
54     def test_flood(self):
55         """ L2 Flood Tests """
56
57         #
58         # Create a single bridge Domain
59         #
60         self.vapi.bridge_domain_add_del(bd_id=1)
61
62         #
63         # add each interface to the BD. 3 interfaces per split horizon group
64         #
65         for i in self.pg_interfaces[0:4]:
66             self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
67                                                  bd_id=1, shg=0)
68         for i in self.pg_interfaces[4:8]:
69             self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
70                                                  bd_id=1, shg=1)
71         for i in self.pg_interfaces[8:12]:
72             self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
73                                                  bd_id=1, shg=2)
74         for i in self.bvi_interfaces:
75             self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
76                                                  bd_id=1, shg=2,
77                                                  port_type=L2_PORT_TYPE.BVI)
78
79         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
80                    src="00:00:de:ad:be:ef") /
81              IP(src="10.10.10.10", dst="1.1.1.1") /
82              UDP(sport=1234, dport=1234) /
83              Raw('\xa5' * 100))
84
85         #
86         # input on pg0 expect copies on pg1->11
87         # this is in SHG=0 so its flooded to all, expect the pg0 since that's
88         # the ingress link
89         #
90         self.pg0.add_stream(p*NUM_PKTS)
91         self.pg_enable_capture(self.pg_interfaces)
92         self.pg_start()
93
94         for i in self.pg_interfaces[1:12]:
95             rx0 = i.get_capture(NUM_PKTS, timeout=1)
96
97         #
98         # input on pg4 (SHG=1) expect copies on pg0->3 (SHG=0)
99         # and pg8->11 (SHG=2)
100         #
101         self.pg4.add_stream(p*NUM_PKTS)
102         self.pg_enable_capture(self.pg_interfaces)
103         self.pg_start()
104
105         for i in self.pg_interfaces[:4]:
106             rx0 = i.get_capture(NUM_PKTS, timeout=1)
107         for i in self.pg_interfaces[8:12]:
108             rx0 = i.get_capture(NUM_PKTS, timeout=1)
109         for i in self.pg_interfaces[4:8]:
110             i.assert_nothing_captured(remark="Different SH group")
111
112         #
113         # An IP route so the packet that hits the BVI is sent out of pg12
114         #
115         ip_route = VppIpRoute(self, "1.1.1.1", 32,
116                               [VppRoutePath(self.pg12.remote_ip4,
117                                             self.pg12.sw_if_index)])
118         ip_route.add_vpp_config()
119
120         self.logger.info(self.vapi.cli("sh bridge 1 detail"))
121
122         #
123         # input on pg0 expect copies on pg1->12
124         # this is in SHG=0 so its flooded to all, expect the pg0 since that's
125         # the ingress link
126         #
127         self.pg0.add_stream(p*NUM_PKTS)
128         self.pg_enable_capture(self.pg_interfaces)
129         self.pg_start()
130
131         for i in self.pg_interfaces[1:]:
132             rx0 = i.get_capture(NUM_PKTS, timeout=1)
133
134         #
135         # input on pg4 (SHG=1) expect copies on pg0->3 (SHG=0)
136         # and pg8->12 (SHG=2)
137         #
138         self.pg4.add_stream(p*NUM_PKTS)
139         self.pg_enable_capture(self.pg_interfaces)
140         self.pg_start()
141
142         for i in self.pg_interfaces[:4]:
143             rx0 = i.get_capture(NUM_PKTS, timeout=1)
144         for i in self.pg_interfaces[8:13]:
145             rx0 = i.get_capture(NUM_PKTS, timeout=1)
146         for i in self.pg_interfaces[4:8]:
147             i.assert_nothing_captured(remark="Different SH group")
148
149         #
150         # cleanup
151         #
152         for i in self.pg_interfaces[:12]:
153             self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
154                                                  bd_id=1, enable=0)
155         for i in self.bvi_interfaces:
156             self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
157                                                  bd_id=1, shg=2,
158                                                  port_type=L2_PORT_TYPE.BVI,
159                                                  enable=0)
160
161         self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
162
163     def test_flood_one(self):
164         """ L2 no-Flood Test """
165
166         #
167         # Create a single bridge Domain
168         #
169         self.vapi.bridge_domain_add_del(bd_id=1)
170
171         #
172         # add 2 interfaces to the BD. this means a flood goes to only
173         # one member
174         #
175         for i in self.pg_interfaces[:2]:
176             self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
177                                                  bd_id=1, shg=0)
178
179         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
180                    src="00:00:de:ad:be:ef") /
181              IP(src="10.10.10.10", dst="1.1.1.1") /
182              UDP(sport=1234, dport=1234) /
183              Raw('\xa5' * 100))
184
185         #
186         # input on pg0 expect copies on pg1
187         #
188         self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
189
190         #
191         # cleanup
192         #
193         for i in self.pg_interfaces[:2]:
194             self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
195                                                  bd_id=1, enable=0)
196         self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
197
198     def test_uu_fwd(self):
199         """ UU Flood """
200
201         #
202         # Create a single bridge Domain
203         #
204         self.vapi.bridge_domain_add_del(bd_id=1, uu_flood=1)
205
206         #
207         # add each interface to the BD. 3 interfaces per split horizon group
208         #
209         for i in self.pg_interfaces[0:4]:
210             self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
211                                                  bd_id=1, shg=0)
212
213         #
214         # an unknown unicast and broadcast packets
215         #
216         p_uu = (Ether(dst="00:00:00:c1:5c:00",
217                       src="00:00:de:ad:be:ef") /
218                 IP(src="10.10.10.10", dst="1.1.1.1") /
219                 UDP(sport=1234, dport=1234) /
220                 Raw('\xa5' * 100))
221         p_bm = (Ether(dst="ff:ff:ff:ff:ff:ff",
222                       src="00:00:de:ad:be:ef") /
223                 IP(src="10.10.10.10", dst="1.1.1.1") /
224                 UDP(sport=1234, dport=1234) /
225                 Raw('\xa5' * 100))
226
227         #
228         # input on pg0, expected copies on pg1->4
229         #
230         self.pg0.add_stream(p_uu*NUM_PKTS)
231         self.pg_enable_capture(self.pg_interfaces)
232         self.pg_start()
233
234         for i in self.pg_interfaces[1:4]:
235             rx0 = i.get_capture(NUM_PKTS, timeout=1)
236
237         self.pg0.add_stream(p_bm*NUM_PKTS)
238         self.pg_enable_capture(self.pg_interfaces)
239         self.pg_start()
240
241         for i in self.pg_interfaces[1:4]:
242             rx0 = i.get_capture(NUM_PKTS, timeout=1)
243
244         #
245         # use pg8 as the uu-fwd interface
246         #
247         self.vapi.sw_interface_set_l2_bridge(
248             rx_sw_if_index=self.pg8.sw_if_index, bd_id=1, shg=0,
249             port_type=L2_PORT_TYPE.UU_FWD)
250
251         #
252         # expect the UU packet on the uu-fwd interface and not be flooded
253         #
254         self.pg0.add_stream(p_uu*NUM_PKTS)
255         self.pg_enable_capture(self.pg_interfaces)
256         self.pg_start()
257
258         rx0 = self.pg8.get_capture(NUM_PKTS, timeout=1)
259
260         for i in self.pg_interfaces[0:4]:
261             i.assert_nothing_captured(remark="UU not flooded")
262
263         self.pg0.add_stream(p_bm*NUM_PKTS)
264         self.pg_enable_capture(self.pg_interfaces)
265         self.pg_start()
266
267         for i in self.pg_interfaces[1:4]:
268             rx0 = i.get_capture(NUM_PKTS, timeout=1)
269
270         #
271         # remove the uu-fwd interface and expect UU to be flooded again
272         #
273         self.vapi.sw_interface_set_l2_bridge(
274             rx_sw_if_index=self.pg8.sw_if_index, bd_id=1, shg=0,
275             port_type=L2_PORT_TYPE.UU_FWD, enable=0)
276
277         self.pg0.add_stream(p_uu*NUM_PKTS)
278         self.pg_enable_capture(self.pg_interfaces)
279         self.pg_start()
280
281         for i in self.pg_interfaces[1:4]:
282             rx0 = i.get_capture(NUM_PKTS, timeout=1)
283
284         #
285         # change the BD config to not support UU-flood
286         #
287         self.vapi.bridge_flags(bd_id=1, is_set=0, flags=BRIDGE_FLAGS.UU_FLOOD)
288
289         self.send_and_assert_no_replies(self.pg0, p_uu)
290
291         #
292         # re-add the uu-fwd interface
293         #
294         self.vapi.sw_interface_set_l2_bridge(
295             rx_sw_if_index=self.pg8.sw_if_index, bd_id=1, shg=0,
296             port_type=L2_PORT_TYPE.UU_FWD)
297         self.logger.info(self.vapi.cli("sh bridge 1 detail"))
298
299         self.pg0.add_stream(p_uu*NUM_PKTS)
300         self.pg_enable_capture(self.pg_interfaces)
301         self.pg_start()
302
303         rx0 = self.pg8.get_capture(NUM_PKTS, timeout=1)
304
305         for i in self.pg_interfaces[0:4]:
306             i.assert_nothing_captured(remark="UU not flooded")
307
308         #
309         # remove the uu-fwd interface
310         #
311         self.vapi.sw_interface_set_l2_bridge(
312             rx_sw_if_index=self.pg8.sw_if_index, bd_id=1, shg=0,
313             port_type=L2_PORT_TYPE.UU_FWD, enable=0)
314         self.send_and_assert_no_replies(self.pg0, p_uu)
315
316         #
317         # cleanup
318         #
319         for i in self.pg_interfaces[:4]:
320             self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
321                                                  bd_id=1, enable=0)
322
323         self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
324
325
326 if __name__ == '__main__':
327     unittest.main(testRunner=VppTestRunner)