luat_lib_iperf.c 7.2 KB

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