blob: cbaedd51273747cce7099ac56c10bbf6e399ac2a [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
Ole Troan46c1c112018-03-14 20:39:40 +01008from framework import VppTestCase, VppTestRunner
Neale Rannsc0a93142018-09-05 15:42:26 -07009from vpp_ip import DpoProto
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 Troan46c1c112018-03-14 20:39:40 +010022from socket import AF_INET, AF_INET6, inet_pton
Ole Troan7f991832018-12-06 17:35:12 +010023from util import reassemble4
24
Ole Troan298c6952018-03-08 12:30:43 +010025""" Testipip is a subclass of VPPTestCase classes.
26
27IPIP tests.
28
29"""
30
31
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020032def ipip_add_tunnel(test, src, dst, table_id=0, dscp=0x0, flags=0):
33 """Add a IPIP tunnel"""
Neale Rannscbd08242019-05-26 11:34:27 -070034 return test.vapi.ipip_add_tunnel(
35 tunnel={
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020036 "src": src,
37 "dst": dst,
38 "table_id": table_id,
39 "instance": 0xFFFFFFFF,
40 "dscp": dscp,
41 "flags": flags,
Neale Rannscbd08242019-05-26 11:34:27 -070042 }
43 )
44
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020045
Neale Ranns95346962019-11-25 13:04:44 +000046# the number of packets to send when injecting traffic.
47# a multiple of 8 minus one, so we test all by 8/4/2/1 loops
48N_PACKETS = 64 - 1
49
Neale Rannscbd08242019-05-26 11:34:27 -070050
Ole Troan298c6952018-03-08 12:30:43 +010051class TestIPIP(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020052 """IPIP Test Case"""
Ole Troan298c6952018-03-08 12:30:43 +010053
54 @classmethod
55 def setUpClass(cls):
56 super(TestIPIP, cls).setUpClass()
Neale Ranns256b67b2020-09-02 14:46:53 +000057 cls.create_pg_interfaces(range(3))
Ole Troan46c1c112018-03-14 20:39:40 +010058 cls.interfaces = list(cls.pg_interfaces)
Ole Troan298c6952018-03-08 12:30:43 +010059
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070060 @classmethod
61 def tearDownClass(cls):
62 super(TestIPIP, cls).tearDownClass()
63
Paul Vinciguerra741865b2018-11-27 06:01:22 -080064 def setUp(self):
65 super(TestIPIP, self).setUp()
Neale Ranns256b67b2020-09-02 14:46:53 +000066 self.table = VppIpTable(self, 1, register=False)
67 self.table.add_vpp_config()
68
Paul Vinciguerra741865b2018-11-27 06:01:22 -080069 for i in self.interfaces:
Ole Troan46c1c112018-03-14 20:39:40 +010070 i.admin_up()
Neale Ranns256b67b2020-09-02 14:46:53 +000071
72 self.pg2.set_table_ip4(self.table.table_id)
73 for i in self.interfaces:
Ole Troan46c1c112018-03-14 20:39:40 +010074 i.config_ip4()
75 i.config_ip6()
76 i.disable_ipv6_ra()
77 i.resolve_arp()
78 i.resolve_ndp()
Ole Troan298c6952018-03-08 12:30:43 +010079
80 def tearDown(self):
81 super(TestIPIP, self).tearDown()
82 if not self.vpp_dead:
Ole Troan46c1c112018-03-14 20:39:40 +010083 for i in self.pg_interfaces:
84 i.unconfig_ip4()
85 i.unconfig_ip6()
Neale Ranns256b67b2020-09-02 14:46:53 +000086 i.set_table_ip4(0)
Ole Troan46c1c112018-03-14 20:39:40 +010087 i.admin_down()
Ole Troan298c6952018-03-08 12:30:43 +010088
Neale Ranns256b67b2020-09-02 14:46:53 +000089 self.table.remove_vpp_config()
90
Ole Troan298c6952018-03-08 12:30:43 +010091 def validate(self, rx, expected):
Ole Troan7f991832018-12-06 17:35:12 +010092 self.assertEqual(rx, expected.__class__(expected))
Ole Troan298c6952018-03-08 12:30:43 +010093
Ole Troan282093f2018-09-19 12:38:51 +020094 def generate_ip4_frags(self, payload_length, fragment_size):
Ole Troan7eb9d962018-08-10 14:39:48 +020095 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
96 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
97 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020098 outer_ip4 = (
99 p_ether
100 / IP(src=self.pg1.remote_ip4, id=RandShort(), dst=self.pg0.local_ip4)
101 / p_ip4
102 / p_payload
103 )
Ole Troan7eb9d962018-08-10 14:39:48 +0200104 frags = fragment(outer_ip4, fragment_size)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200105 p4_reply = p_ip4 / p_payload
Ole Troan7eb9d962018-08-10 14:39:48 +0200106 p4_reply.ttl -= 1
107 return frags, p4_reply
108
Neale Ranns95346962019-11-25 13:04:44 +0000109 def verify_ip4ip4_encaps(self, a, p_ip4s, p_ip4_encaps):
110 for i, p_ip4 in enumerate(p_ip4s):
111 p_ip4.dst = a
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200112 p4 = self.p_ether / p_ip4 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000113 p_ip4_inner = p_ip4
114 p_ip4_inner.ttl -= 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200115 p4_reply = p_ip4_encaps[i] / p_ip4_inner / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000116 p4_reply.ttl -= 1
117 p4_reply.id = 0
118 rx = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1)
119 for p in rx:
120 self.validate(p[1], p4_reply)
121 self.assert_packet_checksums_valid(p)
122
123 def verify_ip6ip4_encaps(self, a, p_ip6s, p_ip4_encaps):
124 for i, p_ip6 in enumerate(p_ip6s):
125 p_ip6.dst = a
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200126 p6 = self.p_ether / p_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000127 p_inner_ip6 = p_ip6
128 p_inner_ip6.hlim -= 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200129 p6_reply = p_ip4_encaps[i] / p_inner_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000130 p6_reply.ttl -= 1
131 rx = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1)
132 for p in rx:
133 self.validate(p[1], p6_reply)
134 self.assert_packet_checksums_valid(p)
135
Ole Troan298c6952018-03-08 12:30:43 +0100136 def test_ipip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200137 """ip{v4,v6} over ip4 test"""
Ole Troan298c6952018-03-08 12:30:43 +0100138
Neale Ranns95346962019-11-25 13:04:44 +0000139 self.pg1.generate_remote_hosts(5)
140 self.pg1.configure_ipv4_neighbors()
Neale Ranns59ff9182019-12-29 23:55:18 +0000141 e = VppEnum.vl_api_tunnel_encap_decap_flags_t
Neale Ranns95346962019-11-25 13:04:44 +0000142 d = VppEnum.vl_api_ip_dscp_t
143 self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200144 self.p_payload = UDP(sport=1234, dport=1234) / Raw(b"X" * 100)
Ole Troan298c6952018-03-08 12:30:43 +0100145
Neale Ranns95346962019-11-25 13:04:44 +0000146 # create a TOS byte by shifting a DSCP code point 2 bits. those 2 bits
147 # are for the ECN.
148 dscp = d.IP_API_DSCP_AF31 << 2
149 ecn = 3
150 dscp_ecn = d.IP_API_DSCP_AF31 << 2 | ecn
Ole Troan298c6952018-03-08 12:30:43 +0100151
Neale Ranns95346962019-11-25 13:04:44 +0000152 # IPv4 transport that copies the DCSP from the payload
153 tun_dscp = VppIpIpTunInterface(
154 self,
155 self.pg0,
156 self.pg0.local_ip4,
157 self.pg1.remote_hosts[0].ip4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200158 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP,
159 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000160 tun_dscp.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000161 # IPv4 transport that copies the DCSP and ECN from the payload
162 tun_dscp_ecn = VppIpIpTunInterface(
163 self,
164 self.pg0,
165 self.pg0.local_ip4,
166 self.pg1.remote_hosts[1].ip4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200167 flags=(
168 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP
169 | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
170 ),
171 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000172 tun_dscp_ecn.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000173 # IPv4 transport that copies the ECN from the payload and sets the
174 # DF bit on encap. copies the ECN on decap
175 tun_ecn = VppIpIpTunInterface(
176 self,
177 self.pg0,
178 self.pg0.local_ip4,
179 self.pg1.remote_hosts[2].ip4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200180 flags=(
181 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
182 | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_DF
183 | e.TUNNEL_API_ENCAP_DECAP_FLAG_DECAP_COPY_ECN
184 ),
185 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000186 tun_ecn.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000187 # IPv4 transport that sets a fixed DSCP in the encap and copies
188 # the DF bit
189 tun = VppIpIpTunInterface(
190 self,
191 self.pg0,
192 self.pg0.local_ip4,
193 self.pg1.remote_hosts[3].ip4,
194 dscp=d.IP_API_DSCP_AF11,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200195 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DF,
196 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000197 tun.add_vpp_config()
Ole Troan298c6952018-03-08 12:30:43 +0100198
Neale Ranns95346962019-11-25 13:04:44 +0000199 # array of all the tunnels
200 tuns = [tun_dscp, tun_dscp_ecn, tun_ecn, tun]
Ole Troan298c6952018-03-08 12:30:43 +0100201
Neale Ranns95346962019-11-25 13:04:44 +0000202 # addresses for prefixes routed via each tunnel
203 a4s = ["" for i in range(len(tuns))]
204 a6s = ["" for i in range(len(tuns))]
205
206 # IP headers with each combination of DSCp/ECN tested
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200207 p_ip6s = [
208 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=dscp),
209 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=dscp_ecn),
210 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=ecn),
211 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=0xFF),
212 ]
213 p_ip4s = [
214 IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp, flags="DF"),
215 IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp_ecn),
216 IP(src="1.2.3.4", dst="130.67.0.1", tos=ecn),
217 IP(src="1.2.3.4", dst="130.67.0.1", tos=0xFF),
218 ]
Neale Ranns95346962019-11-25 13:04:44 +0000219
220 # Configure each tunnel
221 for i, t in enumerate(tuns):
222 # Set interface up and enable IP on it
223 self.vapi.sw_interface_set_flags(t.sw_if_index, 1)
224 self.vapi.sw_interface_set_unnumbered(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200225 sw_if_index=self.pg0.sw_if_index, unnumbered_sw_if_index=t.sw_if_index
226 )
Neale Ranns95346962019-11-25 13:04:44 +0000227
228 # prefix for route / destination address for packets
229 a4s[i] = "130.67.%d.0" % i
230 a6s[i] = "dead:%d::" % i
231
232 # Add IPv4 and IPv6 routes via tunnel interface
233 ip4_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200234 self,
235 a4s[i],
236 24,
237 [
238 VppRoutePath(
239 "0.0.0.0",
240 t.sw_if_index,
241 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
242 )
243 ],
244 )
Neale Ranns95346962019-11-25 13:04:44 +0000245 ip4_via_tunnel.add_vpp_config()
246
247 ip6_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200248 self,
249 a6s[i],
250 64,
251 [
252 VppRoutePath(
253 "::", t.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6
254 )
255 ],
256 )
Neale Ranns95346962019-11-25 13:04:44 +0000257 ip6_via_tunnel.add_vpp_config()
258
259 #
260 # Encapsulation
261 #
262
263 # tun_dscp copies only the dscp
264 # expected TC values are thus only the DCSP value is present from the
265 # inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200266 exp_tcs = [dscp, dscp, 0, 0xFC]
267 p_ip44_encaps = [
268 IP(src=self.pg0.local_ip4, dst=tun_dscp.dst, tos=tc) for tc in exp_tcs
269 ]
270 p_ip64_encaps = [
271 IP(src=self.pg0.local_ip4, dst=tun_dscp.dst, proto="ipv6", id=0, tos=tc)
272 for tc in exp_tcs
273 ]
Ole Troan298c6952018-03-08 12:30:43 +0100274
275 # IPv4 in to IPv4 tunnel
Neale Ranns95346962019-11-25 13:04:44 +0000276 self.verify_ip4ip4_encaps(a4s[0], p_ip4s, p_ip44_encaps)
277 # IPv6 in to IPv4 tunnel
278 self.verify_ip6ip4_encaps(a6s[0], p_ip6s, p_ip64_encaps)
Ole Troan298c6952018-03-08 12:30:43 +0100279
Neale Ranns95346962019-11-25 13:04:44 +0000280 # tun_dscp_ecn copies the dscp and the ecn
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200281 exp_tcs = [dscp, dscp_ecn, ecn, 0xFF]
282 p_ip44_encaps = [
283 IP(src=self.pg0.local_ip4, dst=tun_dscp_ecn.dst, tos=tc) for tc in exp_tcs
284 ]
285 p_ip64_encaps = [
286 IP(src=self.pg0.local_ip4, dst=tun_dscp_ecn.dst, proto="ipv6", id=0, tos=tc)
287 for tc in exp_tcs
288 ]
Neale Ranns95346962019-11-25 13:04:44 +0000289
290 self.verify_ip4ip4_encaps(a4s[1], p_ip4s, p_ip44_encaps)
291 self.verify_ip6ip4_encaps(a6s[1], p_ip6s, p_ip64_encaps)
292
293 # tun_ecn copies only the ecn and always sets DF
294 exp_tcs = [0, ecn, ecn, ecn]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200295 p_ip44_encaps = [
296 IP(src=self.pg0.local_ip4, dst=tun_ecn.dst, flags="DF", tos=tc)
297 for tc in exp_tcs
298 ]
299 p_ip64_encaps = [
300 IP(
301 src=self.pg0.local_ip4,
302 dst=tun_ecn.dst,
303 flags="DF",
304 proto="ipv6",
305 id=0,
306 tos=tc,
307 )
308 for tc in exp_tcs
309 ]
Neale Ranns95346962019-11-25 13:04:44 +0000310
311 self.verify_ip4ip4_encaps(a4s[2], p_ip4s, p_ip44_encaps)
312 self.verify_ip6ip4_encaps(a6s[2], p_ip6s, p_ip64_encaps)
313
314 # tun sets a fixed dscp and copies DF
315 fixed_dscp = tun.dscp << 2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200316 flags = ["DF", 0, 0, 0]
317 p_ip44_encaps = [
318 IP(src=self.pg0.local_ip4, dst=tun.dst, flags=f, tos=fixed_dscp)
319 for f in flags
320 ]
321 p_ip64_encaps = [
322 IP(src=self.pg0.local_ip4, dst=tun.dst, proto="ipv6", id=0, tos=fixed_dscp)
323 for i in range(len(p_ip4s))
324 ]
Neale Ranns95346962019-11-25 13:04:44 +0000325
326 self.verify_ip4ip4_encaps(a4s[3], p_ip4s, p_ip44_encaps)
327 self.verify_ip6ip4_encaps(a6s[3], p_ip6s, p_ip64_encaps)
328
329 #
Ole Troan298c6952018-03-08 12:30:43 +0100330 # Decapsulation
Neale Ranns95346962019-11-25 13:04:44 +0000331 #
332 n_packets_decapped = 0
333 self.p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
Ole Troan298c6952018-03-08 12:30:43 +0100334
335 # IPv4 tunnel to IPv4
Neale Ranns95346962019-11-25 13:04:44 +0000336 tcs = [0, dscp, dscp_ecn, ecn]
337
338 # one overlay packet and all combinations of its encap
Ole Troan298c6952018-03-08 12:30:43 +0100339 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200340 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 +0000341
342 # for each encap tun will produce the same inner packet because it does
343 # not copy up fields from the payload
344 for p_ip4_encap in p_ip4_encaps:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200345 p4 = self.p_ether / p_ip4_encap / p_ip4 / self.p_payload
346 p4_reply = p_ip4 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000347 p4_reply.ttl -= 1
348 rx = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
349 n_packets_decapped += N_PACKETS
350 for p in rx:
351 self.validate(p[1], p4_reply)
352 self.assert_packet_checksums_valid(p)
Ole Troan298c6952018-03-08 12:30:43 +0100353
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200354 err = self.statistics.get_err_counter("/err/ipip4-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +0000355 self.assertEqual(err, n_packets_decapped)
356
357 # tun_ecn copies the ECN bits from the encap to the inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200358 p_ip4_encaps = [
359 IP(src=tun_ecn.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs
360 ]
Neale Ranns95346962019-11-25 13:04:44 +0000361 p_ip4_replys = [p_ip4.copy() for i in range(len(p_ip4_encaps))]
362 p_ip4_replys[2].tos = ecn
363 p_ip4_replys[3].tos = ecn
364 for i, p_ip4_encap in enumerate(p_ip4_encaps):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200365 p4 = self.p_ether / p_ip4_encap / p_ip4 / self.p_payload
366 p4_reply = p_ip4_replys[i] / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000367 p4_reply.ttl -= 1
368 rx = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
369 n_packets_decapped += N_PACKETS
370 for p in rx:
371 self.validate(p[1], p4_reply)
372 self.assert_packet_checksums_valid(p)
373
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200374 err = self.statistics.get_err_counter("/err/ipip4-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +0000375 self.assertEqual(err, n_packets_decapped)
Ole Troan73202102018-08-31 00:29:48 +0200376
Ole Troan298c6952018-03-08 12:30:43 +0100377 # IPv4 tunnel to IPv6
Neale Ranns95346962019-11-25 13:04:44 +0000378 # for each encap tun will produce the same inner packet because it does
379 # not copy up fields from the payload
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200380 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 +0100381 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
Neale Ranns95346962019-11-25 13:04:44 +0000382 for p_ip4_encap in p_ip4_encaps:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200383 p6 = self.p_ether / p_ip4_encap / p_ip6 / self.p_payload
384 p6_reply = p_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000385 p6_reply.hlim = 63
386 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
387 n_packets_decapped += N_PACKETS
388 for p in rx:
389 self.validate(p[1], p6_reply)
390 self.assert_packet_checksums_valid(p)
Ole Troan298c6952018-03-08 12:30:43 +0100391
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200392 err = self.statistics.get_err_counter("/err/ipip4-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +0000393 self.assertEqual(err, n_packets_decapped)
394
395 # IPv4 tunnel to IPv6
396 # tun_ecn copies the ECN bits from the encap to the inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200397 p_ip4_encaps = [
398 IP(src=tun_ecn.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs
399 ]
Neale Ranns95346962019-11-25 13:04:44 +0000400 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
401 p_ip6_replys = [p_ip6.copy() for i in range(len(p_ip4_encaps))]
402 p_ip6_replys[2].tc = ecn
403 p_ip6_replys[3].tc = ecn
404 for i, p_ip4_encap in enumerate(p_ip4_encaps):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200405 p6 = self.p_ether / p_ip4_encap / p_ip6 / self.p_payload
406 p6_reply = p_ip6_replys[i] / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000407 p6_reply.hlim = 63
408 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
409 n_packets_decapped += N_PACKETS
410 for p in rx:
411 self.validate(p[1], p6_reply)
412 self.assert_packet_checksums_valid(p)
413
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200414 err = self.statistics.get_err_counter("/err/ipip4-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +0000415 self.assertEqual(err, n_packets_decapped)
Ole Troan73202102018-08-31 00:29:48 +0200416
Ole Troan7eb9d962018-08-10 14:39:48 +0200417 #
Ole Troan4146c652018-08-08 22:23:19 +0200418 # Fragmentation / Reassembly and Re-fragmentation
Ole Troan7eb9d962018-08-10 14:39:48 +0200419 #
Ole Troan4146c652018-08-08 22:23:19 +0200420 rv = self.vapi.ip_reassembly_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200421 sw_if_index=self.pg1.sw_if_index, enable_ip4=1
422 )
Ole Troan4146c652018-08-08 22:23:19 +0200423
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200424 self.vapi.ip_reassembly_set(
425 timeout_ms=1000,
426 max_reassemblies=1000,
427 max_reassembly_length=1000,
428 expire_walk_interval_ms=10000,
429 is_ip6=0,
430 )
Klement Sekera3a343d42019-05-16 14:35:46 +0200431
Ole Troan7eb9d962018-08-10 14:39:48 +0200432 # Send lots of fragments, verify reassembled packet
Ole Troan282093f2018-09-19 12:38:51 +0200433 frags, p4_reply = self.generate_ip4_frags(3131, 1400)
Ole Troan7eb9d962018-08-10 14:39:48 +0200434 f = []
435 for i in range(0, 1000):
436 f.extend(frags)
437 self.pg1.add_stream(f)
Ole Troan4146c652018-08-08 22:23:19 +0200438 self.pg_enable_capture()
Ole Troan4146c652018-08-08 22:23:19 +0200439 self.pg_start()
Ole Troan7eb9d962018-08-10 14:39:48 +0200440 rx = self.pg0.get_capture(1000)
Neale Ranns95346962019-11-25 13:04:44 +0000441 n_packets_decapped += 1000
Ole Troan7eb9d962018-08-10 14:39:48 +0200442
Ole Troan4146c652018-08-08 22:23:19 +0200443 for p in rx:
444 self.validate(p[1], p4_reply)
445
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200446 err = self.statistics.get_err_counter("/err/ipip4-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +0000447 self.assertEqual(err, n_packets_decapped)
Ole Troan73202102018-08-31 00:29:48 +0200448
Ole Troan7eb9d962018-08-10 14:39:48 +0200449 f = []
450 r = []
451 for i in range(1, 90):
Ole Troan282093f2018-09-19 12:38:51 +0200452 frags, p4_reply = self.generate_ip4_frags(i * 100, 1000)
Ole Troan7eb9d962018-08-10 14:39:48 +0200453 f.extend(frags)
454 r.extend(p4_reply)
455 self.pg_enable_capture()
456 self.pg1.add_stream(f)
457 self.pg_start()
458 rx = self.pg0.get_capture(89)
459 i = 0
460 for p in rx:
461 self.validate(p[1], r[i])
462 i += 1
463
Ole Troan4146c652018-08-08 22:23:19 +0200464 # Now try with re-fragmentation
Ole Troan7eb9d962018-08-10 14:39:48 +0200465 #
466 # Send fragments to tunnel head-end, for the tunnel head end
467 # to reassemble and then refragment
468 #
Ole Troan4146c652018-08-08 22:23:19 +0200469 self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [576, 0, 0, 0])
Ole Troan282093f2018-09-19 12:38:51 +0200470 frags, p4_reply = self.generate_ip4_frags(3123, 1200)
Ole Troan4146c652018-08-08 22:23:19 +0200471 self.pg_enable_capture()
472 self.pg1.add_stream(frags)
473 self.pg_start()
474 rx = self.pg0.get_capture(6)
Ole Troan7f991832018-12-06 17:35:12 +0100475 reass_pkt = reassemble4(rx)
Ole Troan4146c652018-08-08 22:23:19 +0200476 p4_reply.id = 256
477 self.validate(reass_pkt, p4_reply)
478
Ole Troan7eb9d962018-08-10 14:39:48 +0200479 self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1600, 0, 0, 0])
Ole Troan282093f2018-09-19 12:38:51 +0200480 frags, p4_reply = self.generate_ip4_frags(3123, 1200)
Ole Troan7eb9d962018-08-10 14:39:48 +0200481 self.pg_enable_capture()
482 self.pg1.add_stream(frags)
483 self.pg_start()
484 rx = self.pg0.get_capture(2)
Ole Troan7f991832018-12-06 17:35:12 +0100485 reass_pkt = reassemble4(rx)
Ole Troan7eb9d962018-08-10 14:39:48 +0200486 p4_reply.id = 512
487 self.validate(reass_pkt, p4_reply)
488
Neale Ranns0b6a8572019-10-30 17:34:14 +0000489 # send large packets through the tunnel, expect them to be fragmented
Neale Ranns95346962019-11-25 13:04:44 +0000490 self.vapi.sw_interface_set_mtu(tun_dscp.sw_if_index, [600, 0, 0, 0])
Neale Ranns0b6a8572019-10-30 17:34:14 +0000491
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200492 p4 = (
493 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
494 / IP(src="1.2.3.4", dst="130.67.0.1", tos=42)
495 / UDP(sport=1234, dport=1234)
496 / Raw(b"Q" * 1000)
497 )
Neale Ranns0b6a8572019-10-30 17:34:14 +0000498 rx = self.send_and_expect(self.pg0, p4 * 15, self.pg1, 30)
499 inners = []
500 for p in rx:
501 inners.append(p[IP].payload)
502 reass_pkt = reassemble4(inners)
503 for p in reass_pkt:
504 self.assert_packet_checksums_valid(p)
505 self.assertEqual(p[IP].ttl, 63)
506
Ole Troan282093f2018-09-19 12:38:51 +0200507 def test_ipip_create(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200508 """ipip create / delete interface test"""
509 rv = ipip_add_tunnel(self, "1.2.3.4", "2.3.4.5")
Ole Troan282093f2018-09-19 12:38:51 +0200510 sw_if_index = rv.sw_if_index
511 self.vapi.ipip_del_tunnel(sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +0100512
Ole Troan282093f2018-09-19 12:38:51 +0200513 def test_ipip_vrf_create(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200514 """ipip create / delete interface VRF test"""
Ole Troan282093f2018-09-19 12:38:51 +0200515
516 t = VppIpTable(self, 20)
517 t.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200518 rv = ipip_add_tunnel(self, "1.2.3.4", "2.3.4.5", table_id=20)
Ole Troan282093f2018-09-19 12:38:51 +0200519 sw_if_index = rv.sw_if_index
520 self.vapi.ipip_del_tunnel(sw_if_index)
521
522 def payload(self, len):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200523 return "x" * len
Ole Troan282093f2018-09-19 12:38:51 +0200524
Neale Ranns14053c92019-12-29 23:55:18 +0000525 def test_mipip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200526 """p2mp IPv4 tunnel Tests"""
Neale Ranns14053c92019-12-29 23:55:18 +0000527
Neale Ranns256b67b2020-09-02 14:46:53 +0000528 for itf in self.pg_interfaces[:2]:
Neale Ranns14053c92019-12-29 23:55:18 +0000529 #
530 # one underlay nh for each overlay/tunnel peer
531 #
532 itf.generate_remote_hosts(4)
533 itf.configure_ipv4_neighbors()
534
535 #
536 # Create an p2mo IPIP tunnel.
537 # - set it admin up
538 # - assign an IP Addres
539 # - Add a route via the tunnel
540 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200541 ipip_if = VppIpIpTunInterface(
542 self,
543 itf,
544 itf.local_ip4,
545 "0.0.0.0",
546 mode=(VppEnum.vl_api_tunnel_mode_t.TUNNEL_API_MODE_MP),
547 )
Neale Ranns14053c92019-12-29 23:55:18 +0000548 ipip_if.add_vpp_config()
549 ipip_if.admin_up()
550 ipip_if.config_ip4()
551 ipip_if.generate_remote_hosts(4)
552
553 self.logger.info(self.vapi.cli("sh adj"))
554 self.logger.info(self.vapi.cli("sh ip fib"))
555
556 #
557 # ensure we don't match to the tunnel if the source address
558 # is all zeros
559 #
560 # tx = self.create_tunnel_stream_4o4(self.pg0,
561 # "0.0.0.0",
562 # itf.local_ip4,
563 # self.pg0.local_ip4,
564 # self.pg0.remote_ip4)
565 # self.send_and_assert_no_replies(self.pg0, tx)
566
567 #
568 # for-each peer
569 #
570 for ii in range(1, 4):
571 route_addr = "4.4.4.%d" % ii
572
573 #
574 # route traffic via the peer
575 #
576 route_via_tun = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200577 self,
578 route_addr,
579 32,
580 [VppRoutePath(ipip_if._remote_hosts[ii].ip4, ipip_if.sw_if_index)],
581 )
Neale Ranns14053c92019-12-29 23:55:18 +0000582 route_via_tun.add_vpp_config()
583
584 #
Neale Ranns28287212019-12-16 00:53:11 +0000585 # Add a TEIB entry resolves the peer
Neale Ranns14053c92019-12-29 23:55:18 +0000586 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200587 teib = VppTeib(
588 self,
589 ipip_if,
590 ipip_if._remote_hosts[ii].ip4,
591 itf._remote_hosts[ii].ip4,
592 )
Neale Ranns03ce4622020-02-03 10:55:09 +0000593 teib.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200594 self.logger.info(
595 self.vapi.cli("sh adj nbr ipip0 %s" % ipip_if._remote_hosts[ii].ip4)
596 )
Neale Ranns14053c92019-12-29 23:55:18 +0000597
598 #
599 # Send a packet stream that is routed into the tunnel
600 # - packets are IPIP encapped
601 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200602 inner = (
603 IP(dst=route_addr, src="5.5.5.5")
604 / UDP(sport=1234, dport=1234)
605 / Raw(b"0x44" * 100)
606 )
607 tx_e = [
608 (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / inner)
609 for x in range(63)
610 ]
Neale Ranns14053c92019-12-29 23:55:18 +0000611
612 rxs = self.send_and_expect(self.pg0, tx_e, itf)
613
614 for rx in rxs:
615 self.assertEqual(rx[IP].src, itf.local_ip4)
616 self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4)
617
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200618 tx_i = [
619 (
620 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
621 / IP(src=itf._remote_hosts[ii].ip4, dst=itf.local_ip4)
622 / IP(src=self.pg0.local_ip4, dst=self.pg0.remote_ip4)
623 / UDP(sport=1234, dport=1234)
624 / Raw(b"0x44" * 100)
625 )
626 for x in range(63)
627 ]
Neale Ranns14053c92019-12-29 23:55:18 +0000628
629 self.logger.info(self.vapi.cli("sh ipip tunnel-hash"))
630 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
631
632 #
Neale Ranns28287212019-12-16 00:53:11 +0000633 # delete and re-add the TEIB
Neale Ranns14053c92019-12-29 23:55:18 +0000634 #
Neale Ranns03ce4622020-02-03 10:55:09 +0000635 teib.remove_vpp_config()
Neale Ranns14053c92019-12-29 23:55:18 +0000636 self.send_and_assert_no_replies(self.pg0, tx_e)
637 self.send_and_assert_no_replies(self.pg0, tx_i)
638
Neale Ranns03ce4622020-02-03 10:55:09 +0000639 teib.add_vpp_config()
Neale Ranns14053c92019-12-29 23:55:18 +0000640 rx = self.send_and_expect(self.pg0, tx_e, itf)
641 for rx in rxs:
642 self.assertEqual(rx[IP].src, itf.local_ip4)
643 self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4)
644 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
645
Neale Ranns256b67b2020-09-02 14:46:53 +0000646 #
647 # we can also send to the peer's address
648 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200649 inner = (
650 IP(dst=teib.peer, src="5.5.5.5")
651 / UDP(sport=1234, dport=1234)
652 / Raw(b"0x44" * 100)
653 )
654 tx_e = [
655 (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / inner)
656 for x in range(63)
657 ]
Neale Ranns256b67b2020-09-02 14:46:53 +0000658
659 rxs = self.send_and_expect(self.pg0, tx_e, itf)
660
661 #
662 # with all of the peers in place, swap the ip-table of
663 # the ipip interface
664 #
665 table = VppIpTable(self, 2)
666 table.add_vpp_config()
667
668 ipip_if.unconfig_ip4()
669 ipip_if.set_table_ip4(self.table.table_id)
670 ipip_if.config_ip4()
671
672 #
673 # we should still be able to reach the peers from the new table
674 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200675 inner = (
676 IP(dst=teib.peer, src="5.5.5.5")
677 / UDP(sport=1234, dport=1234)
678 / Raw(b"0x44" * 100)
679 )
680 tx_e = [
681 (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / inner)
682 for x in range(63)
683 ]
Neale Ranns256b67b2020-09-02 14:46:53 +0000684
685 rxs = self.send_and_expect(self.pg2, tx_e, itf)
686
Neale Ranns14053c92019-12-29 23:55:18 +0000687 ipip_if.admin_down()
688 ipip_if.unconfig_ip4()
Neale Ranns256b67b2020-09-02 14:46:53 +0000689 ipip_if.set_table_ip4(0)
Neale Ranns14053c92019-12-29 23:55:18 +0000690
Ole Troan282093f2018-09-19 12:38:51 +0200691
692class TestIPIP6(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200693 """IPIP6 Test Case"""
Ole Troan282093f2018-09-19 12:38:51 +0200694
695 @classmethod
696 def setUpClass(cls):
697 super(TestIPIP6, cls).setUpClass()
698 cls.create_pg_interfaces(range(2))
699 cls.interfaces = list(cls.pg_interfaces)
700
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700701 @classmethod
702 def tearDownClass(cls):
703 super(TestIPIP6, cls).tearDownClass()
704
Ole Troan282093f2018-09-19 12:38:51 +0200705 def setUp(self):
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800706 super(TestIPIP6, self).setUp()
Ole Troan282093f2018-09-19 12:38:51 +0200707 for i in self.interfaces:
708 i.admin_up()
709 i.config_ip4()
710 i.config_ip6()
711 i.disable_ipv6_ra()
712 i.resolve_arp()
713 i.resolve_ndp()
714 self.setup_tunnel()
715
716 def tearDown(self):
717 if not self.vpp_dead:
718 self.destroy_tunnel()
719 for i in self.pg_interfaces:
720 i.unconfig_ip4()
721 i.unconfig_ip6()
722 i.admin_down()
723 super(TestIPIP6, self).tearDown()
724
725 def setup_tunnel(self):
Ole Troan298c6952018-03-08 12:30:43 +0100726 # IPv6 transport
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200727 rv = ipip_add_tunnel(self, self.pg0.local_ip6, self.pg1.remote_ip6)
Ole Troan298c6952018-03-08 12:30:43 +0100728
729 sw_if_index = rv.sw_if_index
Ole Troan282093f2018-09-19 12:38:51 +0200730 self.tunnel_if_index = sw_if_index
Ole Troan46c1c112018-03-14 20:39:40 +0100731 self.vapi.sw_interface_set_flags(sw_if_index, 1)
732 self.vapi.sw_interface_set_unnumbered(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200733 sw_if_index=self.pg0.sw_if_index, unnumbered_sw_if_index=sw_if_index
734 )
Ole Troan298c6952018-03-08 12:30:43 +0100735
736 # Add IPv4 and IPv6 routes via tunnel interface
737 ip4_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200738 self,
739 "130.67.0.0",
740 16,
741 [
742 VppRoutePath(
743 "0.0.0.0", sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4
744 )
745 ],
746 )
Ole Troan298c6952018-03-08 12:30:43 +0100747 ip4_via_tunnel.add_vpp_config()
748
749 ip6_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200750 self,
751 "dead::",
752 16,
753 [VppRoutePath("::", sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)],
754 )
Ole Troan298c6952018-03-08 12:30:43 +0100755 ip6_via_tunnel.add_vpp_config()
756
Ole Troan282093f2018-09-19 12:38:51 +0200757 self.tunnel_ip6_via_tunnel = ip6_via_tunnel
758 self.tunnel_ip4_via_tunnel = ip4_via_tunnel
Ole Troan298c6952018-03-08 12:30:43 +0100759
Ole Troan282093f2018-09-19 12:38:51 +0200760 def destroy_tunnel(self):
761 # IPv6 transport
762 self.tunnel_ip4_via_tunnel.remove_vpp_config()
763 self.tunnel_ip6_via_tunnel.remove_vpp_config()
764
765 rv = self.vapi.ipip_del_tunnel(sw_if_index=self.tunnel_if_index)
766
767 def validate(self, rx, expected):
Ole Troan7f991832018-12-06 17:35:12 +0100768 self.assertEqual(rx, expected.__class__(expected))
Ole Troan282093f2018-09-19 12:38:51 +0200769
770 def generate_ip6_frags(self, payload_length, fragment_size):
771 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
772 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
773 p_ip6 = IPv6(src="1::1", dst=self.pg0.remote_ip6)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200774 outer_ip6 = (
775 p_ether
776 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.local_ip6)
777 / IPv6ExtHdrFragment()
778 / p_ip6
779 / p_payload
780 )
Ole Troan282093f2018-09-19 12:38:51 +0200781 frags = fragment6(outer_ip6, fragment_size)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200782 p6_reply = p_ip6 / p_payload
Ole Troan282093f2018-09-19 12:38:51 +0200783 p6_reply.hlim -= 1
784 return frags, p6_reply
785
786 def generate_ip6_hairpin_frags(self, payload_length, fragment_size):
787 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
788 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
789 p_ip6 = IPv6(src="1::1", dst="dead::1")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200790 outer_ip6 = (
791 p_ether
792 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.local_ip6)
793 / IPv6ExtHdrFragment()
794 / p_ip6
795 / p_payload
796 )
Ole Troan282093f2018-09-19 12:38:51 +0200797 frags = fragment6(outer_ip6, fragment_size)
798 p_ip6.hlim -= 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200799 p6_reply = (
800 IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=63)
801 / p_ip6
802 / p_payload
803 )
Ole Troan282093f2018-09-19 12:38:51 +0200804
805 return frags, p6_reply
806
807 def test_encap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200808 """ip{v4,v6} over ip6 test encap"""
Ole Troan282093f2018-09-19 12:38:51 +0200809 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200810 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh="UDP")
Ole Troan282093f2018-09-19 12:38:51 +0200811 p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42)
812 p_payload = UDP(sport=1234, dport=1234)
813
814 # Encapsulation
Ole Troan298c6952018-03-08 12:30:43 +0100815 # IPv6 in to IPv6 tunnel
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200816 p6 = p_ether / p_ip6 / p_payload
817 p6_reply = (
818 IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=64)
819 / p_ip6
820 / p_payload
821 )
Ole Troan298c6952018-03-08 12:30:43 +0100822 p6_reply[1].hlim -= 1
Ole Troan9a475372019-03-05 16:58:24 +0100823 rx = self.send_and_expect(self.pg0, p6 * 11, self.pg1)
Ole Troan298c6952018-03-08 12:30:43 +0100824 for p in rx:
825 self.validate(p[1], p6_reply)
826
827 # IPv4 in to IPv6 tunnel
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200828 p4 = p_ether / p_ip4 / p_payload
829 p4_reply = (
830 IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=64)
831 / p_ip4
832 / p_payload
833 )
Ole Troan298c6952018-03-08 12:30:43 +0100834 p4_reply[1].ttl -= 1
Ole Troan9a475372019-03-05 16:58:24 +0100835 rx = self.send_and_expect(self.pg0, p4 * 11, self.pg1)
Ole Troan298c6952018-03-08 12:30:43 +0100836 for p in rx:
837 self.validate(p[1], p4_reply)
838
Ole Troan282093f2018-09-19 12:38:51 +0200839 def test_decap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200840 """ip{v4,v6} over ip6 test decap"""
Ole Troan298c6952018-03-08 12:30:43 +0100841
842 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200843 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh="UDP")
Ole Troan298c6952018-03-08 12:30:43 +0100844 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
Ole Troan282093f2018-09-19 12:38:51 +0200845 p_payload = UDP(sport=1234, dport=1234)
846
847 # Decapsulation
848 # IPv6 tunnel to IPv4
849
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200850 p4 = (
851 p_ether
852 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.local_ip6)
853 / p_ip4
854 / p_payload
855 )
856 p4_reply = p_ip4 / p_payload
Ole Troan298c6952018-03-08 12:30:43 +0100857 p4_reply.ttl -= 1
Ole Troan9a475372019-03-05 16:58:24 +0100858 rx = self.send_and_expect(self.pg1, p4 * 11, self.pg0)
Ole Troan298c6952018-03-08 12:30:43 +0100859 for p in rx:
860 self.validate(p[1], p4_reply)
861
862 # IPv6 tunnel to IPv6
863 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200864 p6 = (
865 p_ether
866 / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.local_ip6)
867 / p_ip6
868 / p_payload
869 )
870 p6_reply = p_ip6 / p_payload
Ole Troan298c6952018-03-08 12:30:43 +0100871 p6_reply.hlim = 63
Ole Troan9a475372019-03-05 16:58:24 +0100872 rx = self.send_and_expect(self.pg1, p6 * 11, self.pg0)
Ole Troan298c6952018-03-08 12:30:43 +0100873 for p in rx:
874 self.validate(p[1], p6_reply)
875
Neale Ranns95346962019-11-25 13:04:44 +0000876 def verify_ip4ip6_encaps(self, a, p_ip4s, p_ip6_encaps):
877 for i, p_ip4 in enumerate(p_ip4s):
878 p_ip4.dst = a
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200879 p4 = self.p_ether / p_ip4 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000880 p_ip4_inner = p_ip4
881 p_ip4_inner.ttl -= 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200882 p6_reply = p_ip6_encaps[i] / p_ip4_inner / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000883 rx = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1)
884 for p in rx:
885 self.validate(p[1], p6_reply)
886 self.assert_packet_checksums_valid(p)
887
888 def verify_ip6ip6_encaps(self, a, p_ip6s, p_ip6_encaps):
889 for i, p_ip6 in enumerate(p_ip6s):
890 p_ip6.dst = a
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200891 p6 = self.p_ether / p_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000892 p_inner_ip6 = p_ip6
893 p_inner_ip6.hlim -= 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200894 p6_reply = p_ip6_encaps[i] / p_inner_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +0000895 rx = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1)
896 for p in rx:
897 self.validate(p[1], p6_reply)
898 self.assert_packet_checksums_valid(p)
899
900 def test_ipip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200901 """ip{v4,v6} over ip6 test"""
Neale Ranns95346962019-11-25 13:04:44 +0000902
903 # that's annoying
904 self.destroy_tunnel()
905
906 self.pg1.generate_remote_hosts(5)
907 self.pg1.configure_ipv6_neighbors()
Neale Ranns59ff9182019-12-29 23:55:18 +0000908 e = VppEnum.vl_api_tunnel_encap_decap_flags_t
Neale Ranns95346962019-11-25 13:04:44 +0000909 d = VppEnum.vl_api_ip_dscp_t
910 self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200911 self.p_payload = UDP(sport=1234, dport=1234) / Raw(b"X" * 100)
Neale Ranns95346962019-11-25 13:04:44 +0000912
913 # create a TOS byte by shifting a DSCP code point 2 bits. those 2 bits
914 # are for the ECN.
915 dscp = d.IP_API_DSCP_AF31 << 2
916 ecn = 3
917 dscp_ecn = d.IP_API_DSCP_AF31 << 2 | ecn
918
919 # IPv4 transport that copies the DCSP from the payload
920 tun_dscp = VppIpIpTunInterface(
921 self,
922 self.pg0,
923 self.pg0.local_ip6,
924 self.pg1.remote_hosts[0].ip6,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200925 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP,
926 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000927 tun_dscp.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000928 # IPv4 transport that copies the DCSP and ECN from the payload
929 tun_dscp_ecn = VppIpIpTunInterface(
930 self,
931 self.pg0,
932 self.pg0.local_ip6,
933 self.pg1.remote_hosts[1].ip6,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200934 flags=(
935 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP
936 | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
937 ),
938 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000939 tun_dscp_ecn.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000940 # IPv4 transport that copies the ECN from the payload and sets the
941 # DF bit on encap. copies the ECN on decap
942 tun_ecn = VppIpIpTunInterface(
943 self,
944 self.pg0,
945 self.pg0.local_ip6,
946 self.pg1.remote_hosts[2].ip6,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200947 flags=(
948 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
949 | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_DF
950 | e.TUNNEL_API_ENCAP_DECAP_FLAG_DECAP_COPY_ECN
951 ),
952 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000953 tun_ecn.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000954 # IPv4 transport that sets a fixed DSCP in the encap and copies
955 # the DF bit
956 tun = VppIpIpTunInterface(
957 self,
958 self.pg0,
959 self.pg0.local_ip6,
960 self.pg1.remote_hosts[3].ip6,
961 dscp=d.IP_API_DSCP_AF11,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200962 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DF,
963 )
Neale Ranns59ff9182019-12-29 23:55:18 +0000964 tun.add_vpp_config()
Neale Ranns95346962019-11-25 13:04:44 +0000965
966 # array of all the tunnels
967 tuns = [tun_dscp, tun_dscp_ecn, tun_ecn, tun]
968
969 # addresses for prefixes routed via each tunnel
970 a4s = ["" for i in range(len(tuns))]
971 a6s = ["" for i in range(len(tuns))]
972
973 # IP headers for inner packets with each combination of DSCp/ECN tested
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200974 p_ip6s = [
975 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=dscp),
976 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=dscp_ecn),
977 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=ecn),
978 IPv6(src="1::1", dst="DEAD::1", nh="UDP", tc=0xFF),
979 ]
980 p_ip4s = [
981 IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp, flags="DF"),
982 IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp_ecn),
983 IP(src="1.2.3.4", dst="130.67.0.1", tos=ecn),
984 IP(src="1.2.3.4", dst="130.67.0.1", tos=0xFF),
985 ]
Neale Ranns95346962019-11-25 13:04:44 +0000986
987 # Configure each tunnel
988 for i, t in enumerate(tuns):
989 # Set interface up and enable IP on it
990 self.vapi.sw_interface_set_flags(t.sw_if_index, 1)
991 self.vapi.sw_interface_set_unnumbered(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200992 sw_if_index=self.pg0.sw_if_index, unnumbered_sw_if_index=t.sw_if_index
993 )
Neale Ranns95346962019-11-25 13:04:44 +0000994
995 # prefix for route / destination address for packets
996 a4s[i] = "130.67.%d.0" % i
997 a6s[i] = "dead:%d::" % i
998
999 # Add IPv4 and IPv6 routes via tunnel interface
1000 ip4_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001001 self,
1002 a4s[i],
1003 24,
1004 [
1005 VppRoutePath(
1006 "0.0.0.0",
1007 t.sw_if_index,
1008 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
1009 )
1010 ],
1011 )
Neale Ranns95346962019-11-25 13:04:44 +00001012 ip4_via_tunnel.add_vpp_config()
1013
1014 ip6_via_tunnel = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001015 self,
1016 a6s[i],
1017 64,
1018 [
1019 VppRoutePath(
1020 "::", t.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6
1021 )
1022 ],
1023 )
Neale Ranns95346962019-11-25 13:04:44 +00001024 ip6_via_tunnel.add_vpp_config()
1025
1026 #
1027 # Encapsulation
1028 #
1029
1030 # tun_dscp copies only the dscp
1031 # expected TC values are thus only the DCSP value is present from the
1032 # inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001033 exp_tcs = [dscp, dscp, 0, 0xFC]
1034 p_ip6_encaps = [
1035 IPv6(src=self.pg0.local_ip6, dst=tun_dscp.dst, tc=tc) for tc in exp_tcs
1036 ]
Neale Ranns95346962019-11-25 13:04:44 +00001037
1038 # IPv4 in to IPv4 tunnel
1039 self.verify_ip4ip6_encaps(a4s[0], p_ip4s, p_ip6_encaps)
1040 # IPv6 in to IPv4 tunnel
1041 self.verify_ip6ip6_encaps(a6s[0], p_ip6s, p_ip6_encaps)
1042
1043 # tun_dscp_ecn copies the dscp and the ecn
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001044 exp_tcs = [dscp, dscp_ecn, ecn, 0xFF]
1045 p_ip6_encaps = [
1046 IPv6(src=self.pg0.local_ip6, dst=tun_dscp_ecn.dst, tc=tc) for tc in exp_tcs
1047 ]
Neale Ranns95346962019-11-25 13:04:44 +00001048
1049 self.verify_ip4ip6_encaps(a4s[1], p_ip4s, p_ip6_encaps)
1050 self.verify_ip6ip6_encaps(a6s[1], p_ip6s, p_ip6_encaps)
1051
1052 # tun_ecn copies only the ecn and always sets DF
1053 exp_tcs = [0, ecn, ecn, ecn]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001054 p_ip6_encaps = [
1055 IPv6(src=self.pg0.local_ip6, dst=tun_ecn.dst, tc=tc) for tc in exp_tcs
1056 ]
Neale Ranns95346962019-11-25 13:04:44 +00001057
1058 self.verify_ip4ip6_encaps(a4s[2], p_ip4s, p_ip6_encaps)
1059 self.verify_ip6ip6_encaps(a6s[2], p_ip6s, p_ip6_encaps)
1060
1061 # tun sets a fixed dscp
1062 fixed_dscp = tun.dscp << 2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001063 p_ip6_encaps = [
1064 IPv6(src=self.pg0.local_ip6, dst=tun.dst, tc=fixed_dscp)
1065 for i in range(len(p_ip4s))
1066 ]
Neale Ranns95346962019-11-25 13:04:44 +00001067
1068 self.verify_ip4ip6_encaps(a4s[3], p_ip4s, p_ip6_encaps)
1069 self.verify_ip6ip6_encaps(a6s[3], p_ip6s, p_ip6_encaps)
1070
1071 #
1072 # Decapsulation
1073 #
1074 n_packets_decapped = self.statistics.get_err_counter(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001075 "/err/ipip6-input/packets decapsulated"
1076 )
Neale Ranns95346962019-11-25 13:04:44 +00001077
1078 self.p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1079
1080 # IPv6 tunnel to IPv4
1081 tcs = [0, dscp, dscp_ecn, ecn]
1082
1083 # one overlay packet and all combinations of its encap
1084 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001085 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 +00001086
1087 # for each encap tun will produce the same inner packet because it does
1088 # not copy up fields from the payload
1089 for p_ip6_encap in p_ip6_encaps:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001090 p6 = self.p_ether / p_ip6_encap / p_ip4 / self.p_payload
1091 p4_reply = p_ip4 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +00001092 p4_reply.ttl -= 1
1093 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1094 n_packets_decapped += N_PACKETS
1095 for p in rx:
1096 self.validate(p[1], p4_reply)
1097 self.assert_packet_checksums_valid(p)
1098
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001099 err = self.statistics.get_err_counter("/err/ipip6-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +00001100 self.assertEqual(err, n_packets_decapped)
1101
1102 # tun_ecn copies the ECN bits from the encap to the inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001103 p_ip6_encaps = [
1104 IPv6(src=tun_ecn.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs
1105 ]
Neale Ranns95346962019-11-25 13:04:44 +00001106 p_ip4_replys = [p_ip4.copy() for i in range(len(p_ip6_encaps))]
1107 p_ip4_replys[2].tos = ecn
1108 p_ip4_replys[3].tos = ecn
1109 for i, p_ip6_encap in enumerate(p_ip6_encaps):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001110 p6 = self.p_ether / p_ip6_encap / p_ip4 / self.p_payload
1111 p4_reply = p_ip4_replys[i] / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +00001112 p4_reply.ttl -= 1
1113 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1114 n_packets_decapped += N_PACKETS
1115 for p in rx:
1116 self.validate(p[1], p4_reply)
1117 self.assert_packet_checksums_valid(p)
1118
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001119 err = self.statistics.get_err_counter("/err/ipip6-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +00001120 self.assertEqual(err, n_packets_decapped)
1121
1122 # IPv6 tunnel to IPv6
1123 # for each encap tun will produce the same inner packet because it does
1124 # not copy up fields from the payload
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001125 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 +00001126 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
1127 for p_ip6_encap in p_ip6_encaps:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001128 p6 = self.p_ether / p_ip6_encap / p_ip6 / self.p_payload
1129 p6_reply = p_ip6 / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +00001130 p6_reply.hlim = 63
1131 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1132 n_packets_decapped += N_PACKETS
1133 for p in rx:
1134 self.validate(p[1], p6_reply)
1135 self.assert_packet_checksums_valid(p)
1136
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001137 err = self.statistics.get_err_counter("/err/ipip6-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +00001138 self.assertEqual(err, n_packets_decapped)
1139
1140 # IPv6 tunnel to IPv6
1141 # tun_ecn copies the ECN bits from the encap to the inner
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001142 p_ip6_encaps = [
1143 IPv6(src=tun_ecn.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs
1144 ]
Neale Ranns95346962019-11-25 13:04:44 +00001145 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
1146 p_ip6_replys = [p_ip6.copy() for i in range(len(p_ip6_encaps))]
1147 p_ip6_replys[2].tc = ecn
1148 p_ip6_replys[3].tc = ecn
1149 for i, p_ip6_encap in enumerate(p_ip6_encaps):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001150 p6 = self.p_ether / p_ip6_encap / p_ip6 / self.p_payload
1151 p6_reply = p_ip6_replys[i] / self.p_payload
Neale Ranns95346962019-11-25 13:04:44 +00001152 p6_reply.hlim = 63
1153 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1154 n_packets_decapped += N_PACKETS
1155 for p in rx:
1156 self.validate(p[1], p6_reply)
1157 self.assert_packet_checksums_valid(p)
1158
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001159 err = self.statistics.get_err_counter("/err/ipip6-input/packets decapsulated")
Neale Ranns95346962019-11-25 13:04:44 +00001160 self.assertEqual(err, n_packets_decapped)
1161
Ole Troan282093f2018-09-19 12:38:51 +02001162 def test_frag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001163 """ip{v4,v6} over ip6 test frag"""
Ole Troan282093f2018-09-19 12:38:51 +02001164
1165 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001166 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh="UDP")
Ole Troan282093f2018-09-19 12:38:51 +02001167 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
1168 p_payload = UDP(sport=1234, dport=1234)
1169
1170 #
1171 # Fragmentation / Reassembly and Re-fragmentation
1172 #
1173 rv = self.vapi.ip_reassembly_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001174 sw_if_index=self.pg1.sw_if_index, enable_ip6=1
1175 )
Ole Troan282093f2018-09-19 12:38:51 +02001176
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001177 self.vapi.ip_reassembly_set(
1178 timeout_ms=1000,
1179 max_reassemblies=1000,
1180 max_reassembly_length=1000,
1181 expire_walk_interval_ms=10000,
1182 is_ip6=1,
1183 )
Klement Sekera3a343d42019-05-16 14:35:46 +02001184
Ole Troan282093f2018-09-19 12:38:51 +02001185 # Send lots of fragments, verify reassembled packet
Ole Troan233e4682019-05-16 15:01:34 +02001186 before_cnt = self.statistics.get_err_counter(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001187 "/err/ipip6-input/packets decapsulated"
1188 )
Ole Troan282093f2018-09-19 12:38:51 +02001189 frags, p6_reply = self.generate_ip6_frags(3131, 1400)
1190 f = []
1191 for i in range(0, 1000):
1192 f.extend(frags)
1193 self.pg1.add_stream(f)
1194 self.pg_enable_capture()
1195 self.pg_start()
1196 rx = self.pg0.get_capture(1000)
1197
1198 for p in rx:
1199 self.validate(p[1], p6_reply)
1200
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001201 cnt = self.statistics.get_err_counter("/err/ipip6-input/packets decapsulated")
Ole Troan282093f2018-09-19 12:38:51 +02001202 self.assertEqual(cnt, before_cnt + 1000)
1203
1204 f = []
1205 r = []
1206 # TODO: Check out why reassembly of atomic fragments don't work
1207 for i in range(10, 90):
1208 frags, p6_reply = self.generate_ip6_frags(i * 100, 1000)
1209 f.extend(frags)
1210 r.extend(p6_reply)
1211 self.pg_enable_capture()
1212 self.pg1.add_stream(f)
1213 self.pg_start()
1214 rx = self.pg0.get_capture(80)
1215 i = 0
1216 for p in rx:
1217 self.validate(p[1], r[i])
1218 i += 1
1219
1220 # Simple fragmentation
1221 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1222 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
1223
1224 # IPv6 in to IPv6 tunnel
1225 p_payload = UDP(sport=1234, dport=1234) / self.payload(1300)
1226
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001227 p6 = p_ether / p_ip6 / p_payload
1228 p6_reply = (
1229 IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=63)
1230 / p_ip6
1231 / p_payload
1232 )
Ole Troan282093f2018-09-19 12:38:51 +02001233 p6_reply[1].hlim -= 1
1234 self.pg_enable_capture()
1235 self.pg0.add_stream(p6)
1236 self.pg_start()
1237 rx = self.pg1.get_capture(2)
1238
1239 # Scapy defragment doesn't deal well with multiple layers
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001240 # of same type / Ethernet header first
Ole Troan282093f2018-09-19 12:38:51 +02001241 f = [p[1] for p in rx]
1242 reass_pkt = defragment6(f)
1243 self.validate(reass_pkt, p6_reply)
1244
1245 # Now try with re-fragmentation
1246 #
1247 # Send large fragments to tunnel head-end, for the tunnel head end
1248 # to reassemble and then refragment out the tunnel again.
1249 # Hair-pinning
1250 #
1251 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
1252 frags, p6_reply = self.generate_ip6_hairpin_frags(8000, 1200)
1253 self.pg_enable_capture()
1254 self.pg1.add_stream(frags)
1255 self.pg_start()
1256 rx = self.pg1.get_capture(7)
1257 f = [p[1] for p in rx]
1258 reass_pkt = defragment6(f)
1259 p6_reply.id = 256
1260 self.validate(reass_pkt, p6_reply)
1261
Neale Rannsec5371e2022-03-04 11:45:41 +00001262 def test_ip6_mpls_frag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001263 """Test fragmenting IPv6 over MPLS"""
Neale Rannsec5371e2022-03-04 11:45:41 +00001264
1265 # IPv6 packets must be locally generated to be fragmented
1266 # the use of tunnel encaps
1267 tun_dst = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001268 self,
1269 "1000::1",
1270 128,
1271 [
1272 VppRoutePath(
1273 self.pg1.remote_ip6, self.pg1.sw_if_index, labels=[VppMplsLabel(32)]
1274 )
1275 ],
1276 ).add_vpp_config()
Neale Rannsec5371e2022-03-04 11:45:41 +00001277
1278 tun = VppIpIpTunInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001279 self, self.pg0, self.pg0.local_ip6, "1000::1"
1280 ).add_vpp_config()
Neale Rannsec5371e2022-03-04 11:45:41 +00001281
1282 tun.admin_up()
1283 tun.config_ip6()
1284 tun.config_ip4()
1285
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001286 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2000, 0, 0, 0])
Neale Rannsec5371e2022-03-04 11:45:41 +00001287
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001288 p_6k = (
1289 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1290 / IPv6(src=self.pg0.remote_ip6, dst=tun.remote_ip6)
1291 / UDP(sport=1234, dport=5678)
1292 / Raw(b"0xa" * 2000)
1293 )
1294 p_2k = (
1295 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1296 / IPv6(src=self.pg0.remote_ip6, dst=tun.remote_ip6)
1297 / UDP(sport=1234, dport=5678)
1298 / Raw(b"0xa" * 1000)
1299 )
1300 p_1k = (
1301 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1302 / IPv6(src=self.pg0.remote_ip6, dst=tun.remote_ip6)
1303 / UDP(sport=1234, dport=5678)
1304 / Raw(b"0xa" * 600)
1305 )
Neale Rannsec5371e2022-03-04 11:45:41 +00001306
1307 # this is now the interface MTU frags
1308 rxs = self.send_and_expect(self.pg0, [p_6k], self.pg1, n_rx=4)
1309 self.assertEqual(rxs[0][UDP].dport, 5678)
1310 for rx in rxs:
1311 self.assertEqual(rx[MPLS].label, 32)
1312 self.assertEqual(rx[IPv6].dst, "1000::1")
1313 self.assertEqual(rx[IPv6].dst, "1000::1")
1314 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
1315 self.send_and_expect(self.pg0, [p_1k], self.pg1)
1316
Ole Troan298c6952018-03-08 12:30:43 +01001317 def test_ipip_create(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001318 """ipip create / delete interface test"""
1319 rv = ipip_add_tunnel(self, "1.2.3.4", "2.3.4.5")
Ole Troan298c6952018-03-08 12:30:43 +01001320 sw_if_index = rv.sw_if_index
Ole Troan46c1c112018-03-14 20:39:40 +01001321 self.vapi.ipip_del_tunnel(sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +01001322
Neale Ranns61502112018-08-22 00:21:14 -07001323 def test_ipip_vrf_create(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001324 """ipip create / delete interface VRF test"""
Neale Ranns61502112018-08-22 00:21:14 -07001325
1326 t = VppIpTable(self, 20)
1327 t.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001328 rv = ipip_add_tunnel(self, "1.2.3.4", "2.3.4.5", table_id=20)
Neale Ranns61502112018-08-22 00:21:14 -07001329 sw_if_index = rv.sw_if_index
1330 self.vapi.ipip_del_tunnel(sw_if_index)
1331
Ole Troan4146c652018-08-08 22:23:19 +02001332 def payload(self, len):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001333 return "x" * len
Ole Troan4146c652018-08-08 22:23:19 +02001334
Ole Troan298c6952018-03-08 12:30:43 +01001335
Tianyu Li6d95f8c2022-02-25 05:51:10 +00001336class TestIPIPMPLS(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001337 """MPLS Test Case"""
Neale Rannse294de62020-12-21 09:52:24 +00001338
1339 @classmethod
1340 def setUpClass(cls):
Tianyu Li6d95f8c2022-02-25 05:51:10 +00001341 super(TestIPIPMPLS, cls).setUpClass()
Neale Rannse294de62020-12-21 09:52:24 +00001342 cls.create_pg_interfaces(range(2))
1343 cls.interfaces = list(cls.pg_interfaces)
1344
1345 @classmethod
1346 def tearDownClass(cls):
Tianyu Li6d95f8c2022-02-25 05:51:10 +00001347 super(TestIPIPMPLS, cls).tearDownClass()
Neale Rannse294de62020-12-21 09:52:24 +00001348
1349 def setUp(self):
Tianyu Li6d95f8c2022-02-25 05:51:10 +00001350 super(TestIPIPMPLS, self).setUp()
Neale Rannse294de62020-12-21 09:52:24 +00001351 for i in self.interfaces:
1352 i.admin_up()
1353 i.config_ip4()
1354 i.config_ip6()
1355 i.disable_ipv6_ra()
1356 i.resolve_arp()
1357 i.resolve_ndp()
1358
1359 def tearDown(self):
Tianyu Li6d95f8c2022-02-25 05:51:10 +00001360 super(TestIPIPMPLS, self).tearDown()
Neale Rannse294de62020-12-21 09:52:24 +00001361
1362 for i in self.pg_interfaces:
1363 i.unconfig_ip4()
1364 i.unconfig_ip6()
1365 i.admin_down()
1366
1367 def test_mpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001368 """MPLS over ip{6,4} test"""
Neale Rannse294de62020-12-21 09:52:24 +00001369
1370 tbl = VppMplsTable(self, 0)
1371 tbl.add_vpp_config()
1372
1373 self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001374 self.p_payload = UDP(sport=1234, dport=1234) / Raw(b"X" * 100)
Neale Rannse294de62020-12-21 09:52:24 +00001375 f = FibPathProto
1376
1377 # IPv4 transport
1378 tun4 = VppIpIpTunInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001379 self, self.pg1, self.pg1.local_ip4, self.pg1.remote_ip4
1380 ).add_vpp_config()
Neale Rannse294de62020-12-21 09:52:24 +00001381 tun4.admin_up()
1382 tun4.config_ip4()
1383 tun4.enable_mpls()
1384
1385 # IPv6 transport
1386 tun6 = VppIpIpTunInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001387 self, self.pg1, self.pg1.local_ip6, self.pg1.remote_ip6
1388 ).add_vpp_config()
Neale Rannse294de62020-12-21 09:52:24 +00001389 tun6.admin_up()
1390 tun6.config_ip6()
1391 tun6.enable_mpls()
1392
1393 # ip routes into the tunnels with output labels
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001394 r4 = VppIpRoute(
1395 self,
1396 "1.1.1.1",
1397 32,
1398 [
1399 VppRoutePath(
1400 tun4.remote_ip4, tun4.sw_if_index, labels=[VppMplsLabel(44)]
1401 )
1402 ],
1403 ).add_vpp_config()
1404 r6 = VppIpRoute(
1405 self,
1406 "1::1",
1407 128,
1408 [
1409 VppRoutePath(
1410 tun6.remote_ip6, tun6.sw_if_index, labels=[VppMplsLabel(66)]
1411 )
1412 ],
1413 ).add_vpp_config()
Neale Rannse294de62020-12-21 09:52:24 +00001414
1415 # deag MPLS routes from the tunnel
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001416 r4 = VppMplsRoute(
1417 self, 44, 1, [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index)]
1418 ).add_vpp_config()
1419 r6 = VppMplsRoute(
1420 self,
1421 66,
1422 1,
1423 [VppRoutePath(self.pg0.remote_ip6, self.pg0.sw_if_index)],
1424 eos_proto=f.FIB_PATH_NH_PROTO_IP6,
1425 ).add_vpp_config()
Neale Rannse294de62020-12-21 09:52:24 +00001426
1427 #
1428 # Tunnel Encap
1429 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001430 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 +00001431
1432 rxs = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1)
1433
1434 for rx in rxs:
1435 self.assertEqual(rx[IP].src, self.pg1.local_ip4)
1436 self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
1437 self.assertEqual(rx[MPLS].label, 44)
1438 inner = rx[MPLS].payload
1439 self.assertEqual(inner.src, "2.2.2.2")
1440 self.assertEqual(inner.dst, "1.1.1.1")
1441
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001442 p6 = self.p_ether / IPv6(src="2::2", dst="1::1") / self.p_payload
Neale Rannse294de62020-12-21 09:52:24 +00001443
1444 rxs = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1)
1445
1446 for rx in rxs:
1447 self.assertEqual(rx[IPv6].src, self.pg1.local_ip6)
1448 self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6)
1449 self.assertEqual(rx[MPLS].label, 66)
1450 inner = rx[MPLS].payload
1451 self.assertEqual(inner.src, "2::2")
1452 self.assertEqual(inner.dst, "1::1")
1453
1454 #
1455 # Tunnel Decap
1456 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001457 p4 = (
1458 self.p_ether
1459 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1460 / MPLS(label=44, ttl=4)
1461 / IP(src="1.1.1.1", dst="2.2.2.2")
1462 / self.p_payload
1463 )
Neale Rannse294de62020-12-21 09:52:24 +00001464
1465 rxs = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
1466
1467 for rx in rxs:
1468 self.assertEqual(rx[IP].src, "1.1.1.1")
1469 self.assertEqual(rx[IP].dst, "2.2.2.2")
1470
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001471 p6 = (
1472 self.p_ether
1473 / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6)
1474 / MPLS(label=66, ttl=4)
1475 / IPv6(src="1::1", dst="2::2")
1476 / self.p_payload
1477 )
Neale Rannse294de62020-12-21 09:52:24 +00001478
1479 rxs = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1480
1481 for rx in rxs:
1482 self.assertEqual(rx[IPv6].src, "1::1")
1483 self.assertEqual(rx[IPv6].dst, "2::2")
1484
1485 tun4.disable_mpls()
1486 tun6.disable_mpls()
1487
1488
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001489if __name__ == "__main__":
Ole Troan298c6952018-03-08 12:30:43 +01001490 unittest.main(testRunner=VppTestRunner)