1 # Copyright (c) 2019 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."""
17 from random import choice
18 from string import letters
19 from ipaddress import ip_network, ip_address
21 from enum import Enum, IntEnum
23 from resources.libraries.python.PapiExecutor import PapiExecutor
24 from resources.libraries.python.topology import Topology
25 from resources.libraries.python.VatExecutor import VatExecutor
26 from resources.libraries.python.VatJsonUtil import VatJsonUtil
30 """Generate random string as a key.
32 :param length: Length of generated payload.
34 :returns: The generated payload.
37 return ''.join(choice(letters) for _ in range(length)).encode('hex')
39 class PolicyAction(Enum):
45 def __init__(self, string):
49 class CryptoAlg(Enum):
50 """Encryption algorithms."""
51 AES_CBC_128 = ('aes-cbc-128', 'AES-CBC', 16)
52 AES_CBC_192 = ('aes-cbc-192', 'AES-CBC', 24)
53 AES_CBC_256 = ('aes-cbc-256', 'AES-CBC', 32)
54 AES_GCM_128 = ('aes-gcm-128', 'AES-GCM', 20)
55 AES_GCM_256 = ('aes-gcm-256', 'AES-GCM', 40)
57 def __init__(self, alg_name, scapy_name, key_len):
58 self.alg_name = alg_name
59 self.scapy_name = scapy_name
60 self.key_len = key_len
64 """Integrity algorithm."""
65 SHA1_96 = ('sha1-96', 'HMAC-SHA1-96', 20)
66 SHA_256_128 = ('sha-256-128', 'SHA2-256-128', 32)
67 SHA_384_192 = ('sha-384-192', 'SHA2-384-192', 48)
68 SHA_512_256 = ('sha-512-256', 'SHA2-512-256', 64)
69 AES_GCM_128 = ('aes-gcm-128', 'AES-GCM', 20)
70 AES_GCM_256 = ('aes-gcm-256', 'AES-GCM', 40)
72 def __init__(self, alg_name, scapy_name, key_len):
73 self.alg_name = alg_name
74 self.scapy_name = scapy_name
75 self.key_len = key_len
78 class IPsecProto(IntEnum):
84 class IPsecUtil(object):
85 """IPsec utilities."""
88 def policy_action_bypass():
89 """Return policy action bypass.
91 :returns: PolicyAction enum BYPASS object.
94 return PolicyAction.BYPASS
97 def policy_action_discard():
98 """Return policy action discard.
100 :returns: PolicyAction enum DISCARD object.
103 return PolicyAction.DISCARD
106 def policy_action_protect():
107 """Return policy action protect.
109 :returns: PolicyAction enum PROTECT object.
112 return PolicyAction.PROTECT
115 def crypto_alg_aes_cbc_128():
116 """Return encryption algorithm aes-cbc-128.
118 :returns: CryptoAlg enum AES_CBC_128 object.
121 return CryptoAlg.AES_CBC_128
124 def crypto_alg_aes_cbc_192():
125 """Return encryption algorithm aes-cbc-192.
127 :returns: CryptoAlg enum AES_CBC_192 objec.
130 return CryptoAlg.AES_CBC_192
133 def crypto_alg_aes_cbc_256():
134 """Return encryption algorithm aes-cbc-256.
136 :returns: CryptoAlg enum AES_CBC_256 object.
139 return CryptoAlg.AES_CBC_256
142 def crypto_alg_aes_gcm_128():
143 """Return encryption algorithm aes-gcm-128.
145 :returns: CryptoAlg enum AES_GCM_128 object.
148 return CryptoAlg.AES_GCM_128
151 def crypto_alg_aes_gcm_256():
152 """Return encryption algorithm aes-gcm-256.
154 :returns: CryptoAlg enum AES_GCM_128 object.
157 return CryptoAlg.AES_GCM_256
160 def get_crypto_alg_key_len(crypto_alg):
161 """Return encryption algorithm key length.
163 :param crypto_alg: Encryption algorithm.
164 :type crypto_alg: CryptoAlg
165 :returns: Key length.
168 return crypto_alg.key_len
171 def get_crypto_alg_scapy_name(crypto_alg):
172 """Return encryption algorithm scapy name.
174 :param crypto_alg: Encryption algorithm.
175 :type crypto_alg: CryptoAlg
176 :returns: Algorithm scapy name.
179 return crypto_alg.scapy_name
182 def integ_alg_sha1_96():
183 """Return integrity algorithm SHA1-96.
185 :returns: IntegAlg enum SHA1_96 object.
188 return IntegAlg.SHA1_96
191 def integ_alg_sha_256_128():
192 """Return integrity algorithm SHA-256-128.
194 :returns: IntegAlg enum SHA_256_128 object.
197 return IntegAlg.SHA_256_128
200 def integ_alg_sha_384_192():
201 """Return integrity algorithm SHA-384-192.
203 :returns: IntegAlg enum SHA_384_192 object.
206 return IntegAlg.SHA_384_192
209 def integ_alg_sha_512_256():
210 """Return integrity algorithm SHA-512-256.
212 :returns: IntegAlg enum SHA_512_256 object.
215 return IntegAlg.SHA_512_256
218 def integ_alg_aes_gcm_128():
219 """Return integrity algorithm AES-GCM-128.
221 :returns: IntegAlg enum AES_GCM_128 object.
224 return IntegAlg.AES_GCM_128
227 def integ_alg_aes_gcm_256():
228 """Return integrity algorithm AES-GCM-256.
230 :returns: IntegAlg enum AES_GCM_256 object.
233 return IntegAlg.AES_GCM_256
236 def get_integ_alg_key_len(integ_alg):
237 """Return integrity algorithm key length.
239 :param integ_alg: Integrity algorithm.
240 :type integ_alg: IntegAlg
241 :returns: Key length.
244 return integ_alg.key_len
247 def get_integ_alg_scapy_name(integ_alg):
248 """Return integrity algorithm scapy name.
250 :param integ_alg: Integrity algorithm.
251 :type integ_alg: IntegAlg
252 :returns: Algorithm scapy name.
255 return integ_alg.scapy_name
258 def ipsec_proto_esp():
259 """Return IPSec protocol ESP.
261 :returns: IPsecProto enum ESP object.
264 return int(IPsecProto.ESP)
267 def ipsec_proto_ah():
268 """Return IPSec protocol AH.
270 :returns: IPsecProto enum AH object.
273 return int(IPsecProto.SEC_AH)
276 def vpp_ipsec_select_backend(node, protocol, index=1):
277 """Select IPsec backend.
279 :param node: VPP node to select IPsec backend on.
280 :param protocol: IPsec protocol.
281 :param index: Backend index.
283 :type protocol: IPsecProto
285 :raises RuntimeError: If failed to select IPsec backend or if no API
289 cmd = 'ipsec_select_backend'
290 cmd_reply = 'ipsec_select_backend_reply'
291 err_msg = 'Failed to select IPsec backend on host {host}'.format(
293 args = dict(protocol=protocol, index=index)
294 with PapiExecutor(node) as papi_exec:
295 papi_resp = papi_exec.add(cmd, **args).execute_should_pass(err_msg)
296 data = papi_resp.reply[0]['api_reply'][cmd_reply]
297 if data['retval'] != 0:
298 raise RuntimeError('Failed to select IPsec backend on host {host}'.
299 format(host=node['host']))
302 def vpp_ipsec_backend_dump(node):
303 """Dump IPsec backends.
305 :param node: VPP node to dump IPsec backend on.
309 err_msg = 'Failed to dump IPsec backends on host {host}'.format(
311 with PapiExecutor(node) as papi_exec:
312 papi_exec.add('ipsec_backend_dump').execute_should_pass(
313 err_msg, process_reply=False)
316 def vpp_ipsec_add_sad_entry(node, sad_id, spi, crypto_alg, crypto_key,
317 integ_alg, integ_key, tunnel_src=None,
319 """Create Security Association Database entry on the VPP node.
321 :param node: VPP node to add SAD entry on.
322 :param sad_id: SAD entry ID.
323 :param spi: Security Parameter Index of this SAD entry.
324 :param crypto_alg: The encryption algorithm name.
325 :param crypto_key: The encryption key string.
326 :param integ_alg: The integrity algorithm name.
327 :param integ_key: The integrity key string.
328 :param tunnel_src: Tunnel header source IPv4 or IPv6 address. If not
329 specified ESP transport mode is used.
330 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address. If
331 not specified ESP transport mode is used.
335 :type crypto_alg: CryptoAlg
336 :type crypto_key: str
337 :type integ_alg: IntegAlg
339 :type tunnel_src: str
340 :type tunnel_dst: str
342 ckey = crypto_key.encode('hex')
343 ikey = integ_key.encode('hex')
344 tunnel = 'tunnel-src {0} tunnel-dst {1}'.format(tunnel_src, tunnel_dst)\
345 if tunnel_src is not None and tunnel_dst is not None else ''
347 out = VatExecutor.cmd_from_template(node,
348 'ipsec/ipsec_sad_add_entry.vat',
349 sad_id=sad_id, spi=spi,
350 calg=crypto_alg.alg_name, ckey=ckey,
351 ialg=integ_alg.alg_name, ikey=ikey,
353 VatJsonUtil.verify_vat_retval(
355 err_msg='Add SAD entry failed on {0}'.format(node['host']))
358 def vpp_ipsec_add_sad_entries(node, n_entries, sad_id, spi, crypto_alg,
359 crypto_key, integ_alg, integ_key,
360 tunnel_src=None, tunnel_dst=None):
361 """Create multiple Security Association Database entries on VPP node.
363 :param node: VPP node to add SAD entry on.
364 :param n_entries: Number of SAD entries to be created.
365 :param sad_id: First SAD entry ID. All subsequent SAD entries will have
367 :param spi: Security Parameter Index of first SAD entry. All subsequent
368 SAD entries will have spi incremented by 1.
369 :param crypto_alg: The encryption algorithm name.
370 :param crypto_key: The encryption key string.
371 :param integ_alg: The integrity algorithm name.
372 :param integ_key: The integrity key string.
373 :param tunnel_src: Tunnel header source IPv4 or IPv6 address. If not
374 specified ESP transport mode is used.
375 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address. If
376 not specified ESP transport mode is used.
381 :type crypto_alg: CryptoAlg
382 :type crypto_key: str
383 :type integ_alg: IntegAlg
385 :type tunnel_src: str
386 :type tunnel_dst: str
388 tmp_filename = '/tmp/ipsec_sad_{0}_add_del_entry.script'.format(sad_id)
390 addr_incr = 1 << (32 - 24)
392 with open(tmp_filename, 'w') as tmp_file:
393 for i in range(0, n_entries):
395 if not crypto_alg.alg_name.startswith('aes-gcm-'):
397 'integ-alg {integ_alg} integ-key {integ_key}'.
399 integ_alg=integ_alg.alg_name,
400 integ_key=integ_key))
402 'tunnel-src {laddr} tunnel-dst {raddr}'.
404 laddr=ip_address(unicode(tunnel_src)) + i * addr_incr,
405 raddr=ip_address(unicode(tunnel_dst)) + i * addr_incr)
406 if tunnel_src and tunnel_dst is not None else '')
408 'exec ipsec sa add {sad_id} esp spi {spi} '
409 'crypto-alg {crypto_alg} crypto-key {crypto_key} '
410 '{integ} {tunnel}\n'.
414 crypto_alg=crypto_alg.alg_name,
415 crypto_key=crypto_key,
420 vat.execute_script(tmp_filename, node, timeout=300, json_out=False,
421 copy_on_execute=True)
422 os.remove(tmp_filename)
425 def vpp_ipsec_set_ip_route(node, n_tunnels, tunnel_src, traffic_addr,
426 tunnel_dst, interface, raddr_range):
427 """Set IP address and route on interface.
429 :param node: VPP node to add config on.
430 :param n_tunnels: Number of tunnels to create.
431 :param tunnel_src: Tunnel header source IPv4 or IPv6 address.
432 :param traffic_addr: Traffic destination IP address to route.
433 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address.
434 :param interface: Interface key on node 1.
435 :param raddr_range: Mask specifying range of Policy selector Remote IPv4
436 addresses. Valid values are from 1 to 32.
439 :type tunnel_src: str
440 :type traffic_addr: str
441 :type tunnel_dst: str
443 :type raddr_range: int
445 tmp_filename = '/tmp/ipsec_set_ip.script'
447 addr_incr = 1 << (32 - raddr_range)
449 with open(tmp_filename, 'w') as tmp_file:
450 for i in range(0, n_tunnels):
452 'exec set interface ip address {interface} {laddr}/24\n'
453 'exec ip route add {taddr}/32 via {raddr} {interface}\n'.
455 interface=Topology.get_interface_name(node, interface),
456 laddr=ip_address(unicode(tunnel_src)) + i * addr_incr,
457 raddr=ip_address(unicode(tunnel_dst)) + i * addr_incr,
458 taddr=ip_address(unicode(traffic_addr)) + i))
461 vat.execute_script(tmp_filename, node, timeout=300, json_out=False,
462 copy_on_execute=True)
463 os.remove(tmp_filename)
466 def vpp_ipsec_sa_set_key(node, sa_id, crypto_key, integ_key):
467 """Update Security Association (SA) keys.
469 :param node: VPP node to update SA keys.
470 :param sa_id: SAD entry ID.
471 :param crypto_key: The encryption key string.
472 :param integ_key: The integrity key string.
475 :type crypto_key: str
478 ckey = crypto_key.encode('hex')
479 ikey = integ_key.encode('hex')
481 out = VatExecutor.cmd_from_template(
482 node, 'ipsec/ipsec_sa_set_key.vat', json_param=False, sa_id=sa_id,
483 ckey=ckey, ikey=ikey)
484 VatJsonUtil.verify_vat_retval(
486 err_msg='Update SA key failed on {0}'.format(node['host']))
489 def vpp_ipsec_add_spd(node, spd_id):
490 """Create Security Policy Database on the VPP node.
492 :param node: VPP node to add SPD on.
493 :param spd_id: SPD ID.
497 out = VatExecutor.cmd_from_template(node, 'ipsec/ipsec_spd_add.vat',
499 VatJsonUtil.verify_vat_retval(
501 err_msg='Add SPD {0} failed on {1}'.format(spd_id, node['host']))
504 def vpp_ipsec_spd_add_if(node, spd_id, interface):
505 """Add interface to the Security Policy Database.
507 :param node: VPP node.
508 :param spd_id: SPD ID to add interface on.
509 :param interface: Interface name or sw_if_index.
512 :type interface: str or int
514 sw_if_index = Topology.get_interface_sw_index(node, interface)\
515 if isinstance(interface, basestring) else interface
517 out = VatExecutor.cmd_from_template(node,
518 'ipsec/ipsec_interface_add_spd.vat',
519 spd_id=spd_id, sw_if_id=sw_if_index)
520 VatJsonUtil.verify_vat_retval(
522 err_msg='Add interface {0} to SPD {1} failed on {2}'.format(
523 interface, spd_id, node['host']))
526 def vpp_ipsec_policy_add(node, spd_id, priority, action, inbound=True,
527 sa_id=None, laddr_range=None, raddr_range=None,
528 proto=None, lport_range=None, rport_range=None,
530 """Create Security Policy Database entry on the VPP node.
532 :param node: VPP node to add SPD entry on.
533 :param spd_id: SPD ID to add entry on.
534 :param priority: SPD entry priority, higher number = higher priority.
535 :param action: Policy action.
536 :param inbound: If True policy is for inbound traffic, otherwise
538 :param sa_id: SAD entry ID for protect action.
539 :param laddr_range: Policy selector local IPv4 or IPv6 address range in
540 format IP/prefix or IP/mask. If no mask is provided,
541 it's considered to be /32.
542 :param raddr_range: Policy selector remote IPv4 or IPv6 address range in
543 format IP/prefix or IP/mask. If no mask is provided,
544 it's considered to be /32.
545 :param proto: Policy selector next layer protocol number.
546 :param lport_range: Policy selector local TCP/UDP port range in format
547 <port_start>-<port_end>.
548 :param rport_range: Policy selector remote TCP/UDP port range in format
549 <port_start>-<port_end>.
550 :param is_ipv6: True in case of IPv6 policy when IPv6 address range is
551 not defined so it will default to address ::/0, otherwise False.
555 :type action: PolicyAction
558 :type laddr_range: string
559 :type raddr_range: string
561 :type lport_range: string
562 :type rport_range: string
565 direction = 'inbound' if inbound else 'outbound'
567 if laddr_range is None and is_ipv6:
570 if raddr_range is None and is_ipv6:
573 act_str = action.value
574 if PolicyAction.PROTECT == action and sa_id is not None:
575 act_str += ' sa {0}'.format(sa_id)
578 if laddr_range is not None:
579 net = ip_network(unicode(laddr_range), strict=False)
580 selector += 'local-ip-range {0} - {1} '.format(
581 net.network_address, net.broadcast_address)
582 if raddr_range is not None:
583 net = ip_network(unicode(raddr_range), strict=False)
584 selector += 'remote-ip-range {0} - {1} '.format(
585 net.network_address, net.broadcast_address)
586 if proto is not None:
587 selector += 'protocol {0} '.format(proto)
588 if lport_range is not None:
589 selector += 'local-port-range {0} '.format(lport_range)
590 if rport_range is not None:
591 selector += 'remote-port-range {0} '.format(rport_range)
593 out = VatExecutor.cmd_from_template(
594 node, 'ipsec/ipsec_policy_add.vat', json_param=False, spd_id=spd_id,
595 priority=priority, action=act_str, direction=direction,
597 VatJsonUtil.verify_vat_retval(
599 err_msg='Add IPsec policy ID {0} failed on {1}'.format(
600 spd_id, node['host']))
603 def vpp_ipsec_spd_add_entries(node, n_entries, spd_id, priority, inbound,
605 """Create multiple Security Policy Database entries on the VPP node.
607 :param node: VPP node to add SPD entries on.
608 :param n_entries: Number of SPD entries to be added.
609 :param spd_id: SPD ID to add entries on.
610 :param priority: SPD entries priority, higher number = higher priority.
611 :param inbound: If True policy is for inbound traffic, otherwise
613 :param sa_id: SAD entry ID for first entry. Each subsequent entry will
614 SAD entry ID incremented by 1.
615 :param raddr_ip: Policy selector remote IPv4 start address for the first
616 entry. Remote IPv4 end address will be calculated depending on
617 raddr_range parameter. Each subsequent entry will have start address
618 next after IPv4 end address of previous entry.
625 :type raddr_ip: string
627 tmp_filename = '/tmp/ipsec_spd_{0}_add_del_entry.script'.format(sa_id)
629 with open(tmp_filename, 'w') as tmp_file:
630 for i in range(0, n_entries):
631 raddr_s = ip_address(unicode(raddr_ip)) + i
632 raddr_e = ip_address(unicode(raddr_ip)) + (i + 1) - 1
634 'exec ipsec policy add spd {spd_id} priority {priority} '
635 '{direction} action protect sa {sa_id} '
636 'remote-ip-range {raddr_s} - {raddr_e}\n'.
640 direction='inbound' if inbound else 'outbound',
644 tmp_file.write(tunnel)
646 vat.execute_script(tmp_filename, node, timeout=300, json_out=False,
647 copy_on_execute=True)
648 os.remove(tmp_filename)
651 def vpp_ipsec_create_tunnel_interfaces(nodes, if1_ip_addr, if2_ip_addr,
652 if1_key, if2_key, n_tunnels,
653 crypto_alg, integ_alg, raddr_ip1,
654 raddr_ip2, raddr_range):
655 """Create multiple IPsec tunnel interfaces between two VPP nodes.
657 :param nodes: VPP nodes to create tunnel interfaces.
658 :param if1_ip_addr: VPP node 1 interface IP4 address.
659 :param if2_ip_addr: VPP node 2 interface IP4 address.
660 :param if1_key: VPP node 1 interface key from topology file.
661 :param if2_key: VPP node 2 interface key from topology file.
662 :param n_tunnels: Number of tunnell interfaces to create.
663 :param crypto_alg: The encryption algorithm name.
664 :param integ_alg: The integrity algorithm name.
665 :param raddr_ip1: Policy selector remote IPv4 start address for the
666 first tunnel in direction node1->node2.
667 :param raddr_ip2: Policy selector remote IPv4 start address for the
668 first tunnel in direction node2->node1.
669 :param raddr_range: Mask specifying range of Policy selector Remote IPv4
670 addresses. Valid values are from 1 to 32.
672 :type if1_ip_addr: str
673 :type if2_ip_addr: str
677 :type crypto_alg: CryptoAlg
678 :type integ_alg: IntegAlg
679 :type raddr_ip1: string
680 :type raddr_ip2: string
681 :type raddr_range: int
685 addr_incr = 1 << (32 - raddr_range)
687 tmp_fn1 = '/tmp/ipsec_create_tunnel_dut1.config'
688 tmp_fn2 = '/tmp/ipsec_create_tunnel_dut2.config'
692 with open(tmp_fn1, 'w') as tmp_f1, open(tmp_fn2, 'w') as tmp_f2:
693 for i in range(0, n_tunnels):
694 ckey = gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg))
695 ikey = gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg))
697 if not crypto_alg.alg_name.startswith('aes-gcm-'):
699 'integ_alg {integ_alg} '
700 'local_integ_key {local_integ_key} '
701 'remote_integ_key {remote_integ_key} '
703 integ_alg=integ_alg.alg_name,
704 local_integ_key=ikey,
705 remote_integ_key=ikey))
707 'exec set interface ip address {uifc} {laddr}/24\n'
708 'ipsec_tunnel_if_add_del '
709 'local_spi {local_spi} '
710 'remote_spi {remote_spi} '
711 'crypto_alg {crypto_alg} '
712 'local_crypto_key {local_crypto_key} '
713 'remote_crypto_key {remote_crypto_key} '
716 'remote_ip {raddr}\n'
719 remote_spi=spi_2 + i,
720 crypto_alg=crypto_alg.alg_name,
721 local_crypto_key=ckey,
722 remote_crypto_key=ckey,
724 laddr=ip_address(unicode(if1_ip_addr)) + i * addr_incr,
725 raddr=ip_address(unicode(if2_ip_addr)) + i * addr_incr,
726 uifc=Topology.get_interface_name(nodes['DUT1'],
729 'exec set interface ip address {uifc} {laddr}/24\n'
730 'ipsec_tunnel_if_add_del '
731 'local_spi {local_spi} '
732 'remote_spi {remote_spi} '
733 'crypto_alg {crypto_alg} '
734 'local_crypto_key {local_crypto_key} '
735 'remote_crypto_key {remote_crypto_key} '
738 'remote_ip {raddr}\n'
741 remote_spi=spi_1 + i,
742 crypto_alg=crypto_alg.alg_name,
743 local_crypto_key=ckey,
744 remote_crypto_key=ckey,
746 laddr=ip_address(unicode(if2_ip_addr)) + i * addr_incr,
747 raddr=ip_address(unicode(if1_ip_addr)) + i * addr_incr,
748 uifc=Topology.get_interface_name(nodes['DUT2'],
750 vat.execute_script(tmp_fn1, nodes['DUT1'], timeout=300, json_out=False,
751 copy_on_execute=True)
752 vat.execute_script(tmp_fn2, nodes['DUT2'], timeout=300, json_out=False,
753 copy_on_execute=True)
757 with open(tmp_fn1, 'w') as tmp_f1, open(tmp_fn2, 'w') as tmp_f2:
758 for i in range(0, n_tunnels):
760 'exec set interface unnumbered ipsec{i} use {uifc}\n'
761 'exec set interface state ipsec{i} up\n'
762 'exec ip route add {taddr}/32 via {raddr} ipsec{i}\n'
764 taddr=ip_address(unicode(raddr_ip2)) + i,
765 raddr=ip_address(unicode(if2_ip_addr)) + i * addr_incr,
767 uifc=Topology.get_interface_name(nodes['DUT1'],
770 'exec set interface unnumbered ipsec{i} use {uifc}\n'
771 'exec set interface state ipsec{i} up\n'
772 'exec ip route add {taddr}/32 via {raddr} ipsec{i}\n'
774 taddr=ip_address(unicode(raddr_ip1)) + i,
775 raddr=ip_address(unicode(if1_ip_addr)) + i * addr_incr,
777 uifc=Topology.get_interface_name(nodes['DUT2'],
779 vat.execute_script(tmp_fn1, nodes['DUT1'], timeout=300, json_out=False,
780 copy_on_execute=True)
781 vat.execute_script(tmp_fn2, nodes['DUT2'], timeout=300, json_out=False,
782 copy_on_execute=True)
787 def vpp_ipsec_add_multiple_tunnels(nodes, interface1, interface2,
788 n_tunnels, crypto_alg, integ_alg,
789 tunnel_ip1, tunnel_ip2, raddr_ip1,
790 raddr_ip2, raddr_range):
791 """Create multiple IPsec tunnels between two VPP nodes.
793 :param nodes: VPP nodes to create tunnels.
794 :param interface1: Interface name or sw_if_index on node 1.
795 :param interface2: Interface name or sw_if_index on node 2.
796 :param n_tunnels: Number of tunnels to create.
797 :param crypto_alg: The encryption algorithm name.
798 :param integ_alg: The integrity algorithm name.
799 :param tunnel_ip1: Tunnel node1 IPv4 address.
800 :param tunnel_ip2: Tunnel node2 IPv4 address.
801 :param raddr_ip1: Policy selector remote IPv4 start address for the
802 first tunnel in direction node1->node2.
803 :param raddr_ip2: Policy selector remote IPv4 start address for the
804 first tunnel in direction node2->node1.
805 :param raddr_range: Mask specifying range of Policy selector Remote IPv4
806 addresses. Valid values are from 1 to 32.
808 :type interface1: str or int
809 :type interface2: str or int
811 :type crypto_alg: CryptoAlg
813 :type tunnel_ip1: str
814 :type tunnel_ip2: str
815 :type raddr_ip1: string
816 :type raddr_ip2: string
817 :type raddr_range: int
827 crypto_key = gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg))
828 integ_key = gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg))
830 IPsecUtil.vpp_ipsec_set_ip_route(
831 nodes['DUT1'], n_tunnels, tunnel_ip1, raddr_ip2, tunnel_ip2,
832 interface1, raddr_range)
833 IPsecUtil.vpp_ipsec_set_ip_route(
834 nodes['DUT2'], n_tunnels, tunnel_ip2, raddr_ip1, tunnel_ip1,
835 interface2, raddr_range)
837 IPsecUtil.vpp_ipsec_add_spd(
838 nodes['DUT1'], spd_id)
839 IPsecUtil.vpp_ipsec_spd_add_if(
840 nodes['DUT1'], spd_id, interface1)
841 IPsecUtil.vpp_ipsec_policy_add(
842 nodes['DUT1'], spd_id, p_hi, PolicyAction.BYPASS, inbound=False,
844 IPsecUtil.vpp_ipsec_policy_add(
845 nodes['DUT1'], spd_id, p_hi, PolicyAction.BYPASS, inbound=True,
848 IPsecUtil.vpp_ipsec_add_spd(
849 nodes['DUT2'], spd_id)
850 IPsecUtil.vpp_ipsec_spd_add_if(
851 nodes['DUT2'], spd_id, interface2)
852 IPsecUtil.vpp_ipsec_policy_add(
853 nodes['DUT2'], spd_id, p_hi, PolicyAction.BYPASS, inbound=False,
855 IPsecUtil.vpp_ipsec_policy_add(
856 nodes['DUT2'], spd_id, p_hi, PolicyAction.BYPASS, inbound=True,
859 IPsecUtil.vpp_ipsec_add_sad_entries(
860 nodes['DUT1'], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key,
861 integ_alg, integ_key, tunnel_ip1, tunnel_ip2)
863 IPsecUtil.vpp_ipsec_spd_add_entries(
864 nodes['DUT1'], n_tunnels, spd_id, p_lo, False, sa_id_1, raddr_ip2)
866 IPsecUtil.vpp_ipsec_add_sad_entries(
867 nodes['DUT2'], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key,
868 integ_alg, integ_key, tunnel_ip1, tunnel_ip2)
870 IPsecUtil.vpp_ipsec_spd_add_entries(
871 nodes['DUT2'], n_tunnels, spd_id, p_lo, True, sa_id_1, raddr_ip2)
873 IPsecUtil.vpp_ipsec_add_sad_entries(
874 nodes['DUT2'], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key,
875 integ_alg, integ_key, tunnel_ip2, tunnel_ip1)
877 IPsecUtil.vpp_ipsec_spd_add_entries(
878 nodes['DUT2'], n_tunnels, spd_id, p_lo, False, sa_id_2, raddr_ip1)
880 IPsecUtil.vpp_ipsec_add_sad_entries(
881 nodes['DUT1'], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key,
882 integ_alg, integ_key, tunnel_ip2, tunnel_ip1)
884 IPsecUtil.vpp_ipsec_spd_add_entries(
885 nodes['DUT1'], n_tunnels, spd_id, p_lo, True, sa_id_2, raddr_ip1)
888 def vpp_ipsec_show(node):
889 """Run "show ipsec" debug CLI command.
891 :param node: Node to run command on.
894 VatExecutor().execute_script('ipsec/ipsec_show.vat', node,