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