Add FW Version

Message ID 20200812183235.30714-1-dliu@iol.unh.edu (mailing list archive)
State Superseded
Headers
Series Add FW Version |

Commit Message

dliu Aug. 12, 2020, 6:32 p.m. UTC
  Add firmware version test case
Add firmware version test plan
Add firmware version cfg file

Signed-off-by: David Liu <dliu@iol.unh.edu>
---
 conf/firmware_version.cfg                 |  25 ++++
 framework/pmd_output.py                   |   6 +
 test_plans/firmware_version_test_plan.rst |  79 ++++++++++++
 tests/TestSuite_firmware_version.py       | 149 ++++++++++++++++++++++
 4 files changed, 259 insertions(+)
 create mode 100644 conf/firmware_version.cfg
 create mode 100644 test_plans/firmware_version_test_plan.rst
 create mode 100644 tests/TestSuite_firmware_version.py
  

Comments

Ma, LihongX Aug. 13, 2020, 1:45 a.m. UTC | #1
Hi, David liu
Now the Copyright of intel is 2020, eg 'Copyright(c) 2020 Intel Corporation. All rights reserved'
And can you add the version info when you submit the patch, eg "[dts] [PATCH V1] Add FW Version", it will make it easy for us to review and merge.

Thanks,
Regards,
Ma,lihong

-----Original Message-----
From: dts <dts-bounces@dpdk.org> On Behalf Of David Liu
Sent: Thursday, August 13, 2020 2:33 AM
To: dts@dpdk.org
Cc: lylavoie@iol.unh.edu; David Liu <dliu@iol.unh.edu>
Subject: [dts] [PATCH] Add FW Version

Add firmware version test case
Add firmware version test plan
Add firmware version cfg file

Signed-off-by: David Liu <dliu@iol.unh.edu>
---
 conf/firmware_version.cfg                 |  25 ++++
 framework/pmd_output.py                   |   6 +
 test_plans/firmware_version_test_plan.rst |  79 ++++++++++++
 tests/TestSuite_firmware_version.py       | 149 ++++++++++++++++++++++
 4 files changed, 259 insertions(+)
 create mode 100644 conf/firmware_version.cfg  create mode 100644 test_plans/firmware_version_test_plan.rst
 create mode 100644 tests/TestSuite_firmware_version.py

diff --git a/conf/firmware_version.cfg b/conf/firmware_version.cfg new file mode 100644 index 0000000..70549db
--- /dev/null
+++ b/conf/firmware_version.cfg
@@ -0,0 +1,25 @@
+# Users could change these configuration on demand:
+#
+#  - expected_firmware_version is a dictionary defining expected firmware version.
+# Each diver will have different version format.
+# The pattern for supported expected firmare version:
+#
+#   - i40e:
+#           {'driver' : ['X.XX', '0x8000XXXX', 'X.X.X']}
+#   - mlx5:
+#           {'driver' : ['XX.XX.XXXX', 'MT_XXXXXX']}
+#   - bnxt:
+#           {'driver' : ['XXX.XXX.XXX.XXX/pkg', 'XXX.XXX.XXX.XXX']}
+#
+# Note: run ./dts and use show port info <port_id> command will show 
+you the # firmware version.
+
+#Example:
+#[suite]
+#expected_firmware_version = {
+#    'i40e': ['0x80002919', '5.05', '1.1313.0'],
+#    'mlx5' : ['12.25.6555', 'MT_555555555'],
+#    'bnxt' : ['236.0.222.0/pkg', '216.3.254.0']}
+
+[suite]
+expected_firmware_version = {}
diff --git a/framework/pmd_output.py b/framework/pmd_output.py index 2d66743..22ed9a0 100644
--- a/framework/pmd_output.py
+++ b/framework/pmd_output.py
@@ -237,6 +237,12 @@ class PmdOutput():
         """
         return self.get_detail_from_port_info("MAC address: ", "([0-9A-F]{2}:){5}[0-9A-F]{2}", port_id)
 
+    def get_firmware_version(self, port_id):
+        """
+        Get the firmware version.
+        """
+        return self.get_detail_from_port_info("Firmware-version: ", 
+ "\S.*", port_id)
+
     def get_port_connect_socket(self, port_id):
         """
         Get the socket id which the specified port is connecting with.
