test framework: vpp_papi_provider.py - further cleanup
[vpp.git] / test / vpp_ip_route.py
index 00a79f4..2be0e79 100644 (file)
@@ -4,9 +4,9 @@
   object abstractions for representing IP routes in VPP
 """
 
-from vpp_object import *
+from vpp_object import VppObject
 from socket import inet_pton, inet_ntop, AF_INET, AF_INET6
-from vpp_ip import *
+from vpp_ip import DpoProto, VppIpPrefix
 
 # from vnet/vnet/mpls/mpls_types.h
 MPLS_IETF_MAX_LABEL = 0xfffff
@@ -35,6 +35,13 @@ class MplsLspMode:
     UNIFORM = 1
 
 
+def ip_to_dpo_proto(addr):
+    if addr.version == 6:
+        return DpoProto.DPO_PROTO_IP6
+    else:
+        return DpoProto.DPO_PROTO_IP4
+
+
 def find_route(test, ip_addr, len, table_id=0, inet=AF_INET):
     if inet == AF_INET:
         s = 4
@@ -46,8 +53,8 @@ def find_route(test, ip_addr, len, table_id=0, inet=AF_INET):
     route_addr = inet_pton(inet, ip_addr)
     for e in routes:
         if route_addr == e.address[:s] \
-           and len == e.address_length \
-           and table_id == e.table_id:
+                and len == e.address_length \
+                and table_id == e.table_id:
             return True
     return False
 
@@ -64,9 +71,44 @@ def find_mroute(test, grp_addr, src_addr, grp_addr_len,
     saddr = inet_pton(inet, src_addr)
     for e in routes:
         if gaddr == e.grp_address[:s] \
-           and grp_addr_len == e.address_length \
-           and saddr == e.src_address[:s] \
-           and table_id == e.table_id:
+                and grp_addr_len == e.address_length \
+                and saddr == e.src_address[:s] \
+                and table_id == e.table_id:
+            return True
+    return False
+
+
+def find_mpls_route(test, table_id, label, eos_bit, paths=None):
+    dump = test.vapi.mpls_fib_dump()
+    for e in dump:
+        if label == e.label \
+                and eos_bit == e.eos_bit \
+                and table_id == e.table_id:
+            if not paths:
+                return True
+            else:
+                if (len(paths) != len(e.path)):
+                    return False
+                for i in range(len(paths)):
+                    if (paths[i] != e.path[i]):
+                        return False
+                return True
+    return False
+
+
+def fib_interface_ip_prefix(test, address, length, sw_if_index):
+    vp = VppIpPrefix(address, length)
+    addrs = test.vapi.ip_address_dump(sw_if_index, is_ipv6=vp.is_ip6)
+
+    if vp.is_ip6:
+        n = 16
+    else:
+        n = 4
+
+    for a in addrs:
+        if a.prefix_length == length and \
+                a.sw_if_index == sw_if_index and \
+                a.ip[:n] == vp.bytes:
             return True
     return False
 
@@ -82,19 +124,18 @@ class VppIpTable(VppObject):
         self.is_ip6 = is_ip6
 
     def add_vpp_config(self):
-        self._test.vapi.ip_table_add_del(
-            self.table_id,
-            is_ipv6=self.is_ip6,
-            is_add=1)
+        self._test.vapi.ip_table_add_del(is_ipv6=self.is_ip6, is_add=1,
+                                         table_id=self.table_id)
         self._test.registry.register(self, self._test.logger)
 
     def remove_vpp_config(self):
-        self._test.vapi.ip_table_add_del(
-            self.table_id,
-            is_ipv6=self.is_ip6,
-            is_add=0)
+        self._test.vapi.ip_table_add_del(is_ipv6=self.is_ip6, is_add=0,
+                                         table_id=self.table_id)
 
     def query_vpp_config(self):
+        if self.table_id == 0:
+            # the default table always exists
+            return False
         # find the default route
         return find_route(self._test,
                           "::" if self.is_ip6 else "0.0.0.0",
@@ -111,6 +152,75 @@ class VppIpTable(VppObject):
                  self.table_id))
 
 
+class VppIpInterfaceAddress(VppObject):
+
+    def __init__(self, test, intf, addr, len):
+        self._test = test
+        self.intf = intf
+        self.prefix = VppIpPrefix(addr, len)
+
+    def add_vpp_config(self):
+        self._test.vapi.sw_interface_add_del_address(
+            sw_if_index=self.intf.sw_if_index, address=self.prefix.bytes,
+            address_length=self.prefix.length, is_ipv6=self.prefix.is_ip6,
+            is_add=1)
+        self._test.registry.register(self, self._test.logger)
+
+    def remove_vpp_config(self):
+        self._test.vapi.sw_interface_add_del_address(
+            sw_if_index=self.intf.sw_if_index, address=self.prefix.bytes,
+            address_length=self.prefix.length, is_ipv6=self.prefix.is_ip6,
+            is_add=0)
+
+    def query_vpp_config(self):
+        return fib_interface_ip_prefix(self._test,
+                                       self.prefix.address,
+                                       self.prefix.length,
+                                       self.intf.sw_if_index)
+
+    def __str__(self):
+        return self.object_id()
+
+    def object_id(self):
+        return "interface-ip-%s-%s" % (self.intf, self.prefix)
+
+
+class VppIpInterfaceBind(VppObject):
+
+    def __init__(self, test, intf, table):
+        self._test = test
+        self.intf = intf
+        self.table = table
+
+    def add_vpp_config(self):
+        if self.table.is_ip6:
+            self.intf.set_table_ip6(self.table.table_id)
+        else:
+            self.intf.set_table_ip4(self.table.table_id)
+        self._test.registry.register(self, self._test.logger)
+
+    def remove_vpp_config(self):
+        if 0 == self.table.table_id:
+            return
+        if self.table.is_ip6:
+            self.intf.set_table_ip6(0)
+        else:
+            self.intf.set_table_ip4(0)
+
+    def query_vpp_config(self):
+        if 0 == self.table.table_id:
+            return False
+        return self._test.vapi.sw_interface_get_table(
+            self.intf.sw_if_index,
+            self.table.is_ip6).vrf_id == self.table.table_id
+
+    def __str__(self):
+        return self.object_id()
+
+    def object_id(self):
+        return "interface-bind-%s-%s" % (self.intf, self.table)
+
+
 class VppMplsLabel(object):
     def __init__(self, value, mode=MplsLspMode.PIPE, ttl=64, exp=0):
         self.value = value
@@ -125,6 +235,23 @@ class VppMplsLabel(object):
                 'exp': self.exp,
                 'is_uniform': is_uniform}
 
+    def __eq__(self, other):
+        if isinstance(other, self.__class__):
+            return (self.value == other.value and
+                    self.ttl == other.ttl and
+                    self.exp == other.exp and
+                    self.mode == other.mode)
+        elif hasattr(other, 'label'):
+            return (self.value == other.label and
+                    self.ttl == other.ttl and
+                    self.exp == other.exp and
+                    (self.mode == MplsLspMode.UNIFORM) == other.is_uniform)
+        else:
+            return False
+
+    def __ne__(self, other):
+        return not (self == other)
+
 
 class VppRoutePath(object):
 
@@ -144,13 +271,13 @@ class VppRoutePath(object):
             is_dvr=0,
             next_hop_id=0xffffffff,
             proto=DpoProto.DPO_PROTO_IP4):
+        self.proto = proto
         self.nh_itf = nh_sw_if_index
         self.nh_table_id = nh_table_id
         self.nh_via_label = nh_via_label
         self.nh_labels = labels
         self.weight = 1
         self.rpf_id = rpf_id
-        self.proto = proto
         if self.proto is DpoProto.DPO_PROTO_IP6:
             self.nh_addr = inet_pton(AF_INET6, nh_addr)
         elif self.proto is DpoProto.DPO_PROTO_IP4:
@@ -182,7 +309,6 @@ class VppRoutePath(object):
     def encode(self):
         return {'next_hop': self.nh_addr,
                 'weight': 1,
-                'afi': 0,
                 'preference': 0,
                 'table_id': self.nh_table_id,
                 'next_hop_id': self.next_hop_id,
@@ -193,7 +319,21 @@ class VppRoutePath(object):
                 'label_stack': self.encode_labels()}
 
     def __eq__(self, other):
-        return self.nh_addr == other.nh_addr
+        if isinstance(other, self.__class__):
+            return self.nh_addr == other.nh_addr
+        elif hasattr(other, 'sw_if_index'):
+            # vl_api_fib_path_t
+            if (len(self.nh_labels) != other.n_labels):
+                return False
+            for i in range(len(self.nh_labels)):
+                if (self.nh_labels[i] != other.label_stack[i]):
+                    return False
+            return self.nh_itf == other.sw_if_index
+        else:
+            return False
+
+    def __ne__(self, other):
+        return not (self == other)
 
 
 class VppMRoutePath(VppRoutePath):
@@ -242,8 +382,7 @@ class VppIpRoute(VppObject):
         self.is_prohibit = is_prohibit
 
     def add_vpp_config(self):
-        if self.is_local or self.is_unreach or \
-           self.is_prohibit or self.is_drop:
+        if self.is_unreach or self.is_prohibit or self.is_drop:
             r = self._test.vapi.ip_add_del_route(
                 self.dest_addr,
                 self.dest_addr_len,
@@ -272,6 +411,7 @@ class VppIpRoute(VppObject):
                     next_hop_id=path.next_hop_id,
                     is_ipv6=self.is_ip6,
                     is_dvr=path.is_dvr,
+                    is_local=self.is_local,
                     is_resolve_host=path.is_resolve_host,
                     is_resolve_attached=path.is_resolve_attached,
                     is_source_lookup=path.is_source_lookup,
@@ -281,8 +421,7 @@ class VppIpRoute(VppObject):
         self._test.registry.register(self, self._test.logger)
 
     def remove_vpp_config(self):
-        if self.is_local or self.is_unreach or \
-           self.is_prohibit or self.is_drop:
+        if self.is_unreach or self.is_prohibit or self.is_drop:
             self._test.vapi.ip_add_del_route(
                 self.dest_addr,
                 self.dest_addr_len,
@@ -527,7 +666,7 @@ class VppMplsIpBind(VppObject):
         dump = self._test.vapi.mpls_fib_dump()
         for e in dump:
             if self.local_label == e.label \
-               and self.table_id == e.table_id:
+                    and self.table_id == e.table_id:
                 return True
         return False
 
@@ -625,13 +764,8 @@ class VppMplsRoute(VppObject):
                                                is_add=0)
 
     def query_vpp_config(self):
-        dump = self._test.vapi.mpls_fib_dump()
-        for e in dump:
-            if self.local_label == e.label \
-               and self.eos_bit == e.eos_bit \
-               and self.table_id == e.table_id:
-                return True
-        return False
+        return find_mpls_route(self._test, self.table_id,
+                               self.local_label, self.eos_bit)
 
     def __str__(self):
         return self.object_id()
@@ -640,7 +774,7 @@ class VppMplsRoute(VppObject):
         return ("%d:%s/%d"
                 % (self.table_id,
                    self.local_label,
-                   20+self.eos_bit))
+                   20 + self.eos_bit))
 
     def get_stats_to(self):
         c = self._test.statistics.get_counter("/net/route/to")