fix(IPsec): fix policy tests
[csit.git] / resources / libraries / python / IPsecUtil.py
index 6bf3e8d..e3b3c88 100644 (file)
@@ -1,5 +1,5 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
-# Copyright (c) 2021 PANTHEON.tech s.r.o.
+# Copyright (c) 2022 Cisco and/or its affiliates.
+# Copyright (c) 2022 PANTHEON.tech s.r.o.
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at:
@@ -437,7 +437,7 @@ class IPsecUtil:
             src_addr = u""
             dst_addr = u""
 
-        cmd = u"ipsec_sad_entry_add_del_v2"
+        cmd = u"ipsec_sad_entry_add_del_v3"
         err_msg = f"Failed to add Security Association Database entry " \
             f"on host {node[u'host']}"
         sad_entry = dict(
@@ -448,12 +448,15 @@ class IPsecUtil:
             integrity_algorithm=integ_alg.alg_int_repr if integ_alg else 0,
             integrity_key=ikey,
             flags=flags,
-            tunnel_src=str(src_addr),
-            tunnel_dst=str(dst_addr),
-            tunnel_flags=int(
-                TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
+            tunnel=dict(
+                src=str(src_addr),
+                dst=str(dst_addr),
+                table_id=0,
+                encap_decap_flags=int(
+                    TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
+                ),
+                dscp=int(IpDscp.IP_API_DSCP_CS0),
             ),
-            dscp=int(IpDscp.IP_API_DSCP_CS0),
             protocol=int(IPsecProto.IPSEC_API_PROTO_ESP),
             udp_src_port=4500,  # default value in api
             udp_dst_port=4500  # default value in api
@@ -551,7 +554,7 @@ class IPsecUtil:
                     IPsecSadFlags.IPSEC_API_SAD_FLAG_IS_TUNNEL_V6
                 )
 
-        cmd = u"ipsec_sad_entry_add_del_v2"
+        cmd = u"ipsec_sad_entry_add_del_v3"
         err_msg = f"Failed to add Security Association Database entry " \
             f"on host {node[u'host']}"
 
@@ -563,12 +566,15 @@ class IPsecUtil:
             integrity_algorithm=integ_alg.alg_int_repr if integ_alg else 0,
             integrity_key=ikey,
             flags=flags,
-            tunnel_src=str(src_addr),
-            tunnel_dst=str(dst_addr),
-            tunnel_flags=int(
-                TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
+            tunnel=dict(
+                src=str(src_addr),
+                dst=str(dst_addr),
+                table_id=0,
+                encap_decap_flags=int(
+                    TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
+                ),
+                dscp=int(IpDscp.IP_API_DSCP_CS0),
             ),
-            dscp=int(IpDscp.IP_API_DSCP_CS0),
             protocol=int(IPsecProto.IPSEC_API_PROTO_ESP),
             udp_src_port=4500,  # default value in api
             udp_dst_port=4500  # default value in api
@@ -581,10 +587,14 @@ class IPsecUtil:
             for i in range(n_entries):
                 args[u"entry"][u"sad_id"] = int(sad_id) + i
                 args[u"entry"][u"spi"] = int(spi) + i
-                args[u"entry"][u"tunnel_src"] = str(src_addr + i * addr_incr) \
+                args[u"entry"][u"tunnel"][u"src"] = (
+                    str(src_addr + i * addr_incr)
                     if tunnel_src and tunnel_dst else src_addr
-                args[u"entry"][u"tunnel_dst"] = str(dst_addr + i * addr_incr) \
+                )
+                args[u"entry"][u"tunnel"][u"dst"] = (
+                    str(dst_addr + i * addr_incr)
                     if tunnel_src and tunnel_dst else dst_addr
+                )
                 history = bool(not 1 < i < n_entries - 2)
                 papi_exec.add(cmd, history=history, **args)
             papi_exec.get_replies(err_msg)
@@ -617,6 +627,7 @@ class IPsecUtil:
         tunnel_src = ip_address(tunnel_src)
         tunnel_dst = ip_address(tunnel_dst)
         traffic_addr = ip_address(traffic_addr)
+        tunnel_dst_prefix = 128 if tunnel_dst.version == 6 else 32
         addr_incr = 1 << (128 - raddr_range) if tunnel_src.version == 6 \
             else 1 << (32 - raddr_range)
 
@@ -626,11 +637,15 @@ class IPsecUtil:
             with open(tmp_filename, 'w') as tmp_file:
                 if_name = Topology.get_interface_name(node, interface)
                 for i in range(n_tunnels):
+                    tunnel_dst_addr = tunnel_dst + i * addr_incr
                     conf = f"exec set interface ip address {if_name} " \
                         f"{tunnel_src + i * addr_incr}/{raddr_range}\n" \
                         f"exec ip route add {traffic_addr + i}/" \
-                        f"{128 if traffic_addr.version == 6 else 32} " \
-                        f"via {tunnel_dst + i * addr_incr} {if_name}\n"
+                        f"{tunnel_dst_prefix} " \
+                        f"via {tunnel_dst_addr} {if_name}\n" \
+                        f"exec ip route add {tunnel_dst_addr}/" \
+                        f"{tunnel_dst_prefix} " \
+                        f"via {tunnel_dst_addr} {if_name}\n"
                     if dst_mac:
                         conf = f"{conf}exec set ip neighbor {if_name} " \
                                f"{tunnel_dst + i * addr_incr} {dst_mac}\n"
@@ -674,20 +689,29 @@ class IPsecUtil:
 
         with PapiSocketExecutor(node) as papi_exec:
             for i in range(n_tunnels):
+                tunnel_dst_addr = tunnel_dst + i * addr_incr
                 args1[u"prefix"] = IPUtil.create_prefix_object(
                     tunnel_src + i * addr_incr, raddr_range
                 )
                 args2[u"route"] = IPUtil.compose_vpp_route_structure(
                     node, traffic_addr + i,
-                    prefix_len=128 if traffic_addr.version == 6 else 32,
-                    interface=interface, gateway=tunnel_dst + i * addr_incr
+                    prefix_len=tunnel_dst_prefix,
+                    interface=interface, gateway=tunnel_dst_addr
                 )
                 history = bool(not 1 < i < n_tunnels - 2)
                 papi_exec.add(cmd1, history=history, **args1).\
                     add(cmd2, history=history, **args2)
+
+                args2[u"route"] = IPUtil.compose_vpp_route_structure(
+                    node, tunnel_dst_addr,
+                    prefix_len=tunnel_dst_prefix,
+                    interface=interface, gateway=tunnel_dst_addr
+                )
+                papi_exec.add(cmd2, history=history, **args2)
+
                 if dst_mac:
                     args3[u"neighbor"][u"ip_address"] = ip_address(
-                        tunnel_dst + i * addr_incr
+                        tunnel_dst_addr
                     )
                     papi_exec.add(cmd3, history=history, **args3)
             papi_exec.get_replies(err_msg)
@@ -777,11 +801,11 @@ class IPsecUtil:
         :type action: IPsecUtil.PolicyAction
         :type inbound: bool
         :type bidirectional: bool
-        :raises NotImplemented: When the action is PolicyAction.PROTECT.
+        :raises NotImplementedError: When the action is PolicyAction.PROTECT.
         """
 
         if action == PolicyAction.PROTECT:
-            raise NotImplemented('Policy action PROTECT is not supported.')
+            raise NotImplementedError('Policy action PROTECT is not supported.')
 
         spd_id_dir1 = 1
         spd_id_dir2 = 2
@@ -813,12 +837,12 @@ class IPsecUtil:
             # create a NetworkIncrement representation of the network,
             # then skip the matching network
             no_match_local_addr_range = NetworkIncrement(
-                ip_network(local_addr_range), 1
+                ip_network(local_addr_range)
             )
             next(no_match_local_addr_range)
 
             no_match_remote_addr_range = NetworkIncrement(
-                ip_network(remote_addr_range), 1
+                ip_network(remote_addr_range)
             )
             next(no_match_remote_addr_range)
 
@@ -834,12 +858,12 @@ class IPsecUtil:
                 # reset the networks so that we're using a unified config
                 # the address ranges are switched
                 no_match_remote_addr_range = NetworkIncrement(
-                    ip_network(local_addr_range), 1
+                    ip_network(local_addr_range)
                 )
                 next(no_match_remote_addr_range)
 
                 no_match_local_addr_range = NetworkIncrement(
-                    ip_network(remote_addr_range), 1
+                    ip_network(remote_addr_range)
                 )
                 next(no_match_local_addr_range)
                 # non-matching entries direction 2
@@ -1004,7 +1028,7 @@ class IPsecUtil:
             tmp_filename = f"/tmp/ipsec_spd_{spd_id}_add_del_entry.script"
 
             with open(tmp_filename, 'w') as tmp_file:
-                for i in range(n_entries):
+                for _ in range(n_entries):
                     direction = u'inbound' if inbound else u'outbound'
                     sa = f' sa {sa_id.inc_fmt()}' if sa_id is not None else ''
                     protocol = f' protocol {protocol}' if proto else ''
@@ -1031,7 +1055,7 @@ class IPsecUtil:
             os.remove(tmp_filename)
             return
 
-        for i in range(n_entries):
+        for _ in range(n_entries):
             IPsecUtil.vpp_ipsec_add_spd_entry(
                 node, spd_id, next(priority), action, inbound,
                 next(sa_id) if sa_id is not None else sa_id,
@@ -1439,7 +1463,7 @@ class IPsecUtil:
             # Configure IPSec SAD entries
             ckeys = [bytes()] * existing_tunnels
             ikeys = [bytes()] * existing_tunnels
-            cmd = u"ipsec_sad_entry_add_del_v2"
+            cmd = u"ipsec_sad_entry_add_del_v3"
             c_key = dict(
                 length=0,
                 data=None
@@ -1457,16 +1481,18 @@ class IPsecUtil:
                 integrity_algorithm=integ_alg.alg_int_repr if integ_alg else 0,
                 integrity_key=i_key,
                 flags=None,
-                tunnel_src=0,
-                tunnel_dst=0,
-                tunnel_flags=int(
-                    TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
+                tunnel=dict(
+                    src=0,
+                    dst=0,
+                    table_id=0,
+                    encap_decap_flags=int(
+                        TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
+                    ),
+                    dscp=int(IpDscp.IP_API_DSCP_CS0),
                 ),
-                dscp=int(IpDscp.IP_API_DSCP_CS0),
-                table_id=0,
                 salt=0,
                 udp_src_port=IPSEC_UDP_PORT_NONE,
-                udp_dst_port=IPSEC_UDP_PORT_NONE
+                udp_dst_port=IPSEC_UDP_PORT_NONE,
             )
             args = dict(
                 is_add=True,
@@ -1679,7 +1705,7 @@ class IPsecUtil:
                 ]
             )
             # Configure IPSec SAD entries
-            cmd = u"ipsec_sad_entry_add_del_v2"
+            cmd = u"ipsec_sad_entry_add_del_v3"
             c_key = dict(
                 length=0,
                 data=None
@@ -1692,23 +1718,23 @@ class IPsecUtil:
                 sad_id=None,
                 spi=None,
                 protocol=int(IPsecProto.IPSEC_API_PROTO_ESP),
-
                 crypto_algorithm=crypto_alg.alg_int_repr,
                 crypto_key=c_key,
                 integrity_algorithm=integ_alg.alg_int_repr if integ_alg else 0,
                 integrity_key=i_key,
-
                 flags=None,
-                tunnel_src=0,
-                tunnel_dst=0,
-                tunnel_flags=int(
-                    TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
+                tunnel=dict(
+                    src=0,
+                    dst=0,
+                    table_id=0,
+                    encap_decap_flags=int(
+                        TunnelEncpaDecapFlags.TUNNEL_API_ENCAP_DECAP_FLAG_NONE
+                    ),
+                    dscp=int(IpDscp.IP_API_DSCP_CS0),
                 ),
-                dscp=int(IpDscp.IP_API_DSCP_CS0),
-                table_id=0,
                 salt=0,
                 udp_src_port=IPSEC_UDP_PORT_NONE,
-                udp_dst_port=IPSEC_UDP_PORT_NONE
+                udp_dst_port=IPSEC_UDP_PORT_NONE,
             )
             args = dict(
                 is_add=True,
@@ -2124,6 +2150,10 @@ class IPsecUtil:
         sa_id_2 = 200000
         spi_1 = 300000
         spi_2 = 400000
+        dut1_local_outbound_range = ip_network(f"{tunnel_ip1}/8", False).\
+            with_prefixlen
+        dut1_remote_outbound_range = ip_network(f"{tunnel_ip2}/8", False).\
+            with_prefixlen
 
         crypto_key = gen_key(
             IPsecUtil.get_crypto_alg_key_len(crypto_alg)
@@ -2143,11 +2173,13 @@ class IPsecUtil:
         IPsecUtil.vpp_ipsec_spd_add_if(nodes[u"DUT1"], spd_id, interface1)
         IPsecUtil.vpp_ipsec_add_spd_entry(
             nodes[u"DUT1"], spd_id, p_hi, PolicyAction.BYPASS, inbound=False,
-            proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8"
+            proto=50, laddr_range=dut1_local_outbound_range,
+            raddr_range=dut1_remote_outbound_range
         )
         IPsecUtil.vpp_ipsec_add_spd_entry(
             nodes[u"DUT1"], spd_id, p_hi, PolicyAction.BYPASS, inbound=True,
-            proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8"
+            proto=50, laddr_range=dut1_remote_outbound_range,
+            raddr_range=dut1_local_outbound_range
         )
 
         IPsecUtil.vpp_ipsec_add_sad_entries(
@@ -2159,7 +2191,7 @@ class IPsecUtil:
             nodes[u"DUT1"], n_tunnels, spd_id, priority=ObjIncrement(p_lo, 0),
             action=PolicyAction.PROTECT, inbound=False,
             sa_id=ObjIncrement(sa_id_1, 1),
-            raddr_range=NetworkIncrement(ip_network(raddr_ip2), 1)
+            raddr_range=NetworkIncrement(ip_network(raddr_ip2))
         )
 
         IPsecUtil.vpp_ipsec_add_sad_entries(
@@ -2170,25 +2202,26 @@ class IPsecUtil:
             nodes[u"DUT1"], n_tunnels, spd_id, priority=ObjIncrement(p_lo, 0),
             action=PolicyAction.PROTECT, inbound=True,
             sa_id=ObjIncrement(sa_id_2, 1),
-            raddr_range=NetworkIncrement(ip_network(raddr_ip1), 1)
+            raddr_range=NetworkIncrement(ip_network(raddr_ip1))
         )
 
         if u"DUT2" in nodes.keys():
+            rmac = Topology.get_interface_mac(nodes[u"DUT1"], interface1)
             IPsecUtil.vpp_ipsec_set_ip_route(
                 nodes[u"DUT2"], n_tunnels, tunnel_ip2, raddr_ip1, tunnel_ip1,
-                interface2, raddr_range)
+                interface2, raddr_range, rmac)
 
             IPsecUtil.vpp_ipsec_add_spd(nodes[u"DUT2"], spd_id)
             IPsecUtil.vpp_ipsec_spd_add_if(nodes[u"DUT2"], spd_id, interface2)
             IPsecUtil.vpp_ipsec_add_spd_entry(
                 nodes[u"DUT2"], spd_id, p_hi, PolicyAction.BYPASS,
-                inbound=False, proto=50, laddr_range=u"100.0.0.0/8",
-                raddr_range=u"100.0.0.0/8"
+                inbound=False, proto=50, laddr_range=dut1_remote_outbound_range,
+                raddr_range=dut1_local_outbound_range
             )
             IPsecUtil.vpp_ipsec_add_spd_entry(
                 nodes[u"DUT2"], spd_id, p_hi, PolicyAction.BYPASS,
-                inbound=True, proto=50, laddr_range=u"100.0.0.0/8",
-                raddr_range=u"100.0.0.0/8"
+                inbound=True, proto=50, laddr_range=dut1_local_outbound_range,
+                raddr_range=dut1_remote_outbound_range
             )
 
             IPsecUtil.vpp_ipsec_add_sad_entries(
@@ -2196,10 +2229,11 @@ class IPsecUtil:
                 crypto_key, integ_alg, integ_key, tunnel_ip1, tunnel_ip2
             )
             IPsecUtil.vpp_ipsec_add_spd_entries(
-                nodes[u"DUT2"], n_tunnels, spd_id, priority=ObjIncrement(p_lo, 0),
+                nodes[u"DUT2"], n_tunnels, spd_id,
+                priority=ObjIncrement(p_lo, 0),
                 action=PolicyAction.PROTECT, inbound=True,
                 sa_id=ObjIncrement(sa_id_1, 1),
-                raddr_range=NetworkIncrement(ip_network(raddr_ip2), 1)
+                raddr_range=NetworkIncrement(ip_network(raddr_ip2))
             )
 
             IPsecUtil.vpp_ipsec_add_sad_entries(
@@ -2207,10 +2241,11 @@ class IPsecUtil:
                 crypto_key, integ_alg, integ_key, tunnel_ip2, tunnel_ip1
             )
             IPsecUtil.vpp_ipsec_add_spd_entries(
-                nodes[u"DUT2"], n_tunnels, spd_id, priority=ObjIncrement(p_lo, 0),
+                nodes[u"DUT2"], n_tunnels, spd_id,
+                priority=ObjIncrement(p_lo, 0),
                 action=PolicyAction.PROTECT, inbound=False,
                 sa_id=ObjIncrement(sa_id_2, 1),
-                raddr_range=NetworkIncrement(ip_network(raddr_ip1), 1)
+                raddr_range=NetworkIncrement(ip_network(raddr_ip1))
             )
 
     @staticmethod
@@ -2230,6 +2265,6 @@ class IPsecUtil:
         :type node: dict
         """
         cmds = [
-            u"ipsec_sa_v2_dump"
+            u"ipsec_sa_v3_dump"
         ]
         PapiSocketExecutor.dump_and_log(node, cmds)