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_256 = ('aes-cbc-256', 'AES-CBC', 32)
53 AES_GCM_128 = ('aes-gcm-128', 'AES-GCM', 16)
54 AES_GCM_256 = ('aes-gcm-256', 'AES-GCM', 32)
56 def __init__(self, alg_name, scapy_name, key_len):
57 self.alg_name = alg_name
58 self.scapy_name = scapy_name
59 self.key_len = key_len
63 """Integrity algorithm."""
64 SHA_256_128 = ('sha-256-128', 'SHA2-256-128', 32)
65 SHA_512_256 = ('sha-512-256', 'SHA2-512-256', 64)
66 AES_GCM_128 = ('aes-gcm-128', 'AES-GCM', 16)
67 AES_GCM_256 = ('aes-gcm-256', 'AES-GCM', 32)
69 def __init__(self, alg_name, scapy_name, key_len):
70 self.alg_name = alg_name
71 self.scapy_name = scapy_name
72 self.key_len = key_len
75 class IPsecProto(IntEnum):
81 class IPsecUtil(object):
82 """IPsec utilities."""
85 def policy_action_bypass():
86 """Return policy action bypass.
88 :returns: PolicyAction enum BYPASS object.
91 return PolicyAction.BYPASS
94 def policy_action_discard():
95 """Return policy action discard.
97 :returns: PolicyAction enum DISCARD object.
100 return PolicyAction.DISCARD
103 def policy_action_protect():
104 """Return policy action protect.
106 :returns: PolicyAction enum PROTECT object.
109 return PolicyAction.PROTECT
112 def crypto_alg_aes_cbc_128():
113 """Return encryption algorithm aes-cbc-128.
115 :returns: CryptoAlg enum AES_CBC_128 object.
118 return CryptoAlg.AES_CBC_128
121 def crypto_alg_aes_cbc_256():
122 """Return encryption algorithm aes-cbc-256.
124 :returns: CryptoAlg enum AES_CBC_256 object.
127 return CryptoAlg.AES_CBC_256
130 def crypto_alg_aes_gcm_128():
131 """Return encryption algorithm aes-gcm-128.
133 :returns: CryptoAlg enum AES_GCM_128 object.
136 return CryptoAlg.AES_GCM_128
139 def crypto_alg_aes_gcm_256():
140 """Return encryption algorithm aes-gcm-256.
142 :returns: CryptoAlg enum AES_GCM_128 object.
145 return CryptoAlg.AES_GCM_256
148 def get_crypto_alg_key_len(crypto_alg):
149 """Return encryption algorithm key length.
151 :param crypto_alg: Encryption algorithm.
152 :type crypto_alg: CryptoAlg
153 :returns: Key length.
156 return crypto_alg.key_len
159 def get_crypto_alg_scapy_name(crypto_alg):
160 """Return encryption algorithm scapy name.
162 :param crypto_alg: Encryption algorithm.
163 :type crypto_alg: CryptoAlg
164 :returns: Algorithm scapy name.
167 return crypto_alg.scapy_name
170 def integ_alg_sha_256_128():
171 """Return integrity algorithm SHA-256-128.
173 :returns: IntegAlg enum SHA_256_128 object.
176 return IntegAlg.SHA_256_128
179 def integ_alg_sha_512_256():
180 """Return integrity algorithm SHA-512-256.
182 :returns: IntegAlg enum SHA_512_256 object.
185 return IntegAlg.SHA_512_256
188 def integ_alg_aes_gcm_128():
189 """Return integrity algorithm AES-GCM-128.
191 :returns: IntegAlg enum AES_GCM_128 object.
194 return IntegAlg.AES_GCM_128
197 def integ_alg_aes_gcm_256():
198 """Return integrity algorithm AES-GCM-256.
200 :returns: IntegAlg enum AES_GCM_256 object.
203 return IntegAlg.AES_GCM_256
206 def get_integ_alg_key_len(integ_alg):
207 """Return integrity algorithm key length.
209 :param integ_alg: Integrity algorithm.
210 :type integ_alg: IntegAlg
211 :returns: Key length.
214 return integ_alg.key_len
217 def get_integ_alg_scapy_name(integ_alg):
218 """Return integrity algorithm scapy name.
220 :param integ_alg: Integrity algorithm.
221 :type integ_alg: IntegAlg
222 :returns: Algorithm scapy name.
225 return integ_alg.scapy_name
228 def ipsec_proto_esp():
229 """Return IPSec protocol ESP.
231 :returns: IPsecProto enum ESP object.
234 return int(IPsecProto.ESP)
237 def ipsec_proto_ah():
238 """Return IPSec protocol AH.
240 :returns: IPsecProto enum AH object.
243 return int(IPsecProto.SEC_AH)
246 def vpp_ipsec_select_backend(node, protocol, index=1):
247 """Select IPsec backend.
249 :param node: VPP node to select IPsec backend on.
250 :param protocol: IPsec protocol.
251 :param index: Backend index.
253 :type protocol: IPsecProto
255 :raises RuntimeError: If failed to select IPsec backend or if no API
259 cmd = 'ipsec_select_backend'
260 err_msg = 'Failed to select IPsec backend on host {host}'.format(
262 args = dict(protocol=protocol, index=index)
263 with PapiExecutor(node) as papi_exec:
264 papi_exec.add(cmd, **args).get_reply(err_msg)
267 def vpp_ipsec_backend_dump(node):
268 """Dump IPsec backends.
270 :param node: VPP node to dump IPsec backend on.
274 err_msg = 'Failed to dump IPsec backends on host {host}'.format(
276 with PapiExecutor(node) as papi_exec:
277 papi_exec.add('ipsec_backend_dump').get_details(err_msg)
280 def vpp_ipsec_add_sad_entry(node, sad_id, spi, crypto_alg, crypto_key,
281 integ_alg, integ_key, tunnel_src=None,
283 """Create Security Association Database entry on the VPP node.
285 :param node: VPP node to add SAD entry on.
286 :param sad_id: SAD entry ID.
287 :param spi: Security Parameter Index of this SAD entry.
288 :param crypto_alg: The encryption algorithm name.
289 :param crypto_key: The encryption key string.
290 :param integ_alg: The integrity algorithm name.
291 :param integ_key: The integrity key string.
292 :param tunnel_src: Tunnel header source IPv4 or IPv6 address. If not
293 specified ESP transport mode is used.
294 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address. If
295 not specified ESP transport mode is used.
299 :type crypto_alg: CryptoAlg
300 :type crypto_key: str
301 :type integ_alg: IntegAlg
303 :type tunnel_src: str
304 :type tunnel_dst: str
306 ckey = crypto_key.encode('hex')
307 ikey = integ_key.encode('hex')
308 tunnel = 'tunnel-src {0} tunnel-dst {1}'.format(tunnel_src, tunnel_dst)\
309 if tunnel_src is not None and tunnel_dst is not None else ''
311 out = VatExecutor.cmd_from_template(node,
312 'ipsec/ipsec_sad_add_entry.vat',
313 sad_id=sad_id, spi=spi,
314 calg=crypto_alg.alg_name, ckey=ckey,
315 ialg=integ_alg.alg_name, ikey=ikey,
317 VatJsonUtil.verify_vat_retval(
319 err_msg='Add SAD entry failed on {0}'.format(node['host']))
322 def vpp_ipsec_add_sad_entries(node, n_entries, sad_id, spi, crypto_alg,
323 crypto_key, integ_alg, integ_key,
324 tunnel_src=None, tunnel_dst=None):
325 """Create multiple Security Association Database entries on VPP node.
327 :param node: VPP node to add SAD entry on.
328 :param n_entries: Number of SAD entries to be created.
329 :param sad_id: First SAD entry ID. All subsequent SAD entries will have
331 :param spi: Security Parameter Index of first SAD entry. All subsequent
332 SAD entries will have spi incremented by 1.
333 :param crypto_alg: The encryption algorithm name.
334 :param crypto_key: The encryption key string.
335 :param integ_alg: The integrity algorithm name.
336 :param integ_key: The integrity key string.
337 :param tunnel_src: Tunnel header source IPv4 or IPv6 address. If not
338 specified ESP transport mode is used.
339 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address. If
340 not specified ESP transport mode is used.
345 :type crypto_alg: CryptoAlg
346 :type crypto_key: str
347 :type integ_alg: IntegAlg
349 :type tunnel_src: str
350 :type tunnel_dst: str
352 tmp_filename = '/tmp/ipsec_sad_{0}_add_del_entry.script'.format(sad_id)
354 addr_incr = 1 << (32 - 24)
356 with open(tmp_filename, 'w') as tmp_file:
357 for i in range(0, n_entries):
359 if not crypto_alg.alg_name.startswith('aes-gcm-'):
361 'integ-alg {integ_alg} integ-key {integ_key}'.
363 integ_alg=integ_alg.alg_name,
364 integ_key=integ_key))
366 'tunnel-src {laddr} tunnel-dst {raddr}'.
368 laddr=ip_address(unicode(tunnel_src)) + i * addr_incr,
369 raddr=ip_address(unicode(tunnel_dst)) + i * addr_incr)
370 if tunnel_src and tunnel_dst is not None else '')
372 'exec ipsec sa add {sad_id} esp spi {spi} '
373 'crypto-alg {crypto_alg} crypto-key {crypto_key} '
374 '{integ} {tunnel}\n'.
378 crypto_alg=crypto_alg.alg_name,
379 crypto_key=crypto_key,
384 vat.execute_script(tmp_filename, node, timeout=300, json_out=False,
385 copy_on_execute=True)
386 os.remove(tmp_filename)
389 def vpp_ipsec_set_ip_route(node, n_tunnels, tunnel_src, traffic_addr,
390 tunnel_dst, interface, raddr_range):
391 """Set IP address and route on interface.
393 :param node: VPP node to add config on.
394 :param n_tunnels: Number of tunnels to create.
395 :param tunnel_src: Tunnel header source IPv4 or IPv6 address.
396 :param traffic_addr: Traffic destination IP address to route.
397 :param tunnel_dst: Tunnel header destination IPv4 or IPv6 address.
398 :param interface: Interface key on node 1.
399 :param raddr_range: Mask specifying range of Policy selector Remote IPv4
400 addresses. Valid values are from 1 to 32.
403 :type tunnel_src: str
404 :type traffic_addr: str
405 :type tunnel_dst: str
407 :type raddr_range: int
409 tmp_filename = '/tmp/ipsec_set_ip.script'
411 addr_incr = 1 << (32 - raddr_range)
413 with open(tmp_filename, 'w') as tmp_file:
414 for i in range(0, n_tunnels):
416 'exec set interface ip address {interface} {laddr}/24\n'
417 'exec ip route add {taddr}/32 via {raddr} {interface}\n'.
419 interface=Topology.get_interface_name(node, interface),
420 laddr=ip_address(unicode(tunnel_src)) + i * addr_incr,
421 raddr=ip_address(unicode(tunnel_dst)) + i * addr_incr,
422 taddr=ip_address(unicode(traffic_addr)) + i))
425 vat.execute_script(tmp_filename, node, timeout=300, json_out=False,
426 copy_on_execute=True)
427 os.remove(tmp_filename)
430 def vpp_ipsec_sa_set_key(node, sa_id, crypto_key, integ_key):
431 """Update Security Association (SA) keys.
433 :param node: VPP node to update SA keys.
434 :param sa_id: SAD entry ID.
435 :param crypto_key: The encryption key string.
436 :param integ_key: The integrity key string.
439 :type crypto_key: str
442 ckey = crypto_key.encode('hex')
443 ikey = integ_key.encode('hex')
445 out = VatExecutor.cmd_from_template(
446 node, 'ipsec/ipsec_sa_set_key.vat', json_param=False, sa_id=sa_id,
447 ckey=ckey, ikey=ikey)
448 VatJsonUtil.verify_vat_retval(
450 err_msg='Update SA key failed on {0}'.format(node['host']))
453 def vpp_ipsec_add_spd(node, spd_id):
454 """Create Security Policy Database on the VPP node.
456 :param node: VPP node to add SPD on.
457 :param spd_id: SPD ID.
461 out = VatExecutor.cmd_from_template(node, 'ipsec/ipsec_spd_add.vat',
463 VatJsonUtil.verify_vat_retval(
465 err_msg='Add SPD {0} failed on {1}'.format(spd_id, node['host']))
468 def vpp_ipsec_spd_add_if(node, spd_id, interface):
469 """Add interface to the Security Policy Database.
471 :param node: VPP node.
472 :param spd_id: SPD ID to add interface on.
473 :param interface: Interface name or sw_if_index.
476 :type interface: str or int
478 sw_if_index = Topology.get_interface_sw_index(node, interface)\
479 if isinstance(interface, basestring) else interface
481 out = VatExecutor.cmd_from_template(node,
482 'ipsec/ipsec_interface_add_spd.vat',
483 spd_id=spd_id, sw_if_id=sw_if_index)
484 VatJsonUtil.verify_vat_retval(
486 err_msg='Add interface {0} to SPD {1} failed on {2}'.format(
487 interface, spd_id, node['host']))
490 def vpp_ipsec_policy_add(node, spd_id, priority, action, inbound=True,
491 sa_id=None, laddr_range=None, raddr_range=None,
492 proto=None, lport_range=None, rport_range=None,
494 """Create Security Policy Database entry on the VPP node.
496 :param node: VPP node to add SPD entry on.
497 :param spd_id: SPD ID to add entry on.
498 :param priority: SPD entry priority, higher number = higher priority.
499 :param action: Policy action.
500 :param inbound: If True policy is for inbound traffic, otherwise
502 :param sa_id: SAD entry ID for protect action.
503 :param laddr_range: Policy selector local IPv4 or IPv6 address range in
504 format IP/prefix or IP/mask. If no mask is provided,
505 it's considered to be /32.
506 :param raddr_range: Policy selector remote IPv4 or IPv6 address range in
507 format IP/prefix or IP/mask. If no mask is provided,
508 it's considered to be /32.
509 :param proto: Policy selector next layer protocol number.
510 :param lport_range: Policy selector local TCP/UDP port range in format
511 <port_start>-<port_end>.
512 :param rport_range: Policy selector remote TCP/UDP port range in format
513 <port_start>-<port_end>.
514 :param is_ipv6: True in case of IPv6 policy when IPv6 address range is
515 not defined so it will default to address ::/0, otherwise False.
519 :type action: PolicyAction
522 :type laddr_range: string
523 :type raddr_range: string
525 :type lport_range: string
526 :type rport_range: string
529 direction = 'inbound' if inbound else 'outbound'
531 if laddr_range is None and is_ipv6:
534 if raddr_range is None and is_ipv6:
537 act_str = action.value
538 if PolicyAction.PROTECT == action and sa_id is not None:
539 act_str += ' sa {0}'.format(sa_id)
542 if laddr_range is not None:
543 net = ip_network(unicode(laddr_range), strict=False)
544 selector += 'local-ip-range {0} - {1} '.format(
545 net.network_address, net.broadcast_address)
546 if raddr_range is not None:
547 net = ip_network(unicode(raddr_range), strict=False)
548 selector += 'remote-ip-range {0} - {1} '.format(
549 net.network_address, net.broadcast_address)
550 if proto is not None:
551 selector += 'protocol {0} '.format(proto)
552 if lport_range is not None:
553 selector += 'local-port-range {0} '.format(lport_range)
554 if rport_range is not None:
555 selector += 'remote-port-range {0} '.format(rport_range)
557 out = VatExecutor.cmd_from_template(
558 node, 'ipsec/ipsec_policy_add.vat', json_param=False, spd_id=spd_id,
559 priority=priority, action=act_str, direction=direction,
561 VatJsonUtil.verify_vat_retval(
563 err_msg='Add IPsec policy ID {0} failed on {1}'.format(
564 spd_id, node['host']))
567 def vpp_ipsec_spd_add_entries(node, n_entries, spd_id, priority, inbound,
569 """Create multiple Security Policy Database entries on the VPP node.
571 :param node: VPP node to add SPD entries on.
572 :param n_entries: Number of SPD entries to be added.
573 :param spd_id: SPD ID to add entries on.
574 :param priority: SPD entries priority, higher number = higher priority.
575 :param inbound: If True policy is for inbound traffic, otherwise
577 :param sa_id: SAD entry ID for first entry. Each subsequent entry will
578 SAD entry ID incremented by 1.
579 :param raddr_ip: Policy selector remote IPv4 start address for the first
580 entry. Remote IPv4 end address will be calculated depending on
581 raddr_range parameter. Each subsequent entry will have start address
582 next after IPv4 end address of previous entry.
589 :type raddr_ip: string
591 tmp_filename = '/tmp/ipsec_spd_{0}_add_del_entry.script'.format(sa_id)
593 with open(tmp_filename, 'w') as tmp_file:
594 for i in range(0, n_entries):
595 raddr_s = ip_address(unicode(raddr_ip)) + i
596 raddr_e = ip_address(unicode(raddr_ip)) + (i + 1) - 1
598 'exec ipsec policy add spd {spd_id} priority {priority} '
599 '{direction} action protect sa {sa_id} '
600 'remote-ip-range {raddr_s} - {raddr_e} '
601 'local-ip-range 0.0.0.0 - 255.255.255.255\n'.
605 direction='inbound' if inbound else 'outbound',
609 tmp_file.write(tunnel)
611 vat.execute_script(tmp_filename, node, timeout=300, json_out=False,
612 copy_on_execute=True)
613 os.remove(tmp_filename)
616 def vpp_ipsec_create_tunnel_interfaces(nodes, if1_ip_addr, if2_ip_addr,
617 if1_key, if2_key, n_tunnels,
618 crypto_alg, integ_alg, raddr_ip1,
619 raddr_ip2, raddr_range):
620 """Create multiple IPsec tunnel interfaces between two VPP nodes.
622 :param nodes: VPP nodes to create tunnel interfaces.
623 :param if1_ip_addr: VPP node 1 interface IP4 address.
624 :param if2_ip_addr: VPP node 2 interface IP4 address.
625 :param if1_key: VPP node 1 interface key from topology file.
626 :param if2_key: VPP node 2 interface key from topology file.
627 :param n_tunnels: Number of tunnell interfaces to create.
628 :param crypto_alg: The encryption algorithm name.
629 :param integ_alg: The integrity algorithm name.
630 :param raddr_ip1: Policy selector remote IPv4 start address for the
631 first tunnel in direction node1->node2.
632 :param raddr_ip2: Policy selector remote IPv4 start address for the
633 first tunnel in direction node2->node1.
634 :param raddr_range: Mask specifying range of Policy selector Remote IPv4
635 addresses. Valid values are from 1 to 32.
637 :type if1_ip_addr: str
638 :type if2_ip_addr: str
642 :type crypto_alg: CryptoAlg
643 :type integ_alg: IntegAlg
644 :type raddr_ip1: string
645 :type raddr_ip2: string
646 :type raddr_range: int
650 addr_incr = 1 << (32 - raddr_range)
652 tmp_fn1 = '/tmp/ipsec_create_tunnel_dut1.config'
653 tmp_fn2 = '/tmp/ipsec_create_tunnel_dut2.config'
657 with open(tmp_fn1, 'w') as tmp_f1, open(tmp_fn2, 'w') as tmp_f2:
659 'exec create loopback interface\n'
660 'exec set interface state loop0 up\n'
661 'exec set interface ip address {uifc} {iaddr}/24\n'
663 iaddr=ip_address(unicode(if2_ip_addr)) - 1,
664 uifc=Topology.get_interface_name(nodes['DUT1'], if1_key)))
666 'exec set interface ip address {uifc} {iaddr}/24\n'
668 iaddr=ip_address(unicode(if2_ip_addr)),
669 uifc=Topology.get_interface_name(nodes['DUT2'], if2_key)))
670 for i in range(0, n_tunnels):
671 ckey = gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg))
672 ikey = gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg))
674 if not crypto_alg.alg_name.startswith('aes-gcm-'):
676 'integ_alg {integ_alg} '
677 'local_integ_key {local_integ_key} '
678 'remote_integ_key {remote_integ_key} '
680 integ_alg=integ_alg.alg_name,
681 local_integ_key=ikey,
682 remote_integ_key=ikey))
684 'exec set interface ip address loop0 {laddr}/32\n'
685 'ipsec_tunnel_if_add_del '
686 'local_spi {local_spi} '
687 'remote_spi {remote_spi} '
688 'crypto_alg {crypto_alg} '
689 'local_crypto_key {local_crypto_key} '
690 'remote_crypto_key {remote_crypto_key} '
693 'remote_ip {raddr}\n'
696 remote_spi=spi_2 + i,
697 crypto_alg=crypto_alg.alg_name,
698 local_crypto_key=ckey,
699 remote_crypto_key=ckey,
701 laddr=ip_address(unicode(if1_ip_addr)) + i * addr_incr,
702 raddr=ip_address(unicode(if2_ip_addr))))
704 'ipsec_tunnel_if_add_del '
705 'local_spi {local_spi} '
706 'remote_spi {remote_spi} '
707 'crypto_alg {crypto_alg} '
708 'local_crypto_key {local_crypto_key} '
709 'remote_crypto_key {remote_crypto_key} '
712 'remote_ip {raddr}\n'
715 remote_spi=spi_1 + i,
716 crypto_alg=crypto_alg.alg_name,
717 local_crypto_key=ckey,
718 remote_crypto_key=ckey,
720 laddr=ip_address(unicode(if2_ip_addr)),
721 raddr=ip_address(unicode(if1_ip_addr)) + i * addr_incr))
722 vat.execute_script(tmp_fn1, nodes['DUT1'], timeout=1800, json_out=False,
723 copy_on_execute=True)
724 vat.execute_script(tmp_fn2, nodes['DUT2'], timeout=1800, json_out=False,
725 copy_on_execute=True)
729 with open(tmp_fn1, 'w') as tmp_f1, open(tmp_fn2, 'w') as tmp_f2:
731 'exec ip route add {raddr} via {uifc} {iaddr}\n'
733 raddr=ip_network(unicode(if1_ip_addr+'/8'), False),
734 iaddr=ip_address(unicode(if2_ip_addr)) - 1,
735 uifc=Topology.get_interface_name(nodes['DUT2'], if2_key)))
736 for i in range(0, n_tunnels):
738 'exec set interface unnumbered ipsec{i} use {uifc}\n'
739 'exec set interface state ipsec{i} up\n'
740 'exec ip route add {taddr}/32 via ipsec{i}\n'
742 taddr=ip_address(unicode(raddr_ip2)) + i,
744 uifc=Topology.get_interface_name(nodes['DUT1'],
747 'exec set interface unnumbered ipsec{i} use {uifc}\n'
748 'exec set interface state ipsec{i} up\n'
749 'exec ip route add {taddr}/32 via ipsec{i}\n'
751 taddr=ip_address(unicode(raddr_ip1)) + i,
753 uifc=Topology.get_interface_name(nodes['DUT2'],
755 vat.execute_script(tmp_fn1, nodes['DUT1'], timeout=1800, json_out=False,
756 copy_on_execute=True)
757 vat.execute_script(tmp_fn2, nodes['DUT2'], timeout=1800, json_out=False,
758 copy_on_execute=True)
763 def vpp_ipsec_add_multiple_tunnels(nodes, interface1, interface2,
764 n_tunnels, crypto_alg, integ_alg,
765 tunnel_ip1, tunnel_ip2, raddr_ip1,
766 raddr_ip2, raddr_range):
767 """Create multiple IPsec tunnels between two VPP nodes.
769 :param nodes: VPP nodes to create tunnels.
770 :param interface1: Interface name or sw_if_index on node 1.
771 :param interface2: Interface name or sw_if_index on node 2.
772 :param n_tunnels: Number of tunnels to create.
773 :param crypto_alg: The encryption algorithm name.
774 :param integ_alg: The integrity algorithm name.
775 :param tunnel_ip1: Tunnel node1 IPv4 address.
776 :param tunnel_ip2: Tunnel node2 IPv4 address.
777 :param raddr_ip1: Policy selector remote IPv4 start address for the
778 first tunnel in direction node1->node2.
779 :param raddr_ip2: Policy selector remote IPv4 start address for the
780 first tunnel in direction node2->node1.
781 :param raddr_range: Mask specifying range of Policy selector Remote IPv4
782 addresses. Valid values are from 1 to 32.
784 :type interface1: str or int
785 :type interface2: str or int
787 :type crypto_alg: CryptoAlg
789 :type tunnel_ip1: str
790 :type tunnel_ip2: str
791 :type raddr_ip1: string
792 :type raddr_ip2: string
793 :type raddr_range: int
803 crypto_key = gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg))
804 integ_key = gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg))
806 IPsecUtil.vpp_ipsec_set_ip_route(
807 nodes['DUT1'], n_tunnels, tunnel_ip1, raddr_ip2, tunnel_ip2,
808 interface1, raddr_range)
809 IPsecUtil.vpp_ipsec_set_ip_route(
810 nodes['DUT2'], n_tunnels, tunnel_ip2, raddr_ip1, tunnel_ip1,
811 interface2, raddr_range)
813 IPsecUtil.vpp_ipsec_add_spd(
814 nodes['DUT1'], spd_id)
815 IPsecUtil.vpp_ipsec_spd_add_if(
816 nodes['DUT1'], spd_id, interface1)
817 IPsecUtil.vpp_ipsec_policy_add(
818 nodes['DUT1'], spd_id, p_hi, PolicyAction.BYPASS, inbound=False,
819 proto=50, laddr_range='100.0.0.0/8', raddr_range='100.0.0.0/8')
820 IPsecUtil.vpp_ipsec_policy_add(
821 nodes['DUT1'], spd_id, p_hi, PolicyAction.BYPASS, inbound=True,
822 proto=50, laddr_range='100.0.0.0/8', raddr_range='100.0.0.0/8')
824 IPsecUtil.vpp_ipsec_add_spd(
825 nodes['DUT2'], spd_id)
826 IPsecUtil.vpp_ipsec_spd_add_if(
827 nodes['DUT2'], spd_id, interface2)
828 IPsecUtil.vpp_ipsec_policy_add(
829 nodes['DUT2'], spd_id, p_hi, PolicyAction.BYPASS, inbound=False,
830 proto=50, laddr_range='100.0.0.0/8', raddr_range='100.0.0.0/8')
831 IPsecUtil.vpp_ipsec_policy_add(
832 nodes['DUT2'], spd_id, p_hi, PolicyAction.BYPASS, inbound=True,
833 proto=50, laddr_range='100.0.0.0/8', raddr_range='100.0.0.0/8')
835 IPsecUtil.vpp_ipsec_add_sad_entries(
836 nodes['DUT1'], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key,
837 integ_alg, integ_key, tunnel_ip1, tunnel_ip2)
839 IPsecUtil.vpp_ipsec_spd_add_entries(
840 nodes['DUT1'], n_tunnels, spd_id, p_lo, False, sa_id_1, raddr_ip2)
842 IPsecUtil.vpp_ipsec_add_sad_entries(
843 nodes['DUT2'], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key,
844 integ_alg, integ_key, tunnel_ip1, tunnel_ip2)
846 IPsecUtil.vpp_ipsec_spd_add_entries(
847 nodes['DUT2'], n_tunnels, spd_id, p_lo, True, sa_id_1, raddr_ip2)
849 IPsecUtil.vpp_ipsec_add_sad_entries(
850 nodes['DUT2'], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key,
851 integ_alg, integ_key, tunnel_ip2, tunnel_ip1)
853 IPsecUtil.vpp_ipsec_spd_add_entries(
854 nodes['DUT2'], n_tunnels, spd_id, p_lo, False, sa_id_2, raddr_ip1)
856 IPsecUtil.vpp_ipsec_add_sad_entries(
857 nodes['DUT1'], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key,
858 integ_alg, integ_key, tunnel_ip2, tunnel_ip1)
860 IPsecUtil.vpp_ipsec_spd_add_entries(
861 nodes['DUT1'], n_tunnels, spd_id, p_lo, True, sa_id_2, raddr_ip1)
864 def vpp_ipsec_show(node):
865 """Run "show ipsec" debug CLI command.
867 :param node: Node to run command on.
870 VatExecutor().execute_script('ipsec/ipsec_show.vat', node,