5 from framework import VppTestCase
6 from asfframework import 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_v2(
61 bd_id=1, is_add=1, flood=1, uu_flood=1, forward=1, learn=1
65 # add each interface to the BD. 3 interfaces per split horizon group
67 for i in self.pg_interfaces[0:4]:
68 self.vapi.sw_interface_set_l2_bridge(
69 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=0
71 for i in self.pg_interfaces[4:8]:
72 self.vapi.sw_interface_set_l2_bridge(
73 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=1
75 for i in self.pg_interfaces[8:12]:
76 self.vapi.sw_interface_set_l2_bridge(
77 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=2
79 for i in self.bvi_interfaces:
80 self.vapi.sw_interface_set_l2_bridge(
81 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=2, port_type=L2_PORT_TYPE.BVI
85 Ether(dst="ff:ff:ff:ff:ff:ff", src="00:00:de:ad:be:ef")
86 / IP(src="10.10.10.10", dst="1.1.1.1")
87 / UDP(sport=1234, dport=1234)
92 # input on pg0 expect copies on pg1->11
93 # this is in SHG=0 so its flooded to all, expect the pg0 since that's
96 self.pg0.add_stream(p * NUM_PKTS)
97 self.pg_enable_capture(self.pg_interfaces)
100 for i in self.pg_interfaces[1:12]:
101 rx0 = i.get_capture(NUM_PKTS, timeout=1)
104 # input on pg4 (SHG=1) expect copies on pg0->3 (SHG=0)
105 # and pg8->11 (SHG=2)
107 self.pg4.add_stream(p * NUM_PKTS)
108 self.pg_enable_capture(self.pg_interfaces)
111 for i in self.pg_interfaces[:4]:
112 rx0 = i.get_capture(NUM_PKTS, timeout=1)
113 for i in self.pg_interfaces[8:12]:
114 rx0 = i.get_capture(NUM_PKTS, timeout=1)
115 for i in self.pg_interfaces[4:8]:
116 i.assert_nothing_captured(remark="Different SH group")
119 # An IP route so the packet that hits the BVI is sent out of pg12
121 ip_route = VppIpRoute(
125 [VppRoutePath(self.pg12.remote_ip4, self.pg12.sw_if_index)],
127 ip_route.add_vpp_config()
129 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
132 # input on pg0 expect copies on pg1->12
133 # this is in SHG=0 so its flooded to all, expect the pg0 since that's
136 self.pg0.add_stream(p * NUM_PKTS)
137 self.pg_enable_capture(self.pg_interfaces)
140 for i in self.pg_interfaces[1:]:
141 rx0 = i.get_capture(NUM_PKTS, timeout=1)
144 # input on pg4 (SHG=1) expect copies on pg0->3 (SHG=0)
145 # and pg8->12 (SHG=2)
147 self.pg4.add_stream(p * NUM_PKTS)
148 self.pg_enable_capture(self.pg_interfaces)
151 for i in self.pg_interfaces[:4]:
152 rx0 = i.get_capture(NUM_PKTS, timeout=1)
153 for i in self.pg_interfaces[8:13]:
154 rx0 = i.get_capture(NUM_PKTS, timeout=1)
155 for i in self.pg_interfaces[4:8]:
156 i.assert_nothing_captured(remark="Different SH group")
161 for i in self.pg_interfaces[:12]:
162 self.vapi.sw_interface_set_l2_bridge(
163 rx_sw_if_index=i.sw_if_index, bd_id=1, enable=0
165 for i in self.bvi_interfaces:
166 self.vapi.sw_interface_set_l2_bridge(
167 rx_sw_if_index=i.sw_if_index,
170 port_type=L2_PORT_TYPE.BVI,
174 self.vapi.bridge_domain_add_del_v2(bd_id=1, is_add=0)
176 def test_flood_one(self):
177 """L2 no-Flood Test"""
180 # Create a single bridge Domain
182 self.vapi.bridge_domain_add_del_v2(
183 bd_id=1, is_add=1, flood=1, uu_flood=1, forward=1, learn=1
187 # add 2 interfaces to the BD. this means a flood goes to only
190 for i in self.pg_interfaces[:2]:
191 self.vapi.sw_interface_set_l2_bridge(
192 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=0
196 Ether(dst="ff:ff:ff:ff:ff:ff", src="00:00:de:ad:be:ef")
197 / IP(src="10.10.10.10", dst="1.1.1.1")
198 / UDP(sport=1234, dport=1234)
203 # input on pg0 expect copies on pg1
205 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
210 for i in self.pg_interfaces[:2]:
211 self.vapi.sw_interface_set_l2_bridge(
212 rx_sw_if_index=i.sw_if_index, bd_id=1, enable=0
214 self.vapi.bridge_domain_add_del_v2(bd_id=1, is_add=0)
216 def test_uu_fwd(self):
220 # Create a single bridge Domain
222 self.vapi.bridge_domain_add_del_v2(
223 bd_id=1, is_add=1, uu_flood=1, flood=1, forward=1, learn=1
227 # add each interface to the BD. 3 interfaces per split horizon group
229 for i in self.pg_interfaces[0:4]:
230 self.vapi.sw_interface_set_l2_bridge(
231 rx_sw_if_index=i.sw_if_index, bd_id=1, shg=0
235 # an unknown unicast and broadcast packets
238 Ether(dst="00:00:00:c1:5c:00", 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)
244 Ether(dst="ff:ff:ff:ff:ff:ff", src="00:00:de:ad:be:ef")
245 / IP(src="10.10.10.10", dst="1.1.1.1")
246 / UDP(sport=1234, dport=1234)
251 # input on pg0, expected copies on pg1->4
253 self.pg0.add_stream(p_uu * NUM_PKTS)
254 self.pg_enable_capture(self.pg_interfaces)
257 for i in self.pg_interfaces[1:4]:
258 rx0 = i.get_capture(NUM_PKTS, timeout=1)
260 self.pg0.add_stream(p_bm * NUM_PKTS)
261 self.pg_enable_capture(self.pg_interfaces)
264 for i in self.pg_interfaces[1:4]:
265 rx0 = i.get_capture(NUM_PKTS, timeout=1)
268 # use pg8 as the uu-fwd interface
270 self.vapi.sw_interface_set_l2_bridge(
271 rx_sw_if_index=self.pg8.sw_if_index,
274 port_type=L2_PORT_TYPE.UU_FWD,
278 # expect the UU packet on the uu-fwd interface and not be flooded
280 self.pg0.add_stream(p_uu * NUM_PKTS)
281 self.pg_enable_capture(self.pg_interfaces)
284 rx0 = self.pg8.get_capture(NUM_PKTS, timeout=1)
286 for i in self.pg_interfaces[0:4]:
287 i.assert_nothing_captured(remark="UU not flooded")
289 self.pg0.add_stream(p_bm * NUM_PKTS)
290 self.pg_enable_capture(self.pg_interfaces)
293 for i in self.pg_interfaces[1:4]:
294 rx0 = i.get_capture(NUM_PKTS, timeout=1)
297 # remove the uu-fwd interface and expect UU to be flooded again
299 self.vapi.sw_interface_set_l2_bridge(
300 rx_sw_if_index=self.pg8.sw_if_index,
303 port_type=L2_PORT_TYPE.UU_FWD,
307 self.pg0.add_stream(p_uu * NUM_PKTS)
308 self.pg_enable_capture(self.pg_interfaces)
311 for i in self.pg_interfaces[1:4]:
312 rx0 = i.get_capture(NUM_PKTS, timeout=1)
315 # change the BD config to not support UU-flood
317 self.vapi.bridge_flags(bd_id=1, is_set=0, flags=BRIDGE_FLAGS.UU_FLOOD)
319 self.send_and_assert_no_replies(self.pg0, p_uu)
322 # re-add the uu-fwd interface
324 self.vapi.sw_interface_set_l2_bridge(
325 rx_sw_if_index=self.pg8.sw_if_index,
328 port_type=L2_PORT_TYPE.UU_FWD,
330 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
332 self.pg0.add_stream(p_uu * NUM_PKTS)
333 self.pg_enable_capture(self.pg_interfaces)
336 rx0 = self.pg8.get_capture(NUM_PKTS, timeout=1)
338 for i in self.pg_interfaces[0:4]:
339 i.assert_nothing_captured(remark="UU not flooded")
342 # remove the uu-fwd interface
344 self.vapi.sw_interface_set_l2_bridge(
345 rx_sw_if_index=self.pg8.sw_if_index,
348 port_type=L2_PORT_TYPE.UU_FWD,
351 self.send_and_assert_no_replies(self.pg0, p_uu)
356 for i in self.pg_interfaces[:4]:
357 self.vapi.sw_interface_set_l2_bridge(
358 rx_sw_if_index=i.sw_if_index, bd_id=1, enable=0
361 self.vapi.bridge_domain_add_del_v2(bd_id=1, is_add=0)
364 if __name__ == "__main__":
365 unittest.main(testRunner=VppTestRunner)