* [dts] [PATCH 1/2] support html report for nic performance result @ 2017-05-10 4:59 Yulong Pei 2017-05-10 4:59 ` [dts] [PATCH 2/2] tests: support html report for single core performance test Yulong Pei 2017-05-11 5:42 ` [dts] [PATCH 1/2] support html report for nic performance result Liu, Yong 0 siblings, 2 replies; 11+ messages in thread From: Yulong Pei @ 2017-05-10 4:59 UTC (permalink / raw) To: dts; +Cc: qian.q.xu, yong.liu support html report for nic performance result and support to send it out by email. Signed-off-by: Yulong Pei <yulong.pei@intel.com> --- nics/perf_report.jinja | 82 +++++++++++++++++++++++++++++++++++++++++ nics/perf_report.py | 79 ++++++++++++++++++++++++++++++++++++++++ nics/system_info.py | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 260 insertions(+) create mode 100644 nics/perf_report.jinja create mode 100644 nics/perf_report.py create mode 100644 nics/system_info.py diff --git a/nics/perf_report.jinja b/nics/perf_report.jinja new file mode 100644 index 0000000..1a3f903 --- /dev/null +++ b/nics/perf_report.jinja @@ -0,0 +1,82 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="UTF-8" /> +<title>{{ title }}</title> +<style> +table, th, td { + border: 1px solid black; + border-collapse: collapse; +} +th, td { + padding: 5px; + text-align: left; + background-color: #33A1C9; +} +</style> +</head> + +<body> + +<div id="dpdk_info"> +<h2> DPDK Git Information </h2> +<p> Branch: {{ git_info['branch'] }} </p> +<p> commit: {{ git_info['commit'] }} </p> +<p> Author: {{ git_info['author'] }} </p> +<p> Date: {{ git_info['date'] }} </p> +<p> Summary: {{ git_info['summary'] }} </p> +</div> + +<div id="nic_info"> + <h2>NIC Detail Information</h2> + <table> + <tr> + <th>Item</th> + <th>Description</th> + </tr> + {% for key in nic_infos %} + <tr> + <td>{{ key }}</td> + <td>{{ nic_infos[key] }}</td> + </tr> + {% endfor %} + </table> +</div> + +<div id="test_result"> + <h2>Test Result:</h2> + <table> + <tr> + <th>Frame_size(bytes)</th> + <th>Throughput(Mpps)</th> + <th>Line rate%</th> + </tr> + {% for result in test_results %} + <tr> + <td>{{ result[0] }}</td> + <td>{{ result[1] }}</td> + <td>{{ result[2] }}</td> + </tr> + {% endfor %} + </table> +</div> + +<div id="system_info"> + <h2>Hardware and Software Ingredients</h2> + <table> + <tr> + <th>Item</th> + <th>Description</th> + </tr> + {% for key in system_infos %} + <tr> + <td>{{ key }}</td> + <td>{{ system_infos[key] }}</td> + </tr> + {% endfor %} + </table> +</div> + +</body> + +</html> diff --git a/nics/perf_report.py b/nics/perf_report.py new file mode 100644 index 0000000..2517a68 --- /dev/null +++ b/nics/perf_report.py @@ -0,0 +1,79 @@ +import os +import time +import re + +import jinja2 +import smtplib + +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from collections import OrderedDict +#install GitPython +from git import Repo +from system_info import SystemInfo + +def get_dpdk_git_info(repo_dir="/root/dpdk"): + + if not os.path.exists(repo_dir): + return None + + commit = OrderedDict() + + git_repo = Repo(repo_dir) + assert not git_repo.bare + + latest_commit = git_repo.active_branch.commit + commit['branch'] = str(git_repo.active_branch) + commit['commit'] = str(latest_commit) + commit['author'] = latest_commit.author + commit['date'] = time.ctime(latest_commit.authored_date) + commit['summary'] = latest_commit.summary + return commit + +def generate_html_report(file_tpl, perf_data, git_info, nic_info, system_info): + + if not os.path.exists(file_tpl): + return None + + templateLoader = jinja2.FileSystemLoader(searchpath = "/") + templateEnv = jinja2.Environment(loader=templateLoader) + template = templateEnv.get_template(file_tpl) + + templateVars = { "title" : "Daily Performance Test Report", \ + "test_results" : perf_data, \ + "system_infos" : system_info, \ + "nic_infos" : nic_info, \ + "git_info" : git_info \ + } + + output = template.render(templateVars) + return output + +#sender = 'zzz@intel.com' +#mailto = ['xxx@intel.com', 'yyy@intel.com'] +def html_message(sender, mailto, subject, html_msg): + + msg = MIMEMultipart('alternative') + msg['From'] = sender + msg['to'] = ";".join(mailto) + msg['Subject'] = subject + + msg.attach(MIMEText(html_msg, 'html')) + + return msg + +#smtp = smtplib.SMTP('smtp.intel.com') +def send_email(sender, mailto, message, smtp_server): + + try: + smtp = smtplib.SMTP(smtp_server) + smtp.sendmail(sender, mailto, message.as_string()) + smtp.quit() + print "OK to sent email." + except Exception, e: + print "Failed to send email " + str(e) + +def send_html_report(sender, mailto, subject, html_msg, smtp_server): + + message = html_message(sender, mailto, subject, html_msg) + send_email(sender, mailto, message, smtp_server) diff --git a/nics/system_info.py b/nics/system_info.py new file mode 100644 index 0000000..a78c841 --- /dev/null +++ b/nics/system_info.py @@ -0,0 +1,99 @@ +#!/usr/bin/python + +import os +import time +import re + +from collections import OrderedDict +#install GitPython +from git import Repo + +class SystemInfo(object): + + def __init__(self, dut, pci_device_id): + self.dut = dut + self.pci_device_id = pci_device_id + self.session = self.dut.session + self.system_info = OrderedDict() + self.nic_info = OrderedDict() + + def get_system_info(self): + + board = self.session.send_expect("dmidecode -s system-product-name", "# ") + self.system_info["Board"] = board + + processors = self.session.send_expect("dmidecode -s processor-version", "# ") + processor = processors.split('\r\n')[0] + self.system_info["CPU"] = processor + + memories = self.session.send_expect("dmidecode -t memory", "]# ") + channels, size, speed = self._strip_memory(memories) + memory_info = "Total %d MBs in %d channels @ %s" %(size, channels, speed) + self.system_info["Memory"] = memory_info + + release = self.session.send_expect("lsb_release -d |awk -F':' '{print $2}'", "# ") + self.system_info["Operating system"] = release + + kernel = self.session.send_expect("uname -r", "# ") + self.system_info["Linux kernel version"] = kernel + + gcc_info = self.session.send_expect("gcc --version", "# ") + gcc = gcc_info.split('\r\n')[0] + self.system_info["GCC version"] = gcc + + return self.system_info + + def _strip_memory(self, memories): + """ + Size: 8192 MB Locator: DIMM_A1 Speed: 2133 MHz + """ + s_regex = r"(\s+)Size: (\d+) MB" + l_regex= r"(\s+)Locator: DIMM_(\w+)" + speed_regex = r"(\s+)Speed: (.*)" + size = "" + locate = "" + speed = "Unknown" + memory_infos = [] + memory_channel = set() + lines = memories.split('\r\n') + total_size = 0 + for line in lines: + m = re.match(s_regex, line) + if m: + size = m.group(2) + l_m = re.match(l_regex, line) + if l_m: + locate = l_m.group(2) + s_m = re.match(speed_regex, line) + if s_m: + speed = s_m.group(2) + if speed != "Unknown": + memory={"Size": size, "Locate": locate, "Speed": speed} + memory_infos.append(memory) + speed = "Unknown" + total_size += int(size) + memory_channel.add(locate[0]) + + return len(memory_channel), total_size, memory_infos[0]["Speed"] + + def get_nic_info(self): + + vendor = self.session.send_expect("cat /sys/bus/pci/devices/%s/vendor" % self.pci_device_id, "# ") + if "No such" in vendor: + return None + device = self.session.send_expect("cat /sys/bus/pci/devices/%s/device" % self.pci_device_id, "# ") + if "No such" in device: + return None + + interface = self.session.send_expect("ls --color=never /sys/bus/pci/devices/%s/net" % self.pci_device_id, "# ") + if "No such" in interface: + return None + firmware = self.session.send_expect("ethtool -i %s | grep --color=never firmware |awk -F':' '{print $2}'" % interface, "# ") + if "No such" in firmware: + return None + + self.nic_info['nic_name'] = self.session.send_expect("lspci -vmmks %s |grep -i ^device |awk -F':' '{print $2}'" % self.pci_device_id, "# ") + self.nic_info['device_id'] = vendor[2:] + ':' + device[2:] + self.nic_info['firmware-version'] = firmware + return self.nic_info + -- 2.5.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [dts] [PATCH 2/2] tests: support html report for single core performance test 2017-05-10 4:59 [dts] [PATCH 1/2] support html report for nic performance result Yulong Pei @ 2017-05-10 4:59 ` Yulong Pei 2017-05-11 5:50 ` Liu, Yong 2017-05-11 5:42 ` [dts] [PATCH 1/2] support html report for nic performance result Liu, Yong 1 sibling, 1 reply; 11+ messages in thread From: Yulong Pei @ 2017-05-10 4:59 UTC (permalink / raw) To: dts; +Cc: qian.q.xu, yong.liu support html report for single core performance test. Signed-off-by: Yulong Pei <yulong.pei@intel.com> --- tests/TestSuite_pmd.py | 69 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/tests/TestSuite_pmd.py b/tests/TestSuite_pmd.py index 2d5b485..d004310 100644 --- a/tests/TestSuite_pmd.py +++ b/tests/TestSuite_pmd.py @@ -37,12 +37,20 @@ Test userland 10Gb PMD import utils import re import time +import os + from test_case import TestCase from time import sleep from settings import HEADER_SIZE from pmd_output import PmdOutput from etgen import IxiaPacketGenerator +from settings import FOLDERS +from system_info import SystemInfo +import perf_report +from datetime import datetime + + class TestPmd(TestCase,IxiaPacketGenerator): def set_up_all(self): @@ -53,7 +61,7 @@ class TestPmd(TestCase,IxiaPacketGenerator): """ self.tester.extend_external_packet_generator(TestPmd, self) - self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518] + self.frame_sizes = [64, 72, 128, 256, 512, 1024, 1280, 1518] self.rxfreet_values = [0, 8, 16, 32, 64, 128] @@ -62,10 +70,11 @@ class TestPmd(TestCase,IxiaPacketGenerator): self.table_header = ['Frame Size'] for test_cycle in self.test_cycles: - self.table_header.append("app") self.table_header.append("%s Mpps" % test_cycle['cores']) self.table_header.append("% linerate") + self.perf_results = {'header': [], 'data': []} + self.blacklist = "" # Update config file and rebuild to get best perf on FVL @@ -75,6 +84,19 @@ class TestPmd(TestCase,IxiaPacketGenerator): # Based on h/w type, choose how many ports to use self.dut_ports = self.dut.get_ports() + # Get dut system information + port_num = self.dut_ports[0] + pci_device_id = self.dut.ports_info[port_num]['pci'] + ori_driver = self.dut.ports_info[port_num]['port'].get_nic_driver() + self.dut.ports_info[port_num]['port'].bind_driver() + + sut = SystemInfo(self.dut, pci_device_id) + self.system_info = sut.get_system_info() + self.nic_info = sut.get_nic_info() + + self.dut.ports_info[port_num]['port'].bind_driver(ori_driver) + ###### + self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE[ 'ip'] + HEADER_SIZE['tcp'] @@ -92,12 +114,37 @@ class TestPmd(TestCase,IxiaPacketGenerator): """ Run single core performance """ + self.perf_results['header'] = [] + self.perf_results['data'] = [] + if len(self.dut_ports) >= 4: self.pmd_performance_4ports() else: self.verify(len(self.dut_ports) >= 2, "Insufficient ports for 2 ports performance test") self.pmd_performance_2ports() + #To replace False to True for if condition to send the result by email. + if False: + repo_dir = FOLDERS["Depends"] + r'/dpdk' + git_info = perf_report.get_dpdk_git_info(repo_dir) + self.verify(git_info is not None, "get dpdk git repo error") + + tpl_path = FOLDERS["NicDriver"] + r'/perf_report.jinja' + file_tpl = os.path.abspath(tpl_path) + html_msg = perf_report.generate_html_report(file_tpl, \ + perf_data = self.perf_results['data'], \ + git_info = git_info, \ + nic_info = self.nic_info, \ + system_info = self.system_info) + self.verify(html_msg is not None, "generate html report error") + + subject = "Single core performance test with %d ports %s -- %s" % \ + (len(self.dut_ports), self.nic, datetime.now().strftime('%Y-%m-%d %H:%M')) + sender = 'xxxxxx@intel.com' + mailto = ['xxxxxx@intel.com'] + smtp_server = 'smtp.intel.com' + perf_report.send_html_report(sender, mailto, subject, html_msg, smtp_server) + def pmd_performance_4ports(self): """ PMD Performance Benchmarking with 4 ports. @@ -159,8 +206,9 @@ class TestPmd(TestCase,IxiaPacketGenerator): _, pps = self.tester.traffic_generator_throughput(tgen_input, rate_percent=100, delay=60) pps /= 1000000.0 - test_cycle['Mpps'][frame_size] = pps - test_cycle['pct'][frame_size] = pps * 100 / wirespeed + pct = pps * 100 / wirespeed + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) + test_cycle['pct'][frame_size] = float('%.3f' % pct) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) @@ -173,16 +221,16 @@ class TestPmd(TestCase,IxiaPacketGenerator): # Print results self.result_table_create(self.table_header) + self.perf_results['header'] = self.table_header for frame_size in self.frame_sizes: table_row = [frame_size] - for test_cycle in self.test_cycles: - table_row.append("testpmd") table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) self.result_table_add(table_row) + self.perf_results['data'].append(table_row) self.result_table_print() @@ -241,10 +289,10 @@ class TestPmd(TestCase,IxiaPacketGenerator): # run traffic generator _, pps = self.tester.traffic_generator_throughput(tgen_input, rate_percent=100, delay=60) - pps /= 1000000.0 - test_cycle['Mpps'][frame_size] = pps - test_cycle['pct'][frame_size] = pps * 100 / wirespeed + pct = pps * 100 / wirespeed + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) + test_cycle['pct'][frame_size] = float('%.3f' % pct) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) @@ -257,14 +305,15 @@ class TestPmd(TestCase,IxiaPacketGenerator): # Print results self.result_table_create(self.table_header) + self.perf_results['header'] = self.table_header for frame_size in self.frame_sizes: table_row = [frame_size] for test_cycle in self.test_cycles: - table_row.append("testpmd") table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) self.result_table_add(table_row) + self.perf_results['data'].append(table_row) self.result_table_print() -- 2.5.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [dts] [PATCH 2/2] tests: support html report for single core performance test 2017-05-10 4:59 ` [dts] [PATCH 2/2] tests: support html report for single core performance test Yulong Pei @ 2017-05-11 5:50 ` Liu, Yong 0 siblings, 0 replies; 11+ messages in thread From: Liu, Yong @ 2017-05-11 5:50 UTC (permalink / raw) To: Pei, Yulong, dts; +Cc: Xu, Qian Q Yulong, one comment below. > -----Original Message----- > From: Pei, Yulong > Sent: Wednesday, May 10, 2017 1:00 PM > To: dts@dpdk.org > Cc: Xu, Qian Q <qian.q.xu@intel.com>; Liu, Yong <yong.liu@intel.com> > Subject: [PATCH 2/2] tests: support html report for single core > performance test > > support html report for single core performance test. > > Signed-off-by: Yulong Pei <yulong.pei@intel.com> > --- > tests/TestSuite_pmd.py | 69 ++++++++++++++++++++++++++++++++++++++++++--- > ----- > 1 file changed, 59 insertions(+), 10 deletions(-) > > diff --git a/tests/TestSuite_pmd.py b/tests/TestSuite_pmd.py > index 2d5b485..d004310 100644 > --- a/tests/TestSuite_pmd.py > +++ b/tests/TestSuite_pmd.py > @@ -37,12 +37,20 @@ Test userland 10Gb PMD > import utils > import re > import time > +import os > + > from test_case import TestCase > from time import sleep > from settings import HEADER_SIZE > from pmd_output import PmdOutput > from etgen import IxiaPacketGenerator > > +from settings import FOLDERS > +from system_info import SystemInfo > +import perf_report > +from datetime import datetime > + > + > class TestPmd(TestCase,IxiaPacketGenerator): > > def set_up_all(self): > @@ -53,7 +61,7 @@ class TestPmd(TestCase,IxiaPacketGenerator): > """ > self.tester.extend_external_packet_generator(TestPmd, self) > > - self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518] > + self.frame_sizes = [64, 72, 128, 256, 512, 1024, 1280, 1518] > > self.rxfreet_values = [0, 8, 16, 32, 64, 128] > > @@ -62,10 +70,11 @@ class TestPmd(TestCase,IxiaPacketGenerator): > > self.table_header = ['Frame Size'] > for test_cycle in self.test_cycles: > - self.table_header.append("app") > self.table_header.append("%s Mpps" % test_cycle['cores']) > self.table_header.append("% linerate") > > + self.perf_results = {'header': [], 'data': []} > + > self.blacklist = "" > > # Update config file and rebuild to get best perf on FVL > @@ -75,6 +84,19 @@ class TestPmd(TestCase,IxiaPacketGenerator): > # Based on h/w type, choose how many ports to use > self.dut_ports = self.dut.get_ports() > > + # Get dut system information > + port_num = self.dut_ports[0] > + pci_device_id = self.dut.ports_info[port_num]['pci'] > + ori_driver = > self.dut.ports_info[port_num]['port'].get_nic_driver() > + self.dut.ports_info[port_num]['port'].bind_driver() > + > + sut = SystemInfo(self.dut, pci_device_id) > + self.system_info = sut.get_system_info() > + self.nic_info = sut.get_nic_info() > + > + self.dut.ports_info[port_num]['port'].bind_driver(ori_driver) > + ###### > + > self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE[ > 'ip'] + HEADER_SIZE['tcp'] > > @@ -92,12 +114,37 @@ class TestPmd(TestCase,IxiaPacketGenerator): > """ > Run single core performance > """ > + self.perf_results['header'] = [] > + self.perf_results['data'] = [] > + > if len(self.dut_ports) >= 4: > self.pmd_performance_4ports() > else: > self.verify(len(self.dut_ports) >= 2, "Insufficient ports for > 2 ports performance test") > self.pmd_performance_2ports() > > + #To replace False to True for if condition to send the result by > email. > + if False: > + repo_dir = FOLDERS["Depends"] + r'/dpdk' If run dts with skip snapshot option, dpdk folder under dep may not existed. Performance report generation at least has one dependency on testing setup, so please add more description about the dependencies in code comments. > + git_info = perf_report.get_dpdk_git_info(repo_dir) > + self.verify(git_info is not None, "get dpdk git repo error") > + > + tpl_path = FOLDERS["NicDriver"] + r'/perf_report.jinja' > + file_tpl = os.path.abspath(tpl_path) > + html_msg = perf_report.generate_html_report(file_tpl, \ > + perf_data = > self.perf_results['data'], \ > + git_info = > git_info, \ > + nic_info = > self.nic_info, \ > + system_info = > self.system_info) > + self.verify(html_msg is not None, "generate html report > error") > + > + subject = "Single core performance test with %d ports %s -- > %s" % \ > + (len(self.dut_ports), self.nic, > datetime.now().strftime('%Y-%m-%d %H:%M')) > + sender = 'xxxxxx@intel.com' > + mailto = ['xxxxxx@intel.com'] > + smtp_server = 'smtp.intel.com' > + perf_report.send_html_report(sender, mailto, subject, > html_msg, smtp_server) > + > def pmd_performance_4ports(self): > """ > PMD Performance Benchmarking with 4 ports. > @@ -159,8 +206,9 @@ class TestPmd(TestCase,IxiaPacketGenerator): > _, pps = > self.tester.traffic_generator_throughput(tgen_input, rate_percent=100, > delay=60) > > pps /= 1000000.0 > - test_cycle['Mpps'][frame_size] = pps > - test_cycle['pct'][frame_size] = pps * 100 / wirespeed > + pct = pps * 100 / wirespeed > + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) > + test_cycle['pct'][frame_size] = float('%.3f' % pct) > > self.dut.send_expect("stop", "testpmd> ") > self.dut.send_expect("quit", "# ", 30) > @@ -173,16 +221,16 @@ class TestPmd(TestCase,IxiaPacketGenerator): > > # Print results > self.result_table_create(self.table_header) > + self.perf_results['header'] = self.table_header > > for frame_size in self.frame_sizes: > table_row = [frame_size] > - > for test_cycle in self.test_cycles: > - table_row.append("testpmd") > table_row.append(test_cycle['Mpps'][frame_size]) > table_row.append(test_cycle['pct'][frame_size]) > > self.result_table_add(table_row) > + self.perf_results['data'].append(table_row) > > self.result_table_print() > > @@ -241,10 +289,10 @@ class TestPmd(TestCase,IxiaPacketGenerator): > # run traffic generator > _, pps = > self.tester.traffic_generator_throughput(tgen_input, rate_percent=100, > delay=60) > > - > pps /= 1000000.0 > - test_cycle['Mpps'][frame_size] = pps > - test_cycle['pct'][frame_size] = pps * 100 / wirespeed > + pct = pps * 100 / wirespeed > + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) > + test_cycle['pct'][frame_size] = float('%.3f' % pct) > > self.dut.send_expect("stop", "testpmd> ") > self.dut.send_expect("quit", "# ", 30) > @@ -257,14 +305,15 @@ class TestPmd(TestCase,IxiaPacketGenerator): > > # Print results > self.result_table_create(self.table_header) > + self.perf_results['header'] = self.table_header > for frame_size in self.frame_sizes: > table_row = [frame_size] > for test_cycle in self.test_cycles: > - table_row.append("testpmd") > table_row.append(test_cycle['Mpps'][frame_size]) > table_row.append(test_cycle['pct'][frame_size]) > > self.result_table_add(table_row) > + self.perf_results['data'].append(table_row) > > self.result_table_print() > > -- > 2.5.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [dts] [PATCH 1/2] support html report for nic performance result 2017-05-10 4:59 [dts] [PATCH 1/2] support html report for nic performance result Yulong Pei 2017-05-10 4:59 ` [dts] [PATCH 2/2] tests: support html report for single core performance test Yulong Pei @ 2017-05-11 5:42 ` Liu, Yong 2017-05-10 10:27 ` [dts] [PATCH v2 " Yulong Pei 2017-05-11 3:13 ` [dts] [PATCH v3 1/2] support html report for nic performance result Yulong Pei 1 sibling, 2 replies; 11+ messages in thread From: Liu, Yong @ 2017-05-11 5:42 UTC (permalink / raw) To: Pei, Yulong, dts; +Cc: Xu, Qian Q Thanks Yulong, some comments below. > -----Original Message----- > From: Pei, Yulong > Sent: Wednesday, May 10, 2017 1:00 PM > To: dts@dpdk.org > Cc: Xu, Qian Q <qian.q.xu@intel.com>; Liu, Yong <yong.liu@intel.com> > Subject: [PATCH 1/2] support html report for nic performance result > > support html report for nic performance result and support to send it > out by email. > > Signed-off-by: Yulong Pei <yulong.pei@intel.com> > --- > nics/perf_report.jinja | 82 +++++++++++++++++++++++++++++++++++++++++ > nics/perf_report.py | 79 ++++++++++++++++++++++++++++++++++++++++ > nics/system_info.py | 99 > ++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 260 insertions(+) > create mode 100644 nics/perf_report.jinja > create mode 100644 nics/perf_report.py > create mode 100644 nics/system_info.py > > diff --git a/nics/perf_report.jinja b/nics/perf_report.jinja > new file mode 100644 > index 0000000..1a3f903 > --- /dev/null > +++ b/nics/perf_report.jinja > @@ -0,0 +1,82 @@ > +<!doctype html> > +<html lang="en"> > +<head> > +<meta charset="UTF-8" /> > +<title>{{ title }}</title> > +<style> > +table, th, td { > + border: 1px solid black; > + border-collapse: collapse; > +} > +th, td { > + padding: 5px; > + text-align: left; > + background-color: #33A1C9; > +} > +</style> > +</head> > + > +<body> > + > +<div id="dpdk_info"> > +<h2> DPDK Git Information </h2> > +<p> Branch: {{ git_info['branch'] }} </p> > +<p> commit: {{ git_info['commit'] }} </p> > +<p> Author: {{ git_info['author'] }} </p> > +<p> Date: {{ git_info['date'] }} </p> > +<p> Summary: {{ git_info['summary'] }} </p> > +</div> > + > +<div id="nic_info"> > + <h2>NIC Detail Information</h2> > + <table> > + <tr> > + <th>Item</th> > + <th>Description</th> > + </tr> > + {% for key in nic_infos %} > + <tr> > + <td>{{ key }}</td> > + <td>{{ nic_infos[key] }}</td> > + </tr> > + {% endfor %} > + </table> > +</div> > + > +<div id="test_result"> > + <h2>Test Result:</h2> > + <table> > + <tr> > + <th>Frame_size(bytes)</th> > + <th>Throughput(Mpps)</th> > + <th>Line rate%</th> > + </tr> > + {% for result in test_results %} > + <tr> > + <td>{{ result[0] }}</td> > + <td>{{ result[1] }}</td> > + <td>{{ result[2] }}</td> > + </tr> > + {% endfor %} > + </table> > +</div> > + > +<div id="system_info"> > + <h2>Hardware and Software Ingredients</h2> > + <table> > + <tr> > + <th>Item</th> > + <th>Description</th> > + </tr> > + {% for key in system_infos %} > + <tr> > + <td>{{ key }}</td> > + <td>{{ system_infos[key] }}</td> > + </tr> > + {% endfor %} > + </table> > +</div> > + > +</body> > + > +</html> > diff --git a/nics/perf_report.py b/nics/perf_report.py Yulong, please add copyright for each python file. > new file mode 100644 > index 0000000..2517a68 > --- /dev/null > +++ b/nics/perf_report.py > @@ -0,0 +1,79 @@ > +import os > +import time > +import re > + > +import jinja2 > +import smtplib > + > +from email.mime.text import MIMEText > +from email.mime.multipart import MIMEMultipart > +from collections import OrderedDict > +#install GitPython > +from git import Repo > +from system_info import SystemInfo > + > +def get_dpdk_git_info(repo_dir="/root/dpdk"): > + > + if not os.path.exists(repo_dir): > + return None > + > + commit = OrderedDict() > + > + git_repo = Repo(repo_dir) > + assert not git_repo.bare > + > + latest_commit = git_repo.active_branch.commit > + commit['branch'] = str(git_repo.active_branch) > + commit['commit'] = str(latest_commit) > + commit['author'] = latest_commit.author > + commit['date'] = time.ctime(latest_commit.authored_date) > + commit['summary'] = latest_commit.summary > + return commit > + > +def generate_html_report(file_tpl, perf_data, git_info, nic_info, > system_info): > + > + if not os.path.exists(file_tpl): > + return None > + > + templateLoader = jinja2.FileSystemLoader(searchpath = "/") > + templateEnv = jinja2.Environment(loader=templateLoader) > + template = templateEnv.get_template(file_tpl) > + > + templateVars = { "title" : "Daily Performance Test Report", \ > + "test_results" : perf_data, \ > + "system_infos" : system_info, \ > + "nic_infos" : nic_info, \ > + "git_info" : git_info \ > + } > + > + output = template.render(templateVars) > + return output > + > +#sender = 'zzz@intel.com' > +#mailto = ['xxx@intel.com', 'yyy@intel.com'] > +def html_message(sender, mailto, subject, html_msg): > + > + msg = MIMEMultipart('alternative') > + msg['From'] = sender > + msg['to'] = ";".join(mailto) > + msg['Subject'] = subject > + > + msg.attach(MIMEText(html_msg, 'html')) > + > + return msg > + > +#smtp = smtplib.SMTP('smtp.intel.com') > +def send_email(sender, mailto, message, smtp_server): > + > + try: > + smtp = smtplib.SMTP(smtp_server) > + smtp.sendmail(sender, mailto, message.as_string()) > + smtp.quit() > + print "OK to sent email." > + except Exception, e: > + print "Failed to send email " + str(e) Please use utils.red and utils.green for those failure and successful log. > + > +def send_html_report(sender, mailto, subject, html_msg, smtp_server): > + > + message = html_message(sender, mailto, subject, html_msg) > + send_email(sender, mailto, message, smtp_server) > diff --git a/nics/system_info.py b/nics/system_info.py > new file mode 100644 > index 0000000..a78c841 > --- /dev/null > +++ b/nics/system_info.py > @@ -0,0 +1,99 @@ > +#!/usr/bin/python > + > +import os > +import time > +import re > + > +from collections import OrderedDict > +#install GitPython > +from git import Repo > + > +class SystemInfo(object): > + > + def __init__(self, dut, pci_device_id): > + self.dut = dut > + self.pci_device_id = pci_device_id > + self.session = self.dut.session > + self.system_info = OrderedDict() > + self.nic_info = OrderedDict() > + > + def get_system_info(self): > + > + board = self.session.send_expect("dmidecode -s system-product- > name", "# ") > + self.system_info["Board"] = board > + > + processors = self.session.send_expect("dmidecode -s processor- > version", "# ") > + processor = processors.split('\r\n')[0] > + self.system_info["CPU"] = processor > + > + memories = self.session.send_expect("dmidecode -t memory", "]# ") > + channels, size, speed = self._strip_memory(memories) > + memory_info = "Total %d MBs in %d channels @ %s" %(size, > channels, speed) > + self.system_info["Memory"] = memory_info > + > + release = self.session.send_expect("lsb_release -d |awk -F':' > '{print $2}'", "# ") > + self.system_info["Operating system"] = release > + > + kernel = self.session.send_expect("uname -r", "# ") > + self.system_info["Linux kernel version"] = kernel > + > + gcc_info = self.session.send_expect("gcc --version", "# ") > + gcc = gcc_info.split('\r\n')[0] > + self.system_info["GCC version"] = gcc > + > + return self.system_info > + > + def _strip_memory(self, memories): > + """ > + Size: 8192 MB Locator: DIMM_A1 Speed: 2133 MHz > + """ > + s_regex = r"(\s+)Size: (\d+) MB" > + l_regex= r"(\s+)Locator: DIMM_(\w+)" > + speed_regex = r"(\s+)Speed: (.*)" > + size = "" > + locate = "" > + speed = "Unknown" > + memory_infos = [] > + memory_channel = set() > + lines = memories.split('\r\n') > + total_size = 0 > + for line in lines: > + m = re.match(s_regex, line) > + if m: > + size = m.group(2) > + l_m = re.match(l_regex, line) > + if l_m: > + locate = l_m.group(2) > + s_m = re.match(speed_regex, line) > + if s_m: > + speed = s_m.group(2) > + if speed != "Unknown": > + memory={"Size": size, "Locate": locate, "Speed": speed} > + memory_infos.append(memory) > + speed = "Unknown" > + total_size += int(size) > + memory_channel.add(locate[0]) > + > + return len(memory_channel), total_size, memory_infos[0]["Speed"] > + > + def get_nic_info(self): > + > + vendor = self.session.send_expect("cat > /sys/bus/pci/devices/%s/vendor" % self.pci_device_id, "# ") > + if "No such" in vendor: > + return None > + device = self.session.send_expect("cat > /sys/bus/pci/devices/%s/device" % self.pci_device_id, "# ") > + if "No such" in device: > + return None > + > + interface = self.session.send_expect("ls --color=never > /sys/bus/pci/devices/%s/net" % self.pci_device_id, "# ") > + if "No such" in interface: > + return None > + firmware = self.session.send_expect("ethtool -i %s | grep -- > color=never firmware |awk -F':' '{print $2}'" % interface, "# ") > + if "No such" in firmware: > + return None > + > + self.nic_info['nic_name'] = self.session.send_expect("lspci - > vmmks %s |grep -i ^device |awk -F':' '{print $2}'" % self.pci_device_id, > "# ") Please try to keep each line in 79 characters. > + self.nic_info['device_id'] = vendor[2:] + ':' + device[2:] > + self.nic_info['firmware-version'] = firmware > + return self.nic_info > + > -- > 2.5.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [dts] [PATCH v2 1/2] support html report for nic performance result 2017-05-11 5:42 ` [dts] [PATCH 1/2] support html report for nic performance result Liu, Yong @ 2017-05-10 10:27 ` Yulong Pei 2017-05-10 10:27 ` [dts] [PATCH v2 2/2] tests: support html report for single core performance test Yulong Pei 2017-05-11 3:13 ` [dts] [PATCH v3 1/2] support html report for nic performance result Yulong Pei 1 sibling, 1 reply; 11+ messages in thread From: Yulong Pei @ 2017-05-10 10:27 UTC (permalink / raw) To: dts; +Cc: qian.q.xu, yong.liu support html report for nic performance result and support to send it out by email. Signed-off-by: Yulong Pei <yulong.pei@intel.com> --- nics/perf_report.jinja | 82 ++++++++++++++++++++++++++++++ nics/perf_report.py | 111 +++++++++++++++++++++++++++++++++++++++++ nics/system_info.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100644 nics/perf_report.jinja create mode 100644 nics/perf_report.py create mode 100644 nics/system_info.py diff --git a/nics/perf_report.jinja b/nics/perf_report.jinja new file mode 100644 index 0000000..1a3f903 --- /dev/null +++ b/nics/perf_report.jinja @@ -0,0 +1,82 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="UTF-8" /> +<title>{{ title }}</title> +<style> +table, th, td { + border: 1px solid black; + border-collapse: collapse; +} +th, td { + padding: 5px; + text-align: left; + background-color: #33A1C9; +} +</style> +</head> + +<body> + +<div id="dpdk_info"> +<h2> DPDK Git Information </h2> +<p> Branch: {{ git_info['branch'] }} </p> +<p> commit: {{ git_info['commit'] }} </p> +<p> Author: {{ git_info['author'] }} </p> +<p> Date: {{ git_info['date'] }} </p> +<p> Summary: {{ git_info['summary'] }} </p> +</div> + +<div id="nic_info"> + <h2>NIC Detail Information</h2> + <table> + <tr> + <th>Item</th> + <th>Description</th> + </tr> + {% for key in nic_infos %} + <tr> + <td>{{ key }}</td> + <td>{{ nic_infos[key] }}</td> + </tr> + {% endfor %} + </table> +</div> + +<div id="test_result"> + <h2>Test Result:</h2> + <table> + <tr> + <th>Frame_size(bytes)</th> + <th>Throughput(Mpps)</th> + <th>Line rate%</th> + </tr> + {% for result in test_results %} + <tr> + <td>{{ result[0] }}</td> + <td>{{ result[1] }}</td> + <td>{{ result[2] }}</td> + </tr> + {% endfor %} + </table> +</div> + +<div id="system_info"> + <h2>Hardware and Software Ingredients</h2> + <table> + <tr> + <th>Item</th> + <th>Description</th> + </tr> + {% for key in system_infos %} + <tr> + <td>{{ key }}</td> + <td>{{ system_infos[key] }}</td> + </tr> + {% endfor %} + </table> +</div> + +</body> + +</html> diff --git a/nics/perf_report.py b/nics/perf_report.py new file mode 100644 index 0000000..6251a05 --- /dev/null +++ b/nics/perf_report.py @@ -0,0 +1,111 @@ +# 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 time +import re + +import jinja2 +import smtplib + +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from collections import OrderedDict +#install GitPython +from git import Repo +from system_info import SystemInfo +import utils + +def get_dpdk_git_info(repo_dir="/root/dpdk"): + + if not os.path.exists(repo_dir): + return None + + commit = OrderedDict() + + git_repo = Repo(repo_dir) + assert not git_repo.bare + + latest_commit = git_repo.active_branch.commit + commit['branch'] = str(git_repo.active_branch) + commit['commit'] = str(latest_commit) + commit['author'] = latest_commit.author + commit['date'] = time.ctime(latest_commit.authored_date) + commit['summary'] = latest_commit.summary + return commit + +def generate_html_report(file_tpl, perf_data, git_info, nic_info, system_info): + + if not os.path.exists(file_tpl): + return None + + templateLoader = jinja2.FileSystemLoader(searchpath = "/") + templateEnv = jinja2.Environment(loader=templateLoader) + template = templateEnv.get_template(file_tpl) + + templateVars = { "title" : "Daily Performance Test Report", \ + "test_results" : perf_data, \ + "system_infos" : system_info, \ + "nic_infos" : nic_info, \ + "git_info" : git_info \ + } + + output = template.render(templateVars) + return output + +#sender = 'zzz@intel.com' +#mailto = ['xxx@intel.com', 'yyy@intel.com'] +def html_message(sender, mailto, subject, html_msg): + + msg = MIMEMultipart('alternative') + msg['From'] = sender + msg['to'] = ";".join(mailto) + msg['Subject'] = subject + + msg.attach(MIMEText(html_msg, 'html')) + + return msg + +#smtp = smtplib.SMTP('smtp.intel.com') +def send_email(sender, mailto, message, smtp_server): + + try: + smtp = smtplib.SMTP(smtp_server) + smtp.sendmail(sender, mailto, message.as_string()) + smtp.quit() + print utils.GREEN("Email sent successfully.") + except Exception, e: + print utils.RED("Failed to send email " + str(e)) + +def send_html_report(sender, mailto, subject, html_msg, smtp_server): + + message = html_message(sender, mailto, subject, html_msg) + send_email(sender, mailto, message, smtp_server) diff --git a/nics/system_info.py b/nics/system_info.py new file mode 100644 index 0000000..1f473d8 --- /dev/null +++ b/nics/system_info.py @@ -0,0 +1,133 @@ +# 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 time +import re + +from collections import OrderedDict +#install GitPython +from git import Repo + +class SystemInfo(object): + + def __init__(self, dut, pci_device_id): + self.dut = dut + self.pci_device_id = pci_device_id + self.session = self.dut.session + self.system_info = OrderedDict() + self.nic_info = OrderedDict() + + def get_system_info(self): + + board = self.session.send_expect("dmidecode -s system-product-name", "# ") + self.system_info["Board"] = board + + processors = self.session.send_expect("dmidecode -s processor-version", "# ") + processor = processors.split('\r\n')[0] + self.system_info["CPU"] = processor + + memories = self.session.send_expect("dmidecode -t memory", "]# ") + channels, size, speed = self._strip_memory(memories) + memory_info = "Total %d MBs in %d channels @ %s" %(size, channels, speed) + self.system_info["Memory"] = memory_info + + release = self.session.send_expect("lsb_release -d |awk -F':' '{print $2}'", "# ") + self.system_info["Operating system"] = release + + kernel = self.session.send_expect("uname -r", "# ") + self.system_info["Linux kernel version"] = kernel + + gcc_info = self.session.send_expect("gcc --version", "# ") + gcc = gcc_info.split('\r\n')[0] + self.system_info["GCC version"] = gcc + + return self.system_info + + def _strip_memory(self, memories): + """ + Size: 8192 MB Locator: DIMM_A1 Speed: 2133 MHz + """ + s_regex = r"(\s+)Size: (\d+) MB" + l_regex= r"(\s+)Locator: DIMM_(\w+)" + speed_regex = r"(\s+)Speed: (.*)" + size = "" + locate = "" + speed = "Unknown" + memory_infos = [] + memory_channel = set() + lines = memories.split('\r\n') + total_size = 0 + for line in lines: + m = re.match(s_regex, line) + if m: + size = m.group(2) + l_m = re.match(l_regex, line) + if l_m: + locate = l_m.group(2) + s_m = re.match(speed_regex, line) + if s_m: + speed = s_m.group(2) + if speed != "Unknown": + memory={"Size": size, "Locate": locate, "Speed": speed} + memory_infos.append(memory) + speed = "Unknown" + total_size += int(size) + memory_channel.add(locate[0]) + + return len(memory_channel), total_size, memory_infos[0]["Speed"] + + def get_nic_info(self): + + cmd = "cat /sys/bus/pci/devices/%s/vendor" % self.pci_device_id + vendor = self.session.send_expect(cmd, "# ") + if "No such" in vendor: + return None + + cmd = "cat /sys/bus/pci/devices/%s/device" % self.pci_device_id + device = self.session.send_expect(cmd, "# ") + if "No such" in device: + return None + + cmd = "ls --color=never /sys/bus/pci/devices/%s/net" % self.pci_device_id + interface = self.session.send_expect(cmd, "# ") + if "No such" in interface: + return None + cmd = "ethtool -i %s | grep --color=never firmware |awk -F':' '{print $2}'" % interface + firmware = self.session.send_expect(cmd, "# ") + if "No such" in firmware: + return None + cmd = "lspci -vmmks %s |grep -i ^device |awk -F':' '{print $2}'" % self.pci_device_id + self.nic_info['nic_name'] = self.session.send_expect(cmd, "# ") + self.nic_info['device_id'] = vendor[2:] + ':' + device[2:] + self.nic_info['firmware-version'] = firmware + return self.nic_info + -- 2.5.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [dts] [PATCH v2 2/2] tests: support html report for single core performance test 2017-05-10 10:27 ` [dts] [PATCH v2 " Yulong Pei @ 2017-05-10 10:27 ` Yulong Pei 0 siblings, 0 replies; 11+ messages in thread From: Yulong Pei @ 2017-05-10 10:27 UTC (permalink / raw) To: dts; +Cc: qian.q.xu, yong.liu support html report for single core performance test. Signed-off-by: Yulong Pei <yulong.pei@intel.com> --- tests/TestSuite_pmd.py | 70 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/tests/TestSuite_pmd.py b/tests/TestSuite_pmd.py index 2d5b485..8f4b22c 100644 --- a/tests/TestSuite_pmd.py +++ b/tests/TestSuite_pmd.py @@ -37,12 +37,20 @@ Test userland 10Gb PMD import utils import re import time +import os + from test_case import TestCase from time import sleep from settings import HEADER_SIZE from pmd_output import PmdOutput from etgen import IxiaPacketGenerator +from settings import FOLDERS +from system_info import SystemInfo +import perf_report +from datetime import datetime + + class TestPmd(TestCase,IxiaPacketGenerator): def set_up_all(self): @@ -53,7 +61,7 @@ class TestPmd(TestCase,IxiaPacketGenerator): """ self.tester.extend_external_packet_generator(TestPmd, self) - self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518] + self.frame_sizes = [64, 72, 128, 256, 512, 1024, 1280, 1518] self.rxfreet_values = [0, 8, 16, 32, 64, 128] @@ -62,10 +70,11 @@ class TestPmd(TestCase,IxiaPacketGenerator): self.table_header = ['Frame Size'] for test_cycle in self.test_cycles: - self.table_header.append("app") self.table_header.append("%s Mpps" % test_cycle['cores']) self.table_header.append("% linerate") + self.perf_results = {'header': [], 'data': []} + self.blacklist = "" # Update config file and rebuild to get best perf on FVL @@ -75,6 +84,19 @@ class TestPmd(TestCase,IxiaPacketGenerator): # Based on h/w type, choose how many ports to use self.dut_ports = self.dut.get_ports() + # Get dut system information + port_num = self.dut_ports[0] + pci_device_id = self.dut.ports_info[port_num]['pci'] + ori_driver = self.dut.ports_info[port_num]['port'].get_nic_driver() + self.dut.ports_info[port_num]['port'].bind_driver() + + sut = SystemInfo(self.dut, pci_device_id) + self.system_info = sut.get_system_info() + self.nic_info = sut.get_nic_info() + + self.dut.ports_info[port_num]['port'].bind_driver(ori_driver) + ###### + self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE[ 'ip'] + HEADER_SIZE['tcp'] @@ -92,12 +114,38 @@ class TestPmd(TestCase,IxiaPacketGenerator): """ Run single core performance """ + self.perf_results['header'] = [] + self.perf_results['data'] = [] + if len(self.dut_ports) >= 4: self.pmd_performance_4ports() else: self.verify(len(self.dut_ports) >= 2, "Insufficient ports for 2 ports performance test") self.pmd_performance_2ports() + #To replace False to True for if condition to send the result by email. + if False: + #it need place dpdk source git repo under dep directory. + repo_dir = FOLDERS["Depends"] + r'/dpdk' + git_info = perf_report.get_dpdk_git_info(repo_dir) + self.verify(git_info is not None, "get dpdk git repo error") + + tpl_path = FOLDERS["NicDriver"] + r'/perf_report.jinja' + file_tpl = os.path.abspath(tpl_path) + html_msg = perf_report.generate_html_report(file_tpl, \ + perf_data = self.perf_results['data'], \ + git_info = git_info, \ + nic_info = self.nic_info, \ + system_info = self.system_info) + self.verify(html_msg is not None, "generate html report error") + + subject = "Single core performance test with %d ports %s -- %s" % \ + (len(self.dut_ports), self.nic, datetime.now().strftime('%Y-%m-%d %H:%M')) + sender = 'xxxxxx@intel.com' + mailto = ['xxxxxx@intel.com'] + smtp_server = 'smtp.intel.com' + perf_report.send_html_report(sender, mailto, subject, html_msg, smtp_server) + def pmd_performance_4ports(self): """ PMD Performance Benchmarking with 4 ports. @@ -159,8 +207,9 @@ class TestPmd(TestCase,IxiaPacketGenerator): _, pps = self.tester.traffic_generator_throughput(tgen_input, rate_percent=100, delay=60) pps /= 1000000.0 - test_cycle['Mpps'][frame_size] = pps - test_cycle['pct'][frame_size] = pps * 100 / wirespeed + pct = pps * 100 / wirespeed + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) + test_cycle['pct'][frame_size] = float('%.3f' % pct) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) @@ -173,16 +222,16 @@ class TestPmd(TestCase,IxiaPacketGenerator): # Print results self.result_table_create(self.table_header) + self.perf_results['header'] = self.table_header for frame_size in self.frame_sizes: table_row = [frame_size] - for test_cycle in self.test_cycles: - table_row.append("testpmd") table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) self.result_table_add(table_row) + self.perf_results['data'].append(table_row) self.result_table_print() @@ -241,10 +290,10 @@ class TestPmd(TestCase,IxiaPacketGenerator): # run traffic generator _, pps = self.tester.traffic_generator_throughput(tgen_input, rate_percent=100, delay=60) - pps /= 1000000.0 - test_cycle['Mpps'][frame_size] = pps - test_cycle['pct'][frame_size] = pps * 100 / wirespeed + pct = pps * 100 / wirespeed + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) + test_cycle['pct'][frame_size] = float('%.3f' % pct) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) @@ -257,14 +306,15 @@ class TestPmd(TestCase,IxiaPacketGenerator): # Print results self.result_table_create(self.table_header) + self.perf_results['header'] = self.table_header for frame_size in self.frame_sizes: table_row = [frame_size] for test_cycle in self.test_cycles: - table_row.append("testpmd") table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) self.result_table_add(table_row) + self.perf_results['data'].append(table_row) self.result_table_print() -- 2.5.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [dts] [PATCH v3 1/2] support html report for nic performance result 2017-05-11 5:42 ` [dts] [PATCH 1/2] support html report for nic performance result Liu, Yong 2017-05-10 10:27 ` [dts] [PATCH v2 " Yulong Pei @ 2017-05-11 3:13 ` Yulong Pei 2017-05-11 3:13 ` [dts] [PATCH v3 2/2] tests: support html report for single core performance test Yulong Pei 2017-05-12 9:19 ` [dts] [PATCH v3 1/2] support html report for nic performance result Liu, Yong 1 sibling, 2 replies; 11+ messages in thread From: Yulong Pei @ 2017-05-11 3:13 UTC (permalink / raw) To: dts; +Cc: qian.q.xu, yong.liu support html report for nic performance result and support to send it out by email. Signed-off-by: Yulong Pei <yulong.pei@intel.com> --- nics/perf_report.jinja | 82 ++++++++++++++++++++++++++++++ nics/perf_report.py | 111 +++++++++++++++++++++++++++++++++++++++++ nics/system_info.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100644 nics/perf_report.jinja create mode 100644 nics/perf_report.py create mode 100644 nics/system_info.py diff --git a/nics/perf_report.jinja b/nics/perf_report.jinja new file mode 100644 index 0000000..1a3f903 --- /dev/null +++ b/nics/perf_report.jinja @@ -0,0 +1,82 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="UTF-8" /> +<title>{{ title }}</title> +<style> +table, th, td { + border: 1px solid black; + border-collapse: collapse; +} +th, td { + padding: 5px; + text-align: left; + background-color: #33A1C9; +} +</style> +</head> + +<body> + +<div id="dpdk_info"> +<h2> DPDK Git Information </h2> +<p> Branch: {{ git_info['branch'] }} </p> +<p> commit: {{ git_info['commit'] }} </p> +<p> Author: {{ git_info['author'] }} </p> +<p> Date: {{ git_info['date'] }} </p> +<p> Summary: {{ git_info['summary'] }} </p> +</div> + +<div id="nic_info"> + <h2>NIC Detail Information</h2> + <table> + <tr> + <th>Item</th> + <th>Description</th> + </tr> + {% for key in nic_infos %} + <tr> + <td>{{ key }}</td> + <td>{{ nic_infos[key] }}</td> + </tr> + {% endfor %} + </table> +</div> + +<div id="test_result"> + <h2>Test Result:</h2> + <table> + <tr> + <th>Frame_size(bytes)</th> + <th>Throughput(Mpps)</th> + <th>Line rate%</th> + </tr> + {% for result in test_results %} + <tr> + <td>{{ result[0] }}</td> + <td>{{ result[1] }}</td> + <td>{{ result[2] }}</td> + </tr> + {% endfor %} + </table> +</div> + +<div id="system_info"> + <h2>Hardware and Software Ingredients</h2> + <table> + <tr> + <th>Item</th> + <th>Description</th> + </tr> + {% for key in system_infos %} + <tr> + <td>{{ key }}</td> + <td>{{ system_infos[key] }}</td> + </tr> + {% endfor %} + </table> +</div> + +</body> + +</html> diff --git a/nics/perf_report.py b/nics/perf_report.py new file mode 100644 index 0000000..e833d6c --- /dev/null +++ b/nics/perf_report.py @@ -0,0 +1,111 @@ +# 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 time +import re + +import jinja2 +import smtplib + +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from collections import OrderedDict +#install GitPython +from git import Repo +from system_info import SystemInfo +import utils + +def get_dpdk_git_info(repo_dir="/root/dpdk"): + + if not os.path.exists(repo_dir): + return None + + commit = OrderedDict() + + git_repo = Repo(repo_dir) + assert not git_repo.bare + + latest_commit = git_repo.active_branch.commit + commit['branch'] = str(git_repo.active_branch) + commit['commit'] = str(latest_commit) + commit['author'] = latest_commit.author + commit['date'] = time.ctime(latest_commit.authored_date) + commit['summary'] = latest_commit.summary + return commit + +def generate_html_report(file_tpl, perf_data, git_info, nic_info, system_info): + + if not os.path.exists(file_tpl): + return None + + templateLoader = jinja2.FileSystemLoader(searchpath = "/") + templateEnv = jinja2.Environment(loader=templateLoader) + template = templateEnv.get_template(file_tpl) + + templateVars = { "title" : "Daily Performance Test Report", \ + "test_results" : perf_data, \ + "system_infos" : system_info, \ + "nic_infos" : nic_info, \ + "git_info" : git_info \ + } + + output = template.render(templateVars) + return output + +#sender = 'zzz@intel.com' +#mailto = ['xxx@intel.com', 'yyy@intel.com'] +def html_message(sender, mailto, subject, html_msg): + + msg = MIMEMultipart('alternative') + msg['From'] = sender + msg['to'] = ";".join(mailto) + msg['Subject'] = subject + + msg.attach(MIMEText(html_msg, 'html')) + + return msg + +#smtp = smtplib.SMTP('smtp.intel.com') +def send_email(sender, mailto, message, smtp_server): + + try: + smtp = smtplib.SMTP(smtp_server) + smtp.sendmail(sender, mailto, message.as_string()) + smtp.quit() + print utils.GREEN("Email sent successfully.") + except Exception, e: + print utils.RED("Failed to send email " + str(e)) + +def send_html_report(sender, mailto, subject, html_msg, smtp_server): + + message = html_message(sender, mailto, subject, html_msg) + send_email(sender, mailto, message, smtp_server) diff --git a/nics/system_info.py b/nics/system_info.py new file mode 100644 index 0000000..1f473d8 --- /dev/null +++ b/nics/system_info.py @@ -0,0 +1,133 @@ +# 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 time +import re + +from collections import OrderedDict +#install GitPython +from git import Repo + +class SystemInfo(object): + + def __init__(self, dut, pci_device_id): + self.dut = dut + self.pci_device_id = pci_device_id + self.session = self.dut.session + self.system_info = OrderedDict() + self.nic_info = OrderedDict() + + def get_system_info(self): + + board = self.session.send_expect("dmidecode -s system-product-name", "# ") + self.system_info["Board"] = board + + processors = self.session.send_expect("dmidecode -s processor-version", "# ") + processor = processors.split('\r\n')[0] + self.system_info["CPU"] = processor + + memories = self.session.send_expect("dmidecode -t memory", "]# ") + channels, size, speed = self._strip_memory(memories) + memory_info = "Total %d MBs in %d channels @ %s" %(size, channels, speed) + self.system_info["Memory"] = memory_info + + release = self.session.send_expect("lsb_release -d |awk -F':' '{print $2}'", "# ") + self.system_info["Operating system"] = release + + kernel = self.session.send_expect("uname -r", "# ") + self.system_info["Linux kernel version"] = kernel + + gcc_info = self.session.send_expect("gcc --version", "# ") + gcc = gcc_info.split('\r\n')[0] + self.system_info["GCC version"] = gcc + + return self.system_info + + def _strip_memory(self, memories): + """ + Size: 8192 MB Locator: DIMM_A1 Speed: 2133 MHz + """ + s_regex = r"(\s+)Size: (\d+) MB" + l_regex= r"(\s+)Locator: DIMM_(\w+)" + speed_regex = r"(\s+)Speed: (.*)" + size = "" + locate = "" + speed = "Unknown" + memory_infos = [] + memory_channel = set() + lines = memories.split('\r\n') + total_size = 0 + for line in lines: + m = re.match(s_regex, line) + if m: + size = m.group(2) + l_m = re.match(l_regex, line) + if l_m: + locate = l_m.group(2) + s_m = re.match(speed_regex, line) + if s_m: + speed = s_m.group(2) + if speed != "Unknown": + memory={"Size": size, "Locate": locate, "Speed": speed} + memory_infos.append(memory) + speed = "Unknown" + total_size += int(size) + memory_channel.add(locate[0]) + + return len(memory_channel), total_size, memory_infos[0]["Speed"] + + def get_nic_info(self): + + cmd = "cat /sys/bus/pci/devices/%s/vendor" % self.pci_device_id + vendor = self.session.send_expect(cmd, "# ") + if "No such" in vendor: + return None + + cmd = "cat /sys/bus/pci/devices/%s/device" % self.pci_device_id + device = self.session.send_expect(cmd, "# ") + if "No such" in device: + return None + + cmd = "ls --color=never /sys/bus/pci/devices/%s/net" % self.pci_device_id + interface = self.session.send_expect(cmd, "# ") + if "No such" in interface: + return None + cmd = "ethtool -i %s | grep --color=never firmware |awk -F':' '{print $2}'" % interface + firmware = self.session.send_expect(cmd, "# ") + if "No such" in firmware: + return None + cmd = "lspci -vmmks %s |grep -i ^device |awk -F':' '{print $2}'" % self.pci_device_id + self.nic_info['nic_name'] = self.session.send_expect(cmd, "# ") + self.nic_info['device_id'] = vendor[2:] + ':' + device[2:] + self.nic_info['firmware-version'] = firmware + return self.nic_info + -- 2.5.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [dts] [PATCH v3 2/2] tests: support html report for single core performance test 2017-05-11 3:13 ` [dts] [PATCH v3 1/2] support html report for nic performance result Yulong Pei @ 2017-05-11 3:13 ` Yulong Pei 2017-05-12 3:03 ` Xu, Qian Q 2017-05-12 9:19 ` [dts] [PATCH v3 1/2] support html report for nic performance result Liu, Yong 1 sibling, 1 reply; 11+ messages in thread From: Yulong Pei @ 2017-05-11 3:13 UTC (permalink / raw) To: dts; +Cc: qian.q.xu, yong.liu support html report for single core performance test. Signed-off-by: Yulong Pei <yulong.pei@intel.com> --- tests/TestSuite_pmd.py | 70 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/tests/TestSuite_pmd.py b/tests/TestSuite_pmd.py index 2d5b485..8f4b22c 100644 --- a/tests/TestSuite_pmd.py +++ b/tests/TestSuite_pmd.py @@ -37,12 +37,20 @@ Test userland 10Gb PMD import utils import re import time +import os + from test_case import TestCase from time import sleep from settings import HEADER_SIZE from pmd_output import PmdOutput from etgen import IxiaPacketGenerator +from settings import FOLDERS +from system_info import SystemInfo +import perf_report +from datetime import datetime + + class TestPmd(TestCase,IxiaPacketGenerator): def set_up_all(self): @@ -53,7 +61,7 @@ class TestPmd(TestCase,IxiaPacketGenerator): """ self.tester.extend_external_packet_generator(TestPmd, self) - self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518] + self.frame_sizes = [64, 72, 128, 256, 512, 1024, 1280, 1518] self.rxfreet_values = [0, 8, 16, 32, 64, 128] @@ -62,10 +70,11 @@ class TestPmd(TestCase,IxiaPacketGenerator): self.table_header = ['Frame Size'] for test_cycle in self.test_cycles: - self.table_header.append("app") self.table_header.append("%s Mpps" % test_cycle['cores']) self.table_header.append("% linerate") + self.perf_results = {'header': [], 'data': []} + self.blacklist = "" # Update config file and rebuild to get best perf on FVL @@ -75,6 +84,19 @@ class TestPmd(TestCase,IxiaPacketGenerator): # Based on h/w type, choose how many ports to use self.dut_ports = self.dut.get_ports() + # Get dut system information + port_num = self.dut_ports[0] + pci_device_id = self.dut.ports_info[port_num]['pci'] + ori_driver = self.dut.ports_info[port_num]['port'].get_nic_driver() + self.dut.ports_info[port_num]['port'].bind_driver() + + sut = SystemInfo(self.dut, pci_device_id) + self.system_info = sut.get_system_info() + self.nic_info = sut.get_nic_info() + + self.dut.ports_info[port_num]['port'].bind_driver(ori_driver) + ###### + self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE[ 'ip'] + HEADER_SIZE['tcp'] @@ -92,12 +114,38 @@ class TestPmd(TestCase,IxiaPacketGenerator): """ Run single core performance """ + self.perf_results['header'] = [] + self.perf_results['data'] = [] + if len(self.dut_ports) >= 4: self.pmd_performance_4ports() else: self.verify(len(self.dut_ports) >= 2, "Insufficient ports for 2 ports performance test") self.pmd_performance_2ports() + #To replace False to True for if condition to send the result by email. + if False: + #it need place dpdk source git repo under dep directory. + repo_dir = FOLDERS["Depends"] + r'/dpdk' + git_info = perf_report.get_dpdk_git_info(repo_dir) + self.verify(git_info is not None, "get dpdk git repo error") + + tpl_path = FOLDERS["NicDriver"] + r'/perf_report.jinja' + file_tpl = os.path.abspath(tpl_path) + html_msg = perf_report.generate_html_report(file_tpl, \ + perf_data = self.perf_results['data'], \ + git_info = git_info, \ + nic_info = self.nic_info, \ + system_info = self.system_info) + self.verify(html_msg is not None, "generate html report error") + + subject = "Single core performance test with %d ports %s -- %s" % \ + (len(self.dut_ports), self.nic, datetime.now().strftime('%Y-%m-%d %H:%M')) + sender = 'xxxxxx@intel.com' + mailto = ['xxxxxx@intel.com'] + smtp_server = 'smtp.intel.com' + perf_report.send_html_report(sender, mailto, subject, html_msg, smtp_server) + def pmd_performance_4ports(self): """ PMD Performance Benchmarking with 4 ports. @@ -159,8 +207,9 @@ class TestPmd(TestCase,IxiaPacketGenerator): _, pps = self.tester.traffic_generator_throughput(tgen_input, rate_percent=100, delay=60) pps /= 1000000.0 - test_cycle['Mpps'][frame_size] = pps - test_cycle['pct'][frame_size] = pps * 100 / wirespeed + pct = pps * 100 / wirespeed + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) + test_cycle['pct'][frame_size] = float('%.3f' % pct) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) @@ -173,16 +222,16 @@ class TestPmd(TestCase,IxiaPacketGenerator): # Print results self.result_table_create(self.table_header) + self.perf_results['header'] = self.table_header for frame_size in self.frame_sizes: table_row = [frame_size] - for test_cycle in self.test_cycles: - table_row.append("testpmd") table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) self.result_table_add(table_row) + self.perf_results['data'].append(table_row) self.result_table_print() @@ -241,10 +290,10 @@ class TestPmd(TestCase,IxiaPacketGenerator): # run traffic generator _, pps = self.tester.traffic_generator_throughput(tgen_input, rate_percent=100, delay=60) - pps /= 1000000.0 - test_cycle['Mpps'][frame_size] = pps - test_cycle['pct'][frame_size] = pps * 100 / wirespeed + pct = pps * 100 / wirespeed + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) + test_cycle['pct'][frame_size] = float('%.3f' % pct) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) @@ -257,14 +306,15 @@ class TestPmd(TestCase,IxiaPacketGenerator): # Print results self.result_table_create(self.table_header) + self.perf_results['header'] = self.table_header for frame_size in self.frame_sizes: table_row = [frame_size] for test_cycle in self.test_cycles: - table_row.append("testpmd") table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) self.result_table_add(table_row) + self.perf_results['data'].append(table_row) self.result_table_print() -- 2.5.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [dts] [PATCH v3 2/2] tests: support html report for single core performance test 2017-05-11 3:13 ` [dts] [PATCH v3 2/2] tests: support html report for single core performance test Yulong Pei @ 2017-05-12 3:03 ` Xu, Qian Q 2017-05-12 5:35 ` Pei, Yulong 0 siblings, 1 reply; 11+ messages in thread From: Xu, Qian Q @ 2017-05-12 3:03 UTC (permalink / raw) To: Pei, Yulong, dts; +Cc: Liu, Yong, Xu, Qian Q Yulong Some comments: 1. Could we add different RXD/TXD check? 512,1024,2048,4096 2. Maybe we can only keep 64, 72 Bytes for daily test, only in release performance test, we need test all packet sizes. 3. Do you cover 2ports(40G) test case for the single core? As to the single core test 1. If it's for per patch set performance test, I think 64/72 packet size is enough, different RXD/TXD configurations. 2. If to figure out the single core performance, we need do a full check. Maybe not need automate these, but need check full FVL40Gx2, NNT10Gx4, FVL10Gx4 NDR--zero packet loss, which RXD/TXD is best recommended. PDR--0.5% packet loss, which RXD/TXD is best recommended. Allowed drops 1q/port, 2q/port for FVL40G, NNT10G for both NDR and Allowed drops > -----Original Message----- > From: Pei, Yulong > Sent: Thursday, May 11, 2017 11:14 AM > To: dts@dpdk.org > Cc: Xu, Qian Q <qian.q.xu@intel.com>; Liu, Yong <yong.liu@intel.com> > Subject: [PATCH v3 2/2] tests: support html report for single core performance > test > > support html report for single core performance test. > > Signed-off-by: Yulong Pei <yulong.pei@intel.com> > --- > tests/TestSuite_pmd.py | 70 > ++++++++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 60 insertions(+), 10 deletions(-) > > diff --git a/tests/TestSuite_pmd.py b/tests/TestSuite_pmd.py index > 2d5b485..8f4b22c 100644 > --- a/tests/TestSuite_pmd.py > +++ b/tests/TestSuite_pmd.py > @@ -37,12 +37,20 @@ Test userland 10Gb PMD import utils import re import > time > +import os > + > from test_case import TestCase > from time import sleep > from settings import HEADER_SIZE > from pmd_output import PmdOutput > from etgen import IxiaPacketGenerator > > +from settings import FOLDERS > +from system_info import SystemInfo > +import perf_report > +from datetime import datetime > + > + > class TestPmd(TestCase,IxiaPacketGenerator): > > def set_up_all(self): > @@ -53,7 +61,7 @@ class TestPmd(TestCase,IxiaPacketGenerator): > """ > self.tester.extend_external_packet_generator(TestPmd, self) > > - self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518] > + self.frame_sizes = [64, 72, 128, 256, 512, 1024, 1280, 1518] > > self.rxfreet_values = [0, 8, 16, 32, 64, 128] > > @@ -62,10 +70,11 @@ class TestPmd(TestCase,IxiaPacketGenerator): > > self.table_header = ['Frame Size'] > for test_cycle in self.test_cycles: > - self.table_header.append("app") > self.table_header.append("%s Mpps" % test_cycle['cores']) > self.table_header.append("% linerate") > > + self.perf_results = {'header': [], 'data': []} > + > self.blacklist = "" > > # Update config file and rebuild to get best perf on FVL @@ -75,6 +84,19 > @@ class TestPmd(TestCase,IxiaPacketGenerator): > # Based on h/w type, choose how many ports to use > self.dut_ports = self.dut.get_ports() > > + # Get dut system information > + port_num = self.dut_ports[0] > + pci_device_id = self.dut.ports_info[port_num]['pci'] > + ori_driver = self.dut.ports_info[port_num]['port'].get_nic_driver() > + self.dut.ports_info[port_num]['port'].bind_driver() > + > + sut = SystemInfo(self.dut, pci_device_id) > + self.system_info = sut.get_system_info() > + self.nic_info = sut.get_nic_info() > + > + self.dut.ports_info[port_num]['port'].bind_driver(ori_driver) > + ###### > + > self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE[ > 'ip'] + HEADER_SIZE['tcp'] > > @@ -92,12 +114,38 @@ class TestPmd(TestCase,IxiaPacketGenerator): > """ > Run single core performance > """ > + self.perf_results['header'] = [] > + self.perf_results['data'] = [] > + > if len(self.dut_ports) >= 4: > self.pmd_performance_4ports() > else: > self.verify(len(self.dut_ports) >= 2, "Insufficient ports for 2 ports > performance test") > self.pmd_performance_2ports() > > + #To replace False to True for if condition to send the result by email. > + if False: > + #it need place dpdk source git repo under dep directory. > + repo_dir = FOLDERS["Depends"] + r'/dpdk' > + git_info = perf_report.get_dpdk_git_info(repo_dir) > + self.verify(git_info is not None, "get dpdk git repo > + error") > + > + tpl_path = FOLDERS["NicDriver"] + r'/perf_report.jinja' > + file_tpl = os.path.abspath(tpl_path) > + html_msg = perf_report.generate_html_report(file_tpl, \ > + perf_data = self.perf_results['data'], \ > + git_info = git_info, \ > + nic_info = self.nic_info, \ > + system_info = self.system_info) > + self.verify(html_msg is not None, "generate html report > + error") > + > + subject = "Single core performance test with %d ports %s -- %s" % \ > + (len(self.dut_ports), self.nic, datetime.now().strftime('%Y-%m- > %d %H:%M')) > + sender = 'xxxxxx@intel.com' > + mailto = ['xxxxxx@intel.com'] > + smtp_server = 'smtp.intel.com' > + perf_report.send_html_report(sender, mailto, subject, > + html_msg, smtp_server) > + > def pmd_performance_4ports(self): > """ > PMD Performance Benchmarking with 4 ports. > @@ -159,8 +207,9 @@ class TestPmd(TestCase,IxiaPacketGenerator): > _, pps = self.tester.traffic_generator_throughput(tgen_input, > rate_percent=100, delay=60) > > pps /= 1000000.0 > - test_cycle['Mpps'][frame_size] = pps > - test_cycle['pct'][frame_size] = pps * 100 / wirespeed > + pct = pps * 100 / wirespeed > + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) > + test_cycle['pct'][frame_size] = float('%.3f' % pct) > > self.dut.send_expect("stop", "testpmd> ") > self.dut.send_expect("quit", "# ", 30) @@ -173,16 +222,16 @@ class > TestPmd(TestCase,IxiaPacketGenerator): > > # Print results > self.result_table_create(self.table_header) > + self.perf_results['header'] = self.table_header > > for frame_size in self.frame_sizes: > table_row = [frame_size] > - > for test_cycle in self.test_cycles: > - table_row.append("testpmd") > table_row.append(test_cycle['Mpps'][frame_size]) > table_row.append(test_cycle['pct'][frame_size]) > > self.result_table_add(table_row) > + self.perf_results['data'].append(table_row) > > self.result_table_print() > > @@ -241,10 +290,10 @@ class TestPmd(TestCase,IxiaPacketGenerator): > # run traffic generator > _, pps = self.tester.traffic_generator_throughput(tgen_input, > rate_percent=100, delay=60) > > - > pps /= 1000000.0 > - test_cycle['Mpps'][frame_size] = pps > - test_cycle['pct'][frame_size] = pps * 100 / wirespeed > + pct = pps * 100 / wirespeed > + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) > + test_cycle['pct'][frame_size] = float('%.3f' % pct) > > self.dut.send_expect("stop", "testpmd> ") > self.dut.send_expect("quit", "# ", 30) @@ -257,14 +306,15 @@ class > TestPmd(TestCase,IxiaPacketGenerator): > > # Print results > self.result_table_create(self.table_header) > + self.perf_results['header'] = self.table_header > for frame_size in self.frame_sizes: > table_row = [frame_size] > for test_cycle in self.test_cycles: > - table_row.append("testpmd") > table_row.append(test_cycle['Mpps'][frame_size]) > table_row.append(test_cycle['pct'][frame_size]) > > self.result_table_add(table_row) > + self.perf_results['data'].append(table_row) > > self.result_table_print() > > -- > 2.5.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [dts] [PATCH v3 2/2] tests: support html report for single core performance test 2017-05-12 3:03 ` Xu, Qian Q @ 2017-05-12 5:35 ` Pei, Yulong 0 siblings, 0 replies; 11+ messages in thread From: Pei, Yulong @ 2017-05-12 5:35 UTC (permalink / raw) To: Xu, Qian Q, dts; +Cc: Liu, Yong Hi Qian, The requirement that you mentioned was in my todo list, This patch only to make the original TestSuite_pmd.py send test result by html report directly. Best Regards Yulong Pei -----Original Message----- From: Xu, Qian Q Sent: Friday, May 12, 2017 11:04 AM To: Pei, Yulong <yulong.pei@intel.com>; dts@dpdk.org Cc: Liu, Yong <yong.liu@intel.com>; Xu, Qian Q <qian.q.xu@intel.com> Subject: RE: [PATCH v3 2/2] tests: support html report for single core performance test Yulong Some comments: 1. Could we add different RXD/TXD check? 512,1024,2048,4096 2. Maybe we can only keep 64, 72 Bytes for daily test, only in release performance test, we need test all packet sizes. 3. Do you cover 2ports(40G) test case for the single core? As to the single core test 1. If it's for per patch set performance test, I think 64/72 packet size is enough, different RXD/TXD configurations. 2. If to figure out the single core performance, we need do a full check. Maybe not need automate these, but need check full FVL40Gx2, NNT10Gx4, FVL10Gx4 NDR--zero packet loss, which RXD/TXD is best recommended. PDR--0.5% packet loss, which RXD/TXD is best recommended. Allowed drops 1q/port, 2q/port for FVL40G, NNT10G for both NDR and Allowed drops > -----Original Message----- > From: Pei, Yulong > Sent: Thursday, May 11, 2017 11:14 AM > To: dts@dpdk.org > Cc: Xu, Qian Q <qian.q.xu@intel.com>; Liu, Yong <yong.liu@intel.com> > Subject: [PATCH v3 2/2] tests: support html report for single core performance > test > > support html report for single core performance test. > > Signed-off-by: Yulong Pei <yulong.pei@intel.com> > --- > tests/TestSuite_pmd.py | 70 > ++++++++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 60 insertions(+), 10 deletions(-) > > diff --git a/tests/TestSuite_pmd.py b/tests/TestSuite_pmd.py index > 2d5b485..8f4b22c 100644 > --- a/tests/TestSuite_pmd.py > +++ b/tests/TestSuite_pmd.py > @@ -37,12 +37,20 @@ Test userland 10Gb PMD import utils import re import > time > +import os > + > from test_case import TestCase > from time import sleep > from settings import HEADER_SIZE > from pmd_output import PmdOutput > from etgen import IxiaPacketGenerator > > +from settings import FOLDERS > +from system_info import SystemInfo > +import perf_report > +from datetime import datetime > + > + > class TestPmd(TestCase,IxiaPacketGenerator): > > def set_up_all(self): > @@ -53,7 +61,7 @@ class TestPmd(TestCase,IxiaPacketGenerator): > """ > self.tester.extend_external_packet_generator(TestPmd, self) > > - self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518] > + self.frame_sizes = [64, 72, 128, 256, 512, 1024, 1280, 1518] > > self.rxfreet_values = [0, 8, 16, 32, 64, 128] > > @@ -62,10 +70,11 @@ class TestPmd(TestCase,IxiaPacketGenerator): > > self.table_header = ['Frame Size'] > for test_cycle in self.test_cycles: > - self.table_header.append("app") > self.table_header.append("%s Mpps" % test_cycle['cores']) > self.table_header.append("% linerate") > > + self.perf_results = {'header': [], 'data': []} > + > self.blacklist = "" > > # Update config file and rebuild to get best perf on FVL @@ -75,6 +84,19 > @@ class TestPmd(TestCase,IxiaPacketGenerator): > # Based on h/w type, choose how many ports to use > self.dut_ports = self.dut.get_ports() > > + # Get dut system information > + port_num = self.dut_ports[0] > + pci_device_id = self.dut.ports_info[port_num]['pci'] > + ori_driver = self.dut.ports_info[port_num]['port'].get_nic_driver() > + self.dut.ports_info[port_num]['port'].bind_driver() > + > + sut = SystemInfo(self.dut, pci_device_id) > + self.system_info = sut.get_system_info() > + self.nic_info = sut.get_nic_info() > + > + self.dut.ports_info[port_num]['port'].bind_driver(ori_driver) > + ###### > + > self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE[ > 'ip'] + HEADER_SIZE['tcp'] > > @@ -92,12 +114,38 @@ class TestPmd(TestCase,IxiaPacketGenerator): > """ > Run single core performance > """ > + self.perf_results['header'] = [] > + self.perf_results['data'] = [] > + > if len(self.dut_ports) >= 4: > self.pmd_performance_4ports() > else: > self.verify(len(self.dut_ports) >= 2, "Insufficient ports for 2 ports > performance test") > self.pmd_performance_2ports() > > + #To replace False to True for if condition to send the result by email. > + if False: > + #it need place dpdk source git repo under dep directory. > + repo_dir = FOLDERS["Depends"] + r'/dpdk' > + git_info = perf_report.get_dpdk_git_info(repo_dir) > + self.verify(git_info is not None, "get dpdk git repo > + error") > + > + tpl_path = FOLDERS["NicDriver"] + r'/perf_report.jinja' > + file_tpl = os.path.abspath(tpl_path) > + html_msg = perf_report.generate_html_report(file_tpl, \ > + perf_data = self.perf_results['data'], \ > + git_info = git_info, \ > + nic_info = self.nic_info, \ > + system_info = self.system_info) > + self.verify(html_msg is not None, "generate html report > + error") > + > + subject = "Single core performance test with %d ports %s -- %s" % \ > + (len(self.dut_ports), self.nic, datetime.now().strftime('%Y-%m- > %d %H:%M')) > + sender = 'xxxxxx@intel.com' > + mailto = ['xxxxxx@intel.com'] > + smtp_server = 'smtp.intel.com' > + perf_report.send_html_report(sender, mailto, subject, > + html_msg, smtp_server) > + > def pmd_performance_4ports(self): > """ > PMD Performance Benchmarking with 4 ports. > @@ -159,8 +207,9 @@ class TestPmd(TestCase,IxiaPacketGenerator): > _, pps = self.tester.traffic_generator_throughput(tgen_input, > rate_percent=100, delay=60) > > pps /= 1000000.0 > - test_cycle['Mpps'][frame_size] = pps > - test_cycle['pct'][frame_size] = pps * 100 / wirespeed > + pct = pps * 100 / wirespeed > + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) > + test_cycle['pct'][frame_size] = float('%.3f' % pct) > > self.dut.send_expect("stop", "testpmd> ") > self.dut.send_expect("quit", "# ", 30) @@ -173,16 +222,16 @@ class > TestPmd(TestCase,IxiaPacketGenerator): > > # Print results > self.result_table_create(self.table_header) > + self.perf_results['header'] = self.table_header > > for frame_size in self.frame_sizes: > table_row = [frame_size] > - > for test_cycle in self.test_cycles: > - table_row.append("testpmd") > table_row.append(test_cycle['Mpps'][frame_size]) > table_row.append(test_cycle['pct'][frame_size]) > > self.result_table_add(table_row) > + self.perf_results['data'].append(table_row) > > self.result_table_print() > > @@ -241,10 +290,10 @@ class TestPmd(TestCase,IxiaPacketGenerator): > # run traffic generator > _, pps = self.tester.traffic_generator_throughput(tgen_input, > rate_percent=100, delay=60) > > - > pps /= 1000000.0 > - test_cycle['Mpps'][frame_size] = pps > - test_cycle['pct'][frame_size] = pps * 100 / wirespeed > + pct = pps * 100 / wirespeed > + test_cycle['Mpps'][frame_size] = float('%.3f' % pps) > + test_cycle['pct'][frame_size] = float('%.3f' % pct) > > self.dut.send_expect("stop", "testpmd> ") > self.dut.send_expect("quit", "# ", 30) @@ -257,14 +306,15 @@ class > TestPmd(TestCase,IxiaPacketGenerator): > > # Print results > self.result_table_create(self.table_header) > + self.perf_results['header'] = self.table_header > for frame_size in self.frame_sizes: > table_row = [frame_size] > for test_cycle in self.test_cycles: > - table_row.append("testpmd") > table_row.append(test_cycle['Mpps'][frame_size]) > table_row.append(test_cycle['pct'][frame_size]) > > self.result_table_add(table_row) > + self.perf_results['data'].append(table_row) > > self.result_table_print() > > -- > 2.5.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [dts] [PATCH v3 1/2] support html report for nic performance result 2017-05-11 3:13 ` [dts] [PATCH v3 1/2] support html report for nic performance result Yulong Pei 2017-05-11 3:13 ` [dts] [PATCH v3 2/2] tests: support html report for single core performance test Yulong Pei @ 2017-05-12 9:19 ` Liu, Yong 1 sibling, 0 replies; 11+ messages in thread From: Liu, Yong @ 2017-05-12 9:19 UTC (permalink / raw) To: Yulong Pei, dts; +Cc: qian.q.xu Thanks yulong. Applied in. On 05/11/2017 11:13 AM, Yulong Pei wrote: > support html report for nic performance result and support to send it > out by email. > > Signed-off-by: Yulong Pei<yulong.pei@intel.com> > --- > nics/perf_report.jinja | 82 ++++++++++++++++++++++++++++++ > nics/perf_report.py | 111 +++++++++++++++++++++++++++++++++++++++++ > nics/system_info.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 326 insertions(+) > create mode 100644 nics/perf_report.jinja > create mode 100644 nics/perf_report.py > create mode 100644 nics/system_info.py ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2017-05-12 9:31 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-05-10 4:59 [dts] [PATCH 1/2] support html report for nic performance result Yulong Pei 2017-05-10 4:59 ` [dts] [PATCH 2/2] tests: support html report for single core performance test Yulong Pei 2017-05-11 5:50 ` Liu, Yong 2017-05-11 5:42 ` [dts] [PATCH 1/2] support html report for nic performance result Liu, Yong 2017-05-10 10:27 ` [dts] [PATCH v2 " Yulong Pei 2017-05-10 10:27 ` [dts] [PATCH v2 2/2] tests: support html report for single core performance test Yulong Pei 2017-05-11 3:13 ` [dts] [PATCH v3 1/2] support html report for nic performance result Yulong Pei 2017-05-11 3:13 ` [dts] [PATCH v3 2/2] tests: support html report for single core performance test Yulong Pei 2017-05-12 3:03 ` Xu, Qian Q 2017-05-12 5:35 ` Pei, Yulong 2017-05-12 9:19 ` [dts] [PATCH v3 1/2] support html report for nic performance result Liu, Yong
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).