6 from framework import VppTestCase, VppTestRunner
7 from vpp_ip_route import VppIpRoute, VppRoutePath
8 from vpp_l2 import L2_PORT_TYPE, BRIDGE_FLAGS
10 from scapy.packet import Raw
11 from scapy.layers.l2 import Ether
12 from scapy.layers.inet import IP, UDP
17 class TestL2Flood(VppTestCase):
22 super(TestL2Flood, cls).setUpClass()
25 def tearDownClass(cls):
26 super(TestL2Flood, cls).tearDownClass()
29 super(TestL2Flood, self).setUp()
31 # 12 l2 interface and one l3
32 self.create_pg_interfaces(range(13))
33 self.create_bvi_interfaces(1)
35 for i in self.pg_interfaces:
37 for i in self.bvi_interfaces:
40 self.pg12.config_ip4()
41 self.pg12.resolve_arp()
42 self.bvi0.config_ip4()
45 self.pg12.unconfig_ip4()
46 self.bvi0.unconfig_ip4()
48 for i in self.pg_interfaces:
50 for i in self.bvi_interfaces:
52 super(TestL2Flood, self).tearDown()
58 # Create a single bridge Domain
60 self.vapi.bridge_domain_add_del(bd_id=1)
63 # add each interface to the BD. 3 interfaces per split horizon group
65 for i in self.pg_interfaces[0:4]:
66 self.vapi.sw_interface_set_l2_bridge(
67 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=0
69 for i in self.pg_interfaces[4:8]:
70 self.vapi.sw_interface_set_l2_bridge(
71 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=1
73 for i in self.pg_interfaces[8:12]:
74 self.vapi.sw_interface_set_l2_bridge(
75 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=2
77 for i in self.bvi_interfaces:
78 self.vapi.sw_interface_set_l2_bridge(
79 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=2, port_type=L2_PORT_TYPE.BVI
83 Ether(dst="ff:ff:ff:ff:ff:ff", src="00:00:de:ad:be:ef")
84 / IP(src="10.10.10.10", dst="1.1.1.1")
85 / UDP(sport=1234, dport=1234)
90 # input on pg0 expect copies on pg1->11
91 # this is in SHG=0 so its flooded to all, expect the pg0 since that's
94 self.pg0.add_stream(p * NUM_PKTS)
95 self.pg_enable_capture(self.pg_interfaces)
98 for i in self.pg_interfaces[1:12]:
99 rx0 = i.get_capture(NUM_PKTS, timeout=1)
102 # input on pg4 (SHG=1) expect copies on pg0->3 (SHG=0)
103 # and pg8->11 (SHG=2)
105 self.pg4.add_stream(p * NUM_PKTS)
106 self.pg_enable_capture(self.pg_interfaces)
109 for i in self.pg_interfaces[:4]:
110 rx0 = i.get_capture(NUM_PKTS, timeout=1)
111 for i in self.pg_interfaces[8:12]:
112 rx0 = i.get_capture(NUM_PKTS, timeout=1)
113 for i in self.pg_interfaces[4:8]:
114 i.assert_nothing_captured(remark="Different SH group")
117 # An IP route so the packet that hits the BVI is sent out of pg12
119 ip_route = VppIpRoute(
123 [VppRoutePath(self.pg12.remote_ip4, self.pg12.sw_if_index)],
125 ip_route.add_vpp_config()
127 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
130 # input on pg0 expect copies on pg1->12
131 # this is in SHG=0 so its flooded to all, expect the pg0 since that's
134 self.pg0.add_stream(p * NUM_PKTS)
135 self.pg_enable_capture(self.pg_interfaces)
138 for i in self.pg_interfaces[1:]:
139 rx0 = i.get_capture(NUM_PKTS, timeout=1)
142 # input on pg4 (SHG=1) expect copies on pg0->3 (SHG=0)
143 # and pg8->12 (SHG=2)
145 self.pg4.add_stream(p * NUM_PKTS)
146 self.pg_enable_capture(self.pg_interfaces)
149 for i in self.pg_interfaces[:4]:
150 rx0 = i.get_capture(NUM_PKTS, timeout=1)
151 for i in self.pg_interfaces[8:13]:
152 rx0 = i.get_capture(NUM_PKTS, timeout=1)
153 for i in self.pg_interfaces[4:8]:
154 i.assert_nothing_captured(remark="Different SH group")
159 for i in self.pg_interfaces[:12]:
160 self.vapi.sw_interface_set_l2_bridge(
161 rx_sw_if_index=i.sw_if_index, bd_id=1, enable=0
163 for i in self.bvi_interfaces:
164 self.vapi.sw_interface_set_l2_bridge(
165 rx_sw_if_index=i.sw_if_index,
168 port_type=L2_PORT_TYPE.BVI,
172 self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
174 def test_flood_one(self):
175 """L2 no-Flood Test"""
178 # Create a single bridge Domain
180 self.vapi.bridge_domain_add_del(bd_id=1)
183 # add 2 interfaces to the BD. this means a flood goes to only
186 for i in self.pg_interfaces[:2]:
187 self.vapi.sw_interface_set_l2_bridge(
188 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=0
192 Ether(dst="ff:ff:ff:ff:ff:ff", src="00:00:de:ad:be:ef")
193 / IP(src="10.10.10.10", dst="1.1.1.1")
194 / UDP(sport=1234, dport=1234)
199 # input on pg0 expect copies on pg1
201 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
206 for i in self.pg_interfaces[:2]:
207 self.vapi.sw_interface_set_l2_bridge(
208 rx_sw_if_index=i.sw_if_index, bd_id=1, enable=0
210 self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
212 def test_uu_fwd(self):
216 # Create a single bridge Domain
218 self.vapi.bridge_domain_add_del(bd_id=1, uu_flood=1)
221 # add each interface to the BD. 3 interfaces per split horizon group
223 for i in self.pg_interfaces[0:4]:
224 self.vapi.sw_interface_set_l2_bridge(
225 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=0
229 # an unknown unicast and broadcast packets
232 Ether(dst="00:00:00:c1:5c:00", src="00:00:de:ad:be:ef")
233 / IP(src="10.10.10.10", dst="1.1.1.1")
234 / UDP(sport=1234, dport=1234)
238 Ether(dst="ff:ff:ff:ff:ff:ff", src="00:00:de:ad:be:ef")
239 / IP(src="10.10.10.10", dst="1.1.1.1")
240 / UDP(sport=1234, dport=1234)
245 # input on pg0, expected copies on pg1->4
247 self.pg0.add_stream(p_uu * NUM_PKTS)
248 self.pg_enable_capture(self.pg_interfaces)
251 for i in self.pg_interfaces[1:4]:
252 rx0 = i.get_capture(NUM_PKTS, timeout=1)
254 self.pg0.add_stream(p_bm * NUM_PKTS)
255 self.pg_enable_capture(self.pg_interfaces)
258 for i in self.pg_interfaces[1:4]:
259 rx0 = i.get_capture(NUM_PKTS, timeout=1)
262 # use pg8 as the uu-fwd interface
264 self.vapi.sw_interface_set_l2_bridge(
265 rx_sw_if_index=self.pg8.sw_if_index,
268 port_type=L2_PORT_TYPE.UU_FWD,
272 # expect the UU packet on the uu-fwd interface and not be flooded
274 self.pg0.add_stream(p_uu * NUM_PKTS)
275 self.pg_enable_capture(self.pg_interfaces)
278 rx0 = self.pg8.get_capture(NUM_PKTS, timeout=1)
280 for i in self.pg_interfaces[0:4]:
281 i.assert_nothing_captured(remark="UU not flooded")
283 self.pg0.add_stream(p_bm * NUM_PKTS)
284 self.pg_enable_capture(self.pg_interfaces)
287 for i in self.pg_interfaces[1:4]:
288 rx0 = i.get_capture(NUM_PKTS, timeout=1)
291 # remove the uu-fwd interface and expect UU to be flooded again
293 self.vapi.sw_interface_set_l2_bridge(
294 rx_sw_if_index=self.pg8.sw_if_index,
297 port_type=L2_PORT_TYPE.UU_FWD,
301 self.pg0.add_stream(p_uu * NUM_PKTS)
302 self.pg_enable_capture(self.pg_interfaces)
305 for i in self.pg_interfaces[1:4]:
306 rx0 = i.get_capture(NUM_PKTS, timeout=1)
309 # change the BD config to not support UU-flood
311 self.vapi.bridge_flags(bd_id=1, is_set=0, flags=BRIDGE_FLAGS.UU_FLOOD)
313 self.send_and_assert_no_replies(self.pg0, p_uu)
316 # re-add the uu-fwd interface
318 self.vapi.sw_interface_set_l2_bridge(
319 rx_sw_if_index=self.pg8.sw_if_index,
322 port_type=L2_PORT_TYPE.UU_FWD,
324 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
326 self.pg0.add_stream(p_uu * NUM_PKTS)
327 self.pg_enable_capture(self.pg_interfaces)
330 rx0 = self.pg8.get_capture(NUM_PKTS, timeout=1)
332 for i in self.pg_interfaces[0:4]:
333 i.assert_nothing_captured(remark="UU not flooded")
336 # remove the uu-fwd interface
338 self.vapi.sw_interface_set_l2_bridge(
339 rx_sw_if_index=self.pg8.sw_if_index,
342 port_type=L2_PORT_TYPE.UU_FWD,
345 self.send_and_assert_no_replies(self.pg0, p_uu)
350 for i in self.pg_interfaces[:4]:
351 self.vapi.sw_interface_set_l2_bridge(
352 rx_sw_if_index=i.sw_if_index, bd_id=1, enable=0
355 self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
358 if __name__ == "__main__":
359 unittest.main(testRunner=VppTestRunner)