diff options
18 files changed, 444 insertions, 184 deletions
@@ -1,4 +1,4 @@ -v2.14 +v2.15 diff --git a/doc/release_notes.asciidoc b/doc/release_notes.asciidoc index a3bf54cc..7bf6fd12 100755 --- a/doc/release_notes.asciidoc +++ b/doc/release_notes.asciidoc @@ -23,6 +23,17 @@ ifdef::backend-docbook[] endif::backend-docbook[] +== Release 2.15 == + +* XL710/X710 VF mode work (SR-IOV) works better now +* 599 VF mode work (SR-IOV) is not supported due to issues + +=== fix issues: === + +* link:https://trex-tgn.cisco.com/youtrack/issue/trex-333[trex-333] +* link:https://trex-tgn.cisco.com/youtrack/issue/trex-331[trex-331] + + == Release 2.14 == * Another performance improvement in Stateful case with high active flows. There is less burstiness. diff --git a/doc/trex_book.asciidoc b/doc/trex_book.asciidoc index 16f9248d..aba11609 100755 --- a/doc/trex_book.asciidoc +++ b/doc/trex_book.asciidoc @@ -2551,7 +2551,6 @@ NIC with two ports will work better from performance prospective, so it is bette ==== Limitation/Issues * Stateless mode ``per stream statistics'' feature is handled in software (No hardware support like in X710 card). -* link:https://trex-tgn.cisco.com/youtrack/issue/trex-260[64B performance issue] * link:https://trex-tgn.cisco.com/youtrack/issue/trex-261[Latency issue] * link:https://trex-tgn.cisco.com/youtrack/issue/trex-262[Statful RX out of order] * link:https://trex-tgn.cisco.com/youtrack/issue/trex-273[Fedora 21 & OFED 3.4.1] diff --git a/scripts/automation/regression/setups/kiwi02/benchmark.yaml b/scripts/automation/regression/setups/kiwi02/benchmark.yaml index 1eefccaf..b6055366 100644 --- a/scripts/automation/regression/setups/kiwi02/benchmark.yaml +++ b/scripts/automation/regression/setups/kiwi02/benchmark.yaml @@ -272,7 +272,7 @@ test_performance_vm_single_cpu: cfg: mult : "90%" mpps_per_core_golden : - min: 11.2 + min: 10.0 max: 13.1 @@ -280,7 +280,7 @@ test_performance_vm_single_cpu_cached: cfg: mult : "90%" mpps_per_core_golden : - min: 20.5 + min: 18.0 max: 25.0 @@ -289,7 +289,7 @@ test_performance_syn_attack_single_cpu: cfg: mult : "90%" mpps_per_core_golden : - min: 9.3 + min: 8.0 max: 11.5 test_performance_vm_multi_cpus: @@ -297,7 +297,7 @@ test_performance_vm_multi_cpus: core_count : 4 mult : "90%" mpps_per_core_golden : - min: 9.7 + min: 8.0 max: 12.5 @@ -306,7 +306,7 @@ test_performance_vm_multi_cpus_cached: core_count : 4 mult : "90%" mpps_per_core_golden : - min: 19.0 + min: 18.0 max: 22.0 test_performance_syn_attack_multi_cpus: @@ -314,6 +314,6 @@ test_performance_syn_attack_multi_cpus: core_count : 4 mult : "90%" mpps_per_core_golden : - min: 8.4 + min: 8.0 max: 10.5 diff --git a/scripts/automation/regression/setups/trex21/benchmark.yaml b/scripts/automation/regression/setups/trex21/benchmark.yaml new file mode 100644 index 00000000..b366b3fb --- /dev/null +++ b/scripts/automation/regression/setups/trex21/benchmark.yaml @@ -0,0 +1,155 @@ +################################################################ +#### TRex benchmark configuration file #### +################################################################ + +### stateful ### + +test_jumbo: + multiplier : 2.8 + cores : 1 + bw_per_core : 106.652 + + +test_routing_imix: + multiplier : 0.5 + cores : 1 + bw_per_core : 11.577 + + +test_routing_imix_64: + multiplier : 28 + cores : 1 + bw_per_core : 2.030 + + +test_static_routing_imix_asymmetric: + multiplier : 0.8 + cores : 1 + bw_per_core : 13.742 + + + +### stateless ### + +test_CPU_benchmark: + profiles: + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 64} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 64, stream_count: 10} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 64, stream_count: 100} + cpu_util : 1 + bw_per_core : 1 + +# causes queue full +# - name : stl/udp_for_benchmarks.py +# kwargs : {packet_len: 64, stream_count: 1000} +# cpu_util : 1 +# bw_per_core : 1 + + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 128} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 256} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 512} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 1500} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 4000} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 9000} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 9000, stream_count: 10} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_for_benchmarks.py + kwargs : {packet_len: 9000, stream_count: 100} + cpu_util : 1 + bw_per_core : 1 + +# not enough memory + queue full if memory increase +# - name : stl/udp_for_benchmarks.py +# kwargs : {packet_len: 9000, stream_count: 1000} +# cpu_util : 1 +# bw_per_core : 1 + + - name : stl/imix.py + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_1pkt_tuple_gen.py + kwargs : {packet_len: 64} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_1pkt_tuple_gen.py + kwargs : {packet_len: 128} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_1pkt_tuple_gen.py + kwargs : {packet_len: 256} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_1pkt_tuple_gen.py + kwargs : {packet_len: 512} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_1pkt_tuple_gen.py + kwargs : {packet_len: 1500} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_1pkt_tuple_gen.py + kwargs : {packet_len: 4000} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_1pkt_tuple_gen.py + kwargs : {packet_len: 9000} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/pcap.py + kwargs : {ipg_usec: 4, loop_count: 0} + cpu_util : 1 + bw_per_core : 1 + + - name : stl/udp_rand_len_9k.py + cpu_util : 1 + bw_per_core : 1 + + - name : stl/hlt/hlt_udp_rand_len_9k.py + cpu_util : 1 + bw_per_core : 1 + + diff --git a/scripts/automation/regression/setups/trex21/config.yaml b/scripts/automation/regression/setups/trex21/config.yaml new file mode 100644 index 00000000..3cf135c3 --- /dev/null +++ b/scripts/automation/regression/setups/trex21/config.yaml @@ -0,0 +1,40 @@ +################################################################ +#### TRex nightly test configuration file #### +################################################################ + + +### TRex configuration: +# hostname - can be DNS name or IP for the TRex machine for ssh to the box +# password - root password for TRex machine +# is_dual - should the TRex inject with -p ? +# version_path - path to the TRex version and executable +# cores - how many cores should be used +# latency - rate of latency packets injected by the TRex +# modes - list of modes (tagging) of this setup (loopback etc.) +# * loopback - Trex works via loopback. Router and TFTP configurations may be skipped. +# * VM - Virtual OS (accept low CPU utilization in tests, latency can get spikes) +# * virt_nics - NICs are virtual (VMXNET3 etc.) + +### Router configuration: +# hostname - the router hostname as apears in ______# cli prefix +# ip_address - the router's ip that can be used to communicate with +# image - the desired imaged wished to be loaded as the router's running config +# line_password - router password when access via Telent +# en_password - router password when changing to "enable" mode +# interfaces - an array of client-server pairs, representing the interfaces configurations of the router +# configurations - an array of configurations that could possibly loaded into the router during the test. +# The "clean" configuration is a mandatory configuration the router will load with to run the basic test bench + +### TFTP configuration: +# hostname - the tftp hostname +# ip_address - the tftp's ip address +# images_path - the tftp's relative path in which the router's images are located + +### Test_misc configuration: +# expected_bw - the "golden" bandwidth (in Gbps) results planned on receiving from the test + +trex: + hostname : csi-trex-21 + cores : 1 + modes : ['loopback', 'virt_nics'] + diff --git a/scripts/automation/regression/stateful_tests/trex_general_test.py b/scripts/automation/regression/stateful_tests/trex_general_test.py index 4453fd94..dc3f9943 100755 --- a/scripts/automation/regression/stateful_tests/trex_general_test.py +++ b/scripts/automation/regression/stateful_tests/trex_general_test.py @@ -313,7 +313,7 @@ class CTRexGeneral_Test(unittest.TestCase): # check that max latency does not exceed 1 msec if self.configuration.trex['trex_name'] == '10.56.217.210': # temporary workaround for latency issue in kiwi02, remove it ASAP. http://trex-tgn.cisco.com/youtrack/issue/trex-194 allowed_latency = 8000 - elif self.is_VM: + elif self.is_VM or self.is_virt_nics: allowed_latency = 9999999 else: # no excuses, check 1ms allowed_latency = 1000 @@ -321,7 +321,7 @@ class CTRexGeneral_Test(unittest.TestCase): self.fail('LatencyError: Maximal latency exceeds %s (usec)' % allowed_latency) # check that avg latency does not exceed 1 msec - if self.is_VM: + if self.is_VM or self.is_virt_nics: allowed_latency = 9999999 else: # no excuses, check 1ms allowed_latency = 1000 diff --git a/scripts/automation/regression/stateful_tests/trex_imix_test.py b/scripts/automation/regression/stateful_tests/trex_imix_test.py index 5f52fab7..4cb01db3 100755 --- a/scripts/automation/regression/stateful_tests/trex_imix_test.py +++ b/scripts/automation/regression/stateful_tests/trex_imix_test.py @@ -141,6 +141,8 @@ class CTRexIMIX_Test(CTRexGeneral_Test): self.check_general_scenario_results(trex_res) self.check_CPU_benchmark(trex_res) + + # the name intentionally not matches nose default pattern, including the test should be specified explicitly def dummy(self): ret = self.trex.start_trex( diff --git a/scripts/automation/regression/stateless_tests/stl_rx_test.py b/scripts/automation/regression/stateless_tests/stl_rx_test.py index 8812ac48..3d4ed977 100644 --- a/scripts/automation/regression/stateless_tests/stl_rx_test.py +++ b/scripts/automation/regression/stateless_tests/stl_rx_test.py @@ -32,6 +32,12 @@ class STLRX_Test(CStlGeneral_Test): 'latency_9k_max_average': 100, 'latency_9k_max_latency': 250, }, + 'rte_i40evf_pmd': { + 'rate_percent': 80, + 'total_pkts': 1000, + 'rate_latency': 1, + 'latency_9k_enable': False, + }, 'rte_igb_pmd': { 'rate_percent': 80, 'total_pkts': 500, @@ -526,19 +532,37 @@ class STLRX_Test(CStlGeneral_Test): except STLError as e: assert False , '{0}'.format(e) + def _run_fcs_stream (self,is_vm): + """ this test send 1 64 byte packet with latency and check that all counters are reported as 64 bytes""" + res=True + try: + all_ports=list(CTRexScenario.stl_ports_map['map'].keys()); + for port in all_ports: + for l in [True,False]: + print(" test port {0} latency : {1} ".format(port,l)) + self.send_1_burst(port,l,100) + except Exception as e: + if is_vm : + res=False + else: + raise e + return(res); + + def test_fcs_stream(self): """ this test send 1 64 byte packet with latency and check that all counters are reported as 64 bytes""" - if self.is_virt_nics: - self.skip('Skip this for virtual NICs') - - all_ports=list(CTRexScenario.stl_ports_map['map'].keys()); - for port in all_ports: - for l in [True,False]: - print(" test port {0} latency : {1} ".format(port,l)) - self.send_1_burst(port,l,100) + is_vm=self.is_virt_nics # in case of VM and vSwitch there are drop of packets in some cases, let retry number of times + # in this case we just want to check functionality that packet of 64 is reported as 64 in all levels + retry=1 + if is_vm: + retry=4 + for i in range(0,retry): + if self._run_fcs_stream (is_vm): + break; + print("==> retry %d .." %(i)); # this test adds more and more latency streams and re-test with incremental diff --git a/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py index 4e7deb93..490e3b7a 100755 --- a/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py +++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py @@ -1110,6 +1110,13 @@ class CTRexResult(object): self.clear_results() self.latency_checked = True self.filtered_latency_amount = filtered_latency_amount + self.set_warmup_default() + + def set_warmup_default (self): + self.set_warmup(0.96) + + def set_warmup (self,new_warmup_max): + self.warmup_max = new_warmup_max def __repr__(self): return ("Is valid history? {arg}\n".format( arg = self.is_valid_hist() ) + @@ -1414,7 +1421,7 @@ class CTRexResult(object): self._current_tx_rate = CTRexResult.__get_value_by_path(latest_dump, "trex-global.data", "m_tx_(?!expected_)\w+") if not self._done_warmup and self._expected_tx_rate is not None: # check for up to 4% change between expected and actual - if (self._current_tx_rate['m_tx_bps'] > 0.96 * self._expected_tx_rate['m_tx_expected_bps']): + if (self._current_tx_rate['m_tx_bps'] > self.warmup_max * self._expected_tx_rate['m_tx_expected_bps']): self._done_warmup = True latest_dump['warmup_barrier'] = True diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py index cf594948..30a699c5 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py @@ -1536,7 +1536,7 @@ def get_TOS(user_kwargs, kwargs): if user_args & (TOS2 - TOS1) and user_args & (TOS1 - TOS2): raise STLError('You have mixed %s and %s TOS parameters' % (TOS1, TOS2)) if user_args & (TOS0 - TOS1 - TOS2): - return (kwargs['ip_precedence'] << 5) + (kwargs['ip_tos_field'] << 2) + kwargs['ip_mbz'] + return (kwargs['ip_precedence'] << 5) + (kwargs['ip_tos_field'] << 1) + kwargs['ip_mbz'] if user_args & (TOS1 - TOS2): return (kwargs['ip_precedence'] << 5) + (kwargs['ip_delay'] << 4) + (kwargs['ip_throughput'] << 3) + (kwargs['ip_reliability'] << 2) + (kwargs['ip_cost'] << 1) + kwargs['ip_reserved'] return (kwargs['ip_dscp'] << 2) + kwargs['ip_cu'] diff --git a/scripts/ko/3.10.0-514.el7.x86_64/igb_uio.ko b/scripts/ko/3.10.0-514.el7.x86_64/igb_uio.ko Binary files differnew file mode 100644 index 00000000..b23189d0 --- /dev/null +++ b/scripts/ko/3.10.0-514.el7.x86_64/igb_uio.ko diff --git a/scripts/trex-cfg b/scripts/trex-cfg index 08e1110f..02d50eb6 100755 --- a/scripts/trex-cfg +++ b/scripts/trex-cfg @@ -47,13 +47,7 @@ if ! lsmod | grep -q igb_uio ; then exit 1 fi km=ko/$SYS/igb_uio.ko - if [ -e $km ] ; then - insmod $km - if [ $? -ne 0 ]; then - echo "Failed inserting igb_uio module" - exit 1 - fi - else + if [ ! -e $km ]; then echo "ERROR: We don't have precompiled igb_uio.ko module for your kernel version" echo Will try compiling automatically. { @@ -73,6 +67,13 @@ if ! lsmod | grep -q igb_uio ; then } echo Success. fi + if [ -e $km ]; then + insmod $km + if [ $? -ne 0 ]; then + echo "Failed inserting igb_uio module" + exit 1 + fi + fi fi # try to bind the ports from the configuration file (new DPDK) diff --git a/scripts/trex_show_threads.py b/scripts/trex_show_threads.py index 1824d073..d0e34fe9 100755 --- a/scripts/trex_show_threads.py +++ b/scripts/trex_show_threads.py @@ -17,7 +17,8 @@ def read_task_stats (task_path): stat_data = open(stat, 'r').readline().split() stats_dict['last_sched_cpu'] = stat_data[-14] - + stats_dict['priority'] = stat_data[17] if stat_data[43] == '0' else 'RT' + return stats_dict @@ -26,7 +27,7 @@ def show_threads (pid): task_paths = ["{0}/{1}".format(process_dir, task) for task in os.listdir(process_dir)] - header = [ 'Task Name', 'PID', 'Allowed CPU', 'Last Sched CPU', 'Asked Ctx Switch', 'Forced Ctx Switch'] + header = [ 'Task Name', 'PID', 'Priority', 'Allowed CPU', 'Last Sched CPU', 'Asked Ctx Switch', 'Forced Ctx Switch'] for x in header: print('{:^20}'.format(x)), print("") @@ -41,6 +42,7 @@ def show_threads (pid): # name print("{:<20}".format(task['name'])), print("{:^20}".format(task['pid'])), + print("{:^20}".format(task['priority'])), print("{:^20}".format(task['cpus_allowed_list'])), print("{:^20}".format(task['last_sched_cpu'])), print("{:^20}".format(task['voluntary_ctxt_switches'])), diff --git a/src/bp_sim.h b/src/bp_sim.h index 282e7fe4..217446ed 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -628,6 +628,14 @@ public: return (btGetMaskBit32(m_flags1, 9, 9) ? true : false); } + void set_rt_prio_mode(bool enable) { + btSetMaskBit32(m_flags1, 10, 10, (enable ? 1 : 0) ); + } + + bool get_rt_prio_mode() { + return (btGetMaskBit32(m_flags1, 10, 10) ? true : false); + } + public: void Dump(FILE *fd); diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 1d315fa7..ebad39df 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -133,7 +133,6 @@ static char global_master_id_str[10]; class CTRexExtendedDriverBase { public: - /* by default NIC driver adds CRC */ virtual bool has_crc_added() { return true; @@ -154,6 +153,7 @@ public: } virtual int stop_queue(CPhyEthIF * _if, uint16_t q_num); + void get_extended_stats_fixed(CPhyEthIF * _if, CPhyEthIFStats *stats, int fix_i, int fix_o); virtual void get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats)=0; virtual void clear_extended_stats(CPhyEthIF * _if)=0; virtual int wait_for_stable_link(); @@ -237,10 +237,10 @@ public: virtual int set_rcv_all(CPhyEthIF * _if, bool set_on); }; -class CTRexExtendedDriverBase1GVm : public CTRexExtendedDriverBase { +class CTRexExtendedDriverVirtio : public CTRexExtendedDriverBase { public: - CTRexExtendedDriverBase1GVm(){ + CTRexExtendedDriverVirtio() { /* we are working in mode that we have 1 queue for rx and one queue for tx*/ CGlobalInfo::m_options.preview.set_vm_one_queue_enable(true); } @@ -254,12 +254,10 @@ public: } static CTRexExtendedDriverBase * create(){ - return ( new CTRexExtendedDriverBase1GVm() ); + return ( new CTRexExtendedDriverVirtio() ); } - virtual void update_global_config_fdir(port_cfg_t * cfg){ - - } + virtual void update_global_config_fdir(port_cfg_t * cfg) {} virtual int get_min_sample_rate(void){ return ( RX_CHECK_MIX_SAMPLE_RATE_1G); @@ -288,28 +286,53 @@ public: virtual int set_rcv_all(CPhyEthIF * _if, bool set_on) {return 0;} }; -class CTRexExtendedDriverVf : public CTRexExtendedDriverBase1GVm { +class CTRexExtendedDriverVmxnet3 : public CTRexExtendedDriverVirtio { +public: + CTRexExtendedDriverVmxnet3(){ + /* we are working in mode in which we have 1 queue for rx and one queue for tx*/ + CGlobalInfo::m_options.preview.set_vm_one_queue_enable(true); + } + + static CTRexExtendedDriverBase * create() { + return ( new CTRexExtendedDriverVmxnet3() ); + } + + virtual void update_configuration(port_cfg_t * cfg); +}; +class CTRexExtendedDriverI40evf : public CTRexExtendedDriverVirtio { public: - CTRexExtendedDriverVf(){ - /* we are working in mode in which we have we have 1 queue for rx and one queue for tx*/ + CTRexExtendedDriverI40evf(){ + /* we are working in mode in which we have 1 queue for rx and one queue for tx*/ CGlobalInfo::m_options.preview.set_vm_one_queue_enable(true); } virtual void get_extended_stats(CPhyEthIF * _if, CPhyEthIFStats *stats) { - uint64_t prev_ipackets = stats->ipackets; - uint64_t prev_opackets = stats->opackets; + get_extended_stats_fixed(_if, stats, 0, 4); + } - CTRexExtendedDriverBase1GVm::get_extended_stats(_if, stats); - // Since this driver report byte counts without Ethernet FCS (4 bytes), we need to fix the reported numbers - stats->ibytes += (stats->ipackets - prev_ipackets) * 4; - stats->obytes += (stats->opackets - prev_opackets) * 4; + virtual void update_configuration(port_cfg_t * cfg); + static CTRexExtendedDriverBase * create() { + return ( new CTRexExtendedDriverI40evf() ); } - static CTRexExtendedDriverBase * create(){ - return ( new CTRexExtendedDriverVf() ); +}; + +class CTRexExtendedDriverIxgbevf : public CTRexExtendedDriverI40evf { + +public: + CTRexExtendedDriverIxgbevf(){ + /* we are working in mode in which we have 1 queue for rx and one queue for tx*/ + CGlobalInfo::m_options.preview.set_vm_one_queue_enable(true); + } + virtual void get_extended_stats(CPhyEthIF * _if, CPhyEthIFStats *stats) { + get_extended_stats_fixed(_if, stats, 4, 4); + } + + static CTRexExtendedDriverBase * create() { + return ( new CTRexExtendedDriverIxgbevf() ); } }; -class CTRexExtendedDriverBaseE1000 : public CTRexExtendedDriverBase1GVm { +class CTRexExtendedDriverBaseE1000 : public CTRexExtendedDriverVirtio { CTRexExtendedDriverBaseE1000() { // E1000 driver is only relevant in VM in our case CGlobalInfo::m_options.preview.set_vm_one_queue_enable(true); @@ -320,6 +343,9 @@ public: } // e1000 driver handing us packets with ethernet CRC, so we need to chop them virtual uint8_t get_num_crc_fix_bytes() {return 4;} + + virtual void get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats); + }; class CTRexExtendedDriverBase10G : public CTRexExtendedDriverBase { @@ -593,11 +619,11 @@ private: register_driver(std::string("net_mlx5"),CTRexExtendedDriverBaseMlnx5G::create); /* virtual devices */ - register_driver(std::string("rte_em_pmd"),CTRexExtendedDriverBaseE1000::create); - register_driver(std::string("rte_vmxnet3_pmd"),CTRexExtendedDriverBase1GVm::create); - register_driver(std::string("rte_virtio_pmd"),CTRexExtendedDriverBase1GVm::create); - register_driver(std::string("rte_ixgbevf_pmd"),CTRexExtendedDriverVf::create); - register_driver(std::string("rte_i40evf_pmd"),CTRexExtendedDriverVf::create); + register_driver(std::string("rte_em_pmd"), CTRexExtendedDriverBaseE1000::create); + register_driver(std::string("rte_vmxnet3_pmd"), CTRexExtendedDriverVmxnet3::create); + register_driver(std::string("rte_virtio_pmd"), CTRexExtendedDriverVirtio::create); + register_driver(std::string("rte_i40evf_pmd"), CTRexExtendedDriverI40evf::create); + register_driver(std::string("rte_ixgbevf_pmd"), CTRexExtendedDriverIxgbevf::create); m_driver_was_set=false; m_drv=0; @@ -713,7 +739,8 @@ enum { OPT_HELP, OPT_ARP_REF_PER, OPT_NO_OFED_CHECK, OPT_NO_SCAPY_SERVER, - OPT_ACTIVE_FLOW + OPT_ACTIVE_FLOW, + OPT_RT }; /* these are the argument types: @@ -774,6 +801,7 @@ static CSimpleOpt::SOption parser_options[] = { OPT_ARP_REF_PER, "--arp-refresh-period", SO_REQ_SEP }, { OPT_NO_OFED_CHECK, "--no-ofed-check", SO_NONE }, { OPT_NO_SCAPY_SERVER, "--no-scapy-server", SO_NONE }, + { OPT_RT, "--rt", SO_NONE }, SO_END_OF_OPTIONS }; @@ -828,6 +856,7 @@ static int usage(){ printf(" --no-ofed-check : Disable the check of OFED version \n"); printf(" --no-scapy-server : Disable Scapy server implicit start at stateless \n"); printf(" --no-watchdog : Disable watchdog \n"); + printf(" --rt : Run TRex DP/RX cores in realtime priority \n"); printf(" -p : Send all flow packets from the same interface (choosed randomly between client ad server ports) without changing their src/dst IP \n"); printf(" -pm : Platform factor. If you have splitter in the setup, you can multiply the total results by this factor \n"); printf(" e.g --pm 2.0 will multiply all the results bps in this factor \n"); @@ -956,6 +985,9 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t po->preview.set_ipv6_mode_enable(true); break; + case OPT_RT: + po->preview.set_rt_prio_mode(true); + break; case OPT_LEARN : po->m_learn_mode = CParserOption::LEARN_MODE_IP_OPTION; @@ -1223,6 +1255,7 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t po->set_tw_levels(lp->m_levels); } } + return 0; } @@ -3685,6 +3718,7 @@ void CGlobalTRex::rx_sl_configure(void) { int CGlobalTRex::ixgbe_start(void){ int i; + for (i=0; i<m_max_ports; i++) { socket_id_t socket_id = CGlobalInfo::m_socket.port_to_socket((port_id_t)i); assert(CGlobalInfo::m_mem_pool[socket_id].m_mbuf_pool_2048); @@ -3693,14 +3727,14 @@ int CGlobalTRex::ixgbe_start(void){ uint16_t rx_rss = get_ex_drv()->enable_rss_drop_workaround(); if ( get_vm_one_queue_enable() ) { - /* VMXNET3 does claim to support 16K but somehow does not work */ - /* reduce to 2000 */ m_port_cfg.m_port_conf.rxmode.max_rx_pkt_len = 2000; /* In VM case, there is one tx q and one rx q */ _if->configure(1, 1, &m_port_cfg.m_port_conf); // Only 1 rx queue, so use it for everything m_rx_core_tx_q_id = 0; _if->set_rx_queue(0); + // We usually have less memory in VM, so don't use the 9k pool. This means that large packets will + // be received in chain of few mbufs _if->rx_queue_setup(0, RTE_TEST_RX_DESC_VM_DEFAULT, socket_id, &m_port_cfg.m_rx_conf, CGlobalInfo::m_mem_pool[socket_id].m_mbuf_pool_2048); // 1 TX queue in VM case @@ -4846,8 +4880,20 @@ int CGlobalTRex::run_in_master() { int CGlobalTRex::run_in_rx_core(void){ + CPreviewMode *lp = &CGlobalInfo::m_options.preview; + rte_thread_setname(pthread_self(), "TRex RX"); - + + /* set RT mode if set */ + if (lp->get_rt_prio_mode()) { + struct sched_param param; + param.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m) != 0) { + perror("setting RT priroity mode on RX core failed with error"); + exit(EXIT_FAILURE); + } + } + if (get_is_stateless()) { m_sl_rx_running = true; m_rx_sl.start(); @@ -4864,11 +4910,22 @@ int CGlobalTRex::run_in_rx_core(void){ int CGlobalTRex::run_in_core(virtual_thread_id_t virt_core_id){ std::stringstream ss; - + CPreviewMode *lp = &CGlobalInfo::m_options.preview; + ss << "Trex DP core " << int(virt_core_id); rte_thread_setname(pthread_self(), ss.str().c_str()); + + /* set RT mode if set */ + if (lp->get_rt_prio_mode()) { + struct sched_param param; + param.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m) != 0) { + perror("setting RT priroity mode on DP core failed with error"); + exit(EXIT_FAILURE); + } + } - CPreviewMode *lp=&CGlobalInfo::m_options.preview; + if ( lp->getSingleCore() && (virt_core_id==2 ) && (lp-> getCores() ==1) ){ @@ -5868,6 +5925,35 @@ CFlowStatParser *CTRexExtendedDriverBase::get_flow_stat_parser() { return parser; } +void CTRexExtendedDriverBase::get_extended_stats_fixed(CPhyEthIF * _if, CPhyEthIFStats *stats, int fix_i, int fix_o) { + struct rte_eth_stats stats1; + struct rte_eth_stats *prev_stats = &stats->m_prev_stats; + rte_eth_stats_get(_if->get_port_id(), &stats1); + + stats->ipackets += stats1.ipackets - prev_stats->ipackets; + // Some drivers report input byte counts without Ethernet FCS (4 bytes), we need to fix the reported numbers + stats->ibytes += stats1.ibytes - prev_stats->ibytes + (stats1.ipackets - prev_stats->ipackets) * fix_i; + stats->opackets += stats1.opackets - prev_stats->opackets; + // Some drivers report output byte counts without Ethernet FCS (4 bytes), we need to fix the reported numbers + stats->obytes += stats1.obytes - prev_stats->obytes + (stats1.opackets - prev_stats->opackets) * fix_o; + stats->f_ipackets += 0; + stats->f_ibytes += 0; + stats->ierrors += stats1.imissed + stats1.ierrors + stats1.rx_nombuf + - prev_stats->imissed - prev_stats->ierrors - prev_stats->rx_nombuf; + stats->oerrors += stats1.oerrors - prev_stats->oerrors; + stats->imcasts += 0; + stats->rx_nombuf += stats1.rx_nombuf - prev_stats->rx_nombuf; + + prev_stats->ipackets = stats1.ipackets; + prev_stats->ibytes = stats1.ibytes; + prev_stats->opackets = stats1.opackets; + prev_stats->obytes = stats1.obytes; + prev_stats->imissed = stats1.imissed; + prev_stats->oerrors = stats1.oerrors; + prev_stats->ierrors = stats1.ierrors; + prev_stats->rx_nombuf = stats1.rx_nombuf; +} + // in 1G we need to wait if links became ready to soon void CTRexExtendedDriverBase1G::wait_after_link_up(){ wait_x_sec(6 + CGlobalInfo::m_options.m_wait_before_traffic); @@ -6648,31 +6734,7 @@ int CTRexExtendedDriverBase40G::dump_fdir_global_stats(CPhyEthIF * _if, FILE *fd } void CTRexExtendedDriverBase40G::get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats) { - struct rte_eth_stats stats1; - struct rte_eth_stats *prev_stats = &stats->m_prev_stats; - rte_eth_stats_get(_if->get_port_id(), &stats1); - - stats->ipackets += stats1.ipackets - prev_stats->ipackets; - stats->ibytes += stats1.ibytes - prev_stats->ibytes; - stats->opackets += stats1.opackets - prev_stats->opackets; - // Since this driver report obytes count without Ethernet FCS (4 bytes), we need to fix the reported numbers - stats->obytes += stats1.obytes - prev_stats->obytes + (stats1.opackets - prev_stats->opackets) * 4; - stats->f_ipackets += 0; - stats->f_ibytes += 0; - stats->ierrors += stats1.imissed + stats1.ierrors + stats1.rx_nombuf - - prev_stats->imissed - prev_stats->ierrors - prev_stats->rx_nombuf; - stats->oerrors += stats1.oerrors - prev_stats->oerrors; - stats->imcasts += 0; - stats->rx_nombuf += stats1.rx_nombuf - prev_stats->rx_nombuf; - - prev_stats->ipackets = stats1.ipackets; - prev_stats->ibytes = stats1.ibytes; - prev_stats->opackets = stats1.opackets; - prev_stats->obytes = stats1.obytes; - prev_stats->imissed = stats1.imissed; - prev_stats->oerrors = stats1.oerrors; - prev_stats->ierrors = stats1.ierrors; - prev_stats->rx_nombuf = stats1.rx_nombuf; + get_extended_stats_fixed(_if, stats, 0, 4); } int CTRexExtendedDriverBase40G::wait_for_stable_link(){ @@ -6892,33 +6954,7 @@ int CTRexExtendedDriverBaseMlnx5G::dump_fdir_global_stats(CPhyEthIF * _if, FILE } void CTRexExtendedDriverBaseMlnx5G::get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats){ - - struct rte_eth_stats stats1; - struct rte_eth_stats *prev_stats = &stats->m_prev_stats; - rte_eth_stats_get(_if->get_port_id(), &stats1); - - stats->ipackets += stats1.ipackets - prev_stats->ipackets; - stats->ibytes += stats1.ibytes - prev_stats->ibytes + - + (stats1.ipackets << 2) - (prev_stats->ipackets << 2); - stats->opackets += stats1.opackets - prev_stats->opackets; - stats->obytes += stats1.obytes - prev_stats->obytes - + (stats1.opackets << 2) - (prev_stats->opackets << 2); - stats->f_ipackets += 0; - stats->f_ibytes += 0; - stats->ierrors += stats1.imissed + stats1.ierrors + stats1.rx_nombuf - - prev_stats->imissed - prev_stats->ierrors - prev_stats->rx_nombuf; - stats->oerrors += stats1.oerrors - prev_stats->oerrors; - stats->imcasts += 0; - stats->rx_nombuf += stats1.rx_nombuf - prev_stats->rx_nombuf; - - prev_stats->ipackets = stats1.ipackets; - prev_stats->ibytes = stats1.ibytes; - prev_stats->opackets = stats1.opackets; - prev_stats->obytes = stats1.obytes; - prev_stats->imissed = stats1.imissed; - prev_stats->oerrors = stats1.oerrors; - prev_stats->ierrors = stats1.ierrors; - prev_stats->rx_nombuf = stats1.rx_nombuf; + get_extended_stats_fixed(_if, stats, 4, 4); } int CTRexExtendedDriverBaseMlnx5G::wait_for_stable_link(){ @@ -7055,31 +7091,8 @@ void CTRexExtendedDriverBaseVIC::clear_extended_stats(CPhyEthIF * _if){ } void CTRexExtendedDriverBaseVIC::get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats) { - struct rte_eth_stats stats1; - struct rte_eth_stats *prev_stats = &stats->m_prev_stats; - rte_eth_stats_get(_if->get_port_id(), &stats1); - - stats->ipackets += stats1.ipackets - prev_stats->ipackets; - stats->ibytes += stats1.ibytes - prev_stats->ibytes - - ((stats1.ipackets << 2) - (prev_stats->ipackets << 2)); - stats->opackets += stats1.opackets - prev_stats->opackets; - stats->obytes += stats1.obytes - prev_stats->obytes; - stats->f_ipackets += 0; - stats->f_ibytes += 0; - stats->ierrors += stats1.imissed + stats1.ierrors + stats1.rx_nombuf - - prev_stats->imissed - prev_stats->ierrors - prev_stats->rx_nombuf; - stats->oerrors += stats1.oerrors - prev_stats->oerrors; - stats->imcasts += 0; - stats->rx_nombuf += stats1.rx_nombuf - prev_stats->rx_nombuf; - - prev_stats->ipackets = stats1.ipackets; - prev_stats->ibytes = stats1.ibytes; - prev_stats->opackets = stats1.opackets; - prev_stats->obytes = stats1.obytes; - prev_stats->imissed = stats1.imissed; - prev_stats->oerrors = stats1.oerrors; - prev_stats->ierrors = stats1.ierrors; - prev_stats->rx_nombuf = stats1.rx_nombuf; + // In VIC, we need to reduce 4 bytes from the amount reported for each incoming packet + get_extended_stats_fixed(_if, stats, -4, 0); } int CTRexExtendedDriverBaseVIC::verify_fw_ver(int port_id) { @@ -7137,66 +7150,54 @@ CFlowStatParser *CTRexExtendedDriverBaseVIC::get_flow_stat_parser() { ///////////////////////////////////////////////////////////////////////////////////// - - -void CTRexExtendedDriverBase1GVm::update_configuration(port_cfg_t * cfg){ - struct rte_eth_dev_info dev_info; - rte_eth_dev_info_get((uint8_t) 0,&dev_info); - +void CTRexExtendedDriverVirtio::update_configuration(port_cfg_t * cfg){ cfg->m_tx_conf.tx_thresh.pthresh = TX_PTHRESH_1G; cfg->m_tx_conf.tx_thresh.hthresh = TX_HTHRESH; cfg->m_tx_conf.tx_thresh.wthresh = 0; - cfg->m_tx_conf.txq_flags=dev_info.default_txconf.txq_flags; - + // must have this, otherwise the driver fail at init + cfg->m_tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMS; } - -int CTRexExtendedDriverBase1GVm::configure_rx_filter_rules(CPhyEthIF * _if){ +int CTRexExtendedDriverVirtio::configure_rx_filter_rules(CPhyEthIF * _if){ return (0); } -void CTRexExtendedDriverBase1GVm::clear_extended_stats(CPhyEthIF * _if){ - +void CTRexExtendedDriverVirtio::clear_extended_stats(CPhyEthIF * _if){ rte_eth_stats_reset(_if->get_port_id()); - } -int CTRexExtendedDriverBase1GVm::stop_queue(CPhyEthIF * _if, uint16_t q_num) { +int CTRexExtendedDriverVirtio::stop_queue(CPhyEthIF * _if, uint16_t q_num) { return (0); } -void CTRexExtendedDriverBase1GVm::get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats){ - struct rte_eth_stats stats1; - struct rte_eth_stats *prev_stats = &stats->m_prev_stats; - rte_eth_stats_get(_if->get_port_id(), &stats1); - - stats->ipackets += stats1.ipackets - prev_stats->ipackets; - stats->ibytes += stats1.ibytes - prev_stats->ibytes; - stats->opackets += stats1.opackets - prev_stats->opackets; - stats->obytes += stats1.obytes - prev_stats->obytes; - stats->f_ipackets += 0; - stats->f_ibytes += 0; - stats->ierrors += stats1.imissed + stats1.ierrors + stats1.rx_nombuf - - prev_stats->imissed - prev_stats->ierrors - prev_stats->rx_nombuf; - stats->oerrors += stats1.oerrors - prev_stats->oerrors; - stats->imcasts += 0; - stats->rx_nombuf += stats1.rx_nombuf - prev_stats->rx_nombuf; +void CTRexExtendedDriverBaseE1000::get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats){ + get_extended_stats_fixed(_if, stats, 0, 4); +} - prev_stats->ipackets = stats1.ipackets; - prev_stats->ibytes = stats1.ibytes; - prev_stats->opackets = stats1.opackets; - prev_stats->obytes = stats1.obytes; - prev_stats->imissed = stats1.imissed; - prev_stats->oerrors = stats1.oerrors; - prev_stats->ierrors = stats1.ierrors; - prev_stats->rx_nombuf = stats1.rx_nombuf; +void CTRexExtendedDriverVirtio::get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats) { + get_extended_stats_fixed(_if, stats, 4, 4); } -int CTRexExtendedDriverBase1GVm::wait_for_stable_link(){ +int CTRexExtendedDriverVirtio::wait_for_stable_link(){ wait_x_sec(CGlobalInfo::m_options.m_wait_before_traffic); return (0); } +/////////////////////////////////////////////////////////// VMxnet3 +void CTRexExtendedDriverVmxnet3::update_configuration(port_cfg_t * cfg){ + cfg->m_tx_conf.tx_thresh.pthresh = TX_PTHRESH_1G; + cfg->m_tx_conf.tx_thresh.hthresh = TX_HTHRESH; + cfg->m_tx_conf.tx_thresh.wthresh = 0; + // must have this, otherwise the driver fail at init + cfg->m_tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMSCTP; +} + +///////////////////////////////////////////////////////// VF +void CTRexExtendedDriverI40evf::update_configuration(port_cfg_t * cfg) { + cfg->m_tx_conf.tx_thresh.pthresh = TX_PTHRESH; + cfg->m_tx_conf.tx_thresh.hthresh = TX_HTHRESH; + cfg->m_tx_conf.tx_thresh.wthresh = TX_WTHRESH; +} /** diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp index 3f73a5d7..836dc5de 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -853,13 +853,13 @@ TrexRpcCmdValidate::_run(const Json::Value ¶ms, Json::Value &result) { result["result"]["rate"]["max_bps_l2"] = graph->get_max_bps_l2(); result["result"]["rate"]["max_bps_l1"] = graph->get_max_bps_l1(); result["result"]["rate"]["max_pps"] = graph->get_max_pps(); - result["result"]["rate"]["max_line_util"] = (graph->get_max_bps_l1() / port->get_port_speed_bps()) * 100.0; + result["result"]["rate"]["max_line_util"] = (graph->get_max_bps_l1() / port->get_port_speed_bps()) * 100.01; /* min values */ result["result"]["rate"]["min_bps_l2"] = graph->get_max_bps_l2(0); result["result"]["rate"]["min_bps_l1"] = graph->get_max_bps_l1(0); result["result"]["rate"]["min_pps"] = graph->get_max_pps(0); - result["result"]["rate"]["min_line_util"] = (graph->get_max_bps_l1(0) / port->get_port_speed_bps()) * 100.0; + result["result"]["rate"]["min_line_util"] = (graph->get_max_bps_l1(0) / port->get_port_speed_bps()) * 100.01; result["result"]["graph"]["expected_duration"] = graph->get_duration(); result["result"]["graph"]["events_count"] = (int)graph->get_events().size(); diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index bfc7dce4..b88ac715 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -696,12 +696,6 @@ TrexStatelessPort::calculate_effective_factor(const TrexPortMultiplier &mul, boo /* did we exceeded the max L1 line rate ? */ double expected_l1_rate = m_graph_obj->get_max_bps_l1(factor); - /* if not force and exceeded - throw exception */ - if ( (!force) && (expected_l1_rate > get_port_speed_bps()) ) { - stringstream ss; - ss << "Expected L1 B/W: '" << bps_to_gbps(expected_l1_rate) << " Gbps' exceeds port line rate: '" << bps_to_gbps(get_port_speed_bps()) << " Gbps'"; - throw TrexException(ss.str()); - } /* L1 BW must be positive */ if (expected_l1_rate <= 0){ @@ -717,7 +711,23 @@ TrexStatelessPort::calculate_effective_factor(const TrexPortMultiplier &mul, boo throw TrexException(ss.str()); } - return factor; + /* if force simply return the value */ + if (force) { + return factor; + } else { + + /* due to float calculations we allow 0.1% roundup */ + if ( (expected_l1_rate / get_port_speed_bps()) > 1.0001 ) { + stringstream ss; + ss << "Expected L1 B/W: '" << bps_to_gbps(expected_l1_rate) << " Gbps' exceeds port line rate: '" << bps_to_gbps(get_port_speed_bps()) << " Gbps'"; + throw TrexException(ss.str()); + } + + /* in any case, without force, do not return any value higher than the max factor */ + double max_factor = m_graph_obj->get_factor_bps_l1(get_port_speed_bps()); + return std::min(max_factor, factor); + } + } double |