blob: ba1c2465f124ff9e2999bcb5d87be053f9cb05bb [file] [log] [blame]
Klement Sekera31da2e32018-06-24 22:49:55 +02001import unittest
Klement Sekera611864f2018-09-26 11:19:00 +02002import socket
Neale Ranns80f6fd52019-04-16 02:41:34 +00003import struct
Klement Sekera31da2e32018-06-24 22:49:55 +02004
Neale Ranns53f526b2019-02-25 14:32:02 +00005from scapy.layers.inet import IP, ICMP, TCP, UDP
Damjan Mariona829b132019-04-24 23:39:16 +02006from scapy.layers.ipsec import SecurityAssociation, ESP
snaramre5d4b8912019-12-13 23:39:35 +00007from scapy.layers.l2 import Ether
Paul Vinciguerra582eac52020-04-03 12:18:40 -04008from scapy.packet import raw, Raw
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02009from scapy.layers.inet6 import (
10 IPv6,
11 ICMPv6EchoRequest,
12 IPv6ExtHdrHopByHop,
13 IPv6ExtHdrFragment,
14 IPv6ExtHdrDestOpt,
15)
Neale Ranns02950402019-12-20 00:54:57 +000016
Klement Sekera31da2e32018-06-24 22:49:55 +020017
18from framework import VppTestCase, VppTestRunner
Neale Ranns14046982019-07-29 14:49:52 +000019from util import ppp, reassemble4, fragment_rfc791, fragment_rfc8200
Neale Ranns17dcec02019-01-09 21:22:20 -080020from vpp_papi import VppEnum
Klement Sekera31da2e32018-06-24 22:49:55 +020021
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020022from vpp_ipsec import VppIpsecSpd, VppIpsecSpdEntry, VppIpsecSpdItfBinding
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +000023from ipaddress import ip_address
24from re import search
25from os import popen
26
Klement Sekera31da2e32018-06-24 22:49:55 +020027
Paul Vinciguerrae061dad2020-12-04 14:57:51 -050028class IPsecIPv4Params:
Neale Ranns17dcec02019-01-09 21:22:20 -080029
Klement Sekera611864f2018-09-26 11:19:00 +020030 addr_type = socket.AF_INET
31 addr_any = "0.0.0.0"
32 addr_bcast = "255.255.255.255"
33 addr_len = 32
34 is_ipv6 = 0
Klement Sekera611864f2018-09-26 11:19:00 +020035
Neale Ranns17dcec02019-01-09 21:22:20 -080036 def __init__(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020037 self.remote_tun_if_host = "1.1.1.1"
38 self.remote_tun_if_host6 = "1111::1"
Klement Sekera611864f2018-09-26 11:19:00 +020039
Neale Ranns28287212019-12-16 00:53:11 +000040 self.scapy_tun_sa_id = 100
Neale Rannsa9e27742020-12-23 16:22:28 +000041 self.scapy_tun_spi = 1000
Neale Ranns28287212019-12-16 00:53:11 +000042 self.vpp_tun_sa_id = 200
Neale Rannsa9e27742020-12-23 16:22:28 +000043 self.vpp_tun_spi = 2000
Klement Sekera611864f2018-09-26 11:19:00 +020044
Neale Ranns28287212019-12-16 00:53:11 +000045 self.scapy_tra_sa_id = 300
Neale Rannsa9e27742020-12-23 16:22:28 +000046 self.scapy_tra_spi = 3000
Neale Ranns28287212019-12-16 00:53:11 +000047 self.vpp_tra_sa_id = 400
Neale Rannsa9e27742020-12-23 16:22:28 +000048 self.vpp_tra_spi = 4000
Klement Sekera611864f2018-09-26 11:19:00 +020049
Neale Ranns9ec846c2021-02-09 14:04:02 +000050 self.outer_hop_limit = 64
51 self.inner_hop_limit = 255
52 self.outer_flow_label = 0
53 self.inner_flow_label = 0x12345
54
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020055 self.auth_algo_vpp_id = (
56 VppEnum.vl_api_ipsec_integ_alg_t.IPSEC_API_INTEG_ALG_SHA1_96
57 )
58 self.auth_algo = "HMAC-SHA1-96" # scapy name
59 self.auth_key = b"C91KUR9GYMm5GfkEvNjX"
Neale Ranns17dcec02019-01-09 21:22:20 -080060
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020061 self.crypt_algo_vpp_id = (
62 VppEnum.vl_api_ipsec_crypto_alg_t.IPSEC_API_CRYPTO_ALG_AES_CBC_128
63 )
64 self.crypt_algo = "AES-CBC" # scapy name
65 self.crypt_key = b"JPjyOWBeVEQiMe7h"
Neale Ranns80f6fd52019-04-16 02:41:34 +000066 self.salt = 0
Neale Ranns53f526b2019-02-25 14:32:02 +000067 self.flags = 0
68 self.nat_header = None
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020069 self.tun_flags = (
70 VppEnum.vl_api_tunnel_encap_decap_flags_t.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
71 )
Neale Ranns041add72020-01-02 04:06:10 +000072 self.dscp = 0
Neale Ranns8c609af2021-02-25 10:05:32 +000073 self.async_mode = False
Klement Sekera611864f2018-09-26 11:19:00 +020074
75
Paul Vinciguerrae061dad2020-12-04 14:57:51 -050076class IPsecIPv6Params:
Neale Ranns17dcec02019-01-09 21:22:20 -080077
Klement Sekera611864f2018-09-26 11:19:00 +020078 addr_type = socket.AF_INET6
79 addr_any = "0::0"
80 addr_bcast = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
81 addr_len = 128
82 is_ipv6 = 1
Klement Sekera611864f2018-09-26 11:19:00 +020083
Neale Ranns17dcec02019-01-09 21:22:20 -080084 def __init__(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020085 self.remote_tun_if_host = "1111:1111:1111:1111:1111:1111:1111:1111"
86 self.remote_tun_if_host4 = "1.1.1.1"
Klement Sekera611864f2018-09-26 11:19:00 +020087
Neale Ranns28287212019-12-16 00:53:11 +000088 self.scapy_tun_sa_id = 500
Neale Ranns17dcec02019-01-09 21:22:20 -080089 self.scapy_tun_spi = 3001
Neale Ranns28287212019-12-16 00:53:11 +000090 self.vpp_tun_sa_id = 600
Neale Ranns17dcec02019-01-09 21:22:20 -080091 self.vpp_tun_spi = 3000
Klement Sekera611864f2018-09-26 11:19:00 +020092
Neale Ranns28287212019-12-16 00:53:11 +000093 self.scapy_tra_sa_id = 700
Neale Ranns17dcec02019-01-09 21:22:20 -080094 self.scapy_tra_spi = 4001
Neale Ranns28287212019-12-16 00:53:11 +000095 self.vpp_tra_sa_id = 800
Neale Ranns17dcec02019-01-09 21:22:20 -080096 self.vpp_tra_spi = 4000
Klement Sekera611864f2018-09-26 11:19:00 +020097
Neale Ranns9ec846c2021-02-09 14:04:02 +000098 self.outer_hop_limit = 64
99 self.inner_hop_limit = 255
100 self.outer_flow_label = 0
101 self.inner_flow_label = 0x12345
102
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200103 self.auth_algo_vpp_id = (
104 VppEnum.vl_api_ipsec_integ_alg_t.IPSEC_API_INTEG_ALG_SHA1_96
105 )
106 self.auth_algo = "HMAC-SHA1-96" # scapy name
107 self.auth_key = b"C91KUR9GYMm5GfkEvNjX"
Neale Ranns17dcec02019-01-09 21:22:20 -0800108
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200109 self.crypt_algo_vpp_id = (
110 VppEnum.vl_api_ipsec_crypto_alg_t.IPSEC_API_CRYPTO_ALG_AES_CBC_128
111 )
112 self.crypt_algo = "AES-CBC" # scapy name
113 self.crypt_key = b"JPjyOWBeVEQiMe7h"
Neale Ranns80f6fd52019-04-16 02:41:34 +0000114 self.salt = 0
Neale Ranns53f526b2019-02-25 14:32:02 +0000115 self.flags = 0
116 self.nat_header = None
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200117 self.tun_flags = (
118 VppEnum.vl_api_tunnel_encap_decap_flags_t.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
119 )
Neale Ranns041add72020-01-02 04:06:10 +0000120 self.dscp = 0
Neale Ranns8c609af2021-02-25 10:05:32 +0000121 self.async_mode = False
Klement Sekera611864f2018-09-26 11:19:00 +0200122
123
Neale Ranns12989b52019-09-26 16:20:19 +0000124def mk_scapy_crypt_key(p):
Benoît Ganne490b9272021-01-22 18:03:09 +0100125 if p.crypt_algo in ("AES-GCM", "AES-CTR"):
Neale Ranns6afaae12019-07-17 15:07:14 +0000126 return p.crypt_key + struct.pack("!I", p.salt)
127 else:
128 return p.crypt_key
129
130
Neale Ranns2ac885c2019-03-20 18:24:43 +0000131def config_tun_params(p, encryption_type, tun_if):
132 ip_class_by_addr_type = {socket.AF_INET: IP, socket.AF_INET6: IPv6}
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200133 esn_en = bool(
134 p.flags & (VppEnum.vl_api_ipsec_sad_flags_t.IPSEC_API_SAD_FLAG_USE_ESN)
135 )
Neale Rannsf3a66222020-01-02 05:04:00 +0000136 p.tun_dst = tun_if.remote_addr[p.addr_type]
137 p.tun_src = tun_if.local_addr[p.addr_type]
Neale Ranns12989b52019-09-26 16:20:19 +0000138 crypt_key = mk_scapy_crypt_key(p)
Neale Ranns2ac885c2019-03-20 18:24:43 +0000139 p.scapy_tun_sa = SecurityAssociation(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200140 encryption_type,
Arthur de Kerhor0df06b62022-11-16 18:45:24 +0100141 spi=p.scapy_tun_spi,
Neale Ranns80f6fd52019-04-16 02:41:34 +0000142 crypt_algo=p.crypt_algo,
143 crypt_key=crypt_key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200144 auth_algo=p.auth_algo,
145 auth_key=p.auth_key,
146 tunnel_header=ip_class_by_addr_type[p.addr_type](src=p.tun_dst, dst=p.tun_src),
Neale Ranns3833ffd2019-03-21 14:34:09 +0000147 nat_t_header=p.nat_header,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200148 esn_en=esn_en,
149 )
Neale Ranns2ac885c2019-03-20 18:24:43 +0000150 p.vpp_tun_sa = SecurityAssociation(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200151 encryption_type,
Arthur de Kerhor0df06b62022-11-16 18:45:24 +0100152 spi=p.vpp_tun_spi,
Neale Ranns80f6fd52019-04-16 02:41:34 +0000153 crypt_algo=p.crypt_algo,
154 crypt_key=crypt_key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200155 auth_algo=p.auth_algo,
156 auth_key=p.auth_key,
157 tunnel_header=ip_class_by_addr_type[p.addr_type](dst=p.tun_dst, src=p.tun_src),
Neale Ranns3833ffd2019-03-21 14:34:09 +0000158 nat_t_header=p.nat_header,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200159 esn_en=esn_en,
160 )
Neale Ranns2ac885c2019-03-20 18:24:43 +0000161
162
163def config_tra_params(p, encryption_type):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200164 esn_en = bool(
165 p.flags & (VppEnum.vl_api_ipsec_sad_flags_t.IPSEC_API_SAD_FLAG_USE_ESN)
166 )
Neale Ranns12989b52019-09-26 16:20:19 +0000167 crypt_key = mk_scapy_crypt_key(p)
Neale Ranns2ac885c2019-03-20 18:24:43 +0000168 p.scapy_tra_sa = SecurityAssociation(
169 encryption_type,
Arthur de Kerhor0df06b62022-11-16 18:45:24 +0100170 spi=p.scapy_tra_spi,
Neale Ranns2ac885c2019-03-20 18:24:43 +0000171 crypt_algo=p.crypt_algo,
Neale Ranns80f6fd52019-04-16 02:41:34 +0000172 crypt_key=crypt_key,
Neale Ranns2ac885c2019-03-20 18:24:43 +0000173 auth_algo=p.auth_algo,
174 auth_key=p.auth_key,
Neale Ranns3833ffd2019-03-21 14:34:09 +0000175 nat_t_header=p.nat_header,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200176 esn_en=esn_en,
177 )
Neale Ranns2ac885c2019-03-20 18:24:43 +0000178 p.vpp_tra_sa = SecurityAssociation(
179 encryption_type,
Arthur de Kerhor0df06b62022-11-16 18:45:24 +0100180 spi=p.vpp_tra_spi,
Neale Ranns2ac885c2019-03-20 18:24:43 +0000181 crypt_algo=p.crypt_algo,
Neale Ranns80f6fd52019-04-16 02:41:34 +0000182 crypt_key=crypt_key,
Neale Ranns2ac885c2019-03-20 18:24:43 +0000183 auth_algo=p.auth_algo,
184 auth_key=p.auth_key,
Neale Ranns3833ffd2019-03-21 14:34:09 +0000185 nat_t_header=p.nat_header,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200186 esn_en=esn_en,
187 )
Neale Ranns2ac885c2019-03-20 18:24:43 +0000188
189
Klement Sekera31da2e32018-06-24 22:49:55 +0200190class TemplateIpsec(VppTestCase):
191 """
Dave Wallaced1706812021-08-12 18:36:02 -0400192 TRANSPORT MODE::
Klement Sekera31da2e32018-06-24 22:49:55 +0200193
Dave Wallaced1706812021-08-12 18:36:02 -0400194 ------ encrypt ---
195 |tra_if| <-------> |VPP|
196 ------ decrypt ---
Klement Sekera31da2e32018-06-24 22:49:55 +0200197
Dave Wallaced1706812021-08-12 18:36:02 -0400198 TUNNEL MODE::
Klement Sekera31da2e32018-06-24 22:49:55 +0200199
Dave Wallaced1706812021-08-12 18:36:02 -0400200 ------ encrypt --- plain ---
201 |tun_if| <------- |VPP| <------ |pg1|
202 ------ --- ---
Klement Sekera31da2e32018-06-24 22:49:55 +0200203
Dave Wallaced1706812021-08-12 18:36:02 -0400204 ------ decrypt --- plain ---
205 |tun_if| -------> |VPP| ------> |pg1|
206 ------ --- ---
Klement Sekera31da2e32018-06-24 22:49:55 +0200207 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200208
Neale Ranns4f33c802019-04-10 12:39:10 +0000209 tun_spd_id = 1
210 tra_spd_id = 2
Klement Sekera31da2e32018-06-24 22:49:55 +0200211
Neale Ranns8e4a89b2019-01-23 08:16:17 -0800212 def ipsec_select_backend(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200213 """empty method to be overloaded when necessary"""
Klement Sekerab4d30532018-11-08 13:00:02 +0100214 pass
215
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700216 @classmethod
217 def setUpClass(cls):
218 super(TemplateIpsec, cls).setUpClass()
219
220 @classmethod
221 def tearDownClass(cls):
222 super(TemplateIpsec, cls).tearDownClass()
223
Neale Ranns3833ffd2019-03-21 14:34:09 +0000224 def setup_params(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200225 if not hasattr(self, "ipv4_params"):
Neale Ranns041add72020-01-02 04:06:10 +0000226 self.ipv4_params = IPsecIPv4Params()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200227 if not hasattr(self, "ipv6_params"):
Neale Ranns041add72020-01-02 04:06:10 +0000228 self.ipv6_params = IPsecIPv6Params()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200229 self.params = {
230 self.ipv4_params.addr_type: self.ipv4_params,
231 self.ipv6_params.addr_type: self.ipv6_params,
232 }
Neale Ranns8e4a89b2019-01-23 08:16:17 -0800233
Neale Ranns4f33c802019-04-10 12:39:10 +0000234 def config_interfaces(self):
Neale Ranns8e4a89b2019-01-23 08:16:17 -0800235 self.create_pg_interfaces(range(3))
236 self.interfaces = list(self.pg_interfaces)
237 for i in self.interfaces:
Klement Sekera31da2e32018-06-24 22:49:55 +0200238 i.admin_up()
239 i.config_ip4()
240 i.resolve_arp()
Klement Sekera611864f2018-09-26 11:19:00 +0200241 i.config_ip6()
242 i.resolve_ndp()
Neale Ranns4f33c802019-04-10 12:39:10 +0000243
244 def setUp(self):
245 super(TemplateIpsec, self).setUp()
246
247 self.setup_params()
248
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200249 self.vpp_esp_protocol = VppEnum.vl_api_ipsec_proto_t.IPSEC_API_PROTO_ESP
250 self.vpp_ah_protocol = VppEnum.vl_api_ipsec_proto_t.IPSEC_API_PROTO_AH
Neale Ranns4f33c802019-04-10 12:39:10 +0000251
252 self.config_interfaces()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700253
Neale Ranns8e4a89b2019-01-23 08:16:17 -0800254 self.ipsec_select_backend()
Klement Sekera31da2e32018-06-24 22:49:55 +0200255
Neale Ranns4f33c802019-04-10 12:39:10 +0000256 def unconfig_interfaces(self):
Neale Ranns8e4a89b2019-01-23 08:16:17 -0800257 for i in self.interfaces:
258 i.admin_down()
259 i.unconfig_ip4()
260 i.unconfig_ip6()
261
Neale Ranns4f33c802019-04-10 12:39:10 +0000262 def tearDown(self):
263 super(TemplateIpsec, self).tearDown()
264
265 self.unconfig_interfaces()
266
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700267 def show_commands_at_teardown(self):
268 self.logger.info(self.vapi.cli("show hardware"))
Klement Sekera31da2e32018-06-24 22:49:55 +0200269
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200270 def gen_encrypt_pkts(self, p, sa, sw_intf, src, dst, count=1, payload_size=54):
271 return [
272 Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac)
273 / sa.encrypt(IP(src=src, dst=dst) / ICMP() / Raw(b"X" * payload_size))
274 for i in range(count)
275 ]
Klement Sekera31da2e32018-06-24 22:49:55 +0200276
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200277 def gen_encrypt_pkts6(self, p, sa, sw_intf, src, dst, count=1, payload_size=54):
278 return [
279 Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac)
280 / sa.encrypt(
281 IPv6(src=src, dst=dst, hlim=p.inner_hop_limit, fl=p.inner_flow_label)
282 / ICMPv6EchoRequest(id=0, seq=1, data="X" * payload_size)
283 )
284 for i in range(count)
285 ]
Klement Sekera611864f2018-09-26 11:19:00 +0200286
Neale Rannsd7603d92019-03-28 08:56:10 +0000287 def gen_pkts(self, sw_intf, src, dst, count=1, payload_size=54):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200288 return [
289 Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac)
290 / IP(src=src, dst=dst)
291 / ICMP()
292 / Raw(b"X" * payload_size)
293 for i in range(count)
294 ]
Klement Sekera31da2e32018-06-24 22:49:55 +0200295
Neale Ranns9ec846c2021-02-09 14:04:02 +0000296 def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=54):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200297 return [
298 Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac)
299 / IPv6(src=src, dst=dst, hlim=p.inner_hop_limit, fl=p.inner_flow_label)
300 / ICMPv6EchoRequest(id=0, seq=1, data="X" * payload_size)
301 for i in range(count)
302 ]
Klement Sekera611864f2018-09-26 11:19:00 +0200303
Klement Sekera31da2e32018-06-24 22:49:55 +0200304
Neale Ranns4f33c802019-04-10 12:39:10 +0000305class IpsecTcp(object):
306 def verify_tcp_checksum(self):
Florin Corasa1175b72022-01-26 00:15:03 -0800307 # start http cli server listener on http://0.0.0.0:80
308 self.vapi.cli("http cli server")
Klement Sekera611864f2018-09-26 11:19:00 +0200309 p = self.params[socket.AF_INET]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200310 send = Ether(
311 src=self.tun_if.remote_mac, dst=self.tun_if.local_mac
312 ) / p.scapy_tun_sa.encrypt(
313 IP(src=p.remote_tun_if_host, dst=self.tun_if.local_ip4)
314 / TCP(flags="S", dport=80)
315 )
Klement Sekera31da2e32018-06-24 22:49:55 +0200316 self.logger.debug(ppp("Sending packet:", send))
Klement Sekera611864f2018-09-26 11:19:00 +0200317 recv = self.send_and_expect(self.tun_if, [send], self.tun_if)
Klement Sekera31da2e32018-06-24 22:49:55 +0200318 recv = recv[0]
Neale Ranns2ac885c2019-03-20 18:24:43 +0000319 decrypted = p.vpp_tun_sa.decrypt(recv[IP])
Klement Sekera31da2e32018-06-24 22:49:55 +0200320 self.assert_packet_checksums_valid(decrypted)
321
322
Neale Ranns4f33c802019-04-10 12:39:10 +0000323class IpsecTcpTests(IpsecTcp):
324 def test_tcp_checksum(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200325 """verify checksum correctness for vpp generated packets"""
Neale Ranns4f33c802019-04-10 12:39:10 +0000326 self.verify_tcp_checksum()
327
328
329class IpsecTra4(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200330 """verify methods for Transport v4"""
331
Neale Ranns8c609af2021-02-25 10:05:32 +0000332 def get_replay_counts(self, p):
Neale Ranns93688d72022-08-09 03:34:51 +0000333 replay_node_name = "/err/%s/replay" % self.tra4_decrypt_node_name[0]
Neale Ranns8c609af2021-02-25 10:05:32 +0000334 count = self.statistics.get_err_counter(replay_node_name)
335
336 if p.async_mode:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200337 replay_post_node_name = (
Neale Ranns93688d72022-08-09 03:34:51 +0000338 "/err/%s/replay" % self.tra4_decrypt_node_name[p.async_mode]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200339 )
Neale Ranns8c609af2021-02-25 10:05:32 +0000340 count += self.statistics.get_err_counter(replay_post_node_name)
341
342 return count
343
344 def get_hash_failed_counts(self, p):
345 if ESP == self.encryption_type and p.crypt_algo == "AES-GCM":
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200346 hash_failed_node_name = (
Neale Ranns93688d72022-08-09 03:34:51 +0000347 "/err/%s/decryption_failed" % self.tra4_decrypt_node_name[p.async_mode]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200348 )
Neale Ranns8c609af2021-02-25 10:05:32 +0000349 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200350 hash_failed_node_name = (
Neale Ranns93688d72022-08-09 03:34:51 +0000351 "/err/%s/integ_error" % self.tra4_decrypt_node_name[p.async_mode]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200352 )
Neale Ranns8c609af2021-02-25 10:05:32 +0000353 count = self.statistics.get_err_counter(hash_failed_node_name)
354
355 if p.async_mode:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200356 count += self.statistics.get_err_counter("/err/crypto-dispatch/bad-hmac")
Neale Ranns8c609af2021-02-25 10:05:32 +0000357
358 return count
359
Neale Ranns5b891102021-06-28 13:31:28 +0000360 def verify_hi_seq_num(self):
361 p = self.params[socket.AF_INET]
362 saf = VppEnum.vl_api_ipsec_sad_flags_t
363 esn_on = p.vpp_tra_sa.esn_en
364 ar_on = p.flags & saf.IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY
365
Neale Ranns93688d72022-08-09 03:34:51 +0000366 seq_cycle_node_name = "/err/%s/seq_cycled" % self.tra4_encrypt_node_name
Neale Ranns5b891102021-06-28 13:31:28 +0000367 replay_count = self.get_replay_counts(p)
368 hash_failed_count = self.get_hash_failed_counts(p)
369 seq_cycle_count = self.statistics.get_err_counter(seq_cycle_node_name)
370
371 # a few packets so we get the rx seq number above the window size and
372 # thus can simulate a wrap with an out of window packet
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200373 pkts = [
374 (
375 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
376 / p.scapy_tra_sa.encrypt(
377 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
378 seq_num=seq,
379 )
380 )
381 for seq in range(63, 80)
382 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000383 recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if)
384
385 # these 4 packets will all choose seq-num 0 to decrpyt since none
386 # are out of window when first checked. however, once #200 has
387 # decrypted it will move the window to 200 and has #81 is out of
388 # window. this packet should be dropped.
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200389 pkts = [
390 (
391 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
392 / p.scapy_tra_sa.encrypt(
393 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
394 seq_num=200,
395 )
396 ),
397 (
398 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
399 / p.scapy_tra_sa.encrypt(
400 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
401 seq_num=81,
402 )
403 ),
404 (
405 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
406 / p.scapy_tra_sa.encrypt(
407 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
408 seq_num=201,
409 )
410 ),
411 (
412 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
413 / p.scapy_tra_sa.encrypt(
414 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
415 seq_num=202,
416 )
417 ),
418 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000419
420 # if anti-replay is off then we won't drop #81
421 n_rx = 3 if ar_on else 4
422 self.send_and_expect(self.tra_if, pkts, self.tra_if, n_rx=n_rx)
423 # this packet is one before the wrap
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200424 pkts = [
425 (
426 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
427 / p.scapy_tra_sa.encrypt(
428 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
429 seq_num=203,
430 )
431 )
432 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000433 recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if)
434
Neale Rannsfe2d23f2022-11-18 04:24:09 +0000435 # a replayed packet, then an out of window, then a legit
436 # tests that a early failure on the batch doesn't affect subsequent packets.
437 pkts = [
438 (
439 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
440 / p.scapy_tra_sa.encrypt(
441 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
442 seq_num=203,
443 )
444 ),
445 (
446 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
447 / p.scapy_tra_sa.encrypt(
448 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
449 seq_num=81,
450 )
451 ),
452 (
453 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
454 / p.scapy_tra_sa.encrypt(
455 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
456 seq_num=204,
457 )
458 ),
459 ]
460 n_rx = 1 if ar_on else 3
461 recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if, n_rx=n_rx)
462
Neale Ranns5b891102021-06-28 13:31:28 +0000463 # move the window over half way to a wrap
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200464 pkts = [
465 (
466 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
467 / p.scapy_tra_sa.encrypt(
468 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
469 seq_num=0x80000001,
470 )
471 )
472 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000473 recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if)
474
475 # anti-replay will drop old packets, no anti-replay will not
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200476 pkts = [
477 (
478 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
479 / p.scapy_tra_sa.encrypt(
480 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
481 seq_num=0x44000001,
482 )
483 )
484 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000485
486 if ar_on:
487 self.send_and_assert_no_replies(self.tra_if, pkts)
488 else:
489 recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if)
490
491 if esn_on:
492 #
493 # validate wrapping the ESN
494 #
495
496 # wrap scapy's TX SA SN
497 p.scapy_tra_sa.seq_num = 0x100000005
498
499 # send a packet that wraps the window for both AR and no AR
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200500 pkts = [
501 (
502 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
503 / p.scapy_tra_sa.encrypt(
504 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4)
505 / ICMP(),
506 seq_num=0x100000005,
507 )
508 )
509 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000510
511 rxs = self.send_and_expect(self.tra_if, pkts, self.tra_if)
512 for rx in rxs:
513 decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
514
515 # move the window forward to half way to the next wrap
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200516 pkts = [
517 (
518 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
519 / p.scapy_tra_sa.encrypt(
520 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4)
521 / ICMP(),
522 seq_num=0x180000005,
523 )
524 )
525 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000526
527 rxs = self.send_and_expect(self.tra_if, pkts, self.tra_if)
528
529 # a packet less than 2^30 from the current position is:
530 # - AR: out of window and dropped
531 # - non-AR: accepted
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200532 pkts = [
533 (
534 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
535 / p.scapy_tra_sa.encrypt(
536 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4)
537 / ICMP(),
538 seq_num=0x170000005,
539 )
540 )
541 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000542
543 if ar_on:
544 self.send_and_assert_no_replies(self.tra_if, pkts)
545 else:
546 self.send_and_expect(self.tra_if, pkts, self.tra_if)
547
548 # a packet more than 2^30 from the current position is:
549 # - AR: out of window and dropped
550 # - non-AR: considered a wrap, but since it's not a wrap
551 # it won't decrpyt and so will be dropped
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200552 pkts = [
553 (
554 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
555 / p.scapy_tra_sa.encrypt(
556 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4)
557 / ICMP(),
558 seq_num=0x130000005,
559 )
560 )
561 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000562
563 self.send_and_assert_no_replies(self.tra_if, pkts)
564
565 # a packet less than 2^30 from the current position and is a
566 # wrap; (the seq is currently at 0x180000005).
567 # - AR: out of window so considered a wrap, so accepted
568 # - non-AR: not considered a wrap, so won't decrypt
569 p.scapy_tra_sa.seq_num = 0x260000005
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200570 pkts = [
571 (
572 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
573 / p.scapy_tra_sa.encrypt(
574 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4)
575 / ICMP(),
576 seq_num=0x260000005,
577 )
578 )
579 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000580 if ar_on:
581 self.send_and_expect(self.tra_if, pkts, self.tra_if)
582 else:
583 self.send_and_assert_no_replies(self.tra_if, pkts)
584
585 #
586 # window positions are different now for AR/non-AR
587 # move non-AR forward
588 #
589 if not ar_on:
590 # a packet more than 2^30 from the current position and is a
591 # wrap; (the seq is currently at 0x180000005).
592 # - AR: accepted
593 # - non-AR: not considered a wrap, so won't decrypt
594
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200595 pkts = [
596 (
597 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
598 / p.scapy_tra_sa.encrypt(
599 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4)
600 / ICMP(),
601 seq_num=0x200000005,
602 )
603 ),
604 (
605 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
606 / p.scapy_tra_sa.encrypt(
607 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4)
608 / ICMP(),
609 seq_num=0x200000006,
610 )
611 ),
612 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000613 self.send_and_expect(self.tra_if, pkts, self.tra_if)
614
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200615 pkts = [
616 (
617 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
618 / p.scapy_tra_sa.encrypt(
619 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4)
620 / ICMP(),
621 seq_num=0x260000005,
622 )
623 )
624 ]
Neale Ranns5b891102021-06-28 13:31:28 +0000625 self.send_and_expect(self.tra_if, pkts, self.tra_if)
626
Neale Ranns6afaae12019-07-17 15:07:14 +0000627 def verify_tra_anti_replay(self):
Neale Rannsde847272018-11-28 01:38:34 -0800628 p = self.params[socket.AF_INET]
snaramre5d4b8912019-12-13 23:39:35 +0000629 esn_en = p.vpp_tra_sa.esn_en
Neale Rannsde847272018-11-28 01:38:34 -0800630
Neale Ranns93688d72022-08-09 03:34:51 +0000631 seq_cycle_node_name = "/err/%s/seq_cycled" % self.tra4_encrypt_node_name
Neale Ranns8c609af2021-02-25 10:05:32 +0000632 replay_count = self.get_replay_counts(p)
633 hash_failed_count = self.get_hash_failed_counts(p)
Neale Ranns6afaae12019-07-17 15:07:14 +0000634 seq_cycle_count = self.statistics.get_err_counter(seq_cycle_node_name)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100635 hash_err = "integ_error"
Neale Rannsde847272018-11-28 01:38:34 -0800636
Neale Ranns6afaae12019-07-17 15:07:14 +0000637 if ESP == self.encryption_type:
Neale Ranns93688d72022-08-09 03:34:51 +0000638 undersize_node_name = "/err/%s/runt" % self.tra4_decrypt_node_name[0]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200639 undersize_count = self.statistics.get_err_counter(undersize_node_name)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100640 # For AES-GCM an error in the hash is reported as a decryption failure
641 if p.crypt_algo == "AES-GCM":
642 hash_err = "decryption_failed"
643 # In async mode, we don't report errors in the hash.
644 if p.async_mode:
645 hash_err = ""
Neale Ranns6afaae12019-07-17 15:07:14 +0000646
647 #
648 # send packets with seq numbers 1->34
649 # this means the window size is still in Case B (see RFC4303
650 # Appendix A)
651 #
652 # for reasons i haven't investigated Scapy won't create a packet with
653 # seq_num=0
654 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200655 pkts = [
656 (
657 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
658 / p.scapy_tra_sa.encrypt(
659 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
660 seq_num=seq,
661 )
662 )
663 for seq in range(1, 34)
664 ]
Neale Ranns6afaae12019-07-17 15:07:14 +0000665 recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if)
666
667 # replayed packets are dropped
Neale Ranns5b891102021-06-28 13:31:28 +0000668 self.send_and_assert_no_replies(self.tra_if, pkts, timeout=0.2)
Neale Ranns6afaae12019-07-17 15:07:14 +0000669 replay_count += len(pkts)
Neale Ranns8c609af2021-02-25 10:05:32 +0000670 self.assertEqual(self.get_replay_counts(p), replay_count)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100671 err = p.tra_sa_in.get_err("replay")
672 self.assertEqual(err, replay_count)
Neale Ranns6afaae12019-07-17 15:07:14 +0000673
674 #
Neale Ranns3b9374f2019-08-01 04:45:15 -0700675 # now send a batch of packets all with the same sequence number
676 # the first packet in the batch is legitimate, the rest bogus
677 #
Neale Ranns8c609af2021-02-25 10:05:32 +0000678 self.vapi.cli("clear error")
679 self.vapi.cli("clear node counters")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200680 pkts = Ether(
681 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
682 ) / p.scapy_tra_sa.encrypt(
683 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
684 seq_num=35,
685 )
686 recv_pkts = self.send_and_expect(self.tra_if, pkts * 8, self.tra_if, n_rx=1)
Neale Ranns3b9374f2019-08-01 04:45:15 -0700687 replay_count += 7
Neale Ranns8c609af2021-02-25 10:05:32 +0000688 self.assertEqual(self.get_replay_counts(p), replay_count)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100689 err = p.tra_sa_in.get_err("replay")
690 self.assertEqual(err, replay_count)
Neale Ranns3b9374f2019-08-01 04:45:15 -0700691
692 #
Neale Ranns6afaae12019-07-17 15:07:14 +0000693 # now move the window over to 257 (more than one byte) and into Case A
694 #
Neale Ranns8c609af2021-02-25 10:05:32 +0000695 self.vapi.cli("clear error")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200696 pkt = Ether(
697 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
698 ) / p.scapy_tra_sa.encrypt(
699 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
700 seq_num=257,
701 )
Neale Rannsde847272018-11-28 01:38:34 -0800702 recv_pkts = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
703
Neale Ranns3833ffd2019-03-21 14:34:09 +0000704 # replayed packets are dropped
Neale Ranns5b891102021-06-28 13:31:28 +0000705 self.send_and_assert_no_replies(self.tra_if, pkt * 3, timeout=0.2)
Neale Ranns6afaae12019-07-17 15:07:14 +0000706 replay_count += 3
Neale Ranns8c609af2021-02-25 10:05:32 +0000707 self.assertEqual(self.get_replay_counts(p), replay_count)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100708 err = p.tra_sa_in.get_err("replay")
709 self.assertEqual(err, replay_count)
Neale Ranns3833ffd2019-03-21 14:34:09 +0000710
Neale Rannsde847272018-11-28 01:38:34 -0800711 # the window size is 64 packets
712 # in window are still accepted
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200713 pkt = Ether(
714 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
715 ) / p.scapy_tra_sa.encrypt(
716 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
717 seq_num=200,
718 )
Neale Rannsde847272018-11-28 01:38:34 -0800719 recv_pkts = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
720
Neale Rannsde847272018-11-28 01:38:34 -0800721 # a packet that does not decrypt does not move the window forward
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200722 bogus_sa = SecurityAssociation(
723 self.encryption_type,
Arthur de Kerhor0df06b62022-11-16 18:45:24 +0100724 p.scapy_tra_spi,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200725 crypt_algo=p.crypt_algo,
726 crypt_key=mk_scapy_crypt_key(p)[::-1],
727 auth_algo=p.auth_algo,
728 auth_key=p.auth_key[::-1],
729 )
730 pkt = Ether(
731 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
732 ) / bogus_sa.encrypt(
733 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
734 seq_num=350,
735 )
Neale Ranns5b891102021-06-28 13:31:28 +0000736 self.send_and_assert_no_replies(self.tra_if, pkt * 17, timeout=0.2)
Neale Rannsde847272018-11-28 01:38:34 -0800737
Neale Ranns6afaae12019-07-17 15:07:14 +0000738 hash_failed_count += 17
Neale Ranns8c609af2021-02-25 10:05:32 +0000739 self.assertEqual(self.get_hash_failed_counts(p), hash_failed_count)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100740 if hash_err != "":
741 err = p.tra_sa_in.get_err(hash_err)
742 self.assertEqual(err, hash_failed_count)
Neale Rannsde847272018-11-28 01:38:34 -0800743
Damjan Mariona829b132019-04-24 23:39:16 +0200744 # a malformed 'runt' packet
745 # created by a mis-constructed SA
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200746 if ESP == self.encryption_type and p.crypt_algo != "NULL":
Arthur de Kerhor0df06b62022-11-16 18:45:24 +0100747 bogus_sa = SecurityAssociation(self.encryption_type, p.scapy_tra_spi)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200748 pkt = Ether(
749 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
750 ) / bogus_sa.encrypt(
751 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
752 seq_num=350,
753 )
Neale Ranns5b891102021-06-28 13:31:28 +0000754 self.send_and_assert_no_replies(self.tra_if, pkt * 17, timeout=0.2)
Damjan Mariona829b132019-04-24 23:39:16 +0200755
Neale Ranns6afaae12019-07-17 15:07:14 +0000756 undersize_count += 17
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200757 self.assert_error_counter_equal(undersize_node_name, undersize_count)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100758 err = p.tra_sa_in.get_err("runt")
759 self.assertEqual(err, undersize_count)
Damjan Mariona829b132019-04-24 23:39:16 +0200760
Neale Rannsde847272018-11-28 01:38:34 -0800761 # which we can determine since this packet is still in the window
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200762 pkt = Ether(
763 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
764 ) / p.scapy_tra_sa.encrypt(
765 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
766 seq_num=234,
767 )
Klement Sekera14d7e902018-12-10 13:46:09 +0100768 self.send_and_expect(self.tra_if, [pkt], self.tra_if)
Neale Rannsde847272018-11-28 01:38:34 -0800769
Neale Ranns6afaae12019-07-17 15:07:14 +0000770 #
Neale Ranns3833ffd2019-03-21 14:34:09 +0000771 # out of window are dropped
Neale Ranns6afaae12019-07-17 15:07:14 +0000772 # this is Case B. So VPP will consider this to be a high seq num wrap
773 # and so the decrypt attempt will fail
774 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200775 pkt = Ether(
776 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
777 ) / p.scapy_tra_sa.encrypt(
778 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
779 seq_num=17,
780 )
Neale Ranns5b891102021-06-28 13:31:28 +0000781 self.send_and_assert_no_replies(self.tra_if, pkt * 17, timeout=0.2)
Neale Ranns00a44202019-03-21 16:36:28 +0000782
snaramre5d4b8912019-12-13 23:39:35 +0000783 if esn_en:
Neale Ranns3833ffd2019-03-21 14:34:09 +0000784 # an out of window error with ESN looks like a high sequence
785 # wrap. but since it isn't then the verify will fail.
Neale Ranns6afaae12019-07-17 15:07:14 +0000786 hash_failed_count += 17
Neale Ranns8c609af2021-02-25 10:05:32 +0000787 self.assertEqual(self.get_hash_failed_counts(p), hash_failed_count)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100788 if hash_err != "":
789 err = p.tra_sa_in.get_err(hash_err)
790 self.assertEqual(err, hash_failed_count)
Neale Ranns3833ffd2019-03-21 14:34:09 +0000791
792 else:
Neale Ranns6afaae12019-07-17 15:07:14 +0000793 replay_count += 17
Neale Ranns8c609af2021-02-25 10:05:32 +0000794 self.assertEqual(self.get_replay_counts(p), replay_count)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100795 err = p.tra_sa_in.get_err("replay")
796 self.assertEqual(err, replay_count)
Neale Ranns3833ffd2019-03-21 14:34:09 +0000797
Neale Ranns6afaae12019-07-17 15:07:14 +0000798 # valid packet moves the window over to 258
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200799 pkt = Ether(
800 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
801 ) / p.scapy_tra_sa.encrypt(
802 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
803 seq_num=258,
804 )
Neale Ranns3833ffd2019-03-21 14:34:09 +0000805 rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
806 decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
807
Neale Ranns6afaae12019-07-17 15:07:14 +0000808 #
809 # move VPP's SA TX seq-num to just before the seq-number wrap.
810 # then fire in a packet that VPP should drop on TX because it
811 # causes the TX seq number to wrap; unless we're using extened sequence
812 # numbers.
813 #
Arthur de Kerhor0df06b62022-11-16 18:45:24 +0100814 self.vapi.cli("test ipsec sa %d seq 0xffffffff" % p.vpp_tra_sa_id)
Neale Ranns6afaae12019-07-17 15:07:14 +0000815 self.logger.info(self.vapi.ppcli("show ipsec sa 0"))
816 self.logger.info(self.vapi.ppcli("show ipsec sa 1"))
Neale Ranns3833ffd2019-03-21 14:34:09 +0000817
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200818 pkts = [
819 (
820 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
821 / p.scapy_tra_sa.encrypt(
822 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
823 seq_num=seq,
824 )
825 )
826 for seq in range(259, 280)
827 ]
Neale Ranns3833ffd2019-03-21 14:34:09 +0000828
snaramre5d4b8912019-12-13 23:39:35 +0000829 if esn_en:
Neale Ranns6afaae12019-07-17 15:07:14 +0000830 rxs = self.send_and_expect(self.tra_if, pkts, self.tra_if)
Neale Ranns3833ffd2019-03-21 14:34:09 +0000831
Neale Ranns6afaae12019-07-17 15:07:14 +0000832 #
833 # in order for scapy to decrypt its SA's high order number needs
834 # to wrap
835 #
836 p.vpp_tra_sa.seq_num = 0x100000000
837 for rx in rxs:
838 decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
839
840 #
841 # wrap scapy's TX high sequence number. VPP is in case B, so it
842 # will consider this a high seq wrap also.
843 # The low seq num we set it to will place VPP's RX window in Case A
844 #
Neale Ranns3833ffd2019-03-21 14:34:09 +0000845 p.scapy_tra_sa.seq_num = 0x100000005
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200846 pkt = Ether(
847 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
848 ) / p.scapy_tra_sa.encrypt(
849 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
850 seq_num=0x100000005,
851 )
Neale Ranns3833ffd2019-03-21 14:34:09 +0000852 rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
Neale Ranns5b891102021-06-28 13:31:28 +0000853
Neale Ranns3833ffd2019-03-21 14:34:09 +0000854 decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
Neale Ranns6afaae12019-07-17 15:07:14 +0000855
856 #
857 # A packet that has seq num between (2^32-64) and 5 is within
858 # the window
859 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200860 p.scapy_tra_sa.seq_num = 0xFFFFFFFD
861 pkt = Ether(
862 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
863 ) / p.scapy_tra_sa.encrypt(
864 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
865 seq_num=0xFFFFFFFD,
866 )
Neale Ranns6afaae12019-07-17 15:07:14 +0000867 rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
868 decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
869
870 #
871 # While in case A we cannot wrap the high sequence number again
Neale Ranns5b891102021-06-28 13:31:28 +0000872 # because VPP will consider this packet to be one that moves the
Neale Ranns6afaae12019-07-17 15:07:14 +0000873 # window forward
874 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200875 pkt = Ether(
876 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
877 ) / p.scapy_tra_sa.encrypt(
878 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
879 seq_num=0x200000999,
880 )
881 self.send_and_assert_no_replies(
882 self.tra_if, [pkt], self.tra_if, timeout=0.2
883 )
Neale Ranns6afaae12019-07-17 15:07:14 +0000884
885 hash_failed_count += 1
Neale Ranns8c609af2021-02-25 10:05:32 +0000886 self.assertEqual(self.get_hash_failed_counts(p), hash_failed_count)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100887 if hash_err != "":
888 err = p.tra_sa_in.get_err(hash_err)
889 self.assertEqual(err, hash_failed_count)
Neale Ranns6afaae12019-07-17 15:07:14 +0000890
891 #
Neale Ranns5b891102021-06-28 13:31:28 +0000892 # but if we move the window forward to case B, then we can wrap
Neale Ranns6afaae12019-07-17 15:07:14 +0000893 # again
894 #
895 p.scapy_tra_sa.seq_num = 0x100000555
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200896 pkt = Ether(
897 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
898 ) / p.scapy_tra_sa.encrypt(
899 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
900 seq_num=0x100000555,
901 )
Neale Ranns6afaae12019-07-17 15:07:14 +0000902 rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
903 decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
904
905 p.scapy_tra_sa.seq_num = 0x200000444
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200906 pkt = Ether(
907 src=self.tra_if.remote_mac, dst=self.tra_if.local_mac
908 ) / p.scapy_tra_sa.encrypt(
909 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
910 seq_num=0x200000444,
911 )
Neale Ranns6afaae12019-07-17 15:07:14 +0000912 rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
913 decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
914
Neale Ranns3833ffd2019-03-21 14:34:09 +0000915 else:
Neale Ranns6afaae12019-07-17 15:07:14 +0000916 #
917 # without ESN TX sequence numbers can't wrap and packets are
918 # dropped from here on out.
919 #
Neale Ranns5b891102021-06-28 13:31:28 +0000920 self.send_and_assert_no_replies(self.tra_if, pkts, timeout=0.2)
Neale Ranns6afaae12019-07-17 15:07:14 +0000921 seq_cycle_count += len(pkts)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200922 self.assert_error_counter_equal(seq_cycle_node_name, seq_cycle_count)
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100923 err = p.tra_sa_out.get_err("seq_cycled")
924 self.assertEqual(err, seq_cycle_count)
Neale Ranns00a44202019-03-21 16:36:28 +0000925
Neale Rannsde847272018-11-28 01:38:34 -0800926 # move the security-associations seq number on to the last we used
Neale Ranns00a44202019-03-21 16:36:28 +0000927 self.vapi.cli("test ipsec sa %d seq 0x15f" % p.scapy_tra_sa_id)
Neale Rannsde847272018-11-28 01:38:34 -0800928 p.scapy_tra_sa.seq_num = 351
929 p.vpp_tra_sa.seq_num = 351
930
Neale Rannse11203e2021-09-21 12:34:19 +0000931 def verify_tra_lost(self):
932 p = self.params[socket.AF_INET]
933 esn_en = p.vpp_tra_sa.esn_en
934
935 #
936 # send packets with seq numbers 1->34
937 # this means the window size is still in Case B (see RFC4303
938 # Appendix A)
939 #
940 # for reasons i haven't investigated Scapy won't create a packet with
941 # seq_num=0
942 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200943 pkts = [
944 (
945 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
946 / p.scapy_tra_sa.encrypt(
947 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
948 seq_num=seq,
949 )
950 )
951 for seq in range(1, 3)
952 ]
Neale Rannse11203e2021-09-21 12:34:19 +0000953 self.send_and_expect(self.tra_if, pkts, self.tra_if)
954
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100955 self.assertEqual(p.tra_sa_in.get_err("lost"), 0)
Neale Rannse11203e2021-09-21 12:34:19 +0000956
957 # skip a sequence number
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200958 pkts = [
959 (
960 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
961 / p.scapy_tra_sa.encrypt(
962 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
963 seq_num=seq,
964 )
965 )
966 for seq in range(4, 6)
967 ]
Neale Rannse11203e2021-09-21 12:34:19 +0000968 self.send_and_expect(self.tra_if, pkts, self.tra_if)
969
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100970 self.assertEqual(p.tra_sa_in.get_err("lost"), 0)
Neale Rannse11203e2021-09-21 12:34:19 +0000971
972 # the lost packet are counted untill we get up past the first
973 # sizeof(replay_window) packets
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200974 pkts = [
975 (
976 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
977 / p.scapy_tra_sa.encrypt(
978 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
979 seq_num=seq,
980 )
981 )
982 for seq in range(6, 100)
983 ]
Neale Rannse11203e2021-09-21 12:34:19 +0000984 self.send_and_expect(self.tra_if, pkts, self.tra_if)
985
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100986 self.assertEqual(p.tra_sa_in.get_err("lost"), 1)
Neale Rannse11203e2021-09-21 12:34:19 +0000987
988 # lost of holes in the sequence
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200989 pkts = [
990 (
991 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
992 / p.scapy_tra_sa.encrypt(
993 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
994 seq_num=seq,
995 )
996 )
997 for seq in range(100, 200, 2)
998 ]
Neale Rannse11203e2021-09-21 12:34:19 +0000999 self.send_and_expect(self.tra_if, pkts, self.tra_if, n_rx=50)
1000
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001001 pkts = [
1002 (
1003 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
1004 / p.scapy_tra_sa.encrypt(
1005 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
1006 seq_num=seq,
1007 )
1008 )
1009 for seq in range(200, 300)
1010 ]
Neale Rannse11203e2021-09-21 12:34:19 +00001011 self.send_and_expect(self.tra_if, pkts, self.tra_if)
1012
Arthur de Kerhorad95b062022-11-16 19:12:05 +01001013 self.assertEqual(p.tra_sa_in.get_err("lost"), 51)
Neale Rannse11203e2021-09-21 12:34:19 +00001014
1015 # a big hole in the seq number space
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001016 pkts = [
1017 (
1018 Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac)
1019 / p.scapy_tra_sa.encrypt(
1020 IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(),
1021 seq_num=seq,
1022 )
1023 )
1024 for seq in range(400, 500)
1025 ]
Neale Rannse11203e2021-09-21 12:34:19 +00001026 self.send_and_expect(self.tra_if, pkts, self.tra_if)
1027
Arthur de Kerhorad95b062022-11-16 19:12:05 +01001028 self.assertEqual(p.tra_sa_in.get_err("lost"), 151)
Neale Rannse11203e2021-09-21 12:34:19 +00001029
Filip Tehlarefcad1a2020-02-04 09:36:04 +00001030 def verify_tra_basic4(self, count=1, payload_size=54):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001031 """ipsec v4 transport basic test"""
Klement Sekera10d066e2018-11-13 11:12:57 +01001032 self.vapi.cli("clear errors")
Neale Ranns6afaae12019-07-17 15:07:14 +00001033 self.vapi.cli("clear ipsec sa")
Klement Sekera31da2e32018-06-24 22:49:55 +02001034 try:
Klement Sekera611864f2018-09-26 11:19:00 +02001035 p = self.params[socket.AF_INET]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001036 send_pkts = self.gen_encrypt_pkts(
1037 p,
1038 p.scapy_tra_sa,
1039 self.tra_if,
1040 src=self.tra_if.remote_ip4,
1041 dst=self.tra_if.local_ip4,
1042 count=count,
1043 payload_size=payload_size,
1044 )
1045 recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if)
Neale Rannsde847272018-11-28 01:38:34 -08001046 for rx in recv_pkts:
Neale Ranns1b582b82019-04-18 19:49:13 -07001047 self.assertEqual(len(rx) - len(Ether()), rx[IP].len)
1048 self.assert_packet_checksums_valid(rx)
Klement Sekera611864f2018-09-26 11:19:00 +02001049 try:
Neale Rannsde847272018-11-28 01:38:34 -08001050 decrypted = p.vpp_tra_sa.decrypt(rx[IP])
Klement Sekera611864f2018-09-26 11:19:00 +02001051 self.assert_packet_checksums_valid(decrypted)
1052 except:
Neale Rannsde847272018-11-28 01:38:34 -08001053 self.logger.debug(ppp("Unexpected packet:", rx))
Klement Sekera611864f2018-09-26 11:19:00 +02001054 raise
Klement Sekera31da2e32018-06-24 22:49:55 +02001055 finally:
1056 self.logger.info(self.vapi.ppcli("show error"))
Paul Vinciguerra9673e3e2019-05-10 20:41:08 -04001057 self.logger.info(self.vapi.ppcli("show ipsec all"))
Klement Sekera31da2e32018-06-24 22:49:55 +02001058
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001059 pkts = p.tra_sa_in.get_stats()["packets"]
1060 self.assertEqual(
1061 pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)
1062 )
1063 pkts = p.tra_sa_out.get_stats()["packets"]
1064 self.assertEqual(
1065 pkts, count, "incorrect SA out counts: expected %d != %d" % (count, pkts)
1066 )
Arthur de Kerhorad95b062022-11-16 19:12:05 +01001067 self.assertEqual(p.tra_sa_out.get_err("lost"), 0)
1068 self.assertEqual(p.tra_sa_in.get_err("lost"), 0)
Neale Rannseba31ec2019-02-17 18:04:27 +00001069
Klement Sekera10d066e2018-11-13 11:12:57 +01001070 self.assert_packet_counter_equal(self.tra4_encrypt_node_name, count)
Neale Ranns8c609af2021-02-25 10:05:32 +00001071 self.assert_packet_counter_equal(self.tra4_decrypt_node_name[0], count)
Klement Sekera10d066e2018-11-13 11:12:57 +01001072
Neale Ranns4f33c802019-04-10 12:39:10 +00001073
1074class IpsecTra4Tests(IpsecTra4):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001075 """UT test methods for Transport v4"""
1076
Neale Ranns4f33c802019-04-10 12:39:10 +00001077 def test_tra_anti_replay(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001078 """ipsec v4 transport anti-replay test"""
Neale Ranns6afaae12019-07-17 15:07:14 +00001079 self.verify_tra_anti_replay()
Neale Ranns4f33c802019-04-10 12:39:10 +00001080
Neale Rannse11203e2021-09-21 12:34:19 +00001081 def test_tra_lost(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001082 """ipsec v4 transport lost packet test"""
Neale Rannse11203e2021-09-21 12:34:19 +00001083 self.verify_tra_lost()
1084
Neale Ranns4f33c802019-04-10 12:39:10 +00001085 def test_tra_basic(self, count=1):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001086 """ipsec v4 transport basic test"""
Neale Ranns4f33c802019-04-10 12:39:10 +00001087 self.verify_tra_basic4(count=1)
1088
Klement Sekera31da2e32018-06-24 22:49:55 +02001089 def test_tra_burst(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001090 """ipsec v4 transport burst test"""
Neale Ranns4f33c802019-04-10 12:39:10 +00001091 self.verify_tra_basic4(count=257)
Klement Sekera611864f2018-09-26 11:19:00 +02001092
Neale Ranns53f526b2019-02-25 14:32:02 +00001093
Neale Ranns4f33c802019-04-10 12:39:10 +00001094class IpsecTra6(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001095 """verify methods for Transport v6"""
1096
Filip Tehlarefcad1a2020-02-04 09:36:04 +00001097 def verify_tra_basic6(self, count=1, payload_size=54):
Klement Sekera10d066e2018-11-13 11:12:57 +01001098 self.vapi.cli("clear errors")
Filip Tehlarefcad1a2020-02-04 09:36:04 +00001099 self.vapi.cli("clear ipsec sa")
Klement Sekera31da2e32018-06-24 22:49:55 +02001100 try:
Klement Sekera611864f2018-09-26 11:19:00 +02001101 p = self.params[socket.AF_INET6]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001102 send_pkts = self.gen_encrypt_pkts6(
1103 p,
1104 p.scapy_tra_sa,
1105 self.tra_if,
1106 src=self.tra_if.remote_ip6,
1107 dst=self.tra_if.local_ip6,
1108 count=count,
1109 payload_size=payload_size,
1110 )
1111 recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if)
Neale Rannsde847272018-11-28 01:38:34 -08001112 for rx in recv_pkts:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001113 self.assertEqual(len(rx) - len(Ether()) - len(IPv6()), rx[IPv6].plen)
Klement Sekera611864f2018-09-26 11:19:00 +02001114 try:
Neale Rannsde847272018-11-28 01:38:34 -08001115 decrypted = p.vpp_tra_sa.decrypt(rx[IPv6])
Klement Sekera611864f2018-09-26 11:19:00 +02001116 self.assert_packet_checksums_valid(decrypted)
1117 except:
Neale Rannsde847272018-11-28 01:38:34 -08001118 self.logger.debug(ppp("Unexpected packet:", rx))
Klement Sekera611864f2018-09-26 11:19:00 +02001119 raise
Klement Sekera31da2e32018-06-24 22:49:55 +02001120 finally:
1121 self.logger.info(self.vapi.ppcli("show error"))
Paul Vinciguerra9673e3e2019-05-10 20:41:08 -04001122 self.logger.info(self.vapi.ppcli("show ipsec all"))
Klement Sekera31da2e32018-06-24 22:49:55 +02001123
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001124 pkts = p.tra_sa_in.get_stats()["packets"]
1125 self.assertEqual(
1126 pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)
1127 )
1128 pkts = p.tra_sa_out.get_stats()["packets"]
1129 self.assertEqual(
1130 pkts, count, "incorrect SA out counts: expected %d != %d" % (count, pkts)
1131 )
Klement Sekera10d066e2018-11-13 11:12:57 +01001132 self.assert_packet_counter_equal(self.tra6_encrypt_node_name, count)
Neale Ranns8c609af2021-02-25 10:05:32 +00001133 self.assert_packet_counter_equal(self.tra6_decrypt_node_name[0], count)
Klement Sekera10d066e2018-11-13 11:12:57 +01001134
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001135 def gen_encrypt_pkts_ext_hdrs6(
1136 self, sa, sw_intf, src, dst, count=1, payload_size=54
1137 ):
1138 return [
1139 Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac)
1140 / sa.encrypt(
1141 IPv6(src=src, dst=dst)
1142 / ICMPv6EchoRequest(id=0, seq=1, data="X" * payload_size)
1143 )
1144 for i in range(count)
1145 ]
Neale Ranns02950402019-12-20 00:54:57 +00001146
1147 def gen_pkts_ext_hdrs6(self, sw_intf, src, dst, count=1, payload_size=54):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001148 return [
1149 Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac)
1150 / IPv6(src=src, dst=dst)
1151 / IPv6ExtHdrHopByHop()
1152 / IPv6ExtHdrFragment(id=2, offset=200)
1153 / Raw(b"\xff" * 200)
1154 for i in range(count)
1155 ]
Neale Ranns02950402019-12-20 00:54:57 +00001156
1157 def verify_tra_encrypted6(self, p, sa, rxs):
1158 decrypted = []
1159 for rx in rxs:
1160 self.assert_packet_checksums_valid(rx)
1161 try:
1162 decrypt_pkt = p.vpp_tra_sa.decrypt(rx[IPv6])
1163 decrypted.append(decrypt_pkt)
1164 self.assert_equal(decrypt_pkt.src, self.tra_if.local_ip6)
1165 self.assert_equal(decrypt_pkt.dst, self.tra_if.remote_ip6)
1166 except:
1167 self.logger.debug(ppp("Unexpected packet:", rx))
1168 try:
1169 self.logger.debug(ppp("Decrypted packet:", decrypt_pkt))
1170 except:
1171 pass
1172 raise
1173 return decrypted
1174
1175 def verify_tra_66_ext_hdrs(self, p):
1176 count = 63
1177
1178 #
1179 # check we can decrypt with options
1180 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001181 tx = self.gen_encrypt_pkts_ext_hdrs6(
1182 p.scapy_tra_sa,
1183 self.tra_if,
1184 src=self.tra_if.remote_ip6,
1185 dst=self.tra_if.local_ip6,
1186 count=count,
1187 )
Neale Ranns02950402019-12-20 00:54:57 +00001188 self.send_and_expect(self.tra_if, tx, self.tra_if)
1189
1190 #
1191 # injecting a packet from ourselves to be routed of box is a hack
1192 # but it matches an outbout policy, alors je ne regrette rien
1193 #
1194
1195 # one extension before ESP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001196 tx = (
1197 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
1198 / IPv6(src=self.tra_if.local_ip6, dst=self.tra_if.remote_ip6)
1199 / IPv6ExtHdrFragment(id=2, offset=200)
1200 / Raw(b"\xff" * 200)
1201 )
Neale Ranns02950402019-12-20 00:54:57 +00001202
1203 rxs = self.send_and_expect(self.pg2, [tx], self.tra_if)
1204 dcs = self.verify_tra_encrypted6(p, p.vpp_tra_sa, rxs)
1205
1206 for dc in dcs:
1207 # for reasons i'm not going to investigate scapy does not
1208 # created the correct headers after decrypt. but reparsing
1209 # the ipv6 packet fixes it
1210 dc = IPv6(raw(dc[IPv6]))
1211 self.assert_equal(dc[IPv6ExtHdrFragment].id, 2)
1212
1213 # two extensions before ESP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001214 tx = (
1215 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
1216 / IPv6(src=self.tra_if.local_ip6, dst=self.tra_if.remote_ip6)
1217 / IPv6ExtHdrHopByHop()
1218 / IPv6ExtHdrFragment(id=2, offset=200)
1219 / Raw(b"\xff" * 200)
1220 )
Neale Ranns02950402019-12-20 00:54:57 +00001221
1222 rxs = self.send_and_expect(self.pg2, [tx], self.tra_if)
1223 dcs = self.verify_tra_encrypted6(p, p.vpp_tra_sa, rxs)
1224
1225 for dc in dcs:
1226 dc = IPv6(raw(dc[IPv6]))
1227 self.assertTrue(dc[IPv6ExtHdrHopByHop])
1228 self.assert_equal(dc[IPv6ExtHdrFragment].id, 2)
1229
1230 # two extensions before ESP, one after
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001231 tx = (
1232 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
1233 / IPv6(src=self.tra_if.local_ip6, dst=self.tra_if.remote_ip6)
1234 / IPv6ExtHdrHopByHop()
1235 / IPv6ExtHdrFragment(id=2, offset=200)
1236 / IPv6ExtHdrDestOpt()
1237 / Raw(b"\xff" * 200)
1238 )
Neale Ranns02950402019-12-20 00:54:57 +00001239
1240 rxs = self.send_and_expect(self.pg2, [tx], self.tra_if)
1241 dcs = self.verify_tra_encrypted6(p, p.vpp_tra_sa, rxs)
1242
1243 for dc in dcs:
1244 dc = IPv6(raw(dc[IPv6]))
1245 self.assertTrue(dc[IPv6ExtHdrDestOpt])
1246 self.assertTrue(dc[IPv6ExtHdrHopByHop])
1247 self.assert_equal(dc[IPv6ExtHdrFragment].id, 2)
1248
Neale Ranns4f33c802019-04-10 12:39:10 +00001249
1250class IpsecTra6Tests(IpsecTra6):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001251 """UT test methods for Transport v6"""
1252
Neale Ranns4f33c802019-04-10 12:39:10 +00001253 def test_tra_basic6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001254 """ipsec v6 transport basic test"""
Neale Ranns4f33c802019-04-10 12:39:10 +00001255 self.verify_tra_basic6(count=1)
1256
Klement Sekera611864f2018-09-26 11:19:00 +02001257 def test_tra_burst6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001258 """ipsec v6 transport burst test"""
Neale Ranns4f33c802019-04-10 12:39:10 +00001259 self.verify_tra_basic6(count=257)
Klement Sekera31da2e32018-06-24 22:49:55 +02001260
Klement Sekera611864f2018-09-26 11:19:00 +02001261
Neale Ranns02950402019-12-20 00:54:57 +00001262class IpsecTra6ExtTests(IpsecTra6):
1263 def test_tra_ext_hdrs_66(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001264 """ipsec 6o6 tra extension headers test"""
Neale Ranns02950402019-12-20 00:54:57 +00001265 self.verify_tra_66_ext_hdrs(self.params[socket.AF_INET6])
1266
1267
Neale Ranns53f526b2019-02-25 14:32:02 +00001268class IpsecTra46Tests(IpsecTra4Tests, IpsecTra6Tests):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001269 """UT test methods for Transport v6 and v4"""
1270
Neale Ranns53f526b2019-02-25 14:32:02 +00001271 pass
1272
1273
Neale Ranns2ac885c2019-03-20 18:24:43 +00001274class IpsecTun4(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001275 """verify methods for Tunnel v4"""
1276
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001277 def verify_counters4(self, p, count, n_frags=None, worker=None):
Klement Sekera6aa58b72019-05-16 14:34:55 +02001278 if not n_frags:
1279 n_frags = count
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001280 if hasattr(p, "spd_policy_in_any"):
1281 pkts = p.spd_policy_in_any.get_stats(worker)["packets"]
1282 self.assertEqual(
1283 pkts,
1284 count,
1285 "incorrect SPD any policy: expected %d != %d" % (count, pkts),
1286 )
Neale Ranns987aea82019-03-27 13:40:35 +00001287
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001288 if hasattr(p, "tun_sa_in"):
1289 pkts = p.tun_sa_in.get_stats(worker)["packets"]
1290 self.assertEqual(
1291 pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)
1292 )
1293 pkts = p.tun_sa_out.get_stats(worker)["packets"]
1294 self.assertEqual(
1295 pkts,
1296 n_frags,
1297 "incorrect SA out counts: expected %d != %d" % (count, pkts),
1298 )
Neale Ranns987aea82019-03-27 13:40:35 +00001299
Klement Sekera6aa58b72019-05-16 14:34:55 +02001300 self.assert_packet_counter_equal(self.tun4_encrypt_node_name, n_frags)
Neale Ranns8c609af2021-02-25 10:05:32 +00001301 self.assert_packet_counter_equal(self.tun4_decrypt_node_name[0], count)
Neale Ranns987aea82019-03-27 13:40:35 +00001302
Neale Rannsf05e7322019-03-29 20:23:58 +00001303 def verify_decrypted(self, p, rxs):
1304 for rx in rxs:
1305 self.assert_equal(rx[IP].src, p.remote_tun_if_host)
1306 self.assert_equal(rx[IP].dst, self.pg1.remote_ip4)
1307 self.assert_packet_checksums_valid(rx)
1308
Christian Hoppsfb7e7ed2019-11-03 07:02:15 -05001309 def verify_esp_padding(self, sa, esp_payload, decrypt_pkt):
1310 align = sa.crypt_algo.block_size
1311 if align < 4:
1312 align = 4
1313 exp_len = (len(decrypt_pkt) + 2 + (align - 1)) & ~(align - 1)
1314 exp_len += sa.crypt_algo.iv_size
1315 exp_len += sa.crypt_algo.icv_size or sa.auth_algo.icv_size
1316 self.assertEqual(exp_len, len(esp_payload))
1317
Neale Rannsf05e7322019-03-29 20:23:58 +00001318 def verify_encrypted(self, p, sa, rxs):
1319 decrypt_pkts = []
1320 for rx in rxs:
Neale Ranns41afb332019-07-16 06:19:35 -07001321 if p.nat_header:
Arthur de Kerhor4117b242022-08-31 19:13:03 +02001322 self.assertEqual(rx[UDP].dport, p.nat_header.dport)
Neale Ranns1b582b82019-04-18 19:49:13 -07001323 self.assert_packet_checksums_valid(rx)
1324 self.assertEqual(len(rx) - len(Ether()), rx[IP].len)
Neale Rannsf05e7322019-03-29 20:23:58 +00001325 try:
Christian Hoppsfb7e7ed2019-11-03 07:02:15 -05001326 rx_ip = rx[IP]
1327 decrypt_pkt = p.vpp_tun_sa.decrypt(rx_ip)
Neale Rannsf05e7322019-03-29 20:23:58 +00001328 if not decrypt_pkt.haslayer(IP):
1329 decrypt_pkt = IP(decrypt_pkt[Raw].load)
Christian Hoppsfb7e7ed2019-11-03 07:02:15 -05001330 if rx_ip.proto == socket.IPPROTO_ESP:
1331 self.verify_esp_padding(sa, rx_ip[ESP].data, decrypt_pkt)
Neale Rannsf05e7322019-03-29 20:23:58 +00001332 decrypt_pkts.append(decrypt_pkt)
1333 self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip4)
1334 self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host)
1335 except:
1336 self.logger.debug(ppp("Unexpected packet:", rx))
1337 try:
1338 self.logger.debug(ppp("Decrypted packet:", decrypt_pkt))
1339 except:
1340 pass
1341 raise
1342 pkts = reassemble4(decrypt_pkts)
1343 for pkt in pkts:
1344 self.assert_packet_checksums_valid(pkt)
1345
Neale Rannsd7603d92019-03-28 08:56:10 +00001346 def verify_tun_44(self, p, count=1, payload_size=64, n_rx=None):
Klement Sekera10d066e2018-11-13 11:12:57 +01001347 self.vapi.cli("clear errors")
Neale Ranns02950402019-12-20 00:54:57 +00001348 self.vapi.cli("clear ipsec counters")
Neale Ranns28287212019-12-16 00:53:11 +00001349 self.vapi.cli("clear ipsec sa")
Neale Rannsd7603d92019-03-28 08:56:10 +00001350 if not n_rx:
1351 n_rx = count
Klement Sekera31da2e32018-06-24 22:49:55 +02001352 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001353 send_pkts = self.gen_encrypt_pkts(
1354 p,
1355 p.scapy_tun_sa,
1356 self.tun_if,
1357 src=p.remote_tun_if_host,
1358 dst=self.pg1.remote_ip4,
1359 count=count,
1360 payload_size=payload_size,
1361 )
Klement Sekera611864f2018-09-26 11:19:00 +02001362 recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1)
Neale Rannsf05e7322019-03-29 20:23:58 +00001363 self.verify_decrypted(p, recv_pkts)
1364
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001365 send_pkts = self.gen_pkts(
1366 self.pg1,
1367 src=self.pg1.remote_ip4,
1368 dst=p.remote_tun_if_host,
1369 count=count,
1370 payload_size=payload_size,
1371 )
1372 recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if, n_rx)
Neale Rannsf05e7322019-03-29 20:23:58 +00001373 self.verify_encrypted(p, p.vpp_tun_sa, recv_pkts)
1374
Neale Rannsf3a66222020-01-02 05:04:00 +00001375 for rx in recv_pkts:
1376 self.assertEqual(rx[IP].src, p.tun_src)
1377 self.assertEqual(rx[IP].dst, p.tun_dst)
1378
Klement Sekera31da2e32018-06-24 22:49:55 +02001379 finally:
1380 self.logger.info(self.vapi.ppcli("show error"))
Paul Vinciguerra9673e3e2019-05-10 20:41:08 -04001381 self.logger.info(self.vapi.ppcli("show ipsec all"))
Klement Sekera31da2e32018-06-24 22:49:55 +02001382
Neale Ranns02950402019-12-20 00:54:57 +00001383 self.logger.info(self.vapi.ppcli("show ipsec sa 0"))
1384 self.logger.info(self.vapi.ppcli("show ipsec sa 4"))
Klement Sekera6aa58b72019-05-16 14:34:55 +02001385 self.verify_counters4(p, count, n_rx)
Neale Rannseba31ec2019-02-17 18:04:27 +00001386
Neale Ranns28287212019-12-16 00:53:11 +00001387 def verify_tun_dropped_44(self, p, count=1, payload_size=64, n_rx=None):
1388 self.vapi.cli("clear errors")
1389 if not n_rx:
1390 n_rx = count
1391 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001392 send_pkts = self.gen_encrypt_pkts(
1393 p,
1394 p.scapy_tun_sa,
1395 self.tun_if,
1396 src=p.remote_tun_if_host,
1397 dst=self.pg1.remote_ip4,
1398 count=count,
1399 )
Neale Ranns28287212019-12-16 00:53:11 +00001400 self.send_and_assert_no_replies(self.tun_if, send_pkts)
1401
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001402 send_pkts = self.gen_pkts(
1403 self.pg1,
1404 src=self.pg1.remote_ip4,
1405 dst=p.remote_tun_if_host,
1406 count=count,
1407 payload_size=payload_size,
1408 )
Neale Ranns28287212019-12-16 00:53:11 +00001409 self.send_and_assert_no_replies(self.pg1, send_pkts)
1410
1411 finally:
1412 self.logger.info(self.vapi.ppcli("show error"))
1413 self.logger.info(self.vapi.ppcli("show ipsec all"))
1414
Neale Ranns14046982019-07-29 14:49:52 +00001415 def verify_tun_reass_44(self, p):
1416 self.vapi.cli("clear errors")
1417 self.vapi.ip_reassembly_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001418 sw_if_index=self.tun_if.sw_if_index, enable_ip4=True
1419 )
Neale Ranns14046982019-07-29 14:49:52 +00001420
1421 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001422 send_pkts = self.gen_encrypt_pkts(
1423 p,
1424 p.scapy_tun_sa,
1425 self.tun_if,
1426 src=p.remote_tun_if_host,
1427 dst=self.pg1.remote_ip4,
1428 payload_size=1900,
1429 count=1,
1430 )
Neale Ranns14046982019-07-29 14:49:52 +00001431 send_pkts = fragment_rfc791(send_pkts[0], 1400)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001432 recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1, n_rx=1)
Neale Ranns14046982019-07-29 14:49:52 +00001433 self.verify_decrypted(p, recv_pkts)
1434
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001435 send_pkts = self.gen_pkts(
1436 self.pg1, src=self.pg1.remote_ip4, dst=p.remote_tun_if_host, count=1
1437 )
1438 recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if)
Neale Ranns14046982019-07-29 14:49:52 +00001439 self.verify_encrypted(p, p.vpp_tun_sa, recv_pkts)
1440
1441 finally:
1442 self.logger.info(self.vapi.ppcli("show error"))
1443 self.logger.info(self.vapi.ppcli("show ipsec all"))
1444
1445 self.verify_counters4(p, 1, 1)
1446 self.vapi.ip_reassembly_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001447 sw_if_index=self.tun_if.sw_if_index, enable_ip4=False
1448 )
Neale Ranns14046982019-07-29 14:49:52 +00001449
Neale Ranns987aea82019-03-27 13:40:35 +00001450 def verify_tun_64(self, p, count=1):
1451 self.vapi.cli("clear errors")
Neale Rannsdd4ccf22020-06-30 07:47:14 +00001452 self.vapi.cli("clear ipsec sa")
Neale Ranns987aea82019-03-27 13:40:35 +00001453 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001454 send_pkts = self.gen_encrypt_pkts6(
1455 p,
1456 p.scapy_tun_sa,
1457 self.tun_if,
1458 src=p.remote_tun_if_host6,
1459 dst=self.pg1.remote_ip6,
1460 count=count,
1461 )
Neale Ranns987aea82019-03-27 13:40:35 +00001462 recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1)
1463 for recv_pkt in recv_pkts:
1464 self.assert_equal(recv_pkt[IPv6].src, p.remote_tun_if_host6)
1465 self.assert_equal(recv_pkt[IPv6].dst, self.pg1.remote_ip6)
1466 self.assert_packet_checksums_valid(recv_pkt)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001467 send_pkts = self.gen_pkts6(
1468 p,
1469 self.pg1,
1470 src=self.pg1.remote_ip6,
1471 dst=p.remote_tun_if_host6,
1472 count=count,
1473 )
Neale Ranns987aea82019-03-27 13:40:35 +00001474 recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if)
1475 for recv_pkt in recv_pkts:
1476 try:
1477 decrypt_pkt = p.vpp_tun_sa.decrypt(recv_pkt[IP])
1478 if not decrypt_pkt.haslayer(IPv6):
1479 decrypt_pkt = IPv6(decrypt_pkt[Raw].load)
1480 self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip6)
1481 self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host6)
1482 self.assert_packet_checksums_valid(decrypt_pkt)
1483 except:
1484 self.logger.error(ppp("Unexpected packet:", recv_pkt))
1485 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001486 self.logger.debug(ppp("Decrypted packet:", decrypt_pkt))
Neale Ranns987aea82019-03-27 13:40:35 +00001487 except:
1488 pass
1489 raise
1490 finally:
1491 self.logger.info(self.vapi.ppcli("show error"))
Paul Vinciguerra9673e3e2019-05-10 20:41:08 -04001492 self.logger.info(self.vapi.ppcli("show ipsec all"))
Neale Rannseba31ec2019-02-17 18:04:27 +00001493
Klement Sekera6aa58b72019-05-16 14:34:55 +02001494 self.verify_counters4(p, count)
Klement Sekera10d066e2018-11-13 11:12:57 +01001495
Neale Ranns41afb332019-07-16 06:19:35 -07001496 def verify_keepalive(self, p):
Neale Ranns992a4d02022-01-10 11:21:17 +00001497 # the sizeof Raw is calculated to pad to the minimum ehternet
1498 # frame size of 64 btyes
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001499 pkt = (
1500 Ether(src=self.tun_if.remote_mac, dst=self.tun_if.local_mac)
1501 / IP(src=p.remote_tun_if_host, dst=self.tun_if.local_ip4)
1502 / UDP(sport=333, dport=4500)
1503 / Raw(b"\xff")
1504 / Padding(0 * 21)
1505 )
1506 self.send_and_assert_no_replies(self.tun_if, pkt * 31)
Neale Ranns41afb332019-07-16 06:19:35 -07001507 self.assert_error_counter_equal(
Neale Ranns93688d72022-08-09 03:34:51 +00001508 "/err/%s/nat_keepalive" % self.tun4_input_node, 31
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001509 )
Neale Ranns41afb332019-07-16 06:19:35 -07001510
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001511 pkt = (
1512 Ether(src=self.tun_if.remote_mac, dst=self.tun_if.local_mac)
1513 / IP(src=p.remote_tun_if_host, dst=self.tun_if.local_ip4)
1514 / UDP(sport=333, dport=4500)
1515 / Raw(b"\xfe")
1516 )
1517 self.send_and_assert_no_replies(self.tun_if, pkt * 31)
Neale Ranns93688d72022-08-09 03:34:51 +00001518 self.assert_error_counter_equal("/err/%s/too_short" % self.tun4_input_node, 31)
Neale Ranns41afb332019-07-16 06:19:35 -07001519
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001520 pkt = (
1521 Ether(src=self.tun_if.remote_mac, dst=self.tun_if.local_mac)
1522 / IP(src=p.remote_tun_if_host, dst=self.tun_if.local_ip4)
1523 / UDP(sport=333, dport=4500)
1524 / Raw(b"\xfe")
1525 / Padding(0 * 21)
1526 )
1527 self.send_and_assert_no_replies(self.tun_if, pkt * 31)
Neale Ranns93688d72022-08-09 03:34:51 +00001528 self.assert_error_counter_equal("/err/%s/too_short" % self.tun4_input_node, 62)
Neale Ranns992a4d02022-01-10 11:21:17 +00001529
Neale Ranns2ac885c2019-03-20 18:24:43 +00001530
1531class IpsecTun4Tests(IpsecTun4):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001532 """UT test methods for Tunnel v4"""
1533
Neale Ranns2ac885c2019-03-20 18:24:43 +00001534 def test_tun_basic44(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001535 """ipsec 4o4 tunnel basic test"""
Neale Ranns2ac885c2019-03-20 18:24:43 +00001536 self.verify_tun_44(self.params[socket.AF_INET], count=1)
Neale Ranns02950402019-12-20 00:54:57 +00001537 self.tun_if.admin_down()
1538 self.tun_if.resolve_arp()
1539 self.tun_if.admin_up()
1540 self.verify_tun_44(self.params[socket.AF_INET], count=1)
Neale Ranns2ac885c2019-03-20 18:24:43 +00001541
Neale Ranns14046982019-07-29 14:49:52 +00001542 def test_tun_reass_basic44(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001543 """ipsec 4o4 tunnel basic reassembly test"""
Neale Ranns14046982019-07-29 14:49:52 +00001544 self.verify_tun_reass_44(self.params[socket.AF_INET])
1545
Klement Sekera611864f2018-09-26 11:19:00 +02001546 def test_tun_burst44(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001547 """ipsec 4o4 tunnel burst test"""
Neale Ranns02950402019-12-20 00:54:57 +00001548 self.verify_tun_44(self.params[socket.AF_INET], count=127)
1549
1550
Neale Ranns2ac885c2019-03-20 18:24:43 +00001551class IpsecTun6(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001552 """verify methods for Tunnel v6"""
1553
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001554 def verify_counters6(self, p_in, p_out, count, worker=None):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001555 if hasattr(p_in, "tun_sa_in"):
1556 pkts = p_in.tun_sa_in.get_stats(worker)["packets"]
1557 self.assertEqual(
1558 pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)
1559 )
1560 if hasattr(p_out, "tun_sa_out"):
1561 pkts = p_out.tun_sa_out.get_stats(worker)["packets"]
1562 self.assertEqual(
1563 pkts,
1564 count,
1565 "incorrect SA out counts: expected %d != %d" % (count, pkts),
1566 )
Neale Ranns987aea82019-03-27 13:40:35 +00001567 self.assert_packet_counter_equal(self.tun6_encrypt_node_name, count)
Neale Ranns8c609af2021-02-25 10:05:32 +00001568 self.assert_packet_counter_equal(self.tun6_decrypt_node_name[0], count)
Neale Ranns987aea82019-03-27 13:40:35 +00001569
Neale Rannsc87b66c2019-02-07 07:26:12 -08001570 def verify_decrypted6(self, p, rxs):
1571 for rx in rxs:
1572 self.assert_equal(rx[IPv6].src, p.remote_tun_if_host)
1573 self.assert_equal(rx[IPv6].dst, self.pg1.remote_ip6)
1574 self.assert_packet_checksums_valid(rx)
1575
1576 def verify_encrypted6(self, p, sa, rxs):
1577 for rx in rxs:
1578 self.assert_packet_checksums_valid(rx)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001579 self.assertEqual(len(rx) - len(Ether()) - len(IPv6()), rx[IPv6].plen)
Neale Ranns9ec846c2021-02-09 14:04:02 +00001580 self.assert_equal(rx[IPv6].hlim, p.outer_hop_limit)
1581 if p.outer_flow_label:
1582 self.assert_equal(rx[IPv6].fl, p.outer_flow_label)
Neale Rannsc87b66c2019-02-07 07:26:12 -08001583 try:
1584 decrypt_pkt = p.vpp_tun_sa.decrypt(rx[IPv6])
1585 if not decrypt_pkt.haslayer(IPv6):
1586 decrypt_pkt = IPv6(decrypt_pkt[Raw].load)
1587 self.assert_packet_checksums_valid(decrypt_pkt)
1588 self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip6)
1589 self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host)
Neale Ranns9ec846c2021-02-09 14:04:02 +00001590 self.assert_equal(decrypt_pkt.hlim, p.inner_hop_limit - 1)
1591 self.assert_equal(decrypt_pkt.fl, p.inner_flow_label)
Neale Rannsc87b66c2019-02-07 07:26:12 -08001592 except:
1593 self.logger.debug(ppp("Unexpected packet:", rx))
1594 try:
1595 self.logger.debug(ppp("Decrypted packet:", decrypt_pkt))
1596 except:
1597 pass
1598 raise
1599
Neale Ranns49378f22022-01-10 10:38:43 +00001600 def verify_drop_tun_tx_66(self, p_in, count=1, payload_size=64):
1601 self.vapi.cli("clear errors")
1602 self.vapi.cli("clear ipsec sa")
1603
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001604 send_pkts = self.gen_pkts6(
1605 p_in,
1606 self.pg1,
1607 src=self.pg1.remote_ip6,
1608 dst=p_in.remote_tun_if_host,
1609 count=count,
1610 payload_size=payload_size,
1611 )
Neale Ranns49378f22022-01-10 10:38:43 +00001612 self.send_and_assert_no_replies(self.tun_if, send_pkts)
1613 self.logger.info(self.vapi.cli("sh punt stats"))
1614
1615 def verify_drop_tun_rx_66(self, p_in, count=1, payload_size=64):
Klement Sekera10d066e2018-11-13 11:12:57 +01001616 self.vapi.cli("clear errors")
Neale Rannsc87b66c2019-02-07 07:26:12 -08001617 self.vapi.cli("clear ipsec sa")
1618
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001619 send_pkts = self.gen_encrypt_pkts6(
1620 p_in,
1621 p_in.scapy_tun_sa,
1622 self.tun_if,
1623 src=p_in.remote_tun_if_host,
1624 dst=self.pg1.remote_ip6,
1625 count=count,
1626 )
Neale Rannsc87b66c2019-02-07 07:26:12 -08001627 self.send_and_assert_no_replies(self.tun_if, send_pkts)
Neale Ranns49378f22022-01-10 10:38:43 +00001628
1629 def verify_drop_tun_66(self, p_in, count=1, payload_size=64):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001630 self.verify_drop_tun_tx_66(p_in, count=count, payload_size=payload_size)
1631 self.verify_drop_tun_rx_66(p_in, count=count, payload_size=payload_size)
Neale Rannsc87b66c2019-02-07 07:26:12 -08001632
1633 def verify_tun_66(self, p_in, p_out=None, count=1, payload_size=64):
1634 self.vapi.cli("clear errors")
1635 self.vapi.cli("clear ipsec sa")
1636 if not p_out:
1637 p_out = p_in
Klement Sekera31da2e32018-06-24 22:49:55 +02001638 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001639 send_pkts = self.gen_encrypt_pkts6(
1640 p_in,
1641 p_in.scapy_tun_sa,
1642 self.tun_if,
1643 src=p_in.remote_tun_if_host,
1644 dst=self.pg1.remote_ip6,
1645 count=count,
1646 payload_size=payload_size,
1647 )
Klement Sekera611864f2018-09-26 11:19:00 +02001648 recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1)
Neale Rannsc87b66c2019-02-07 07:26:12 -08001649 self.verify_decrypted6(p_in, recv_pkts)
1650
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001651 send_pkts = self.gen_pkts6(
1652 p_in,
1653 self.pg1,
1654 src=self.pg1.remote_ip6,
1655 dst=p_out.remote_tun_if_host,
1656 count=count,
1657 payload_size=payload_size,
1658 )
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001659 recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if)
Neale Rannsc87b66c2019-02-07 07:26:12 -08001660 self.verify_encrypted6(p_out, p_out.vpp_tun_sa, recv_pkts)
1661
Neale Rannsf3a66222020-01-02 05:04:00 +00001662 for rx in recv_pkts:
1663 self.assertEqual(rx[IPv6].src, p_out.tun_src)
1664 self.assertEqual(rx[IPv6].dst, p_out.tun_dst)
1665
Klement Sekera31da2e32018-06-24 22:49:55 +02001666 finally:
1667 self.logger.info(self.vapi.ppcli("show error"))
Paul Vinciguerra9673e3e2019-05-10 20:41:08 -04001668 self.logger.info(self.vapi.ppcli("show ipsec all"))
Neale Rannsc87b66c2019-02-07 07:26:12 -08001669 self.verify_counters6(p_in, p_out, count)
Klement Sekera31da2e32018-06-24 22:49:55 +02001670
Neale Ranns14046982019-07-29 14:49:52 +00001671 def verify_tun_reass_66(self, p):
1672 self.vapi.cli("clear errors")
1673 self.vapi.ip_reassembly_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001674 sw_if_index=self.tun_if.sw_if_index, enable_ip6=True
1675 )
Neale Ranns14046982019-07-29 14:49:52 +00001676
1677 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001678 send_pkts = self.gen_encrypt_pkts6(
1679 p,
1680 p.scapy_tun_sa,
1681 self.tun_if,
1682 src=p.remote_tun_if_host,
1683 dst=self.pg1.remote_ip6,
1684 count=1,
1685 payload_size=1850,
1686 )
Neale Ranns14046982019-07-29 14:49:52 +00001687 send_pkts = fragment_rfc8200(send_pkts[0], 1, 1400, self.logger)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001688 recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1, n_rx=1)
Neale Ranns14046982019-07-29 14:49:52 +00001689 self.verify_decrypted6(p, recv_pkts)
1690
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001691 send_pkts = self.gen_pkts6(
1692 p,
1693 self.pg1,
1694 src=self.pg1.remote_ip6,
1695 dst=p.remote_tun_if_host,
1696 count=1,
1697 payload_size=64,
1698 )
1699 recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if)
Neale Ranns14046982019-07-29 14:49:52 +00001700 self.verify_encrypted6(p, p.vpp_tun_sa, recv_pkts)
1701 finally:
1702 self.logger.info(self.vapi.ppcli("show error"))
1703 self.logger.info(self.vapi.ppcli("show ipsec all"))
1704 self.verify_counters6(p, p, 1)
1705 self.vapi.ip_reassembly_enable_disable(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001706 sw_if_index=self.tun_if.sw_if_index, enable_ip6=False
1707 )
Neale Ranns14046982019-07-29 14:49:52 +00001708
Neale Ranns987aea82019-03-27 13:40:35 +00001709 def verify_tun_46(self, p, count=1):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001710 """ipsec 4o6 tunnel basic test"""
Neale Ranns987aea82019-03-27 13:40:35 +00001711 self.vapi.cli("clear errors")
Neale Rannsdd4ccf22020-06-30 07:47:14 +00001712 self.vapi.cli("clear ipsec sa")
Neale Ranns987aea82019-03-27 13:40:35 +00001713 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001714 send_pkts = self.gen_encrypt_pkts(
1715 p,
1716 p.scapy_tun_sa,
1717 self.tun_if,
1718 src=p.remote_tun_if_host4,
1719 dst=self.pg1.remote_ip4,
1720 count=count,
1721 )
Neale Ranns987aea82019-03-27 13:40:35 +00001722 recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1)
1723 for recv_pkt in recv_pkts:
1724 self.assert_equal(recv_pkt[IP].src, p.remote_tun_if_host4)
1725 self.assert_equal(recv_pkt[IP].dst, self.pg1.remote_ip4)
1726 self.assert_packet_checksums_valid(recv_pkt)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001727 send_pkts = self.gen_pkts(
1728 self.pg1,
1729 src=self.pg1.remote_ip4,
1730 dst=p.remote_tun_if_host4,
1731 count=count,
1732 )
Neale Ranns987aea82019-03-27 13:40:35 +00001733 recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if)
1734 for recv_pkt in recv_pkts:
1735 try:
1736 decrypt_pkt = p.vpp_tun_sa.decrypt(recv_pkt[IPv6])
1737 if not decrypt_pkt.haslayer(IP):
1738 decrypt_pkt = IP(decrypt_pkt[Raw].load)
1739 self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip4)
1740 self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host4)
1741 self.assert_packet_checksums_valid(decrypt_pkt)
1742 except:
1743 self.logger.debug(ppp("Unexpected packet:", recv_pkt))
1744 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001745 self.logger.debug(ppp("Decrypted packet:", decrypt_pkt))
Neale Ranns987aea82019-03-27 13:40:35 +00001746 except:
1747 pass
1748 raise
1749 finally:
1750 self.logger.info(self.vapi.ppcli("show error"))
Paul Vinciguerra9673e3e2019-05-10 20:41:08 -04001751 self.logger.info(self.vapi.ppcli("show ipsec all"))
Neale Rannsc87b66c2019-02-07 07:26:12 -08001752 self.verify_counters6(p, p, count)
Klement Sekera10d066e2018-11-13 11:12:57 +01001753
Matthew Smith6f1eb482022-08-09 22:19:38 +00001754 def verify_keepalive(self, p):
1755 # the sizeof Raw is calculated to pad to the minimum ehternet
1756 # frame size of 64 btyes
1757 pkt = (
1758 Ether(src=self.tun_if.remote_mac, dst=self.tun_if.local_mac)
1759 / IPv6(src=p.remote_tun_if_host, dst=self.tun_if.local_ip6)
1760 / UDP(sport=333, dport=4500)
1761 / Raw(b"\xff")
1762 / Padding(0 * 1)
1763 )
1764 self.send_and_assert_no_replies(self.tun_if, pkt * 31)
1765 self.assert_error_counter_equal(
1766 "/err/%s/nat_keepalive" % self.tun6_input_node, 31
1767 )
1768
1769 pkt = (
1770 Ether(src=self.tun_if.remote_mac, dst=self.tun_if.local_mac)
1771 / IPv6(src=p.remote_tun_if_host, dst=self.tun_if.local_ip6)
1772 / UDP(sport=333, dport=4500)
1773 / Raw(b"\xfe")
1774 )
1775 self.send_and_assert_no_replies(self.tun_if, pkt * 31)
1776 self.assert_error_counter_equal("/err/%s/too_short" % self.tun6_input_node, 31)
1777
1778 pkt = (
1779 Ether(src=self.tun_if.remote_mac, dst=self.tun_if.local_mac)
1780 / IPv6(src=p.remote_tun_if_host, dst=self.tun_if.local_ip6)
1781 / UDP(sport=333, dport=4500)
1782 / Raw(b"\xfe")
1783 / Padding(0 * 21)
1784 )
1785 self.send_and_assert_no_replies(self.tun_if, pkt * 31)
1786 self.assert_error_counter_equal("/err/%s/too_short" % self.tun6_input_node, 62)
1787
Neale Ranns2ac885c2019-03-20 18:24:43 +00001788
1789class IpsecTun6Tests(IpsecTun6):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001790 """UT test methods for Tunnel v6"""
Neale Ranns2ac885c2019-03-20 18:24:43 +00001791
1792 def test_tun_basic66(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001793 """ipsec 6o6 tunnel basic test"""
Neale Ranns2ac885c2019-03-20 18:24:43 +00001794 self.verify_tun_66(self.params[socket.AF_INET6], count=1)
1795
Neale Ranns14046982019-07-29 14:49:52 +00001796 def test_tun_reass_basic66(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001797 """ipsec 6o6 tunnel basic reassembly test"""
Neale Ranns14046982019-07-29 14:49:52 +00001798 self.verify_tun_reass_66(self.params[socket.AF_INET6])
1799
Klement Sekera611864f2018-09-26 11:19:00 +02001800 def test_tun_burst66(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001801 """ipsec 6o6 tunnel burst test"""
Neale Ranns2ac885c2019-03-20 18:24:43 +00001802 self.verify_tun_66(self.params[socket.AF_INET6], count=257)
Klement Sekera611864f2018-09-26 11:19:00 +02001803
1804
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001805class IpsecTun6HandoffTests(IpsecTun6):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001806 """UT test methods for Tunnel v6 with multiple workers"""
1807
Klement Sekera8d815022021-03-15 16:58:10 +01001808 vpp_worker_count = 2
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001809
1810 def test_tun_handoff_66(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001811 """ipsec 6o6 tunnel worker hand-off test"""
Brian Russell7a29a2d2021-02-22 18:42:24 +00001812 self.vapi.cli("clear errors")
1813 self.vapi.cli("clear ipsec sa")
1814
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001815 N_PKTS = 15
1816 p = self.params[socket.AF_INET6]
1817
1818 # inject alternately on worker 0 and 1. all counts on the SA
1819 # should be against worker 0
1820 for worker in [0, 1, 0, 1]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001821 send_pkts = self.gen_encrypt_pkts6(
1822 p,
1823 p.scapy_tun_sa,
1824 self.tun_if,
1825 src=p.remote_tun_if_host,
1826 dst=self.pg1.remote_ip6,
1827 count=N_PKTS,
1828 )
1829 recv_pkts = self.send_and_expect(
1830 self.tun_if, send_pkts, self.pg1, worker=worker
1831 )
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001832 self.verify_decrypted6(p, recv_pkts)
1833
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001834 send_pkts = self.gen_pkts6(
1835 p,
1836 self.pg1,
1837 src=self.pg1.remote_ip6,
1838 dst=p.remote_tun_if_host,
1839 count=N_PKTS,
1840 )
1841 recv_pkts = self.send_and_expect(
1842 self.pg1, send_pkts, self.tun_if, worker=worker
1843 )
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001844 self.verify_encrypted6(p, p.vpp_tun_sa, recv_pkts)
1845
1846 # all counts against the first worker that was used
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001847 self.verify_counters6(p, p, 4 * N_PKTS, worker=0)
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001848
1849
1850class IpsecTun4HandoffTests(IpsecTun4):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001851 """UT test methods for Tunnel v4 with multiple workers"""
1852
Klement Sekera8d815022021-03-15 16:58:10 +01001853 vpp_worker_count = 2
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001854
1855 def test_tun_handooff_44(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001856 """ipsec 4o4 tunnel worker hand-off test"""
Brian Russell7a29a2d2021-02-22 18:42:24 +00001857 self.vapi.cli("clear errors")
1858 self.vapi.cli("clear ipsec sa")
1859
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001860 N_PKTS = 15
1861 p = self.params[socket.AF_INET]
1862
1863 # inject alternately on worker 0 and 1. all counts on the SA
1864 # should be against worker 0
1865 for worker in [0, 1, 0, 1]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001866 send_pkts = self.gen_encrypt_pkts(
1867 p,
1868 p.scapy_tun_sa,
1869 self.tun_if,
1870 src=p.remote_tun_if_host,
1871 dst=self.pg1.remote_ip4,
1872 count=N_PKTS,
1873 )
1874 recv_pkts = self.send_and_expect(
1875 self.tun_if, send_pkts, self.pg1, worker=worker
1876 )
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001877 self.verify_decrypted(p, recv_pkts)
1878
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001879 send_pkts = self.gen_pkts(
1880 self.pg1,
1881 src=self.pg1.remote_ip4,
1882 dst=p.remote_tun_if_host,
1883 count=N_PKTS,
1884 )
1885 recv_pkts = self.send_and_expect(
1886 self.pg1, send_pkts, self.tun_if, worker=worker
1887 )
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001888 self.verify_encrypted(p, p.vpp_tun_sa, recv_pkts)
1889
1890 # all counts against the first worker that was used
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001891 self.verify_counters4(p, 4 * N_PKTS, worker=0)
Neale Ranns4a56f4e2019-12-23 04:10:25 +00001892
1893
Neale Ranns53f526b2019-02-25 14:32:02 +00001894class IpsecTun46Tests(IpsecTun4Tests, IpsecTun6Tests):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001895 """UT test methods for Tunnel v6 & v4"""
1896
Klement Sekera611864f2018-09-26 11:19:00 +02001897 pass
1898
Klement Sekera31da2e32018-06-24 22:49:55 +02001899
Zachary Leaf26fec712021-10-26 10:05:58 -05001900class IPSecIPv4Fwd(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001901 """Test IPSec by capturing and verifying IPv4 forwarded pkts"""
1902
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00001903 @classmethod
1904 def setUpConstants(cls):
Zachary Leaf26fec712021-10-26 10:05:58 -05001905 super(IPSecIPv4Fwd, cls).setUpConstants()
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00001906
1907 def setUp(self):
Zachary Leaf26fec712021-10-26 10:05:58 -05001908 super(IPSecIPv4Fwd, self).setUp()
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00001909 # store SPD objects so we can remove configs on tear down
1910 self.spd_objs = []
1911 self.spd_policies = []
1912
1913 def tearDown(self):
1914 # remove SPD policies
1915 for obj in self.spd_policies:
1916 obj.remove_vpp_config()
1917 self.spd_policies = []
1918 # remove SPD items (interface bindings first, then SPD)
1919 for obj in reversed(self.spd_objs):
1920 obj.remove_vpp_config()
1921 self.spd_objs = []
1922 # close down pg intfs
1923 for pg in self.pg_interfaces:
1924 pg.unconfig_ip4()
1925 pg.admin_down()
Zachary Leaf26fec712021-10-26 10:05:58 -05001926 super(IPSecIPv4Fwd, self).tearDown()
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00001927
1928 def create_interfaces(self, num_ifs=2):
1929 # create interfaces pg0 ... pg<num_ifs>
1930 self.create_pg_interfaces(range(num_ifs))
1931 for pg in self.pg_interfaces:
1932 # put the interface up
1933 pg.admin_up()
1934 # configure IPv4 address on the interface
1935 pg.config_ip4()
1936 # resolve ARP, so that we know VPP MAC
1937 pg.resolve_arp()
1938 self.logger.info(self.vapi.ppcli("show int addr"))
1939
1940 def spd_create_and_intf_add(self, spd_id, pg_list):
1941 spd = VppIpsecSpd(self, spd_id)
1942 spd.add_vpp_config()
1943 self.spd_objs.append(spd)
1944 for pg in pg_list:
1945 spdItf = VppIpsecSpdItfBinding(self, spd, pg)
1946 spdItf.add_vpp_config()
1947 self.spd_objs.append(spdItf)
1948
1949 def get_policy(self, policy_type):
1950 e = VppEnum.vl_api_ipsec_spd_action_t
1951 if policy_type == "protect":
1952 return e.IPSEC_API_SPD_ACTION_PROTECT
1953 elif policy_type == "bypass":
1954 return e.IPSEC_API_SPD_ACTION_BYPASS
1955 elif policy_type == "discard":
1956 return e.IPSEC_API_SPD_ACTION_DISCARD
1957 else:
1958 raise Exception("Invalid policy type: %s", policy_type)
1959
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001960 def spd_add_rem_policy(
1961 self,
1962 spd_id,
1963 src_if,
1964 dst_if,
1965 proto,
1966 is_out,
1967 priority,
1968 policy_type,
1969 remove=False,
1970 all_ips=False,
Fan Zhangab0bf0c2022-05-25 20:03:40 +00001971 ip_range=False,
1972 local_ip_start=ip_address("0.0.0.0"),
1973 local_ip_stop=ip_address("255.255.255.255"),
1974 remote_ip_start=ip_address("0.0.0.0"),
1975 remote_ip_stop=ip_address("255.255.255.255"),
1976 remote_port_start=0,
1977 remote_port_stop=65535,
1978 local_port_start=0,
1979 local_port_stop=65535,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001980 ):
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00001981 spd = VppIpsecSpd(self, spd_id)
1982
1983 if all_ips:
1984 src_range_low = ip_address("0.0.0.0")
1985 src_range_high = ip_address("255.255.255.255")
1986 dst_range_low = ip_address("0.0.0.0")
1987 dst_range_high = ip_address("255.255.255.255")
Fan Zhangab0bf0c2022-05-25 20:03:40 +00001988
1989 elif ip_range:
1990 src_range_low = local_ip_start
1991 src_range_high = local_ip_stop
1992 dst_range_low = remote_ip_start
1993 dst_range_high = remote_ip_stop
1994
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00001995 else:
1996 src_range_low = src_if.remote_ip4
1997 src_range_high = src_if.remote_ip4
1998 dst_range_low = dst_if.remote_ip4
1999 dst_range_high = dst_if.remote_ip4
2000
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002001 spdEntry = VppIpsecSpdEntry(
2002 self,
2003 spd,
2004 0,
2005 src_range_low,
2006 src_range_high,
2007 dst_range_low,
2008 dst_range_high,
2009 proto,
2010 priority=priority,
2011 policy=self.get_policy(policy_type),
2012 is_outbound=is_out,
Fan Zhangab0bf0c2022-05-25 20:03:40 +00002013 remote_port_start=remote_port_start,
2014 remote_port_stop=remote_port_stop,
2015 local_port_start=local_port_start,
2016 local_port_stop=local_port_stop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002017 )
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002018
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002019 if remove is False:
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002020 spdEntry.add_vpp_config()
2021 self.spd_policies.append(spdEntry)
2022 else:
2023 spdEntry.remove_vpp_config()
2024 self.spd_policies.remove(spdEntry)
2025 self.logger.info(self.vapi.ppcli("show ipsec all"))
2026 return spdEntry
2027
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002028 def create_stream(self, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=5678):
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002029 packets = []
2030 for i in range(pkt_count):
2031 # create packet info stored in the test case instance
2032 info = self.create_packet_info(src_if, dst_if)
2033 # convert the info into packet payload
2034 payload = self.info_to_payload(info)
2035 # create the packet itself
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002036 p = (
2037 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
2038 / IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4)
2039 / UDP(sport=src_prt, dport=dst_prt)
2040 / Raw(payload)
2041 )
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002042 # store a copy of the packet in the packet info
2043 info.data = p.copy()
2044 # append the packet to the list
2045 packets.append(p)
2046 # return the created packet list
2047 return packets
2048
2049 def verify_capture(self, src_if, dst_if, capture):
2050 packet_info = None
2051 for packet in capture:
2052 try:
2053 ip = packet[IP]
2054 udp = packet[UDP]
2055 # convert the payload to packet info object
2056 payload_info = self.payload_to_info(packet)
2057 # make sure the indexes match
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002058 self.assert_equal(
2059 payload_info.src, src_if.sw_if_index, "source sw_if_index"
2060 )
2061 self.assert_equal(
2062 payload_info.dst, dst_if.sw_if_index, "destination sw_if_index"
2063 )
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002064 packet_info = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002065 src_if.sw_if_index, dst_if.sw_if_index, packet_info
2066 )
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002067 # make sure we didn't run out of saved packets
2068 self.assertIsNotNone(packet_info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002069 self.assert_equal(
2070 payload_info.index, packet_info.index, "packet info index"
2071 )
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002072 saved_packet = packet_info.data # fetch the saved packet
2073 # assert the values match
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002074 self.assert_equal(ip.src, saved_packet[IP].src, "IP source address")
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002075 # ... more assertions here
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002076 self.assert_equal(udp.sport, saved_packet[UDP].sport, "UDP source port")
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002077 except Exception as e:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002078 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002079 raise
2080 remaining_packet = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002081 src_if.sw_if_index, dst_if.sw_if_index, packet_info
2082 )
2083 self.assertIsNone(
2084 remaining_packet,
2085 "Interface %s: Packet expected from interface "
2086 "%s didn't arrive" % (dst_if.name, src_if.name),
2087 )
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002088
2089 def verify_policy_match(self, pkt_count, spdEntry):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002090 self.logger.info("XXXX %s %s", str(spdEntry), str(spdEntry.get_stats()))
2091 matched_pkts = spdEntry.get_stats().get("packets")
2092 self.logger.info("Policy %s matched: %d pkts", str(spdEntry), matched_pkts)
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002093 self.assert_equal(pkt_count, matched_pkts)
2094
Zachary Leaf26fec712021-10-26 10:05:58 -05002095
2096class SpdFlowCacheTemplate(IPSecIPv4Fwd):
2097 @classmethod
2098 def setUpConstants(cls):
2099 super(SpdFlowCacheTemplate, cls).setUpConstants()
2100 # Override this method with required cmdline parameters e.g.
2101 # cls.vpp_cmdline.extend(["ipsec", "{",
2102 # "ipv4-outbound-spd-flow-cache on",
2103 # "}"])
2104 # cls.logger.info("VPP modified cmdline is %s" % " "
2105 # .join(cls.vpp_cmdline))
2106
2107 def setUp(self):
2108 super(SpdFlowCacheTemplate, self).setUp()
2109
2110 def tearDown(self):
2111 super(SpdFlowCacheTemplate, self).tearDown()
2112
Zachary Leaf7cd35f52021-06-25 08:11:15 -05002113 def get_spd_flow_cache_entries(self, outbound):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002114 """'show ipsec spd' output:
Zachary Leaf7cd35f52021-06-25 08:11:15 -05002115 ipv4-inbound-spd-flow-cache-entries: 0
2116 ipv4-outbound-spd-flow-cache-entries: 0
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002117 """
2118 show_ipsec_reply = self.vapi.cli("show ipsec spd")
2119 # match the relevant section of 'show ipsec spd' output
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002120 if outbound:
Zachary Leaf7cd35f52021-06-25 08:11:15 -05002121 regex_match = re.search(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002122 "ipv4-outbound-spd-flow-cache-entries: (.*)",
2123 show_ipsec_reply,
2124 re.DOTALL,
2125 )
Zachary Leaf7cd35f52021-06-25 08:11:15 -05002126 else:
2127 regex_match = re.search(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002128 "ipv4-inbound-spd-flow-cache-entries: (.*)", show_ipsec_reply, re.DOTALL
2129 )
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002130 if regex_match is None:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002131 raise Exception(
2132 "Unable to find spd flow cache entries \
2133 in 'show ipsec spd' CLI output - regex failed to match"
2134 )
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002135 else:
2136 try:
2137 num_entries = int(regex_match.group(1))
2138 except ValueError:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002139 raise Exception(
2140 "Unable to get spd flow cache entries \
2141 from 'show ipsec spd' string: %s",
2142 regex_match.group(0),
2143 )
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002144 self.logger.info("%s", regex_match.group(0))
2145 return num_entries
2146
2147 def verify_num_outbound_flow_cache_entries(self, expected_elements):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002148 self.assertEqual(
2149 self.get_spd_flow_cache_entries(outbound=True), expected_elements
2150 )
Zachary Leaf7cd35f52021-06-25 08:11:15 -05002151
2152 def verify_num_inbound_flow_cache_entries(self, expected_elements):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002153 self.assertEqual(
2154 self.get_spd_flow_cache_entries(outbound=False), expected_elements
2155 )
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002156
2157 def crc32_supported(self):
2158 # lscpu is part of util-linux package, available on all Linux Distros
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002159 stream = os.popen("lscpu")
Govindarajan Mohandoss6d7dfcb2021-03-19 19:20:49 +00002160 cpu_info = stream.read()
2161 # feature/flag "crc32" on Aarch64 and "sse4_2" on x86
2162 # see vppinfra/crc32.h
2163 if "crc32" or "sse4_2" in cpu_info:
2164 self.logger.info("\ncrc32 supported:\n" + cpu_info)
2165 return True
2166 else:
2167 self.logger.info("\ncrc32 NOT supported:\n" + cpu_info)
2168 return False
2169
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002170
Piotr Bronowski651cc012022-07-08 12:45:51 +00002171class IPSecIPv6Fwd(VppTestCase):
2172 """Test IPSec by capturing and verifying IPv6 forwarded pkts"""
2173
2174 @classmethod
2175 def setUpConstants(cls):
2176 super(IPSecIPv6Fwd, cls).setUpConstants()
2177
2178 def setUp(self):
2179 super(IPSecIPv6Fwd, self).setUp()
2180 # store SPD objects so we can remove configs on tear down
2181 self.spd_objs = []
2182 self.spd_policies = []
2183
2184 def tearDown(self):
2185 # remove SPD policies
2186 for obj in self.spd_policies:
2187 obj.remove_vpp_config()
2188 self.spd_policies = []
2189 # remove SPD items (interface bindings first, then SPD)
2190 for obj in reversed(self.spd_objs):
2191 obj.remove_vpp_config()
2192 self.spd_objs = []
2193 # close down pg intfs
2194 for pg in self.pg_interfaces:
2195 pg.unconfig_ip6()
2196 pg.admin_down()
2197 super(IPSecIPv6Fwd, self).tearDown()
2198
2199 def create_interfaces(self, num_ifs=2):
2200 # create interfaces pg0 ... pg<num_ifs>
2201 self.create_pg_interfaces(range(num_ifs))
2202 for pg in self.pg_interfaces:
2203 # put the interface up
2204 pg.admin_up()
2205 # configure IPv6 address on the interface
2206 pg.config_ip6()
2207 pg.resolve_ndp()
2208 self.logger.info(self.vapi.ppcli("show int addr"))
2209
2210 def spd_create_and_intf_add(self, spd_id, pg_list):
2211 spd = VppIpsecSpd(self, spd_id)
2212 spd.add_vpp_config()
2213 self.spd_objs.append(spd)
2214 for pg in pg_list:
2215 spdItf = VppIpsecSpdItfBinding(self, spd, pg)
2216 spdItf.add_vpp_config()
2217 self.spd_objs.append(spdItf)
2218
2219 def get_policy(self, policy_type):
2220 e = VppEnum.vl_api_ipsec_spd_action_t
2221 if policy_type == "protect":
2222 return e.IPSEC_API_SPD_ACTION_PROTECT
2223 elif policy_type == "bypass":
2224 return e.IPSEC_API_SPD_ACTION_BYPASS
2225 elif policy_type == "discard":
2226 return e.IPSEC_API_SPD_ACTION_DISCARD
2227 else:
2228 raise Exception("Invalid policy type: %s", policy_type)
2229
2230 def spd_add_rem_policy(
2231 self,
2232 spd_id,
2233 src_if,
2234 dst_if,
2235 proto,
2236 is_out,
2237 priority,
2238 policy_type,
2239 remove=False,
2240 all_ips=False,
2241 ip_range=False,
2242 local_ip_start=ip_address("0::0"),
2243 local_ip_stop=ip_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
2244 remote_ip_start=ip_address("0::0"),
2245 remote_ip_stop=ip_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
2246 remote_port_start=0,
2247 remote_port_stop=65535,
2248 local_port_start=0,
2249 local_port_stop=65535,
2250 ):
2251 spd = VppIpsecSpd(self, spd_id)
2252
2253 if all_ips:
2254 src_range_low = ip_address("0::0")
2255 src_range_high = ip_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
2256 dst_range_low = ip_address("0::0")
2257 dst_range_high = ip_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
2258
2259 elif ip_range:
2260 src_range_low = local_ip_start
2261 src_range_high = local_ip_stop
2262 dst_range_low = remote_ip_start
2263 dst_range_high = remote_ip_stop
2264
2265 else:
2266 src_range_low = src_if.remote_ip6
2267 src_range_high = src_if.remote_ip6
2268 dst_range_low = dst_if.remote_ip6
2269 dst_range_high = dst_if.remote_ip6
2270
2271 spdEntry = VppIpsecSpdEntry(
2272 self,
2273 spd,
2274 0,
2275 src_range_low,
2276 src_range_high,
2277 dst_range_low,
2278 dst_range_high,
2279 proto,
2280 priority=priority,
2281 policy=self.get_policy(policy_type),
2282 is_outbound=is_out,
2283 remote_port_start=remote_port_start,
2284 remote_port_stop=remote_port_stop,
2285 local_port_start=local_port_start,
2286 local_port_stop=local_port_stop,
2287 )
2288
2289 if remove is False:
2290 spdEntry.add_vpp_config()
2291 self.spd_policies.append(spdEntry)
2292 else:
2293 spdEntry.remove_vpp_config()
2294 self.spd_policies.remove(spdEntry)
2295 self.logger.info(self.vapi.ppcli("show ipsec all"))
2296 return spdEntry
2297
2298 def create_stream(self, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=5678):
2299 packets = []
2300 for i in range(pkt_count):
2301 # create packet info stored in the test case instance
2302 info = self.create_packet_info(src_if, dst_if)
2303 # convert the info into packet payload
2304 payload = self.info_to_payload(info)
2305 # create the packet itself
2306 p = (
2307 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
2308 / IPv6(src=src_if.remote_ip6, dst=dst_if.remote_ip6)
2309 / UDP(sport=src_prt, dport=dst_prt)
2310 / Raw(payload)
2311 )
2312 # store a copy of the packet in the packet info
2313 info.data = p.copy()
2314 # append the packet to the list
2315 packets.append(p)
2316 # return the created packet list
2317 return packets
2318
2319 def verify_capture(self, src_if, dst_if, capture):
2320 packet_info = None
2321 for packet in capture:
2322 try:
2323 ip = packet[IPv6]
2324 udp = packet[UDP]
2325 # convert the payload to packet info object
2326 payload_info = self.payload_to_info(packet)
2327 # make sure the indexes match
2328 self.assert_equal(
2329 payload_info.src, src_if.sw_if_index, "source sw_if_index"
2330 )
2331 self.assert_equal(
2332 payload_info.dst, dst_if.sw_if_index, "destination sw_if_index"
2333 )
2334 packet_info = self.get_next_packet_info_for_interface2(
2335 src_if.sw_if_index, dst_if.sw_if_index, packet_info
2336 )
2337 # make sure we didn't run out of saved packets
2338 self.assertIsNotNone(packet_info)
2339 self.assert_equal(
2340 payload_info.index, packet_info.index, "packet info index"
2341 )
2342 saved_packet = packet_info.data # fetch the saved packet
2343 # assert the values match
2344 self.assert_equal(ip.src, saved_packet[IPv6].src, "IP source address")
2345 # ... more assertions here
2346 self.assert_equal(udp.sport, saved_packet[UDP].sport, "UDP source port")
2347 except Exception as e:
2348 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2349 raise
2350 remaining_packet = self.get_next_packet_info_for_interface2(
2351 src_if.sw_if_index, dst_if.sw_if_index, packet_info
2352 )
2353 self.assertIsNone(
2354 remaining_packet,
2355 "Interface %s: Packet expected from interface "
2356 "%s didn't arrive" % (dst_if.name, src_if.name),
2357 )
2358
2359 def verify_policy_match(self, pkt_count, spdEntry):
2360 self.logger.info("XXXX %s %s", str(spdEntry), str(spdEntry.get_stats()))
2361 matched_pkts = spdEntry.get_stats().get("packets")
2362 self.logger.info("Policy %s matched: %d pkts", str(spdEntry), matched_pkts)
2363 self.assert_equal(pkt_count, matched_pkts)
2364
2365
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002366if __name__ == "__main__":
Klement Sekera31da2e32018-06-24 22:49:55 +02002367 unittest.main(testRunner=VppTestRunner)