test suite reviews and discussions
 help / color / mirror / Atom feed
* [dts] [PATCH V4 1/2] tests/multiprocess: add pf multiprocess test case
@ 2022-05-19  7:48 Jiale Song
  2022-05-19  7:48 ` [dts] [PATCH V4 2/2] test_plans/multiprocess: " Jiale Song
  0 siblings, 1 reply; 4+ messages in thread
From: Jiale Song @ 2022-05-19  7:48 UTC (permalink / raw)
  To: dts; +Cc: Jiale Song

Signed-off-by: Jiale Song <songx.jiale@intel.com>
---
 tests/TestSuite_multiprocess.py | 1443 ++++++++++++++++++++++++++++++-
 1 file changed, 1440 insertions(+), 3 deletions(-)

diff --git a/tests/TestSuite_multiprocess.py b/tests/TestSuite_multiprocess.py
index 79744722..0b1dd19f 100644
--- a/tests/TestSuite_multiprocess.py
+++ b/tests/TestSuite_multiprocess.py
@@ -34,17 +34,32 @@ DPDK Test suite.
 Multi-process Test.
 """
 
+import copy
 import os
+import random
+import re
 import time
+import traceback
+from collections import OrderedDict
 
 import framework.utils as utils
+from framework.exception import VerifyFailure
+from framework.packet import Packet
+from framework.pktgen import PacketGeneratorHelper
+from framework.pmd_output import PmdOutput
+from framework.test_case import TestCase, check_supported_nic
+from framework.utils import GREEN, RED
+
+from .rte_flow_common import FdirProcessing as fdirprocess
+from .rte_flow_common import RssProcessing as rssprocess
 
 executions = []
-from framework.pktgen import PacketGeneratorHelper
-from framework.test_case import TestCase
 
 
 class TestMultiprocess(TestCase):
+
+    support_nic = ["ICE_100G-E810C_QSFP", "ICE_25G-E810C_SFP", "ICE_25G-E810_XXV_SFP"]
+
     def set_up_all(self):
         """
         Run at the start of each test suite.
@@ -58,6 +73,7 @@ class TestMultiprocess(TestCase):
         # self.verify('bsdapp' not in self.target, "Multiprocess not support freebsd")
 
         self.verify(len(self.dut.get_all_cores()) >= 4, "Not enough Cores")
+        self.pkt = Packet()
         self.dut_ports = self.dut.get_ports()
         self.socket = self.dut.get_numa_id(self.dut_ports[0])
         extra_option = "-Dexamples='multi_process/client_server_mp/mp_server,multi_process/client_server_mp/mp_client,multi_process/simple_mp,multi_process/symmetric_mp'"
@@ -90,6 +106,15 @@ class TestMultiprocess(TestCase):
             self.output_path = os.sep.join([cur_path, self.logger.log_path])
         # create an instance to set stream field setting
         self.pktgen_helper = PacketGeneratorHelper()
+        self.dport_info0 = self.dut.ports_info[self.dut_ports[0]]
+        self.pci0 = self.dport_info0["pci"]
+        self.tester_ifaces = [
+            self.tester.get_interface(self.dut.ports_map[port])
+            for port in self.dut_ports
+        ]
+        rxq = 1
+        self.session_list = []
+        self.logfmt = "*" * 20
 
     def set_up(self):
         """
@@ -97,6 +122,661 @@ class TestMultiprocess(TestCase):
         """
         pass
 
+    def launch_multi_testpmd(self, proc_type, queue_num, process_num, **kwargs):
+        self.session_list = [
+            self.dut.new_session("process_{}".format(i)) for i in range(process_num)
+        ]
+        self.pmd_output_list = [
+            PmdOutput(self.dut, self.session_list[i]) for i in range(process_num)
+        ]
+        self.dut.init_reserved_core()
+        proc_type_list = []
+        self.out_list = []
+        if isinstance(proc_type, list):
+            proc_type_list = copy.deepcopy(proc_type)
+            proc_type = proc_type_list[0]
+        for i in range(process_num):
+            cores = self.dut.get_reserved_core("2C", socket=0)
+            if i != 0 and proc_type_list:
+                proc_type = proc_type_list[1]
+            eal_param = "--proc-type={} -a {} --log-level=ice,7".format(
+                proc_type, self.pci0
+            )
+            param = "--rxq={0} --txq={0} --num-procs={1} --proc-id={2}".format(
+                queue_num, process_num, i
+            )
+            if kwargs.get("options") is not None:
+                param = "".join([param, kwargs.get("options")])
+            out = self.pmd_output_list[i].start_testpmd(
+                cores=cores,
+                eal_param=eal_param,
+                param=param,
+                timeout=kwargs.get("timeout", 20),
+            )
+            self.out_list.append(out)
+            self.pmd_output_list[i].execute_cmd("set fwd rxonly")
+            self.pmd_output_list[i].execute_cmd("set verbose 1")
+            self.pmd_output_list[i].execute_cmd("start")
+            self.pmd_output_list[i].execute_cmd("clear port stats all")
+
+    def get_pkt_statistic_process(self, out, **kwargs):
+        """
+        :param out: information received by testpmd process after sending packets and port statistics
+        :return: forward statistic dict, eg: {'rx-packets':1, 'tx-packets:0, 'tx-dropped':1}
+        """
+        p = re.compile(
+            r"Forward\s+Stats\s+for\s+RX\s+Port=\s+{}/Queue=([\s\d+]\d+)\s+.*\n.*RX-packets:\s+(\d+)\s+TX-packets:\s+(\d+)\s+TX-dropped:\s+(\d+)\s".format(
+                kwargs.get("port_id")
+            )
+        )
+        item_name = ["rx-packets", "tx-packets", "tx-dropped"]
+        statistic = p.findall(out)
+        if statistic:
+            rx_pkt_total, tx_pkt_total, tx_drop_total = 0, 0, 0
+            queue_set = set()
+            for item in statistic:
+                queue, rx_pkt, tx_pkt, tx_drop = map(int, item)
+                queue_set.add(queue)
+                rx_pkt_total += rx_pkt
+                tx_pkt_total += tx_pkt
+                tx_drop_total += tx_drop
+            static_dict = {
+                k: v
+                for k, v in zip(item_name, [rx_pkt_total, tx_pkt_total, tx_drop_total])
+            }
+            static_dict["queue"] = queue_set
+            return static_dict
+        else:
+            raise Exception("got wrong output, not match pattern {}".format(p.pattern))
+
+    def random_packet(self, pkt_num):
+        pkt = Packet()
+        pkt.generate_random_pkts(
+            pktnum=pkt_num,
+            dstmac="00:11:22:33:44:55",
+        )
+        pkt.send_pkt(crb=self.tester, tx_port=self.tester_ifaces[0], count=1)
+
+    def specify_packet(self, que_num):
+        # create rule to set queue as one of each process queues
+        rule_str = "flow create 0 ingress pattern eth / ipv4 src is 192.168.{0}.3  / end actions queue index {0} / end"
+        rules = [rule_str.format(i) for i in range(que_num)]
+        fdirprocess(
+            self, self.pmd_output_list[0], self.tester_ifaces, rxq=que_num
+        ).create_rule(rules)
+        # send 1 packet for each queue,the number of packets should be received by each process is (queue_num/proc_num)
+        pkt = Packet()
+        pkt_num = que_num
+        self.logger.info("packet num:{}".format(pkt_num))
+        packets = [
+            'Ether(dst="00:11:22:33:44:55") / IP(src="192.168.{0}.3", dst="192.168.0.21") / Raw("x" * 80)'.format(
+                i
+            )
+            for i in range(pkt_num)
+        ]
+        pkt.update_pkt(packets)
+        pkt.send_pkt(crb=self.tester, tx_port=self.tester_ifaces[0], count=1)
+
+    def _multiprocess_data_pass(self, case):
+        que_num, proc_num = case.get("queue_num"), case.get("proc_num")
+        pkt_num = case.setdefault("pkt_num", que_num)
+        step = int(que_num / proc_num)
+        proc_queue = [set(range(i, i + step)) for i in range(0, que_num, step)]
+        queue_dict = {
+            k: v
+            for k, v in zip(
+                ["process_{}".format(i) for i in range(que_num)], proc_queue
+            )
+        }
+        # start testpmd multi-process
+        self.launch_multi_testpmd(
+            proc_type=case.get("proc_type"), queue_num=que_num, process_num=proc_num
+        )
+        # send random or specify packets
+        packet_func = getattr(self, case.get("packet_type") + "_packet")
+        packet_func(pkt_num)
+        # get output for each process
+        process_static = {}
+        for i in range(len(self.pmd_output_list)):
+            out = self.pmd_output_list[i].execute_cmd("stop")
+            static = self.get_pkt_statistic_process(out, port_id=0)
+            process_static["process_{}".format(i)] = static
+        self.logger.info("process output static:{}".format(process_static))
+        # check whether each process receives packet, and ecah process receives packets with the corresponding queue
+        for k, v in process_static.items():
+            self.verify(
+                v.get("rx-packets") > 0,
+                "fail:process:{} does not receive packet".format(k),
+            )
+            self.verify(
+                v.get("queue").issubset(queue_dict.get(k)),
+                "fail: {} is not a subset of {}, "
+                "process should use its own queues".format(
+                    v.get("queue"), queue_dict.get(k)
+                ),
+            )
+        self.logger.info("pass:each process receives packets and uses its own queue")
+        # check whether the sum of packets received by all processes is equal to the number of packets sent
+        received_pkts = sum(
+            int(v.get("rx-packets", 0)) for v in process_static.values()
+        )
+        self.verify(
+            received_pkts == pkt_num,
+            "the number of packets received is not equal to packets sent,"
+            "send packet:{}, received packet:{}".format(pkt_num, received_pkts),
+        )
+        self.logger.info(
+            "pass:the number of packets received is {}, equal to packets sent".format(
+                received_pkts
+            )
+        )
+
+    def check_rss(self, out, **kwargs):
+        """
+        check whether the packet directed by rss or not according to the specified parameters
+        :param out: information received by testpmd after sending packets and port statistics
+        :param kwargs: some specified parameters, such as: rxq, stats
+        :return: queue value list
+        usage:
+            check_rss(out, rxq=rxq, stats=stats)
+        """
+        self.logger.info("{0} check rss {0}".format(self.logfmt))
+        rxq = kwargs.get("rxq")
+        p = re.compile("RSS\shash=(\w+)\s-\sRSS\squeue=(\w+)")
+        pkt_info = p.findall(out)
+        self.verify(
+            pkt_info,
+            "no information matching the pattern was found,pattern:{}".format(
+                p.pattern
+            ),
+        )
+        pkt_queue = set([int(i[1], 16) for i in pkt_info])
+        if kwargs.get("stats"):
+            self.verify(
+                all([int(i[0], 16) % rxq == int(i[1], 16) for i in pkt_info]),
+                "some pkt not directed by rss.",
+            )
+            self.logger.info((GREEN("pass: all pkts directed by rss")))
+        else:
+            self.verify(
+                not any([int(i[0], 16) % rxq == int(i[1], 16) for i in pkt_info]),
+                "some pkt directed by rss, expect not directed by rss",
+            )
+            self.logger.info((GREEN("pass: no pkt directed by rss")))
+        return pkt_queue
+
+    def check_queue(self, out, check_param, **kwargs):
+        """
+        verify that queue value matches the expected value
+        :param out: information received by testpmd after sending packets and port statistics
+        :param check_param: check item name and value, eg
+                            "check_param": {"port_id": 0, "queue": 2}
+        :param kwargs: some specified parameters, such as: pkt_num, port_id, stats
+        :return:
+        """
+        self.logger.info("{0} check queue {0}".format(self.logfmt))
+        queue = check_param["queue"]
+        if isinstance(check_param["queue"], int):
+            queue = [queue]
+        patt = re.compile(
+            r"port\s+{}/queue(.+?):\s+received\s+(\d+)\s+packets".format(
+                kwargs.get("port_id")
+            )
+        )
+        res = patt.findall(out)
+        if res:
+            pkt_queue = set([int(i[0]) for i in res])
+            if kwargs.get("stats"):
+                self.verify(
+                    all(q in queue for q in pkt_queue),
+                    "fail: queue id not matched, expect queue {}, got {}".format(
+                        queue, pkt_queue
+                    ),
+                )
+                self.logger.info((GREEN("pass: queue id {} matched".format(pkt_queue))))
+            else:
+                try:
+                    self.verify(
+                        not any(q in queue for q in pkt_queue),
+                        "fail: queue id should not matched, {} should not in {}".format(
+                            pkt_queue, queue
+                        ),
+                    )
+                    self.logger.info(
+                        (GREEN("pass: queue id {} not matched".format(pkt_queue)))
+                    )
+                except VerifyFailure:
+                    self.logger.info(
+                        "queue id {} contains the queue {} specified in rule, so need to check"
+                        " whether the packet directed by rss or not".format(
+                            pkt_queue, queue
+                        )
+                    )
+                    # for mismatch packet the 'stats' parameter is False, need to change to True
+                    kwargs["stats"] = True
+                    self.check_rss(out, **kwargs)
+
+        else:
+            raise Exception("got wrong output, not match pattern")
+
+    def check_mark_id(self, out, check_param, **kwargs):
+        """
+        verify that the mark ID matches the expected value
+        :param out: information received by testpmd after sending packets
+        :param check_param: check item name and value, eg
+                            "check_param": {"port_id": 0, "mark_id": 1}
+        :param kwargs: some specified parameters,eg: stats
+        :return: None
+        usage:
+            check_mark_id(out, check_param, stats=stats)
+        """
+        self.logger.info("{0} check mark id {0}".format(self.logfmt))
+        fdir_scanner = re.compile("FDIR matched ID=(0x\w+)")
+        all_mark = fdir_scanner.findall(out)
+        stats = kwargs.get("stats")
+        if stats:
+            mark_list = set(int(i, 16) for i in all_mark)
+            self.verify(
+                all([i == check_param["mark_id"] for i in mark_list]) and mark_list,
+                "failed: some packet mark id of {} not match expect {}".format(
+                    mark_list, check_param["mark_id"]
+                ),
+            )
+            self.logger.info((GREEN("pass: all packets mark id are matched ")))
+        else:
+            # for mismatch packet,verify no mark id in output of received packet
+            self.verify(
+                not all_mark, "mark id {} in output, expect no mark id".format(all_mark)
+            )
+            self.logger.info((GREEN("pass: no mark id in output")))
+
+    def check_drop(self, out, **kwargs):
+        """
+        check the drop number of packets according to the specified parameters
+        :param out: information received by testpmd after sending packets and port statistics
+        :param kwargs: some specified parameters, such as: pkt_num, port_id, stats
+        :return: None
+        usage:
+            chek_drop(out, pkt_num=pkt_num, port_id=portid, stats=stats)
+        """
+        self.logger.info("{0} check drop {0}".format(self.logfmt))
+        pkt_num = kwargs.get("pkt_num")
+        stats = kwargs.get("stats")
+        res = self.get_pkt_statistic(out, **kwargs)
+        self.verify(
+            pkt_num == res["rx-total"],
+            "failed: get wrong amount of packet {}, expected {}".format(
+                res["rx-total"], pkt_num
+            ),
+        )
+        drop_packet_num = res["rx-dropped"]
+        if stats:
+            self.verify(
+                drop_packet_num == pkt_num,
+                "failed: {} packet dropped,expect {} dropped".format(
+                    drop_packet_num, pkt_num
+                ),
+            )
+            self.logger.info(
+                (
+                    GREEN(
+                        "pass: drop packet number {} is matched".format(drop_packet_num)
+                    )
+                )
+            )
+        else:
+            self.verify(
+                drop_packet_num == 0 and res["rx-packets"] == pkt_num,
+                "failed: {} packet dropped, expect 0 packet dropped".format(
+                    drop_packet_num
+                ),
+            )
+            self.logger.info(
+                (
+                    GREEN(
+                        "pass: drop packet number {} is matched".format(drop_packet_num)
+                    )
+                )
+            )
+
+    @staticmethod
+    def get_pkt_statistic(out, **kwargs):
+        """
+        :param out: information received by testpmd after sending packets and port statistics
+        :return: rx statistic dict, eg: {'rx-packets':1, 'rx-dropped':0, 'rx-total':1}
+        """
+        p = re.compile(
+            r"Forward\sstatistics\s+for\s+port\s+{}\s+.*\n.*RX-packets:\s(\d+)\s+RX-dropped:\s(\d+)\s+RX-total:\s(\d+)\s".format(
+                kwargs.get("port_id")
+            )
+        )
+        item_name = ["rx-packets", "rx-dropped", "rx-total"]
+        statistic = p.findall(out)
+        if statistic:
+            static_dict = {
+                k: v for k, v in zip(item_name, list(map(int, list(statistic[0]))))
+            }
+            return static_dict
+        else:
+            raise Exception(
+                "got wrong output, not match pattern {}".format(p.pattern).replace(
+                    "\\\\", "\\"
+                )
+            )
+
+    def send_pkt_get_output(
+        self, instance_obj, pkts, port_id=0, count=1, interval=0, get_stats=False
+    ):
+        instance_obj.pmd_output.execute_cmd("clear port stats all")
+        tx_port = self.tester_ifaces[port_id]
+        self.logger.info("----------send packet-------------")
+        self.logger.info("{}".format(pkts))
+        if not isinstance(pkts, list):
+            pkts = [pkts]
+        self.pkt.update_pkt(pkts)
+        self.pkt.send_pkt(
+            crb=self.tester,
+            tx_port=tx_port,
+            count=count,
+            interval=interval,
+        )
+        out1 = instance_obj.pmd_output.get_output(timeout=1)
+        if get_stats:
+            out2 = instance_obj.pmd_output.execute_cmd("show port stats all")
+            instance_obj.pmd_output.execute_cmd("stop")
+        else:
+            out2 = instance_obj.pmd_output.execute_cmd("stop")
+        instance_obj.pmd_output.execute_cmd("start")
+        return "".join([out1, out2])
+
+    def check_pkt_num(self, out, **kwargs):
+        """
+        check number of received packets matches the expected value
+        :param out: information received by testpmd after sending packets and port statistics
+        :param kwargs: some specified parameters, such as: pkt_num, port_id
+        :return: rx statistic dict
+        """
+        self.logger.info(
+            "{0} check pkt num for port:{1} {0}".format(
+                self.logfmt, kwargs.get("port_id")
+            )
+        )
+        pkt_num = kwargs.get("pkt_num")
+        res = self.get_pkt_statistic(out, **kwargs)
+        res_num = res["rx-total"]
+        self.verify(
+            res_num == pkt_num,
+            "fail: got wrong number of packets, expect pakcet number {}, got {}".format(
+                pkt_num, res_num
+            ),
+        )
+        self.logger.info(
+            (GREEN("pass: pkt num is {} same as expected".format(pkt_num)))
+        )
+        return res
+
+    def check_with_param(self, out, pkt_num, check_param, stats=True):
+        """
+        according to the key and value of the check parameter,
+        perform the corresponding verification in the out information
+        :param out: information received by testpmd after sending packets and port statistics
+        :param pkt_num: number of packets sent
+        :param check_param: check item name and value, eg:
+                            "check_param": {"port_id": 0, "mark_id": 1, "queue": 1}
+                            "check_param": {"port_id": 0, "drop": 1}
+        :param stats: effective status of rule, True or False, default is True
+        :return:
+        usage:
+            check_with_param(out, pkt_num, check_param, stats)
+            check_with_param(out, pkt_num, check_param=check_param)
+        """
+        rxq = check_param.get("rxq")
+        port_id = (
+            check_param["port_id"] if check_param.get("port_id") is not None else 0
+        )
+        match_flag = True
+        """
+        check_dict shows the supported check items,the key is item name and value represent the check priority,
+        the smaller the value, the higher the priority, priority default value is 999. if need to add new check item,
+        please add it to the dict and implement the corresponding method and named as 'check_itemname',eg: check_queue
+        """
+        self.matched_queue = []
+        default_pri = 999
+        check_dict = {
+            "queue": default_pri,
+            "drop": default_pri,
+            "mark_id": 1,
+            "rss": default_pri,
+        }
+        params = {"port_id": port_id, "rxq": rxq, "pkt_num": pkt_num, "stats": stats}
+        # sort check_param order by priority, from high to low, set priority as 999 if key not in check_dict
+        check_param = OrderedDict(
+            sorted(
+                check_param.items(),
+                key=lambda item: check_dict.get(item[0], default_pri),
+            )
+        )
+        if not check_param.get("drop"):
+            self.check_pkt_num(out, **params)
+        for k in check_param:
+            parameter = copy.deepcopy(params)
+            if k not in check_dict:
+                continue
+            func_name = "check_{}".format(k)
+            try:
+                func = getattr(self, func_name)
+            except AttributeError:
+                emsg = "{},this func is not implemented, please check!".format(
+                    traceback.format_exc()
+                )
+                raise Exception(emsg)
+            else:
+                # for mismatch packet, if the check item is 'rss',should also verify the packets are distributed by rss
+                if k == "rss" and not stats:
+                    parameter["stats"] = True
+                    match_flag = False
+                res = func(out=out, check_param=check_param, **parameter)
+                if k == "rss" and match_flag:
+                    self.matched_queue.append(res)
+
+    def destroy_rule(self, instance_obj, port_id=0, rule_id=None):
+        rule_id = 0 if rule_id is None else rule_id
+        if not isinstance(rule_id, list):
+            rule_id = [rule_id]
+        for i in rule_id:
+            out = instance_obj.pmd_output.execute_cmd(
+                "flow destroy {} rule {}".format(port_id, i)
+            )
+            p = re.compile(r"Flow rule #(\d+) destroyed")
+            m = p.search(out)
+            self.verify(m, "flow rule {} delete failed".format(rule_id))
+
+    def multiprocess_flow_data(self, case, **pmd_param):
+        que_num, proc_num = pmd_param.get("queue_num"), pmd_param.get("proc_num")
+        # start testpmd multi-process
+        self.launch_multi_testpmd(
+            proc_type=pmd_param.get("proc_type"),
+            queue_num=que_num,
+            process_num=proc_num,
+        )
+        self.pmd_output_list[0].execute_cmd("flow flush 0")
+        check_param = case["check_param"]
+        check_param["rxq"] = pmd_param.get("queue_num")
+        if check_param.get("rss"):
+            [pmd.execute_cmd("port config all rss all") for pmd in self.pmd_output_list]
+        fdir_pro = fdirprocess(
+            self,
+            self.pmd_output_list[0],
+            self.tester_ifaces,
+            rxq=pmd_param.get("queue_num"),
+        )
+        fdir_pro.create_rule(case.get("rule"))
+        # send match and mismatch packet
+        packets = [case.get("packet")["match"], case.get("packet")["mismatch"]]
+        for i in range(2):
+            out1 = self.send_pkt_get_output(fdir_pro, packets[i])
+            patt = re.compile(
+                r"port\s+{}/queue(.+?):\s+received\s+(\d+)\s+packets".format(
+                    check_param.get("port_id")
+                )
+            )
+            if patt.findall(out1) and check_param.get("rss"):
+                self.logger.info(
+                    "check whether the packets received by the primary process are distributed by RSS"
+                )
+                self.check_rss(out1, stats=True, **check_param)
+            for proc_pmd in self.pmd_output_list[1:]:
+                out2 = proc_pmd.get_output(timeout=1)
+                out3 = proc_pmd.execute_cmd("stop")
+                out1 = "".join([out1, out2, out3])
+                proc_pmd.execute_cmd("start")
+                if patt.findall(out2) and check_param.get("rss"):
+                    self.logger.info(
+                        "check whether the packets received by the secondary process are distributed by RSS"
+                    )
+                    self.check_rss(out2, stats=True, **check_param)
+            pkt_num = len(packets[i])
+            self.check_with_param(
+                out1,
+                pkt_num=pkt_num,
+                check_param=check_param,
+                stats=True if i == 0 else False,
+            )
+
+    def _handle_test(self, tests, instance_obj, port_id=0):
+        instance_obj.pmd_output.wait_link_status_up(port_id)
+        for test in tests:
+            if "send_packet" in test:
+                out = self.send_pkt_get_output(
+                    instance_obj, test["send_packet"], port_id
+                )
+                for proc_pmd in self.pmd_output_list[1:]:
+                    out1 = proc_pmd.get_output(timeout=1)
+                    out = "".join([out, out1])
+            if "action" in test:
+                instance_obj.handle_actions(out, test["action"])
+
+    def multiprocess_rss_data(self, case, **pmd_param):
+        que_num, proc_num = pmd_param.get("queue_num"), pmd_param.get("proc_num")
+        # start testpmd multi-process
+        self.launch_multi_testpmd(
+            proc_type=pmd_param.get("proc_type"),
+            queue_num=que_num,
+            process_num=proc_num,
+            options=pmd_param.get("options", None),
+        )
+        self.pmd_output_list[0].execute_cmd("flow flush 0")
+        rss_pro = rssprocess(
+            self,
+            self.pmd_output_list[0],
+            self.tester_ifaces,
+            rxq=pmd_param.get("queue_num"),
+        )
+        rss_pro.error_msgs = []
+        # handle tests
+        tests = case["test"]
+        port_id = case["port_id"]
+        self.logger.info("------------handle test--------------")
+        # validate rule
+        rule = case.get("rule", None)
+        if rule:
+            rss_pro.validate_rule(rule=rule)
+            rule_ids = rss_pro.create_rule(rule=rule)
+            rss_pro.check_rule(rule_list=rule_ids)
+        self._handle_test(tests, rss_pro, port_id)
+        # handle post-test
+        if "post-test" in case:
+            self.logger.info("------------handle post-test--------------")
+            self.destroy_rule(rss_pro, port_id=port_id, rule_id=rule_ids)
+            rss_pro.check_rule(port_id=port_id, stats=False)
+            self._handle_test(case["post-test"], rss_pro, port_id)
+        if rss_pro.error_msgs:
+            self.verify(
+                False,
+                " ".join([errs.replace("'", " ") for errs in rss_pro.error_msgs[:500]]),
+            )
+
+    def rte_flow(self, case_list, func_name, **kwargs):
+        """
+        main flow of case:
+            1. iterate the case list and do the below steps:
+                a. get the subcase name and init dict to save result
+                b. call method by func name to execute case step
+                c. record case result and err msg if case failed
+                d. clear flow rule
+            2. calculate the case passing rate according to the result dict
+            3. record case result and pass rate in the case log file
+            4. verify whether the case pass rate is equal to 100, if not, mark the case as failed and raise the err msg
+        :param case_list: case list, each item is a subcase of case
+        :param func_name: hadle case method name, eg:
+                        'flow_rule_operate': a method of 'FlowRuleProcessing' class,
+                        used to handle flow rule related suites,such as fdir and switch_filter
+                        'handle_rss_distribute_cases': a method of 'RssProcessing' class,
+                        used to handle rss related suites
+        :return:
+        usage:
+        for flow rule related:
+            rte_flow(caselist, flow_rule_operate)
+        for rss related:
+            rte_flow(caselist, handle_rss_distribute_cases)
+        """
+        if not isinstance(case_list, list):
+            case_list = [case_list]
+        test_results = dict()
+        for case in case_list:
+            case_name = case.get("sub_casename")
+            test_results[case_name] = {}
+            try:
+                self.logger.info("{0} case_name:{1} {0}".format("*" * 20, case_name))
+                func_name(case, **kwargs)
+            except Exception:
+                test_results[case_name]["result"] = "failed"
+                test_results[case_name]["err"] = re.sub(
+                    r"['\r\n]", "", str(traceback.format_exc(limit=1))
+                ).replace("\\\\", "\\")
+                self.logger.info(
+                    (
+                        RED(
+                            "case failed:{}, err:{}".format(
+                                case_name, traceback.format_exc()
+                            )
+                        )
+                    )
+                )
+            else:
+                test_results[case_name]["result"] = "passed"
+                self.logger.info((GREEN("case passed: {}".format(case_name))))
+            finally:
+                self.session_list[0].send_command("flow flush 0", timeout=1)
+                for sess in self.session_list:
+                    self.dut.close_session(sess)
+        pass_rate = (
+            round(
+                sum(1 for k in test_results if "passed" in test_results[k]["result"])
+                / len(test_results),
+                4,
+            )
+            * 100
+        )
+        self.logger.info(
+            [
+                "{}:{}".format(sub_name, test_results[sub_name]["result"])
+                for sub_name in test_results
+            ]
+        )
+        self.logger.info("pass rate is: {}".format(pass_rate))
+        msg = [
+            "subcase_name:{}:{},err:{}".format(
+                name, test_results[name].get("result"), test_results[name].get("err")
+            )
+            for name in test_results.keys()
+            if "failed" in test_results[name]["result"]
+        ]
+        self.verify(
+            int(pass_rate) == 100,
+            "some subcases failed, detail as below:{}".format(msg),
+        )
+
     def test_multiprocess_simple_mpbasicoperation(self):
         """
         Basic operation.
@@ -274,6 +954,761 @@ class TestMultiprocess(TestCase):
 
         self.session_secondary.send_expect("quit", "# ")
 
+    def test_multiprocess_symmetric_mp_packet(self):
+        # run multiple symmetric_mp process
+        portMask = utils.create_mask(self.dut_ports)
+        # launch symmetric_mp, process num is 2
+        proc_num = 2
+        session_list = [
+            self.dut.new_session("process_{}".format(i)) for i in range(proc_num)
+        ]
+        for i in range(proc_num):
+            session_list[i].send_expect(
+                self.app_symmetric_mp
+                + " -l {} -n 4 --proc-type=auto {} -- -p {} --num-procs={} --proc-id={}".format(
+                    i + 1, self.eal_param, portMask, proc_num, i
+                ),
+                "Finished Process Init",
+            )
+        # send packets
+        packet_num = random.randint(20, 256)
+        self.logger.info("packet num:{}".format(packet_num))
+        self.random_packet(packet_num)
+        res = []
+        for session_obj in session_list:
+            try:
+                out = session_obj.send_command("^C")
+            except Exception as e:
+                self.logger.err("Error occured:{}".format(traceback.format_exc(e)))
+            finally:
+                session_obj.close()
+            rx_num = re.search(r"Port 0: RX - (?P<RX>\d+)", out)
+            rx_nums = int(rx_num.group("RX"))
+            self.verify(
+                rx_nums > 0,
+                "fail: {} received packets shoud greater than 0, actual is {}".format(
+                    session_obj.name, rx_nums
+                ),
+            )
+            res.append(rx_nums)
+        rx_total = sum(res)
+        self.logger.info("RX total:{}, send packet:{}".format(rx_total, packet_num))
+        self.verify(
+            rx_total >= packet_num,
+            "some packet not received by symmetric_mp, "
+            "number of RX total should greater than or equal to send packet",
+        )
+
+    def test_multiprocess_server_client_mp_packet(self):
+        # run multiple client_server_mp process
+        portMask = utils.create_mask(self.dut_ports)
+        # launch client_server_mp, client process num is 2
+        proc_num = 2
+        session_list = [
+            self.dut.new_session("process_{}".format(i)) for i in range(proc_num + 1)
+        ]
+        server_session = session_list[-1]
+        # start server
+        server_session.send_expect(
+            self.app_mp_server
+            + " -l 1,2 -n 4 -- -p {} -n {}".format(portMask, proc_num),
+            "Finished Process Init",
+        )
+        # start client
+        for i in range(proc_num):
+            self.dut.init_reserved_core()
+            session_list[i].send_expect(
+                self.app_mp_client
+                + " -l {} -n 4 --proc-type=auto -- -n {}".format(i + 3, i),
+                "Finished Process Init",
+            )
+        # send packets
+        packet_num = random.randint(20, 256)
+        self.logger.info("packet num:{}".format(packet_num))
+        self.random_packet(packet_num)
+        out = server_session.get_session_before(timeout=5)
+        for session_obj in session_list:
+            try:
+                session_obj.send_command("^C")
+            except Exception as e:
+                self.logger.err("Error occured:{}".format(traceback.format_exc(e)))
+            finally:
+                session_obj.close()
+        res = re.search(
+            r"Port \d+\s+-\s+rx:\s+(?P<rx>\d+)\s+tx:.*PORTS", out, re.DOTALL
+        )
+        rx_num = re.findall(r"Client\s+\d\s+-\s+rx:\s+(\d+)", res.group(0))
+        for i in range(proc_num):
+            self.verify(
+                int(rx_num[i]) > 0,
+                "fail: client_{} received packets shoud greater than 0, "
+                "actual is {}".format(i, int(rx_num[i])),
+            )
+        rx_total = sum(int(rx) for rx in rx_num)
+        self.logger.info("rx total:{}, send packet:{}".format(rx_total, packet_num))
+        self.verify(
+            rx_total >= packet_num,
+            "some packet not received by server_client process,"
+            "number of RX total should greater than or equal to send packet.",
+        )
+
+    # test testpmd multi-process
+    @check_supported_nic(support_nic)
+    def test_multiprocess_auto_process_type_detected(self):
+        # start 2 process
+        self.launch_multi_testpmd("auto", 8, 2)
+        # get output of each process and check the detected process type is correctly
+        process_type = ["PRIMARY", "SECONDARY"]
+        for i in range(2):
+            self.verify(
+                "Auto-detected process type: {}".format(process_type[i])
+                in self.out_list[i],
+                "the process type is not correctly, expect {}".format(process_type[i]),
+            )
+            self.logger.info(
+                "pass: Auto-detected {} process type correctly".format(process_type[i])
+            )
+
+    @check_supported_nic(support_nic)
+    def test_multiprocess_negative_2_primary_process(self):
+        # start 2 primary process
+        try:
+            self.launch_multi_testpmd(["primary", "primary"], 8, 2, timeout=10)
+        except Exception as e:
+            # check second process start failed
+            self.verify(
+                "Is another primary process running?" in e.output,
+                "fail: More than one primary process was started, only one should be started!",
+            )
+            self.logger.info(
+                "pass: only one primary process start successfully, match the expect"
+            )
+            return
+        self.verify(False, "fail: 2 primary process launch succeed, expect launch fail")
+
+    @check_supported_nic(support_nic)
+    def test_multiprocess_negative_exceed_process_num(self):
+        """
+        If the specified number of processes is exceeded, starting the process will fail
+        """
+        # start 2 process
+        proc_type, queue_num, process_num = "auto", 8, 2
+        self.launch_multi_testpmd(proc_type, queue_num, process_num)
+        # start a process with 'proc-id=2', should start failed
+        pmd_2 = PmdOutput(self.dut, self.dut.new_session("process_2"))
+        self.dut.init_reserved_core()
+        cores = self.dut.get_reserved_core("2C", socket=1)
+        eal_param = "--proc-type={} -a {} --log-level=ice,7".format("auto", self.pci0)
+        param = "--rxq={0} --txq={0} --num-procs={1} --proc-id={2}".format(
+            queue_num, process_num, 2
+        )
+        try:
+            pmd_2.start_testpmd(
+                cores=cores, eal_param=eal_param, param=param, timeout=10
+            )
+        except Exception as e:
+            p = re.compile(
+                r"The\s+multi-process\s+option\s+'proc-id\(\d+\)'\s+should\s+be\s+less\s+than\s+'num-procs\(\d+\)'"
+            )
+            res = p.search(e.output)
+            self.verify(
+                res,
+                "fail: 'multi-process proc-id should be less than num-process' should in output",
+            )
+            self.logger.info(
+                "pass: exceed the specified number, process launch failed as expected"
+            )
+            return
+        self.verify(
+            False,
+            "fail: exceed the specified number, process launch succeed, expect launch fail",
+        )
+
+    @check_supported_nic(support_nic)
+    def test_multiprocess_proc_type_random_packet(self):
+
+        case_list = [
+            {
+                "sub_casename": "proc_type_auto_4_process",
+                "queue_num": 16,
+                "proc_num": 4,
+                "proc_type": "auto",
+                "packet_type": "random",
+                "pkt_num": 30,
+            },
+            {
+                "sub_casename": "proc_type_primary_secondary_2_process",
+                "queue_num": 4,
+                "proc_num": 2,
+                "proc_type": ["primary", "secondary"],
+                "packet_type": "random",
+                "pkt_num": 20,
+            },
+        ]
+        self.rte_flow(case_list, self._multiprocess_data_pass)
+
+    @check_supported_nic(support_nic)
+    def test_multiprocess_proc_type_specify_packet(self):
+        case_list = [
+            {
+                "sub_casename": "proc_type_auto_2_process",
+                "queue_num": 8,
+                "proc_num": 2,
+                "proc_type": "auto",
+                "packet_type": "specify",
+            },
+            {
+                "sub_casename": "proc_type_primary_secondary_3_process",
+                "queue_num": 6,
+                "proc_num": 3,
+                "proc_type": ["primary", "secondary"],
+                "packet_type": "specify",
+            },
+        ]
+        self.rte_flow(case_list, self._multiprocess_data_pass)
+
+    @check_supported_nic(support_nic)
+    def test_multiprocess_with_fdir_rule(self):
+        pmd_param = {
+            "queue_num": 64,
+            "proc_num": 2,
+            "proc_type": "auto",
+        }
+        MAC_IPV4_PAY = {
+            "match": [
+                'Ether(dst="00:11:22:33:44:55")/IP(src="192.168.0.20",dst="192.168.0.21", proto=255, ttl=2, tos=4) / Raw("x" * 80)'
+            ],
+            "mismatch": [
+                'Ether(dst="00:11:22:33:44:55")/IP(src="192.168.0.20",dst="192.168.0.22", proto=255, ttl=2, tos=4) / Raw("x" * 80)',
+                'Ether(dst="00:11:22:33:44:55")/IP(src="192.168.0.22",dst="192.168.0.21", proto=255, ttl=2, tos=4) / Raw("x" * 80)',
+                'Ether(dst="00:11:22:33:44:55")/IP(src="192.168.0.20",dst="192.168.1.21", proto=255, ttl=2, tos=4) / Raw("x" * 80)',
+                'Ether(dst="00:11:22:33:44:55")/IP(src="192.168.0.20",dst="192.168.0.21", proto=1, ttl=2, tos=4) / Raw("x" * 80)',
+                'Ether(dst="00:11:22:33:44:55")/IP(src="192.168.0.20",dst="192.168.0.21", proto=255, ttl=3, tos=4) / Raw("x" * 80)',
+                'Ether(dst="00:11:22:33:44:55")/IP(src="192.168.0.20",dst="192.168.0.21", proto=255, ttl=2, tos=9) / Raw("x" * 80)',
+            ],
+        }
+        mac_ipv4_pay_queue_index = {
+            "sub_casename": "mac_ipv4_pay_queue_index",
+            "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions queue index 62 / mark id 4 / end",
+            "packet": MAC_IPV4_PAY,
+            "check_param": {"port_id": 0, "queue": 62, "mark_id": 4},
+        }
+        mac_ipv4_pay_drop = {
+            "sub_casename": "mac_ipv4_pay_drop",
+            "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions drop / mark / end",
+            "packet": MAC_IPV4_PAY,
+            "check_param": {"port_id": 0, "drop": True},
+        }
+        mac_ipv4_pay_rss_queues = {
+            "sub_casename": "mac_ipv4_pay_rss_queues",
+            "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions rss queues 31 32 end / mark / end",
+            "packet": MAC_IPV4_PAY,
+            "check_param": {"port_id": 0, "queue": [31, 32]},
+        }
+        mac_ipv4_pay_mark_rss = {
+            "sub_casename": "mac_ipv4_pay_mark_rss",
+            "rule": "flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions mark / rss / end",
+            "packet": MAC_IPV4_PAY,
+            "check_param": {"port_id": 0, "mark_id": 0, "rss": True},
+        }
+        case_list = [
+            mac_ipv4_pay_queue_index,
+            mac_ipv4_pay_drop,
+            mac_ipv4_pay_rss_queues,
+            mac_ipv4_pay_mark_rss,
+        ]
+        self.rte_flow(case_list, self.multiprocess_flow_data, **pmd_param)
+
+    @check_supported_nic(support_nic)
+    def test_multiprocess_with_rss_toeplitz(self):
+        pmd_param = {
+            "queue_num": 32,
+            "proc_num": 2,
+            "proc_type": "auto",
+            "options": " --disable-rss --rxd=384 --txd=384",
+        }
+        mac_ipv4_tcp_toeplitz_basic_pkt = {
+            "ipv4-tcp": [
+                'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+            ],
+        }
+        mac_ipv4_tcp_toeplitz_non_basic_pkt = [
+            'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/UDP(sport=22,dport=23)/("X"*480)',
+            'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IPv6(src="ABAB:910B:6666:3457:8295:3333:1800:2929",dst="CDCD:910A:2222:5498:8475:1111:3900:2020")/TCP(sport=22,dport=23)/Raw("x"*80)',
+        ]
+        mac_ipv4_tcp_l2_src = {
+            "sub_casename": "mac_ipv4_tcp_l2_src",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types eth l2-src-only end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.3", src="192.168.0.5")/TCP(sport=25,dport=99)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_l2_dst = {
+            "sub_casename": "mac_ipv4_tcp_l2_dst",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types eth l2-dst-only end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.3", src="192.168.0.5")/TCP(sport=25,dport=99)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_non_basic_pkt,
+                    "action": "check_no_hash",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_l2src_l2dst = {
+            "sub_casename": "mac_ipv4_tcp_l2src_l2dst",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types eth end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.3", src="192.168.0.5")/TCP(sport=25,dport=99)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_non_basic_pkt,
+                    "action": "check_no_hash",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_l3_src = {
+            "sub_casename": "mac_ipv4_tcp_l3_src",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-src-only end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=32,dport=33)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_l3_dst = {
+            "sub_casename": "mac_ipv4_tcp_l3_dst",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-dst-only end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=32,dport=33)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_l3src_l4src = {
+            "sub_casename": "mac_ipv4_tcp_l3src_l4src",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-src-only l4-src-only end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=32,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=33)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_l3src_l4dst = {
+            "sub_casename": "mac_ipv4_tcp_l3src_l4dst",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-src-only l4-dst-only end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=33)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=32,dport=23)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_l3dst_l4src = {
+            "sub_casename": "mac_ipv4_tcp_l3dst_l4src",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-dst-only l4-src-only end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=32,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=33)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_l3dst_l4dst = {
+            "sub_casename": "mac_ipv4_tcp_l3dst_l4dst",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-dst-only l4-dst-only end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=33)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=32,dport=23)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_l4_src = {
+            "sub_casename": "mac_ipv4_tcp_l4_src",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l4-src-only end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=32,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.1.1", src="192.168.1.2")/TCP(sport=22,dport=33)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_l4_dst = {
+            "sub_casename": "mac_ipv4_tcp_l4_dst",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l4-dst-only end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=33)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.1.1", src="192.168.1.2")/TCP(sport=32,dport=23)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_all = {
+            "sub_casename": "mac_ipv4_tcp_all",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=33)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=32,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+        mac_ipv4_tcp_ipv4 = {
+            "sub_casename": "mac_ipv4_tcp_ipv4",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4 end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"],
+                    "action": "save_hash",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_different",
+                },
+                {
+                    "send_packet": 'Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+                    "action": "check_hash_same",
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": [
+                        mac_ipv4_tcp_toeplitz_basic_pkt["ipv4-tcp"][0],
+                    ],
+                    "action": "check_no_hash",
+                },
+            ],
+        }
+
+        case_list = [
+            mac_ipv4_tcp_l2_src,
+            mac_ipv4_tcp_l2_dst,
+            mac_ipv4_tcp_l2src_l2dst,
+            mac_ipv4_tcp_l3_src,
+            mac_ipv4_tcp_l3_dst,
+            mac_ipv4_tcp_l3src_l4src,
+            mac_ipv4_tcp_l3src_l4dst,
+            mac_ipv4_tcp_l3dst_l4src,
+            mac_ipv4_tcp_l3dst_l4dst,
+            mac_ipv4_tcp_l4_src,
+            mac_ipv4_tcp_l4_dst,
+            mac_ipv4_tcp_all,
+            mac_ipv4_tcp_ipv4,
+        ]
+        self.rte_flow(case_list, self.multiprocess_rss_data, **pmd_param)
+
+    @check_supported_nic(support_nic)
+    def test_multiprocess_with_rss_symmetric(self):
+        pmd_param = {
+            "queue_num": 64,
+            "proc_num": 2,
+            "proc_type": "auto",
+        }
+        packets = [
+            'Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/("X"*480)',
+            'Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.2", src="192.168.0.1")/("X"*480)',
+            'Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="12.168.0.2")/TCP(sport=22,dport=23)/("X"*480)',
+            'Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.2", src="12.168.0.1")/TCP(sport=22,dport=23)/("X"*480)',
+        ]
+        mac_ipv4_symmetric = {
+            "sub_casename": "mac_ipv4_all",
+            "port_id": 0,
+            "rule": "flow create 0 ingress pattern eth / ipv4 / end actions rss func symmetric_toeplitz types ipv4 end key_len 0 queues end / end",
+            "test": [
+                {
+                    "send_packet": packets[0],
+                    "action": {"save_hash": "ipv4-nonfrag"},
+                },
+                {
+                    "send_packet": packets[1],
+                    "action": {"check_hash_same": "ipv4-nonfrag"},
+                },
+                {
+                    "send_packet": packets[2],
+                    "action": {"save_hash": "ipv4-tcp"},
+                },
+                {
+                    "send_packet": packets[3],
+                    "action": {"check_hash_same": "ipv4-tcp"},
+                },
+            ],
+            "post-test": [
+                {
+                    "send_packet": packets[0],
+                    "action": {"save_or_no_hash": "ipv4-nonfrag-post"},
+                },
+                {
+                    "send_packet": packets[1],
+                    "action": {"check_no_hash_or_different": "ipv4-nonfrag-post"},
+                },
+                {
+                    "send_packet": packets[2],
+                    "action": {"save_or_no_hash": "ipv4-tcp-post"},
+                },
+                {
+                    "send_packet": packets[3],
+                    "action": {"check_no_hash_or_different": "ipv4-tcp-post"},
+                },
+            ],
+        }
+        self.rte_flow(mac_ipv4_symmetric, self.multiprocess_rss_data, **pmd_param)
+
     def test_perf_multiprocess_performance(self):
         """
         Benchmark Multiprocess performance.
@@ -499,8 +1934,10 @@ class TestMultiprocess(TestCase):
         """
         Run after each test case.
         """
+        if self.session_list:
+            for sess in self.session_list:
+                self.dut.close_session(sess)
         self.dut.kill_all()
-        pass
 
     def tear_down_all(self):
         """
-- 
2.17.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [dts] [PATCH V4 2/2] test_plans/multiprocess: add pf multiprocess test case
  2022-05-19  7:48 [dts] [PATCH V4 1/2] tests/multiprocess: add pf multiprocess test case Jiale Song
@ 2022-05-19  7:48 ` Jiale Song
  2022-05-19  8:22   ` Peng, Yuan
  2022-05-25 10:14   ` lijuan.tu
  0 siblings, 2 replies; 4+ messages in thread
