Core: Rework CPU allocation
[csit.git] / resources / libraries / python / IPsecUtil.py
index c99105a..520cf7b 100644 (file)
@@ -29,8 +29,9 @@ from resources.libraries.python.IPAddress import IPAddress
 from resources.libraries.python.IPUtil import IPUtil, IpDscp, MPLS_LABEL_INVALID
 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
 from resources.libraries.python.ssh import scp_node
-from resources.libraries.python.topology import Topology
+from resources.libraries.python.topology import Topology, NodeType
 from resources.libraries.python.VatExecutor import VatExecutor
+from resources.libraries.python.VPPUtil import VPPUtil
 
 
 IPSEC_UDP_PORT_NONE = 0xffff
@@ -94,18 +95,18 @@ class IPsecProto(IntEnum):
 
 class IPsecSadFlags(IntEnum):
     """IPsec Security Association Database flags."""
-    IPSEC_API_SAD_FLAG_NONE = 0,
+    IPSEC_API_SAD_FLAG_NONE = 0
     # Enable extended sequence numbers
-    IPSEC_API_SAD_FLAG_USE_ESN = 0x01,
+    IPSEC_API_SAD_FLAG_USE_ESN = 0x01
     # Enable Anti - replay
-    IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY = 0x02,
+    IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY = 0x02
     # IPsec tunnel mode if non-zero, else transport mode
-    IPSEC_API_SAD_FLAG_IS_TUNNEL = 0x04,
+    IPSEC_API_SAD_FLAG_IS_TUNNEL = 0x04
     # IPsec tunnel mode is IPv6 if non-zero, else IPv4 tunnel
     # only valid if is_tunnel is non-zero
-    IPSEC_API_SAD_FLAG_IS_TUNNEL_V6 = 0x08,
+    IPSEC_API_SAD_FLAG_IS_TUNNEL_V6 = 0x08
     # Enable UDP encapsulation for NAT traversal
-    IPSEC_API_SAD_FLAG_UDP_ENCAP = 0x10,
+    IPSEC_API_SAD_FLAG_UDP_ENCAP = 0x10
     # IPsec SA is or inbound traffic
     IPSEC_API_SAD_FLAG_IS_INBOUND = 0x40
 
@@ -324,27 +325,57 @@ class IPsecUtil:
 
     @staticmethod
     def vpp_ipsec_crypto_sw_scheduler_set_worker(
-            node, worker_index, crypto_enable=False):
+            node, workers, crypto_enable=False):
         """Enable or disable crypto on specific vpp worker threads.
 
         :param node: VPP node to enable or disable crypto for worker threads.
-        :param worker_index: VPP worker thread index.
+        :param workers: List of VPP thread numbers.
         :param crypto_enable: Disable or enable crypto work.
         :type node: dict
-        :type worker_index: int
+        :type workers: Iterable[int]
         :type crypto_enable: bool
         :raises RuntimeError: If failed to enable or disable crypto for worker
             thread or if no API reply received.
         """
