blob: 7f3c57a399d298db91b7c4e1b06a5f7b258ef9e8 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns055b2312018-07-20 01:16:04 -07002
3import unittest
4import socket
5
6from framework import VppTestCase, VppTestRunner
7from vpp_ip_route import VppIpRoute, VppRoutePath
Neale Ranns93cc3ee2018-10-10 07:22:51 -07008from vpp_l2 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
Paul Vinciguerra4271c972019-05-14 13:25:49 -040014NUM_PKTS = 67
15
Neale Ranns055b2312018-07-20 01:16:04 -070016
17class TestL2Flood(VppTestCase):
18 """ L2-flood """
19
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070020 @classmethod
21 def setUpClass(cls):
22 super(TestL2Flood, cls).setUpClass()
23
24 @classmethod
25 def tearDownClass(cls):
26 super(TestL2Flood, cls).tearDownClass()
27
Neale Ranns055b2312018-07-20 01:16:04 -070028 def setUp(self):
29 super(TestL2Flood, self).setUp()
30
31 # 12 l2 interface and one l3
32 self.create_pg_interfaces(range(13))
Neale Ranns192b13f2019-03-15 02:16:20 -070033 self.create_bvi_interfaces(1)
Neale Ranns055b2312018-07-20 01:16:04 -070034
35 for i in self.pg_interfaces:
36 i.admin_up()
Neale Ranns192b13f2019-03-15 02:16:20 -070037 for i in self.bvi_interfaces:
Neale Ranns055b2312018-07-20 01:16:04 -070038 i.admin_up()
39
40 self.pg12.config_ip4()
41 self.pg12.resolve_arp()
Neale Ranns192b13f2019-03-15 02:16:20 -070042 self.bvi0.config_ip4()
Neale Ranns055b2312018-07-20 01:16:04 -070043
44 def tearDown(self):
45 self.pg12.unconfig_ip4()
Neale Ranns192b13f2019-03-15 02:16:20 -070046 self.bvi0.unconfig_ip4()
Neale Ranns055b2312018-07-20 01:16:04 -070047
48 for i in self.pg_interfaces:
49 i.admin_down()
Neale Ranns192b13f2019-03-15 02:16:20 -070050 for i in self.bvi_interfaces:
Neale Ranns055b2312018-07-20 01:16:04 -070051 i.admin_down()
52 super(TestL2Flood, self).tearDown()
53
54 def test_flood(self):
55 """ L2 Flood Tests """
56
57 #
58 # Create a single bridge Domain
59 #
Ole Troana5b2eec2019-03-11 19:23:25 +010060 self.vapi.bridge_domain_add_del(bd_id=1)
Neale Ranns055b2312018-07-20 01:16:04 -070061
62 #
63 # add each interface to the BD. 3 interfaces per split horizon group
64 #
65 for i in self.pg_interfaces[0:4]:
Ole Troana5b2eec2019-03-11 19:23:25 +010066 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
67 bd_id=1, shg=0)
Neale Ranns055b2312018-07-20 01:16:04 -070068 for i in self.pg_interfaces[4:8]:
Ole Troana5b2eec2019-03-11 19:23:25 +010069 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
70 bd_id=1, shg=1)
Neale Ranns055b2312018-07-20 01:16:04 -070071 for i in self.pg_interfaces[8:12]:
Ole Troana5b2eec2019-03-11 19:23:25 +010072 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
73 bd_id=1, shg=2)
Neale Ranns192b13f2019-03-15 02:16:20 -070074 for i in self.bvi_interfaces:
Ole Troana5b2eec2019-03-11 19:23:25 +010075 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
76 bd_id=1, shg=2,
Neale Rannsb4743802018-09-05 09:13:57 -070077 port_type=L2_PORT_TYPE.BVI)
Neale Ranns055b2312018-07-20 01:16:04 -070078
79 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
80 src="00:00:de:ad:be:ef") /
81 IP(src="10.10.10.10", dst="1.1.1.1") /
82 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +010083 Raw(b'\xa5' * 100))
Neale Ranns055b2312018-07-20 01:16:04 -070084
85 #
86 # input on pg0 expect copies on pg1->11
87 # this is in SHG=0 so its flooded to all, expect the pg0 since that's
88 # the ingress link
89 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -040090 self.pg0.add_stream(p*NUM_PKTS)
Neale Ranns055b2312018-07-20 01:16:04 -070091 self.pg_enable_capture(self.pg_interfaces)
92 self.pg_start()
93
94 for i in self.pg_interfaces[1:12]:
Paul Vinciguerra4271c972019-05-14 13:25:49 -040095 rx0 = i.get_capture(NUM_PKTS, timeout=1)
Neale Ranns055b2312018-07-20 01:16:04 -070096
Neale Ranns055b2312018-07-20 01:16:04 -070097 #
98 # input on pg4 (SHG=1) expect copies on pg0->3 (SHG=0)
99 # and pg8->11 (SHG=2)
100 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400101 self.pg4.add_stream(p*NUM_PKTS)
Neale Ranns055b2312018-07-20 01:16:04 -0700102 self.pg_enable_capture(self.pg_interfaces)
103 self.pg_start()
104
105 for i in self.pg_interfaces[:4]:
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400106 rx0 = i.get_capture(NUM_PKTS, timeout=1)
Neale Ranns055b2312018-07-20 01:16:04 -0700107 for i in self.pg_interfaces[8:12]:
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400108 rx0 = i.get_capture(NUM_PKTS, timeout=1)
Neale Ranns055b2312018-07-20 01:16:04 -0700109 for i in self.pg_interfaces[4:8]:
110 i.assert_nothing_captured(remark="Different SH group")
111
112 #
113 # An IP route so the packet that hits the BVI is sent out of pg12
114 #
115 ip_route = VppIpRoute(self, "1.1.1.1", 32,
116 [VppRoutePath(self.pg12.remote_ip4,
117 self.pg12.sw_if_index)])
118 ip_route.add_vpp_config()
119
120 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
121
122 #
123 # input on pg0 expect copies on pg1->12
124 # this is in SHG=0 so its flooded to all, expect the pg0 since that's
125 # the ingress link
126 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400127 self.pg0.add_stream(p*NUM_PKTS)
Neale Ranns055b2312018-07-20 01:16:04 -0700128 self.pg_enable_capture(self.pg_interfaces)
129 self.pg_start()
130
131 for i in self.pg_interfaces[1:]:
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400132 rx0 = i.get_capture(NUM_PKTS, timeout=1)
Neale Ranns055b2312018-07-20 01:16:04 -0700133
134 #
135 # input on pg4 (SHG=1) expect copies on pg0->3 (SHG=0)
136 # and pg8->12 (SHG=2)
137 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400138 self.pg4.add_stream(p*NUM_PKTS)
Neale Ranns055b2312018-07-20 01:16:04 -0700139 self.pg_enable_capture(self.pg_interfaces)
140 self.pg_start()
141
142 for i in self.pg_interfaces[:4]:
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400143 rx0 = i.get_capture(NUM_PKTS, timeout=1)
Neale Ranns055b2312018-07-20 01:16:04 -0700144 for i in self.pg_interfaces[8:13]:
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400145 rx0 = i.get_capture(NUM_PKTS, timeout=1)
Neale Ranns055b2312018-07-20 01:16:04 -0700146 for i in self.pg_interfaces[4:8]:
147 i.assert_nothing_captured(remark="Different SH group")
148
149 #
150 # cleanup
151 #
152 for i in self.pg_interfaces[:12]:
Ole Troana5b2eec2019-03-11 19:23:25 +0100153 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
154 bd_id=1, enable=0)
Neale Ranns192b13f2019-03-15 02:16:20 -0700155 for i in self.bvi_interfaces:
Ole Troana5b2eec2019-03-11 19:23:25 +0100156 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
157 bd_id=1, shg=2,
Neale Rannsb4743802018-09-05 09:13:57 -0700158 port_type=L2_PORT_TYPE.BVI,
159 enable=0)
160
Ole Troana5b2eec2019-03-11 19:23:25 +0100161 self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
Neale Rannsb4743802018-09-05 09:13:57 -0700162
Neale Rannsb9fa29d2018-10-02 07:27:02 -0700163 def test_flood_one(self):
164 """ L2 no-Flood Test """
165
166 #
167 # Create a single bridge Domain
168 #
Ole Troana5b2eec2019-03-11 19:23:25 +0100169 self.vapi.bridge_domain_add_del(bd_id=1)
Neale Rannsb9fa29d2018-10-02 07:27:02 -0700170
171 #
172 # add 2 interfaces to the BD. this means a flood goes to only
173 # one member
174 #
175 for i in self.pg_interfaces[:2]:
Ole Troana5b2eec2019-03-11 19:23:25 +0100176 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
177 bd_id=1, shg=0)
Neale Rannsb9fa29d2018-10-02 07:27:02 -0700178
179 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
180 src="00:00:de:ad:be:ef") /
181 IP(src="10.10.10.10", dst="1.1.1.1") /
182 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +0100183 Raw(b'\xa5' * 100))
Neale Rannsb9fa29d2018-10-02 07:27:02 -0700184
185 #
186 # input on pg0 expect copies on pg1
187 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400188 self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
Neale Rannsb9fa29d2018-10-02 07:27:02 -0700189
190 #
191 # cleanup
192 #
193 for i in self.pg_interfaces[:2]:
Ole Troana5b2eec2019-03-11 19:23:25 +0100194 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
195 bd_id=1, enable=0)
196 self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
Neale Rannsb9fa29d2018-10-02 07:27:02 -0700197
Neale Rannsb4743802018-09-05 09:13:57 -0700198 def test_uu_fwd(self):
199 """ UU Flood """
200
201 #
202 # Create a single bridge Domain
203 #
Ole Troana5b2eec2019-03-11 19:23:25 +0100204 self.vapi.bridge_domain_add_del(bd_id=1, uu_flood=1)
Neale Rannsb4743802018-09-05 09:13:57 -0700205
206 #
207 # add each interface to the BD. 3 interfaces per split horizon group
208 #
209 for i in self.pg_interfaces[0:4]:
Ole Troana5b2eec2019-03-11 19:23:25 +0100210 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
211 bd_id=1, shg=0)
Neale Rannsb4743802018-09-05 09:13:57 -0700212
213 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700214 # an unknown unicast and broadcast packets
Neale Rannsb4743802018-09-05 09:13:57 -0700215 #
216 p_uu = (Ether(dst="00:00:00:c1:5c:00",
217 src="00:00:de:ad:be:ef") /
218 IP(src="10.10.10.10", dst="1.1.1.1") /
219 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +0100220 Raw(b'\xa5' * 100))
Neale Rannsd29cc882018-10-10 15:55:01 +0000221 p_bm = (Ether(dst="ff:ff:ff:ff:ff:ff",
222 src="00:00:de:ad:be:ef") /
223 IP(src="10.10.10.10", dst="1.1.1.1") /
224 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +0100225 Raw(b'\xa5' * 100))
Neale Rannsb4743802018-09-05 09:13:57 -0700226
227 #
228 # input on pg0, expected copies on pg1->4
229 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400230 self.pg0.add_stream(p_uu*NUM_PKTS)
Neale Rannsb4743802018-09-05 09:13:57 -0700231 self.pg_enable_capture(self.pg_interfaces)
232 self.pg_start()
233
234 for i in self.pg_interfaces[1:4]:
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400235 rx0 = i.get_capture(NUM_PKTS, timeout=1)
Neale Rannsb4743802018-09-05 09:13:57 -0700236
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400237 self.pg0.add_stream(p_bm*NUM_PKTS)
Neale Rannsd29cc882018-10-10 15:55:01 +0000238 self.pg_enable_capture(self.pg_interfaces)
239 self.pg_start()
240
241 for i in self.pg_interfaces[1:4]:
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400242 rx0 = i.get_capture(NUM_PKTS, timeout=1)
Neale Rannsd29cc882018-10-10 15:55:01 +0000243
Neale Rannsb4743802018-09-05 09:13:57 -0700244 #
245 # use pg8 as the uu-fwd interface
246 #
Ole Troana5b2eec2019-03-11 19:23:25 +0100247 self.vapi.sw_interface_set_l2_bridge(
248 rx_sw_if_index=self.pg8.sw_if_index, bd_id=1, shg=0,
249 port_type=L2_PORT_TYPE.UU_FWD)
Neale Rannsb4743802018-09-05 09:13:57 -0700250
251 #
252 # expect the UU packet on the uu-fwd interface and not be flooded
253 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400254 self.pg0.add_stream(p_uu*NUM_PKTS)
Neale Rannsb4743802018-09-05 09:13:57 -0700255 self.pg_enable_capture(self.pg_interfaces)
256 self.pg_start()
257
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400258 rx0 = self.pg8.get_capture(NUM_PKTS, timeout=1)
Neale Rannsb4743802018-09-05 09:13:57 -0700259
260 for i in self.pg_interfaces[0:4]:
261 i.assert_nothing_captured(remark="UU not flooded")
262
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400263 self.pg0.add_stream(p_bm*NUM_PKTS)
Neale Rannsd29cc882018-10-10 15:55:01 +0000264 self.pg_enable_capture(self.pg_interfaces)
265 self.pg_start()
266
267 for i in self.pg_interfaces[1:4]:
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400268 rx0 = i.get_capture(NUM_PKTS, timeout=1)
Neale Rannsd29cc882018-10-10 15:55:01 +0000269
Neale Rannsb4743802018-09-05 09:13:57 -0700270 #
271 # remove the uu-fwd interface and expect UU to be flooded again
272 #
Ole Troana5b2eec2019-03-11 19:23:25 +0100273 self.vapi.sw_interface_set_l2_bridge(
274 rx_sw_if_index=self.pg8.sw_if_index, bd_id=1, shg=0,
275 port_type=L2_PORT_TYPE.UU_FWD, enable=0)
Neale Rannsb4743802018-09-05 09:13:57 -0700276
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400277 self.pg0.add_stream(p_uu*NUM_PKTS)
Neale Rannsb4743802018-09-05 09:13:57 -0700278 self.pg_enable_capture(self.pg_interfaces)
279 self.pg_start()
280
281 for i in self.pg_interfaces[1:4]:
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400282 rx0 = i.get_capture(NUM_PKTS, timeout=1)
Neale Rannsb4743802018-09-05 09:13:57 -0700283
284 #
285 # change the BD config to not support UU-flood
286 #
Ole Troana5b2eec2019-03-11 19:23:25 +0100287 self.vapi.bridge_flags(bd_id=1, is_set=0, flags=BRIDGE_FLAGS.UU_FLOOD)
Neale Rannsb4743802018-09-05 09:13:57 -0700288
289 self.send_and_assert_no_replies(self.pg0, p_uu)
290
291 #
292 # re-add the uu-fwd interface
293 #
Ole Troana5b2eec2019-03-11 19:23:25 +0100294 self.vapi.sw_interface_set_l2_bridge(
295 rx_sw_if_index=self.pg8.sw_if_index, bd_id=1, shg=0,
296 port_type=L2_PORT_TYPE.UU_FWD)
Neale Rannsb4743802018-09-05 09:13:57 -0700297 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
298
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400299 self.pg0.add_stream(p_uu*NUM_PKTS)
Neale Rannsb4743802018-09-05 09:13:57 -0700300 self.pg_enable_capture(self.pg_interfaces)
301 self.pg_start()
302
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400303 rx0 = self.pg8.get_capture(NUM_PKTS, timeout=1)
Neale Rannsb4743802018-09-05 09:13:57 -0700304
305 for i in self.pg_interfaces[0:4]:
306 i.assert_nothing_captured(remark="UU not flooded")
307
308 #
309 # remove the uu-fwd interface
310 #
Ole Troana5b2eec2019-03-11 19:23:25 +0100311 self.vapi.sw_interface_set_l2_bridge(
312 rx_sw_if_index=self.pg8.sw_if_index, bd_id=1, shg=0,
313 port_type=L2_PORT_TYPE.UU_FWD, enable=0)
Neale Rannsb4743802018-09-05 09:13:57 -0700314 self.send_and_assert_no_replies(self.pg0, p_uu)
315
316 #
317 # cleanup
318 #
319 for i in self.pg_interfaces[:4]:
Ole Troana5b2eec2019-03-11 19:23:25 +0100320 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=i.sw_if_index,
321 bd_id=1, enable=0)
Neale Ranns055b2312018-07-20 01:16:04 -0700322
Ole Troana5b2eec2019-03-11 19:23:25 +0100323 self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
Neale Ranns055b2312018-07-20 01:16:04 -0700324
325
326if __name__ == '__main__':
327 unittest.main(testRunner=VppTestRunner)