* [dts] [Patch V1] ramework/pktgen.py: Add packet generator framework, and integrate Trex into the framework sent this patch on behalf of chen hongli @ 2017-09-20 12:09 wang fei 2017-09-22 5:42 ` Liu, Yong 0 siblings, 1 reply; 3+ messages in thread From: wang fei @ 2017-09-20 12:09 UTC (permalink / raw) To: dts; +Cc: wang fei Signed-off-by: wang fei <feix.y.wang@intel.com> --- framework/pktgen.py | 420 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 420 insertions(+) create mode 100644 framework/pktgen.py diff --git a/framework/pktgen.py b/framework/pktgen.py new file mode 100644 index 0000000..03550bd --- /dev/null +++ b/framework/pktgen.py @@ -0,0 +1,420 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2017 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 sys +import re +import string +import time +import json +import argparse +import IPy +import logging + +from abc import abstractmethod +#from trex_stl_lib.api import STLClient, STLStream, STLPktBuilder, Ether, IP, STLTXCont +from config import IxiaConf +from ssh_connection import SSHConnection +from settings import SCAPY2IXIA +from logger import getLogger +from exception import VerifyFailure +from utils import create_mask +from uuid import uuid4 +from pickletools import optimize +from tester import Tester +#from serializer import Serializer + +FORMAT = '%(message)s' +logging.basicConfig(format=FORMAT) +logger = logging.getLogger('TrexA') +logger.setLevel(logging.INFO) +# change operation directory +cwd = os.getcwd() +sys.path.append(cwd + '/nics') +sys.path.append(cwd + '/framework') +sys.path.append(cwd + '/tests') +sys.path.append(cwd + '/dep') +#sys.path.append("/opt/trex-core-2.26/scripts/automation/trex_control_plane/stl/trex_stl_lib") +sys.path.insert(0, "/opt/trex-core-2.26/scripts/automation/"+\ + "trex_control_plane/stl") +#from api import STLClient, STLStream, STLPktBuilder, Ether, IP, STLTXCont +from trex_stl_lib.api import * +from crb import Crb +from config import PktgenConf, CrbsConf +#from net_device import GetNicObj + +class PacketGenerator(object): +#class PacketGenerator(Crb): + """ + Basic class for packet generator, define basic function for each kinds of + generators + """ + def __init__(self, tester): + self.__streams = [] + self.tester = tester + + @abstractmethod + def _check_options(self, opts={}): + pass + + @abstractmethod + def prepare_generator(self): + pass + + @abstractmethod + def _prepare_transmission(self, stream_ids=[]): + pass + + @abstractmethod + def _start_transmission(self, stream_ids, delay=50): + pass + + @abstractmethod + def _stop_transmission(self, stream_id): + pass + + @abstractmethod + def _retrieve_port_statistic(self, stream_id): + pass + + def add_stream(self, tx_port, rx_port, pcap_file): + stream_id = None + + stream_id = len(self.__streams) + stream = {'tx_port': tx_port, + 'rx_port': rx_port, + 'pcap_file': pcap_file} + self.__streams.append(stream) + + return stream_id + + def config_stream(self, stream_id=0, opts={}): + if self._check_options(opts) is not True: + self.logger.error("Failed to configure stream[%d]" % stream_id) + return + + stream = self.__streams[stream_id] + stream['options'] = opts + + def measure_throughput(self, stream_ids=[], delay=50): + """ + Measure throughput on each tx ports + """ + + bps_rx = [] + pps_rx = [] + self._prepare_transmission(stream_ids=stream_ids) + self._start_transmission(stream_ids) + + time.sleep(delay) + for stream_id in stream_ids: + rxbps_rates, rxpps_rates = self._retrieve_port_statistic(stream_id) + + bps_rx.append(rxbps_rates) + pps_rx.append(rxpps_rates) + self._stop_transmission(stream_id) + bps_rx_total = self._summary_statistic(bps_rx) + pps_rx_total = self._summary_statistic(pps_rx) + + print "throughput: pps_rx %f, bps_rx %f" % (pps_rx_total, bps_rx_total) + + return bps_rx_total, pps_rx_total + + + + def _summary_statistic(self, array=[]): + """ + Summary all values in statistic array + """ + summary = 0.000 + for value in array: + summary += value + + + return summary + + def _get_stream(self, stream_id): + return self.__streams[stream_id] + + def _get_generator_conf_instance(self, pktgen_type): + conf_inst = PktgenConf(pktgen_type=pktgen_type) + return conf_inst + + @abstractmethod + def quit_generator(self): + pass + +class TrexPacketGenerator(PacketGenerator): + """ + Trex packet generator, detail usage can be seen at + https://trex-tgn.cisco.com/trex/doc/trex_manual.html + """ + def __init__(self, tester): + self._conn = None + self._ports = [] + self._traffic_ports = [] + self._transmit_streams = {} + self.trex_app = "scripts/t-rex-64" + + self.conf_inst = self._get_generator_conf_instance("trex") + self.conf = self.conf_inst.load_pktgen_config() + self.options_keys = [ 'rate', 'ip', 'vlan'] + self.ip_keys = ['start', 'end','action', 'mask', 'step'] + self.vlan_keys = ['start', 'end', 'action', 'step', 'count'] + super(TrexPacketGenerator, self).__init__(tester) + + def connect(self): + self._conn = STLClient(server=self.conf["server"]) + time.sleep(30) + self._conn.connect() + for p in self._conn.get_all_ports(): + self._ports.append(p) + + logger.debug(self._ports) + + def disconnect(self): + self._conn.disconnect() + + def _check_options(self, opts={}): + for key in opts: + if key in self.options_keys: + if key == 'ip': + ip = opts['ip'] + for ip_key in ip: + if not ip_key in self.ip_keys: + print " %s is invalid ip option" % ip_key + return False + if key == 'action': + if not ip[key] == 'inc' or not ip[key] == 'dec': + print " %s is invalid ip action" % ip[key] + return False + elif key == 'vlan': + vlan = opts['vlan'] + for vlan_key in vlan: + if not vlan_key in self.vlan_keys: + print " %s is invalid vlan option" % vlan_key + return False + if key == 'action': + if not vlan[key] == 'inc' or not ip[key] == 'dec': + print " %s is invalid vlan action" % vlan[key] + return False + else: + print " %s is invalid option" % key + return False + return True + + def create_vm (self, ip_src_range, ip_dst_range, action='inc', step=1): + if not ip_src_range and not ip_dst_range: + return None + + vm = [] + + if ip_src_range: + vm += [STLVmFlowVar(name="src", min_value = ip_src_range['start'], max_value = ip_src_range['end'], size = 4, op = action), + STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src") + ] + + if ip_dst_range: + vm += [STLVmFlowVar(name="dst", min_value = ip_dst_range['start'], max_value = ip_dst_range['end'], size = 4, op = action), + STLVmWrFlowVar(fv_name="dst",pkt_offset = "IP.dst") + ] + + vm += [STLVmFixIpv4(offset = "IP") + ] + + return vm + + def prepare_generator(self): + app_param_temp = "-i" + + for key in self.conf: + #key, value = pktgen_conf + if key == 'config_file': + app_param_temp = app_param_temp + " --cfg " + self.conf[key] + elif key == 'core_num': + app_param_temp = app_param_temp + " -c " + self.conf[key] + + app = self.conf['trex_root_path'] + os.sep + self.trex_app + + cmd = app + " " + app_param_temp + + self.tester.send_expect("cd /opt/trex-core-2.26/scripts", "#", 70) + self.tester.send_expect(cmd, "", 40) + + time.sleep(15) + + self.connect() + + self.tester.send_expect("cd " + cwd, "#", 70) + + def _prepare_transmission(self, stream_ids=[]): + # Create base packet and pad it to size + streams = [] + ip_src_range = {} + ip_dst_range = {} + ip_src_range_temp = [] + ip_dst_range_temp = [] + + # prepare stream configuration + for stream_id in stream_ids: + stream = self._get_stream(stream_id) + tx_port = stream['tx_port'] + rx_port = stream['rx_port'] + rx_port_name = "port%d" % rx_port + option = stream['options'] + + #set rate + rate = option['rate'] + ip = option['ip'] + mask = ip['mask'] + step_temp = ip['step'].split('.') + + #get the subnet range of src and dst ip + if self.conf.has_key("ip_src"): + ip_src = self.conf['ip_src'] + ip_src_range_string = IPy.IP(IPy.IP(ip_src).make_net(mask).strNormal()).strNormal(3) + ip_src_range_temp = ip_src_range_string.split('-') + ip_src_range['start'] = ip_src_range_temp[0] + ip_src_range['end'] = ip_src_range_temp[1] + + if self.conf.has_key("ip_dst"): + ip_dst = self.conf['ip_dst'] + ip_dst_range_string = IPy.IP(IPy.IP(ip_dst).make_net(mask).strNormal()).strNormal(3) + ip_dst_range_temp = ip_dst_range_string.split('-') + ip_dst_range['start'] = ip_dst_range_temp[0] + ip_dst_range['end'] = ip_dst_range_temp[1] + + pcap_file = stream['pcap_file'] + + vm = self.create_vm(ip_src_range, ip_dst_range, action=ip['action'], step=step_temp[3]) + + stl_stream = STLStream(packet = STLPktBuilder(pkt = pcap_file, vm=vm), mode = STLTXCont(percentage=100)) + + self._transmit_streams[stream_id] = stl_stream + + def _start_transmission(self, stream_ids, delay=50): + self._conn.reset(ports=self._ports) + self._conn.clear_stats() + self._conn.set_port_attr(self._ports, promiscuous=True) + duration_int = int(self.conf["duration"]) + rate = "100%" + warmup = 15 + + if self.conf.has_key("warmup"): + warmup = int(self.conf["warmup"]) + + for p in self._ports: + for stream_id in stream_ids: + stream = self._get_stream(stream_id) + if stream["tx_port"] == p: + self._conn.add_streams(self._transmit_streams[stream_id], ports=[p]) + rate = stream["options"]["rate"] + self._traffic_ports.append(p) + + if self.conf.has_key("core_mask"): + self._conn.start(ports=self._traffic_ports, mult=rate, duration=warmup, core_mask=self.conf["core_mask"]) + self._conn.wait_on_traffic(ports=self._traffic_ports, timeout=warmup+30) + else: + self._conn.start(ports=self._traffic_ports, mult=rate, duration=warmup) + self._conn.wait_on_traffic(ports=self._traffic_ports, timeout=warmup+30) + + self._conn.clear_stats() + + if self.conf.has_key("core_mask"): + self._conn.start(ports=self._traffic_ports, mult=rate, duration=duration_int, core_mask=self.conf["core_mask"]) + else: + self._conn.start(ports=self._traffic_ports, mult=rate, duration=duration_int) + + if self._conn.get_warnings(): + for warning in self._conn.get_warnings(): + logger.warn(warning) + + def _stop_transmission(self, stream_id): + self._conn.stop(ports=self._traffic_ports, rx_delay_ms=5000) + + def _retrieve_port_statistic(self, stream_id): + stats = self._conn.get_stats() + stream = self._get_stream(stream_id) + port_id = stream["rx_port"] + port_stats = stats[port_id] + print "Port %d stats: %s " % (port_id,port_stats) + rate_rx_pkts = port_stats["rx_pps"] + rate_rx_bits = port_stats["rx_bps_L1"] + print "rx_port: %d, rate_rx_pkts: %f, rate_rx_bits:%f " % (port_id,rate_rx_pkts,rate_rx_bits) + return rate_rx_bits, rate_rx_pkts + + def quit_generator(self): + self.disconnect() + +def getPacketGenerator(tester, pktgen_type="trex"): + """ + Get packet generator object + """ + + if pktgen_type == "dpdk": + return DpdkPacketGenerator(tester) + elif pktgen_type == "ixia": + return IxiaPacketGenerator(tester) + elif pktgen_type == "trex": + return TrexPacketGenerator(tester) + + +if __name__ == "__main__": + # init pktgen stream options + options = { + 'rate' : '100%', + 'ip': {'action': 'inc', 'mask' : '255.255.255.0', 'step':'0.0.0.1'} + } + crbsconf = CrbsConf() + crb = (crbsconf.load_crbs_config())[0] + tester = Tester(crb, None) + # framework initial + trex = getPacketGenerator(tester, pktgen_type="trex") + + conf_inst = trex._get_generator_conf_instance("trex") + conf = conf_inst.load_pktgen_config() + # prepare running environment + trex.prepare_generator() + + #config stream and convert options into pktgen commands + stream_id1 = trex.add_stream(0, 1, conf['pcap_file']) + trex.config_stream(stream_id=stream_id1, opts=options) + stream_id2 = trex.add_stream(1, 0, conf['pcap_file']) + trex.config_stream(stream_id=stream_id2, opts=options) + stream_id3 = trex.add_stream(0, 1, conf['pcap_file']) + trex.config_stream(stream_id=stream_id3, opts=options) + stream_id4 = trex.add_stream(1, 0, conf['pcap_file']) + trex.config_stream(stream_id=stream_id4, opts=options) + #pktgen.prepare_transmission(stream_ids=[stream_id]) + trex.measure_throughput(stream_ids=[stream_id1,stream_id2,stream_id3,stream_id4], delay=5) + #trex.measure_throughput(stream_ids=[stream_id1,stream_id2], delay=5) + # comeback to framework + trex.quit_generator() -- 2.7.4 ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [dts] [Patch V1] ramework/pktgen.py: Add packet generator framework, and integrate Trex into the framework sent this patch on behalf of chen hongli 2017-09-20 12:09 [dts] [Patch V1] ramework/pktgen.py: Add packet generator framework, and integrate Trex into the framework sent this patch on behalf of chen hongli wang fei @ 2017-09-22 5:42 ` Liu, Yong 2017-09-22 5:45 ` Xu, Qian Q 0 siblings, 1 reply; 3+ messages in thread From: Liu, Yong @ 2017-09-22 5:42 UTC (permalink / raw) To: Wang, FeiX Y, dts; +Cc: Wang, FeiX Y Fei, Please check with pep8 first, please add description and each function. I think this patch is one of packet generator patch set. Please send with patch set. And also some comments are inline. Thanks, Marvin > -----Original Message----- > From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of wang fei > Sent: Wednesday, September 20, 2017 8:09 PM > To: dts@dpdk.org > Cc: Wang, FeiX Y <feix.y.wang@intel.com> > Subject: [dts] [Patch V1] ramework/pktgen.py: Add packet generator > framework, and integrate Trex into the framework sent this patch on behalf > of chen hongli > > Signed-off-by: wang fei <feix.y.wang@intel.com> > --- > framework/pktgen.py | 420 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 420 insertions(+) > create mode 100644 framework/pktgen.py > > diff --git a/framework/pktgen.py b/framework/pktgen.py > new file mode 100644 > index 0000000..03550bd > --- /dev/null > +++ b/framework/pktgen.py > @@ -0,0 +1,420 @@ > +# BSD LICENSE > +# > +# Copyright(c) 2010-2017 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 sys > +import re > +import string > +import time > +import json > +import argparse > +import IPy > +import logging > + > +from abc import abstractmethod > +#from trex_stl_lib.api import STLClient, STLStream, STLPktBuilder, Ether, > IP, STLTXCont > +from config import IxiaConf > +from ssh_connection import SSHConnection > +from settings import SCAPY2IXIA > +from logger import getLogger > +from exception import VerifyFailure > +from utils import create_mask > +from uuid import uuid4 > +from pickletools import optimize > +from tester import Tester > +#from serializer import Serializer > + > +FORMAT = '%(message)s' > +logging.basicConfig(format=FORMAT) > +logger = logging.getLogger('TrexA') > +logger.setLevel(logging.INFO) > +# change operation directory > +cwd = os.getcwd() > +sys.path.append(cwd + '/nics') > +sys.path.append(cwd + '/framework') > +sys.path.append(cwd + '/tests') > +sys.path.append(cwd + '/dep') > +#sys.path.append("/opt/trex-core- > 2.26/scripts/automation/trex_control_plane/stl/trex_stl_lib") > +sys.path.insert(0, "/opt/trex-core-2.26/scripts/automation/"+\ > + "trex_control_plane/stl") Please do not hardcoded directory, this folder should be configured in configuration file. > +#from api import STLClient, STLStream, STLPktBuilder, Ether, IP, > STLTXCont Please remove useless code. > +from trex_stl_lib.api import * > +from crb import Crb > +from config import PktgenConf, CrbsConf > +#from net_device import GetNicObj > + > +class PacketGenerator(object): > +#class PacketGenerator(Crb): > + """ > + Basic class for packet generator, define basic function for each > kinds of > + generators > + """ > + def __init__(self, tester): > + self.__streams = [] > + self.tester = tester > + > + @abstractmethod > + def _check_options(self, opts={}): > + pass > + > + @abstractmethod > + def prepare_generator(self): > + pass > + > + @abstractmethod > + def _prepare_transmission(self, stream_ids=[]): > + pass > + > + @abstractmethod > + def _start_transmission(self, stream_ids, delay=50): > + pass > + > + @abstractmethod > + def _stop_transmission(self, stream_id): > + pass > + > + @abstractmethod > + def _retrieve_port_statistic(self, stream_id): > + pass > + > + def add_stream(self, tx_port, rx_port, pcap_file): > + stream_id = None > + > + stream_id = len(self.__streams) > + stream = {'tx_port': tx_port, > + 'rx_port': rx_port, > + 'pcap_file': pcap_file} > + self.__streams.append(stream) > + > + return stream_id > + > + def config_stream(self, stream_id=0, opts={}): > + if self._check_options(opts) is not True: > + self.logger.error("Failed to configure stream[%d]" % > stream_id) > + return > + > + stream = self.__streams[stream_id] > + stream['options'] = opts > + > + def measure_throughput(self, stream_ids=[], delay=50): > + """ > + Measure throughput on each tx ports > + """ > + > + bps_rx = [] > + pps_rx = [] > + self._prepare_transmission(stream_ids=stream_ids) > + self._start_transmission(stream_ids) > + > + time.sleep(delay) > + for stream_id in stream_ids: > + rxbps_rates, rxpps_rates = > self._retrieve_port_statistic(stream_id) > + > + bps_rx.append(rxbps_rates) > + pps_rx.append(rxpps_rates) Need to separate statistic record and summary, need another loop here. > + self._stop_transmission(stream_id) > + bps_rx_total = self._summary_statistic(bps_rx) > + pps_rx_total = self._summary_statistic(pps_rx) > + > + print "throughput: pps_rx %f, bps_rx %f" % (pps_rx_total, > bps_rx_total) > + > + return bps_rx_total, pps_rx_total > + > + > + > + def _summary_statistic(self, array=[]): > + """ > + Summary all values in statistic array > + """ > + summary = 0.000 > + for value in array: > + summary += value > + > + > + return summary > + > + def _get_stream(self, stream_id): > + return self.__streams[stream_id] > + > + def _get_generator_conf_instance(self, pktgen_type): > + conf_inst = PktgenConf(pktgen_type=pktgen_type) > + return conf_inst > + > + @abstractmethod > + def quit_generator(self): > + pass > + > +class TrexPacketGenerator(PacketGenerator): > + """ > + Trex packet generator, detail usage can be seen at > + https://trex-tgn.cisco.com/trex/doc/trex_manual.html > + """ > + def __init__(self, tester): > + self._conn = None > + self._ports = [] > + self._traffic_ports = [] > + self._transmit_streams = {} > + self.trex_app = "scripts/t-rex-64" > + > + self.conf_inst = self._get_generator_conf_instance("trex") > + self.conf = self.conf_inst.load_pktgen_config() > + self.options_keys = [ 'rate', 'ip', 'vlan'] > + self.ip_keys = ['start', 'end','action', 'mask', 'step'] > + self.vlan_keys = ['start', 'end', 'action', 'step', 'count'] > + super(TrexPacketGenerator, self).__init__(tester) > + > + def connect(self): Need to check whether connection is successful, if not need raise some kind of errors. > + self._conn = STLClient(server=self.conf["server"]) > + time.sleep(30) > + self._conn.connect() > + for p in self._conn.get_all_ports(): > + self._ports.append(p) > + > + logger.debug(self._ports) > + > + def disconnect(self): > + self._conn.disconnect() > + > + def _check_options(self, opts={}): Could you implement the check function based on some kind of dict? Like: {'ip': { {'start': ip_format, 'end': ip_format, 'action': ["inc", "dec"], 'mask': mask_format, 'step': ip_format} > + for key in opts: > + if key in self.options_keys: > + if key == 'ip': > + ip = opts['ip'] > + for ip_key in ip: > + if not ip_key in self.ip_keys: > + print " %s is invalid ip option" % ip_key Please use function "self.tester.logger.error" to log error. > + return False > + if key == 'action': > + if not ip[key] == 'inc' or not ip[key] == > 'dec': > + print " %s is invalid ip action" % ip[key] > + return False > + elif key == 'vlan': > + vlan = opts['vlan'] > + for vlan_key in vlan: > + if not vlan_key in self.vlan_keys: > + print " %s is invalid vlan option" % vlan_key > + return False > + if key == 'action': > + if not vlan[key] == 'inc' or not ip[key] == > 'dec': > + print " %s is invalid vlan action" % > vlan[key] > + return False > + else: > + print " %s is invalid option" % key > + return False > + return True > + > + def create_vm (self, ip_src_range, ip_dst_range, action='inc', > step=1): > + if not ip_src_range and not ip_dst_range: > + return None > + > + vm = [] > + > + if ip_src_range: > + vm += [STLVmFlowVar(name="src", min_value = > ip_src_range['start'], max_value = ip_src_range['end'], size = 4, op = > action), > + STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src") > + ] > + > + if ip_dst_range: > + vm += [STLVmFlowVar(name="dst", min_value = > ip_dst_range['start'], max_value = ip_dst_range['end'], size = 4, op = > action), > + STLVmWrFlowVar(fv_name="dst",pkt_offset = "IP.dst") > + ] > + > + vm += [STLVmFixIpv4(offset = "IP") > + ] > + > + return vm > + > + def prepare_generator(self): > + app_param_temp = "-i" > + > + for key in self.conf: > + #key, value = pktgen_conf > + if key == 'config_file': > + app_param_temp = app_param_temp + " --cfg " + > self.conf[key] > + elif key == 'core_num': > + app_param_temp = app_param_temp + " -c " + self.conf[key] > + > + app = self.conf['trex_root_path'] + os.sep + self.trex_app > + > + cmd = app + " " + app_param_temp > + > + self.tester.send_expect("cd /opt/trex-core-2.26/scripts", "#", 70) > + self.tester.send_expect(cmd, "", 40) If here is to start trex, need some criteria check for trex. > + Please do not change working folder, it may cause unexpected behaviors. > + time.sleep(15) > + > + self.connect() > + > + self.tester.send_expect("cd " + cwd, "#", 70) > + > + def _prepare_transmission(self, stream_ids=[]): > + # Create base packet and pad it to size > + streams = [] > + ip_src_range = {} > + ip_dst_range = {} > + ip_src_range_temp = [] > + ip_dst_range_temp = [] > + > + # prepare stream configuration > + for stream_id in stream_ids: > + stream = self._get_stream(stream_id) > + tx_port = stream['tx_port'] > + rx_port = stream['rx_port'] > + rx_port_name = "port%d" % rx_port > + option = stream['options'] > + > + #set rate > + rate = option['rate'] > + ip = option['ip'] > + mask = ip['mask'] > + step_temp = ip['step'].split('.') > + > + #get the subnet range of src and dst ip > + if self.conf.has_key("ip_src"): > + ip_src = self.conf['ip_src'] > + ip_src_range_string = > IPy.IP(IPy.IP(ip_src).make_net(mask).strNormal()).strNormal(3) > + ip_src_range_temp = ip_src_range_string.split('-') > + ip_src_range['start'] = ip_src_range_temp[0] > + ip_src_range['end'] = ip_src_range_temp[1] > + > + if self.conf.has_key("ip_dst"): > + ip_dst = self.conf['ip_dst'] > + ip_dst_range_string = > IPy.IP(IPy.IP(ip_dst).make_net(mask).strNormal()).strNormal(3) > + ip_dst_range_temp = ip_dst_range_string.split('-') > + ip_dst_range['start'] = ip_dst_range_temp[0] > + ip_dst_range['end'] = ip_dst_range_temp[1] > + > + pcap_file = stream['pcap_file'] > + > + vm = self.create_vm(ip_src_range, ip_dst_range, > action=ip['action'], step=step_temp[3]) > + Here need to check whether vm is valid. > + stl_stream = STLStream(packet = STLPktBuilder(pkt = pcap_file, > vm=vm), mode = STLTXCont(percentage=100)) > + > + self._transmit_streams[stream_id] = stl_stream > + > + def _start_transmission(self, stream_ids, delay=50): > + self._conn.reset(ports=self._ports) > + self._conn.clear_stats() > + self._conn.set_port_attr(self._ports, promiscuous=True) > + duration_int = int(self.conf["duration"]) > + rate = "100%" > + warmup = 15 > + > + if self.conf.has_key("warmup"): > + warmup = int(self.conf["warmup"]) > + > + for p in self._ports: > + for stream_id in stream_ids: > + stream = self._get_stream(stream_id) > + if stream["tx_port"] == p: > + > self._conn.add_streams(self._transmit_streams[stream_id], ports=[p]) > + rate = stream["options"]["rate"] > + self._traffic_ports.append(p) > + > + if self.conf.has_key("core_mask"): > + self._conn.start(ports=self._traffic_ports, mult=rate, > duration=warmup, core_mask=self.conf["core_mask"]) > + self._conn.wait_on_traffic(ports=self._traffic_ports, > timeout=warmup+30) > + else: > + self._conn.start(ports=self._traffic_ports, mult=rate, > duration=warmup) > + self._conn.wait_on_traffic(ports=self._traffic_ports, > timeout=warmup+30) > + > + self._conn.clear_stats() > + > + if self.conf.has_key("core_mask"): > + self._conn.start(ports=self._traffic_ports, mult=rate, > duration=duration_int, core_mask=self.conf["core_mask"]) > + else: > + self._conn.start(ports=self._traffic_ports, mult=rate, > duration=duration_int) > + > + if self._conn.get_warnings(): > + for warning in self._conn.get_warnings(): > + logger.warn(warning) > + > + def _stop_transmission(self, stream_id): > + self._conn.stop(ports=self._traffic_ports, rx_delay_ms=5000) > + > + def _retrieve_port_statistic(self, stream_id): > + stats = self._conn.get_stats() > + stream = self._get_stream(stream_id) > + port_id = stream["rx_port"] > + port_stats = stats[port_id] > + print "Port %d stats: %s " % (port_id,port_stats) > + rate_rx_pkts = port_stats["rx_pps"] > + rate_rx_bits = port_stats["rx_bps_L1"] > + print "rx_port: %d, rate_rx_pkts: %f, rate_rx_bits:%f " % > (port_id,rate_rx_pkts,rate_rx_bits) > + return rate_rx_bits, rate_rx_pkts > + > + def quit_generator(self): > + self.disconnect() > + > +def getPacketGenerator(tester, pktgen_type="trex"): > + """ > + Get packet generator object > + """ > + > + if pktgen_type == "dpdk": > + return DpdkPacketGenerator(tester) > + elif pktgen_type == "ixia": > + return IxiaPacketGenerator(tester) > + elif pktgen_type == "trex": > + return TrexPacketGenerator(tester) > + > + > +if __name__ == "__main__": > + # init pktgen stream options > + options = { > + 'rate' : '100%', > + 'ip': {'action': 'inc', 'mask' : '255.255.255.0', 'step':'0.0.0.1'} > + } > + crbsconf = CrbsConf() > + crb = (crbsconf.load_crbs_config())[0] > + tester = Tester(crb, None) > + # framework initial > + trex = getPacketGenerator(tester, pktgen_type="trex") > + > + conf_inst = trex._get_generator_conf_instance("trex") > + conf = conf_inst.load_pktgen_config() > + # prepare running environment > + trex.prepare_generator() > + > + #config stream and convert options into pktgen commands > + stream_id1 = trex.add_stream(0, 1, conf['pcap_file']) > + trex.config_stream(stream_id=stream_id1, opts=options) > + stream_id2 = trex.add_stream(1, 0, conf['pcap_file']) > + trex.config_stream(stream_id=stream_id2, opts=options) > + stream_id3 = trex.add_stream(0, 1, conf['pcap_file']) > + trex.config_stream(stream_id=stream_id3, opts=options) > + stream_id4 = trex.add_stream(1, 0, conf['pcap_file']) > + trex.config_stream(stream_id=stream_id4, opts=options) > + #pktgen.prepare_transmission(stream_ids=[stream_id]) > + > trex.measure_throughput(stream_ids=[stream_id1,stream_id2,stream_id3,strea > m_id4], delay=5) > + #trex.measure_throughput(stream_ids=[stream_id1,stream_id2], delay=5) > + # comeback to framework > + trex.quit_generator() > -- > 2.7.4 ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [dts] [Patch V1] ramework/pktgen.py: Add packet generator framework, and integrate Trex into the framework sent this patch on behalf of chen hongli 2017-09-22 5:42 ` Liu, Yong @ 2017-09-22 5:45 ` Xu, Qian Q 0 siblings, 0 replies; 3+ messages in thread From: Xu, Qian Q @ 2017-09-22 5:45 UTC (permalink / raw) To: Liu, Yong, Wang, FeiX Y, dts; +Cc: Chen, HongliX, Xia, JuanX + Hongli/juan in case you didn't receive it. > -----Original Message----- > From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of Liu, Yong > Sent: Friday, September 22, 2017 1:42 PM > To: Wang, FeiX Y <feix.y.wang@intel.com>; dts@dpdk.org > Cc: Wang, FeiX Y <feix.y.wang@intel.com> > Subject: Re: [dts] [Patch V1] ramework/pktgen.py: Add packet generator > framework, and integrate Trex into the framework sent this patch on behalf of > chen hongli > > Fei, > Please check with pep8 first, please add description and each function. > I think this patch is one of packet generator patch set. Please send with patch > set. > And also some comments are inline. > > Thanks, > Marvin > > > -----Original Message----- > > From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of wang fei > > Sent: Wednesday, September 20, 2017 8:09 PM > > To: dts@dpdk.org > > Cc: Wang, FeiX Y <feix.y.wang@intel.com> > > Subject: [dts] [Patch V1] ramework/pktgen.py: Add packet generator > > framework, and integrate Trex into the framework sent this patch on > > behalf of chen hongli > > > > Signed-off-by: wang fei <feix.y.wang@intel.com> > > --- > > framework/pktgen.py | 420 > > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > > 1 file changed, 420 insertions(+) > > create mode 100644 framework/pktgen.py > > > > diff --git a/framework/pktgen.py b/framework/pktgen.py new file mode > > 100644 index 0000000..03550bd > > --- /dev/null > > +++ b/framework/pktgen.py > > @@ -0,0 +1,420 @@ > > +# BSD LICENSE > > +# > > +# Copyright(c) 2010-2017 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 sys > > +import re > > +import string > > +import time > > +import json > > +import argparse > > +import IPy > > +import logging > > + > > +from abc import abstractmethod > > +#from trex_stl_lib.api import STLClient, STLStream, STLPktBuilder, > > +Ether, > > IP, STLTXCont > > +from config import IxiaConf > > +from ssh_connection import SSHConnection from settings import > > +SCAPY2IXIA from logger import getLogger from exception import > > +VerifyFailure from utils import create_mask from uuid import uuid4 > > +from pickletools import optimize from tester import Tester #from > > +serializer import Serializer > > + > > +FORMAT = '%(message)s' > > +logging.basicConfig(format=FORMAT) > > +logger = logging.getLogger('TrexA') > > +logger.setLevel(logging.INFO) > > +# change operation directory > > +cwd = os.getcwd() > > +sys.path.append(cwd + '/nics') > > +sys.path.append(cwd + '/framework') > > +sys.path.append(cwd + '/tests') > > +sys.path.append(cwd + '/dep') > > +#sys.path.append("/opt/trex-core- > > 2.26/scripts/automation/trex_control_plane/stl/trex_stl_lib") > > +sys.path.insert(0, "/opt/trex-core-2.26/scripts/automation/"+\ > > + "trex_control_plane/stl") > > > Please do not hardcoded directory, this folder should be configured in > configuration file. > > > +#from api import STLClient, STLStream, STLPktBuilder, Ether, IP, > > STLTXCont > > Please remove useless code. > > > +from trex_stl_lib.api import * > > +from crb import Crb > > +from config import PktgenConf, CrbsConf #from net_device import > > +GetNicObj > > + > > +class PacketGenerator(object): > > +#class PacketGenerator(Crb): > > + """ > > + Basic class for packet generator, define basic function for each > > kinds of > > + generators > > + """ > > + def __init__(self, tester): > > + self.__streams = [] > > + self.tester = tester > > + > > + @abstractmethod > > + def _check_options(self, opts={}): > > + pass > > + > > + @abstractmethod > > + def prepare_generator(self): > > + pass > > + > > + @abstractmethod > > + def _prepare_transmission(self, stream_ids=[]): > > + pass > > + > > + @abstractmethod > > + def _start_transmission(self, stream_ids, delay=50): > > + pass > > + > > + @abstractmethod > > + def _stop_transmission(self, stream_id): > > + pass > > + > > + @abstractmethod > > + def _retrieve_port_statistic(self, stream_id): > > + pass > > + > > + def add_stream(self, tx_port, rx_port, pcap_file): > > + stream_id = None > > + > > + stream_id = len(self.__streams) > > + stream = {'tx_port': tx_port, > > + 'rx_port': rx_port, > > + 'pcap_file': pcap_file} > > + self.__streams.append(stream) > > + > > + return stream_id > > + > > + def config_stream(self, stream_id=0, opts={}): > > + if self._check_options(opts) is not True: > > + self.logger.error("Failed to configure stream[%d]" % > > stream_id) > > + return > > + > > + stream = self.__streams[stream_id] > > + stream['options'] = opts > > + > > + def measure_throughput(self, stream_ids=[], delay=50): > > + """ > > + Measure throughput on each tx ports > > + """ > > + > > + bps_rx = [] > > + pps_rx = [] > > + self._prepare_transmission(stream_ids=stream_ids) > > + self._start_transmission(stream_ids) > > + > > + time.sleep(delay) > > + for stream_id in stream_ids: > > + rxbps_rates, rxpps_rates = > > self._retrieve_port_statistic(stream_id) > > + > > + bps_rx.append(rxbps_rates) > > + pps_rx.append(rxpps_rates) > > Need to separate statistic record and summary, need another loop here. > > > + self._stop_transmission(stream_id) > > + bps_rx_total = self._summary_statistic(bps_rx) > > + pps_rx_total = self._summary_statistic(pps_rx) > > + > > + print "throughput: pps_rx %f, bps_rx %f" % (pps_rx_total, > > bps_rx_total) > > + > > + return bps_rx_total, pps_rx_total > > + > > + > > + > > + def _summary_statistic(self, array=[]): > > + """ > > + Summary all values in statistic array > > + """ > > + summary = 0.000 > > + for value in array: > > + summary += value > > + > > + > > + return summary > > + > > + def _get_stream(self, stream_id): > > + return self.__streams[stream_id] > > + > > + def _get_generator_conf_instance(self, pktgen_type): > > + conf_inst = PktgenConf(pktgen_type=pktgen_type) > > + return conf_inst > > + > > + @abstractmethod > > + def quit_generator(self): > > + pass > > + > > +class TrexPacketGenerator(PacketGenerator): > > + """ > > + Trex packet generator, detail usage can be seen at > > + https://trex-tgn.cisco.com/trex/doc/trex_manual.html > > + """ > > + def __init__(self, tester): > > + self._conn = None > > + self._ports = [] > > + self._traffic_ports = [] > > + self._transmit_streams = {} > > + self.trex_app = "scripts/t-rex-64" > > + > > + self.conf_inst = self._get_generator_conf_instance("trex") > > + self.conf = self.conf_inst.load_pktgen_config() > > + self.options_keys = [ 'rate', 'ip', 'vlan'] > > + self.ip_keys = ['start', 'end','action', 'mask', 'step'] > > + self.vlan_keys = ['start', 'end', 'action', 'step', 'count'] > > + super(TrexPacketGenerator, self).__init__(tester) > > + > > + def connect(self): > > Need to check whether connection is successful, if not need raise some kind of > errors. > > > + self._conn = STLClient(server=self.conf["server"]) > > + time.sleep(30) > > + self._conn.connect() > > + for p in self._conn.get_all_ports(): > > + self._ports.append(p) > > + > > + logger.debug(self._ports) > > + > > + def disconnect(self): > > + self._conn.disconnect() > > + > > + def _check_options(self, opts={}): > > Could you implement the check function based on some kind of dict? > > Like: > {'ip': { {'start': ip_format, 'end': ip_format, 'action': ["inc", "dec"], 'mask': > mask_format, 'step': ip_format} > > > > + for key in opts: > > + if key in self.options_keys: > > + if key == 'ip': > > + ip = opts['ip'] > > + for ip_key in ip: > > + if not ip_key in self.ip_keys: > > + print " %s is invalid ip option" % ip_key > > Please use function "self.tester.logger.error" to log error. > > > + return False > > + if key == 'action': > > + if not ip[key] == 'inc' or not ip[key] == > > 'dec': > > + print " %s is invalid ip action" % ip[key] > > + return False > > + elif key == 'vlan': > > + vlan = opts['vlan'] > > + for vlan_key in vlan: > > + if not vlan_key in self.vlan_keys: > > + print " %s is invalid vlan option" % vlan_key > > + return False > > + if key == 'action': > > + if not vlan[key] == 'inc' or not ip[key] > > + == > > 'dec': > > + print " %s is invalid vlan action" % > > vlan[key] > > + return False > > + else: > > + print " %s is invalid option" % key > > + return False > > + return True > > + > > + def create_vm (self, ip_src_range, ip_dst_range, action='inc', > > step=1): > > + if not ip_src_range and not ip_dst_range: > > + return None > > + > > + vm = [] > > + > > + if ip_src_range: > > + vm += [STLVmFlowVar(name="src", min_value = > > ip_src_range['start'], max_value = ip_src_range['end'], size = 4, op = > > action), > > + STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src") > > + ] > > + > > + if ip_dst_range: > > + vm += [STLVmFlowVar(name="dst", min_value = > > ip_dst_range['start'], max_value = ip_dst_range['end'], size = 4, op = > > action), > > + STLVmWrFlowVar(fv_name="dst",pkt_offset = "IP.dst") > > + ] > > + > > + vm += [STLVmFixIpv4(offset = "IP") > > + ] > > + > > + return vm > > + > > + def prepare_generator(self): > > + app_param_temp = "-i" > > + > > + for key in self.conf: > > + #key, value = pktgen_conf > > + if key == 'config_file': > > + app_param_temp = app_param_temp + " --cfg " + > > self.conf[key] > > + elif key == 'core_num': > > + app_param_temp = app_param_temp + " -c " + > > + self.conf[key] > > + > > + app = self.conf['trex_root_path'] + os.sep + self.trex_app > > + > > + cmd = app + " " + app_param_temp > > + > > + self.tester.send_expect("cd /opt/trex-core-2.26/scripts", "#", 70) > > + self.tester.send_expect(cmd, "", 40) > > If here is to start trex, need some criteria check for trex. > > > > + > > Please do not change working folder, it may cause unexpected behaviors. > > > + time.sleep(15) > > + > > + self.connect() > > + > > + self.tester.send_expect("cd " + cwd, "#", 70) > > + > > + def _prepare_transmission(self, stream_ids=[]): > > + # Create base packet and pad it to size > > + streams = [] > > + ip_src_range = {} > > + ip_dst_range = {} > > + ip_src_range_temp = [] > > + ip_dst_range_temp = [] > > + > > + # prepare stream configuration > > + for stream_id in stream_ids: > > + stream = self._get_stream(stream_id) > > + tx_port = stream['tx_port'] > > + rx_port = stream['rx_port'] > > + rx_port_name = "port%d" % rx_port > > + option = stream['options'] > > + > > + #set rate > > + rate = option['rate'] > > + ip = option['ip'] > > + mask = ip['mask'] > > + step_temp = ip['step'].split('.') > > + > > + #get the subnet range of src and dst ip > > + if self.conf.has_key("ip_src"): > > + ip_src = self.conf['ip_src'] > > + ip_src_range_string = > > IPy.IP(IPy.IP(ip_src).make_net(mask).strNormal()).strNormal(3) > > + ip_src_range_temp = ip_src_range_string.split('-') > > + ip_src_range['start'] = ip_src_range_temp[0] > > + ip_src_range['end'] = ip_src_range_temp[1] > > + > > + if self.conf.has_key("ip_dst"): > > + ip_dst = self.conf['ip_dst'] > > + ip_dst_range_string = > > IPy.IP(IPy.IP(ip_dst).make_net(mask).strNormal()).strNormal(3) > > + ip_dst_range_temp = ip_dst_range_string.split('-') > > + ip_dst_range['start'] = ip_dst_range_temp[0] > > + ip_dst_range['end'] = ip_dst_range_temp[1] > > + > > + pcap_file = stream['pcap_file'] > > + > > + vm = self.create_vm(ip_src_range, ip_dst_range, > > action=ip['action'], step=step_temp[3]) > > + > > Here need to check whether vm is valid. > > > + stl_stream = STLStream(packet = STLPktBuilder(pkt = > > + pcap_file, > > vm=vm), mode = STLTXCont(percentage=100)) > > + > > + self._transmit_streams[stream_id] = stl_stream > > + > > + def _start_transmission(self, stream_ids, delay=50): > > + self._conn.reset(ports=self._ports) > > + self._conn.clear_stats() > > + self._conn.set_port_attr(self._ports, promiscuous=True) > > + duration_int = int(self.conf["duration"]) > > + rate = "100%" > > + warmup = 15 > > + > > + if self.conf.has_key("warmup"): > > + warmup = int(self.conf["warmup"]) > > + > > + for p in self._ports: > > + for stream_id in stream_ids: > > + stream = self._get_stream(stream_id) > > + if stream["tx_port"] == p: > > + > > self._conn.add_streams(self._transmit_streams[stream_id], ports=[p]) > > + rate = stream["options"]["rate"] > > + self._traffic_ports.append(p) > > + > > + if self.conf.has_key("core_mask"): > > + self._conn.start(ports=self._traffic_ports, mult=rate, > > duration=warmup, core_mask=self.conf["core_mask"]) > > + self._conn.wait_on_traffic(ports=self._traffic_ports, > > timeout=warmup+30) > > + else: > > + self._conn.start(ports=self._traffic_ports, mult=rate, > > duration=warmup) > > + self._conn.wait_on_traffic(ports=self._traffic_ports, > > timeout=warmup+30) > > + > > + self._conn.clear_stats() > > + > > + if self.conf.has_key("core_mask"): > > + self._conn.start(ports=self._traffic_ports, mult=rate, > > duration=duration_int, core_mask=self.conf["core_mask"]) > > + else: > > + self._conn.start(ports=self._traffic_ports, mult=rate, > > duration=duration_int) > > + > > + if self._conn.get_warnings(): > > + for warning in self._conn.get_warnings(): > > + logger.warn(warning) > > + > > + def _stop_transmission(self, stream_id): > > + self._conn.stop(ports=self._traffic_ports, rx_delay_ms=5000) > > + > > + def _retrieve_port_statistic(self, stream_id): > > + stats = self._conn.get_stats() > > + stream = self._get_stream(stream_id) > > + port_id = stream["rx_port"] > > + port_stats = stats[port_id] > > + print "Port %d stats: %s " % (port_id,port_stats) > > + rate_rx_pkts = port_stats["rx_pps"] > > + rate_rx_bits = port_stats["rx_bps_L1"] > > + print "rx_port: %d, rate_rx_pkts: %f, rate_rx_bits:%f " % > > (port_id,rate_rx_pkts,rate_rx_bits) > > + return rate_rx_bits, rate_rx_pkts > > + > > + def quit_generator(self): > > + self.disconnect() > > + > > +def getPacketGenerator(tester, pktgen_type="trex"): > > + """ > > + Get packet generator object > > + """ > > + > > + if pktgen_type == "dpdk": > > + return DpdkPacketGenerator(tester) > > + elif pktgen_type == "ixia": > > + return IxiaPacketGenerator(tester) > > + elif pktgen_type == "trex": > > + return TrexPacketGenerator(tester) > > + > > + > > +if __name__ == "__main__": > > + # init pktgen stream options > > + options = { > > + 'rate' : '100%', > > + 'ip': {'action': 'inc', 'mask' : '255.255.255.0', 'step':'0.0.0.1'} > > + } > > + crbsconf = CrbsConf() > > + crb = (crbsconf.load_crbs_config())[0] > > + tester = Tester(crb, None) > > + # framework initial > > + trex = getPacketGenerator(tester, pktgen_type="trex") > > + > > + conf_inst = trex._get_generator_conf_instance("trex") > > + conf = conf_inst.load_pktgen_config() > > + # prepare running environment > > + trex.prepare_generator() > > + > > + #config stream and convert options into pktgen commands > > + stream_id1 = trex.add_stream(0, 1, conf['pcap_file']) > > + trex.config_stream(stream_id=stream_id1, opts=options) > > + stream_id2 = trex.add_stream(1, 0, conf['pcap_file']) > > + trex.config_stream(stream_id=stream_id2, opts=options) > > + stream_id3 = trex.add_stream(0, 1, conf['pcap_file']) > > + trex.config_stream(stream_id=stream_id3, opts=options) > > + stream_id4 = trex.add_stream(1, 0, conf['pcap_file']) > > + trex.config_stream(stream_id=stream_id4, opts=options) > > + #pktgen.prepare_transmission(stream_ids=[stream_id]) > > + > > trex.measure_throughput(stream_ids=[stream_id1,stream_id2,stream_id3,s > > trea > > m_id4], delay=5) > > + #trex.measure_throughput(stream_ids=[stream_id1,stream_id2], delay=5) > > + # comeback to framework > > + trex.quit_generator() > > -- > > 2.7.4 ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-09-22 5:45 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-09-20 12:09 [dts] [Patch V1] ramework/pktgen.py: Add packet generator framework, and integrate Trex into the framework sent this patch on behalf of chen hongli wang fei 2017-09-22 5:42 ` Liu, Yong 2017-09-22 5:45 ` Xu, Qian Q
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).