iperf_test.py 14 KB

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