diff --git a/test_plans/firmware_version_test_plan.rst b/test_plans/firmware_version_test_plan.rst
new file mode 100644
index 0000000..f6f92a6
--- /dev/null
+++ b/test_plans/firmware_version_test_plan.rst
@@ -0,0 +1,79 @@
+.. # BSD LICENSE
+    #
+    # Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+    # Copyright © 2018[, 2019] The University of New Hampshire. 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.
+
+=======================
+Firmware Version Test
+=======================
+
+The Firmware Version Test checks the firmware version from the device 
+info and compares to the firmware version defined by user. This test 
+case is driver restricted since each driver will have different version format.
+
+
+Prerequisites
+=============
+
+If using vfio the kernel must be >= 3.6+ and VT-d must be enabled in 
+bios.When using vfio, use the following commands to load the vfio 
+driver and bind it to the device under test::
+
+   modprobe vfio
+   modprobe vfio-pci
+   usertools/dpdk-devbind.py --bind=vfio-pci device_bus_id
+
+Assuming that ports are up and working, then launch the ``testpmd`` 
+application with the following arguments::
+
+  ./build/app/testpmd -- -i --portmask=0x3
+
+Ensure the ```firmware_version.cfg``` file have the correct name and 
+firmware version.
+
+Test Case : Firmware Version Test
+===================================
+
+1. Use testpmd to show the port info that contained the firmware version::
+
+      testpmd> show port info <PORT_ID>
+
+2. Compares the outputted firmware version with the firmware version listed in the
+    ```firmware_version.cfg``` file. Different driver will have different version
+    format.
+    Currently support: i40e, mlx5, bnxt
+
+    Example below:
+    {'i40e' : ['5.01', '0x80002341', '1.1.1']}
+    {'mlx5' : ['12.14.3462', 'MT_2416545656']}
+    {'bnxt' : ['236.0.222.0', '216.3.254.0']}
+
+
+3. Verifies they matches.
\ No newline at end of file
diff --git a/tests/TestSuite_firmware_version.py b/tests/TestSuite_firmware_version.py
new file mode 100644
index 0000000..a7cda89
--- /dev/null
+++ b/tests/TestSuite_firmware_version.py
@@ -0,0 +1,149 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# Copyright © 2018[, 2019] The University of New Hampshire. 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.
+"""
+from pmd_output import PmdOutput
+from test_case import TestCase
+import re
+
+
+class TestFirmwareVersion(TestCase):
+
+    def set_up_all(self):
+        """
+        Run at the start of each test suite.
+        """
+        self.ports = self.dut.get_ports()
+
+        self.pmdout = PmdOutput(self.dut)
+
+    def set_up(self):
+        """
+        Run before each test case.
+        """
+        pass
+
+    def check_firmware_version(self, exp_fwversion, fwversion):
+        vf = ['major', 'minor', 'path', 'build']
+        fwversion = re.split("\\.", fwversion)
+        exp_fwversion = re.split("\\.", exp_fwversion)
+
+        self.verify(len(exp_fwversion) == len(fwversion), "Invalid 
+ version format")
+
+        for i in range(len(exp_fwversion)):
+            if fwversion[i] != exp_fwversion[i] and i == 0:
+                self.verify(False,
+                            f"Fail: {vf[i]} version is different expected {exp_fwversion[i]} but was {fwversion[i]}")
+            elif fwversion[i] != exp_fwversion[i] and i > 0:
+                print(f"Warning: {vf[i]} version is different expected 
+ {exp_fwversion[i]} but was {fwversion[i]}")
+
+    def check_format(self, exp, out, name, pattern, match):
+        if match is None:
+            self.verify(re.search(pattern, exp) is not None, f"Invalid expected {name} format")
+            self.verify(re.search(pattern, out) is not None, f"Invalid {name} format")
+        else:
+            exp = re.findall(pattern, exp)
+            out = re.findall(pattern, out)
+
+            self.verify(exp[0] == match, f"Invalid expected {name} format")
+            self.verify(out[0] == match, f"Invalid {name} format")
+
+    def test_firmware_version(self):
+        self.pmdout.start_testpmd("Default")
+
+        # Read the version cfg
+        expected_version_list = 
+ self.get_suite_cfg()['expected_firmware_version']
+
+        self.verify(self.kdriver in expected_version_list, "driver is not in the cfg file")
+        expected_version_info = expected_version_list[self.kdriver]
+
+        for port in self.ports:
+            out = self.dut.send_expect(f"show port info {port}", "testpmd> ")
+            self.verify("Firmware-version:" in out, "Firmware version 
+ not detected")
+
+            version_info = self.pmdout.get_firmware_version(port)
+
+            if self.kdriver == "i40e":
+                # Get the version information from output and cfg file
+                fwversion, etrackid, networkdriver = version_info.split()
+                exp_etrackid, exp_fwversion, exp_networkdriver = 
+ expected_version_info
+                
+                self.check_format(exp_fwversion, fwversion, "version", 
+ r'^\d{1,4}\.\d{1,4}$', None)
+
+                self.check_firmware_version(exp_fwversion, fwversion)
+
+                self.check_format(exp_etrackid, etrackid, "etrackid", 
+ r'^.{0,6}', "0x8000")
+
+                self.check_format(exp_networkdriver, networkdriver,
+                                  "network driver", 
+ r'^\d{1,4}\.\d{1,4}\.\d{1,4}$', None)
+
+            elif self.kdriver == "mlx5":
+                # Get the version information from output and cfg file
+                exp_fwversion, exp_psid = expected_version_info
+                fwversion, psid = version_info.split()
+
+                self.check_format(exp_fwversion, fwversion, "version", 
+ r'^\d{1,4}\.\d{1,4}\.\d{1,4}$', None)
+
+                self.check_firmware_version(exp_fwversion, fwversion)
+
+                # remove "(" and ")" from the string
+                psid = re.sub('[()]', '', psid)
+
+                self.check_format(exp_psid, psid, "psid", r'^.{0,3}', 
+ "MT_")
+
+            elif self.kdriver == "bnxt":
+                # Get the version information from output and cfg file
+                exp_pkg, exp_fwversion = expected_version_info
+                pkg, fwversion = version_info.split()
+
+                self.check_format(exp_fwversion, fwversion, "version", 
+ r'^\d{1,4}\.\d{1,4}\.\d{1,4}\.\d{1,4}$', None)
+
+                self.check_firmware_version(exp_fwversion, fwversion)
+
+                self.check_format(exp_pkg, pkg, "pkg", 
+ r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\S{1,3}$', None)
+
+            else:
+                self.verify(False, f"Test: case fails on {self.kdriver} 
+ driver")
+
+    def tear_down(self):
+        """
+        Run after each test case.
+        """
+        self.dut.kill_all()
+
+    def tear_down_all(self):
+        """
+        Run after each test suite.
+        """
+        self.dut.kill_all()
--
2.17.1
  

Patch

diff --git a/conf/firmware_version.cfg b/conf/firmware_version.cfg
new file mode 100644
index 0000000..70549db
--- /dev/null
+++ b/conf/firmware_version.cfg
@@ -0,0 +1,25 @@ 
+# Users could change these configuration on demand:
+#
+#  - expected_firmware_version is a dictionary defining expected firmware version.
+# Each diver will have different version format.
+# The pattern for supported expected firmare version:
+#
+#   - i40e:
+#           {'driver' : ['X.XX', '0x8000XXXX', 'X.X.X']}
+#   - mlx5:
+#           {'driver' : ['XX.XX.XXXX', 'MT_XXXXXX']}
+#   - bnxt:
+#           {'driver' : ['XXX.XXX.XXX.XXX/pkg', 'XXX.XXX.XXX.XXX']}
+#
+# Note: run ./dts and use show port info <port_id> command will show you the
+# firmware version.
+
+#Example:
+#[suite]
+#expected_firmware_version = {
+#    'i40e': ['0x80002919', '5.05', '1.1313.0'],
+#    'mlx5' : ['12.25.6555', 'MT_555555555'],
+#    'bnxt' : ['236.0.222.0/pkg', '216.3.254.0']}
+
+[suite]
+expected_firmware_version = {}
diff --git a/framework/pmd_output.py b/framework/pmd_output.py
index 2d66743..22ed9a0 100644
--- a/framework/pmd_output.py
+++ b/framework/pmd_output.py
@@ -237,6 +237,12 @@  class PmdOutput():
         """
         return self.get_detail_from_port_info("MAC address: ", "([0-9A-F]{2}:){5}[0-9A-F]{2}", port_id)
 
