diff --git a/oec-hardware-1.1.4-fix-configip-dpdk.patch b/oec-hardware-1.1.4-fix-configip-dpdk.patch new file mode 100644 index 0000000000000000000000000000000000000000..c5432b31ed39e2f718e3b111625dd1accc13b443 --- /dev/null +++ b/oec-hardware-1.1.4-fix-configip-dpdk.patch @@ -0,0 +1,542 @@ +diff -Naur rpm/hwcompatible/compatibility.py oech/hwcompatible/compatibility.py +--- rpm/hwcompatible/compatibility.py 2023-02-28 17:56:07.000000000 +0800 ++++ oech/hwcompatible/compatibility.py 2023-06-13 23:26:19.339482340 +0800 +@@ -518,6 +518,17 @@ + self.test_factory.append(test) + self.logger.info("add %s test %s" % (test["name"], + test["device"].get_name())) ++ for index, test in enumerate(self.test_factory): ++ for test_new in test_factory: ++ if test["name"] != test_new["name"]: ++ continue ++ self_test_path = test["device"].path ++ new_test_path = test_new["device"].path ++ if not self_test_path and not new_test_path: ++ continue ++ if self_test_path == new_test_path: ++ self.test_factory[index]['device'] = test_new['device'] ++ + self.test_factory.sort(key=lambda k: k["name"]) + FactoryDocument(CertEnv.factoryfile, self.logger, self.test_factory).save() + +diff -Naur rpm/oec-hardware.spec oech/oec-hardware.spec +--- rpm/oec-hardware.spec 2023-02-28 17:59:44.000000000 +0800 ++++ oech/oec-hardware.spec 2023-06-13 23:26:19.339482340 +0800 +@@ -25,7 +25,7 @@ + Summary: openEuler Hardware Compatibility Test Server + Group: Development/Tools + Requires: python3, python3-devel, python3-flask, python3-uWSGI +-Requires: nginx, tar, qperf, psmisc ++Requires: nginx, tar, qperf, psmisc, dpdk, dpdk-tools, dpdk-devel + + %description + openEuler Hardware Compatibility Test Suite +@@ -75,7 +75,7 @@ + rm -rf /var/lock/oech.lock + + %changelog +-* Mon Feb 28 2023 cuixucui - 1.1.4-0 ++* Tue Feb 28 2023 cuixucui - 1.1.4-0 + 1. Add board information in the test report + 2. Add spdk test case + 3. Add dpdk test case +diff -Naur rpm/server/server.py oech/server/server.py +--- rpm/server/server.py 2023-02-28 17:56:07.000000000 +0800 ++++ oech/server/server.py 2023-06-13 23:26:19.343482340 +0800 +@@ -25,6 +25,7 @@ + from urllib.request import urlopen, Request + from urllib.error import HTTPError + from flask import Flask, render_template, redirect, url_for, abort, request, send_from_directory, flash ++from werkzeug import secure_filename + + app = Flask(__name__) + app.secret_key = os.urandom(24) +@@ -32,6 +33,7 @@ + dir_server = os.path.dirname(os.path.realpath(__file__)) + dir_results = os.path.join(dir_server, 'results') + dir_files = os.path.join(dir_server, 'files') ++DPDK_DRIVER = "uio_pci_generic" + + + @app.errorhandler(400) +@@ -98,9 +100,9 @@ + abort(404) + + try: +- with open(json_info, 'r') as file_content: ++ with open(secure_filename(json_info), 'r') as file_content: + info = json.load(file_content) +- with open(json_results, 'r') as file_content: ++ with open(secure_filename(json_results), 'r') as file_content: + results = json.load(file_content) + except json.decoder.JSONDecodeError as error: + sys.stderr.write("The file %s is not json file.\n") +@@ -125,7 +127,7 @@ + abort(404) + + try: +- with open(json_results, 'r') as file_content: ++ with open(secure_filename(json_results), 'r') as file_content: + results = json.load(file_content) + except json.decoder.JSONDecodeError as error: + sys.stderr.write("The file %s is not json file.\n") +@@ -154,7 +156,7 @@ + abort(404) + + try: +- with open(json_devices, 'r') as file_content: ++ with open(secure_filename(json_devices), 'r') as file_content: + devices = json.load(file_content) + except json.decoder.JSONDecodeError as error: + sys.stderr.write("The file %s is not json file.\n") +@@ -194,7 +196,7 @@ + if not os.path.exists(logpath): + logpath = os.path.join(dir_job, 'job.log') + +- with open(logpath, 'r') as file_content: ++ with open(secure_filename(logpath), 'r') as file_content: + log = file_content.read().split('\n') + + return render_template('log.html', host=host, id=oec_id, job=job, name=name, log=log) +@@ -217,14 +219,14 @@ + + cert = "" + try: +- with open(json_cert, 'r') as file_content: ++ with open(secure_filename(json_cert), 'r') as file_content: + cert = json.load(file_content) + except json.decoder.JSONDecodeError: + sys.stderr.write("The file %s is not json file.\n") + return False + + attachment = "" +- with open(tar_job, 'rb') as file_content: ++ with open(secure_filename(tar_job), 'rb') as file_content: + attachment = base64.b64encode(file_content.read()) + + form = {} +@@ -279,7 +281,7 @@ + os.makedirs(dir_job) + + tar_job = dir_job + '.tar' +- with open(tar_job, 'wb') as file_content: ++ with open(secure_filename(tar_job), 'wb') as file_content: + file_content.write(ori_file) + result = subprocess.getstatusoutput( + "tar xf '%s' -C '%s'" % (tar_job, os.path.dirname(dir_job))) +@@ -322,7 +324,7 @@ + if not os.path.exists(dir_files): + os.makedirs(dir_files) + +- with open(filepath, 'wb') as file_content: ++ with open(secure_filename(filepath), 'wb') as file_content: + file_content.write(base64.b64decode(filetext)) + + return render_template('upload.html', filename=filename, filetext=filetext, +@@ -356,31 +358,36 @@ + return render_template('index.html') + + ++@app.route('/api/get/ethpeer', methods=['GET', 'POST']) ++def get_ethpeer(): ++ """ ++ get ethpeer ++ """ ++ dic = {} ++ card_id = request.values.get('cardid', '') ++ __setting_dpdk_env() ++ interface = __get_server_port(card_id) ++ ethpeer = subprocess.getoutput("ip link show dev %s | grep 'link/ether' | awk '{print $2}'" % interface) ++ dic = {'ethpeer': ethpeer} ++ ++ return dic ++ ++ + @app.route('/api/bind/server', methods=['GET', 'POST']) + def bind_server_card(): + """ + Bind server card + """ +- __setting_dpdk_env() ++ interface = "" + card_id = request.values.get('cardid', '') +- dpdk_driver = "uio_pci_generic" +- ports = [] +- dic = {} +- ports = subprocess.getoutput("ip link show up | grep 'state UP' | awk -F ': ' '{print $2}'").split('\n') +- for pt in ports: +- pci_num = subprocess.getoutput("ethtool -i %s | grep 'bus-info' | awk '{print $2}'" % pt) +- quad = __get_quad(pci_num) +- if operator.eq(quad, eval(card_id)): +- ethpeer = subprocess.getoutput("cat /sys/class/net/%s/address" % pt) +- subprocess.getoutput("ip link set down %s" % pt) +- dic = {'ethpeer': ethpeer} +- cmd = subprocess.getstatusoutput("dpdk-devbind.py -b %s %s" % (dpdk_driver, pci_num)) +- if cmd[0] != 0: +- sys.stderr.write("Bind server card failed.\n") +- return False +- break ++ interface = __get_server_port(card_id) ++ pci_num = subprocess.getoutput("ethtool -i %s | grep 'bus-info' | awk '{print $2}'" % interface) ++ subprocess.getoutput("ip link set down %s" % interface) ++ cmd = subprocess.getstatusoutput("dpdk-devbind -b %s %s" % (DPDK_DRIVER, pci_num)) ++ if cmd[0] != 0: ++ sys.stderr.write("Bind server card failed.\n") + +- return dic ++ return render_template('index.html') + + + @app.route('/api/unbind/server', methods=['GET', 'POST']) +@@ -388,14 +395,13 @@ + """ + Unbind server card + """ +- dpdk_driver = "uio_pci_generic" + card_id = request.values.get('cardid', '') +- pci_num = subprocess.getoutput("dpdk-devbind.py -s | grep 'drv=%s' | awk '{print $1}'" % dpdk_driver) ++ pci_num = subprocess.getoutput("dpdk-devbind -s | grep 'drv=%s' | awk '{print $1}'" % DPDK_DRIVER) + quad = __get_quad(pci_num) + kernel_driver = subprocess.getoutput("lspci -s %s -v | grep 'Kernel modules' | awk '{print $3}'" % pci_num) + if operator.eq(quad, eval(card_id)): +- subprocess.getoutput("dpdk-devbind.py -b %s %s" % (kernel_driver, pci_num)) +- result = subprocess.getoutput(("dpdk-devbind.py -s | grep {0}").format(pci_num)) ++ subprocess.getoutput("dpdk-devbind -b %s %s" % (kernel_driver, pci_num)) ++ result = subprocess.getoutput(("dpdk-devbind -s | grep {0}").format(pci_num)) + interface = re.search(r'if=(\S*)', result).group(1) + subprocess.getoutput("ip link set up %s") % interface + +@@ -410,11 +416,13 @@ + valid_commands = ['rping', 'rcopy', 'ib_read_bw', + 'ib_write_bw', 'ib_send_bw', 'qperf', 'dpdk-testpmd'] + cmd = request.values.get('cmd', '') ++ pci_num = "" ++ interface = "" ++ card_id = request.values.get('cardid', '') + cmd = cmd.split() + if (not cmd) or (cmd[0] not in valid_commands + ['all']): + sys.stdout.write("Invalid command: {0}.\n".format(cmd)) + abort(400) +- + if act == 'start': + if cmd[0] == 'rping': + cmd = ['rping', '-s'] +@@ -428,11 +436,17 @@ + sys.stderr.write("No ibdev or ibport found.\n") + abort(400) + cmd.extend(['-d', ibdev, '-i', ibport]) +- if cmd[0] == 'dpdk-testpmd': +- result = subprocess.getstatusoutput("lspci | grep Mellanox") ++ if 'dpdk' in cmd[0]: ++ result = subprocess.getstatusoutput("dpdk-devbind -s | grep 'drv=%s'" % DPDK_DRIVER) + if result[0] == 0: ++ pci_num = subprocess.getoutput("dpdk-devbind -s | grep 'drv=%s' | awk '{print $1}'" % DPDK_DRIVER) ++ else: + __setting_dpdk_env() +- cmd = ['dpdk-testpmd', '-l', '8-15', '-n', '4', '--', '--forward-mode=rxonly'] ++ interface = __get_server_port(card_id) ++ pci_num = subprocess.getoutput("ethtool -i %s | grep 'bus-info' | awk '{print $2}'" ++ % interface) ++ cmd = ['dpdk-testpmd', '-l', '0-1', '-n', '1', '-a', pci_num, '--', '--forward-mode=rxonly'] ++ time.sleep(3) + __execute_cmd(cmd) + + elif act == 'stop': +@@ -447,6 +461,24 @@ + return render_template('index.html') + + ++def __get_server_port(card_id): ++ """ ++ get server interface ++ """ ++ ports = [] ++ interface = "" ++ ports = subprocess.getoutput("ip link show up | grep 'state UP' | awk -F ': ' '{print $2}'").split('\n') ++ for pt in ports: ++ pci_num = subprocess.getoutput("ethtool -i %s | grep 'bus-info' | awk '{print $2}'" % pt) ++ quad = __get_quad(pci_num) ++ if operator.eq(quad, eval(card_id)): ++ result = subprocess.getoutput(("dpdk-devbind -s | grep {0}").format(pci_num)) ++ interface = re.search(r'if=(\S*)', result).group(1) ++ break ++ ++ return interface ++ ++ + def __stop_process(process_name): + check_cmd = subprocess.getstatusoutput( + "ps -ef | grep %s | grep -v grep" % process_name) +@@ -457,7 +489,8 @@ + + + def __execute_cmd(cmd): +- pipe = subprocess.Popen(cmd) ++ pipe = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf8') + time.sleep(3) + if pipe.poll(): # supposed to be 0(foreground) or None(background) + abort(400) +@@ -511,9 +544,8 @@ + """ + Dpdk server environment setting + """ +- dpdk_driver = "uio_pci_generic" +- subprocess.getoutput("modprobe uio; modprobe %s" % dpdk_driver) +- if subprocess.getstatusoutput("lsmod | grep uio_pci_generic")[0] != 0: ++ subprocess.getoutput("modprobe uio; modprobe %s" % DPDK_DRIVER) ++ if subprocess.getstatusoutput("lsmod | grep %s" % DPDK_DRIVER)[0] != 0: + sys.stderr.write("Dpdk driver moprobe failed.\n") + return False + subprocess.getoutput("dpdk-hugepages.py -u") +diff -Naur rpm/tests/dpdk/dpdk.py oech/tests/dpdk/dpdk.py +--- rpm/tests/dpdk/dpdk.py 2023-02-28 17:56:07.000000000 +0800 ++++ oech/tests/dpdk/dpdk.py 2023-06-13 23:26:19.343482340 +0800 +@@ -39,16 +39,19 @@ + + def __init__(self): + Test.__init__(self) ++ self.requirements = ["dpdk", "dpdk-tools", "dpdk-devel"] + self.config_data = dict() + self.interface = None + self.server_ip = "" + self.server_port = 80 + self.portmask = "0xffff" + self.packet_size = 1514 +- self.support_driver = ['mlx4_core', 'mlx5_core', 'ixgbe', 'i40e', 'ice', 'hinic'] ++ self.support_driver = ['mlx4_core', 'mlx5_core', 'ixgbe', 'ice', 'hinic', 'igc'] + self.dpdk_driver = 'uio_pci_generic' + self.kernel_driver = None + self.retries = 3 ++ self.speed = 0 # Mb/s ++ self.target_bandwidth_percent = 0.8 + self.device = "" + self.pci = "" + self.card_id = None +@@ -78,6 +81,19 @@ + self.server_ip = CertDocument(CertEnv.certificationfile, self.logger).get_server() + self.test_prepare() + ++ def get_interface_speed(self): ++ """ ++ Get speed on the interface ++ :return: ++ """ ++ speed = self.command.run_cmd( ++ "ethtool %s | grep Speed | awk '{print $2}'" % self.interface) ++ if speed[2] != 0: ++ self.logger.error("No speed found on the interface.") ++ return 0 ++ ++ return int(speed[0][:-5]) ++ + def check_bind(self): + """ + Check whether binding card is required +@@ -90,17 +106,17 @@ + return False + else: + self.logger.info("DPDK driver is loading...") +- subprocess.getoutput("modprobe uio; modprobe uio_pci_generic") +- if self.command.run_cmd("lsmod | grep uio_pci_generic", terminal_print=True)[2] != 0: ++ subprocess.getoutput("modprobe uio; modprobe %s" % self.dpdk_driver) ++ if self.command.run_cmd("lsmod | grep %s" % self.dpdk_driver, terminal_print=True)[2] != 0: + self.logger.error("DPDK driver is loaded failed!") + return False + else: ++ self.logger.info("Get server card's ethpeer...") ++ if not self.get_ethpeer(): ++ return False + if self.kernel_driver == "mlx4_core" or self.kernel_driver == "mlx5_core": + self.logger.info("The mellanox network card does not need to be bound.") + self.command.run_cmd("modprobe -a ib_uverbs mlx5_core mlx5_ib mlx4_core", terminal_print=True) +- self.ethpeer = self.command.run_cmd("grep %s /proc/net/arp | awk '{print $4}'" % +- self.interface)[0].strip('\n') +- self.logger.info("The mac of the server card is %s" % self.ethpeer) + else: + self.logger.info("Server dpdk is binding...") + if not self.server_dpdk_bind(): +@@ -110,6 +126,32 @@ + return False + return True + ++ def get_ethpeer(self): ++ """ ++ Get ethpeer. ++ :return: ++ """ ++ form = {'serverip': self.server_ip, 'cardid': self.card_id} ++ url = 'http://{}:%s/api/get/ethpeer'.format(self.server_ip) % self.server_port ++ data = urlencode(form).encode('utf8') ++ headers = { ++ 'Content-type': 'application/x-www-form-urlencoded', ++ 'Accept': 'text/plain' ++ } ++ request = Request(url, data=data, headers=headers) ++ try: ++ response = urlopen(request) ++ except Exception: ++ self.logger.error("Call remote server url %s failed." % url) ++ return False ++ self.logger.info(str(response.headers), terminal_print=False) ++ self.ethpeer = json.loads(response.read())['ethpeer'] ++ self.logger.info("The mac of the server card is %s" % self.ethpeer) ++ self.logger.info("Status: %u %s" % (response.code, response.msg)) ++ if response.code != 200: ++ return False ++ return True ++ + def client_dpdk_bind(self): + """ + Bind client card with dpdk driver +@@ -149,8 +191,6 @@ + self.logger.error("Call remote server url %s failed." % url) + return False + self.logger.info(str(response.headers), terminal_print=False) +- self.ethpeer = json.loads(response.read())['ethpeer'] +- self.logger.info("The mac of the server card is %s" % self.ethpeer) + self.logger.info("Status: %u %s" % (response.code, response.msg)) + if response.code != 200: + return False +@@ -217,19 +257,18 @@ + Test speed + :return: + """ +- self.logger.info("Running dpdk speed test...", terminal_print=False) + command = [ + 'dpdk-testpmd', +- '-l', '8-15', +- '-n', '4', ++ '-l', '0-1', ++ '-n', '1', + '-a', self.pci, + '--', +- '--eth-peer=0,%s' % self.ethpeer, + '--portmask=0x1', + '--txpkts=%d' % self.packet_size, +- '--rxq=2', +- '--txq=2', ++ '--rxq=4', ++ '--txq=4', + '--forward-mode=txonly', ++ '--eth-peer=0,%s' % self.ethpeer, + '--stats-period=2' + ] + res = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) +@@ -238,18 +277,26 @@ + res.terminate() + with os.fdopen(os.open(self.test_dpdk_file, FILE_FLAGS, FILE_MODES), "w") as log: + log.write(str(res.stdout.read(), 'UTF-8')) +- time.sleep(3) +- res = self.command.run_cmd("grep Tx-pps %s | awk '{print $2}'" % self.test_dpdk_file)[0] +- res_list = res.split("\n")[1:-1] ++ time.sleep(30) ++ res = self.command.run_cmd("grep Tx-bps %s | awk '{print $4}'" % self.test_dpdk_file) ++ if res[2] != 0: ++ self.logger.error("The test data result is empty, Please check if the server is configured properly!") ++ res_list = res[0].split("\n")[-10:-1] + int_list = [int(x) for x in res_list] + number = len(int_list) + if number != 0: +- pps = sum(int_list) / number +- self.logger.info("The average speed is around %f Mb/s" % (8 * self.packet_size * pps / 1e6)) ++ bandwidth = float(sum(int_list) / number / 1e6) + # 1e6 = 1000000.0 +- return True ++ target_bandwidth = self.target_bandwidth_percent * self.speed ++ self.logger.info("Current bandwidth is around %.2f Mb/s, target is %.2fMb/s" % ++ (bandwidth, target_bandwidth)) ++ if bandwidth > target_bandwidth: ++ self.logger.info("Test dpdk bandwidth successfully.") ++ return True ++ self.logger.error("Test dpdk bandwidth failed!") ++ return False + else: +- self.logger.error("Test data acquisition failed!") ++ self.logger.error("No data obtained for testing dpdk, Please manually check!") + return False + + def ifdown(self, interface): +@@ -259,7 +306,7 @@ + :return: + """ + self.command.run_cmd("ip link set down %s" % interface) +- for _ in range(5): ++ for _ in range(10): + result = self.command.run_cmd( + "ip link show %s | grep 'state DOWN'" % interface, ignore_errors=True) + if result[2] == 0: +@@ -277,7 +324,7 @@ + :return: + """ + self.command.run_cmd("ip link set up %s" % interface) +- for _ in range(5): ++ for _ in range(10): + result = self.command.run_cmd( + "ip link show %s | grep 'state UP'" % interface, ignore_errors=True) + if result[2] == 0: +@@ -293,6 +340,13 @@ + Test ICMP + :return: + """ ++ self.speed = self.get_interface_speed() ++ if self.speed: ++ self.logger.info("The speed of %s is %sMb/s." % ++ (self.interface, self.speed)) ++ else: ++ self.logger.error("Set speed of %s failed." % self.interface) ++ + count = 500 + cmd = "ping -q -c %d -i 0 %s | grep 'packet loss' | awk '{print $6}'" % ( + count, self.server_ip) +@@ -312,7 +366,7 @@ + :return: + """ + form = dict() +- form['cmd'] = cmd ++ form = {'cmd': cmd, 'serverip': self.server_ip, 'cardid': self.card_id} + url = 'http://%s/api/%s' % (self.server_ip, act) + data = urlencode(form).encode('utf8') + headers = { +@@ -323,7 +377,7 @@ + try: + response = urlopen(request) + except Exception: +- self.logger.error("Call remote server url %s failed." % url) ++ self.logger.error("Call remote dpdk server url %s failed." % url) + return False + self.logger.info("Status: %u %s" % (response.code, response.msg)) + return int(response.code) == 200 +diff -Naur rpm/tests/kabi/kabi.py oech/tests/kabi/kabi.py +--- rpm/tests/kabi/kabi.py 2023-02-28 17:56:07.000000000 +0800 ++++ oech/tests/kabi/kabi.py 2023-06-13 23:26:19.347482340 +0800 +@@ -95,7 +95,7 @@ + if data and hsdp[0] in data: + continue + elif data and hsdp[0] not in data: +- if not self.changed_logpath.exists(): ++ if not os.path.exists(self.changed_logpath): + self.command.run_cmd("echo 'standard_symvers cur_symvers' | tee %s" % ( + self.changed_logpath), log_print=False) + +diff -Naur rpm/tests/network/network.py oech/tests/network/network.py +--- rpm/tests/network/network.py 2023-02-28 17:56:07.000000000 +0800 ++++ oech/tests/network/network.py 2023-06-13 23:26:19.355482340 +0800 +@@ -136,7 +136,7 @@ + :return: + """ + self.command.run_cmd("ip link set down %s" % interface) +- for _ in range(5): ++ for _ in range(10): + result = self.command.run_cmd( + "ip link show %s | grep 'state DOWN'" % interface, ignore_errors=False) + if result[2] == 0: +@@ -154,7 +154,7 @@ + :return: + """ + self.command.run_cmd("ip link set up %s" % interface) +- for _ in range(5): ++ for _ in range(10): + result = self.command.run_cmd( + "ip link show %s | grep 'state UP'" % interface, ignore_errors=False) + if result[2] == 0: diff --git a/oec-hardware.spec b/oec-hardware.spec index 2f74915190122f32defe7143817101ef1eab3c44..6f571435f4d98fb570ef5c88e32d2787b823ed25 100644 --- a/oec-hardware.spec +++ b/oec-hardware.spec @@ -4,13 +4,14 @@ Name: oec-hardware Summary: openEuler Hardware Compatibility Test Suite Version: 1.1.4 -Release: 0 +Release: 1 Group: Development/Tools License: Mulan PSL v2 URL: https://gitee.com/openeuler/oec-hardware Source0: https://gitee.com/openeuler/oec-hardware/repository/archive/v%{version}.tar.gz # patch fix issue +Patch0001: oec-hardware-1.1.4-fix-configip-dpdk.patch Buildroot: %{_tmppath}/%{name}-%{version}-root BuildRequires: gcc @@ -34,6 +35,7 @@ openEuler Hardware Compatibility Test Server %prep %setup -q -c +%patch1 -p1 %build strip tests/keycard/libswsds_%{_arch}.so @@ -76,6 +78,14 @@ DESTDIR=$RPM_BUILD_ROOT make install rm -rf /var/lock/oech.lock %changelog +* Tue Jun 13 2023 cuixucui - 1.1.4-1 +- Add igc dpdk +- Secure_filename to improve input robustness and security +- Correcting bug, self.changed_ Logpath is a string +- Increase the number of network card up detection times +- Resolve the issue of IP configuration failure + + * Tue Feb 28 2023 cuixucui - 1.1.4-0 - Add board information in the test report - Add spdk test case