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