+    def get_firmware_version(self, port_id):
+        """
+        Get the firmware version.
+        """
+        return self.get_detail_from_port_info("Firmware-version: ", "\S.*", port_id)
+
     def get_port_connect_socket(self, port_id):
         """
         Get the socket id which the specified port is connecting with.
diff --git a/test_plans/firmware_version_test_plan.rst b/test_plans/firmware_version_test_plan.rst
new file mode 100644
index 0000000..f6f92a6
--- /dev/null
+++ b/test_plans/firmware_version_test_plan.rst
@@ -0,0 +1,79 @@ 
+.. # BSD LICENSE
+    #
+    # Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+    # Copyright © 2018[, 2019] The University of New Hampshire. 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.
+
+=======================
+Firmware Version Test
+=======================
+
+The Firmware Version Test checks the firmware version from the device info and
+compares to the firmware version defined by user. This test case is driver
+restricted since each driver will have different version format.
+
+
+Prerequisites
+=============
+
+If using vfio the kernel must be >= 3.6+ and VT-d must be enabled in bios.When
+using vfio, use the following commands to load the vfio driver and bind it
+to the device under test::
+
+   modprobe vfio
+   modprobe vfio-pci
+   usertools/dpdk-devbind.py --bind=vfio-pci device_bus_id
+
+Assuming that ports are up and working, then launch the ``testpmd`` application
+with the following arguments::
+
+  ./build/app/testpmd -- -i --portmask=0x3
+
+Ensure the ```firmware_version.cfg``` file have the correct name and firmware
+version.
+
+Test Case : Firmware Version Test
+===================================
+
+1. Use testpmd to show the port info that contained the firmware version::
+
+      testpmd> show port info <PORT_ID>
+
+2. Compares the outputted firmware version with the firmware version listed in the
+    ```firmware_version.cfg``` file. Different driver will have different version
+    format.
+    Currently support: i40e, mlx5, bnxt
+
+    Example below:
+    {'i40e' : ['5.01', '0x80002341', '1.1.1']}
+    {'mlx5' : ['12.14.3462', 'MT_2416545656']}
+    {'bnxt' : ['236.0.222.0', '216.3.254.0']}
+
+
+3. Verifies they matches.
\ No newline at end of file
diff --git a/tests/TestSuite_firmware_version.py b/tests/TestSuite_firmware_version.py
new file mode 100644
index 0000000..a7cda89
--- /dev/null
+++ b/tests/TestSuite_firmware_version.py
@@ -0,0 +1,149 @@ 
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# Copyright © 2018[, 2019] The University of New Hampshire. 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.
+"""
+from pmd_output import PmdOutput
+from test_case import TestCase
+import re
+
+
+class TestFirmwareVersion(TestCase):
+
+    def set_up_all(self):
+        """
+        Run at the start of each test suite.
+        """
+        self.ports = self.dut.get_ports()
+
+        self.pmdout = PmdOutput(self.dut)
+
+    def set_up(self):
+        """
+        Run before each test case.
+        """
+        pass
+
+    def check_firmware_version(self, exp_fwversion, fwversion):
+        vf = ['major', 'minor', 'path', 'build']
+        fwversion = re.split("\\.", fwversion)
+        exp_fwversion = re.split("\\.", exp_fwversion)
+
+        self.verify(len(exp_fwversion) == len(fwversion), "Invalid version format")
+
+        for i in range(len(exp_fwversion)):
+            if fwversion[i] != exp_fwversion[i] and i == 0:
+                self.verify(False,
+                            f"Fail: {vf[i]} version is different expected {exp_fwversion[i]} but was {fwversion[i]}")
+            elif fwversion[i] != exp_fwversion[i] and i > 0:
+                print(f"Warning: {vf[i]} version is different expected {exp_fwversion[i]} but was {fwversion[i]}")
+
+    def check_format(self, exp, out, name, pattern, match):
+        if match is None:
+            self.verify(re.search(pattern, exp) is not None, f"Invalid expected {name} format")
+            self.verify(re.search(pattern, out) is not None, f"Invalid {name} format")
+        else:
+            exp = re.findall(pattern, exp)
+            out = re.findall(pattern, out)
+
+            self.verify(exp[0] == match, f"Invalid expected {name} format")
+            self.verify(out[0] == match, f"Invalid {name} format")
+
+    def test_firmware_version(self):
+        self.pmdout.start_testpmd("Default")
+
+        # Read the version cfg
+        expected_version_list = self.get_suite_cfg()['expected_firmware_version']
+
+        self.verify(self.kdriver in expected_version_list, "driver is not in the cfg file")
+        expected_version_info = expected_version_list[self.kdriver]
+
+        for port in self.ports:
+            out = self.dut.send_expect(f"show port info {port}", "testpmd> ")
+            self.verify("Firmware-version:" in out, "Firmware version not detected")
+
+            version_info = self.pmdout.get_firmware_version(port)
+
+            if self.kdriver == "i40e":
+                # Get the version information from output and cfg file
+                fwversion, etrackid, networkdriver = version_info.split()
+                exp_etrackid, exp_fwversion, exp_networkdriver = expected_version_info
+                
+                self.check_format(exp_fwversion, fwversion, "version", r'^\d{1,4}\.\d{1,4}$', None)
+
+                self.check_firmware_version(exp_fwversion, fwversion)
+
+                self.check_format(exp_etrackid, etrackid, "etrackid", r'^.{0,6}', "0x8000")
+
+                self.check_format(exp_networkdriver, networkdriver,
+                                  "network driver", r'^\d{1,4}\.\d{1,4}\.\d{1,4}$', None)
+
+            elif self.kdriver == "mlx5":
+                # Get the version information from output and cfg file
+                exp_fwversion, exp_psid = expected_version_info
+                fwversion, psid = version_info.split()
+
+                self.check_format(exp_fwversion, fwversion, "version", r'^\d{1,4}\.\d{1,4}\.\d{1,4}$', None)
+
+                self.check_firmware_version(exp_fwversion, fwversion)
+
+                # remove "(" and ")" from the string
+                psid = re.sub('[()]', '', psid)
+
+                self.check_format(exp_psid, psid, "psid", r'^.{0,3}', "MT_")
+
+            elif self.kdriver == "bnxt":
+                # Get the version information from output and cfg file
+                exp_pkg, exp_fwversion = expected_version_info
+                pkg, fwversion = version_info.split()
+
+                self.check_format(exp_fwversion, fwversion, "version", r'^\d{1,4}\.\d{1,4}\.\d{1,4}\.\d{1,4}$', None)
+
+                self.check_firmware_version(exp_fwversion, fwversion)
+
+                self.check_format(exp_pkg, pkg, "pkg", r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\S{1,3}$', None)
+
+            else:
+                self.verify(False, f"Test: case fails on {self.kdriver} driver")
+
+    def tear_down(self):
+        """
+        Run after each test case.
+        """
+        self.dut.kill_all()
+
+    def tear_down_all(self):
+        """
+        Run after each test suite.
+        """
+        self.dut.kill_all()