test suite reviews and discussions
 help / color / mirror / Atom feed
* [dts] [PATCH V1 0/2] packet_capture: upload suite test plan/automation script
@ 2018-06-06  5:33 yufengx.mo
  2018-06-06  5:33 ` [dts] [PATCH V1 1/2] packet_capture: upload test plan yufengx.mo
  2018-06-06  5:33 ` [dts] [PATCH V1 2/2] packet_capture: upload automation script yufengx.mo
  0 siblings, 2 replies; 3+ messages in thread
From: yufengx.mo @ 2018-06-06  5:33 UTC (permalink / raw)
  To: dts; +Cc: yufengmx

From: yufengmx <yufengx.mo@intel.com>

*. packet_capture test plan 
*. packet_capture automation script 

yufengmx (2):
  packet_capture: upload test plan
  packet_capture: upload automation script

 test_plans/packet_capture_test_plan.rst | 425 +++++++++++++++
 tests/TestSuite_packet_capture.py       | 892 ++++++++++++++++++++++++++++++++
 2 files changed, 1317 insertions(+)
 create mode 100644 test_plans/packet_capture_test_plan.rst
 create mode 100644 tests/TestSuite_packet_capture.py

-- 
1.9.3

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

* [dts] [PATCH V1 1/2] packet_capture: upload test plan
  2018-06-06  5:33 [dts] [PATCH V1 0/2] packet_capture: upload suite test plan/automation script yufengx.mo
@ 2018-06-06  5:33 ` yufengx.mo
  2018-06-06  5:33 ` [dts] [PATCH V1 2/2] packet_capture: upload automation script yufengx.mo
  1 sibling, 0 replies; 3+ messages in thread
From: yufengx.mo @ 2018-06-06  5:33 UTC (permalink / raw)
  To: dts; +Cc: yufengmx

From: yufengmx <yufengx.mo@intel.com>


Packet capture framework feature support packet capturing on dpdk ethernet
devices. DPDK provides dpdk-pdump tool under app/pdump directory for packet
capturing on dpdk.

Signed-off-by: yufengmx <yufengx.mo@intel.com>
---
 test_plans/packet_capture_test_plan.rst | 425 ++++++++++++++++++++++++++++++++
 1 file changed, 425 insertions(+)
 create mode 100644 test_plans/packet_capture_test_plan.rst

