[dts] [PATCH v7] framework/packet: support packet sniffer to specify running machine

Phil Yang phil.yang at arm.com
Fri Oct 19 11:25:01 CEST 2018


By default, the Tester is supposed to be the server which running DTS
and the packet sniff methods are running on it.
However, if DTS was not running on the Tester and the Tester is another
remote server, so packet sniff methods cannot sniff Tester's packets
correctly.

This patch adds support for packet sniff methods to specify running
machine and implements sniff packet methods in class tester.

1. Add parameter to sniff_packet and load_sniff_pcap methods to specify
the running machine.
2. Remove load_sniff_packets method in packet.py.
3. Add tcpdump_sniff_packets, load_tcpdump_sniff_pcap and
load_tcpdump_sniff_packets for class tester with the new sniff_packet
API.
4. Update tester.check_random_pkts method with
tester.tcpdump_sniff_packets and tester.load_tcpdump_sniff_packets to
make it execution on the Tester.

Signed-off-by: Phil Yang <phil.yang at arm.com>
Suggested-by: Marvin Liu <yong.liu at intel.com>
Suggested-by: Tu Lijuan <lijuan.tu at intel.com>
---
 framework/packet.py | 97 +++++++++++++++++++++++++----------------------------
 framework/tester.py | 48 +++++++++++++++++++++++---
 2 files changed, 89 insertions(+), 56 deletions(-)