-        cmd = u"crypto_sw_scheduler_set_worker"
-        err_msg = f"Failed to disable/enable crypto for worker thread " \
-            f"on host {node[u'host']}"
-        args = dict(
-            worker_index=worker_index,
-            crypto_enable=crypto_enable
-        )
-        with PapiSocketExecutor(node) as papi_exec:
-            papi_exec.add(cmd, **args).get_reply(err_msg)
+        for worker in workers:
+            cmd = u"crypto_sw_scheduler_set_worker"
+            err_msg = f"Failed to disable/enable crypto for worker thread " \
+                f"on host {node[u'host']}"
+            args = dict(
+                worker_index=worker - 1,
+                crypto_enable=crypto_enable
+            )
+            with PapiSocketExecutor(node) as papi_exec:
+                papi_exec.add(cmd, **args).get_reply(err_msg)
+
+    @staticmethod
+    def vpp_ipsec_crypto_sw_scheduler_set_worker_on_all_duts(
+            nodes, workers, crypto_enable=False):
+        """Enable or disable crypto on specific vpp worker threads.
+
+        :param node: VPP node to enable or disable crypto for worker threads.
+        :param workers: List of VPP thread numbers.
+        :param crypto_enable: Disable or enable crypto work.
+        :type node: dict
+        :type workers: Iterable[int]
+        :type crypto_enable: bool
+        :raises RuntimeError: If failed to enable or disable crypto for worker
+            thread or if no API reply received.
+        """
+        for node in nodes.values():
+            if node[u"type"] == NodeType.DUT:
+                thread_data = VPPUtil.vpp_show_threads(node)
+                worker_cnt = len(thread_data) - 1
+                if not worker_cnt:
+                    return None
+                worker_ids = list()
+                for item in thread_data:
+                    if str(item.cpu_id) in workers.split(u","):
+                        worker_ids.append(item.id)
+
+                IPsecUtil.vpp_ipsec_crypto_sw_scheduler_set_worker(
+                    node, workers=worker_ids, crypto_enable=crypto_enable
+                )
 
     @staticmethod
     def vpp_ipsec_add_sad_entry(
@@ -553,7 +584,7 @@ class IPsecUtil:
     @staticmethod
     def vpp_ipsec_set_ip_route(
             node, n_tunnels, tunnel_src, traffic_addr, tunnel_dst, interface,
-            raddr_range):
+            raddr_range, dst_mac=None):
         """Set IP address and route on interface.
 
         :param node: VPP node to add config on.
@@ -565,6 +596,7 @@ class IPsecUtil:
         :param raddr_range: Mask specifying range of Policy selector Remote IP
             addresses. Valid values are from 1 to 32 in case of IPv4 and to 128
             in case of IPv6.
+        :param dst_mac: The MAC address of destination tunnels.
         :type node: dict
         :type n_tunnels: int
         :type tunnel_src: str
@@ -572,6 +604,7 @@ class IPsecUtil:
         :type tunnel_dst: str
         :type interface: str
         :type raddr_range: int
+        :type dst_mac: str
         """
         tunnel_src = ip_address(tunnel_src)
         tunnel_dst = ip_address(tunnel_dst)
@@ -590,7 +623,11 @@ class IPsecUtil:
                         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"
+                    if dst_mac:
+                        conf = f"{conf}exec set ip neighbor {if_name} " \
+                               f"{tunnel_dst + i * addr_incr} {dst_mac}\n"
                     tmp_file.write(conf)
+
             VatExecutor().execute_script(
                 tmp_filename, node, timeout=300, json_out=False,
                 copy_on_execute=True
@@ -611,8 +648,21 @@ class IPsecUtil:
             is_multipath=0,
             route=None
         )
-        err_msg = f"Failed to configure IP addresses and IP routes " \
-            f"on interface {interface} on host {node[u'host']}"
+        cmd3 = u"ip_neighbor_add_del"
+        args3 = dict(
+            is_add=True,
+            neighbor=dict(
+                sw_if_index=Topology.get_interface_sw_index(node, interface),
+                flags=0,
+                mac_address=str(dst_mac),
+                ip_address=None
+            )
+        )
+        err_msg = f"Failed to configure IP addresses, IP routes and " \
+            f"IP neighbor on interface {interface} on host {node[u'host']}" \
+            if dst_mac \
+            else f"Failed to configure IP addresses and IP routes " \
+                 f"on interface {interface} on host {node[u'host']}"
 
         with PapiSocketExecutor(node) as papi_exec:
             for i in range(n_tunnels):
@@ -627,6 +677,11 @@ class IPsecUtil:
                 history = bool(not 1 < i < n_tunnels - 2)
                 papi_exec.add(cmd1, history=history, **args1).\
                     add(cmd2, history=history, **args2)
+                if dst_mac:
+                    args3[u"neighbor"][u"ip_address"] = ip_address(
+                        tunnel_dst + i * addr_incr
+                    )
+                    papi_exec.add(cmd3, history=history, **args3)
             papi_exec.get_replies(err_msg)
 
     @staticmethod
@@ -1938,12 +1993,12 @@ class IPsecUtil:
             IPsecUtil.get_integ_alg_key_len(integ_alg)
         ).decode() if integ_alg else u""
 
