diff --git a/tests/TestSuite_cvl_pf_qinq_switch_filter.py b/tests/TestSuite_cvl_pf_qinq_switch_filter.py
new file mode 100644
index 00000000..cb04e183
--- /dev/null
+++ b/tests/TestSuite_cvl_pf_qinq_switch_filter.py
@@ -0,0 +1,348 @@
+# BSD LICENSE
+#
+# Copyright(c) 2021 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.
+
+import time
+import tests.rte_flow_common as rfc
+
+from framework.packet import Packet
+from framework.pmd_output import PmdOutput
+from framework.test_case import TestCase, skip_unsupported_pkg
+from framework.utils import GREEN, RED
+from scapy.all import *
+
+LAUNCH_QUEUE = 16
+
+mac_qinq_basic_pkts = {
+    'mac_qinq_ipv4': 'Ether(dst="00:11:22:33:44:55",type=0x8100)/Dot1Q(vlan=2,type=0x8100)/Dot1Q(vlan=0x1,type=0x0800)/IP(src="192.168.1.1", dst="192.168.1.2")/("X"*80)',
+    'mac_qinq_ipv6': 'Ether(dst="00:11:22:33:44:55",type=0x8100)/Dot1Q(vlan=2,type=0x8100)/Dot1Q(vlan=0x1,type=0x86DD)/IPv6(dst="CDCD:910A:2222:5498:8475:1111:3900:2020")/("X"*80)',
+    'mac_qinq_ipv4_udp': 'Ether(dst="00:11:22:33:44:55",type=0x8100)/Dot1Q(vlan=2,type=0x8100)/Dot1Q(vlan=0x1,type=0x0800)/IP()/UDP(sport=50,dport=23)/("X"*80)',
+    'mac_qinq_ipv6_udp': 'Ether(dst="00:11:22:33:44:55",type=0x8100)/Dot1Q(vlan=2,type=0x8100)/Dot1Q(vlan=0x1,type=0x86DD)/IPv6(dst="CDCD:910A:2222:5498:8475:1111:3900:2020")/UDP(sport=50,dport=23)/("X"*80)',
+    'mac_qinq_ipv4_tcp': 'Ether(dst="00:11:22:33:44:55",type=0x8100)/Dot1Q(vlan=2,type=0x8100)/Dot1Q(vlan=0x1,type=0x0800)/IP()/TCP(sport=50,dport=23)/("X"*80)',
+    'mac_qinq_ipv6_tcp': 'Ether(dst="00:11:22:33:44:55",type=0x8100)/Dot1Q(vlan=2,type=0x8100)/Dot1Q(vlan=0x1,type=0x86DD)/IPv6(dst="CDCD:910A:2222:5498:8475:1111:3900:2020")/TCP(sport=50,dport=23)/("X"*80)',
+}
+
+# no-pipeline mode
+tv_mac_qinq_ipv4_queue_index = {
+    "name": "tv_mac_qinq_ipv4_queue_index",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv4 src is 192.168.1.1 dst is 192.168.1.2 / end actions queue index 2 / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv4']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('192.168.1.1', '192.168.1.3'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('192.168.1.2', '192.168.1.4'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "queue": 2}
+}
+
+tv_mac_qinq_ipv4_rss_queues = {
+    "name": "tv_mac_qinq_ipv4_rss_queues",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv4 src is 192.168.1.1 dst is 192.168.1.2 / end actions rss queues 4 5 end / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv4']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('192.168.1.1', '192.168.1.3'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('192.168.1.2', '192.168.1.4'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "queue": [4, 5]}
+}
+
+tv_mac_qinq_ipv4_drop = {
+    "name": "tv_mac_qinq_ipv4_drop",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv4 src is 192.168.1.1 dst is 192.168.1.2 / end actions drop / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv4']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('192.168.1.1', '192.168.1.3'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4'].replace('192.168.1.2', '192.168.1.4'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "drop": True}
+}
+
+tvs_mac_qinq_ipv4 = [tv_mac_qinq_ipv4_queue_index, tv_mac_qinq_ipv4_rss_queues, tv_mac_qinq_ipv4_drop]
+
+tv_mac_qinq_ipv6_queue_index = {
+    "name": "tv_mac_qinq_ipv6_queue_index",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv6 dst is CDCD:910A:2222:5498:8475:1111:3900:2020 / end actions queue index 2 / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv6']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('CDCD:910A:2222:5498:8475:1111:3900:2020', 'CDCD:910A:2222:5498:8475:1111:3900:2023'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "queue": 2}
+}
+
+tv_mac_qinq_ipv6_rss_queues = {
+    "name": "tv_mac_qinq_ipv6_rss_queues",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv6 dst is CDCD:910A:2222:5498:8475:1111:3900:2020 / end actions rss queues 4 5 end / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv6']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('CDCD:910A:2222:5498:8475:1111:3900:2020', 'CDCD:910A:2222:5498:8475:1111:3900:2023'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "queue": [4, 5]}
+}
+
+tv_mac_qinq_ipv6_drop = {
+    "name": "tv_mac_qinq_ipv6_drop",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv6 dst is CDCD:910A:2222:5498:8475:1111:3900:2020 / end actions drop / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv6']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('CDCD:910A:2222:5498:8475:1111:3900:2020', 'CDCD:910A:2222:5498:8475:1111:3900:2023'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "drop": True}
+}
+
+tvs_mac_qinq_ipv6 = [tv_mac_qinq_ipv6_queue_index, tv_mac_qinq_ipv6_rss_queues, tv_mac_qinq_ipv6_drop]
+
+
+tv_mac_qinq_ipv4_udp_queue_index = {
+    "name": "tv_mac_qinq_ipv4_udp_queue_index",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv4 / udp src is 50 dst is 23 / end actions queue index 2 / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv4_udp']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('23', '22'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('50', '51'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "queue": 2}
+}
+
+tv_mac_qinq_ipv4_udp_rss_queues = {
+    "name": "tv_mac_qinq_ipv4_udp_rss_queues",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv4 / udp src is 50 dst is 23 / end actions rss queues 4 5 end / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv4_udp']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('23', '22'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('50', '51'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "queue": [4, 5]}
+}
+
+tv_mac_qinq_ipv4_udp_drop = {
+    "name": "tv_mac_qinq_ipv4_udp_drop",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv4 / udp src is 50 dst is 23 / end actions drop / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv4_udp']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('23', '22'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv4_udp'].replace('50', '51'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "drop": True}
+}
+
+tvs_mac_qinq_ipv4_udp = [tv_mac_qinq_ipv4_udp_queue_index, tv_mac_qinq_ipv4_udp_rss_queues, tv_mac_qinq_ipv4_udp_drop]
+
+tv_mac_qinq_ipv6_udp_queue_index = {
+    "name": "tv_mac_qinq_ipv6_udp_queue_index",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv6 / udp src is 50 dst is 23 / end actions queue index 2 / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv6_udp']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('23', '22'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('50', '51'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "queue": 2}
+}
+
+tv_mac_qinq_ipv6_udp_rss_queues = {
+    "name": "tv_mac_qinq_ipv6_udp_rss_queues",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv6 / udp src is 50 dst is 23 / end actions rss queues 4 5 end / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv6_udp']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('23', '22'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('50', '51'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "queue": [4, 5]}
+}
+
+tv_mac_qinq_ipv6_udp_drop = {
+    "name": "tv_mac_qinq_ipv6_udp_drop",
+    "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / vlan tci is 2 / vlan tci is 1 / ipv6 / udp src is 50 dst is 23 / end actions drop / end",
+    "scapy_str": {"matched": [mac_qinq_basic_pkts['mac_qinq_ipv6_udp']],
+                  "unmatched": [mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('vlan=2', 'vlan=1'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('vlan=0x1', 'vlan=0x2'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('23', '22'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('00:11:22:33:44:55', '00:11:22:33:44:66'),
+                                mac_qinq_basic_pkts['mac_qinq_ipv6_udp'].replace('50', '51'),]
+                  },
+    "check_param": {"port_id": 0, "rxq": LAUNCH_QUEUE, "drop": True}
+}
+
+tvs_mac_qinq_ipv6_udp = [tv_mac_qinq_ipv6_udp_queue_index, tv_mac_qinq_ipv6_udp_rss_queues, tv_mac_qinq_ipv6_udp_drop]
+
+tvs_mac_qinq_ipv4_tcp = [eval(str(element).replace('tv_mac_qinq_ipv4_udp', 'tv_mac_qinq_ipv4_tcp')
+                                          .replace('ipv4 / udp', 'ipv4 / tcp')
+                                          .replace('IP()/UDP', 'IP()/TCP')
+                              )
+                         for element in tvs_mac_qinq_ipv4_udp]
+
+tvs_mac_qinq_ipv6_tcp = [eval(str(element).replace('tv_mac_qinq_ipv6_udp', 'tv_mac_qinq_ipv6_tcp')
+                                          .replace('ipv6 / udp', 'ipv6 / tcp')
+                                          .replace('UDP(sport=50,', 'TCP(sport=50,')
+                              )
+                         for element in tvs_mac_qinq_ipv6_udp]
+
+
+# pipeline mode
+
+tvs_mac_qinq_ipv4_pipeline_mode = [eval(str(element).replace('tv_mac_qinq_ipv4', 'tv_mac_qinq_ipv4_pipeline_mode')
+                                                    .replace('flow create 0 ingress', 'flow create 0 priority 0 ingress')
+                              )
+                         for element in tvs_mac_qinq_ipv4]
+
+tvs_mac_qinq_ipv6_pipeline_mode = [eval(str(element).replace('tv_mac_qinq_ipv6', 'tv_mac_qinq_ipv6_pipeline_mode')
+                                                    .replace('flow create 0 ingress', 'flow create 0 priority 0 ingress')
+                              )
+                         for element in tvs_mac_qinq_ipv6]
+
+tvs_mac_qinq_ipv4_udp_pipeline_mode = [eval(str(element).replace('tv_mac_qinq_ipv4_udp', 'tv_mac_qinq_ipv4_udp_pipeline_mode')
+                                                        .replace('flow create 0 ingress', 'flow create 0 priority 0 ingress')
+                              )
+                         for element in tvs_mac_qinq_ipv4_udp]
+
+tvs_mac_qinq_ipv6_udp_pipeline_mode = [eval(str(element).replace('tv_mac_qinq_ipv6_udp', 'tv_mac_qinq_ipv6_udp_pipeline_mode')
+                                                        .replace('flow create 0 ingress', 'flow create 0 priority 0 ingress')
+                              )
+                         for element in tvs_mac_qinq_ipv6_udp]
+
+tvs_mac_qinq_ipv4_tcp_pipeline_mode = [eval(str(element).replace('tv_mac_qinq_ipv4_tcp', 'tv_mac_qinq_ipv4_tcp_pipeline_mode')
+                                                        .replace('flow create 0 ingress', 'flow create 0 priority 0 ingress')
+                              )
+                         for element in tvs_mac_qinq_ipv4_tcp]
+
+tvs_mac_qinq_ipv6_tcp_pipeline_mode = [eval(str(element).replace('tv_mac_qinq_ipv6_tcp', 'tv_mac_qinq_ipv6_tcp_pipeline_mode')
+                                                        .replace('flow create 0 ingress', 'flow create 0 priority 0 ingress')
+                              )
+                         for element in tvs_mac_qinq_ipv6_tcp]
+
+
+class TestCvlQinqSwitchFilter(TestCase):
+    def set_up_all(self):
+        self.ports = self.dut.get_ports(self.nic)
+
+        # init pkt
+        self.pkt = Packet()
+        # set default app parameter
+        self.pmd_out = PmdOutput(self.dut)
+        self.tester_mac = self.tester.get_mac(0)
+        self.tester_port0 = self.tester.get_local_port(self.ports[0])
+        self.tester_iface0 = self.tester.get_interface(self.tester_port0)
+
+        self.tester.send_expect('ifconfig {} up'.format(self.tester_iface0), '# ')
+        self.param = '--rxq={} --txq={}'.format(LAUNCH_QUEUE, LAUNCH_QUEUE)
+        self.cores = self.dut.get_core_list("1S/4C/1T")
+
+        self.ports_pci = self.dut.ports_info[self.ports[0]]['pci']
+
+        self.fdirprocess = rfc.FdirProcessing(self, self.pmd_out, [self.tester_iface0], LAUNCH_QUEUE)
+
+    def set_up(self):
+        self.dut.bind_interfaces_linux('vfio-pci')
+
+    def launch_testpmd(self, is_pipeline_mode=False):
+        if is_pipeline_mode:
+            self.pmd_out.start_testpmd(cores=self.cores, ports=[0], port_options={0:"pipeline-mode-support=1"}, \
+                                                                               param=self.param)
+        else:
+            self.pmd_out.start_testpmd(cores=self.cores, ports=[self.ports_pci], param=self.param)
+        self.dut.send_expect("show port info all", "testpmd> ")
+        self.dut.send_expect("set fwd rxonly", "testpmd> ")
+        self.dut.send_expect("set verbose 1", "testpmd> ")
+        self.dut.send_expect("start", "testpmd> ")
+
+    def tear_down(self):
+        self.dut.send_expect("quit", "# ")
+        self.dut.kill_all()
+
+    def tear_down_all(self):
+        self.dut.kill_all()
+
+    def test_mac_qinq_ipv4(self):
+        self.launch_testpmd()
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv4)
+
+    def test_mac_qinq_ipv6(self):
+        self.launch_testpmd()
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv6)
+
+    def test_mac_qinq_ipv4_udp(self):
+        self.launch_testpmd()
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv4_udp)
+
+    def test_mac_qinq_ipv6_udp(self):
+        self.launch_testpmd()
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv6_udp)
+
+    def test_mac_qinq_ipv4_tcp(self):
+        self.launch_testpmd()
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv4_tcp)
+
+    def test_mac_qinq_ipv6_tcp(self):
+        self.launch_testpmd()
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv6_tcp)
+
+    def test_mac_qinq_ipv4_pipeline_mode(self):
+        self.launch_testpmd(is_pipeline_mode=True)
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv4_pipeline_mode)
+
+    def test_mac_qinq_ipv6_pipeline_mode(self):
+        self.launch_testpmd(is_pipeline_mode=True)
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv6_pipeline_mode)
+
+    def test_mac_qinq_ipv4_udp_pipeline_mode(self):
+        self.launch_testpmd(is_pipeline_mode=True)
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv4_udp_pipeline_mode)
+
+    def test_mac_qinq_ipv6_udp_pipeline_mode(self):
+        self.launch_testpmd(is_pipeline_mode=True)
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv6_udp_pipeline_mode)
+
+    def test_mac_qinq_ipv4_tcp_pipeline_mode(self):
+        self.launch_testpmd(is_pipeline_mode=True)
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv4_tcp_pipeline_mode)
+
+    def test_mac_qinq_ipv6_tcp_pipeline_mode(self):
+        self.launch_testpmd(is_pipeline_mode=True)
+        self.fdirprocess.flow_director_validate(tvs_mac_qinq_ipv6_tcp_pipeline_mode)
