[dts] [PATCH v4] add dynamic flow type test suite

Liu, Yong yong.liu at intel.com
Tue Nov 21 06:38:22 CET 2017


Xueqin,
Few comments are inline.

Thanks,
Marvin

> -----Original Message-----
> From: dts [mailto:dts-bounces at dpdk.org] On Behalf Of Xueqin Lin
> Sent: Tuesday, November 21, 2017 7:11 AM
> To: dts at dpdk.org
> Cc: Lin, Xueqin <xueqin.lin at intel.com>
> Subject: [dts] [PATCH v4] add dynamic flow type test suite
> 
> ---
>  tests/TestSuite_dynamic_flowtype.py | 293
> ++++++++++++++++++++++++++++++++++++
>  1 file changed, 293 insertions(+)
>  create mode 100644 tests/TestSuite_dynamic_flowtype.py
> 
> diff --git a/tests/TestSuite_dynamic_flowtype.py
> b/tests/TestSuite_dynamic_flowtype.py
> new file mode 100644
> index 0000000..98baa31
> --- /dev/null
> +++ b/tests/TestSuite_dynamic_flowtype.py
> @@ -0,0 +1,293 @@
> +# <COPYRIGHT_TAG>
> +
> +import time
> +import re
> +import sys
> +import utils
> +from qemu_kvm import QEMUKvm

Please remove useless import.

> +from test_case import TestCase
> +from pmd_output import PmdOutput
> +from settings import get_nic_name
Please remove useless import.

> +import random
> +
> +VM_CORES_MASK = 'all'
> +
> +
> +class TestDynamic_Flowtype(TestCase):

Please change the name to TestDynamicFlowtype.

