blob: ebc99e853889050d22ce06807bb9e7c3b95abcba [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
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00003from framework import tag_fixme_vpp_workers
Neale Ranns810086d2017-11-05 16:26:46 -08004from framework import VppTestCase, VppTestRunner
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
Neale Ranns810086d2017-11-05 16:26:46 -080020
21from scapy.packet import Raw
Klement Sekerab9ef2732018-06-24 22:49:33 +020022from scapy.layers.l2 import Ether
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +020023from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns810086d2017-11-05 16:26:46 -080024from scapy.layers.inet6 import IPv6
25from scapy.contrib.mpls import MPLS
26
Paul Vinciguerra4271c972019-05-14 13:25:49 -040027NUM_PKTS = 67
Vladislav Grishenko5c801b32022-06-23 00:45:16 +050028ENTROPY_PORT_MIN = 0x3 << 14
29ENTROPY_PORT_MAX = 0xFFFF
Paul Vinciguerra4271c972019-05-14 13:25:49 -040030
Neale Ranns810086d2017-11-05 16:26:46 -080031
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000032@tag_fixme_vpp_workers
Neale Ranns810086d2017-11-05 16:26:46 -080033class TestUdpEncap(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020034 """UDP Encap Test Case"""
Neale Ranns810086d2017-11-05 16:26:46 -080035
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070036 @classmethod
37 def setUpClass(cls):
38 super(TestUdpEncap, cls).setUpClass()
39
40 @classmethod
41 def tearDownClass(cls):
42 super(TestUdpEncap, cls).tearDownClass()
43
Neale Ranns810086d2017-11-05 16:26:46 -080044 def setUp(self):
45 super(TestUdpEncap, self).setUp()
46
47 # create 2 pg interfaces
48 self.create_pg_interfaces(range(4))
49
50 # setup interfaces
51 # assign them different tables.
52 table_id = 0
53 self.tables = []
54
55 for i in self.pg_interfaces:
56 i.admin_up()
57
58 if table_id != 0:
59 tbl = VppIpTable(self, table_id)
60 tbl.add_vpp_config()
61 self.tables.append(tbl)
62 tbl = VppIpTable(self, table_id, is_ip6=1)
63 tbl.add_vpp_config()
64 self.tables.append(tbl)
65
66 i.set_table_ip4(table_id)
67 i.set_table_ip6(table_id)
68 i.config_ip4()
69 i.resolve_arp()
70 i.config_ip6()
71 i.resolve_ndp()
72 table_id += 1
73
74 def tearDown(self):
75 for i in self.pg_interfaces:
76 i.unconfig_ip4()
77 i.unconfig_ip6()
Neale Ranns810086d2017-11-05 16:26:46 -080078 i.set_table_ip4(0)
79 i.set_table_ip6(0)
80 i.admin_down()
81 super(TestUdpEncap, self).tearDown()
82
Vladislav Grishenko5c801b32022-06-23 00:45:16 +050083 def validate_outer4(self, rx, encap_obj, sport_entropy=False):
Neale Ranns810086d2017-11-05 16:26:46 -080084 self.assertEqual(rx[IP].src, encap_obj.src_ip_s)
85 self.assertEqual(rx[IP].dst, encap_obj.dst_ip_s)
Vladislav Grishenko5c801b32022-06-23 00:45:16 +050086 if sport_entropy:
87 self.assert_in_range(rx[UDP].sport, ENTROPY_PORT_MIN, ENTROPY_PORT_MAX)
88 else:
89 self.assertEqual(rx[UDP].sport, encap_obj.src_port)
Neale Ranns810086d2017-11-05 16:26:46 -080090 self.assertEqual(rx[UDP].dport, encap_obj.dst_port)
91
Vladislav Grishenko5c801b32022-06-23 00:45:16 +050092 def validate_outer6(self, rx, encap_obj, sport_entropy=False):
Neale Ranns810086d2017-11-05 16:26:46 -080093 self.assertEqual(rx[IPv6].src, encap_obj.src_ip_s)
94 self.assertEqual(rx[IPv6].dst, encap_obj.dst_ip_s)
Vladislav Grishenko5c801b32022-06-23 00:45:16 +050095 if sport_entropy:
96 self.assert_in_range(rx[UDP].sport, ENTROPY_PORT_MIN, ENTROPY_PORT_MAX)
97 else:
98 self.assertEqual(rx[UDP].sport, encap_obj.src_port)
Neale Ranns810086d2017-11-05 16:26:46 -080099 self.assertEqual(rx[UDP].dport, encap_obj.dst_port)
100
101 def validate_inner4(self, rx, tx, ttl=None):
Neale Ranns31ed7442018-02-23 05:29:09 -0800102 self.assertEqual(rx[IP].src, tx[IP].src)
103 self.assertEqual(rx[IP].dst, tx[IP].dst)
Neale Ranns810086d2017-11-05 16:26:46 -0800104 if ttl:
Neale Ranns31ed7442018-02-23 05:29:09 -0800105 self.assertEqual(rx[IP].ttl, ttl)
Neale Ranns810086d2017-11-05 16:26:46 -0800106 else:
Neale Ranns31ed7442018-02-23 05:29:09 -0800107 self.assertEqual(rx[IP].ttl, tx[IP].ttl)
Neale Ranns810086d2017-11-05 16:26:46 -0800108
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200109 def validate_inner6(self, rx, tx, hlim=None):
Neale Ranns810086d2017-11-05 16:26:46 -0800110 self.assertEqual(rx.src, tx[IPv6].src)
111 self.assertEqual(rx.dst, tx[IPv6].dst)
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200112 if hlim:
113 self.assertEqual(rx.hlim, hlim)
114 else:
115 self.assertEqual(rx.hlim, tx[IPv6].hlim)
Neale Ranns810086d2017-11-05 16:26:46 -0800116
Neale Ranns810086d2017-11-05 16:26:46 -0800117 def test_udp_encap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200118 """UDP Encap test"""
Neale Ranns810086d2017-11-05 16:26:46 -0800119
120 #
121 # construct a UDP encap object through each of the peers
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700122 # v4 through the first two peers, v6 through the second.
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200123 # The last encap is v4 and is used to check the codepath
124 # where 2 different udp encap objects are processed at the
125 # same time
Neale Ranns810086d2017-11-05 16:26:46 -0800126 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200127 udp_encap_0 = VppUdpEncap(
128 self, self.pg0.local_ip4, self.pg0.remote_ip4, 330, 440
129 )
130 udp_encap_1 = VppUdpEncap(
131 self, self.pg1.local_ip4, self.pg1.remote_ip4, 331, 441, table_id=1
132 )
133 udp_encap_2 = VppUdpEncap(
134 self, self.pg2.local_ip6, self.pg2.remote_ip6, 332, 442, table_id=2
135 )
136 udp_encap_3 = VppUdpEncap(
137 self, self.pg3.local_ip6, self.pg3.remote_ip6, 333, 443, table_id=3
138 )
139 udp_encap_4 = VppUdpEncap(
140 self, self.pg0.local_ip4, self.pg0.remote_ip4, 334, 444
141 )
Neale Ranns810086d2017-11-05 16:26:46 -0800142 udp_encap_0.add_vpp_config()
143 udp_encap_1.add_vpp_config()
144 udp_encap_2.add_vpp_config()
145 udp_encap_3.add_vpp_config()
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200146 udp_encap_4.add_vpp_config()
Neale Ranns810086d2017-11-05 16:26:46 -0800147
Neale Rannsd0df49f2018-08-08 01:06:40 -0700148 self.logger.info(self.vapi.cli("sh udp encap"))
149
150 self.assertTrue(find_udp_encap(self, udp_encap_2))
151 self.assertTrue(find_udp_encap(self, udp_encap_3))
152 self.assertTrue(find_udp_encap(self, udp_encap_0))
153 self.assertTrue(find_udp_encap(self, udp_encap_1))
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200154 self.assertTrue(find_udp_encap(self, udp_encap_4))
Neale Rannsd0df49f2018-08-08 01:06:40 -0700155
Neale Ranns810086d2017-11-05 16:26:46 -0800156 #
157 # Routes via each UDP encap object - all combinations of v4 and v6.
158 #
Neale Ranns097fa662018-05-01 05:17:55 -0700159 route_4o4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200160 self,
161 "1.1.0.1",
162 24,
163 [
164 VppRoutePath(
165 "0.0.0.0",
166 0xFFFFFFFF,
167 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
168 next_hop_id=udp_encap_0.id,
169 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
170 )
171 ],
172 table_id=1,
173 )
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200174 # specific route to match encap4, to test encap of 2 packets using 2
175 # different encap
176 route_4o4_2 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200177 self,
178 "1.1.0.2",
179 32,
180 [
181 VppRoutePath(
182 "0.0.0.0",
183 0xFFFFFFFF,
184 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
185 next_hop_id=udp_encap_4.id,
186 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
187 )
188 ],
189 table_id=1,
190 )
Neale Ranns097fa662018-05-01 05:17:55 -0700191 route_4o6 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200192 self,
193 "1.1.2.1",
194 32,
195 [
196 VppRoutePath(
197 "0.0.0.0",
198 0xFFFFFFFF,
199 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
200 next_hop_id=udp_encap_2.id,
201 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
202 )
203 ],
204 )
Neale Ranns097fa662018-05-01 05:17:55 -0700205 route_6o4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200206 self,
207 "2001::1",
208 128,
209 [
210 VppRoutePath(
211 "0.0.0.0",
212 0xFFFFFFFF,
213 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
214 next_hop_id=udp_encap_1.id,
215 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
216 )
217 ],
218 )
Neale Ranns097fa662018-05-01 05:17:55 -0700219 route_6o6 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200220 self,
221 "2001::3",
222 128,
223 [
224 VppRoutePath(
225 "0.0.0.0",
226 0xFFFFFFFF,
227 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
228 next_hop_id=udp_encap_3.id,
229 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
230 )
231 ],
232 )
Neale Ranns810086d2017-11-05 16:26:46 -0800233 route_4o6.add_vpp_config()
234 route_6o6.add_vpp_config()
235 route_6o4.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700236 route_4o4.add_vpp_config()
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200237 route_4o4_2.add_vpp_config()
Neale Ranns810086d2017-11-05 16:26:46 -0800238
239 #
240 # 4o4 encap
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200241 # we add a single packet matching the last encap at the beginning of
242 # the packet vector so that we encap 2 packets with different udp
243 # encap object at the same time
Neale Ranns810086d2017-11-05 16:26:46 -0800244 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200245 p_4o4 = (
246 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
247 / IP(src="2.2.2.2", dst="1.1.0.1")
248 / UDP(sport=1234, dport=1234)
249 / Raw(b"\xa5" * 100)
250 )
251 p_4o4_2 = (
252 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
253 / IP(src="2.2.2.2", dst="1.1.0.2")
254 / UDP(sport=1234, dport=1234)
255 / Raw(b"\xa5" * 100)
256 )
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200257 rx = self.send_and_expect(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200258 self.pg1, p_4o4_2 * 1 + p_4o4 * (NUM_PKTS - 1), self.pg0
259 )
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200260 # checking encap4 magic packet
261 p = rx.pop(0)
262 self.validate_outer4(p, udp_encap_4)
263 p = IP(p["UDP"].payload.load)
264 self.validate_inner4(p, p_4o4_2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200265 self.assertEqual(udp_encap_4.get_stats()["packets"], 1)
Benoît Ganne0ec1c6d2022-05-04 11:26:09 +0200266 # checking remaining packets for encap0
Neale Ranns810086d2017-11-05 16:26:46 -0800267 for p in rx:
268 self.validate_outer4(p, udp_encap_0)
269 p = IP(p["UDP"].payload.load)
270 self.validate_inner4(p, p_4o4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200271 self.assertEqual(udp_encap_0.get_stats()["packets"], NUM_PKTS - 1)
Neale Ranns810086d2017-11-05 16:26:46 -0800272
273 #
274 # 4o6 encap
275 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200276 p_4o6 = (
277 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
278 / IP(src="2.2.2.2", dst="1.1.2.1")
279 / UDP(sport=1234, dport=1234)
280 / Raw(b"\xa5" * 100)
281 )
282 rx = self.send_and_expect(self.pg0, p_4o6 * NUM_PKTS, self.pg2)
Neale Ranns810086d2017-11-05 16:26:46 -0800283 for p in rx:
284 self.validate_outer6(p, udp_encap_2)
285 p = IP(p["UDP"].payload.load)
286 self.validate_inner4(p, p_4o6)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200287 self.assertEqual(udp_encap_2.get_stats()["packets"], NUM_PKTS)
Neale Ranns810086d2017-11-05 16:26:46 -0800288
289 #
290 # 6o4 encap
291 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200292 p_6o4 = (
293 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
294 / IPv6(src="2001::100", dst="2001::1")
295 / UDP(sport=1234, dport=1234)
296 / Raw(b"\xa5" * 100)
297 )
298 rx = self.send_and_expect(self.pg0, p_6o4 * NUM_PKTS, self.pg1)
Neale Ranns810086d2017-11-05 16:26:46 -0800299 for p in rx:
300 self.validate_outer4(p, udp_encap_1)
301 p = IPv6(p["UDP"].payload.load)
302 self.validate_inner6(p, p_6o4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200303 self.assertEqual(udp_encap_1.get_stats()["packets"], NUM_PKTS)
Neale Ranns810086d2017-11-05 16:26:46 -0800304
305 #
306 # 6o6 encap
307 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200308 p_6o6 = (
309 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
310 / IPv6(src="2001::100", dst="2001::3")
311 / UDP(sport=1234, dport=1234)
312 / Raw(b"\xa5" * 100)
313 )
314 rx = self.send_and_expect(self.pg0, p_6o6 * NUM_PKTS, self.pg3)
Neale Ranns810086d2017-11-05 16:26:46 -0800315 for p in rx:
316 self.validate_outer6(p, udp_encap_3)
317 p = IPv6(p["UDP"].payload.load)
318 self.validate_inner6(p, p_6o6)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200319 self.assertEqual(udp_encap_3.get_stats()["packets"], NUM_PKTS)
Neale Ranns810086d2017-11-05 16:26:46 -0800320
321 #
322 # A route with an output label
323 # the TTL of the inner packet is decremented on LSP ingress
324 #
Neale Ranns097fa662018-05-01 05:17:55 -0700325 route_4oMPLSo4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200326 self,
327 "1.1.2.22",
328 32,
329 [
330 VppRoutePath(
331 "0.0.0.0",
332 0xFFFFFFFF,
333 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
334 next_hop_id=1,
335 labels=[VppMplsLabel(66)],
336 )
337 ],
338 )
Neale Ranns810086d2017-11-05 16:26:46 -0800339 route_4oMPLSo4.add_vpp_config()
340
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200341 p_4omo4 = (
342 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
343 / IP(src="2.2.2.2", dst="1.1.2.22")
344 / UDP(sport=1234, dport=1234)
345 / Raw(b"\xa5" * 100)
346 )
347 rx = self.send_and_expect(self.pg0, p_4omo4 * NUM_PKTS, self.pg1)
Neale Ranns810086d2017-11-05 16:26:46 -0800348 for p in rx:
349 self.validate_outer4(p, udp_encap_1)
350 p = MPLS(p["UDP"].payload.load)
351 self.validate_inner4(p, p_4omo4, ttl=63)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200352 self.assertEqual(udp_encap_1.get_stats()["packets"], 2 * NUM_PKTS)
Neale Ranns810086d2017-11-05 16:26:46 -0800353
Vladislav Grishenko5c801b32022-06-23 00:45:16 +0500354 def test_udp_encap_entropy(self):
355 """UDP Encap src port entropy test"""
356
357 #
358 # construct a UDP encap object through each of the peers
359 # v4 through the first two peers, v6 through the second.
360 # use zero source port to enable entropy per rfc7510.
361 #
362 udp_encap_0 = VppUdpEncap(self, self.pg0.local_ip4, self.pg0.remote_ip4, 0, 440)
363 udp_encap_1 = VppUdpEncap(
364 self, self.pg1.local_ip4, self.pg1.remote_ip4, 0, 441, table_id=1
365 )
366 udp_encap_2 = VppUdpEncap(
367 self, self.pg2.local_ip6, self.pg2.remote_ip6, 0, 442, table_id=2
368 )
369 udp_encap_3 = VppUdpEncap(
370 self, self.pg3.local_ip6, self.pg3.remote_ip6, 0, 443, table_id=3
371 )
372 udp_encap_0.add_vpp_config()
373 udp_encap_1.add_vpp_config()
374 udp_encap_2.add_vpp_config()
375 udp_encap_3.add_vpp_config()
376
377 self.logger.info(self.vapi.cli("sh udp encap"))
378
379 self.assertTrue(find_udp_encap(self, udp_encap_0))
380 self.assertTrue(find_udp_encap(self, udp_encap_1))
381 self.assertTrue(find_udp_encap(self, udp_encap_2))
382 self.assertTrue(find_udp_encap(self, udp_encap_3))
383
384 #
385 # Routes via each UDP encap object - all combinations of v4 and v6.
386 #
387 route_4o4 = VppIpRoute(
388 self,
389 "1.1.0.1",
390 24,
391 [
392 VppRoutePath(
393 "0.0.0.0",
394 0xFFFFFFFF,
395 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
396 next_hop_id=udp_encap_0.id,
397 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
398 )
399 ],
400 table_id=1,
401 )
402 route_4o6 = VppIpRoute(
403 self,
404 "1.1.2.1",
405 32,
406 [
407 VppRoutePath(
408 "0.0.0.0",
409 0xFFFFFFFF,
410 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
411 next_hop_id=udp_encap_2.id,
412 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
413 )
414 ],
415 )
416 route_6o4 = VppIpRoute(
417 self,
418 "2001::1",
419 128,
420 [
421 VppRoutePath(
422 "0.0.0.0",
423 0xFFFFFFFF,
424 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
425 next_hop_id=udp_encap_1.id,
426 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
427 )
428 ],
429 )
430 route_6o6 = VppIpRoute(
431 self,
432 "2001::3",
433 128,
434 [
435 VppRoutePath(
436 "0.0.0.0",
437 0xFFFFFFFF,
438 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
439 next_hop_id=udp_encap_3.id,
440 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
441 )
442 ],
443 )
444 route_4o4.add_vpp_config()
445 route_4o6.add_vpp_config()
446 route_6o6.add_vpp_config()
447 route_6o4.add_vpp_config()
448
449 #
450 # 4o4 encap
451 #
452 p_4o4 = []
453 for i in range(NUM_PKTS):
454 p_4o4.append(
455 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
456 / IP(src="2.2.2.2", dst="1.1.0.1")
457 / UDP(sport=1234 + i, dport=1234)
458 / Raw(b"\xa5" * 100)
459 )
460 rx = self.send_and_expect(self.pg1, p_4o4, self.pg0)
461 sports = set()
462 for i, p in enumerate(rx):
463 self.validate_outer4(p, udp_encap_0, True)
464 sports.add(p["UDP"].sport)
465 p = IP(p["UDP"].payload.load)
466 self.validate_inner4(p, p_4o4[i])
467 self.assertEqual(udp_encap_0.get_stats()["packets"], NUM_PKTS)
468 self.assertGreater(
469 len(sports), 1, "source port {} is not an entropy value".format(sports)
470 )
471
472 #
473 # 4o6 encap
474 #
475 p_4o6 = []
476 for i in range(NUM_PKTS):
477 p_4o6.append(
478 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
479 / IP(src="2.2.2.2", dst="1.1.2.1")
480 / UDP(sport=1234 + i, dport=1234)
481 / Raw(b"\xa5" * 100)
482 )
483 rx = self.send_and_expect(self.pg0, p_4o6, self.pg2)
484 sports = set()
485 for p in rx:
486 self.validate_outer6(p, udp_encap_2, True)
487 sports.add(p["UDP"].sport)
488 p = IP(p["UDP"].payload.load)
489 self.validate_inner4(p, p_4o6[i])
490 self.assertEqual(udp_encap_2.get_stats()["packets"], NUM_PKTS)
491 self.assertGreater(
492 len(sports), 1, "source port {} is not an entropy value".format(sports)
493 )
494
495 #
496 # 6o4 encap
497 #
498 p_6o4 = []
499 for i in range(NUM_PKTS):
500 p_6o4.append(
501 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
502 / IPv6(src="2001::100", dst="2001::1")
503 / UDP(sport=1234 + i, dport=1234)
504 / Raw(b"\xa5" * 100)
505 )
506 rx = self.send_and_expect(self.pg0, p_6o4, self.pg1)
507 sports = set()
508 for p in rx:
509 self.validate_outer4(p, udp_encap_1, True)
510 sports.add(p["UDP"].sport)
511 p = IPv6(p["UDP"].payload.load)
512 self.validate_inner6(p, p_6o4[i])
513 self.assertEqual(udp_encap_1.get_stats()["packets"], NUM_PKTS)
514 self.assertGreater(
515 len(sports), 1, "source port {} is not an entropy value".format(sports)
516 )
517
518 #
519 # 6o6 encap
520 #
521 p_6o6 = []
522 for i in range(NUM_PKTS):
523 p_6o6.append(
524 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
525 / IPv6(src="2001::100", dst="2001::3")
526 / UDP(sport=1234 + i, dport=1234)
527 / Raw(b"\xa5" * 100)
528 )
529 rx = self.send_and_expect(self.pg0, p_6o6, self.pg3)
530 sports = set()
531 for p in rx:
532 self.validate_outer6(p, udp_encap_3, True)
533 sports.add(p["UDP"].sport)
534 p = IPv6(p["UDP"].payload.load)
535 self.validate_inner6(p, p_6o6[i])
536 self.assertEqual(udp_encap_3.get_stats()["packets"], NUM_PKTS)
537 self.assertGreater(
538 len(sports), 1, "source port {} is not an entropy value".format(sports)
539 )
540
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200541 def test_udp_decap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200542 """UDP Decap test"""
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200543 #
544 # construct a UDP decap object for each type of protocol
545 #
546
547 # IPv4
548 udp_api_proto = VppEnum.vl_api_udp_decap_next_proto_t
549 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP4
550 udp_decap_0 = VppUdpDecap(self, 1, 220, next_proto)
551
552 # IPv6
553 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP6
554 udp_decap_1 = VppUdpDecap(self, 0, 221, next_proto)
555
556 # MPLS
557 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_MPLS
558 udp_decap_2 = VppUdpDecap(self, 1, 222, next_proto)
559
560 udp_decap_0.add_vpp_config()
561 udp_decap_1.add_vpp_config()
562 udp_decap_2.add_vpp_config()
563
564 #
565 # Routes via the corresponding pg after the UDP decap
566 #
567 route_4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200568 self,
569 "1.1.1.1",
570 32,
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200571 [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)],
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200572 table_id=0,
573 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200574
575 route_6 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200576 self, "2001::1", 128, [VppRoutePath("::", self.pg1.sw_if_index)], table_id=1
577 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200578
579 route_mo4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200580 self,
581 "3.3.3.3",
582 32,
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200583 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200584 table_id=2,
585 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200586
587 route_4.add_vpp_config()
588 route_6.add_vpp_config()
589 route_mo4.add_vpp_config()
590
591 #
592 # Adding neighbors to route the packets
593 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200594 n_4 = VppNeighbor(self, self.pg0.sw_if_index, "00:11:22:33:44:55", "1.1.1.1")
595 n_6 = VppNeighbor(self, self.pg1.sw_if_index, "11:22:33:44:55:66", "2001::1")
596 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 +0200597
598 n_4.add_vpp_config()
599 n_6.add_vpp_config()
600 n_mo4.add_vpp_config()
601
602 #
603 # MPLS decapsulation config
604 #
605 mpls_table = VppMplsTable(self, 0)
606 mpls_table.add_vpp_config()
607 mpls_route = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200608 self,
609 77,
610 1,
611 [
612 VppRoutePath(
613 "0.0.0.0",
614 0xFFFFFFFF,
615 nh_table_id=2,
616 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
617 )
618 ],
619 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200620 mpls_route.add_vpp_config()
621
622 #
623 # UDP over ipv4 decap
624 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200625 p_4 = (
626 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
627 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
628 / UDP(sport=1111, dport=220)
629 / IP(src="2.2.2.2", dst="1.1.1.1")
630 / UDP(sport=1234, dport=4321)
631 / Raw(b"\xa5" * 100)
632 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200633
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200634 rx = self.send_and_expect(self.pg0, p_4 * NUM_PKTS, self.pg0)
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200635 p_4 = IP(p_4["UDP"].payload)
636 for p in rx:
637 p = IP(p["Ether"].payload)
638 self.validate_inner4(p, p_4, ttl=63)
639
640 #
641 # UDP over ipv6 decap
642 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200643 p_6 = (
644 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
645 / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6)
646 / UDP(sport=2222, dport=221)
647 / IPv6(src="2001::100", dst="2001::1")
648 / UDP(sport=1234, dport=4321)
649 / Raw(b"\xa5" * 100)
650 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200651
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200652 rx = self.send_and_expect(self.pg1, p_6 * NUM_PKTS, self.pg1)
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200653 p_6 = IPv6(p_6["UDP"].payload)
654 p = IPv6(rx[0]["Ether"].payload)
655 for p in rx:
656 p = IPv6(p["Ether"].payload)
657 self.validate_inner6(p, p_6, hlim=63)
658
659 #
660 # UDP over mpls decap
661 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200662 p_mo4 = (
663 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
664 / IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4)
665 / UDP(sport=3333, dport=222)
666 / MPLS(label=77, ttl=1)
667 / IP(src="4.4.4.4", dst="3.3.3.3")
668 / UDP(sport=1234, dport=4321)
669 / Raw(b"\xa5" * 100)
670 )
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200671
672 self.pg2.enable_mpls()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200673 rx = self.send_and_expect(self.pg2, p_mo4 * NUM_PKTS, self.pg2)
Arthur de Kerhor8a6f5d32021-05-20 11:48:00 +0200674 self.pg2.disable_mpls()
675 p_mo4 = IP(MPLS(p_mo4["UDP"].payload).payload)
676 for p in rx:
677 p = IP(p["Ether"].payload)
678 self.validate_inner4(p, p_mo4, ttl=63)
679
Neale Ranns810086d2017-11-05 16:26:46 -0800680
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +0000681@tag_fixme_vpp_workers
Florin Coras40903ac2018-06-10 14:41:23 -0700682class TestUDP(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200683 """UDP Test Case"""
Florin Coras40903ac2018-06-10 14:41:23 -0700684
685 @classmethod
686 def setUpClass(cls):
687 super(TestUDP, cls).setUpClass()
688
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700689 @classmethod
690 def tearDownClass(cls):
691 super(TestUDP, cls).tearDownClass()
692
Florin Coras40903ac2018-06-10 14:41:23 -0700693 def setUp(self):
694 super(TestUDP, self).setUp()
Jakub Grajciar6a2794e2020-11-24 11:22:01 +0100695 self.vapi.session_enable_disable(is_enable=1)
Klement Sekerab9ef2732018-06-24 22:49:33 +0200696 self.create_loopback_interfaces(2)
Florin Coras40903ac2018-06-10 14:41:23 -0700697
698 table_id = 0
699
700 for i in self.lo_interfaces:
701 i.admin_up()
702
703 if table_id != 0:
704 tbl = VppIpTable(self, table_id)
705 tbl.add_vpp_config()
706
707 i.set_table_ip4(table_id)
708 i.config_ip4()
709 table_id += 1
710
711 # Configure namespaces
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200712 self.vapi.app_namespace_add_del(
713 namespace_id="0", sw_if_index=self.loop0.sw_if_index
714 )
715 self.vapi.app_namespace_add_del(
716 namespace_id="1", sw_if_index=self.loop1.sw_if_index
717 )
Florin Coras40903ac2018-06-10 14:41:23 -0700718
719 def tearDown(self):
720 for i in self.lo_interfaces:
721 i.unconfig_ip4()
722 i.set_table_ip4(0)
723 i.admin_down()
Jakub Grajciar6a2794e2020-11-24 11:22:01 +0100724 self.vapi.session_enable_disable(is_enable=0)
Florin Coras40903ac2018-06-10 14:41:23 -0700725 super(TestUDP, self).tearDown()
726
727 def test_udp_transfer(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200728 """UDP echo client/server transfer"""
Florin Coras40903ac2018-06-10 14:41:23 -0700729
730 # Add inter-table routes
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200731 ip_t01 = VppIpRoute(
732 self,
733 self.loop1.local_ip4,
734 32,
735 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)],
736 )
737 ip_t10 = VppIpRoute(
738 self,
739 self.loop0.local_ip4,
740 32,
741 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)],
742 table_id=1,
743 )
Florin Coras40903ac2018-06-10 14:41:23 -0700744 ip_t01.add_vpp_config()
745 ip_t10.add_vpp_config()
746
747 # Start builtin server and client
748 uri = "udp://" + self.loop0.local_ip4 + "/1234"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200749 error = self.vapi.cli(
750 "test echo server appns 0 fifo-size 4 no-echo" + "uri " + uri
751 )
Florin Coras40903ac2018-06-10 14:41:23 -0700752 if error:
753 self.logger.critical(error)
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800754 self.assertNotIn("failed", error)
Florin Coras40903ac2018-06-10 14:41:23 -0700755
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200756 error = self.vapi.cli(
757 "test echo client mbytes 10 appns 1 "
758 + "fifo-size 4 no-output test-bytes "
759 + "syn-timeout 2 no-return uri "
760 + uri
761 )
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
Florin Coras7a2abce2020-04-05 19:25:44 +0000766 self.logger.debug(self.vapi.cli("show session verbose 2"))
767
Florin Coras40903ac2018-06-10 14:41:23 -0700768 # Delete inter-table routes
769 ip_t01.remove_vpp_config()
770 ip_t10.remove_vpp_config()
771
772
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200773if __name__ == "__main__":
Neale Ranns810086d2017-11-05 16:26:46 -0800774 unittest.main(testRunner=VppTestRunner)