diff --git a/framework/packet.py b/framework/packet.py
index 976b82b..d5b8517 100755
--- a/framework/packet.py
+++ b/framework/packet.py
@@ -33,7 +33,6 @@
 Generic packet create, transmit and analyze module
 Base on scapy(python program for packet manipulation)
 """
-
 import os
 import time
 import sys
@@ -61,6 +60,7 @@ from scapy.route import *
 from scapy.packet import bind_layers, Raw
 from scapy.sendrecv import sendp
 from scapy.arch import get_if_hwaddr
+from pexpect import pxssh
 
 # load extension layers
 exec_file = os.path.realpath(__file__)
@@ -812,15 +812,26 @@ def get_filter_cmd(filters=[]):
         return ""
 
 
-def sniff_packets(intf, count=0, timeout=5, filters=[]):
+def sniff_packets(intf, count=0, timeout=5, filters=[], target=[]):
     """
     sniff all packets for certain port in certain seconds
     """
     param = ""
     direct_param = r"(\s+)\[ (\S+) in\|out\|inout \]"
-    tcpdump_help = subprocess.check_output("tcpdump -h; echo 0",
-                                           stderr=subprocess.STDOUT,
-                                           shell=True)
+
+    try:
+        tcpdump_help_session=pxssh.pxssh()
+        tcpdump_help_session.login(server=target[0], username=target[1],
+                                   password=target[2], original_prompt='[$#>]',
+                                   login_timeout=20)
+        tcpdump_help_session.sendline('tcpdump -h')
+        tcpdump_help_session.prompt()
+        tcpdump_help=tcpdump_help_session.before
+        tcpdump_help_session.logout()
+    except pxssh.ExceptionPxssh as e:
+        print ('pxssh failed on login.')
+        print (e)
+
     for line in tcpdump_help.split('\n'):
         m = re.match(direct_param, line)
         if m:
@@ -850,16 +861,24 @@ def sniff_packets(intf, count=0, timeout=5, filters=[]):
     else:
         cmd = sniff_cmd % options
 
-    args = shlex.split(cmd)
+    try:
+        tcpdump_session=pxssh.pxssh()
+        tcpdump_session.login(server=target[0], username=target[1],
+                              password=target[2], original_prompt='[$#>]',
+                              login_timeout=20)
+        tcpdump_session.sendline(cmd)
+        pipe = tcpdump_session
+    except pxssh.ExceptionPxssh as e:
+        print ('pxssh failed on login.')
+        print (e)
 
-    pipe = subprocess.Popen(args)
     index = str(time.time())
     SNIFF_PIDS[index] = (pipe, intf, timeout)
     time.sleep(1)
     return index
 
 
-def load_sniff_pcap(index=''):
+def load_sniff_pcap(index='', target=[]):
     """
     Stop sniffer and return pcap file
     """
@@ -868,58 +887,36 @@ def load_sniff_pcap(index=''):
         pipe, intf, timeout = SNIFF_PIDS[index]
         time_elapse = int(time.time() - float(index))
         while time_elapse < timeout:
-            if pipe.poll() is not None:
+            if pipe.prompt(timeout=1):
                 child_exit = True
                 break
 
-            time.sleep(1)
             time_elapse += 1
 
         if not child_exit:
-            pipe.send_signal(signal.SIGINT)
-            pipe.wait()
-
-        # wait pcap file ready
-        time.sleep(1)
-        return "/tmp/sniff_%s.pcap" % intf
-
-    return ""
-
-
-def load_sniff_packets(index=''):
-    """
-    Stop sniffer and return packet objects
-    """
-    pkts = []
-    child_exit = False
-    if index in SNIFF_PIDS.keys():
-        pipe, intf, timeout = SNIFF_PIDS[index]
-        time_elapse = int(time.time() - float(index))
-        while time_elapse < timeout:
-            if pipe.poll() is not None:
+            try:
+                # Stop Tcpdump on the target server
+                tcpdump_quit_session=pxssh.pxssh()
+                tcpdump_quit_session.login(server=target[0], username=target[1],
+                                           password=target[2], original_prompt='[$#>]',
+                                           login_timeout=20)
+                tcpdump_quit_session.sendline('kill -2 $(pidof tcpdump)')
+                tcpdump_quit_session.prompt()
+                tcpdump_quit_session.logout()
                 child_exit = True
-                break
+            except pxssh.ExceptionPxssh as e:
+                print ('pxssh failed on login.')
+                print (e)
 
-            time.sleep(1)
-            time_elapse += 1
-
-        if not child_exit:
-            pipe.send_signal(signal.SIGINT)
-            pipe.wait()
+        # Close the Tcpdump_session
+        pipe.prompt()
+        pipe.logout()
 
         # wait pcap file ready
         time.sleep(1)
-        try:
-            cap_pkts = rdpcap("/tmp/sniff_%s.pcap" % intf)
-            for pkt in cap_pkts:
-                # packet gen should be scapy
-                packet = Packet(tx_port=intf)
-                packet.pktgen.assign_pkt(pkt)
-                pkts.append(packet)
-        except:
-            pass
+        return "/tmp/sniff_%s.pcap" % intf
 
-    return pkts
+    return ""
 
 
 def load_pcapfile(filename=""):
@@ -978,12 +975,8 @@ def strip_pktload(pkt=None, layer="L2"):
 ###############################################################################
 ###############################################################################
 if __name__ == "__main__":
-    inst = sniff_packets("lo", timeout=5, filters=[{'layer': 'ether',
-                         'config': {'dst': 'FF:FF:FF:FF:FF:FF'}}])
-    inst = sniff_packets("lo", timeout=5)
     pkt = Packet(pkt_type='UDP')
     pkt.send_pkt(tx_port='lo')
-    pkts = load_sniff_packets(inst)
 
     pkt = Packet(pkt_type='UDP', pkt_len=1500, ran_payload=True)
     pkt.send_pkt(tx_port='lo')
diff --git a/framework/tester.py b/framework/tester.py
index a775f68..4e651a1 100755
--- a/framework/tester.py
+++ b/framework/tester.py
@@ -35,6 +35,7 @@ Interface for bulk traffic generators.
 
 import re
 import subprocess
+import os
 from time import sleep
 from settings import NICS, load_global_setting, PERF_SETTING
 from crb import Crb
@@ -560,8 +561,6 @@ class Tester(Crb):
         module = __import__("packet")
         pkt_c = getattr(module, "Packet")
         send_f = getattr(module, "send_packets")
-        sniff_f = getattr(module, "sniff_packets")
-        load_f = getattr(module, "load_sniff_packets")
         compare_f = getattr(module, "compare_pktload")
         strip_f = getattr(module, "strip_pktload")
         save_f = getattr(module, "save_packets")
@@ -606,7 +605,7 @@ class Tester(Crb):
 
             # send and sniff packets
             save_f(pkts=pkts, filename="/tmp/%s_tx.pcap" % txIntf)
-            inst = sniff_f(intf=rxIntf, count=pktnum, timeout=timeout, filters=
+            inst = self.tcpdump_sniff_packets(intf=rxIntf, count=pktnum, timeout=timeout, filters=
                 [{'layer': 'network', 'config': {'srcport': '65535'}},
                  {'layer': 'network', 'config': {'dstport': '65535'}}])
             rx_inst[rxport] = inst
@@ -627,7 +626,7 @@ class Tester(Crb):
         # Verify all packets
         prev_id = -1
         for txport, rxport in portList:
-            recv_pkts = load_f(rx_inst[rxport])
+            recv_pkts = self.load_tcpdump_sniff_packets(rx_inst[rxport])
 
             # only report when recevied number not matched
             if len(tx_pkts[txport]) > len(recv_pkts):
@@ -704,6 +703,47 @@ class Tester(Crb):
             self.proc.kill()
             self.proc = None
 
+    def tcpdump_sniff_packets(self, intf, count=0, timeout=5, filters=[]):
+        """
+        Wrapper for packet module sniff_packets
+        """
+        # load functions in packet module
+        module = __import__("packet")
+        sniff_f = getattr(module, "sniff_packets")
+
+        target=[]
+        target.append(self.get_ip_address())
+        target.append(self.get_username())
+        target.append(self.get_password())
+        return sniff_f(intf, count, timeout, filters, target)
+
+    def load_tcpdump_sniff_pcap(self, index=''):
+        """
+        Wrapper for packet module load_sniff_pcap
+        """
+        # load functions in packet module
+        module = __import__("packet")
+        load_pcap_f = getattr(module, "load_sniff_pcap")
+
+        target=[]
+        target.append(self.get_ip_address())
+        target.append(self.get_username())
+        target.append(self.get_password())
+        pcap = load_pcap_f(index, target)
+        self.session.copy_file_from(pcap)
+
+        return pcap.split(os.sep)[-1]
+
+    def load_tcpdump_sniff_packets(self, index=''):
+        """
+        Wrapper for packet module load_pcapfile
+        """
+        # load functions in packet module
+        packet = __import__("packet")
+        file = self.load_tcpdump_sniff_pcap(index)
+
+        return packet.load_pcapfile(file)
+
     def kill_all(self, killall=False):
         """
         Kill all scapy process or DPDK application on tester.
-- 
2.7.4



More information about the dts mailing list