blob: eb04df492444aeb1ba3d93b38d98506b29a8a9fe [file] [log] [blame]
Piotr Bronowski993b6be2022-08-31 13:48:14 +00001import socket
2import unittest
3import ipaddress
4
5from util import ppp
Dave Wallace8800f732023-08-31 00:47:44 -04006from asfframework import VppTestRunner
7from template_ipsec import IPSecIPv4Fwd
Piotr Bronowski993b6be2022-08-31 13:48:14 +00008from template_ipsec import IPSecIPv6Fwd
9from test_ipsec_esp import TemplateIpsecEsp
vinay Tripathibc5f5302023-10-20 05:20:47 +000010from template_ipsec import SpdFastPathTemplate
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000011from config import config
Piotr Bronowski993b6be2022-08-31 13:48:14 +000012
13
14def debug_signal_handler(signal, frame):
15 import pdb
16
17 pdb.set_trace()
18
19
20import signal
21
22signal.signal(signal.SIGINT, debug_signal_handler)
23
24
vinay Tripathibc5f5302023-10-20 05:20:47 +000025class SpdFastPathInbound(SpdFastPathTemplate):
Piotr Bronowski993b6be2022-08-31 13:48:14 +000026 # In test cases derived from this class, packets in IPv4 FWD path
27 # are configured to go through IPSec inbound SPD policy lookup.
28 # Note that order in which the rules are applied is
29 # PROTECT, BYPASS, DISCARD. Therefore BYPASS rules take
30 # precedence over DISCARD.
31 #
32 # Override setUpConstants to enable inbound fast path in config
33 @classmethod
34 def setUpConstants(cls):
35 super(SpdFastPathInbound, cls).setUpConstants()
36 cls.vpp_cmdline.extend(["ipsec", "{", "ipv4-inbound-spd-fast-path on", "}"])
37 cls.logger.info("VPP modified cmdline is %s" % " ".join(cls.vpp_cmdline))
38
Piotr Bronowski993b6be2022-08-31 13:48:14 +000039
40class SpdFastPathInboundProtect(TemplateIpsecEsp):
41 @classmethod
42 def setUpConstants(cls):
43 super(SpdFastPathInboundProtect, cls).setUpConstants()
44 cls.vpp_cmdline.extend(["ipsec", "{", "ipv4-inbound-spd-fast-path on", "}"])
45 cls.logger.info("VPP modified cmdline is %s" % " ".join(cls.vpp_cmdline))
46
47 @classmethod
48 def setUpClass(cls):
49 super(SpdFastPathInboundProtect, cls).setUpClass()
50
51 @classmethod
52 def tearDownClass(cls):
53 super(SpdFastPathInboundProtect, cls).tearDownClass()
54
55 def setUp(self):
56 super(SpdFastPathInboundProtect, self).setUp()
57
58 def tearDown(self):
59 self.unconfig_network()
60 super(SpdFastPathInboundProtect, self).tearDown()
61
62
63class SpdFastPathIPv6Inbound(IPSecIPv6Fwd):
64 # In test cases derived from this class, packets in IPvr6 FWD path
65 # are configured to go through IPSec inbound SPD policy lookup.
66 # Note that order in which the rules are applied is
67 # PROTECT, BYPASS, DISCARD. Therefore BYPASS rules take
68 # precedence over DISCARDi.
69
70 # Override setUpConstants to enable inbound fast path in config
71 @classmethod
72 def setUpConstants(cls):
73 super(SpdFastPathIPv6Inbound, cls).setUpConstants()
74 cls.vpp_cmdline.extend(["ipsec", "{", "ipv6-inbound-spd-fast-path on", "}"])
75 cls.logger.info("VPP modified cmdline is %s" % " ".join(cls.vpp_cmdline))
76
77
Piotr Bronowski06abf232022-09-20 14:44:36 +000078class SpdFastPathIPv6InboundProtect(TemplateIpsecEsp):
79 @classmethod
80 def setUpConstants(cls):
81 super(SpdFastPathIPv6InboundProtect, cls).setUpConstants()
82 cls.vpp_cmdline.extend(["ipsec", "{", "ipv6-inbound-spd-fast-path on", "}"])
83 cls.logger.info("VPP modified cmdline is %s" % " ".join(cls.vpp_cmdline))
84
85 @classmethod
86 def setUpClass(cls):
87 super(SpdFastPathIPv6InboundProtect, cls).setUpClass()
88
89 @classmethod
90 def tearDownClass(cls):
91 super(SpdFastPathIPv6InboundProtect, cls).tearDownClass()
92
93 def setUp(self):
94 super(SpdFastPathIPv6InboundProtect, self).setUp()
95
96 def tearDown(self):
97 self.unconfig_network()
98 super(SpdFastPathIPv6InboundProtect, self).tearDown()
99
100
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000101class IPSec4SpdTestCaseBypass(SpdFastPathInbound):
102 """ IPSec/IPv4 inbound: Policy mode test case with fast path \
103 (add bypass)"""
104
105 def test_ipsec_spd_inbound_bypass(self):
106 # In this test case, packets in IPv4 FWD path are configured
107 # to go through IPSec inbound SPD policy lookup.
108 #
109 # 2 inbound SPD rules (1 HIGH and 1 LOW) are added.
110 # - High priority rule action is set to DISCARD.
111 # - Low priority rule action is set to BYPASS.
112 #
113 # Since BYPASS rules take precedence over DISCARD
114 # (the order being PROTECT, BYPASS, DISCARD) we expect the
115 # BYPASS rule to match and traffic to be correctly forwarded.
116 self.create_interfaces(2)
117 pkt_count = 5
118
119 self.spd_create_and_intf_add(1, [self.pg1, self.pg0])
120
121 # create input rules
122 # bypass rule should take precedence over discard rule,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000123 # even though it's lower priority, because for input policies
124 # matching PROTECT policies precedes matching BYPASS policies
125 # which preceeds matching for DISCARD policies.
126 # Any hit stops the process.
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000127 policy_0 = self.spd_add_rem_policy( # inbound, priority 10
128 1,
129 self.pg1,
130 self.pg0,
131 socket.IPPROTO_UDP,
132 is_out=0,
133 priority=10,
134 policy_type="bypass",
135 ip_range=True,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000136 local_ip_start=self.pg1.remote_ip4,
137 local_ip_stop=self.pg1.remote_ip4,
138 remote_ip_start=self.pg0.remote_ip4,
139 remote_ip_stop=self.pg0.remote_ip4,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000140 )
141 policy_1 = self.spd_add_rem_policy( # inbound, priority 15
142 1,
143 self.pg1,
144 self.pg0,
145 socket.IPPROTO_UDP,
146 is_out=0,
147 priority=15,
148 policy_type="discard",
149 ip_range=True,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000150 local_ip_start=self.pg1.remote_ip4,
151 local_ip_stop=self.pg1.remote_ip4,
152 remote_ip_start=self.pg0.remote_ip4,
153 remote_ip_stop=self.pg0.remote_ip4,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000154 )
155
156 # create output rule so we can capture forwarded packets
157 policy_2 = self.spd_add_rem_policy( # outbound, priority 10
158 1,
159 self.pg0,
160 self.pg1,
161 socket.IPPROTO_UDP,
162 is_out=1,
163 priority=10,
164 policy_type="bypass",
165 )
166
167 # create the packet stream
168 packets = self.create_stream(self.pg0, self.pg1, pkt_count)
169 # add the stream to the source interface
170 self.pg0.add_stream(packets)
171 self.pg1.enable_capture()
172 self.pg_start()
173
174 # check capture on pg1
175 capture = self.pg1.get_capture()
176 for packet in capture:
177 try:
178 self.logger.debug(ppp("SPD Add - Got packet:", packet))
179 except Exception:
180 self.logger.error(ppp("Unexpected or invalid packet:", packet))
181 raise
182 self.logger.debug("SPD: Num packets: %s", len(capture.res))
183
184 # verify captured packets
185 self.verify_capture(self.pg0, self.pg1, capture)
186 # verify all policies matched the expected number of times
187 self.verify_policy_match(pkt_count, policy_0)
188 self.verify_policy_match(0, policy_1)
189 self.verify_policy_match(pkt_count, policy_2)
190
191
192class IPSec4SpdTestCaseDiscard(SpdFastPathInbound):
193 """ IPSec/IPv4 inbound: Policy mode test case with fast path \
194 (add discard)"""
195
196 def test_ipsec_spd_inbound_discard(self):
197 # In this test case, packets in IPv4 FWD path are configured
198 # to go through IPSec inbound SPD policy lookup.
199 #
200 # Rule action is set to DISCARD.
201
202 self.create_interfaces(2)
203 pkt_count = 5
204
205 self.spd_create_and_intf_add(1, [self.pg1, self.pg0])
206
207 # create input rules
208 # bypass rule should take precedence over discard rule,
209 # even though it's lower priority
210 policy_0 = self.spd_add_rem_policy( # inbound, priority 10
211 1,
Piotr Bronowski06abf232022-09-20 14:44:36 +0000212 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000213 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000214 socket.IPPROTO_UDP,
215 is_out=0,
216 priority=10,
217 policy_type="discard",
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000218 )
219
220 # create output rule so we can capture forwarded packets
221 policy_1 = self.spd_add_rem_policy( # outbound, priority 10
222 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000223 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000224 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000225 socket.IPPROTO_UDP,
226 is_out=1,
227 priority=10,
228 policy_type="bypass",
229 )
230
231 # create the packet stream
232 packets = self.create_stream(self.pg0, self.pg1, pkt_count)
233 # add the stream to the source interface
234 self.pg0.add_stream(packets)
235 self.pg1.enable_capture()
236 self.pg_start()
237
238 # check capture on pg1
239 capture = self.pg1.assert_nothing_captured()
240
241 # verify all policies matched the expected number of times
242 self.verify_policy_match(pkt_count, policy_0)
243 self.verify_policy_match(0, policy_1)
244
245
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000246@unittest.skipIf(
247 "ping" in config.excluded_plugins, "Exclude tests requiring Ping plugin"
248)
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000249class IPSec4SpdTestCaseProtect(SpdFastPathInboundProtect):
250 """ IPSec/IPv4 inbound: Policy mode test case with fast path \
251 (add protect)"""
252
253 @classmethod
254 def setUpClass(cls):
255 super(IPSec4SpdTestCaseProtect, cls).setUpClass()
256
257 @classmethod
258 def tearDownClass(cls):
259 super(IPSec4SpdTestCaseProtect, cls).tearDownClass()
260
261 def setUp(self):
262 super(IPSec4SpdTestCaseProtect, self).setUp()
263
264 def tearDown(self):
265 super(IPSec4SpdTestCaseProtect, self).tearDown()
266
267 def test_ipsec_spd_inbound_protect(self):
Piotr Bronowski06abf232022-09-20 14:44:36 +0000268 # In this test case, encrypted packets in IPv4
269 # PROTECT path are configured
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000270 # to go through IPSec inbound SPD policy lookup.
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000271
272 pkt_count = 5
273 payload_size = 64
274 p = self.params[socket.AF_INET]
275 send_pkts = self.gen_encrypt_pkts(
276 p,
277 p.scapy_tra_sa,
278 self.tra_if,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000279 src=self.tra_if.remote_ip4,
280 dst=self.tra_if.local_ip4,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000281 count=pkt_count,
282 payload_size=payload_size,
283 )
284 recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if)
285
286 self.logger.info(self.vapi.ppcli("show error"))
287 self.logger.info(self.vapi.ppcli("show ipsec all"))
288
289 pkts = p.tra_sa_in.get_stats()["packets"]
290 self.assertEqual(
291 pkts,
292 pkt_count,
293 "incorrect SA in counts: expected %d != %d" % (pkt_count, pkts),
294 )
295 pkts = p.tra_sa_out.get_stats()["packets"]
296 self.assertEqual(
297 pkts,
298 pkt_count,
299 "incorrect SA out counts: expected %d != %d" % (pkt_count, pkts),
300 )
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100301 self.assertEqual(p.tra_sa_out.get_err("lost"), 0)
302 self.assertEqual(p.tra_sa_in.get_err("lost"), 0)
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000303
304
305class IPSec4SpdTestCaseAddIPRange(SpdFastPathInbound):
306 """ IPSec/IPv4 inbound: Policy mode test case with fast path \
307 (add ips range with any port rule)"""
308
309 def test_ipsec_spd_inbound_add(self):
310 # In this test case, packets in IPv4 FWD path are configured
311 # to go through IPSec inbound SPD policy lookup.
312 # 2 SPD bypass rules (1 for inbound and 1 for outbound) are added.
313 # Traffic sent on pg0 interface should match fast path priority
314 # rule and should be sent out on pg1 interface.
315 self.create_interfaces(2)
316 pkt_count = 5
317 s_ip_s1 = ipaddress.ip_address(self.pg0.remote_ip4)
318 s_ip_e1 = ipaddress.ip_address(int(s_ip_s1) + 5)
319 d_ip_s1 = ipaddress.ip_address(self.pg1.remote_ip4)
320 d_ip_e1 = ipaddress.ip_address(int(d_ip_s1) + 0)
321
322 s_ip_s0 = ipaddress.ip_address(self.pg0.remote_ip4)
323 s_ip_e0 = ipaddress.ip_address(int(s_ip_s0) + 6)
324 d_ip_s0 = ipaddress.ip_address(self.pg1.remote_ip4)
325 d_ip_e0 = ipaddress.ip_address(int(d_ip_s0) + 0)
326 self.spd_create_and_intf_add(1, [self.pg1, self.pg0])
327
328 policy_0 = self.spd_add_rem_policy( # inbound fast path, priority 10
329 1,
330 self.pg0,
331 self.pg1,
332 socket.IPPROTO_UDP,
333 is_out=0,
334 priority=10,
335 policy_type="bypass",
336 ip_range=True,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000337 local_ip_start=d_ip_s0,
338 local_ip_stop=d_ip_e0,
339 remote_ip_start=s_ip_s0,
340 remote_ip_stop=s_ip_e0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000341 )
342 policy_1 = self.spd_add_rem_policy( # outbound, priority 5
343 1,
344 self.pg0,
345 self.pg1,
346 socket.IPPROTO_UDP,
347 is_out=1,
348 priority=5,
349 policy_type="bypass",
350 ip_range=True,
351 local_ip_start=s_ip_s1,
352 local_ip_stop=s_ip_e1,
353 remote_ip_start=d_ip_s1,
354 remote_ip_stop=d_ip_e1,
355 )
356
357 # create the packet stream
358 packets = self.create_stream(self.pg0, self.pg1, pkt_count)
359 # add the stream to the source interface + enable capture
360 self.pg0.add_stream(packets)
361 self.pg0.enable_capture()
362 self.pg1.enable_capture()
363 # start the packet generator
364 self.pg_start()
365 # get capture
366 capture = self.pg1.get_capture()
367 for packet in capture:
368 try:
369 self.logger.debug(ppp("SPD - Got packet:", packet))
370 except Exception:
371 self.logger.error(ppp("Unexpected or invalid packet:", packet))
372 raise
373 self.logger.debug("SPD: Num packets: %s", len(capture.res))
374
375 # assert nothing captured on pg0
376 self.pg0.assert_nothing_captured()
377 # verify captured packets
378 self.verify_capture(self.pg0, self.pg1, capture)
379 # verify all policies matched the expected number of times
380 self.verify_policy_match(pkt_count, policy_0)
381 self.verify_policy_match(pkt_count, policy_1)
382
383
384class IPSec4SpdTestCaseAddAll(SpdFastPathInbound):
385 """ IPSec/IPv4 inbound: Policy mode test case with fast path \
386 (add all ips ports rule)"""
387
388 def test_ipsec_spd_inbound_add(self):
389 # In this test case, packets in IPv4 FWD path are configured
390 # to go through IPSec inbound SPD policy lookup.
391 # 2 SPD rules (1 HIGH and 1 LOW) are added.
392 # Low priority rule action is set to BYPASS all ips.
393 # High priority rule action is set to DISCARD all ips.
394 # Traffic not sent on pg0 interface when HIGH discard priority rule is added.
395 # Then LOW priority
396 # rule is added and send the same traffic to pg0, this time expect
397 # the traffic is bypassed as bypass takes priority over discard.
398 self.create_interfaces(2)
399 pkt_count = 5
400 self.spd_create_and_intf_add(1, [self.pg0, self.pg1])
401
402 policy_0 = self.spd_add_rem_policy( # inbound, priority 20
403 1,
404 self.pg0,
405 self.pg1,
406 socket.IPPROTO_UDP,
407 is_out=0,
408 priority=20,
409 policy_type="discard",
410 all_ips=True,
411 )
412
413 policy_1 = self.spd_add_rem_policy( # inbound, priority 20
414 1,
415 self.pg0,
416 self.pg1,
417 socket.IPPROTO_UDP,
418 is_out=True,
419 priority=5,
420 policy_type="bypass",
421 all_ips=True,
422 )
423
424 # create the packet stream
425 packets = self.create_stream(self.pg0, self.pg1, pkt_count)
426 # add the stream to the source interface + enable capture
427 self.pg0.add_stream(packets)
428 self.pg0.enable_capture()
429 self.pg1.enable_capture()
430 # start the packet generator
431 self.pg_start()
432 # assert nothing captured on pg0 and pg1
433 self.pg0.assert_nothing_captured()
434 self.pg1.assert_nothing_captured()
435
436 policy_2 = self.spd_add_rem_policy( # inbound, priority 10
437 1,
438 self.pg0,
439 self.pg1,
440 socket.IPPROTO_UDP,
441 is_out=0,
442 priority=10,
443 policy_type="bypass",
444 all_ips=True,
445 )
446
447 # create the packet stream
448 packets = self.create_stream(self.pg0, self.pg1, pkt_count)
449 # add the stream to the source interface + enable capture
450 self.pg0.add_stream(packets)
451 self.pg0.enable_capture()
452 self.pg1.enable_capture()
453 # start the packet generator
454 self.pg_start()
455 # get capture
456 capture = self.pg1.get_capture(expected_count=pkt_count)
457 for packet in capture:
458 try:
459 self.logger.debug(ppp("SPD - Got packet:", packet))
460 except Exception:
461 self.logger.error(ppp("Unexpected or invalid packet:", packet))
462 raise
463 self.logger.debug("SPD: Num packets: %s", len(capture.res))
464
465 # assert nothing captured on pg0
466 self.pg0.assert_nothing_captured()
467 # verify all policies matched the expected number of times
468 self.verify_policy_match(pkt_count, policy_2)
469
470
471class IPSec4SpdTestCaseRemove(SpdFastPathInbound):
472 """ IPSec/IPv4 inbound: Policy mode test case with fast path \
473 (remove rule)"""
474
475 def test_ipsec_spd_inbound_remove(self):
476 # In this test case, packets in IPv4 FWD path are configured
477 # to go through IPSec inbound SPD policy lookup.
478 # 2 SPD rules (1 HIGH and 1 LOW) are added.
479 # High priority rule action is set to BYPASS.
480 # Low priority rule action is set to DISCARD.
481 # High priority rule is then removed.
482 # Traffic sent on pg0 interface should match low priority
483 # rule and should be discarded after SPD lookup.
484 self.create_interfaces(2)
485 pkt_count = 5
486 self.spd_create_and_intf_add(1, [self.pg0, self.pg1])
487 policy_0 = self.spd_add_rem_policy( # inbound, priority 10
488 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000489 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000490 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000491 socket.IPPROTO_UDP,
492 is_out=0,
493 priority=10,
494 policy_type="bypass",
495 )
496 policy_1 = self.spd_add_rem_policy( # inbound, priority 5
497 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000498 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000499 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000500 socket.IPPROTO_UDP,
501 is_out=0,
502 priority=5,
503 policy_type="discard",
504 )
505
506 policy_out = self.spd_add_rem_policy( # outbound, priority 10
507 1,
508 self.pg0,
509 self.pg1,
510 socket.IPPROTO_UDP,
511 is_out=1,
512 priority=10,
513 policy_type="bypass",
514 )
515
516 # create the packet stream
517 packets = self.create_stream(self.pg0, self.pg1, pkt_count)
518 # add the stream to the source interface + enable capture
519 self.pg0.add_stream(packets)
520 self.pg0.enable_capture()
521 self.pg1.enable_capture()
522 # start the packet generator
523 self.pg_start()
524 # get capture
525 capture = self.pg1.get_capture()
526 for packet in capture:
527 try:
528 self.logger.debug(ppp("SPD - Got packet:", packet))
529 except Exception:
530 self.logger.error(ppp("Unexpected or invalid packet:", packet))
531 raise
532
533 # assert nothing captured on pg0
534 self.pg0.assert_nothing_captured()
535 # verify capture on pg1
536 self.logger.debug("SPD: Num packets: %s", len(capture.res))
537 self.verify_capture(self.pg0, self.pg1, capture)
538 # verify all policies matched the expected number of times
539 self.verify_policy_match(pkt_count, policy_0)
540 self.verify_policy_match(0, policy_1)
541 # now remove the bypass rule
542 self.spd_add_rem_policy( # outbound, priority 10
543 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000544 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000545 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000546 socket.IPPROTO_UDP,
547 is_out=0,
548 priority=10,
549 policy_type="bypass",
550 remove=True,
551 )
552
553 # resend the same packets
554 self.pg0.add_stream(packets)
555 self.pg0.enable_capture() # flush the old captures
556 self.pg1.enable_capture()
557 self.pg_start()
558 # assert nothing captured on pg0
559 self.pg0.assert_nothing_captured()
560 # all packets will be dropped by SPD rule
561 self.pg1.assert_nothing_captured()
562 # verify all policies matched the expected number of times
563 self.verify_policy_match(pkt_count, policy_0)
564 self.verify_policy_match(pkt_count, policy_1)
565
566
567class IPSec4SpdTestCaseReadd(SpdFastPathInbound):
568 """ IPSec/IPv4 inbound: Policy mode test case with fast path \
569 (add, remove, re-add)"""
570
571 def test_ipsec_spd_inbound_readd(self):
572 # In this test case, packets in IPv4 FWD path are configured
573 # to go through IPSec outbound SPD policy lookup.
574 # 2 SPD rules (1 HIGH and 1 LOW) are added.
575 # High priority rule action is set to BYPASS.
576 # Low priority rule action is set to DISCARD.
577 # Traffic sent on pg0 interface should match high priority
578 # rule and should be sent out on pg1 interface.
579 # High priority rule is then removed.
580 # Traffic sent on pg0 interface should match low priority
581 # rule and should be discarded after SPD lookup.
582 # Readd high priority rule.
583 # Traffic sent on pg0 interface should match high priority
584 # rule and should be sent out on pg1 interface.
585 self.create_interfaces(2)
586 pkt_count = 5
587 self.spd_create_and_intf_add(1, [self.pg0, self.pg1])
588 policy_0 = self.spd_add_rem_policy( # inbound, priority 10
589 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000590 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000591 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000592 socket.IPPROTO_UDP,
593 is_out=0,
594 priority=10,
595 policy_type="bypass",
596 )
597 policy_1 = self.spd_add_rem_policy( # inbound, priority 5
598 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000599 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000600 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000601 socket.IPPROTO_UDP,
602 is_out=0,
603 priority=5,
604 policy_type="discard",
605 )
606 policy_2 = self.spd_add_rem_policy( # outbound, priority 10
607 1,
608 self.pg0,
609 self.pg1,
610 socket.IPPROTO_UDP,
611 is_out=1,
612 priority=10,
613 policy_type="bypass",
614 )
615
616 # create the packet stream
617 packets = self.create_stream(self.pg0, self.pg1, pkt_count)
618 # add the stream to the source interface + enable capture
619 self.pg0.add_stream(packets)
620 self.pg0.enable_capture()
621 self.pg1.enable_capture()
622 # start the packet generator
623 self.pg_start()
624 # get capture
625 capture = self.pg1.get_capture()
626 for packet in capture:
627 try:
628 self.logger.debug(ppp("SPD - Got packet:", packet))
629 except Exception:
630 self.logger.error(ppp("Unexpected or invalid packet:", packet))
631 raise
632 self.logger.debug("SPD: Num packets: %s", len(capture.res))
633
634 # assert nothing captured on pg0
635 self.pg0.assert_nothing_captured()
636 # verify capture on pg1
637 self.verify_capture(self.pg0, self.pg1, capture)
638 # verify all policies matched the expected number of times
639 self.verify_policy_match(pkt_count, policy_0)
640 self.verify_policy_match(0, policy_1)
641 # remove the bypass rule, leaving only the discard rule
642 self.spd_add_rem_policy( # inbound, priority 10
643 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000644 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000645 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000646 socket.IPPROTO_UDP,
647 is_out=0,
648 priority=10,
649 policy_type="bypass",
650 remove=True,
651 )
652
653 # resend the same packets
654 self.pg0.add_stream(packets)
655 self.pg0.enable_capture() # flush the old captures
656 self.pg1.enable_capture()
657 self.pg_start()
658
659 # assert nothing captured on pg0
660 self.pg0.assert_nothing_captured()
661 # all packets will be dropped by SPD rule
662 self.pg1.assert_nothing_captured()
663 # verify all policies matched the expected number of times
664 self.verify_policy_match(pkt_count, policy_0)
665 self.verify_policy_match(pkt_count, policy_1)
666
667 # now readd the bypass rule
668 policy_0 = self.spd_add_rem_policy( # outbound, priority 10
669 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000670 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000671 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000672 socket.IPPROTO_UDP,
673 is_out=0,
674 priority=10,
675 policy_type="bypass",
676 )
677
678 # resend the same packets
679 self.pg0.add_stream(packets)
680 self.pg0.enable_capture() # flush the old captures
681 self.pg1.enable_capture()
682 self.pg_start()
683
684 # get capture
685 capture = self.pg1.get_capture(pkt_count)
686 for packet in capture:
687 try:
688 self.logger.debug(ppp("SPD - Got packet:", packet))
689 except Exception:
690 self.logger.error(ppp("Unexpected or invalid packet:", packet))
691 raise
692 self.logger.debug("SPD: Num packets: %s", len(capture.res))
693
694 # assert nothing captured on pg0
695 self.pg0.assert_nothing_captured()
696 # verify captured packets
697 self.verify_capture(self.pg0, self.pg1, capture)
698 # verify all policies matched the expected number of times
699 self.verify_policy_match(pkt_count, policy_0)
700 self.verify_policy_match(pkt_count, policy_1)
701
702
703class IPSec4SpdTestCaseMultiple(SpdFastPathInbound):
704 """ IPSec/IPv4 inbound: Policy mode test case with fast path \
705 (multiple interfaces, multiple rules)"""
706
707 def test_ipsec_spd_inbound_multiple(self):
708 # In this test case, packets in IPv4 FWD path are configured to go
709 # through IPSec outbound SPD policy lookup.
710 # Multiples rules on multiple interfaces are tested at the same time.
711 # 3x interfaces are configured, binding the same SPD to each.
712 # Each interface has 2 SPD rules (1 BYPASS and 1 DISCARD).
713 # On pg0 & pg1, the BYPASS rule is HIGH priority
714 # On pg2, the DISCARD rule is HIGH priority
715 # Traffic should be received on pg0 & pg1 and dropped on pg2.
716 self.create_interfaces(3)
717 pkt_count = 5
718 # bind SPD to all interfaces
719 self.spd_create_and_intf_add(1, self.pg_interfaces)
720 # add rules on all interfaces
721 policy_01 = self.spd_add_rem_policy( # inbound, priority 10
722 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000723 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000724 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000725 socket.IPPROTO_UDP,
726 is_out=0,
727 priority=10,
728 policy_type="bypass",
729 )
730 policy_02 = self.spd_add_rem_policy( # inbound, priority 5
731 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000732 self.pg1,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000733 self.pg0,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000734 socket.IPPROTO_UDP,
735 is_out=0,
736 priority=5,
737 policy_type="discard",
738 )
739
740 policy_11 = self.spd_add_rem_policy( # inbound, priority 10
741 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000742 self.pg2,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000743 self.pg1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000744 socket.IPPROTO_UDP,
745 is_out=0,
746 priority=10,
747 policy_type="bypass",
748 )
749 policy_12 = self.spd_add_rem_policy( # inbound, priority 5
750 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000751 self.pg2,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000752 self.pg1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000753 socket.IPPROTO_UDP,
754 is_out=0,
755 priority=5,
756 policy_type="discard",
757 )
758
759 policy_21 = self.spd_add_rem_policy( # inbound, priority 5
760 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000761 self.pg0,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000762 self.pg2,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000763 socket.IPPROTO_UDP,
764 is_out=0,
765 priority=5,
766 policy_type="bypass",
767 )
768 policy_22 = self.spd_add_rem_policy( # inbound, priority 10
769 1,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000770 self.pg0,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000771 self.pg2,
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000772 socket.IPPROTO_UDP,
773 is_out=0,
774 priority=10,
775 policy_type="discard",
776 )
777
778 # interfaces bound to an SPD, will by default drop outbound
779 # traffic with no matching policies. add catch-all outbound
780 # bypass rule to SPD:
781 self.spd_add_rem_policy( # outbound, all interfaces
782 1,
783 None,
784 None,
785 socket.IPPROTO_UDP,
786 is_out=1,
787 priority=10,
788 policy_type="bypass",
789 all_ips=True,
790 )
791
792 # create the packet streams
793 packets0 = self.create_stream(self.pg0, self.pg1, pkt_count)
794 packets1 = self.create_stream(self.pg1, self.pg2, pkt_count)
795 packets2 = self.create_stream(self.pg2, self.pg0, pkt_count)
796 # add the streams to the source interfaces
797 self.pg0.add_stream(packets0)
798 self.pg1.add_stream(packets1)
799 self.pg2.add_stream(packets2)
800 # enable capture on all interfaces
801 for pg in self.pg_interfaces:
802 pg.enable_capture()
803 # start the packet generator
804 self.pg_start()
805
806 # get captures
807 if_caps = []
808 for pg in [self.pg1, self.pg2]: # we are expecting captures on pg1/pg2
809 if_caps.append(pg.get_capture())
810 for packet in if_caps[-1]:
811 try:
812 self.logger.debug(ppp("SPD - Got packet:", packet))
813 except Exception:
814 self.logger.error(ppp("Unexpected or invalid packet:", packet))
815 raise
816 self.logger.debug("SPD: Num packets: %s", len(if_caps[0].res))
817 self.logger.debug("SPD: Num packets: %s", len(if_caps[1].res))
818
819 # verify captures that matched BYPASS rule
820 self.verify_capture(self.pg0, self.pg1, if_caps[0])
821 self.verify_capture(self.pg1, self.pg2, if_caps[1])
822 # verify that traffic to pg0 matched BYPASS rule
823 # although DISCARD rule had higher prioriy and was not dropped
824 self.verify_policy_match(pkt_count, policy_21)
825
826 # verify all packets that were expected to match rules, matched
827 # pg0 -> pg1
828 self.verify_policy_match(pkt_count, policy_01)
829 self.verify_policy_match(0, policy_02)
830 # pg1 -> pg2
831 self.verify_policy_match(pkt_count, policy_11)
832 self.verify_policy_match(0, policy_12)
833 # pg2 -> pg0
834 self.verify_policy_match(0, policy_22)
835
836
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000837@unittest.skipIf(
838 "ping" in config.excluded_plugins, "Exclude tests requiring Ping plugin"
839)
Piotr Bronowski06abf232022-09-20 14:44:36 +0000840class IPSec6SpdTestCaseProtect(SpdFastPathIPv6InboundProtect):
841 """ IPSec/IPv6 inbound: Policy mode test case with fast path \
842 (add protect)"""
843
844 @classmethod
845 def setUpClass(cls):
846 super(IPSec6SpdTestCaseProtect, cls).setUpClass()
847
848 @classmethod
849 def tearDownClass(cls):
850 super(IPSec6SpdTestCaseProtect, cls).tearDownClass()
851
852 def setUp(self):
853 super(IPSec6SpdTestCaseProtect, self).setUp()
854
855 def tearDown(self):
856 super(IPSec6SpdTestCaseProtect, self).tearDown()
857
858 def test_ipsec6_spd_inbound_protect(self):
859 pkt_count = 5
860 payload_size = 64
861 p = self.params[socket.AF_INET6]
862 send_pkts = self.gen_encrypt_pkts6(
863 p,
864 p.scapy_tra_sa,
865 self.tra_if,
Piotr Bronowski1d9780a2022-10-21 15:48:55 +0000866 src=self.tra_if.remote_ip6,
867 dst=self.tra_if.local_ip6,
Piotr Bronowski06abf232022-09-20 14:44:36 +0000868 count=pkt_count,
869 payload_size=payload_size,
870 )
871 recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if)
872
873 self.logger.info(self.vapi.ppcli("show error"))
874 self.logger.info(self.vapi.ppcli("show ipsec all"))
875 pkts = p.tra_sa_in.get_stats()["packets"]
876 self.assertEqual(
877 pkts,
878 pkt_count,
879 "incorrect SA in counts: expected %d != %d" % (pkt_count, pkts),
880 )
881 pkts = p.tra_sa_out.get_stats()["packets"]
882 self.assertEqual(
883 pkts,
884 pkt_count,
885 "incorrect SA out counts: expected %d != %d" % (pkt_count, pkts),
886 )
Arthur de Kerhorad95b062022-11-16 19:12:05 +0100887 self.assertEqual(p.tra_sa_out.get_err("lost"), 0)
888 self.assertEqual(p.tra_sa_in.get_err("lost"), 0)
Piotr Bronowski06abf232022-09-20 14:44:36 +0000889
890
Piotr Bronowski993b6be2022-08-31 13:48:14 +0000891if __name__ == "__main__":
892 unittest.main(testRunner=VppTestRunner)