diff --git a/test_plans/packet_capture_test_plan.rst b/test_plans/packet_capture_test_plan.rst
new file mode 100644
index 0000000..de8b636
--- /dev/null
+++ b/test_plans/packet_capture_test_plan.rst
@@ -0,0 +1,425 @@
+.. Copyright (c) <2010-2018> Intel Corporation
+   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.
+
+================
+  packet capture
+================
+
+Packet capture framework feature support packet capturing on dpdk ethernet 
+devices. DPDK provides dpdk-pdump tool under app/pdump directory for packet 
+capturing on dpdk.
+
+The dpdk-pdump application will act as the secondary process. The EAL thread
+polls for packet capture fd. If fd polled matches packet capture fd, it will 
+initiate packet capture processing.
+
+The testpmd application will act as the primary process. The primary process 
+create socket for packet capture connection with the secondary process and 
+registers socket with packet capture epoll event. Packet capture event will 
+be polled as part of interrupt thread.
+
+The primary process creates mempool and two rte_rings for packets duplication
+and sharing packet info with the secondary process respectively.
+
+Upon receiving packet capture event, the primary process receive either 
+register RX/TX callbacks or remove RX/TX callbacks message from the secondary
+process on socket.If packet matches, reference count of packet will be 
+incremented and enqueued to second rte_ring for the secondary process to use.
+
+note: DPDK technical document refer to ``/doc/guides/tools/pdump.rst``
+
+Prerequisites
+=============
+* 2x NICs (2 full duplex ports per NIC) plugged into the available slots on a 
+platform, another two nic ports are linked with cables.
+
+  Connections ports between TESTER and DUT
+       TESTER                                DUT
+               physical link             logical link
+     .--------.                          .--------.
+     | portA0 | <----------------------> | portB0 |
+     |        |                          |        |
+     | portA1 | <----------------------> | portB1 |
+     |        |                          |        |
+     '--------'                          |        |
+                                 ------> | portB2 |
+                                |        |        |
+                                 ------> | portB3 |
+                                         '--------'
+
+note: portB0/portB1 are the binded ports. 
+      portB2/portB3 keep link up status and don't bind to dpdk driver.
+      Except portB0/portB1, DUT should have other two ports on link up status 
+
+Test cases
+==========
+The testpmd application act as server process with port-topology chained mode,
+the dpdk-pdump act as client process to dump capture packet with different 
+options setting. Select one port of tester as tx port, another port of tester 
+as rx port, send different type packets from two ports, check pcap files' 
+content dumped by scapy and tcpdump to confirm testpmd working correctly, 
+check pcap files' content dumped by tcpdump and dpdk-pdump to confirm 
+dpdk-pdump working correctly.  
+
+dpdk-pdump command format
+-------------------------
+* packet capture framework tool dpdk-pdump command format, parameters inside 
+the parenthesis represents the mandatory parameters, parameters inside the 
+square brackets represents optional 
+parameters::
+./app/dpdk-pdump -- --pdump=
+'(port = <port_id> |device_id = <pci address>), 
+(queue=<queue number>),  
+(rx-dev=<iface/path to pcap file> | tx-dev=<iface/path to pcap file>), 
+[ring-size=<size>], 
+[mbuf-size=<size>], 
+[total-num-mbufs=<size>]'
+
+transmission packets' format
+----------------------------
+* IP_RAW 
+  [Ether()/IP()/Raw('\0'*60)]
+* TCP 
+  [Ether()/IP()/TCP()/Raw('\0'*60)]
+* UDP 
+  [Ether()/IP()/UDP()/Raw('\0'*60)]
+* SCTP 
+  [Ether()/IP()/SCTP()/Raw('\0'*40)]
+* IPv6_TCP 
+  [Ether()/IPv6()/TCP()/Raw('\0'*60)]
+* IPv6_UDP 
+  [Ether()/IPv6()/UDP()/Raw('\0'*60)]
+* IPv6_SCTP 
+  [Ether()/IP()/IPv6()/SCTP()/Raw('\0'*40)]
+* VLAN_UDP 
+  [Ether()/Dot1Q()/IP()/UDP()/Raw('\0'*40)]
+* TIMESYNC 
+  [Ether(dst='FF:FF:FF:FF:FF:FF',type=0x88f7)/"\\x00\\x02"]
+* ARP 
+  [Ether(dst='FF:FF:FF:FF:FF:FF')/ARP()]
+* LLDP 
+  [Ether()/LLDP()/LLDPManagementAddress()]
+  notice: LLDP()/LLDPManagementAddress() method are in dts/dep/lldp.py 
+
+port configuration
+------------------
+* confirm two NICs physical link on a platform:
+  dut port 0 <---> tester port 0
+  dut port 1 <---> tester port 1
+  
+* Bind two port on DUT:
+ ./usertools/dpdk_nic_bind.py --bind=igb_uio <dut port 0 pci address> \ 
+  <dut port 1 pci address>
+
+* On dut, use port 0 as rx/tx port.
+  If dut port 0 rx dump is set, scapy send packet from tester port 0 and 
+  tcpdump dumps tester 
+  port 1's packet.
+   
+  If dut port 0 tx dump is set, scapy send packet from tester port 1 and 
+  tcpdump dumps tester 
+  port 0's packet.
+
+* If using interfaces as dpdk-pdump vdev, prepare two ports on DUT, which 
+  haven't been binded to dpdk and have been in linked status 
+
+Test Case 1: test pdump port
+============================
+Test different port type defintion options::
+* port=<dut port id>
+* device_id=<dut pci address>
+
+steps:
+*. Boot up dpdk's testpmd with chained option:
+	./app/testpmd -c 0x6 -n 4 -- -i --port-topology=chained
+	testpmd> set fwd io
+	testpmd> start
+
+*. When test VLAN_UDP type packet transmission, set vlan:
+    
+    testpmd> vlan set filter off 1
+    testpmd> start
+
+*. Boot up dpdk-pdump:
+    ./app/dpdk-pdump -- --pdump  '<port option>,queue=*,\
+    tx-dev=/tmp/pdump-tx.pcap,rx-dev=/tmp/pdump-rx.pcap'
+
+*. Set up linux's tcpdump to receiver packet on tester:
+	tcpdump -i <rx port name> -w /tmp/sniff-<rx port name>.pcap
+	tcpdump -i <tx port name> -w /tmp/sniff-<tx port name>.pcap
+
+*. Send packet on tester by port 0:
+   sendp(<packet format>, iface=<port 0 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+file dumped by dpdk-pdump with pcap files dumped by tcpdump.
+
+*. Send packet on tester by port 1:
+    sendp(<packet format>, iface=<port 1 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+file dumped by dpdk-pdump with pcap files dumped by tcpdump.
+
+Test Case 2: test pdump queue
+=============================
+Capture first queue traffic
+test different queue options::
+* first queue: 
+  queue=0
+* all: 
+  queue=*
+
+steps:
+*. Boot up dpdk's testpmd with chained option:
+	./app/testpmd -c 0x6 -n 4 -- -i --port-topology=chained
+	testpmd> set fwd io
+	testpmd> start
+
+*. When test VLAN_UDP type packet transmission, set vlan:
+
+    testpmd> vlan set filter off 1
+    testpmd> start
+
+*. Boot up dpdk-pdump:
+    ./app/dpdk-pdump -- --pdump  'port=0,<queue option>,\
+    tx-dev=/tmp/pdump-tx.pcap,rx-dev=/tmp/pdump-rx.pcap'
+
+*. Set up linux's tcpdump to receiver packet on tester:
+	tcpdump -i <rx port name> -w /tmp/sniff-<rx port name>.pcap
+	tcpdump -i <tx port name> -w /tmp/sniff-<tx port name>.pcap
+
+*. Send packet on tester by port 0:
+    sendp(<packet format>, iface=<port 0 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump. 
+
+*. Send packet on tester by port 1:
+   sendp(<packet format>, iface=<port 1 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump.
+
+Test Case 3: test pdump dev pcap 
+================================
+Dump rx/tx transmission packets into a specified pcap files.
+test different dump options::
+* tx-dev=/tmp/pdump-tx.pcap,rx-dev=/tmp/pdump-rx.pcap
+* rx-dev=/tmp/pdump-rx.pcap
+* tx-dev=/tmp/pdump-tx.pcap
+
+steps:
+*. Boot up dpdk's testpmd with chained option:
+	./app/testpmd -c 0x6 -n 4 -- -i --port-topology=chained
+	testpmd> set fwd io
+	testpmd> start
+
+*. When test VLAN_UDP type packet transmission, set vlan:
+
+    testpmd> vlan set filter off 1
+    testpmd> start
+
+*. Boot up dpdk-pdump with pdump options:
+    ./app/dpdk-pdump -- --pdump  'port=0,queue=*,<dump object>'
+
+*. Set up linux's tcpdump to receiver packet on tester:
+	tcpdump -i <rx port name> -w /tmp/sniff-<rx port name>.pcap
+	tcpdump -i <tx port name> -w /tmp/sniff-<tx port name>.pcap
+
+*. Send packet on tester by port 0:
+    sendp(<packet format>, iface=<port 0 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump(ignore when only 
+   set tx-dev).
+
+*. Send packet on tester by port 1:
+    sendp(<packet format>, iface=<port 1 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump(ignore when only 
+   set rx-dev).
+
+Test Case 4: test pdump dev iface 
+=================================
+Dump rx/tx transmission packets to a specifed port, which is on link status.
+test different dump options::
+* tx-dev=<dut tx port name>,rx-dev=<dut rx port name>
+* rx-dev=<dut rx port name>
+* tx-dev=<dut tx port name>
+
+steps:
+*. Boot up dpdk's testpmd with chained option:
+	./app/testpmd -c 0x6 -n 4 -- -i --port-topology=chained
+	testpmd> set fwd io
+	testpmd> start
+
+*. When test VLAN_UDP type packet transmission, set vlan:
+    
+    testpmd> vlan set filter off 1
+    testpmd> start
+
+*. Boot up dpdk-pdump with pdump options:
+    ./app/dpdk-pdump -- --pdump  'port=0,queue=*,<dump object>'
+
+*. Set up linux's tcpdump to receiver packet on tester:
+	tcpdump -i <rx port name> -w /tmp/sniff-<rx port name>.pcap
+	tcpdump -i <tx port name> -w /tmp/sniff-<tx port name>.pcap
+
+*. Set up linux's tcpdump to receiver packet of dpdk-pdump on Dut::
+	when rx-dev is set
+	
+	tcpdump -i <dut rx port name> -w /tmp/pdump-rx.pcap
+	
+	when tx-dev is set
+	
+	tcpdump -i <dut tx port name> -w /tmp/pdump-tx.pcap
+
+*. Send packet on tester by port 0:
+    sendp(<packet format>, iface=<port 0 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump(ignore when only 
+   set tx-dev).
+
+*. Send packet on tester by port 1:
+    sendp(<packet format>, iface=<port 1 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump(ignore when only 
+   set rx-dev).
+
+Test Case 5: test pdump ring size 
+=================================
+Test ring size option, set value within 2^[1~27]
+
+steps:
+*. Boot up dpdk's testpmd with chained option:
+	./app/testpmd -c 0x6 -n 4 -- -i --port-topology=chained
+	testpmd> set fwd io
+	testpmd> start
+
+*. When test VLAN_UDP type packet transmission, set vlan:
+    
+    testpmd> vlan set filter off 1
+    testpmd> start
+
+*. Boot up dpdk-pdump with pdump options:
+    ./app/dpdk-pdump -- --pdump  'port=0,queue=*,\
+    tx-dev=/tmp/pdump-tx.pcap,rx-dev=/tmp/pdump-rx.pcap,ring-size=1024'
+
+*. Set up linux's tcpdump to receiver packet on tester:
+	tcpdump -i <rx port name> -w /tmp/sniff-<rx port name>.pcap
+	tcpdump -i <tx port name> -w /tmp/sniff-<tx port name>.pcap
+
+*. Send packet on tester by port 0:
+    sendp(<packet format>, iface=<port 0 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump.
+
+*. Send packet on tester by port 1:
+    sendp(<packet format>, iface=<port 1 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump.
+
+Test Case 6: test pdump mbuf size 
+=================================
+Test mbuf size option, set value within [252~50000]. min value is decided by 
+single packet size, max value is decided by test platform memory size.
+
+steps:
+*. Boot up dpdk's testpmd with chained option:
+	./app/testpmd -c 0x6 -n 4 -- -i --port-topology=chained
+	testpmd> set fwd io
+	testpmd> start
+
+*. When test VLAN_UDP type packet transmission, set vlan:
+    
+    testpmd> vlan set filter off 1
+    testpmd> start
+
+*. Boot up dpdk-pdump with pdump options:
+    ./app/dpdk-pdump -- --pdump  'port=0,queue=*,\
+    tx-dev=/tmp/pdump-tx.pcap,rx-dev=/tmp/pdump-rx.pcap,mbuf-size=2048'
+
+*. Set up linux's tcpdump to receiver packet on tester:
+	tcpdump -i <rx port name> -w /tmp/sniff-<rx port name>.pcap
+	tcpdump -i <tx port name> -w /tmp/sniff-<tx port name>.pcap
+
+*. Send packet on tester by port 0:
+    sendp(<packet format>, iface=<port 0 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump.
+
+*. Send packet on tester by port 1:
+    sendp(<packet format>, iface=<port 1 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump.
+
+Test Case 7: test pdump total num mbufs 
+=======================================
+Test total-num-mbufs option, set value within [1025~65535]
+
+steps:
+*. Boot up dpdk's testpmd with chained option:
+	./app/testpmd -c 0x6 -n 4 -- -i --port-topology=chained
+	testpmd> set fwd io
+	testpmd> start
+
+*. When test VLAN_UDP type packet transmission, set vlan:
+
+    testpmd> vlan set filter off 1
+    testpmd> start
+
+*. Boot up dpdk-pdump with pdump options:
+    ./app/dpdk-pdump -- --pdump  'port=0,queue=*,\
+    tx-dev=/tmp/pdump-tx.pcap,rx-dev=/tmp/pdump-rx.pcap,total-num-mbufs=8191'
+
+*. Set up linux's tcpdump to receiver packet on tester:
+	tcpdump -i <rx port name> -w /tmp/sniff-<rx port name>.pcap
+	tcpdump -i <tx port name> -w /tmp/sniff-<tx port name>.pcap
+
+*. Send packet on tester by port 0:
+    sendp(<packet format>, iface=<port 0 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump.
+
+*. Send packet on tester by port 1:
+    sendp(<packet format>, iface=<port 1 name>)
+
+*. Compare pcap file of scapy with the pcap file dumped by tcpdump. Compare pcap 
+   file dumped by dpdk-pdump with pcap files dumped by tcpdump.
-- 
1.9.3

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

* [dts] [PATCH V1 2/2] packet_capture: upload automation script
  2018-06-06  5:33 [dts] [PATCH V1 0/2] packet_capture: upload suite test plan/automation script yufengx.mo
  2018-06-06  5:33 ` [dts] [PATCH V1 1/2] packet_capture: upload test plan yufengx.mo
@ 2018-06-06  5:33 ` yufengx.mo
  1 sibling, 0 replies; 3+ messages in thread
From: yufengx.mo @ 2018-06-06  5:33 UTC (permalink / raw)
  To: dts; +Cc: yufengmx

From: yufengmx <yufengx.mo@intel.com>


Packet capture framework feature support packet capturing on dpdk ethernet
devices. DPDK provides dpdk-pdump tool under app/pdump directory for packet
capturing on dpdk.

Signed-off-by: yufengmx <yufengx.mo@intel.com>
---
 tests/TestSuite_packet_capture.py | 892 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 892 insertions(+)
 create mode 100644 tests/TestSuite_packet_capture.py

diff --git a/tests/TestSuite_packet_capture.py b/tests/TestSuite_packet_capture.py
new file mode 100644
index 0000000..638266e
--- /dev/null
+++ b/tests/TestSuite_packet_capture.py
@@ -0,0 +1,892 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2018 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 packet_capture features of dpdk-pdump tool
+'''
+
+import os
+import traceback
+
+import time
+import re
+import types
+import random
+from pprint import pformat
+
+from scapy.utils import rdpcap
+from scapy.packet import NoPayload
+from scapy.packet import Packet as scapyPacket
+from scapy.fields import ConditionalField,Emph
+from scapy.base_classes import SetGen
+
+from test_case import TestCase
+from exception import VerifyFailure
+from pmd_output import PmdOutput
+from packet import Packet, sniff_packets, load_sniff_packets
+
+from settings import load_global_setting, DEBUG_SETTING
+
+if load_global_setting(DEBUG_SETTING) == "yes":
+    print_flag = True
+else:
+    print_flag = False
+
+jSep = os.sep.join
+
+class parsePacket(object):
+    '''
+    this class is used to parse pcap files' packets' layer content
+    '''
+    def __init__(self, filename, skip_flag=False):
+        self.pcapFile = filename
+        self.packetLayers = dict()
+        self.skip = skip_flag
+
+    def parse_packet_layer(self, pkt_object):
+        '''
+        parse one packet every layers' fields and value
+        '''
+        if pkt_object == None:
+            return
+
+        self.packetLayers[pkt_object.name] = dict()
+        for curfield in pkt_object.fields_desc:
+            if isinstance(curfield, ConditionalField) and \
+                not curfield._evalcond(pkt_object):
+                continue
+            field_value = pkt_object.getfieldval(curfield.name)
+            if isinstance(field_value, scapyPacket) or (curfield.islist and \
+                        curfield.holds_packets and type(field_value) is list):
+                continue
+            repr_value = curfield.i2repr(pkt_object, field_value)
+            if isinstance(repr_value, str):
+                repr_value = repr_value.replace(os.linesep, 
+                                    os.linesep + " "*(len(curfield.name) +4))
+            self.packetLayers[pkt_object.name][curfield.name] = repr_value
+
+        if isinstance(pkt_object.payload, NoPayload):
+            return
+        else:
+            self.parse_packet_layer(pkt_object.payload)
+
+    def get_valid_packet(self, pcap_pkts_origin, number):
+        cnt = 0
+        for packet in pcap_pkts_origin:
+            self.parse_packet_layer(packet)
+            if self.skip:
+                flag = 'LLDP' not in self.packetLayers.keys()
+            else:
+                flag = True
+            if self.packetLayers["Ethernet"]['dst'] == 'ff:ff:ff:ff:ff:ff' and \
+                flag: 
+                if number == cnt:
+                    break
+                cnt += 1
+            self.packetLayers.clear()
+
+    def parse_pcap(self, number=0):
+        '''
+        parse one packet content
+        '''
+        pcap_pkts = []
+        try:
+            if os.path.exists(self.pcapFile) == False:
+                warning = "{0} is not exist !".format(self.pcapFile)
+                return warning
+            
+            pcap_pkts = rdpcap(self.pcapFile)
+            # parse packets' every layers and fields
+            if len(pcap_pkts) == 0:
+                warning = "{0} is empty".format(self.pcapFile)
+                return warning
+            elif number>= len(pcap_pkts):
+                warning = "{0} is missing No.{1} packet".format(
+                                                        self.pcapFile, number)
+                return warning
+
+            self.get_valid_packet(pcap_pkts, number)
+
+        except Exception,e:
+            print (e)
+        finally:
+            pass
+
+        return None
+
+class TestPacketCapture(TestCase):
+    @property
+    def driver(self):
+        return self.kdriver
+
+    @property
+    def is_deubg(self):
+        return self._enable_debug
+
+    def set_up_all(self):
+        '''
+        Run at the start of each test suite.
+        '''
+        self.ports = self.dut.get_ports()
+        self.verify(self.target == "x86_64-native-linuxapp-gcc",
+                    "only support x86_64-native-linuxapp-gcc")
+        self.verify(len(self.ports) >= 2, "Insufficient ports for testing")
+        self.test_port0_id = 0
+        self.test_port1_id = 1
+        # compile dpdk app with SW CONFIG_RTE_LIBRTE_PMD_PCAP open
+        self.dut_skip_compile = self.dut.skip_setup
+        #------------------------------------------------------------------
+        # used for save log
+        self.pdump_output = jSep(["/root", 'pdumpLog'])
+        if not self.is_existed(self.pdump_output):
+            cmd = "mkdir -p {0}".format(self.pdump_output)
+            self.dut.send_expect(cmd, "# ")
+        #####################################################################
+        if not (self.dut_skip_compile and self.check_pcap_lib()):
+            self.pcap_SW = "CONFIG_RTE_LIBRTE_PMD_PCAP"
+            cmd = "sed -i -e 's/{0}=n$/{0}=y/' config/common_base".format(
+                                                                self.pcap_SW)
+            self.dut.send_expect(cmd, "# ", 30)
+            self.dut.skip_setup = False
+            self.dut.build_install_dpdk(self.target)
+        #####################################################################
+        self.session_ex = self.dut.new_session()
+        # secondary process (dpdk-pdump)
+        self.pdump_dir = self.dut.base_dir + os.sep + \
+                                          "%s/build/app/pdump/" % self.target
+        cmd = "ls {0} -F | grep '*'".format(self.pdump_dir)
+        exe_files = self.dut.send_expect(cmd, "# ").splitlines()
+        if len(exe_files) == 1:
+            self.tool_name = exe_files[0][:-1]
+        else:
+            self.verify(False, "tool name exception !")
+        self.dut_dpdk_pdump_dir = self.dut.base_dir + os.sep + \
+                                  "%s/app/%s" % (self.target, self.tool_name)
+        self.dpdk_pdump = self.dut_dpdk_pdump_dir + \
+                          " --file-prefix=test -- --pdump "
+        # every option string length should be less than 32 bytes 
+#         self.dpdk_pdump = self.dut_dpdk_pdump_dir + " -- --pdump "
+        self.send_pcap = jSep([self.pdump_output, "scapy_%s_%s_%d.pcap"])
+        self.rx_pcap = jSep([self.pdump_output, "pdump-rx.pcap"])
+        self.tx_pcap = jSep([self.pdump_output, "pdump-tx.pcap"])
+        self.rxtx_pcap = jSep([self.pdump_output, "pdump-rxtx.pcap"])
+        self.rx_iface = None
+        self.tx_iface = None
+        self.rxtx_iface = None
+        self.rx_packet_pos = 0
+        self.tx_packet_pos = 0
+        self.dev_iface_flag = False
+        # primary process
+        self.pmdout = PmdOutput(self.dut)
+
+        # False: reduce test items for regression testing, 
+        #        shut off base test environment checking
+        # True: make a full range testing
+        self.full_test = True
+        # get tcpdump options
+        self.check_tcpdump_options()
+
+    def is_existed(self, path):
+        ''' check if file existed '''
+        cmd = "ls {0}".format(path)
+        self.dut.send_expect(cmd, "# ")
+        cmd = "echo $?"
+        output = self.dut.send_expect(cmd, "# ")
+        ret = True if output == "0" else False
+        
+        return ret
+
+    def check_tcpdump_options(self):
+        param = ""
+        direct_param = r"(\s+)\[ -(\w) in\|out\|inout \]"
+        tcpdump_help = self.dut.send_expect("tcpdump -h", "# ")
+        for line in tcpdump_help.split('\n'):
+            m = re.match(direct_param, line)
+            if m:
+                param = "-" + m.group(2) + " out"
+        self.tcpdump = "tcpdump -i {0} " + param + " -w {1} >/dev/null 2>&1 &"
+
+    def check_pcap_lib(self):
+        pcap_lib_dir = os.sep.join([self.dut.base_dir,
+                                    self.target,
+                                    "lib/librte_pmd_pcap.a"])
+        self.dut.send_expect("ll %s"%pcap_lib_dir, "# ")
+        if self.dut.send_expect("echo $?", "# ") == "0":
+            return True
+        else:
+            return False
+
+    def get_packet_types(self):
+        '''
+        '''
+        packet_types = ["TCP",
+                        "UDP",
+                        "SCTP",
+                        "TIMESYNC",
+                        "ARP",
+                        "LLDP",
+                        "IP_RAW",
+                        "IPv6_TCP",
+                        "IPv6_UDP",
+                        "IPv6_SCTP",
+                        "VLAN_UDP"]
+
+        if self.full_test:
+            test_packet_types = packet_types
+        else:
+            test_packet_types = ["IPv6_TCP"]
+
+        return test_packet_types
+
+    def generate_options(self, port_id, pci, intf, types):
+        port_types = ["port=%d,"%port_id,
+                      "device_id=%s,"%pci]
+        dump_pcap_types = [["tx-dev={0},rx-dev={1},".format(self.tx_pcap,
+                                                            self.rx_pcap),
+                       {"rx": [self.rx_pcap, 1],
+                        "tx": [self.tx_pcap, 1]}],
+                      ["rx-dev={0},".format(self.rx_pcap),
+                       {"rx": [self.rx_pcap, 1],
+                        "tx": [None, 0]}],
+                      ["tx-dev={0},".format(self.tx_pcap),
+                       {"rx": [None, 0],
+                        "tx": [self.tx_pcap, 1]}],
+                    ]
+        dump_iface_types = [["tx-dev={0},rx-dev={1},".format(self.tx_iface,
+                                                             self.rx_iface),
+                       {"rx": [self.rx_pcap, 1],
+                        "tx": [self.tx_pcap, 1]}],
+                      ["rx-dev={0},".format(self.rx_iface),
+                       {"rx": [self.rx_pcap, 1],
+                        "tx": [None, 0]}],
+                      ["tx-dev={0},".format(self.tx_iface),
+                       {"rx": [None, 0],
+                        "tx": [self.tx_pcap, 1]}]
+                    ]
+
+        queue_types = ["queue=*,", "queue=0,"]
+        # ring size
+        maxPower = 27
+        minPower = 1
+        ring_size_types = ["ring-size=%d,"%(2**minPower), 
+                           "ring-size=%d,"% (2**random.randint(minPower+1,
+                                                               maxPower)),
+                           "ring-size=%d,"%(2**maxPower)]
+        # mbuf size
+        max_mbuf_size = 50000 #59520
+        min_mbuf_size = 252
+        mbuf_size_types = ["mbuf-size=%d,"%min_mbuf_size,
+                           "mbuf-size=%d,"%random.randint(min_mbuf_size+1,
+                                                          max_mbuf_size),
+                           "mbuf-size=%d,"%max_mbuf_size]
+        # total number mbuf
+        max_total_num_mbufs = 65535
+        min_total_num_mbufs = 1025
+        total_num_mbufs_types = [
+                     "total-num-mbufs=%d,"%min_total_num_mbufs, 
+                     "total-num-mbufs=%d,"%random.randint(min_total_num_mbufs+1,
+                                                          max_total_num_mbufs),
+                     "total-num-mbufs=%d,"%max_total_num_mbufs]
+
+        if "port" in types:
+            port_num = len(port_types)
+        else:
+            port_num = 1
+
+        if "dev-pcap" in types:
+            dump_types = dump_pcap_types
+        elif  "dev-iface" in types:
+            dump_types = dump_iface_types
+        else: 
+            dump_types = dump_pcap_types[:1]
+
+        if "queue" in types:
+            queue_num = len(queue_types)
+        else:
+            queue_num = 1
+
+        option_exds = [""]
+        if "ring_size" in types:
+            option_exds = ring_size_types[:]
+        
+        if "mbuf_size" in types:
+            option_exds =  mbuf_size_types[:]
+            
+        if "total_num_mbufs" in types:
+            option_exds = total_num_mbufs_types[:]
+
+        options = list()
+        for port in port_types[:port_num]:
+            for queue in queue_types[:queue_num]:
+                for dump in dump_types:
+                    for option_exd in option_exds:
+                        options.append([
+                                ((port + queue+ dump[0]) + option_exd)[:-1],
+                                dump[1]])
+
+        return options
+
+    def set_up(self):
+        '''
+        Run before each test case.
+        '''
+        self.exit_flag = False
+
+    def compare_pkts(self, refPkt=None, targetPkt=None, pkt_type=None,
+                     refPacketNo=0, targetPacketNo=0):
+        '''
+        compare two pcap files' specified packet content
+        '''
+        if self.is_deubg:
+            msgs = [
+                "   " + "*"*50,
+                "   <%s> No.%d packet is the reference packet"%(refPkt, 
+                                                              refPacketNo),
+                "   <%s> No.%d packet is the target packet"%(targetPkt,
+                                                           targetPacketNo),
+                "   " + "*"*50]
+            self.logger.info(os.linesep.join(msgs))
+        warning = None
+        refObj = parsePacket(refPkt)
+        warning = refObj.parse_pcap(number=refPacketNo) 
+        if warning:
+            return warning
+        # dpdk vlan doesn't add a `802.1Q` field in packet, remove this before
+        # comparison
+        # remove it for dpdk has realized it after 18.02 
+#         if pkt_type == 'VLAN_UDP' and '802.1Q' in refObj.packetLayers.keys():
+#             refObj.packetLayers['Ethernet']['type'] = \
+#                                         refObj.packetLayers['802.1Q']['type']
+#             refObj.packetLayers.pop('802.1Q')
+
+        targetObj = parsePacket(targetPkt)
+        warning = targetObj.parse_pcap(number=targetPacketNo)
+        if warning:
+            return warning
+        #------------------------------------------------------------------
+        # remove some fields, which are filled by dpdk automatically
+        # if packet is filled with `Padding`, remove this
+        if "Padding" in  targetObj.packetLayers.keys():
+            targetObj.packetLayers.pop("Padding")
+        if len(refObj.packetLayers) != len(targetObj.packetLayers):
+            refObj_layer = pformat(refObj.packetLayers)
+            targetObj_layer = pformat(targetObj.packetLayers)
+            self.logger.info(os.linesep + "refObj:    %s"%refObj_layer)
+            self.logger.info(os.linesep + "targetObj: %s"%targetObj_layer)
+            warning = "packet {0} layers are not as expected".format(targetPkt)
+            return warning
+
+        for layer in refObj.packetLayers.keys():
+            if layer not in targetObj.packetLayers.keys():
+                warning = "{0} has no [{1}] layer".format(targetPkt, layer)
+                return warning
+            
+            if (pkt_type in ['TIMESYNC', 'VLAN_UDP']) and layer == 'Raw':
+                continue
+            
+            refLayerFields = refObj.packetLayers[layer]
+            targetLayerFields = targetObj.packetLayers[layer]
+            if len(refLayerFields) != len(targetLayerFields):
+                warning = "{0} [{1}] layer has no expected fields".format(
+                                                            targetPkt, layer)
+                return warning
+            
+            for field in refLayerFields.keys():
+                if field == 'src' or field == 'dst':
+                    continue
+                if field not in targetLayerFields.keys():
+                    warning = ("{0} layer [{1}] "
+                               "has no [{2}] field").format(targetPkt,
+                                                            layer, field)
+                    return warning
+                if refLayerFields[field] != targetLayerFields[field]:
+                    warning = ("{0} [{1}] layer [{2}] "
+                               "field has no expected value").format(targetPkt,
+                                                                     layer,
+                                                                     field)
+                    return warning
+
+        return warning
+
+    def clear_ASLR(self):
+        cmd = "echo 0 > /proc/sys/kernel/randomize_va_space"
+        self.session_ex.send_expect(cmd, "# ", timeout=10)
+        time.sleep(2)
+
+    def reset_ASLR(self):
+        cmd = "echo 2 > /proc/sys/kernel/randomize_va_space"
+        self.session_ex.send_expect(cmd, "# ", timeout=10)
+        time.sleep(4)
+
+    def start_testpmd(self):
+        self.dut.send_expect("rm -fr {0}/*".format(self.pdump_output),
+                             "# ", timeout=10)
+        offloadd = '0x1fbf' if self.driver == 'i40e' else '0x2203f'
+        param_opt = "--port-topology=chained --tx-offloads={0}".format(offloadd)
+        # boot up testpmd
+        self.pmdout.start_testpmd("Default",
+                        param=param_opt,
+                        )
+        self.pmdout.execute_cmd("set fwd io")
+        self.pmdout.execute_cmd("start")
+        time.sleep(2)
+
+    def stop_testpmd(self):
+        # quit testpmd
+        self.pmdout.execute_cmd("stop")
+        self.pmdout.quit()
+        time.sleep(2)
+
+    def check_dut_file_exist(self, file_path):
+        self.session_ex.send_expect("ll %s"%file_path, "# ")
+        if self.session_ex.send_expect("echo $?", "# ") == "0":
+            return True
+        else:
+            return False
+
+    def start_tcpdump_pdump_iface(self, option):
+        if option["rx"][0] != None and option["tx"][0] != None and \
+           option["rx"][0] == option["tx"][0]:
+            if self.check_dut_file_exist(self.rxtx_pcap):
+                self.session_ex.send_expect("rm -f %s"%self.rxtx_pcap, "# ")
+            cmd = self.tcpdump.format(self.rxtx_iface, self.rxtx_pcap)
+            self.session_ex.send_expect(cmd, "# ")
+        else:
+            if option["rx"][0] != None:
+                if self.check_dut_file_exist(self.rx_pcap):
+                    self.session_ex.send_expect("rm -f %s"%self.rx_pcap, "# ")
+                cmd = self.tcpdump.format(self.rx_iface, self.rx_pcap)
+                self.session_ex.send_expect(cmd, "# ")
+
+            if option["tx"][0] != None:
+                if self.check_dut_file_exist(self.tx_pcap):
+                    self.session_ex.send_expect("rm -f %s"%self.tx_pcap, "# ")
+                cmd = self.tcpdump.format(self.tx_iface, self.tx_pcap)
+                self.session_ex.send_expect(cmd, "# ")
+        time.sleep(4)
+
+    def stop_tcpdump_pdump_iface(self):
+        self.session_ex.send_expect("killall tcpdump", "# ", 5)
+        time.sleep(2)
+
+    def start_dpdk_pdump(self, option):
+        # boot up dpdk-pdump tool with packet_capture feature set
+        # delete last time dumped files
+        self.session_ex.send_expect("rm -fr {0}/*".format(self.pdump_output),
+                                    "# ")
+        self.session_ex.send_expect("cd %s"%self.dut.base_dir, "# ")
+        if self.is_deubg: # for debugging
+            curTime = time.localtime()
+            microTime = "%04d%02d%02d-%02d_%02d_%02d"%(   curTime.tm_year,
+                                                     curTime.tm_mon,
+                                                     curTime.tm_mday,
+                                                     curTime.tm_hour,
+                                                     curTime.tm_min,
+                                                     curTime.tm_sec)
+            if self.check_dut_file_exist("/root/pdump/") == False:
+                self.session_ex.send_expect("mkdir /root/pdump", "# ")
+            cmd = "echo %s "%self.dpdk_pdump + \
+                  " '%s' > /root/pdump/pdump_%s.log &"%(option[0], microTime)
+            self.session_ex.send_expect(cmd, "# ")
+            cmd = self.dpdk_pdump + \
+                  " '%s' >> /root/pdump/pdump_%s.log &"%(option[0], microTime)
+        else:
+            cmd = self.dpdk_pdump + " '%s' >/dev/null 2>&1 &"%(option[0])
+        self.logger.info(cmd)
+        self.session_ex.send_expect(cmd, "# ", 15)
+        time.sleep(6)
+
+    def check_pdump_ready(self, option):
+        rx_dump_pcap = option["rx"][0]
+        if rx_dump_pcap:
+            self.verify(self.check_dut_file_exist(rx_dump_pcap), 
+                        "{1} {0} is not ready".format(rx_dump_pcap,
+                                                      self.tool_name))
+        tx_dump_pcap = option["tx"][0]
+        if tx_dump_pcap:
+            self.verify(self.check_dut_file_exist(tx_dump_pcap),
+                        "{1} {0} is not ready".format(tx_dump_pcap,
+                                                      self.tool_name))
+
+    def stop_dpdk_pdump(self):
+        # quit dpdk-pdump
+        self.session_ex.send_expect("killall %s"%self.tool_name, "# ", 5)
+        time.sleep(3)
+
+    def packet_capture_dump_packets(self, pkt_type, number, **kwargs):
+        if pkt_type == 'VLAN_UDP':
+            self.pmdout.execute_cmd("vlan set filter off 0")
+            self.pmdout.execute_cmd("vlan set filter off 1")
+            self.pmdout.execute_cmd("start")
+        # tester's port 0 and port 1 work under chained mode.
+        port_0 = self.ports[self.test_port0_id]
+        port_1 = self.ports[self.test_port1_id]
+        ################################################
+        # check send tx packet by port 0
+        # send packet to dut and compare dpdk-pdump dump pcap with 
+        # scapy pcap file
+        intf = self.tester.get_interface(self.tester.get_local_port(port_1))
+        
+        # prepare to catch replay packet in out port
+        recPaket = jSep(['/tmp', "sniff_%s.pcap" % intf])
+        if os.path.exists(recPaket):
+            os.remove(recPaket)
+        inst = sniff_packets(intf, count=1, timeout=20)
+        pkt = Packet(pkt_type=pkt_type)
+        if pkt_type == 'VLAN_UDP':
+            pkt.config_layer('dot1q', {'vlan': 20})
+        src_mac = self.tester.get_mac(self.tester.get_local_port(port_0))
+        pkt.config_layer('ether', {'src': src_mac})
+        # save send packet in a pcap file
+        refPaket = self.send_pcap % (pkt_type, "rx", number)
+        if os.path.exists(refPaket):
+            os.remove(refPaket)
+        pkt.pktgen.write_pcap(refPaket)
+        # send out test packet
+        tester_port = self.tester.get_local_port(port_0)
+        intf = self.tester.get_interface(tester_port)
+        pkt.send_pkt(tx_port=intf)
+        # load pcap file catched by out port
+        time.sleep(1)
+        load_sniff_packets(inst)
+        # compare pcap file received by out port with scapy reference 
+        # packet pcap file
+        warning = self.compare_pkts(refPaket, recPaket, pkt_type)
+        msg = "tcpdump rx Receive Packet error: {0}".format(warning)
+        self.verify(warning == None, msg)
+        ################################################
+        # check send tx packet by port 1
+        # send packet to dut and compare dpdk-pdump dump pcap 
+        # with scapy pcap file
+        intf = self.tester.get_interface(self.tester.get_local_port(port_0))
+        # prepare to catch replay packet in out port
+        recPaket = jSep(['/tmp', "sniff_%s.pcap" % intf])
+        if os.path.exists(recPaket):
+            os.remove(recPaket)
+        inst = sniff_packets(intf, count=1, timeout=20)
+        pkt = Packet(pkt_type=pkt_type)
+        if pkt_type == 'VLAN_UDP':
+            pkt.config_layer('dot1q', {'vlan': 20})
+        src_mac = self.tester.get_mac(self.tester.get_local_port(port_1))
+        pkt.config_layer('ether', {'src': src_mac})
+        # save send packet in a pcap file
+        refPaket = self.send_pcap % (pkt_type, "tx", number)
+        if os.path.exists(refPaket):
+            os.remove(refPaket)
+        pkt.pktgen.write_pcap(refPaket)
+        # send out test packet
+        tester_port = self.tester.get_local_port(port_1)
+        intf = self.tester.get_interface(tester_port)
+        pkt.send_pkt(tx_port=intf)
+        # load pcap file catched by out port
+        time.sleep(1)
+        load_sniff_packets(inst)
+        # compare pcap file received by out port 
+        # with scapy reference packet pcap file
+        warning = self.compare_pkts(refPaket, recPaket, pkt_type)
+        msg = "tcpdump tx Receive Packet error: {0}".format(warning)
+        self.verify(warning == None, msg)
+
+    def packet_capture_check_pdump_pcaps(self, pkt_type, number, **kwargs):
+        ################################################
+        rx_dump_pcap = kwargs["rx"][0]
+        if rx_dump_pcap:
+            self.verify(os.path.exists(rx_dump_pcap), 
+                        "{0} doesn't exist".format(rx_dump_pcap))
+            # save send packet in a pcap file
+            refPaket = self.send_pcap % (pkt_type, "rx", number)
+            self.verify(os.path.exists(refPaket), 
+                        "{0} doesn't exist".format(refPaket))
+            # compare pcap file dumped by dpdk-pdump 
+            # with scapy reference packet pcap file
+            warning = self.compare_pkts(refPaket, rx_dump_pcap, pkt_type, 
+                                        targetPacketNo=self.rx_packet_pos)
+            if kwargs["rx"][1] == 2:
+                self.rx_packet_pos += kwargs["rx"][1]
+            else:
+                self.rx_packet_pos += 1
+            self.verify(warning == None, 
+                        "dpdk-pdump rx dump packet error: {0}".format(warning))
+            msg = "pdump rx {0} packet content is correct".format(pkt_type)
+            self.logger.info(msg)
+        ################################################
+        tx_dump_pcap = kwargs["tx"][0]
+        if tx_dump_pcap:
+            self.verify(os.path.exists(tx_dump_pcap),
+                        "{0} doesn't exist".format(tx_dump_pcap))
+            # set send packet
+            refPaket = self.send_pcap % (pkt_type, "tx", number)
+            self.verify(os.path.exists(refPaket),
+                        "{0} doesn't exist".format(refPaket))
+            # compare pcap file dumped by dpdk-pdump 
+            # with scapy reference packet pcap file
+            if kwargs["tx"][1] == 2 and self.tx_packet_pos == 0:
+                self.tx_packet_pos = 1
+            warning = self.compare_pkts(refPaket, tx_dump_pcap, pkt_type, 
+                                        targetPacketNo=self.tx_packet_pos)
+            if kwargs["tx"][1] == 2:
+                self.tx_packet_pos += kwargs["tx"][1]
+            else:
+                self.tx_packet_pos += 1
+            msg = "dpdk-pdump tx dump packet error: {0}".format(warning)
+            self.verify(warning == None, msg)
+            msg = "pdump tx {0} packet content is correct".format(pkt_type)
+            self.logger.info(msg)
+
+    def packet_capture_test_packets(self, option):
+        self.clear_ASLR()
+        self.start_testpmd()
+        self.start_dpdk_pdump(option)
+        if self.dev_iface_flag == True:
+            self.start_tcpdump_pdump_iface(option[1])
+        self.check_pdump_ready(option[1])
+        number = 0
+        for packet_type in self.get_packet_types():
+            self.packet_capture_dump_packets(packet_type, number, **option[1])
+            number += 1
+            time.sleep(2)
+        if self.dev_iface_flag == True:
+            self.stop_tcpdump_pdump_iface()
+        if self.dut.get_ip_address() != self.tester.get_ip_address():
+            # copy rx pdump data from dut
+            if os.path.exists(self.rx_pcap):
+                os.remove(self.rx_pcap)
+            self.dut.session.copy_file_from(self.rx_pcap, self.rx_pcap)
+            # copy tx pdump data from dut
+            if os.path.exists(self.tx_pcap):
+                os.remove(self.tx_pcap)
+            self.dut.session.copy_file_from(self.tx_pcap, self.tx_pcap)
+        self.stop_dpdk_pdump()
+        self.stop_testpmd()
+
+        number = 0
+        self.rx_packet_pos = 0
+        self.tx_packet_pos = 0
+        for packet_type in self.get_packet_types():
+            self.packet_capture_check_pdump_pcaps(packet_type, number,
+                                                  **option[1])
+            number += 1
+            time.sleep(2)
+        self.reset_ASLR()
+
+    def packet_capture_test_options(self, pdump_options):
+        try:
+            for option in pdump_options:
+                self.packet_capture_test_packets(option)
+
+            self.exit_flag = True
+        except Exception as e:
+            self.logger.error(traceback.format_exc())
+            raise VerifyFailure(e)
+        finally:
+            pass
+
+    def test_pdump_port(self):
+        '''
+        test different port options::
+        * port=<dut port id>
+        * device_id=<dut pci address>
+        '''
+        port_id = self.test_port0_id
+        port_name = self.dut.ports_info[port_id]['intf']
+        port_pci = self.dut.ports_info[port_id]['pci']
+        test_types = ["port"]
+        options = self.generate_options( port_id, port_pci, port_name, 
+                                         test_types)
+        self.packet_capture_test_options(options)
+
+    def test_pdump_dev_pcap(self):
+        '''
+        test different dump options with pcap files as output::
+        * tx-dev=/xxx/pdump-tx.pcap,rx-dev=/xxx/pdump-rx.pcap
+        * rx-dev=/xxx/pdump-rx.pcap
+        * tx-dev=/xxx/pdump-tx.pcap
+        '''
+        port_id = self.test_port0_id
+        port_name = self.dut.ports_info[port_id]['intf']
+        port_pci = self.dut.ports_info[port_id]['pci']
+        test_types = ["dev-pcap"]
+        options = self.generate_options( port_id, port_pci, port_name,
+                                         test_types)
+        self.packet_capture_test_options(options)
+
+    def get_dut_iface(self):
+        # only physical nic support PROMISC
+        cmd = "ip link show | grep PROMISC | awk {'print $2'}"
+        out = self.dut.send_expect(cmd, "# ")
+        pat = "(.*):"
+        ifaces = [intf for intf in re.findall(pat, out, re.M) if intf]
+        # get dut/tester ip to check if they are in a platform
+        tester_ip = self.tester.get_ip_address()
+        dut_ip = self.dut.get_ip_address()
+        for link_port in range(len(self.ports)):
+            # if they are in a platform, ignore interface used by tester
+            if tester_ip == dut_ip:
+                tester_port = self.tester.get_local_port(link_port)
+                intf = self.tester.get_interface(tester_port)
+                if intf in ifaces:
+                    ifaces.remove(intf)
+            # ignore interface used by dut
+            intf = self.dut.ports_info[link_port]['intf']
+            if intf in ifaces:
+                ifaces.remove(intf)
+        
+        # set ports up
+        tmp_ifaces = ifaces[:]
+        for iface in tmp_ifaces:
+            # ignore current interface used by system
+            cmd = "ifconfig %s | grep 'inet ' "%iface
+            if self.dut.send_expect(cmd, "# ") != "":
+                ifaces.remove(iface)
+            self.dut.send_expect("ifconfig {0} up".format(iface), "# ")
+        time.sleep(10)
+        # get ports on link status
+        tmp_ifaces = ifaces[:]
+        for iface in tmp_ifaces:
+            cmd = "ip link show {0} | grep LOWER_UP".format(iface)
+            self.dut.send_expect(cmd, "# ")
+            output = self.dut.send_expect("echo $?".format(iface), "# ").strip()
+            if output != '0':
+                ifaces.remove(iface)
+
+        self.verify(len(ifaces) >= 2, "Insufficient ports for iface testing")
+        # set iface port for pdump tool output dump packets
+        self.rx_iface = ifaces[0]
+        self.tx_iface = ifaces[1]
+        self.rxtx_iface = ifaces[0]
+
+    def test_pdump_dev_iface(self):
+        '''
+        test different dump options with interfaces as output::
+        * tx-dev=<dut tx port name>,rx-dev=<dut rx port name>
+        * rx-dev=<dut rx port name>
+        * tx-dev=<dut tx port name>
+        '''
+        self.get_dut_iface()
+        port_id = self.test_port0_id
+        port_name = self.dut.ports_info[port_id]['intf']
+        port_pci = self.dut.ports_info[port_id]['pci']
+        test_types = ["dev-iface"]
+        self.dev_iface_flag = True
+        options = self.generate_options( port_id, port_pci, port_name,
+                                         test_types)
+        self.packet_capture_test_options(options)
+
+    def test_pdump_queue(self):
+        '''
+        test different queue options::
+        * first queue: 
+          queue=0
+        * all: 
+          queue=*
+        '''
+        port_id = self.test_port0_id
+        port_name = self.dut.ports_info[port_id]['intf']
+        port_pci = self.dut.ports_info[port_id]['pci']
+        test_types = ["queue"]
+        options = self.generate_options( port_id, port_pci, port_name,
+                                         test_types)
+        self.packet_capture_test_options(options)
+
+    def test_pdump_ring_size(self):
+        '''
+        test ring size option, set value within 2^[1~27]
+        '''
+        port_id = self.test_port0_id
+        port_name = self.dut.ports_info[port_id]['intf']
+        port_pci = self.dut.ports_info[port_id]['pci']
+        test_types = ["ring_size"]
+        options = self.generate_options( port_id, port_pci, port_name,
+                                         test_types)
+        self.packet_capture_test_options(options)
+
+    def test_pdump_mbuf_size(self):
+        '''
+        test mbuf size option, set value within [252~59000]. 
+        min value is decided by single packet size,
+        max value is decided by test platform memery size.
+        '''
+        port_id = self.test_port0_id
+        port_name = self.dut.ports_info[port_id]['intf']
+        port_pci = self.dut.ports_info[port_id]['pci']
+        test_types = ["mbuf_size"]
+        
+        options = self.generate_options( port_id, port_pci, port_name,
+                                         test_types)
+        self.packet_capture_test_options(options)
+
+    def test_pdump_total_num_mbufs(self):
+        '''
+        test total-num-mbufs option, set value within [1025~65535]
+        '''
+        port_id = self.test_port0_id
+        port_name = self.dut.ports_info[port_id]['intf']
+        port_pci = self.dut.ports_info[port_id]['pci']
+        test_types = ["total_num_mbufs"]
+        options = self.generate_options( port_id, port_pci, port_name,
+                                         test_types)
+        self.packet_capture_test_options(options)
+
+    def tear_down(self):
+        '''
+        Run after each test case.
+        '''
+        if self.exit_flag == False:
+            self.stop_dpdk_pdump()
+            self.tester.send_expect("killall testpmd", "# ")
+            self.tester.send_expect("killall tcpdump", "# ")
+        if self.dev_iface_flag:
+            self.stop_tcpdump_pdump_iface()
+            self.dev_iface_flag = False
+
+    def tear_down_all(self):
+        '''
+        Run after each test suite.
+        '''
+        if self.session_ex:
+            self.reset_ASLR()
+            self.session_ex.close()
+            self.session_ex = None
+        # Restore the config file and recompile the package.
+        if not (self.dut_skip_compile and self.check_pcap_lib()):
+            ###################################################################
+            self.dut.send_expect(
+                         ("sed -i -e 's/{0}=y$/{0}=n/' "
+                          "config/common_base").format(self.pcap_SW), "# ", 120)
+            # temporary disable skip_setup
+            skip_setup = self.dut.skip_setup
+            self.dut.skip_setup = True
+            self.dut.build_install_dpdk(self.target)
+            self.dut.skip_setup = skip_setup
+            ###################################################################
+        self.dut.kill_all()
+        
\ No newline at end of file
-- 
1.9.3

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

end of thread, other threads:[~2018-06-06  5:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-06  5:33 [dts] [PATCH V1 0/2] packet_capture: upload suite test plan/automation script yufengx.mo
2018-06-06  5:33 ` [dts] [PATCH V1 1/2] packet_capture: upload test plan yufengx.mo
2018-06-06  5:33 ` [dts] [PATCH V1 2/2] packet_capture: upload automation script yufengx.mo

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