blob: 1f1bcccf7923f414108cc1231b65c8bc381408ee [file] [log] [blame]
Jon Loeliger65866f02020-01-28 07:30:28 -06001#!/usr/bin/env python3
2
Jon Loeliger65866f02020-01-28 07:30:28 -06003import unittest
4
Dave Wallace8800f732023-08-31 00:47:44 -04005from framework import VppTestCase
6from asfframework import VppTestRunner
Jon Loeliger65866f02020-01-28 07:30:28 -06007from vpp_ip_route import VppIpRoute, VppRoutePath
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00008from config import config
Jon Loeliger65866f02020-01-28 07:30:28 -06009
Jon Loeliger65866f02020-01-28 07:30:28 -060010from scapy.layers.l2 import Ether
Alexander Chernavincd5a4a02020-03-12 08:42:12 -040011from scapy.layers.inet import IP, UDP, ICMP, TCP, IPerror, UDPerror
Alexander Chernavin46d0ff32020-03-06 06:11:07 -050012from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded, ICMPv6PacketTooBig
Alexander Chernavincd5a4a02020-03-12 08:42:12 -040013from scapy.layers.inet6 import ICMPv6EchoRequest, ICMPv6EchoReply, IPerror6
Jon Loeliger65866f02020-01-28 07:30:28 -060014
15
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000016@unittest.skipIf("map" in config.excluded_plugins, "Exclude MAP plugin tests")
Jon Loeliger65866f02020-01-28 07:30:28 -060017class TestMAPBR(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020018 """MAP-T Test Cases"""
Jon Loeliger65866f02020-01-28 07:30:28 -060019
20 @classmethod
21 def setUpClass(cls):
22 super(TestMAPBR, cls).setUpClass()
23
24 @classmethod
25 def tearDownClass(cls):
26 super(TestMAPBR, cls).tearDownClass()
27
28 def setUp(self):
29 super(TestMAPBR, self).setUp()
30
31 #
32 # Create 2 pg interfaces.
33 # pg0 is IPv4
34 # pg1 is IPv6
35 #
36 self.create_pg_interfaces(range(2))
37
38 self.pg0.admin_up()
39 self.pg0.config_ip4()
40 self.pg1.generate_remote_hosts(20)
41 self.pg1.configure_ipv4_neighbors()
42 self.pg0.resolve_arp()
43
44 self.pg1.admin_up()
45 self.pg1.config_ip6()
46 self.pg1.generate_remote_hosts(20)
47 self.pg1.configure_ipv6_neighbors()
48
49 #
50 # BR configuration parameters used for all test.
51 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020052 self.ip4_prefix = "198.18.0.0/24"
53 self.ip6_prefix = "2001:db8:f0::/48"
54 self.ip6_src = "2001:db8:ffff:ff00::/64"
Jon Loeliger65866f02020-01-28 07:30:28 -060055 self.ea_bits_len = 12
56 self.psid_offset = 6
57 self.psid_length = 4
58 self.mtu = 1500
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020059 self.tag = "MAP-T BR"
Jon Loeliger65866f02020-01-28 07:30:28 -060060
61 self.ipv4_internet_address = self.pg0.remote_ip4
62 self.ipv4_map_address = "198.18.0.12"
63 self.ipv4_udp_or_tcp_internet_port = 65000
64 self.ipv4_udp_or_tcp_map_port = 16606
65
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020066 self.ipv6_cpe_address = "2001:db8:f0:c30:0:c612:c:3" # 198.18.0.12
67 self.ipv6_spoof_address = "2001:db8:f0:c30:0:c612:1c:3" # 198.18.0.28
68 self.ipv6_spoof_prefix = "2001:db8:f0:c30:0:a00:c:3" # 10.0.0.12
69 self.ipv6_spoof_psid = "2001:db8:f0:c30:0:c612:c:4" # 4
70 self.ipv6_spoof_subnet = "2001:db8:f1:c30:0:c612:c:3" # f1
Jon Loeliger65866f02020-01-28 07:30:28 -060071
72 self.ipv6_udp_or_tcp_internet_port = 65000
73 self.ipv6_udp_or_tcp_map_port = 16606
74 self.ipv6_udp_or_tcp_spoof_port = 16862
75
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020076 self.ipv6_map_address = "2001:db8:ffff:ff00:ac:1001:200:0" # 176.16.1.2
Jon Loeliger65866f02020-01-28 07:30:28 -060077 self.ipv6_map_same_rule_diff_addr = (
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020078 "2001:db8:ffff:ff00:c6:1200:1000:0" # 198.18.0.16
79 )
Jon Loeliger47c99502020-01-30 10:54:58 -060080 self.ipv6_map_same_rule_same_addr = (
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020081 "2001:db8:ffff:ff00:c6:1200:c00:0" # 198.18.0.12
82 )
Jon Loeliger65866f02020-01-28 07:30:28 -060083
84 self.map_br_prefix = "2001:db8:f0::"
85 self.map_br_prefix_len = 48
86 self.psid_number = 3
87
88 #
89 # Add an IPv6 route to the MAP-BR.
90 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020091 map_route = VppIpRoute(
92 self,
93 self.map_br_prefix,
94 self.map_br_prefix_len,
95 [VppRoutePath(self.pg1.remote_ip6, self.pg1.sw_if_index)],
96 )
Jon Loeliger65866f02020-01-28 07:30:28 -060097 map_route.add_vpp_config()
98
Jon Loeliger65866f02020-01-28 07:30:28 -060099 #
100 # Add a MAP BR domain that maps from pg0 to pg1.
101 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200102 self.vapi.map_add_domain(
103 ip4_prefix=self.ip4_prefix,
104 ip6_prefix=self.ip6_prefix,
105 ip6_src=self.ip6_src,
106 ea_bits_len=self.ea_bits_len,
107 psid_offset=self.psid_offset,
108 psid_length=self.psid_length,
109 mtu=self.mtu,
110 tag=self.tag,
111 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600112
113 #
114 # Set BR parameters.
115 #
116 self.vapi.map_param_set_fragmentation(inner=1, ignore_df=0)
117 self.vapi.map_param_set_fragmentation(inner=0, ignore_df=0)
118 self.vapi.map_param_set_icmp(ip4_err_relay_src=self.pg0.local_ip4)
119 self.vapi.map_param_set_traffic_class(copy=1)
120
121 #
122 # Enable MAP-T on interfaces.
123 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200124 self.vapi.map_if_enable_disable(
125 is_enable=1, sw_if_index=self.pg0.sw_if_index, is_translation=1
126 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600127
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200128 self.vapi.map_if_enable_disable(
129 is_enable=1, sw_if_index=self.pg1.sw_if_index, is_translation=1
130 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600131
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200132 self.vapi.map_if_enable_disable(
133 is_enable=1, sw_if_index=self.pg1.sw_if_index, is_translation=1
134 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600135
136 def tearDown(self):
137 super(TestMAPBR, self).tearDown()
138 for i in self.pg_interfaces:
139 i.unconfig_ip4()
140 i.unconfig_ip6()
141 i.admin_down()
142
Jon Loeliger47c99502020-01-30 10:54:58 -0600143 def v4_address_check(self, pkt):
144 self.assertEqual(pkt[IP].src, self.ipv4_map_address)
145 self.assertEqual(pkt[IP].dst, self.ipv4_internet_address)
146
147 def v4_port_check(self, pkt, proto):
148 self.assertEqual(pkt[proto].sport, self.ipv4_udp_or_tcp_map_port)
149 self.assertEqual(pkt[proto].dport, self.ipv4_udp_or_tcp_internet_port)
150
151 def v6_address_check(self, pkt):
152 self.assertEqual(pkt[IPv6].src, self.ipv6_map_address)
153 self.assertEqual(pkt[IPv6].dst, self.ipv6_cpe_address)
154
155 def v6_port_check(self, pkt, proto):
156 self.assertEqual(pkt[proto].sport, self.ipv6_udp_or_tcp_internet_port)
157 self.assertEqual(pkt[proto].dport, self.ipv6_udp_or_tcp_map_port)
158
159 #
160 # Normal translation of UDP packets v4 -> v6 direction
161 # Send 128 frame size packet for IPv4/UDP.
162 # Received packet should be translated into IPv6 packet with no
163 # fragment header.
164 #
165
166 def test_map_t_udp_ip4_to_ip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200167 """MAP-T UDP IPv4 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600168
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200169 eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
170 ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address, tos=0)
171 udp = UDP(
172 sport=self.ipv4_udp_or_tcp_internet_port,
173 dport=self.ipv4_udp_or_tcp_map_port,
174 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600175 payload = "a" * 82
176 tx_pkt = eth / ip / udp / payload
177
178 self.pg_send(self.pg0, tx_pkt * 1)
179
180 rx_pkts = self.pg1.get_capture(1)
181 rx_pkt = rx_pkts[0]
182
183 self.v6_address_check(rx_pkt)
184 self.v6_port_check(rx_pkt, UDP)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200185 self.assertEqual(rx_pkt[IPv6].tc, 0) # IPv4 ToS passed to v6 TC
Jon Loeliger47c99502020-01-30 10:54:58 -0600186 self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="UDP").nh)
187
188 #
189 # Normal translation of TCP packets v4 -> v6 direction.
190 # Send 128 frame size packet for IPv4/TCP.
191 # Received packet should be translated into IPv6 packet with no
192 # fragment header.
193 #
194
195 def test_map_t_tcp_ip4_to_ip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200196 """MAP-T TCP IPv4 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600197
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200198 eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
199 ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address, tos=0)
200 tcp = TCP(
201 sport=self.ipv4_udp_or_tcp_internet_port,
202 dport=self.ipv4_udp_or_tcp_map_port,
203 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600204 payload = "a" * 82
205 tx_pkt = eth / ip / tcp / payload
206
207 self.pg_send(self.pg0, tx_pkt * 1)
208
209 rx_pkts = self.pg1.get_capture(1)
210 rx_pkt = rx_pkts[0]
211
212 self.v6_address_check(rx_pkt)
213 self.v6_port_check(rx_pkt, TCP)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200214 self.assertEqual(rx_pkt[IPv6].tc, 0) # IPv4 ToS passed to v6 TC
Jon Loeliger47c99502020-01-30 10:54:58 -0600215 self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="TCP").nh)
216
217 #
218 # Normal translation of UDP packets v6 -> v4 direction
219 # Send 128 frame size packet for IPv6/UDP.
220 # Received packet should be translated into an IPv4 packet with DF=1.
221 #
222
223 def test_map_t_udp_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200224 """MAP-T UDP IPv6 -> IPv4"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600225
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200226 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
227 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
228 udp = UDP(
229 sport=self.ipv6_udp_or_tcp_map_port,
230 dport=self.ipv6_udp_or_tcp_internet_port,
231 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600232 payload = "a" * 82
233 tx_pkt = eth / ip / udp / payload
234
235 self.pg_send(self.pg1, tx_pkt * 1)
236
237 rx_pkts = self.pg0.get_capture(1)
238 rx_pkt = rx_pkts[0]
239
240 self.v4_address_check(rx_pkt)
241 self.v4_port_check(rx_pkt, UDP)
242 self.assertEqual(rx_pkt[IP].proto, IP(proto="udp").proto)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200243 self.assertEqual(rx_pkt[IP].tos, 0) # IPv6 TC passed to v4 ToS
Jon Loeliger47c99502020-01-30 10:54:58 -0600244 df_bit = IP(flags="DF").flags
245 self.assertNotEqual(rx_pkt[IP].flags & df_bit, df_bit)
246
247 #
248 # Normal translation of TCP packets v6 -> v4 direction
249 # Send 128 frame size packet for IPv6/TCP.
250 # Received packet should be translated into an IPv4 packet with DF=1
251 #
252
253 def test_map_t_tcp_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200254 """MAP-T TCP IPv6 -> IPv4"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600255
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200256 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
257 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
258 tcp = TCP(
259 sport=self.ipv6_udp_or_tcp_map_port,
260 dport=self.ipv6_udp_or_tcp_internet_port,
261 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600262 payload = "a" * 82
263 tx_pkt = eth / ip / tcp / payload
264
265 self.pg_send(self.pg1, tx_pkt * 1)
266
267 rx_pkts = self.pg0.get_capture(1)
268 rx_pkt = rx_pkts[0]
269
270 self.v4_address_check(rx_pkt)
271 self.v4_port_check(rx_pkt, TCP)
272 self.assertEqual(rx_pkt[IP].proto, IP(proto="tcp").proto)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200273 self.assertEqual(rx_pkt[IP].tos, 0) # IPv6 TC passed to v4 ToS
Jon Loeliger47c99502020-01-30 10:54:58 -0600274 df_bit = IP(flags="DF").flags
275 self.assertNotEqual(rx_pkt[IP].flags & df_bit, df_bit)
276
277 #
278 # Translation of ICMP Echo Request v4 -> v6 direction
279 # Received packet should be translated into an IPv6 Echo Request.
280 #
281
282 def test_map_t_echo_request_ip4_to_ip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200283 """MAP-T echo request IPv4 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600284
Steven Luonge4238aa2024-04-19 09:49:20 -0700285 eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200286 ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address)
287 icmp = ICMP(type="echo-request", id=self.ipv6_udp_or_tcp_map_port)
Jon Loeliger47c99502020-01-30 10:54:58 -0600288 payload = "H" * 10
289 tx_pkt = eth / ip / icmp / payload
290
291 self.pg_send(self.pg0, tx_pkt * 1)
292
293 rx_pkts = self.pg1.get_capture(1)
294 rx_pkt = rx_pkts[0]
295
296 self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="ICMPv6").nh)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200297 self.assertEqual(
298 rx_pkt[ICMPv6EchoRequest].type, ICMPv6EchoRequest(type="Echo Request").type
299 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600300 self.assertEqual(rx_pkt[ICMPv6EchoRequest].code, 0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200301 self.assertEqual(rx_pkt[ICMPv6EchoRequest].id, self.ipv6_udp_or_tcp_map_port)
Jon Loeliger47c99502020-01-30 10:54:58 -0600302
303 #
304 # Translation of ICMP Echo Reply v4 -> v6 direction
305 # Received packet should be translated into an IPv6 Echo Reply.
306 #
307
308 def test_map_t_echo_reply_ip4_to_ip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200309 """MAP-T echo reply IPv4 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600310
Steven Luonge4238aa2024-04-19 09:49:20 -0700311 eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200312 ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address)
313 icmp = ICMP(type="echo-reply", id=self.ipv6_udp_or_tcp_map_port)
Jon Loeliger47c99502020-01-30 10:54:58 -0600314 payload = "H" * 10
315 tx_pkt = eth / ip / icmp / payload
316
317 self.pg_send(self.pg0, tx_pkt * 1)
318
319 rx_pkts = self.pg1.get_capture(1)
320 rx_pkt = rx_pkts[0]
321
322 self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="ICMPv6").nh)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200323 self.assertEqual(
324 rx_pkt[ICMPv6EchoReply].type, ICMPv6EchoReply(type="Echo Reply").type
325 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600326 self.assertEqual(rx_pkt[ICMPv6EchoReply].code, 0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200327 self.assertEqual(rx_pkt[ICMPv6EchoReply].id, self.ipv6_udp_or_tcp_map_port)
Jon Loeliger47c99502020-01-30 10:54:58 -0600328
329 #
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400330 # Translation of ICMP Time Exceeded v4 -> v6 direction
331 # Received packet should be translated into an IPv6 Time Exceeded.
332 #
333
334 def test_map_t_time_exceeded_ip4_to_ip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200335 """MAP-T time exceeded IPv4 -> IPv6"""
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400336
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200337 eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
338 ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address)
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400339 icmp = ICMP(type="time-exceeded", code="ttl-zero-during-transit")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200340 ip_inner = IP(dst=self.pg0.remote_ip4, src=self.ipv4_map_address, ttl=1)
341 udp_inner = UDP(
342 sport=self.ipv4_udp_or_tcp_map_port,
343 dport=self.ipv4_udp_or_tcp_internet_port,
344 )
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400345 payload = "H" * 10
346 tx_pkt = eth / ip / icmp / ip_inner / udp_inner / payload
347
348 self.pg_send(self.pg0, tx_pkt * 1)
349
350 rx_pkts = self.pg1.get_capture(1)
351 rx_pkt = rx_pkts[0]
352
353 self.v6_address_check(rx_pkt)
354 self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="ICMPv6").nh)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200355 self.assertEqual(rx_pkt[ICMPv6TimeExceeded].type, ICMPv6TimeExceeded().type)
356 self.assertEqual(
357 rx_pkt[ICMPv6TimeExceeded].code,
358 ICMPv6TimeExceeded(code="hop limit exceeded in transit").code,
359 )
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400360 self.assertEqual(rx_pkt[ICMPv6TimeExceeded].hlim, tx_pkt[IP][1].ttl)
361 self.assertTrue(rx_pkt.haslayer(IPerror6))
362 self.assertTrue(rx_pkt.haslayer(UDPerror))
363 self.assertEqual(rx_pkt[IPv6].src, rx_pkt[IPerror6].dst)
364 self.assertEqual(rx_pkt[IPv6].dst, rx_pkt[IPerror6].src)
365 self.assertEqual(rx_pkt[UDPerror].sport, self.ipv6_udp_or_tcp_map_port)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200366 self.assertEqual(rx_pkt[UDPerror].dport, self.ipv6_udp_or_tcp_internet_port)
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400367
368 #
Jon Loeliger47c99502020-01-30 10:54:58 -0600369 # Translation of ICMP Echo Request v6 -> v4 direction
370 # Received packet should be translated into an IPv4 Echo Request.
371 #
372
373 def test_map_t_echo_request_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200374 """MAP-T echo request IPv6 -> IPv4"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600375
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200376 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
377 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
Jon Loeliger47c99502020-01-30 10:54:58 -0600378 icmp = ICMPv6EchoRequest()
379 icmp.id = self.ipv6_udp_or_tcp_map_port
380 payload = "H" * 10
381 tx_pkt = eth / ip / icmp / payload
382
383 self.pg_send(self.pg1, tx_pkt * 1)
384
385 rx_pkts = self.pg0.get_capture(1)
386 rx_pkt = rx_pkts[0]
387
388 self.assertEqual(rx_pkt[IP].proto, IP(proto="icmp").proto)
389 self.assertEqual(rx_pkt[ICMP].type, ICMP(type="echo-request").type)
390 self.assertEqual(rx_pkt[ICMP].code, 0)
391 self.assertEqual(rx_pkt[ICMP].id, self.ipv6_udp_or_tcp_map_port)
392
393 #
394 # Translation of ICMP Echo Reply v6 -> v4 direction
395 # Received packet should be translated into an IPv4 Echo Reply.
396 #
397
398 def test_map_t_echo_reply_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200399 """MAP-T echo reply IPv6 -> IPv4"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600400
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200401 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
402 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
Jon Loeliger47c99502020-01-30 10:54:58 -0600403 icmp = ICMPv6EchoReply(id=self.ipv6_udp_or_tcp_map_port)
404 payload = "H" * 10
405 tx_pkt = eth / ip / icmp / payload
406
407 self.pg_send(self.pg1, tx_pkt * 1)
408
409 rx_pkts = self.pg0.get_capture(1)
410 rx_pkt = rx_pkts[0]
411
412 self.assertEqual(rx_pkt[IP].proto, IP(proto="icmp").proto)
413 self.assertEqual(rx_pkt[ICMP].type, ICMP(type="echo-reply").type)
414 self.assertEqual(rx_pkt[ICMP].code, 0)
415 self.assertEqual(rx_pkt[ICMP].id, self.ipv6_udp_or_tcp_map_port)
416
Jon Loeliger65866f02020-01-28 07:30:28 -0600417 #
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500418 # Translation of ICMP Packet Too Big v6 -> v4 direction
419 # Received packet should be translated into an IPv4 Dest Unreachable.
420 #
421
422 def test_map_t_packet_too_big_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200423 """MAP-T packet too big IPv6 -> IPv4"""
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500424
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200425 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
426 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500427 icmp = ICMPv6PacketTooBig(mtu=1280)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200428 ip_inner = IPv6(src=self.ipv6_map_address, dst=self.ipv6_cpe_address)
429 udp_inner = UDP(
430 sport=self.ipv6_udp_or_tcp_internet_port,
431 dport=self.ipv6_udp_or_tcp_map_port,
432 )
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500433 payload = "H" * 10
434 tx_pkt = eth / ip / icmp / ip_inner / udp_inner / payload
435
436 self.pg_send(self.pg1, tx_pkt * 1)
437
438 rx_pkts = self.pg0.get_capture(1)
439 rx_pkt = rx_pkts[0]
440
441 self.v4_address_check(rx_pkt)
442 self.assertEqual(rx_pkt[IP].proto, IP(proto="icmp").proto)
443 self.assertEqual(rx_pkt[ICMP].type, ICMP(type="dest-unreach").type)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200444 self.assertEqual(rx_pkt[ICMP].code, ICMP(code="fragmentation-needed").code)
445 self.assertEqual(rx_pkt[ICMP].nexthopmtu, tx_pkt[ICMPv6PacketTooBig].mtu - 20)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500446 self.assertTrue(rx_pkt.haslayer(IPerror))
447 self.assertTrue(rx_pkt.haslayer(UDPerror))
448 self.assertEqual(rx_pkt[IP].src, rx_pkt[IPerror].dst)
449 self.assertEqual(rx_pkt[IP].dst, rx_pkt[IPerror].src)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200450 self.assertEqual(rx_pkt[UDPerror].sport, self.ipv4_udp_or_tcp_internet_port)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500451 self.assertEqual(rx_pkt[UDPerror].dport, self.ipv4_udp_or_tcp_map_port)
452
453 #
454 # Translation of ICMP Time Exceeded v6 -> v4 direction
455 # Received packet should be translated into an IPv4 Time Exceeded.
456 #
457
458 def test_map_t_time_exceeded_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200459 """MAP-T time exceeded IPv6 -> IPv4"""
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500460
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200461 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
462 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500463 icmp = ICMPv6TimeExceeded()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200464 ip_inner = IPv6(src=self.ipv6_map_address, dst=self.ipv6_cpe_address, hlim=1)
465 udp_inner = UDP(
466 sport=self.ipv6_udp_or_tcp_internet_port,
467 dport=self.ipv6_udp_or_tcp_map_port,
468 )
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500469 payload = "H" * 10
470 tx_pkt = eth / ip / icmp / ip_inner / udp_inner / payload
471
472 self.pg_send(self.pg1, tx_pkt * 1)
473
474 rx_pkts = self.pg0.get_capture(1)
475 rx_pkt = rx_pkts[0]
476
477 self.v4_address_check(rx_pkt)
478 self.assertEqual(rx_pkt[IP].proto, IP(proto="icmp").proto)
479 self.assertEqual(rx_pkt[ICMP].type, ICMP(type="time-exceeded").type)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200480 self.assertEqual(rx_pkt[ICMP].code, ICMP(code="ttl-zero-during-transit").code)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500481 self.assertEqual(rx_pkt[ICMP].ttl, tx_pkt[IPv6][1].hlim)
482 self.assertTrue(rx_pkt.haslayer(IPerror))
483 self.assertTrue(rx_pkt.haslayer(UDPerror))
484 self.assertEqual(rx_pkt[IP].src, rx_pkt[IPerror].dst)
485 self.assertEqual(rx_pkt[IP].dst, rx_pkt[IPerror].src)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200486 self.assertEqual(rx_pkt[UDPerror].sport, self.ipv4_udp_or_tcp_internet_port)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500487 self.assertEqual(rx_pkt[UDPerror].dport, self.ipv4_udp_or_tcp_map_port)
488
489 #
Jon Loeliger65866f02020-01-28 07:30:28 -0600490 # Spoofed IPv4 Source Address v6 -> v4 direction
491 # Send a packet with a wrong IPv4 address embedded in bits 72-103.
492 # The BR should either drop the packet, or rewrite the spoofed
493 # source IPv4 as the actual source IPv4 address.
494 # The BR really should drop the packet.
495 #
496
497 def test_map_t_spoof_ipv4_src_addr_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200498 """MAP-T spoof ipv4 src addr IPv6 -> IPv4"""
Jon Loeliger65866f02020-01-28 07:30:28 -0600499
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200500 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
501 ip = IPv6(src=self.ipv6_spoof_address, dst=self.ipv6_map_address)
502 udp = UDP(
503 sport=self.ipv6_udp_or_tcp_map_port,
504 dport=self.ipv6_udp_or_tcp_internet_port,
505 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600506 payload = "a" * 82
507 tx_pkt = eth / ip / udp / payload
508
509 self.pg_send(self.pg1, tx_pkt * 1)
510
511 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200512 self.pg0.assert_nothing_captured(remark="Should drop IPv4 spoof address")
Jon Loeliger65866f02020-01-28 07:30:28 -0600513
514 #
515 # Spoofed IPv4 Source Prefix v6 -> v4 direction
516 # Send a packet with a wrong IPv4 prefix embedded in bits 72-103.
517 # The BR should either drop the packet, or rewrite the source IPv4
518 # to the prefix that matches the source IPv4 address.
519 #
520
521 def test_map_t_spoof_ipv4_src_prefix_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200522 """MAP-T spoof ipv4 src prefix IPv6 -> IPv4"""
Jon Loeliger65866f02020-01-28 07:30:28 -0600523
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200524 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
525 ip = IPv6(src=self.ipv6_spoof_prefix, dst=self.ipv6_map_address)
526 udp = UDP(
527 sport=self.ipv6_udp_or_tcp_map_port,
528 dport=self.ipv6_udp_or_tcp_internet_port,
529 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600530 payload = "a" * 82
531 tx_pkt = eth / ip / udp / payload
532
533 self.pg_send(self.pg1, tx_pkt * 1)
534
535 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200536 self.pg0.assert_nothing_captured(remark="Should drop IPv4 spoof prefix")
Jon Loeliger65866f02020-01-28 07:30:28 -0600537
538 #
539 # Spoofed IPv6 PSID v6 -> v4 direction
540 # Send a packet with a wrong IPv6 port PSID
541 # The BR should drop the packet.
542 #
543
544 def test_map_t_spoof_psid_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200545 """MAP-T spoof psid IPv6 -> IPv4"""
Jon Loeliger65866f02020-01-28 07:30:28 -0600546
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200547 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
548 ip = IPv6(src=self.ipv6_spoof_psid, dst=self.ipv6_map_address)
549 udp = UDP(
550 sport=self.ipv6_udp_or_tcp_map_port,
551 dport=self.ipv6_udp_or_tcp_internet_port,
552 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600553 payload = "a" * 82
554 tx_pkt = eth / ip / udp / payload
555
556 self.pg_send(self.pg1, tx_pkt * 1)
557
558 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200559 self.pg0.assert_nothing_captured(remark="Should drop IPv6 spoof PSID")
Jon Loeliger65866f02020-01-28 07:30:28 -0600560
561 #
562 # Spoofed IPv6 subnet field v6 -> v4 direction
563 # Send a packet with a wrong IPv6 subnet as "2001:db8:f1"
564 # The BR should drop the packet.
565 #
566
567 def test_map_t_spoof_subnet_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200568 """MAP-T spoof subnet IPv6 -> IPv4"""
Jon Loeliger65866f02020-01-28 07:30:28 -0600569
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200570 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
571 ip = IPv6(src=self.ipv6_spoof_subnet, dst=self.ipv6_map_address)
572 udp = UDP(
573 sport=self.ipv6_udp_or_tcp_map_port,
574 dport=self.ipv6_udp_or_tcp_internet_port,
575 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600576 payload = "a" * 82
577 tx_pkt = eth / ip / udp / payload
578
579 self.pg_send(self.pg1, tx_pkt * 1)
580
581 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200582 self.pg0.assert_nothing_captured(remark="Should drop IPv6 spoof subnet")
Jon Loeliger65866f02020-01-28 07:30:28 -0600583
584 #
585 # Spoofed IPv6 port PSID v6 -> v4 direction
586 # Send a packet with a wrong IPv6 port PSID
587 # The BR should drop the packet.
588 #
589
590 def test_map_t_spoof_port_psid_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200591 """MAP-T spoof port psid IPv6 -> IPv4"""
Jon Loeliger65866f02020-01-28 07:30:28 -0600592
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200593 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
594 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
595 udp = UDP(
596 sport=self.ipv6_udp_or_tcp_spoof_port,
597 dport=self.ipv6_udp_or_tcp_internet_port,
598 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600599 payload = "a" * 82
600 tx_pkt = eth / ip / udp / payload
601
602 self.pg_send(self.pg1, tx_pkt * 1)
603
604 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200605 self.pg0.assert_nothing_captured(remark="Should drop IPv6 spoof port PSID")
Jon Loeliger65866f02020-01-28 07:30:28 -0600606
Jon Loeliger47c99502020-01-30 10:54:58 -0600607 #
Vladimir Isaev92511312020-02-26 14:41:46 +0300608 # Spoofed IPv6 ICMP ID PSID v6 -> v4 direction
609 # Send a packet with a wrong IPv6 IMCP ID PSID
610 # The BR should drop the packet.
611 #
612
613 def test_map_t_spoof_icmp_id_psid_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200614 """MAP-T spoof ICMP id psid IPv6 -> IPv4"""
Vladimir Isaev92511312020-02-26 14:41:46 +0300615
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200616 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
617 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
Vladimir Isaev92511312020-02-26 14:41:46 +0300618 icmp = ICMPv6EchoRequest()
619 icmp.id = self.ipv6_udp_or_tcp_spoof_port
620 payload = "H" * 10
621 tx_pkt = eth / ip / icmp / payload
622
623 self.pg_send(self.pg1, tx_pkt * 1)
624
625 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200626 self.pg0.assert_nothing_captured(remark="Should drop IPv6 spoof port PSID")
Vladimir Isaev92511312020-02-26 14:41:46 +0300627
628 #
Jon Loeliger47c99502020-01-30 10:54:58 -0600629 # Map to Map - same rule, different address
630 #
631
632 @unittest.skip("Fixme: correct behavior needs clarification")
633 def test_map_t_same_rule_diff_addr_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200634 """MAP-T same rule, diff addr IPv6 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600635
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200636 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
637 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_same_rule_diff_addr)
638 udp = UDP(sport=self.ipv6_udp_or_tcp_map_port, dport=1025)
Jon Loeliger47c99502020-01-30 10:54:58 -0600639 payload = "a" * 82
640 tx_pkt = eth / ip / udp / payload
641
642 self.pg_send(self.pg1, tx_pkt * 1)
643
644 rx_pkts = self.pg1.get_capture(1)
645 rx_pkt = rx_pkts[0]
646
647 #
648 # Map to Map - same rule, same address
649 #
650
651 @unittest.skip("Fixme: correct behavior needs clarification")
652 def test_map_t_same_rule_same_addr_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200653 """MAP-T same rule, same addr IPv6 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600654
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200655 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
656 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_same_rule_same_addr)
657 udp = UDP(sport=self.ipv6_udp_or_tcp_map_port, dport=1025)
Jon Loeliger47c99502020-01-30 10:54:58 -0600658 payload = "a" * 82
659 tx_pkt = eth / ip / udp / payload
660
661 self.pg_send(self.pg1, tx_pkt * 1)
662
663 rx_pkts = self.pg1.get_capture(1)
664 rx_pkt = rx_pkts[0]
665
Klement Sekera16ce09d2022-04-23 11:34:29 +0200666
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200667if __name__ == "__main__":
Jon Loeliger65866f02020-01-28 07:30:28 -0600668 unittest.main(testRunner=VppTestRunner)