blob: f3bec78ec5ada88a670b30d8af97bcb8c18a85fc [file] [log] [blame]
Ole Troan96068d62020-07-01 13:16:16 +02001#!/usr/bin/env python3
2
3import ipaddress
4import random
5import socket
6import struct
7import unittest
8from io import BytesIO
Ole Troan96068d62020-07-01 13:16:16 +02009
10import scapy.compat
Klement Sekerab23ffd72021-05-31 16:08:53 +020011from framework import VppTestCase, VppTestRunner
Ole Troan96068d62020-07-01 13:16:16 +020012from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020013from scapy.all import (
14 bind_layers,
15 Packet,
16 ByteEnumField,
17 ShortField,
18 IPField,
19 IntField,
20 LongField,
21 XByteField,
22 FlagsField,
23 FieldLenField,
24 PacketListField,
25)
Ole Troan96068d62020-07-01 13:16:16 +020026from scapy.data import IP_PROTOS
27from scapy.layers.inet import IP, TCP, UDP, ICMP
28from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
29from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020030from scapy.layers.inet6 import (
31 IPv6,
32 ICMPv6EchoRequest,
33 ICMPv6EchoReply,
34 ICMPv6ND_NS,
35 ICMPv6ND_NA,
36 ICMPv6NDOptDstLLAddr,
37 fragment6,
38)
Ole Troan96068d62020-07-01 13:16:16 +020039from scapy.layers.l2 import Ether, ARP, GRE
40from scapy.packet import Raw
41from syslog_rfc5424_parser import SyslogMessage, ParseError
42from syslog_rfc5424_parser.constants import SyslogSeverity
43from util import ip4_range
44from util import ppc, ppp
45from vpp_acl import AclRule, VppAcl, VppAclInterface
46from vpp_ip_route import VppIpRoute, VppRoutePath
47from vpp_neighbor import VppNeighbor
48from vpp_papi import VppEnum
49
50
Filip Vargaed2ee5e2021-03-23 12:57:58 +010051class TestNAT66(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020052 """NAT66 Test Cases"""
Ole Troan96068d62020-07-01 13:16:16 +020053
54 @classmethod
55 def setUpClass(cls):
56 super(TestNAT66, cls).setUpClass()
57
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020058 cls.nat_addr = "fd01:ff::2"
Ole Troan96068d62020-07-01 13:16:16 +020059 cls.create_pg_interfaces(range(2))
60 cls.interfaces = list(cls.pg_interfaces)
61
62 for i in cls.interfaces:
63 i.admin_up()
64 i.config_ip6()
65 i.configure_ipv6_neighbors()
66
Filip Vargaed2ee5e2021-03-23 12:57:58 +010067 @property
68 def config_flags(self):
69 return VppEnum.vl_api_nat_config_flags_t
70
71 def plugin_enable(self):
72 self.vapi.nat66_plugin_enable_disable(enable=1)
73
74 def plugin_disable(self):
75 self.vapi.nat66_plugin_enable_disable(enable=0)
76
77 def setUp(self):
78 super(TestNAT66, self).setUp()
79 self.plugin_enable()
80
81 def tearDown(self):
82 super(TestNAT66, self).tearDown()
83 if not self.vpp_dead:
84 self.plugin_disable()
Ole Troan96068d62020-07-01 13:16:16 +020085
86 def test_static(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020087 """1:1 NAT66 test"""
Ole Troan96068d62020-07-01 13:16:16 +020088 flags = self.config_flags.NAT_IS_INSIDE
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020089 self.vapi.nat66_add_del_interface(
90 is_add=1, flags=flags, sw_if_index=self.pg0.sw_if_index
91 )
92 self.vapi.nat66_add_del_interface(is_add=1, sw_if_index=self.pg1.sw_if_index)
Ole Troan96068d62020-07-01 13:16:16 +020093 self.vapi.nat66_add_del_static_mapping(
94 local_ip_address=self.pg0.remote_ip6,
95 external_ip_address=self.nat_addr,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020096 is_add=1,
97 )
Ole Troan96068d62020-07-01 13:16:16 +020098
99 # in2out
100 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200101 p = (
102 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
103 / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6)
104 / TCP()
105 )
Ole Troan96068d62020-07-01 13:16:16 +0200106 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200107 p = (
108 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
109 / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6)
110 / UDP()
111 )
Ole Troan96068d62020-07-01 13:16:16 +0200112 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200113 p = (
114 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
115 / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6)
116 / ICMPv6EchoRequest()
117 )
Ole Troan96068d62020-07-01 13:16:16 +0200118 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200119 p = (
120 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
121 / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6)
122 / GRE()
123 / IP()
124 / TCP()
125 )
Ole Troan96068d62020-07-01 13:16:16 +0200126 pkts.append(p)
127 self.pg0.add_stream(pkts)
128 self.pg_enable_capture(self.pg_interfaces)
129 self.pg_start()
130 capture = self.pg1.get_capture(len(pkts))
131
132 for packet in capture:
133 try:
134 self.assertEqual(packet[IPv6].src, self.nat_addr)
135 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
136 self.assert_packet_checksums_valid(packet)
137 except:
138 self.logger.error(ppp("Unexpected or invalid packet:", packet))
139 raise
140
141 # out2in
142 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200143 p = (
144 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
145 / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr)
146 / TCP()
147 )
Ole Troan96068d62020-07-01 13:16:16 +0200148 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200149 p = (
150 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
151 / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr)
152 / UDP()
153 )
Ole Troan96068d62020-07-01 13:16:16 +0200154 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200155 p = (
156 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
157 / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr)
158 / ICMPv6EchoReply()
159 )
Ole Troan96068d62020-07-01 13:16:16 +0200160 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200161 p = (
162 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
163 / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr)
164 / GRE()
165 / IP()
166 / TCP()
167 )
Ole Troan96068d62020-07-01 13:16:16 +0200168 pkts.append(p)
169 self.pg1.add_stream(pkts)
170 self.pg_enable_capture(self.pg_interfaces)
171 self.pg_start()
172 capture = self.pg0.get_capture(len(pkts))
173 for packet in capture:
174 try:
175 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
176 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
177 self.assert_packet_checksums_valid(packet)
178 except:
179 self.logger.error(ppp("Unexpected or invalid packet:", packet))
180 raise
181
182 sm = self.vapi.nat66_static_mapping_dump()
183 self.assertEqual(len(sm), 1)
184 self.assertEqual(sm[0].total_pkts, 8)
185
186 def test_check_no_translate(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200187 """NAT66 translate only when egress interface is outside interface"""
Ole Troan96068d62020-07-01 13:16:16 +0200188 flags = self.config_flags.NAT_IS_INSIDE
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200189 self.vapi.nat66_add_del_interface(
190 is_add=1, flags=flags, sw_if_index=self.pg0.sw_if_index
191 )
192 self.vapi.nat66_add_del_interface(
193 is_add=1, flags=flags, sw_if_index=self.pg1.sw_if_index
194 )
Ole Troan96068d62020-07-01 13:16:16 +0200195 self.vapi.nat66_add_del_static_mapping(
196 local_ip_address=self.pg0.remote_ip6,
197 external_ip_address=self.nat_addr,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200198 is_add=1,
199 )
Ole Troan96068d62020-07-01 13:16:16 +0200200
201 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200202 p = (
203 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
204 / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6)
205 / UDP()
206 )
Ole Troan96068d62020-07-01 13:16:16 +0200207 self.pg0.add_stream([p])
208 self.pg_enable_capture(self.pg_interfaces)
209 self.pg_start()
210 capture = self.pg1.get_capture(1)
211 packet = capture[0]
212 try:
213 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
214 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
215 except:
216 self.logger.error(ppp("Unexpected or invalid packet:", packet))
217 raise
218
Ole Troan96068d62020-07-01 13:16:16 +0200219
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200220if __name__ == "__main__":
Ole Troan96068d62020-07-01 13:16:16 +0200221 unittest.main(testRunner=VppTestRunner)