> +
> +    def set_up_all(self):
> +        self.verify(self.nic in ['fortville_25g'],
> +                    'dynamic flow type mapping can not support %s nic'
> +                    % self.nic)
> +        ports = self.dut.get_ports()
> +        self.verify(len(ports) >= 1, "Insufficient ports for testing")
> +        valports = [_ for _ in ports if self.tester.get_local_port(_) !=
> -1]
> +        self.dut_port = valports[0]
> +        tester_port = self.tester.get_local_port(self.dut_port)
> +        self.tester_intf = self.tester.get_interface(tester_port)
> +        profile_file = 'dep/gtp.pkgo'
> +        profile_dst = "/tmp/"
> +        self.dut.session.copy_file_to(profile_file, profile_dst)
> +        PF_Q_strip = 'CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF'
> +        self.PF_QUEUE = self.search_queue_number(PF_Q_strip)
> +
> +    def set_up(self):
> +        """
> +        Run before each test case.
> +        """
> +        self.dut_testpmd = PmdOutput(self.dut)
> +        self.dut_testpmd.start_testpmd(
> +            "Default", "--port-topology=chained --txq=%s --rxq=%s"
> +            % (self.PF_QUEUE, self.PF_QUEUE))
> +        self.load_profile()
> +
> +    def search_queue_number(self, Q_strip):
> +        """
> +        Search max queue number from configuration.
> +        """
> +        out = self.dut.send_expect("cat config/common_base", "]# ", 10)
> +        pattern = "(%s=)(\d*)" % Q_strip
> +        s = re.compile(pattern)
> +        res = s.search(out)
> +        if res is None:
> +            print utils.RED('Search no queue number.')
> +            return None
> +        else:
> +            queue = res.group(2)
> +            return int(queue)
> +
> +    def load_profile(self):
> +        """
> +        Load profile to update FVL configuration tables, profile will be
> +        stored in binary file and need to be passed to AQ to program FVL
> +        during initialization stage.
> +        """
> +        self.dut_testpmd.execute_cmd('port stop all')
> +        time.sleep(1)
> +        out = self.dut_testpmd.execute_cmd('ddp get list 0')
> +        self.dut_testpmd.execute_cmd('ddp add 0 /tmp/gtp.pkgo')
> +        out = self.dut_testpmd.execute_cmd('ddp get list 0')
> +        self.verify("Profile number is: 1" in out,
> +                    "Failed to load ddp profile!!!")
> +        self.dut_testpmd.execute_cmd('port start all')
> +        time.sleep(1)
> +        self.dut_testpmd.execute_cmd('set fwd rxonly')
> +        self.dut_testpmd.execute_cmd('set verbose 1')
> +        self.dut_testpmd.execute_cmd('start')
> +
> +    def gtp_packets(self, flowtype=26, match_opt='matched'):
> +        """
> +        Generate different GTP types according to different parameters.
> +        I40e PCTYPEs are statically mapped to RTE_ETH_FLOW_* types in
> +        DPDK, defined in rte_eth_ctrl.h, and flow types used to define
> +        ETH_RSS_* offload types in rte_ethdev.h. RTE_ETH_FLOW_MAX is
> +        defined now as 22, leaves 42 flow type unassigned.
> +        Input:
> +        flowtype: define flow type 26, 23, 24, 25 for GTP types as below
> +                  table, check each layer type, tunnel packet includes
> +                  GTPC and GTPU, GTPC has none inner L3, GTPU has none,
> +                  IPV4 and IPV6 inner L3.
> +        match_opt: PF or VSIs receive match packets to rss queue, but
> +                   receive not match packets to queue 0.
> +
> +        +------------+------------+------------+
> +        |Packet Type |   PCTYPEs  | Flow Types |
> +        +------------+------------+------------+
> +        |GTP-U IPv4  |    22      |   26       |
> +        +------------+------ -----+------------+
> +        |GTP-U IPv6  |    23      |   23       |
> +        +------------+------------+------------+
> +        |GTP-U PAY4  |    24      |   24       |
> +        +------------+------------+------------+
> +        |GTP-C PAY4  |    25      |   25       |
> +        +------------+------------+------------+
> +
> +        """
> +        pkts = []
> +        pkts_ipv4 = {'IPV4': 'Ether()/IP()/Raw("X"*20)'}
> +
> +        pkts_gtpc_pay = {'IPV4/GTPC':
> 'Ether()/IP()/UDP(dport=2123)/GTP_U_Header()/Raw("X"*20)',
> +                         'IPV6/GTPC':
> 'Ether()/IPv6()/UDP(dport=2123)/GTP_U_Header()/Raw("X"*20)'}
> +
> +        pkts_gtpu_pay = {'IPV4/GTPU':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/Raw("X"*20)',
> +                         'IPV6/GTPU':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/Raw("X"*20)'}
> +
> +        pkts_gtpu_ipv4 = {'IPV4/GTPU/IPV4':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IP()/Raw("X"*20)',
> +                          'IPV4/GTPU/IPV4/FRAG':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IP(frag=5)/Raw("X"*20)',
> +                          'IPV4/GTPU/IPV4/UDP':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IP()/UDP()/Raw("X"*20)',
> +                          'IPV4/GTPU/IPV4/TCP':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IP()/TCP()/Raw("X"*20)',
> +                          'IPV4/GTPU/IPV4/SCTP':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IP()/SCTP()/Raw("X"*20)',
> +                          'IPV4/GTPU/IPV4/ICMP':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IP()/ICMP()/Raw("X"*20)',
> +                          'IPV6/GTPU/IPV4':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IP()/Raw("X"*20)',
> +                          'IPV6/GTPU/IPV4/FRAG':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IP(frag=5)/Raw("X"*20)',
> +                          'IPV6/GTPU/IPV4/UDP':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IP()/UDP()/Raw("X"*20)',
> +                          'IPV6/GTPU/IPV4/TCP':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IP()/TCP()/Raw("X"*20)',
> +                          'IPV6/GTPU/IPV4/SCTP':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IP()/SCTP()/Raw("X"*20)',
> +                          'IPV6/GTPU/IPV4/ICMP':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IP()/ICMP()/Raw("X"*20)'}
> +
> +        pkts_gtpu_ipv6 = {'IPV4/GTPU/IPV6/FRAG':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IPv6()/IPv6ExtHdrFragment()/R
> aw("X"*20)',
> +                          'IPV4/GTPU/IPV6':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IPv6()/Raw("X"*20)',
> +                          'IPV4/GTPU/IPV6/UDP':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IPv6()/UDP()/Raw("X"*20)',
> +                          'IPV4/GTPU/IPV6/TCP':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IPv6()/TCP()/Raw("X"*20)',
> +                          'IPV4/GTPU/IPV6/SCTP':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IPv6()/SCTP()/Raw("X"*20)',
> +                          'IPV4/GTPU/IPV6/ICMP':
> 'Ether()/IP()/UDP(dport=2152)/GTP_U_Header()/IPv6(nh=58)/ICMP()/Raw("X"*20
> )',
> +                          'IPV6/GTPU/IPV6/FRAG':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IPv6()/IPv6ExtHdrFragment()
> /Raw("X"*20)',
> +                          'IPV6/GTPU/IPV6':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IPv6()/Raw("X"*20)',
> +                          'IPV6/GTPU/IPV6/UDP':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IPv6()/UDP()/Raw("X"*20)',
> +                          'IPV6/GTPU/IPV6/TCP':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IPv6()/TCP()/Raw("X"*20)',
> +                          'IPV6/GTPU/IPV6/SCTP':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IPv6()/SCTP()/Raw("X"*20)',
> +                          'IPV6/GTPU/IPV6/ICMP':
> 'Ether()/IPv6()/UDP(dport=2152)/GTP_U_Header()/IPv6(nh=58)/ICMP()/Raw("X"*
> 20)'}
> +
> +        if match_opt == 'matched':
> +            # Define flow type for IPV4 as 2 in rte_eth_ctrl.h
> +            if flowtype == 2:
> +                pkts = pkts_ipv4
> +            if flowtype == 23:
> +                pkts = pkts_gtpu_ipv6
> +            if flowtype == 24:
> +                pkts = pkts_gtpu_pay
> +            if flowtype == 25:
> +                pkts = pkts_gtpc_pay
> +            if flowtype == 26:
> +                pkts = pkts_gtpu_ipv4
> +
> +        if match_opt == 'not matched':
> +            if flowtype == 23:
> +                pkts = dict(pkts_gtpc_pay.items() +
> +                            pkts_gtpu_pay.items() +
> +                            pkts_gtpu_ipv4.items())
> +            if flowtype == 24:
> +                pkts = dict(pkts_gtpc_pay.items() +
> +                            pkts_gtpu_ipv4.items() +
> +                            pkts_gtpu_ipv6.items())
> +            if flowtype == 25:
> +                pkts = dict(pkts_gtpu_pay.items() +
> +                            pkts_gtpu_ipv4.items() +
> +                            pkts_gtpu_ipv6.items())
> +            if flowtype == 26:
> +                pkts = dict(pkts_gtpc_pay.items() +
> +                            pkts_gtpu_pay.items() +
> +                            pkts_gtpu_ipv6.items())
> +
> +        return pkts
> +
> +    def packet_send_verify(self, flowtype=26, match_opt='matched'):
> +        """
> +        Send packet and verify rss function.
> +        """
> +        pkts = self.gtp_packets(flowtype, match_opt)
> +        for packet_type in pkts.keys():
> +            self.tester.scapy_append(
> +                'sendp([%s], iface="%s")'
> +                % (pkts[packet_type], self.tester_intf))
> +            self.tester.scapy_execute()
> +            out = self.dut.get_session_output(timeout=2)
> +            if match_opt == 'matched':
> +                self.verify("port 0/queue 0" not in out,
> +                            "Failed to receive packet in rss queue!!!")
> +                self.verify("PKT_RX_RSS_HASH" in out,
> +                            "Failed to receive packet in rss queue!!!")
> +            elif match_opt == 'not matched':
> +                self.verify("port 0/queue 0" in out,
> +                            "Failed to receive packet in queue 0!!!")
> +                self.verify("PKT_RX_RSS_HASH" not in out,
> +                            "Failed to receive packet in queue 0!!!")
> +
> +    def dynamic_flowtype_test(self, pctype=22, flowtype=26, reset=False):
> +        """
> +        Dynamic modify, return or reset the contents of flow type to
> pctype
> +        dynamic mapping, enable rss hash for new protocal.
> +        reset: If reset is true, reset the contents of flow type to
> pctype
> +               mapping. If reset is false, enable rss hash for new
> protocal.
> +        """
> +        out = self.dut_testpmd.execute_cmd('show port 0 pctype mapping')
> +        self.verify("pctype: 63  ->  flowtype: 14" in out,
> +                    "Failed show flow type to pctype mapping!!!")
> +        self.verify("pctype: %s  ->  flowtype: %s"
> +                    % (pctype, flowtype) not in out,
> +                    "Failed show flow type to pctype mapping!!!")
> +        self.dut_testpmd.execute_cmd(
> +            'port config 0 pctype mapping update %s %s' % (pctype,
> flowtype))
> +        out = self.dut_testpmd.execute_cmd('show port 0 pctype mapping')
> +        self.verify("pctype: %s  ->  flowtype: %s"
> +                    % (pctype, flowtype) in out,
> +                    "Failed update flow type to pctype mapping!!!")
> +        if reset is False:
> +            self.dut_testpmd.execute_cmd(
> +                'set_hash_input_set 0 %s udp-key add' % flowtype)
> +            self.dut_testpmd.execute_cmd('port config all rss %s' %
> flowtype)
> +        else:
> +            self.dut_testpmd.execute_cmd('port config 0 pctype mapping
> reset')
> +            out = self.dut_testpmd.execute_cmd('show port 0 pctype
> mapping')
> +            self.verify("pctype: %s  ->  flowtype: %s"
> +                        % (pctype, flowtype) not in out,
> +                        "Failed reset flow type to pctype mapping!!!")
> +            """
> +            Send normal ipv4 packet to test rss, rte_eth_ctrl.h defines
> flow
> +            type for IPV4 is 2.
> +            """
> +            flowtype = 2
> +        for match_opt in ['matched', 'not matched']:
> +            if match_opt == 'not matched' and reset is True:
> +                break
> +            self.packet_send_verify(flowtype, match_opt)
> +
> +    def test_profile_correctness(self):
> +        """
> +        GTP is supported by NVM with profile updated. Check profile
> +        information correctness, includes used protocols, packet
> +        classification types, defined packet types and so on.
> +        """
> +        out = self.dut_testpmd.execute_cmd('ddp get info /tmp/gtp.pkgo')
> +        self.verify("i40e Profile Version" in out,
> +                    "Failed to verify profile version!!!")
> +        self.verify("List of used protocols" in out,
> +                    "Failed to verify profie used protocols!!!")
> +        self.verify("List of defined packet classification types" in out,
> +                    "Failed to verify profile packet classification
> types!!!")
> +        self.verify("List of defined packet types" in out,
> +                    "Failed to verify profile packet types!!!")
> +
> +    def test_dynamic_flowtype_reset(self):
> +        """
> +        Dynamic modify, reset and return the contents of flow type to
> pctype
> +        dynamic mapping.
> +        """
> +        self.dynamic_flowtype_test(pctype=22, flowtype=26, reset=True)
> +
> +    def test_dynamic_flowtype_gtpu_ipv4(self):
> +        """
> +        Dynamic modify, return the contents of flow type to pctype
> dynamic
> +        mapping, enable and verify rss for GTP-U IPV4 packets.
> +        """
> +        self.dynamic_flowtype_test(pctype=22, flowtype=26, reset=False)
> +
> +    def test_dynamic_flowtype_gtpu_ipv6(self):
> +        """
> +        Dynamic modify, return the contents of flow type to pctype
> dynamic
> +        mapping, enable and verify rss for GTP-U IPV6 packets.
> +        """
> +        self.dynamic_flowtype_test(pctype=23, flowtype=23, reset=False)
> +
> +    def test_dynamic_flowtype_gtpu_pay(self):
> +        """
> +        Dynamic modify, return the contents of flow type to pctype
> dynamic
> +        mapping, enable and verify rss for GTP-U PAY packets.
> +        """
> +        self.dynamic_flowtype_test(pctype=24, flowtype=24, reset=False)
> +
> +    def test_dynamic_flowtype_gtpc_pay(self):
> +        """
> +        Dynamic modify, return the contents of flow type to pctype
> dynamic
> +        mapping, enable and verify rss for GTP-C PAY packets.
> +        """
> +        self.dynamic_flowtype_test(pctype=25, flowtype=25, reset=False)
> +
> +    def tear_down(self):
> +        if self.dut_testpmd:
> +            self.dut_testpmd.execute_cmd('write reg 0 0xb8190 1')
> +            self.dut_testpmd.execute_cmd('write reg 0 0xb8190 2')
> +            self.dut_testpmd.quit()
> +
> +    def tear_down_all(self):
> +        self.dut.kill_all()
> --
> 2.5.5



More information about the dts mailing list