From: "Chen, Zhaoyan" <zhaoyan.chen@intel.com>
To: "Xiao, QimaiX" <qimaix.xiao@intel.com>, "dts@dpdk.org" <dts@dpdk.org>
Cc: "Xiao, QimaiX" <qimaix.xiao@intel.com>,
"Chen, Zhaoyan" <zhaoyan.chen@intel.com>
Subject: Re: [dts] [PATCH V1] framework/packet: update packet module of dts
Date: Tue, 8 Oct 2019 02:22:06 +0000 [thread overview]
Message-ID: <9DEEADBC57E43F4DA73B571777FECECA41DD7342@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <20190927180539.2344-2-qimaix.xiao@intel.com>
Acked-by: Chen, Zhaoyan <zhaoyan.chen@intel.com>
Regards,
Zhaoyan Chen
> -----Original Message-----
> From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of Qimai Xiao
> Sent: Saturday, September 28, 2019 2:06 AM
> To: dts@dpdk.org
> Cc: Xiao, QimaiX <qimaix.xiao@intel.com>
> Subject: [dts] [PATCH V1] framework/packet: update packet module of dts
>
> update API of packet and some other optimization
>
> Signed-off-by: Qimai Xiao <qimaix.xiao@intel.com>
> ---
> framework/packet.py | 665 +++++++++++++++++++++++---------------------
> 1 file changed, 354 insertions(+), 311 deletions(-)
>
> diff --git a/framework/packet.py b/framework/packet.py index 502d85c..05b2367
> 100755
> --- a/framework/packet.py
> +++ b/framework/packet.py
> @@ -33,35 +33,19 @@
> Generic packet create, transmit and analyze module Base on scapy(python program
> for packet manipulation) """
> -import os
> -import time
> -import sys
> -import re
> -import signal
> -import random
> -import subprocess
> -import shlex # separate command line for pipe
> -from uuid import uuid4
> -from settings import FOLDERS
> -
> -import struct
> +
> from socket import AF_INET6
> -from scapy.all import conf
> -from scapy.utils import wrpcap, rdpcap, hexstr -from scapy.layers.inet import Ether,
> IP, TCP, UDP, ICMP -from scapy.layers.inet6 import IPv6, IPv6ExtHdrRouting,
> IPv6ExtHdrFragment -from scapy.layers.l2 import Dot1Q, ARP, GRE
> +from scapy.all import *
> from scapy.layers.sctp import SCTP, SCTPChunkData -from scapy.sendrecv import
> sniff -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__)
> DTS_PATH = exec_file.replace('/framework/packet.py', '')
> +# exec_file might be .pyc file, if so, remove 'c'.
> +TMP_PATH = DTS_PATH[:-1] + '/output/tmp/pcap/' if exec_file.endswith('.pyc')
> else DTS_PATH + '/output/tmp/pcap/'
> +
> +if not os.path.exists(TMP_PATH):
> + os.system('mkdir -p %s' % TMP_PATH)
> DEP_FOLDER = DTS_PATH + '/dep'
> sys.path.append(DEP_FOLDER)
>
> @@ -70,9 +54,8 @@ from nvgre import NVGRE, IPPROTO_NVGRE from lldp import
> LLDP, LLDPManagementAddress from Dot1BR import Dot1BR
>
> -# get tester logger
> -from logger import getLogger
> -logger = getLogger('tester')
> +from utils import convert_ip2int
> +from utils import convert_int2ip
>
> # for saving command history
> from utils import get_backtrace_object
> @@ -150,7 +133,16 @@ class scapy(object):
>
> def __init__(self):
> self.pkt = None
> - pass
> + self.pkts = []
> +
> + def append_pkts(self):
> + self.pkts.append(self.pkt)
> +
> + def update_pkts(self):
> + if not self.pkts: # update pkt to a null pkt list.
> + self.pkts.append(self.pkt)
> + else:
> + self.pkts[-1] = self.pkt
>
> def assign_pkt(self, pkt):
> self.pkt = pkt
> @@ -179,14 +171,14 @@ class scapy(object):
> if type is not None:
> pkt_layer.type = type
>
> - def strip_vlan(self, element):
> + def strip_vlan(self, element, p_index=0):
> value = None
>
> - if self.pkt.haslayer('Dot1Q') is 0:
> + if self.pkts[p_index].haslayer('Dot1Q') is 0:
> return None
>
> if element == 'vlan':
> - value = int(str(self.pkt[Dot1Q].vlan))
> + value = int(str(self.pkts[p_index][Dot1Q].vlan))
> return value
>
> def etag(self, pkt_layer, ECIDbase=0, prio=0, type=None):
> @@ -197,19 +189,19 @@ class scapy(object):
> if type is not None:
> pkt_layer.type = type
>
> - def strip_etag(self, element):
> + def strip_etag(self, element, p_index=0):
> value = None
>
> - if self.pkt.haslayer('Dot1BR') is 0:
> + if self.pkts[p_index].haslayer('Dot1BR') is 0:
> return None
>
> if element == 'ECIDbase':
> - value = int(str(self.pkt[Dot1BR].ECIDbase))
> + value = int(str(self.pkts[p_index][Dot1BR].ECIDbase))
> return value
>
> - def strip_layer2(self, element):
> + def strip_layer2(self, element, p_index=0):
> value = None
> - layer = self.pkt.getlayer(0)
> + layer = self.pkts[p_index].getlayer(0)
> if layer is None:
> return None
>
> @@ -222,9 +214,9 @@ class scapy(object):
>
> return value
>
> - def strip_layer3(self, element):
> + def strip_layer3(self, element, p_index=0):
> value = None
> - layer = self.pkt.getlayer(1)
> + layer = self.pkts[p_index].getlayer(1)
> if layer is None:
> return None
>
> @@ -237,9 +229,9 @@ class scapy(object):
>
> return value
>
> - def strip_layer4(self, element):
> + def strip_layer4(self, element, p_index=0):
> value = None
> - layer = self.pkt.getlayer(2)
> + layer = self.pkts[p_index].getlayer(2)
> if layer is None:
> return None
>
> @@ -252,7 +244,8 @@ class scapy(object):
>
> return value
>
> - def ipv4(self, pkt_layer, frag=0, src="127.0.0.1", proto=None, tos=0,
> dst="127.0.0.1", chksum=None, len=None, version=4, flags=None, ihl=None, ttl=64,
> id=1, options=None):
> + def ipv4(self, pkt_layer, frag=0, src="127.0.0.1", proto=None, tos=0,
> dst="127.0.0.1", chksum=None, len=None,
> + version=4, flags=None, ihl=None, ttl=64, id=1, options=None):
> pkt_layer.frag = frag
> pkt_layer.src = src
> if proto is not None:
> @@ -287,7 +280,7 @@ class scapy(object):
> pkt_layer.src = src
> pkt_layer.dst = dst
>
> - def tcp(self, pkt_layer, src=53, dst=53, flags=None, len=None, chksum=None):
> + def tcp(self, pkt_layer, src=53, dst=53, flags=0, len=None, chksum=None):
> pkt_layer.sport = src
> pkt_layer.dport = dst
> if flags is not None:
> @@ -328,66 +321,6 @@ class scapy(object):
> def vxlan(self, pkt_layer, vni=0):
> pkt_layer.vni = vni
>
> - def read_pcap(self, file):
> - pcap_pkts = []
> - try:
> - pcap_pkts = rdpcap(file)
> - except:
> - pass
> -
> - return pcap_pkts
> -
> - def write_pcap(self, file):
> - try:
> - wrpcap(file, self.pkt)
> - except:
> - pass
> -
> - def send_pcap_pkt(self, crb=None, file='', intf='', count=1):
> - if intf == '' or file == '' or crb is None:
> - print "Invalid option for send packet by scapy"
> - return
> -
> - content = 'pkts=rdpcap(\"%s\");sendp(pkts, iface=\"%s\",
> count=\"%s\" );exit()' % (file, intf, count)
> - cmd_file = '/tmp/scapy_%s.cmd' % intf
> -
> - crb.create_file(content, cmd_file)
> - crb.send_expect("scapy -c scapy_%s.cmd &" % intf, "# ")
> -
> - def print_summary(self):
> - # save command into test case history
> - history_list = get_backtrace_object('test_case.py', 'test_history')
> - if type(history_list) is list:
> - history_list.append({"command": "p=%s" % self.pkt.command(), "name":
> "Scapy", "output": ""})
> -
> - logger.info("%s" % self.pkt.command())
> -
> - def send_pkt(self, intf='', count=1):
> - self.print_summary()
> -
> - if intf != '':
> - # wait few seconds for link ready
> - countdown = 600
> - while countdown:
> - link_st = subprocess.check_output("ip link show %s" % intf,
> - stderr=subprocess.STDOUT,
> - shell=True)
> - if "LOWER_UP" in link_st:
> - break
> - else:
> - time.sleep(0.01)
> - countdown -= 1
> - continue
> -
> - # fix fortville can't receive packets with 00:00:00:00:00:00
> - if self.pkt.getlayer(0).src == "00:00:00:00:00:00":
> - self.pkt.getlayer(0).src = get_if_hwaddr(intf)
> - sendp(self.pkt, iface=intf, count=count)
> -
> - # save command into test case history
> - history_list = get_backtrace_object('test_case.py', 'test_history')
> - if type(history_list) is list:
> - history_list.append({"command": "sendp(p, iface=\"%s\")" % intf, "name":
> "Scapy", "output": ""})
>
> class Packet(object):
>
> @@ -413,10 +346,11 @@ class Packet(object):
> 'IPv6_SCTP': {'layers': ['ether', 'ipv6', 'sctp', 'raw'], 'cfgload': True},
> }
>
> - def __init__(self, **options):
> + def __init__(self, pkt_str=None, **options):
> """
> pkt_type: description of packet type
> defined in def_packet
> + args: specify a packet with a string explicitly, will ignore
> + options
> options: special option for Packet module
> pkt_len: length of network packet
> ran_payload: whether payload of packet is random @@ -424,14 +358,41
> @@ class Packet(object):
> pkt_gen: packet generator type
> now only support scapy
> """
> - self.pkt_layers = []
> - self.pkt_len = 64
> self.pkt_opts = options
> + self.pkt_layers = []
>
> - self.pkt_type = "UDP"
> + if 'pkt_gen' in self.pkt_opts.keys():
> + if self.pkt_opts['pkt_gen'] == 'scapy':
> + self.pktgen = scapy()
> + else:
> + print "Not support other pktgen yet!!!"
> + else:
> + self.pktgen = scapy()
>
> - if 'pkt_type' in self.pkt_opts.keys():
> - self.pkt_type = self.pkt_opts['pkt_type']
> + if pkt_str is not None and type(pkt_str) == str:
> + self._scapy_str_to_pkt(pkt_str)
> + elif len(options) == 0:
> + pass
> + else:
> + self._add_pkt(self.pkt_opts)
> + if self.pktgen.pkt is not None:
> + self.pktgen.append_pkts()
> +
> + def __len__(self):
> + return len(self.pktgen.pkts)
> +
> + def __getitem__(self, item):
> + return self.pktgen.pkts[item]
> +
> + def _add_pkt(self, options):
> + """
> + :param options: packt configuration, dictionary type
> + :return:
> + """
> + self.pkt_len = 64
> + self.pkt_type = "UDP"
> + if 'pkt_type' in options.keys():
> + self.pkt_type = options['pkt_type']
>
> if self.pkt_type in self.def_packet.keys():
> self.pkt_layers = self.def_packet[self.pkt_type]['layers']
> @@ -441,21 +402,8 @@ class Packet(object):
> else:
> self._load_pkt_layers()
>
> - if 'pkt_len' in self.pkt_opts.keys():
> - self.pkt_len = self.pkt_opts['pkt_len']
> -
> - if 'pkt_file' in self.pkt_opts.keys():
> - self.uni_name = self.pkt_opts['pkt_file']
> - else:
> - self.uni_name = '/tmp/' + str(uuid4()) + '.pcap'
> -
> - if 'pkt_gen' in self.pkt_opts.keys():
> - if self.pkt_opts['pkt_gen'] == 'scapy':
> - self.pktgen = scapy()
> - else:
> - print "Not support other pktgen yet!!!"
> - else:
> - self.pktgen = scapy()
> + if 'pkt_len' in options.keys():
> + self.pkt_len = options['pkt_len']
>
> self._load_assign_layers()
>
> @@ -483,32 +431,227 @@ class Packet(object):
> raw_confs['payload'] = payload
> self.config_layer('raw', raw_confs)
>
> - def send_pkt(self, crb=None, tx_port='', auto_cfg=True, count=1):
> - if tx_port == '':
> - print "Invalid Tx interface"
> - return
> + def _scapy_str_to_pkt(self, scapy_str):
> + """
>
> - self.tx_port = tx_port
> + :param scapy_str: packet str, eg. 'Ether()/IP()/UDP()'
> + :return: None
> + """
> + layer_li = [re.sub('\(.*?\)', '', i) for i in scapy_str.split('/')]
> + self.pkt_type = '_'.join(layer_li)
> + self._load_pkt_layers()
> + pkt = eval(scapy_str)
> + self.pktgen.assign_pkt(pkt)
>
> - # check with port type
> - if 'ixia' in self.tx_port:
> - print "Not Support Yet"
> + def append_pkt(self, args=None, **kwargs):
> + """
> + :param args: take str type as pkt to append
> + :param kwargs: take dictory type as pkt to append
> + :return: None
> + """
> + if isinstance(args, str):
> + self._scapy_str_to_pkt(args)
> + elif isinstance(kwargs, dict):
> + self.pkt_opts = kwargs
> + if hasattr(self, 'configured_layer_raw'):
> + delattr(self, 'configured_layer_raw')
> + self._add_pkt(kwargs)
> + self.pktgen.append_pkts()
> +
> + def generate_random_pkts(self, dstmac=None, pktnum=100, random_type=None,
> ip_increase=True, random_payload=False,
> + options=None):
> + """
> + # generate random packets
> + :param dstmac: specify the dst mac
> + :param pktnum: packet number to generate
> + :param random_type: specify random packet type
> + :param ip_increase: auto increase ip value
> + :param random_payload: if True, generate random packets with random
> payload
> + :param options: packet layer configuration
> + :return: None
> + """
>
> - if crb is not None:
> - self.pktgen.write_pcap(self.uni_name)
> - crb.session.copy_file_to(self.uni_name)
> - pcap_file = self.uni_name.split('/')[2]
> - self.pktgen.send_pcap_pkt(
> - crb=crb, file=pcap_file, intf=self.tx_port, count=count)
> + random_type = ['TCP', 'UDP', 'IPv6_TCP', 'IPv6_UDP'] if random_type is None
> else random_type
> + options = {'ip': {'src': '192.168.0.1', 'dst': '192.168.1.1'},
> + 'layers_config': []} if options is None else options
> + # give a default value to ip
> + try:
> + src_ip_num = convert_ip2int(options['ip']['src'])
> + except:
> + src_ip_num = 0
> + try:
> + dst_ip_num = convert_ip2int(options['ip']['dst'])
> + except:
> + dst_ip_num = 0
> +
> + for i in range(pktnum):
> + # random the packet type
> + self.pkt_type = random.choice(random_type)
> + self.pkt_layers = self.def_packet[self.pkt_type]['layers']
> + self.check_layer_config()
> + self.pktgen.add_layers(self.pkt_layers)
> + # hardcode src/dst port for some protocol may cause issue
> + if "TCP" in self.pkt_type:
> + self.config_layer('tcp', {'src': 65535, 'dst': 65535})
> + if "UDP" in self.pkt_type:
> + self.config_layer('udp', {'src': 65535, 'dst': 65535})
> + if options.has_key('layers_config'):
> + self.config_layers(options['layers_config'])
> + if dstmac:
> + self.config_layer('ether', {'dst': '%s' % dstmac})
> + # generate auto increase dst ip packet
> + if ip_increase:
> + if 'v6' in self.pkt_type:
> + dstip = convert_int2ip(dst_ip_num, ip_type=6)
> + srcip = convert_int2ip(src_ip_num, ip_type=6)
> + self.config_layer('ipv6', config={'dst': '%s' % (dstip), 'src': '%s' % srcip})
> + else:
> + dstip = convert_int2ip(dst_ip_num, ip_type=4)
> + srcip = convert_int2ip(src_ip_num, ip_type=4)
> + self.config_layer('ipv4', config={'dst': '%s' % (dstip), 'src': '%s' % srcip})
> + dst_ip_num += 1
> + # generate random payload of packet
> + if random_payload and self.def_packet[self.pkt_type]['cfgload']:
> + # TCP packet has a default flags S, packet should not load data, so set it to A
> if has payload
> + if 'TCP' in self.pkt_type:
> + self.config_layer('tcp', {'src': 65535, 'dst':
> + 65535, 'flags': 'A'})
> +
> + payload_len = random.randint(64, 100)
> + payload = []
> + for _ in range(payload_len):
> + payload.append("%02x" % random.randrange(0, 255))
> + self.config_layer('raw', config={'payload': payload})
> + self.pktgen.append_pkts()
> +
> + def save_pcapfile(self, crb=None, filename='saved_pkts.pcap'):
> + """
> +
> + :param crb: session or crb object
> + :param filename: location and name for packets to be saved
> + :return: None
> + """
> + # save pkts to pcap file to local path, then copy to remote tester tmp directory,
> + if crb:
> + trans_path = crb.tmp_file
> + file_name = filename
> + if os.path.isabs(filename): # check if the given filename with a abs path
> + file_dir = os.path.dirname(filename)
> + out = crb.send_expect('ls -d %s' % file_dir, '# ', verify=True)
> + if not isinstance(out, str):
> + raise Exception('%s may not existed on %s' % (file_dir, crb.name))
> + wrpcap(filename, self.pktgen.pkts)
> + trans_path = os.path.abspath(filename)
> + file_name = filename.split(os.path.sep)[-1]
> + # write packets to local tmp path $dts/ouput/tmp/pcap/
> + wrpcap(TMP_PATH + file_name, self.pktgen.pkts)
> + # copy to remote tester tmp path /tmp/tester
> + crb.session.copy_file_to(TMP_PATH + file_name, trans_path)
> else:
> - self.pktgen.send_pkt(intf=self.tx_port, count=count)
> + wrpcap(filename, self.pktgen.pkts)
>
> - def check_layer_config(self, layer, config):
> + def read_pcapfile(self, filename, crb=None):
> + """
> +
> + :param filename: packet to be read from
> + :param crb: session or crb object
> + :return: scapy type packet
> + """
> + # read pcap file from local or remote, then append to pkts list
> + # if crb, read pakcet from remote server, else read from local location
> + if crb:
> + out = crb.send_expect('ls -d %s' % filename, '# ', verify=True)
> + if not isinstance(out, str):
> + raise Exception('%s may not existed on %s' % (filename, crb.name))
> + crb.session.copy_file_from(filename, TMP_PATH)
> + p = rdpcap(TMP_PATH + filename.split(os.path.sep)[-1])
> + else:
> + p = rdpcap(filename)
> + if len(p) == 0:
> + return None
> + self.pktgen.assign_pkt(p[-1])
> + for i in p:
> + self.pktgen.pkts.append(i)
> + return p
> +
> + def _send_pkt(self, crb, tx_port='', count=1, send_bg=False, loop=0, inter=0,
> timeout=15):
> + """
> +
> + :param crb: session or crb object
> + :param tx_port: ether to send packet
> + :param count: send times
> + :param send_bg: send packet background
> + :param loop: send packet in a loop
> + :param inter: interval time
> + :return: None
> + """
> + # save pkts to local pcap file, then copy to remote tester tmp
> + directory
> +
> + time_stamp = str(time.time())
> + pcap_file = 'scapy_{}.pcap'.format(tx_port) + time_stamp
> + self.save_pcapfile(crb, pcap_file)
> + scapy_cmd = 'scapy_{}.cmd'.format(tx_port) + time_stamp
> + cmd_str = 'from scapy.all import *\np=rdpcap("%s")\nprint("packet ready for
> sending...")\nfor i in p:\n\tprint(i.command())\nsendp(p, iface="%s", count=%d,
> loop=%d, inter=%0.3f)' % (
> + crb.tmp_file + pcap_file, tx_port, count, loop, inter)
> + # write send cmd file to local tmp directory then copy to remote tester tmp
> folder
> + with open(TMP_PATH + scapy_cmd, 'w') as f:
> + f.write(cmd_str)
> + crb.session.copy_file_to(TMP_PATH + scapy_cmd, crb.tmp_file)
> +
> + if send_bg: # if send_bg create a new session to execute send action
> + session_prefix = 'scapy_bg_session'
> + scapy_session = crb.create_session(session_prefix + time_stamp)
> + scapy_session.send_command('python %s' % crb.tmp_file + scapy_cmd)
> + else:
> + crb.send_expect('python %s' % crb.tmp_file + scapy_cmd, '# ',
> timeout=timeout)
> + return crb.tmp_file + scapy_cmd
> +
> + def send_pkt(self, crb, tx_port='', count=1, interval=0, timeout=15):
> + self._send_pkt(crb, tx_port, count, inter=interval,
> + timeout=timeout)
> +
> + def send_pkt_bg(self, crb, tx_port='', count=-1, loop=1, interval=0, timeout=3):
> + return self._send_pkt(crb, tx_port=tx_port, count=count, send_bg=True,
> loop=loop, inter=interval,
> + timeout=timeout)
> +
> + def stop_send_pkt_bg(self, crb, filenames):
> + # stop sending action
> + pids = []
> + if isinstance(filenames, list):
> + for file in filenames:
> + out = crb.send_expect('ps -ef |grep %s|grep -v grep' % file, expected='# ')
> + try:
> + pids.append(re.search('\d+', out).group())
> + except AttributeError as e:
> + print(e, ' :%s not killed' % file)
> + else:
> + out = crb.send_expect('ps -ef |grep %s|grep -v grep' % filenames, expected='#
> ')
> + try:
> + pids.append(re.search('\d+', out).group())
> + except AttributeError as e:
> + print(e, ' :%s not killed' % filenames)
> + pid = ' '.join(pids)
> + if pid:
> + crb.send_expect('kill -9 %s' % pid, expected='# ')
> + for i in crb.sessions:
> + if i.name.startswith('scapy_bg_session'):
> + crb.destroy_session(i)
> +
> + def check_layer_config(self):
> """
> check the format of layer configuration
> every layer should has different check function
> """
> - pass
> + for layer in self.pkt_layers:
> + found = False
> + l_type = layer.lower()
> +
> + for types in LayersTypes.values():
> + if l_type in types:
> + found = True
> + break
> +
> + if found is False:
> + self.pkt_layers.remove(l_type)
> + print "INVAILD LAYER TYPE [%s]" % l_type.upper()
>
> def assign_layers(self, layers=None):
> """
> @@ -532,6 +675,8 @@ class Packet(object):
> print "INVAILD LAYER TYPE [%s]" % l_type.upper()
>
> self.pktgen.add_layers(self.pkt_layers)
> + if layers:
> + self.pktgen.update_pkts()
>
> def _load_pkt_layers(self):
> name2type = {
> @@ -590,9 +735,9 @@ class Packet(object):
> else:
> self.config_layer('raw', {'payload': ['00'] * 18})
>
> - if "MAC_IP_IPv6" in self.pkt_type or\
> - "MAC_IP_NVGRE" in self.pkt_type or \
> - "MAC_IP_UDP_VXLAN" in self.pkt_type:
> + if "MAC_IP_IPv6" in self.pkt_type or \
> + "MAC_IP_NVGRE" in self.pkt_type or \
> + "MAC_IP_UDP_VXLAN" in self.pkt_type:
> if "IPv6_SCTP" in self.pkt_type:
> self.config_layer('ipv6', {'nh': 132})
> if "IPv6_ICMP" in self.pkt_type:
> @@ -601,6 +746,8 @@ class Packet(object):
> self.config_layer('raw', {'payload': ['00'] * 40})
> else:
> self.config_layer('raw', {'payload': ['00'] * 18})
> + if 'TCP' in self.pkt_type:
> + self.config_layer('tcp', {'flags': 0})
>
> def config_layer(self, layer, config={}):
> """
> @@ -613,22 +760,23 @@ class Packet(object):
> print "INVALID LAYER ID %s" % layer
> return False
>
> - if self.check_layer_config(layer, config) is False:
> + if self.check_layer_config() is False:
> return False
>
> if 'inner' in layer:
> layer = layer[6:]
>
> pkt_layer = self.pktgen.pkt.getlayer(idx)
> - layer_conf = getattr(self, "_config_layer_%s" % layer)
> + layer_conf = getattr(self.pktgen, layer)
> setattr(self, 'configured_layer_%s' % layer, True)
>
> - return layer_conf(pkt_layer, config)
> + layer_conf(pkt_layer, **config)
>
> def config_layers(self, layers=None):
> """
> Configure packet with multi configurations
> """
> + layers = [] if layers is None else layers # None object is not
> + Iterable
> for layer in layers:
> name, config = layer
> if name not in self.pkt_layers:
> @@ -638,65 +786,28 @@ class Packet(object):
> print "[%s] failed to configure!!!" % name
> raise
>
> - def _config_layer_ether(self, pkt_layer, config):
> - return self.pktgen.ether(pkt_layer, **config)
> -
> - def _config_layer_mac(self, pkt_layer, config):
> - return self.pktgen.ether(pkt_layer, **config)
> -
> - def _config_layer_vlan(self, pkt_layer, config):
> - return self.pktgen.vlan(pkt_layer, **config)
> -
> - def _config_layer_etag(self, pkt_layer, config):
> - return self.pktgen.etag(pkt_layer, **config)
> -
> - def _config_layer_ipv4(self, pkt_layer, config):
> - return self.pktgen.ipv4(pkt_layer, **config)
> -
> - def _config_layer_ipv6(self, pkt_layer, config):
> - return self.pktgen.ipv6(pkt_layer, **config)
> -
> - def _config_layer_udp(self, pkt_layer, config):
> - return self.pktgen.udp(pkt_layer, **config)
> -
> - def _config_layer_tcp(self, pkt_layer, config):
> - return self.pktgen.tcp(pkt_layer, **config)
> -
> - def _config_layer_sctp(self, pkt_layer, config):
> - return self.pktgen.sctp(pkt_layer, **config)
> -
> - def _config_layer_gre(self, pkt_layer, config):
> - return self.pktgen.gre(pkt_layer, **config)
> -
> - def _config_layer_raw(self, pkt_layer, config):
> - return self.pktgen.raw(pkt_layer, **config)
> -
> - def _config_layer_vxlan(self, pkt_layer, config):
> - return self.pktgen.vxlan(pkt_layer, **config)
> -
> - def strip_layer_element(self, layer, element):
> + def strip_layer_element(self, layer, element, p_index=0):
> """
> Strip packet layer elements
> return the status of configure result
> """
> strip_element = getattr(self, "strip_element_%s" % layer)
> + return strip_element(element, p_index)
>
> - return strip_element(element)
> -
> - def strip_element_layer2(self, element):
> - return self.pktgen.strip_layer2(element)
> + def strip_element_layer2(self, element, p_index=0):
> + return self.pktgen.strip_layer2(element, p_index)
>
> - def strip_element_layer3(self, element):
> - return self.pktgen.strip_layer3(element)
> + def strip_element_layer3(self, element, p_index=0):
> + return self.pktgen.strip_layer3(element, p_index)
>
> - def strip_element_vlan(self, element):
> - return self.pktgen.strip_vlan(element)
> + def strip_element_vlan(self, element, p_index=0):
> + return self.pktgen.strip_vlan(element, p_index)
>
> - def strip_element_etag(self, element):
> - return self.pktgen.strip_etag(element)
> + def strip_element_etag(self, element, p_index=0):
> + return self.pktgen.strip_etag(element, p_index)
>
> - def strip_element_layer4(self, element):
> - return self.pktgen.strip_layer4(element)
> + def strip_element_layer4(self, element, p_index=0):
> + return self.pktgen.strip_layer4(element, p_index)
>
>
> def IncreaseIP(addr):
> @@ -725,27 +836,6 @@ def IncreaseIPv6(addr):
> return ipv6
>
>
> -def send_packets(intf, pkts=None, interval=0.01):
> - send_pkts = []
> - try:
> - for pkt in pkts:
> - send_pkts.append(pkt.pktgen.pkt)
> - sendp(send_pkts, iface=intf, inter=interval, verbose=False)
> - except:
> - pass
> -
> -
> -def save_packets(pkts=None, filename=None):
> - save_pkts = []
> - try:
> - for pkt in pkts:
> - save_pkts.append(pkt.pktgen.pkt)
> - if filename:
> - wrpcap(filename, save_pkts)
> - except:
> - pass
> -
> -
> def get_ether_type(eth_type=""):
> # need add more types later
> if eth_type.lower() == "lldp":
> @@ -809,48 +899,46 @@ def get_filter_cmd(filters=[]):
> return ""
>
>
> -def sniff_packets(intf, count=0, timeout=5, filters=[], target=[]):
> +def start_tcpdump(crb, intf, count=0, filters=None, lldp_forbid=True):
> """
> - sniff all packets for certain port in certain seconds
> + sniff all packets from certain port
> """
> + filters = [] if filters is None else filters
> + out = crb.send_expect("ls -d %s" % crb.tmp_file, "# ", verify=True)
> + if out == 2:
> + crb.send_expect("mkdir -p %s" % crb.tmp_file, "# ")
> + filename = '{}sniff_{}.pcap'.format(crb.tmp_file, intf)
> + # delete old pcap file
> + crb.send_expect('rm -rf %s' % filename, '# ')
> +
> param = ""
> direct_param = r"(\s+)\[ (\S+) in\|out\|inout \]"
> -
> - 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)
> + tcpdump_session = crb.create_session('tcpdump_session' + str(time.time()))
> + setattr(tcpdump_session, 'tmp_file', crb.tmp_file)
> + tcpdump_help = tcpdump_session.send_command('tcpdump -h')
>
> for line in tcpdump_help.split('\n'):
> m = re.match(direct_param, line)
> if m:
> - opt = re.search("-Q", m.group(2));
> + opt = re.search("-Q", m.group(2))
> if opt:
> param = "-Q" + " in"
> else:
> - opt = re.search("-P", m.group(2));
> + opt = re.search("-P", m.group(2))
> if opt:
> param = "-P" + " in"
>
> if len(param) == 0:
> print "tcpdump not support direction choice!!!"
>
> - if LLDP_FILTER not in filters:
> + if lldp_forbid and (LLDP_FILTER not in filters):
> filters.append(LLDP_FILTER)
>
> filter_cmd = get_filter_cmd(filters)
>
> sniff_cmd = 'tcpdump -i %(INTF)s %(FILTER)s %(IN_PARAM)s -w %(FILE)s'
> options = {'INTF': intf, 'COUNT': count, 'IN_PARAM': param,
> - 'FILE': '/tmp/sniff_%s.pcap' % intf,
> + 'FILE': filename,
> 'FILTER': filter_cmd}
> if count:
> sniff_cmd += ' -c %(COUNT)d'
> @@ -858,77 +946,27 @@ def sniff_packets(intf, count=0, timeout=5, filters=[],
> target=[]):
> else:
> cmd = sniff_cmd % options
>
> - 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)
> + tcpdump_session.send_command(cmd)
>
> index = str(time.time())
> - SNIFF_PIDS[index] = (pipe, intf, timeout)
> + SNIFF_PIDS[index] = (tcpdump_session, intf, filename)
> time.sleep(1)
> return index
>
>
> -def load_sniff_pcap(index='', target=[]):
> +def stop_and_load_tcpdump_packets(index='', timeout=1):
> """
> - Stop sniffer and return pcap file
> + Stop sniffer and return packet object
> """
> - 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.prompt(timeout=1):
> - child_exit = True
> - break
> -
> - time_elapse += 1
> -
> - if not child_exit:
> - 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
> - except pxssh.ExceptionPxssh as e:
> - print ('pxssh failed on login.')
> - print (e)
> -
> - # Close the Tcpdump_session
> - pipe.prompt()
> - pipe.logout()
> -
> - # wait pcap file ready
> - time.sleep(1)
> - return "/tmp/sniff_%s.pcap" % intf
> -
> - return ""
> -
> -
> -def load_pcapfile(filename=""):
> - pkts = []
> - try:
> - cap_pkts = rdpcap(filename)
> - for pkt in cap_pkts:
> - # packet gen should be scapy
> - packet = Packet()
> - packet.pktgen.assign_pkt(pkt)
> - pkts.append(packet)
> - except:
> - pass
> -
> - return pkts
> + pipe, intf, filename = SNIFF_PIDS.pop(index)
> + pipe.get_session_before(timeout)
> + pipe.send_command('^C')
> + pipe.copy_file_from(filename, TMP_PATH)
> + p = Packet()
> + p.read_pcapfile(TMP_PATH + filename.split(os.sep)[-1])
> + pipe.close()
> + return p
>
>
> def compare_pktload(pkt1=None, pkt2=None, layer="L2"):
> @@ -940,8 +978,8 @@ def compare_pktload(pkt1=None, pkt2=None, layer="L2"):
> elif layer == "L4":
> l_idx = 2
> try:
> - load1 = hexstr(str(pkt1.pktgen.pkt.getlayer(l_idx)))
> - load2 = hexstr(str(pkt2.pktgen.pkt.getlayer(l_idx)))
> + load1 = hexstr(str(pkt1.getlayer(l_idx)))
> + load2 = hexstr(str(pkt2.getlayer(l_idx)))
> except:
> # return pass when scapy failed to extract packet
> return True
> @@ -952,7 +990,7 @@ def compare_pktload(pkt1=None, pkt2=None, layer="L2"):
> return False
>
>
> -def strip_pktload(pkt=None, layer="L2"):
> +def strip_pktload(pkt=None, layer="L2", p_index=0):
> if layer == "L2":
> l_idx = 0
> elif layer == "L3":
> @@ -962,30 +1000,36 @@ def strip_pktload(pkt=None, layer="L2"):
> else:
> l_idx = 0
> try:
> - load = hexstr(str(pkt.pktgen.pkt.getlayer(l_idx)), onlyhex=1)
> + load = hexstr(str(pkt.pktgen.pkts[p_index].getlayer(l_idx)),
> + onlyhex=1)
> except:
> # return pass when scapy failed to extract packet
> load = ""
>
> return load
>
> +
>
> ###########################################################
> ####################
>
> ###########################################################
> ####################
> if __name__ == "__main__":
> - pkt = Packet(pkt_type='UDP')
> - pkt.send_pkt(tx_port='lo')
> +
> + pkt =
> Packet('Ether(type=0x894f)/NSH(Len=0x6,NextProto=0x0,NSP=0x000002,NSI=0xff
> )')
> + sendp(pkt, iface='lo')
> + pkt.config_layer('ipv4', {'dst': '192.168.8.8'})
> + pkt.append_pkt(pkt_type='IPv6_TCP', pkt_len=100)
> + pkt.append_pkt(pkt_type='TCP', pkt_len=100)
> + pkt.config_layer('tcp', config={'flags': 'A'})
> +
> pkt.append_pkt("Ether(dst='11:22:33:44:55:11')/IP(dst='192.168.5.2')/TCP(flags=
> 0)/Raw(load='bbbb')")
> + pkt.generate_random_pkts('11:22:33:44:55:55', random_type=['TCP', 'IPv6_TCP'],
> random_payload=True, pktnum=10)
> + sendp(pkt, iface='lo')
>
> pkt = Packet(pkt_type='UDP', pkt_len=1500, ran_payload=True)
> - pkt.send_pkt(tx_port='lo')
> - pkt = Packet(pkt_type='IPv6_TCP')
> - pkt.send_pkt(tx_port='lo')
> + sendp(pkt, iface='lo')
> pkt = Packet(pkt_type='IPv6_SCTP')
> - pkt.send_pkt(tx_port='lo')
> + sendp(pkt, iface='lo')
> pkt = Packet(pkt_type='VLAN_UDP')
> pkt.config_layer('vlan', {'vlan': 2})
> - pkt.send_pkt(tx_port='lo')
> + sendp(pkt, iface='lo')
>
> - pkt = Packet()
> pkt.assign_layers(['ether', 'vlan', 'ipv4', 'udp',
> 'vxlan', 'inner_mac', 'inner_ipv4', 'inner_udp', 'raw'])
> pkt.config_layer('ether', {'dst': '00:11:22:33:44:55'}) @@ -994,13 +1038,12 @@ if
> __name__ == "__main__":
> pkt.config_layer('udp', {'src': 4789, 'dst': 4789, 'chksum': 0x1111})
> pkt.config_layer('vxlan', {'vni': 2})
> pkt.config_layer('raw', {'payload': ['58'] * 18})
> - pkt.send_pkt(tx_port='lo')
> + sendp(pkt, iface='lo')
>
> - pkt = Packet()
> pkt.assign_layers(['ether', 'vlan', 'ipv4', 'udp',
> 'vxlan', 'inner_mac', 'inner_ipv4', 'inner_udp', 'raw'])
> # config packet
> pkt.config_layers([('ether', {'dst': '00:11:22:33:44:55'}), ('ipv4', {'dst': '1.1.1.1'}),
> ('vxlan', {'vni': 2}), ('raw', {'payload': ['01'] * 18})])
>
> - pkt.send_pkt(tx_port='lo')
> + sendp(pkt, iface='lo')
> --
> 2.17.1
next prev parent reply other threads:[~2019-10-08 2:22 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-27 18:05 [dts] [PATCH V1] tests/: update cases related to new framework Qimai Xiao
2019-09-27 18:05 ` [dts] [PATCH V1] framework/packet: update packet module of dts Qimai Xiao
2019-10-08 2:22 ` Chen, Zhaoyan [this message]
2019-10-12 5:30 ` Tu, Lijuan
2019-09-27 18:05 ` [dts] [PATCH V1] framework/tester: update tester " Qimai Xiao
2019-10-08 2:22 ` Chen, Zhaoyan
2019-10-12 5:30 ` Tu, Lijuan
2019-10-08 2:22 ` [dts] [PATCH V1] tests/: update cases related to new framework Chen, Zhaoyan
2019-10-12 5:30 ` Tu, Lijuan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9DEEADBC57E43F4DA73B571777FECECA41DD7342@SHSMSX104.ccr.corp.intel.com \
--to=zhaoyan.chen@intel.com \
--cc=dts@dpdk.org \
--cc=qimaix.xiao@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).