1 # Copyright (c) 2021 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.Constants import Constants
26 from resources.libraries.python.InterfaceUtil import InterfaceUtil, \
28 from resources.libraries.python.IPAddress import IPAddress
29 from resources.libraries.python.IPUtil import IPUtil, IpDscp, MPLS_LABEL_INVALID
30 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
31 from resources.libraries.python.ssh import scp_node
32 from resources.libraries.python.topology import Topology, NodeType
33 from resources.libraries.python.VatExecutor import VatExecutor
34 from resources.libraries.python.VPPUtil import VPPUtil
37 IPSEC_UDP_PORT_NONE = 0xffff
41 """Generate random string as a key.
43 :param length: Length of generated payload.
45 :returns: The generated payload.
49 choice(ascii_letters) for _ in range(length)
50 ).encode(encoding=u"utf-8")
53 class PolicyAction(Enum):
55 BYPASS = (u"bypass", 0)
56 DISCARD = (u"discard", 1)
57 PROTECT = (u"protect", 3)
59 def __init__(self, policy_name, policy_int_repr):
60 self.policy_name = policy_name
61 self.policy_int_repr = policy_int_repr
64 class CryptoAlg(Enum):
65 """Encryption algorithms."""
66 AES_CBC_128 = (u"aes-cbc-128", 1, u"AES-CBC", 16)
67 AES_CBC_256 = (u"aes-cbc-256", 3, u"AES-CBC", 32)
68 AES_GCM_128 = (u"aes-gcm-128", 7, u"AES-GCM", 16)
69 AES_GCM_256 = (u"aes-gcm-256", 9, u"AES-GCM", 32)
71 def __init__(self, alg_name, alg_int_repr, scapy_name, key_len):
72 self.alg_name = alg_name
73 self.alg_int_repr = alg_int_repr
74 self.scapy_name = scapy_name
75 self.key_len = key_len
79 """Integrity algorithm."""
80 SHA_256_128 = (u"sha-256-128", 4, u"SHA2-256-128", 32)
81 SHA_512_256 = (u"sha-512-256", 6, u"SHA2-512-256", 64)
83 def __init__(self, alg_name, alg_int_repr, scapy_name, key_len):
84 self.alg_name = alg_name
85 self.alg_int_repr = alg_int_repr
86 self.scapy_name = scapy_name
87 self.key_len = key_len
90 class IPsecProto(IntEnum):
92 IPSEC_API_PROTO_ESP = 50
93 IPSEC_API_PROTO_AH = 51
96 class IPsecSadFlags(IntEnum):
97 """IPsec Security Association Database flags."""
98 IPSEC_API_SAD_FLAG_NONE = 0
99 # Enable extended sequence numbers
100 IPSEC_API_SAD_FLAG_USE_ESN = 0x01
101 # Enable Anti - replay
102 IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY = 0x02
103 # IPsec tunnel mode if non-zero, else transport mode
104 IPSEC_API_SAD_FLAG_IS_TUNNEL = 0x04
105 # IPsec tunnel mode is IPv6 if non-zero, else IPv4 tunnel
106 # only valid if is_tunnel is non-zero
107 IPSEC_API_SAD_FLAG_IS_TUNNEL_V6 = 0x08
108 # Enable UDP encapsulation for NAT traversal
109 IPSEC_API_SAD_FLAG_UDP_ENCAP = 0x10
110 # IPsec SA is or inbound traffic
111 IPSEC_API_SAD_FLAG_IS_INBOUND = 0x40
114 class TunnelEncpaDecapFlags(IntEnum):
115 """Flags controlling tunnel behaviour."""
116 TUNNEL_API_ENCAP_DECAP_FLAG_NONE = 0
117 # at encap, copy the DF bit of the payload into the tunnel header
118 TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DF = 1
119 # at encap, set the DF bit in the tunnel header
120 TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_DF = 2
121 # at encap, copy the DSCP bits of the payload into the tunnel header
122 TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP = 4
123 # at encap, copy the ECN bit of the payload into the tunnel header
124 TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN = 8
125 # at decap, copy the ECN bit of the tunnel header into the payload
126 TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_ECN = 16
129 class TunnelMode(IntEnum):
132 TUNNEL_API_MODE_P2P = 0
134 TUNNEL_API_MODE_MP = 1
138 """IPsec utilities."""
141 def policy_action_bypass():
142 """Return policy action bypass.
144 :returns: PolicyAction enum BYPASS object.
147 return PolicyAction.BYPASS
150 def policy_action_discard():
151 """Return policy action discard.
153 :returns: PolicyAction enum DISCARD object.
156 return PolicyAction.DISCARD
159 def policy_action_protect():
160 """Return policy action protect.
162 :returns: PolicyAction enum PROTECT object.
165 return PolicyAction.PROTECT
168 def crypto_alg_aes_cbc_128():
169 """Return encryption algorithm aes-cbc-128.
171 :returns: CryptoAlg enum AES_CBC_128 object.
174 return CryptoAlg.AES_CBC_128
177 def crypto_alg_aes_cbc_256():
178 """Return encryption algorithm aes-cbc-256.
180 :returns: CryptoAlg enum AES_CBC_256 object.
183 return CryptoAlg.AES_CBC_256
186 def crypto_alg_aes_gcm_128():
187 """Return encryption algorithm aes-gcm-128.
189 :returns: CryptoAlg enum AES_GCM_128 object.
192 return CryptoAlg.AES_GCM_128
195 def crypto_alg_aes_gcm_256():
196 """Return encryption algorithm aes-gcm-256.
198 :returns: CryptoAlg enum AES_GCM_128 object.
201 return CryptoAlg.AES_GCM_256
204 def get_crypto_alg_key_len(crypto_alg):
205 """Return encryption algorithm key length.
207 :param crypto_alg: Encryption algorithm.
208 :type crypto_alg: CryptoAlg
209 :returns: Key length.
212 return crypto_alg.key_len
215 def get_crypto_alg_scapy_name(crypto_alg):
216 """Return encryption algorithm scapy name.
218 :param crypto_alg: Encryption algorithm.
219 :type crypto_alg: CryptoAlg
220 :returns: Algorithm scapy name.
223 return crypto_alg.scapy_name
226 def integ_alg_sha_256_128():
227 """Return integrity algorithm SHA-256-128.
229 :returns: IntegAlg enum SHA_256_128 object.
232 return IntegAlg.SHA_256_128
235 def integ_alg_sha_512_256():
236 """Return integrity algorithm SHA-512-256.
238 :returns: IntegAlg enum SHA_512_256 object.
241 return IntegAlg.SHA_512_256
244 def get_integ_alg_key_len(integ_alg):
245 """Return integrity algorithm key length.
247 None argument is accepted, returning zero.
249 :param integ_alg: Integrity algorithm.
250 :type integ_alg: Optional[IntegAlg]
251 :returns: Key length.
254 return 0 if integ_alg is None else integ_alg.key_len
257 def get_integ_alg_scapy_name(integ_alg):
258 """Return integrity algorithm scapy name.
260 :param integ_alg: Integrity algorithm.
261 :type integ_alg: IntegAlg
262 :returns: Algorithm scapy name.
265 return integ_alg.scapy_name
268 def ipsec_proto_esp():
269 """Return IPSec protocol ESP.
271 :returns: IPsecProto enum ESP object.
274 return int(IPsecProto.IPSEC_API_PROTO_ESP)
277 def ipsec_proto_ah():
278 """Return IPSec protocol AH.
280 :returns: IPsecProto enum AH object.
283 return int(IPsecProto.IPSEC_API_PROTO_AH)
286 def vpp_ipsec_select_backend(node, protocol, index=1):
287 """Select IPsec backend.
289 :param node: VPP node to select IPsec backend on.
290 :param protocol: IPsec protocol.
291 :param index: Backend index.
293 :type protocol: IPsecProto
295 :raises RuntimeError: If failed to select IPsec backend or if no API
298 cmd = u"ipsec_select_backend"
299 err_msg = f"Failed to select IPsec backend on host {node[u'host']}"
304 with PapiSocketExecutor(node) as papi_exec:
305 papi_exec.add(cmd, **args).get_reply(err_msg)
308 def vpp_ipsec_set_async_mode(node, async_enable=1):
309 """Set IPsec async mode on|off.
311 :param node: VPP node to set IPsec async mode.
312 :param async_enable: Async mode on or off.
314 :type async_enable: int
315 :raises RuntimeError: If failed to set IPsec async mode or if no API
318 cmd = u"ipsec_set_async_mode"
319 err_msg = f"Failed to set IPsec async mode on host {node[u'host']}"
321 async_enable=async_enable
323 with PapiSocketExecutor(node) as papi_exec:
324 papi_exec.add(cmd, **args).get_reply(err_msg)
327 def vpp_ipsec_crypto_sw_scheduler_set_worker(
328 node, workers, crypto_enable=False):
329 """Enable or disable crypto on specific vpp worker threads.
331 :param node: VPP node to enable or disable crypto for worker threads.
332 :param workers: List of VPP thread numbers.
333 :param crypto_enable: Disable or enable crypto work.
335 :type workers: Iterable[int]
336 :type crypto_enable: bool
337 :raises RuntimeError: If failed to enable or disable crypto for worker
338 thread or if no API reply received.
340 for worker in workers:
341 cmd = u"crypto_sw_scheduler_set_worker"
342 err_msg = f"Failed to disable/enable crypto for worker thread " \
343 f"on host {node[u'host']}"
345 worker_index=worker - 1,
346 crypto_enable=crypto_enable
348 with PapiSocketExecutor(node) as papi_exec:
349 papi_exec.add(cmd, **args).get_reply(err_msg)
352 def vpp_ipsec_crypto_sw_scheduler_set_worker_on_all_duts(
353 nodes, workers, crypto_enable=False):
354 """Enable or disable crypto on specific vpp worker threads.
356 :param node: VPP node to enable or disable crypto for worker threads.
357 :param workers: List of VPP thread numbers.
358 :param crypto_enable: Disable or enable crypto work.
360 :type workers: Iterable[int]
361 :type crypto_enable: bool
362 :raises RuntimeError: If failed to enable or disable crypto for worker
363 thread or if no API reply received.
365 for node in nodes.values():
366 if node[u"type"] == NodeType.DUT:
367 thread_data = VPPUtil.vpp_show_threads(node)
368 worker_cnt = len(thread_data) - 1
372 for item in thread_data:
373 if str(item.cpu_id) in workers.split(u","):
374 worker_ids.append(item.id)
376 IPsecUtil.vpp_ipsec_crypto_sw_scheduler_set_worker(
377 node, workers=worker_ids, crypto_enable=crypto_enable
381 def vpp_ipsec_add_sad_entry(
382 node, sad_id, spi, crypto_alg, crypto_key, integ_alg=None,
383 integ_key=u"", tunnel_src=None, tunnel_dst=None):
384 """Create Security Association Database entry on the VPP node.
386 :param node: VPP node to add SAD entry on.
387 :param sad_id: SAD entry ID.
388 :param spi: Security Parameter Index of this SAD entry.
389 :param crypto_alg: The encryption algorithm name.
390 :param crypto_key: The encryption key string.
391 :param integ_alg: The integrity algorithm name.
392 :param integ_key: The integrity key string.
393 :param tunnel_src: Tunnel header source IPv4 or IPv6 address. If not
394 specified ESP transport mode is used.
395 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address. If
396 not specified ESP transport mode is used.
400 :type crypto_alg: CryptoAlg
401 :type crypto_key: str
402 :type integ_alg: Optional[IntegAlg]
404 :type tunnel_src: str
405 :type tunnel_dst: str
407 if isinstance(crypto_key, str):
408 crypto_key = crypto_key.encode(encoding=u"utf-8")
409 if isinstance(integ_key, str):
410 integ_key = integ_key.encode(encoding=u"utf-8")
412 length=len(crypto_key),
416 length=len(integ_key),
417 data=integ_key if integ_key else 0
420 flags = int(IPsecSadFlags.IPSEC_API_SAD_FLAG_NONE)
421 if tunnel_src and tunnel_dst:
422 flags = flags | int(IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_TUNNEL)
423 src_addr = ip_address(tunnel_src)
424 dst_addr = ip_address(tunnel_dst)
425 if src_addr.version == 6:
427 flags | int(IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_TUNNEL_V6)
432 cmd = u"ipsec_sad_entry_add_del_v2"
433 err_msg = f"Failed to add Security Association Database entry " \
434 f"on host {node[u'host']}"
438 crypto_algorithm=crypto_alg.alg_int_repr,
440 integrity_algorithm=integ_alg.alg_int_repr if integ_alg else 0,
443 tunnel_src=str(src_addr),
444 tunnel_dst=str(dst_addr),
446 TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
448 dscp=int(IpDscp.IP_API_DSCP_CS0),
449 protocol=int(IPsecProto.IPSEC_API_PROTO_ESP),
450 udp_src_port=4500, # default value in api
451 udp_dst_port=4500 # default value in api
457 with PapiSocketExecutor(node) as papi_exec:
458 papi_exec.add(cmd, **args).get_reply(err_msg)
461 def vpp_ipsec_add_sad_entries(
462 node, n_entries, sad_id, spi, crypto_alg, crypto_key,
463 integ_alg=None, integ_key=u"", tunnel_src=None, tunnel_dst=None):
464 """Create multiple Security Association Database entries on VPP node.
466 :param node: VPP node to add SAD entry on.
467 :param n_entries: Number of SAD entries to be created.
468 :param sad_id: First SAD entry ID. All subsequent SAD entries will have
470 :param spi: Security Parameter Index of first SAD entry. All subsequent
471 SAD entries will have spi incremented by 1.
472 :param crypto_alg: The encryption algorithm name.
473 :param crypto_key: The encryption key string.
474 :param integ_alg: The integrity algorithm name.
475 :param integ_key: The integrity key string.
476 :param tunnel_src: Tunnel header source IPv4 or IPv6 address. If not
477 specified ESP transport mode is used.
478 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address. If
479 not specified ESP transport mode is used.
484 :type crypto_alg: CryptoAlg
485 :type crypto_key: str
486 :type integ_alg: Optional[IntegAlg]
488 :type tunnel_src: str
489 :type tunnel_dst: str
491 if isinstance(crypto_key, str):
492 crypto_key = crypto_key.encode(encoding=u"utf-8")
493 if isinstance(integ_key, str):
494 integ_key = integ_key.encode(encoding=u"utf-8")
495 if tunnel_src and tunnel_dst:
496 src_addr = ip_address(tunnel_src)
497 dst_addr = ip_address(tunnel_dst)
502 addr_incr = 1 << (128 - 96) if src_addr.version == 6 \
505 if int(n_entries) > 10:
506 tmp_filename = f"/tmp/ipsec_sad_{sad_id}_add_del_entry.script"
508 with open(tmp_filename, 'w') as tmp_file:
509 for i in range(n_entries):
510 integ = f"integ-alg {integ_alg.alg_name} " \
511 f"integ-key {integ_key.hex()}" \
512 if integ_alg else u""
513 tunnel = f"tunnel src {src_addr + i * addr_incr} " \
514 f"tunnel dst {dst_addr + i * addr_incr}" \
515 if tunnel_src and tunnel_dst else u""
516 conf = f"exec ipsec sa add {sad_id + i} esp spi {spi + i} "\
517 f"crypto-alg {crypto_alg.alg_name} " \
518 f"crypto-key {crypto_key.hex()} " \
519 f"{integ} {tunnel}\n"
523 tmp_filename, node, timeout=300, json_out=False,
526 os.remove(tmp_filename)
530 length=len(crypto_key),
534 length=len(integ_key),
535 data=integ_key if integ_key else 0
538 flags = int(IPsecSadFlags.IPSEC_API_SAD_FLAG_NONE)
539 if tunnel_src and tunnel_dst:
540 flags = flags | int(IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_TUNNEL)
541 if src_addr.version == 6:
543 IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_TUNNEL_V6
546 cmd = u"ipsec_sad_entry_add_del_v2"
547 err_msg = f"Failed to add Security Association Database entry " \
548 f"on host {node[u'host']}"
553 crypto_algorithm=crypto_alg.alg_int_repr,
555 integrity_algorithm=integ_alg.alg_int_repr if integ_alg else 0,
558 tunnel_src=str(src_addr),
559 tunnel_dst=str(dst_addr),
561 TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
563 dscp=int(IpDscp.IP_API_DSCP_CS0),
564 protocol=int(IPsecProto.IPSEC_API_PROTO_ESP),
565 udp_src_port=4500, # default value in api
566 udp_dst_port=4500 # default value in api
572 with PapiSocketExecutor(node) as papi_exec:
573 for i in range(n_entries):
574 args[u"entry"][u"sad_id"] = int(sad_id) + i
575 args[u"entry"][u"spi"] = int(spi) + i
576 args[u"entry"][u"tunnel_src"] = str(src_addr + i * addr_incr) \
577 if tunnel_src and tunnel_dst else src_addr
578 args[u"entry"][u"tunnel_dst"] = str(dst_addr + i * addr_incr) \
579 if tunnel_src and tunnel_dst else dst_addr
580 history = bool(not 1 < i < n_entries - 2)
581 papi_exec.add(cmd, history=history, **args)
582 papi_exec.get_replies(err_msg)
585 def vpp_ipsec_set_ip_route(
586 node, n_tunnels, tunnel_src, traffic_addr, tunnel_dst, interface,
587 raddr_range, dst_mac=None):
588 """Set IP address and route on interface.
590 :param node: VPP node to add config on.
591 :param n_tunnels: Number of tunnels to create.
592 :param tunnel_src: Tunnel header source IPv4 or IPv6 address.
593 :param traffic_addr: Traffic destination IP address to route.
594 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address.
595 :param interface: Interface key on node 1.
596 :param raddr_range: Mask specifying range of Policy selector Remote IP
597 addresses. Valid values are from 1 to 32 in case of IPv4 and to 128
599 :param dst_mac: The MAC address of destination tunnels.
602 :type tunnel_src: str
603 :type traffic_addr: str
604 :type tunnel_dst: str
606 :type raddr_range: int
609 tunnel_src = ip_address(tunnel_src)
610 tunnel_dst = ip_address(tunnel_dst)
611 traffic_addr = ip_address(traffic_addr)
612 addr_incr = 1 << (128 - raddr_range) if tunnel_src.version == 6 \
613 else 1 << (32 - raddr_range)
615 if int(n_tunnels) > 10:
616 tmp_filename = u"/tmp/ipsec_set_ip.script"
618 with open(tmp_filename, 'w') as tmp_file:
619 if_name = Topology.get_interface_name(node, interface)
620 for i in range(n_tunnels):
621 conf = f"exec set interface ip address {if_name} " \
622 f"{tunnel_src + i * addr_incr}/{raddr_range}\n" \
623 f"exec ip route add {traffic_addr + i}/" \
624 f"{128 if traffic_addr.version == 6 else 32} " \
625 f"via {tunnel_dst + i * addr_incr} {if_name}\n"
627 conf = f"{conf}exec set ip neighbor {if_name} " \
628 f"{tunnel_dst + i * addr_incr} {dst_mac}\n"
631 VatExecutor().execute_script(
632 tmp_filename, node, timeout=300, json_out=False,
635 os.remove(tmp_filename)
638 cmd1 = u"sw_interface_add_del_address"
640 sw_if_index=InterfaceUtil.get_interface_index(node, interface),
645 cmd2 = u"ip_route_add_del"
651 cmd3 = u"ip_neighbor_add_del"
655 sw_if_index=Topology.get_interface_sw_index(node, interface),
657 mac_address=str(dst_mac),
661 err_msg = f"Failed to configure IP addresses, IP routes and " \
662 f"IP neighbor on interface {interface} on host {node[u'host']}" \
664 else f"Failed to configure IP addresses and IP routes " \
665 f"on interface {interface} on host {node[u'host']}"
667 with PapiSocketExecutor(node) as papi_exec:
668 for i in range(n_tunnels):
669 args1[u"prefix"] = IPUtil.create_prefix_object(
670 tunnel_src + i * addr_incr, raddr_range
672 args2[u"route"] = IPUtil.compose_vpp_route_structure(
673 node, traffic_addr + i,
674 prefix_len=128 if traffic_addr.version == 6 else 32,
675 interface=interface, gateway=tunnel_dst + i * addr_incr
677 history = bool(not 1 < i < n_tunnels - 2)
678 papi_exec.add(cmd1, history=history, **args1).\
679 add(cmd2, history=history, **args2)
681 args3[u"neighbor"][u"ip_address"] = ip_address(
682 tunnel_dst + i * addr_incr
684 papi_exec.add(cmd3, history=history, **args3)
685 papi_exec.get_replies(err_msg)
688 def vpp_ipsec_add_spd(node, spd_id):
689 """Create Security Policy Database on the VPP node.
691 :param node: VPP node to add SPD on.
692 :param spd_id: SPD ID.
696 cmd = u"ipsec_spd_add_del"
697 err_msg = f"Failed to add Security Policy Database " \
698 f"on host {node[u'host']}"
703 with PapiSocketExecutor(node) as papi_exec:
704 papi_exec.add(cmd, **args).get_reply(err_msg)
707 def vpp_ipsec_spd_add_if(node, spd_id, interface):
708 """Add interface to the Security Policy Database.
710 :param node: VPP node.
711 :param spd_id: SPD ID to add interface on.
712 :param interface: Interface name or sw_if_index.
715 :type interface: str or int
717 cmd = u"ipsec_interface_add_del_spd"
718 err_msg = f"Failed to add interface {interface} to Security Policy " \
719 f"Database {spd_id} on host {node[u'host']}"
722 sw_if_index=InterfaceUtil.get_interface_index(node, interface),
725 with PapiSocketExecutor(node) as papi_exec:
726 papi_exec.add(cmd, **args).get_reply(err_msg)
729 def vpp_ipsec_policy_add(
730 node, spd_id, priority, action, inbound=True, sa_id=None,
731 laddr_range=None, raddr_range=None, proto=None, lport_range=None,
732 rport_range=None, is_ipv6=False):
733 """Create Security Policy Database entry on the VPP node.
735 :param node: VPP node to add SPD entry on.
736 :param spd_id: SPD ID to add entry on.
737 :param priority: SPD entry priority, higher number = higher priority.
738 :param action: Policy action.
739 :param inbound: If True policy is for inbound traffic, otherwise
741 :param sa_id: SAD entry ID for protect action.
742 :param laddr_range: Policy selector local IPv4 or IPv6 address range in
743 format IP/prefix or IP/mask. If no mask is provided,
744 it's considered to be /32.
745 :param raddr_range: Policy selector remote IPv4 or IPv6 address range in
746 format IP/prefix or IP/mask. If no mask is provided,
747 it's considered to be /32.
748 :param proto: Policy selector next layer protocol number.
749 :param lport_range: Policy selector local TCP/UDP port range in format
750 <port_start>-<port_end>.
751 :param rport_range: Policy selector remote TCP/UDP port range in format
752 <port_start>-<port_end>.
753 :param is_ipv6: True in case of IPv6 policy when IPv6 address range is
754 not defined so it will default to address ::/0, otherwise False.
758 :type action: PolicyAction
761 :type laddr_range: string
762 :type raddr_range: string
764 :type lport_range: string
765 :type rport_range: string
768 if laddr_range is None:
769 laddr_range = u"::/0" if is_ipv6 else u"0.0.0.0/0"
771 if raddr_range is None:
772 raddr_range = u"::/0" if is_ipv6 else u"0.0.0.0/0"
774 cmd = u"ipsec_spd_entry_add_del"
775 err_msg = f"Failed to add entry to Security Policy Database {spd_id} " \
776 f"on host {node[u'host']}"
780 priority=int(priority),
781 is_outbound=not inbound,
782 sa_id=int(sa_id) if sa_id else 0,
783 policy=action.policy_int_repr,
784 protocol=int(proto) if proto else 0,
785 remote_address_start=IPAddress.create_ip_address_object(
786 ip_network(raddr_range, strict=False).network_address
788 remote_address_stop=IPAddress.create_ip_address_object(
789 ip_network(raddr_range, strict=False).broadcast_address
791 local_address_start=IPAddress.create_ip_address_object(
792 ip_network(laddr_range, strict=False).network_address
794 local_address_stop=IPAddress.create_ip_address_object(
795 ip_network(laddr_range, strict=False).broadcast_address
797 remote_port_start=int(rport_range.split(u"-")[0]) if rport_range
799 remote_port_stop=int(rport_range.split(u"-")[1]) if rport_range
801 local_port_start=int(lport_range.split(u"-")[0]) if lport_range
803 local_port_stop=int(lport_range.split(u"-")[1]) if rport_range
810 with PapiSocketExecutor(node) as papi_exec:
811 papi_exec.add(cmd, **args).get_reply(err_msg)
814 def vpp_ipsec_spd_add_entries(
815 node, n_entries, spd_id, priority, inbound, sa_id, raddr_ip,
817 """Create multiple Security Policy Database entries on the VPP node.
819 :param node: VPP node to add SPD entries on.
820 :param n_entries: Number of SPD entries to be added.
821 :param spd_id: SPD ID to add entries on.
822 :param priority: SPD entries priority, higher number = higher priority.
823 :param inbound: If True policy is for inbound traffic, otherwise
825 :param sa_id: SAD entry ID for first entry. Each subsequent entry will
826 SAD entry ID incremented by 1.
827 :param raddr_ip: Policy selector remote IPv4 start address for the first
828 entry. Remote IPv4 end address will be calculated depending on
829 raddr_range parameter. Each subsequent entry will have start address
830 next after IPv4 end address of previous entry.
831 :param raddr_range: Required IP addres range.
839 :type raddr_range: int
841 raddr_ip = ip_address(raddr_ip)
842 if int(n_entries) > 10:
843 tmp_filename = f"/tmp/ipsec_spd_{sa_id}_add_del_entry.script"
845 with open(tmp_filename, 'w') as tmp_file:
846 for i in range(n_entries):
847 direction = u'inbound' if inbound else u'outbound'
848 tunnel = f"exec ipsec policy add spd {spd_id} " \
849 f"priority {priority} {direction} " \
850 f"action protect sa {sa_id+i} " \
851 f"remote-ip-range {raddr_ip + i * (raddr_range + 1)} " \
852 f"- {raddr_ip + (i + 1) * raddr_range + i} " \
853 f"local-ip-range 0.0.0.0 - 255.255.255.255\n"
854 tmp_file.write(tunnel)
855 VatExecutor().execute_script(
856 tmp_filename, node, timeout=300, json_out=False,
859 os.remove(tmp_filename)
862 laddr_range = u"::/0" if raddr_ip.version == 6 else u"0.0.0.0/0"
864 cmd = u"ipsec_spd_entry_add_del"
865 err_msg = f"ailed to add entry to Security Policy Database '{spd_id} " \
866 f"on host {node[u'host']}"
870 priority=int(priority),
871 is_outbound=not inbound,
872 sa_id=int(sa_id) if sa_id else 0,
873 policy=getattr(PolicyAction.PROTECT, u"policy_int_repr"),
875 remote_address_start=IPAddress.create_ip_address_object(raddr_ip),
876 remote_address_stop=IPAddress.create_ip_address_object(raddr_ip),
877 local_address_start=IPAddress.create_ip_address_object(
878 ip_network(laddr_range, strict=False).network_address
880 local_address_stop=IPAddress.create_ip_address_object(
881 ip_network(laddr_range, strict=False).broadcast_address
884 remote_port_stop=65535,
886 local_port_stop=65535
893 with PapiSocketExecutor(node) as papi_exec:
894 for i in range(n_entries):
895 args[u"entry"][u"remote_address_start"][u"un"] = \
896 IPAddress.union_addr(raddr_ip + i)
897 args[u"entry"][u"remote_address_stop"][u"un"] = \
898 IPAddress.union_addr(raddr_ip + i)
899 history = bool(not 1 < i < n_entries - 2)
900 papi_exec.add(cmd, history=history, **args)
901 papi_exec.get_replies(err_msg)
904 def _ipsec_create_tunnel_interfaces_dut1_vat(
905 nodes, tun_ips, if1_key, if2_key, n_tunnels, crypto_alg, integ_alg,
906 raddr_ip2, addr_incr, spi_d, existing_tunnels=0):
907 """Create multiple IPsec tunnel interfaces on DUT1 node using VAT.
909 Generate random keys and return them (so DUT2 or TG can decrypt).
911 :param nodes: VPP nodes to create tunnel interfaces.
912 :param tun_ips: Dictionary with VPP node 1 ipsec tunnel interface
913 IPv4/IPv6 address (ip1) and VPP node 2 ipsec tunnel interface
914 IPv4/IPv6 address (ip2).
915 :param if1_key: VPP node 1 interface key from topology file.
916 :param if2_key: VPP node 2 / TG node (in case of 2-node topology)
917 interface key from topology file.
918 :param n_tunnels: Number of tunnel interfaces to be there at the end.
919 :param crypto_alg: The encryption algorithm name.
920 :param integ_alg: The integrity algorithm name.
921 :param raddr_ip2: Policy selector remote IPv4/IPv6 start address for the
922 first tunnel in direction node2->node1.
923 :param spi_d: Dictionary with SPIs for VPP node 1 and VPP node 2.
924 :param addr_incr: IP / IPv6 address incremental step.
925 :param existing_tunnels: Number of tunnel interfaces before creation.
926 Useful mainly for reconf tests. Default 0.
932 :type crypto_alg: CryptoAlg
933 :type integ_alg: Optional[IntegAlg]
934 :type raddr_ip2: IPv4Address or IPv6Address
937 :type existing_tunnels: int
938 :returns: Generated ckeys and ikeys.
939 :rtype: List[bytes], List[bytes]
941 tmp_fn1 = u"/tmp/ipsec_create_tunnel_dut1.config"
942 if1_n = Topology.get_interface_name(nodes[u"DUT1"], if1_key)
944 ckeys = [bytes()] * existing_tunnels
945 ikeys = [bytes()] * existing_tunnels
948 with open(tmp_fn1, u"w") as tmp_f1:
949 rmac = Topology.get_interface_mac(nodes[u"DUT2"], if2_key) \
950 if u"DUT2" in nodes.keys() \
951 else Topology.get_interface_mac(nodes[u"TG"], if2_key)
952 if not existing_tunnels:
954 f"exec create loopback interface\n"
955 f"exec set interface state loop0 up\n"
956 f"exec set interface ip address {if1_n} "
957 f"{tun_ips[u'ip2'] - 1}/"
958 f"{len(tun_ips[u'ip2'].packed)*8*3//4}\n"
959 f"exec set ip neighbor {if1_n} {tun_ips[u'ip2']} {rmac} "
962 for i in range(existing_tunnels, n_tunnels):
964 gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg))
967 gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg))
970 integ = f"integ-alg {integ_alg.alg_name} " \
971 f"integ-key {ikeys[i].hex()} "
975 f"exec set interface ip address loop0 "
976 f"{tun_ips[u'ip1'] + i * addr_incr}/32\n"
977 f"exec create ipip tunnel "
978 f"src {tun_ips[u'ip1'] + i * addr_incr} "
979 f"dst {tun_ips[u'ip2']} "
981 f"exec ipsec sa add {i} "
982 f"spi {spi_d[u'spi_1'] + i} "
983 f"crypto-alg {crypto_alg.alg_name} "
984 f"crypto-key {ckeys[i].hex()} "
987 f"exec ipsec sa add {100000 + i} "
988 f"spi {spi_d[u'spi_2'] + i} "
989 f"crypto-alg {crypto_alg.alg_name} "
990 f"crypto-key {ckeys[i].hex()} "
993 f"exec ipsec tunnel protect ipip{i} "
995 f"sa-in {100000 + i} "
999 tmp_fn1, nodes[u"DUT1"], timeout=1800, json_out=False,
1000 copy_on_execute=True,
1001 history=bool(n_tunnels < 100)
1005 with open(tmp_fn1, 'w') as tmp_f1:
1006 for i in range(existing_tunnels, n_tunnels):
1008 f"exec set interface unnumbered ipip{i} use {if1_n}\n"
1009 f"exec set interface state ipip{i} up\n"
1010 f"exec ip route add "
1011 f"{raddr_ip2 + i}/{len(raddr_ip2.packed)*8} "
1015 tmp_fn1, nodes[u"DUT1"], timeout=1800, json_out=False,
1016 copy_on_execute=True,
1017 history=bool(n_tunnels < 100)
1024 def _ipsec_create_tunnel_interfaces_dut2_vat(
1025 nodes, tun_ips, if2_key, n_tunnels, crypto_alg, ckeys, integ_alg,
1026 ikeys, raddr_ip1, addr_incr, spi_d, existing_tunnels=0):
1027 """Create multiple IPsec tunnel interfaces on DUT2 node using VAT.
1029 This method accesses keys generated by DUT1 method
1030 and does not return anything.
1032 :param nodes: VPP nodes to create tunnel interfaces.
1033 :param tun_ips: Dictionary with VPP node 1 ipsec tunnel interface
1034 IPv4/IPv6 address (ip1) and VPP node 2 ipsec tunnel interface
1035 IPv4/IPv6 address (ip2).
1036 :param if2_key: VPP node 2 / TG node (in case of 2-node topology)
1037 interface key from topology file.
1038 :param n_tunnels: Number of tunnel interfaces to be there at the end.
1039 :param crypto_alg: The encryption algorithm name.
1040 :param ckeys: List of encryption keys.
1041 :param integ_alg: The integrity algorithm name.
1042 :param ikeys: List of integrity keys.
1043 :param spi_d: Dictionary with SPIs for VPP node 1 and VPP node 2.
1044 :param addr_incr: IP / IPv6 address incremental step.
1045 :param existing_tunnels: Number of tunnel interfaces before creation.
1046 Useful mainly for reconf tests. Default 0.
1050 :type n_tunnels: int
1051 :type crypto_alg: CryptoAlg
1052 :type ckeys: Sequence[bytes]
1053 :type integ_alg: Optional[IntegAlg]
1054 :type ikeys: Sequence[bytes]
1055 :type addr_incr: int
1057 :type existing_tunnels: int
1059 tmp_fn2 = u"/tmp/ipsec_create_tunnel_dut2.config"
1060 if2_n = Topology.get_interface_name(nodes[u"DUT2"], if2_key)
1063 with open(tmp_fn2, 'w') as tmp_f2:
1064 if not existing_tunnels:
1066 f"exec set interface ip address {if2_n}"
1067 f" {tun_ips[u'ip2']}/{len(tun_ips[u'ip2'].packed)*8*3/4}\n"
1069 for i in range(existing_tunnels, n_tunnels):
1071 integ = f"integ-alg {integ_alg.alg_name} " \
1072 f"integ-key {ikeys[i].hex()} "
1076 f"exec create ipip tunnel "
1077 f"src {tun_ips[u'ip2']} "
1078 f"dst {tun_ips[u'ip1'] + i * addr_incr} "
1080 f"exec ipsec sa add {100000 + i} "
1081 f"spi {spi_d[u'spi_2'] + i} "
1082 f"crypto-alg {crypto_alg.alg_name} "
1083 f"crypto-key {ckeys[i].hex()} "
1086 f"exec ipsec sa add {i} "
1087 f"spi {spi_d[u'spi_1'] + i} "
1088 f"crypto-alg {crypto_alg.alg_name} "
1089 f"crypto-key {ckeys[i].hex()} "
1092 f"exec ipsec tunnel protect ipip{i} "
1093 f"sa-out {100000 + i} "
1098 tmp_fn2, nodes[u"DUT2"], timeout=1800, json_out=False,
1099 copy_on_execute=True,
1100 history=bool(n_tunnels < 100)
1104 with open(tmp_fn2, 'w') as tmp_f2:
1105 if not existing_tunnels:
1107 f"exec ip route add {tun_ips[u'ip1']}/8 "
1108 f"via {tun_ips[u'ip2'] - 1} {if2_n}\n"
1110 for i in range(existing_tunnels, n_tunnels):
1112 f"exec set interface unnumbered ipip{i} use {if2_n}\n"
1113 f"exec set interface state ipip{i} up\n"
1114 f"exec ip route add "
1115 f"{raddr_ip1 + i}/{len(raddr_ip1.packed)*8} "
1119 tmp_fn2, nodes[u"DUT2"], timeout=1800, json_out=False,
1120 copy_on_execute=True,
1121 history=bool(n_tunnels < 100)
1126 def _ipsec_create_loopback_dut1_papi(nodes, tun_ips, if1_key, if2_key):
1127 """Create loopback interface and set IP address on VPP node 1 interface
1130 :param nodes: VPP nodes to create tunnel interfaces.
1131 :param tun_ips: Dictionary with VPP node 1 ipsec tunnel interface
1132 IPv4/IPv6 address (ip1) and VPP node 2 ipsec tunnel interface
1133 IPv4/IPv6 address (ip2).
1134 :param if1_key: VPP node 1 interface key from topology file.
1135 :param if2_key: VPP node 2 / TG node (in case of 2-node topology)
1136 interface key from topology file.
1142 with PapiSocketExecutor(nodes[u"DUT1"]) as papi_exec:
1143 # Create loopback interface on DUT1, set it to up state
1144 cmd = u"create_loopback_instance"
1150 err_msg = f"Failed to create loopback interface " \
1151 f"on host {nodes[u'DUT1'][u'host']}"
1152 loop_sw_if_idx = papi_exec.add(cmd, **args). \
1153 get_sw_if_index(err_msg)
1154 cmd = u"sw_interface_set_flags"
1156 sw_if_index=loop_sw_if_idx,
1157 flags=InterfaceStatusFlags.IF_STATUS_API_FLAG_ADMIN_UP.value
1159 err_msg = f"Failed to set loopback interface state up " \
1160 f"on host {nodes[u'DUT1'][u'host']}"
1161 papi_exec.add(cmd, **args).get_reply(err_msg)
1162 # Set IP address on VPP node 1 interface
1163 cmd = u"sw_interface_add_del_address"
1165 sw_if_index=InterfaceUtil.get_interface_index(
1166 nodes[u"DUT1"], if1_key
1170 prefix=IPUtil.create_prefix_object(
1171 tun_ips[u"ip2"] - 1, 96 if tun_ips[u"ip2"].version == 6
1175 err_msg = f"Failed to set IP address on interface {if1_key} " \
1176 f"on host {nodes[u'DUT1'][u'host']}"
1177 papi_exec.add(cmd, **args).get_reply(err_msg)
1178 cmd2 = u"ip_neighbor_add_del"
1182 sw_if_index=Topology.get_interface_sw_index(
1183 nodes[u"DUT1"], if1_key
1187 Topology.get_interface_mac(nodes[u"DUT2"], if2_key)
1188 if u"DUT2" in nodes.keys()
1189 else Topology.get_interface_mac(
1190 nodes[u"TG"], if2_key
1193 ip_address=tun_ips[u"ip2"].compressed
1196 err_msg = f"Failed to add IP neighbor on interface {if1_key}"
1197 papi_exec.add(cmd2, **args2).get_reply(err_msg)
1199 return loop_sw_if_idx
1202 def _ipsec_create_tunnel_interfaces_dut1_papi(
1203 nodes, tun_ips, if1_key, if2_key, n_tunnels, crypto_alg, integ_alg,
1204 raddr_ip2, addr_incr, spi_d, existing_tunnels=0):
1205 """Create multiple IPsec tunnel interfaces on DUT1 node using PAPI.
1207 Generate random keys and return them (so DUT2 or TG can decrypt).
1209 :param nodes: VPP nodes to create tunnel interfaces.
1210 :param tun_ips: Dictionary with VPP node 1 ipsec tunnel interface
1211 IPv4/IPv6 address (ip1) and VPP node 2 ipsec tunnel interface
1212 IPv4/IPv6 address (ip2).
1213 :param if1_key: VPP node 1 interface key from topology file.
1214 :param if2_key: VPP node 2 / TG node (in case of 2-node topology)
1215 interface key from topology file.
1216 :param n_tunnels: Number of tunnel interfaces to be there at the end.
1217 :param crypto_alg: The encryption algorithm name.
1218 :param integ_alg: The integrity algorithm name.
1219 :param raddr_ip2: Policy selector remote IPv4/IPv6 start address for the
1220 first tunnel in direction node2->node1.
1221 :param spi_d: Dictionary with SPIs for VPP node 1 and VPP node 2.
1222 :param addr_incr: IP / IPv6 address incremental step.
1223 :param existing_tunnels: Number of tunnel interfaces before creation.
1224 Useful mainly for reconf tests. Default 0.
1229 :type n_tunnels: int
1230 :type crypto_alg: CryptoAlg
1231 :type integ_alg: Optional[IntegAlg]
1232 :type raddr_ip2: IPv4Address or IPv6Address
1233 :type addr_incr: int
1235 :type existing_tunnels: int
1236 :returns: Generated ckeys and ikeys.
1237 :rtype: List[bytes], List[bytes]
1239 if not existing_tunnels:
1240 loop_sw_if_idx = IPsecUtil._ipsec_create_loopback_dut1_papi(
1241 nodes, tun_ips, if1_key, if2_key
1244 loop_sw_if_idx = InterfaceUtil.vpp_get_interface_sw_index(
1245 nodes[u"DUT1"], u"loop0"
1247 with PapiSocketExecutor(nodes[u"DUT1"]) as papi_exec:
1248 # Configure IP addresses on loop0 interface
1249 cmd = u"sw_interface_add_del_address"
1251 sw_if_index=loop_sw_if_idx,
1256 for i in range(existing_tunnels, n_tunnels):
1257 args[u"prefix"] = IPUtil.create_prefix_object(
1258 tun_ips[u"ip1"] + i * addr_incr,
1259 128 if tun_ips[u"ip1"].version == 6 else 32
1262 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1264 # Configure IPIP tunnel interfaces
1265 cmd = u"ipip_add_tunnel"
1267 instance=Constants.BITWISE_NON_ZERO,
1272 TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
1274 mode=int(TunnelMode.TUNNEL_API_MODE_P2P),
1275 dscp=int(IpDscp.IP_API_DSCP_CS0)
1280 ipip_tunnels = [None] * existing_tunnels
1281 for i in range(existing_tunnels, n_tunnels):
1282 args[u"tunnel"][u"src"] = IPAddress.create_ip_address_object(
1283 tun_ips[u"ip1"] + i * addr_incr
1285 args[u"tunnel"][u"dst"] = IPAddress.create_ip_address_object(
1289 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1291 err_msg = f"Failed to add IPIP tunnel interfaces on host" \
1292 f" {nodes[u'DUT1'][u'host']}"
1293 ipip_tunnels.extend(
1295 reply[u"sw_if_index"]
1296 for reply in papi_exec.get_replies(err_msg)
1297 if u"sw_if_index" in reply
1300 # Configure IPSec SAD entries
1301 ckeys = [bytes()] * existing_tunnels
1302 ikeys = [bytes()] * existing_tunnels
1303 cmd = u"ipsec_sad_entry_add_del_v2"
1315 protocol=int(IPsecProto.IPSEC_API_PROTO_ESP),
1316 crypto_algorithm=crypto_alg.alg_int_repr,
1318 integrity_algorithm=integ_alg.alg_int_repr if integ_alg else 0,
1319 integrity_key=i_key,
1324 TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
1326 dscp=int(IpDscp.IP_API_DSCP_CS0),
1329 udp_src_port=IPSEC_UDP_PORT_NONE,
1330 udp_dst_port=IPSEC_UDP_PORT_NONE
1336 for i in range(existing_tunnels, n_tunnels):
1338 gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg))
1341 gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg))
1343 # SAD entry for outband / tx path
1344 args[u"entry"][u"sad_id"] = i
1345 args[u"entry"][u"spi"] = spi_d[u"spi_1"] + i
1347 args[u"entry"][u"crypto_key"][u"length"] = len(ckeys[i])
1348 args[u"entry"][u"crypto_key"][u"data"] = ckeys[i]
1350 args[u"entry"][u"integrity_key"][u"length"] = len(ikeys[i])
1351 args[u"entry"][u"integrity_key"][u"data"] = ikeys[i]
1352 args[u"entry"][u"flags"] = int(
1353 IPsecSadFlags.IPSEC_API_SAD_FLAG_NONE
1356 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1358 # SAD entry for inband / rx path
1359 args[u"entry"][u"sad_id"] = 100000 + i
1360 args[u"entry"][u"spi"] = spi_d[u"spi_2"] + i
1362 args[u"entry"][u"crypto_key"][u"length"] = len(ckeys[i])
1363 args[u"entry"][u"crypto_key"][u"data"] = ckeys[i]
1365 args[u"entry"][u"integrity_key"][u"length"] = len(ikeys[i])
1366 args[u"entry"][u"integrity_key"][u"data"] = ikeys[i]
1367 args[u"entry"][u"flags"] = int(
1368 IPsecSadFlags.IPSEC_API_SAD_FLAG_NONE |
1369 IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_INBOUND
1372 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1374 err_msg = f"Failed to add IPsec SAD entries on host" \
1375 f" {nodes[u'DUT1'][u'host']}"
1376 papi_exec.get_replies(err_msg)
1377 # Add protection for tunnels with IPSEC
1378 cmd = u"ipsec_tunnel_protect_update"
1381 via_label=MPLS_LABEL_INVALID,
1382 obj_id=Constants.BITWISE_NON_ZERO
1384 ipsec_tunnel_protect = dict(
1392 tunnel=ipsec_tunnel_protect
1394 for i in range(existing_tunnels, n_tunnels):
1395 args[u"tunnel"][u"sw_if_index"] = ipip_tunnels[i]
1396 args[u"tunnel"][u"sa_out"] = i
1397 args[u"tunnel"][u"sa_in"] = [100000 + i]
1399 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1401 err_msg = f"Failed to add protection for tunnels with IPSEC " \
1402 f"on host {nodes[u'DUT1'][u'host']}"
1403 papi_exec.get_replies(err_msg)
1405 # Configure unnumbered interfaces
1406 cmd = u"sw_interface_set_unnumbered"
1409 sw_if_index=InterfaceUtil.get_interface_index(
1410 nodes[u"DUT1"], if1_key
1412 unnumbered_sw_if_index=0
1414 for i in range(existing_tunnels, n_tunnels):
1415 args[u"unnumbered_sw_if_index"] = ipip_tunnels[i]
1417 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1420 cmd = u"sw_interface_set_flags"
1423 flags=InterfaceStatusFlags.IF_STATUS_API_FLAG_ADMIN_UP.value
1425 for i in range(existing_tunnels, n_tunnels):
1426 args[u"sw_if_index"] = ipip_tunnels[i]
1428 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1430 # Configure IP routes
1431 cmd = u"ip_route_add_del"
1437 for i in range(existing_tunnels, n_tunnels):
1438 args[u"route"] = IPUtil.compose_vpp_route_structure(
1439 nodes[u"DUT1"], (raddr_ip2 + i).compressed,
1440 prefix_len=128 if raddr_ip2.version == 6 else 32,
1441 interface=ipip_tunnels[i]
1444 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1446 err_msg = f"Failed to add IP routes on host " \
1447 f"{nodes[u'DUT1'][u'host']}"
1448 papi_exec.get_replies(err_msg)
1453 def _ipsec_create_tunnel_interfaces_dut2_papi(
1454 nodes, tun_ips, if2_key, n_tunnels, crypto_alg, ckeys, integ_alg,
1455 ikeys, raddr_ip1, addr_incr, spi_d, existing_tunnels=0):
1456 """Create multiple IPsec tunnel interfaces on DUT2 node using PAPI.
1458 This method accesses keys generated by DUT1 method
1459 and does not return anything.
1461 :param nodes: VPP nodes to create tunnel interfaces.
1462 :param tun_ips: Dictionary with VPP node 1 ipsec tunnel interface
1463 IPv4/IPv6 address (ip1) and VPP node 2 ipsec tunnel interface
1464 IPv4/IPv6 address (ip2).
1465 :param if2_key: VPP node 2 / TG node (in case of 2-node topology)
1466 interface key from topology file.
1467 :param n_tunnels: Number of tunnel interfaces to be there at the end.
1468 :param crypto_alg: The encryption algorithm name.
1469 :param ckeys: List of encryption keys.
1470 :param integ_alg: The integrity algorithm name.
1471 :param ikeys: List of integrity keys.
1472 :param spi_d: Dictionary with SPIs for VPP node 1 and VPP node 2.
1473 :param addr_incr: IP / IPv6 address incremental step.
1474 :param existing_tunnels: Number of tunnel interfaces before creation.
1475 Useful mainly for reconf tests. Default 0.
1479 :type n_tunnels: int
1480 :type crypto_alg: CryptoAlg
1481 :type ckeys: Sequence[bytes]
1482 :type integ_alg: Optional[IntegAlg]
1483 :type ikeys: Sequence[bytes]
1484 :type addr_incr: int
1486 :type existing_tunnels: int
1488 with PapiSocketExecutor(nodes[u"DUT2"]) as papi_exec:
1489 if not existing_tunnels:
1490 # Set IP address on VPP node 2 interface
1491 cmd = u"sw_interface_add_del_address"
1493 sw_if_index=InterfaceUtil.get_interface_index(
1494 nodes[u"DUT2"], if2_key
1498 prefix=IPUtil.create_prefix_object(
1499 tun_ips[u"ip2"], 96 if tun_ips[u"ip2"].version == 6
1503 err_msg = f"Failed to set IP address on interface {if2_key} " \
1504 f"on host {nodes[u'DUT2'][u'host']}"
1505 papi_exec.add(cmd, **args).get_reply(err_msg)
1506 # Configure IPIP tunnel interfaces
1507 cmd = u"ipip_add_tunnel"
1509 instance=Constants.BITWISE_NON_ZERO,
1514 TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
1516 mode=int(TunnelMode.TUNNEL_API_MODE_P2P),
1517 dscp=int(IpDscp.IP_API_DSCP_CS0)
1522 ipip_tunnels = [None] * existing_tunnels
1523 for i in range(existing_tunnels, n_tunnels):
1524 args[u"tunnel"][u"src"] = IPAddress.create_ip_address_object(
1527 args[u"tunnel"][u"dst"] = IPAddress.create_ip_address_object(
1528 tun_ips[u"ip1"] + i * addr_incr
1531 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1533 err_msg = f"Failed to add IPIP tunnel interfaces on host" \
1534 f" {nodes[u'DUT2'][u'host']}"
1535 ipip_tunnels.extend(
1537 reply[u"sw_if_index"]
1538 for reply in papi_exec.get_replies(err_msg)
1539 if u"sw_if_index" in reply
1542 # Configure IPSec SAD entries
1543 cmd = u"ipsec_sad_entry_add_del_v2"
1555 protocol=int(IPsecProto.IPSEC_API_PROTO_ESP),
1557 crypto_algorithm=crypto_alg.alg_int_repr,
1559 integrity_algorithm=integ_alg.alg_int_repr if integ_alg else 0,
1560 integrity_key=i_key,
1566 TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
1568 dscp=int(IpDscp.IP_API_DSCP_CS0),
1571 udp_src_port=IPSEC_UDP_PORT_NONE,
1572 udp_dst_port=IPSEC_UDP_PORT_NONE
1578 for i in range(existing_tunnels, n_tunnels):
1580 gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg))
1583 gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg))
1585 # SAD entry for outband / tx path
1586 args[u"entry"][u"sad_id"] = 100000 + i
1587 args[u"entry"][u"spi"] = spi_d[u"spi_2"] + i
1589 args[u"entry"][u"crypto_key"][u"length"] = len(ckeys[i])
1590 args[u"entry"][u"crypto_key"][u"data"] = ckeys[i]
1592 args[u"entry"][u"integrity_key"][u"length"] = len(ikeys[i])
1593 args[u"entry"][u"integrity_key"][u"data"] = ikeys[i]
1594 args[u"entry"][u"flags"] = int(
1595 IPsecSadFlags.IPSEC_API_SAD_FLAG_NONE
1598 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1600 # SAD entry for inband / rx path
1601 args[u"entry"][u"sad_id"] = i
1602 args[u"entry"][u"spi"] = spi_d[u"spi_1"] + i
1604 args[u"entry"][u"crypto_key"][u"length"] = len(ckeys[i])
1605 args[u"entry"][u"crypto_key"][u"data"] = ckeys[i]
1607 args[u"entry"][u"integrity_key"][u"length"] = len(ikeys[i])
1608 args[u"entry"][u"integrity_key"][u"data"] = ikeys[i]
1609 args[u"entry"][u"flags"] = int(
1610 IPsecSadFlags.IPSEC_API_SAD_FLAG_NONE |
1611 IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_INBOUND
1614 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1616 err_msg = f"Failed to add IPsec SAD entries on host" \
1617 f" {nodes[u'DUT2'][u'host']}"
1618 papi_exec.get_replies(err_msg)
1619 # Add protection for tunnels with IPSEC
1620 cmd = u"ipsec_tunnel_protect_update"
1623 via_label=MPLS_LABEL_INVALID,
1624 obj_id=Constants.BITWISE_NON_ZERO
1626 ipsec_tunnel_protect = dict(
1634 tunnel=ipsec_tunnel_protect
1636 for i in range(existing_tunnels, n_tunnels):
1637 args[u"tunnel"][u"sw_if_index"] = ipip_tunnels[i]
1638 args[u"tunnel"][u"sa_out"] = 100000 + i
1639 args[u"tunnel"][u"sa_in"] = [i]
1641 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1643 err_msg = f"Failed to add protection for tunnels with IPSEC " \
1644 f"on host {nodes[u'DUT2'][u'host']}"
1645 papi_exec.get_replies(err_msg)
1647 if not existing_tunnels:
1648 # Configure IP route
1649 cmd = u"ip_route_add_del"
1650 route = IPUtil.compose_vpp_route_structure(
1651 nodes[u"DUT2"], tun_ips[u"ip1"].compressed,
1652 prefix_len=32 if tun_ips[u"ip1"].version == 6 else 8,
1654 gateway=(tun_ips[u"ip2"] - 1).compressed
1661 papi_exec.add(cmd, **args)
1662 # Configure unnumbered interfaces
1663 cmd = u"sw_interface_set_unnumbered"
1666 sw_if_index=InterfaceUtil.get_interface_index(
1667 nodes[u"DUT2"], if2_key
1669 unnumbered_sw_if_index=0
1671 for i in range(existing_tunnels, n_tunnels):
1672 args[u"unnumbered_sw_if_index"] = ipip_tunnels[i]
1674 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1677 cmd = u"sw_interface_set_flags"
1680 flags=InterfaceStatusFlags.IF_STATUS_API_FLAG_ADMIN_UP.value
1682 for i in range(existing_tunnels, n_tunnels):
1683 args[u"sw_if_index"] = ipip_tunnels[i]
1685 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1687 # Configure IP routes
1688 cmd = u"ip_route_add_del"
1694 for i in range(existing_tunnels, n_tunnels):
1695 args[u"route"] = IPUtil.compose_vpp_route_structure(
1696 nodes[u"DUT1"], (raddr_ip1 + i).compressed,
1697 prefix_len=128 if raddr_ip1.version == 6 else 32,
1698 interface=ipip_tunnels[i]
1701 cmd, history=bool(not 1 < i < n_tunnels - 2), **args
1703 err_msg = f"Failed to add IP routes " \
1704 f"on host {nodes[u'DUT2'][u'host']}"
1705 papi_exec.get_replies(err_msg)
1708 def vpp_ipsec_create_tunnel_interfaces(
1709 nodes, tun_if1_ip_addr, tun_if2_ip_addr, if1_key, if2_key,
1710 n_tunnels, crypto_alg, integ_alg, raddr_ip1, raddr_ip2, raddr_range,
1711 existing_tunnels=0, return_keys=False):
1712 """Create multiple IPsec tunnel interfaces between two VPP nodes.
1714 Some deployments (e.g. devicetest) need to know the generated keys.
1715 But other deployments (e.g. scale perf test) would get spammed
1716 if we returned keys every time.
1718 :param nodes: VPP nodes to create tunnel interfaces.
1719 :param tun_if1_ip_addr: VPP node 1 ipsec tunnel interface IPv4/IPv6
1721 :param tun_if2_ip_addr: VPP node 2 ipsec tunnel interface IPv4/IPv6
1723 :param if1_key: VPP node 1 interface key from topology file.
1724 :param if2_key: VPP node 2 / TG node (in case of 2-node topology)
1725 interface key from topology file.
1726 :param n_tunnels: Number of tunnel interfaces to be there at the end.
1727 :param crypto_alg: The encryption algorithm name.
1728 :param integ_alg: The integrity algorithm name.
1729 :param raddr_ip1: Policy selector remote IPv4/IPv6 start address for the
1730 first tunnel in direction node1->node2.
1731 :param raddr_ip2: Policy selector remote IPv4/IPv6 start address for the
1732 first tunnel in direction node2->node1.
1733 :param raddr_range: Mask specifying range of Policy selector Remote
1734 IPv4/IPv6 addresses. Valid values are from 1 to 32 in case of IPv4
1735 and to 128 in case of IPv6.
1736 :param existing_tunnels: Number of tunnel interfaces before creation.
1737 Useful mainly for reconf tests. Default 0.
1738 :param return_keys: Whether generated keys should be returned.
1740 :type tun_if1_ip_addr: str
1741 :type tun_if2_ip_addr: str
1744 :type n_tunnels: int
1745 :type crypto_alg: CryptoAlg
1746 :type integ_alg: Optonal[IntegAlg]
1747 :type raddr_ip1: string
1748 :type raddr_ip2: string
1749 :type raddr_range: int
1750 :type existing_tunnels: int
1751 :type return_keys: bool
1752 :returns: Ckeys, ikeys, spi_1, spi_2.
1753 :rtype: Optional[List[bytes], List[bytes], int, int]
1755 n_tunnels = int(n_tunnels)
1756 existing_tunnels = int(existing_tunnels)
1762 ip1=ip_address(tun_if1_ip_addr),
1763 ip2=ip_address(tun_if2_ip_addr)
1765 raddr_ip1 = ip_address(raddr_ip1)
1766 raddr_ip2 = ip_address(raddr_ip2)
1767 addr_incr = 1 << (128 - raddr_range) if tun_ips[u"ip1"].version == 6 \
1768 else 1 << (32 - raddr_range)
1770 if n_tunnels - existing_tunnels > 10:
1771 ckeys, ikeys = IPsecUtil._ipsec_create_tunnel_interfaces_dut1_vat(
1772 nodes, tun_ips, if1_key, if2_key, n_tunnels, crypto_alg,
1773 integ_alg, raddr_ip2, addr_incr, spi_d, existing_tunnels
1775 if u"DUT2" in nodes.keys():
1776 IPsecUtil._ipsec_create_tunnel_interfaces_dut2_vat(
1777 nodes, tun_ips, if2_key, n_tunnels, crypto_alg, ckeys,
1778 integ_alg, ikeys, raddr_ip1, addr_incr, spi_d,
1782 ckeys, ikeys = IPsecUtil._ipsec_create_tunnel_interfaces_dut1_papi(
1783 nodes, tun_ips, if1_key, if2_key, n_tunnels, crypto_alg,
1784 integ_alg, raddr_ip2, addr_incr, spi_d, existing_tunnels
1786 if u"DUT2" in nodes.keys():
1787 IPsecUtil._ipsec_create_tunnel_interfaces_dut2_papi(
1788 nodes, tun_ips, if2_key, n_tunnels, crypto_alg, ckeys,
1789 integ_alg, ikeys, raddr_ip1, addr_incr, spi_d,
1794 return ckeys, ikeys, spi_d[u"spi_1"], spi_d[u"spi_2"]
1798 def _create_ipsec_script_files(dut, instances):
1799 """Create script files for configuring IPsec in containers
1801 :param dut: DUT node on which to create the script files
1802 :param instances: number of containers on DUT node
1804 :type instances: int
1807 for cnf in range(0, instances):
1809 f"/tmp/ipsec_create_tunnel_cnf_{dut}_{cnf + 1}.config"
1811 scripts.append(open(script_filename, 'w'))
1815 def _close_and_copy_ipsec_script_files(
1816 dut, nodes, instances, scripts):
1817 """Close created scripts and copy them to containers
1819 :param dut: DUT node on which to create the script files
1820 :param nodes: VPP nodes
1821 :param instances: number of containers on DUT node
1822 :param scripts: dictionary holding the script files
1825 :type instances: int
1828 for cnf in range(0, instances):
1829 scripts[cnf].close()
1831 f"/tmp/ipsec_create_tunnel_cnf_{dut}_{cnf + 1}.config"
1833 scp_node(nodes[dut], script_filename, script_filename)
1837 def vpp_ipsec_create_tunnel_interfaces_in_containers(
1838 nodes, if1_ip_addr, if2_ip_addr, n_tunnels, crypto_alg, integ_alg,
1839 raddr_ip1, raddr_ip2, raddr_range, n_instances):
1840 """Create multiple IPsec tunnel interfaces between two VPP nodes.
1842 :param nodes: VPP nodes to create tunnel interfaces.
1843 :param if1_ip_addr: VPP node 1 interface IP4 address.
1844 :param if2_ip_addr: VPP node 2 interface IP4 address.
1845 :param n_tunnels: Number of tunnell interfaces to create.
1846 :param crypto_alg: The encryption algorithm name.
1847 :param integ_alg: The integrity algorithm name.
1848 :param raddr_ip1: Policy selector remote IPv4 start address for the
1849 first tunnel in direction node1->node2.
1850 :param raddr_ip2: Policy selector remote IPv4 start address for the
1851 first tunnel in direction node2->node1.
1852 :param raddr_range: Mask specifying range of Policy selector Remote
1853 IPv4 addresses. Valid values are from 1 to 32.
1854 :param n_instances: Number of containers.
1856 :type if1_ip_addr: str
1857 :type if2_ip_addr: str
1858 :type n_tunnels: int
1859 :type crypto_alg: CryptoAlg
1860 :type integ_alg: Optional[IntegAlg]
1861 :type raddr_ip1: string
1862 :type raddr_ip2: string
1863 :type raddr_range: int
1864 :type n_instances: int
1868 addr_incr = 1 << (32 - raddr_range)
1870 dut1_scripts = IPsecUtil._create_ipsec_script_files(
1871 u"DUT1", n_instances
1873 dut2_scripts = IPsecUtil._create_ipsec_script_files(
1874 u"DUT2", n_instances
1877 for cnf in range(0, n_instances):
1878 dut1_scripts[cnf].write(
1879 u"create loopback interface\n"
1880 u"set interface state loop0 up\n\n"
1882 dut2_scripts[cnf].write(
1883 f"ip route add {if1_ip_addr}/8 via "
1884 f"{ip_address(if2_ip_addr) + cnf + 100} memif1/{cnf + 1}\n\n"
1887 for tnl in range(0, n_tunnels):
1888 cnf = tnl % n_instances
1890 gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg)), u"hex"
1894 gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)), u"hex"
1898 f"integ-alg {integ_alg.alg_name} "
1899 f"local-integ-key {ikey} "
1900 f"remote-integ-key {ikey} "
1902 # Configure tunnel end point(s) on left side
1903 dut1_scripts[cnf].write(
1904 u"set interface ip address loop0 "
1905 f"{ip_address(if1_ip_addr) + tnl * addr_incr}/32\n"
1906 f"create ipsec tunnel "
1907 f"local-ip {ip_address(if1_ip_addr) + tnl * addr_incr} "
1908 f"local-spi {spi_1 + tnl} "
1909 f"remote-ip {ip_address(if2_ip_addr) + cnf} "
1910 f"remote-spi {spi_2 + tnl} "
1911 f"crypto-alg {crypto_alg.alg_name} "
1912 f"local-crypto-key {ckey} "
1913 f"remote-crypto-key {ckey} "
1914 f"instance {tnl // n_instances} "
1917 f"set interface unnumbered ipip{tnl // n_instances} use loop0\n"
1918 f"set interface state ipip{tnl // n_instances} up\n"
1919 f"ip route add {ip_address(raddr_ip2)+tnl}/32 "
1920 f"via ipip{tnl // n_instances}\n\n"
1922 # Configure tunnel end point(s) on right side
1923 dut2_scripts[cnf].write(
1924 f"set ip neighbor memif1/{cnf + 1} "
1925 f"{ip_address(if1_ip_addr) + tnl * addr_incr} "
1926 f"02:02:00:00:{17:02X}:{cnf:02X} static\n"
1927 f"create ipsec tunnel local-ip {ip_address(if2_ip_addr) + cnf} "
1928 f"local-spi {spi_2 + tnl} "
1929 f"remote-ip {ip_address(if1_ip_addr) + tnl * addr_incr} "
1930 f"remote-spi {spi_1 + tnl} "
1931 f"crypto-alg {crypto_alg.alg_name} "
1932 f"local-crypto-key {ckey} "
1933 f"remote-crypto-key {ckey} "
1934 f"instance {tnl // n_instances} "
1937 f"set interface unnumbered ipip{tnl // n_instances} "
1938 f"use memif1/{cnf + 1}\n"
1939 f"set interface state ipip{tnl // n_instances} up\n"
1940 f"ip route add {ip_address(raddr_ip1) + tnl}/32 "
1941 f"via ipip{tnl // n_instances}\n\n"
1944 IPsecUtil._close_and_copy_ipsec_script_files(
1945 u"DUT1", nodes, n_instances, dut1_scripts)
1946 IPsecUtil._close_and_copy_ipsec_script_files(
1947 u"DUT2", nodes, n_instances, dut2_scripts)
1950 def vpp_ipsec_add_multiple_tunnels(
1951 nodes, interface1, interface2, n_tunnels, crypto_alg, integ_alg,
1952 tunnel_ip1, tunnel_ip2, raddr_ip1, raddr_ip2, raddr_range):
1953 """Create multiple IPsec tunnels between two VPP nodes.
1955 :param nodes: VPP nodes to create tunnels.
1956 :param interface1: Interface name or sw_if_index on node 1.
1957 :param interface2: Interface name or sw_if_index on node 2.
1958 :param n_tunnels: Number of tunnels to create.
1959 :param crypto_alg: The encryption algorithm name.
1960 :param integ_alg: The integrity algorithm name.
1961 :param tunnel_ip1: Tunnel node1 IPv4 address.
1962 :param tunnel_ip2: Tunnel node2 IPv4 address.
1963 :param raddr_ip1: Policy selector remote IPv4 start address for the
1964 first tunnel in direction node1->node2.
1965 :param raddr_ip2: Policy selector remote IPv4 start address for the
1966 first tunnel in direction node2->node1.
1967 :param raddr_range: Mask specifying range of Policy selector Remote
1968 IPv4 addresses. Valid values are from 1 to 32.
1970 :type interface1: str or int
1971 :type interface2: str or int
1972 :type n_tunnels: int
1973 :type crypto_alg: CryptoAlg
1974 :type integ_alg: Optional[IntegAlg]
1975 :type tunnel_ip1: str
1976 :type tunnel_ip2: str
1977 :type raddr_ip1: string
1978 :type raddr_ip2: string
1979 :type raddr_range: int
1989 crypto_key = gen_key(
1990 IPsecUtil.get_crypto_alg_key_len(crypto_alg)
1992 integ_key = gen_key(
1993 IPsecUtil.get_integ_alg_key_len(integ_alg)
1994 ).decode() if integ_alg else u""
1996 rmac = Topology.get_interface_mac(nodes[u"DUT2"], interface2) \
1997 if u"DUT2" in nodes.keys() \
1998 else Topology.get_interface_mac(nodes[u"TG"], interface2)
1999 IPsecUtil.vpp_ipsec_set_ip_route(
2000 nodes[u"DUT1"], n_tunnels, tunnel_ip1, raddr_ip2, tunnel_ip2,
2001 interface1, raddr_range, rmac)
2003 IPsecUtil.vpp_ipsec_add_spd(nodes[u"DUT1"], spd_id)
2004 IPsecUtil.vpp_ipsec_spd_add_if(nodes[u"DUT1"], spd_id, interface1)
2005 IPsecUtil.vpp_ipsec_policy_add(
2006 nodes[u"DUT1"], spd_id, p_hi, PolicyAction.BYPASS, inbound=False,
2007 proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8"
2009 IPsecUtil.vpp_ipsec_policy_add(
2010 nodes[u"DUT1"], spd_id, p_hi, PolicyAction.BYPASS, inbound=True,
2011 proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8"
2014 IPsecUtil.vpp_ipsec_add_sad_entries(
2015 nodes[u"DUT1"], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key,
2016 integ_alg, integ_key, tunnel_ip1, tunnel_ip2
2018 IPsecUtil.vpp_ipsec_spd_add_entries(
2019 nodes[u"DUT1"], n_tunnels, spd_id, p_lo, False, sa_id_1, raddr_ip2
2022 IPsecUtil.vpp_ipsec_add_sad_entries(
2023 nodes[u"DUT1"], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key,
2024 integ_alg, integ_key, tunnel_ip2, tunnel_ip1
2026 IPsecUtil.vpp_ipsec_spd_add_entries(
2027 nodes[u"DUT1"], n_tunnels, spd_id, p_lo, True, sa_id_2, raddr_ip1
2030 if u"DUT2" in nodes.keys():
2031 IPsecUtil.vpp_ipsec_set_ip_route(
2032 nodes[u"DUT2"], n_tunnels, tunnel_ip2, raddr_ip1, tunnel_ip1,
2033 interface2, raddr_range)
2035 IPsecUtil.vpp_ipsec_add_spd(nodes[u"DUT2"], spd_id)
2036 IPsecUtil.vpp_ipsec_spd_add_if(nodes[u"DUT2"], spd_id, interface2)
2037 IPsecUtil.vpp_ipsec_policy_add(
2038 nodes[u"DUT2"], spd_id, p_hi, PolicyAction.BYPASS,
2039 inbound=False, proto=50, laddr_range=u"100.0.0.0/8",
2040 raddr_range=u"100.0.0.0/8"
2042 IPsecUtil.vpp_ipsec_policy_add(
2043 nodes[u"DUT2"], spd_id, p_hi, PolicyAction.BYPASS,
2044 inbound=True, proto=50, laddr_range=u"100.0.0.0/8",
2045 raddr_range=u"100.0.0.0/8"
2048 IPsecUtil.vpp_ipsec_add_sad_entries(
2049 nodes[u"DUT2"], n_tunnels, sa_id_1, spi_1, crypto_alg,
2050 crypto_key, integ_alg, integ_key, tunnel_ip1, tunnel_ip2
2052 IPsecUtil.vpp_ipsec_spd_add_entries(
2053 nodes[u"DUT2"], n_tunnels, spd_id, p_lo, True, sa_id_1,
2057 IPsecUtil.vpp_ipsec_add_sad_entries(
2058 nodes[u"DUT2"], n_tunnels, sa_id_2, spi_2, crypto_alg,
2059 crypto_key, integ_alg, integ_key, tunnel_ip2, tunnel_ip1
2061 IPsecUtil.vpp_ipsec_spd_add_entries(
2062 nodes[u"DUT2"], n_tunnels, spd_id, p_lo, False, sa_id_2,
2068 def vpp_ipsec_show(node):
2069 """Run "show ipsec" debug CLI command.
2071 :param node: Node to run command on.
2074 PapiSocketExecutor.run_cli_cmd(node, u"show ipsec")
2077 def show_ipsec_security_association(node):
2078 """Show IPSec security association.
2080 :param node: DUT node.
2086 PapiSocketExecutor.dump_and_log(node, cmds)