blob: 84d5cb6cd88221273d1e2e5021e7d28035ba54b3 [file] [log] [blame]
Neale Ranns44db1ca2020-12-24 09:16:09 +00001#!/usr/bin/env python3
2
3import unittest
4
5from scapy.layers.inet import IP, UDP
6from scapy.layers.inet6 import IPv6, Raw
Dave Wallace8800f732023-08-31 00:47:44 -04007from scapy.layers.l2 import Ether, ARP
Neale Ranns44db1ca2020-12-24 09:16:09 +00008
Neale Ranns89d939e2021-06-07 09:34:07 +00009from util import reassemble4
Neale Ranns44db1ca2020-12-24 09:16:09 +000010from vpp_object import VppObject
Dave Wallace8800f732023-08-31 00:47:44 -040011from framework import VppTestCase
12from asfframework import VppTestRunner
Neale Ranns89d939e2021-06-07 09:34:07 +000013from vpp_ipip_tun_interface import VppIpIpTunInterface
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020014from template_ipsec import (
15 TemplateIpsec,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020016 IpsecTun4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020017)
18from template_ipsec import (
19 TemplateIpsec,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020020 IpsecTun4,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020021)
Neale Ranns89d939e2021-06-07 09:34:07 +000022from test_ipsec_tun_if_esp import TemplateIpsecItf4
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000023from config import config
Neale Ranns44db1ca2020-12-24 09:16:09 +000024
25
26class VppLcpPair(VppObject):
27 def __init__(self, test, phy, host):
28 self._test = test
29 self.phy = phy
30 self.host = host
31
32 def add_vpp_config(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020033 self._test.vapi.cli("test lcp add phy %s host %s" % (self.phy, self.host))
Neale Ranns44db1ca2020-12-24 09:16:09 +000034 self._test.registry.register(self, self._test.logger)
35 return self
36
37 def remove_vpp_config(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020038 self._test.vapi.cli("test lcp del phy %s host %s" % (self.phy, self.host))
Neale Ranns44db1ca2020-12-24 09:16:09 +000039
40 def object_id(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020041 return "lcp:%d:%d" % (self.phy.sw_if_index, self.host.sw_if_index)
Neale Ranns44db1ca2020-12-24 09:16:09 +000042
43 def query_vpp_config(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020044 pairs = list(self._test.vapi.vpp.details_iter(self._test.vapi.lcp_itf_pair_get))
Neale Ranns44db1ca2020-12-24 09:16:09 +000045
46 for p in pairs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020047 if (
48 p.phy_sw_if_index == self.phy.sw_if_index
49 and p.host_sw_if_index == self.host.sw_if_index
50 ):
Neale Ranns44db1ca2020-12-24 09:16:09 +000051 return True
52 return False
53
54
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000055@unittest.skipIf("linux-cp" in config.excluded_plugins, "Exclude linux-cp plugin tests")
Neale Ranns44db1ca2020-12-24 09:16:09 +000056class TestLinuxCP(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020057 """Linux Control Plane"""
Neale Ranns44db1ca2020-12-24 09:16:09 +000058
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020059 extra_vpp_plugin_config = [
60 "plugin",
61 "linux_cp_plugin.so",
62 "{",
63 "enable",
64 "}",
65 "plugin",
66 "linux_cp_unittest_plugin.so",
67 "{",
68 "enable",
69 "}",
70 ]
Neale Ranns44db1ca2020-12-24 09:16:09 +000071
72 @classmethod
73 def setUpClass(cls):
74 super(TestLinuxCP, cls).setUpClass()
75
76 @classmethod
77 def tearDownClass(cls):
78 super(TestLinuxCP, cls).tearDownClass()
79
80 def setUp(self):
81 super(TestLinuxCP, self).setUp()
82
Neale Ranns89d939e2021-06-07 09:34:07 +000083 # create 4 pg interfaces so we can create two pairs
Neale Ranns44db1ca2020-12-24 09:16:09 +000084 self.create_pg_interfaces(range(4))
85
Neale Ranns89d939e2021-06-07 09:34:07 +000086 # create on ip4 and one ip6 pg tun
87 self.pg_interfaces += self.create_pg_ip4_interfaces(range(4, 5))
88 self.pg_interfaces += self.create_pg_ip6_interfaces(range(5, 6))
89
Neale Ranns44db1ca2020-12-24 09:16:09 +000090 for i in self.pg_interfaces:
91 i.admin_up()
92
93 def tearDown(self):
94 for i in self.pg_interfaces:
95 i.admin_down()
96 super(TestLinuxCP, self).tearDown()
97
98 def test_linux_cp_tap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020099 """Linux CP TAP"""
Neale Ranns44db1ca2020-12-24 09:16:09 +0000100
101 #
102 # Setup
103 #
104
105 arp_opts = {"who-has": 1, "is-at": 2}
106
107 # create two pairs, wihch a bunch of hots on the phys
108 hosts = [self.pg0, self.pg1]
109 phys = [self.pg2, self.pg3]
110 N_HOSTS = 4
111
112 for phy in phys:
113 phy.config_ip4()
114 phy.generate_remote_hosts(4)
115 phy.configure_ipv4_neighbors()
116
117 pair1 = VppLcpPair(self, phys[0], hosts[0]).add_vpp_config()
118 pair2 = VppLcpPair(self, phys[1], hosts[1]).add_vpp_config()
119
120 self.logger.info(self.vapi.cli("sh lcp adj verbose"))
121 self.logger.info(self.vapi.cli("sh lcp"))
122
123 #
124 # Traffic Tests
125 #
126
127 # hosts to phys
128 for phy, host in zip(phys, hosts):
129 for j in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200130 p = (
Steven Luonge4238aa2024-04-19 09:49:20 -0700131 Ether(src=phy.local_mac, dst=host.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200132 / IP(src=phy.local_ip4, dst=phy.remote_hosts[j].ip4)
133 / UDP(sport=1234, dport=1234)
134 / Raw()
135 )
Neale Ranns44db1ca2020-12-24 09:16:09 +0000136
137 rxs = self.send_and_expect(host, [p], phy)
138
139 # verify packet is unchanged
140 for rx in rxs:
141 self.assertEqual(p.show2(True), rx.show2(True))
142
143 # ARPs x-connect to phy
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200144 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=phy.remote_hosts[j].mac) / ARP(
145 op="who-has",
146 hwdst=phy.remote_hosts[j].mac,
147 hwsrc=phy.local_mac,
148 psrc=phy.local_ip4,
149 pdst=phy.remote_hosts[j].ip4,
150 )
Neale Ranns44db1ca2020-12-24 09:16:09 +0000151
152 rxs = self.send_and_expect(host, [p], phy)
153
154 # verify packet is unchanged
155 for rx in rxs:
156 self.assertEqual(p.show2(True), rx.show2(True))
157
158 # phy to host
159 for phy, host in zip(phys, hosts):
160 for j in range(N_HOSTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200161 p = (
162 Ether(dst=phy.local_mac, src=phy.remote_hosts[j].mac)
163 / IP(dst=phy.local_ip4, src=phy.remote_hosts[j].ip4)
164 / UDP(sport=1234, dport=1234)
165 / Raw()
166 )
Neale Ranns44db1ca2020-12-24 09:16:09 +0000167
168 rxs = self.send_and_expect(phy, [p], host)
169
170 # verify packet is unchanged
171 for rx in rxs:
172 self.assertEqual(p.show2(True), rx.show2(True))
173
174 # ARPs rx'd on the phy are sent to the host
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200175 p = Ether(dst="ff:ff:ff:ff:ff:ff", src=phy.remote_hosts[j].mac) / ARP(
176 op="is-at",
177 hwsrc=phy.remote_hosts[j].mac,
178 hwdst=phy.local_mac,
179 pdst=phy.local_ip4,
180 psrc=phy.remote_hosts[j].ip4,
181 )
Neale Ranns44db1ca2020-12-24 09:16:09 +0000182
183 rxs = self.send_and_expect(phy, [p], host)
184
185 # verify packet is unchanged
186 for rx in rxs:
187 self.assertEqual(p.show2(True), rx.show2(True))
188
189 # cleanup
190 for phy in phys:
191 phy.unconfig_ip4()
192
Neale Ranns89d939e2021-06-07 09:34:07 +0000193 def test_linux_cp_tun(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200194 """Linux CP TUN"""
Neale Ranns89d939e2021-06-07 09:34:07 +0000195
196 #
197 # Setup
198 #
199 N_PKTS = 31
200
201 # create two pairs, wihch a bunch of hots on the phys
202 hosts = [self.pg4, self.pg5]
203 phy = self.pg2
204
205 phy.config_ip4()
206 phy.config_ip6()
207 phy.resolve_arp()
208 phy.resolve_ndp()
209
210 tun4 = VppIpIpTunInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200211 self, phy, phy.local_ip4, phy.remote_ip4
212 ).add_vpp_config()
Neale Ranns89d939e2021-06-07 09:34:07 +0000213 tun6 = VppIpIpTunInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200214 self, phy, phy.local_ip6, phy.remote_ip6
215 ).add_vpp_config()
Neale Ranns89d939e2021-06-07 09:34:07 +0000216 tuns = [tun4, tun6]
217
218 tun4.admin_up()
219 tun4.config_ip4()
220 tun6.admin_up()
221 tun6.config_ip6()
222
223 pair1 = VppLcpPair(self, tuns[0], hosts[0]).add_vpp_config()
224 pair2 = VppLcpPair(self, tuns[1], hosts[1]).add_vpp_config()
225
226 self.logger.info(self.vapi.cli("sh lcp adj verbose"))
227 self.logger.info(self.vapi.cli("sh lcp"))
228 self.logger.info(self.vapi.cli("sh ip punt redirect"))
229
230 #
231 # Traffic Tests
232 #
233
234 # host to phy for v4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200235 p = IP(src=tun4.local_ip4, dst="2.2.2.2") / UDP(sport=1234, dport=1234) / Raw()
Neale Ranns89d939e2021-06-07 09:34:07 +0000236
237 rxs = self.send_and_expect(self.pg4, p * N_PKTS, phy)
238
239 # verify inner packet is unchanged and has the tunnel encap
240 for rx in rxs:
241 self.assertEqual(rx[Ether].dst, phy.remote_mac)
242 self.assertEqual(rx[IP].dst, phy.remote_ip4)
243 self.assertEqual(rx[IP].src, phy.local_ip4)
244 inner = IP(rx[IP].payload)
245 self.assertEqual(inner.src, tun4.local_ip4)
246 self.assertEqual(inner.dst, "2.2.2.2")
247
248 # host to phy for v6
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200249 p = IPv6(src=tun6.local_ip6, dst="2::2") / UDP(sport=1234, dport=1234) / Raw()
Neale Ranns89d939e2021-06-07 09:34:07 +0000250
251 rxs = self.send_and_expect(self.pg5, p * N_PKTS, phy)
252
253 # verify inner packet is unchanged and has the tunnel encap
254 for rx in rxs:
255 self.assertEqual(rx[IPv6].dst, phy.remote_ip6)
256 self.assertEqual(rx[IPv6].src, phy.local_ip6)
257 inner = IPv6(rx[IPv6].payload)
258 self.assertEqual(inner.src, tun6.local_ip6)
259 self.assertEqual(inner.dst, "2::2")
260
261 # phy to host v4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200262 p = (
263 Ether(dst=phy.local_mac, src=phy.remote_mac)
264 / IP(dst=phy.local_ip4, src=phy.remote_ip4)
265 / IP(dst=tun4.local_ip4, src=tun4.remote_ip4)
266 / UDP(sport=1234, dport=1234)
267 / Raw()
268 )
Neale Ranns89d939e2021-06-07 09:34:07 +0000269
270 rxs = self.send_and_expect(phy, p * N_PKTS, self.pg4)
271 for rx in rxs:
272 rx = IP(rx)
273 self.assertEqual(rx[IP].dst, tun4.local_ip4)
274 self.assertEqual(rx[IP].src, tun4.remote_ip4)
275
276 # phy to host v6
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200277 p = (
278 Ether(dst=phy.local_mac, src=phy.remote_mac)
279 / IPv6(dst=phy.local_ip6, src=phy.remote_ip6)
280 / IPv6(dst=tun6.local_ip6, src=tun6.remote_ip6)
281 / UDP(sport=1234, dport=1234)
282 / Raw()
283 )
Neale Ranns89d939e2021-06-07 09:34:07 +0000284
285 rxs = self.send_and_expect(phy, p * N_PKTS, self.pg5)
286 for rx in rxs:
287 rx = IPv6(rx)
288 self.assertEqual(rx[IPv6].dst, tun6.local_ip6)
289 self.assertEqual(rx[IPv6].src, tun6.remote_ip6)
290
291 # cleanup
292 phy.unconfig_ip4()
293 phy.unconfig_ip6()
294
295 tun4.unconfig_ip4()
296 tun6.unconfig_ip6()
297
298
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000299@unittest.skipIf("linux-cp" in config.excluded_plugins, "Exclude linux-cp plugin tests")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200300class TestLinuxCPIpsec(TemplateIpsec, TemplateIpsecItf4, IpsecTun4):
301 """IPsec Interface IPv4"""
Neale Ranns89d939e2021-06-07 09:34:07 +0000302
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200303 extra_vpp_plugin_config = [
304 "plugin",
305 "linux_cp_plugin.so",
306 "{",
307 "enable",
308 "}",
309 "plugin",
310 "linux_cp_unittest_plugin.so",
311 "{",
312 "enable",
313 "}",
314 ]
Neale Ranns89d939e2021-06-07 09:34:07 +0000315
316 def setUp(self):
317 super(TestLinuxCPIpsec, self).setUp()
318
319 self.tun_if = self.pg0
320 self.pg_interfaces += self.create_pg_ip4_interfaces(range(3, 4))
321 self.pg_interfaces += self.create_pg_ip6_interfaces(range(4, 5))
322
323 def tearDown(self):
324 super(TestLinuxCPIpsec, self).tearDown()
325
326 def verify_encrypted(self, p, sa, rxs):
327 decrypt_pkts = []
328 for rx in rxs:
329 if p.nat_header:
330 self.assertEqual(rx[UDP].dport, 4500)
331 self.assert_packet_checksums_valid(rx)
332 self.assertEqual(len(rx) - len(Ether()), rx[IP].len)
333 try:
334 rx_ip = rx[IP]
335 decrypt_pkt = p.vpp_tun_sa.decrypt(rx_ip)
336 if not decrypt_pkt.haslayer(IP):
337 decrypt_pkt = IP(decrypt_pkt[Raw].load)
338 if rx_ip.proto == socket.IPPROTO_ESP:
339 self.verify_esp_padding(sa, rx_ip[ESP].data, decrypt_pkt)
340 decrypt_pkts.append(decrypt_pkt)
341 self.assert_equal(decrypt_pkt.src, p.tun_if.local_ip4)
342 self.assert_equal(decrypt_pkt.dst, p.tun_if.remote_ip4)
343 except:
344 self.logger.debug(ppp("Unexpected packet:", rx))
345 try:
346 self.logger.debug(ppp("Decrypted packet:", decrypt_pkt))
347 except:
348 pass
349 raise
350 pkts = reassemble4(decrypt_pkts)
351 for pkt in pkts:
352 self.assert_packet_checksums_valid(pkt)
353
354 def verify_decrypted(self, p, rxs):
355 for rx in rxs:
356 rx = IP(rx)
357 self.assert_equal(rx[IP].src, p.tun_if.remote_ip4)
358 self.assert_equal(rx[IP].dst, p.tun_if.local_ip4)
359 self.assert_packet_checksums_valid(rx)
360
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200361 def gen_encrypt_pkts(self, p, sa, sw_intf, src, dst, count=1, payload_size=54):
362 return [
363 Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac)
364 / sa.encrypt(
365 IP(src=src, dst=dst)
366 / UDP(sport=1111, dport=2222)
367 / Raw(b"X" * payload_size)
368 )
369 for i in range(count)
370 ]
Neale Ranns89d939e2021-06-07 09:34:07 +0000371
372 def test_linux_cp_ipsec4_tun(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200373 """Linux CP Ipsec TUN"""
Neale Ranns89d939e2021-06-07 09:34:07 +0000374
375 #
376 # Setup
377 #
378 N_PKTS = 31
379
380 # the pg that paris with the tunnel
381 self.host = self.pg3
382
383 # tunnel and protection setup
384 p = self.ipv4_params
385
386 self.config_network(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200387 self.config_sa_tun(p, self.pg0.local_ip4, self.pg0.remote_ip4)
Neale Ranns89d939e2021-06-07 09:34:07 +0000388 self.config_protect(p)
389
390 pair = VppLcpPair(self, p.tun_if, self.host).add_vpp_config()
391
Neale Rannsa360e6f2021-11-09 16:15:48 +0000392 self.logger.info(self.vapi.cli("sh int addr"))
Neale Ranns89d939e2021-06-07 09:34:07 +0000393 self.logger.info(self.vapi.cli("sh lcp"))
394 self.logger.info(self.vapi.cli("sh ip punt redirect"))
395
396 #
397 # Traffic Tests
398 #
399
400 # host to phy for v4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200401 pkt = (
402 IP(src=p.tun_if.local_ip4, dst=p.tun_if.remote_ip4)
403 / UDP(sport=1234, dport=1234)
404 / Raw()
405 )
Neale Ranns89d939e2021-06-07 09:34:07 +0000406
407 rxs = self.send_and_expect(self.host, pkt * N_PKTS, self.tun_if)
408 self.verify_encrypted(p, p.vpp_tun_sa, rxs)
409
410 # phy to host for v4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200411 pkts = self.gen_encrypt_pkts(
412 p,
413 p.scapy_tun_sa,
414 self.tun_if,
415 src=p.tun_if.remote_ip4,
416 dst=p.tun_if.local_ip4,
417 count=N_PKTS,
418 )
Neale Rannsa360e6f2021-11-09 16:15:48 +0000419 rxs = self.send_and_expect(self.tun_if, pkts, self.host)
420 self.verify_decrypted(p, rxs)
Neale Ranns89d939e2021-06-07 09:34:07 +0000421
422 # cleanup
423 pair.remove_vpp_config()
424 self.unconfig_protect(p)
425 self.unconfig_sa(p)
426 self.unconfig_network(p)
427
Neale Ranns44db1ca2020-12-24 09:16:09 +0000428
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200429if __name__ == "__main__":
Neale Ranns44db1ca2020-12-24 09:16:09 +0000430 unittest.main(testRunner=VppTestRunner)