+        rmac = Topology.get_interface_mac(nodes[u"DUT2"], interface2) \
+            if u"DUT2" in nodes.keys() \
+            else Topology.get_interface_mac(nodes[u"TG"], interface2)
         IPsecUtil.vpp_ipsec_set_ip_route(
             nodes[u"DUT1"], n_tunnels, tunnel_ip1, raddr_ip2, tunnel_ip2,
-            interface1, raddr_range)
-        IPsecUtil.vpp_ipsec_set_ip_route(
-            nodes[u"DUT2"], n_tunnels, tunnel_ip2, raddr_ip1, tunnel_ip1,
-            interface2, raddr_range)
+            interface1, raddr_range, rmac)
 
         IPsecUtil.vpp_ipsec_add_spd(nodes[u"DUT1"], spd_id)
         IPsecUtil.vpp_ipsec_spd_add_if(nodes[u"DUT1"], spd_id, interface1)
@@ -1956,17 +2011,6 @@ class IPsecUtil:
             proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8"
         )
 
-        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_policy_add(
-            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"
-        )
-        IPsecUtil.vpp_ipsec_policy_add(
-            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"
-        )
-
         IPsecUtil.vpp_ipsec_add_sad_entries(
             nodes[u"DUT1"], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key,
             integ_alg, integ_key, tunnel_ip1, tunnel_ip2
@@ -1976,30 +2020,49 @@ class IPsecUtil:
         )
 
         IPsecUtil.vpp_ipsec_add_sad_entries(
-            nodes[u"DUT2"], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key,
-            integ_alg, integ_key, tunnel_ip1, tunnel_ip2
+            nodes[u"DUT1"], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key,
+            integ_alg, integ_key, tunnel_ip2, tunnel_ip1
         )
         IPsecUtil.vpp_ipsec_spd_add_entries(
-            nodes[u"DUT2"], n_tunnels, spd_id, p_lo, True, sa_id_1, raddr_ip2
+            nodes[u"DUT1"], n_tunnels, spd_id, p_lo, True, sa_id_2, raddr_ip1
         )
 
-        IPsecUtil.vpp_ipsec_add_sad_entries(
-            nodes[u"DUT2"], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key,
-            integ_alg, integ_key, tunnel_ip2, tunnel_ip1
-        )
+        if u"DUT2" in nodes.keys():
+            IPsecUtil.vpp_ipsec_set_ip_route(
+                nodes[u"DUT2"], n_tunnels, tunnel_ip2, raddr_ip1, tunnel_ip1,
+                interface2, raddr_range)
+
+            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_policy_add(
+                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"
+            )
+            IPsecUtil.vpp_ipsec_policy_add(
+                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"
+            )
 
-        IPsecUtil.vpp_ipsec_spd_add_entries(
-            nodes[u"DUT2"], n_tunnels, spd_id, p_lo, False, sa_id_2, raddr_ip1
-        )
+            IPsecUtil.vpp_ipsec_add_sad_entries(
+                nodes[u"DUT2"], n_tunnels, sa_id_1, spi_1, crypto_alg,
+                crypto_key, integ_alg, integ_key, tunnel_ip1, tunnel_ip2
+            )
+            IPsecUtil.vpp_ipsec_spd_add_entries(
+                nodes[u"DUT2"], n_tunnels, spd_id, p_lo, True, sa_id_1,
+                raddr_ip2
+            )
 
-        IPsecUtil.vpp_ipsec_add_sad_entries(
-            nodes[u"DUT1"], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key,
-            integ_alg, integ_key, tunnel_ip2, tunnel_ip1
-        )
+            IPsecUtil.vpp_ipsec_add_sad_entries(
+                nodes[u"DUT2"], n_tunnels, sa_id_2, spi_2, crypto_alg,
+                crypto_key, integ_alg, integ_key, tunnel_ip2, tunnel_ip1
+            )
+            IPsecUtil.vpp_ipsec_spd_add_entries(
+                nodes[u"DUT2"], n_tunnels, spd_id, p_lo, False, sa_id_2,
+                raddr_ip1
+            )
 
-        IPsecUtil.vpp_ipsec_spd_add_entries(
-            nodes[u"DUT1"], n_tunnels, spd_id, p_lo, True, sa_id_2, raddr_ip1
-        )
 
     @staticmethod
     def vpp_ipsec_show(node):