From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id 69334902 for ; Wed, 16 Sep 2015 15:01:17 +0200 (CEST) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga102.fm.intel.com with ESMTP; 16 Sep 2015 06:00:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.17,539,1437462000"; d="scan'208";a="562796651" Received: from pgsmsx105.gar.corp.intel.com ([10.221.44.96]) by FMSMGA003.fm.intel.com with ESMTP; 16 Sep 2015 06:00:54 -0700 Received: from shsmsx151.ccr.corp.intel.com (10.239.6.50) by PGSMSX105.gar.corp.intel.com (10.221.44.96) with Microsoft SMTP Server (TLS) id 14.3.224.2; Wed, 16 Sep 2015 21:00:51 +0800 Received: from shsmsx103.ccr.corp.intel.com ([169.254.4.110]) by SHSMSX151.ccr.corp.intel.com ([169.254.3.12]) with mapi id 14.03.0248.002; Wed, 16 Sep 2015 21:00:50 +0800 From: "Liu, Yong" To: "Mo, YufengX" , "dts@dpdk.org" Thread-Topic: [dts] [PATCH 1/4] add unified packet type module and test suite Thread-Index: AQHQ8F2yvEstUUcBJk6GGKXL3qf3Bp4/HiVQ Date: Wed, 16 Sep 2015 13:00:49 +0000 Message-ID: <86228AFD5BCD8E4EBFD2B90117B5E81E10EF4E72@SHSMSX103.ccr.corp.intel.com> References: <1442393812-30481-1-git-send-email-yufengx.mo@intel.com> <1442393812-30481-2-git-send-email-yufengx.mo@intel.com> In-Reply-To: <1442393812-30481-2-git-send-email-yufengx.mo@intel.com> Accept-Language: zh-CN, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Cc: yufengmx Subject: Re: [dts] [PATCH 1/4] add unified packet type module and test suite X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: test suite reviews and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Sep 2015 13:01:18 -0000 Hi Yufen, Would you please add more descriptions about this new module. What's its target in DTS framework and the basic concept of it?=20 > -----Original Message----- > From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of Yufen Mo > Sent: Wednesday, September 16, 2015 4:57 PM > To: dts@dpdk.org > Cc: yufengmx > Subject: [dts] [PATCH 1/4] add unified packet type module and test suite >=20 > From: yufengmx >=20 > unified packet type test suite implementation >=20 > Signed-off-by: yufengmx > --- > framework/packet.py | 642 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 642 insertions(+) > create mode 100755 framework/packet.py >=20 > diff --git a/framework/packet.py b/framework/packet.py > new file mode 100755 > index 0000000..0a3f330 > --- /dev/null > +++ b/framework/packet.py > @@ -0,0 +1,642 @@ > +#!/usr/bin/python > +# BSD LICENSE > +# > +# Copyright(c) 2010-2015 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. > +""" > +Generic packet create, transmit and analyze module > +Base on scapy(python program for packet manipulation) > +""" > + > +import os > +import time > +import signal > +import sys > +import re > +import signal > +import random > +import subprocess > +from uuid import uuid4 > +from settings import FOLDERS > + > +from scapy.config import conf > +conf.use_pcap =3D True > + > +from scapy.all import conf > +from scapy.utils import struct, socket, wrpcap, rdpcap > +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.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 > + > + > +sys.path.append(FOLDERS['Depends']) > +# load extension layers > +from vxlan import Vxlan > +bind_layers(UDP, Vxlan, dport=3D4789) > +bind_layers(Vxlan, Ether) > +from nvgre import NVGRE, IPPROTO_NVGRE > +bind_layers(IP, NVGRE, proto=3DIPPROTO_NVGRE) > +bind_layers(NVGRE, Ether) > +from lldp import LLDP, LLDPManagementAddress > +bind_layers(Ether, LLDP, type=3D0x88cc) > + > +# packet generator type should be configured later > +PACKETGEN =3D "scapy" > + > +LayersTypes =3D { > + "L2": ['ether', 'dot1q', '1588', 'arp', 'lldp'], > + # ipv4_ext_unknown, ipv6_ext_unknown > + "L3": ['ipv4','ipv4ihl', 'ipv6', 'ipv4_ext', 'ipv6_ext','ipv6_ext2', > 'ipv6_frag'], > + "L4": ['tcp', 'udp', 'frag', 'sctp', 'icmp', 'nofrag'], > + "TUNNEL": ['ip', 'gre', 'vxlan', 'nvgre', 'geneve', 'grenat'], > + "INNER L2": ['inner_mac', 'inner_mac&vlan'], > + # inner_ipv4_unknown, inner_ipv6_unknown > + "INNER L3": ['inner_ipv4', 'inner_ipv4_ext', 'inner_ipv6', > 'inner_ipv6_ext'], > + "INNER L4": ['inner_tcp', 'inner_udp', 'inner_frag', 'inner_sctp', > 'inner_icmp', 'inner_nofrag'], > + "PAYLOAD": ['raw'] > +} > + > +# Saved back groud sniff process id > +SNIFF_PIDS =3D {} > + > +# Saved packet generator process id > +# used in pktgen or tgen > +PKTGEN_PIDS =3D {} > + > + > +class scapy(object): > + SCAPY_LAYERS =3D { > + 'ether': Ether(dst=3D"ff:ff:ff:ff:ff:ff"), > + 'dot1q': Dot1Q(), > + '1588': Ether(type=3D0x88f7), > + 'arp': ARP(), > + 'ipv4': IP(), > + 'ipv4ihl': IP(ihl=3D10), > + 'ipv4_ext': IP(frag=3D5), > + 'ipv6': IPv6(src=3D"::1"), > + 'ipv6_ext': IPv6(src=3D"::1", nh=3D43)/IPv6ExtHdrRouting(), > + 'ipv6_ext2': IPv6()/IPv6ExtHdrRouting(), > + 'udp': UDP(), > + 'tcp': TCP(), > + 'sctp': SCTP(), > + 'icmp': ICMP(), > + 'gre': GRE(), > + 'raw': Raw(), > + 'vxlan': Vxlan(), > + > + 'inner_mac': Ether(), > + 'inner_mac&vlan': Ether() / Dot1Q(), > + 'inner_ipv4': IP(), > + 'inner_ipv4_ext': IP(), > + 'inner_ipv6': IPv6(src=3D"::1"), > + 'inner_ipv6_ext': IPv6(src=3D"::1"), > + > + 'inner_tcp': TCP(), > + 'inner_udp': UDP(), > + 'inner_sctp': SCTP(), > + 'inner_icmp': ICMP(), > + > + 'lldp': LLDP()/LLDPManagementAddress(), > + 'ip_frag': IP(frag=3D5), > + 'ipv6_frag': IPv6(src=3D"::1")/IPv6ExtHdrFragment(), > + 'ip_in_ip': IP()/IP(), > + 'ip_in_ip_frag': IP()/IP(frag=3D5), > + 'ipv6_in_ip': IP()/IPv6(src=3D"::1"), > + 'ipv6_frag_in_ip': IP()/IPv6(src=3D"::1", > nh=3D44)/IPv6ExtHdrFragment(), > + 'nvgre': NVGRE(), > + 'geneve': "Not Implement", > + } > + > + def __init__(self): > + self.pkt =3D None > + pass > + > + def assign_pkt(self, pkt): > + self.pkt =3D pkt > + > + def add_layers(self, layers): > + self.pkt =3D None > + for layer in layers: > + if self.pkt is not None: > + self.pkt =3D self.pkt / self.SCAPY_LAYERS[layer] > + else: > + self.pkt =3D self.SCAPY_LAYERS[layer] > + > + def ether(self, dst=3D"ff:ff:ff:ff:ff:ff", src=3D"00:00:20:00:00:00"= , > type=3DNone): > + self.pkt[Ether].dst =3D dst > + self.pkt[Ether].src =3D src > + if type is not None: > + self.pkt[Ether].type =3D type > + > + def dot1q(self, vlan, prio=3D0, type=3DNone): > + self.pkt[Dot1Q].vlan =3D int(vlan) > + self.pkt[Dot1Q].prio =3D prio > + if type is not None: > + self.pkt[Dot1Q].type =3D type > + > + def strip_dot1q(self, element): > + value =3D None > + > + if self.pkt.haslayer('Dot1Q') is 0: > + return None > + > + if element =3D=3D 'vlan': > + value =3D int(str(self.pkt[Dot1Q].vlan)) > + return value > + > + def ipv4(self, frag=3D0, src=3D"127.0.0.1", proto=3DNone, tos=3D0, > dst=3D"127.0.0.1", chksum=3DNone, len=3DNone, version=3D4, flags=3DNone, = ihl=3DNone, > ttl=3D64, id=3D1, options=3DNone): > + self.pkt[IP].frag =3D frag > + self.pkt[IP].src =3D src > + if proto is not None: > + self.pkt[IP].proto =3D proto > + self.pkt[IP].tos =3D tos > + self.pkt[IP].dst =3D dst > + if chksum is not None: > + self.pkt[IP].chksum =3D chksum > + if len is not None: > + self.pkt[IP].len =3D len > + self.pkt[IP].version =3D version > + if flags is not None: > + self.pkt[IP].flags =3D flags > + if ihl is not None: > + self.pkt[IP].ihl =3D ihl > + self.pkt[IP].ttl =3D ttl > + self.pkt[IP].id =3D id > + if options is not None: > + self.pkt[IP].options =3D options > + > + def ipv6(self, version=3D6, tc=3D0, fl=3D0, plen=3D0, nh=3D0, hlim= =3D64, > src=3D"::1", dst=3D"::1"): > + """ > + Configure IPv6 protocal. > + """ > + self.pkt[IPv6].version =3D version > + self.pkt[IPv6].tc =3D tc > + self.pkt[IPv6].fl =3D fl > + if plen: > + self.pkt[IPv6].plen =3D plen > + if nh: > + self.pkt[IPv6].nh =3D nh > + self.pkt[IPv6].src =3D src > + self.pkt[IPv6].dst =3D dst > + > + def inner_ipv6(self, version=3D6, tc=3D0, fl=3D0, plen=3D0, nh=3D0, = hlim=3D64, > src=3D"::1", dst=3D"::1"): > + """ > + Configure IPv6 protocal. > + """ > + self.pkt[IPv6][Ether][IPv6].version =3D version > + self.pkt[IPv6][Ether][IPv6].tc =3D tc > + self.pkt[IPv6][Ether][IPv6].fl =3D fl > + if plen: > + self.pkt[IPv6][Ether][IPv6].plen =3D plen > + if nh: > + self.pkt[IPv6][Ether][IPv6].nh =3D nh > + self.pkt[IPv6][Ether][IPv6].src =3D src > + self.pkt[IPv6][Ether][IPv6].dst =3D dst > + > + def udp(self, src=3D53, dst=3D53, len=3DNone, chksum=3DNone): > + self.pkt[UDP].sport =3D src > + self.pkt[UDP].dport =3D dst > + if len is not None: > + self.pkt[UDP].len =3D len > + if chksum is not None: > + self.pkt[UDP].chksum =3D chksum > + > + def raw(self, payload=3DNone): > + if payload is not None: > + self.pkt[Raw].load =3D '' > + for load in payload: > + self.pkt[Raw].load +=3D '%c' % int(load, 16) > + > + def vxlan(self, vni=3D0): > + self.pkt[Vxlan].vni =3D vni > + > + def read_pcap(self, file): > + pcap_pkts =3D [] > + try: > + pcap_pkts =3D 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=3DNone, file=3D'', intf=3D''): > + if intf =3D=3D '' or file =3D=3D '' or crb is None: > + print "Invalid option for send packet by scapy" > + return > + > + content =3D 'pkts=3Drdpcap(\"%s\");sendp(pkts, iface=3D\"%s\");e= xit()' % > (file, intf) > + cmd_file =3D '/tmp/scapy_%s.cmd' % intf > + > + crb.create_file(content, cmd_file) > + crb.send_expect("scapy -c scapy_%s.cmd &" % intf, "# ") > + > + def print_summary(self): > + print "Send out pkt %s" % self.pkt.summary() > + > + def send_pkt(self, intf=3D''): > + self.print_summary() > + if intf !=3D '': > + sendp(self.pkt, iface=3Dintf) > + > + > +class Packet(object): > + """ > + Module for config/create packet > + Based on scapy module > + Usage: assign_layers([layers list]) > + config_layer('layername', {layer config}) > + ... > + """ > + def_packet =3D { > + 'TIMESYNC': {'layers': ['ether', 'raw'], 'cfgload': False}, > + 'ARP': {'layers': ['ether', 'arp'], 'cfgload': False}, > + 'LLDP': {'layers': ['ether', 'lldp'], 'cfgload': False}, > + 'TCP': {'layers': ['ether', 'ipv4', 'tcp', 'raw'], 'cfgload': > True}, > + 'UDP': {'layers': ['ether', 'ipv4', 'udp', 'raw'], 'cfgload': > True}, > + 'SCTP': {'layers': ['ether', 'ipv4', 'sctp', 'raw'], 'cfgload': > True}, > + 'IPv6_TCP': {'layers': ['ether', 'ipv6', 'tcp', 'raw'], 'cfgload= ': > True}, > + 'IPv6_UDP': {'layers': ['ether', 'ipv6', 'udp', 'raw'], 'cfgload= ': > True}, > + 'IPv6_SCTP': {'layers': ['ether', 'ipv6', 'sctp', 'raw'], > 'cfgload': True}, > + } > + > + def __init__(self, **options): > + """ > + pkt_type: description of packet type > + defined in def_packet > + options: special option for Packet module > + pkt_len: length of network packet > + ran_payload: whether payload of packet is random > + pkt_file: > + pkt_gen: packet generator type > + now only support scapy > + """ > + self.pkt_layers =3D [] > + self.pkt_len =3D 64 > + self.pkt_opts =3D options > + > + self.pkt_type =3D "UDP" > + > + if 'pkt_type' in self.pkt_opts.keys(): > + self.pkt_type =3D self.pkt_opts['pkt_type'] > + > + if self.pkt_type in self.def_packet.keys(): > + self.pkt_layers =3D self.def_packet[self.pkt_type]['layers'] > + self.pkt_cfgload =3D self.def_packet[self.pkt_type]['cfgload= '] > + if "IPv6" in self.pkt_type: > + self.pkt_len =3D 128 > + else: > + self._load_pkt_layers() > + > + if 'pkt_len' in self.pkt_opts.keys(): > + self.pkt_len =3D self.pkt_opts['pkt_len'] > + > + if 'pkt_file' in self.pkt_opts.keys(): > + self.uni_name =3D self.pkt_opts['pkt_file'] > + else: > + self.uni_name =3D '/tmp/' + str(uuid4()) + '.pcap' > + > + if 'pkt_gen' in self.pkt_opts.keys(): > + if self.pkt_opts['pkt_gen'] =3D=3D 'scapy': > + self.pktgen =3D scapy() > + else: > + print "Not support other pktgen yet!!!" > + else: > + self.pktgen =3D scapy() > + > + def send_pkt(self, crb=3DNone, tx_port=3D'', auto_cfg=3DTrue): > + if tx_port =3D=3D '': > + print "Invalid Tx interface" > + return > + > + self.tx_port =3D tx_port > + > + # assign layer > + self.assign_layers() > + > + # config special layer > + if auto_cfg is True: > + self.config_def_layers() > + > + # handle packet options > + payload_len =3D self.pkt_len - len(self.pktgen.pkt) - 4 > + > + # if raw data has not been configured and payload should > configured > + if hasattr(self, 'configured_layer_raw') is False and > self.pkt_cfgload is True: > + payload =3D [] > + raw_confs =3D {} > + if 'ran_payload' in self.pkt_opts.keys(): > + for loop in range(payload_len): > + payload.append("%02x" % random.randrange(0, 255)) > + else: > + for loop in range(payload_len): > + payload.append('58') # 'X' > + > + raw_confs['payload'] =3D payload > + self._config_layer_raw(raw_confs) > + > + # check with port type > + if 'ixia' in self.tx_port: > + print "Not Support Yet" > + > + if crb is not None: > + self.pktgen.write_pcap(self.uni_name) > + crb.session.copy_file_to(self.uni_name) > + pcap_file =3D self.uni_name.split('/')[2] > + self.pktgen.send_pcap_pkt(crb=3Dcrb, file=3Dpcap_file, > intf=3Dself.tx_port) > + else: > + self.pktgen.send_pkt(intf=3Dself.tx_port) > + > + def check_layer_config(self, layer, config): > + """ > + check the format of layer configuration > + every layer should has different check function > + """ > + pass > + > + def assign_layers(self, layers=3DNone): > + """ > + assign layer for this packet > + maybe need add check layer function > + """ > + if layers is not None: > + self.pkt_layers =3D layers > + > + for layer in self.pkt_layers: > + found =3D False > + l_type =3D layer.lower() > + > + for types in LayersTypes.values(): > + if l_type in types: > + found =3D True > + break > + > + if found is False: > + self.pkt_layers.remove(l_type) > + print "INVAILD LAYER TYPE [%s]" % l_type.upper() > + > + self.pktgen.add_layers(self.pkt_layers) > + > + def _load_pkt_layers(self): > + name2type =3D { > + 'MAC': 'ether', > + 'VLAN': 'dot1q', > + 'IP': 'ipv4', > + 'IPihl': 'ipv4ihl', > + 'IPFRAG': 'ipv4_ext', > + 'IPv6': 'ipv6', > + 'IPv6FRAG': 'ipv6_frag', > + 'IPv6EXT': 'ipv6_ext', > + 'IPv6EXT2': 'ipv6_ext2', > + 'TCP': 'tcp', > + 'UDP': 'udp', > + 'SCTP': 'sctp', > + 'ICMP': 'icmp', > + 'NVGRE': 'nvgre', > + 'GRE': 'gre', > + 'VXLAN': 'vxlan', > + 'PKT': 'raw', > + } > + > + layers =3D self.pkt_type.split('_') > + self.pkt_layers =3D [] > + self.pkt_cfgload =3D True > + for layer in layers: > + if layer in name2type.keys(): > + self.pkt_layers.append(name2type[layer]) > + > + def config_def_layers(self): > + """ > + Handel config packet layers by default > + """ > + if self.pkt_type =3D=3D "TIMESYNC": > + self.config_layer('ether', {'dst': 'FF:FF:FF:FF:FF:FF', > + 'type': 0x88f7}) > + self.config_layer('raw', {'payload': ['00', '02']}) > + > + if self.pkt_type =3D=3D "ARP": > + self.config_layer('ether', {'dst': 'FF:FF:FF:FF:FF:FF'}) > + > + if self.pkt_type =3D=3D "IPv6_SCTP": > + self.config_layer('ipv6', {'nh': 132}) > + > + if "IPv6_NVGRE" in self.pkt_type: > + self.config_layer('ipv6', {'nh': 47}) > + if "IPv6_SCTP" in self.pkt_type: > + self.config_layer('inner_ipv6', {'nh': 132}) > + if "IPv6_ICMP" in self.pkt_type: > + self.config_layer('inner_ipv6', {'nh': 58}) > + if "IPFRAG" in self.pkt_type: > + self.config_layer('raw', {'payload': ['00'] * 40}) > + 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 "IPv6_SCTP" in self.pkt_type: > + self.config_layer('ipv6', {'nh': 132}) > + if "IPv6_ICMP" in self.pkt_type: > + self.config_layer('ipv6', {'nh': 58}) > + if "IPFRAG" in self.pkt_type: > + self.config_layer('raw', {'payload': ['00'] * 40}) > + else: > + self.config_layer('raw', {'payload': ['00'] * 18}) > + > + def config_layer(self, layer, config=3D{}): > + """ > + Configure packet assgined layer > + return the status of configure result > + """ > + try: > + # if inner in layer mean same layer in outer > + if 'inner' in layer: > + dup_layer =3D layer[6:] > + if self.pkt_layers.count(dup_layer) !=3D 2: > + raise > + else: > + idx =3D self.pkt_layers.index(layer) > + except Exception as e: > + print "INVALID LAYER ID %s" % layer > + return -1 > + > + if self.check_layer_config(layer, config) is False: > + return -1 > + > + layer_conf =3D getattr(self, "_config_layer_%s" % layer) > + setattr(self, 'configured_layer_%s' % layer, True) > + > + return layer_conf(config) > + > + def _config_layer_ether(self, config): > + return self.pktgen.ether(**config) > + > + def _config_layer_dot1q(self, config): > + return self.pktgen.dot1q(**config) > + > + def _config_layer_ipv4(self, config): > + return self.pktgen.ipv4(**config) > + > + def _config_layer_ipv6(self, config): > + return self.pktgen.ipv6(**config) > + > + def _config_layer_inner_ipv6(self, config): > + return self.pktgen.inner_ipv6(**config) > + > + def _config_layer_udp(self, config): > + return self.pktgen.udp(**config) > + > + def _config_layer_raw(self, config): > + return self.pktgen.raw(**config) > + > + def _config_layer_vxlan(self, config): > + return self.pktgen.vxlan(**config) > + > + def strip_layer_element(self, layer, element): > + """ > + Strip packet layer elements > + return the status of configure result > + """ > + strip_element =3D getattr(self, "strip_element_%s" % layer) > + > + return strip_element(element) > + > + def strip_element_dot1q(self, element): > + return self.pktgen.strip_dot1q(element) > + > + > +def increment_ip_address(self, addr): > + """ > + Returns the IP address from a given one, like > + 192.168.1.1 ->192.168.1.2 > + If disable ip hw chksum, csum routine will increase ip > + """ > + ip2int =3D lambda ipstr: struct.unpack('!I', socket.inet_aton(ipstr)= )[0] > + x =3D ip2int(addr) > + int2ip =3D lambda n: socket.inet_ntoa(struct.pack('!I', n)) > + return int2ip(x + 1) > + > + > +def increment_ipv6_address(self, addr): > + """ > + Returns the IP address from a given one, like > + FE80:0:0:0:0:0:0:0 -> FE80::1 > + csum routine will increase ip > + """ > + ipv6addr =3D struct.unpack('!8H', socket.inet_pton(AF_INET6, addr)) > + addr =3D list(ipv6addr) > + addr[7] +=3D 1 > + ipv6 =3D socket.inet_ntop(AF_INET6, struct.pack( > + '!8H', addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], > addr[6], addr[7])) > + return ipv6 > + > + > +def sniff_packets(intf, count=3D0, timeout=3D5): > + """ > + sniff all packets for certain port in certain seconds > + """ > + sniff_cmd =3D 'tcpdump -i %(INTF)s -w %(FILE)s' > + options =3D {'INTF': intf, 'COUNT': count, > + 'FILE': '/tmp/sniff_%s.pcap' % intf} > + if count: > + sniff_cmd +=3D ' -c %(COUNT)d' > + cmd =3D sniff_cmd % options > + else: > + cmd =3D sniff_cmd % options > + > + args =3D cmd.split() > + pipe =3D subprocess.Popen(args) > + index =3D str(time.time()) > + SNIFF_PIDS[index] =3D (pipe, intf, timeout) > + return index > + > + > +def load_sniff_packets(index=3D''): > + pkts =3D [] > + child_exit =3D False > + if index in SNIFF_PIDS.keys(): > + pipe, intf, timeout =3D SNIFF_PIDS[index] > + time_elapse =3D int(time.time() - float(index)) > + while time_elapse < timeout: > + if pipe.poll() is not None: > + child_exit =3D True > + break > + > + time.sleep(1) > + time_elapse +=3D 1 > + > + if not child_exit: > + pipe.kill() > + > + # wait pcap file ready > + time.sleep(0.5) > + try: > + cap_pkts =3D rdpcap("/tmp/sniff_%s.pcap" % intf) > + for pkt in cap_pkts: > + # packet gen should be scapy > + packet =3D Packet(tx_port=3Dintf) > + packet.pktgen.assign_pkt(pkt) > + pkts.append(packet) > + except: > + pass > + > + return pkts > + > +########################################################################= # > ################################### > +########################################################################= # > ################################### > +if __name__ =3D=3D "__main__": > + inst =3D sniff_packets("lo", timeout=3D5) > + time.sleep(3) > + pkts =3D load_sniff_packets(inst) > + > + pkt =3D Packet(pkt_type=3D'UDP', pkt_len=3D1500, ran_payload=3DTrue) > + pkt.send_pkt(tx_port=3D'lo') > + pkt =3D Packet(pkt_type=3D'IPv6_TCP') > + pkt.send_pkt(tx_port=3D'lo') > + pkt =3D Packet(pkt_type=3D'IPv6_SCTP') > + pkt.send_pkt(tx_port=3D'lo') > + > + pkt =3D Packet() > + pkt.assign_layers(['ether', 'dot1q', 'ipv4', 'udp', 'vxlan', > 'inner_mac', 'inner_ipv4', 'inner_udp', 'raw']) > + pkt.config_layer('ether', {'dst': '00:11:22:33:44:55'}) > + pkt.config_layer('dot1q', {'vlan': 2}) > + pkt.config_layer('ipv4', {'dst': '1.1.1.1'}) > + pkt.config_layer('udp', {'src': 4789, 'dst': 4789, 'chksum': 0x1111}= ) > + pkt.config_layer('vxlan', {'vni': 2}) > + pkt.config_layer('raw', {'payload': ['58']*18}) > -- > 1.9.3