From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 9F8C9A2EFC for ; Fri, 20 Sep 2019 08:08:58 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 894AD1F2AA; Fri, 20 Sep 2019 08:08:58 +0200 (CEST) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id 39A451F2AA for ; Fri, 20 Sep 2019 08:08:56 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 19 Sep 2019 23:08:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,527,1559545200"; d="scan'208";a="217553189" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by fmsmga002.fm.intel.com with ESMTP; 19 Sep 2019 23:08:53 -0700 Received: from fmsmsx126.amr.corp.intel.com (10.18.125.43) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 19 Sep 2019 23:08:53 -0700 Received: from shsmsx108.ccr.corp.intel.com (10.239.4.97) by FMSMSX126.amr.corp.intel.com (10.18.125.43) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 19 Sep 2019 23:08:52 -0700 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.92]) by SHSMSX108.ccr.corp.intel.com ([169.254.8.146]) with mapi id 14.03.0439.000; Fri, 20 Sep 2019 14:08:51 +0800 From: "Tu, Lijuan" To: "Mo, YufengX" , "dts@dpdk.org" , "Lin, Xueqin" , "Yu, PingX" Thread-Topic: [dts][PATCH V4 1/1] [examples/flow_classify]: upload automation test script Thread-Index: AQHVb1n74iN/y+5gukqD7Z/NntBDNac0FP8w Date: Fri, 20 Sep 2019 06:08:50 +0000 Message-ID: <8CE3E05A3F976642AAB0F4675D0AD20E0BB24A3E@SHSMSX101.ccr.corp.intel.com> References: <20190920022151.11817-1-yufengx.mo@intel.com> <20190920022151.11817-2-yufengx.mo@intel.com> In-Reply-To: <20190920022151.11817-2-yufengx.mo@intel.com> Accept-Language: zh-CN, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-ctpclassification: CTP_NT x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiNGQyZWMxZWQtZjRiNi00M2ViLWE4YWUtMTU4MDFjNjQxZGNlIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoidFJ4OE9YSFRERjE3XC9mSHlxS3Q0Yk41TDZRcVZRMUhGckoxNTBnUXczaVBNQ2pFZlY4RVVzbVwvVFc0NEZ0QmRWIn0= x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dts] [PATCH V4 1/1] [examples/flow_classify]: upload automation test script 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: , Errors-To: dts-bounces@dpdk.org Sender: "dts" Applied, thanks > -----Original Message----- > From: Mo, YufengX > Sent: Friday, September 20, 2019 10:22 AM > To: dts@dpdk.org; Tu, Lijuan ; Lin, Xueqin > ; Yu, PingX > Cc: Mo, YufengX > Subject: [dts][PATCH V4 1/1] [examples/flow_classify]: upload automation > test script >=20 >=20 > This automation test script is for flow classify feature. > flow_classify is the tool to call flow_classify lib for group of packets,= just after > receiving them or before transmitting them. >=20 > Signed-off-by: yufengmx > --- > tests/TestSuite_flow_classify.py | 509 +++++++++++++++++++++++++++++++ > 1 file changed, 509 insertions(+) > create mode 100644 tests/TestSuite_flow_classify.py >=20 > diff --git a/tests/TestSuite_flow_classify.py b/tests/TestSuite_flow_clas= sify.py > new file mode 100644 > index 0000000..ffa6136 > --- /dev/null > +++ b/tests/TestSuite_flow_classify.py > @@ -0,0 +1,509 @@ > +# BSD LICENSE > +# > +# Copyright(c) 2010-2019 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. > + > +import os > +import time > +import re > +from collections import Counter > +from datetime import datetime > + > +from packet import Packet > +from scapy.sendrecv import sendp > + > +from utils import create_mask as dts_create_mask from test_case import > +TestCase from exception import VerifyFailure from settings import > +HEADER_SIZE > + > + > +class TestFlowClassify(TestCase): > + > + def get_cores_mask(self, config=3D'all'): > + sockets =3D [self.dut.get_numa_id(index) for index in self.dut_p= orts] > + socket_count =3D Counter(sockets) > + port_socket =3D socket_count.keys()[0] if len(socket_count) =3D= =3D 1 else -1 > + mask =3D dts_create_mask(self.dut.get_core_list(config, > + socket=3Dport_sock= et)) > + return mask > + > + @property > + def output_path(self): > + suiteName =3D self.__class__.__name__[4:].lower() > + if self.logger.log_path.startswith(os.sep): > + output_path =3D os.path.join(self.logger.log_path, suiteName= ) > + else: > + cur_path =3D os.path.dirname( > + os.path.dirname(os.path.realpath(__file__))) > + output_path =3D os.path.join( > + cur_path, self.logger.log_path, suiteNam= e) > + if not os.path.exists(output_path): > + os.makedirs(output_path) > + > + return output_path > + > + def get_ixia_peer_port(self): > + for cnt in self.dut_ports: > + if self.tester.get_local_port_type(cnt) !=3D 'ixia': > + continue > + tester_port =3D self.tester.get_local_port(cnt) > + return tester_port > + > + def d_console(self, cmds): > + return self.execute_cmds(cmds, con_name=3D'dut') > + > + def d_a_console(self, cmds): > + return self.execute_cmds(cmds, con_name=3D'dut_alt') > + > + def get_console(self, name): > + if name =3D=3D 'dut': > + console =3D self.dut.send_expect > + msg_pipe =3D self.dut.get_session_output > + elif name =3D=3D 'dut_alt': > + console =3D self.dut.alt_session.send_expect > + msg_pipe =3D self.dut.alt_session.session.get_output_all > + else: > + msg =3D 'not support <{}> session'.format(name) > + raise VerifyFailure(msg) > + return console, msg_pipe > + > + def execute_cmds(self, cmds, con_name): > + console, msg_pipe =3D self.get_console(con_name) > + if len(cmds) =3D=3D 0: > + return > + if isinstance(cmds, (str, unicode)): > + cmds =3D [cmds, '# ', 5] > + if not isinstance(cmds[0], list): > + cmds =3D [cmds] > + outputs =3D [] if len(cmds) > 1 else '' > + for item in cmds: > + expected_items =3D item[1] > + expected_str =3D expected_items or '# ' > + try: > + if len(item) =3D=3D 3: > + timeout =3D int(item[2]) > + output =3D console(item[0], expected_str, timeout) > + output =3D msg_pipe() if not output else output > + else: > + # timeout =3D 5 > + output =3D console(item[0], expected_str) > + output =3D msg_pipe() if not output else output > + except Exception as e: > + # self.check_process_status() > + msg =3D "execute '{0}' timeout".format(item[0]) > + raise Exception(msg) > + time.sleep(1) > + if len(cmds) > 1: > + outputs.append(output) > + else: > + outputs =3D output > + return outputs > + > + def get_pkt_len(self, pkt_type): > + # packet size > + frame_size =3D 256 > + headers_size =3D sum( > + map(lambda x: 132 if x =3D=3D 'sctp' else HEADER_SIZE[x], > + ['eth', 'ip', pkt_type])) > + pktlen =3D frame_size - headers_size > + return pktlen > + > + def set_stream(self, stm_names=3DNone): > + ''' set streams for traffic ''' > + pkt_configs =3D { > + # UDP_1: > + # Frame Data/Protocols: Ethernet 2 0800, IPv4,UDP/IP, Fix= ed 64. > + # IPv4 Header Page: Dest Address: 2.2.2.7 Src Address: 2= .2.2.3 > + # UDP Header: Src Port: 32 Dest Port: 33 > + # > + # Stream Control: Stop after this Stream, Packet Count 32= . > + # > + 'UDP_1': { > + 'type': 'UDP', > + 'pkt_layers': { > + 'ipv4': {'src': '2.2.2.3', 'dst': '2.2.2.7'}, > + 'udp': {'src': 32, 'dst': 33}, > + 'raw': {'payload': ['58'] * self.get_pkt_len('udp')}= }}, > + # UDP_2: > + # Frame Data/Protocols: Ethernet 2 0800, IPv4,UDP/IP, Fix= ed 64. > + # IPv4 Header Page: Dest Address: 9.9.9.7 Src Address: 9= .9.9.3 > + # UDP Header: Src Port: 32 Dest Port: 33 > + # > + # Stream Control: Stop after this Stream, Packet Count 32= . > + # > + 'UDP_2': { > + 'type': 'UDP', > + 'pkt_layers': { > + 'ipv4': {'src': '9.9.9.3', 'dst': '9.9.9.7'}, > + 'udp': {'src': 32, 'dst': 33}, > + 'raw': {'payload': ['58'] * self.get_pkt_len('udp')}= }}, > + 'invalid_UDP': { > + 'type': 'UDP', > + 'pkt_layers': { > + 'ipv4': {'src': '9.8.7.6', 'dst': '192.168.0.36'}, > + 'udp': {'src': 10, 'dst': 11}, > + 'raw': {'payload': ['58'] * self.get_pkt_len('udp')}= }}, > + # TCP_1: > + # Frame Data/Protocols: Ethernet 2 0800, IPv4,TCP/IP, Fix= ed 64. > + # IPv4 Header Page: Dest Address: 9.9.9.7 Src Address: 9= .9.9.3 > + # TCP Header: Src Port: 32 Dest Port: 33 > + # > + # Stream Control: Stop after this Stream, Packet Count 32= . > + # > + 'TCP_1': { > + 'type': 'TCP', > + 'pkt_layers': { > + 'ipv4': {'src': '9.9.9.3', 'dst': '9.9.9.7'}, > + 'tcp': {'src': 32, 'dst': 33}, > + 'raw': {'payload': ['58'] * self.get_pkt_len('tcp')}= }}, > + # TCP_2: > + # Frame Data/Protocols: Ethernet 2 0800, IPv4,TCP/IP, Fix= ed 64. > + # IPv4 Header Page: Dest Address: 9.9.8.7 Src Address: 9= .9.8.3 > + # TCP Header: Src Port: 32 Dest Port: 33 > + # > + # Stream Control: Stop after this Stream, Packet Count 32= . > + # > + 'TCP_2': { > + 'type': 'TCP', > + 'pkt_layers': { > + 'ipv4': {'src': '9.9.8.3', 'dst': '9.9.8.7'}, > + 'tcp': {'src': 32, 'dst': 33}, > + 'raw': {'payload': ['58'] * self.get_pkt_len('tcp')}= }}, > + 'invalid_TCP': { > + 'type': 'TCP', > + 'pkt_layers': { > + 'ipv4': {'src': '9.8.7.6', 'dst': '192.168.0.36'}, > + 'tcp': {'src': 10, 'dst': 11}, > + 'raw': {'payload': ['58'] * self.get_pkt_len('tcp')}= }}, > + # SCTP_1: > + # Frame Data/Protocols: Ethernet 2 0800, IPv4, None, Fixe= d 256. > + # IPv4 Header Page: Dest Address: 2.3.4.5 Src Address: 6= .7.8.9 > + # Protocol: 132-SCTP > + # Stream Control: Stop after this Stream, Packet Count 32= . > + # > + 'SCTP_1': { > + 'type': 'SCTP', > + 'pkt_layers': { > + 'ipv4': {'src': '6.7.8.9', 'dst': '2.3.4.5'}, > + 'sctp': {'src': 32, 'dst': 33}, > + 'raw': {'payload': ['58'] * self.get_pkt_len('sctp')= }}}, > + 'invalid_SCTP': { > + 'type': 'SCTP', > + 'pkt_layers': { > + 'ipv4': {'src': '9.8.7.6', 'dst': '192.168.0.36'}, > + 'sctp': {'src': 10, 'dst': 11}, > + 'raw': {'payload': ['58'] * self.get_pkt_len('sctp')= }}}, > + } > + > + # create packet for send > + streams =3D [] > + for stm_name in stm_names: > + if stm_name not in pkt_configs.keys(): > + continue > + values =3D pkt_configs[stm_name] > + savePath =3D os.sep.join([self.output_path, > + "pkt_{0}.pcap".format(stm_name)]) > + pkt_type =3D values.get('type') > + pkt_layers =3D values.get('pkt_layers') > + pkt =3D Packet(pkt_type=3Dpkt_type) > + for layer in pkt_layers.keys(): > + pkt.config_layer(layer, pkt_layers[layer]) > + pkt.pktgen.pkt.show() > + streams.append(pkt.pktgen.pkt) > + > + return streams > + > + def send_packet_by_scapy(self, config): > + tx_iface =3D config.get('tx_intf') > + cmd =3D "ifconfig {0} up".format(tx_iface) > + self.tester.send_expect(cmd, '# ', 30) > + pkts =3D config.get('stream') > + # stream config > + stream_configs =3D config.get('stream configs') > + frame_config =3D stream_configs.get('frame config') > + gapUnit =3D frame_config.get('gapUnit') > + if gapUnit =3D=3D 'gapMilliSeconds': > + time_unit =3D 10e-4 > + elif gapUnit =3D=3D 'gapMicroSeconds': > + time_unit =3D 10e-7 > + else: > + time_unit =3D 1 > + time_unit =3D 10e-4 > + ifg =3D frame_config.get('ifg') > + count =3D stream_configs.get('count') > + interval =3D ifg * time_unit > + # run traffic > + sendp(pkts, iface=3Dtx_iface, inter=3Dinterval, verbose=3DFalse, > + count=3Dcount) > + > + @property > + def target_dir(self): > + ''' get absolute directory of target source code ''' > + target_dir =3D '/root' + self.dut.base_dir[1:] \ > + if self.dut.base_dir.startswith('~') else \ > + self.dut.base_dir > + return target_dir > + > + @property > + def target_name(self): > + return self.dut.target > + > + def prepare_binary(self, name): > + example_dir =3D "examples/" + name > + out =3D self.dut.build_dpdk_apps('./' + example_dir) > + self.verify("Error" not in out, "Compilation error") > + self.verify("No such" not in out, "Compilation error") > + binary_dir =3D os.path.join(self.target_dir, example_dir, 'build= ') > + cmd =3D ["ls -F {0} | grep '*'".format(binary_dir), '# ', 5] > + exec_file =3D self.d_a_console(cmd) > + binary_file =3D os.path.join(binary_dir, exec_file[:-1]) > + return binary_file > + > + def start_flow_classify(self): > + ''' boot up flow_classify ''' > + rule_config =3D os.sep.join([self.target_dir, > + 'examples', > + 'flow_classify', > + 'ipv4_rules_file.txt']) > + if not os.path.exists(rule_config): > + raise VerifyFailure("rules file doesn't existed") > + core =3D "1S/1C/1T" > + option =3D r" -c {0} -n 4 --file-prefix=3Dtest -- --rule_ipv4=3D= {1}".format( > + self.get_cores_mask(core), rule_config) > + prompt =3D 'table_entry_delete succeeded' > + cmd =3D [' '.join([self.flow_classify, option]), prompt, 30] > + output =3D self.d_console(cmd) > + return output > + > + def close_flow_classify(self): > + output =3D self.dut.get_session_output() > + dt =3D datetime.now() > + timestamp =3D dt.strftime('%Y-%m-%d_%H%M%S') > + self.test_data =3D '{0}/{1}_{2}.log'.format( > + self.output_path, 'flow_classify', timestamp) > + with open(self.test_data, 'wb') as fp: > + fp.write(output) > + cmds =3D ['killall flow_classify', '# ', 10] > + self.d_a_console(cmds) > + > + def get_stream_rule_priority(self, stream_type): > + stream_types =3D { > + 'UDP_1': 0, > + 'UDP_2': 1, > + 'TCP_1': 2, > + 'TCP_2': 3, > + 'SCTP_1': 4} > + return stream_types.get(stream_type, None) > + > + def run_traffic(self, config): > + stm_types =3D config.get('stm_types') > + total_packets =3D config.get('total_packets') > + gap =3D config.get('gap') > + flow_type =3D config.get('flow_type') > + # set traffic topology > + pktgen_name =3D 'ixia' if self._enable_perf else 'scapy' > + tx_port =3D self.get_ixia_peer_port() if pktgen_name =3D=3D 'ixi= a' else \ > + self.tester.get_interface(self.tester.get_local_port(0)) > + # set traffic configuration > + ports_topo =3D { > + 'tx_intf': tx_port, > + 'rx_intf': 0, > + 'stream': self.set_stream(stm_types), > + 'stream configs': { > + 'count': total_packets, > + 'frame config': { > + 'gapUnit': 'gapMilliSeconds', > + 'ifg': gap}, > + 'flow_type': flow_type, > + }, } > + # begin traffic checking > + self.logger.info("begin traffic ... ") > + method_name =3D 'send_packet_by_' + pktgen_name > + pkt_gen_func =3D getattr(self, 'send_packet_by_' + pktgen_name) > + if pkt_gen_func: > + result =3D pkt_gen_func(ports_topo) > + else: > + msg =3D 'not support {}'.format(method_name) > + raise VerifyFailure(msg) > + # end traffic > + self.logger.info("complete transmission") > + > + def check_filter_pkts(self, log, rule_priority): > + pat =3D "rule\[{0}\] count=3D(\d+)".format(rule_priority) \ > + if rule_priority is not None else \ > + "rule\[\d+\] count=3D(\d+)" > + with open(log, 'rb') as fp: > + content =3D fp.read() > + if content: > + grp =3D re.findall(pat, content, re.M) > + total =3D reduce(lambda x, y: x + y, [int(i) for i in grp]) = \ > + if grp and len(grp) else 0 > + return total > + > + def check_test_result(self, config): > + stm_types =3D config.get('stm_types') > + total_packets =3D config.get('total_packets') > + flow_type =3D config.get('flow_type') > + self.logger.info(stm_types) > + check_results =3D [] > + for stm_type in stm_types: > + rule_priority =3D self.get_stream_rule_priority(stm_type) > + captured_pkts =3D self.check_filter_pkts(self.test_data, > + rule_priority) > + self.logger.info("%s %d %d" % (stm_type, rule_priority or 0, > + captured_pkts or 0)) > + msg =3D None > + if flow_type =3D=3D 'multi_stream': > + # check if packets are multiple rules' pkts > + # ignore invalid rule > + if rule_priority and captured_pkts % total_packets !=3D = 0: > + msg =3D ("captured packets are not multiples of " > + "rules' {0} packets".format(total_packets)) > + else: > + continue > + elif flow_type =3D=3D 'single_stream': > + if rule_priority is None and captured_pkts !=3D 0: > + msg =3D "invalid stream hasn't been filtered out" > + elif rule_priority is None and captured_pkts !=3D total_= packets: > + msg =3D "expect {0} ".format(total_packets) + \ > + "captured {0}".format(captured_pkts) > + else: > + continue > + else: > + continue > + if msg: > + check_results.append(msg) > + > + if check_results: > + self.logger.error(os.linesep.join(check_results)) > + raise VerifyFailure("test result fail") > + > + def init_params(self): > + self.test_data =3D None > + > + def verify_traffic(self, stm_types=3DNone, gap=3D10, > + flow_type=3D"single_stream"): > + self.logger.info('begin to check ...... ') > + info =3D { > + 'stm_types': stm_types, > + 'flow_type': flow_type, > + 'total_packets': 32, > + 'gap': gap, } > + > + try: > + self.init_params() > + # preset test environment > + self.start_flow_classify() > + # run traffic > + self.run_traffic(info) > + # close flow_classify > + self.close_flow_classify() > + except Exception as e: > + # close flow_classify > + self.close_flow_classify() > + msg =3D 'failed to run traffic' > + self.verify(False, msg) > + # analysis test result > + self.check_test_result(info) > + > + def verify_multiple_rules(self): > + stream_list =3D [ > + 'UDP_1', 'UDP_2', 'invalid_UDP', > + 'TCP_1', 'TCP_2', 'invalid_TCP', > + 'SCTP_1', 'invalid_SCTP'] > + self.verify_traffic(stm_types=3Dstream_list, > + flow_type=3D"multi_stream") > + > + def verify_supported_nic(self): > + supported_drivers =3D ['i40e', 'ixgbe'] > + result =3D all([self.dut.ports_info[index]['port'].default_drive= r in > + supported_drivers > + for index in self.dut_ports]) > + msg =3D "current nic is not supported" > + self.verify(result, msg) > + # > + # Test cases. > + # > + > + def set_up_all(self): > + """ > + Run before each test suite > + """ > + # initialize ports topology > + self.dut_ports =3D self.dut.get_ports() > + self.verify(len(self.dut_ports) >=3D 2, "Insufficient ports") > + # set binary process setting > + self.flow_classify =3D self.prepare_binary('flow_classify') > + self.verify_supported_nic() > + > + def set_up(self): > + """ > + Run before each test case. > + """ > + pass > + > + def tear_down(self): > + """ > + Run after each test case. > + """ > + pass > + > + def tear_down_all(self): > + """ > + Run after each test suite. > + """ > + pass > + > + def test_udp_valid_rule(self): > + stream_list =3D ['UDP_1', 'UDP_2'] > + for stm_type in stream_list: > + self.verify_traffic([stm_type]) > + > + def test_udp_invalid_rule(self): > + stream_list =3D ['invalid_UDP'] > + self.verify_traffic(stream_list) > + > + def test_tcp_valid_rule(self): > + stream_list =3D ['TCP_1', 'TCP_2'] > + for stm_type in stream_list: > + self.verify_traffic([stm_type]) > + > + def test_tcp_invalid_rule(self): > + stream_list =3D ['invalid_TCP'] > + self.verify_traffic(stream_list) > + > + def test_sctp_valid_rule(self): > + stream_list =3D ['SCTP_1'] > + self.verify_traffic(stream_list) > + > + def test_sctp_invalid_rule(self): > + stream_list =3D ['invalid_SCTP'] > + self.verify_traffic(stream_list) > + > + def test_multiple_rules(self): > + self.verify_multiple_rules() > -- > 2.21.0