* [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan @ 2019-11-01 7:06 yufengmx 2019-11-01 7:06 ` [dts] [PATCH V3 1/3] ethtool_stats: " yufengmx ` (4 more replies) 0 siblings, 5 replies; 15+ messages in thread From: yufengmx @ 2019-11-01 7:06 UTC (permalink / raw) To: dts, yinan.wang; +Cc: yufengmx upload ethtool_stats script. update test plan. add test plan index list. v3: - rebase source code for new Packet module refactor. - use testpmd xstat data as reference data to check proc info tool xstat data. - update test plan content. - remove un-used methods. v2: - Follow Wang,yinan suggestion - *. remove --tx-offloads=0xXXXX - *. fix typo yufengmx (3): ethtool_stats: update test plan ethtool_stats: add ethtool_stats_test_plan index label ethtool_stats: add automation script test_plans/ethtool_stats_test_plan.rst | 66 ++-- test_plans/index.rst | 1 + tests/TestSuite_ethtool_stats.py | 498 +++++++++++++++++++++++++ 3 files changed, 544 insertions(+), 21 deletions(-) create mode 100644 tests/TestSuite_ethtool_stats.py -- 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [dts] [PATCH V3 1/3] ethtool_stats: update test plan 2019-11-01 7:06 [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan yufengmx @ 2019-11-01 7:06 ` yufengmx 2019-11-12 15:34 ` Wang, Yinan 2019-11-13 2:20 ` Wang, Yinan 2019-11-01 7:06 ` [dts] [PATCH V3 2/3] ethtool_stats: add ethtool_stats_test_plan index label yufengmx ` (3 subsequent siblings) 4 siblings, 2 replies; 15+ messages in thread From: yufengmx @ 2019-11-01 7:06 UTC (permalink / raw) To: dts, yinan.wang; +Cc: yufengmx use testpmd xstat data as reference data to check proc info tool xstat data. update test plan content. Signed-off-by: yufengmx <yufengx.mo@intel.com> --- test_plans/ethtool_stats_test_plan.rst | 66 ++++++++++++++++++-------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/test_plans/ethtool_stats_test_plan.rst b/test_plans/ethtool_stats_test_plan.rst index 13b5909..95f9e7a 100644 --- a/test_plans/ethtool_stats_test_plan.rst +++ b/test_plans/ethtool_stats_test_plan.rst @@ -47,13 +47,20 @@ that DPDK supports. The idea behind this epic is two fold as following. - the retrieval of aggregate stats upon request (Top level stats). - the retrieval of the extended NIC stats. - grouping of stats logically so they can be retrieved per logical grouping. - - the option to enable/disable the stats groups to retrieve similar to set private flags in ethtool. + - the option to enable/disable the stats groups to retrieve similar to set + private flags in ethtool. Prerequisites ============= 2xNICs (2 full duplex optical ports per NIC). One on dut, another one on tester, -link them together. Update two nics' firmware to latest version. +link them together. Update two nics' firmware to latest version:: + + Tester DUT + .-------. .-------. + | port0 | <------------------> | port0 | + | port1 | <------------------> | port1 | + '-------' '-------' Test cases ========== @@ -64,8 +71,8 @@ bind two ports:: ./usertools/dpdk-devbind.py --bind=igb_uio <pci address 1> <pci address 2> -Test Case: xstat command set intergrity ---------------------------------------- +Test Case: xstat options +------------------------ check ``dpdk-procinfo`` tool support ``xstats`` command options. @@ -80,7 +87,11 @@ steps: #. boot up ``testpmd``:: - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i --port-topology=loop + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop + + testpmd> set fwd io + testpmd> clear port xstats all + testpmd> start #. run ``dpdk-procinfo`` tool:: @@ -88,25 +99,30 @@ steps: #. check ``dpdk-procinfo`` tool output should contain upper options. -Test Case: xstat command ------------------------- +Test Case: xstat statistic integrity +------------------------------------ -check if port extended statistics can get right data. +check if port extended statistics can access by xstat name or xstat id. steps: #. boot up ``testpmd``:: - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i --port-topology=loop + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop + + testpmd> set fwd io + testpmd> clear port xstats all + testpmd> start #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: sendp([Ether()/IP()/UDP()/Raw('\0'*60)], iface=<port 0 name>) -#. run ``dpdk-procinfo`` tool with ``xstats`` option and check if all port have - a correct data of different size packet:: +#. run ``dpdk-procinfo`` tool with ``xstats`` option and check if all ports + extended statistics can access by xstat name or xstat id:: - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-id <N> + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name <statistic name> Test Case: xstat-reset command ------------------------------ @@ -117,7 +133,11 @@ steps: #. boot up ``testpmd``:: - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i --port-topology=loop + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop + + testpmd> set fwd io + testpmd> clear port xstats all + testpmd> start #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: @@ -132,24 +152,26 @@ Test Case: xstat single statistic --------------------------------- check if port extended statistic name can be get by statistic id and check -related data's correctness. +related data's correctness with testpmd xstat data. steps: #. boot up ``testpmd``:: - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i --port-topology=loop - -#. run ``dpdk-procinfo`` tool with ``xstats`` option to get all NIC extended - statistics parameters of port and use the output display sequence as parameter - index in the following search index:: + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats + testpmd> set fwd io + testpmd> clear port xstats all + testpmd> start #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: sendp([Ether()/IP()/UDP()/Raw('\0'*60)], iface=<port 0 name>) +#. run test pmd ``show port xstats all`` to get testpmd port xstat data: + + testpmd> show port xstats all + #. run ``dpdk-procinfo`` tool with ``xstats-id`` option to get the statistic name corresponding with the index id:: @@ -158,4 +180,6 @@ steps: #. run ``dpdk-procinfo`` tool with ``xstats-name`` option to get the statistic data corresponding with the statistic name:: - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name <statistic name> \ No newline at end of file + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name <statistic name> + +#. compare these proc info tool xstat values with testpmd xstat values. \ No newline at end of file -- 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 1/3] ethtool_stats: update test plan 2019-11-01 7:06 ` [dts] [PATCH V3 1/3] ethtool_stats: " yufengmx @ 2019-11-12 15:34 ` Wang, Yinan 2019-11-12 16:03 ` Wang, Yinan 2019-11-13 2:20 ` Wang, Yinan 1 sibling, 1 reply; 15+ messages in thread From: Wang, Yinan @ 2019-11-12 15:34 UTC (permalink / raw) To: Mo, YufengX, dts Hi Yufeng, The test plan you upstreamed can’t work as missing important parameters. Please take a look. --latencystats=N: enable latency and jitter statistcs monitoring on forwarding lcore id N. --bitrate-stats=N: set the logical core N to perform bit-rate calculation. Br, yinan > -----Original Message----- > From: Mo, YufengX <yufengx.mo@intel.com> > Sent: 2019年11月1日 15:07 > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > Cc: Mo, YufengX <yufengx.mo@intel.com> > Subject: [dts][PATCH V3 1/3] ethtool_stats: update test plan > > > use testpmd xstat data as reference data to check proc info tool xstat data. > update test plan content. > > Signed-off-by: yufengmx <yufengx.mo@intel.com> > --- > test_plans/ethtool_stats_test_plan.rst | 66 ++++++++++++++++++-------- > 1 file changed, 45 insertions(+), 21 deletions(-) > > diff --git a/test_plans/ethtool_stats_test_plan.rst > b/test_plans/ethtool_stats_test_plan.rst > index 13b5909..95f9e7a 100644 > --- a/test_plans/ethtool_stats_test_plan.rst > +++ b/test_plans/ethtool_stats_test_plan.rst > @@ -47,13 +47,20 @@ that DPDK supports. The idea behind this epic is two > fold as following. > - the retrieval of aggregate stats upon request (Top level stats). > - the retrieval of the extended NIC stats. > - grouping of stats logically so they can be retrieved per logical grouping. > - - the option to enable/disable the stats groups to retrieve similar to set > private flags in ethtool. > + - the option to enable/disable the stats groups to retrieve similar to set > + private flags in ethtool. > > Prerequisites > ============= > > 2xNICs (2 full duplex optical ports per NIC). One on dut, another one on tester, > -link them together. Update two nics' firmware to latest version. > +link them together. Update two nics' firmware to latest version:: > + > + Tester DUT > + .-------. .-------. > + | port0 | <------------------> | port0 | > + | port1 | <------------------> | port1 | > + '-------' '-------' > > Test cases > ========== > @@ -64,8 +71,8 @@ bind two ports:: > > ./usertools/dpdk-devbind.py --bind=igb_uio <pci address 1> <pci address > 2> > > -Test Case: xstat command set intergrity > ---------------------------------------- > +Test Case: xstat options > +------------------------ > > check ``dpdk-procinfo`` tool support ``xstats`` command options. > > @@ -80,7 +87,11 @@ steps: > > #. boot up ``testpmd``:: > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i > --port-topology=loop > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop > + > + testpmd> set fwd io > + testpmd> clear port xstats all > + testpmd> start > > #. run ``dpdk-procinfo`` tool:: > > @@ -88,25 +99,30 @@ steps: > > #. check ``dpdk-procinfo`` tool output should contain upper options. > > -Test Case: xstat command > ------------------------- > +Test Case: xstat statistic integrity > +------------------------------------ > > -check if port extended statistics can get right data. > +check if port extended statistics can access by xstat name or xstat id. > > steps: > > #. boot up ``testpmd``:: > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i > --port-topology=loop > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop > + > + testpmd> set fwd io > + testpmd> clear port xstats all > + testpmd> start > > #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: > > sendp([Ether()/IP()/UDP()/Raw('\0'*60)], iface=<port 0 name>) > > -#. run ``dpdk-procinfo`` tool with ``xstats`` option and check if all port have > - a correct data of different size packet:: > +#. run ``dpdk-procinfo`` tool with ``xstats`` option and check if all ports > + extended statistics can access by xstat name or xstat id:: > > - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats > + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-id <N> > + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name <statistic > + name> > > Test Case: xstat-reset command > ------------------------------ > @@ -117,7 +133,11 @@ steps: > > #. boot up ``testpmd``:: > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i > --port-topology=loop > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop > + > + testpmd> set fwd io > + testpmd> clear port xstats all > + testpmd> start > > #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: > > @@ -132,24 +152,26 @@ Test Case: xstat single statistic > --------------------------------- > > check if port extended statistic name can be get by statistic id and check > -related data's correctness. > +related data's correctness with testpmd xstat data. > > steps: > > #. boot up ``testpmd``:: > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i > --port-topology=loop > - > -#. run ``dpdk-procinfo`` tool with ``xstats`` option to get all NIC extended > - statistics parameters of port and use the output display sequence as > parameter > - index in the following search index:: > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop > > - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats > + testpmd> set fwd io > + testpmd> clear port xstats all > + testpmd> start > > #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: > > sendp([Ether()/IP()/UDP()/Raw('\0'*60)], iface=<port 0 name>) > > +#. run test pmd ``show port xstats all`` to get testpmd port xstat data: > + > + testpmd> show port xstats all > + > #. run ``dpdk-procinfo`` tool with ``xstats-id`` option to get the statistic > name corresponding with the index id:: > > @@ -158,4 +180,6 @@ steps: > #. run ``dpdk-procinfo`` tool with ``xstats-name`` option to get the statistic > data corresponding with the statistic name:: > > - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name <statistic name> > \ No newline at end of file > + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name <statistic > + name> > + > +#. compare these proc info tool xstat values with testpmd xstat values. > \ No newline at end of file > -- > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 1/3] ethtool_stats: update test plan 2019-11-12 15:34 ` Wang, Yinan @ 2019-11-12 16:03 ` Wang, Yinan 0 siblings, 0 replies; 15+ messages in thread From: Wang, Yinan @ 2019-11-12 16:03 UTC (permalink / raw) To: Mo, YufengX, 'dts@dpdk.org' Acked-by: Wang, Yinan <yinan.wang@intel.com> Sorry, pls ignore below comment as it’s for another test plan. > -----Original Message----- > From: Wang, Yinan > Sent: 2019年11月12日 23:35 > To: Mo, YufengX <yufengx.mo@intel.com>; dts@dpdk.org > Subject: RE: [dts][PATCH V3 1/3] ethtool_stats: update test plan > > Hi Yufeng, > > The test plan you upstreamed can’t work as missing important parameters. > Please take a look. > > --latencystats=N: enable latency and jitter statistcs monitoring on forwarding > lcore id N. > --bitrate-stats=N: set the logical core N to perform bit-rate calculation. > > Br, > yinan > > -----Original Message----- > > From: Mo, YufengX <yufengx.mo@intel.com> > > Sent: 2019年11月1日 15:07 > > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > > Cc: Mo, YufengX <yufengx.mo@intel.com> > > Subject: [dts][PATCH V3 1/3] ethtool_stats: update test plan > > > > > > use testpmd xstat data as reference data to check proc info tool xstat data. > > update test plan content. > > > > Signed-off-by: yufengmx <yufengx.mo@intel.com> > > --- > > test_plans/ethtool_stats_test_plan.rst | 66 > > ++++++++++++++++++-------- > > 1 file changed, 45 insertions(+), 21 deletions(-) > > > > diff --git a/test_plans/ethtool_stats_test_plan.rst > > b/test_plans/ethtool_stats_test_plan.rst > > index 13b5909..95f9e7a 100644 > > --- a/test_plans/ethtool_stats_test_plan.rst > > +++ b/test_plans/ethtool_stats_test_plan.rst > > @@ -47,13 +47,20 @@ that DPDK supports. The idea behind this epic is > > two fold as following. > > - the retrieval of aggregate stats upon request (Top level stats). > > - the retrieval of the extended NIC stats. > > - grouping of stats logically so they can be retrieved per logical > grouping. > > - - the option to enable/disable the stats groups to retrieve similar to set > > private flags in ethtool. > > + - the option to enable/disable the stats groups to retrieve similar to set > > + private flags in ethtool. > > > > Prerequisites > > ============= > > > > 2xNICs (2 full duplex optical ports per NIC). One on dut, another one > > on tester, -link them together. Update two nics' firmware to latest version. > > +link them together. Update two nics' firmware to latest version:: > > + > > + Tester DUT > > + .-------. .-------. > > + | port0 | <------------------> | port0 | > > + | port1 | <------------------> | port1 | > > + '-------' '-------' > > > > Test cases > > ========== > > @@ -64,8 +71,8 @@ bind two ports:: > > > > ./usertools/dpdk-devbind.py --bind=igb_uio <pci address 1> <pci > > address > > 2> > > > > -Test Case: xstat command set intergrity > > ---------------------------------------- > > +Test Case: xstat options > > +------------------------ > > > > check ``dpdk-procinfo`` tool support ``xstats`` command options. > > > > @@ -80,7 +87,11 @@ steps: > > > > #. boot up ``testpmd``:: > > > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i > > --port-topology=loop > > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i > > + --port-topology=loop > > + > > + testpmd> set fwd io > > + testpmd> clear port xstats all > > + testpmd> start > > > > #. run ``dpdk-procinfo`` tool:: > > > > @@ -88,25 +99,30 @@ steps: > > > > #. check ``dpdk-procinfo`` tool output should contain upper options. > > > > -Test Case: xstat command > > ------------------------- > > +Test Case: xstat statistic integrity > > +------------------------------------ > > > > -check if port extended statistics can get right data. > > +check if port extended statistics can access by xstat name or xstat id. > > > > steps: > > > > #. boot up ``testpmd``:: > > > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i > > --port-topology=loop > > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i > > + --port-topology=loop > > + > > + testpmd> set fwd io > > + testpmd> clear port xstats all > > + testpmd> start > > > > #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: > > > > sendp([Ether()/IP()/UDP()/Raw('\0'*60)], iface=<port 0 name>) > > > > -#. run ``dpdk-procinfo`` tool with ``xstats`` option and check if all port have > > - a correct data of different size packet:: > > +#. run ``dpdk-procinfo`` tool with ``xstats`` option and check if all ports > > + extended statistics can access by xstat name or xstat id:: > > > > - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats > > + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-id <N> > > + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name > > + <statistic > > + name> > > > > Test Case: xstat-reset command > > ------------------------------ > > @@ -117,7 +133,11 @@ steps: > > > > #. boot up ``testpmd``:: > > > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i > > --port-topology=loop > > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i > > + --port-topology=loop > > + > > + testpmd> set fwd io > > + testpmd> clear port xstats all > > + testpmd> start > > > > #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: > > > > @@ -132,24 +152,26 @@ Test Case: xstat single statistic > > --------------------------------- > > > > check if port extended statistic name can be get by statistic id and > > check -related data's correctness. > > +related data's correctness with testpmd xstat data. > > > > steps: > > > > #. boot up ``testpmd``:: > > > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i > > --port-topology=loop > > - > > -#. run ``dpdk-procinfo`` tool with ``xstats`` option to get all NIC extended > > - statistics parameters of port and use the output display sequence as > > parameter > > - index in the following search index:: > > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i > > + --port-topology=loop > > > > - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats > > + testpmd> set fwd io > > + testpmd> clear port xstats all > > + testpmd> start > > > > #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: > > > > sendp([Ether()/IP()/UDP()/Raw('\0'*60)], iface=<port 0 name>) > > > > +#. run test pmd ``show port xstats all`` to get testpmd port xstat data: > > + > > + testpmd> show port xstats all > > + > > #. run ``dpdk-procinfo`` tool with ``xstats-id`` option to get the statistic > > name corresponding with the index id:: > > > > @@ -158,4 +180,6 @@ steps: > > #. run ``dpdk-procinfo`` tool with ``xstats-name`` option to get the statistic > > data corresponding with the statistic name:: > > > > - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name <statistic > name> > > \ No newline at end of file > > + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name > > + <statistic > > + name> > > + > > +#. compare these proc info tool xstat values with testpmd xstat values. > > \ No newline at end of file > > -- > > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 1/3] ethtool_stats: update test plan 2019-11-01 7:06 ` [dts] [PATCH V3 1/3] ethtool_stats: " yufengmx 2019-11-12 15:34 ` Wang, Yinan @ 2019-11-13 2:20 ` Wang, Yinan 1 sibling, 0 replies; 15+ messages in thread From: Wang, Yinan @ 2019-11-13 2:20 UTC (permalink / raw) To: Mo, YufengX, dts Acked-by: Wang, Yinan <yinan.wang@intel.com> > -----Original Message----- > From: Mo, YufengX <yufengx.mo@intel.com> > Sent: 2019年11月1日 15:07 > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > Cc: Mo, YufengX <yufengx.mo@intel.com> > Subject: [dts][PATCH V3 1/3] ethtool_stats: update test plan > > > use testpmd xstat data as reference data to check proc info tool xstat data. > update test plan content. > > Signed-off-by: yufengmx <yufengx.mo@intel.com> > --- > test_plans/ethtool_stats_test_plan.rst | 66 ++++++++++++++++++-------- > 1 file changed, 45 insertions(+), 21 deletions(-) > > diff --git a/test_plans/ethtool_stats_test_plan.rst > b/test_plans/ethtool_stats_test_plan.rst > index 13b5909..95f9e7a 100644 > --- a/test_plans/ethtool_stats_test_plan.rst > +++ b/test_plans/ethtool_stats_test_plan.rst > @@ -47,13 +47,20 @@ that DPDK supports. The idea behind this epic is two > fold as following. > - the retrieval of aggregate stats upon request (Top level stats). > - the retrieval of the extended NIC stats. > - grouping of stats logically so they can be retrieved per logical grouping. > - - the option to enable/disable the stats groups to retrieve similar to set > private flags in ethtool. > + - the option to enable/disable the stats groups to retrieve similar to set > + private flags in ethtool. > > Prerequisites > ============= > > 2xNICs (2 full duplex optical ports per NIC). One on dut, another one on tester, > -link them together. Update two nics' firmware to latest version. > +link them together. Update two nics' firmware to latest version:: > + > + Tester DUT > + .-------. .-------. > + | port0 | <------------------> | port0 | > + | port1 | <------------------> | port1 | > + '-------' '-------' > > Test cases > ========== > @@ -64,8 +71,8 @@ bind two ports:: > > ./usertools/dpdk-devbind.py --bind=igb_uio <pci address 1> <pci address > 2> > > -Test Case: xstat command set intergrity > ---------------------------------------- > +Test Case: xstat options > +------------------------ > > check ``dpdk-procinfo`` tool support ``xstats`` command options. > > @@ -80,7 +87,11 @@ steps: > > #. boot up ``testpmd``:: > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i --port-topology=loop > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop > + > + testpmd> set fwd io > + testpmd> clear port xstats all > + testpmd> start > > #. run ``dpdk-procinfo`` tool:: > > @@ -88,25 +99,30 @@ steps: > > #. check ``dpdk-procinfo`` tool output should contain upper options. > > -Test Case: xstat command > ------------------------- > +Test Case: xstat statistic integrity > +------------------------------------ > > -check if port extended statistics can get right data. > +check if port extended statistics can access by xstat name or xstat id. > > steps: > > #. boot up ``testpmd``:: > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i --port-topology=loop > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop > + > + testpmd> set fwd io > + testpmd> clear port xstats all > + testpmd> start > > #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: > > sendp([Ether()/IP()/UDP()/Raw('\0'*60)], iface=<port 0 name>) > > -#. run ``dpdk-procinfo`` tool with ``xstats`` option and check if all port have > - a correct data of different size packet:: > +#. run ``dpdk-procinfo`` tool with ``xstats`` option and check if all ports > + extended statistics can access by xstat name or xstat id:: > > - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats > + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-id <N> > + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name <statistic > + name> > > Test Case: xstat-reset command > ------------------------------ > @@ -117,7 +133,11 @@ steps: > > #. boot up ``testpmd``:: > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i --port-topology=loop > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop > + > + testpmd> set fwd io > + testpmd> clear port xstats all > + testpmd> start > > #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: > > @@ -132,24 +152,26 @@ Test Case: xstat single statistic > --------------------------------- > > check if port extended statistic name can be get by statistic id and check > -related data's correctness. > +related data's correctness with testpmd xstat data. > > steps: > > #. boot up ``testpmd``:: > > - ./<target name>/app/testpmd -c 0x600006 -n 4 -- -i --port-topology=loop > - > -#. run ``dpdk-procinfo`` tool with ``xstats`` option to get all NIC extended > - statistics parameters of port and use the output display sequence as > parameter > - index in the following search index:: > + ./<target name>/app/testpmd -c 0x3 -n 4 -- -i --port-topology=loop > > - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats > + testpmd> set fwd io > + testpmd> clear port xstats all > + testpmd> start > > #. send udp packet of 64/72/128/256/512/1024 size to port 0/1:: > > sendp([Ether()/IP()/UDP()/Raw('\0'*60)], iface=<port 0 name>) > > +#. run test pmd ``show port xstats all`` to get testpmd port xstat data: > + > + testpmd> show port xstats all > + > #. run ``dpdk-procinfo`` tool with ``xstats-id`` option to get the statistic > name corresponding with the index id:: > > @@ -158,4 +180,6 @@ steps: > #. run ``dpdk-procinfo`` tool with ``xstats-name`` option to get the statistic > data corresponding with the statistic name:: > > - ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name <statistic name> > \ No newline at end of file > + ./<target name>/app/dpdk-procinfo -- -p 3 --xstats-name <statistic > + name> > + > +#. compare these proc info tool xstat values with testpmd xstat values. > \ No newline at end of file > -- > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [dts] [PATCH V3 2/3] ethtool_stats: add ethtool_stats_test_plan index label 2019-11-01 7:06 [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan yufengmx 2019-11-01 7:06 ` [dts] [PATCH V3 1/3] ethtool_stats: " yufengmx @ 2019-11-01 7:06 ` yufengmx 2019-11-12 16:00 ` Wang, Yinan 2019-11-01 7:06 ` [dts] [PATCH V3 3/3] ethtool_stats: add automation script yufengmx ` (2 subsequent siblings) 4 siblings, 1 reply; 15+ messages in thread From: yufengmx @ 2019-11-01 7:06 UTC (permalink / raw) To: dts, yinan.wang; +Cc: yufengmx add ethtool_stats_test_plan index label. Signed-off-by: yufengmx <yufengx.mo@intel.com> --- test_plans/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/test_plans/index.rst b/test_plans/index.rst index 4dde8e6..8d0691c 100644 --- a/test_plans/index.rst +++ b/test_plans/index.rst @@ -134,6 +134,7 @@ The following are the test plans for the DPDK DTS automated test system. compressdev_zlib_pmd_test_plan enable_package_download_in_ice_driver_test_plan multicast_test_plan + ethtool_stats_test_plan veb_switch_test_plan vf_daemon_test_plan -- 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 2/3] ethtool_stats: add ethtool_stats_test_plan index label 2019-11-01 7:06 ` [dts] [PATCH V3 2/3] ethtool_stats: add ethtool_stats_test_plan index label yufengmx @ 2019-11-12 16:00 ` Wang, Yinan 0 siblings, 0 replies; 15+ messages in thread From: Wang, Yinan @ 2019-11-12 16:00 UTC (permalink / raw) To: Mo, YufengX, dts Acked-by: Wang, Yinan <yinan.wang@intel.com> > -----Original Message----- > From: Mo, YufengX <yufengx.mo@intel.com> > Sent: 2019年11月1日 15:07 > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > Cc: Mo, YufengX <yufengx.mo@intel.com> > Subject: [dts][PATCH V3 2/3] ethtool_stats: add ethtool_stats_test_plan index > label > > > add ethtool_stats_test_plan index label. > > Signed-off-by: yufengmx <yufengx.mo@intel.com> > --- > test_plans/index.rst | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/test_plans/index.rst b/test_plans/index.rst index 4dde8e6..8d0691c > 100644 > --- a/test_plans/index.rst > +++ b/test_plans/index.rst > @@ -134,6 +134,7 @@ The following are the test plans for the DPDK DTS > automated test system. > compressdev_zlib_pmd_test_plan > enable_package_download_in_ice_driver_test_plan > multicast_test_plan > + ethtool_stats_test_plan > > veb_switch_test_plan > vf_daemon_test_plan > -- > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [dts] [PATCH V3 3/3] ethtool_stats: add automation script 2019-11-01 7:06 [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan yufengmx 2019-11-01 7:06 ` [dts] [PATCH V3 1/3] ethtool_stats: " yufengmx 2019-11-01 7:06 ` [dts] [PATCH V3 2/3] ethtool_stats: add ethtool_stats_test_plan index label yufengmx @ 2019-11-01 7:06 ` yufengmx 2019-11-12 15:38 ` Wang, Yinan 2019-11-12 16:00 ` [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan Wang, Yinan 2019-11-22 3:33 ` Tu, Lijuan 4 siblings, 1 reply; 15+ messages in thread From: yufengmx @ 2019-11-01 7:06 UTC (permalink / raw) To: dts, yinan.wang; +Cc: yufengmx Currently Ethtool supports a more complete list of stats for the same drivers that DPDK supports. The idea behind this epic is two fold as following: 1. To achieve metric equivalence with what linux's ethtool provides. 2. To extend the functionality of the xstats API to enable the following options: ## the retrieval of aggregate stats upon request (Top level stats). ## the retrieval of the extended NIC stats. ## grouping of stats logically so they can be retrieved per logical grouping. ## the option to enable/disable the stats groups to retrieve similar to set private flags in ethtool. Signed-off-by: yufengmx <yufengx.mo@intel.com> --- tests/TestSuite_ethtool_stats.py | 498 +++++++++++++++++++++++++++++++ 1 file changed, 498 insertions(+) create mode 100644 tests/TestSuite_ethtool_stats.py diff --git a/tests/TestSuite_ethtool_stats.py b/tests/TestSuite_ethtool_stats.py new file mode 100644 index 0000000..e8ea941 --- /dev/null +++ b/tests/TestSuite_ethtool_stats.py @@ -0,0 +1,498 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2019 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +''' +DPDK Test suite. +Test support of dpdk-procinfo tool feature +''' + +import re +import time +import os +import traceback + +from utils import create_mask as dts_create_mask +from test_case import TestCase +from pmd_output import PmdOutput +from exception import VerifyFailure + +from packet import Packet +from scapy.sendrecv import sendp +from settings import HEADER_SIZE + + +class TestEthtoolStats(TestCase): + + @property + def target_dir(self): + # get absolute directory of target source code + target_dir = '/root' + self.dut.base_dir[1:] \ + if self.dut.base_dir.startswith('~') else \ + self.dut.base_dir + return target_dir + + def d_a_con(self, cmd): + _cmd = [cmd, '# ', 10] if isinstance(cmd, (str, unicode)) else cmd + output = self.dut.alt_session.send_expect(*_cmd) + output2 = self.dut.alt_session.session.get_session_before(1) + return output + os.linesep + output2 + + def send_packet(self, pkt_config, src_intf): + for pkt_type in pkt_config.keys(): + pkt = Packet(pkt_type=pkt_type) + # set packet every layer's input parameters + if 'layer_configs' in pkt_config[pkt_type].keys(): + pkt_configs = pkt_config[pkt_type]['layer_configs'] + if pkt_configs: + for layer in pkt_configs.keys(): + pkt.config_layer(layer, pkt_configs[layer]) + pkt.send_pkt(crb=self.tester, tx_port=src_intf, count=1) + time.sleep(1) + + def traffic(self): + # make sure interface in link up status + src_intf, src_mac = self.link_topo + cmd = "ifconfig {0} up".format(src_intf) + self.d_a_con(cmd) + # send out packet + for frame_size in self.frame_sizes: + headers_size = sum( + map(lambda x: HEADER_SIZE[x], ['eth', 'ip', 'udp'])) + payload_size = frame_size - headers_size + config_layers = { + 'ether': {'src': src_mac}, + 'raw': {'payload': ['58'] * payload_size}} + pkt_config = {'UDP': {'layer_configs': config_layers}} + self.send_packet(pkt_config, src_intf) + + def init_testpmd(self): + self.testpmd = PmdOutput(self.dut) + self.is_pmd_on = False + + def start_testpmd(self): + self.testpmd.start_testpmd('1S/2C/1T', param='--port-topology=loop') + self.is_pmd_on = True + time.sleep(2) + + def set_testpmd(self): + cmds = [ + 'set fwd io', + 'clear port xstats all', + 'start'] + [self.testpmd.execute_cmd(cmd) for cmd in cmds] + time.sleep(2) + + def close_testpmd(self): + if not self.is_pmd_on: + return + self.testpmd.quit() + self.is_pmd_on = False + + def get_pmd_xstat_data(self): + ''' get testpmd nic extended statistics ''' + cmd = 'show port xstats all' + output = self.testpmd.execute_cmd(cmd) + if "statistics" not in output: + self.logger.error(output) + raise Exception("failed to get port extended statistics data") + data_str = output.splitlines() + port_xstat = {} + cur_port = None + pat = r".*extended statistics for port (\d+).*" + for line in data_str: + if not line.strip(): + continue + if "statistics" in line: + result = re.findall(pat, line.strip()) + if len(result): + cur_port = result[0] + elif cur_port is not None and ": " in line: + if cur_port not in port_xstat: + port_xstat[cur_port] = {} + result = line.strip().split(": ") + if len(result) == 2 and result[0]: + name, value = result + port_xstat[cur_port][name] = value + else: + raise Exception("invalid data") + + return port_xstat + + def clear_pmd_ports_stat(self): + options = ["--xstats-reset ", "--stats-reset "] + for option in options: + cmd = self.dpdk_proc_info + " %s" % option + self.d_a_con(cmd) + time.sleep(1) + + def init_proc_info(self): + ports_count = len(self.dut_ports) + ports_mask = reduce(lambda x, y: x | y, + map(lambda x: 0x1 << x, range(ports_count))) + self.query_tool = os.path.join( + self.target_dir, self.target, 'app', 'dpdk-procinfo') + self.dpdk_proc_info = "%s -v -- -p %s" % (self.query_tool, ports_mask) + + def parse_proc_info_xstat_output(self, msg): + if "statistics" not in msg: + self.logger.error(msg) + raise VerifyFailure("get port statistics data failed") + + port_xstat = {} + cur_port = None + pat = ".*for port (\d)+ .*" + data_str = msg.splitlines() + for line in data_str: + if not line.strip(): + continue + if "statistics" in line: + result = re.findall(pat, line.strip()) + if len(result): + cur_port = result[0] + elif cur_port is not None and ": " in line: + if cur_port not in port_xstat: + port_xstat[cur_port] = {} + result = line.strip().split(": ") + if len(result) == 2 and result[0]: + name, value = result + port_xstat[cur_port][name] = value + else: + raise VerifyFailure("invalid data") + + return port_xstat + + def query_dpdk_xstat_all(self, option="xstats"): + cmd = self.dpdk_proc_info + " --%s" % (option) + output = self.d_a_con(cmd) + infos = self.parse_proc_info_xstat_output(output) + if not infos: + msg = 'get xstat data failed' + raise VerifyFailure(msg) + return infos + + def get_xstat_statistic_id(self, sub_option): + option = "xstats-name" + execept_msgs = [] + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) + msg = self.d_a_con(cmd) + sub_stat_data = self.parse_proc_info_xstat_output(msg) + if sub_option not in msg or not len(sub_stat_data): + execept_msgs.append([option, msg]) + else: + for port in sub_stat_data: + if sub_option not in sub_stat_data[port]: + msg = "{0} {1} data doesn't existed".format( + port, sub_option) + self.logger.error(msg) + continue + if not port: + msg1 = "port {0} [{1}]".format(port, sub_option) + execept_msgs.append([msg1, msg2]) + continue + return sub_stat_data, execept_msgs + + def check_single_stats_result(self, sub_stat_data, all_xstat_data): + execept_msgs = [] + for port, infos in sub_stat_data.items(): + for item in infos: + if not port or \ + port not in all_xstat_data or \ + item not in all_xstat_data[port] or \ + sub_stat_data[port][item] != all_xstat_data[port][item]: + msg1 = "port {0} [{1}]".format(port, item) + msg2 = "expect {0} ".format(all_xstat_data[port][item]) + \ + "show {0}".format(sub_stat_data[port][item]) + execept_msgs.append([msg1, msg2]) + continue + msg2 = "expect {0} ".format(all_xstat_data[port][item]) + \ + "show {0}".format(sub_stat_data[port][item]) + self.logger.info(msg2) + return execept_msgs + + def get_xstat_single_statistic(self, stat, all_xstat_data): + option = "xstats-id" + execept_msgs = [] + for id in stat.values(): + cmd = self.dpdk_proc_info + " --%s %s" % (option, id) + msg = self.d_a_con(cmd) + sub_stat_data = self.parse_proc_info_xstat_output(msg) + if not sub_stat_data or not len(sub_stat_data): + execept_msgs.append([option, msg]) + else: + execept_msgs += self.check_single_stats_result( + sub_stat_data, all_xstat_data) + if len(execept_msgs): + for msgs in execept_msgs: + self.logger.error(msgs[0]) + self.logger.info(msgs[1]) + raise VerifyFailure("query data exception ") + + self.logger.info("all port is correct") + + time.sleep(1) + + def check_xstat_command_list(self): + output = self.d_a_con(self.query_tool) + expected_command = [ + "xstats-reset", + "xstats-name NAME", + "xstats-ids IDLIST", + "xstats-reset"] + pat = ".*--(.*):.*" + handle = re.compile(pat) + result = handle.findall(output) + if not result or len(result) == 0: + cmds = " | ".join(expected_command) + msg = "expected commands {0} have not been included".format(cmds) + raise VerifyFailure(msg) + missing_cmds = [] + for cmd in expected_command: + if cmd not in result: + missing_cmds.append(cmd) + + if len(missing_cmds): + msg = " | ".join(missing_cmds) + " have not been included" + raise VerifyFailure(msg) + + cmds = " | ".join(expected_command) + msg = "expected commands {0} have been included".format(cmds) + self.logger.info(msg) + + def check_xstat_reset_status(self): + all_xstat_data = self.query_dpdk_xstat_all() + execept_msgs = [] + for port in all_xstat_data: + stats_info = all_xstat_data[port] + for stat_name, value in stats_info.items(): + if int(value) != 0: + msg = "port {0} <{1}> [{2}] has not been reset" + execept_msgs.append(msg.format(port, stat_name, value)) + if len(execept_msgs): + self.logger.info(os.linesep.join(execept_msgs)) + raise VerifyFailure("xstat-reset failed") + + self.logger.info("xstat-reset success !") + + def check_xstat_id_cmd(self, all_xstat_data): + execept_msgs = [] + option = "xstats-id" + sub_option = reduce(lambda x, y: str(x) + "," + str(y), + range(len(all_xstat_data['0'].keys()))) + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) + msg = self.d_a_con(cmd) + sub_stat_data = self.parse_proc_info_xstat_output(msg) + if not sub_stat_data or not len(sub_stat_data): + execept_msgs.append([option, msg]) + else: + for port, infos in sub_stat_data.items(): + for item in infos: + if not port or \ + port not in all_xstat_data or \ + item not in all_xstat_data[port]: + msg1 = "port {0} get [{1}] failed".format( + port, item) + execept_msgs.append([msg1]) + continue + if len(execept_msgs): + for msgs in execept_msgs: + self.logger.error(msgs[0]) + raise VerifyFailure("query data exception ") + + self.logger.info("all ports stat id can get") + time.sleep(1) + + def check_xstat_name_cmd(self, all_xstat_data): + option = "xstats-name" + _sub_options = all_xstat_data['0'].keys() + execept_msgs = [] + for sub_option in _sub_options: + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) + msg = self.d_a_con(cmd) + sub_stat_data = self.parse_proc_info_xstat_output(msg) + if sub_option not in msg or not len(sub_stat_data): + execept_msgs.append([option, msg]) + else: + for port in sub_stat_data: + if sub_option not in sub_stat_data[port]: + msg = "{0} {1} data doesn't existed".format( + port, sub_option) + self.logger.error(msg) + continue + if not port or \ + port not in all_xstat_data or \ + sub_option not in all_xstat_data[port]: + msg1 = "port {0} [{1}]".format(port, sub_option) + execept_msgs.append([msg1]) + continue + if len(execept_msgs): + for msgs in execept_msgs: + self.logger.error(msgs[0]) + self.logger.info(msgs[1]) + raise VerifyFailure("query data exception ") + + self.logger.info("all port's stat value can get") + + def check_xstat_statistic_integrity(self, sub_options_ex=None): + all_xstat_data = self.query_dpdk_xstat_all() + self.check_xstat_id_cmd(all_xstat_data) + self.check_xstat_name_cmd(all_xstat_data) + + def check_xstat_single_statistic(self, sub_options_ex=None): + all_xstat_data = self.get_pmd_xstat_data() + self.logger.info("total stat names [%d]" % len(all_xstat_data['0'])) + for stat_name in all_xstat_data['0'].keys(): + # firstly, get statistic name. + stats, execept_msgs = self.get_xstat_statistic_id(stat_name) + if len(execept_msgs): + for msgs in execept_msgs: + self.logger.error(msgs[0]) + self.logger.info(msgs[1]) + continue + self.logger.info(stat_name) + self.get_xstat_single_statistic(stats['0'], all_xstat_data) + + def verify_xstat_command_options(self): + ''' test xstat command set integrity ''' + except_content = None + try: + self.start_testpmd() + self.set_testpmd() + self.check_xstat_command_list() + except Exception as e: + self.logger.error(traceback.format_exc()) + except_content = e + finally: + self.close_testpmd() + + # re-raise verify exception result + if except_content: + raise VerifyFailure(except_content) + + def verify_xstat_reset(self): + ''' test xstat-reset command ''' + except_content = None + try: + self.start_testpmd() + self.set_testpmd() + self.traffic() + self.clear_pmd_ports_stat() + self.check_xstat_reset_status() + except Exception as e: + self.logger.error(traceback.format_exc()) + except_content = e + finally: + self.close_testpmd() + + # re-raise verify exception result + if except_content: + raise VerifyFailure(except_content) + + def verify_xstat_integrity(self): + ''' test xstat command ''' + except_content = None + try: + self.start_testpmd() + self.set_testpmd() + self.check_xstat_statistic_integrity() + except Exception as e: + self.logger.error(traceback.format_exc()) + except_content = e + finally: + self.close_testpmd() + + # re-raise verify exception result + if except_content: + raise VerifyFailure(except_content) + + def verify_xstat_single_statistic(self): + except_content = None + try: + self.start_testpmd() + self.set_testpmd() + self.clear_pmd_ports_stat() + self.traffic() + self.check_xstat_single_statistic() + except Exception as e: + self.logger.error(traceback.format_exc()) + except_content = e + finally: + self.close_testpmd() + + # re-raise verify exception result + if except_content: + raise VerifyFailure(except_content) + + def preset_test_environment(self): + self.is_pmd_on = None + # get link port pairs + port_num = 0 + local_port = self.tester.get_local_port(port_num) + self.link_topo = [ + self.tester.get_interface(local_port), + self.tester.get_mac(local_port)] + # set packet sizes for testing different type + self.frame_sizes = [64, 72, 128, 256, 512, 1024] + # init binary + self.init_testpmd() + self.init_proc_info() + # + # Test cases. + # + + def set_up_all(self): + self.dut_ports = self.dut.get_ports(self.nic) + self.verify(len(self.dut_ports) >= 1, 'Insufficient ports') + self.preset_test_environment() + + def set_up(self): + pass + + def tear_down(self): + pass + + def tear_down_all(self): + pass + + def test_xstat(self): + ''' test xstat command set integrity ''' + self.verify_xstat_command_options() + + def test_xstat_integrity(self): + ''' test xstat date types ''' + self.verify_xstat_integrity() + + def test_xstat_reset(self): + ''' test xstat-reset command ''' + self.verify_xstat_reset() + + def test_xstat_single_statistic(self): + ''' test xstat single data type ''' + self.verify_xstat_single_statistic() -- 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 3/3] ethtool_stats: add automation script 2019-11-01 7:06 ` [dts] [PATCH V3 3/3] ethtool_stats: add automation script yufengmx @ 2019-11-12 15:38 ` Wang, Yinan 2019-11-12 16:02 ` Wang, Yinan 2019-11-13 1:10 ` Mo, YufengX 0 siblings, 2 replies; 15+ messages in thread From: Wang, Yinan @ 2019-11-12 15:38 UTC (permalink / raw) To: Mo, YufengX, dts Hi Yufeng, As discussion, may need add below points: #. add a callback function in pktgen_base class, execute this callback function and query pktgen statistics data at a custom interval. #. implemented automation for ethtool by using this callback function #. Add parameter refer test plan change Br, yinan > -----Original Message----- > From: Mo, YufengX <yufengx.mo@intel.com> > Sent: 2019年11月1日 15:07 > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > Cc: Mo, YufengX <yufengx.mo@intel.com> > Subject: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > > Currently Ethtool supports a more complete list of stats for the same drivers > that DPDK supports. The idea behind this epic is two fold as following: > 1. To achieve metric equivalence with what linux's ethtool provides. > 2. To extend the functionality of the xstats API to enable the following options: > ## the retrieval of aggregate stats upon request (Top level stats). > ## the retrieval of the extended NIC stats. > ## grouping of stats logically so they can be retrieved per logical grouping. > ## the option to enable/disable the stats groups to retrieve similar to set > private flags in ethtool. > > Signed-off-by: yufengmx <yufengx.mo@intel.com> > --- > tests/TestSuite_ethtool_stats.py | 498 > +++++++++++++++++++++++++++++++ > 1 file changed, 498 insertions(+) > create mode 100644 tests/TestSuite_ethtool_stats.py > > diff --git a/tests/TestSuite_ethtool_stats.py b/tests/TestSuite_ethtool_stats.py > new file mode 100644 > index 0000000..e8ea941 > --- /dev/null > +++ b/tests/TestSuite_ethtool_stats.py > @@ -0,0 +1,498 @@ > +# BSD LICENSE > +# > +# Copyright(c) 2010-2019 Intel Corporation. All rights reserved. > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without # > +modification, are permitted provided that the following conditions # > +are met: > +# > +# * Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# * Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in > +# the documentation and/or other materials provided with the > +# distribution. > +# * Neither the name of Intel Corporation nor the names of its > +# contributors may be used to endorse or promote products derived > +# from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS # > +'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # > +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS > FOR # > +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > COPYRIGHT # > +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > INCIDENTAL, # > +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > # > +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > USE, # > +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > ON ANY # > +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # > +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE > USE # > +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > + > +''' > +DPDK Test suite. > +Test support of dpdk-procinfo tool feature ''' > + > +import re > +import time > +import os > +import traceback > + > +from utils import create_mask as dts_create_mask from test_case import > +TestCase from pmd_output import PmdOutput from exception import > +VerifyFailure > + > +from packet import Packet > +from scapy.sendrecv import sendp > +from settings import HEADER_SIZE > + > + > +class TestEthtoolStats(TestCase): > + > + @property > + def target_dir(self): > + # get absolute directory of target source code > + target_dir = '/root' + self.dut.base_dir[1:] \ > + if self.dut.base_dir.startswith('~') else \ > + self.dut.base_dir > + return target_dir > + > + def d_a_con(self, cmd): > + _cmd = [cmd, '# ', 10] if isinstance(cmd, (str, unicode)) else cmd > + output = self.dut.alt_session.send_expect(*_cmd) > + output2 = self.dut.alt_session.session.get_session_before(1) > + return output + os.linesep + output2 > + > + def send_packet(self, pkt_config, src_intf): > + for pkt_type in pkt_config.keys(): > + pkt = Packet(pkt_type=pkt_type) > + # set packet every layer's input parameters > + if 'layer_configs' in pkt_config[pkt_type].keys(): > + pkt_configs = pkt_config[pkt_type]['layer_configs'] > + if pkt_configs: > + for layer in pkt_configs.keys(): > + pkt.config_layer(layer, pkt_configs[layer]) > + pkt.send_pkt(crb=self.tester, tx_port=src_intf, count=1) > + time.sleep(1) > + > + def traffic(self): > + # make sure interface in link up status > + src_intf, src_mac = self.link_topo > + cmd = "ifconfig {0} up".format(src_intf) > + self.d_a_con(cmd) > + # send out packet > + for frame_size in self.frame_sizes: > + headers_size = sum( > + map(lambda x: HEADER_SIZE[x], ['eth', 'ip', 'udp'])) > + payload_size = frame_size - headers_size > + config_layers = { > + 'ether': {'src': src_mac}, > + 'raw': {'payload': ['58'] * payload_size}} > + pkt_config = {'UDP': {'layer_configs': config_layers}} > + self.send_packet(pkt_config, src_intf) > + > + def init_testpmd(self): > + self.testpmd = PmdOutput(self.dut) > + self.is_pmd_on = False > + > + def start_testpmd(self): > + self.testpmd.start_testpmd('1S/2C/1T', > param='--port-topology=loop') > + self.is_pmd_on = True > + time.sleep(2) > + > + def set_testpmd(self): > + cmds = [ > + 'set fwd io', > + 'clear port xstats all', > + 'start'] > + [self.testpmd.execute_cmd(cmd) for cmd in cmds] > + time.sleep(2) > + > + def close_testpmd(self): > + if not self.is_pmd_on: > + return > + self.testpmd.quit() > + self.is_pmd_on = False > + > + def get_pmd_xstat_data(self): > + ''' get testpmd nic extended statistics ''' > + cmd = 'show port xstats all' > + output = self.testpmd.execute_cmd(cmd) > + if "statistics" not in output: > + self.logger.error(output) > + raise Exception("failed to get port extended statistics data") > + data_str = output.splitlines() > + port_xstat = {} > + cur_port = None > + pat = r".*extended statistics for port (\d+).*" > + for line in data_str: > + if not line.strip(): > + continue > + if "statistics" in line: > + result = re.findall(pat, line.strip()) > + if len(result): > + cur_port = result[0] > + elif cur_port is not None and ": " in line: > + if cur_port not in port_xstat: > + port_xstat[cur_port] = {} > + result = line.strip().split(": ") > + if len(result) == 2 and result[0]: > + name, value = result > + port_xstat[cur_port][name] = value > + else: > + raise Exception("invalid data") > + > + return port_xstat > + > + def clear_pmd_ports_stat(self): > + options = ["--xstats-reset ", "--stats-reset "] > + for option in options: > + cmd = self.dpdk_proc_info + " %s" % option > + self.d_a_con(cmd) > + time.sleep(1) > + > + def init_proc_info(self): > + ports_count = len(self.dut_ports) > + ports_mask = reduce(lambda x, y: x | y, > + map(lambda x: 0x1 << x, > range(ports_count))) > + self.query_tool = os.path.join( > + self.target_dir, self.target, 'app', 'dpdk-procinfo') > + self.dpdk_proc_info = "%s -v -- -p %s" % (self.query_tool, > + ports_mask) > + > + def parse_proc_info_xstat_output(self, msg): > + if "statistics" not in msg: > + self.logger.error(msg) > + raise VerifyFailure("get port statistics data failed") > + > + port_xstat = {} > + cur_port = None > + pat = ".*for port (\d)+ .*" > + data_str = msg.splitlines() > + for line in data_str: > + if not line.strip(): > + continue > + if "statistics" in line: > + result = re.findall(pat, line.strip()) > + if len(result): > + cur_port = result[0] > + elif cur_port is not None and ": " in line: > + if cur_port not in port_xstat: > + port_xstat[cur_port] = {} > + result = line.strip().split(": ") > + if len(result) == 2 and result[0]: > + name, value = result > + port_xstat[cur_port][name] = value > + else: > + raise VerifyFailure("invalid data") > + > + return port_xstat > + > + def query_dpdk_xstat_all(self, option="xstats"): > + cmd = self.dpdk_proc_info + " --%s" % (option) > + output = self.d_a_con(cmd) > + infos = self.parse_proc_info_xstat_output(output) > + if not infos: > + msg = 'get xstat data failed' > + raise VerifyFailure(msg) > + return infos > + > + def get_xstat_statistic_id(self, sub_option): > + option = "xstats-name" > + execept_msgs = [] > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > + msg = self.d_a_con(cmd) > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > + if sub_option not in msg or not len(sub_stat_data): > + execept_msgs.append([option, msg]) > + else: > + for port in sub_stat_data: > + if sub_option not in sub_stat_data[port]: > + msg = "{0} {1} data doesn't existed".format( > + port, sub_option) > + self.logger.error(msg) > + continue > + if not port: > + msg1 = "port {0} [{1}]".format(port, sub_option) > + execept_msgs.append([msg1, msg2]) > + continue > + return sub_stat_data, execept_msgs > + > + def check_single_stats_result(self, sub_stat_data, all_xstat_data): > + execept_msgs = [] > + for port, infos in sub_stat_data.items(): > + for item in infos: > + if not port or \ > + port not in all_xstat_data or \ > + item not in all_xstat_data[port] or \ > + sub_stat_data[port][item] != all_xstat_data[port][item]: > + msg1 = "port {0} [{1}]".format(port, item) > + msg2 = "expect {0} ".format(all_xstat_data[port][item]) > + \ > + "show {0}".format(sub_stat_data[port][item]) > + execept_msgs.append([msg1, msg2]) > + continue > + msg2 = "expect {0} ".format(all_xstat_data[port][item]) + \ > + "show {0}".format(sub_stat_data[port][item]) > + self.logger.info(msg2) > + return execept_msgs > + > + def get_xstat_single_statistic(self, stat, all_xstat_data): > + option = "xstats-id" > + execept_msgs = [] > + for id in stat.values(): > + cmd = self.dpdk_proc_info + " --%s %s" % (option, id) > + msg = self.d_a_con(cmd) > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > + if not sub_stat_data or not len(sub_stat_data): > + execept_msgs.append([option, msg]) > + else: > + execept_msgs += self.check_single_stats_result( > + sub_stat_data, all_xstat_data) > + if len(execept_msgs): > + for msgs in execept_msgs: > + self.logger.error(msgs[0]) > + self.logger.info(msgs[1]) > + raise VerifyFailure("query data exception ") > + > + self.logger.info("all port is correct") > + > + time.sleep(1) > + > + def check_xstat_command_list(self): > + output = self.d_a_con(self.query_tool) > + expected_command = [ > + "xstats-reset", > + "xstats-name NAME", > + "xstats-ids IDLIST", > + "xstats-reset"] > + pat = ".*--(.*):.*" > + handle = re.compile(pat) > + result = handle.findall(output) > + if not result or len(result) == 0: > + cmds = " | ".join(expected_command) > + msg = "expected commands {0} have not been > included".format(cmds) > + raise VerifyFailure(msg) > + missing_cmds = [] > + for cmd in expected_command: > + if cmd not in result: > + missing_cmds.append(cmd) > + > + if len(missing_cmds): > + msg = " | ".join(missing_cmds) + " have not been included" > + raise VerifyFailure(msg) > + > + cmds = " | ".join(expected_command) > + msg = "expected commands {0} have been included".format(cmds) > + self.logger.info(msg) > + > + def check_xstat_reset_status(self): > + all_xstat_data = self.query_dpdk_xstat_all() > + execept_msgs = [] > + for port in all_xstat_data: > + stats_info = all_xstat_data[port] > + for stat_name, value in stats_info.items(): > + if int(value) != 0: > + msg = "port {0} <{1}> [{2}] has not been reset" > + execept_msgs.append(msg.format(port, stat_name, > value)) > + if len(execept_msgs): > + self.logger.info(os.linesep.join(execept_msgs)) > + raise VerifyFailure("xstat-reset failed") > + > + self.logger.info("xstat-reset success !") > + > + def check_xstat_id_cmd(self, all_xstat_data): > + execept_msgs = [] > + option = "xstats-id" > + sub_option = reduce(lambda x, y: str(x) + "," + str(y), > + range(len(all_xstat_data['0'].keys()))) > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > + msg = self.d_a_con(cmd) > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > + if not sub_stat_data or not len(sub_stat_data): > + execept_msgs.append([option, msg]) > + else: > + for port, infos in sub_stat_data.items(): > + for item in infos: > + if not port or \ > + port not in all_xstat_data or \ > + item not in all_xstat_data[port]: > + msg1 = "port {0} get [{1}] failed".format( > + port, item) > + execept_msgs.append([msg1]) > + continue > + if len(execept_msgs): > + for msgs in execept_msgs: > + self.logger.error(msgs[0]) > + raise VerifyFailure("query data exception ") > + > + self.logger.info("all ports stat id can get") > + time.sleep(1) > + > + def check_xstat_name_cmd(self, all_xstat_data): > + option = "xstats-name" > + _sub_options = all_xstat_data['0'].keys() > + execept_msgs = [] > + for sub_option in _sub_options: > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > + msg = self.d_a_con(cmd) > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > + if sub_option not in msg or not len(sub_stat_data): > + execept_msgs.append([option, msg]) > + else: > + for port in sub_stat_data: > + if sub_option not in sub_stat_data[port]: > + msg = "{0} {1} data doesn't existed".format( > + port, sub_option) > + self.logger.error(msg) > + continue > + if not port or \ > + port not in all_xstat_data or \ > + sub_option not in all_xstat_data[port]: > + msg1 = "port {0} [{1}]".format(port, sub_option) > + execept_msgs.append([msg1]) > + continue > + if len(execept_msgs): > + for msgs in execept_msgs: > + self.logger.error(msgs[0]) > + self.logger.info(msgs[1]) > + raise VerifyFailure("query data exception ") > + > + self.logger.info("all port's stat value can get") > + > + def check_xstat_statistic_integrity(self, sub_options_ex=None): > + all_xstat_data = self.query_dpdk_xstat_all() > + self.check_xstat_id_cmd(all_xstat_data) > + self.check_xstat_name_cmd(all_xstat_data) > + > + def check_xstat_single_statistic(self, sub_options_ex=None): > + all_xstat_data = self.get_pmd_xstat_data() > + self.logger.info("total stat names [%d]" % len(all_xstat_data['0'])) > + for stat_name in all_xstat_data['0'].keys(): > + # firstly, get statistic name. > + stats, execept_msgs = self.get_xstat_statistic_id(stat_name) > + if len(execept_msgs): > + for msgs in execept_msgs: > + self.logger.error(msgs[0]) > + self.logger.info(msgs[1]) > + continue > + self.logger.info(stat_name) > + self.get_xstat_single_statistic(stats['0'], all_xstat_data) > + > + def verify_xstat_command_options(self): > + ''' test xstat command set integrity ''' > + except_content = None > + try: > + self.start_testpmd() > + self.set_testpmd() > + self.check_xstat_command_list() > + except Exception as e: > + self.logger.error(traceback.format_exc()) > + except_content = e > + finally: > + self.close_testpmd() > + > + # re-raise verify exception result > + if except_content: > + raise VerifyFailure(except_content) > + > + def verify_xstat_reset(self): > + ''' test xstat-reset command ''' > + except_content = None > + try: > + self.start_testpmd() > + self.set_testpmd() > + self.traffic() > + self.clear_pmd_ports_stat() > + self.check_xstat_reset_status() > + except Exception as e: > + self.logger.error(traceback.format_exc()) > + except_content = e > + finally: > + self.close_testpmd() > + > + # re-raise verify exception result > + if except_content: > + raise VerifyFailure(except_content) > + > + def verify_xstat_integrity(self): > + ''' test xstat command ''' > + except_content = None > + try: > + self.start_testpmd() > + self.set_testpmd() > + self.check_xstat_statistic_integrity() > + except Exception as e: > + self.logger.error(traceback.format_exc()) > + except_content = e > + finally: > + self.close_testpmd() > + > + # re-raise verify exception result > + if except_content: > + raise VerifyFailure(except_content) > + > + def verify_xstat_single_statistic(self): > + except_content = None > + try: > + self.start_testpmd() > + self.set_testpmd() > + self.clear_pmd_ports_stat() > + self.traffic() > + self.check_xstat_single_statistic() > + except Exception as e: > + self.logger.error(traceback.format_exc()) > + except_content = e > + finally: > + self.close_testpmd() > + > + # re-raise verify exception result > + if except_content: > + raise VerifyFailure(except_content) > + > + def preset_test_environment(self): > + self.is_pmd_on = None > + # get link port pairs > + port_num = 0 > + local_port = self.tester.get_local_port(port_num) > + self.link_topo = [ > + self.tester.get_interface(local_port), > + self.tester.get_mac(local_port)] > + # set packet sizes for testing different type > + self.frame_sizes = [64, 72, 128, 256, 512, 1024] > + # init binary > + self.init_testpmd() > + self.init_proc_info() > + # > + # Test cases. > + # > + > + def set_up_all(self): > + self.dut_ports = self.dut.get_ports(self.nic) > + self.verify(len(self.dut_ports) >= 1, 'Insufficient ports') > + self.preset_test_environment() > + > + def set_up(self): > + pass > + > + def tear_down(self): > + pass > + > + def tear_down_all(self): > + pass > + > + def test_xstat(self): > + ''' test xstat command set integrity ''' > + self.verify_xstat_command_options() > + > + def test_xstat_integrity(self): > + ''' test xstat date types ''' > + self.verify_xstat_integrity() > + > + def test_xstat_reset(self): > + ''' test xstat-reset command ''' > + self.verify_xstat_reset() > + > + def test_xstat_single_statistic(self): > + ''' test xstat single data type ''' > + self.verify_xstat_single_statistic() > -- > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 3/3] ethtool_stats: add automation script 2019-11-12 15:38 ` Wang, Yinan @ 2019-11-12 16:02 ` Wang, Yinan 2019-11-13 1:10 ` Mo, YufengX 1 sibling, 0 replies; 15+ messages in thread From: Wang, Yinan @ 2019-11-12 16:02 UTC (permalink / raw) To: Mo, YufengX, 'dts@dpdk.org' Acked-by: Wang, Yinan <yinan.wang@intel.com> Sorry, pls ignore below comment as it’s for another tests. > -----Original Message----- > From: Wang, Yinan > Sent: 2019年11月12日 23:39 > To: Mo, YufengX <yufengx.mo@intel.com>; dts@dpdk.org > Subject: RE: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > Hi Yufeng, > > As discussion, may need add below points: > #. add a callback function in pktgen_base class, execute this callback function > and query pktgen statistics data at a custom interval. > #. implemented automation for ethtool by using this callback function #. Add > parameter refer test plan change > > Br, > yinan > > -----Original Message----- > > From: Mo, YufengX <yufengx.mo@intel.com> > > Sent: 2019年11月1日 15:07 > > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > > Cc: Mo, YufengX <yufengx.mo@intel.com> > > Subject: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > > > > > Currently Ethtool supports a more complete list of stats for the same > > drivers that DPDK supports. The idea behind this epic is two fold as following: > > 1. To achieve metric equivalence with what linux's ethtool provides. > > 2. To extend the functionality of the xstats API to enable the following > options: > > ## the retrieval of aggregate stats upon request (Top level stats). > > ## the retrieval of the extended NIC stats. > > ## grouping of stats logically so they can be retrieved per logical > grouping. > > ## the option to enable/disable the stats groups to retrieve similar to set > > private flags in ethtool. > > > > Signed-off-by: yufengmx <yufengx.mo@intel.com> > > --- > > tests/TestSuite_ethtool_stats.py | 498 > > +++++++++++++++++++++++++++++++ > > 1 file changed, 498 insertions(+) > > create mode 100644 tests/TestSuite_ethtool_stats.py > > > > diff --git a/tests/TestSuite_ethtool_stats.py > > b/tests/TestSuite_ethtool_stats.py > > new file mode 100644 > > index 0000000..e8ea941 > > --- /dev/null > > +++ b/tests/TestSuite_ethtool_stats.py > > @@ -0,0 +1,498 @@ > > +# BSD LICENSE > > +# > > +# Copyright(c) 2010-2019 Intel Corporation. All rights reserved. > > +# All rights reserved. > > +# > > +# Redistribution and use in source and binary forms, with or without > > +# modification, are permitted provided that the following conditions > > +# are met: > > +# > > +# * Redistributions of source code must retain the above copyright > > +# notice, this list of conditions and the following disclaimer. > > +# * Redistributions in binary form must reproduce the above copyright > > +# notice, this list of conditions and the following disclaimer in > > +# the documentation and/or other materials provided with the > > +# distribution. > > +# * Neither the name of Intel Corporation nor the names of its > > +# contributors may be used to endorse or promote products derived > > +# from this software without specific prior written permission. > > +# > > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > > CONTRIBUTORS # > > +'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # > > +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS > > FOR # > > +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > > COPYRIGHT # > > +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > > INCIDENTAL, # > > +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > NOT > > # > > +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > > USE, # > > +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > > ON ANY # > > +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # > > +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > THE > > USE # > > +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > > DAMAGE. > > + > > +''' > > +DPDK Test suite. > > +Test support of dpdk-procinfo tool feature ''' > > + > > +import re > > +import time > > +import os > > +import traceback > > + > > +from utils import create_mask as dts_create_mask from test_case > > +import TestCase from pmd_output import PmdOutput from exception > > +import VerifyFailure > > + > > +from packet import Packet > > +from scapy.sendrecv import sendp > > +from settings import HEADER_SIZE > > + > > + > > +class TestEthtoolStats(TestCase): > > + > > + @property > > + def target_dir(self): > > + # get absolute directory of target source code > > + target_dir = '/root' + self.dut.base_dir[1:] \ > > + if self.dut.base_dir.startswith('~') else \ > > + self.dut.base_dir > > + return target_dir > > + > > + def d_a_con(self, cmd): > > + _cmd = [cmd, '# ', 10] if isinstance(cmd, (str, unicode)) else cmd > > + output = self.dut.alt_session.send_expect(*_cmd) > > + output2 = self.dut.alt_session.session.get_session_before(1) > > + return output + os.linesep + output2 > > + > > + def send_packet(self, pkt_config, src_intf): > > + for pkt_type in pkt_config.keys(): > > + pkt = Packet(pkt_type=pkt_type) > > + # set packet every layer's input parameters > > + if 'layer_configs' in pkt_config[pkt_type].keys(): > > + pkt_configs = pkt_config[pkt_type]['layer_configs'] > > + if pkt_configs: > > + for layer in pkt_configs.keys(): > > + pkt.config_layer(layer, pkt_configs[layer]) > > + pkt.send_pkt(crb=self.tester, tx_port=src_intf, count=1) > > + time.sleep(1) > > + > > + def traffic(self): > > + # make sure interface in link up status > > + src_intf, src_mac = self.link_topo > > + cmd = "ifconfig {0} up".format(src_intf) > > + self.d_a_con(cmd) > > + # send out packet > > + for frame_size in self.frame_sizes: > > + headers_size = sum( > > + map(lambda x: HEADER_SIZE[x], ['eth', 'ip', 'udp'])) > > + payload_size = frame_size - headers_size > > + config_layers = { > > + 'ether': {'src': src_mac}, > > + 'raw': {'payload': ['58'] * payload_size}} > > + pkt_config = {'UDP': {'layer_configs': config_layers}} > > + self.send_packet(pkt_config, src_intf) > > + > > + def init_testpmd(self): > > + self.testpmd = PmdOutput(self.dut) > > + self.is_pmd_on = False > > + > > + def start_testpmd(self): > > + self.testpmd.start_testpmd('1S/2C/1T', > > param='--port-topology=loop') > > + self.is_pmd_on = True > > + time.sleep(2) > > + > > + def set_testpmd(self): > > + cmds = [ > > + 'set fwd io', > > + 'clear port xstats all', > > + 'start'] > > + [self.testpmd.execute_cmd(cmd) for cmd in cmds] > > + time.sleep(2) > > + > > + def close_testpmd(self): > > + if not self.is_pmd_on: > > + return > > + self.testpmd.quit() > > + self.is_pmd_on = False > > + > > + def get_pmd_xstat_data(self): > > + ''' get testpmd nic extended statistics ''' > > + cmd = 'show port xstats all' > > + output = self.testpmd.execute_cmd(cmd) > > + if "statistics" not in output: > > + self.logger.error(output) > > + raise Exception("failed to get port extended statistics data") > > + data_str = output.splitlines() > > + port_xstat = {} > > + cur_port = None > > + pat = r".*extended statistics for port (\d+).*" > > + for line in data_str: > > + if not line.strip(): > > + continue > > + if "statistics" in line: > > + result = re.findall(pat, line.strip()) > > + if len(result): > > + cur_port = result[0] > > + elif cur_port is not None and ": " in line: > > + if cur_port not in port_xstat: > > + port_xstat[cur_port] = {} > > + result = line.strip().split(": ") > > + if len(result) == 2 and result[0]: > > + name, value = result > > + port_xstat[cur_port][name] = value > > + else: > > + raise Exception("invalid data") > > + > > + return port_xstat > > + > > + def clear_pmd_ports_stat(self): > > + options = ["--xstats-reset ", "--stats-reset "] > > + for option in options: > > + cmd = self.dpdk_proc_info + " %s" % option > > + self.d_a_con(cmd) > > + time.sleep(1) > > + > > + def init_proc_info(self): > > + ports_count = len(self.dut_ports) > > + ports_mask = reduce(lambda x, y: x | y, > > + map(lambda x: 0x1 << x, > > range(ports_count))) > > + self.query_tool = os.path.join( > > + self.target_dir, self.target, 'app', 'dpdk-procinfo') > > + self.dpdk_proc_info = "%s -v -- -p %s" % (self.query_tool, > > + ports_mask) > > + > > + def parse_proc_info_xstat_output(self, msg): > > + if "statistics" not in msg: > > + self.logger.error(msg) > > + raise VerifyFailure("get port statistics data failed") > > + > > + port_xstat = {} > > + cur_port = None > > + pat = ".*for port (\d)+ .*" > > + data_str = msg.splitlines() > > + for line in data_str: > > + if not line.strip(): > > + continue > > + if "statistics" in line: > > + result = re.findall(pat, line.strip()) > > + if len(result): > > + cur_port = result[0] > > + elif cur_port is not None and ": " in line: > > + if cur_port not in port_xstat: > > + port_xstat[cur_port] = {} > > + result = line.strip().split(": ") > > + if len(result) == 2 and result[0]: > > + name, value = result > > + port_xstat[cur_port][name] = value > > + else: > > + raise VerifyFailure("invalid data") > > + > > + return port_xstat > > + > > + def query_dpdk_xstat_all(self, option="xstats"): > > + cmd = self.dpdk_proc_info + " --%s" % (option) > > + output = self.d_a_con(cmd) > > + infos = self.parse_proc_info_xstat_output(output) > > + if not infos: > > + msg = 'get xstat data failed' > > + raise VerifyFailure(msg) > > + return infos > > + > > + def get_xstat_statistic_id(self, sub_option): > > + option = "xstats-name" > > + execept_msgs = [] > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > > + msg = self.d_a_con(cmd) > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > + if sub_option not in msg or not len(sub_stat_data): > > + execept_msgs.append([option, msg]) > > + else: > > + for port in sub_stat_data: > > + if sub_option not in sub_stat_data[port]: > > + msg = "{0} {1} data doesn't existed".format( > > + port, sub_option) > > + self.logger.error(msg) > > + continue > > + if not port: > > + msg1 = "port {0} [{1}]".format(port, sub_option) > > + execept_msgs.append([msg1, msg2]) > > + continue > > + return sub_stat_data, execept_msgs > > + > > + def check_single_stats_result(self, sub_stat_data, all_xstat_data): > > + execept_msgs = [] > > + for port, infos in sub_stat_data.items(): > > + for item in infos: > > + if not port or \ > > + port not in all_xstat_data or \ > > + item not in all_xstat_data[port] or \ > > + sub_stat_data[port][item] != > all_xstat_data[port][item]: > > + msg1 = "port {0} [{1}]".format(port, item) > > + msg2 = "expect {0} > > + ".format(all_xstat_data[port][item]) > > + \ > > + "show > {0}".format(sub_stat_data[port][item]) > > + execept_msgs.append([msg1, msg2]) > > + continue > > + msg2 = "expect {0} ".format(all_xstat_data[port][item]) + > \ > > + "show {0}".format(sub_stat_data[port][item]) > > + self.logger.info(msg2) > > + return execept_msgs > > + > > + def get_xstat_single_statistic(self, stat, all_xstat_data): > > + option = "xstats-id" > > + execept_msgs = [] > > + for id in stat.values(): > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, id) > > + msg = self.d_a_con(cmd) > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > + if not sub_stat_data or not len(sub_stat_data): > > + execept_msgs.append([option, msg]) > > + else: > > + execept_msgs += self.check_single_stats_result( > > + sub_stat_data, all_xstat_data) > > + if len(execept_msgs): > > + for msgs in execept_msgs: > > + self.logger.error(msgs[0]) > > + self.logger.info(msgs[1]) > > + raise VerifyFailure("query data exception ") > > + > > + self.logger.info("all port is correct") > > + > > + time.sleep(1) > > + > > + def check_xstat_command_list(self): > > + output = self.d_a_con(self.query_tool) > > + expected_command = [ > > + "xstats-reset", > > + "xstats-name NAME", > > + "xstats-ids IDLIST", > > + "xstats-reset"] > > + pat = ".*--(.*):.*" > > + handle = re.compile(pat) > > + result = handle.findall(output) > > + if not result or len(result) == 0: > > + cmds = " | ".join(expected_command) > > + msg = "expected commands {0} have not been > > included".format(cmds) > > + raise VerifyFailure(msg) > > + missing_cmds = [] > > + for cmd in expected_command: > > + if cmd not in result: > > + missing_cmds.append(cmd) > > + > > + if len(missing_cmds): > > + msg = " | ".join(missing_cmds) + " have not been included" > > + raise VerifyFailure(msg) > > + > > + cmds = " | ".join(expected_command) > > + msg = "expected commands {0} have been included".format(cmds) > > + self.logger.info(msg) > > + > > + def check_xstat_reset_status(self): > > + all_xstat_data = self.query_dpdk_xstat_all() > > + execept_msgs = [] > > + for port in all_xstat_data: > > + stats_info = all_xstat_data[port] > > + for stat_name, value in stats_info.items(): > > + if int(value) != 0: > > + msg = "port {0} <{1}> [{2}] has not been reset" > > + execept_msgs.append(msg.format(port, stat_name, > > value)) > > + if len(execept_msgs): > > + self.logger.info(os.linesep.join(execept_msgs)) > > + raise VerifyFailure("xstat-reset failed") > > + > > + self.logger.info("xstat-reset success !") > > + > > + def check_xstat_id_cmd(self, all_xstat_data): > > + execept_msgs = [] > > + option = "xstats-id" > > + sub_option = reduce(lambda x, y: str(x) + "," + str(y), > > + range(len(all_xstat_data['0'].keys()))) > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > > + msg = self.d_a_con(cmd) > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > + if not sub_stat_data or not len(sub_stat_data): > > + execept_msgs.append([option, msg]) > > + else: > > + for port, infos in sub_stat_data.items(): > > + for item in infos: > > + if not port or \ > > + port not in all_xstat_data or \ > > + item not in all_xstat_data[port]: > > + msg1 = "port {0} get [{1}] failed".format( > > + port, item) > > + execept_msgs.append([msg1]) > > + continue > > + if len(execept_msgs): > > + for msgs in execept_msgs: > > + self.logger.error(msgs[0]) > > + raise VerifyFailure("query data exception ") > > + > > + self.logger.info("all ports stat id can get") > > + time.sleep(1) > > + > > + def check_xstat_name_cmd(self, all_xstat_data): > > + option = "xstats-name" > > + _sub_options = all_xstat_data['0'].keys() > > + execept_msgs = [] > > + for sub_option in _sub_options: > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > > + msg = self.d_a_con(cmd) > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > + if sub_option not in msg or not len(sub_stat_data): > > + execept_msgs.append([option, msg]) > > + else: > > + for port in sub_stat_data: > > + if sub_option not in sub_stat_data[port]: > > + msg = "{0} {1} data doesn't existed".format( > > + port, sub_option) > > + self.logger.error(msg) > > + continue > > + if not port or \ > > + port not in all_xstat_data or \ > > + sub_option not in all_xstat_data[port]: > > + msg1 = "port {0} [{1}]".format(port, sub_option) > > + execept_msgs.append([msg1]) > > + continue > > + if len(execept_msgs): > > + for msgs in execept_msgs: > > + self.logger.error(msgs[0]) > > + self.logger.info(msgs[1]) > > + raise VerifyFailure("query data exception ") > > + > > + self.logger.info("all port's stat value can get") > > + > > + def check_xstat_statistic_integrity(self, sub_options_ex=None): > > + all_xstat_data = self.query_dpdk_xstat_all() > > + self.check_xstat_id_cmd(all_xstat_data) > > + self.check_xstat_name_cmd(all_xstat_data) > > + > > + def check_xstat_single_statistic(self, sub_options_ex=None): > > + all_xstat_data = self.get_pmd_xstat_data() > > + self.logger.info("total stat names [%d]" % len(all_xstat_data['0'])) > > + for stat_name in all_xstat_data['0'].keys(): > > + # firstly, get statistic name. > > + stats, execept_msgs = self.get_xstat_statistic_id(stat_name) > > + if len(execept_msgs): > > + for msgs in execept_msgs: > > + self.logger.error(msgs[0]) > > + self.logger.info(msgs[1]) > > + continue > > + self.logger.info(stat_name) > > + self.get_xstat_single_statistic(stats['0'], > > + all_xstat_data) > > + > > + def verify_xstat_command_options(self): > > + ''' test xstat command set integrity ''' > > + except_content = None > > + try: > > + self.start_testpmd() > > + self.set_testpmd() > > + self.check_xstat_command_list() > > + except Exception as e: > > + self.logger.error(traceback.format_exc()) > > + except_content = e > > + finally: > > + self.close_testpmd() > > + > > + # re-raise verify exception result > > + if except_content: > > + raise VerifyFailure(except_content) > > + > > + def verify_xstat_reset(self): > > + ''' test xstat-reset command ''' > > + except_content = None > > + try: > > + self.start_testpmd() > > + self.set_testpmd() > > + self.traffic() > > + self.clear_pmd_ports_stat() > > + self.check_xstat_reset_status() > > + except Exception as e: > > + self.logger.error(traceback.format_exc()) > > + except_content = e > > + finally: > > + self.close_testpmd() > > + > > + # re-raise verify exception result > > + if except_content: > > + raise VerifyFailure(except_content) > > + > > + def verify_xstat_integrity(self): > > + ''' test xstat command ''' > > + except_content = None > > + try: > > + self.start_testpmd() > > + self.set_testpmd() > > + self.check_xstat_statistic_integrity() > > + except Exception as e: > > + self.logger.error(traceback.format_exc()) > > + except_content = e > > + finally: > > + self.close_testpmd() > > + > > + # re-raise verify exception result > > + if except_content: > > + raise VerifyFailure(except_content) > > + > > + def verify_xstat_single_statistic(self): > > + except_content = None > > + try: > > + self.start_testpmd() > > + self.set_testpmd() > > + self.clear_pmd_ports_stat() > > + self.traffic() > > + self.check_xstat_single_statistic() > > + except Exception as e: > > + self.logger.error(traceback.format_exc()) > > + except_content = e > > + finally: > > + self.close_testpmd() > > + > > + # re-raise verify exception result > > + if except_content: > > + raise VerifyFailure(except_content) > > + > > + def preset_test_environment(self): > > + self.is_pmd_on = None > > + # get link port pairs > > + port_num = 0 > > + local_port = self.tester.get_local_port(port_num) > > + self.link_topo = [ > > + self.tester.get_interface(local_port), > > + self.tester.get_mac(local_port)] > > + # set packet sizes for testing different type > > + self.frame_sizes = [64, 72, 128, 256, 512, 1024] > > + # init binary > > + self.init_testpmd() > > + self.init_proc_info() > > + # > > + # Test cases. > > + # > > + > > + def set_up_all(self): > > + self.dut_ports = self.dut.get_ports(self.nic) > > + self.verify(len(self.dut_ports) >= 1, 'Insufficient ports') > > + self.preset_test_environment() > > + > > + def set_up(self): > > + pass > > + > > + def tear_down(self): > > + pass > > + > > + def tear_down_all(self): > > + pass > > + > > + def test_xstat(self): > > + ''' test xstat command set integrity ''' > > + self.verify_xstat_command_options() > > + > > + def test_xstat_integrity(self): > > + ''' test xstat date types ''' > > + self.verify_xstat_integrity() > > + > > + def test_xstat_reset(self): > > + ''' test xstat-reset command ''' > > + self.verify_xstat_reset() > > + > > + def test_xstat_single_statistic(self): > > + ''' test xstat single data type ''' > > + self.verify_xstat_single_statistic() > > -- > > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 3/3] ethtool_stats: add automation script 2019-11-12 15:38 ` Wang, Yinan 2019-11-12 16:02 ` Wang, Yinan @ 2019-11-13 1:10 ` Mo, YufengX 2019-11-13 2:19 ` Wang, Yinan 1 sibling, 1 reply; 15+ messages in thread From: Mo, YufengX @ 2019-11-13 1:10 UTC (permalink / raw) To: Wang, Yinan, dts Hi,wang,yinan This script no need those yours description. Can you give a detail description. And this test plan(ethtool_stats doesn't use pktgen module. Please make sure what you said is in the right place. BRs Yufen, Mo > -----Original Message----- > From: Wang, Yinan > Sent: Tuesday, November 12, 2019 11:39 PM > To: Mo, YufengX <yufengx.mo@intel.com>; dts@dpdk.org > Subject: RE: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > Hi Yufeng, > > As discussion, may need add below points: > #. add a callback function in pktgen_base class, execute this callback function and query pktgen statistics data at a custom interval. > #. implemented automation for ethtool by using this callback function > #. Add parameter refer test plan change > > Br, > yinan > > -----Original Message----- > > From: Mo, YufengX <yufengx.mo@intel.com> > > Sent: 2019年11月1日 15:07 > > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > > Cc: Mo, YufengX <yufengx.mo@intel.com> > > Subject: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > > > > > Currently Ethtool supports a more complete list of stats for the same drivers > > that DPDK supports. The idea behind this epic is two fold as following: > > 1. To achieve metric equivalence with what linux's ethtool provides. > > 2. To extend the functionality of the xstats API to enable the following options: > > ## the retrieval of aggregate stats upon request (Top level stats). > > ## the retrieval of the extended NIC stats. > > ## grouping of stats logically so they can be retrieved per logical grouping. > > ## the option to enable/disable the stats groups to retrieve similar to set > > private flags in ethtool. > > > > Signed-off-by: yufengmx <yufengx.mo@intel.com> > > --- > > tests/TestSuite_ethtool_stats.py | 498 > > +++++++++++++++++++++++++++++++ > > 1 file changed, 498 insertions(+) > > create mode 100644 tests/TestSuite_ethtool_stats.py > > > > diff --git a/tests/TestSuite_ethtool_stats.py b/tests/TestSuite_ethtool_stats.py > > new file mode 100644 > > index 0000000..e8ea941 > > --- /dev/null > > +++ b/tests/TestSuite_ethtool_stats.py > > @@ -0,0 +1,498 @@ > > +# BSD LICENSE > > +# > > +# Copyright(c) 2010-2019 Intel Corporation. All rights reserved. > > +# All rights reserved. > > +# > > +# Redistribution and use in source and binary forms, with or without # > > +modification, are permitted provided that the following conditions # > > +are met: > > +# > > +# * Redistributions of source code must retain the above copyright > > +# notice, this list of conditions and the following disclaimer. > > +# * Redistributions in binary form must reproduce the above copyright > > +# notice, this list of conditions and the following disclaimer in > > +# the documentation and/or other materials provided with the > > +# distribution. > > +# * Neither the name of Intel Corporation nor the names of its > > +# contributors may be used to endorse or promote products derived > > +# from this software without specific prior written permission. > > +# > > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > > CONTRIBUTORS # > > +'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # > > +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS > > FOR # > > +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > > COPYRIGHT # > > +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > > INCIDENTAL, # > > +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > > # > > +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > > USE, # > > +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > > ON ANY # > > +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # > > +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE > > USE # > > +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > > DAMAGE. > > + > > +''' > > +DPDK Test suite. > > +Test support of dpdk-procinfo tool feature ''' > > + > > +import re > > +import time > > +import os > > +import traceback > > + > > +from utils import create_mask as dts_create_mask from test_case import > > +TestCase from pmd_output import PmdOutput from exception import > > +VerifyFailure > > + > > +from packet import Packet > > +from scapy.sendrecv import sendp > > +from settings import HEADER_SIZE > > + > > + > > +class TestEthtoolStats(TestCase): > > + > > + @property > > + def target_dir(self): > > + # get absolute directory of target source code > > + target_dir = '/root' + self.dut.base_dir[1:] \ > > + if self.dut.base_dir.startswith('~') else \ > > + self.dut.base_dir > > + return target_dir > > + > > + def d_a_con(self, cmd): > > + _cmd = [cmd, '# ', 10] if isinstance(cmd, (str, unicode)) else cmd > > + output = self.dut.alt_session.send_expect(*_cmd) > > + output2 = self.dut.alt_session.session.get_session_before(1) > > + return output + os.linesep + output2 > > + > > + def send_packet(self, pkt_config, src_intf): > > + for pkt_type in pkt_config.keys(): > > + pkt = Packet(pkt_type=pkt_type) > > + # set packet every layer's input parameters > > + if 'layer_configs' in pkt_config[pkt_type].keys(): > > + pkt_configs = pkt_config[pkt_type]['layer_configs'] > > + if pkt_configs: > > + for layer in pkt_configs.keys(): > > + pkt.config_layer(layer, pkt_configs[layer]) > > + pkt.send_pkt(crb=self.tester, tx_port=src_intf, count=1) > > + time.sleep(1) > > + > > + def traffic(self): > > + # make sure interface in link up status > > + src_intf, src_mac = self.link_topo > > + cmd = "ifconfig {0} up".format(src_intf) > > + self.d_a_con(cmd) > > + # send out packet > > + for frame_size in self.frame_sizes: > > + headers_size = sum( > > + map(lambda x: HEADER_SIZE[x], ['eth', 'ip', 'udp'])) > > + payload_size = frame_size - headers_size > > + config_layers = { > > + 'ether': {'src': src_mac}, > > + 'raw': {'payload': ['58'] * payload_size}} > > + pkt_config = {'UDP': {'layer_configs': config_layers}} > > + self.send_packet(pkt_config, src_intf) > > + > > + def init_testpmd(self): > > + self.testpmd = PmdOutput(self.dut) > > + self.is_pmd_on = False > > + > > + def start_testpmd(self): > > + self.testpmd.start_testpmd('1S/2C/1T', > > param='--port-topology=loop') > > + self.is_pmd_on = True > > + time.sleep(2) > > + > > + def set_testpmd(self): > > + cmds = [ > > + 'set fwd io', > > + 'clear port xstats all', > > + 'start'] > > + [self.testpmd.execute_cmd(cmd) for cmd in cmds] > > + time.sleep(2) > > + > > + def close_testpmd(self): > > + if not self.is_pmd_on: > > + return > > + self.testpmd.quit() > > + self.is_pmd_on = False > > + > > + def get_pmd_xstat_data(self): > > + ''' get testpmd nic extended statistics ''' > > + cmd = 'show port xstats all' > > + output = self.testpmd.execute_cmd(cmd) > > + if "statistics" not in output: > > + self.logger.error(output) > > + raise Exception("failed to get port extended statistics data") > > + data_str = output.splitlines() > > + port_xstat = {} > > + cur_port = None > > + pat = r".*extended statistics for port (\d+).*" > > + for line in data_str: > > + if not line.strip(): > > + continue > > + if "statistics" in line: > > + result = re.findall(pat, line.strip()) > > + if len(result): > > + cur_port = result[0] > > + elif cur_port is not None and ": " in line: > > + if cur_port not in port_xstat: > > + port_xstat[cur_port] = {} > > + result = line.strip().split(": ") > > + if len(result) == 2 and result[0]: > > + name, value = result > > + port_xstat[cur_port][name] = value > > + else: > > + raise Exception("invalid data") > > + > > + return port_xstat > > + > > + def clear_pmd_ports_stat(self): > > + options = ["--xstats-reset ", "--stats-reset "] > > + for option in options: > > + cmd = self.dpdk_proc_info + " %s" % option > > + self.d_a_con(cmd) > > + time.sleep(1) > > + > > + def init_proc_info(self): > > + ports_count = len(self.dut_ports) > > + ports_mask = reduce(lambda x, y: x | y, > > + map(lambda x: 0x1 << x, > > range(ports_count))) > > + self.query_tool = os.path.join( > > + self.target_dir, self.target, 'app', 'dpdk-procinfo') > > + self.dpdk_proc_info = "%s -v -- -p %s" % (self.query_tool, > > + ports_mask) > > + > > + def parse_proc_info_xstat_output(self, msg): > > + if "statistics" not in msg: > > + self.logger.error(msg) > > + raise VerifyFailure("get port statistics data failed") > > + > > + port_xstat = {} > > + cur_port = None > > + pat = ".*for port (\d)+ .*" > > + data_str = msg.splitlines() > > + for line in data_str: > > + if not line.strip(): > > + continue > > + if "statistics" in line: > > + result = re.findall(pat, line.strip()) > > + if len(result): > > + cur_port = result[0] > > + elif cur_port is not None and ": " in line: > > + if cur_port not in port_xstat: > > + port_xstat[cur_port] = {} > > + result = line.strip().split(": ") > > + if len(result) == 2 and result[0]: > > + name, value = result > > + port_xstat[cur_port][name] = value > > + else: > > + raise VerifyFailure("invalid data") > > + > > + return port_xstat > > + > > + def query_dpdk_xstat_all(self, option="xstats"): > > + cmd = self.dpdk_proc_info + " --%s" % (option) > > + output = self.d_a_con(cmd) > > + infos = self.parse_proc_info_xstat_output(output) > > + if not infos: > > + msg = 'get xstat data failed' > > + raise VerifyFailure(msg) > > + return infos > > + > > + def get_xstat_statistic_id(self, sub_option): > > + option = "xstats-name" > > + execept_msgs = [] > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > > + msg = self.d_a_con(cmd) > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > + if sub_option not in msg or not len(sub_stat_data): > > + execept_msgs.append([option, msg]) > > + else: > > + for port in sub_stat_data: > > + if sub_option not in sub_stat_data[port]: > > + msg = "{0} {1} data doesn't existed".format( > > + port, sub_option) > > + self.logger.error(msg) > > + continue > > + if not port: > > + msg1 = "port {0} [{1}]".format(port, sub_option) > > + execept_msgs.append([msg1, msg2]) > > + continue > > + return sub_stat_data, execept_msgs > > + > > + def check_single_stats_result(self, sub_stat_data, all_xstat_data): > > + execept_msgs = [] > > + for port, infos in sub_stat_data.items(): > > + for item in infos: > > + if not port or \ > > + port not in all_xstat_data or \ > > + item not in all_xstat_data[port] or \ > > + sub_stat_data[port][item] != all_xstat_data[port][item]: > > + msg1 = "port {0} [{1}]".format(port, item) > > + msg2 = "expect {0} ".format(all_xstat_data[port][item]) > > + \ > > + "show {0}".format(sub_stat_data[port][item]) > > + execept_msgs.append([msg1, msg2]) > > + continue > > + msg2 = "expect {0} ".format(all_xstat_data[port][item]) + \ > > + "show {0}".format(sub_stat_data[port][item]) > > + self.logger.info(msg2) > > + return execept_msgs > > + > > + def get_xstat_single_statistic(self, stat, all_xstat_data): > > + option = "xstats-id" > > + execept_msgs = [] > > + for id in stat.values(): > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, id) > > + msg = self.d_a_con(cmd) > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > + if not sub_stat_data or not len(sub_stat_data): > > + execept_msgs.append([option, msg]) > > + else: > > + execept_msgs += self.check_single_stats_result( > > + sub_stat_data, all_xstat_data) > > + if len(execept_msgs): > > + for msgs in execept_msgs: > > + self.logger.error(msgs[0]) > > + self.logger.info(msgs[1]) > > + raise VerifyFailure("query data exception ") > > + > > + self.logger.info("all port is correct") > > + > > + time.sleep(1) > > + > > + def check_xstat_command_list(self): > > + output = self.d_a_con(self.query_tool) > > + expected_command = [ > > + "xstats-reset", > > + "xstats-name NAME", > > + "xstats-ids IDLIST", > > + "xstats-reset"] > > + pat = ".*--(.*):.*" > > + handle = re.compile(pat) > > + result = handle.findall(output) > > + if not result or len(result) == 0: > > + cmds = " | ".join(expected_command) > > + msg = "expected commands {0} have not been > > included".format(cmds) > > + raise VerifyFailure(msg) > > + missing_cmds = [] > > + for cmd in expected_command: > > + if cmd not in result: > > + missing_cmds.append(cmd) > > + > > + if len(missing_cmds): > > + msg = " | ".join(missing_cmds) + " have not been included" > > + raise VerifyFailure(msg) > > + > > + cmds = " | ".join(expected_command) > > + msg = "expected commands {0} have been included".format(cmds) > > + self.logger.info(msg) > > + > > + def check_xstat_reset_status(self): > > + all_xstat_data = self.query_dpdk_xstat_all() > > + execept_msgs = [] > > + for port in all_xstat_data: > > + stats_info = all_xstat_data[port] > > + for stat_name, value in stats_info.items(): > > + if int(value) != 0: > > + msg = "port {0} <{1}> [{2}] has not been reset" > > + execept_msgs.append(msg.format(port, stat_name, > > value)) > > + if len(execept_msgs): > > + self.logger.info(os.linesep.join(execept_msgs)) > > + raise VerifyFailure("xstat-reset failed") > > + > > + self.logger.info("xstat-reset success !") > > + > > + def check_xstat_id_cmd(self, all_xstat_data): > > + execept_msgs = [] > > + option = "xstats-id" > > + sub_option = reduce(lambda x, y: str(x) + "," + str(y), > > + range(len(all_xstat_data['0'].keys()))) > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > > + msg = self.d_a_con(cmd) > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > + if not sub_stat_data or not len(sub_stat_data): > > + execept_msgs.append([option, msg]) > > + else: > > + for port, infos in sub_stat_data.items(): > > + for item in infos: > > + if not port or \ > > + port not in all_xstat_data or \ > > + item not in all_xstat_data[port]: > > + msg1 = "port {0} get [{1}] failed".format( > > + port, item) > > + execept_msgs.append([msg1]) > > + continue > > + if len(execept_msgs): > > + for msgs in execept_msgs: > > + self.logger.error(msgs[0]) > > + raise VerifyFailure("query data exception ") > > + > > + self.logger.info("all ports stat id can get") > > + time.sleep(1) > > + > > + def check_xstat_name_cmd(self, all_xstat_data): > > + option = "xstats-name" > > + _sub_options = all_xstat_data['0'].keys() > > + execept_msgs = [] > > + for sub_option in _sub_options: > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > > + msg = self.d_a_con(cmd) > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > + if sub_option not in msg or not len(sub_stat_data): > > + execept_msgs.append([option, msg]) > > + else: > > + for port in sub_stat_data: > > + if sub_option not in sub_stat_data[port]: > > + msg = "{0} {1} data doesn't existed".format( > > + port, sub_option) > > + self.logger.error(msg) > > + continue > > + if not port or \ > > + port not in all_xstat_data or \ > > + sub_option not in all_xstat_data[port]: > > + msg1 = "port {0} [{1}]".format(port, sub_option) > > + execept_msgs.append([msg1]) > > + continue > > + if len(execept_msgs): > > + for msgs in execept_msgs: > > + self.logger.error(msgs[0]) > > + self.logger.info(msgs[1]) > > + raise VerifyFailure("query data exception ") > > + > > + self.logger.info("all port's stat value can get") > > + > > + def check_xstat_statistic_integrity(self, sub_options_ex=None): > > + all_xstat_data = self.query_dpdk_xstat_all() > > + self.check_xstat_id_cmd(all_xstat_data) > > + self.check_xstat_name_cmd(all_xstat_data) > > + > > + def check_xstat_single_statistic(self, sub_options_ex=None): > > + all_xstat_data = self.get_pmd_xstat_data() > > + self.logger.info("total stat names [%d]" % len(all_xstat_data['0'])) > > + for stat_name in all_xstat_data['0'].keys(): > > + # firstly, get statistic name. > > + stats, execept_msgs = self.get_xstat_statistic_id(stat_name) > > + if len(execept_msgs): > > + for msgs in execept_msgs: > > + self.logger.error(msgs[0]) > > + self.logger.info(msgs[1]) > > + continue > > + self.logger.info(stat_name) > > + self.get_xstat_single_statistic(stats['0'], all_xstat_data) > > + > > + def verify_xstat_command_options(self): > > + ''' test xstat command set integrity ''' > > + except_content = None > > + try: > > + self.start_testpmd() > > + self.set_testpmd() > > + self.check_xstat_command_list() > > + except Exception as e: > > + self.logger.error(traceback.format_exc()) > > + except_content = e > > + finally: > > + self.close_testpmd() > > + > > + # re-raise verify exception result > > + if except_content: > > + raise VerifyFailure(except_content) > > + > > + def verify_xstat_reset(self): > > + ''' test xstat-reset command ''' > > + except_content = None > > + try: > > + self.start_testpmd() > > + self.set_testpmd() > > + self.traffic() > > + self.clear_pmd_ports_stat() > > + self.check_xstat_reset_status() > > + except Exception as e: > > + self.logger.error(traceback.format_exc()) > > + except_content = e > > + finally: > > + self.close_testpmd() > > + > > + # re-raise verify exception result > > + if except_content: > > + raise VerifyFailure(except_content) > > + > > + def verify_xstat_integrity(self): > > + ''' test xstat command ''' > > + except_content = None > > + try: > > + self.start_testpmd() > > + self.set_testpmd() > > + self.check_xstat_statistic_integrity() > > + except Exception as e: > > + self.logger.error(traceback.format_exc()) > > + except_content = e > > + finally: > > + self.close_testpmd() > > + > > + # re-raise verify exception result > > + if except_content: > > + raise VerifyFailure(except_content) > > + > > + def verify_xstat_single_statistic(self): > > + except_content = None > > + try: > > + self.start_testpmd() > > + self.set_testpmd() > > + self.clear_pmd_ports_stat() > > + self.traffic() > > + self.check_xstat_single_statistic() > > + except Exception as e: > > + self.logger.error(traceback.format_exc()) > > + except_content = e > > + finally: > > + self.close_testpmd() > > + > > + # re-raise verify exception result > > + if except_content: > > + raise VerifyFailure(except_content) > > + > > + def preset_test_environment(self): > > + self.is_pmd_on = None > > + # get link port pairs > > + port_num = 0 > > + local_port = self.tester.get_local_port(port_num) > > + self.link_topo = [ > > + self.tester.get_interface(local_port), > > + self.tester.get_mac(local_port)] > > + # set packet sizes for testing different type > > + self.frame_sizes = [64, 72, 128, 256, 512, 1024] > > + # init binary > > + self.init_testpmd() > > + self.init_proc_info() > > + # > > + # Test cases. > > + # > > + > > + def set_up_all(self): > > + self.dut_ports = self.dut.get_ports(self.nic) > > + self.verify(len(self.dut_ports) >= 1, 'Insufficient ports') > > + self.preset_test_environment() > > + > > + def set_up(self): > > + pass > > + > > + def tear_down(self): > > + pass > > + > > + def tear_down_all(self): > > + pass > > + > > + def test_xstat(self): > > + ''' test xstat command set integrity ''' > > + self.verify_xstat_command_options() > > + > > + def test_xstat_integrity(self): > > + ''' test xstat date types ''' > > + self.verify_xstat_integrity() > > + > > + def test_xstat_reset(self): > > + ''' test xstat-reset command ''' > > + self.verify_xstat_reset() > > + > > + def test_xstat_single_statistic(self): > > + ''' test xstat single data type ''' > > + self.verify_xstat_single_statistic() > > -- > > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 3/3] ethtool_stats: add automation script 2019-11-13 1:10 ` Mo, YufengX @ 2019-11-13 2:19 ` Wang, Yinan 2019-11-13 2:20 ` Mo, YufengX 0 siblings, 1 reply; 15+ messages in thread From: Wang, Yinan @ 2019-11-13 2:19 UTC (permalink / raw) To: Mo, YufengX, dts Acked-by: Wang, Yinan <yinan.wang@intel.com> Yes,I found it and already send you email for correcting it. > -----Original Message----- > From: Mo, YufengX <yufengx.mo@intel.com> > Sent: 2019年11月13日 9:10 > To: Wang, Yinan <yinan.wang@intel.com>; dts@dpdk.org > Subject: RE: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > Hi,wang,yinan > > This script no need those yours description. Can you give a detail description. > > And this test plan(ethtool_stats doesn't use pktgen module. Please make sure > what you said is in the right place. > > BRs > Yufen, Mo > > > -----Original Message----- > > From: Wang, Yinan > > Sent: Tuesday, November 12, 2019 11:39 PM > > To: Mo, YufengX <yufengx.mo@intel.com>; dts@dpdk.org > > Subject: RE: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > > > Hi Yufeng, > > > > As discussion, may need add below points: > > #. add a callback function in pktgen_base class, execute this callback function > and query pktgen statistics data at a custom interval. > > #. implemented automation for ethtool by using this callback function > > #. Add parameter refer test plan change > > > > Br, > > yinan > > > -----Original Message----- > > > From: Mo, YufengX <yufengx.mo@intel.com> > > > Sent: 2019年11月1日 15:07 > > > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > > > Cc: Mo, YufengX <yufengx.mo@intel.com> > > > Subject: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > > > > > > > > Currently Ethtool supports a more complete list of stats for the > > > same drivers that DPDK supports. The idea behind this epic is two fold as > following: > > > 1. To achieve metric equivalence with what linux's ethtool provides. > > > 2. To extend the functionality of the xstats API to enable the following > options: > > > ## the retrieval of aggregate stats upon request (Top level stats). > > > ## the retrieval of the extended NIC stats. > > > ## grouping of stats logically so they can be retrieved per logical > grouping. > > > ## the option to enable/disable the stats groups to retrieve similar to > set > > > private flags in ethtool. > > > > > > Signed-off-by: yufengmx <yufengx.mo@intel.com> > > > --- > > > tests/TestSuite_ethtool_stats.py | 498 > > > +++++++++++++++++++++++++++++++ > > > 1 file changed, 498 insertions(+) > > > create mode 100644 tests/TestSuite_ethtool_stats.py > > > > > > diff --git a/tests/TestSuite_ethtool_stats.py > > > b/tests/TestSuite_ethtool_stats.py > > > new file mode 100644 > > > index 0000000..e8ea941 > > > --- /dev/null > > > +++ b/tests/TestSuite_ethtool_stats.py > > > @@ -0,0 +1,498 @@ > > > +# BSD LICENSE > > > +# > > > +# Copyright(c) 2010-2019 Intel Corporation. All rights reserved. > > > +# All rights reserved. > > > +# > > > +# Redistribution and use in source and binary forms, with or > > > +without # modification, are permitted provided that the following > > > +conditions # are met: > > > +# > > > +# * Redistributions of source code must retain the above copyright > > > +# notice, this list of conditions and the following disclaimer. > > > +# * Redistributions in binary form must reproduce the above copyright > > > +# notice, this list of conditions and the following disclaimer in > > > +# the documentation and/or other materials provided with the > > > +# distribution. > > > +# * Neither the name of Intel Corporation nor the names of its > > > +# contributors may be used to endorse or promote products derived > > > +# from this software without specific prior written permission. > > > +# > > > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > > > CONTRIBUTORS # > > > +'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > # > > > +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND > FITNESS > > > FOR # > > > +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > > > COPYRIGHT # > > > +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > > > INCIDENTAL, # > > > +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > NOT > > > # > > > +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS > OF > > > USE, # > > > +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > > > ON ANY # > > > +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > > > +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > THE > > > USE # > > > +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > > > DAMAGE. > > > + > > > +''' > > > +DPDK Test suite. > > > +Test support of dpdk-procinfo tool feature ''' > > > + > > > +import re > > > +import time > > > +import os > > > +import traceback > > > + > > > +from utils import create_mask as dts_create_mask from test_case > > > +import TestCase from pmd_output import PmdOutput from exception > > > +import VerifyFailure > > > + > > > +from packet import Packet > > > +from scapy.sendrecv import sendp > > > +from settings import HEADER_SIZE > > > + > > > + > > > +class TestEthtoolStats(TestCase): > > > + > > > + @property > > > + def target_dir(self): > > > + # get absolute directory of target source code > > > + target_dir = '/root' + self.dut.base_dir[1:] \ > > > + if self.dut.base_dir.startswith('~') else \ > > > + self.dut.base_dir > > > + return target_dir > > > + > > > + def d_a_con(self, cmd): > > > + _cmd = [cmd, '# ', 10] if isinstance(cmd, (str, unicode)) else cmd > > > + output = self.dut.alt_session.send_expect(*_cmd) > > > + output2 = self.dut.alt_session.session.get_session_before(1) > > > + return output + os.linesep + output2 > > > + > > > + def send_packet(self, pkt_config, src_intf): > > > + for pkt_type in pkt_config.keys(): > > > + pkt = Packet(pkt_type=pkt_type) > > > + # set packet every layer's input parameters > > > + if 'layer_configs' in pkt_config[pkt_type].keys(): > > > + pkt_configs = pkt_config[pkt_type]['layer_configs'] > > > + if pkt_configs: > > > + for layer in pkt_configs.keys(): > > > + pkt.config_layer(layer, pkt_configs[layer]) > > > + pkt.send_pkt(crb=self.tester, tx_port=src_intf, count=1) > > > + time.sleep(1) > > > + > > > + def traffic(self): > > > + # make sure interface in link up status > > > + src_intf, src_mac = self.link_topo > > > + cmd = "ifconfig {0} up".format(src_intf) > > > + self.d_a_con(cmd) > > > + # send out packet > > > + for frame_size in self.frame_sizes: > > > + headers_size = sum( > > > + map(lambda x: HEADER_SIZE[x], ['eth', 'ip', 'udp'])) > > > + payload_size = frame_size - headers_size > > > + config_layers = { > > > + 'ether': {'src': src_mac}, > > > + 'raw': {'payload': ['58'] * payload_size}} > > > + pkt_config = {'UDP': {'layer_configs': config_layers}} > > > + self.send_packet(pkt_config, src_intf) > > > + > > > + def init_testpmd(self): > > > + self.testpmd = PmdOutput(self.dut) > > > + self.is_pmd_on = False > > > + > > > + def start_testpmd(self): > > > + self.testpmd.start_testpmd('1S/2C/1T', > > > param='--port-topology=loop') > > > + self.is_pmd_on = True > > > + time.sleep(2) > > > + > > > + def set_testpmd(self): > > > + cmds = [ > > > + 'set fwd io', > > > + 'clear port xstats all', > > > + 'start'] > > > + [self.testpmd.execute_cmd(cmd) for cmd in cmds] > > > + time.sleep(2) > > > + > > > + def close_testpmd(self): > > > + if not self.is_pmd_on: > > > + return > > > + self.testpmd.quit() > > > + self.is_pmd_on = False > > > + > > > + def get_pmd_xstat_data(self): > > > + ''' get testpmd nic extended statistics ''' > > > + cmd = 'show port xstats all' > > > + output = self.testpmd.execute_cmd(cmd) > > > + if "statistics" not in output: > > > + self.logger.error(output) > > > + raise Exception("failed to get port extended statistics data") > > > + data_str = output.splitlines() > > > + port_xstat = {} > > > + cur_port = None > > > + pat = r".*extended statistics for port (\d+).*" > > > + for line in data_str: > > > + if not line.strip(): > > > + continue > > > + if "statistics" in line: > > > + result = re.findall(pat, line.strip()) > > > + if len(result): > > > + cur_port = result[0] > > > + elif cur_port is not None and ": " in line: > > > + if cur_port not in port_xstat: > > > + port_xstat[cur_port] = {} > > > + result = line.strip().split(": ") > > > + if len(result) == 2 and result[0]: > > > + name, value = result > > > + port_xstat[cur_port][name] = value > > > + else: > > > + raise Exception("invalid data") > > > + > > > + return port_xstat > > > + > > > + def clear_pmd_ports_stat(self): > > > + options = ["--xstats-reset ", "--stats-reset "] > > > + for option in options: > > > + cmd = self.dpdk_proc_info + " %s" % option > > > + self.d_a_con(cmd) > > > + time.sleep(1) > > > + > > > + def init_proc_info(self): > > > + ports_count = len(self.dut_ports) > > > + ports_mask = reduce(lambda x, y: x | y, > > > + map(lambda x: 0x1 << x, > > > range(ports_count))) > > > + self.query_tool = os.path.join( > > > + self.target_dir, self.target, 'app', 'dpdk-procinfo') > > > + self.dpdk_proc_info = "%s -v -- -p %s" % (self.query_tool, > > > + ports_mask) > > > + > > > + def parse_proc_info_xstat_output(self, msg): > > > + if "statistics" not in msg: > > > + self.logger.error(msg) > > > + raise VerifyFailure("get port statistics data failed") > > > + > > > + port_xstat = {} > > > + cur_port = None > > > + pat = ".*for port (\d)+ .*" > > > + data_str = msg.splitlines() > > > + for line in data_str: > > > + if not line.strip(): > > > + continue > > > + if "statistics" in line: > > > + result = re.findall(pat, line.strip()) > > > + if len(result): > > > + cur_port = result[0] > > > + elif cur_port is not None and ": " in line: > > > + if cur_port not in port_xstat: > > > + port_xstat[cur_port] = {} > > > + result = line.strip().split(": ") > > > + if len(result) == 2 and result[0]: > > > + name, value = result > > > + port_xstat[cur_port][name] = value > > > + else: > > > + raise VerifyFailure("invalid data") > > > + > > > + return port_xstat > > > + > > > + def query_dpdk_xstat_all(self, option="xstats"): > > > + cmd = self.dpdk_proc_info + " --%s" % (option) > > > + output = self.d_a_con(cmd) > > > + infos = self.parse_proc_info_xstat_output(output) > > > + if not infos: > > > + msg = 'get xstat data failed' > > > + raise VerifyFailure(msg) > > > + return infos > > > + > > > + def get_xstat_statistic_id(self, sub_option): > > > + option = "xstats-name" > > > + execept_msgs = [] > > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > > > + msg = self.d_a_con(cmd) > > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > > + if sub_option not in msg or not len(sub_stat_data): > > > + execept_msgs.append([option, msg]) > > > + else: > > > + for port in sub_stat_data: > > > + if sub_option not in sub_stat_data[port]: > > > + msg = "{0} {1} data doesn't existed".format( > > > + port, sub_option) > > > + self.logger.error(msg) > > > + continue > > > + if not port: > > > + msg1 = "port {0} [{1}]".format(port, sub_option) > > > + execept_msgs.append([msg1, msg2]) > > > + continue > > > + return sub_stat_data, execept_msgs > > > + > > > + def check_single_stats_result(self, sub_stat_data, all_xstat_data): > > > + execept_msgs = [] > > > + for port, infos in sub_stat_data.items(): > > > + for item in infos: > > > + if not port or \ > > > + port not in all_xstat_data or \ > > > + item not in all_xstat_data[port] or \ > > > + sub_stat_data[port][item] != > all_xstat_data[port][item]: > > > + msg1 = "port {0} [{1}]".format(port, item) > > > + msg2 = "expect {0} > > > + ".format(all_xstat_data[port][item]) > > > + \ > > > + "show > {0}".format(sub_stat_data[port][item]) > > > + execept_msgs.append([msg1, msg2]) > > > + continue > > > + msg2 = "expect {0} ".format(all_xstat_data[port][item]) > + \ > > > + "show {0}".format(sub_stat_data[port][item]) > > > + self.logger.info(msg2) > > > + return execept_msgs > > > + > > > + def get_xstat_single_statistic(self, stat, all_xstat_data): > > > + option = "xstats-id" > > > + execept_msgs = [] > > > + for id in stat.values(): > > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, id) > > > + msg = self.d_a_con(cmd) > > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > > + if not sub_stat_data or not len(sub_stat_data): > > > + execept_msgs.append([option, msg]) > > > + else: > > > + execept_msgs += self.check_single_stats_result( > > > + sub_stat_data, all_xstat_data) > > > + if len(execept_msgs): > > > + for msgs in execept_msgs: > > > + self.logger.error(msgs[0]) > > > + self.logger.info(msgs[1]) > > > + raise VerifyFailure("query data exception ") > > > + > > > + self.logger.info("all port is correct") > > > + > > > + time.sleep(1) > > > + > > > + def check_xstat_command_list(self): > > > + output = self.d_a_con(self.query_tool) > > > + expected_command = [ > > > + "xstats-reset", > > > + "xstats-name NAME", > > > + "xstats-ids IDLIST", > > > + "xstats-reset"] > > > + pat = ".*--(.*):.*" > > > + handle = re.compile(pat) > > > + result = handle.findall(output) > > > + if not result or len(result) == 0: > > > + cmds = " | ".join(expected_command) > > > + msg = "expected commands {0} have not been > > > included".format(cmds) > > > + raise VerifyFailure(msg) > > > + missing_cmds = [] > > > + for cmd in expected_command: > > > + if cmd not in result: > > > + missing_cmds.append(cmd) > > > + > > > + if len(missing_cmds): > > > + msg = " | ".join(missing_cmds) + " have not been included" > > > + raise VerifyFailure(msg) > > > + > > > + cmds = " | ".join(expected_command) > > > + msg = "expected commands {0} have been > included".format(cmds) > > > + self.logger.info(msg) > > > + > > > + def check_xstat_reset_status(self): > > > + all_xstat_data = self.query_dpdk_xstat_all() > > > + execept_msgs = [] > > > + for port in all_xstat_data: > > > + stats_info = all_xstat_data[port] > > > + for stat_name, value in stats_info.items(): > > > + if int(value) != 0: > > > + msg = "port {0} <{1}> [{2}] has not been reset" > > > + execept_msgs.append(msg.format(port, > stat_name, > > > value)) > > > + if len(execept_msgs): > > > + self.logger.info(os.linesep.join(execept_msgs)) > > > + raise VerifyFailure("xstat-reset failed") > > > + > > > + self.logger.info("xstat-reset success !") > > > + > > > + def check_xstat_id_cmd(self, all_xstat_data): > > > + execept_msgs = [] > > > + option = "xstats-id" > > > + sub_option = reduce(lambda x, y: str(x) + "," + str(y), > > > + range(len(all_xstat_data['0'].keys()))) > > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > > > + msg = self.d_a_con(cmd) > > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > > + if not sub_stat_data or not len(sub_stat_data): > > > + execept_msgs.append([option, msg]) > > > + else: > > > + for port, infos in sub_stat_data.items(): > > > + for item in infos: > > > + if not port or \ > > > + port not in all_xstat_data or \ > > > + item not in all_xstat_data[port]: > > > + msg1 = "port {0} get [{1}] failed".format( > > > + port, item) > > > + execept_msgs.append([msg1]) > > > + continue > > > + if len(execept_msgs): > > > + for msgs in execept_msgs: > > > + self.logger.error(msgs[0]) > > > + raise VerifyFailure("query data exception ") > > > + > > > + self.logger.info("all ports stat id can get") > > > + time.sleep(1) > > > + > > > + def check_xstat_name_cmd(self, all_xstat_data): > > > + option = "xstats-name" > > > + _sub_options = all_xstat_data['0'].keys() > > > + execept_msgs = [] > > > + for sub_option in _sub_options: > > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, > sub_option) > > > + msg = self.d_a_con(cmd) > > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > > + if sub_option not in msg or not len(sub_stat_data): > > > + execept_msgs.append([option, msg]) > > > + else: > > > + for port in sub_stat_data: > > > + if sub_option not in sub_stat_data[port]: > > > + msg = "{0} {1} data doesn't existed".format( > > > + port, sub_option) > > > + self.logger.error(msg) > > > + continue > > > + if not port or \ > > > + port not in all_xstat_data or \ > > > + sub_option not in all_xstat_data[port]: > > > + msg1 = "port {0} [{1}]".format(port, > sub_option) > > > + execept_msgs.append([msg1]) > > > + continue > > > + if len(execept_msgs): > > > + for msgs in execept_msgs: > > > + self.logger.error(msgs[0]) > > > + self.logger.info(msgs[1]) > > > + raise VerifyFailure("query data exception ") > > > + > > > + self.logger.info("all port's stat value can get") > > > + > > > + def check_xstat_statistic_integrity(self, sub_options_ex=None): > > > + all_xstat_data = self.query_dpdk_xstat_all() > > > + self.check_xstat_id_cmd(all_xstat_data) > > > + self.check_xstat_name_cmd(all_xstat_data) > > > + > > > + def check_xstat_single_statistic(self, sub_options_ex=None): > > > + all_xstat_data = self.get_pmd_xstat_data() > > > + self.logger.info("total stat names [%d]" % len(all_xstat_data['0'])) > > > + for stat_name in all_xstat_data['0'].keys(): > > > + # firstly, get statistic name. > > > + stats, execept_msgs = self.get_xstat_statistic_id(stat_name) > > > + if len(execept_msgs): > > > + for msgs in execept_msgs: > > > + self.logger.error(msgs[0]) > > > + self.logger.info(msgs[1]) > > > + continue > > > + self.logger.info(stat_name) > > > + self.get_xstat_single_statistic(stats['0'], > > > + all_xstat_data) > > > + > > > + def verify_xstat_command_options(self): > > > + ''' test xstat command set integrity ''' > > > + except_content = None > > > + try: > > > + self.start_testpmd() > > > + self.set_testpmd() > > > + self.check_xstat_command_list() > > > + except Exception as e: > > > + self.logger.error(traceback.format_exc()) > > > + except_content = e > > > + finally: > > > + self.close_testpmd() > > > + > > > + # re-raise verify exception result > > > + if except_content: > > > + raise VerifyFailure(except_content) > > > + > > > + def verify_xstat_reset(self): > > > + ''' test xstat-reset command ''' > > > + except_content = None > > > + try: > > > + self.start_testpmd() > > > + self.set_testpmd() > > > + self.traffic() > > > + self.clear_pmd_ports_stat() > > > + self.check_xstat_reset_status() > > > + except Exception as e: > > > + self.logger.error(traceback.format_exc()) > > > + except_content = e > > > + finally: > > > + self.close_testpmd() > > > + > > > + # re-raise verify exception result > > > + if except_content: > > > + raise VerifyFailure(except_content) > > > + > > > + def verify_xstat_integrity(self): > > > + ''' test xstat command ''' > > > + except_content = None > > > + try: > > > + self.start_testpmd() > > > + self.set_testpmd() > > > + self.check_xstat_statistic_integrity() > > > + except Exception as e: > > > + self.logger.error(traceback.format_exc()) > > > + except_content = e > > > + finally: > > > + self.close_testpmd() > > > + > > > + # re-raise verify exception result > > > + if except_content: > > > + raise VerifyFailure(except_content) > > > + > > > + def verify_xstat_single_statistic(self): > > > + except_content = None > > > + try: > > > + self.start_testpmd() > > > + self.set_testpmd() > > > + self.clear_pmd_ports_stat() > > > + self.traffic() > > > + self.check_xstat_single_statistic() > > > + except Exception as e: > > > + self.logger.error(traceback.format_exc()) > > > + except_content = e > > > + finally: > > > + self.close_testpmd() > > > + > > > + # re-raise verify exception result > > > + if except_content: > > > + raise VerifyFailure(except_content) > > > + > > > + def preset_test_environment(self): > > > + self.is_pmd_on = None > > > + # get link port pairs > > > + port_num = 0 > > > + local_port = self.tester.get_local_port(port_num) > > > + self.link_topo = [ > > > + self.tester.get_interface(local_port), > > > + self.tester.get_mac(local_port)] > > > + # set packet sizes for testing different type > > > + self.frame_sizes = [64, 72, 128, 256, 512, 1024] > > > + # init binary > > > + self.init_testpmd() > > > + self.init_proc_info() > > > + # > > > + # Test cases. > > > + # > > > + > > > + def set_up_all(self): > > > + self.dut_ports = self.dut.get_ports(self.nic) > > > + self.verify(len(self.dut_ports) >= 1, 'Insufficient ports') > > > + self.preset_test_environment() > > > + > > > + def set_up(self): > > > + pass > > > + > > > + def tear_down(self): > > > + pass > > > + > > > + def tear_down_all(self): > > > + pass > > > + > > > + def test_xstat(self): > > > + ''' test xstat command set integrity ''' > > > + self.verify_xstat_command_options() > > > + > > > + def test_xstat_integrity(self): > > > + ''' test xstat date types ''' > > > + self.verify_xstat_integrity() > > > + > > > + def test_xstat_reset(self): > > > + ''' test xstat-reset command ''' > > > + self.verify_xstat_reset() > > > + > > > + def test_xstat_single_statistic(self): > > > + ''' test xstat single data type ''' > > > + self.verify_xstat_single_statistic() > > > -- > > > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 3/3] ethtool_stats: add automation script 2019-11-13 2:19 ` Wang, Yinan @ 2019-11-13 2:20 ` Mo, YufengX 0 siblings, 0 replies; 15+ messages in thread From: Mo, YufengX @ 2019-11-13 2:20 UTC (permalink / raw) To: Wang, Yinan, dts Thanks > -----Original Message----- > From: Wang, Yinan > Sent: Wednesday, November 13, 2019 10:20 AM > To: Mo, YufengX <yufengx.mo@intel.com>; dts@dpdk.org > Subject: RE: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > Acked-by: Wang, Yinan <yinan.wang@intel.com> > > Yes,I found it and already send you email for correcting it. > > > -----Original Message----- > > From: Mo, YufengX <yufengx.mo@intel.com> > > Sent: 2019年11月13日 9:10 > > To: Wang, Yinan <yinan.wang@intel.com>; dts@dpdk.org > > Subject: RE: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > > > Hi,wang,yinan > > > > This script no need those yours description. Can you give a detail description. > > > > And this test plan(ethtool_stats doesn't use pktgen module. Please make sure > > what you said is in the right place. > > > > BRs > > Yufen, Mo > > > > > -----Original Message----- > > > From: Wang, Yinan > > > Sent: Tuesday, November 12, 2019 11:39 PM > > > To: Mo, YufengX <yufengx.mo@intel.com>; dts@dpdk.org > > > Subject: RE: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > > > > > Hi Yufeng, > > > > > > As discussion, may need add below points: > > > #. add a callback function in pktgen_base class, execute this callback function > > and query pktgen statistics data at a custom interval. > > > #. implemented automation for ethtool by using this callback function > > > #. Add parameter refer test plan change > > > > > > Br, > > > yinan > > > > -----Original Message----- > > > > From: Mo, YufengX <yufengx.mo@intel.com> > > > > Sent: 2019年11月1日 15:07 > > > > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > > > > Cc: Mo, YufengX <yufengx.mo@intel.com> > > > > Subject: [dts][PATCH V3 3/3] ethtool_stats: add automation script > > > > > > > > > > > > Currently Ethtool supports a more complete list of stats for the > > > > same drivers that DPDK supports. The idea behind this epic is two fold as > > following: > > > > 1. To achieve metric equivalence with what linux's ethtool provides. > > > > 2. To extend the functionality of the xstats API to enable the following > > options: > > > > ## the retrieval of aggregate stats upon request (Top level stats). > > > > ## the retrieval of the extended NIC stats. > > > > ## grouping of stats logically so they can be retrieved per logical > > grouping. > > > > ## the option to enable/disable the stats groups to retrieve similar to > > set > > > > private flags in ethtool. > > > > > > > > Signed-off-by: yufengmx <yufengx.mo@intel.com> > > > > --- > > > > tests/TestSuite_ethtool_stats.py | 498 > > > > +++++++++++++++++++++++++++++++ > > > > 1 file changed, 498 insertions(+) > > > > create mode 100644 tests/TestSuite_ethtool_stats.py > > > > > > > > diff --git a/tests/TestSuite_ethtool_stats.py > > > > b/tests/TestSuite_ethtool_stats.py > > > > new file mode 100644 > > > > index 0000000..e8ea941 > > > > --- /dev/null > > > > +++ b/tests/TestSuite_ethtool_stats.py > > > > @@ -0,0 +1,498 @@ > > > > +# BSD LICENSE > > > > +# > > > > +# Copyright(c) 2010-2019 Intel Corporation. All rights reserved. > > > > +# All rights reserved. > > > > +# > > > > +# Redistribution and use in source and binary forms, with or > > > > +without # modification, are permitted provided that the following > > > > +conditions # are met: > > > > +# > > > > +# * Redistributions of source code must retain the above copyright > > > > +# notice, this list of conditions and the following disclaimer. > > > > +# * Redistributions in binary form must reproduce the above copyright > > > > +# notice, this list of conditions and the following disclaimer in > > > > +# the documentation and/or other materials provided with the > > > > +# distribution. > > > > +# * Neither the name of Intel Corporation nor the names of its > > > > +# contributors may be used to endorse or promote products derived > > > > +# from this software without specific prior written permission. > > > > +# > > > > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > > > > CONTRIBUTORS # > > > > +'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > > # > > > > +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND > > FITNESS > > > > FOR # > > > > +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > > > > COPYRIGHT # > > > > +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > > > > INCIDENTAL, # > > > > +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > > NOT > > > > # > > > > +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS > > OF > > > > USE, # > > > > +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > > > > ON ANY # > > > > +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > > > > +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > > THE > > > > USE # > > > > +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > > > > DAMAGE. > > > > + > > > > +''' > > > > +DPDK Test suite. > > > > +Test support of dpdk-procinfo tool feature ''' > > > > + > > > > +import re > > > > +import time > > > > +import os > > > > +import traceback > > > > + > > > > +from utils import create_mask as dts_create_mask from test_case > > > > +import TestCase from pmd_output import PmdOutput from exception > > > > +import VerifyFailure > > > > + > > > > +from packet import Packet > > > > +from scapy.sendrecv import sendp > > > > +from settings import HEADER_SIZE > > > > + > > > > + > > > > +class TestEthtoolStats(TestCase): > > > > + > > > > + @property > > > > + def target_dir(self): > > > > + # get absolute directory of target source code > > > > + target_dir = '/root' + self.dut.base_dir[1:] \ > > > > + if self.dut.base_dir.startswith('~') else \ > > > > + self.dut.base_dir > > > > + return target_dir > > > > + > > > > + def d_a_con(self, cmd): > > > > + _cmd = [cmd, '# ', 10] if isinstance(cmd, (str, unicode)) else cmd > > > > + output = self.dut.alt_session.send_expect(*_cmd) > > > > + output2 = self.dut.alt_session.session.get_session_before(1) > > > > + return output + os.linesep + output2 > > > > + > > > > + def send_packet(self, pkt_config, src_intf): > > > > + for pkt_type in pkt_config.keys(): > > > > + pkt = Packet(pkt_type=pkt_type) > > > > + # set packet every layer's input parameters > > > > + if 'layer_configs' in pkt_config[pkt_type].keys(): > > > > + pkt_configs = pkt_config[pkt_type]['layer_configs'] > > > > + if pkt_configs: > > > > + for layer in pkt_configs.keys(): > > > > + pkt.config_layer(layer, pkt_configs[layer]) > > > > + pkt.send_pkt(crb=self.tester, tx_port=src_intf, count=1) > > > > + time.sleep(1) > > > > + > > > > + def traffic(self): > > > > + # make sure interface in link up status > > > > + src_intf, src_mac = self.link_topo > > > > + cmd = "ifconfig {0} up".format(src_intf) > > > > + self.d_a_con(cmd) > > > > + # send out packet > > > > + for frame_size in self.frame_sizes: > > > > + headers_size = sum( > > > > + map(lambda x: HEADER_SIZE[x], ['eth', 'ip', 'udp'])) > > > > + payload_size = frame_size - headers_size > > > > + config_layers = { > > > > + 'ether': {'src': src_mac}, > > > > + 'raw': {'payload': ['58'] * payload_size}} > > > > + pkt_config = {'UDP': {'layer_configs': config_layers}} > > > > + self.send_packet(pkt_config, src_intf) > > > > + > > > > + def init_testpmd(self): > > > > + self.testpmd = PmdOutput(self.dut) > > > > + self.is_pmd_on = False > > > > + > > > > + def start_testpmd(self): > > > > + self.testpmd.start_testpmd('1S/2C/1T', > > > > param='--port-topology=loop') > > > > + self.is_pmd_on = True > > > > + time.sleep(2) > > > > + > > > > + def set_testpmd(self): > > > > + cmds = [ > > > > + 'set fwd io', > > > > + 'clear port xstats all', > > > > + 'start'] > > > > + [self.testpmd.execute_cmd(cmd) for cmd in cmds] > > > > + time.sleep(2) > > > > + > > > > + def close_testpmd(self): > > > > + if not self.is_pmd_on: > > > > + return > > > > + self.testpmd.quit() > > > > + self.is_pmd_on = False > > > > + > > > > + def get_pmd_xstat_data(self): > > > > + ''' get testpmd nic extended statistics ''' > > > > + cmd = 'show port xstats all' > > > > + output = self.testpmd.execute_cmd(cmd) > > > > + if "statistics" not in output: > > > > + self.logger.error(output) > > > > + raise Exception("failed to get port extended statistics data") > > > > + data_str = output.splitlines() > > > > + port_xstat = {} > > > > + cur_port = None > > > > + pat = r".*extended statistics for port (\d+).*" > > > > + for line in data_str: > > > > + if not line.strip(): > > > > + continue > > > > + if "statistics" in line: > > > > + result = re.findall(pat, line.strip()) > > > > + if len(result): > > > > + cur_port = result[0] > > > > + elif cur_port is not None and ": " in line: > > > > + if cur_port not in port_xstat: > > > > + port_xstat[cur_port] = {} > > > > + result = line.strip().split(": ") > > > > + if len(result) == 2 and result[0]: > > > > + name, value = result > > > > + port_xstat[cur_port][name] = value > > > > + else: > > > > + raise Exception("invalid data") > > > > + > > > > + return port_xstat > > > > + > > > > + def clear_pmd_ports_stat(self): > > > > + options = ["--xstats-reset ", "--stats-reset "] > > > > + for option in options: > > > > + cmd = self.dpdk_proc_info + " %s" % option > > > > + self.d_a_con(cmd) > > > > + time.sleep(1) > > > > + > > > > + def init_proc_info(self): > > > > + ports_count = len(self.dut_ports) > > > > + ports_mask = reduce(lambda x, y: x | y, > > > > + map(lambda x: 0x1 << x, > > > > range(ports_count))) > > > > + self.query_tool = os.path.join( > > > > + self.target_dir, self.target, 'app', 'dpdk-procinfo') > > > > + self.dpdk_proc_info = "%s -v -- -p %s" % (self.query_tool, > > > > + ports_mask) > > > > + > > > > + def parse_proc_info_xstat_output(self, msg): > > > > + if "statistics" not in msg: > > > > + self.logger.error(msg) > > > > + raise VerifyFailure("get port statistics data failed") > > > > + > > > > + port_xstat = {} > > > > + cur_port = None > > > > + pat = ".*for port (\d)+ .*" > > > > + data_str = msg.splitlines() > > > > + for line in data_str: > > > > + if not line.strip(): > > > > + continue > > > > + if "statistics" in line: > > > > + result = re.findall(pat, line.strip()) > > > > + if len(result): > > > > + cur_port = result[0] > > > > + elif cur_port is not None and ": " in line: > > > > + if cur_port not in port_xstat: > > > > + port_xstat[cur_port] = {} > > > > + result = line.strip().split(": ") > > > > + if len(result) == 2 and result[0]: > > > > + name, value = result > > > > + port_xstat[cur_port][name] = value > > > > + else: > > > > + raise VerifyFailure("invalid data") > > > > + > > > > + return port_xstat > > > > + > > > > + def query_dpdk_xstat_all(self, option="xstats"): > > > > + cmd = self.dpdk_proc_info + " --%s" % (option) > > > > + output = self.d_a_con(cmd) > > > > + infos = self.parse_proc_info_xstat_output(output) > > > > + if not infos: > > > > + msg = 'get xstat data failed' > > > > + raise VerifyFailure(msg) > > > > + return infos > > > > + > > > > + def get_xstat_statistic_id(self, sub_option): > > > > + option = "xstats-name" > > > > + execept_msgs = [] > > > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > > > > + msg = self.d_a_con(cmd) > > > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > > > + if sub_option not in msg or not len(sub_stat_data): > > > > + execept_msgs.append([option, msg]) > > > > + else: > > > > + for port in sub_stat_data: > > > > + if sub_option not in sub_stat_data[port]: > > > > + msg = "{0} {1} data doesn't existed".format( > > > > + port, sub_option) > > > > + self.logger.error(msg) > > > > + continue > > > > + if not port: > > > > + msg1 = "port {0} [{1}]".format(port, sub_option) > > > > + execept_msgs.append([msg1, msg2]) > > > > + continue > > > > + return sub_stat_data, execept_msgs > > > > + > > > > + def check_single_stats_result(self, sub_stat_data, all_xstat_data): > > > > + execept_msgs = [] > > > > + for port, infos in sub_stat_data.items(): > > > > + for item in infos: > > > > + if not port or \ > > > > + port not in all_xstat_data or \ > > > > + item not in all_xstat_data[port] or \ > > > > + sub_stat_data[port][item] != > > all_xstat_data[port][item]: > > > > + msg1 = "port {0} [{1}]".format(port, item) > > > > + msg2 = "expect {0} > > > > + ".format(all_xstat_data[port][item]) > > > > + \ > > > > + "show > > {0}".format(sub_stat_data[port][item]) > > > > + execept_msgs.append([msg1, msg2]) > > > > + continue > > > > + msg2 = "expect {0} ".format(all_xstat_data[port][item]) > > + \ > > > > + "show {0}".format(sub_stat_data[port][item]) > > > > + self.logger.info(msg2) > > > > + return execept_msgs > > > > + > > > > + def get_xstat_single_statistic(self, stat, all_xstat_data): > > > > + option = "xstats-id" > > > > + execept_msgs = [] > > > > + for id in stat.values(): > > > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, id) > > > > + msg = self.d_a_con(cmd) > > > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > > > + if not sub_stat_data or not len(sub_stat_data): > > > > + execept_msgs.append([option, msg]) > > > > + else: > > > > + execept_msgs += self.check_single_stats_result( > > > > + sub_stat_data, all_xstat_data) > > > > + if len(execept_msgs): > > > > + for msgs in execept_msgs: > > > > + self.logger.error(msgs[0]) > > > > + self.logger.info(msgs[1]) > > > > + raise VerifyFailure("query data exception ") > > > > + > > > > + self.logger.info("all port is correct") > > > > + > > > > + time.sleep(1) > > > > + > > > > + def check_xstat_command_list(self): > > > > + output = self.d_a_con(self.query_tool) > > > > + expected_command = [ > > > > + "xstats-reset", > > > > + "xstats-name NAME", > > > > + "xstats-ids IDLIST", > > > > + "xstats-reset"] > > > > + pat = ".*--(.*):.*" > > > > + handle = re.compile(pat) > > > > + result = handle.findall(output) > > > > + if not result or len(result) == 0: > > > > + cmds = " | ".join(expected_command) > > > > + msg = "expected commands {0} have not been > > > > included".format(cmds) > > > > + raise VerifyFailure(msg) > > > > + missing_cmds = [] > > > > + for cmd in expected_command: > > > > + if cmd not in result: > > > > + missing_cmds.append(cmd) > > > > + > > > > + if len(missing_cmds): > > > > + msg = " | ".join(missing_cmds) + " have not been included" > > > > + raise VerifyFailure(msg) > > > > + > > > > + cmds = " | ".join(expected_command) > > > > + msg = "expected commands {0} have been > > included".format(cmds) > > > > + self.logger.info(msg) > > > > + > > > > + def check_xstat_reset_status(self): > > > > + all_xstat_data = self.query_dpdk_xstat_all() > > > > + execept_msgs = [] > > > > + for port in all_xstat_data: > > > > + stats_info = all_xstat_data[port] > > > > + for stat_name, value in stats_info.items(): > > > > + if int(value) != 0: > > > > + msg = "port {0} <{1}> [{2}] has not been reset" > > > > + execept_msgs.append(msg.format(port, > > stat_name, > > > > value)) > > > > + if len(execept_msgs): > > > > + self.logger.info(os.linesep.join(execept_msgs)) > > > > + raise VerifyFailure("xstat-reset failed") > > > > + > > > > + self.logger.info("xstat-reset success !") > > > > + > > > > + def check_xstat_id_cmd(self, all_xstat_data): > > > > + execept_msgs = [] > > > > + option = "xstats-id" > > > > + sub_option = reduce(lambda x, y: str(x) + "," + str(y), > > > > + range(len(all_xstat_data['0'].keys()))) > > > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, sub_option) > > > > + msg = self.d_a_con(cmd) > > > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > > > + if not sub_stat_data or not len(sub_stat_data): > > > > + execept_msgs.append([option, msg]) > > > > + else: > > > > + for port, infos in sub_stat_data.items(): > > > > + for item in infos: > > > > + if not port or \ > > > > + port not in all_xstat_data or \ > > > > + item not in all_xstat_data[port]: > > > > + msg1 = "port {0} get [{1}] failed".format( > > > > + port, item) > > > > + execept_msgs.append([msg1]) > > > > + continue > > > > + if len(execept_msgs): > > > > + for msgs in execept_msgs: > > > > + self.logger.error(msgs[0]) > > > > + raise VerifyFailure("query data exception ") > > > > + > > > > + self.logger.info("all ports stat id can get") > > > > + time.sleep(1) > > > > + > > > > + def check_xstat_name_cmd(self, all_xstat_data): > > > > + option = "xstats-name" > > > > + _sub_options = all_xstat_data['0'].keys() > > > > + execept_msgs = [] > > > > + for sub_option in _sub_options: > > > > + cmd = self.dpdk_proc_info + " --%s %s" % (option, > > sub_option) > > > > + msg = self.d_a_con(cmd) > > > > + sub_stat_data = self.parse_proc_info_xstat_output(msg) > > > > + if sub_option not in msg or not len(sub_stat_data): > > > > + execept_msgs.append([option, msg]) > > > > + else: > > > > + for port in sub_stat_data: > > > > + if sub_option not in sub_stat_data[port]: > > > > + msg = "{0} {1} data doesn't existed".format( > > > > + port, sub_option) > > > > + self.logger.error(msg) > > > > + continue > > > > + if not port or \ > > > > + port not in all_xstat_data or \ > > > > + sub_option not in all_xstat_data[port]: > > > > + msg1 = "port {0} [{1}]".format(port, > > sub_option) > > > > + execept_msgs.append([msg1]) > > > > + continue > > > > + if len(execept_msgs): > > > > + for msgs in execept_msgs: > > > > + self.logger.error(msgs[0]) > > > > + self.logger.info(msgs[1]) > > > > + raise VerifyFailure("query data exception ") > > > > + > > > > + self.logger.info("all port's stat value can get") > > > > + > > > > + def check_xstat_statistic_integrity(self, sub_options_ex=None): > > > > + all_xstat_data = self.query_dpdk_xstat_all() > > > > + self.check_xstat_id_cmd(all_xstat_data) > > > > + self.check_xstat_name_cmd(all_xstat_data) > > > > + > > > > + def check_xstat_single_statistic(self, sub_options_ex=None): > > > > + all_xstat_data = self.get_pmd_xstat_data() > > > > + self.logger.info("total stat names [%d]" % len(all_xstat_data['0'])) > > > > + for stat_name in all_xstat_data['0'].keys(): > > > > + # firstly, get statistic name. > > > > + stats, execept_msgs = self.get_xstat_statistic_id(stat_name) > > > > + if len(execept_msgs): > > > > + for msgs in execept_msgs: > > > > + self.logger.error(msgs[0]) > > > > + self.logger.info(msgs[1]) > > > > + continue > > > > + self.logger.info(stat_name) > > > > + self.get_xstat_single_statistic(stats['0'], > > > > + all_xstat_data) > > > > + > > > > + def verify_xstat_command_options(self): > > > > + ''' test xstat command set integrity ''' > > > > + except_content = None > > > > + try: > > > > + self.start_testpmd() > > > > + self.set_testpmd() > > > > + self.check_xstat_command_list() > > > > + except Exception as e: > > > > + self.logger.error(traceback.format_exc()) > > > > + except_content = e > > > > + finally: > > > > + self.close_testpmd() > > > > + > > > > + # re-raise verify exception result > > > > + if except_content: > > > > + raise VerifyFailure(except_content) > > > > + > > > > + def verify_xstat_reset(self): > > > > + ''' test xstat-reset command ''' > > > > + except_content = None > > > > + try: > > > > + self.start_testpmd() > > > > + self.set_testpmd() > > > > + self.traffic() > > > > + self.clear_pmd_ports_stat() > > > > + self.check_xstat_reset_status() > > > > + except Exception as e: > > > > + self.logger.error(traceback.format_exc()) > > > > + except_content = e > > > > + finally: > > > > + self.close_testpmd() > > > > + > > > > + # re-raise verify exception result > > > > + if except_content: > > > > + raise VerifyFailure(except_content) > > > > + > > > > + def verify_xstat_integrity(self): > > > > + ''' test xstat command ''' > > > > + except_content = None > > > > + try: > > > > + self.start_testpmd() > > > > + self.set_testpmd() > > > > + self.check_xstat_statistic_integrity() > > > > + except Exception as e: > > > > + self.logger.error(traceback.format_exc()) > > > > + except_content = e > > > > + finally: > > > > + self.close_testpmd() > > > > + > > > > + # re-raise verify exception result > > > > + if except_content: > > > > + raise VerifyFailure(except_content) > > > > + > > > > + def verify_xstat_single_statistic(self): > > > > + except_content = None > > > > + try: > > > > + self.start_testpmd() > > > > + self.set_testpmd() > > > > + self.clear_pmd_ports_stat() > > > > + self.traffic() > > > > + self.check_xstat_single_statistic() > > > > + except Exception as e: > > > > + self.logger.error(traceback.format_exc()) > > > > + except_content = e > > > > + finally: > > > > + self.close_testpmd() > > > > + > > > > + # re-raise verify exception result > > > > + if except_content: > > > > + raise VerifyFailure(except_content) > > > > + > > > > + def preset_test_environment(self): > > > > + self.is_pmd_on = None > > > > + # get link port pairs > > > > + port_num = 0 > > > > + local_port = self.tester.get_local_port(port_num) > > > > + self.link_topo = [ > > > > + self.tester.get_interface(local_port), > > > > + self.tester.get_mac(local_port)] > > > > + # set packet sizes for testing different type > > > > + self.frame_sizes = [64, 72, 128, 256, 512, 1024] > > > > + # init binary > > > > + self.init_testpmd() > > > > + self.init_proc_info() > > > > + # > > > > + # Test cases. > > > > + # > > > > + > > > > + def set_up_all(self): > > > > + self.dut_ports = self.dut.get_ports(self.nic) > > > > + self.verify(len(self.dut_ports) >= 1, 'Insufficient ports') > > > > + self.preset_test_environment() > > > > + > > > > + def set_up(self): > > > > + pass > > > > + > > > > + def tear_down(self): > > > > + pass > > > > + > > > > + def tear_down_all(self): > > > > + pass > > > > + > > > > + def test_xstat(self): > > > > + ''' test xstat command set integrity ''' > > > > + self.verify_xstat_command_options() > > > > + > > > > + def test_xstat_integrity(self): > > > > + ''' test xstat date types ''' > > > > + self.verify_xstat_integrity() > > > > + > > > > + def test_xstat_reset(self): > > > > + ''' test xstat-reset command ''' > > > > + self.verify_xstat_reset() > > > > + > > > > + def test_xstat_single_statistic(self): > > > > + ''' test xstat single data type ''' > > > > + self.verify_xstat_single_statistic() > > > > -- > > > > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan 2019-11-01 7:06 [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan yufengmx ` (2 preceding siblings ...) 2019-11-01 7:06 ` [dts] [PATCH V3 3/3] ethtool_stats: add automation script yufengmx @ 2019-11-12 16:00 ` Wang, Yinan 2019-11-22 3:33 ` Tu, Lijuan 4 siblings, 0 replies; 15+ messages in thread From: Wang, Yinan @ 2019-11-12 16:00 UTC (permalink / raw) To: Mo, YufengX, dts Acked-by: Wang, Yinan <yinan.wang@intel.com> > -----Original Message----- > From: Mo, YufengX <yufengx.mo@intel.com> > Sent: 2019年11月1日 15:07 > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > Cc: Mo, YufengX <yufengx.mo@intel.com> > Subject: [dts][PATCH V3 0/3] ethtool_stats: upload script and update test plan > > upload ethtool_stats script. > update test plan. > add test plan index list. > > v3: > - rebase source code for new Packet module refactor. > - use testpmd xstat data as reference data to check proc info tool xstat data. > - update test plan content. > - remove un-used methods. > > v2: > - Follow Wang,yinan suggestion > - *. remove --tx-offloads=0xXXXX > - *. fix typo > > yufengmx (3): > ethtool_stats: update test plan > ethtool_stats: add ethtool_stats_test_plan index label > ethtool_stats: add automation script > > test_plans/ethtool_stats_test_plan.rst | 66 ++-- > test_plans/index.rst | 1 + > tests/TestSuite_ethtool_stats.py | 498 > +++++++++++++++++++++++++ > 3 files changed, 544 insertions(+), 21 deletions(-) create mode 100644 > tests/TestSuite_ethtool_stats.py > > -- > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan 2019-11-01 7:06 [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan yufengmx ` (3 preceding siblings ...) 2019-11-12 16:00 ` [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan Wang, Yinan @ 2019-11-22 3:33 ` Tu, Lijuan 4 siblings, 0 replies; 15+ messages in thread From: Tu, Lijuan @ 2019-11-22 3:33 UTC (permalink / raw) To: Mo, YufengX, dts, Wang, Yinan; +Cc: Mo, YufengX Applied the series, thanks > -----Original Message----- > From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of yufengmx > Sent: Friday, November 1, 2019 3:07 PM > To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com> > Cc: Mo, YufengX <yufengx.mo@intel.com> > Subject: [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test > plan > > upload ethtool_stats script. > update test plan. > add test plan index list. > > v3: > - rebase source code for new Packet module refactor. > - use testpmd xstat data as reference data to check proc info tool xstat data. > - update test plan content. > - remove un-used methods. > > v2: > - Follow Wang,yinan suggestion > - *. remove --tx-offloads=0xXXXX > - *. fix typo > > yufengmx (3): > ethtool_stats: update test plan > ethtool_stats: add ethtool_stats_test_plan index label > ethtool_stats: add automation script > > test_plans/ethtool_stats_test_plan.rst | 66 ++-- > test_plans/index.rst | 1 + > tests/TestSuite_ethtool_stats.py | 498 +++++++++++++++++++++++++ > 3 files changed, 544 insertions(+), 21 deletions(-) create mode 100644 > tests/TestSuite_ethtool_stats.py > > -- > 2.21.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2019-11-22 3:33 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-11-01 7:06 [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan yufengmx 2019-11-01 7:06 ` [dts] [PATCH V3 1/3] ethtool_stats: " yufengmx 2019-11-12 15:34 ` Wang, Yinan 2019-11-12 16:03 ` Wang, Yinan 2019-11-13 2:20 ` Wang, Yinan 2019-11-01 7:06 ` [dts] [PATCH V3 2/3] ethtool_stats: add ethtool_stats_test_plan index label yufengmx 2019-11-12 16:00 ` Wang, Yinan 2019-11-01 7:06 ` [dts] [PATCH V3 3/3] ethtool_stats: add automation script yufengmx 2019-11-12 15:38 ` Wang, Yinan 2019-11-12 16:02 ` Wang, Yinan 2019-11-13 1:10 ` Mo, YufengX 2019-11-13 2:19 ` Wang, Yinan 2019-11-13 2:20 ` Mo, YufengX 2019-11-12 16:00 ` [dts] [PATCH V3 0/3] ethtool_stats: upload script and update test plan Wang, Yinan 2019-11-22 3:33 ` Tu, Lijuan
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).