test suite reviews and discussions
 help / color / mirror / Atom feed
From: yufengmx <yufengx.mo@intel.com>
To: dts@dpdk.org, lei.a.yao@intel.com
Cc: yufengmx <yufengx.mo@intel.com>
Subject: [dts] [PATCH V3 1/3] tests/malicious_driver_event_indication: upload automation
Date: Mon, 25 May 2020 10:23:13 +0800	[thread overview]
Message-ID: <20200525022315.3214-2-yufengx.mo@intel.com> (raw)
In-Reply-To: <20200525022315.3214-1-yufengx.mo@intel.com>

 script

Malicious driver event indication process in FVL PF driver.

Signed-off-by: yufengmx <yufengx.mo@intel.com>
---
 ...Suite_malicious_driver_event_indication.py | 335 ++++++++++++++++++
 1 file changed, 335 insertions(+)
 create mode 100644 tests/TestSuite_malicious_driver_event_indication.py

diff --git a/tests/TestSuite_malicious_driver_event_indication.py b/tests/TestSuite_malicious_driver_event_indication.py
new file mode 100644
index 0000000..f297ab9
--- /dev/null
+++ b/tests/TestSuite_malicious_driver_event_indication.py
@@ -0,0 +1,335 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2020 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#   * Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+#   * Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.
+#   * Neither the name of Intel Corporation nor the names of its
+#     contributors may be used to endorse or promote products derived
+#     from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""
+DPDK Test suite.
+Malicious driver event indication process test suite.
+"""
+import os
+import re
+import time
+import traceback
+from contextlib import contextmanager
+
+
+from exception import VerifyFailure
+from test_case import TestCase
+import utils
+
+
+class TestSuiteMaliciousDrvEventIndication(TestCase):
+
+    def d_con(self, cmd):
+        _cmd = [cmd, '# ', 10] if isinstance(cmd, str) else cmd
+        return self.dut.send_expect(*_cmd)
+
+    def d_a_con(self, cmd):
+        _cmd = [cmd, '# ', 10] if isinstance(cmd, str) else cmd
+        return self.dut.alt_session.send_expect(*_cmd)
+
+    def vf_pmd_con(self, cmd):
+        if not self.vf_pmd_session:
+            return
+        _cmd = [cmd, '# ', 10] if isinstance(cmd, str) else cmd
+        output = self.vf_pmd_session.session.send_expect(*_cmd)
+        return output
+
+    @property
+    def target_dir(self):
+        # get absolute directory of target source code
+        target_dir = '/root' + self.dut.base_dir[1:] \
+                     if self.dut.base_dir.startswith('~') else \
+                     self.dut.base_dir
+        return target_dir
+
+    def preset_dpdk_compilation(self):
+        cmd = ';'.join([
+            'cd %s',
+            'rm -f app/test-pmd/bak_txonly.c',
+            'cp -f app/test-pmd/txonly.c app/test-pmd/bak_txonly.c',
+            "sed -i 's/nb_tx = rte_eth_tx_burst/for \(nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt\+\+\) "
+            "\{ pkts_burst\[nb_pkt\]->data_len = 15 ;\} nb_tx = rte_eth_tx_burst/g' app/test-pmd/txonly.c"]) % self.target_dir
+        self.d_a_con(cmd)
+        # rebuild dpdk source code
+        self.dut.build_install_dpdk(self.target)
+
+    @contextmanager
+    def restore_dpdk_compilation(self):
+        try:
+            yield
+        finally:
+            cmd = ';'.join([
+                'cd {target}',
+                'rm -f app/test-pmd/txonly.c',
+                'cp -f app/test-pmd/bak_txonly.c app/test-pmd/txonly.c',
+                ]).format(**{
+                    'target': self.target_dir, })
+            self.d_a_con(cmd)
+            # rebuild dpdk source code
+            self.dut.build_install_dpdk(self.target)
+
+    def vf_create(self):
+        port_id = 0
+        port_obj = self.dut.ports_info[port_id]['port']
+        self.dut.generate_sriov_vfs_by_port(port_id, 1)
+        pf_pci = port_obj.pci
+        sriov_vfs_port = self.dut.ports_info[port_id].get('vfs_port')
+        if not sriov_vfs_port:
+            msg = "failed to create vf on dut port {}".format(pf_pci)
+            raise VerifyFailure(msg)
+        for port in sriov_vfs_port:
+            port.bind_driver(driver=self.drivername)
+        vf_mac = "00:12:34:56:78:01"
+        self.vf_ports_info[port_id] = {
+            'pf_pci': pf_pci,
+            'vfs_pci': port_obj.get_sriov_vfs_pci(),
+            'vf_mac': vf_mac, }
+        time.sleep(1)
+
+    def vf_destroy(self):
+        if not self.vf_ports_info:
+            return
+        for port_id, _ in self.vf_ports_info.items():
+            self.dut.destroy_sriov_vfs_by_port(port_id)
+            port_obj = self.dut.ports_info[port_id]['port']
+            port_obj.bind_driver(self.drivername)
+        self.vf_ports_info = None
+
+    def init_pf_testpmd(self):
+        self.pf_testpmd = "{}/{}/app/testpmd".format(
+            self.target_dir, self.dut.target)
+
+    def start_pf_testpmd(self):
+        core_mask = utils.create_mask(self.pf_pmd_cores)
+        cmd = (
+            "{bin} "
+            "-v "
+            "-c {core_mask} "
+            "-n {mem_channel} "
+            "--file-prefix={prefix} "
+            "{whitelist} "
+            "-- -i ").format(**{
+                'bin': self.pf_testpmd,
+                'core_mask': core_mask,
+                'mem_channel': self.dut.get_memory_channels(),
+                'whitelist': self.pf_pmd_whitelist,
+                'prefix': 'pf_pmd', })
+        self.d_con([cmd, "testpmd> ", 120])
+        self.is_pf_pmd_on = True
+        time.sleep(1)
+
+    def close_pf_testpmd(self):
+        if not self.is_pf_pmd_on:
+            return
+        self.d_con(['quit', '# ', 15])
+        self.is_pf_pmd_on = False
+
+    def get_pf_testpmd_reponse(self):
+        output = self.dut.get_session_output(timeout=2)
+        return output
+
+    def init_vf_testpmd(self):
+        self.vf_pmd_session_name = 'vf_testpmd'
+        self.vf_pmd_session = self.dut.create_session(self.vf_pmd_session_name)
+        self.vf_testpmd = "{}/{}/app/testpmd_vf".format(
+            self.target_dir, self.dut.target)
+        cmd = 'rm -f {vf_pmd};cp -f {pf_pmd} {vf_pmd}'.format(
+            **{'pf_pmd': self.pf_testpmd, 'vf_pmd': self.vf_testpmd})
+        self.d_a_con(cmd)
+
+    def start_vf_testpmd(self):
+        core_mask = utils.create_mask(self.vf_pmd_cores)
+        cmd = (
+            "{bin} "
+            "-v "
+            "-c {core_mask} "
+            "-n {mem_channel} "
+            "--file-prefix={prefix} "
+            "{whitelist} "
+            "-- -i ").format(**{
+                'bin': self.vf_testpmd,
+                'core_mask': core_mask,
+                'mem_channel': self.dut.get_memory_channels(),
+                'whitelist': self.vf_pmd_whitelist,
+                'prefix': 'vf_pmd', })
+        self.vf_pmd_con([cmd, "testpmd> ", 120])
+        self.is_vf_pmd_on = True
+        cmds = [
+            'set fwd txonly',
+            'start', ]
+        [self.vf_pmd_con([cmd, "testpmd> ", 15]) for cmd in cmds]
+        time.sleep(1)
+
+    def close_vf_testpmd(self):
+        if not self.is_vf_pmd_on:
+            return
+        self.vf_pmd_con(['quit', '# ', 15])
+        self.is_vf_pmd_on = False
+
+    def get_vf_testpmd_reponse(self):
+        if not self.vf_pmd_session:
+            return ''
+        output = self.vf_pmd_session.session.get_output_all()
+        return output
+
+    def check_event_is_detected(self):
+        pf_output = self.get_pf_testpmd_reponse()
+        expected_strs = [
+            'malicious programming detected',
+            'TX driver issue detected on PF',
+            'TX driver issue detected on VF 0 1times', ]
+        for expected_str in expected_strs:
+            msg = "'{}' not display".format(expected_str)
+            self.verify(expected_str in pf_output, msg)
+        pat = 'Malicious Driver Detection event 0x(\d+) on TX queue (\d+) PF number 0x(\d+) VF number 0x(\d+) device ' + self.vf_ports_info[0].get('pf_pci')
+        result = re.findall(pat, pf_output)
+        msg = "'Malicious Driver Detection event not detected"
+        self.verify(result and len(result), msg)
+
+    def check_event_counter_number(self, total):
+        pf_output = self.get_pf_testpmd_reponse()
+        expected_str = "TX driver issue detected on VF 0 {0}times".format(total)
+        msg = "'{}' not display".format(expected_str)
+        self.verify(expected_str in pf_output, msg)
+
+    def verify_malicious_driver_event_detected(self):
+        except_content = None
+        try:
+            self.start_pf_testpmd()
+            self.start_vf_testpmd()
+            self.check_event_is_detected()
+        except Exception as e:
+            self.logger.error(traceback.format_exc())
+            except_content = e
+        finally:
+            self.close_vf_testpmd()
+            self.close_pf_testpmd()
+        # re-raise verify exception result
+        if except_content:
+            raise VerifyFailure(except_content)
+
+    def verify_malicious_driver_event_counter_number(self):
+        except_content = None
+        try:
+            self.start_pf_testpmd()
+            total = 3
+            for _ in range(total):
+                self.start_vf_testpmd()
+                self.close_vf_testpmd()
+            self.check_event_counter_number(total)
+        except Exception as e:
+            self.logger.error(traceback.format_exc())
+            except_content = e
+        finally:
+            self.close_vf_testpmd()
+            self.close_pf_testpmd()
+        # re-raise verify exception result
+        if except_content:
+            raise VerifyFailure(except_content)
+
+    def verify_supported_nic(self):
+        supported_drivers = ['i40e']
+        result = all([self.dut.ports_info[index]['port'].default_driver in
+                      supported_drivers
+                      for index in self.dut_ports])
+        msg = "current nic <0> is not supported".format(self.nic)
+        self.verify(result, msg)
+
+    def preset_pmd_res(self):
+        # get whitelist and cores
+        socket = self.dut.get_numa_id(self.dut_ports[0])
+        corelist = self.dut.get_core_list("1S/6C/1T", socket=socket)[2:]
+        self.pf_pmd_whitelist = '-w ' + self.vf_ports_info[0].get('pf_pci')
+        self.pf_pmd_cores = corelist[:2]
+        self.vf_pmd_whitelist = '-w ' + self.vf_ports_info[0].get('vfs_pci')[0]
+        self.vf_pmd_cores = corelist[2:]
+
+    def init_params(self):
+        self.is_pf_pmd_on = self.is_vf_pmd_on = None
+        self.vf_ports_info = {}
+
+    def preset_test_environment(self):
+        self.preset_dpdk_compilation()
+        self.init_pf_testpmd()
+        self.init_vf_testpmd()
+        self.vf_create()
+        # get socket and cores
+        self.preset_pmd_res()
+
+    def destroy_resource(self):
+        with self.restore_dpdk_compilation():
+            self.vf_destroy()
+            if self.vf_pmd_session:
+                self.dut.close_session(self.vf_pmd_session)
+                self.vf_pmd_session = None
+    #
+    # Test cases.
+    #
+    def set_up_all(self):
+        """
+        Run at the start of each test suite.
+        """
+        self.init_params()
+        self.dut_ports = self.dut.get_ports(self.nic)
+        self.verify(len(self.dut_ports) >= 1, "Not enough ports")
+        self.verify_supported_nic()
+        # prepare testing environment
+        self.preset_test_environment()
+
+    def tear_down_all(self):
+        """
+        Run after each test suite.
+        """
+        self.destroy_resource()
+
+    def set_up(self):
+        """
+        Run before each test case.
+        """
+        pass
+
+    def tear_down(self):
+        """
+        Run after each test case.
+        """
+        self.dut.kill_all()
+
+    def test_malicious_driver_event_detected(self):
+        """
+        Check log output when malicious driver events is detected
+        """
+        self.verify_malicious_driver_event_detected()
+
+    def test_malicious_driver_event_counter_number(self):
+        """
+        Check the event counter number for malicious driver events
+        """
+        self.verify_malicious_driver_event_counter_number()
-- 
2.21.0


  reply	other threads:[~2020-05-25  2:21 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-25  2:23 [dts] [PATCH V3 0/3] tests/malicious_driver_event_indication: upload test plan and automation script yufengmx
2020-05-25  2:23 ` yufengmx [this message]
2020-05-25  2:23 ` [dts] [PATCH V3 2/3] tests/malicious_driver_event_indication: update test plan yufengmx
2020-05-26  2:08   ` Yao, Lei A
2020-05-25  2:23 ` [dts] [PATCH V3 3/3] tests/malicious_driver_event_indication: add " yufengmx
2020-05-26  2:16   ` Yao, Lei A

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200525022315.3214-2-yufengx.mo@intel.com \
    --to=yufengx.mo@intel.com \
    --cc=dts@dpdk.org \
    --cc=lei.a.yao@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).