luat_lib_iperf.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. @module iperf
  3. @summary 吞吐量测试
  4. @catalog 网络API
  5. @version 1.0
  6. @date 2025.02.14
  7. @tag LUAT_USE_IPERF
  8. @usage
  9. -- 支持server模式, 也支持client模式
  10. */
  11. #include "luat_base.h"
  12. #include "luat_lwiperf.h"
  13. #include "luat_network_adapter.h"
  14. #include "luat_netdrv.h"
  15. #include "luat_msgbus.h"
  16. #include "lwip/ip.h"
  17. #include "lwip/tcpip.h"
  18. #define LUAT_LOG_TAG "iperf"
  19. #include "luat_log.h"
  20. static void* iperf_session;
  21. static int l_iperf_report_handle(lua_State*L, void* ptr) {
  22. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  23. uint32_t bytes_transferred, ms_duration, bandwidth;
  24. bytes_transferred = msg->arg1;
  25. ms_duration = msg->arg2;
  26. bandwidth = (int)ptr;
  27. lua_getglobal(L, "sys_pub");
  28. lua_pushstring(L, "IPERF_REPORT");
  29. lua_pushinteger(L, bytes_transferred);
  30. lua_pushinteger(L, ms_duration);
  31. lua_pushinteger(L, bandwidth);
  32. LLOGD("report bytes %ld ms_duration %ld bandwidth %ld kbps", bytes_transferred, ms_duration, bandwidth);
  33. lua_call(L, 4, 0);
  34. return 0;
  35. }
  36. static void iperf_report_cb(void *arg, enum lwiperf_report_type report_type,
  37. const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port,
  38. u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec) {
  39. rtos_msg_t msg = {0};
  40. msg.arg1 = bytes_transferred;
  41. msg.arg2 = ms_duration;
  42. msg.ptr = (void*)bandwidth_kbitpsec;
  43. msg.handler = l_iperf_report_handle;
  44. luat_msgbus_put(&msg, 0);
  45. }
  46. typedef struct iperf_start_ctx {
  47. luat_netdrv_t* drv;
  48. uint8_t mode;
  49. const ip_addr_t* remote_ip;
  50. }iperf_start_ctx_t;
  51. static void iperf_start_cb(void* args) {
  52. char buff[64] = {0};
  53. char buff2[64] = {0};
  54. iperf_start_ctx_t* ctx = (iperf_start_ctx_t*)args;
  55. uint8_t is_server = ctx->mode;
  56. luat_netdrv_t* drv = ctx->drv;
  57. const ip_addr_t* remote_ip = ctx->remote_ip;
  58. ipaddr_ntoa_r(&drv->netif->ip_addr, buff, sizeof(buff));
  59. LLOGD("启动iperf %s %p", is_server ? "server" : "client", remote_ip);
  60. if (is_server) {
  61. iperf_session = luat_lwiperf_start_tcp_server(&drv->netif->ip_addr, 5001, iperf_report_cb, NULL);
  62. LLOGD("iperf listen %s:5001", buff);
  63. }
  64. else {
  65. luat_lwiperf_start_tcp_client(remote_ip, 5001, LWIPERF_CLIENT, iperf_report_cb, NULL, &drv->netif->ip_addr);
  66. ipaddr_ntoa_r(remote_ip, buff2, sizeof(buff2));
  67. LLOGD("iperf connect %s --> %s:5001", buff, buff2);
  68. }
  69. }
  70. static int start_gogogo(int adpater_id, int is_server, const ip_addr_t* remote_ip) {
  71. if (adpater_id < 0 || adpater_id >= NW_ADAPTER_INDEX_LWIP_NETIF_QTY) {
  72. // 必须明确指定合法的索引号
  73. LLOGE("非法的网络适配器索引号 %d", adpater_id);
  74. return 0;
  75. }
  76. // 首先, 通过netdrv获取对应的网络设备的netif
  77. luat_netdrv_t* drv = luat_netdrv_get(adpater_id);
  78. if (drv == NULL || drv->netif == NULL) {
  79. LLOGE("非法的网络适配器索引号 %d", adpater_id);
  80. return 0;
  81. }
  82. if (!netif_is_up(drv->netif) || !netif_is_link_up(drv->netif) || ip_addr_isany(&drv->netif->ip_addr)) {
  83. LLOGE("该网络还没就绪, 无法启动");
  84. return 0;
  85. }
  86. iperf_start_ctx_t ctx = {
  87. .drv = drv,
  88. .mode = is_server,
  89. .remote_ip = remote_ip
  90. };
  91. tcpip_callback_with_block(iperf_start_cb, &ctx, 1);
  92. return iperf_session != NULL;
  93. }
  94. /*
  95. 启动server模式
  96. @api iperf.server(id)
  97. @int 网络适配器的id, 必须填, 例如 socket.LWIP_ETH0
  98. @return boolean 成功返回true, 失败返回false
  99. @usage
  100. -- 启动server模式, 监听5001端口
  101. -- 注意, 该网卡必须已经联网成功, 并且有ip地址
  102. if iperf then
  103. log.info("启动iperf服务器端")
  104. iperf.server(socket.LWIP_ETH)
  105. end
  106. -- 测试结果回调
  107. sys.subscribe("IPERF_REPORT", function(bytes, ms_duration, bandwidth)
  108. log.info("iperf", bytes, ms_duration, bandwidth)
  109. end)
  110. */
  111. static int l_iperf_server(lua_State *L) {
  112. if (iperf_session != NULL) {
  113. LLOGE("已经启动了server或者client,要先关掉才能启动新的");
  114. return 0;
  115. }
  116. int adpater_id = luaL_checkinteger(L, 1);
  117. if (start_gogogo(adpater_id, 1, NULL)) {
  118. lua_pushboolean(L, 1);
  119. return 1;
  120. }
  121. return 0;
  122. }
  123. /*
  124. 启动client模式
  125. @api iperf.client(id)
  126. @int 网络适配器的id, 必须填, 例如 socket.LWIP_ETH0
  127. @string 远程服务器的ip, 只能是ipv4地址,不支持域名!!! 必须填值
  128. @return boolean 成功返回true, 失败返回false
  129. @usage
  130. -- 启动client模式, 连接服务器的5001端口
  131. -- 注意, 该网卡必须已经联网成功, 并且有ip地址
  132. if iperf then
  133. log.info("启动iperf客户端端")
  134. -- 47.94.236.172 是演示服务器, 不一定有开启
  135. iperf.client(socket.LWIP_ETH, "47.94.236.172")
  136. sys.wait(60*1000)
  137. -- 测试完成停掉
  138. iperf.abort()
  139. end
  140. -- 测试结果回调
  141. sys.subscribe("IPERF_REPORT", function(bytes, ms_duration, bandwidth)
  142. log.info("iperf", bytes, ms_duration, bandwidth)
  143. end)
  144. */
  145. static int l_iperf_client(lua_State *L) {
  146. ip_addr_t remote_ip = {0};
  147. if (iperf_session != NULL) {
  148. LLOGE("已经启动了server或者client,要先关掉才能启动新的");
  149. return 0;
  150. }
  151. int adpater_id = luaL_checkinteger(L, 1);
  152. const char* ip = luaL_checkstring(L, 2);
  153. if (ipaddr_aton(ip, &remote_ip) == 0) {
  154. LLOGE("非法的ip地址 %s", ip);
  155. return 0;
  156. }
  157. if (start_gogogo(adpater_id, 0, &remote_ip)) {
  158. lua_pushboolean(L, 1);
  159. return 1;
  160. }
  161. return 0;
  162. }
  163. /*
  164. 关闭iperf
  165. @api iperf.abort()
  166. @return boolean 成功返回true, 失败返回false
  167. @usage
  168. -- 关闭已经启动的server或者client
  169. */
  170. static int l_iperf_abort(lua_State *L) {
  171. if (iperf_session == NULL) {
  172. return 0;
  173. }
  174. luat_lwiperf_abort(iperf_session);
  175. iperf_session = NULL;
  176. lua_pushboolean(L, 1);
  177. return 1;
  178. }
  179. #include "rotable2.h"
  180. static const rotable_Reg_t reg_iperf[] =
  181. {
  182. { "server" , ROREG_FUNC(l_iperf_server)},
  183. { "client" , ROREG_FUNC(l_iperf_client)},
  184. { "abort" , ROREG_FUNC(l_iperf_abort)},
  185. { NULL, ROREG_INT(0)}
  186. };
  187. LUAMOD_API int luaopen_iperf( lua_State *L ) {
  188. luat_newlib2(L, reg_iperf);
  189. return 1;
  190. }