From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id A72D4108D for ; Tue, 24 Jan 2017 09:23:48 +0100 (CET) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 24 Jan 2017 00:23:47 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,277,1477983600"; d="scan'208";a="34638389" Received: from unknown (HELO dpdk-fedora20.icx.intel.com) ([10.240.176.135]) by orsmga002.jf.intel.com with ESMTP; 24 Jan 2017 00:23:46 -0800 From: Marvin Liu To: dts@dpdk.org Cc: Marvin Liu Date: Tue, 24 Jan 2017 16:24:50 +0800 Message-Id: <1485246291-6496-1-git-send-email-yong.liu@intel.com> X-Mailer: git-send-email 1.9.3 Subject: [dts] [PATCH 1/2] framework packet: support packet filter in sniff command 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: Tue, 24 Jan 2017 08:23:49 -0000 This function can be helpful for filter out those unexpected packets. Filter will be translated to bpf format and append into tcpdump command line. Signed-off-by: Marvin Liu diff --git a/framework/packet.py b/framework/packet.py index 05a3d1f..52b0821 100755 --- a/framework/packet.py +++ b/framework/packet.py @@ -41,6 +41,7 @@ import re import signal import random import subprocess +import shlex # separate command line for pipe from uuid import uuid4 from settings import FOLDERS @@ -95,6 +96,9 @@ SNIFF_PIDS = {} # used in pktgen or tgen PKTGEN_PIDS = {} +# default filter for LLDP packet +LLDP_FILTER = {'layer': 'ether', 'config': {'type': 'not lldp'}} + class scapy(object): SCAPY_LAYERS = { @@ -165,7 +169,7 @@ class scapy(object): def vlan(self, pkt_layer, vlan, prio=0, type=None): if pkt_layer.name != "802.1Q": - return + return pkt_layer.vlan = int(vlan) pkt_layer.prio = prio if type is not None: @@ -183,7 +187,7 @@ class scapy(object): def etag(self, pkt_layer, ECIDbase=0, prio=0, type=None): if pkt_layer.name != "802.1BR": - return + return pkt_layer.ECIDbase = int(ECIDbase) pkt_layer.prio = prio if type is not None: @@ -224,6 +228,8 @@ class scapy(object): value = layer.src elif element == 'dst': value = layer.dst + else: + value = layer.getfieldval(element) return value @@ -237,6 +243,8 @@ class scapy(object): value = layer.sport elif element == 'dst': value = layer.dport + else: + value = layer.getfieldval(element) return value @@ -303,7 +311,7 @@ class scapy(object): if payload is not None: pkt_layer.load = '' for hex1, hex2 in payload: - pkt_layer.load += struct.pack("=B", int('%s%s' %(hex1, hex2), 16)) + pkt_layer.load += struct.pack("=B", int('%s%s' % (hex1, hex2), 16)) def gre(self, pkt_layer, proto=None): if proto is not None: @@ -499,11 +507,11 @@ class Packet(object): 'VLAN': 'vlan', 'ETAG': 'etag', 'IP': 'ipv4', - 'IPv4-TUNNEL':'inner_ipv4', + 'IPv4-TUNNEL': 'inner_ipv4', 'IPihl': 'ipv4ihl', 'IPFRAG': 'ipv4_ext', 'IPv6': 'ipv6', - 'IPv6-TUNNEL':'inner_ipv6', + 'IPv6-TUNNEL': 'inner_ipv6', 'IPv6FRAG': 'ipv6_frag', 'IPv6EXT': 'ipv6_ext', 'IPv6EXT2': 'ipv6_ext2', @@ -706,14 +714,68 @@ def save_packets(pkts=None, filename=None): pass -def sniff_packets(intf, count=0, timeout=5): +def get_ether_type(eth_type=""): + # need add more types later + if eth_type.lower() == "lldp": + return '0x88cc' + elif eth_type.lower() == "ip": + return '0x0800' + elif eth_type.lower() == "ipv6": + return '0x86dd' + + return 'not support' + + +def get_filter_cmd(filters=[]): + """ + Return bpd formated filter string, only support ether layer now + """ + filter_sep = " and " + filter_cmds = "" + for pktfilter in filters: + filter_cmd = "" + if pktfilter['layer'] == 'ether': + if pktfilter['config'].keys()[0] == 'dst': + dmac = pktfilter['config']['dst'] + filter_cmd = "ether dst %s" % dmac + elif pktfilter['config'].keys()[0] == 'src': + smac = pktfilter['config']['src'] + filter_cmd = "ether src %s" % smac + elif pktfilter['config'].keys()[0] == 'type': + eth_type = pktfilter['config']['type'] + eth_format = r"(\w+) (\w+)" + m = re.match(eth_format, eth_type) + if m: + type_hex = get_ether_type(m.group(2)) + if type_hex == 'not support': + continue + if m.group(1) == 'is': + filter_cmd = 'ether[12:2] = %s' % type_hex + elif m.group(1) == 'not': + filter_cmd = 'ether[12:2] != %s' % type_hex + + if len(filter_cmds): + if len(filter_cmd): + filter_cmds += filter_sep + filter_cmds += filter_cmd + else: + filter_cmds = filter_cmd + + if len(filter_cmds): + return ' \'' + filter_cmds + '\' ' + else: + return "" + + +def sniff_packets(intf, count=0, timeout=5, filters=[]): """ sniff all packets for certain port in certain seconds """ param = "" direct_param = r"(\s+)\[ -(\w) in\|out\|inout \]" tcpdump_help = subprocess.check_output("tcpdump -h; echo 0", - stderr=subprocess.STDOUT, shell=True) + stderr=subprocess.STDOUT, + shell=True) for line in tcpdump_help.split('\n'): m = re.match(direct_param, line) if m: @@ -722,16 +784,23 @@ def sniff_packets(intf, count=0, timeout=5): if len(param) == 0: print "tcpdump not support direction chioce!!!" - sniff_cmd = 'tcpdump -i %(INTF)s %(IN_PARAM)s -w %(FILE)s' + if 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': '/tmp/sniff_%s.pcap' % intf, + 'FILTER': filter_cmd} if count: sniff_cmd += ' -c %(COUNT)d' cmd = sniff_cmd % options else: cmd = sniff_cmd % options - args = cmd.split() + args = shlex.split(cmd) + pipe = subprocess.Popen(args) index = str(time.time()) SNIFF_PIDS[index] = (pipe, intf, timeout) @@ -807,6 +876,7 @@ def compare_pktload(pkt1=None, pkt2=None, layer="L2"): else: return False + def strip_pktload(pkt=None, layer="L2"): if layer == "L2": l_idx = 0 @@ -827,6 +897,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') @@ -858,6 +930,6 @@ if __name__ == "__main__": '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})]) + ('vxlan', {'vni': 2}), ('raw', {'payload': ['01'] * 18})]) pkt.send_pkt(tx_port='lo') -- 1.9.1