blob: 5a2694cbb63236a7ab5ab1605d5e05a4ad49da26 [file] [log] [blame]
Neale Ranns055b2312018-07-20 01:16:04 -07001#!/usr/bin/env python
2
3import unittest
4import socket
5
6from framework import VppTestCase, VppTestRunner
7from vpp_ip_route import VppIpRoute, VppRoutePath
Neale Rannsb4743802018-09-05 09:13:57 -07008from vpp_papi_provider import L2_PORT_TYPE, BRIDGE_FLAGS
Neale Ranns055b2312018-07-20 01:16:04 -07009
10from scapy.packet import Raw
11from scapy.layers.l2 import Ether
12from scapy.layers.inet import IP, UDP
13
14
15class 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:
Neale Rannsb4743802018-09-05 09:13:57 -070062 self.vapi.sw_interface_set_l2_bridge(i.sw_if_index, 1, 2,
63 port_type=L2_PORT_TYPE.BVI)
Neale Ranns055b2312018-07-20 01:16:04 -070064
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
Neale Ranns055b2312018-07-20 01:16:04 -070083 #
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,
Neale Rannsb4743802018-09-05 09:13:57 -0700142 port_type=L2_PORT_TYPE.BVI,
143 enable=0)
144
145 self.vapi.bridge_domain_add_del(1, is_add=0)
146
Neale Rannsb9fa29d2018-10-02 07:27:02 -0700147 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
Neale Rannsb4743802018-09-05 09:13:57 -0700180 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 #
Neale Rannsd29cc882018-10-10 15:55:01 +0000195 # an unknown unicast and braodcast packets
Neale Rannsb4743802018-09-05 09:13:57 -0700196 #
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))
Neale Rannsd29cc882018-10-10 15:55:01 +0000202 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))
Neale Rannsb4743802018-09-05 09:13:57 -0700207
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
Neale Rannsd29cc882018-10-10 15:55:01 +0000218 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
Neale Rannsb4743802018-09-05 09:13:57 -0700225 #
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
Neale Rannsd29cc882018-10-10 15:55:01 +0000243 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
Neale Rannsb4743802018-09-05 09:13:57 -0700250 #
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)
Neale Ranns055b2312018-07-20 01:16:04 -0700300
301 self.vapi.bridge_domain_add_del(1, is_add=0)
302
303
304if __name__ == '__main__':
305 unittest.main(testRunner=VppTestRunner)