blob: ff6023cea26987cfd295529362d17ab25d4115c8 [file] [log] [blame]
Neale Ranns44db1ca2020-12-24 09:16:09 +00001#!/usr/bin/env python3
2
3import unittest
Dave Wallacecf9356d2024-07-23 01:28:19 -04004import socket
Neale Ranns44db1ca2020-12-24 09:16:09 +00005
6from scapy.layers.inet import IP, UDP
7from scapy.layers.inet6 import IPv6, Raw
Dave Wallace8800f732023-08-31 00:47:44 -04008from scapy.layers.l2 import Ether, ARP
Neale Ranns44db1ca2020-12-24 09:16:09 +00009
Neale Ranns89d939e2021-06-07 09:34:07 +000010from util import reassemble4
Neale Ranns44db1ca2020-12-24 09:16:09 +000011from vpp_object import VppObject
Dave Wallace8800f732023-08-31 00:47:44 -040012from framework import VppTestCase
13from asfframework import VppTestRunner
Neale Ranns89d939e2021-06-07 09:34:07 +000014from vpp_ipip_tun_interface import VppIpIpTunInterface
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020015from template_ipsec import (
16 TemplateIpsec,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020017 IpsecTun4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020018)
19from template_ipsec import (
20 TemplateIpsec,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020021 IpsecTun4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020022)
Neale Ranns89d939e2021-06-07 09:34:07 +000023from test_ipsec_tun_if_esp import TemplateIpsecItf4
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000024from config import config
Neale Ranns44db1ca2020-12-24 09:16:09 +000025
26
27class VppLcpPair(VppObject):
28 def __init__(self, test, phy, host):
29 self._test = test
30 self.phy = phy
31 self.host = host
32
33 def add_vpp_config(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020034 self._test.vapi.cli("test lcp add phy %s host %s" % (self.phy, self.host))
Neale Ranns44db1ca2020-12-24 09:16:09 +000035 self._test.registry.register(self, self._test.logger)
36 return self
37
38 def remove_vpp_config(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020039 self._test.vapi.cli("test lcp del phy %s host %s" % (self.phy, self.host))
Neale Ranns44db1ca2020-12-24 09:16:09 +000040
41 def object_id(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020042 return "lcp:%d:%d" % (self.phy.sw_if_index, self.host.sw_if_index)
Neale Ranns44db1ca2020-12-24 09:16:09 +000043
44 def query_vpp_config(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020045 pairs = list(self._test.vapi.vpp.details_iter(self._test.vapi.lcp_itf_pair_get))
Neale Ranns44db1ca2020-12-24 09:16:09 +000046
47 for p in pairs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020048 if (
49 p.phy_sw_if_index == self.phy.sw_if_index
50 and p.host_sw_if_index == self.host.sw_if_index
51 ):
Neale Ranns44db1ca2020-12-24 09:16:09 +000052 return True
53 return False
54
55
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000056@unittest.skipIf("linux-cp" in config.excluded_plugins, "Exclude linux-cp plugin tests")
Neale Ranns44db1ca2020-12-24 09:16:09 +000057class TestLinuxCP(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020058 """Linux Control Plane"""
Neale Ranns44db1ca2020-12-24 09:16:09 +000059
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020060 extra_vpp_plugin_config = [
61 "plugin",
62 "linux_cp_plugin.so",
63 "{",
64 "enable",
65 "}",
66 "plugin",
67 "linux_cp_unittest_plugin.so",
68 "{",
69 "enable",
70 "}",
71 ]
Neale Ranns44db1ca2020-12-24 09:16:09 +000072
73 @classmethod
74 def setUpClass(cls):
75 super(TestLinuxCP, cls).setUpClass()
76
77 @classmethod
78 def tearDownClass(cls):
79 super(TestLinuxCP, cls).tearDownClass()
80
81 def setUp(self):
82 super(TestLinuxCP, self).setUp()
83
Neale Ranns89d939e2021-06-07 09:34:07 +000084 # create 4 pg interfaces so we can create two pairs
Neale Ranns44db1ca2020-12-24 09:16:09 +000085 self.create_pg_interfaces(range(4))
86
Neale Ranns89d939e2021-06-07 09:34:07 +000087 # create on ip4 and one ip6 pg tun
88 self.pg_interfaces += self.create_pg_ip4_interfaces(range(4, 5))
89 self.pg_interfaces += self.create_pg_ip6_interfaces(range(5, 6))
90
Neale Ranns44db1ca2020-12-24 09:16:09 +000091 for i in self.pg_interfaces:
92 i.admin_up()
93
94 def tearDown(self):
95 for i in self.pg_interfaces:
96 i.admin_down()
97 super(TestLinuxCP, self).tearDown()
98
99 def test_linux_cp_tap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200100 """Linux CP TAP"""
Neale Ranns44db1ca2020-12-24 09:16:09 +0000101
102 #
103 # Setup
104 #
105
106 arp_opts = {"who-has": 1, "is-at": 2}
107
108 # create two pairs, wihch a bunch of hots on the phys
109 hosts = [self.pg0, self.pg1]
110 phys = [self.pg2, self.pg3]
111 N_HOSTS = 4
112
113 for phy in phys:
114 phy.config_ip4()
115 phy.generate_remote_hosts(4)
116 phy.configure_ipv4_neighbors()
117
118 pair1 = VppLcpPair(self, phys[0], hosts[0]).add_vpp_config()
119 pair2 = VppLcpPair(self, phys[1], hosts[1]).add_vpp_config()
120
121 self.logger.info(self.vapi.cli("sh lcp adj verbose"))
122 self.logger.info(self.vapi.cli("sh lcp"))
123
124 #
125 # Traffic Tests
126 #
127
128 # hosts to phys
129 for phy, host in zip(phys, hosts):
130 for j in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200131 p = (
Steven Luonge4238aa2024-04-19 09:49:20 -0700132 Ether(src=phy.local_mac, dst=host.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200133 / IP(src=phy.local_ip4, dst=phy.remote_hosts[j].ip4)
134 / UDP(sport=1234, dport=1234)
135 / Raw()
136 )
Neale Ranns44db1ca2020-12-24 09:16:09 +0000137
138 rxs = self.send_and_expect(host, [p], phy)
139
140 # verify packet is unchanged
141 for rx in rxs:
142 self.assertEqual(p.show2(True), rx.show2(True))
143
144 # ARPs x-connect to phy
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200145 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=phy.remote_hosts[j].mac) / ARP(
146 op="who-has",
147 hwdst=phy.remote_hosts[j].mac,
148 hwsrc=phy.local_mac,
149 psrc=phy.local_ip4,
150 pdst=phy.remote_hosts[j].ip4,
151 )
Neale Ranns44db1ca2020-12-24 09:16:09 +0000152
153 rxs = self.send_and_expect(host, [p], phy)
154
155 # verify packet is unchanged
156 for rx in rxs:
157 self.assertEqual(p.show2(True), rx.show2(True))
158
159 # phy to host
160 for phy, host in zip(phys, hosts):
161 for j in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200162 p = (
163 Ether(dst=phy.local_mac, src=phy.remote_hosts[j].mac)
164 / IP(dst=phy.local_ip4, src=phy.remote_hosts[j].ip4)
165 / UDP(sport=1234, dport=1234)
166 / Raw()
167 )
Neale Ranns44db1ca2020-12-24 09:16:09 +0000168
169 rxs = self.send_and_expect(phy, [p], host)
170
171 # verify packet is unchanged
172 for rx in rxs:
173 self.assertEqual(p.show2(True), rx.show2(True))
174
175 # ARPs rx'd on the phy are sent to the host
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200176 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=phy.remote_hosts[j].mac) / ARP(
177 op="is-at",
178 hwsrc=phy.remote_hosts[j].mac,
179 hwdst=phy.local_mac,
180 pdst=phy.local_ip4,
181 psrc=phy.remote_hosts[j].ip4,
182 )
Neale Ranns44db1ca2020-12-24 09:16:09 +0000183
184 rxs = self.send_and_expect(phy, [p], host)
185
186 # verify packet is unchanged
187 for rx in rxs:
188 self.assertEqual(p.show2(True), rx.show2(True))
189
190 # cleanup
191 for phy in phys:
192 phy.unconfig_ip4()
193
Neale Ranns89d939e2021-06-07 09:34:07 +0000194 def test_linux_cp_tun(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200195 """Linux CP TUN"""
Neale Ranns89d939e2021-06-07 09:34:07 +0000196
197 #
198 # Setup
199 #
200 N_PKTS = 31
201
202 # create two pairs, wihch a bunch of hots on the phys
203 hosts = [self.pg4, self.pg5]
204 phy = self.pg2
205
206 phy.config_ip4()
207 phy.config_ip6()
208 phy.resolve_arp()
209 phy.resolve_ndp()
210
211 tun4 = VppIpIpTunInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200212 self, phy, phy.local_ip4, phy.remote_ip4
213 ).add_vpp_config()
Neale Ranns89d939e2021-06-07 09:34:07 +0000214 tun6 = VppIpIpTunInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200215 self, phy, phy.local_ip6, phy.remote_ip6
216 ).add_vpp_config()
Neale Ranns89d939e2021-06-07 09:34:07 +0000217 tuns = [tun4, tun6]
218
219 tun4.admin_up()
220 tun4.config_ip4()
221 tun6.admin_up()
222 tun6.config_ip6()
223
224 pair1 = VppLcpPair(self, tuns[0], hosts[0]).add_vpp_config()
225 pair2 = VppLcpPair(self, tuns[1], hosts[1]).add_vpp_config()
226
227 self.logger.info(self.vapi.cli("sh lcp adj verbose"))
228 self.logger.info(self.vapi.cli("sh lcp"))
229 self.logger.info(self.vapi.cli("sh ip punt redirect"))
230
231 #
232 # Traffic Tests
233 #
234
235 # host to phy for v4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200236 p = IP(src=tun4.local_ip4, dst="2.2.2.2") / UDP(sport=1234, dport=1234) / Raw()
Neale Ranns89d939e2021-06-07 09:34:07 +0000237
238 rxs = self.send_and_expect(self.pg4, p * N_PKTS, phy)
239
240 # verify inner packet is unchanged and has the tunnel encap
241 for rx in rxs:
242 self.assertEqual(rx[Ether].dst, phy.remote_mac)
243 self.assertEqual(rx[IP].dst, phy.remote_ip4)
244 self.assertEqual(rx[IP].src, phy.local_ip4)
Dave Wallacecf9356d2024-07-23 01:28:19 -0400245 inner = IP(bytes(rx[IP].payload))
Neale Ranns89d939e2021-06-07 09:34:07 +0000246 self.assertEqual(inner.src, tun4.local_ip4)
247 self.assertEqual(inner.dst, "2.2.2.2")
248
249 # host to phy for v6
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200250 p = IPv6(src=tun6.local_ip6, dst="2::2") / UDP(sport=1234, dport=1234) / Raw()
Neale Ranns89d939e2021-06-07 09:34:07 +0000251
252 rxs = self.send_and_expect(self.pg5, p * N_PKTS, phy)
253
254 # verify inner packet is unchanged and has the tunnel encap
255 for rx in rxs:
256 self.assertEqual(rx[IPv6].dst, phy.remote_ip6)
257 self.assertEqual(rx[IPv6].src, phy.local_ip6)
Dave Wallacecf9356d2024-07-23 01:28:19 -0400258 inner = IPv6(bytes(rx[IPv6].payload))
Neale Ranns89d939e2021-06-07 09:34:07 +0000259 self.assertEqual(inner.src, tun6.local_ip6)
260 self.assertEqual(inner.dst, "2::2")
261
262 # phy to host v4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200263 p = (
264 Ether(dst=phy.local_mac, src=phy.remote_mac)
265 / IP(dst=phy.local_ip4, src=phy.remote_ip4)
266 / IP(dst=tun4.local_ip4, src=tun4.remote_ip4)
267 / UDP(sport=1234, dport=1234)
268 / Raw()
269 )
Neale Ranns89d939e2021-06-07 09:34:07 +0000270
271 rxs = self.send_and_expect(phy, p * N_PKTS, self.pg4)
272 for rx in rxs:
Dave Wallacecf9356d2024-07-23 01:28:19 -0400273 rx = IP(bytes(rx))
Neale Ranns89d939e2021-06-07 09:34:07 +0000274 self.assertEqual(rx[IP].dst, tun4.local_ip4)
275 self.assertEqual(rx[IP].src, tun4.remote_ip4)
276
277 # phy to host v6
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200278 p = (
279 Ether(dst=phy.local_mac, src=phy.remote_mac)
280 / IPv6(dst=phy.local_ip6, src=phy.remote_ip6)
281 / IPv6(dst=tun6.local_ip6, src=tun6.remote_ip6)
282 / UDP(sport=1234, dport=1234)
283 / Raw()
284 )
Neale Ranns89d939e2021-06-07 09:34:07 +0000285
286 rxs = self.send_and_expect(phy, p * N_PKTS, self.pg5)
287 for rx in rxs:
Dave Wallacecf9356d2024-07-23 01:28:19 -0400288 rx = IPv6(bytes(rx))
Neale Ranns89d939e2021-06-07 09:34:07 +0000289 self.assertEqual(rx[IPv6].dst, tun6.local_ip6)
290 self.assertEqual(rx[IPv6].src, tun6.remote_ip6)
291
292 # cleanup
293 phy.unconfig_ip4()
294 phy.unconfig_ip6()
295
296 tun4.unconfig_ip4()
297 tun6.unconfig_ip6()
298
299
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000300@unittest.skipIf("linux-cp" in config.excluded_plugins, "Exclude linux-cp plugin tests")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200301class TestLinuxCPIpsec(TemplateIpsec, TemplateIpsecItf4, IpsecTun4):
302 """IPsec Interface IPv4"""
Neale Ranns89d939e2021-06-07 09:34:07 +0000303
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200304 extra_vpp_plugin_config = [
305 "plugin",
306 "linux_cp_plugin.so",
307 "{",
308 "enable",
309 "}",
310 "plugin",
311 "linux_cp_unittest_plugin.so",
312 "{",
313 "enable",
314 "}",
315 ]
Neale Ranns89d939e2021-06-07 09:34:07 +0000316
317 def setUp(self):
318 super(TestLinuxCPIpsec, self).setUp()
319
320 self.tun_if = self.pg0
321 self.pg_interfaces += self.create_pg_ip4_interfaces(range(3, 4))
322 self.pg_interfaces += self.create_pg_ip6_interfaces(range(4, 5))
323
324 def tearDown(self):
325 super(TestLinuxCPIpsec, self).tearDown()
326
327 def verify_encrypted(self, p, sa, rxs):
328 decrypt_pkts = []
329 for rx in rxs:
330 if p.nat_header:
331 self.assertEqual(rx[UDP].dport, 4500)
332 self.assert_packet_checksums_valid(rx)
333 self.assertEqual(len(rx) - len(Ether()), rx[IP].len)
334 try:
335 rx_ip = rx[IP]
336 decrypt_pkt = p.vpp_tun_sa.decrypt(rx_ip)
337 if not decrypt_pkt.haslayer(IP):
338 decrypt_pkt = IP(decrypt_pkt[Raw].load)
339 if rx_ip.proto == socket.IPPROTO_ESP:
340 self.verify_esp_padding(sa, rx_ip[ESP].data, decrypt_pkt)
341 decrypt_pkts.append(decrypt_pkt)
342 self.assert_equal(decrypt_pkt.src, p.tun_if.local_ip4)
343 self.assert_equal(decrypt_pkt.dst, p.tun_if.remote_ip4)
344 except:
345 self.logger.debug(ppp("Unexpected packet:", rx))
346 try:
347 self.logger.debug(ppp("Decrypted packet:", decrypt_pkt))
348 except:
349 pass
350 raise
351 pkts = reassemble4(decrypt_pkts)
352 for pkt in pkts:
353 self.assert_packet_checksums_valid(pkt)
354
355 def verify_decrypted(self, p, rxs):
356 for rx in rxs:
Dave Wallacecf9356d2024-07-23 01:28:19 -0400357 rx = IP(bytes(rx))
Neale Ranns89d939e2021-06-07 09:34:07 +0000358 self.assert_equal(rx[IP].src, p.tun_if.remote_ip4)
359 self.assert_equal(rx[IP].dst, p.tun_if.local_ip4)
360 self.assert_packet_checksums_valid(rx)
361
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200362 def gen_encrypt_pkts(self, p, sa, sw_intf, src, dst, count=1, payload_size=54):
363 return [
364 Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac)
365 / sa.encrypt(
366 IP(src=src, dst=dst)
367 / UDP(sport=1111, dport=2222)
368 / Raw(b"X" * payload_size)
369 )
370 for i in range(count)
371 ]
Neale Ranns89d939e2021-06-07 09:34:07 +0000372
373 def test_linux_cp_ipsec4_tun(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200374 """Linux CP Ipsec TUN"""
Neale Ranns89d939e2021-06-07 09:34:07 +0000375
376 #
377 # Setup
378 #
379 N_PKTS = 31
380
381 # the pg that paris with the tunnel
382 self.host = self.pg3
383
384 # tunnel and protection setup
385 p = self.ipv4_params
386
387 self.config_network(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200388 self.config_sa_tun(p, self.pg0.local_ip4, self.pg0.remote_ip4)
Neale Ranns89d939e2021-06-07 09:34:07 +0000389 self.config_protect(p)
390
391 pair = VppLcpPair(self, p.tun_if, self.host).add_vpp_config()
392
Neale Rannsa360e6f2021-11-09 16:15:48 +0000393 self.logger.info(self.vapi.cli("sh int addr"))
Neale Ranns89d939e2021-06-07 09:34:07 +0000394 self.logger.info(self.vapi.cli("sh lcp"))
395 self.logger.info(self.vapi.cli("sh ip punt redirect"))
396
397 #
398 # Traffic Tests
399 #
400
401 # host to phy for v4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200402 pkt = (
403 IP(src=p.tun_if.local_ip4, dst=p.tun_if.remote_ip4)
404 / UDP(sport=1234, dport=1234)
405 / Raw()
406 )
Neale Ranns89d939e2021-06-07 09:34:07 +0000407
408 rxs = self.send_and_expect(self.host, pkt * N_PKTS, self.tun_if)
409 self.verify_encrypted(p, p.vpp_tun_sa, rxs)
410
411 # phy to host for v4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200412 pkts = self.gen_encrypt_pkts(
413 p,
414 p.scapy_tun_sa,
415 self.tun_if,
416 src=p.tun_if.remote_ip4,
417 dst=p.tun_if.local_ip4,
418 count=N_PKTS,
419 )
Neale Rannsa360e6f2021-11-09 16:15:48 +0000420 rxs = self.send_and_expect(self.tun_if, pkts, self.host)
421 self.verify_decrypted(p, rxs)
Neale Ranns89d939e2021-06-07 09:34:07 +0000422
423 # cleanup
424 pair.remove_vpp_config()
425 self.unconfig_protect(p)
426 self.unconfig_sa(p)
427 self.unconfig_network(p)
428
Neale Ranns44db1ca2020-12-24 09:16:09 +0000429
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200430if __name__ == "__main__":
Neale Ranns44db1ca2020-12-24 09:16:09 +0000431 unittest.main(testRunner=VppTestRunner)