blob: 85b35fa7f24528d9cc790406406fddc699bc7bf2 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Ole Troan46c1c112018-03-14 20:39:40 +01002"""IP{4,6} over IP{v,6} tunnel functional tests"""
Ole Troan298c6952018-03-08 12:30:43 +01003
4import unittest
Neale Ranns0b6a8572019-10-30 17:34:14 +00005from scapy.layers.inet6 import IPv6, Ether, IP, UDP, IPv6ExtHdrFragment, Raw
Neale Rannse294de62020-12-21 09:52:24 +00006from scapy.contrib.mpls import MPLS
Ole Troan282093f2018-09-19 12:38:51 +02007from scapy.all import fragment, fragment6, RandShort, defragment6
Dave Wallace8800f732023-08-31 00:47:44 -04008from framework import VppTestCase
9from asfframework import VppTestRunner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020010from vpp_ip_route import (
11 VppIpRoute,
12 VppRoutePath,
13 VppIpTable,
14 FibPathProto,
15 VppMplsLabel,
16 VppMplsRoute,
17 VppMplsTable,
18)
Neale Ranns95346962019-11-25 13:04:44 +000019from vpp_ipip_tun_interface import VppIpIpTunInterface
Neale Ranns28287212019-12-16 00:53:11 +000020from vpp_teib import VppTeib
Neale Ranns95346962019-11-25 13:04:44 +000021from vpp_papi import VppEnum
Ole Troan7f991832018-12-06 17:35:12 +010022from util import reassemble4
23
Ole Troan298c6952018-03-08 12:30:43 +010024""" Testipip is a subclass of VPPTestCase classes.
25
26IPIP tests.
27
28"""
29
30
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020031def ipip_add_tunnel(test, src, dst, table_id=0, dscp=0x0, flags=0):
32 """Add a IPIP tunnel"""
Neale Rannscbd08242019-05-26 11:34:27 -070033 return test.vapi.ipip_add_tunnel(
34 tunnel={
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020035 "src": src,
36 "dst": dst,
37 "table_id": table_id,
38 "instance": 0xFFFFFFFF,
39 "dscp": dscp,
40 "flags": flags,
Neale Rannscbd08242019-05-26 11:34:27 -070041 }
42 )
43
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020044
Neale Ranns95346962019-11-25 13:04:44 +000045# the number of packets to send when injecting traffic.
46# a multiple of 8 minus one, so we test all by 8/4/2/1 loops
47N_PACKETS = 64 - 1
48
Neale Rannscbd08242019-05-26 11:34:27 -070049
Ole Troan298c6952018-03-08 12:30:43 +010050class TestIPIP(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020051 """IPIP Test Case"""
Ole Troan298c6952018-03-08 12:30:43 +010052
53 @classmethod
54 def setUpClass(cls):
55 super(TestIPIP, cls).setUpClass()
Neale Ranns256b67b2020-09-02 14:46:53 +000056 cls.create_pg_interfaces(range(3))
Ole Troan46c1c112018-03-14 20:39:40 +010057 cls.interfaces = list(cls.pg_interfaces)
Ole Troan298c6952018-03-08 12:30:43 +010058
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070059 @classmethod
60 def tearDownClass(cls):
61 super(TestIPIP, cls).tearDownClass()
62
Paul Vinciguerra741865b2018-11-27 06:01:22 -080063 def setUp(self):
64 super(TestIPIP, self).setUp()
Neale Ranns256b67b2020-09-02 14:46:53 +000065 self.table = VppIpTable(self, 1, register=False)
66 self.table.add_vpp_config()
67
Paul Vinciguerra741865b2018-11-27 06:01:22 -080068 for i in self.interfaces:
Ole Troan46c1c112018-03-14 20:39:40 +010069 i.admin_up()
Neale Ranns256b67b2020-09-02 14:46:53 +000070
71 self.pg2.set_table_ip4(self.table.table_id)
72 for i in self.interfaces:
Ole Troan46c1c112018-03-14 20:39:40 +010073 i.config_ip4()
74 i.config_ip6()
75 i.disable_ipv6_ra()
76 i.resolve_arp()
77 i.resolve_ndp()
Ole Troan298c6952018-03-08 12:30:43 +010078
79 def tearDown(self):
80 super(TestIPIP, self).tearDown()
81 if not self.vpp_dead:
Ole Troan46c1c112018-03-14 20:39:40 +010082 for i in self.pg_interfaces:
83 i.unconfig_ip4()
84 i.unconfig_ip6()
Neale Ranns256b67b2020-09-02 14:46:53 +000085 i.set_table_ip4(0)
Ole Troan46c1c112018-03-14 20:39:40 +010086 i.admin_down()
Ole Troan298c6952018-03-08 12:30:43 +010087
Neale Ranns256b67b2020-09-02 14:46:53 +000088 self.table.remove_vpp_config()
89
Ole Troan298c6952018-03-08 12:30:43 +010090 def validate(self, rx, expected):
Dave Wallacecf9356d2024-07-23 01:28:19 -040091 self.assertTrue(bytes(rx), bytes(expected))
Ole Troan298c6952018-03-08 12:30:43 +010092
Ole Troan282093f2018-09-19 12:38:51 +020093 def generate_ip4_frags(self, payload_length, fragment_size):
Ole Troan7eb9d962018-08-10 14:39:48 +020094 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
95 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
96 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020097 outer_ip4 = (
98 p_ether
99 / IP(src=self.pg1.remote_ip4, id=RandShort(), dst=self.pg0.local_ip4)
100 / p_ip4
101 / p_payload
102 )
Ole Troan7eb9d962018-08-10 14:39:48 +0200103 frags = fragment(outer_ip4, fragment_size)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200104 p4_reply = p_ip4 / p_payload
Ole Troan7eb9d962018-08-10 14:39:48 +0200105 p4_reply.ttl -= 1
106 return frags, p4_reply
107
Neale Ranns95346962019-11-25 13:04:44 +0000108 def verify_ip4ip4_encaps(self, a, p_ip4s, p_ip4_encaps):
109 for i, p_ip4 in enumerate(p_ip4s):
110 p_ip4.dst = a
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200111 p4 = self.p_ether / p_ip4 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000112 p_ip4_inner = p_ip4
113 p_ip4_inner.ttl -= 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200114 p4_reply = p_ip4_encaps[i] / p_ip4_inner / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000115 p4_reply.ttl -= 1
116 p4_reply.id = 0
117 rx = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1)
118 for p in rx:
119 self.validate(p[1], p4_reply)
120 self.assert_packet_checksums_valid(p)
121
122 def verify_ip6ip4_encaps(self, a, p_ip6s, p_ip4_encaps):
123 for i, p_ip6 in enumerate(p_ip6s):
124 p_ip6.dst = a
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200125 p6 = self.p_ether / p_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000126 p_inner_ip6 = p_ip6
127 p_inner_ip6.hlim -= 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200128 p6_reply = p_ip4_encaps[i] / p_inner_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000129 p6_reply.ttl -= 1
130 rx = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1)
131 for p in rx:
132 self.validate(p[1], p6_reply)
133 self.assert_packet_checksums_valid(p)
134
Ole Troan298c6952018-03-08 12:30:43 +0100135 def test_ipip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200136 """ip{v4,v6} over ip4 test"""
Ole Troan298c6952018-03-08 12:30:43 +0100137
Neale Ranns95346962019-11-25 13:04:44 +0000138 self.pg1.generate_remote_hosts(5)
139 self.pg1.configure_ipv4_neighbors()
Neale Ranns59ff9182019-12-29 23:55:18 +0000140 e = VppEnum.vl_api_tunnel_encap_decap_flags_t
Neale Ranns95346962019-11-25 13:04:44 +0000141 d = VppEnum.vl_api_ip_dscp_t
142 self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200143 self.p_payload = UDP(sport=1234, dport=1234) / Raw(b"X" * 100)
Ole Troan298c6952018-03-08 12:30:43 +0100144
Neale Ranns95346962019-11-25 13:04:44 +0000145 # create a TOS byte by shifting a DSCP code point 2 bits. those 2 bits
146 # are for the ECN.
147 dscp = d.IP_API_DSCP_AF31 << 2
148 ecn = 3
149 dscp_ecn = d.IP_API_DSCP_AF31 << 2 | ecn
Ole Troan298c6952018-03-08 12:30:43 +0100150
Neale Ranns95346962019-11-25 13:04:44 +0000151 # IPv4 transport that copies the DCSP from the payload
152 tun_dscp = VppIpIpTunInterface(
153 self,
154 self.pg0,
155 self.pg0.local_ip4,
156 self.pg1.remote_hosts[0].ip4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200157 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP,
158 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000159 tun_dscp.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000160 # IPv4 transport that copies the DCSP and ECN from the payload
161 tun_dscp_ecn = VppIpIpTunInterface(
162 self,
163 self.pg0,
164 self.pg0.local_ip4,
165 self.pg1.remote_hosts[1].ip4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200166 flags=(
167 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP
168 | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
169 ),
170 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000171 tun_dscp_ecn.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000172 # IPv4 transport that copies the ECN from the payload and sets the
173 # DF bit on encap. copies the ECN on decap
174 tun_ecn = VppIpIpTunInterface(
175 self,
176 self.pg0,
177 self.pg0.local_ip4,
178 self.pg1.remote_hosts[2].ip4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200179 flags=(
180 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
181 | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_DF
182 | e.TUNNEL_API_ENCAP_DECAP_FLAG_DECAP_COPY_ECN
183 ),
184 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000185 tun_ecn.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000186 # IPv4 transport that sets a fixed DSCP in the encap and copies
187 # the DF bit
188 tun = VppIpIpTunInterface(
189 self,
190 self.pg0,
191 self.pg0.local_ip4,
192 self.pg1.remote_hosts[3].ip4,
193 dscp=d.IP_API_DSCP_AF11,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200194 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DF,
195 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000196 tun.add_vpp_config()
Ole Troan298c6952018-03-08 12:30:43 +0100197
Neale Ranns95346962019-11-25 13:04:44 +0000198 # array of all the tunnels
199 tuns = [tun_dscp, tun_dscp_ecn, tun_ecn, tun]
Ole Troan298c6952018-03-08 12:30:43 +0100200
Neale Ranns95346962019-11-25 13:04:44 +0000201 # addresses for prefixes routed via each tunnel
202 a4s = ["" for i in range(len(tuns))]
203 a6s = ["" for i in range(len(tuns))]
204
205 # IP headers with each combination of DSCp/ECN tested
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200206 p_ip6s = [
207 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=dscp),
208 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=dscp_ecn),
209 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=ecn),
210 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=0xFF),
211 ]
212 p_ip4s = [
213 IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp, flags="DF"),
214 IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp_ecn),
215 IP(src="1.2.3.4", dst="130.67.0.1", tos=ecn),
216 IP(src="1.2.3.4", dst="130.67.0.1", tos=0xFF),
217 ]
Neale Ranns95346962019-11-25 13:04:44 +0000218
219 # Configure each tunnel
220 for i, t in enumerate(tuns):
221 # Set interface up and enable IP on it
222 self.vapi.sw_interface_set_flags(t.sw_if_index, 1)
223 self.vapi.sw_interface_set_unnumbered(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200224 sw_if_index=self.pg0.sw_if_index, unnumbered_sw_if_index=t.sw_if_index
225 )
Neale Ranns95346962019-11-25 13:04:44 +0000226
227 # prefix for route / destination address for packets
228 a4s[i] = "130.67.%d.0" % i
229 a6s[i] = "dead:%d::" % i
230
231 # Add IPv4 and IPv6 routes via tunnel interface
232 ip4_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200233 self,
234 a4s[i],
235 24,
236 [
237 VppRoutePath(
238 "0.0.0.0",
239 t.sw_if_index,
240 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
241 )
242 ],
243 )
Neale Ranns95346962019-11-25 13:04:44 +0000244 ip4_via_tunnel.add_vpp_config()
245
246 ip6_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200247 self,
248 a6s[i],
249 64,
250 [
251 VppRoutePath(
252 "::", t.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6
253 )
254 ],
255 )
Neale Ranns95346962019-11-25 13:04:44 +0000256 ip6_via_tunnel.add_vpp_config()
257
258 #
259 # Encapsulation
260 #
261
262 # tun_dscp copies only the dscp
263 # expected TC values are thus only the DCSP value is present from the
264 # inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200265 exp_tcs = [dscp, dscp, 0, 0xFC]
266 p_ip44_encaps = [
267 IP(src=self.pg0.local_ip4, dst=tun_dscp.dst, tos=tc) for tc in exp_tcs
268 ]
269 p_ip64_encaps = [
270 IP(src=self.pg0.local_ip4, dst=tun_dscp.dst, proto="ipv6", id=0, tos=tc)
271 for tc in exp_tcs
272 ]
Ole Troan298c6952018-03-08 12:30:43 +0100273
274 # IPv4 in to IPv4 tunnel
Neale Ranns95346962019-11-25 13:04:44 +0000275 self.verify_ip4ip4_encaps(a4s[0], p_ip4s, p_ip44_encaps)
276 # IPv6 in to IPv4 tunnel
277 self.verify_ip6ip4_encaps(a6s[0], p_ip6s, p_ip64_encaps)
Ole Troan298c6952018-03-08 12:30:43 +0100278
Neale Ranns95346962019-11-25 13:04:44 +0000279 # tun_dscp_ecn copies the dscp and the ecn
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200280 exp_tcs = [dscp, dscp_ecn, ecn, 0xFF]
281 p_ip44_encaps = [
282 IP(src=self.pg0.local_ip4, dst=tun_dscp_ecn.dst, tos=tc) for tc in exp_tcs
283 ]
284 p_ip64_encaps = [
285 IP(src=self.pg0.local_ip4, dst=tun_dscp_ecn.dst, proto="ipv6", id=0, tos=tc)
286 for tc in exp_tcs
287 ]
Neale Ranns95346962019-11-25 13:04:44 +0000288
289 self.verify_ip4ip4_encaps(a4s[1], p_ip4s, p_ip44_encaps)
290 self.verify_ip6ip4_encaps(a6s[1], p_ip6s, p_ip64_encaps)
291
292 # tun_ecn copies only the ecn and always sets DF
293 exp_tcs = [0, ecn, ecn, ecn]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200294 p_ip44_encaps = [
295 IP(src=self.pg0.local_ip4, dst=tun_ecn.dst, flags="DF", tos=tc)
296 for tc in exp_tcs
297 ]
298 p_ip64_encaps = [
299 IP(
300 src=self.pg0.local_ip4,
301 dst=tun_ecn.dst,
302 flags="DF",
303 proto="ipv6",
304 id=0,
305 tos=tc,
306 )
307 for tc in exp_tcs
308 ]
Neale Ranns95346962019-11-25 13:04:44 +0000309
310 self.verify_ip4ip4_encaps(a4s[2], p_ip4s, p_ip44_encaps)
311 self.verify_ip6ip4_encaps(a6s[2], p_ip6s, p_ip64_encaps)
312
313 # tun sets a fixed dscp and copies DF
314 fixed_dscp = tun.dscp << 2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200315 flags = ["DF", 0, 0, 0]
316 p_ip44_encaps = [
317 IP(src=self.pg0.local_ip4, dst=tun.dst, flags=f, tos=fixed_dscp)
318 for f in flags
319 ]
320 p_ip64_encaps = [
321 IP(src=self.pg0.local_ip4, dst=tun.dst, proto="ipv6", id=0, tos=fixed_dscp)
322 for i in range(len(p_ip4s))
323 ]
Neale Ranns95346962019-11-25 13:04:44 +0000324
325 self.verify_ip4ip4_encaps(a4s[3], p_ip4s, p_ip44_encaps)
326 self.verify_ip6ip4_encaps(a6s[3], p_ip6s, p_ip64_encaps)
327
328 #
Ole Troan298c6952018-03-08 12:30:43 +0100329 # Decapsulation
Neale Ranns95346962019-11-25 13:04:44 +0000330 #
331 n_packets_decapped = 0
332 self.p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
Ole Troan298c6952018-03-08 12:30:43 +0100333
334 # IPv4 tunnel to IPv4
Neale Ranns95346962019-11-25 13:04:44 +0000335 tcs = [0, dscp, dscp_ecn, ecn]
336
337 # one overlay packet and all combinations of its encap
Ole Troan298c6952018-03-08 12:30:43 +0100338 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200339 p_ip4_encaps = [IP(src=tun.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs]
Neale Ranns95346962019-11-25 13:04:44 +0000340
341 # for each encap tun will produce the same inner packet because it does
342 # not copy up fields from the payload
343 for p_ip4_encap in p_ip4_encaps:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200344 p4 = self.p_ether / p_ip4_encap / p_ip4 / self.p_payload
345 p4_reply = p_ip4 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000346 p4_reply.ttl -= 1
347 rx = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
348 n_packets_decapped += N_PACKETS
349 for p in rx:
350 self.validate(p[1], p4_reply)
351 self.assert_packet_checksums_valid(p)
Ole Troan298c6952018-03-08 12:30:43 +0100352
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200353 err = self.statistics.get_err_counter("/err/ipip4-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +0000354 self.assertEqual(err, n_packets_decapped)
355
356 # tun_ecn copies the ECN bits from the encap to the inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200357 p_ip4_encaps = [
358 IP(src=tun_ecn.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs
359 ]
Neale Ranns95346962019-11-25 13:04:44 +0000360 p_ip4_replys = [p_ip4.copy() for i in range(len(p_ip4_encaps))]
361 p_ip4_replys[2].tos = ecn
362 p_ip4_replys[3].tos = ecn
363 for i, p_ip4_encap in enumerate(p_ip4_encaps):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200364 p4 = self.p_ether / p_ip4_encap / p_ip4 / self.p_payload
365 p4_reply = p_ip4_replys[i] / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000366 p4_reply.ttl -= 1
367 rx = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
368 n_packets_decapped += N_PACKETS
369 for p in rx:
370 self.validate(p[1], p4_reply)
371 self.assert_packet_checksums_valid(p)
372
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200373 err = self.statistics.get_err_counter("/err/ipip4-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +0000374 self.assertEqual(err, n_packets_decapped)
Ole Troan73202102018-08-31 00:29:48 +0200375
Ole Troan298c6952018-03-08 12:30:43 +0100376 # IPv4 tunnel to IPv6
Neale Ranns95346962019-11-25 13:04:44 +0000377 # for each encap tun will produce the same inner packet because it does
378 # not copy up fields from the payload
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200379 p_ip4_encaps = [IP(src=tun.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs]
Ole Troan298c6952018-03-08 12:30:43 +0100380 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
Neale Ranns95346962019-11-25 13:04:44 +0000381 for p_ip4_encap in p_ip4_encaps:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200382 p6 = self.p_ether / p_ip4_encap / p_ip6 / self.p_payload
383 p6_reply = p_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000384 p6_reply.hlim = 63
385 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
386 n_packets_decapped += N_PACKETS
387 for p in rx:
388 self.validate(p[1], p6_reply)
389 self.assert_packet_checksums_valid(p)
Ole Troan298c6952018-03-08 12:30:43 +0100390
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200391 err = self.statistics.get_err_counter("/err/ipip4-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +0000392 self.assertEqual(err, n_packets_decapped)
393
394 # IPv4 tunnel to IPv6
395 # tun_ecn copies the ECN bits from the encap to the inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200396 p_ip4_encaps = [
397 IP(src=tun_ecn.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs
398 ]
Neale Ranns95346962019-11-25 13:04:44 +0000399 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
400 p_ip6_replys = [p_ip6.copy() for i in range(len(p_ip4_encaps))]
401 p_ip6_replys[2].tc = ecn
402 p_ip6_replys[3].tc = ecn
403 for i, p_ip4_encap in enumerate(p_ip4_encaps):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200404 p6 = self.p_ether / p_ip4_encap / p_ip6 / self.p_payload
405 p6_reply = p_ip6_replys[i] / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000406 p6_reply.hlim = 63
407 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
408 n_packets_decapped += N_PACKETS
409 for p in rx:
410 self.validate(p[1], p6_reply)
411 self.assert_packet_checksums_valid(p)
412
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200413 err = self.statistics.get_err_counter("/err/ipip4-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +0000414 self.assertEqual(err, n_packets_decapped)
Ole Troan73202102018-08-31 00:29:48 +0200415
Ole Troan7eb9d962018-08-10 14:39:48 +0200416 #
Ole Troan4146c652018-08-08 22:23:19 +0200417 # Fragmentation / Reassembly and Re-fragmentation
Ole Troan7eb9d962018-08-10 14:39:48 +0200418 #
Ole Troan4146c652018-08-08 22:23:19 +0200419 rv = self.vapi.ip_reassembly_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200420 sw_if_index=self.pg1.sw_if_index, enable_ip4=1
421 )
Ole Troan4146c652018-08-08 22:23:19 +0200422
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200423 self.vapi.ip_reassembly_set(
424 timeout_ms=1000,
425 max_reassemblies=1000,
426 max_reassembly_length=1000,
427 expire_walk_interval_ms=10000,
428 is_ip6=0,
429 )
Klement Sekera3a343d42019-05-16 14:35:46 +0200430
Ole Troan7eb9d962018-08-10 14:39:48 +0200431 # Send lots of fragments, verify reassembled packet
Ole Troan282093f2018-09-19 12:38:51 +0200432 frags, p4_reply = self.generate_ip4_frags(3131, 1400)
Ole Troan7eb9d962018-08-10 14:39:48 +0200433 f = []
434 for i in range(0, 1000):
435 f.extend(frags)
436 self.pg1.add_stream(f)
Ole Troan4146c652018-08-08 22:23:19 +0200437 self.pg_enable_capture()
Ole Troan4146c652018-08-08 22:23:19 +0200438 self.pg_start()
Ole Troan7eb9d962018-08-10 14:39:48 +0200439 rx = self.pg0.get_capture(1000)
Neale Ranns95346962019-11-25 13:04:44 +0000440 n_packets_decapped += 1000
Ole Troan7eb9d962018-08-10 14:39:48 +0200441
Ole Troan4146c652018-08-08 22:23:19 +0200442 for p in rx:
443 self.validate(p[1], p4_reply)
444
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200445 err = self.statistics.get_err_counter("/err/ipip4-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +0000446 self.assertEqual(err, n_packets_decapped)
Ole Troan73202102018-08-31 00:29:48 +0200447
Ole Troan7eb9d962018-08-10 14:39:48 +0200448 f = []
449 r = []
450 for i in range(1, 90):
Ole Troan282093f2018-09-19 12:38:51 +0200451 frags, p4_reply = self.generate_ip4_frags(i * 100, 1000)
Ole Troan7eb9d962018-08-10 14:39:48 +0200452 f.extend(frags)
453 r.extend(p4_reply)
454 self.pg_enable_capture()
455 self.pg1.add_stream(f)
456 self.pg_start()
457 rx = self.pg0.get_capture(89)
458 i = 0
459 for p in rx:
460 self.validate(p[1], r[i])
461 i += 1
462
Ole Troan4146c652018-08-08 22:23:19 +0200463 # Now try with re-fragmentation
Ole Troan7eb9d962018-08-10 14:39:48 +0200464 #
465 # Send fragments to tunnel head-end, for the tunnel head end
466 # to reassemble and then refragment
467 #
Ole Troan4146c652018-08-08 22:23:19 +0200468 self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [576, 0, 0, 0])
Ole Troan282093f2018-09-19 12:38:51 +0200469 frags, p4_reply = self.generate_ip4_frags(3123, 1200)
Ole Troan4146c652018-08-08 22:23:19 +0200470 self.pg_enable_capture()
471 self.pg1.add_stream(frags)
472 self.pg_start()
473 rx = self.pg0.get_capture(6)
Ole Troan7f991832018-12-06 17:35:12 +0100474 reass_pkt = reassemble4(rx)
Ole Troan4146c652018-08-08 22:23:19 +0200475 p4_reply.id = 256
476 self.validate(reass_pkt, p4_reply)
477
Ole Troan7eb9d962018-08-10 14:39:48 +0200478 self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1600, 0, 0, 0])
Ole Troan282093f2018-09-19 12:38:51 +0200479 frags, p4_reply = self.generate_ip4_frags(3123, 1200)
Ole Troan7eb9d962018-08-10 14:39:48 +0200480 self.pg_enable_capture()
481 self.pg1.add_stream(frags)
482 self.pg_start()
483 rx = self.pg0.get_capture(2)
Ole Troan7f991832018-12-06 17:35:12 +0100484 reass_pkt = reassemble4(rx)
Ole Troan7eb9d962018-08-10 14:39:48 +0200485 p4_reply.id = 512
486 self.validate(reass_pkt, p4_reply)
487
Neale Ranns0b6a8572019-10-30 17:34:14 +0000488 # send large packets through the tunnel, expect them to be fragmented
Neale Ranns95346962019-11-25 13:04:44 +0000489 self.vapi.sw_interface_set_mtu(tun_dscp.sw_if_index, [600, 0, 0, 0])
Neale Ranns0b6a8572019-10-30 17:34:14 +0000490
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200491 p4 = (
492 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
493 / IP(src="1.2.3.4", dst="130.67.0.1", tos=42)
494 / UDP(sport=1234, dport=1234)
495 / Raw(b"Q" * 1000)
496 )
Neale Ranns0b6a8572019-10-30 17:34:14 +0000497 rx = self.send_and_expect(self.pg0, p4 * 15, self.pg1, 30)
498 inners = []
499 for p in rx:
500 inners.append(p[IP].payload)
501 reass_pkt = reassemble4(inners)
502 for p in reass_pkt:
503 self.assert_packet_checksums_valid(p)
504 self.assertEqual(p[IP].ttl, 63)
505
Ole Troan282093f2018-09-19 12:38:51 +0200506 def test_ipip_create(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200507 """ipip create / delete interface test"""
508 rv = ipip_add_tunnel(self, "1.2.3.4", "2.3.4.5")
Ole Troan282093f2018-09-19 12:38:51 +0200509 sw_if_index = rv.sw_if_index
510 self.vapi.ipip_del_tunnel(sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +0100511
Ole Troan282093f2018-09-19 12:38:51 +0200512 def test_ipip_vrf_create(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200513 """ipip create / delete interface VRF test"""
Ole Troan282093f2018-09-19 12:38:51 +0200514
515 t = VppIpTable(self, 20)
516 t.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200517 rv = ipip_add_tunnel(self, "1.2.3.4", "2.3.4.5", table_id=20)
Ole Troan282093f2018-09-19 12:38:51 +0200518 sw_if_index = rv.sw_if_index
519 self.vapi.ipip_del_tunnel(sw_if_index)
520
521 def payload(self, len):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200522 return "x" * len
Ole Troan282093f2018-09-19 12:38:51 +0200523
Neale Ranns14053c92019-12-29 23:55:18 +0000524 def test_mipip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200525 """p2mp IPv4 tunnel Tests"""
Neale Ranns14053c92019-12-29 23:55:18 +0000526
Neale Ranns256b67b2020-09-02 14:46:53 +0000527 for itf in self.pg_interfaces[:2]:
Neale Ranns14053c92019-12-29 23:55:18 +0000528 #
529 # one underlay nh for each overlay/tunnel peer
530 #
531 itf.generate_remote_hosts(4)
532 itf.configure_ipv4_neighbors()
533
534 #
535 # Create an p2mo IPIP tunnel.
536 # - set it admin up
537 # - assign an IP Addres
538 # - Add a route via the tunnel
539 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200540 ipip_if = VppIpIpTunInterface(
541 self,
542 itf,
543 itf.local_ip4,
544 "0.0.0.0",
545 mode=(VppEnum.vl_api_tunnel_mode_t.TUNNEL_API_MODE_MP),
546 )
Neale Ranns14053c92019-12-29 23:55:18 +0000547 ipip_if.add_vpp_config()
548 ipip_if.admin_up()
549 ipip_if.config_ip4()
550 ipip_if.generate_remote_hosts(4)
551
552 self.logger.info(self.vapi.cli("sh adj"))
553 self.logger.info(self.vapi.cli("sh ip fib"))
554
555 #
556 # ensure we don't match to the tunnel if the source address
557 # is all zeros
558 #
559 # tx = self.create_tunnel_stream_4o4(self.pg0,
560 # "0.0.0.0",
561 # itf.local_ip4,
562 # self.pg0.local_ip4,
563 # self.pg0.remote_ip4)
564 # self.send_and_assert_no_replies(self.pg0, tx)
565
566 #
567 # for-each peer
568 #
569 for ii in range(1, 4):
570 route_addr = "4.4.4.%d" % ii
571
572 #
573 # route traffic via the peer
574 #
575 route_via_tun = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200576 self,
577 route_addr,
578 32,
579 [VppRoutePath(ipip_if._remote_hosts[ii].ip4, ipip_if.sw_if_index)],
580 )
Neale Ranns14053c92019-12-29 23:55:18 +0000581 route_via_tun.add_vpp_config()
582
583 #
Neale Ranns28287212019-12-16 00:53:11 +0000584 # Add a TEIB entry resolves the peer
Neale Ranns14053c92019-12-29 23:55:18 +0000585 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200586 teib = VppTeib(
587 self,
588 ipip_if,
589 ipip_if._remote_hosts[ii].ip4,
590 itf._remote_hosts[ii].ip4,
591 )
Neale Ranns03ce4622020-02-03 10:55:09 +0000592 teib.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200593 self.logger.info(
594 self.vapi.cli("sh adj nbr ipip0 %s" % ipip_if._remote_hosts[ii].ip4)
595 )
Neale Ranns14053c92019-12-29 23:55:18 +0000596
597 #
598 # Send a packet stream that is routed into the tunnel
599 # - packets are IPIP encapped
600 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200601 inner = (
602 IP(dst=route_addr, src="5.5.5.5")
603 / UDP(sport=1234, dport=1234)
604 / Raw(b"0x44" * 100)
605 )
606 tx_e = [
607 (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / inner)
608 for x in range(63)
609 ]
Neale Ranns14053c92019-12-29 23:55:18 +0000610
611 rxs = self.send_and_expect(self.pg0, tx_e, itf)
612
613 for rx in rxs:
614 self.assertEqual(rx[IP].src, itf.local_ip4)
615 self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4)
616
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200617 tx_i = [
618 (
619 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
620 / IP(src=itf._remote_hosts[ii].ip4, dst=itf.local_ip4)
621 / IP(src=self.pg0.local_ip4, dst=self.pg0.remote_ip4)
622 / UDP(sport=1234, dport=1234)
623 / Raw(b"0x44" * 100)
624 )
625 for x in range(63)
626 ]
Neale Ranns14053c92019-12-29 23:55:18 +0000627
628 self.logger.info(self.vapi.cli("sh ipip tunnel-hash"))
629 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
630
631 #
Neale Ranns28287212019-12-16 00:53:11 +0000632 # delete and re-add the TEIB
Neale Ranns14053c92019-12-29 23:55:18 +0000633 #
Neale Ranns03ce4622020-02-03 10:55:09 +0000634 teib.remove_vpp_config()
Neale Ranns14053c92019-12-29 23:55:18 +0000635 self.send_and_assert_no_replies(self.pg0, tx_e)
636 self.send_and_assert_no_replies(self.pg0, tx_i)
637
Neale Ranns03ce4622020-02-03 10:55:09 +0000638 teib.add_vpp_config()
Neale Ranns14053c92019-12-29 23:55:18 +0000639 rx = self.send_and_expect(self.pg0, tx_e, itf)
640 for rx in rxs:
641 self.assertEqual(rx[IP].src, itf.local_ip4)
642 self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4)
643 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
644
Neale Ranns256b67b2020-09-02 14:46:53 +0000645 #
646 # we can also send to the peer's address
647 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200648 inner = (
649 IP(dst=teib.peer, src="5.5.5.5")
650 / UDP(sport=1234, dport=1234)
651 / Raw(b"0x44" * 100)
652 )
653 tx_e = [
654 (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / inner)
655 for x in range(63)
656 ]
Neale Ranns256b67b2020-09-02 14:46:53 +0000657
658 rxs = self.send_and_expect(self.pg0, tx_e, itf)
659
660 #
661 # with all of the peers in place, swap the ip-table of
662 # the ipip interface
663 #
664 table = VppIpTable(self, 2)
665 table.add_vpp_config()
666
667 ipip_if.unconfig_ip4()
668 ipip_if.set_table_ip4(self.table.table_id)
669 ipip_if.config_ip4()
670
671 #
672 # we should still be able to reach the peers from the new table
673 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200674 inner = (
675 IP(dst=teib.peer, src="5.5.5.5")
676 / UDP(sport=1234, dport=1234)
677 / Raw(b"0x44" * 100)
678 )
679 tx_e = [
Steven Luonge4238aa2024-04-19 09:49:20 -0700680 (Ether(dst=self.pg2.local_mac, src=self.pg0.remote_mac) / inner)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200681 for x in range(63)
682 ]
Neale Ranns256b67b2020-09-02 14:46:53 +0000683
684 rxs = self.send_and_expect(self.pg2, tx_e, itf)
685
Neale Ranns14053c92019-12-29 23:55:18 +0000686 ipip_if.admin_down()
687 ipip_if.unconfig_ip4()
Neale Ranns256b67b2020-09-02 14:46:53 +0000688 ipip_if.set_table_ip4(0)
Neale Ranns14053c92019-12-29 23:55:18 +0000689
Ole Troan282093f2018-09-19 12:38:51 +0200690
691class TestIPIP6(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200692 """IPIP6 Test Case"""
Ole Troan282093f2018-09-19 12:38:51 +0200693
694 @classmethod
695 def setUpClass(cls):
696 super(TestIPIP6, cls).setUpClass()
697 cls.create_pg_interfaces(range(2))
698 cls.interfaces = list(cls.pg_interfaces)
699
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700700 @classmethod
701 def tearDownClass(cls):
702 super(TestIPIP6, cls).tearDownClass()
703
Ole Troan282093f2018-09-19 12:38:51 +0200704 def setUp(self):
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800705 super(TestIPIP6, self).setUp()
Ole Troan282093f2018-09-19 12:38:51 +0200706 for i in self.interfaces:
707 i.admin_up()
708 i.config_ip4()
709 i.config_ip6()
710 i.disable_ipv6_ra()
711 i.resolve_arp()
712 i.resolve_ndp()
713 self.setup_tunnel()
714
715 def tearDown(self):
716 if not self.vpp_dead:
717 self.destroy_tunnel()
718 for i in self.pg_interfaces:
719 i.unconfig_ip4()
720 i.unconfig_ip6()
721 i.admin_down()
722 super(TestIPIP6, self).tearDown()
723
724 def setup_tunnel(self):
Ole Troan298c6952018-03-08 12:30:43 +0100725 # IPv6 transport
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200726 rv = ipip_add_tunnel(self, self.pg0.local_ip6, self.pg1.remote_ip6)
Ole Troan298c6952018-03-08 12:30:43 +0100727
728 sw_if_index = rv.sw_if_index
Ole Troan282093f2018-09-19 12:38:51 +0200729 self.tunnel_if_index = sw_if_index
Ole Troan46c1c112018-03-14 20:39:40 +0100730 self.vapi.sw_interface_set_flags(sw_if_index, 1)
731 self.vapi.sw_interface_set_unnumbered(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200732 sw_if_index=self.pg0.sw_if_index, unnumbered_sw_if_index=sw_if_index
733 )
Ole Troan298c6952018-03-08 12:30:43 +0100734
735 # Add IPv4 and IPv6 routes via tunnel interface
736 ip4_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200737 self,
738 "130.67.0.0",
739 16,
740 [
741 VppRoutePath(
742 "0.0.0.0", sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4
743 )
744 ],
745 )
Ole Troan298c6952018-03-08 12:30:43 +0100746 ip4_via_tunnel.add_vpp_config()
747
748 ip6_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200749 self,
750 "dead::",
751 16,
752 [VppRoutePath("::", sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)],
753 )
Ole Troan298c6952018-03-08 12:30:43 +0100754 ip6_via_tunnel.add_vpp_config()
755
Ole Troan282093f2018-09-19 12:38:51 +0200756 self.tunnel_ip6_via_tunnel = ip6_via_tunnel
757 self.tunnel_ip4_via_tunnel = ip4_via_tunnel
Ole Troan298c6952018-03-08 12:30:43 +0100758
Ole Troan282093f2018-09-19 12:38:51 +0200759 def destroy_tunnel(self):
760 # IPv6 transport
761 self.tunnel_ip4_via_tunnel.remove_vpp_config()
762 self.tunnel_ip6_via_tunnel.remove_vpp_config()
763
764 rv = self.vapi.ipip_del_tunnel(sw_if_index=self.tunnel_if_index)
765
766 def validate(self, rx, expected):
Dave Wallacecf9356d2024-07-23 01:28:19 -0400767 self.assertTrue(bytes(rx), bytes(expected))
Ole Troan282093f2018-09-19 12:38:51 +0200768
769 def generate_ip6_frags(self, payload_length, fragment_size):
770 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
771 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
772 p_ip6 = IPv6(src="1::1", dst=self.pg0.remote_ip6)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200773 outer_ip6 = (
774 p_ether
775 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.local_ip6)
776 / IPv6ExtHdrFragment()
777 / p_ip6
778 / p_payload
779 )
Ole Troan282093f2018-09-19 12:38:51 +0200780 frags = fragment6(outer_ip6, fragment_size)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200781 p6_reply = p_ip6 / p_payload
Ole Troan282093f2018-09-19 12:38:51 +0200782 p6_reply.hlim -= 1
783 return frags, p6_reply
784
785 def generate_ip6_hairpin_frags(self, payload_length, fragment_size):
786 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
787 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
788 p_ip6 = IPv6(src="1::1", dst="dead::1")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200789 outer_ip6 = (
790 p_ether
791 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.local_ip6)
792 / IPv6ExtHdrFragment()
793 / p_ip6
794 / p_payload
795 )
Ole Troan282093f2018-09-19 12:38:51 +0200796 frags = fragment6(outer_ip6, fragment_size)
797 p_ip6.hlim -= 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200798 p6_reply = (
799 IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=63)
800 / p_ip6
801 / p_payload
802 )
Ole Troan282093f2018-09-19 12:38:51 +0200803
804 return frags, p6_reply
805
806 def test_encap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200807 """ip{v4,v6} over ip6 test encap"""
Ole Troan282093f2018-09-19 12:38:51 +0200808 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200809 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh="UDP")
Ole Troan282093f2018-09-19 12:38:51 +0200810 p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42)
811 p_payload = UDP(sport=1234, dport=1234)
812
813 # Encapsulation
Ole Troan298c6952018-03-08 12:30:43 +0100814 # IPv6 in to IPv6 tunnel
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200815 p6 = p_ether / p_ip6 / p_payload
816 p6_reply = (
817 IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=64)
818 / p_ip6
819 / p_payload
820 )
Ole Troan298c6952018-03-08 12:30:43 +0100821 p6_reply[1].hlim -= 1
Ole Troan9a475372019-03-05 16:58:24 +0100822 rx = self.send_and_expect(self.pg0, p6 * 11, self.pg1)
Ole Troan298c6952018-03-08 12:30:43 +0100823 for p in rx:
824 self.validate(p[1], p6_reply)
825
826 # IPv4 in to IPv6 tunnel
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200827 p4 = p_ether / p_ip4 / p_payload
828 p4_reply = (
829 IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=64)
830 / p_ip4
831 / p_payload
832 )
Ole Troan298c6952018-03-08 12:30:43 +0100833 p4_reply[1].ttl -= 1
Ole Troan9a475372019-03-05 16:58:24 +0100834 rx = self.send_and_expect(self.pg0, p4 * 11, self.pg1)
Ole Troan298c6952018-03-08 12:30:43 +0100835 for p in rx:
836 self.validate(p[1], p4_reply)
837
Ole Troan282093f2018-09-19 12:38:51 +0200838 def test_decap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200839 """ip{v4,v6} over ip6 test decap"""
Ole Troan298c6952018-03-08 12:30:43 +0100840
841 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200842 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh="UDP")
Ole Troan298c6952018-03-08 12:30:43 +0100843 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
Ole Troan282093f2018-09-19 12:38:51 +0200844 p_payload = UDP(sport=1234, dport=1234)
845
846 # Decapsulation
847 # IPv6 tunnel to IPv4
848
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200849 p4 = (
850 p_ether
851 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.local_ip6)
852 / p_ip4
853 / p_payload
854 )
855 p4_reply = p_ip4 / p_payload
Ole Troan298c6952018-03-08 12:30:43 +0100856 p4_reply.ttl -= 1
Ole Troan9a475372019-03-05 16:58:24 +0100857 rx = self.send_and_expect(self.pg1, p4 * 11, self.pg0)
Ole Troan298c6952018-03-08 12:30:43 +0100858 for p in rx:
859 self.validate(p[1], p4_reply)
860
861 # IPv6 tunnel to IPv6
862 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200863 p6 = (
864 p_ether
865 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.local_ip6)
866 / p_ip6
867 / p_payload
868 )
869 p6_reply = p_ip6 / p_payload
Ole Troan298c6952018-03-08 12:30:43 +0100870 p6_reply.hlim = 63
Ole Troan9a475372019-03-05 16:58:24 +0100871 rx = self.send_and_expect(self.pg1, p6 * 11, self.pg0)
Ole Troan298c6952018-03-08 12:30:43 +0100872 for p in rx:
873 self.validate(p[1], p6_reply)
874
Neale Ranns95346962019-11-25 13:04:44 +0000875 def verify_ip4ip6_encaps(self, a, p_ip4s, p_ip6_encaps):
876 for i, p_ip4 in enumerate(p_ip4s):
877 p_ip4.dst = a
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200878 p4 = self.p_ether / p_ip4 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000879 p_ip4_inner = p_ip4
880 p_ip4_inner.ttl -= 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200881 p6_reply = p_ip6_encaps[i] / p_ip4_inner / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000882 rx = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1)
883 for p in rx:
884 self.validate(p[1], p6_reply)
885 self.assert_packet_checksums_valid(p)
886
887 def verify_ip6ip6_encaps(self, a, p_ip6s, p_ip6_encaps):
888 for i, p_ip6 in enumerate(p_ip6s):
889 p_ip6.dst = a
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200890 p6 = self.p_ether / p_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000891 p_inner_ip6 = p_ip6
892 p_inner_ip6.hlim -= 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200893 p6_reply = p_ip6_encaps[i] / p_inner_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000894 rx = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1)
895 for p in rx:
896 self.validate(p[1], p6_reply)
897 self.assert_packet_checksums_valid(p)
898
899 def test_ipip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200900 """ip{v4,v6} over ip6 test"""
Neale Ranns95346962019-11-25 13:04:44 +0000901
902 # that's annoying
903 self.destroy_tunnel()
904
905 self.pg1.generate_remote_hosts(5)
906 self.pg1.configure_ipv6_neighbors()
Neale Ranns59ff9182019-12-29 23:55:18 +0000907 e = VppEnum.vl_api_tunnel_encap_decap_flags_t
Neale Ranns95346962019-11-25 13:04:44 +0000908 d = VppEnum.vl_api_ip_dscp_t
909 self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200910 self.p_payload = UDP(sport=1234, dport=1234) / Raw(b"X" * 100)
Neale Ranns95346962019-11-25 13:04:44 +0000911
912 # create a TOS byte by shifting a DSCP code point 2 bits. those 2 bits
913 # are for the ECN.
914 dscp = d.IP_API_DSCP_AF31 << 2
915 ecn = 3
916 dscp_ecn = d.IP_API_DSCP_AF31 << 2 | ecn
917
918 # IPv4 transport that copies the DCSP from the payload
919 tun_dscp = VppIpIpTunInterface(
920 self,
921 self.pg0,
922 self.pg0.local_ip6,
923 self.pg1.remote_hosts[0].ip6,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200924 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP,
925 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000926 tun_dscp.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000927 # IPv4 transport that copies the DCSP and ECN from the payload
928 tun_dscp_ecn = VppIpIpTunInterface(
929 self,
930 self.pg0,
931 self.pg0.local_ip6,
932 self.pg1.remote_hosts[1].ip6,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200933 flags=(
934 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP
935 | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
936 ),
937 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000938 tun_dscp_ecn.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000939 # IPv4 transport that copies the ECN from the payload and sets the
940 # DF bit on encap. copies the ECN on decap
941 tun_ecn = VppIpIpTunInterface(
942 self,
943 self.pg0,
944 self.pg0.local_ip6,
945 self.pg1.remote_hosts[2].ip6,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200946 flags=(
947 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
948 | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_DF
949 | e.TUNNEL_API_ENCAP_DECAP_FLAG_DECAP_COPY_ECN
950 ),
951 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000952 tun_ecn.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000953 # IPv4 transport that sets a fixed DSCP in the encap and copies
954 # the DF bit
955 tun = VppIpIpTunInterface(
956 self,
957 self.pg0,
958 self.pg0.local_ip6,
959 self.pg1.remote_hosts[3].ip6,
960 dscp=d.IP_API_DSCP_AF11,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200961 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DF,
962 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000963 tun.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000964
965 # array of all the tunnels
966 tuns = [tun_dscp, tun_dscp_ecn, tun_ecn, tun]
967
968 # addresses for prefixes routed via each tunnel
969 a4s = ["" for i in range(len(tuns))]
970 a6s = ["" for i in range(len(tuns))]
971
972 # IP headers for inner packets with each combination of DSCp/ECN tested
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200973 p_ip6s = [
974 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=dscp),
975 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=dscp_ecn),
976 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=ecn),
977 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=0xFF),
978 ]
979 p_ip4s = [
980 IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp, flags="DF"),
981 IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp_ecn),
982 IP(src="1.2.3.4", dst="130.67.0.1", tos=ecn),
983 IP(src="1.2.3.4", dst="130.67.0.1", tos=0xFF),
984 ]
Neale Ranns95346962019-11-25 13:04:44 +0000985
986 # Configure each tunnel
987 for i, t in enumerate(tuns):
988 # Set interface up and enable IP on it
989 self.vapi.sw_interface_set_flags(t.sw_if_index, 1)
990 self.vapi.sw_interface_set_unnumbered(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200991 sw_if_index=self.pg0.sw_if_index, unnumbered_sw_if_index=t.sw_if_index
992 )
Neale Ranns95346962019-11-25 13:04:44 +0000993
994 # prefix for route / destination address for packets
995 a4s[i] = "130.67.%d.0" % i
996 a6s[i] = "dead:%d::" % i
997
998 # Add IPv4 and IPv6 routes via tunnel interface
999 ip4_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001000 self,
1001 a4s[i],
1002 24,
1003 [
1004 VppRoutePath(
1005 "0.0.0.0",
1006 t.sw_if_index,
1007 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
1008 )
1009 ],
1010 )
Neale Ranns95346962019-11-25 13:04:44 +00001011 ip4_via_tunnel.add_vpp_config()
1012
1013 ip6_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001014 self,
1015 a6s[i],
1016 64,
1017 [
1018 VppRoutePath(
1019 "::", t.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6
1020 )
1021 ],
1022 )
Neale Ranns95346962019-11-25 13:04:44 +00001023 ip6_via_tunnel.add_vpp_config()
1024
1025 #
1026 # Encapsulation
1027 #
1028
1029 # tun_dscp copies only the dscp
1030 # expected TC values are thus only the DCSP value is present from the
1031 # inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001032 exp_tcs = [dscp, dscp, 0, 0xFC]
1033 p_ip6_encaps = [
1034 IPv6(src=self.pg0.local_ip6, dst=tun_dscp.dst, tc=tc) for tc in exp_tcs
1035 ]
Neale Ranns95346962019-11-25 13:04:44 +00001036
1037 # IPv4 in to IPv4 tunnel
1038 self.verify_ip4ip6_encaps(a4s[0], p_ip4s, p_ip6_encaps)
1039 # IPv6 in to IPv4 tunnel
1040 self.verify_ip6ip6_encaps(a6s[0], p_ip6s, p_ip6_encaps)
1041
1042 # tun_dscp_ecn copies the dscp and the ecn
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001043 exp_tcs = [dscp, dscp_ecn, ecn, 0xFF]
1044 p_ip6_encaps = [
1045 IPv6(src=self.pg0.local_ip6, dst=tun_dscp_ecn.dst, tc=tc) for tc in exp_tcs
1046 ]
Neale Ranns95346962019-11-25 13:04:44 +00001047
1048 self.verify_ip4ip6_encaps(a4s[1], p_ip4s, p_ip6_encaps)
1049 self.verify_ip6ip6_encaps(a6s[1], p_ip6s, p_ip6_encaps)
1050
1051 # tun_ecn copies only the ecn and always sets DF
1052 exp_tcs = [0, ecn, ecn, ecn]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001053 p_ip6_encaps = [
1054 IPv6(src=self.pg0.local_ip6, dst=tun_ecn.dst, tc=tc) for tc in exp_tcs
1055 ]
Neale Ranns95346962019-11-25 13:04:44 +00001056
1057 self.verify_ip4ip6_encaps(a4s[2], p_ip4s, p_ip6_encaps)
1058 self.verify_ip6ip6_encaps(a6s[2], p_ip6s, p_ip6_encaps)
1059
1060 # tun sets a fixed dscp
1061 fixed_dscp = tun.dscp << 2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001062 p_ip6_encaps = [
1063 IPv6(src=self.pg0.local_ip6, dst=tun.dst, tc=fixed_dscp)
1064 for i in range(len(p_ip4s))
1065 ]
Neale Ranns95346962019-11-25 13:04:44 +00001066
1067 self.verify_ip4ip6_encaps(a4s[3], p_ip4s, p_ip6_encaps)
1068 self.verify_ip6ip6_encaps(a6s[3], p_ip6s, p_ip6_encaps)
1069
1070 #
1071 # Decapsulation
1072 #
1073 n_packets_decapped = self.statistics.get_err_counter(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001074 "/err/ipip6-input/packets decapsulated"
1075 )
Neale Ranns95346962019-11-25 13:04:44 +00001076
1077 self.p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1078
1079 # IPv6 tunnel to IPv4
1080 tcs = [0, dscp, dscp_ecn, ecn]
1081
1082 # one overlay packet and all combinations of its encap
1083 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001084 p_ip6_encaps = [IPv6(src=tun.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs]
Neale Ranns95346962019-11-25 13:04:44 +00001085
1086 # for each encap tun will produce the same inner packet because it does
1087 # not copy up fields from the payload
1088 for p_ip6_encap in p_ip6_encaps:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001089 p6 = self.p_ether / p_ip6_encap / p_ip4 / self.p_payload
1090 p4_reply = p_ip4 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +00001091 p4_reply.ttl -= 1
1092 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1093 n_packets_decapped += N_PACKETS
1094 for p in rx:
1095 self.validate(p[1], p4_reply)
1096 self.assert_packet_checksums_valid(p)
1097
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001098 err = self.statistics.get_err_counter("/err/ipip6-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +00001099 self.assertEqual(err, n_packets_decapped)
1100
1101 # tun_ecn copies the ECN bits from the encap to the inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001102 p_ip6_encaps = [
1103 IPv6(src=tun_ecn.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs
1104 ]
Neale Ranns95346962019-11-25 13:04:44 +00001105 p_ip4_replys = [p_ip4.copy() for i in range(len(p_ip6_encaps))]
1106 p_ip4_replys[2].tos = ecn
1107 p_ip4_replys[3].tos = ecn
1108 for i, p_ip6_encap in enumerate(p_ip6_encaps):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001109 p6 = self.p_ether / p_ip6_encap / p_ip4 / self.p_payload
1110 p4_reply = p_ip4_replys[i] / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +00001111 p4_reply.ttl -= 1
1112 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1113 n_packets_decapped += N_PACKETS
1114 for p in rx:
1115 self.validate(p[1], p4_reply)
1116 self.assert_packet_checksums_valid(p)
1117
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001118 err = self.statistics.get_err_counter("/err/ipip6-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +00001119 self.assertEqual(err, n_packets_decapped)
1120
1121 # IPv6 tunnel to IPv6
1122 # for each encap tun will produce the same inner packet because it does
1123 # not copy up fields from the payload
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001124 p_ip6_encaps = [IPv6(src=tun.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs]
Neale Ranns95346962019-11-25 13:04:44 +00001125 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
1126 for p_ip6_encap in p_ip6_encaps:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001127 p6 = self.p_ether / p_ip6_encap / p_ip6 / self.p_payload
1128 p6_reply = p_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +00001129 p6_reply.hlim = 63
1130 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1131 n_packets_decapped += N_PACKETS
1132 for p in rx:
1133 self.validate(p[1], p6_reply)
1134 self.assert_packet_checksums_valid(p)
1135
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001136 err = self.statistics.get_err_counter("/err/ipip6-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +00001137 self.assertEqual(err, n_packets_decapped)
1138
1139 # IPv6 tunnel to IPv6
1140 # tun_ecn copies the ECN bits from the encap to the inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001141 p_ip6_encaps = [
1142 IPv6(src=tun_ecn.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs
1143 ]
Neale Ranns95346962019-11-25 13:04:44 +00001144 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
1145 p_ip6_replys = [p_ip6.copy() for i in range(len(p_ip6_encaps))]
1146 p_ip6_replys[2].tc = ecn
1147 p_ip6_replys[3].tc = ecn
1148 for i, p_ip6_encap in enumerate(p_ip6_encaps):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001149 p6 = self.p_ether / p_ip6_encap / p_ip6 / self.p_payload
1150 p6_reply = p_ip6_replys[i] / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +00001151 p6_reply.hlim = 63
1152 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1153 n_packets_decapped += N_PACKETS
1154 for p in rx:
1155 self.validate(p[1], p6_reply)
1156 self.assert_packet_checksums_valid(p)
1157
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001158 err = self.statistics.get_err_counter("/err/ipip6-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +00001159 self.assertEqual(err, n_packets_decapped)
1160
Ole Troan282093f2018-09-19 12:38:51 +02001161 def test_frag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001162 """ip{v4,v6} over ip6 test frag"""
Ole Troan282093f2018-09-19 12:38:51 +02001163
1164 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001165 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh="UDP")
Ole Troan282093f2018-09-19 12:38:51 +02001166 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
1167 p_payload = UDP(sport=1234, dport=1234)
1168
1169 #
1170 # Fragmentation / Reassembly and Re-fragmentation
1171 #
1172 rv = self.vapi.ip_reassembly_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001173 sw_if_index=self.pg1.sw_if_index, enable_ip6=1
1174 )
Ole Troan282093f2018-09-19 12:38:51 +02001175
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001176 self.vapi.ip_reassembly_set(
1177 timeout_ms=1000,
1178 max_reassemblies=1000,
1179 max_reassembly_length=1000,
1180 expire_walk_interval_ms=10000,
1181 is_ip6=1,
1182 )
Klement Sekera3a343d42019-05-16 14:35:46 +02001183
Ole Troan282093f2018-09-19 12:38:51 +02001184 # Send lots of fragments, verify reassembled packet
Ole Troan233e4682019-05-16 15:01:34 +02001185 before_cnt = self.statistics.get_err_counter(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001186 "/err/ipip6-input/packets decapsulated"
1187 )
Ole Troan282093f2018-09-19 12:38:51 +02001188 frags, p6_reply = self.generate_ip6_frags(3131, 1400)
1189 f = []
1190 for i in range(0, 1000):
1191 f.extend(frags)
1192 self.pg1.add_stream(f)
1193 self.pg_enable_capture()
1194 self.pg_start()
1195 rx = self.pg0.get_capture(1000)
1196
1197 for p in rx:
1198 self.validate(p[1], p6_reply)
1199
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001200 cnt = self.statistics.get_err_counter("/err/ipip6-input/packets decapsulated")
Ole Troan282093f2018-09-19 12:38:51 +02001201 self.assertEqual(cnt, before_cnt + 1000)
1202
1203 f = []
1204 r = []
1205 # TODO: Check out why reassembly of atomic fragments don't work
1206 for i in range(10, 90):
1207 frags, p6_reply = self.generate_ip6_frags(i * 100, 1000)
1208 f.extend(frags)
1209 r.extend(p6_reply)
1210 self.pg_enable_capture()
1211 self.pg1.add_stream(f)
1212 self.pg_start()
1213 rx = self.pg0.get_capture(80)
1214 i = 0
1215 for p in rx:
1216 self.validate(p[1], r[i])
1217 i += 1
1218
1219 # Simple fragmentation
1220 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1221 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
1222
1223 # IPv6 in to IPv6 tunnel
1224 p_payload = UDP(sport=1234, dport=1234) / self.payload(1300)
1225
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001226 p6 = p_ether / p_ip6 / p_payload
1227 p6_reply = (
1228 IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=63)
1229 / p_ip6
1230 / p_payload
1231 )
Ole Troan282093f2018-09-19 12:38:51 +02001232 p6_reply[1].hlim -= 1
1233 self.pg_enable_capture()
1234 self.pg0.add_stream(p6)
1235 self.pg_start()
1236 rx = self.pg1.get_capture(2)
1237
1238 # Scapy defragment doesn't deal well with multiple layers
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001239 # of same type / Ethernet header first
Ole Troan282093f2018-09-19 12:38:51 +02001240 f = [p[1] for p in rx]
1241 reass_pkt = defragment6(f)
1242 self.validate(reass_pkt, p6_reply)
1243
1244 # Now try with re-fragmentation
1245 #
1246 # Send large fragments to tunnel head-end, for the tunnel head end
1247 # to reassemble and then refragment out the tunnel again.
1248 # Hair-pinning
1249 #
1250 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
1251 frags, p6_reply = self.generate_ip6_hairpin_frags(8000, 1200)
1252 self.pg_enable_capture()
1253 self.pg1.add_stream(frags)
1254 self.pg_start()
1255 rx = self.pg1.get_capture(7)
1256 f = [p[1] for p in rx]
1257 reass_pkt = defragment6(f)
1258 p6_reply.id = 256
1259 self.validate(reass_pkt, p6_reply)
1260
Neale Rannsec5371e2022-03-04 11:45:41 +00001261 def test_ip6_mpls_frag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001262 """Test fragmenting IPv6 over MPLS"""
Neale Rannsec5371e2022-03-04 11:45:41 +00001263
1264 # IPv6 packets must be locally generated to be fragmented
1265 # the use of tunnel encaps
1266 tun_dst = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001267 self,
1268 "1000::1",
1269 128,
1270 [
1271 VppRoutePath(
1272 self.pg1.remote_ip6, self.pg1.sw_if_index, labels=[VppMplsLabel(32)]
1273 )
1274 ],
1275 ).add_vpp_config()
Neale Rannsec5371e2022-03-04 11:45:41 +00001276
1277 tun = VppIpIpTunInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001278 self, self.pg0, self.pg0.local_ip6, "1000::1"
1279 ).add_vpp_config()
Neale Rannsec5371e2022-03-04 11:45:41 +00001280
1281 tun.admin_up()
1282 tun.config_ip6()
1283 tun.config_ip4()
1284
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001285 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2000, 0, 0, 0])
Neale Rannsec5371e2022-03-04 11:45:41 +00001286
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001287 p_6k = (
1288 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1289 / IPv6(src=self.pg0.remote_ip6, dst=tun.remote_ip6)
1290 / UDP(sport=1234, dport=5678)
1291 / Raw(b"0xa" * 2000)
1292 )
1293 p_2k = (
1294 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1295 / IPv6(src=self.pg0.remote_ip6, dst=tun.remote_ip6)
1296 / UDP(sport=1234, dport=5678)
1297 / Raw(b"0xa" * 1000)
1298 )
1299 p_1k = (
1300 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1301 / IPv6(src=self.pg0.remote_ip6, dst=tun.remote_ip6)
1302 / UDP(sport=1234, dport=5678)
1303 / Raw(b"0xa" * 600)
1304 )
Neale Rannsec5371e2022-03-04 11:45:41 +00001305
1306 # this is now the interface MTU frags
1307 rxs = self.send_and_expect(self.pg0, [p_6k], self.pg1, n_rx=4)
1308 self.assertEqual(rxs[0][UDP].dport, 5678)
1309 for rx in rxs:
1310 self.assertEqual(rx[MPLS].label, 32)
1311 self.assertEqual(rx[IPv6].dst, "1000::1")
1312 self.assertEqual(rx[IPv6].dst, "1000::1")
1313 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
1314 self.send_and_expect(self.pg0, [p_1k], self.pg1)
1315
Ole Troan298c6952018-03-08 12:30:43 +01001316 def test_ipip_create(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001317 """ipip create / delete interface test"""
1318 rv = ipip_add_tunnel(self, "1.2.3.4", "2.3.4.5")
Ole Troan298c6952018-03-08 12:30:43 +01001319 sw_if_index = rv.sw_if_index
Ole Troan46c1c112018-03-14 20:39:40 +01001320 self.vapi.ipip_del_tunnel(sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +01001321
Neale Ranns61502112018-08-22 00:21:14 -07001322 def test_ipip_vrf_create(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001323 """ipip create / delete interface VRF test"""
Neale Ranns61502112018-08-22 00:21:14 -07001324
1325 t = VppIpTable(self, 20)
1326 t.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001327 rv = ipip_add_tunnel(self, "1.2.3.4", "2.3.4.5", table_id=20)
Neale Ranns61502112018-08-22 00:21:14 -07001328 sw_if_index = rv.sw_if_index
1329 self.vapi.ipip_del_tunnel(sw_if_index)
1330
Ole Troan4146c652018-08-08 22:23:19 +02001331 def payload(self, len):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001332 return "x" * len
Ole Troan4146c652018-08-08 22:23:19 +02001333
Ole Troan298c6952018-03-08 12:30:43 +01001334
Tianyu Li6d95f8c2022-02-25 05:51:10 +00001335class TestIPIPMPLS(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001336 """MPLS Test Case"""
Neale Rannse294de62020-12-21 09:52:24 +00001337
1338 @classmethod
1339 def setUpClass(cls):
Tianyu Li6d95f8c2022-02-25 05:51:10 +00001340 super(TestIPIPMPLS, cls).setUpClass()
Neale Rannse294de62020-12-21 09:52:24 +00001341 cls.create_pg_interfaces(range(2))
1342 cls.interfaces = list(cls.pg_interfaces)
1343
1344 @classmethod
1345 def tearDownClass(cls):
Tianyu Li6d95f8c2022-02-25 05:51:10 +00001346 super(TestIPIPMPLS, cls).tearDownClass()
Neale Rannse294de62020-12-21 09:52:24 +00001347
1348 def setUp(self):
Tianyu Li6d95f8c2022-02-25 05:51:10 +00001349 super(TestIPIPMPLS, self).setUp()
Neale Rannse294de62020-12-21 09:52:24 +00001350 for i in self.interfaces:
1351 i.admin_up()
1352 i.config_ip4()
1353 i.config_ip6()
1354 i.disable_ipv6_ra()
1355 i.resolve_arp()
1356 i.resolve_ndp()
1357
1358 def tearDown(self):
Tianyu Li6d95f8c2022-02-25 05:51:10 +00001359 super(TestIPIPMPLS, self).tearDown()
Neale Rannse294de62020-12-21 09:52:24 +00001360
1361 for i in self.pg_interfaces:
1362 i.unconfig_ip4()
1363 i.unconfig_ip6()
1364 i.admin_down()
1365
1366 def test_mpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001367 """MPLS over ip{6,4} test"""
Neale Rannse294de62020-12-21 09:52:24 +00001368
1369 tbl = VppMplsTable(self, 0)
1370 tbl.add_vpp_config()
1371
1372 self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001373 self.p_payload = UDP(sport=1234, dport=1234) / Raw(b"X" * 100)
Neale Rannse294de62020-12-21 09:52:24 +00001374 f = FibPathProto
1375
1376 # IPv4 transport
1377 tun4 = VppIpIpTunInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001378 self, self.pg1, self.pg1.local_ip4, self.pg1.remote_ip4
1379 ).add_vpp_config()
Neale Rannse294de62020-12-21 09:52:24 +00001380 tun4.admin_up()
1381 tun4.config_ip4()
1382 tun4.enable_mpls()
1383
1384 # IPv6 transport
1385 tun6 = VppIpIpTunInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001386 self, self.pg1, self.pg1.local_ip6, self.pg1.remote_ip6
1387 ).add_vpp_config()
Neale Rannse294de62020-12-21 09:52:24 +00001388 tun6.admin_up()
1389 tun6.config_ip6()
1390 tun6.enable_mpls()
1391
1392 # ip routes into the tunnels with output labels
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001393 r4 = VppIpRoute(
1394 self,
1395 "1.1.1.1",
1396 32,
1397 [
1398 VppRoutePath(
1399 tun4.remote_ip4, tun4.sw_if_index, labels=[VppMplsLabel(44)]
1400 )
1401 ],
1402 ).add_vpp_config()
1403 r6 = VppIpRoute(
1404 self,
1405 "1::1",
1406 128,
1407 [
1408 VppRoutePath(
1409 tun6.remote_ip6, tun6.sw_if_index, labels=[VppMplsLabel(66)]
1410 )
1411 ],
1412 ).add_vpp_config()
Neale Rannse294de62020-12-21 09:52:24 +00001413
1414 # deag MPLS routes from the tunnel
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001415 r4 = VppMplsRoute(
1416 self, 44, 1, [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index)]
1417 ).add_vpp_config()
1418 r6 = VppMplsRoute(
1419 self,
1420 66,
1421 1,
1422 [VppRoutePath(self.pg0.remote_ip6, self.pg0.sw_if_index)],
1423 eos_proto=f.FIB_PATH_NH_PROTO_IP6,
1424 ).add_vpp_config()
Neale Rannse294de62020-12-21 09:52:24 +00001425
1426 #
1427 # Tunnel Encap
1428 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001429 p4 = self.p_ether / IP(src="2.2.2.2", dst="1.1.1.1") / self.p_payload
Neale Rannse294de62020-12-21 09:52:24 +00001430
1431 rxs = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1)
1432
1433 for rx in rxs:
1434 self.assertEqual(rx[IP].src, self.pg1.local_ip4)
1435 self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
1436 self.assertEqual(rx[MPLS].label, 44)
1437 inner = rx[MPLS].payload
1438 self.assertEqual(inner.src, "2.2.2.2")
1439 self.assertEqual(inner.dst, "1.1.1.1")
1440
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001441 p6 = self.p_ether / IPv6(src="2::2", dst="1::1") / self.p_payload
Neale Rannse294de62020-12-21 09:52:24 +00001442
1443 rxs = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1)
1444
1445 for rx in rxs:
1446 self.assertEqual(rx[IPv6].src, self.pg1.local_ip6)
1447 self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6)
1448 self.assertEqual(rx[MPLS].label, 66)
1449 inner = rx[MPLS].payload
1450 self.assertEqual(inner.src, "2::2")
1451 self.assertEqual(inner.dst, "1::1")
1452
1453 #
1454 # Tunnel Decap
1455 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001456 p4 = (
Steven Luonge4238aa2024-04-19 09:49:20 -07001457 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001458 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1459 / MPLS(label=44, ttl=4)
1460 / IP(src="1.1.1.1", dst="2.2.2.2")
1461 / self.p_payload
1462 )
Neale Rannse294de62020-12-21 09:52:24 +00001463
1464 rxs = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
1465
1466 for rx in rxs:
1467 self.assertEqual(rx[IP].src, "1.1.1.1")
1468 self.assertEqual(rx[IP].dst, "2.2.2.2")
1469
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001470 p6 = (
Steven Luonge4238aa2024-04-19 09:49:20 -07001471 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001472 / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6)
1473 / MPLS(label=66, ttl=4)
1474 / IPv6(src="1::1", dst="2::2")
1475 / self.p_payload
1476 )
Neale Rannse294de62020-12-21 09:52:24 +00001477
1478 rxs = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1479
1480 for rx in rxs:
1481 self.assertEqual(rx[IPv6].src, "1::1")
1482 self.assertEqual(rx[IPv6].dst, "2::2")
1483
1484 tun4.disable_mpls()
1485 tun6.disable_mpls()
1486
1487
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001488if __name__ == "__main__":
Ole Troan298c6952018-03-08 12:30:43 +01001489 unittest.main(testRunner=VppTestRunner)