blob: 0f9c5121f6d780ba149656f927288eb30bb962ea [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Eyal Baricef1e2a2018-06-18 13:01:59 +03002
3import socket
4import unittest
5from framework import VppTestCase, VppTestRunner
6from template_bd import BridgeDomain
7
8from scapy.layers.l2 import Ether
Artem Glazychev839dcc02020-12-01 02:39:21 +07009from scapy.packet import Raw, bind_layers
Vladimir Isaev698eb872020-05-21 16:34:17 +030010from scapy.layers.inet6 import IP, IPv6, UDP
Eyal Baricef1e2a2018-06-18 13:01:59 +030011from scapy.layers.vxlan import VXLAN
Paul Vinciguerra2f156312020-05-02 22:34:40 -040012
13import util
Neale Ranns097fa662018-05-01 05:17:55 -070014from vpp_ip_route import VppIpRoute, VppRoutePath
Jakub Grajciar7c0eb562020-03-02 13:55:31 +010015from vpp_vxlan_tunnel import VppVxlanTunnel
Neale Ranns097fa662018-05-01 05:17:55 -070016from vpp_ip import INVALID_INDEX
Eyal Baricef1e2a2018-06-18 13:01:59 +030017
18
Eyal Baridd47eca2018-07-08 08:15:56 +030019class TestVxlan6(BridgeDomain, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020020 """VXLAN over IPv6 Test Case"""
Eyal Baricef1e2a2018-06-18 13:01:59 +030021
22 def __init__(self, *args):
23 BridgeDomain.__init__(self)
24 VppTestCase.__init__(self, *args)
25
26 def encapsulate(self, pkt, vni):
27 """
28 Encapsulate the original payload frame by adding VXLAN header with its
29 UDP, IP and Ethernet fields
30 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020031 return (
32 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
33 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6)
34 / UDP(sport=self.dport, dport=self.dport, chksum=0)
35 / VXLAN(vni=vni, flags=self.flags)
36 / pkt
37 )
Eyal Baricef1e2a2018-06-18 13:01:59 +030038
39 @classmethod
40 def ip_range(cls, s, e):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020041 """range of remote ip's"""
42 tmp = cls.pg0.remote_ip6.rsplit(":", 1)[0]
Eyal Baricef1e2a2018-06-18 13:01:59 +030043 return ("%s:%x" % (tmp, i) for i in range(s, e))
44
45 def encap_mcast(self, pkt, src_ip, src_mac, vni):
46 """
47 Encapsulate the original payload frame by adding VXLAN header with its
48 UDP, IP and Ethernet fields
49 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020050 return (
51 Ether(src=src_mac, dst=self.mcast_mac)
52 / IPv6(src=src_ip, dst=self.mcast_ip6)
53 / UDP(sport=self.dport, dport=self.dport, chksum=0)
54 / VXLAN(vni=vni, flags=self.flags)
55 / pkt
56 )
Eyal Baricef1e2a2018-06-18 13:01:59 +030057
58 def decapsulate(self, pkt):
59 """
60 Decapsulate the original payload frame by removing VXLAN header
61 """
62 # check if is set I flag
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020063 self.assertEqual(pkt[VXLAN].flags, int("0x8", 16))
Eyal Baricef1e2a2018-06-18 13:01:59 +030064 return pkt[VXLAN].payload
65
66 # Method for checking VXLAN encapsulation.
67 #
68 def check_encapsulation(self, pkt, vni, local_only=False, mcast_pkt=False):
69 # TODO: add error messages
70 # Verify source MAC is VPP_MAC and destination MAC is MY_MAC resolved
71 # by VPP using ARP.
72 self.assertEqual(pkt[Ether].src, self.pg0.local_mac)
73 if not local_only:
74 if not mcast_pkt:
75 self.assertEqual(pkt[Ether].dst, self.pg0.remote_mac)
76 else:
77 self.assertEqual(pkt[Ether].dst, type(self).mcast_mac)
78 # Verify VXLAN tunnel source IP is VPP_IP and destination IP is MY_IP.
79 self.assertEqual(pkt[IPv6].src, self.pg0.local_ip6)
80 if not local_only:
81 if not mcast_pkt:
82 self.assertEqual(pkt[IPv6].dst, self.pg0.remote_ip6)
83 else:
84 self.assertEqual(pkt[IPv6].dst, type(self).mcast_ip6)
85 # Verify UDP destination port is VXLAN 4789, source UDP port could be
86 # arbitrary.
Artem Glazychev839dcc02020-12-01 02:39:21 +070087 self.assertEqual(pkt[UDP].dport, self.dport)
Vladimir Isaev698eb872020-05-21 16:34:17 +030088 # Verify UDP checksum
89 self.assert_udp_checksum_valid(pkt, ignore_zero_checksum=False)
Eyal Baricef1e2a2018-06-18 13:01:59 +030090 # Verify VNI
91 self.assertEqual(pkt[VXLAN].vni, vni)
92
93 @classmethod
Artem Glazychev839dcc02020-12-01 02:39:21 +070094 def create_vxlan_flood_test_bd(cls, vni, n_ucast_tunnels, port):
Eyal Baricef1e2a2018-06-18 13:01:59 +030095 # Create 10 ucast vxlan tunnels under bd
96 start = 10
97 end = start + n_ucast_tunnels
Eyal Baricef1e2a2018-06-18 13:01:59 +030098 for dest_ip6 in cls.ip_range(start, end):
Eyal Baricef1e2a2018-06-18 13:01:59 +030099 # add host route so dest ip will not be resolved
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200100 rip = VppIpRoute(
101 cls,
102 dest_ip6,
103 128,
104 [VppRoutePath(cls.pg0.remote_ip6, INVALID_INDEX)],
105 register=False,
106 )
Neale Ranns097fa662018-05-01 05:17:55 -0700107 rip.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200108 r = VppVxlanTunnel(
109 cls,
110 src=cls.pg0.local_ip6,
111 src_port=port,
112 dst_port=port,
113 dst=dest_ip6,
114 vni=vni,
115 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100116 r.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700117 cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index, bd_id=vni)
Eyal Baricef1e2a2018-06-18 13:01:59 +0300118
119 @classmethod
120 def add_mcast_tunnels_load(cls):
121 cls.add_del_mcast_tunnels_load(is_add=1)
122
123 @classmethod
124 def del_mcast_tunnels_load(cls):
125 cls.add_del_mcast_tunnels_load(is_add=0)
126
127 # Class method to start the VXLAN test case.
128 # Overrides setUpClass method in VppTestCase class.
129 # Python try..except statement is used to ensure that the tear down of
130 # the class will be executed even if exception is raised.
131 # @param cls The class pointer.
132 @classmethod
133 def setUpClass(cls):
Eyal Baridd47eca2018-07-08 08:15:56 +0300134 super(TestVxlan6, cls).setUpClass()
Eyal Baricef1e2a2018-06-18 13:01:59 +0300135
136 try:
Eyal Baricef1e2a2018-06-18 13:01:59 +0300137 cls.flags = 0x8
138
139 # Create 2 pg interfaces.
140 cls.create_pg_interfaces(range(4))
141 for pg in cls.pg_interfaces:
142 pg.admin_up()
143
Paul Vinciguerra2f156312020-05-02 22:34:40 -0400144 # Configure IPv6 addresses on VPP pg0.
Eyal Baricef1e2a2018-06-18 13:01:59 +0300145 cls.pg0.config_ip6()
146
147 # Resolve MAC address for VPP's IP address on pg0.
148 cls.pg0.resolve_ndp()
149
Paul Vinciguerra2f156312020-05-02 22:34:40 -0400150 # Our Multicast address
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200151 cls.mcast_ip6 = "ff0e::1"
Paul Vinciguerra2f156312020-05-02 22:34:40 -0400152 cls.mcast_mac = util.mcast_ip_to_mac(cls.mcast_ip6)
Eyal Baricef1e2a2018-06-18 13:01:59 +0300153 except Exception:
Eyal Baridd47eca2018-07-08 08:15:56 +0300154 super(TestVxlan6, cls).tearDownClass()
Eyal Baricef1e2a2018-06-18 13:01:59 +0300155 raise
156
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800157 @classmethod
158 def tearDownClass(cls):
159 super(TestVxlan6, cls).tearDownClass()
160
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100161 def setUp(self):
162 super(TestVxlan6, self).setUp()
Artem Glazychev839dcc02020-12-01 02:39:21 +0700163
164 def createVxLANInterfaces(self, port=4789):
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100165 # Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1
166 # into BD.
Artem Glazychev839dcc02020-12-01 02:39:21 +0700167 self.dport = port
168
Neale Ranns91fd9102020-04-03 07:46:28 +0000169 self.single_tunnel_vni = 0x12345
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100170 self.single_tunnel_bd = 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200171 r = VppVxlanTunnel(
172 self,
173 src=self.pg0.local_ip6,
174 dst=self.pg0.remote_ip6,
175 src_port=self.dport,
176 dst_port=self.dport,
177 vni=self.single_tunnel_vni,
178 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100179 r.add_vpp_config()
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100180 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200181 rx_sw_if_index=r.sw_if_index, bd_id=self.single_tunnel_bd
182 )
183 self.vapi.sw_interface_set_l2_bridge(
184 rx_sw_if_index=self.pg1.sw_if_index, bd_id=self.single_tunnel_bd
185 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100186
187 # Setup vni 2 to test multicast flooding
188 self.n_ucast_tunnels = 10
189 self.mcast_flood_bd = 2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200190 self.create_vxlan_flood_test_bd(
191 self.mcast_flood_bd, self.n_ucast_tunnels, self.dport
192 )
193 r = VppVxlanTunnel(
194 self,
195 src=self.pg0.local_ip6,
196 dst=self.mcast_ip6,
197 src_port=self.dport,
198 dst_port=self.dport,
199 mcast_sw_if_index=1,
200 vni=self.mcast_flood_bd,
201 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100202 r.add_vpp_config()
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100203 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200204 rx_sw_if_index=r.sw_if_index, bd_id=self.mcast_flood_bd
205 )
206 self.vapi.sw_interface_set_l2_bridge(
207 rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.mcast_flood_bd
208 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100209
210 # Setup vni 3 to test unicast flooding
211 self.ucast_flood_bd = 3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200212 self.create_vxlan_flood_test_bd(
213 self.ucast_flood_bd, self.n_ucast_tunnels, self.dport
214 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100215 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200216 rx_sw_if_index=self.pg3.sw_if_index, bd_id=self.ucast_flood_bd
217 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100218
Artem Glazychev839dcc02020-12-01 02:39:21 +0700219 # Set scapy listen custom port for VxLAN
220 bind_layers(UDP, VXLAN, dport=self.dport)
221
Eyal Baricef1e2a2018-06-18 13:01:59 +0300222 # Method to define VPP actions before tear down of the test case.
223 # Overrides tearDown method in VppTestCase class.
224 # @param self The object pointer.
225 def tearDown(self):
Eyal Baridd47eca2018-07-08 08:15:56 +0300226 super(TestVxlan6, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700227
228 def show_commands_at_teardown(self):
229 self.logger.info(self.vapi.cli("show bridge-domain 1 detail"))
230 self.logger.info(self.vapi.cli("show bridge-domain 2 detail"))
231 self.logger.info(self.vapi.cli("show bridge-domain 3 detail"))
232 self.logger.info(self.vapi.cli("show vxlan tunnel"))
Eyal Baricef1e2a2018-06-18 13:01:59 +0300233
Artem Glazychev839dcc02020-12-01 02:39:21 +0700234 def encap_fragmented_packet(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200235 frame = (
236 Ether(src="00:00:00:00:00:02", dst="00:00:00:00:00:01")
237 / IP(src="4.3.2.1", dst="1.2.3.4")
238 / UDP(sport=20000, dport=10000)
239 / Raw(b"\xa5" * 1000)
240 )
Vladimir Isaev698eb872020-05-21 16:34:17 +0300241
242 frags = util.fragment_rfc791(frame, 400)
243
244 self.pg1.add_stream(frags)
245
246 self.pg0.enable_capture()
247
248 self.pg_start()
249
250 out = self.pg0.get_capture(3)
251
252 payload = []
253 for pkt in out:
254 payload.append(self.decapsulate(pkt))
255 self.check_encapsulation(pkt, self.single_tunnel_vni)
256
257 reassembled = util.reassemble4(payload)
258
259 self.assertEqual(Ether(raw(frame))[IP], reassembled[IP])
260
Artem Glazychev839dcc02020-12-01 02:39:21 +0700261 """
262 Tests with default port (4789)
263 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200264
Artem Glazychev839dcc02020-12-01 02:39:21 +0700265 def test_decap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200266 """Decapsulation test
Artem Glazychev839dcc02020-12-01 02:39:21 +0700267 from BridgeDoman
268 """
269 self.createVxLANInterfaces()
270 super(TestVxlan6, self).test_decap()
271
272 def test_encap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200273 """Encapsulation test
Artem Glazychev839dcc02020-12-01 02:39:21 +0700274 from BridgeDoman
275 """
276 self.createVxLANInterfaces()
277 super(TestVxlan6, self).test_encap()
278
279 def test_encap_fragmented_packet(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200280 """Encapsulation test send fragments from pg1
Artem Glazychev839dcc02020-12-01 02:39:21 +0700281 Verify receipt of encapsulated frames on pg0
282 """
283 self.createVxLANInterfaces()
284 self.encap_fragmented_packet()
285
286 def test_ucast_flood(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200287 """Unicast flood test
Artem Glazychev839dcc02020-12-01 02:39:21 +0700288 from BridgeDoman
289 """
290 self.createVxLANInterfaces()
291 super(TestVxlan6, self).test_ucast_flood()
292
293 def test_mcast_flood(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200294 """Multicast flood test
Artem Glazychev839dcc02020-12-01 02:39:21 +0700295 from BridgeDoman
296 """
297 self.createVxLANInterfaces()
298 super(TestVxlan6, self).test_mcast_flood()
299
300 def test_mcast_rcv(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200301 """Multicast receive test
Artem Glazychev839dcc02020-12-01 02:39:21 +0700302 from BridgeDoman
303 """
304 self.createVxLANInterfaces()
305 super(TestVxlan6, self).test_mcast_rcv()
306
307 """
308 Tests with custom port
309 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200310
Artem Glazychev839dcc02020-12-01 02:39:21 +0700311 def test_decap_custom_port(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200312 """Decapsulation test custom port
Artem Glazychev839dcc02020-12-01 02:39:21 +0700313 from BridgeDoman
314 """
315 self.createVxLANInterfaces(1111)
316 super(TestVxlan6, self).test_decap()
317
318 def test_encap_custom_port(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200319 """Encapsulation test custom port
Artem Glazychev839dcc02020-12-01 02:39:21 +0700320 from BridgeDoman
321 """
322 self.createVxLANInterfaces(1111)
323 super(TestVxlan6, self).test_encap()
324
325 def test_ucast_flood_custom_port(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200326 """Unicast flood test custom port
Artem Glazychev839dcc02020-12-01 02:39:21 +0700327 from BridgeDoman
328 """
329 self.createVxLANInterfaces(1111)
330 super(TestVxlan6, self).test_ucast_flood()
331
332 def test_mcast_flood_custom_port(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200333 """Multicast flood test custom port
Artem Glazychev839dcc02020-12-01 02:39:21 +0700334 from BridgeDoman
335 """
336 self.createVxLANInterfaces(1111)
337 super(TestVxlan6, self).test_mcast_flood()
338
339 def test_mcast_rcv_custom_port(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200340 """Multicast receive test custom port
Artem Glazychev839dcc02020-12-01 02:39:21 +0700341 from BridgeDoman
342 """
343 self.createVxLANInterfaces(1111)
344 super(TestVxlan6, self).test_mcast_rcv()
345
Eyal Baricef1e2a2018-06-18 13:01:59 +0300346
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200347if __name__ == "__main__":
Eyal Baricef1e2a2018-06-18 13:01:59 +0300348 unittest.main(testRunner=VppTestRunner)