From: Jiale Song @ 2022-05-19  7:48 UTC (permalink / raw)
  To: dts; +Cc: Jiale Song

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 34397 bytes --]

pf have no data transmission case.
so add 10 cases in pf multiprocess test suite.

Signed-off-by: Jiale Song <songx.jiale@intel.com>
---
 test_plans/multiprocess_test_plan.rst | 665 ++++++++++++++++++++++++++
 1 file changed, 665 insertions(+)

diff --git a/test_plans/multiprocess_test_plan.rst b/test_plans/multiprocess_test_plan.rst
index efb7fe05..bbd7899e 100644
--- a/test_plans/multiprocess_test_plan.rst
+++ b/test_plans/multiprocess_test_plan.rst
@@ -247,6 +247,23 @@ among RX queues. Record traffic throughput results as below.
 | Packet Rate(mpps) |  X  |  X  |  X  |  X  |  X  |  X  |
 +-------------------+-----+-----+-----+-----+-----+-----+
 
+Test Case: Function Tests
+-------------------------
+start 2 symmetric_mp process, send some packets, the number of packets is a random value between 20 and 256.
+summarize all received packets and check whether it is bigger than or equal to the number of sent packets
+
+1. start 2 process::
+
+    /dpdk-symmetric_mp  -l 1 -n 4 --proc-type=auto  -a 0000:05:00.0 -a 0000:08:00.0 -- -p 0x3 --num-procs=2 --proc-id=0
+    /dpdk-symmetric_mp  -l 2 -n 4 --proc-type=auto  -a 0000:05:00.0 -a 0000:08:00.0 -- -p 0x3 --num-procs=2 --proc-id=1
+
+2. send some packets,the number of packets is a random value between 20 and 256, packet type including IPV6/4,TCP/UDP,
+   refer to Random_Packet
+
+3. stop all process and check output::
+
+    the number of received packets for each process should bigger than 0.
+    summarize all received packets for all process should bigger than or equal to the number of sent packets
 
 Client Server Multiprocess Tests
 ================================
