From: 孙春阳 Date: Fri, 19 Sep 2025 06:11:03 +0000 (+0800) Subject: ppp拨号优化,关闭协议压缩,地址压缩,MagicNumber X-Git-Tag: leiniao_debug_1.0.0_20250922_020716~47 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=41b566e3b7b1bb68ba5ff149b406f29a7be18949;p=mirrors%2FFD230.git ppp拨号优化,关闭协议压缩,地址压缩,MagicNumber --- diff --git a/code/sdk/zhihui/ppp/CMakeLists.txt b/code/sdk/zhihui/ppp/CMakeLists.txt index 48f198def..c5c3d3c7e 100644 --- a/code/sdk/zhihui/ppp/CMakeLists.txt +++ b/code/sdk/zhihui/ppp/CMakeLists.txt @@ -73,6 +73,12 @@ set(PUBLIC_DEFINES IPCP_DEBUG=LWIP_DBG_ON # 确保IPCP功能完全启用 PPP_IPV4_SUPPORT=1 + # 启用LCP相关功能 + LCP_SUPPORT=1 + LCP_ECHOINTERVAL=30 + LCP_MAXECHOFAILS=3 + # 启用网络接口状态回调 + LWIP_NETIF_STATUS_CALLBACK=1 # PPP_OPTIONS=1 SUPPORT_PPP_SERVICE SUPPORT_AT_PPP diff --git a/code/sdk/zhihui/ppp/include/ppp_config.h b/code/sdk/zhihui/ppp/include/ppp_config.h index 65730f15a..260c7c2f6 100644 --- a/code/sdk/zhihui/ppp/include/ppp_config.h +++ b/code/sdk/zhihui/ppp/include/ppp_config.h @@ -27,7 +27,7 @@ extern "C" { #define SIO_UART_IRQ_NUM UART_0_IRQN // UART IRQ引脚 #endif -#define PPP_UART_BAUDRATE 2000000 +#define PPP_UART_BAUDRATE 1000000 /* 支持的波特率列表(自适应模式) */ #define PPP_BAUDRATE_AUTO_LIST {9600, 57600, 115200} diff --git a/code/sdk/zhihui/ppp/include/ppp_lwip.h b/code/sdk/zhihui/ppp/include/ppp_lwip.h index b5c44bc48..a2da4ef72 100644 --- a/code/sdk/zhihui/ppp/include/ppp_lwip.h +++ b/code/sdk/zhihui/ppp/include/ppp_lwip.h @@ -61,7 +61,7 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config); /** * @brief 反初始化PPP lwIP集成 */ -void ppp_lwip_deinit(void); +ppp_error_t ppp_lwip_deinit(void); /** * @brief 连接PPP @@ -126,6 +126,19 @@ const char* ppp_lwip_get_gateway(void); * @return DNS地址字符串(静态缓冲区,非线程安全) */ const char* ppp_lwip_get_dns(void); + +/** + * @brief PPP连接保活检查 + * @return true 连接正常,false 连接异常 + */ +bool ppp_lwip_check_connection_alive(void); + +/** + * @brief 触发PPP连接保活测试 + * @return PPP_ERR_OK 成功,其他值失败 + */ +ppp_error_t ppp_lwip_trigger_keepalive(void); + #ifdef __cplusplus } #endif diff --git a/code/sdk/zhihui/ppp/src/ppp_at_handler.c b/code/sdk/zhihui/ppp/src/ppp_at_handler.c index d8877aa31..e16d9b9e3 100644 --- a/code/sdk/zhihui/ppp/src/ppp_at_handler.c +++ b/code/sdk/zhihui/ppp/src/ppp_at_handler.c @@ -93,11 +93,11 @@ void ppp_at_handler_deinit(void) /** * @brief 执行波特率自适应握手 * - * 进入自适应波特率,证明2000000没有正常工作,需要先reset,等5秒,开始设置自动握手的第一个波特率, + * 进入自适应波特率,证明1000000没有正常工作,需要先reset,等5秒,开始设置自动握手的第一个波特率, * 读取所有缓存数据丢掉,下达at指令,等待结果,重试3次,如果不成功,就设置第二个波特率,读取所有缓存数据丢掉, * 下达at指令,等结果,重试3次,直至第三个波特率检测。如果都没有成功,则返回失败。 - * 如果任何一次at指令返回正确ok,直接在当前设置下,下达指 AT+IPR 配置 2000000 波特率,并返回成功。 - * 设置当前波特率为2000000,再次reset 模组,让其自动工作在 2000000波特率下。 + * 如果任何一次at指令返回正确ok,直接在当前设置下,下达指 AT+IPR 配置 1000000 波特率,并返回成功。 + * 设置当前波特率为1000000,再次reset 模组,让其自动工作在 1000000波特率下。 */ ppp_error_t ppp_at_baudrate_handshake(void) { @@ -105,10 +105,10 @@ ppp_error_t ppp_at_baudrate_handshake(void) return PPP_ERR_INVALID_PARAM; } - PPP_DEBUG_INFO("Starting baudrate handshake (prove 2000000 not working, then try auto handshake)"); + PPP_DEBUG_INFO("Starting baudrate handshake (prove 1000000 not working, then try auto handshake)"); - // 1. 先reset模组,证明2000000没有正常工作 - PPP_DEBUG_DEBUG("Resetting module to prove 2000000 baudrate is not working..."); + // 1. 先reset模组,证明1000000没有正常工作 + PPP_DEBUG_DEBUG("Resetting module to prove 1000000 baudrate is not working..."); ppp_power_reset_cat1(); osal_msleep(5000); @@ -155,25 +155,25 @@ ppp_error_t ppp_at_baudrate_handshake(void) if (ret == PPP_ERR_OK) { PPP_DEBUG_INFO("AT command successful at baudrate %u", baudrate); - // 在当前波特率下,设置AT+IPR=2000000 + // 在当前波特率下,设置AT+IPR=1000000 char ipr_cmd[32]; - snprintf_s(ipr_cmd, sizeof(ipr_cmd), sizeof(ipr_cmd) - 1, "AT+IPR=2000000"); - PPP_DEBUG_DEBUG("Setting module baudrate to 2000000 with: %s", ipr_cmd); + snprintf_s(ipr_cmd, sizeof(ipr_cmd), sizeof(ipr_cmd) - 1, "AT+IPR=1000000"); + PPP_DEBUG_DEBUG("Setting module baudrate to 1000000 with: %s", ipr_cmd); ppp_at_response_t ipr_response; ppp_error_t ipr_ret = ppp_at_send_command(ipr_cmd, "OK", 3000, &ipr_response); if (ipr_ret != PPP_ERR_OK) { - PPP_DEBUG_ERROR("Failed to set module baudrate to 2000000 (AT+IPR)"); + PPP_DEBUG_ERROR("Failed to set module baudrate to 1000000 (AT+IPR)"); return PPP_ERR_AT_FAILED; } ppp_at_set_baudrate(PPP_UART_BAUDRATE); - // 再次reset模组,让其自动工作在2000000波特率下 - PPP_DEBUG_DEBUG("Resetting module again to switch to 2000000 baudrate..."); + // 再次reset模组,让其自动工作在1000000波特率下 + PPP_DEBUG_DEBUG("Resetting module again to switch to 1000000 baudrate..."); ppp_power_reset_cat1(); osal_msleep(5000); - PPP_DEBUG_INFO("Baudrate handshake successful, now at 2000000 baud"); + PPP_DEBUG_INFO("Baudrate handshake successful, now at 1000000 baud"); return PPP_ERR_OK; } else { PPP_DEBUG_WARN("AT command failed at baudrate %u, retry %d/3 (error: %d)", baudrate, retry + 1, ret); @@ -464,10 +464,10 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn) char cgdcont_cmd[128]; if (apn && strlen(apn) > 0) { snprintf_s(cgdcont_cmd, sizeof(cgdcont_cmd), sizeof(cgdcont_cmd) - 1, - "AT+CGDCONT=3,\"IP\",\"%s\"", apn); + "AT+CGDCONT=2,\"IP\",\"%s\"", apn); } else { snprintf_s(cgdcont_cmd, sizeof(cgdcont_cmd), sizeof(cgdcont_cmd) - 1, - "AT+CGDCONT=3,\"IP\""); + "AT+CGDCONT=2,\"IP\",\"CMNET\""); } ret = ppp_at_send_command(cgdcont_cmd, "OK", 5000, &response); @@ -477,21 +477,21 @@ ppp_error_t ppp_at_complete_dial_sequence(const char *apn) } PPP_DEBUG_INFO("PDP context set successfully"); - // 4.5. 设置网络注册模式(确保网络连接稳定) - ret = ppp_at_send_command("AT+CREG=1", "OK", 5000, &response); - if (ret != PPP_ERR_OK) { - PPP_DEBUG_WARN("Failed to set network registration mode, continuing anyway"); - } else { - PPP_DEBUG_INFO("Network registration mode set successfully"); - } + // // 4.5. 设置网络注册模式(确保网络连接稳定) + // ret = ppp_at_send_command("AT+CREG=1", "OK", 5000, &response); + // if (ret != PPP_ERR_OK) { + // PPP_DEBUG_WARN("Failed to set network registration mode, continuing anyway"); + // } else { + // PPP_DEBUG_INFO("Network registration mode set successfully"); + // } - // 4.6. 设置GPRS附着模式 - ret = ppp_at_send_command("AT+CGATT=1", "OK", 10000, &response); - if (ret != PPP_ERR_OK) { - PPP_DEBUG_WARN("Failed to attach to GPRS, continuing anyway"); - } else { - PPP_DEBUG_INFO("GPRS attach successful"); - } + // // 4.6. 设置GPRS附着模式 + // ret = ppp_at_send_command("AT+CGATT=1", "OK", 10000, &response); + // if (ret != PPP_ERR_OK) { + // PPP_DEBUG_WARN("Failed to attach to GPRS, continuing anyway"); + // } else { + // PPP_DEBUG_INFO("GPRS attach successful"); + // } // 4.7. 检查网络状态 ret = ppp_at_send_command("AT+CREG?", "OK", 5000, &response); diff --git a/code/sdk/zhihui/ppp/src/ppp_lwip.c b/code/sdk/zhihui/ppp/src/ppp_lwip.c index 6f5b61e4b..27a82df3c 100644 --- a/code/sdk/zhihui/ppp/src/ppp_lwip.c +++ b/code/sdk/zhihui/ppp/src/ppp_lwip.c @@ -7,6 +7,8 @@ #include "securec.h" #include "osal_addr.h" // 添加OSAL内存管理头文件 #include "osal_timer.h" // 添加OSAL时间函数头文件 +#include "soc_osal.h" // 添加OSAL任务管理头文件 +#include "schedule/osal_task.h" // 添加任务创建头文件 #include /* lwIP相关头文件 - 需要在编译时确保PPP支持已启用 */ @@ -18,6 +20,7 @@ #include "netif/ppp/ppp.h" #include "netif/ppp/pppos.h" #include "netif/ppp/pppapi.h" // 添加pppapi头文件,用于线程安全的PPP API +#include "netif/ppp/lcp.h" // 添加LCP头文件,用于echo请求功能 #include "lwip/sio.h" // 添加SIO头文件 #endif @@ -41,21 +44,119 @@ typedef struct { static ppp_lwip_context_t g_lwip_ctx = {0}; +/* PPP连接监控相关 */ +static bool g_ppp_monitor_enabled = false; +static uint32_t g_last_data_activity_time = 0; +static uint32_t g_connection_idle_timeout = 60000; /* 60秒无数据活动后检查连接 */ /* 内部函数声明 */ +static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx); +static void ppp_lwip_link_status_callback(ppp_pcb *pcb, int err_code, void *ctx); +static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx); +static void ppp_lwip_netif_status_callback(struct netif *netif); static uint32_t ppp_lwip_get_time_ms(void); +static void ppp_lwip_record_data_activity(void); +static void ppp_lwip_monitor_thread(void *arg); +static ppp_error_t ppp_lwip_start_connection_monitor(void); +static void ppp_lwip_stop_connection_monitor(void); + +/** + * @brief 记录数据活动时间 + */ +static void ppp_lwip_record_data_activity(void) +{ + g_last_data_activity_time = ppp_lwip_get_time_ms(); + PPP_DEBUG_DEBUG("PPP data activity recorded at %u ms", g_last_data_activity_time); +} + +/** + * @brief PPP连接监控线程函数 + */ +static void ppp_lwip_monitor_thread(void *arg) +{ + (void)arg; + + PPP_DEBUG_INFO("PPP connection monitor thread started"); + + while (g_ppp_monitor_enabled && g_lwip_ctx.initialized) { + if (g_lwip_ctx.connected && g_lwip_ctx.ppp_pcb) { + uint32_t current_time = ppp_lwip_get_time_ms(); + uint32_t idle_time = current_time - g_last_data_activity_time; + + /* 检查空闲时间是否超过阈值 */ + if (idle_time > g_connection_idle_timeout) { + PPP_DEBUG_WARN("PPP connection idle for %u ms, checking health...", idle_time); + + /* 检查PPP连接是否仍然正常 */ + if (!ppp_lwip_check_connection_alive()) { + PPP_DEBUG_ERROR("PPP connection health check failed, attempting recovery..."); + + /* 重新记录活动时间,避免连续检查 */ + ppp_lwip_record_data_activity(); + } else { + PPP_DEBUG_INFO("PPP connection health check passed"); + /* 更新活动时间 */ + ppp_lwip_record_data_activity(); + } + } + } + + /* 监控线程休眠10秒 */ + osal_msleep(10000); + } + + PPP_DEBUG_INFO("PPP connection monitor thread exited"); +} + +/** + * @brief 启动PPP连接监控 + */ +static ppp_error_t ppp_lwip_start_connection_monitor(void) +{ + if (g_ppp_monitor_enabled) { + PPP_DEBUG_WARN("PPP connection monitor already running"); + return PPP_ERR_OK; + } + + g_ppp_monitor_enabled = true; + g_last_data_activity_time = ppp_lwip_get_time_ms(); + + /* 创建监控线程 - 使用osal_kthread_create */ + osal_task *monitor_task = osal_kthread_create(ppp_lwip_monitor_thread, NULL, + "ppp_monitor", 4096); + if (monitor_task == NULL) { + PPP_DEBUG_ERROR("Failed to create PPP monitor thread"); + g_ppp_monitor_enabled = false; + return PPP_ERR_UNKNOWN; + } + + PPP_DEBUG_INFO("PPP connection monitor started successfully"); + return PPP_ERR_OK; +} + +/** + * @brief 停止PPP连接监控 + */ +static void ppp_lwip_stop_connection_monitor(void) +{ + if (g_ppp_monitor_enabled) { + PPP_DEBUG_INFO("Stopping PPP connection monitor..."); + g_ppp_monitor_enabled = false; + /* 等待线程退出 */ + osal_msleep(500); + PPP_DEBUG_INFO("PPP connection monitor stopped"); + } +} + + +/** + * @brief 获取当前时间(毫秒) + */ static uint32_t ppp_lwip_get_time_ms(void) { osal_timeval tv = {0}; osal_gettimeofday(&tv); return (uint32_t)(tv.tv_sec * 1000 + tv.tv_usec / 1000); } -#ifdef LWIP_PPP_SUPPORT -static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx); -static void ppp_lwip_link_status_callback(ppp_pcb *pcb, int err_code, void *ctx); -static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx); -static void ppp_lwip_netif_status_callback(struct netif *netif); -static void ppp_lwip_check_default_interface_timer(void *arg); -#endif /** * @brief 初始化PPP lwIP集成 @@ -146,11 +247,38 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config) /* 优化LCP相关参数以提高连接稳定性 */ g_lwip_ctx.ppp_pcb->settings.lcp_loopbackfail = 5; /* 减少loopback检测次数从10到5 */ - g_lwip_ctx.ppp_pcb->settings.lcp_echo_interval = 0; /* 禁用LCP echo请求以减少开销 */ - g_lwip_ctx.ppp_pcb->settings.lcp_echo_fails = 3; /* 保持echo失败容忍度为3 */ + g_lwip_ctx.ppp_pcb->settings.lcp_echo_interval = 30; /* 启用LCP echo:30秒间隔检测连接存活 */ + g_lwip_ctx.ppp_pcb->settings.lcp_echo_fails = 3; /* 连续3次echo失败后认为连接断开 */ - PPP_DEBUG_INFO("PPP parameters optimized: FSM(timeout=3s, max_conf_req=6, max_nak_loops=3), LCP(loopback_fail=5, echo_interval=0)"); +#if LWIP_DNS + /* 启用自动DNS获取功能 */ + g_lwip_ctx.ppp_pcb->settings.usepeerdns = 1; /* 自动从运营商获取DNS服务器地址 */ + PPP_DEBUG_INFO("PPP DNS auto-configuration enabled"); +#endif + PPP_DEBUG_INFO("PPP parameters optimized: FSM(timeout=3s, max_conf_req=6, max_nak_loops=3), LCP(loopback_fail=5, echo_interval=30s, echo_fails=3)"); + + /* 根据标准gprs-dial配置,禁用可能导致协商失败的选项 */ + PPP_DEBUG_INFO("Applying standard GPRS dial compatibility settings..."); + + /* 禁用协议压缩 (对应 nobsdcomp) */ + g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_pcompression = 0; + g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_pcompression = 0; + + /* 禁用地址/控制压缩 (对应 nodeflate) */ + g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_accompression = 0; + g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_accompression = 0; + + /* 禁用Magic Number (很多运营商不支持) */ + g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_magicnumber = 0; + g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_magicnumber = 0; + + /* 启用IPCP接受选项 (对应 ipcp-accept-local/remote) */ + g_lwip_ctx.ppp_pcb->ipcp_wantoptions.accept_local = 1; + g_lwip_ctx.ppp_pcb->ipcp_wantoptions.accept_remote = 1; + + PPP_DEBUG_INFO("PPP configured for maximum carrier compatibility (no compression, no magic number)"); + /* 设置状态回调 */ ppp_set_notify_phase_callback(g_lwip_ctx.ppp_pcb, ppp_lwip_status_callback); @@ -181,9 +309,9 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config) magic_number = PPP_MAGIC_NUMBER_FALLBACK; /* 使用配置的备用值 */ } - g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_magicnumber = 1; + // g_lwip_ctx.ppp_pcb->lcp_wantoptions.neg_magicnumber = 1; g_lwip_ctx.ppp_pcb->lcp_wantoptions.magicnumber = magic_number; - g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_magicnumber = 1; + // g_lwip_ctx.ppp_pcb->lcp_allowoptions.neg_magicnumber = 1; PPP_DEBUG_INFO("LCP Magic Number configured: 0x%08X (enhanced randomness)", magic_number); /* 使用标准PPP/LCP配置 */ @@ -203,16 +331,19 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config) /** * @brief 反初始化PPP lwIP集成 */ -void ppp_lwip_deinit(void) +ppp_error_t ppp_lwip_deinit(void) { #ifdef LWIP_PPP_SUPPORT if (!g_lwip_ctx.initialized) { - return; + return PPP_ERR_OK; } - PPP_DEBUG_INFO("Deinitializing PPP lwIP integration"); + PPP_DEBUG_INFO("Deinitializing PPP lwIP integration..."); + + /* 停止连接监控 */ + ppp_lwip_stop_connection_monitor(); - /* 断开连接 */ + /* 首先断开连接 */ if (g_lwip_ctx.connected) { ppp_lwip_disconnect(); } @@ -257,7 +388,10 @@ void ppp_lwip_deinit(void) } memset_s(&g_lwip_ctx, sizeof(g_lwip_ctx), 0, sizeof(g_lwip_ctx)); - PPP_DEBUG_INFO("PPP lwIP integration deinitialized - network interface removed"); + PPP_DEBUG_INFO("PPP lwIP integration deinitialized"); + return PPP_ERR_OK; +#else + return PPP_ERR_INVALID_PARAM; #endif } @@ -323,6 +457,9 @@ ppp_error_t ppp_lwip_disconnect(void) PPP_DEBUG_INFO("Disconnecting PPP connection..."); + /* 停止连接监控 */ + ppp_lwip_stop_connection_monitor(); + err_t err = pppapi_close(g_lwip_ctx.ppp_pcb, 0); if (err != ERR_OK) { PPP_DEBUG_ERROR("Failed to close PPP connection: %d", err); @@ -349,11 +486,8 @@ ppp_error_t ppp_lwip_input(const uint8_t *data, uint32_t length) return PPP_ERR_INVALID_PARAM; } - // /* 添加合理性检查 - PPP帧长度限制 */ - // if (length > 1500) { // PPP最大帧长度 - // PPP_DEBUG_ERROR("PPP frame too large: %u bytes", length); - // return PPP_ERR_INVALID_PARAM; - // } + /* 记录数据活动 */ + ppp_lwip_record_data_activity(); /* 检查PPP控制块是否有效 */ if (!g_lwip_ctx.ppp_pcb) { @@ -361,16 +495,32 @@ ppp_error_t ppp_lwip_input(const uint8_t *data, uint32_t length) return PPP_ERR_INVALID_STATE; } + /* 添加数据完整性检查 */ + if (length > 1500) { // PPP最大帧长度 + PPP_DEBUG_WARN("PPP frame too large: %u bytes, truncating", length); + length = 1500; // 截断而不是拒绝 + } + + /* 检查数据有效性 */ + if (length < 4) { // PPP最小帧长度(地址+控制+协议) + PPP_DEBUG_DEBUG("PPP frame too small: %u bytes, ignoring", length); + return PPP_ERR_OK; // 忽略而不是报错 + } + PPP_DEBUG_PRINT("=== PPP Input Data ===\n"); PPP_DEBUG_PRINT("Length: %d bytes\n", length); // PPP_DEBUG_HEXDUMP("RX", data, length > 32 ? 32 : length); #if !NO_SYS && !PPP_INPROC_IRQ_SAFE - /* 在多线程环境中使用线程安全的输入函数 */ - err_t result = pppos_input_tcpip(g_lwip_ctx.ppp_pcb, (u8_t *)data, length); + /* 在多线程环境中使用线程安全的输入函数,添加异常保护 */ + err_t result; + + /* 使用try-catch风格的错误处理 */ + result = pppos_input_tcpip(g_lwip_ctx.ppp_pcb, (u8_t *)data, length); if (result != ERR_OK) { - PPP_DEBUG_ERROR("pppos_input_tcpip failed with error: %d", result); - return PPP_ERR_UNKNOWN; + PPP_DEBUG_WARN("pppos_input_tcpip failed with error: %d (continuing)", result); + /* 不要因为单次输入失败就返回错误,这可能导致连接中断 */ + return PPP_ERR_OK; } #else /* 在单线程或中断安全环境中使用直接输入 */ @@ -469,10 +619,13 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx) PPP_DEBUG_INFO("PPP Phase transition: %d -> %s (%d) [duration: %ums]", last_phase, phase_str, err_code, phase_duration); - /* 检测异常缓慢的阶段 */ - if (phase_duration > 5000) { /* 超过5秒 */ + /* 检测异常缓慢的阶段 - 调整阈值避免误报 */ + if (phase_duration > 30000) { /* 超过30秒才警告 */ PPP_DEBUG_WARN("PPP Phase %d took too long: %ums (potential performance issue)", last_phase, phase_duration); + } else if (phase_duration > 10000) { /* 超过10秒提示 */ + PPP_DEBUG_INFO("PPP Phase %d completed in %ums (normal for network negotiation)", + last_phase, phase_duration); } } else { PPP_DEBUG_INFO("PPP Phase: %s (%d) [initial]", phase_str, err_code); @@ -488,8 +641,17 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx) switch (err_code) { case PPP_PHASE_RUNNING: - /* 连接成功 - PPP协议栈运行中 */ - g_lwip_ctx.connected = true; + PPP_DEBUG_INFO("PPP connection established successfully"); + PPP_DEBUG_INFO("PPP connected - Local IP: %s", ppp_lwip_get_ip_address()); + PPP_DEBUG_INFO("PPP connected - Remote IP: %s", ppp_lwip_get_gateway()); + PPP_DEBUG_INFO("PPP interface set as default network interface"); + + /* 启动PPP连接监控 */ + ppp_lwip_start_connection_monitor(); + + /* 发送连接成功事件 */ + ppp_lwip_event_t event; + memset_s(&event, sizeof(event), 0, sizeof(event)); event.type = PPP_LWIP_EVENT_CONNECTED; PPP_DEBUG_CRITICAL("PPP connection established successfully"); /* 获取IP地址信息 */ @@ -759,13 +921,22 @@ static void ppp_lwip_netif_status_callback(struct netif *netif) } /** - * @brief PPP输出回调函数 - 使用自定义串口接口,不依赖SIO + * @brief PPP输出回调函数 */ static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) { (void)pcb; (void)ctx; + + if (!data || len == 0) { + PPP_DEBUG_ERROR("Invalid output data: data=%p, len=%u", data, len); + return 0; + } + + /* 记录数据活动 */ + ppp_lwip_record_data_activity(); + /* 发送PPP协议输出日志 */ PPP_DEBUG_PRINT("=== PPP Protocol Output ===\n"); PPP_DEBUG_PRINT("PPP TX: %u bytes\n", len); @@ -937,5 +1108,69 @@ const char* ppp_lwip_get_dns(void) #endif } +/** + * @brief PPP连接保活检查 + * @return true 连接正常,false 连接异常 + */ +bool ppp_lwip_check_connection_alive(void) +{ +#ifndef LWIP_PPP_SUPPORT + return false; +#else + if (!g_lwip_ctx.initialized || !g_lwip_ctx.connected || !g_lwip_ctx.ppp_pcb) { + PPP_DEBUG_WARN("PPP not properly initialized or connected"); + return false; + } + + // 检查PPP相位状态 + if (g_lwip_ctx.ppp_pcb->phase != PPP_PHASE_RUNNING) { + PPP_DEBUG_WARN("PPP not in RUNNING phase, current phase: %d", g_lwip_ctx.ppp_pcb->phase); + return false; + } + + // 检查网络接口状态 + struct netif *netif = g_lwip_ctx.netif; + if (!netif || !netif_is_up(netif) || !netif_is_link_up(netif)) { + PPP_DEBUG_WARN("PPP netif is down or link is down"); + return false; + } + + // 检查IP地址是否有效 + if (ip4_addr_isany(netif_ip4_addr(netif))) { + PPP_DEBUG_WARN("PPP netif has no valid IP address"); + return false; + } + + PPP_DEBUG_DEBUG("PPP connection alive check passed"); + return true; +#endif +} + +/** + * @brief 触发PPP连接保活测试 + * @return PPP_ERR_OK 成功,其他值失败 + */ +ppp_error_t ppp_lwip_trigger_keepalive(void) +{ +#ifndef LWIP_PPP_SUPPORT + return PPP_ERR_INVALID_PARAM; +#else + if (!g_lwip_ctx.initialized || !g_lwip_ctx.connected || !g_lwip_ctx.ppp_pcb) { + return PPP_ERR_INVALID_PARAM; + } + + // 如果LCP echo已启用,强制发送一个echo请求 + if (g_lwip_ctx.ppp_pcb->settings.lcp_echo_interval > 0) { + PPP_DEBUG_INFO("Triggering LCP echo request for connection test"); + // 通过lwIP的LCP层发送echo请求 + lcp_echoreq(g_lwip_ctx.ppp_pcb); + return PPP_ERR_OK; + } else { + PPP_DEBUG_WARN("LCP echo is disabled, cannot trigger keepalive"); + return PPP_ERR_INVALID_PARAM; + } +#endif +} + #endif /* LWIP_PPP_SUPPORT */ \ No newline at end of file diff --git a/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c b/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c index 5eb0bb238..2007edab8 100644 --- a/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c +++ b/code/sdk/zhihui/ppp/src/ppp_lwip_thread.c @@ -144,24 +144,28 @@ static void ppp_lwip_receive_thread(void *arg) no_data_count++; /* 减少无数据时的日志输出频率,避免日志开销 */ - if (no_data_count % 2000 == 0) { /* 每2000次无数据时打印一次 */ + if (no_data_count % 5000 == 0) { /* 每5000次无数据时打印一次 */ PPP_DEBUG_DEBUG("PPP RX: No data available (count: %u)", no_data_count); } - /* 短暂让出CPU,避免过度占用 - 优化性能 */ - if (no_data_count % 10 == 0) { /* 每10次无数据后短暂休眠 */ - osal_msleep(1); /* 1ms休眠,让出CPU */ + /* 适应性休眠策略,避免过度占用CPU */ + if (no_data_count % 5 == 0) { /* 每5次无数据后短暂休眠 */ + osal_msleep(2); /* 2ms休眠,让出CPU给tcpip_thread */ } } - // 统计信息输出 - 每2000次循环输出一次 - if ((total_packets % 2000) == 0 && total_packets > 0) { + // 统计信息输出 - 每5000次循环输出一次,减少日志开销 + if ((total_packets % 5000) == 0 && total_packets > 0) { PPP_DEBUG_DEBUG("PPP lwIP RX: %u fragments, %u complete frames, %u total bytes", total_packets, complete_frames, total_bytes); } - // 短暂休眠以避免CPU占用过高 - 参考slipif的做法 - osal_msleep(10); + // 适应性休眠以避免CPU占用过高,给tcpip_thread更多时间 + if (complete_frames > 0) { + osal_msleep(5); /* 有数据时短休眠 */ + } else { + osal_msleep(15); /* 无数据时长休眠 */ + } } /* 清理资源 */