ip6-nd: fix coverity warning
[vpp.git] / test / framework.py
old mode 100755 (executable)
new mode 100644 (file)
index 0acc160..f4b168b
@@ -23,6 +23,7 @@ from traceback import format_exception
 from logging import FileHandler, DEBUG, Formatter
 from enum import Enum
 from abc import ABC, abstractmethod
 from logging import FileHandler, DEBUG, Formatter
 from enum import Enum
 from abc import ABC, abstractmethod
+from struct import pack, unpack
 
 import scapy.compat
 from scapy.packet import Raw
 
 import scapy.compat
 from scapy.packet import Raw
@@ -32,6 +33,7 @@ from vpp_sub_interface import VppSubInterface
 from vpp_lo_interface import VppLoInterface
 from vpp_bvi_interface import VppBviInterface
 from vpp_papi_provider import VppPapiProvider
 from vpp_lo_interface import VppLoInterface
 from vpp_bvi_interface import VppBviInterface
 from vpp_papi_provider import VppPapiProvider
+from vpp_papi import VppEnum
 import vpp_papi
 from vpp_papi.vpp_stats import VPPStats
 from vpp_papi.vpp_transport_socket import VppTransportSocketIOError
 import vpp_papi
 from vpp_papi.vpp_stats import VPPStats
 from vpp_papi.vpp_transport_socket import VppTransportSocketIOError
@@ -413,18 +415,7 @@ class VppTestCase(CPUInterface, unittest.TestCase):
         c = os.getenv("CACHE_OUTPUT", "1")
         cls.cache_vpp_output = False if c.lower() in ("n", "no", "0") else True
         cls.vpp_bin = os.getenv('VPP_BIN', "vpp")
         c = os.getenv("CACHE_OUTPUT", "1")
         cls.cache_vpp_output = False if c.lower() in ("n", "no", "0") else True
         cls.vpp_bin = os.getenv('VPP_BIN', "vpp")
-        cls.plugin_path = os.getenv('VPP_PLUGIN_PATH')
-        cls.test_plugin_path = os.getenv('VPP_TEST_PLUGIN_PATH')
-        cls.extern_plugin_path = os.getenv('EXTERN_PLUGINS')
-        plugin_path = None
-        if cls.plugin_path is not None:
-            if cls.extern_plugin_path is not None:
-                plugin_path = "%s:%s" % (
-                    cls.plugin_path, cls.extern_plugin_path)
-            else:
-                plugin_path = cls.plugin_path
-        elif cls.extern_plugin_path is not None:
-            plugin_path = cls.extern_plugin_path
+        extern_plugin_path = os.getenv('EXTERN_PLUGINS')
         debug_cli = ""
         if cls.step or cls.debug_gdb or cls.debug_gdbserver:
             debug_cli = "cli-listen localhost:5002"
         debug_cli = ""
         if cls.step or cls.debug_gdb or cls.debug_gdbserver:
             debug_cli = "cli-listen localhost:5002"
@@ -452,6 +443,9 @@ class VppTestCase(CPUInterface, unittest.TestCase):
             "api-trace", "{", "on", "}",
             "api-segment", "{", "prefix", cls.get_api_segment_prefix(), "}",
             "cpu", "{", "main-core", str(cls.cpus[0]), ]
             "api-trace", "{", "on", "}",
             "api-segment", "{", "prefix", cls.get_api_segment_prefix(), "}",
             "cpu", "{", "main-core", str(cls.cpus[0]), ]
+        if extern_plugin_path is not None:
+            cls.extra_vpp_plugin_config.append(
+                "add-path %s" % extern_plugin_path)
         if cls.get_vpp_worker_count():
             cls.vpp_cmdline.extend([
                 "corelist-workers", ",".join([str(x) for x in cls.cpus[1:]])])
         if cls.get_vpp_worker_count():
             cls.vpp_cmdline.extend([
                 "corelist-workers", ",".join([str(x) for x in cls.cpus[1:]])])
@@ -471,10 +465,6 @@ class VppTestCase(CPUInterface, unittest.TestCase):
 
         if cls.extra_vpp_punt_config is not None:
             cls.vpp_cmdline.extend(cls.extra_vpp_punt_config)
 
         if cls.extra_vpp_punt_config is not None:
             cls.vpp_cmdline.extend(cls.extra_vpp_punt_config)