@@ -333,3 +350,651 @@ An example set of results is shown below.
 +----------------------+-----+-----+-----+-----+-----+-----+
 | Packet Rate(mpps)    |  X  |  X  |  X  |  X  |  X  |  X  |
 +----------------------+-----+-----+-----+-----+-----+-----+
+
+Test Case: Function Tests
+-------------------------
+start server process and 2 client process, send some packets, the number of packets is a random value between 20 and 256.
+summarize all received packets and check whether it is bigger than or equal to the number of sent packets
+
+1. start server process::
+
+    ./dpdk-mp_server  -l 1,2 -n 4 -- -p 0x3 -n 2
+
+2. start 2 client process::
+
+    ./dpdk-mp_client  -l 3 -n 4 --proc-type=auto -- -n 0
+    ./dpdk-mp_client  -l 4 -n 4 --proc-type=auto -- -n 1
+
+3. send some packets,the number of packets is a random value between 20 and 256, packet type include IPV6/4,TCP/UDP,
+   refer to Random_Packet
+
+4. stop all process and check output::
+
+    the number of received packets for each client should bigger than 0.
+    summarize all received packets for all clients should bigger than or equal to the number of sent packets
+
+Testpmd Multi-Process Test
+==========================
+
+Description
+-----------
+
+This is a multi-process test for Testpmd application, which demonstrates how multiple processes can
+work together to perform packet in parallel.
+
+Test Methodology
+----------------
+Testpmd support to specify total number of processes and current process ID.
+Each process owns subset of Rx and Tx queues
+The following are the command-line options for testpmd multi-process support::
+
+   primary process:
+   ./dpdk-testpmd -a xxx --proc-type=auto -l 0-1 -- -i --rxq=4 --txq=4 --num-procs=2 --proc-id=0
+
+   secondary process:
+   ./dpdk-testpmd -a xxx --proc-type=auto -l 2-3 -- -i --rxq=4 --txq=4 --num-procs=2 --proc-id=1
+
+   --num-procs:
+      The number of processes which will be used
+   --proc-id:
+      The ID of the current process (ID < num-procs),ID should be different in primary process and secondary
+      process, which starts from ‘0’.
+
+All queues are allocated to different processes based on proc_num and proc_id
+Calculation rule for queue::
+
+   start(queue start id) = proc_id * nb_q / num_procs
+   end(queue end id) = start + nb_q / num_procs
+
+For example, if testpmd is configured to have 4 Tx and Rx queues, queues 0 and 1 will be used by the primary process and
+queues 2 and 3 will be used by the secondary process.
+
+Note::
+
+   nb_q is the number of queues
+   The number of queues should be a multiple of the number of processes. If not, redundant queues will exist after
+   queues are allocated to processes. If RSS is enabled, packet loss occurs when traffic is sent to all processes at the
+   same time.Some traffic goes to redundant queues and cannot be forwarded.
+   All the dev ops is supported in primary process. While secondary process is not permitted to allocate or release
+   shared memory.
+   When secondary is running, port in primary is not permitted to be stopped.
+   Reconfigure operation is only valid in primary.
+   Stats is supported, stats will not change when one quits and starts, as they share the same buffer to store the stats.
+   Flow rules are maintained in process level:
+      primary and secondary has its own flow list (but one flow list in HW). The two can see all the queues, so setting
+      the flow rules for the other is OK. But in the testpmd primary process receiving or transmitting packets from the
+      queue allocated for secondary process is not permitted, and same for secondary process
+
+   Flow API and RSS are supported
+
+Prerequisites
+-------------
+
+1. Hardware:
+   columbiaville_25g/columbiaville_100g
+
+2. Software:
+   DPDK: http://dpdk.org/git/dpdk
+   scapy: http://www.secdev.org/projects/scapy/
+
+3. Copy specific ice package to /lib/firmware/intel/ice/ddp/ice.pkg
+
+4. Bind the pf to dpdk driver::
+
+    ./usertools/dpdk-devbind.py -b vfio-pci 05:00.0
+
+Default parameters
+------------------
+
+   MAC::
+
+    [Dest MAC]: 00:11:22:33:44:55
+
+   IPv4::
+
+    [Source IP]: 192.168.0.20
+    [Dest IP]: 192.168.0.21
+    [IP protocol]: 255
+    [TTL]: 2
+    [DSCP]: 4
+
+   TCP::
+
+    [Source Port]: 22
+    [Dest Port]: 23
+
+   Random_Packet::
+
+      Ether(dst='00:11:22:33:44:55', src='00:00:20:00:00:00')/IPv6(src='::192.168.0.1', version=6, tc=0, fl=0, dst='::192.168.1.1', hlim=64)/TCP(sport=65535, dport=65535, flags=0)/Raw(),
+      Ether(dst='00:11:22:33:44:55', src='00:00:20:00:00:00')/IP(frag=0, src='192.168.0.1', tos=0, dst='192.168.1.2', version=4, ttl=64, id=1)/UDP(sport=65535, dport=65535)/Raw(),
+      Ether(dst='00:11:22:33:44:55', src='00:00:20:00:00:00')/IPv6(src='::192.168.0.1', version=6, tc=0, fl=0, dst='::192.168.1.3', hlim=64)/UDP(sport=65535, dport=65535)/Raw(),
+      Ether(dst='00:11:22:33:44:55', src='00:00:20:00:00:00')/IPv6(src='::192.168.0.1', version=6, tc=0, fl=0, dst='::192.168.1.4', hlim=64)/UDP(sport=65535, dport=65535)/Raw(),
+      Ether(dst='00:11:22:33:44:55', src='00:00:20:00:00:00')/IPv6(src='::192.168.0.1', version=6, tc=0, fl=0, dst='::192.168.1.5', hlim=64)/TCP(sport=65535, dport=65535, flags=0)/Raw(),
+      Ether(dst='00:11:22:33:44:55', src='00:00:20:00:00:00')/IP(frag=0, src='192.168.0.1', tos=0, dst='192.168.1.15', version=4, ttl=64, id=1)/UDP(sport=65535, dport=65535)/Raw(),
+      Ether(dst='00:11:22:33:44:55', src='00:00:20:00:00:00')/IPv6(src='::192.168.0.1', version=6, tc=0, fl=0, dst='::192.168.1.16', hlim=64)/TCP(sport=65535, dport=65535, flags=0)/Raw(),
+      Ether(dst='00:11:22:33:44:55', src='00:00:20:00:00:00')/IPv6(src='::192.168.0.1', version=6, tc=0, fl=0, dst='::192.168.1.27', hlim=64)/TCP(sport=65535, dport=65535, flags=0)/Raw(),
+      Ether(dst='00:11:22:33:44:55', src='00:00:20:00:00:00')/IP(frag=0, src='192.168.0.1', tos=0, dst='192.168.1.28', version=4, ttl=64, id=1)/TCP(sport=65535, dport=65535, flags=0)/Raw(),
+      Ether(dst='00:11:22:33:44:55', src='00:00:20:00:00:00')/IPv6(src='::192.168.0.1', version=6, tc=0, fl=0, dst='::192.168.1.30', hlim=64)/TCP(sport=65535, dport=65535, flags=0)/Raw()
+
+Test Case: multiprocess proc_type random packet
+===============================================
+
+Subcase 1: proc_type_auto_4_process
+-----------------------------------
+1. Launch the app ``testpmd``, start 4 process with rxq/txq set as 16 (proc_id:0~3, queue id:0~15) with the following arguments::
+
+   ./dpdk-testpmd -l 1,2 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=16 --txq=16 --num-procs=4 --proc-id=0
+   ./dpdk-testpmd -l 3,4 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=16 --txq=16 --num-procs=4 --proc-id=1
+   ./dpdk-testpmd -l 5,6 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=16 --txq=16 --num-procs=4 --proc-id=2
+   ./dpdk-testpmd -l 7,8 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=16 --txq=16 --num-procs=4 --proc-id=3
+
+2. Send 20 random packets::
+
+      packets generated by script, packet type including 'TCP', 'UDP', 'IPv6_TCP', 'IPv6_UDP', like as: Random_Packet
+
+3. Check whether each process receives 5 packets with the corresponding queue::
+
+      process 0 should receive 5 packets with queue 0~3
+      process 1 should receive 5 packets with queue 4~7
+      process 2 should receive 5 packets with queue 8~11
+      process 3 should receive 5 packets with queue 12~15
+
+4. Check the statistics is correctly, the total number of packets received is 20
+
+Subcase 2: proc_type_primary_secondary_2_process
+------------------------------------------------
+1. Launch the app ``testpmd``, start 2 process with rxq/txq set as 4 (proc_id:0~1, queue id:0~3) with the following arguments::
+
+      ./dpdk-testpmd -l 1,2 --proc-type=primary   -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=4 --txq=4 --num-procs=2 --proc-id=0
+      ./dpdk-testpmd -l 3,4 --proc-type=secondary -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=4 --txq=4 --num-procs=2 --proc-id=1
+
+2. Send 20 random packets::
+
+      packets generated by script, packet type including 'TCP', 'TCP', 'IPv6_TCP', 'IPv6_UDP', such as: Random_Packet
+
+3. Check whether each process receives 10 packets with the corresponding queue::
+
+      process 0 should receive 10 packets with queue 0~1
+      process 1 should receive 10 packets with queue 2~3
+
+4. Check the statistics is correctly, the total number of packets received is 20
+
+Test Case: multiprocess proc_type specify packet
+================================================
+
+Subcase 1: proc_type_auto_2_process
+-----------------------------------
+1. Launch the app ``testpmd``, start 2 process with rxq/txq set as 8 (proc_id:0~1, queue id:0~7) with the following arguments::
+
+    ./dpdk-testpmd -l 1,2 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=8 --txq=8 --num-procs=2 --proc-id=0
+    ./dpdk-testpmd -l 3,4 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=8 --txq=8 --num-procs=2 --proc-id=1
+
+2. Create rule to set queue as one of each process queues::
+
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.0.20  / end actions queue index 0 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.1.20  / end actions queue index 1 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.2.20 / end actions queue index 2 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.3.20 / end actions queue index 3 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.4.20  / end actions queue index 4 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.5.20 / end actions queue index 5 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.6.20 / end actions queue index 6 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.7.20 / end actions queue index 7 / end
+
+3. Send 1 matched packet for each rule::
+
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.0.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.1.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.2.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.3.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.4.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.5.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.6.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.7.20")/("X"*46)
+
+4. Check whether each process receives 4 packets with the corresponding queue::
+
+    process 0 should receive 4 packets with queue 0~3
+    process 1 should receive 4 packets with queue 4~7
+
+5. Check the statistics is correctly, the total number of packets received is 8
+
+Subcase 2: proc_type_primary_secondary_3_process
+------------------------------------------------
+1. Launch the app ``testpmd``, start 3 process with rxq/txq set as 6 (proc_id:0~2, queue id:0~5) with the following arguments::
+
+    x86_64-native-linuxapp-gcc/app/dpdk-testpmd -l 1,2 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=6 --txq=6 --num-procs=3 --proc-id=0
+    x86_64-native-linuxapp-gcc/app/dpdk-testpmd -l 3,4 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=6 --txq=6 --num-procs=3 --proc-id=1
+    x86_64-native-linuxapp-gcc/app/dpdk-testpmd -l 5,6 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=6 --txq=6 --num-procs=3 --proc-id=2
+
+2. Create rule to set queue as one of each process queues::
+
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.0.20  / end actions queue index 0 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.1.20  / end actions queue index 1 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.2.20 / end actions queue index 2 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.3.20 / end actions queue index 3 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.4.20  / end actions queue index 4 / end
+    flow create 0 ingress pattern eth / ipv4 src is 192.168.5.20 / end actions queue index 5 / end
+
+3. Send 1 matched packet for each rule::
+
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.0.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.1.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.2.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.3.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.4.20")/("X"*46)
+    Ether(dst="00:11:22:33:44:55")/IP(src="192.168.5.20")/("X"*46)
+
+4. Check whether each process receives 2 packets with the corresponding queue::
+
+    process 0 should receive 2 packets with queue 0~1
+    process 1 should receive 2 packets with queue 2~3
+    process 2 should receive 2 packets with queue 4~5
+
+5. Check the statistics is correctly, the total number of packets received is 6
+
+Test Case: test_multiprocess_with_fdir_rule
+===========================================
+Launch the app ``testpmd``, start 2 process with rxq/txq set as 64 (proc_id:0~1, queue id:0~63) with the following arguments::
+
+    x86_64-native-linuxapp-gcc/app/dpdk-testpmd -l 1,2 -n 4 -a 0000:05:00.0 --proc-type=auto  --log-level=ice,7 -- -i --rxq=64 --txq=64  --num-procs=2 --proc-id=0
+    x86_64-native-linuxapp-gcc/app/dpdk-testpmd -l 3,4 -n 4 -a 0000:05:00.0 --proc-type=auto  --log-level=ice,7 -- -i --rxq=64 --txq=64  --num-procs=2 --proc-id=1
+
+Subcase 1: mac_ipv4_pay_queue_index
+-----------------------------------
+1. Create rule::
+
+    flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions queue index 62 / mark id 4 / end
+
+2. Send matched packets, check the packets is distributed to queue 62 with FDIR matched ID=0x4.
+   Send unmatched packets, check the packets are distributed by RSS without FDIR matched ID
+
+3. Verify rules can be listed and destroyed::
+
+    testpmd> flow list 0
+
+   check the rule listed.
+   destroy the rule::
+
+    testpmd> flow destroy 0 rule 0
+
+4. Verify matched packet is distributed by RSS without FDIR matched ID.
+   check there is no rule listed.
+
+Subcase 2: mac_ipv4_pay_rss_queues
+----------------------------------
+1. Create rule::
+
+    flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions rss queues 31 32 end / end
+
+2. Send matched packets, check the packets is distributed to queue 31 or 32.
+   Send unmatched packets, check the packets are distributed by RSS
+
+3. Repeat step 3 of subcase 1
+
+4. Verify matched packet is distributed by RSS.
+   check there is no rule listed.
+
+Subcase 3: mac_ipv4_pay_drop
+----------------------------
+1. Create rule::
+
+    flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions drop / end
+
+2. Send matched packets, check the packets are dropped.
+   Send unmatched packets, check the packets are not dropped
+
+3. Repeat step 3 of subcase 1
+
+4. Verify matched packets are not dropped.
+   check there is no rule listed.
+
+Subcase 4: mac_ipv4_pay_mark_rss
+--------------------------------
+1. Create rule::
+
+    flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions mark / rss / end
+
+2. Send matched packets, check the packets are distributed by RSS with FDIR matched ID=0x0.
+   Send unmatched packets, check the packets are distributed by RSS without FDIR matched ID
+
+3. Repeat step 3 of subcase 1
+
+4. Verify matched packets are distributed to the same queue without FDIR matched ID.
+   check there is no rule listed.
+
+Note: step2 and step4 need to check whether all received packets of each process are distributed by RSS
+
+
+Test Case: test_multiprocess_with_rss_toeplitz
+==============================================
+Launch the app ``testpmd``,start 2 process with queue num set as 32 (proc_id: 0~1, queue id: 0~31) with the following arguments::
+
+    ./dpdk-testpmd -l 1,2 -n 4 -a 0000:af:00.0 --proc-type=auto  --log-level=ice,7 -- -i --rxq=32 --txq=32 --disable-rss --rxd=384 --txd=384 --num-procs=2 --proc-id=0
+    ./dpdk-testpmd -l 3,4 -n 4 -a 0000:af:00.0 --proc-type=auto  --log-level=ice,7 -- -i --rxq=32 --txq=32 --disable-rss --rxd=384 --txd=384 --num-procs=2 --proc-id=1
+
+all the test cases run the same test steps as below::
+
+    1. validate rule.
+    2. create rule and list rule.
+    3. send a basic hit pattern packet,record the hash value,
+       check the packet is distributed to queues by RSS.
+    4. send hit pattern packet with changed input set in the rule.
+       check the received packet have different hash value with basic packet.
+       check the packet is distributed to queues by rss.
+    5. send hit pattern packet with changed input set not in the rule.
+       check the received packet have same hash value with the basic packet.
+       check the packet is distributed to queues by rss.
+    6. destroy the rule and list rule.
+    7. send same packet with step 3.
+       check the received packets have no hash value, and distributed to queue 0.
+
+    Note: step3, step4 and step5 need to check whether all received packets of each process are distributed by RSS
+
+basic hit pattern packets are the same in this test case.
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+
+not hit pattern packets are the same in this test case::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IPv6(src="ABAB:910B:6666:3457:8295:3333:1800:2929",dst="CDCD:910A:2222:5498:8475:1111:3900:2020")/TCP(sport=22,dport=23)/Raw("x"*80)],iface="ens786f0")
+
+Subcase 1: mac_ipv4_tcp_l2_src
+------------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types eth l2-src-only end key_len 0 queues end / end
+
+2. hit pattern/defined input set::
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.3", src="192.168.0.5")/TCP(sport=25,dport=99)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_l2_dst
+----------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types eth l2-dst-only end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.3", src="192.168.0.5")/TCP(sport=25,dport=99)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_l2src_l2dst
+---------------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types eth end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.3", src="192.168.0.5")/TCP(sport=25,dport=99)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_l3_src
+----------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-src-only end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=32,dport=33)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_l3_dst
+----------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-dst-only end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=32,dport=33)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_l3src_l4src
+---------------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-src-only l4-src-only end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=32,dport=23)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=33)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_l3src_l4dst
+---------------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-src-only l4-dst-only end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=33)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=32,dport=23)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_l3dst_l4src
+---------------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-dst-only l4-src-only end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=32,dport=23)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=33)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_l3dst_l4dst
+---------------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-dst-only l4-dst-only end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=33)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=32,dport=23)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_l4_src
+----------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l4-src-only end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=32,dport=23)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.1.1", src="192.168.1.2")/TCP(sport=22,dport=33)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_l4_dst
+----------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l4-dst-only end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=33)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.1.1", src="192.168.1.2")/TCP(sport=32,dport=23)/("X"*480)],iface="ens786f0")
+
+Subcase: mac_ipv4_tcp_ipv4
+--------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4 end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(dst="00:11:22:33:44:53", src="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=32,dport=33)/("X"*480)],iface="enp134s0f0")
+
+Subcase: mac_ipv4_tcp_all
+-------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=33)/("X"*480)],iface="ens786f0")
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=32,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.1.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(src="00:11:22:33:44:55", dst="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.1.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+
+3. hit pattern/not defined input set:
+ipv4-tcp packets::
+
+    sendp([Ether(src="00:11:22:33:44:53", dst="68:05:CA:BB:27:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+
+
+Test Case: test_multiprocess_with_rss_symmetric
+===============================================
+Launch the app ``testpmd``, start 2 process with queue num set as 16(proc_id: 0~1, queue id: 0~15) with the following arguments::
+
+    ./dpdk-testpmd -l 1,2 -n 4 -a 0000:af:00.0 --proc-type=auto  --log-level=ice,7 -- -i --rxq=16 --txq=16  --num-procs=2 --proc-id=0
+    ./dpdk-testpmd -l 3,4 -n 4 -a 0000:af:00.0 --proc-type=auto  --log-level=ice,7 -- -i --rxq=16 --txq=16  --num-procs=2 --proc-id=1
+
+test steps as below::
+
+    1. validate and create rule.
+    2. set "port config all rss all".
+    3. send hit pattern packets with switched value of input set in the rule.
+       check the received packets have the same hash value.
+       check all the packets are distributed to queues by rss
+    4. destroy the rule and list rule.
+    5. send same packets with step 3
+       check the received packets have no hash value, or have different hash value.
+
+    Note: step3 needs to check whether all received packets of each process are distributed by RSS
+
+Subcase: mac_ipv4_symmetric
+---------------------------
+1. create rss rule::
+
+    flow create 0 ingress pattern eth / ipv4 / end actions rss func symmetric_toeplitz types ipv4 end key_len 0 queues end / end
+
+2. hit pattern/defined input set:
+ipv4-nonfrag packets::
+
+    sendp([Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/("X"*480)],iface="ens786f0")
+    sendp([Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.2", src="192.168.0.1")/("X"*480)],iface="ens786f0")
+
+ipv4-frag packets::
+
+    sendp([Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2",frag=6)/("X"*480)],iface="ens786f0")
+    sendp([Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.2", src="192.168.0.1",frag=6)/("X"*480)],iface="ens786f0")
+
+ipv4-tcp packets::
+
+    sendp([Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.1", src="192.168.0.2")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+    sendp([Ether(dst="00:11:22:33:44:55", src="68:05:CA:BB:26:E0")/IP(dst="192.168.0.2", src="192.168.0.1")/TCP(sport=22,dport=23)/("X"*480)],iface="ens786f0")
+
+Test Case: test_multiprocess_auto_process_type_detected
+=======================================================
+1. start 2 process with queue num set as 8 (proc_id:0~1,queue id:0~7)::
+
+    ./dpdk-testpmd -l 1,2 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=8 --txq=8 --num-procs=2 --proc-id=0
+    ./dpdk-testpmd -l 3,4 --proc-type=auto -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=8 --txq=8 --num-procs=2 --proc-id=1
+
+2. check the ouput of each process::
+
+    process 1 output contains 'Auto-detected process type: PRIMARY'
+    process 2 output contains 'Auto-detected process type: SECONDARY'
+
+Test Case: test_multiprocess_negative_2_primary_process
+=======================================================
+1. start 2 process with queue num set as 4 (proc_id:0~1,queue id:0~3)::
+
+   ./dpdk-testpmd -l 1,2 --proc-type=primary -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=4 --txq=4 --num-procs=2 --proc-id=0
+   ./dpdk-testpmd -l 3,4 --proc-type=primary -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=4 --txq=4 --num-procs=2 --proc-id=1
+
+2. check the ouput of each process::
+
+    process 1 launches successfully
+    process 2 launches failed and output contains 'Is another primary process running?'
+
+Test Case: test_multiprocess_negative_exceed_process_num
+========================================================
+1. start 3 process exceed the specifed num 2::
+
+   ./dpdk-testpmd -l 1,2 --proc-type=primary -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=8 --txq=8 --num-procs=2 --proc-id=0
+   ./dpdk-testpmd -l 3,4 --proc-type=primary -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=8 --txq=8 --num-procs=2 --proc-id=1
+   ./dpdk-testpmd -l 5,6 --proc-type=primary -a 0000:05:00.0  --log-level=ice,7 -- -i --rxq=8 --txq=8 --num-procs=2 --proc-id=2
+
+2. check the ouput of each process::
+
+    the first and second processes should be launched successfully
+    the third process should be launched failed and output should contain the following string:
+    'multi-process option proc-id(2) should be less than num-procs(2)'
-- 
2.17.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [dts] [PATCH V4 2/2] test_plans/multiprocess: add pf multiprocess test case
  2022-05-19  7:48 ` [dts] [PATCH V4 2/2] test_plans/multiprocess: " Jiale Song
@ 2022-05-19  8:22   ` Peng, Yuan
  2022-05-25 10:14   ` lijuan.tu
  1 sibling, 0 replies; 4+ messages in thread
From: Peng, Yuan @ 2022-05-19  8:22 UTC (permalink / raw)
  To: Jiale, SongX, dts; +Cc: Jiale, SongX

Acked-by: Peng, Yuan <yuan.peng@intel.com>

-----Original Message-----
From: Jiale Song <songx.jiale@intel.com> 
Sent: Thursday, May 19, 2022 3:48 PM
To: dts@dpdk.org
Cc: Jiale, SongX <songx.jiale@intel.com>
Subject: [dts] [PATCH V4 2/2] test_plans/multiprocess: add pf multiprocess test case

pf have no data transmission case.
so add 10 cases in pf multiprocess test suite.

Signed-off-by: Jiale Song <songx.jiale@intel.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [dts] [PATCH V4 2/2] test_plans/multiprocess: add pf multiprocess test case
  2022-05-19  7:48 ` [dts] [PATCH V4 2/2] test_plans/multiprocess: " Jiale Song
  2022-05-19  8:22   ` Peng, Yuan
@ 2022-05-25 10:14   ` lijuan.tu
  1 sibling, 0 replies; 4+ messages in thread
From: lijuan.tu @ 2022-05-25 10:14 UTC (permalink / raw)
  To: dts, Jiale Song; +Cc: Jiale Song

On Thu, 19 May 2022 15:48:21 +0800, Jiale Song <songx.jiale@intel.com> wrote:
> pf have no data transmission case.
> so add 10 cases in pf multiprocess test suite.
> 
> Signed-off-by: Jiale Song <songx.jiale@intel.com>


Series applied, thanks

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-05-25 10:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-19  7:48 [dts] [PATCH V4 1/2] tests/multiprocess: add pf multiprocess test case Jiale Song
2022-05-19  7:48 ` [dts] [PATCH V4 2/2] test_plans/multiprocess: " Jiale Song
2022-05-19  8:22   ` Peng, Yuan
2022-05-25 10:14   ` lijuan.tu

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).