ipsec: IPSec protection for multi-point tunnel interfaces
[vpp.git] / test / vpp_ipsec.py
index 0241fdf..268fe68 100644 (file)
@@ -1,4 +1,4 @@
-from vpp_object import *
+from vpp_object import VppObject
 from ipaddress import ip_address
 from vpp_papi import VppEnum
 
@@ -8,6 +8,10 @@ except NameError:
     text_type = str
 
 
+def mk_counter():
+    return {'packets': 0, 'bytes': 0}
+
+
 class VppIpsecSpd(VppObject):
     """
     VPP SPD DB
@@ -24,9 +28,6 @@ class VppIpsecSpd(VppObject):
     def remove_vpp_config(self):
         self.test.vapi.ipsec_spd_add_del(self.id, is_add=0)
 
-    def __str__(self):
-        return self.object_id()
-
     def object_id(self):
         return "ipsec-spd-%d" % self.id
 
@@ -41,7 +42,7 @@ class VppIpsecSpd(VppObject):
 class VppIpsecSpdItfBinding(VppObject):
     """
     VPP SPD DB to interface binding
-    (i.e. this SPD is used on this interfce)
+    (i.e. this SPD is used on this interface)
     """
 
     def __init__(self, test, spd, itf):
@@ -59,9 +60,6 @@ class VppIpsecSpdItfBinding(VppObject):
                                                    self.itf.sw_if_index,
                                                    is_add=0)
 
-    def __str__(self):
-        return self.object_id()
-
     def object_id(self):
         return "bind-%s-to-%s" % (self.spd.id, self.itf)
 
@@ -149,9 +147,6 @@ class VppIpsecSpdEntry(VppObject):
             remote_port_stop=self.remote_port_stop,
             is_add=0)
 
-    def __str__(self):
-        return self.object_id()
-
     def object_id(self):
         return "spd-entry-%d-%d-%d-%d-%d-%d" % (self.spd.id,
                                                 self.priority,
@@ -172,9 +167,16 @@ class VppIpsecSpdEntry(VppObject):
                 return True
         return False
 
-    def get_stats(self):
+    def get_stats(self, worker=None):
         c = self.test.statistics.get_counter("/net/ipsec/policy")
-        return c[0][self.stat_index]
+        if worker is None:
+            total = mk_counter()
+            for t in c:
+                total['packets'] += t[self.stat_index]['packets']
+            return total
+        else:
+            # +1 to skip main thread
+            return c[worker+1][self.stat_index]
 
 
 class VppIpsecSA(VppObject):
@@ -187,7 +189,7 @@ class VppIpsecSA(VppObject):
                  crypto_alg, crypto_key,
                  proto,
                  tun_src=None, tun_dst=None,
-                 flags=None):
+                 flags=None, salt=0):
         e = VppEnum.vl_api_ipsec_sad_flags_t
         self.test = test
         self.id = id
@@ -197,6 +199,7 @@ class VppIpsecSA(VppObject):
         self.crypto_alg = crypto_alg
         self.crypto_key = crypto_key
         self.proto = proto
+        self.salt = salt
 
         self.tun_src = tun_src
         self.tun_dst = tun_dst
@@ -223,7 +226,8 @@ class VppIpsecSA(VppObject):
             self.proto,
             (self.tun_src if self.tun_src else []),
             (self.tun_dst if self.tun_dst else []),
-            flags=self.flags)
+            flags=self.flags,
+            salt=self.salt)
         self.stat_index = r.stat_index
         self.test.registry.register(self, self.test.logger)
 
@@ -241,9 +245,6 @@ class VppIpsecSA(VppObject):
             flags=self.flags,
             is_add=0)
 
-    def __str__(self):
-        return self.object_id()
-
     def object_id(self):
         return "ipsec-sa-%d" % self.id
 
@@ -254,6 +255,70 @@ class VppIpsecSA(VppObject):
                 return True
         return False
 
-    def get_stats(self):
+    def get_stats(self, worker=None):
         c = self.test.statistics.get_counter("/net/ipsec/sa")
-        return c[0][self.stat_index]
+        if worker is None:
+            total = mk_counter()
+            for t in c:
+                total['packets'] += t[self.stat_index]['packets']
+            return total
+        else:
+            # +1 to skip main thread
+            return c[worker+1][self.stat_index]
+
+
+class VppIpsecTunProtect(VppObject):
+    """
+    VPP IPSEC tunnel protection
+    """
+
+    def __init__(self, test, itf, sa_out, sas_in, nh=None):
+        self.test = test
+        self.itf = itf
+        self.sas_in = []
+        for sa in sas_in:
+            self.sas_in.append(sa.id)
+        self.sa_out = sa_out.id
+        self.nh = nh
+        if not self.nh:
+            self.nh = "0.0.0.0"
+
+    def update_vpp_config(self, sa_out, sas_in):
+        self.sas_in = []
+        for sa in sas_in:
+            self.sas_in.append(sa.id)
+        self.sa_out = sa_out.id
+        self.test.vapi.ipsec_tunnel_protect_update(
+            tunnel={
+                'sw_if_index': self.itf._sw_if_index,
+                'n_sa_in': len(self.sas_in),
+                'sa_out': self.sa_out,
+                'sa_in': self.sas_in,
+                'nh': self.nh})
+
+    def object_id(self):
+        return "ipsec-tun-protect-%s-%s" % (self.itf, self.nh)
+
+    def add_vpp_config(self):
+        self.test.vapi.ipsec_tunnel_protect_update(
+            tunnel={
+                'sw_if_index': self.itf._sw_if_index,
+                'n_sa_in': len(self.sas_in),
+                'sa_out': self.sa_out,
+                'sa_in': self.sas_in,
+                'nh': self.nh})
+        self.test.registry.register(self, self.test.logger)
+
+    def remove_vpp_config(self):
+        self.test.vapi.ipsec_tunnel_protect_del(
+            sw_if_index=self.itf.sw_if_index,
+            nh=self.nh)
+
+    def query_vpp_config(self):
+        bs = self.test.vapi.ipsec_tunnel_protect_dump(
+            sw_if_index=self.itf.sw_if_index)
+        for b in bs:
+            if b.tun.sw_if_index == self.itf.sw_if_index and \
+               self.nh == str(b.tun.nh):
+                return True
+        return False