-        if plugin_path is not None:
-            cls.vpp_cmdline.extend(["plugin_path", plugin_path])
-        if cls.test_plugin_path is not None:
-            cls.vpp_cmdline.extend(["test_plugin_path", cls.test_plugin_path])
 
         if not cls.debug_attach:
             cls.logger.info("vpp_cmdline args: %s" % cls.vpp_cmdline)
 
         if not cls.debug_attach:
             cls.logger.info("vpp_cmdline args: %s" % cls.vpp_cmdline)
@@ -818,8 +808,6 @@ class VppTestCase(CPUInterface, unittest.TestCase):
             self.logger.info("Moving %s to %s\n" % (tmp_api_trace,
                                                     vpp_api_trace_log))
             os.rename(tmp_api_trace, vpp_api_trace_log)
             self.logger.info("Moving %s to %s\n" % (tmp_api_trace,
                                                     vpp_api_trace_log))
             os.rename(tmp_api_trace, vpp_api_trace_log)
-            self.logger.info(self.vapi.ppcli("api trace custom-dump %s" %
-                                             vpp_api_trace_log))
         except VppTransportSocketIOError:
             self.logger.debug("VppTransportSocketIOError: Vpp dead. "
                               "Cannot log show commands.")
         except VppTransportSocketIOError:
             self.logger.debug("VppTransportSocketIOError: Vpp dead. "
                               "Cannot log show commands.")
@@ -915,7 +903,8 @@ class VppTestCase(CPUInterface, unittest.TestCase):
         cls._pcaps = []
 
     @classmethod
         cls._pcaps = []
 
     @classmethod
-    def create_pg_interfaces(cls, interfaces, gso=0, gso_size=0):
+    def create_pg_interfaces_internal(cls, interfaces, gso=0, gso_size=0,
+                                      mode=None):
         """
         Create packet-generator interfaces.
 
         """
         Create packet-generator interfaces.
 
@@ -925,12 +914,36 @@ class VppTestCase(CPUInterface, unittest.TestCase):
         """
         result = []
         for i in interfaces:
         """
         result = []
         for i in interfaces:
-            intf = VppPGInterface(cls, i, gso, gso_size)
+            intf = VppPGInterface(cls, i, gso, gso_size, mode)
             setattr(cls, intf.name, intf)
             result.append(intf)
         cls.pg_interfaces = result
         return result
 
             setattr(cls, intf.name, intf)
             result.append(intf)
         cls.pg_interfaces = result
         return result
 
+    @classmethod
+    def create_pg_ip4_interfaces(cls, interfaces, gso=0, gso_size=0):
+        pgmode = VppEnum.vl_api_pg_interface_mode_t
+        return cls.create_pg_interfaces_internal(interfaces, gso, gso_size,
+                                                 pgmode.PG_API_MODE_IP4)
+
+    @classmethod
+    def create_pg_ip6_interfaces(cls, interfaces, gso=0, gso_size=0):
+        pgmode = VppEnum.vl_api_pg_interface_mode_t
+        return cls.create_pg_interfaces_internal(interfaces, gso, gso_size,
+                                                 pgmode.PG_API_MODE_IP6)
+
+    @classmethod
+    def create_pg_interfaces(cls, interfaces, gso=0, gso_size=0):
+        pgmode = VppEnum.vl_api_pg_interface_mode_t
+        return cls.create_pg_interfaces_internal(interfaces, gso, gso_size,
+                                                 pgmode.PG_API_MODE_ETHERNET)
+
+    @classmethod
+    def create_pg_ethernet_interfaces(cls, interfaces, gso=0, gso_size=0):
+        pgmode = VppEnum.vl_api_pg_interface_mode_t
+        return cls.create_pg_interfaces_internal(interfaces, gso, gso_size,
+                                                 pgmode.PG_API_MODE_ETHERNET)
+
     @classmethod
     def create_loopback_interfaces(cls, count):
         """
     @classmethod
     def create_loopback_interfaces(cls, count):
         """
@@ -1018,8 +1031,10 @@ class VppTestCase(CPUInterface, unittest.TestCase):
 
         :returns: string containing serialized data from packet info
         """
 
         :returns: string containing serialized data from packet info
         """
-        return "%d %d %d %d %d" % (info.index, info.src, info.dst,
-                                   info.ip, info.proto)
+
+        # retrieve payload, currently 18 bytes (4 x ints + 1 short)
+        return pack('iiiih', info.index, info.src,
+                    info.dst, info.ip, info.proto)
 
     @staticmethod
     def payload_to_info(payload, payload_field='load'):
 
     @staticmethod
     def payload_to_info(payload, payload_field='load'):
