blob: 939a57f73438c2aaecee3e79cdbe0699fbe12f82 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Damjan Marionf56b77a2016-10-03 19:44:57 +02002
Eyal Baric4aaee12016-12-20 18:36:46 +02003import socket
Paul Vinciguerra2f156312020-05-02 22:34:40 -04004from util import ip4_range, reassemble4
Damjan Marionf56b77a2016-10-03 19:44:57 +02005import unittest
Dave Wallace8800f732023-08-31 00:47:44 -04006from framework import VppTestCase
7from asfframework import VppTestRunner
Damjan Marionf56b77a2016-10-03 19:44:57 +02008from template_bd import BridgeDomain
9
snaramre5d4b8912019-12-13 23:39:35 +000010from scapy.layers.l2 import Ether
Artem Glazychev23e5f092022-02-21 17:51:29 +070011from scapy.layers.l2 import ARP
Artem Glazychev839dcc02020-12-01 02:39:21 +070012from scapy.packet import Raw, bind_layers
Damjan Marionf56b77a2016-10-03 19:44:57 +020013from scapy.layers.inet import IP, UDP
Vladislav Grishenkof2fc97a2024-01-24 20:33:12 +050014from scapy.layers.inet6 import IPv6
Matej Klottondeb69842016-12-09 15:05:46 +010015from scapy.layers.vxlan import VXLAN
Vladislav Grishenkof2fc97a2024-01-24 20:33:12 +050016from scapy.contrib.mpls import MPLS
Paul Vinciguerra2f156312020-05-02 22:34:40 -040017
18import util
Neale Ranns097fa662018-05-01 05:17:55 -070019from vpp_ip_route import VppIpRoute, VppRoutePath
Jakub Grajciar7c0eb562020-03-02 13:55:31 +010020from vpp_vxlan_tunnel import VppVxlanTunnel
Neale Ranns097fa662018-05-01 05:17:55 -070021from vpp_ip import INVALID_INDEX
Artem Glazychev23e5f092022-02-21 17:51:29 +070022from vpp_neighbor import VppNeighbor
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000023from config import config
Damjan Marionf56b77a2016-10-03 19:44:57 +020024
25
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000026@unittest.skipIf("vxlan" in config.excluded_plugins, "Exclude VXLAN plugin tests")
Klement Sekeraf62ae122016-10-11 11:47:09 +020027class TestVxlan(BridgeDomain, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020028 """VXLAN Test Case"""
Damjan Marionf56b77a2016-10-03 19:44:57 +020029
Damjan Marionf56b77a2016-10-03 19:44:57 +020030 def __init__(self, *args):
31 BridgeDomain.__init__(self)
Damjan Marionf56b77a2016-10-03 19:44:57 +020032 VppTestCase.__init__(self, *args)
33
Eyal Baric4aaee12016-12-20 18:36:46 +020034 def encapsulate(self, pkt, vni):
Klement Sekeraf62ae122016-10-11 11:47:09 +020035 """
36 Encapsulate the original payload frame by adding VXLAN header with its
37 UDP, IP and Ethernet fields
38 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020039 return (
40 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
41 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
42 / UDP(sport=self.dport, dport=self.dport, chksum=0)
43 / VXLAN(vni=vni, flags=self.flags)
44 / pkt
45 )
Eyal Baric4aaee12016-12-20 18:36:46 +020046
Eyal Baricef1e2a2018-06-18 13:01:59 +030047 def ip_range(self, start, end):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020048 """range of remote ip's"""
Eyal Baricef1e2a2018-06-18 13:01:59 +030049 return ip4_range(self.pg0.remote_ip4, start, end)
50
Eyal Baric4aaee12016-12-20 18:36:46 +020051 def encap_mcast(self, pkt, src_ip, src_mac, vni):
52 """
53 Encapsulate the original payload frame by adding VXLAN header with its
54 UDP, IP and Ethernet fields
55 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020056 return (
57 Ether(src=src_mac, dst=self.mcast_mac)
58 / IP(src=src_ip, dst=self.mcast_ip4)
59 / UDP(sport=self.dport, dport=self.dport, chksum=0)
60 / VXLAN(vni=vni, flags=self.flags)
61 / pkt
62 )
Damjan Marionf56b77a2016-10-03 19:44:57 +020063
Damjan Marionf56b77a2016-10-03 19:44:57 +020064 def decapsulate(self, pkt):
Klement Sekeraf62ae122016-10-11 11:47:09 +020065 """
66 Decapsulate the original payload frame by removing VXLAN header
67 """
Matej Klottondeb69842016-12-09 15:05:46 +010068 # check if is set I flag
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020069 self.assertEqual(pkt[VXLAN].flags, int("0x8", 16))
Damjan Marionf56b77a2016-10-03 19:44:57 +020070 return pkt[VXLAN].payload
71
Klement Sekeraf62ae122016-10-11 11:47:09 +020072 # Method for checking VXLAN encapsulation.
Damjan Marionf56b77a2016-10-03 19:44:57 +020073 #
Eyal Bari6ae5ee72017-03-23 09:53:51 +020074 def check_encapsulation(self, pkt, vni, local_only=False, mcast_pkt=False):
Damjan Marionf56b77a2016-10-03 19:44:57 +020075 # TODO: add error messages
Klement Sekeraf62ae122016-10-11 11:47:09 +020076 # Verify source MAC is VPP_MAC and destination MAC is MY_MAC resolved
Damjan Marionf56b77a2016-10-03 19:44:57 +020077 # by VPP using ARP.
Klement Sekeraf62ae122016-10-11 11:47:09 +020078 self.assertEqual(pkt[Ether].src, self.pg0.local_mac)
Eyal Baric4aaee12016-12-20 18:36:46 +020079 if not local_only:
Eyal Bari6ae5ee72017-03-23 09:53:51 +020080 if not mcast_pkt:
81 self.assertEqual(pkt[Ether].dst, self.pg0.remote_mac)
82 else:
83 self.assertEqual(pkt[Ether].dst, type(self).mcast_mac)
Klement Sekeraf62ae122016-10-11 11:47:09 +020084 # Verify VXLAN tunnel source IP is VPP_IP and destination IP is MY_IP.
85 self.assertEqual(pkt[IP].src, self.pg0.local_ip4)
Eyal Baric4aaee12016-12-20 18:36:46 +020086 if not local_only:
Eyal Bari6ae5ee72017-03-23 09:53:51 +020087 if not mcast_pkt:
88 self.assertEqual(pkt[IP].dst, self.pg0.remote_ip4)
89 else:
90 self.assertEqual(pkt[IP].dst, type(self).mcast_ip4)
Klement Sekeraf62ae122016-10-11 11:47:09 +020091 # Verify UDP destination port is VXLAN 4789, source UDP port could be
Damjan Marionf56b77a2016-10-03 19:44:57 +020092 # arbitrary.
Artem Glazychev839dcc02020-12-01 02:39:21 +070093 self.assertEqual(pkt[UDP].dport, self.dport)
Vladimir Isaev698eb872020-05-21 16:34:17 +030094 # Verify UDP checksum
95 self.assert_udp_checksum_valid(pkt)
Eyal Baric4aaee12016-12-20 18:36:46 +020096 # Verify VNI
97 self.assertEqual(pkt[VXLAN].vni, vni)
98
Eyal Baric4aaee12016-12-20 18:36:46 +020099 @classmethod
Artem Glazychev839dcc02020-12-01 02:39:21 +0700100 def create_vxlan_flood_test_bd(cls, vni, n_ucast_tunnels, port):
Eyal Baric4aaee12016-12-20 18:36:46 +0200101 # Create 10 ucast vxlan tunnels under bd
102 ip_range_start = 10
Eyal Barid81da8c2017-01-11 13:39:54 +0200103 ip_range_end = ip_range_start + n_ucast_tunnels
Neale Ranns097fa662018-05-01 05:17:55 -0700104 next_hop_address = cls.pg0.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200105 for dest_ip4 in ip4_range(next_hop_address, ip_range_start, ip_range_end):
Paul Vinciguerra2f156312020-05-02 22:34:40 -0400106 # add host route so dest_ip4 will not be resolved
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200107 rip = VppIpRoute(
108 cls,
109 dest_ip4,
110 32,
111 [VppRoutePath(next_hop_address, INVALID_INDEX)],
112 register=False,
113 )
Neale Ranns097fa662018-05-01 05:17:55 -0700114 rip.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700115
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200116 r = VppVxlanTunnel(
117 cls,
118 src=cls.pg0.local_ip4,
119 src_port=port,
120 dst_port=port,
121 dst=dest_ip4,
122 vni=vni,
123 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100124 r.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700125 cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index, bd_id=vni)
Eyal Baric4aaee12016-12-20 18:36:46 +0200126
127 @classmethod
Artem Glazychev839dcc02020-12-01 02:39:21 +0700128 def add_del_shared_mcast_dst_load(cls, port, is_add):
Eyal Bari4bce2902017-01-16 12:02:46 +0200129 """
130 add or del tunnels sharing the same mcast dst
131 to test vxlan ref_count mechanism
132 """
Gabriel Ganne7e665d62017-11-17 09:18:53 +0100133 n_shared_dst_tunnels = 20
Eyal Bari4bce2902017-01-16 12:02:46 +0200134 vni_start = 10000
135 vni_end = vni_start + n_shared_dst_tunnels
136 for vni in range(vni_start, vni_end):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200137 r = VppVxlanTunnel(
138 cls,
139 src=cls.pg0.local_ip4,
140 src_port=port,
141 dst_port=port,
142 dst=cls.mcast_ip4,
143 mcast_sw_if_index=1,
144 vni=vni,
145 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100146 if is_add:
147 r.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200148 if r.sw_if_index == 0xFFFFFFFF:
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100149 raise ValueError("bad sw_if_index: ~0")
150 else:
151 r.remove_vpp_config()
Eyal Bari4bce2902017-01-16 12:02:46 +0200152
153 @classmethod
Artem Glazychev839dcc02020-12-01 02:39:21 +0700154 def add_shared_mcast_dst_load(cls, port):
155 cls.add_del_shared_mcast_dst_load(port=port, is_add=1)
Eyal Bari4bce2902017-01-16 12:02:46 +0200156
157 @classmethod
Artem Glazychev839dcc02020-12-01 02:39:21 +0700158 def del_shared_mcast_dst_load(cls, port):
159 cls.add_del_shared_mcast_dst_load(port=port, is_add=0)
Eyal Bari4bce2902017-01-16 12:02:46 +0200160
161 @classmethod
Artem Glazychev839dcc02020-12-01 02:39:21 +0700162 def add_del_mcast_tunnels_load(cls, port, is_add):
Eyal Bari4bce2902017-01-16 12:02:46 +0200163 """
164 add or del tunnels to test vxlan stability
165 """
166 n_distinct_dst_tunnels = 200
Eyal Baric4aaee12016-12-20 18:36:46 +0200167 ip_range_start = 10
Eyal Bari4bce2902017-01-16 12:02:46 +0200168 ip_range_end = ip_range_start + n_distinct_dst_tunnels
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200169 for dest_ip4 in ip4_range(cls.mcast_ip4, ip_range_start, ip_range_end):
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100170 vni = bytearray(socket.inet_pton(socket.AF_INET, dest_ip4))[3]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200171 r = VppVxlanTunnel(
172 cls,
173 src=cls.pg0.local_ip4,
174 src_port=port,
175 dst_port=port,
176 dst=dest_ip4,
177 mcast_sw_if_index=1,
178 vni=vni,
179 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100180 if is_add:
181 r.add_vpp_config()
182 else:
183 r.remove_vpp_config()
Eyal Baric4aaee12016-12-20 18:36:46 +0200184
185 @classmethod
Artem Glazychev839dcc02020-12-01 02:39:21 +0700186 def add_mcast_tunnels_load(cls, port):
187 cls.add_del_mcast_tunnels_load(port=port, is_add=1)
Eyal Baric4aaee12016-12-20 18:36:46 +0200188
189 @classmethod
Artem Glazychev839dcc02020-12-01 02:39:21 +0700190 def del_mcast_tunnels_load(cls, port):
191 cls.add_del_mcast_tunnels_load(port=port, is_add=0)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200192
Klement Sekeraf62ae122016-10-11 11:47:09 +0200193 # Class method to start the VXLAN test case.
Damjan Marionf56b77a2016-10-03 19:44:57 +0200194 # Overrides setUpClass method in VppTestCase class.
195 # Python try..except statement is used to ensure that the tear down of
196 # the class will be executed even if exception is raised.
197 # @param cls The class pointer.
198 @classmethod
199 def setUpClass(cls):
200 super(TestVxlan, cls).setUpClass()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200201
Klement Sekeraf62ae122016-10-11 11:47:09 +0200202 try:
Matej Klottondeb69842016-12-09 15:05:46 +0100203 cls.flags = 0x8
Klement Sekeraf62ae122016-10-11 11:47:09 +0200204
205 # Create 2 pg interfaces.
Eyal Baric4aaee12016-12-20 18:36:46 +0200206 cls.create_pg_interfaces(range(4))
207 for pg in cls.pg_interfaces:
208 pg.admin_up()
Klement Sekeraf62ae122016-10-11 11:47:09 +0200209
210 # Configure IPv4 addresses on VPP pg0.
211 cls.pg0.config_ip4()
212
213 # Resolve MAC address for VPP's IP address on pg0.
214 cls.pg0.resolve_arp()
215
Eyal Baric4aaee12016-12-20 18:36:46 +0200216 # Our Multicast address
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200217 cls.mcast_ip4 = "239.1.1.1"
Paul Vinciguerra2f156312020-05-02 22:34:40 -0400218 cls.mcast_mac = util.mcast_ip_to_mac(cls.mcast_ip4)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200219 except Exception:
Paul Vinciguerra2f156312020-05-02 22:34:40 -0400220 cls.tearDownClass()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200221 raise
222
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700223 @classmethod
224 def tearDownClass(cls):
225 super(TestVxlan, cls).tearDownClass()
226
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100227 def setUp(self):
228 super(TestVxlan, self).setUp()
Artem Glazychev839dcc02020-12-01 02:39:21 +0700229
230 def createVxLANInterfaces(self, port=4789):
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100231 # Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1
232 # into BD.
Artem Glazychev839dcc02020-12-01 02:39:21 +0700233 self.dport = port
234
Neale Ranns91fd9102020-04-03 07:46:28 +0000235 self.single_tunnel_vni = 0x12345
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100236 self.single_tunnel_bd = 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200237 r = VppVxlanTunnel(
238 self,
239 src=self.pg0.local_ip4,
240 dst=self.pg0.remote_ip4,
241 src_port=self.dport,
242 dst_port=self.dport,
243 vni=self.single_tunnel_vni,
244 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100245 r.add_vpp_config()
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100246 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200247 rx_sw_if_index=r.sw_if_index, bd_id=self.single_tunnel_bd
248 )
249 self.vapi.sw_interface_set_l2_bridge(
250 rx_sw_if_index=self.pg1.sw_if_index, bd_id=self.single_tunnel_bd
251 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100252
253 # Setup vni 2 to test multicast flooding
254 self.n_ucast_tunnels = 10
255 self.mcast_flood_bd = 2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200256 self.create_vxlan_flood_test_bd(
257 self.mcast_flood_bd, self.n_ucast_tunnels, self.dport
258 )
259 r = VppVxlanTunnel(
260 self,
261 src=self.pg0.local_ip4,
262 dst=self.mcast_ip4,
263 src_port=self.dport,
264 dst_port=self.dport,
265 mcast_sw_if_index=1,
266 vni=self.mcast_flood_bd,
267 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100268 r.add_vpp_config()
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100269 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200270 rx_sw_if_index=r.sw_if_index, bd_id=self.mcast_flood_bd
271 )
272 self.vapi.sw_interface_set_l2_bridge(
273 rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.mcast_flood_bd
274 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100275
276 # Add and delete mcast tunnels to check stability
Artem Glazychev839dcc02020-12-01 02:39:21 +0700277 self.add_shared_mcast_dst_load(self.dport)
278 self.add_mcast_tunnels_load(self.dport)
279 self.del_shared_mcast_dst_load(self.dport)
280 self.del_mcast_tunnels_load(self.dport)
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100281
282 # Setup vni 3 to test unicast flooding
283 self.ucast_flood_bd = 3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200284 self.create_vxlan_flood_test_bd(
285 self.ucast_flood_bd, self.n_ucast_tunnels, self.dport
286 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100287 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200288 rx_sw_if_index=self.pg3.sw_if_index, bd_id=self.ucast_flood_bd
289 )
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100290
Artem Glazychev839dcc02020-12-01 02:39:21 +0700291 # Set scapy listen custom port for VxLAN
292 bind_layers(UDP, VXLAN, dport=self.dport)
Jakub Grajciar7c0eb562020-03-02 13:55:31 +0100293
Vladislav Grishenkof2fc97a2024-01-24 20:33:12 +0500294 def encap_packets(self):
295 def encap_frames(frame, n=10):
296 frames = []
297
298 # Provide IP flow hash difference.
299 for i in range(n):
300 p = frame.copy()
301 p[UDP].dport += i
302 frames.append(p)
303
304 self.pg1.add_stream(frames)
305
306 self.pg0.enable_capture()
307 self.pg_start()
308
309 # Pick received frames and check if they're correctly encapsulated.
310 out = self.pg0.get_capture(n)
311 sports = set()
312 for i in range(n):
313 pkt = out[i]
314 self.check_encapsulation(pkt, self.single_tunnel_vni)
315
316 payload = self.decapsulate(pkt)
317 self.assert_eq_pkts(payload, frames[i])
318
319 sports.add(pkt[UDP].sport)
320
321 # Check src port randomization presence, not concerned with the
322 # src ports split ratio, just as long as there are more then one.
323 self.assertGreaterEqual(len(sports), min(n, 2))
324
325 frame_ip4 = (
326 Ether(src="00:00:00:00:00:02", dst="00:00:00:00:00:01")
327 / IP(src="4.3.2.1", dst="1.2.3.4")
328 / UDP(sport=20000, dport=10000)
329 / Raw("\xa5" * 100)
330 )
331 encap_frames(frame_ip4)
332
333 frame_ip6 = (
334 Ether(src="00:00:00:00:00:02", dst="00:00:00:00:00:01")
335 / IPv6(src="2001:db8::4321", dst="2001:db8::1234")
336 / UDP(sport=20000, dport=10000)
337 / Raw("\xa5" * 100)
338 )
339 encap_frames(frame_ip6)
340
341 frame_mpls4 = (
342 Ether(src="00:00:00:00:00:02", dst="00:00:00:00:00:01")
343 / MPLS(label=44, ttl=64)
344 / IP(src="4.3.2.1", dst="1.2.3.4")
345 / UDP(sport=20000, dport=10000)
346 / Raw("\xa5" * 100)
347 )
348 encap_frames(frame_mpls4)
349
350 frame_mpls6 = (
351 Ether(src="00:00:00:00:00:02", dst="00:00:00:00:00:01")
352 / MPLS(label=44, ttl=64)
353 / IPv6(src="2001:db8::4321", dst="2001:db8::1234")
354 / UDP(sport=20000, dport=10000)
355 / Raw("\xa5" * 100)
356 )
357 encap_frames(frame_mpls6)
358
Artem Glazychev839dcc02020-12-01 02:39:21 +0700359 def encap_big_packet(self):
Ole Troanb3655e52018-08-16 22:08:49 +0200360 self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1500, 0, 0, 0])
361
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200362 frame = (
363 Ether(src="00:00:00:00:00:02", dst="00:00:00:00:00:01")
364 / IP(src="4.3.2.1", dst="1.2.3.4")
365 / UDP(sport=20000, dport=10000)
366 / Raw(b"\xa5" * 1450)
367 )
Ole Troanb3655e52018-08-16 22:08:49 +0200368
369 self.pg1.add_stream([frame])
370
371 self.pg0.enable_capture()
372
373 self.pg_start()
374
375 # Pick first received frame and check if it's correctly encapsulated.
376 out = self.pg0.get_capture(2)
377 ether = out[0]
Ole Troan7f991832018-12-06 17:35:12 +0100378 pkt = reassemble4(out)
Ole Troanb3655e52018-08-16 22:08:49 +0200379 pkt = ether / pkt
Neale Ranns91fd9102020-04-03 07:46:28 +0000380 self.check_encapsulation(pkt, self.single_tunnel_vni)
Ole Troanb3655e52018-08-16 22:08:49 +0200381
382 payload = self.decapsulate(pkt)
383 # TODO: Scapy bug?
384 # self.assert_eq_pkts(payload, frame)
385
Artem Glazychev839dcc02020-12-01 02:39:21 +0700386 """
387 Tests with default port (4789)
388 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200389
Artem Glazychev839dcc02020-12-01 02:39:21 +0700390 def test_decap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200391 """Decapsulation test
Artem Glazychev839dcc02020-12-01 02:39:21 +0700392 from BridgeDoman
393 """
394 self.createVxLANInterfaces()
395 super(TestVxlan, self).test_decap()
396
397 def test_encap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200398 """Encapsulation test
Artem Glazychev839dcc02020-12-01 02:39:21 +0700399 from BridgeDoman
400 """
401 self.createVxLANInterfaces()
Vladislav Grishenkof2fc97a2024-01-24 20:33:12 +0500402 self.encap_packets()
Artem Glazychev839dcc02020-12-01 02:39:21 +0700403
404 def test_encap_big_packet(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200405 """Encapsulation test send big frame from pg1
Artem Glazychev839dcc02020-12-01 02:39:21 +0700406 Verify receipt of encapsulated frames on pg0
407 """
408 self.createVxLANInterfaces()
409 self.encap_big_packet()
410
411 def test_ucast_flood(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200412 """Unicast flood test
Artem Glazychev839dcc02020-12-01 02:39:21 +0700413 from BridgeDoman
414 """
415 self.createVxLANInterfaces()
416 super(TestVxlan, self).test_ucast_flood()
417
418 def test_mcast_flood(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200419 """Multicast flood test
Artem Glazychev839dcc02020-12-01 02:39:21 +0700420 from BridgeDoman
421 """
422 self.createVxLANInterfaces()
423 super(TestVxlan, self).test_mcast_flood()
424
425 def test_mcast_rcv(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200426 """Multicast receive test
Artem Glazychev839dcc02020-12-01 02:39:21 +0700427 from BridgeDoman
428 """
429 self.createVxLANInterfaces()
430 super(TestVxlan, self).test_mcast_rcv()
431
432 """
433 Tests with custom port
434 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200435
Artem Glazychev839dcc02020-12-01 02:39:21 +0700436 def test_decap_custom_port(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200437 """Decapsulation test custom port
Artem Glazychev839dcc02020-12-01 02:39:21 +0700438 from BridgeDoman
439 """
440 self.createVxLANInterfaces(1111)
441 super(TestVxlan, self).test_decap()
442
443 def test_encap_custom_port(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200444 """Encapsulation test custom port
Artem Glazychev839dcc02020-12-01 02:39:21 +0700445 from BridgeDoman
446 """
447 self.createVxLANInterfaces(1111)
448 super(TestVxlan, self).test_encap()
449
450 def test_ucast_flood_custom_port(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200451 """Unicast flood test custom port
Artem Glazychev839dcc02020-12-01 02:39:21 +0700452 from BridgeDoman
453 """
454 self.createVxLANInterfaces(1111)
455 super(TestVxlan, self).test_ucast_flood()
456
457 def test_mcast_flood_custom_port(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200458 """Multicast flood test custom port
Artem Glazychev839dcc02020-12-01 02:39:21 +0700459 from BridgeDoman
460 """
461 self.createVxLANInterfaces(1111)
462 super(TestVxlan, self).test_mcast_flood()
463
464 def test_mcast_rcv_custom_port(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200465 """Multicast receive test custom port
Artem Glazychev839dcc02020-12-01 02:39:21 +0700466 from BridgeDoman
467 """
468 self.createVxLANInterfaces(1111)
469 super(TestVxlan, self).test_mcast_rcv()
470
Klement Sekeraf62ae122016-10-11 11:47:09 +0200471 # Method to define VPP actions before tear down of the test case.
Damjan Marionf56b77a2016-10-03 19:44:57 +0200472 # Overrides tearDown method in VppTestCase class.
473 # @param self The object pointer.
Artem Glazychev839dcc02020-12-01 02:39:21 +0700474
Damjan Marionf56b77a2016-10-03 19:44:57 +0200475 def tearDown(self):
476 super(TestVxlan, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700477
478 def show_commands_at_teardown(self):
479 self.logger.info(self.vapi.cli("show bridge-domain 1 detail"))
480 self.logger.info(self.vapi.cli("show bridge-domain 2 detail"))
481 self.logger.info(self.vapi.cli("show bridge-domain 3 detail"))
482 self.logger.info(self.vapi.cli("show vxlan tunnel"))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200483
Matej Klottondeb69842016-12-09 15:05:46 +0100484
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000485@unittest.skipIf("vxlan" in config.excluded_plugins, "Exclude VXLAN plugin tests")
Neale Ranns1b5ca982020-12-16 13:06:58 +0000486class TestVxlan2(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200487 """VXLAN Test Case"""
488
Neale Ranns1b5ca982020-12-16 13:06:58 +0000489 def setUp(self):
490 super(TestVxlan2, self).setUp()
491
492 # Create 2 pg interfaces.
493 self.create_pg_interfaces(range(4))
494 for pg in self.pg_interfaces:
495 pg.admin_up()
496
497 # Configure IPv4 addresses on VPP pg0.
498 self.pg0.config_ip4()
499 self.pg0.resolve_arp()
500
501 def tearDown(self):
502 super(TestVxlan2, self).tearDown()
503
504 def test_xconnect(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200505 """VXLAN source address not local"""
Neale Ranns1b5ca982020-12-16 13:06:58 +0000506
507 #
508 # test the broken configuration of a VXLAN tunnel whose
509 # source address is not local ot the box. packets sent
510 # through the tunnel should be dropped
511 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200512 t = VppVxlanTunnel(self, src="10.0.0.5", dst=self.pg0.local_ip4, vni=1000)
Neale Ranns1b5ca982020-12-16 13:06:58 +0000513 t.add_vpp_config()
514 t.admin_up()
515
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200516 self.vapi.sw_interface_set_l2_xconnect(
517 t.sw_if_index, self.pg1.sw_if_index, enable=1
518 )
519 self.vapi.sw_interface_set_l2_xconnect(
520 self.pg1.sw_if_index, t.sw_if_index, enable=1
521 )
Neale Ranns1b5ca982020-12-16 13:06:58 +0000522
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200523 p = (
524 Ether(src="00:11:22:33:44:55", dst="00:00:00:11:22:33")
525 / IP(src="4.3.2.1", dst="1.2.3.4")
526 / UDP(sport=20000, dport=10000)
527 / Raw(b"\xa5" * 1450)
528 )
Neale Ranns1b5ca982020-12-16 13:06:58 +0000529
530 rx = self.send_and_assert_no_replies(self.pg1, [p])
531
532
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000533@unittest.skipIf("vxlan" in config.excluded_plugins, "Exclude VXLAN plugin tests")
Artem Glazychev23e5f092022-02-21 17:51:29 +0700534class TestVxlanL2Mode(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200535 """VXLAN Test Case"""
536
Artem Glazychev23e5f092022-02-21 17:51:29 +0700537 def setUp(self):
538 super(TestVxlanL2Mode, self).setUp()
539
540 # Create 2 pg interfaces.
541 self.create_pg_interfaces(range(2))
542 for pg in self.pg_interfaces:
543 pg.admin_up()
544
545 # Configure IPv4 addresses on VPP pg0.
546 self.pg0.config_ip4()
547 self.pg0.resolve_arp()
548
549 # Configure IPv4 addresses on VPP pg1.
550 self.pg1.config_ip4()
551
552 def tearDown(self):
553 super(TestVxlanL2Mode, self).tearDown()
554
555 def test_l2_mode(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200556 """VXLAN L2 mode"""
557 t = VppVxlanTunnel(
558 self, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4, vni=1000, is_l3=False
559 )
Artem Glazychev23e5f092022-02-21 17:51:29 +0700560 t.add_vpp_config()
561 t.config_ip4()
562 t.admin_up()
563
564 dstIP = t.local_ip4[:-1] + "2"
565
566 # Create a packet to send
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200567 p = (
568 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
569 / IP(src=self.pg1.local_ip4, dst=dstIP)
570 / UDP(sport=555, dport=556)
571 / Raw(b"\x00" * 80)
572 )
Artem Glazychev23e5f092022-02-21 17:51:29 +0700573
574 # Expect ARP request
575 rx = self.send_and_expect(self.pg1, [p], self.pg0)
576 for p in rx:
577 self.assertEqual(p[Ether].dst, self.pg0.remote_mac)
578 self.assertEqual(p[Ether].src, self.pg0.local_mac)
579 self.assertEqual(p[ARP].op, 1)
580 self.assertEqual(p[ARP].pdst, dstIP)
581
582 # Resolve ARP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200583 VppNeighbor(self, t.sw_if_index, self.pg1.remote_mac, dstIP).add_vpp_config()
Artem Glazychev23e5f092022-02-21 17:51:29 +0700584
585 # Send packets
586 NUM_PKTS = 128
Steven Luonge4238aa2024-04-19 09:49:20 -0700587 p.dst = self.pg1.local_mac
Artem Glazychev23e5f092022-02-21 17:51:29 +0700588 rx = self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
589 self.assertEqual(NUM_PKTS, len(rx))
590
591
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200592if __name__ == "__main__":
Damjan Marionf56b77a2016-10-03 19:44:57 +0200593 unittest.main(testRunner=VppTestRunner)