1 # Copyright (c) 2020 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """IPsec utilities library."""
18 from enum import Enum, IntEnum
20 from random import choice
21 from string import ascii_letters
23 from ipaddress import ip_network, ip_address
25 from resources.libraries.python.IPUtil import IPUtil
26 from resources.libraries.python.InterfaceUtil import InterfaceUtil, \
28 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
29 from resources.libraries.python.ssh import scp_node
30 from resources.libraries.python.topology import Topology
31 from resources.libraries.python.VatExecutor import VatExecutor
35 """Generate random string as a key.
37 :param length: Length of generated payload.
39 :returns: The generated payload.
43 choice(ascii_letters) for _ in range(length)
44 ).encode(encoding=u"utf-8")
47 class PolicyAction(Enum):
49 BYPASS = (u"bypass", 0)
50 DISCARD = (u"discard", 1)
51 PROTECT = (u"protect", 3)
53 def __init__(self, policy_name, policy_int_repr):
54 self.policy_name = policy_name
55 self.policy_int_repr = policy_int_repr
58 class CryptoAlg(Enum):
59 """Encryption algorithms."""
60 AES_CBC_128 = (u"aes-cbc-128", 1, u"AES-CBC", 16)
61 AES_CBC_256 = (u"aes-cbc-256", 3, u"AES-CBC", 32)
62 AES_GCM_128 = (u"aes-gcm-128", 7, u"AES-GCM", 16)
63 AES_GCM_256 = (u"aes-gcm-256", 9, u"AES-GCM", 32)
65 def __init__(self, alg_name, alg_int_repr, scapy_name, key_len):
66 self.alg_name = alg_name
67 self.alg_int_repr = alg_int_repr
68 self.scapy_name = scapy_name
69 self.key_len = key_len
73 """Integrity algorithm."""
74 SHA_256_128 = (u"sha-256-128", 4, u"SHA2-256-128", 32)
75 SHA_512_256 = (u"sha-512-256", 6, u"SHA2-512-256", 64)
77 def __init__(self, alg_name, alg_int_repr, scapy_name, key_len):
78 self.alg_name = alg_name
79 self.alg_int_repr = alg_int_repr
80 self.scapy_name = scapy_name
81 self.key_len = key_len
84 class IPsecProto(IntEnum):
90 class IPsecSadFlags(IntEnum):
91 """IPsec Security Association Database flags."""
92 IPSEC_API_SAD_FLAG_NONE = 0
93 IPSEC_API_SAD_FLAG_IS_TUNNEL = 4
94 IPSEC_API_SAD_FLAG_IS_TUNNEL_V6 = 8
98 """IPsec utilities."""
101 def policy_action_bypass():
102 """Return policy action bypass.
104 :returns: PolicyAction enum BYPASS object.
107 return PolicyAction.BYPASS
110 def policy_action_discard():
111 """Return policy action discard.
113 :returns: PolicyAction enum DISCARD object.
116 return PolicyAction.DISCARD
119 def policy_action_protect():
120 """Return policy action protect.
122 :returns: PolicyAction enum PROTECT object.
125 return PolicyAction.PROTECT
128 def crypto_alg_aes_cbc_128():
129 """Return encryption algorithm aes-cbc-128.
131 :returns: CryptoAlg enum AES_CBC_128 object.
134 return CryptoAlg.AES_CBC_128
137 def crypto_alg_aes_cbc_256():
138 """Return encryption algorithm aes-cbc-256.
140 :returns: CryptoAlg enum AES_CBC_256 object.
143 return CryptoAlg.AES_CBC_256
146 def crypto_alg_aes_gcm_128():
147 """Return encryption algorithm aes-gcm-128.
149 :returns: CryptoAlg enum AES_GCM_128 object.
152 return CryptoAlg.AES_GCM_128
155 def crypto_alg_aes_gcm_256():
156 """Return encryption algorithm aes-gcm-256.
158 :returns: CryptoAlg enum AES_GCM_128 object.
161 return CryptoAlg.AES_GCM_256
164 def get_crypto_alg_key_len(crypto_alg):
165 """Return encryption algorithm key length.
167 :param crypto_alg: Encryption algorithm.
168 :type crypto_alg: CryptoAlg
169 :returns: Key length.
172 return crypto_alg.key_len
175 def get_crypto_alg_scapy_name(crypto_alg):
176 """Return encryption algorithm scapy name.
178 :param crypto_alg: Encryption algorithm.
179 :type crypto_alg: CryptoAlg
180 :returns: Algorithm scapy name.
183 return crypto_alg.scapy_name
186 def integ_alg_sha_256_128():
187 """Return integrity algorithm SHA-256-128.
189 :returns: IntegAlg enum SHA_256_128 object.
192 return IntegAlg.SHA_256_128
195 def integ_alg_sha_512_256():
196 """Return integrity algorithm SHA-512-256.
198 :returns: IntegAlg enum SHA_512_256 object.
201 return IntegAlg.SHA_512_256
204 def get_integ_alg_key_len(integ_alg):
205 """Return integrity algorithm key length.
207 :param integ_alg: Integrity algorithm.
208 :type integ_alg: IntegAlg
209 :returns: Key length.
212 return integ_alg.key_len
215 def get_integ_alg_scapy_name(integ_alg):
216 """Return integrity algorithm scapy name.
218 :param integ_alg: Integrity algorithm.
219 :type integ_alg: IntegAlg
220 :returns: Algorithm scapy name.
223 return integ_alg.scapy_name
226 def ipsec_proto_esp():
227 """Return IPSec protocol ESP.
229 :returns: IPsecProto enum ESP object.
232 return int(IPsecProto.ESP)
235 def ipsec_proto_ah():
236 """Return IPSec protocol AH.
238 :returns: IPsecProto enum AH object.
241 return int(IPsecProto.SEC_AH)
244 def vpp_ipsec_select_backend(node, protocol, index=1):
245 """Select IPsec backend.
247 :param node: VPP node to select IPsec backend on.
248 :param protocol: IPsec protocol.
249 :param index: Backend index.
251 :type protocol: IPsecProto
253 :raises RuntimeError: If failed to select IPsec backend or if no API
256 cmd = u"ipsec_select_backend"
257 err_msg = f"Failed to select IPsec backend on host {node[u'host']}"
262 with PapiSocketExecutor(node) as papi_exec:
263 papi_exec.add(cmd, **args).get_reply(err_msg)
266 def vpp_ipsec_add_sad_entry(
267 node, sad_id, spi, crypto_alg, crypto_key, integ_alg=None,
268 integ_key=u"", tunnel_src=None, tunnel_dst=None):
269 """Create Security Association Database entry on the VPP node.
271 :param node: VPP node to add SAD entry on.
272 :param sad_id: SAD entry ID.
273 :param spi: Security Parameter Index of this SAD entry.
274 :param crypto_alg: The encryption algorithm name.
275 :param crypto_key: The encryption key string.
276 :param integ_alg: The integrity algorithm name.
277 :param integ_key: The integrity key string.
278 :param tunnel_src: Tunnel header source IPv4 or IPv6 address. If not
279 specified ESP transport mode is used.
280 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address. If
281 not specified ESP transport mode is used.
285 :type crypto_alg: CryptoAlg
286 :type crypto_key: str
287 :type integ_alg: IntegAlg
289 :type tunnel_src: str
290 :type tunnel_dst: str
292 if isinstance(crypto_key, str):
293 crypto_key = crypto_key.encode(encoding=u"utf-8")
294 if isinstance(integ_key, str):
295 integ_key = integ_key.encode(encoding=u"utf-8")
297 length=len(crypto_key),
301 length=len(integ_key),
302 data=integ_key if integ_key else 0
305 flags = int(IPsecSadFlags.IPSEC_API_SAD_FLAG_NONE)
306 if tunnel_src and tunnel_dst:
307 flags = flags | int(IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_TUNNEL)
308 src_addr = ip_address(tunnel_src)
309 dst_addr = ip_address(tunnel_dst)
310 if src_addr.version == 6:
312 flags | int(IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_TUNNEL_V6)
317 cmd = u"ipsec_sad_entry_add_del"
318 err_msg = f"Failed to add Security Association Database entry " \
319 f"on host {node[u'host']}"
323 crypto_algorithm=crypto_alg.alg_int_repr,
325 integrity_algorithm=integ_alg.alg_int_repr if integ_alg else 0,
328 tunnel_src=str(src_addr),
329 tunnel_dst=str(dst_addr),
330 protocol=int(IPsecProto.ESP)
336 with PapiSocketExecutor(node) as papi_exec:
337 papi_exec.add(cmd, **args).get_reply(err_msg)
340 def vpp_ipsec_add_sad_entries(
341 node, n_entries, sad_id, spi, crypto_alg, crypto_key,
342 integ_alg=None, integ_key=u"", tunnel_src=None, tunnel_dst=None):
343 """Create multiple Security Association Database entries on VPP node.
345 :param node: VPP node to add SAD entry on.
346 :param n_entries: Number of SAD entries to be created.
347 :param sad_id: First SAD entry ID. All subsequent SAD entries will have
349 :param spi: Security Parameter Index of first SAD entry. All subsequent
350 SAD entries will have spi incremented by 1.
351 :param crypto_alg: The encryption algorithm name.
352 :param crypto_key: The encryption key string.
353 :param integ_alg: The integrity algorithm name.
354 :param integ_key: The integrity key string.
355 :param tunnel_src: Tunnel header source IPv4 or IPv6 address. If not
356 specified ESP transport mode is used.
357 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address. If
358 not specified ESP transport mode is used.
363 :type crypto_alg: CryptoAlg
364 :type crypto_key: str
365 :type integ_alg: IntegAlg
367 :type tunnel_src: str
368 :type tunnel_dst: str
370 if isinstance(crypto_key, str):
371 crypto_key = crypto_key.encode(encoding=u"utf-8")
372 if isinstance(integ_key, str):
373 integ_key = integ_key.encode(encoding=u"utf-8")
374 if tunnel_src and tunnel_dst:
375 src_addr = ip_address(tunnel_src)
376 dst_addr = ip_address(tunnel_dst)
381 addr_incr = 1 << (128 - 96) if src_addr.version == 6 \
384 if int(n_entries) > 10:
385 tmp_filename = f"/tmp/ipsec_sad_{sad_id}_add_del_entry.script"
387 with open(tmp_filename, 'w') as tmp_file:
388 for i in range(n_entries):
389 integ = f"integ-alg {integ_alg.alg_name} " \
390 f"integ-key {integ_key.hex()}" \
391 if integ_alg else u""
392 tunnel = f"tunnel-src {src_addr + i * addr_incr} " \
393 f"tunnel-dst {dst_addr + i * addr_incr}" \
394 if tunnel_src and tunnel_dst else u""
395 conf = f"exec ipsec sa add {sad_id + i} esp spi {spi + i} "\
396 f"crypto-alg {crypto_alg.alg_name} " \
397 f"crypto-key {crypto_key.hex()} " \
398 f"{integ} {tunnel}\n"
402 tmp_filename, node, timeout=300, json_out=False,
405 os.remove(tmp_filename)
409 length=len(crypto_key),
413 length=len(integ_key),
414 data=integ_key if integ_key else 0
417 flags = int(IPsecSadFlags.IPSEC_API_SAD_FLAG_NONE)
418 if tunnel_src and tunnel_dst:
419 flags = flags | int(IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_TUNNEL)
420 if src_addr.version == 6:
422 IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_TUNNEL_V6
425 cmd = u"ipsec_sad_entry_add_del"
426 err_msg = f"Failed to add Security Association Database entry " \
427 f"on host {node[u'host']}"
432 crypto_algorithm=crypto_alg.alg_int_repr,
434 integrity_algorithm=integ_alg.alg_int_repr if integ_alg else 0,
437 tunnel_src=str(src_addr),
438 tunnel_dst=str(dst_addr),
439 protocol=int(IPsecProto.ESP)
445 with PapiSocketExecutor(node) as papi_exec:
446 for i in range(n_entries):
447 args[u"entry"][u"sad_id"] = int(sad_id) + i
448 args[u"entry"][u"spi"] = int(spi) + i
449 args[u"entry"][u"tunnel_src"] = str(src_addr + i * addr_incr) \
450 if tunnel_src and tunnel_dst else src_addr
451 args[u"entry"][u"tunnel_dst"] = str(dst_addr + i * addr_incr) \
452 if tunnel_src and tunnel_dst else dst_addr
453 history = bool(not 1 < i < n_entries - 2)
454 papi_exec.add(cmd, history=history, **args)
455 papi_exec.get_replies(err_msg)
458 def vpp_ipsec_set_ip_route(
459 node, n_tunnels, tunnel_src, traffic_addr, tunnel_dst, interface,
461 """Set IP address and route on interface.
463 :param node: VPP node to add config on.
464 :param n_tunnels: Number of tunnels to create.
465 :param tunnel_src: Tunnel header source IPv4 or IPv6 address.
466 :param traffic_addr: Traffic destination IP address to route.
467 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address.
468 :param interface: Interface key on node 1.
469 :param raddr_range: Mask specifying range of Policy selector Remote IP
470 addresses. Valid values are from 1 to 32 in case of IPv4 and to 128
474 :type tunnel_src: str
475 :type traffic_addr: str
476 :type tunnel_dst: str
478 :type raddr_range: int
480 laddr = ip_address(tunnel_src)
481 raddr = ip_address(tunnel_dst)
482 taddr = ip_address(traffic_addr)
483 addr_incr = 1 << (128 - raddr_range) if laddr.version == 6 \
484 else 1 << (32 - raddr_range)
486 if int(n_tunnels) > 10:
487 tmp_filename = u"/tmp/ipsec_set_ip.script"
489 with open(tmp_filename, 'w') as tmp_file:
490 if_name = Topology.get_interface_name(node, interface)
491 for i in range(n_tunnels):
492 conf = f"exec set interface ip address {if_name} " \
493 f"{laddr + i * addr_incr}/{raddr_range}\n" \
494 f"exec ip route add {taddr + i}/" \
495 f"{128 if taddr.version == 6 else 32} " \
496 f"via {raddr + i * addr_incr} {if_name}\n"
500 tmp_filename, node, timeout=300, json_out=False,
503 os.remove(tmp_filename)
506 cmd1 = u"sw_interface_add_del_address"
508 sw_if_index=InterfaceUtil.get_interface_index(node, interface),
513 cmd2 = u"ip_route_add_del"
519 err_msg = f"Failed to configure IP addresses and IP routes " \
520 f"on interface {interface} on host {node[u'host']}"
522 with PapiSocketExecutor(node) as papi_exec:
523 for i in range(n_tunnels):
524 args1[u"prefix"] = IPUtil.create_prefix_object(
525 laddr + i * addr_incr, raddr_range
527 args2[u"route"] = IPUtil.compose_vpp_route_structure(
529 prefix_len=128 if taddr.version == 6 else 32,
530 interface=interface, gateway=raddr + i * addr_incr
532 history = bool(not 1 < i < n_tunnels - 2)
533 papi_exec.add(cmd1, history=history, **args1).\
534 add(cmd2, history=history, **args2)
535 papi_exec.get_replies(err_msg)
538 def vpp_ipsec_add_spd(node, spd_id):
539 """Create Security Policy Database on the VPP node.
541 :param node: VPP node to add SPD on.
542 :param spd_id: SPD ID.
546 cmd = u"ipsec_spd_add_del"
547 err_msg = f"Failed to add Security Policy Database " \
548 f"on host {node[u'host']}"
553 with PapiSocketExecutor(node) as papi_exec:
554 papi_exec.add(cmd, **args).get_reply(err_msg)
557 def vpp_ipsec_spd_add_if(node, spd_id, interface):
558 """Add interface to the Security Policy Database.
560 :param node: VPP node.
561 :param spd_id: SPD ID to add interface on.
562 :param interface: Interface name or sw_if_index.
565 :type interface: str or int
567 cmd = u"ipsec_interface_add_del_spd"
568 err_msg = f"Failed to add interface {interface} to Security Policy " \
569 f"Database {spd_id} on host {node[u'host']}"
572 sw_if_index=InterfaceUtil.get_interface_index(node, interface),
575 with PapiSocketExecutor(node) as papi_exec:
576 papi_exec.add(cmd, **args).get_reply(err_msg)
579 def vpp_ipsec_policy_add(
580 node, spd_id, priority, action, inbound=True, sa_id=None,
581 laddr_range=None, raddr_range=None, proto=None, lport_range=None,
582 rport_range=None, is_ipv6=False):
583 """Create Security Policy Database entry on the VPP node.
585 :param node: VPP node to add SPD entry on.
586 :param spd_id: SPD ID to add entry on.
587 :param priority: SPD entry priority, higher number = higher priority.
588 :param action: Policy action.
589 :param inbound: If True policy is for inbound traffic, otherwise
591 :param sa_id: SAD entry ID for protect action.
592 :param laddr_range: Policy selector local IPv4 or IPv6 address range in
593 format IP/prefix or IP/mask. If no mask is provided,
594 it's considered to be /32.
595 :param raddr_range: Policy selector remote IPv4 or IPv6 address range in
596 format IP/prefix or IP/mask. If no mask is provided,
597 it's considered to be /32.
598 :param proto: Policy selector next layer protocol number.
599 :param lport_range: Policy selector local TCP/UDP port range in format
600 <port_start>-<port_end>.
601 :param rport_range: Policy selector remote TCP/UDP port range in format
602 <port_start>-<port_end>.
603 :param is_ipv6: True in case of IPv6 policy when IPv6 address range is
604 not defined so it will default to address ::/0, otherwise False.
608 :type action: PolicyAction
611 :type laddr_range: string
612 :type raddr_range: string
614 :type lport_range: string
615 :type rport_range: string
618 if laddr_range is None:
619 laddr_range = u"::/0" if is_ipv6 else u"0.0.0.0/0"
621 if raddr_range is None:
622 raddr_range = u"::/0" if is_ipv6 else u"0.0.0.0/0"
624 cmd = u"ipsec_spd_entry_add_del"
625 err_msg = f"Failed to add entry to Security Policy Database {spd_id} " \
626 f"on host {node[u'host']}"
630 priority=int(priority),
631 is_outbound=0 if inbound else 1,
632 sa_id=int(sa_id) if sa_id else 0,
633 policy=action.policy_int_repr,
634 protocol=int(proto) if proto else 0,
635 remote_address_start=IPUtil.create_ip_address_object(
636 ip_network(raddr_range, strict=False).network_address
638 remote_address_stop=IPUtil.create_ip_address_object(
639 ip_network(raddr_range, strict=False).broadcast_address
641 local_address_start=IPUtil.create_ip_address_object(
642 ip_network(laddr_range, strict=False).network_address
644 local_address_stop=IPUtil.create_ip_address_object(
645 ip_network(laddr_range, strict=False).broadcast_address
647 remote_port_start=int(rport_range.split(u"-")[0]) if rport_range
649 remote_port_stop=int(rport_range.split(u"-")[1]) if rport_range
651 local_port_start=int(lport_range.split(u"-")[0]) if lport_range
653 local_port_stop=int(lport_range.split(u"-")[1]) if rport_range
660 with PapiSocketExecutor(node) as papi_exec:
661 papi_exec.add(cmd, **args).get_reply(err_msg)
664 def vpp_ipsec_spd_add_entries(
665 node, n_entries, spd_id, priority, inbound, sa_id, raddr_ip,
667 """Create multiple Security Policy Database entries on the VPP node.
669 :param node: VPP node to add SPD entries on.
670 :param n_entries: Number of SPD entries to be added.
671 :param spd_id: SPD ID to add entries on.
672 :param priority: SPD entries priority, higher number = higher priority.
673 :param inbound: If True policy is for inbound traffic, otherwise
675 :param sa_id: SAD entry ID for first entry. Each subsequent entry will
676 SAD entry ID incremented by 1.
677 :param raddr_ip: Policy selector remote IPv4 start address for the first
678 entry. Remote IPv4 end address will be calculated depending on
679 raddr_range parameter. Each subsequent entry will have start address
680 next after IPv4 end address of previous entry.
681 :param raddr_range: Required IP addres range.
689 :type raddr_range: int
691 raddr_ip = ip_address(raddr_ip)
692 if int(n_entries) > 10:
693 tmp_filename = f"/tmp/ipsec_spd_{sa_id}_add_del_entry.script"
695 with open(tmp_filename, 'w') as tmp_file:
696 for i in range(n_entries):
697 direction = u'inbound' if inbound else u'outbound'
698 tunnel = f"exec ipsec policy add spd {spd_id} " \
699 f"priority {priority} {direction} " \
700 f"action protect sa {sa_id+i} " \
701 f"remote-ip-range {raddr_ip + i * (raddr_range + 1)} " \
702 f"- {raddr_ip + (i + 1) * raddr_range + i} " \
703 f"local-ip-range 0.0.0.0 - 255.255.255.255\n"
704 tmp_file.write(tunnel)
705 VatExecutor().execute_script(
706 tmp_filename, node, timeout=300, json_out=False,
709 os.remove(tmp_filename)
712 laddr_range = u"::/0" if raddr_ip.version == 6 else u"0.0.0.0/0"
714 cmd = u"ipsec_spd_entry_add_del"
715 err_msg = f"ailed to add entry to Security Policy Database '{spd_id} " \
716 f"on host {node[u'host']}"
720 priority=int(priority),
721 is_outbound=0 if inbound else 1,
722 sa_id=int(sa_id) if sa_id else 0,
723 policy=IPsecUtil.policy_action_protect().policy_int_repr,
725 remote_address_start=IPUtil.create_ip_address_object(raddr_ip),
726 remote_address_stop=IPUtil.create_ip_address_object(raddr_ip),
727 local_address_start=IPUtil.create_ip_address_object(
728 ip_network(laddr_range, strict=False).network_address
730 local_address_stop=IPUtil.create_ip_address_object(
731 ip_network(laddr_range, strict=False).broadcast_address
734 remote_port_stop=65535,
736 local_port_stop=65535
743 with PapiSocketExecutor(node) as papi_exec:
744 for i in range(n_entries):
745 args[u"entry"][u"remote_address_start"][u"un"] = \
746 IPUtil.union_addr(raddr_ip + i)
747 args[u"entry"][u"remote_address_stop"][u"un"] = \
748 IPUtil.union_addr(raddr_ip + i)
749 history = bool(not 1 < i < n_entries - 2)
750 papi_exec.add(cmd, history=history, **args)
751 papi_exec.get_replies(err_msg)
754 def vpp_ipsec_create_tunnel_interfaces(
755 nodes, if1_ip_addr, if2_ip_addr, if1_key, if2_key, n_tunnels,
756 crypto_alg, integ_alg, raddr_ip1, raddr_ip2, raddr_range,
758 """Create multiple IPsec tunnel interfaces between two VPP nodes.
760 :param nodes: VPP nodes to create tunnel interfaces.
761 :param if1_ip_addr: VPP node 1 interface IPv4/IPv6 address.
762 :param if2_ip_addr: VPP node 2 interface IPv4/IPv6 address.
763 :param if1_key: VPP node 1 interface key from topology file.
764 :param if2_key: VPP node 2 interface key from topology file.
765 :param n_tunnels: Number of tunnel interfaces to be there at the end.
766 :param crypto_alg: The encryption algorithm name.
767 :param integ_alg: The integrity algorithm name.
768 :param raddr_ip1: Policy selector remote IPv4/IPv6 start address for the
769 first tunnel in direction node1->node2.
770 :param raddr_ip2: Policy selector remote IPv4/IPv6 start address for the
771 first tunnel in direction node2->node1.
772 :param raddr_range: Mask specifying range of Policy selector Remote
773 IPv4/IPv6 addresses. Valid values are from 1 to 32 in case of IPv4
774 and to 128 in case of IPv6.
775 :param existing_tunnels: Number of tunnel interfaces before creation.
776 Useful mainly for reconf tests. Default 0.
778 :type if1_ip_addr: str
779 :type if2_ip_addr: str
783 :type crypto_alg: CryptoAlg
784 :type integ_alg: IntegAlg
785 :type raddr_ip1: string
786 :type raddr_ip2: string
787 :type raddr_range: int
788 :type existing_tunnels: int
790 n_tunnels = int(n_tunnels)
791 existing_tunnels = int(existing_tunnels)
794 if1_ip = ip_address(if1_ip_addr)
795 if2_ip = ip_address(if2_ip_addr)
796 raddr_ip1 = ip_address(raddr_ip1)
797 raddr_ip2 = ip_address(raddr_ip2)
798 addr_incr = 1 << (128 - raddr_range) if if1_ip.version == 6 \
799 else 1 << (32 - raddr_range)
801 if n_tunnels - existing_tunnels > 10:
802 tmp_fn1 = u"/tmp/ipsec_create_tunnel_dut1.config"
803 tmp_fn2 = u"/tmp/ipsec_create_tunnel_dut2.config"
804 if1_n = Topology.get_interface_name(nodes[u"DUT1"], if1_key)
805 if2_n = Topology.get_interface_name(nodes[u"DUT2"], if2_key)
806 mask = 96 if if2_ip.version == 6 else 24
807 mask2 = 128 if if2_ip.version == 6 else 32
809 with open(tmp_fn1, 'w') as tmp_f1, open(tmp_fn2, 'w') as tmp_f2:
810 rmac = Topology.get_interface_mac(nodes[u"DUT2"], if2_key)
811 if not existing_tunnels:
813 f"exec create loopback interface\n"
814 f"exec set interface state loop0 up\n"
815 f"exec set interface ip address "
816 f"{if1_n} {if2_ip - 1}/{mask}\n"
817 f"exec set ip neighbor {if1_n} {if2_ip}/{mask2} {rmac}"
821 f"exec set interface ip address {if2_n}"
822 f" {if2_ip}/{mask}\n"
824 for i in range(existing_tunnels, n_tunnels):
826 IPsecUtil.get_crypto_alg_key_len(crypto_alg)
830 IPsecUtil.get_integ_alg_key_len(integ_alg)
832 integ = f"integ_alg {integ_alg.alg_name} " \
833 f"local_integ_key {ikey} remote_integ_key {ikey} "
837 f"exec set interface ip address loop0 "
838 f"{if1_ip + i * addr_incr}/32\n"
839 f"ipsec_tunnel_if_add_del "
840 f"local_spi {spi_1 + i} remote_spi {spi_2 + i} "
841 f"crypto_alg {crypto_alg.alg_name} "
842 f"local_crypto_key {ckey} remote_crypto_key {ckey} "
844 f"local_ip {if1_ip + i * addr_incr} "
845 f"remote_ip {if2_ip} "
849 f"ipsec_tunnel_if_add_del "
850 f"local_spi {spi_2 + i} remote_spi {spi_1 + i} "
851 f"crypto_alg {crypto_alg.alg_name} "
852 f"local_crypto_key {ckey} remote_crypto_key {ckey} "
854 f"local_ip {if2_ip} "
855 f"remote_ip {if1_ip + i * addr_incr} "
859 tmp_fn1, nodes[u"DUT1"], timeout=1800, json_out=False,
860 copy_on_execute=True,
861 history=bool(n_tunnels < 100)
864 tmp_fn2, nodes[u"DUT2"], timeout=1800, json_out=False,
865 copy_on_execute=True,
866 history=bool(n_tunnels < 100)
871 with open(tmp_fn1, 'w') as tmp_f1, open(tmp_fn2, 'w') as tmp_f2:
872 if not existing_tunnels:
874 f"exec ip route add {if1_ip}/8 via {if2_ip - 1}"
877 for i in range(existing_tunnels, n_tunnels):
879 f"exec set interface unnumbered ipip{i} use {if1_n}\n"
880 f"exec set interface state ipip{i} up\n"
881 f"exec ip route add {raddr_ip2 + i}/{mask2} "
885 f"exec set interface unnumbered ipip{i} use {if2_n}\n"
886 f"exec set interface state ipip{i} up\n"
887 f"exec ip route add {raddr_ip1 + i}/{mask2} "
891 tmp_fn1, nodes[u"DUT1"], timeout=1800, json_out=False,
892 copy_on_execute=True,
893 history=bool(n_tunnels < 100)
896 tmp_fn2, nodes[u"DUT2"], timeout=1800, json_out=False,
897 copy_on_execute=True,
898 history=bool(n_tunnels < 100)
904 if not existing_tunnels:
905 with PapiSocketExecutor(nodes[u"DUT1"]) as papi_exec:
906 # Create loopback interface on DUT1, set it to up state
907 cmd1 = u"create_loopback"
911 err_msg = f"Failed to create loopback interface " \
912 f"on host {nodes[u'DUT1'][u'host']}"
913 loop_sw_if_idx = papi_exec.add(cmd1, **args1).\
914 get_sw_if_index(err_msg)
915 cmd1 = u"sw_interface_set_flags"
917 sw_if_index=loop_sw_if_idx,
918 flags=InterfaceStatusFlags.IF_STATUS_API_FLAG_ADMIN_UP.value
920 err_msg = f"Failed to set loopback interface state up " \
921 f"on host {nodes[u'DUT1'][u'host']}"
922 papi_exec.add(cmd1, **args1).get_reply(err_msg)
923 # Set IP address on VPP node 1 interface
924 cmd1 = u"sw_interface_add_del_address"
926 sw_if_index=InterfaceUtil.get_interface_index(
927 nodes[u"DUT1"], if1_key
931 prefix=IPUtil.create_prefix_object(
932 if2_ip - 1, 96 if if2_ip.version == 6 else 24
935 err_msg = f"Failed to set IP address on interface {if1_key} " \
936 f"on host {nodes[u'DUT1'][u'host']}"
937 papi_exec.add(cmd1, **args1).get_reply(err_msg)
938 cmd4 = u"ip_neighbor_add_del"
942 sw_if_index=Topology.get_interface_sw_index(
943 nodes[u"DUT1"], if1_key
947 Topology.get_interface_mac(nodes[u"DUT2"], if2_key)
949 ip_address=str(ip_address(if2_ip_addr))
952 err_msg = f"Failed to add IP neighbor on interface {if1_key}"
953 papi_exec.add(cmd4, **args4).get_reply(err_msg)
955 # Executor not open, as InterfaceUtil will open its own.
956 loop_sw_if_idx = InterfaceUtil.vpp_get_interface_sw_index(
957 nodes[u"DUT1"], u"loop0")
958 cmd1 = u"sw_interface_add_del_address"
959 with PapiSocketExecutor(nodes[u"DUT1"]) as papi_exec:
960 # Configure IPsec tunnel interfaces
962 sw_if_index=loop_sw_if_idx,
967 cmd2 = u"ipsec_tunnel_if_add_del"
974 crypto_alg=crypto_alg.alg_int_repr,
975 local_crypto_key_len=0,
976 local_crypto_key=None,
977 remote_crypto_key_len=0,
978 remote_crypto_key=None,
979 integ_alg=integ_alg.alg_int_repr if integ_alg else 0,
980 local_integ_key_len=0,
981 local_integ_key=None,
982 remote_integ_key_len=0,
983 remote_integ_key=None,
986 err_msg = f"Failed to add IPsec tunnel interfaces " \
987 f"on host {nodes[u'DUT1'][u'host']}"
988 ipsec_tunnels = [None] * existing_tunnels
989 ckeys = [None] * existing_tunnels
990 ikeys = [None] * existing_tunnels
991 for i in range(existing_tunnels, n_tunnels):
993 gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg))
997 gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg))
999 args1[u"prefix"] = IPUtil.create_prefix_object(
1000 if1_ip + i * addr_incr, 128 if if1_ip.version == 6 else 32
1002 args2[u"local_spi"] = spi_1 + i
1003 args2[u"remote_spi"] = spi_2 + i
1004 args2[u"local_ip"] = IPUtil.create_ip_address_object(
1005 if1_ip + i * addr_incr
1007 args2[u"remote_ip"] = IPUtil.create_ip_address_object(if2_ip)
1008 args2[u"local_crypto_key_len"] = len(ckeys[i])
1009 args2[u"local_crypto_key"] = ckeys[i]
1010 args2[u"remote_crypto_key_len"] = len(ckeys[i])
1011 args2[u"remote_crypto_key"] = ckeys[i]
1013 args2[u"local_integ_key_len"] = len(ikeys[i])
1014 args2[u"local_integ_key"] = ikeys[i]
1015 args2[u"remote_integ_key_len"] = len(ikeys[i])
1016 args2[u"remote_integ_key"] = ikeys[i]
1017 history = bool(not 1 < i < n_tunnels - 2)
1018 papi_exec.add(cmd1, history=history, **args1).\
1019 add(cmd2, history=history, **args2)
1020 replies = papi_exec.get_replies(err_msg)
1021 for reply in replies:
1022 if u"sw_if_index" in reply:
1023 ipsec_tunnels.append(reply[u"sw_if_index"])
1024 # Configure IP routes
1025 cmd1 = u"sw_interface_set_unnumbered"
1028 sw_if_index=InterfaceUtil.get_interface_index(
1029 nodes[u"DUT1"], if1_key
1031 unnumbered_sw_if_index=0
1033 cmd2 = u"sw_interface_set_flags"
1036 flags=InterfaceStatusFlags.IF_STATUS_API_FLAG_ADMIN_UP.value
1038 cmd3 = u"ip_route_add_del"
1044 err_msg = f"Failed to add IP routes " \
1045 f"on host {nodes[u'DUT1'][u'host']}"
1046 for i in range(existing_tunnels, n_tunnels):
1047 args1[u"unnumbered_sw_if_index"] = ipsec_tunnels[i]
1048 args2[u"sw_if_index"] = ipsec_tunnels[i]
1049 args3[u"route"] = IPUtil.compose_vpp_route_structure(
1050 nodes[u"DUT1"], (raddr_ip2 + i).compressed,
1051 prefix_len=128 if raddr_ip2.version == 6 else 32,
1052 interface=ipsec_tunnels[i]
1054 history = bool(not 1 < i < n_tunnels - 2)
1055 papi_exec.add(cmd1, history=history, **args1).\
1056 add(cmd2, history=history, **args2).\
1057 add(cmd3, history=history, **args3)
1058 papi_exec.get_replies(err_msg)
1060 with PapiSocketExecutor(nodes[u"DUT2"]) as papi_exec:
1061 if not existing_tunnels:
1062 # Set IP address on VPP node 2 interface
1063 cmd1 = u"sw_interface_add_del_address"
1065 sw_if_index=InterfaceUtil.get_interface_index(
1066 nodes[u"DUT2"], if2_key
1070 prefix=IPUtil.create_prefix_object(
1071 if2_ip, 96 if if2_ip.version == 6 else 24
1074 err_msg = f"Failed to set IP address on interface {if2_key} " \
1075 f"on host {nodes[u'DUT2'][u'host']}"
1076 papi_exec.add(cmd1, **args1).get_reply(err_msg)
1077 # Configure IPsec tunnel interfaces
1078 cmd2 = u"ipsec_tunnel_if_add_del"
1081 local_ip=IPUtil.create_ip_address_object(if2_ip),
1085 crypto_alg=crypto_alg.alg_int_repr,
1086 local_crypto_key_len=0,
1087 local_crypto_key=None,
1088 remote_crypto_key_len=0,
1089 remote_crypto_key=None,
1090 integ_alg=integ_alg.alg_int_repr if integ_alg else 0,
1091 local_integ_key_len=0,
1092 local_integ_key=None,
1093 remote_integ_key_len=0,
1094 remote_integ_key=None,
1097 err_msg = f"Failed to add IPsec tunnel interfaces " \
1098 f"on host {nodes[u'DUT2'][u'host']}"
1099 ipsec_tunnels = [None] * existing_tunnels
1100 for i in range(existing_tunnels, n_tunnels):
1101 args2[u"local_spi"] = spi_2 + i
1102 args2[u"remote_spi"] = spi_1 + i
1103 args2[u"local_ip"] = IPUtil.create_ip_address_object(if2_ip)
1104 args2[u"remote_ip"] = IPUtil.create_ip_address_object(
1105 if1_ip + i * addr_incr)
1106 args2[u"local_crypto_key_len"] = len(ckeys[i])
1107 args2[u"local_crypto_key"] = ckeys[i]
1108 args2[u"remote_crypto_key_len"] = len(ckeys[i])
1109 args2[u"remote_crypto_key"] = ckeys[i]
1111 args2[u"local_integ_key_len"] = len(ikeys[i])
1112 args2[u"local_integ_key"] = ikeys[i]
1113 args2[u"remote_integ_key_len"] = len(ikeys[i])
1114 args2[u"remote_integ_key"] = ikeys[i]
1115 history = bool(not 1 < i < n_tunnels - 2)
1116 papi_exec.add(cmd2, history=history, **args2)
1117 replies = papi_exec.get_replies(err_msg)
1118 for reply in replies:
1119 if u"sw_if_index" in reply:
1120 ipsec_tunnels.append(reply[u"sw_if_index"])
1121 if not existing_tunnels:
1122 # Configure IP routes
1123 cmd1 = u"ip_route_add_del"
1124 route = IPUtil.compose_vpp_route_structure(
1125 nodes[u"DUT2"], if1_ip.compressed,
1126 prefix_len=32 if if1_ip.version == 6 else 8,
1128 gateway=(if2_ip - 1).compressed
1135 papi_exec.add(cmd1, **args1)
1136 cmd1 = u"sw_interface_set_unnumbered"
1139 sw_if_index=InterfaceUtil.get_interface_index(
1140 nodes[u"DUT2"], if2_key
1142 unnumbered_sw_if_index=0
1144 cmd2 = u"sw_interface_set_flags"
1147 flags=InterfaceStatusFlags.IF_STATUS_API_FLAG_ADMIN_UP.value
1149 cmd3 = u"ip_route_add_del"
1155 err_msg = f"Failed to add IP routes " \
1156 f"on host {nodes[u'DUT2'][u'host']}"
1157 for i in range(existing_tunnels, n_tunnels):
1158 args1[u"unnumbered_sw_if_index"] = ipsec_tunnels[i]
1159 args2[u"sw_if_index"] = ipsec_tunnels[i]
1160 args3[u"route"] = IPUtil.compose_vpp_route_structure(
1161 nodes[u"DUT1"], (raddr_ip1 + i).compressed,
1162 prefix_len=128 if raddr_ip1.version == 6 else 32,
1163 interface=ipsec_tunnels[i]
1165 history = bool(not 1 < i < n_tunnels - 2)
1166 papi_exec.add(cmd1, history=history, **args1). \
1167 add(cmd2, history=history, **args2). \
1168 add(cmd3, history=history, **args3)
1169 papi_exec.get_replies(err_msg)
1172 def _create_ipsec_script_files(dut, instances):
1173 """Create script files for configuring IPsec in containers
1175 :param dut: DUT node on which to create the script files
1176 :param instances: number of containers on DUT node
1178 :type instances: int
1181 for cnf in range(0, instances):
1183 f"/tmp/ipsec_create_tunnel_cnf_{dut}_{cnf + 1}.config"
1185 scripts.append(open(script_filename, 'w'))
1189 def _close_and_copy_ipsec_script_files(
1190 dut, nodes, instances, scripts):
1191 """Close created scripts and copy them to containers
1193 :param dut: DUT node on which to create the script files
1194 :param nodes: VPP nodes
1195 :param instances: number of containers on DUT node
1196 :param scripts: dictionary holding the script files
1199 :type instances: int
1202 for cnf in range(0, instances):
1203 scripts[cnf].close()
1205 f"/tmp/ipsec_create_tunnel_cnf_{dut}_{cnf + 1}.config"
1207 scp_node(nodes[dut], script_filename, script_filename)
1211 def vpp_ipsec_create_tunnel_interfaces_in_containers(
1212 nodes, if1_ip_addr, if2_ip_addr, if1_key, if2_key, n_tunnels,
1213 crypto_alg, integ_alg, raddr_ip1, raddr_ip2, raddr_range,
1215 """Create multiple IPsec tunnel interfaces between two VPP nodes.
1217 :param nodes: VPP nodes to create tunnel interfaces.
1218 :param if1_ip_addr: VPP node 1 interface IP4 address.
1219 :param if2_ip_addr: VPP node 2 interface IP4 address.
1220 :param if1_key: VPP node 1 interface key from topology file.
1221 :param if2_key: VPP node 2 interface key from topology file.
1222 :param n_tunnels: Number of tunnell interfaces to create.
1223 :param crypto_alg: The encryption algorithm name.
1224 :param integ_alg: The integrity algorithm name.
1225 :param raddr_ip1: Policy selector remote IPv4 start address for the
1226 first tunnel in direction node1->node2.
1227 :param raddr_ip2: Policy selector remote IPv4 start address for the
1228 first tunnel in direction node2->node1.
1229 :param raddr_range: Mask specifying range of Policy selector Remote
1230 IPv4 addresses. Valid values are from 1 to 32.
1231 :param n_instances: Number of containers.
1233 :type if1_ip_addr: str
1234 :type if2_ip_addr: str
1237 :type n_tunnels: int
1238 :type crypto_alg: CryptoAlg
1239 :type integ_alg: IntegAlg
1240 :type raddr_ip1: string
1241 :type raddr_ip2: string
1242 :type raddr_range: int
1243 :type n_instances: int
1247 addr_incr = 1 << (32 - raddr_range)
1249 dut1_scripts = IPsecUtil._create_ipsec_script_files(
1250 u"DUT1", n_instances)
1251 dut2_scripts = IPsecUtil._create_ipsec_script_files(
1252 u"DUT2", n_instances)
1254 for cnf in range(0, n_instances):
1255 dut1_scripts[cnf].write(
1256 u"create loopback interface\n"
1257 u"set interface state loop0 up\n\n"
1259 dut2_scripts[cnf].write(
1260 f"ip route add {if1_ip_addr}/8 via "
1261 f"{ip_address(if2_ip_addr) + cnf + 100} memif1/{cnf + 1}\n\n"
1264 for tnl in range(0, n_tunnels):
1265 tnl_incr = tnl * addr_incr
1266 cnf = tnl % n_instances
1267 i = tnl // n_instances
1268 ckey = gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg)).hex()
1271 ikey = gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)).hex()
1273 f"integ-alg {integ_alg.alg_name} "
1274 f"local-integ-key {ikey} "
1275 f"remote-integ-key {ikey} "
1278 # Configure tunnel end point(s) on left side
1279 dut1_scripts[cnf].write(
1280 u"set interface ip address loop0 "
1281 f"{ip_address(if1_ip_addr) + tnl_incr}/32\n"
1282 f"create ipsec tunnel "
1283 f"local-ip {ip_address(if1_ip_addr) + tnl_incr} "
1284 f"local-spi {spi_1 + tnl} "
1285 f"remote-ip {ip_address(if2_ip_addr) + cnf} "
1286 f"remote-spi {spi_2 + tnl} "
1287 f"crypto-alg {crypto_alg.alg_name} "
1288 f"local-crypto-key {ckey} "
1289 f"remote-crypto-key {ckey} "
1293 f"set interface unnumbered ipip{i} use loop0\n"
1294 f"set interface state ipip{i} up\n"
1295 f"ip route add {ip_address(raddr_ip2)+tnl}/32 via ipip{i}\n\n"
1298 # Configure tunnel end point(s) on right side
1299 dut2_scripts[cnf].write(
1300 f"set ip neighbor memif1/{cnf + 1} "
1301 f"{ip_address(if1_ip_addr) + tnl_incr} "
1302 f"02:02:00:00:{17:02X}:{cnf:02X} static\n"
1303 f"create ipsec tunnel local-ip {ip_address(if2_ip_addr) + cnf} "
1304 f"local-spi {spi_2 + tnl} "
1305 f"remote-ip {ip_address(if1_ip_addr) + tnl_incr} "
1306 f"remote-spi {spi_1 + tnl} "
1307 f"crypto-alg {crypto_alg.alg_name} "
1308 f"local-crypto-key {ckey} "
1309 f"remote-crypto-key {ckey} "
1313 f"set interface unnumbered ipip{i} use memif1/{cnf + 1}\n"
1314 f"set interface state ipip{i} up\n"
1315 f"ip route add {ip_address(raddr_ip1) + tnl}/32 via ipip{i}\n\n"
1318 IPsecUtil._close_and_copy_ipsec_script_files(
1319 u"DUT1", nodes, n_instances, dut1_scripts)
1320 IPsecUtil._close_and_copy_ipsec_script_files(
1321 u"DUT2", nodes, n_instances, dut2_scripts)
1324 def vpp_ipsec_add_multiple_tunnels(
1325 nodes, interface1, interface2, n_tunnels, crypto_alg, integ_alg,
1326 tunnel_ip1, tunnel_ip2, raddr_ip1, raddr_ip2, raddr_range):
1327 """Create multiple IPsec tunnels between two VPP nodes.
1329 :param nodes: VPP nodes to create tunnels.
1330 :param interface1: Interface name or sw_if_index on node 1.
1331 :param interface2: Interface name or sw_if_index on node 2.
1332 :param n_tunnels: Number of tunnels to create.
1333 :param crypto_alg: The encryption algorithm name.
1334 :param integ_alg: The integrity algorithm name.
1335 :param tunnel_ip1: Tunnel node1 IPv4 address.
1336 :param tunnel_ip2: Tunnel node2 IPv4 address.
1337 :param raddr_ip1: Policy selector remote IPv4 start address for the
1338 first tunnel in direction node1->node2.
1339 :param raddr_ip2: Policy selector remote IPv4 start address for the
1340 first tunnel in direction node2->node1.
1341 :param raddr_range: Mask specifying range of Policy selector Remote
1342 IPv4 addresses. Valid values are from 1 to 32.
1344 :type interface1: str or int
1345 :type interface2: str or int
1346 :type n_tunnels: int
1347 :type crypto_alg: CryptoAlg
1348 :type integ_alg: IntegAlg
1349 :type tunnel_ip1: str
1350 :type tunnel_ip2: str
1351 :type raddr_ip1: string
1352 :type raddr_ip2: string
1353 :type raddr_range: int
1363 crypto_key = gen_key(
1364 IPsecUtil.get_crypto_alg_key_len(crypto_alg)
1366 integ_key = gen_key(
1367 IPsecUtil.get_integ_alg_key_len(integ_alg)
1368 ).decode() if integ_alg else u""
1370 IPsecUtil.vpp_ipsec_set_ip_route(
1371 nodes[u"DUT1"], n_tunnels, tunnel_ip1, raddr_ip2, tunnel_ip2,
1372 interface1, raddr_range)
1373 IPsecUtil.vpp_ipsec_set_ip_route(
1374 nodes[u"DUT2"], n_tunnels, tunnel_ip2, raddr_ip1, tunnel_ip1,
1375 interface2, raddr_range)
1377 IPsecUtil.vpp_ipsec_add_spd(nodes[u"DUT1"], spd_id)
1378 IPsecUtil.vpp_ipsec_spd_add_if(nodes[u"DUT1"], spd_id, interface1)
1379 IPsecUtil.vpp_ipsec_policy_add(
1380 nodes[u"DUT1"], spd_id, p_hi, PolicyAction.BYPASS, inbound=False,
1381 proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8"
1383 IPsecUtil.vpp_ipsec_policy_add(
1384 nodes[u"DUT1"], spd_id, p_hi, PolicyAction.BYPASS, inbound=True,
1385 proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8"
1388 IPsecUtil.vpp_ipsec_add_spd(nodes[u"DUT2"], spd_id)
1389 IPsecUtil.vpp_ipsec_spd_add_if(nodes[u"DUT2"], spd_id, interface2)
1390 IPsecUtil.vpp_ipsec_policy_add(
1391 nodes[u"DUT2"], spd_id, p_hi, PolicyAction.BYPASS, inbound=False,
1392 proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8"
1394 IPsecUtil.vpp_ipsec_policy_add(
1395 nodes[u"DUT2"], spd_id, p_hi, PolicyAction.BYPASS, inbound=True,
1396 proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8"
1399 IPsecUtil.vpp_ipsec_add_sad_entries(
1400 nodes[u"DUT1"], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key,
1401 integ_alg, integ_key, tunnel_ip1, tunnel_ip2
1403 IPsecUtil.vpp_ipsec_spd_add_entries(
1404 nodes[u"DUT1"], n_tunnels, spd_id, p_lo, False, sa_id_1, raddr_ip2
1407 IPsecUtil.vpp_ipsec_add_sad_entries(
1408 nodes[u"DUT2"], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key,
1409 integ_alg, integ_key, tunnel_ip1, tunnel_ip2
1411 IPsecUtil.vpp_ipsec_spd_add_entries(
1412 nodes[u"DUT2"], n_tunnels, spd_id, p_lo, True, sa_id_1, raddr_ip2
1415 IPsecUtil.vpp_ipsec_add_sad_entries(
1416 nodes[u"DUT2"], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key,
1417 integ_alg, integ_key, tunnel_ip2, tunnel_ip1
1420 IPsecUtil.vpp_ipsec_spd_add_entries(
1421 nodes[u"DUT2"], n_tunnels, spd_id, p_lo, False, sa_id_2, raddr_ip1
1424 IPsecUtil.vpp_ipsec_add_sad_entries(
1425 nodes[u"DUT1"], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key,
1426 integ_alg, integ_key, tunnel_ip2, tunnel_ip1
1429 IPsecUtil.vpp_ipsec_spd_add_entries(
1430 nodes[u"DUT1"], n_tunnels, spd_id, p_lo, True, sa_id_2, raddr_ip1
1434 def vpp_ipsec_show(node):
1435 """Run "show ipsec" debug CLI command.
1437 :param node: Node to run command on.
1440 PapiSocketExecutor.run_cli_cmd(node, u"show ipsec")