@@ -1034,13 +1049,18 @@ class VppTestCase(CPUInterface, unittest.TestCase):
         :returns: _PacketInfo object containing de-serialized data from payload
 
         """
         :returns: _PacketInfo object containing de-serialized data from payload
 
         """
-        numbers = getattr(payload, payload_field).split()
+
+        # retrieve payload, currently 18 bytes (4 x ints + 1 short)
+        payload_b = getattr(payload, payload_field)[:18]
+
         info = _PacketInfo()
         info = _PacketInfo()
-        info.index = int(numbers[0])
-        info.src = int(numbers[1])
-        info.dst = int(numbers[2])
-        info.ip = int(numbers[3])
-        info.proto = int(numbers[4])
+        info.index, info.src, info.dst, info.ip, info.proto \
+            = unpack('iiiih', payload_b)
+
+        # some SRv6 TCs depend on get an exception if bad values are detected
+        if info.index > 0x4000:
+            raise ValueError('Index value is invalid')
+
         return info
 
     def get_next_packet_info(self, info):
         return info
 
     def get_next_packet_info(self, info):
@@ -1264,12 +1284,17 @@ class VppTestCase(CPUInterface, unittest.TestCase):
             "Finished sleep (%s) - slept %es (wanted %es)",
             remark, after - before, timeout)
 
             "Finished sleep (%s) - slept %es (wanted %es)",
             remark, after - before, timeout)
 
+    def virtual_sleep(self, timeout, remark=None):
+        self.logger.debug("Moving VPP time by %s (%s)", timeout, remark)
+        self.vapi.cli("set clock adjust %s" % timeout)
+
     def pg_send(self, intf, pkts, worker=None, trace=True):
         intf.add_stream(pkts, worker=worker)
         self.pg_enable_capture(self.pg_interfaces)
         self.pg_start(trace=trace)
 
     def pg_send(self, intf, pkts, worker=None, trace=True):
         intf.add_stream(pkts, worker=worker)
         self.pg_enable_capture(self.pg_interfaces)
         self.pg_start(trace=trace)
 
-    def send_and_assert_no_replies(self, intf, pkts, remark="", timeout=None):
+    def send_and_assert_no_replies(self, intf, pkts, remark="", timeout=None,
+                                   trace=True):
         self.pg_send(intf, pkts)
         if not timeout:
             timeout = 1
         self.pg_send(intf, pkts)
         if not timeout:
             timeout = 1
@@ -1277,6 +1302,8 @@ class VppTestCase(CPUInterface, unittest.TestCase):
             i.get_capture(0, timeout=timeout)
             i.assert_nothing_captured(remark=remark)
             timeout = 0.1
             i.get_capture(0, timeout=timeout)
             i.assert_nothing_captured(remark=remark)
             timeout = 0.1
+        if trace:
+            self.logger.debug(self.vapi.cli("show trace"))
 
     def send_and_expect(self, intf, pkts, output, n_rx=None, worker=None,
                         trace=True):
 
     def send_and_expect(self, intf, pkts, output, n_rx=None, worker=None,
                         trace=True):
@@ -1284,6 +1311,8 @@ class VppTestCase(CPUInterface, unittest.TestCase):
             n_rx = len(pkts)
         self.pg_send(intf, pkts, worker=worker, trace=trace)
         rx = output.get_capture(n_rx)
             n_rx = len(pkts)
         self.pg_send(intf, pkts, worker=worker, trace=trace)
         rx = output.get_capture(n_rx)
+        if trace:
+            self.logger.debug(self.vapi.cli("show trace"))
         return rx
 
     def send_and_expect_only(self, intf, pkts, output, timeout=None):
         return rx
 
     def send_and_expect_only(self, intf, pkts, output, timeout=None):
@@ -1721,8 +1750,9 @@ class Worker(Thread):
             self.result = os.EX_OSFILE
             raise EnvironmentError(
                 "executable '%s' is not found or executable." % executable)
             self.result = os.EX_OSFILE
             raise EnvironmentError(
                 "executable '%s' is not found or executable." % executable)
-        self.logger.debug("Running executable: '{app}'"
-                          .format(app=' '.join(self.args)))
+        self.logger.debug("Running executable '{app}': '{cmd}'"
+                          .format(app=self.app_name,
+                                  cmd=' '.join(self.args)))
         env = os.environ.copy()
         env.update(self.env)
         env["CK_LOG_FILE_NAME"] = "-"
         env = os.environ.copy()
         env.update(self.env)
         env["CK_LOG_FILE_NAME"] = "-"