blob: 0de0e31520c637262385396d21731755e5c7c567 [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
Jon Loeliger65866f02020-01-28 07:30:28 -06008
Jon Loeliger65866f02020-01-28 07:30:28 -06009from scapy.layers.l2 import Ether
Alexander Chernavincd5a4a02020-03-12 08:42:12 -040010from scapy.layers.inet import IP, UDP, ICMP, TCP, IPerror, UDPerror
Alexander Chernavin46d0ff32020-03-06 06:11:07 -050011from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded, ICMPv6PacketTooBig
Alexander Chernavincd5a4a02020-03-12 08:42:12 -040012from scapy.layers.inet6 import ICMPv6EchoRequest, ICMPv6EchoReply, IPerror6
Jon Loeliger65866f02020-01-28 07:30:28 -060013
14
15class TestMAPBR(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020016 """MAP-T Test Cases"""
Jon Loeliger65866f02020-01-28 07:30:28 -060017
18 @classmethod
19 def setUpClass(cls):
20 super(TestMAPBR, cls).setUpClass()
21
22 @classmethod
23 def tearDownClass(cls):
24 super(TestMAPBR, cls).tearDownClass()
25
26 def setUp(self):
27 super(TestMAPBR, self).setUp()
28
29 #
30 # Create 2 pg interfaces.
31 # pg0 is IPv4
32 # pg1 is IPv6
33 #
34 self.create_pg_interfaces(range(2))
35
36 self.pg0.admin_up()
37 self.pg0.config_ip4()
38 self.pg1.generate_remote_hosts(20)
39 self.pg1.configure_ipv4_neighbors()
40 self.pg0.resolve_arp()
41
42 self.pg1.admin_up()
43 self.pg1.config_ip6()
44 self.pg1.generate_remote_hosts(20)
45 self.pg1.configure_ipv6_neighbors()
46
47 #
48 # BR configuration parameters used for all test.
49 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020050 self.ip4_prefix = "198.18.0.0/24"
51 self.ip6_prefix = "2001:db8:f0::/48"
52 self.ip6_src = "2001:db8:ffff:ff00::/64"
Jon Loeliger65866f02020-01-28 07:30:28 -060053 self.ea_bits_len = 12
54 self.psid_offset = 6
55 self.psid_length = 4
56 self.mtu = 1500
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020057 self.tag = "MAP-T BR"
Jon Loeliger65866f02020-01-28 07:30:28 -060058
59 self.ipv4_internet_address = self.pg0.remote_ip4
60 self.ipv4_map_address = "198.18.0.12"
61 self.ipv4_udp_or_tcp_internet_port = 65000
62 self.ipv4_udp_or_tcp_map_port = 16606
63
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020064 self.ipv6_cpe_address = "2001:db8:f0:c30:0:c612:c:3" # 198.18.0.12
65 self.ipv6_spoof_address = "2001:db8:f0:c30:0:c612:1c:3" # 198.18.0.28
66 self.ipv6_spoof_prefix = "2001:db8:f0:c30:0:a00:c:3" # 10.0.0.12
67 self.ipv6_spoof_psid = "2001:db8:f0:c30:0:c612:c:4" # 4
68 self.ipv6_spoof_subnet = "2001:db8:f1:c30:0:c612:c:3" # f1
Jon Loeliger65866f02020-01-28 07:30:28 -060069
70 self.ipv6_udp_or_tcp_internet_port = 65000
71 self.ipv6_udp_or_tcp_map_port = 16606
72 self.ipv6_udp_or_tcp_spoof_port = 16862
73
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020074 self.ipv6_map_address = "2001:db8:ffff:ff00:ac:1001:200:0" # 176.16.1.2
Jon Loeliger65866f02020-01-28 07:30:28 -060075 self.ipv6_map_same_rule_diff_addr = (
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020076 "2001:db8:ffff:ff00:c6:1200:1000:0" # 198.18.0.16
77 )
Jon Loeliger47c99502020-01-30 10:54:58 -060078 self.ipv6_map_same_rule_same_addr = (
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020079 "2001:db8:ffff:ff00:c6:1200:c00:0" # 198.18.0.12
80 )
Jon Loeliger65866f02020-01-28 07:30:28 -060081
82 self.map_br_prefix = "2001:db8:f0::"
83 self.map_br_prefix_len = 48
84 self.psid_number = 3
85
86 #
87 # Add an IPv6 route to the MAP-BR.
88 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020089 map_route = VppIpRoute(
90 self,
91 self.map_br_prefix,
92 self.map_br_prefix_len,
93 [VppRoutePath(self.pg1.remote_ip6, self.pg1.sw_if_index)],
94 )
Jon Loeliger65866f02020-01-28 07:30:28 -060095 map_route.add_vpp_config()
96
Jon Loeliger65866f02020-01-28 07:30:28 -060097 #
98 # Add a MAP BR domain that maps from pg0 to pg1.
99 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200100 self.vapi.map_add_domain(
101 ip4_prefix=self.ip4_prefix,
102 ip6_prefix=self.ip6_prefix,
103 ip6_src=self.ip6_src,
104 ea_bits_len=self.ea_bits_len,
105 psid_offset=self.psid_offset,
106 psid_length=self.psid_length,
107 mtu=self.mtu,
108 tag=self.tag,
109 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600110
111 #
112 # Set BR parameters.
113 #
114 self.vapi.map_param_set_fragmentation(inner=1, ignore_df=0)
115 self.vapi.map_param_set_fragmentation(inner=0, ignore_df=0)
116 self.vapi.map_param_set_icmp(ip4_err_relay_src=self.pg0.local_ip4)
117 self.vapi.map_param_set_traffic_class(copy=1)
118
119 #
120 # Enable MAP-T on interfaces.
121 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200122 self.vapi.map_if_enable_disable(
123 is_enable=1, sw_if_index=self.pg0.sw_if_index, is_translation=1
124 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600125
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200126 self.vapi.map_if_enable_disable(
127 is_enable=1, sw_if_index=self.pg1.sw_if_index, is_translation=1
128 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600129
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200130 self.vapi.map_if_enable_disable(
131 is_enable=1, sw_if_index=self.pg1.sw_if_index, is_translation=1
132 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600133
134 def tearDown(self):
135 super(TestMAPBR, self).tearDown()
136 for i in self.pg_interfaces:
137 i.unconfig_ip4()
138 i.unconfig_ip6()
139 i.admin_down()
140
Jon Loeliger47c99502020-01-30 10:54:58 -0600141 def v4_address_check(self, pkt):
142 self.assertEqual(pkt[IP].src, self.ipv4_map_address)
143 self.assertEqual(pkt[IP].dst, self.ipv4_internet_address)
144
145 def v4_port_check(self, pkt, proto):
146 self.assertEqual(pkt[proto].sport, self.ipv4_udp_or_tcp_map_port)
147 self.assertEqual(pkt[proto].dport, self.ipv4_udp_or_tcp_internet_port)
148
149 def v6_address_check(self, pkt):
150 self.assertEqual(pkt[IPv6].src, self.ipv6_map_address)
151 self.assertEqual(pkt[IPv6].dst, self.ipv6_cpe_address)
152
153 def v6_port_check(self, pkt, proto):
154 self.assertEqual(pkt[proto].sport, self.ipv6_udp_or_tcp_internet_port)
155 self.assertEqual(pkt[proto].dport, self.ipv6_udp_or_tcp_map_port)
156
157 #
158 # Normal translation of UDP packets v4 -> v6 direction
159 # Send 128 frame size packet for IPv4/UDP.
160 # Received packet should be translated into IPv6 packet with no
161 # fragment header.
162 #
163
164 def test_map_t_udp_ip4_to_ip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200165 """MAP-T UDP IPv4 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600166
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200167 eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
168 ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address, tos=0)
169 udp = UDP(
170 sport=self.ipv4_udp_or_tcp_internet_port,
171 dport=self.ipv4_udp_or_tcp_map_port,
172 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600173 payload = "a" * 82
174 tx_pkt = eth / ip / udp / payload
175
176 self.pg_send(self.pg0, tx_pkt * 1)
177
178 rx_pkts = self.pg1.get_capture(1)
179 rx_pkt = rx_pkts[0]
180
181 self.v6_address_check(rx_pkt)
182 self.v6_port_check(rx_pkt, UDP)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200183 self.assertEqual(rx_pkt[IPv6].tc, 0) # IPv4 ToS passed to v6 TC
Jon Loeliger47c99502020-01-30 10:54:58 -0600184 self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="UDP").nh)
185
186 #
187 # Normal translation of TCP packets v4 -> v6 direction.
188 # Send 128 frame size packet for IPv4/TCP.
189 # Received packet should be translated into IPv6 packet with no
190 # fragment header.
191 #
192
193 def test_map_t_tcp_ip4_to_ip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200194 """MAP-T TCP IPv4 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600195
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200196 eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
197 ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address, tos=0)
198 tcp = TCP(
199 sport=self.ipv4_udp_or_tcp_internet_port,
200 dport=self.ipv4_udp_or_tcp_map_port,
201 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600202 payload = "a" * 82
203 tx_pkt = eth / ip / tcp / payload
204
205 self.pg_send(self.pg0, tx_pkt * 1)
206
207 rx_pkts = self.pg1.get_capture(1)
208 rx_pkt = rx_pkts[0]
209
210 self.v6_address_check(rx_pkt)
211 self.v6_port_check(rx_pkt, TCP)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200212 self.assertEqual(rx_pkt[IPv6].tc, 0) # IPv4 ToS passed to v6 TC
Jon Loeliger47c99502020-01-30 10:54:58 -0600213 self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="TCP").nh)
214
215 #
216 # Normal translation of UDP packets v6 -> v4 direction
217 # Send 128 frame size packet for IPv6/UDP.
218 # Received packet should be translated into an IPv4 packet with DF=1.
219 #
220
221 def test_map_t_udp_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200222 """MAP-T UDP IPv6 -> IPv4"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600223
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200224 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
225 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
226 udp = UDP(
227 sport=self.ipv6_udp_or_tcp_map_port,
228 dport=self.ipv6_udp_or_tcp_internet_port,
229 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600230 payload = "a" * 82
231 tx_pkt = eth / ip / udp / payload
232
233 self.pg_send(self.pg1, tx_pkt * 1)
234
235 rx_pkts = self.pg0.get_capture(1)
236 rx_pkt = rx_pkts[0]
237
238 self.v4_address_check(rx_pkt)
239 self.v4_port_check(rx_pkt, UDP)
240 self.assertEqual(rx_pkt[IP].proto, IP(proto="udp").proto)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200241 self.assertEqual(rx_pkt[IP].tos, 0) # IPv6 TC passed to v4 ToS
Jon Loeliger47c99502020-01-30 10:54:58 -0600242 df_bit = IP(flags="DF").flags
243 self.assertNotEqual(rx_pkt[IP].flags & df_bit, df_bit)
244
245 #
246 # Normal translation of TCP packets v6 -> v4 direction
247 # Send 128 frame size packet for IPv6/TCP.
248 # Received packet should be translated into an IPv4 packet with DF=1
249 #
250
251 def test_map_t_tcp_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200252 """MAP-T TCP IPv6 -> IPv4"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600253
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200254 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
255 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
256 tcp = TCP(
257 sport=self.ipv6_udp_or_tcp_map_port,
258 dport=self.ipv6_udp_or_tcp_internet_port,
259 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600260 payload = "a" * 82
261 tx_pkt = eth / ip / tcp / payload
262
263 self.pg_send(self.pg1, tx_pkt * 1)
264
265 rx_pkts = self.pg0.get_capture(1)
266 rx_pkt = rx_pkts[0]
267
268 self.v4_address_check(rx_pkt)
269 self.v4_port_check(rx_pkt, TCP)
270 self.assertEqual(rx_pkt[IP].proto, IP(proto="tcp").proto)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200271 self.assertEqual(rx_pkt[IP].tos, 0) # IPv6 TC passed to v4 ToS
Jon Loeliger47c99502020-01-30 10:54:58 -0600272 df_bit = IP(flags="DF").flags
273 self.assertNotEqual(rx_pkt[IP].flags & df_bit, df_bit)
274
275 #
276 # Translation of ICMP Echo Request v4 -> v6 direction
277 # Received packet should be translated into an IPv6 Echo Request.
278 #
279
280 def test_map_t_echo_request_ip4_to_ip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200281 """MAP-T echo request IPv4 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600282
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200283 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
284 ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address)
285 icmp = ICMP(type="echo-request", id=self.ipv6_udp_or_tcp_map_port)
Jon Loeliger47c99502020-01-30 10:54:58 -0600286 payload = "H" * 10
287 tx_pkt = eth / ip / icmp / payload
288
289 self.pg_send(self.pg0, tx_pkt * 1)
290
291 rx_pkts = self.pg1.get_capture(1)
292 rx_pkt = rx_pkts[0]
293
294 self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="ICMPv6").nh)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200295 self.assertEqual(
296 rx_pkt[ICMPv6EchoRequest].type, ICMPv6EchoRequest(type="Echo Request").type
297 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600298 self.assertEqual(rx_pkt[ICMPv6EchoRequest].code, 0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200299 self.assertEqual(rx_pkt[ICMPv6EchoRequest].id, self.ipv6_udp_or_tcp_map_port)
Jon Loeliger47c99502020-01-30 10:54:58 -0600300
301 #
302 # Translation of ICMP Echo Reply v4 -> v6 direction
303 # Received packet should be translated into an IPv6 Echo Reply.
304 #
305
306 def test_map_t_echo_reply_ip4_to_ip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200307 """MAP-T echo reply IPv4 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600308
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200309 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
310 ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address)
311 icmp = ICMP(type="echo-reply", id=self.ipv6_udp_or_tcp_map_port)
Jon Loeliger47c99502020-01-30 10:54:58 -0600312 payload = "H" * 10
313 tx_pkt = eth / ip / icmp / payload
314
315 self.pg_send(self.pg0, tx_pkt * 1)
316
317 rx_pkts = self.pg1.get_capture(1)
318 rx_pkt = rx_pkts[0]
319
320 self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="ICMPv6").nh)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200321 self.assertEqual(
322 rx_pkt[ICMPv6EchoReply].type, ICMPv6EchoReply(type="Echo Reply").type
323 )
Jon Loeliger47c99502020-01-30 10:54:58 -0600324 self.assertEqual(rx_pkt[ICMPv6EchoReply].code, 0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200325 self.assertEqual(rx_pkt[ICMPv6EchoReply].id, self.ipv6_udp_or_tcp_map_port)
Jon Loeliger47c99502020-01-30 10:54:58 -0600326
327 #
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400328 # Translation of ICMP Time Exceeded v4 -> v6 direction
329 # Received packet should be translated into an IPv6 Time Exceeded.
330 #
331
332 def test_map_t_time_exceeded_ip4_to_ip6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200333 """MAP-T time exceeded IPv4 -> IPv6"""
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400334
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200335 eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
336 ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address)
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400337 icmp = ICMP(type="time-exceeded", code="ttl-zero-during-transit")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200338 ip_inner = IP(dst=self.pg0.remote_ip4, src=self.ipv4_map_address, ttl=1)
339 udp_inner = UDP(
340 sport=self.ipv4_udp_or_tcp_map_port,
341 dport=self.ipv4_udp_or_tcp_internet_port,
342 )
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400343 payload = "H" * 10
344 tx_pkt = eth / ip / icmp / ip_inner / udp_inner / payload
345
346 self.pg_send(self.pg0, tx_pkt * 1)
347
348 rx_pkts = self.pg1.get_capture(1)
349 rx_pkt = rx_pkts[0]
350
351 self.v6_address_check(rx_pkt)
352 self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="ICMPv6").nh)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200353 self.assertEqual(rx_pkt[ICMPv6TimeExceeded].type, ICMPv6TimeExceeded().type)
354 self.assertEqual(
355 rx_pkt[ICMPv6TimeExceeded].code,
356 ICMPv6TimeExceeded(code="hop limit exceeded in transit").code,
357 )
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400358 self.assertEqual(rx_pkt[ICMPv6TimeExceeded].hlim, tx_pkt[IP][1].ttl)
359 self.assertTrue(rx_pkt.haslayer(IPerror6))
360 self.assertTrue(rx_pkt.haslayer(UDPerror))
361 self.assertEqual(rx_pkt[IPv6].src, rx_pkt[IPerror6].dst)
362 self.assertEqual(rx_pkt[IPv6].dst, rx_pkt[IPerror6].src)
363 self.assertEqual(rx_pkt[UDPerror].sport, self.ipv6_udp_or_tcp_map_port)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200364 self.assertEqual(rx_pkt[UDPerror].dport, self.ipv6_udp_or_tcp_internet_port)
Alexander Chernavincd5a4a02020-03-12 08:42:12 -0400365
366 #
Jon Loeliger47c99502020-01-30 10:54:58 -0600367 # Translation of ICMP Echo Request v6 -> v4 direction
368 # Received packet should be translated into an IPv4 Echo Request.
369 #
370
371 def test_map_t_echo_request_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200372 """MAP-T echo request IPv6 -> IPv4"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600373
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200374 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
375 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
Jon Loeliger47c99502020-01-30 10:54:58 -0600376 icmp = ICMPv6EchoRequest()
377 icmp.id = self.ipv6_udp_or_tcp_map_port
378 payload = "H" * 10
379 tx_pkt = eth / ip / icmp / payload
380
381 self.pg_send(self.pg1, tx_pkt * 1)
382
383 rx_pkts = self.pg0.get_capture(1)
384 rx_pkt = rx_pkts[0]
385
386 self.assertEqual(rx_pkt[IP].proto, IP(proto="icmp").proto)
387 self.assertEqual(rx_pkt[ICMP].type, ICMP(type="echo-request").type)
388 self.assertEqual(rx_pkt[ICMP].code, 0)
389 self.assertEqual(rx_pkt[ICMP].id, self.ipv6_udp_or_tcp_map_port)
390
391 #
392 # Translation of ICMP Echo Reply v6 -> v4 direction
393 # Received packet should be translated into an IPv4 Echo Reply.
394 #
395
396 def test_map_t_echo_reply_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200397 """MAP-T echo reply IPv6 -> IPv4"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600398
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200399 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
400 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
Jon Loeliger47c99502020-01-30 10:54:58 -0600401 icmp = ICMPv6EchoReply(id=self.ipv6_udp_or_tcp_map_port)
402 payload = "H" * 10
403 tx_pkt = eth / ip / icmp / payload
404
405 self.pg_send(self.pg1, tx_pkt * 1)
406
407 rx_pkts = self.pg0.get_capture(1)
408 rx_pkt = rx_pkts[0]
409
410 self.assertEqual(rx_pkt[IP].proto, IP(proto="icmp").proto)
411 self.assertEqual(rx_pkt[ICMP].type, ICMP(type="echo-reply").type)
412 self.assertEqual(rx_pkt[ICMP].code, 0)
413 self.assertEqual(rx_pkt[ICMP].id, self.ipv6_udp_or_tcp_map_port)
414
Jon Loeliger65866f02020-01-28 07:30:28 -0600415 #
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500416 # Translation of ICMP Packet Too Big v6 -> v4 direction
417 # Received packet should be translated into an IPv4 Dest Unreachable.
418 #
419
420 def test_map_t_packet_too_big_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200421 """MAP-T packet too big IPv6 -> IPv4"""
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500422
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200423 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
424 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500425 icmp = ICMPv6PacketTooBig(mtu=1280)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200426 ip_inner = IPv6(src=self.ipv6_map_address, dst=self.ipv6_cpe_address)
427 udp_inner = UDP(
428 sport=self.ipv6_udp_or_tcp_internet_port,
429 dport=self.ipv6_udp_or_tcp_map_port,
430 )
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500431 payload = "H" * 10
432 tx_pkt = eth / ip / icmp / ip_inner / udp_inner / payload
433
434 self.pg_send(self.pg1, tx_pkt * 1)
435
436 rx_pkts = self.pg0.get_capture(1)
437 rx_pkt = rx_pkts[0]
438
439 self.v4_address_check(rx_pkt)
440 self.assertEqual(rx_pkt[IP].proto, IP(proto="icmp").proto)
441 self.assertEqual(rx_pkt[ICMP].type, ICMP(type="dest-unreach").type)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200442 self.assertEqual(rx_pkt[ICMP].code, ICMP(code="fragmentation-needed").code)
443 self.assertEqual(rx_pkt[ICMP].nexthopmtu, tx_pkt[ICMPv6PacketTooBig].mtu - 20)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500444 self.assertTrue(rx_pkt.haslayer(IPerror))
445 self.assertTrue(rx_pkt.haslayer(UDPerror))
446 self.assertEqual(rx_pkt[IP].src, rx_pkt[IPerror].dst)
447 self.assertEqual(rx_pkt[IP].dst, rx_pkt[IPerror].src)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200448 self.assertEqual(rx_pkt[UDPerror].sport, self.ipv4_udp_or_tcp_internet_port)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500449 self.assertEqual(rx_pkt[UDPerror].dport, self.ipv4_udp_or_tcp_map_port)
450
451 #
452 # Translation of ICMP Time Exceeded v6 -> v4 direction
453 # Received packet should be translated into an IPv4 Time Exceeded.
454 #
455
456 def test_map_t_time_exceeded_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200457 """MAP-T time exceeded IPv6 -> IPv4"""
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500458
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200459 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
460 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500461 icmp = ICMPv6TimeExceeded()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200462 ip_inner = IPv6(src=self.ipv6_map_address, dst=self.ipv6_cpe_address, hlim=1)
463 udp_inner = UDP(
464 sport=self.ipv6_udp_or_tcp_internet_port,
465 dport=self.ipv6_udp_or_tcp_map_port,
466 )
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500467 payload = "H" * 10
468 tx_pkt = eth / ip / icmp / ip_inner / udp_inner / payload
469
470 self.pg_send(self.pg1, tx_pkt * 1)
471
472 rx_pkts = self.pg0.get_capture(1)
473 rx_pkt = rx_pkts[0]
474
475 self.v4_address_check(rx_pkt)
476 self.assertEqual(rx_pkt[IP].proto, IP(proto="icmp").proto)
477 self.assertEqual(rx_pkt[ICMP].type, ICMP(type="time-exceeded").type)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200478 self.assertEqual(rx_pkt[ICMP].code, ICMP(code="ttl-zero-during-transit").code)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500479 self.assertEqual(rx_pkt[ICMP].ttl, tx_pkt[IPv6][1].hlim)
480 self.assertTrue(rx_pkt.haslayer(IPerror))
481 self.assertTrue(rx_pkt.haslayer(UDPerror))
482 self.assertEqual(rx_pkt[IP].src, rx_pkt[IPerror].dst)
483 self.assertEqual(rx_pkt[IP].dst, rx_pkt[IPerror].src)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200484 self.assertEqual(rx_pkt[UDPerror].sport, self.ipv4_udp_or_tcp_internet_port)
Alexander Chernavin46d0ff32020-03-06 06:11:07 -0500485 self.assertEqual(rx_pkt[UDPerror].dport, self.ipv4_udp_or_tcp_map_port)
486
487 #
Jon Loeliger65866f02020-01-28 07:30:28 -0600488 # Spoofed IPv4 Source Address v6 -> v4 direction
489 # Send a packet with a wrong IPv4 address embedded in bits 72-103.
490 # The BR should either drop the packet, or rewrite the spoofed
491 # source IPv4 as the actual source IPv4 address.
492 # The BR really should drop the packet.
493 #
494
495 def test_map_t_spoof_ipv4_src_addr_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200496 """MAP-T spoof ipv4 src addr IPv6 -> IPv4"""
Jon Loeliger65866f02020-01-28 07:30:28 -0600497
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200498 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
499 ip = IPv6(src=self.ipv6_spoof_address, dst=self.ipv6_map_address)
500 udp = UDP(
501 sport=self.ipv6_udp_or_tcp_map_port,
502 dport=self.ipv6_udp_or_tcp_internet_port,
503 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600504 payload = "a" * 82
505 tx_pkt = eth / ip / udp / payload
506
507 self.pg_send(self.pg1, tx_pkt * 1)
508
509 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200510 self.pg0.assert_nothing_captured(remark="Should drop IPv4 spoof address")
Jon Loeliger65866f02020-01-28 07:30:28 -0600511
512 #
513 # Spoofed IPv4 Source Prefix v6 -> v4 direction
514 # Send a packet with a wrong IPv4 prefix embedded in bits 72-103.
515 # The BR should either drop the packet, or rewrite the source IPv4
516 # to the prefix that matches the source IPv4 address.
517 #
518
519 def test_map_t_spoof_ipv4_src_prefix_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200520 """MAP-T spoof ipv4 src prefix IPv6 -> IPv4"""
Jon Loeliger65866f02020-01-28 07:30:28 -0600521
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200522 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
523 ip = IPv6(src=self.ipv6_spoof_prefix, dst=self.ipv6_map_address)
524 udp = UDP(
525 sport=self.ipv6_udp_or_tcp_map_port,
526 dport=self.ipv6_udp_or_tcp_internet_port,
527 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600528 payload = "a" * 82
529 tx_pkt = eth / ip / udp / payload
530
531 self.pg_send(self.pg1, tx_pkt * 1)
532
533 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200534 self.pg0.assert_nothing_captured(remark="Should drop IPv4 spoof prefix")
Jon Loeliger65866f02020-01-28 07:30:28 -0600535
536 #
537 # Spoofed IPv6 PSID v6 -> v4 direction
538 # Send a packet with a wrong IPv6 port PSID
539 # The BR should drop the packet.
540 #
541
542 def test_map_t_spoof_psid_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200543 """MAP-T spoof psid IPv6 -> IPv4"""
Jon Loeliger65866f02020-01-28 07:30:28 -0600544
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200545 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
546 ip = IPv6(src=self.ipv6_spoof_psid, dst=self.ipv6_map_address)
547 udp = UDP(
548 sport=self.ipv6_udp_or_tcp_map_port,
549 dport=self.ipv6_udp_or_tcp_internet_port,
550 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600551 payload = "a" * 82
552 tx_pkt = eth / ip / udp / payload
553
554 self.pg_send(self.pg1, tx_pkt * 1)
555
556 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200557 self.pg0.assert_nothing_captured(remark="Should drop IPv6 spoof PSID")
Jon Loeliger65866f02020-01-28 07:30:28 -0600558
559 #
560 # Spoofed IPv6 subnet field v6 -> v4 direction
561 # Send a packet with a wrong IPv6 subnet as "2001:db8:f1"
562 # The BR should drop the packet.
563 #
564
565 def test_map_t_spoof_subnet_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200566 """MAP-T spoof subnet IPv6 -> IPv4"""
Jon Loeliger65866f02020-01-28 07:30:28 -0600567
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200568 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
569 ip = IPv6(src=self.ipv6_spoof_subnet, dst=self.ipv6_map_address)
570 udp = UDP(
571 sport=self.ipv6_udp_or_tcp_map_port,
572 dport=self.ipv6_udp_or_tcp_internet_port,
573 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600574 payload = "a" * 82
575 tx_pkt = eth / ip / udp / payload
576
577 self.pg_send(self.pg1, tx_pkt * 1)
578
579 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200580 self.pg0.assert_nothing_captured(remark="Should drop IPv6 spoof subnet")
Jon Loeliger65866f02020-01-28 07:30:28 -0600581
582 #
583 # Spoofed IPv6 port PSID v6 -> v4 direction
584 # Send a packet with a wrong IPv6 port PSID
585 # The BR should drop the packet.
586 #
587
588 def test_map_t_spoof_port_psid_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200589 """MAP-T spoof port psid IPv6 -> IPv4"""
Jon Loeliger65866f02020-01-28 07:30:28 -0600590
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200591 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
592 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
593 udp = UDP(
594 sport=self.ipv6_udp_or_tcp_spoof_port,
595 dport=self.ipv6_udp_or_tcp_internet_port,
596 )
Jon Loeliger65866f02020-01-28 07:30:28 -0600597 payload = "a" * 82
598 tx_pkt = eth / ip / udp / payload
599
600 self.pg_send(self.pg1, tx_pkt * 1)
601
602 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200603 self.pg0.assert_nothing_captured(remark="Should drop IPv6 spoof port PSID")
Jon Loeliger65866f02020-01-28 07:30:28 -0600604
Jon Loeliger47c99502020-01-30 10:54:58 -0600605 #
Vladimir Isaev92511312020-02-26 14:41:46 +0300606 # Spoofed IPv6 ICMP ID PSID v6 -> v4 direction
607 # Send a packet with a wrong IPv6 IMCP ID PSID
608 # The BR should drop the packet.
609 #
610
611 def test_map_t_spoof_icmp_id_psid_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200612 """MAP-T spoof ICMP id psid IPv6 -> IPv4"""
Vladimir Isaev92511312020-02-26 14:41:46 +0300613
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200614 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
615 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address)
Vladimir Isaev92511312020-02-26 14:41:46 +0300616 icmp = ICMPv6EchoRequest()
617 icmp.id = self.ipv6_udp_or_tcp_spoof_port
618 payload = "H" * 10
619 tx_pkt = eth / ip / icmp / payload
620
621 self.pg_send(self.pg1, tx_pkt * 1)
622
623 self.pg0.get_capture(0, timeout=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200624 self.pg0.assert_nothing_captured(remark="Should drop IPv6 spoof port PSID")
Vladimir Isaev92511312020-02-26 14:41:46 +0300625
626 #
Jon Loeliger47c99502020-01-30 10:54:58 -0600627 # Map to Map - same rule, different address
628 #
629
630 @unittest.skip("Fixme: correct behavior needs clarification")
631 def test_map_t_same_rule_diff_addr_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200632 """MAP-T same rule, diff addr IPv6 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600633
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200634 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
635 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_same_rule_diff_addr)
636 udp = UDP(sport=self.ipv6_udp_or_tcp_map_port, dport=1025)
Jon Loeliger47c99502020-01-30 10:54:58 -0600637 payload = "a" * 82
638 tx_pkt = eth / ip / udp / payload
639
640 self.pg_send(self.pg1, tx_pkt * 1)
641
642 rx_pkts = self.pg1.get_capture(1)
643 rx_pkt = rx_pkts[0]
644
645 #
646 # Map to Map - same rule, same address
647 #
648
649 @unittest.skip("Fixme: correct behavior needs clarification")
650 def test_map_t_same_rule_same_addr_ip6_to_ip4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200651 """MAP-T same rule, same addr IPv6 -> IPv6"""
Jon Loeliger47c99502020-01-30 10:54:58 -0600652
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200653 eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
654 ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_same_rule_same_addr)
655 udp = UDP(sport=self.ipv6_udp_or_tcp_map_port, dport=1025)
Jon Loeliger47c99502020-01-30 10:54:58 -0600656 payload = "a" * 82
657 tx_pkt = eth / ip / udp / payload
658
659 self.pg_send(self.pg1, tx_pkt * 1)
660
661 rx_pkts = self.pg1.get_capture(1)
662 rx_pkt = rx_pkts[0]
663
Klement Sekera16ce09d2022-04-23 11:34:29 +0200664
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200665if __name__ == "__main__":
Jon Loeliger65866f02020-01-28 07:30:28 -0600666 unittest.main(testRunner=VppTestRunner)