blob: 6315f0efd5eec436f4c2c09448192ff9e195ec7b [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Klement Sekerab9ef2732018-06-24 22:49:33 +02002import unittest
Dave Wallace8800f732023-08-31 00:47:44 -04003from framework import VppTestCase
4from asfframework import VppTestRunner, tag_fixme_vpp_workers
Neale Ranns097fa662018-05-01 05:17:55 -07005
Paul Vinciguerraa279d9c2019-02-28 09:00:09 -08006from vpp_udp_encap import find_udp_encap, VppUdpEncap
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +02007from vpp_udp_decap import VppUdpDecap
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02008from vpp_ip_route import (
9 VppIpRoute,
10 VppRoutePath,
11 VppIpTable,
12 VppMplsLabel,
13 VppMplsTable,
14 VppMplsRoute,
15 FibPathType,
16 FibPathProto,
17)
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +020018from vpp_neighbor import VppNeighbor
19from vpp_papi import VppEnum
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000020from config import config
Neale Ranns810086d2017-11-05 16:26:46 -080021
22from scapy.packet import Raw
Klement Sekerab9ef2732018-06-24 22:49:33 +020023from scapy.layers.l2 import Ether
Dave Wallace8800f732023-08-31 00:47:44 -040024from scapy.layers.inet import IP, UDP
Neale Ranns810086d2017-11-05 16:26:46 -080025from scapy.layers.inet6 import IPv6
26from scapy.contrib.mpls import MPLS
27
Paul Vinciguerra4271c972019-05-14 13:25:49 -040028NUM_PKTS = 67
Vladislav Grishenko5c801b32022-06-23 00:45:16 +050029ENTROPY_PORT_MIN = 0x3 << 14
30ENTROPY_PORT_MAX = 0xFFFF
Paul Vinciguerra4271c972019-05-14 13:25:49 -040031
Neale Ranns810086d2017-11-05 16:26:46 -080032
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000033@tag_fixme_vpp_workers
Neale Ranns810086d2017-11-05 16:26:46 -080034class TestUdpEncap(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020035 """UDP Encap Test Case"""
Neale Ranns810086d2017-11-05 16:26:46 -080036
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070037 @classmethod
38 def setUpClass(cls):
39 super(TestUdpEncap, cls).setUpClass()
40
41 @classmethod
42 def tearDownClass(cls):
43 super(TestUdpEncap, cls).tearDownClass()
44
Neale Ranns810086d2017-11-05 16:26:46 -080045 def setUp(self):
46 super(TestUdpEncap, self).setUp()
47
48 # create 2 pg interfaces
49 self.create_pg_interfaces(range(4))
50
51 # setup interfaces
52 # assign them different tables.
53 table_id = 0
54 self.tables = []
55
56 for i in self.pg_interfaces:
57 i.admin_up()
58
59 if table_id != 0:
60 tbl = VppIpTable(self, table_id)
61 tbl.add_vpp_config()
62 self.tables.append(tbl)
63 tbl = VppIpTable(self, table_id, is_ip6=1)
64 tbl.add_vpp_config()
65 self.tables.append(tbl)
66
67 i.set_table_ip4(table_id)
68 i.set_table_ip6(table_id)
69 i.config_ip4()
70 i.resolve_arp()
71 i.config_ip6()
72 i.resolve_ndp()
73 table_id += 1
74
75 def tearDown(self):
76 for i in self.pg_interfaces:
77 i.unconfig_ip4()
78 i.unconfig_ip6()
Neale Ranns810086d2017-11-05 16:26:46 -080079 i.set_table_ip4(0)
80 i.set_table_ip6(0)
81 i.admin_down()
82 super(TestUdpEncap, self).tearDown()
83
Vladislav Grishenko5c801b32022-06-23 00:45:16 +050084 def validate_outer4(self, rx, encap_obj, sport_entropy=False):
Neale Ranns810086d2017-11-05 16:26:46 -080085 self.assertEqual(rx[IP].src, encap_obj.src_ip_s)
86 self.assertEqual(rx[IP].dst, encap_obj.dst_ip_s)
Vladislav Grishenko5c801b32022-06-23 00:45:16 +050087 if sport_entropy:
88 self.assert_in_range(rx[UDP].sport, ENTROPY_PORT_MIN, ENTROPY_PORT_MAX)
89 else:
90 self.assertEqual(rx[UDP].sport, encap_obj.src_port)
Neale Ranns810086d2017-11-05 16:26:46 -080091 self.assertEqual(rx[UDP].dport, encap_obj.dst_port)
92
Vladislav Grishenko5c801b32022-06-23 00:45:16 +050093 def validate_outer6(self, rx, encap_obj, sport_entropy=False):
Neale Ranns810086d2017-11-05 16:26:46 -080094 self.assertEqual(rx[IPv6].src, encap_obj.src_ip_s)
95 self.assertEqual(rx[IPv6].dst, encap_obj.dst_ip_s)
Vladislav Grishenko5c801b32022-06-23 00:45:16 +050096 if sport_entropy:
97 self.assert_in_range(rx[UDP].sport, ENTROPY_PORT_MIN, ENTROPY_PORT_MAX)
98 else:
99 self.assertEqual(rx[UDP].sport, encap_obj.src_port)
Neale Ranns810086d2017-11-05 16:26:46 -0800100 self.assertEqual(rx[UDP].dport, encap_obj.dst_port)
101
102 def validate_inner4(self, rx, tx, ttl=None):
Neale Ranns31ed7442018-02-23 05:29:09 -0800103 self.assertEqual(rx[IP].src, tx[IP].src)
104 self.assertEqual(rx[IP].dst, tx[IP].dst)
Neale Ranns810086d2017-11-05 16:26:46 -0800105 if ttl:
Neale Ranns31ed7442018-02-23 05:29:09 -0800106 self.assertEqual(rx[IP].ttl, ttl)
Neale Ranns810086d2017-11-05 16:26:46 -0800107 else:
Neale Ranns31ed7442018-02-23 05:29:09 -0800108 self.assertEqual(rx[IP].ttl, tx[IP].ttl)
Neale Ranns810086d2017-11-05 16:26:46 -0800109
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200110 def validate_inner6(self, rx, tx, hlim=None):
Neale Ranns810086d2017-11-05 16:26:46 -0800111 self.assertEqual(rx.src, tx[IPv6].src)
112 self.assertEqual(rx.dst, tx[IPv6].dst)
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200113 if hlim:
114 self.assertEqual(rx.hlim, hlim)
115 else:
116 self.assertEqual(rx.hlim, tx[IPv6].hlim)
Neale Ranns810086d2017-11-05 16:26:46 -0800117
Neale Ranns810086d2017-11-05 16:26:46 -0800118 def test_udp_encap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200119 """UDP Encap test"""
Neale Ranns810086d2017-11-05 16:26:46 -0800120
121 #
122 # construct a UDP encap object through each of the peers
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700123 # v4 through the first two peers, v6 through the second.
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200124 # The last encap is v4 and is used to check the codepath
125 # where 2 different udp encap objects are processed at the
126 # same time
Neale Ranns810086d2017-11-05 16:26:46 -0800127 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200128 udp_encap_0 = VppUdpEncap(
129 self, self.pg0.local_ip4, self.pg0.remote_ip4, 330, 440
130 )
131 udp_encap_1 = VppUdpEncap(
132 self, self.pg1.local_ip4, self.pg1.remote_ip4, 331, 441, table_id=1
133 )
134 udp_encap_2 = VppUdpEncap(
135 self, self.pg2.local_ip6, self.pg2.remote_ip6, 332, 442, table_id=2
136 )
137 udp_encap_3 = VppUdpEncap(
138 self, self.pg3.local_ip6, self.pg3.remote_ip6, 333, 443, table_id=3
139 )
140 udp_encap_4 = VppUdpEncap(
141 self, self.pg0.local_ip4, self.pg0.remote_ip4, 334, 444
142 )
Neale Ranns810086d2017-11-05 16:26:46 -0800143 udp_encap_0.add_vpp_config()
144 udp_encap_1.add_vpp_config()
145 udp_encap_2.add_vpp_config()
146 udp_encap_3.add_vpp_config()
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200147 udp_encap_4.add_vpp_config()
Neale Ranns810086d2017-11-05 16:26:46 -0800148
Neale Rannsd0df49f2018-08-08 01:06:40 -0700149 self.logger.info(self.vapi.cli("sh udp encap"))
150
151 self.assertTrue(find_udp_encap(self, udp_encap_2))
152 self.assertTrue(find_udp_encap(self, udp_encap_3))
153 self.assertTrue(find_udp_encap(self, udp_encap_0))
154 self.assertTrue(find_udp_encap(self, udp_encap_1))
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200155 self.assertTrue(find_udp_encap(self, udp_encap_4))
Neale Rannsd0df49f2018-08-08 01:06:40 -0700156
Neale Ranns810086d2017-11-05 16:26:46 -0800157 #
158 # Routes via each UDP encap object - all combinations of v4 and v6.
159 #
Neale Ranns097fa662018-05-01 05:17:55 -0700160 route_4o4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200161 self,
162 "1.1.0.1",
163 24,
164 [
165 VppRoutePath(
166 "0.0.0.0",
167 0xFFFFFFFF,
168 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
169 next_hop_id=udp_encap_0.id,
170 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
171 )
172 ],
173 table_id=1,
174 )
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200175 # specific route to match encap4, to test encap of 2 packets using 2
176 # different encap
177 route_4o4_2 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200178 self,
179 "1.1.0.2",
180 32,
181 [
182 VppRoutePath(
183 "0.0.0.0",
184 0xFFFFFFFF,
185 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
186 next_hop_id=udp_encap_4.id,
187 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
188 )
189 ],
190 table_id=1,
191 )
Neale Ranns097fa662018-05-01 05:17:55 -0700192 route_4o6 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200193 self,
194 "1.1.2.1",
195 32,
196 [
197 VppRoutePath(
198 "0.0.0.0",
199 0xFFFFFFFF,
200 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
201 next_hop_id=udp_encap_2.id,
202 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
203 )
204 ],
205 )
Neale Ranns097fa662018-05-01 05:17:55 -0700206 route_6o4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200207 self,
208 "2001::1",
209 128,
210 [
211 VppRoutePath(
212 "0.0.0.0",
213 0xFFFFFFFF,
214 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
215 next_hop_id=udp_encap_1.id,
216 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
217 )
218 ],
219 )
Neale Ranns097fa662018-05-01 05:17:55 -0700220 route_6o6 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200221 self,
222 "2001::3",
223 128,
224 [
225 VppRoutePath(
226 "0.0.0.0",
227 0xFFFFFFFF,
228 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
229 next_hop_id=udp_encap_3.id,
230 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
231 )
232 ],
233 )
Neale Ranns810086d2017-11-05 16:26:46 -0800234 route_4o6.add_vpp_config()
235 route_6o6.add_vpp_config()
236 route_6o4.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700237 route_4o4.add_vpp_config()
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200238 route_4o4_2.add_vpp_config()
Neale Ranns810086d2017-11-05 16:26:46 -0800239
240 #
241 # 4o4 encap
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200242 # we add a single packet matching the last encap at the beginning of
243 # the packet vector so that we encap 2 packets with different udp
244 # encap object at the same time
Neale Ranns810086d2017-11-05 16:26:46 -0800245 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200246 p_4o4 = (
247 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
248 / IP(src="2.2.2.2", dst="1.1.0.1")
249 / UDP(sport=1234, dport=1234)
250 / Raw(b"\xa5" * 100)
251 )
252 p_4o4_2 = (
253 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
254 / IP(src="2.2.2.2", dst="1.1.0.2")
255 / UDP(sport=1234, dport=1234)
256 / Raw(b"\xa5" * 100)
257 )
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200258 rx = self.send_and_expect(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200259 self.pg1, p_4o4_2 * 1 + p_4o4 * (NUM_PKTS - 1), self.pg0
260 )
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200261 # checking encap4 magic packet
262 p = rx.pop(0)
263 self.validate_outer4(p, udp_encap_4)
264 p = IP(p["UDP"].payload.load)
265 self.validate_inner4(p, p_4o4_2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200266 self.assertEqual(udp_encap_4.get_stats()["packets"], 1)
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200267 # checking remaining packets for encap0
Neale Ranns810086d2017-11-05 16:26:46 -0800268 for p in rx:
269 self.validate_outer4(p, udp_encap_0)
270 p = IP(p["UDP"].payload.load)
271 self.validate_inner4(p, p_4o4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200272 self.assertEqual(udp_encap_0.get_stats()["packets"], NUM_PKTS - 1)
Neale Ranns810086d2017-11-05 16:26:46 -0800273
274 #
275 # 4o6 encap
276 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200277 p_4o6 = (
278 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
279 / IP(src="2.2.2.2", dst="1.1.2.1")
280 / UDP(sport=1234, dport=1234)
281 / Raw(b"\xa5" * 100)
282 )
283 rx = self.send_and_expect(self.pg0, p_4o6 * NUM_PKTS, self.pg2)
Neale Ranns810086d2017-11-05 16:26:46 -0800284 for p in rx:
285 self.validate_outer6(p, udp_encap_2)
286 p = IP(p["UDP"].payload.load)
287 self.validate_inner4(p, p_4o6)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200288 self.assertEqual(udp_encap_2.get_stats()["packets"], NUM_PKTS)
Neale Ranns810086d2017-11-05 16:26:46 -0800289
290 #
291 # 6o4 encap
292 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200293 p_6o4 = (
294 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
295 / IPv6(src="2001::100", dst="2001::1")
296 / UDP(sport=1234, dport=1234)
297 / Raw(b"\xa5" * 100)
298 )
299 rx = self.send_and_expect(self.pg0, p_6o4 * NUM_PKTS, self.pg1)
Neale Ranns810086d2017-11-05 16:26:46 -0800300 for p in rx:
301 self.validate_outer4(p, udp_encap_1)
302 p = IPv6(p["UDP"].payload.load)
303 self.validate_inner6(p, p_6o4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200304 self.assertEqual(udp_encap_1.get_stats()["packets"], NUM_PKTS)
Neale Ranns810086d2017-11-05 16:26:46 -0800305
306 #
307 # 6o6 encap
308 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200309 p_6o6 = (
310 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
311 / IPv6(src="2001::100", dst="2001::3")
312 / UDP(sport=1234, dport=1234)
313 / Raw(b"\xa5" * 100)
314 )
315 rx = self.send_and_expect(self.pg0, p_6o6 * NUM_PKTS, self.pg3)
Neale Ranns810086d2017-11-05 16:26:46 -0800316 for p in rx:
317 self.validate_outer6(p, udp_encap_3)
318 p = IPv6(p["UDP"].payload.load)
319 self.validate_inner6(p, p_6o6)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200320 self.assertEqual(udp_encap_3.get_stats()["packets"], NUM_PKTS)
Neale Ranns810086d2017-11-05 16:26:46 -0800321
322 #
323 # A route with an output label
324 # the TTL of the inner packet is decremented on LSP ingress
325 #
Neale Ranns097fa662018-05-01 05:17:55 -0700326 route_4oMPLSo4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200327 self,
328 "1.1.2.22",
329 32,
330 [
331 VppRoutePath(
332 "0.0.0.0",
333 0xFFFFFFFF,
334 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
335 next_hop_id=1,
336 labels=[VppMplsLabel(66)],
337 )
338 ],
339 )
Neale Ranns810086d2017-11-05 16:26:46 -0800340 route_4oMPLSo4.add_vpp_config()
341
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200342 p_4omo4 = (
343 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
344 / IP(src="2.2.2.2", dst="1.1.2.22")
345 / UDP(sport=1234, dport=1234)
346 / Raw(b"\xa5" * 100)
347 )
348 rx = self.send_and_expect(self.pg0, p_4omo4 * NUM_PKTS, self.pg1)
Neale Ranns810086d2017-11-05 16:26:46 -0800349 for p in rx:
350 self.validate_outer4(p, udp_encap_1)
351 p = MPLS(p["UDP"].payload.load)
352 self.validate_inner4(p, p_4omo4, ttl=63)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200353 self.assertEqual(udp_encap_1.get_stats()["packets"], 2 * NUM_PKTS)
Neale Ranns810086d2017-11-05 16:26:46 -0800354
Vladislav Grishenko5c801b32022-06-23 00:45:16 +0500355 def test_udp_encap_entropy(self):
356 """UDP Encap src port entropy test"""
357
358 #
359 # construct a UDP encap object through each of the peers
360 # v4 through the first two peers, v6 through the second.
361 # use zero source port to enable entropy per rfc7510.
362 #
363 udp_encap_0 = VppUdpEncap(self, self.pg0.local_ip4, self.pg0.remote_ip4, 0, 440)
364 udp_encap_1 = VppUdpEncap(
365 self, self.pg1.local_ip4, self.pg1.remote_ip4, 0, 441, table_id=1
366 )
367 udp_encap_2 = VppUdpEncap(
368 self, self.pg2.local_ip6, self.pg2.remote_ip6, 0, 442, table_id=2
369 )
370 udp_encap_3 = VppUdpEncap(
371 self, self.pg3.local_ip6, self.pg3.remote_ip6, 0, 443, table_id=3
372 )
373 udp_encap_0.add_vpp_config()
374 udp_encap_1.add_vpp_config()
375 udp_encap_2.add_vpp_config()
376 udp_encap_3.add_vpp_config()
377
378 self.logger.info(self.vapi.cli("sh udp encap"))
379
380 self.assertTrue(find_udp_encap(self, udp_encap_0))
381 self.assertTrue(find_udp_encap(self, udp_encap_1))
382 self.assertTrue(find_udp_encap(self, udp_encap_2))
383 self.assertTrue(find_udp_encap(self, udp_encap_3))
384
385 #
386 # Routes via each UDP encap object - all combinations of v4 and v6.
387 #
388 route_4o4 = VppIpRoute(
389 self,
390 "1.1.0.1",
391 24,
392 [
393 VppRoutePath(
394 "0.0.0.0",
395 0xFFFFFFFF,
396 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
397 next_hop_id=udp_encap_0.id,
398 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
399 )
400 ],
401 table_id=1,
402 )
403 route_4o6 = VppIpRoute(
404 self,
405 "1.1.2.1",
406 32,
407 [
408 VppRoutePath(
409 "0.0.0.0",
410 0xFFFFFFFF,
411 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
412 next_hop_id=udp_encap_2.id,
413 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
414 )
415 ],
416 )
417 route_6o4 = VppIpRoute(
418 self,
419 "2001::1",
420 128,
421 [
422 VppRoutePath(
423 "0.0.0.0",
424 0xFFFFFFFF,
425 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
426 next_hop_id=udp_encap_1.id,
427 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
428 )
429 ],
430 )
431 route_6o6 = VppIpRoute(
432 self,
433 "2001::3",
434 128,
435 [
436 VppRoutePath(
437 "0.0.0.0",
438 0xFFFFFFFF,
439 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
440 next_hop_id=udp_encap_3.id,
441 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
442 )
443 ],
444 )
445 route_4o4.add_vpp_config()
446 route_4o6.add_vpp_config()
447 route_6o6.add_vpp_config()
448 route_6o4.add_vpp_config()
449
450 #
451 # 4o4 encap
452 #
453 p_4o4 = []
454 for i in range(NUM_PKTS):
455 p_4o4.append(
456 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
457 / IP(src="2.2.2.2", dst="1.1.0.1")
458 / UDP(sport=1234 + i, dport=1234)
459 / Raw(b"\xa5" * 100)
460 )
461 rx = self.send_and_expect(self.pg1, p_4o4, self.pg0)
462 sports = set()
463 for i, p in enumerate(rx):
464 self.validate_outer4(p, udp_encap_0, True)
465 sports.add(p["UDP"].sport)
466 p = IP(p["UDP"].payload.load)
467 self.validate_inner4(p, p_4o4[i])
468 self.assertEqual(udp_encap_0.get_stats()["packets"], NUM_PKTS)
469 self.assertGreater(
470 len(sports), 1, "source port {} is not an entropy value".format(sports)
471 )
472
473 #
474 # 4o6 encap
475 #
476 p_4o6 = []
477 for i in range(NUM_PKTS):
478 p_4o6.append(
479 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
480 / IP(src="2.2.2.2", dst="1.1.2.1")
481 / UDP(sport=1234 + i, dport=1234)
482 / Raw(b"\xa5" * 100)
483 )
484 rx = self.send_and_expect(self.pg0, p_4o6, self.pg2)
485 sports = set()
486 for p in rx:
487 self.validate_outer6(p, udp_encap_2, True)
488 sports.add(p["UDP"].sport)
489 p = IP(p["UDP"].payload.load)
490 self.validate_inner4(p, p_4o6[i])
491 self.assertEqual(udp_encap_2.get_stats()["packets"], NUM_PKTS)
492 self.assertGreater(
493 len(sports), 1, "source port {} is not an entropy value".format(sports)
494 )
495
496 #
497 # 6o4 encap
498 #
499 p_6o4 = []
500 for i in range(NUM_PKTS):
501 p_6o4.append(
502 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
503 / IPv6(src="2001::100", dst="2001::1")
504 / UDP(sport=1234 + i, dport=1234)
505 / Raw(b"\xa5" * 100)
506 )
507 rx = self.send_and_expect(self.pg0, p_6o4, self.pg1)
508 sports = set()
509 for p in rx:
510 self.validate_outer4(p, udp_encap_1, True)
511 sports.add(p["UDP"].sport)
512 p = IPv6(p["UDP"].payload.load)
513 self.validate_inner6(p, p_6o4[i])
514 self.assertEqual(udp_encap_1.get_stats()["packets"], NUM_PKTS)
515 self.assertGreater(
516 len(sports), 1, "source port {} is not an entropy value".format(sports)
517 )
518
519 #
520 # 6o6 encap
521 #
522 p_6o6 = []
523 for i in range(NUM_PKTS):
524 p_6o6.append(
525 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
526 / IPv6(src="2001::100", dst="2001::3")
527 / UDP(sport=1234 + i, dport=1234)
528 / Raw(b"\xa5" * 100)
529 )
530 rx = self.send_and_expect(self.pg0, p_6o6, self.pg3)
531 sports = set()
532 for p in rx:
533 self.validate_outer6(p, udp_encap_3, True)
534 sports.add(p["UDP"].sport)
535 p = IPv6(p["UDP"].payload.load)
536 self.validate_inner6(p, p_6o6[i])
537 self.assertEqual(udp_encap_3.get_stats()["packets"], NUM_PKTS)
538 self.assertGreater(
539 len(sports), 1, "source port {} is not an entropy value".format(sports)
540 )
541
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200542 def test_udp_decap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200543 """UDP Decap test"""
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200544 #
545 # construct a UDP decap object for each type of protocol
546 #
547
548 # IPv4
549 udp_api_proto = VppEnum.vl_api_udp_decap_next_proto_t
550 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP4
551 udp_decap_0 = VppUdpDecap(self, 1, 220, next_proto)
552
553 # IPv6
554 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP6
555 udp_decap_1 = VppUdpDecap(self, 0, 221, next_proto)
556
557 # MPLS
558 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_MPLS
559 udp_decap_2 = VppUdpDecap(self, 1, 222, next_proto)
560
561 udp_decap_0.add_vpp_config()
562 udp_decap_1.add_vpp_config()
563 udp_decap_2.add_vpp_config()
564
565 #
566 # Routes via the corresponding pg after the UDP decap
567 #
568 route_4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200569 self,
570 "1.1.1.1",
571 32,
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200572 [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)],
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200573 table_id=0,
574 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200575
576 route_6 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200577 self, "2001::1", 128, [VppRoutePath("::", self.pg1.sw_if_index)], table_id=1
578 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200579
580 route_mo4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200581 self,
582 "3.3.3.3",
583 32,
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200584 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200585 table_id=2,
586 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200587
588 route_4.add_vpp_config()
589 route_6.add_vpp_config()
590 route_mo4.add_vpp_config()
591
592 #
593 # Adding neighbors to route the packets
594 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200595 n_4 = VppNeighbor(self, self.pg0.sw_if_index, "00:11:22:33:44:55", "1.1.1.1")
596 n_6 = VppNeighbor(self, self.pg1.sw_if_index, "11:22:33:44:55:66", "2001::1")
597 n_mo4 = VppNeighbor(self, self.pg2.sw_if_index, "22:33:44:55:66:77", "3.3.3.3")
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200598
599 n_4.add_vpp_config()
600 n_6.add_vpp_config()
601 n_mo4.add_vpp_config()
602
603 #
604 # MPLS decapsulation config
605 #
606 mpls_table = VppMplsTable(self, 0)
607 mpls_table.add_vpp_config()
608 mpls_route = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200609 self,
610 77,
611 1,
612 [
613 VppRoutePath(
614 "0.0.0.0",
615 0xFFFFFFFF,
616 nh_table_id=2,
617 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
618 )
619 ],
620 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200621 mpls_route.add_vpp_config()
622
623 #
624 # UDP over ipv4 decap
625 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200626 p_4 = (
627 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
628 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
629 / UDP(sport=1111, dport=220)
630 / IP(src="2.2.2.2", dst="1.1.1.1")
631 / UDP(sport=1234, dport=4321)
632 / Raw(b"\xa5" * 100)
633 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200634
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200635 rx = self.send_and_expect(self.pg0, p_4 * NUM_PKTS, self.pg0)
Dave Wallacecf9356d2024-07-23 01:28:19 -0400636 p_4 = IP(bytes(p_4["UDP"].payload))
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200637 for p in rx:
Dave Wallacecf9356d2024-07-23 01:28:19 -0400638 p = IP(bytes(p["Ether"].payload))
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200639 self.validate_inner4(p, p_4, ttl=63)
640
641 #
642 # UDP over ipv6 decap
643 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200644 p_6 = (
645 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
646 / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6)
647 / UDP(sport=2222, dport=221)
648 / IPv6(src="2001::100", dst="2001::1")
649 / UDP(sport=1234, dport=4321)
650 / Raw(b"\xa5" * 100)
651 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200652
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200653 rx = self.send_and_expect(self.pg1, p_6 * NUM_PKTS, self.pg1)
Dave Wallacecf9356d2024-07-23 01:28:19 -0400654 p_6 = IPv6(bytes(p_6["UDP"].payload))
655 p = IPv6(bytes(rx[0]["Ether"].payload))
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200656 for p in rx:
Dave Wallacecf9356d2024-07-23 01:28:19 -0400657 p = IPv6(bytes(p["Ether"].payload))
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200658 self.validate_inner6(p, p_6, hlim=63)
659
660 #
661 # UDP over mpls decap
662 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200663 p_mo4 = (
664 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
665 / IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4)
666 / UDP(sport=3333, dport=222)
667 / MPLS(label=77, ttl=1)
668 / IP(src="4.4.4.4", dst="3.3.3.3")
669 / UDP(sport=1234, dport=4321)
670 / Raw(b"\xa5" * 100)
671 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200672
673 self.pg2.enable_mpls()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200674 rx = self.send_and_expect(self.pg2, p_mo4 * NUM_PKTS, self.pg2)
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200675 self.pg2.disable_mpls()
Dave Wallacecf9356d2024-07-23 01:28:19 -0400676 p_mo4 = IP(bytes(MPLS(bytes(p_mo4["UDP"].payload)).payload))
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200677 for p in rx:
Dave Wallacecf9356d2024-07-23 01:28:19 -0400678 p = IP(bytes(p["Ether"].payload))
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200679 self.validate_inner4(p, p_mo4, ttl=63)
680
Neale Ranns810086d2017-11-05 16:26:46 -0800681
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +0000682@tag_fixme_vpp_workers
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000683@unittest.skipIf(
684 "hs_apps" in config.excluded_plugins, "Exclude tests requiring hs_apps plugin"
685)
Florin Coras40903ac2018-06-10 14:41:23 -0700686class TestUDP(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200687 """UDP Test Case"""
Florin Coras40903ac2018-06-10 14:41:23 -0700688
689 @classmethod
690 def setUpClass(cls):
691 super(TestUDP, cls).setUpClass()
692
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700693 @classmethod
694 def tearDownClass(cls):
695 super(TestUDP, cls).tearDownClass()
696
Florin Coras40903ac2018-06-10 14:41:23 -0700697 def setUp(self):
698 super(TestUDP, self).setUp()
Jakub Grajciar6a2794e2020-11-24 11:22:01 +0100699 self.vapi.session_enable_disable(is_enable=1)
Klement Sekerab9ef2732018-06-24 22:49:33 +0200700 self.create_loopback_interfaces(2)
Florin Coras40903ac2018-06-10 14:41:23 -0700701
702 table_id = 0
703
704 for i in self.lo_interfaces:
705 i.admin_up()
706
707 if table_id != 0:
708 tbl = VppIpTable(self, table_id)
709 tbl.add_vpp_config()
710
711 i.set_table_ip4(table_id)
712 i.config_ip4()
713 table_id += 1
714
715 # Configure namespaces
Nathan Skrzypczak51f1b262023-04-27 12:43:46 +0200716 self.vapi.app_namespace_add_del_v4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200717 namespace_id="0", sw_if_index=self.loop0.sw_if_index
718 )
Nathan Skrzypczak51f1b262023-04-27 12:43:46 +0200719 self.vapi.app_namespace_add_del_v4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200720 namespace_id="1", sw_if_index=self.loop1.sw_if_index
721 )
Florin Coras40903ac2018-06-10 14:41:23 -0700722
723 def tearDown(self):
724 for i in self.lo_interfaces:
725 i.unconfig_ip4()
726 i.set_table_ip4(0)
727 i.admin_down()
Steven Luong67bae202024-07-08 11:21:23 -0700728 # Unconfigure namespaces - remove our locks to the vrf tables
729 self.vapi.app_namespace_add_del_v4(
730 is_add=0, namespace_id="0", sw_if_index=self.loop0.sw_if_index
731 )
732 self.vapi.app_namespace_add_del_v4(
733 is_add=0, namespace_id="1", sw_if_index=self.loop1.sw_if_index
734 )
735
Jakub Grajciar6a2794e2020-11-24 11:22:01 +0100736 self.vapi.session_enable_disable(is_enable=0)
Florin Coras40903ac2018-06-10 14:41:23 -0700737 super(TestUDP, self).tearDown()
738
739 def test_udp_transfer(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200740 """UDP echo client/server transfer"""
Florin Coras40903ac2018-06-10 14:41:23 -0700741
742 # Add inter-table routes
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200743 ip_t01 = VppIpRoute(
744 self,
745 self.loop1.local_ip4,
746 32,
747 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)],
748 )
749 ip_t10 = VppIpRoute(
750 self,
751 self.loop0.local_ip4,
752 32,
753 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)],
754 table_id=1,
755 )
Florin Coras40903ac2018-06-10 14:41:23 -0700756 ip_t01.add_vpp_config()
757 ip_t10.add_vpp_config()
758
759 # Start builtin server and client
760 uri = "udp://" + self.loop0.local_ip4 + "/1234"
Filip Tehlarefe875e2023-09-04 14:17:52 +0200761 error = self.vapi.cli("test echo server appns 0 fifo-size 4k " + "uri " + uri)
Florin Coras40903ac2018-06-10 14:41:23 -0700762 if error:
763 self.logger.critical(error)
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800764 self.assertNotIn("failed", error)
Florin Coras40903ac2018-06-10 14:41:23 -0700765
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200766 error = self.vapi.cli(
767 "test echo client mbytes 10 appns 1 "
Filip Tehlarefe875e2023-09-04 14:17:52 +0200768 + "fifo-size 4k "
769 + "syn-timeout 2 uri "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200770 + uri
771 )
Florin Coras40903ac2018-06-10 14:41:23 -0700772 if error:
773 self.logger.critical(error)
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800774 self.assertNotIn("failed", error)
Florin Coras40903ac2018-06-10 14:41:23 -0700775
Florin Coras7a2abce2020-04-05 19:25:44 +0000776 self.logger.debug(self.vapi.cli("show session verbose 2"))
777
Florin Coras40903ac2018-06-10 14:41:23 -0700778 # Delete inter-table routes
779 ip_t01.remove_vpp_config()
780 ip_t10.remove_vpp_config()
781
782
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200783if __name__ == "__main__":
Neale Ranns810086d2017-11-05 16:26:46 -0800784 unittest.main(testRunner=VppTestRunner)