iperf_test.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. """
  2. Test case for iperf example.
  3. This test case might have problem running on windows:
  4. 1. direct use of `make`
  5. 2. use `sudo killall iperf` to force kill iperf, didn't implement windows version
  6. The test env Example_ShieldBox do need the following config::
  7. Example_ShieldBox:
  8. ap_list:
  9. - ssid: "ssid"
  10. password: "password"
  11. outlet: 1
  12. apc_ip: "192.168.1.88"
  13. attenuator_port: "/dev/ttyUSB0"
  14. iperf: "/dev/ttyUSB1"
  15. apc_ip: "192.168.1.88"
  16. pc_nic: "eth0"
  17. """
  18. from __future__ import division, unicode_literals
  19. import os
  20. import re
  21. import subprocess
  22. import time
  23. from builtins import range, str
  24. import ttfw_idf
  25. from idf_iperf_test_util import Attenuator, IperfUtility, PowerControl, TestReport
  26. from idf_iperf_test_util.IperfUtility import SCAN_RETRY_COUNT, SCAN_TIMEOUT, TEST_TIME
  27. from tiny_test_fw import DUT, TinyFW, Utility
  28. # configurations
  29. RETRY_COUNT_FOR_BEST_PERFORMANCE = 2
  30. ATTEN_VALUE_LIST = range(0, 60, 2)
  31. CONFIG_NAME_PATTERN = re.compile(r'sdkconfig\.ci\.(.+)')
  32. # We need to auto compare the difference between adjacent configs (01 -> 00, 02 -> 01, ...) and put them to reports.
  33. # Using numbers for config will make this easy.
  34. # Use default value `99` for config with best performance.
  35. BEST_PERFORMANCE_CONFIG = '99'
  36. class IperfTestUtilitySoftap(IperfUtility.IperfTestUtility):
  37. """ iperf test implementation """
  38. def __init__(self, dut, softap_dut, config_name, test_result=None):
  39. IperfUtility.IperfTestUtility.__init__(self, dut, config_name, 'softap', '1234567890', None, None, test_result)
  40. self.softap_dut = softap_dut
  41. self.softap_ip = '192.168.4.1'
  42. def setup(self):
  43. """
  44. setup iperf test:
  45. 1. kill current iperf process
  46. 2. reboot DUT (currently iperf is not very robust, need to reboot DUT)
  47. 3. scan to get AP RSSI
  48. 4. connect to AP
  49. """
  50. self.softap_dut.write('restart')
  51. self.softap_dut.expect_any('iperf>', 'esp32>', timeout=30)
  52. self.softap_dut.write('ap {} {}'.format(self.ap_ssid, self.ap_password))
  53. self.dut.write('restart')
  54. self.dut.expect_any('iperf>', 'esp32>', timeout=30)
  55. self.dut.write('scan {}'.format(self.ap_ssid))
  56. for _ in range(SCAN_RETRY_COUNT):
  57. try:
  58. rssi = int(self.dut.expect(re.compile(r'\[{}]\[rssi=(-\d+)]'.format(self.ap_ssid)),
  59. timeout=SCAN_TIMEOUT)[0])
  60. break
  61. except DUT.ExpectTimeout:
  62. continue
  63. else:
  64. raise AssertionError('Failed to scan AP')
  65. self.dut.write('sta {} {}'.format(self.ap_ssid, self.ap_password))
  66. dut_ip = self.dut.expect(re.compile(r'sta ip: ([\d.]+), mask: ([\d.]+), gw: ([\d.]+)'))[0]
  67. return dut_ip, rssi
  68. def _test_once(self, proto, direction):
  69. """ do measure once for one type """
  70. # connect and scan to get RSSI
  71. dut_ip, rssi = self.setup()
  72. assert direction in ['rx', 'tx']
  73. assert proto in ['tcp', 'udp']
  74. # run iperf test
  75. if direction == 'tx':
  76. if proto == 'tcp':
  77. self.softap_dut.write('iperf -s -i 1 -t {}'.format(TEST_TIME))
  78. # wait until DUT TCP server created
  79. try:
  80. self.softap_dut.expect('iperf tcp server create successfully', timeout=1)
  81. except DUT.ExpectTimeout:
  82. # compatible with old iperf example binary
  83. pass
  84. self.dut.write('iperf -c {} -i 1 -t {}'.format(self.softap_ip, TEST_TIME))
  85. else:
  86. self.softap_dut.write('iperf -s -u -i 1 -t {}'.format(TEST_TIME))
  87. self.dut.write('iperf -c {} -u -i 1 -t {}'.format(self.softap_ip, TEST_TIME))
  88. else:
  89. if proto == 'tcp':
  90. self.dut.write('iperf -s -i 1 -t {}'.format(TEST_TIME))
  91. # wait until DUT TCP server created
  92. try:
  93. self.dut.expect('iperf tcp server create successfully', timeout=1)
  94. except DUT.ExpectTimeout:
  95. # compatible with old iperf example binary
  96. pass
  97. self.softap_dut.write('iperf -c {} -i 1 -t {}'.format(dut_ip, TEST_TIME))
  98. else:
  99. self.dut.write('iperf -s -u -i 1 -t {}'.format(TEST_TIME))
  100. self.softap_dut.write('iperf -c {} -u -i 1 -t {}'.format(dut_ip, TEST_TIME))
  101. time.sleep(60)
  102. if direction == 'tx':
  103. server_raw_data = self.dut.read()
  104. else:
  105. server_raw_data = self.softap_dut.read()
  106. self.dut.write('iperf -a')
  107. self.softap_dut.write('iperf -a')
  108. self.dut.write('heap')
  109. heap_size = self.dut.expect(re.compile(r'min heap size: (\d+)\D'))[0]
  110. # return server raw data (for parsing test results) and RSSI
  111. return server_raw_data, rssi, heap_size
  112. @ttfw_idf.idf_example_test(env_tag='Example_ShieldBox_Basic', target=['ESP32', 'ESP32S2', 'ESP32C3', 'ESP32S3'], category='stress')
  113. def test_wifi_throughput_with_different_configs(env, extra_data):
  114. """
  115. steps: |
  116. 1. build iperf with specified configs
  117. 2. test throughput for all routers
  118. """
  119. pc_nic_ip = env.get_pc_nic_info('pc_nic', 'ipv4')['addr']
  120. pc_iperf_log_file = os.path.join(env.log_path, 'pc_iperf_log.md')
  121. ap_info = {
  122. 'ssid': env.get_variable('ap_ssid'),
  123. 'password': env.get_variable('ap_password'),
  124. }
  125. config_names_raw = subprocess.check_output(['ls', os.path.dirname(os.path.abspath(__file__))])
  126. config_names = CONFIG_NAME_PATTERN.findall(config_names_raw)
  127. if not config_names:
  128. raise ValueError('no configs found in {}'.format(os.path.dirname(__file__)))
  129. test_result = dict()
  130. sdkconfig_files = dict()
  131. for config_name in config_names:
  132. # 1. get the config
  133. sdkconfig_files[config_name] = os.path.join(os.path.dirname(__file__),
  134. 'sdkconfig.ci.{}'.format(config_name))
  135. # 2. get DUT and download
  136. dut = env.get_dut('iperf', 'examples/wifi/iperf', app_config_name=config_name)
  137. dut.start_app()
  138. dut.expect_any('iperf>', 'esp32>')
  139. # 3. run test for each required att value
  140. test_result[config_name] = {
  141. 'tcp_tx': IperfUtility.TestResult('tcp', 'tx', config_name),
  142. 'tcp_rx': IperfUtility.TestResult('tcp', 'rx', config_name),
  143. 'udp_tx': IperfUtility.TestResult('udp', 'tx', config_name),
  144. 'udp_rx': IperfUtility.TestResult('udp', 'rx', config_name),
  145. }
  146. test_utility = IperfUtility.IperfTestUtility(dut, config_name, ap_info['ssid'], ap_info['password'], pc_nic_ip,
  147. pc_iperf_log_file, test_result[config_name])
  148. for _ in range(RETRY_COUNT_FOR_BEST_PERFORMANCE):
  149. test_utility.run_all_cases(0)
  150. for result_type in test_result[config_name]:
  151. summary = str(test_result[config_name][result_type])
  152. if summary:
  153. Utility.console_log(summary, color='orange')
  154. # 4. check test results
  155. env.close_dut('iperf')
  156. # 5. generate report
  157. report = TestReport.ThroughputForConfigsReport(os.path.join(env.log_path, 'Performance',
  158. 'ThroughputForConfigsReport'),
  159. ap_info['ssid'], test_result, sdkconfig_files)
  160. report.generate_report()
  161. @ttfw_idf.idf_example_test(env_tag='Example_ShieldBox', target=['ESP32', 'ESP32S2', 'ESP32C3', 'ESP32S3'], category='stress')
  162. def test_wifi_throughput_vs_rssi(env, extra_data):
  163. """
  164. steps: |
  165. 1. build with best performance config
  166. 2. switch on one router
  167. 3. set attenuator value from 0-60 for each router
  168. 4. test TCP tx rx and UDP tx rx throughput
  169. """
  170. att_port = env.get_variable('attenuator_port')
  171. ap_list = env.get_variable('ap_list')
  172. pc_nic_ip = env.get_pc_nic_info('pc_nic', 'ipv4')['addr']
  173. apc_ip = env.get_variable('apc_ip')
  174. pc_iperf_log_file = os.path.join(env.log_path, 'pc_iperf_log.md')
  175. test_result = {
  176. 'tcp_tx': IperfUtility.TestResult('tcp', 'tx', BEST_PERFORMANCE_CONFIG),
  177. 'tcp_rx': IperfUtility.TestResult('tcp', 'rx', BEST_PERFORMANCE_CONFIG),
  178. 'udp_tx': IperfUtility.TestResult('udp', 'tx', BEST_PERFORMANCE_CONFIG),
  179. 'udp_rx': IperfUtility.TestResult('udp', 'rx', BEST_PERFORMANCE_CONFIG),
  180. }
  181. # 1. get DUT and download
  182. dut = env.get_dut('iperf', 'examples/wifi/iperf', app_config_name=BEST_PERFORMANCE_CONFIG)
  183. dut.start_app()
  184. dut.expect_any('iperf>', 'esp32>')
  185. # 2. run test for each required att value
  186. for ap_info in ap_list:
  187. test_utility = IperfUtility.IperfTestUtility(dut, BEST_PERFORMANCE_CONFIG, ap_info['ssid'],
  188. ap_info['password'], pc_nic_ip, pc_iperf_log_file, test_result)
  189. PowerControl.Control.control_rest(apc_ip, ap_info['outlet'], 'OFF')
  190. PowerControl.Control.control(apc_ip, {ap_info['outlet']: 'ON'})
  191. Attenuator.set_att(att_port, 0)
  192. if not test_utility.wait_ap_power_on():
  193. Utility.console_log('[{}] failed to power on, skip testing this AP'
  194. .format(ap_info['ssid']), color='red')
  195. continue
  196. for atten_val in ATTEN_VALUE_LIST:
  197. assert Attenuator.set_att(att_port, atten_val) is True
  198. try:
  199. test_utility.run_all_cases(atten_val)
  200. except AssertionError:
  201. break
  202. # 3. check test results
  203. env.close_dut('iperf')
  204. # 4. generate report
  205. report = TestReport.ThroughputVsRssiReport(os.path.join(env.log_path, 'Performance', 'STAThroughputVsRssiReport'),
  206. test_result)
  207. report.generate_report()
  208. @ttfw_idf.idf_example_test(env_tag='Example_ShieldBox_Basic',
  209. target=['ESP32', 'ESP32S2', 'ESP32C3', 'ESP32S3'], ci_target=['ESP32'])
  210. def test_wifi_throughput_basic(env, extra_data):
  211. """
  212. steps: |
  213. 1. test TCP tx rx and UDP tx rx throughput
  214. 2. compare with the pre-defined pass standard
  215. """
  216. pc_nic_ip = env.get_pc_nic_info('pc_nic', 'ipv4')['addr']
  217. pc_iperf_log_file = os.path.join(env.log_path, 'pc_iperf_log.md')
  218. ap_info = {
  219. 'ssid': env.get_variable('ap_ssid'),
  220. 'password': env.get_variable('ap_password'),
  221. }
  222. # 1. get DUT
  223. dut = env.get_dut('iperf', 'examples/wifi/iperf', app_config_name=BEST_PERFORMANCE_CONFIG)
  224. dut.start_app()
  225. dut.expect_any('iperf>', 'esp32>')
  226. # 2. preparing
  227. test_result = {
  228. 'tcp_tx': IperfUtility.TestResult('tcp', 'tx', BEST_PERFORMANCE_CONFIG),
  229. 'tcp_rx': IperfUtility.TestResult('tcp', 'rx', BEST_PERFORMANCE_CONFIG),
  230. 'udp_tx': IperfUtility.TestResult('udp', 'tx', BEST_PERFORMANCE_CONFIG),
  231. 'udp_rx': IperfUtility.TestResult('udp', 'rx', BEST_PERFORMANCE_CONFIG),
  232. }
  233. test_utility = IperfUtility.IperfTestUtility(dut, BEST_PERFORMANCE_CONFIG, ap_info['ssid'], ap_info['password'],
  234. pc_nic_ip, pc_iperf_log_file, test_result)
  235. # 3. run test for TCP Tx, Rx and UDP Tx, Rx
  236. for _ in range(RETRY_COUNT_FOR_BEST_PERFORMANCE):
  237. test_utility.run_all_cases(0)
  238. # 4. log performance and compare with pass standard
  239. performance_items = []
  240. for throughput_type in test_result:
  241. ttfw_idf.log_performance('{}_throughput'.format(throughput_type),
  242. '{:.02f} Mbps'.format(test_result[throughput_type].get_best_throughput()))
  243. performance_items.append(['{}_throughput'.format(throughput_type),
  244. '{:.02f} Mbps'.format(test_result[throughput_type].get_best_throughput())])
  245. # 5. save to report
  246. TinyFW.JunitReport.update_performance(performance_items)
  247. # do check after logging, otherwise test will exit immediately if check fail, some performance can't be logged.
  248. for throughput_type in test_result:
  249. ttfw_idf.check_performance('{}_throughput'.format(throughput_type),
  250. test_result[throughput_type].get_best_throughput(), dut.TARGET)
  251. env.close_dut('iperf')
  252. @ttfw_idf.idf_example_test(env_tag='Example_ShieldBox2', target=['ESP32', 'ESP32S2', 'ESP32C3', 'ESP32S3'], category='stress')
  253. def test_softap_throughput_vs_rssi(env, extra_data):
  254. """
  255. steps: |
  256. 1. build with best performance config
  257. 2. switch on one router
  258. 3. set attenuator value from 0-60 for each router
  259. 4. test TCP tx rx and UDP tx rx throughput
  260. """
  261. att_port = env.get_variable('attenuator_port')
  262. test_result = {
  263. 'tcp_tx': IperfUtility.TestResult('tcp', 'tx', BEST_PERFORMANCE_CONFIG),
  264. 'tcp_rx': IperfUtility.TestResult('tcp', 'rx', BEST_PERFORMANCE_CONFIG),
  265. 'udp_tx': IperfUtility.TestResult('udp', 'tx', BEST_PERFORMANCE_CONFIG),
  266. 'udp_rx': IperfUtility.TestResult('udp', 'rx', BEST_PERFORMANCE_CONFIG),
  267. }
  268. # 1. get DUT and download
  269. softap_dut = env.get_dut('softap_iperf', 'examples/wifi/iperf')
  270. softap_dut.start_app()
  271. softap_dut.expect_any('iperf>', 'esp32>')
  272. sta_dut = env.get_dut('sta_iperf', 'examples/wifi/iperf', app_config_name=BEST_PERFORMANCE_CONFIG)
  273. sta_dut.start_app()
  274. sta_dut.expect_any('iperf>', 'esp32>')
  275. # 2. run test for each required att value
  276. test_utility = IperfTestUtilitySoftap(sta_dut, softap_dut, BEST_PERFORMANCE_CONFIG, test_result)
  277. Attenuator.set_att(att_port, 0)
  278. for atten_val in ATTEN_VALUE_LIST:
  279. assert Attenuator.set_att(att_port, atten_val) is True
  280. try:
  281. test_utility.run_all_cases(atten_val)
  282. except AssertionError:
  283. break
  284. env.close_dut('softap_iperf')
  285. env.close_dut('sta_iperf')
  286. # 3. generate report
  287. report = TestReport.ThroughputVsRssiReport(os.path.join(env.log_path, 'Performance',
  288. 'SoftAPThroughputVsRssiReport'),test_result)
  289. report.generate_report()
  290. if __name__ == '__main__':
  291. # test_wifi_throughput_basic(env_config_file='EnvConfig.yml')
  292. # test_wifi_throughput_with_different_configs(env_config_file='EnvConfig.yml')
  293. test_wifi_throughput_vs_rssi(env_config_file='EnvConfig.yml', target='ESP32C3')
  294. test_softap_throughput_vs_rssi(env_config_file='EnvConfig.yml')