Merge #2283 into sdk650pathc0423 from refs/changes/2283/head
authorsnickersun@163.com <accounts_62b90f7fcf51ade33b6f628e@mail.teambition.com>
Thu, 18 Sep 2025 02:39:40 +0000 (02:39 +0000)
committersnickersun@163.com <accounts_62b90f7fcf51ade33b6f628e@mail.teambition.com>
Thu, 18 Sep 2025 02:39:40 +0000 (02:39 +0000)
雷鸟 ai_old添加编译配置

* refs/changes/2283/head: (4 commits squashed)

  - 雷鸟 ai_old添加编译配置

  - 添加AT^PPPDEBUGSET动态修改打印等级指令

  - 添加tcp client测试用例

  - Merge branch &#39;sdk650pathc0423&#39; of codeup.aliyun.com:64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423

Signed-off-by: snickersun@163.com <accounts_62b90f7fcf51ade33b6f628e@mail.teambition.com>
Reviewed-by: snickersun@163.com <accounts_62b90f7fcf51ade33b6f628e@mail.teambition.com>
Merged-by: snickersun@163.com <accounts_62b90f7fcf51ade33b6f628e@mail.teambition.com>
link: https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230/change/2283
17 files changed:
code/sdk/build/config/target_config/brandy/config.py
code/sdk/zhihui/ppp/CMakeLists.txt
code/sdk/zhihui/ppp/doc/dynamic_debug_usage.md [new file with mode: 0644]
code/sdk/zhihui/ppp/example/Makefile [new file with mode: 0644]
code/sdk/zhihui/ppp/example/README_TCP_TEST.md [new file with mode: 0644]
code/sdk/zhihui/ppp/example/ppp_at_cmd.c
code/sdk/zhihui/ppp/example/ppp_example.c
code/sdk/zhihui/ppp/example/ppp_tcp_test.c [new file with mode: 0644]
code/sdk/zhihui/ppp/example/ppp_tcp_test_main.c [new file with mode: 0644]
code/sdk/zhihui/ppp/include/ppp_config.h
code/sdk/zhihui/ppp/include/ppp_debug.h
code/sdk/zhihui/ppp/include/ppp_debug_manager.h [new file with mode: 0644]
code/sdk/zhihui/ppp/include/ppp_lwip.h
code/sdk/zhihui/ppp/include/ppp_tcp_lwip_compat.h [new file with mode: 0644]
code/sdk/zhihui/ppp/include/ppp_tcp_test.h [new file with mode: 0644]
code/sdk/zhihui/ppp/src/ppp_debug_manager.c [new file with mode: 0644]
code/sdk/zhihui/ppp/src/ppp_lwip.c

index 1cbb4c4..dff9169 100644 (file)
@@ -1277,6 +1277,7 @@ target = {
             # 'AILPAY_SUPPORT',
             # 'SUPPORT_FACTORY_SERVICE',
             # 'MEMORY_CORRUPTION',
+            'SUPPORT_AI_SERVICE',
             'SAP_EFFECT_SWS_SUPPORT',
             'AUDIO_SMARTPA_AW88082',
             'LCD_JD9885',
index 41539d6..4e83333 100644 (file)
@@ -10,6 +10,7 @@ set(PPP_AT_CMD_SOURCE
     ${CMAKE_CURRENT_SOURCE_DIR}/example/ppp_example.c
     # ${CMAKE_CURRENT_SOURCE_DIR}/example/ppp_power_example.c
     ${CMAKE_CURRENT_SOURCE_DIR}/example/api_shell.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/example/ppp_tcp_test.c
 )
 # 源文件列表
 set(SOURCES
@@ -19,6 +20,7 @@ set(SOURCES
     src/ppp_lwip.c
     src/ppp_lwip_thread.c
     src/ppp_debug.c
+    src/ppp_debug_manager.c
     src/ppp_power_ctl.c
     src/ppp_cat1_api.c
     src/ppp_stub_functions.c
@@ -75,6 +77,7 @@ set(PUBLIC_DEFINES
     # PPP_OPTIONS=1 
     SUPPORT_PPP_SERVICE
     SUPPORT_AT_PPP
+    SUPPORT_TCP_TEST
 )
 
 set(PRIVATE_DEFINES
diff --git a/code/sdk/zhihui/ppp/doc/dynamic_debug_usage.md b/code/sdk/zhihui/ppp/doc/dynamic_debug_usage.md
new file mode 100644 (file)
index 0000000..0519ecb
--- /dev/null
@@ -0,0 +1 @@
+ 
\ No newline at end of file
diff --git a/code/sdk/zhihui/ppp/example/Makefile b/code/sdk/zhihui/ppp/example/Makefile
new file mode 100644 (file)
index 0000000..208b52e
--- /dev/null
@@ -0,0 +1,83 @@
+# Makefile for PPP TCP Test Client
+# 基于Python版本tcp_test_client.py实现的C语言版本
+
+# 编译器设置
+CC = gcc
+CFLAGS = -Wall -Wextra -std=c99 -O2 -g
+LDFLAGS = -pthread
+
+# 目录设置
+SRC_DIR = .
+INC_DIR = ../include
+BUILD_DIR = build
+
+# 目标程序
+TARGET = ppp_tcp_test
+
+# 源文件
+SRCS = ppp_tcp_test.c ppp_tcp_test_main.c
+
+# 目标文件
+OBJS = $(SRCS:%.c=$(BUILD_DIR)/%.o)
+
+# 头文件依赖
+INCLUDES = -I$(INC_DIR) -I.
+
+# 默认目标
+all: $(BUILD_DIR)/$(TARGET)
+
+# 创建构建目录
+$(BUILD_DIR):
+       mkdir -p $(BUILD_DIR)
+
+# 编译目标程序
+$(BUILD_DIR)/$(TARGET): $(BUILD_DIR) $(OBJS)
+       $(CC) $(OBJS) -o $@ $(LDFLAGS)
+       @echo "Build complete: $@"
+
+# 编译源文件
+$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
+       $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
+
+# 清理
+clean:
+       rm -rf $(BUILD_DIR)
+
+# 安装
+install: $(BUILD_DIR)/$(TARGET)
+       cp $(BUILD_DIR)/$(TARGET) /usr/local/bin/$(TARGET)
+       @echo "Installed to /usr/local/bin/$(TARGET)"
+
+# 卸载
+uninstall:
+       rm -f /usr/local/bin/$(TARGET)
+       @echo "Uninstalled $(TARGET)"
+
+# 测试运行
+test: $(BUILD_DIR)/$(TARGET)
+       @echo "Running basic test..."
+       $(BUILD_DIR)/$(TARGET) --help
+
+# 示例运行
+example: $(BUILD_DIR)/$(TARGET)
+       @echo "Running example test (需要服务器支持)..."
+       $(BUILD_DIR)/$(TARGET) --host 127.0.0.1 --port 8910 --connections 2 --time 10 --verbose
+
+# 显示帮助
+help:
+       @echo "Available targets:"
+       @echo "  all       - Build the TCP test client"
+       @echo "  clean     - Remove build files"
+       @echo "  install   - Install to /usr/local/bin"
+       @echo "  uninstall - Remove from /usr/local/bin"
+       @echo "  test      - Run basic functionality test"
+       @echo "  example   - Run example test (needs server)"
+       @echo "  help      - Show this help"
+       @echo ""
+       @echo "Usage examples:"
+       @echo "  make"
+       @echo "  make test"
+       @echo "  make example"
+       @echo "  ./build/$(TARGET) --host 192.168.1.100 --port 8080 --connections 5 --time 30"
+
+.PHONY: all clean install uninstall test example help 
\ No newline at end of file
diff --git a/code/sdk/zhihui/ppp/example/README_TCP_TEST.md b/code/sdk/zhihui/ppp/example/README_TCP_TEST.md
new file mode 100644 (file)
index 0000000..0519ecb
--- /dev/null
@@ -0,0 +1 @@
+ 
\ No newline at end of file
index 3ceb0ff..f34636a 100644 (file)
@@ -12,6 +12,8 @@
 #include "ppp_types.h"
 #include "ppp_api.h"
 #include "ppp_at_handler.h"
+#include "ppp_debug_manager.h"
+#include "ppp_tcp_test.h"
 #include "ppp_example.h"
 
 
@@ -1591,6 +1593,321 @@ static errcode_t at_ppp_test_uart_performance(uint8_t *para, uint32_t paraLen)
     return ERRCODE_SUCC;
 }
 
+/**
+ * @brief AT^PPPDEBUGSET - 设置PPP调试级别
+ * @param para 参数: 调试级别 (0=NONE, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG) 或级别名称
+ * @param paraLen 参数长度
+ */
+static errcode_t at_ppp_debug_set_level(uint8_t *para, uint32_t paraLen)
+{
+    if (!para || paraLen == 0) {
+        PRINT("[PPP_ERR]PPP DEBUG SET: Missing debug level parameter\r\n");
+        PRINT("[PPP_INFO]Usage: AT^PPPDEBUGSET=<level>\r\n");
+        PRINT("[PPP_INFO]Levels: 0=NONE, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG\r\n");
+        PRINT("[PPP_INFO]Or use names: NONE, ERROR, WARN, INFO, DEBUG\r\n");
+        return ERRCODE_FAIL;
+    }
+    
+    // 将参数转换为字符串
+    char level_str[16] = {0};
+    uint32_t copy_len = (paraLen < sizeof(level_str) - 1) ? paraLen : sizeof(level_str) - 1;
+    memcpy(level_str, para, copy_len);
+    level_str[copy_len] = '\0';
+    
+    PRINT("[PPP_INFO]PPP DEBUG SET: Setting debug level to '%s'...\r\n", level_str);
+    
+    ppp_error_t ret = PPP_ERR_OK;
+    
+    // 尝试按数字设置
+    if (level_str[0] >= '0' && level_str[0] <= '4' && level_str[1] == '\0') {
+        int level = level_str[0] - '0';
+        ret = ppp_debug_set_level(level);
+        if (ret == PPP_ERR_OK) {
+            PRINT("[PPP_INFO]PPP DEBUG SET: Debug level set to %d (%s)\r\n", 
+                  level, ppp_debug_get_level_name(level));
+        }
+    } else {
+        // 尝试按名称设置
+        ret = ppp_debug_set_level_by_name(level_str);
+        if (ret == PPP_ERR_OK) {
+            int current_level = ppp_debug_get_level();
+            PRINT("[PPP_INFO]PPP DEBUG SET: Debug level set to %s (%d)\r\n", 
+                  ppp_debug_get_level_name(current_level), current_level);
+        }
+    }
+    
+    if (ret != PPP_ERR_OK) {
+        PRINT("[PPP_ERR]PPP DEBUG SET: Invalid debug level '%s'\r\n", level_str);
+        PRINT("[PPP_INFO]Valid levels: 0=NONE, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG\r\n");
+        return ERRCODE_FAIL;
+    }
+    
+    return ERRCODE_SUCC;
+}
+
+/**
+ * @brief AT^PPPDEBUGGET - 获取当前PPP调试级别
+ */
+static errcode_t at_ppp_debug_get_level(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    int current_level = ppp_debug_get_level();
+    const char *level_name = ppp_debug_get_level_name(current_level);
+    
+    PRINT("[PPP_INFO]PPP DEBUG GET: Current debug level is %d (%s)\r\n", 
+          current_level, level_name);
+    
+    // 显示各级别的含义
+    PRINT("[PPP_INFO]Debug levels:\r\n");
+    PRINT("[PPP_INFO]  0=NONE  - No debug output\r\n");
+    PRINT("[PPP_INFO]  1=ERROR - Error messages only\r\n");
+    PRINT("[PPP_INFO]  2=WARN  - Warnings and errors\r\n");
+    PRINT("[PPP_INFO]  3=INFO  - Info, warnings and errors\r\n");
+    PRINT("[PPP_INFO]  4=DEBUG - All debug messages\r\n");
+    
+    return ERRCODE_SUCC;
+}
+#include "ppp_debug.h"
+/**
+ * @brief AT^PPPDEBUGTEST - 测试各级别调试输出
+ */
+static errcode_t at_ppp_debug_test_output(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    int current_level = ppp_debug_get_level();
+    
+    PRINT("[PPP_INFO]PPP DEBUG TEST: Testing debug output at level %d (%s)\r\n", 
+          current_level, ppp_debug_get_level_name(current_level));
+    
+    // 测试各级别输出
+    PPP_DEBUG_ERROR("This is an ERROR message (level 1)");
+    PPP_DEBUG_WARN("This is a WARN message (level 2)");
+    PPP_DEBUG_INFO("This is an INFO message (level 3)");
+    PPP_DEBUG_DEBUG("This is a DEBUG message (level 4)");
+    PPP_DEBUG_CRITICAL("This is a CRITICAL message (always shown)");
+    
+    PRINT("[PPP_INFO]PPP DEBUG TEST: Test completed\r\n");
+    
+    return ERRCODE_SUCC;
+}
+
+/**
+ * @brief AT^PPPDEBUGDEFAULT - 重置调试级别为默认值
+ */
+static errcode_t at_ppp_debug_reset_level(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+    ppp_error_t ret = ppp_debug_reset_level();
+    if (ret == PPP_ERR_OK) {
+        int current_level = ppp_debug_get_level();
+        PRINT("[PPP_INFO]PPP DEBUG RESET: Debug level reset to default %d (%s)\r\n", 
+              current_level, ppp_debug_get_level_name(current_level));
+        return ERRCODE_SUCC;
+    } else {
+        PRINT("[PPP_ERR]PPP DEBUG RESET: Failed to reset debug level\r\n");
+        return ERRCODE_FAIL;
+    }
+}
+
+/**
+ * @brief AT^PPPTCPPERF - PPP TCP性能测试
+ * @param para 参数: 服务器地址,端口,连接数,测试时间
+ * @param paraLen 参数长度
+ */
+static errcode_t at_ppp_tcp_performance_test(uint8_t *para, uint32_t paraLen)
+{
+    if (!para || paraLen == 0) {
+        PRINT("[PPP_ERR]PPP TCP PERF: Missing parameters\r\n");
+        PRINT("[PPP_INFO]Usage: AT^PPPTCPPERF=<host>,<port>,<connections>,<time>\r\n");
+        PRINT("[PPP_INFO]Example: AT^PPPTCPPERF=110.42.224.129,8910,5,30\r\n");
+        return ERRCODE_FAIL;
+    }
+    
+    uint8_t argv[CUSTOM_UTILS_MAX_ARGC][CUSTOM_UTILS_MAX_ARGV_LEN];
+    uint32_t argc;
+    
+    if (ConvertCmdToParam(para, paraLen, argv, &argc) != CUSTOM_UTILS_SUCCESS || argc != 4) {
+        PRINT("[PPP_ERR]PPP TCP PERF: Invalid parameters, need 4 parameters, got %d\r\n", argc);
+        PRINT("[PPP_INFO]Usage: AT^PPPTCPPERF=<host>,<port>,<connections>,<time>\r\n");
+        return ERRCODE_FAIL;
+    }
+    
+    // 解析参数
+    char *server_host = (char*)argv[0];
+    int port = atoi((char*)argv[1]);
+    int connections = atoi((char*)argv[2]);
+    int test_time = atoi((char*)argv[3]);
+    
+    // 参数验证
+    if (port < 1 || port > 65535) {
+        PRINT("[PPP_ERR]PPP TCP PERF: Invalid port %d (must be 1-65535)\r\n", port);
+        return ERRCODE_FAIL;
+    }
+    
+    if (connections < 1 || connections > TCP_TEST_MAX_CONNECTIONS) {
+        PRINT("[PPP_ERR]PPP TCP PERF: Invalid connections %d (must be 1-%d)\r\n", 
+              connections, TCP_TEST_MAX_CONNECTIONS);
+        return ERRCODE_FAIL;
+    }
+    
+    if (test_time < 1 || test_time > 3600) {
+        PRINT("[PPP_ERR]PPP TCP PERF: Invalid test time %d (must be 1-3600 seconds)\r\n", test_time);
+        return ERRCODE_FAIL;
+    }
+    
+    PRINT("[PPP_INFO]PPP TCP PERF: Starting TCP performance test\r\n");
+    PRINT("[PPP_INFO]Target: %s:%d\r\n", server_host, port);
+    PRINT("[PPP_INFO]Connections: %d\r\n", connections);
+    PRINT("[PPP_INFO]Duration: %d seconds\r\n", test_time);
+    
+#ifdef SUPPORT_TCP_TEST
+    // 初始化TCP测试配置
+    tcp_test_config_t config;
+    strncpy(config.server_host, server_host, sizeof(config.server_host) - 1);
+    config.server_host[sizeof(config.server_host) - 1] = '\0';
+    config.server_port = (uint16_t)port;
+    config.test_duration = (uint32_t)test_time;
+    config.connection_count = (uint16_t)connections;
+    config.verbose = false; // AT命令模式不使用详细输出
+    config.send_interval_ms = 10; // 10ms间隔,适合AT命令模式
+    config.data_min_size = 64;    // 较小的数据包
+    config.data_max_size = 1024;  // 适中的最大包
+    
+    // 初始化TCP测试
+    ppp_error_t ret = tcp_test_init();
+    if (ret != PPP_ERR_OK) {
+        PRINT("[PPP_ERR]PPP TCP PERF: Failed to initialize TCP test: %d\r\n", ret);
+        return ERRCODE_FAIL;
+    }
+    
+    // 启动测试
+    ret = tcp_test_start(&config);
+    if (ret != PPP_ERR_OK) {
+        PRINT("[PPP_ERR]PPP TCP PERF: Failed to start TCP test: %d\r\n", ret);
+        tcp_test_deinit();
+        return ERRCODE_FAIL;
+    }
+    
+    PRINT("[PPP_INFO]PPP TCP PERF: Test started successfully\r\n");
+    PRINT("[PPP_INFO]PPP TCP PERF: Use AT^PPPTCPSTOP to stop early\r\n");
+    PRINT("[PPP_INFO]PPP TCP PERF: Use AT^PPPTCPSTATS to check status\r\n");
+    
+    return ERRCODE_SUCC;
+    
+#else
+    PRINT("[PPP_ERR]PPP TCP PERF: TCP test not supported in this build\r\n");
+    PRINT("[PPP_INFO]PPP TCP PERF: Enable SUPPORT_TCP_TEST to use this feature\r\n");
+    return ERRCODE_FAIL;
+#endif
+}
+
+/**
+ * @brief AT^PPPTCPSTOP - 停止TCP性能测试
+ */
+static errcode_t at_ppp_tcp_test_stop(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+#ifdef SUPPORT_TCP_TEST
+    if (!tcp_test_is_running()) {
+        PRINT("[PPP_INFO]PPP TCP STOP: No TCP test is currently running\r\n");
+        return ERRCODE_SUCC;
+    }
+    
+    PRINT("[PPP_INFO]PPP TCP STOP: Stopping TCP performance test...\r\n");
+    
+    ppp_error_t ret = tcp_test_stop();
+    if (ret != PPP_ERR_OK) {
+        PRINT("[PPP_ERR]PPP TCP STOP: Failed to stop TCP test: %d\r\n", ret);
+        return ERRCODE_FAIL;
+    }
+    
+    // 清理资源
+    tcp_test_deinit();
+    
+    PRINT("[PPP_INFO]PPP TCP STOP: TCP test stopped successfully\r\n");
+    return ERRCODE_SUCC;
+    
+#else
+    PRINT("[PPP_ERR]PPP TCP STOP: TCP test not supported in this build\r\n");
+    return ERRCODE_FAIL;
+#endif
+}
+
+/**
+ * @brief AT^PPPTCPSTATS - 获取TCP测试统计信息
+ */
+static errcode_t at_ppp_tcp_test_stats(uint8_t *para, uint32_t paraLen)
+{
+    (void)para;
+    (void)paraLen;
+    
+#ifdef SUPPORT_TCP_TEST
+    if (!tcp_test_is_running()) {
+        PRINT("[PPP_INFO]PPP TCP STATS: No TCP test is currently running\r\n");
+        return ERRCODE_SUCC;
+    }
+    
+    // 获取全局统计信息
+    tcp_global_stats_t stats;
+    ppp_error_t ret = tcp_test_get_stats(&stats);
+    if (ret != PPP_ERR_OK) {
+        PRINT("[PPP_ERR]PPP TCP STATS: Failed to get TCP test stats: %d\r\n", ret);
+        return ERRCODE_FAIL;
+    }
+    
+    // 计算运行时间
+    uint32_t current_time = tcp_test_get_time_ms();
+    uint32_t elapsed_ms = current_time - stats.start_time;
+    uint32_t elapsed_sec = elapsed_ms / 1000;
+    
+    // 显示统计信息
+    PRINT("[PPP_INFO]=== TCP Performance Test Statistics ===\r\n");
+    PRINT("[PPP_INFO]Test Status: %s\r\n", stats.test_running ? "RUNNING" : "STOPPED");
+    PRINT("[PPP_INFO]Elapsed Time: %d seconds\r\n", elapsed_sec);
+    PRINT("[PPP_INFO]Successful Connections: %d\r\n", stats.successful_connections);
+    PRINT("[PPP_INFO]Failed Connections: %d\r\n", stats.failed_connections);
+    PRINT("[PPP_INFO]Packets Sent: %llu\r\n", stats.total_packets_sent);
+    PRINT("[PPP_INFO]Packets Received: %llu\r\n", stats.total_packets_received);
+    PRINT("[PPP_INFO]Bytes Sent: %llu\r\n", stats.total_bytes_sent);
+    PRINT("[PPP_INFO]Bytes Received: %llu\r\n", stats.total_bytes_received);
+    PRINT("[PPP_INFO]Total Errors: %d\r\n", stats.total_errors);
+    PRINT("[PPP_INFO]Data Verification Errors: %d\r\n", stats.data_verification_errors);
+    
+    // 计算传输速率
+    if (elapsed_ms > 0) {
+        uint64_t throughput_bps = (stats.total_bytes_sent * 1000) / elapsed_ms;
+        char bytes_buf[64];
+        PRINT("[PPP_INFO]Average Throughput: %s/s\r\n", 
+              tcp_test_format_bytes(throughput_bps, bytes_buf, sizeof(bytes_buf)));
+        
+        float packet_rate = (float)stats.total_packets_sent * 1000 / elapsed_ms;
+        PRINT("[PPP_INFO]Average Packet Rate: %.1f packets/s\r\n", packet_rate);
+    }
+    
+    // 计算成功率
+    if (stats.total_packets_sent > 0) {
+        float success_rate = (float)stats.total_packets_received / stats.total_packets_sent * 100;
+        PRINT("[PPP_INFO]Packet Success Rate: %.1f%%\r\n", success_rate);
+    }
+    
+    PRINT("[PPP_INFO]========================================\r\n");
+    
+    return ERRCODE_SUCC;
+    
+#else
+    PRINT("[PPP_ERR]PPP TCP STATS: TCP test not supported in this build\r\n");
+    return ERRCODE_FAIL;
+#endif
+}
+
 static const at_cmd_table_t g_ppp_cmd[] = {
     { (char *)"AT^CAT1POWER",       cat1_power, (char *)"1" },
     { (char *)"AT^CAT1GETSIGNAL",   at_cat1_getsignal, (char *)"1" },
@@ -1642,6 +1959,13 @@ static const at_cmd_table_t g_ppp_cmd[] = {
     { (char *)"AT^WSMULTISTATUS",   at_ws_multi_test_status, (char *)" " },
 #endif
     { (char *)"AT^PPPSIGNALINFO",   at_ppp_get_signal_info, (char *)" " },
+    { (char *)"AT^PPPDEBUGSET",     at_ppp_debug_set_level, (char *)"level" },
+    { (char *)"AT^PPPDEBUGGET",     at_ppp_debug_get_level, (char *)" " },
+    { (char *)"AT^PPPDEBUGTEST",    at_ppp_debug_test_output, (char *)" " },
+    { (char *)"AT^PPPDEBUGDEFAULT",  at_ppp_debug_reset_level, (char *)" " },
+    { (char *)"AT^PPPTCPPERF",      at_ppp_tcp_performance_test, (char *)"host,port,connections,time" },
+    { (char *)"AT^PPPTCPSTOP",      at_ppp_tcp_test_stop, (char *)" " },
+    { (char *)"AT^PPPTCPSTATS",      at_ppp_tcp_test_stats, (char *)" " },
 };
 
 at_cmd_table_t *get_ppp_cmd_table(uint32_t *cmd_count)
index cc4c357..7334b3a 100644 (file)
@@ -369,6 +369,12 @@ static void network_monitor_task(void *arg)
         PRINT("Sim Status: %d\r\n", cat1_api_runtime_get_cat1_simstat());
         PRINT("Network Type: %d\r\n", cat1_api_runtime_get_cat1_networktype());
 
+        // 这些接口已移至ppp_lwip.c实现
+        PRINT("ip: %s\r\n", ppp_lwip_get_ip_address());
+        PRINT("netmask: %s\r\n", ppp_lwip_get_netmask());
+        PRINT("gateway: %s\r\n", ppp_lwip_get_gateway());
+        PRINT("dns: %s\r\n", ppp_lwip_get_dns());
+
         ppp_state_t state = ppp_get_state();
         switch (state) {
             case PPP_STATE_IDLE:
diff --git a/code/sdk/zhihui/ppp/example/ppp_tcp_test.c b/code/sdk/zhihui/ppp/example/ppp_tcp_test.c
new file mode 100644 (file)
index 0000000..3620095
--- /dev/null
@@ -0,0 +1,737 @@
+/**
+ * @file ppp_tcp_test.c
+ * @brief PPP TCP性能测试客户端实现
+ * 
+ * 基于Python版本tcp_test_client.py实现的C语言版本
+ * 支持多连接并发测试、性能统计和数据验证
+ * 使用lwIP socket接口兼容嵌入式环境
+ */
+
+#include "ppp_tcp_test.h"
+#include "ppp_debug.h"
+#include "ppp_tcp_lwip_compat.h"  /* lwIP兼容性定义 */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+/* 时间相关头文件 */
+#ifndef USE_LWIP_SOCKET
+#include <sys/time.h>
+#endif
+
+/* 系统相关头文件 */
+#ifdef USE_LWIP_SOCKET
+    /* 使用嵌入式环境的简化定义 */
+    #include "osal_mutex.h"
+    #include "osal_task.h"
+    
+    /* 简化的兼容性定义 */
+    #define TCP_MUTEX_INIT(mutex)       osal_mutex_init(&(mutex))
+    #define TCP_MUTEX_DESTROY(mutex)    osal_mutex_destroy(&(mutex))
+    #define TCP_MUTEX_LOCK(mutex)       osal_mutex_lock(&(mutex))
+    #define TCP_MUTEX_UNLOCK(mutex)     osal_mutex_unlock(&(mutex))
+    #define TCP_TIMER_CREATE(id, cb, arg, period, cycle) (*(id) = 0) /* 简化实现 */
+    #define TCP_TIMER_DELETE(id)        /* 简化实现 */
+    #define TCP_TASK_CREATE(func, arg, name, size) \
+        do { \
+            osal_kthread_create((osal_kthread_handler)func, arg, name, size); \
+        } while(0)
+    #define TCP_SLEEP_MS(ms)            osal_msleep(ms)
+    #define TCP_STRERROR(err)           "socket error"
+    
+    typedef osal_mutex tcp_mutex_t;
+    typedef int tcp_timer_id_t;
+    
+#else
+    /* 使用标准POSIX环境 */
+    #include <pthread.h>
+    #include <unistd.h>
+    #include <sys/time.h>
+    
+    /* POSIX兼容性定义 */
+    #define TCP_MUTEX_INIT(mutex)       pthread_mutex_init(&(mutex), NULL)
+    #define TCP_MUTEX_DESTROY(mutex)    pthread_mutex_destroy(&(mutex))
+    #define TCP_MUTEX_LOCK(mutex)       pthread_mutex_lock(&(mutex))
+    #define TCP_MUTEX_UNLOCK(mutex)     pthread_mutex_unlock(&(mutex))
+    #define TCP_TIMER_CREATE(id, cb, arg, period, cycle) (*(id) = 0) /* 简化实现 */
+    #define TCP_TIMER_DELETE(id)        /* 简化实现 */
+    #define TCP_TASK_CREATE(func, arg, name, size) \
+        do { \
+            pthread_t thread_id; \
+            pthread_create(&thread_id, NULL, func, arg); \
+            pthread_detach(thread_id); \
+        } while(0)
+    #define TCP_SLEEP_MS(ms)            usleep((ms) * 1000)
+    #define TCP_STRERROR(err)           strerror(err)
+    
+    typedef pthread_mutex_t tcp_mutex_t;
+    typedef int tcp_timer_id_t;
+    
+
+#endif
+
+/* 全局测试管理器 */
+static tcp_test_manager_t g_tcp_test_manager = {0};
+static tcp_mutex_t g_tcp_stats_mutex;
+static bool g_tcp_test_initialized = false;
+
+/* 内部函数声明 */
+static ppp_error_t tcp_test_create_connection_thread(uint16_t conn_id);
+static void* tcp_test_connection_worker(void *arg);
+static ppp_error_t tcp_test_generate_data(uint16_t conn_id, uint32_t packet_id, 
+                                          uint8_t *buffer, uint32_t size);
+static uint32_t tcp_test_calculate_checksum(const uint8_t *data, uint32_t size);
+static bool tcp_test_verify_data(const uint8_t *sent_data, const uint8_t *recv_data, uint32_t size);
+static void tcp_test_stats_timer_callback(void *arg);
+static void tcp_test_signal_handler(int signum);
+static ppp_error_t tcp_test_connect_socket(int *sock_fd, const char *host, uint16_t port);
+
+/**
+ * @brief 初始化TCP测试
+ */
+ppp_error_t tcp_test_init(void)
+{
+    if (g_tcp_test_initialized) {
+        return PPP_ERR_OK;
+    }
+    
+    // 初始化互斥锁
+    if (TCP_MUTEX_INIT(g_tcp_stats_mutex) != 0) {
+        PPP_DEBUG_ERROR("Failed to initialize TCP test mutex");
+        return PPP_ERR_MEMORY;
+    }
+    
+    // 清零管理器
+    memset(&g_tcp_test_manager, 0, sizeof(g_tcp_test_manager));
+    
+    // 设置信号处理 (仅在POSIX环境下)
+#ifndef USE_LWIP_SOCKET
+    signal(SIGINT, tcp_test_signal_handler);
+    signal(SIGTERM, tcp_test_signal_handler);
+#endif
+    
+    g_tcp_test_initialized = true;
+    PPP_DEBUG_INFO("TCP test initialized successfully");
+    
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 反初始化TCP测试
+ */
+ppp_error_t tcp_test_deinit(void)
+{
+    if (!g_tcp_test_initialized) {
+        return PPP_ERR_OK;
+    }
+    
+    // 停止测试
+    tcp_test_stop();
+    
+    // 销毁互斥锁
+    TCP_MUTEX_DESTROY(g_tcp_stats_mutex);
+    
+    g_tcp_test_initialized = false;
+    PPP_DEBUG_INFO("TCP test deinitialized");
+    
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 启动TCP测试
+ */
+ppp_error_t tcp_test_start(const tcp_test_config_t *config)
+{
+    if (!g_tcp_test_initialized) {
+        PPP_DEBUG_ERROR("TCP test not initialized");
+        return PPP_ERR_INVALID_STATE;
+    }
+    
+    if (!config) {
+        PPP_DEBUG_ERROR("Invalid config parameter");
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    if (g_tcp_test_manager.global_stats.test_running) {
+        PPP_DEBUG_ERROR("TCP test already running");
+        return PPP_ERR_INVALID_STATE;
+    }
+    
+    // 复制配置
+    memcpy(&g_tcp_test_manager.config, config, sizeof(tcp_test_config_t));
+    
+    // 初始化全局统计
+    memset(&g_tcp_test_manager.global_stats, 0, sizeof(tcp_global_stats_t));
+    g_tcp_test_manager.global_stats.start_time = tcp_test_get_time_ms();
+    g_tcp_test_manager.global_stats.test_running = true;
+    g_tcp_test_manager.stop_flag = false;
+    
+    // 初始化连接统计
+    for (int i = 0; i < config->connection_count; i++) {
+        memset(&g_tcp_test_manager.connections[i], 0, sizeof(tcp_connection_stats_t));
+        g_tcp_test_manager.connections[i].conn_id = i;
+        g_tcp_test_manager.connections[i].socket_fd = -1;
+    }
+    
+    printf("TCP性能测试客户端\n");
+    printf("目标服务器: %s:%d\n", config->server_host, config->server_port);
+    printf("测试时间: %d 秒\n", config->test_duration);
+    printf("并发连接: %d\n", config->connection_count);
+    printf("数据包大小: %d-%d 字节\n", config->data_min_size, config->data_max_size);
+    printf("========================================\n");
+    
+    // 启动统计定时器
+    TCP_TIMER_CREATE(&g_tcp_test_manager.stats_timer_id, 
+                     tcp_test_stats_timer_callback, NULL,
+                     TCP_TEST_STATS_INTERVAL * 1000, 
+                     TCP_TEST_STATS_INTERVAL * 1000);
+    
+    // 创建连接线程
+    for (int i = 0; i < config->connection_count; i++) {
+        ppp_error_t ret = tcp_test_create_connection_thread(i);
+        if (ret != PPP_ERR_OK) {
+            PPP_DEBUG_ERROR("Failed to create connection thread %d", i);
+            tcp_test_stop();
+            return ret;
+        }
+        
+        // 错开连接启动时间
+        TCP_SLEEP_MS(100); // 100ms
+    }
+    
+    PPP_DEBUG_INFO("TCP test started with %d connections", config->connection_count);
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 停止TCP测试
+ */
+ppp_error_t tcp_test_stop(void)
+{
+    if (!g_tcp_test_manager.global_stats.test_running) {
+        return PPP_ERR_OK;
+    }
+    
+    printf("\n正在停止TCP测试...\n");
+    
+    // 设置停止标志
+    g_tcp_test_manager.stop_flag = true;
+    g_tcp_test_manager.global_stats.test_running = false;
+    g_tcp_test_manager.global_stats.end_time = tcp_test_get_time_ms();
+    
+    // 停止统计定时器
+    if (g_tcp_test_manager.stats_timer_id != 0) {
+        TCP_TIMER_DELETE(g_tcp_test_manager.stats_timer_id);
+        g_tcp_test_manager.stats_timer_id = 0;
+    }
+    
+    // 等待所有连接线程结束
+    printf("等待所有连接关闭...\n");
+    TCP_SLEEP_MS(2000); // 给线程时间退出
+    
+    // 强制关闭所有socket
+    for (int i = 0; i < g_tcp_test_manager.config.connection_count; i++) {
+        tcp_connection_stats_t *conn = &g_tcp_test_manager.connections[i];
+        if (conn->socket_fd >= 0) {
+            TCP_CLOSE(conn->socket_fd);
+            conn->socket_fd = -1;
+            conn->connected = false;
+        }
+    }
+    
+    // 打印最终报告
+    tcp_test_print_report();
+    
+    PPP_DEBUG_INFO("TCP test stopped");
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 获取测试状态
+ */
+bool tcp_test_is_running(void)
+{
+    return g_tcp_test_manager.global_stats.test_running;
+}
+
+/**
+ * @brief 获取全局统计信息
+ */
+ppp_error_t tcp_test_get_stats(tcp_global_stats_t *stats)
+{
+    if (!stats) {
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+    memcpy(stats, &g_tcp_test_manager.global_stats, sizeof(tcp_global_stats_t));
+    TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+    
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 创建连接线程
+ */
+static ppp_error_t tcp_test_create_connection_thread(uint16_t conn_id)
+{
+    uint16_t *arg = malloc(sizeof(uint16_t));
+    if (!arg) {
+        return PPP_ERR_MEMORY;
+    }
+    
+    *arg = conn_id;
+    
+    TCP_TASK_CREATE(tcp_test_connection_worker, arg, "tcp_test_conn", 8192);
+    
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 连接工作线程
+ */
+static void* tcp_test_connection_worker(void *arg)
+{
+    uint16_t conn_id = *(uint16_t*)arg;
+    free(arg);
+    
+    tcp_connection_stats_t *conn = &g_tcp_test_manager.connections[conn_id];
+    tcp_test_config_t *config = &g_tcp_test_manager.config;
+    
+    conn->thread_running = true;
+    
+    uint32_t connect_start = tcp_test_get_time_ms();
+    
+    // 建立连接
+    ppp_error_t ret = tcp_test_connect_socket(&conn->socket_fd, 
+                                             config->server_host, 
+                                             config->server_port);
+    
+    if (ret != PPP_ERR_OK) {
+        PPP_DEBUG_ERROR("[连接 %03d] 连接失败", conn_id);
+        TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+        g_tcp_test_manager.global_stats.failed_connections++;
+        TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+        conn->thread_running = false;
+        return NULL;
+    }
+    
+    conn->connected = true;
+    conn->connect_time_ms = tcp_test_get_time_ms() - connect_start;
+    
+    TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+    g_tcp_test_manager.global_stats.successful_connections++;
+    TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+    
+    printf("[连接 %03d] 连接成功,耗时 %d ms\n", conn_id, conn->connect_time_ms);
+    
+    // 数据传输循环
+    uint32_t packet_counter = 0;
+    uint8_t send_buffer[TCP_TEST_MAX_DATA_SIZE];
+    uint8_t recv_buffer[TCP_TEST_MAX_DATA_SIZE];
+    
+    uint32_t test_end_time = g_tcp_test_manager.global_stats.start_time + 
+                            (config->test_duration * 1000);
+    
+    while (!g_tcp_test_manager.stop_flag && 
+           tcp_test_get_time_ms() < test_end_time) {
+        
+        // 生成随机大小的测试数据
+        uint32_t data_size = config->data_min_size + 
+                            (rand() % (config->data_max_size - config->data_min_size + 1));
+        
+        // 生成测试数据
+        ret = tcp_test_generate_data(conn_id, packet_counter, send_buffer, data_size);
+        if (ret != PPP_ERR_OK) {
+            conn->errors++;
+            continue;
+        }
+        
+        // 发送数据
+        ssize_t bytes_sent = TCP_SEND(conn->socket_fd, send_buffer, data_size, 0);
+        if (bytes_sent != (ssize_t)data_size) {
+            if (bytes_sent < 0) {
+                PPP_DEBUG_ERROR("[连接 %03d] 发送失败: %s", conn_id, TCP_STRERROR(TCP_GET_ERRNO()));
+                conn->errors++;
+                break;
+            } else {
+                PPP_DEBUG_WARN("[连接 %03d] 发送不完整 (%ld/%d 字节)", 
+                              conn_id, bytes_sent, data_size);
+            }
+        }
+        
+        conn->packets_sent++;
+        conn->bytes_sent += bytes_sent;
+        
+        // 接收回显数据
+        ssize_t total_received = 0;
+        uint32_t recv_start = tcp_test_get_time_ms();
+        
+        while (total_received < data_size && 
+               (tcp_test_get_time_ms() - recv_start) < (TCP_TEST_RECV_TIMEOUT * 1000)) {
+            
+            ssize_t bytes_recv = TCP_RECV(conn->socket_fd, 
+                                        recv_buffer + total_received,
+                                        data_size - total_received,
+                                        0);
+            
+            if (bytes_recv > 0) {
+                total_received += bytes_recv;
+            } else if (bytes_recv == 0) {
+                PPP_DEBUG_WARN("[连接 %03d] 连接关闭", conn_id);
+                goto thread_exit;
+            } else {
+                int err = TCP_GET_ERRNO();
+                if (err != TCP_EAGAIN && err != TCP_EWOULDBLOCK) {
+                    PPP_DEBUG_ERROR("[连接 %03d] 接收失败: %s", conn_id, TCP_STRERROR(err));
+                    conn->errors++;
+                    goto thread_exit;
+                }
+            }
+            
+            TCP_SLEEP_MS(1); // 1ms延迟
+        }
+        
+        if (total_received == data_size) {
+            conn->packets_received++;
+            conn->bytes_received += total_received;
+            
+            // 验证数据完整性
+            if (!tcp_test_verify_data(send_buffer, recv_buffer, data_size)) {
+                conn->data_errors++;
+                TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+                g_tcp_test_manager.global_stats.data_verification_errors++;
+                TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+            }
+        } else {
+            PPP_DEBUG_WARN("[连接 %03d] 接收数据不完整: %ld/%d 字节", 
+                          conn_id, total_received, data_size);
+            conn->errors++;
+        }
+        
+        // 更新全局统计
+        TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+        g_tcp_test_manager.global_stats.total_packets_sent++;
+        g_tcp_test_manager.global_stats.total_bytes_sent += bytes_sent;
+        if (total_received == data_size) {
+            g_tcp_test_manager.global_stats.total_packets_received++;
+            g_tcp_test_manager.global_stats.total_bytes_received += total_received;
+        } else {
+            g_tcp_test_manager.global_stats.total_errors++;
+        }
+        TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+        
+        conn->last_activity_time = tcp_test_get_time_ms();
+        packet_counter++;
+        
+        // 控制发送频率
+        if (config->send_interval_ms > 0) {
+            TCP_SLEEP_MS(config->send_interval_ms);
+        } else {
+            TCP_SLEEP_MS((rand() % 10 + 1)); // 1-10ms随机延迟
+        }
+    }
+    
+thread_exit:
+    // 关闭连接
+    if (conn->socket_fd >= 0) {
+        TCP_CLOSE(conn->socket_fd);
+        conn->socket_fd = -1;
+    }
+    
+    conn->connected = false;
+    conn->thread_running = false;
+    
+    return NULL;
+}
+
+/**
+ * @brief 建立Socket连接
+ */
+static ppp_error_t tcp_test_connect_socket(int *sock_fd, const char *host, uint16_t port)
+{
+    int fd = TCP_SOCKET(TCP_AF_INET, TCP_SOCK_STREAM, 0);
+    if (fd < 0) {
+        PPP_DEBUG_ERROR("Failed to create socket: %s", TCP_STRERROR(TCP_GET_ERRNO()));
+        return PPP_ERR_UNKNOWN;
+    }
+    
+#ifndef USE_LWIP_SOCKET
+    // 设置连接超时 (仅在POSIX环境下)
+    struct timeval timeout;
+    timeout.tv_sec = TCP_TEST_CONNECT_TIMEOUT;
+    timeout.tv_usec = 0;
+    
+    if (TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0 ||
+        TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
+        PPP_DEBUG_WARN("Failed to set socket timeout");
+    }
+#else
+    // 在lwIP环境下设置超时 (使用简化方式)
+    int timeout_ms = TCP_TEST_CONNECT_TIMEOUT * 1000;
+    if (TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_RCVTIMEO, &timeout_ms, sizeof(timeout_ms)) < 0 ||
+        TCP_SETSOCKOPT(fd, TCP_SOL_SOCKET, TCP_SO_SNDTIMEO, &timeout_ms, sizeof(timeout_ms)) < 0) {
+        PPP_DEBUG_WARN("Failed to set socket timeout in lwIP");
+    }
+#endif
+    
+    struct sockaddr_in server_addr;
+    memset(&server_addr, 0, sizeof(server_addr));
+    server_addr.sin_family = TCP_AF_INET;
+    server_addr.sin_port = TCP_HTONS(port);
+    
+    if (TCP_INET_PTON(TCP_AF_INET, host, &server_addr.sin_addr) <= 0) {
+        PPP_DEBUG_ERROR("Invalid server address: %s", host);
+        TCP_CLOSE(fd);
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    if (TCP_CONNECT(fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
+        PPP_DEBUG_ERROR("Failed to connect to %s:%d: %s", host, port, TCP_STRERROR(TCP_GET_ERRNO()));
+        TCP_CLOSE(fd);
+        return PPP_ERR_UNKNOWN;
+    }
+    
+    *sock_fd = fd;
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 生成测试数据
+ */
+static ppp_error_t tcp_test_generate_data(uint16_t conn_id, uint32_t packet_id, 
+                                          uint8_t *buffer, uint32_t size)
+{
+    if (!buffer || size < sizeof(tcp_test_packet_header_t)) {
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    tcp_test_packet_header_t *header = (tcp_test_packet_header_t*)buffer;
+    header->conn_id = TCP_HTONS(conn_id);
+    header->packet_id = TCP_HTONL(packet_id);
+    header->data_size = TCP_HTONS(size);
+    header->timestamp = TCP_HTONL(tcp_test_get_time_ms());
+    
+    // 填充随机数据
+    for (uint32_t i = sizeof(tcp_test_packet_header_t); i < size - sizeof(uint32_t); i++) {
+        buffer[i] = rand() & 0xFF;
+    }
+    
+    // 计算校验和
+    header->checksum = TCP_HTONL(tcp_test_calculate_checksum(buffer, size - sizeof(uint32_t)));
+    
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 计算校验和
+ */
+static uint32_t tcp_test_calculate_checksum(const uint8_t *data, uint32_t size)
+{
+    uint32_t checksum = 0;
+    for (uint32_t i = 0; i < size; i++) {
+        checksum += data[i];
+    }
+    return checksum;
+}
+
+/**
+ * @brief 验证数据完整性
+ */
+static bool tcp_test_verify_data(const uint8_t *sent_data, const uint8_t *recv_data, uint32_t size)
+{
+    return memcmp(sent_data, recv_data, size) == 0;
+}
+
+/**
+ * @brief 统计定时器回调
+ */
+static void tcp_test_stats_timer_callback(void *arg)
+{
+    (void)arg;
+    
+    if (!g_tcp_test_manager.global_stats.test_running) {
+        return;
+    }
+    
+    uint32_t current_time = tcp_test_get_time_ms();
+    uint32_t elapsed = current_time - g_tcp_test_manager.global_stats.start_time;
+    uint32_t remaining = 0;
+    
+    if (elapsed < g_tcp_test_manager.config.test_duration * 1000) {
+        remaining = (g_tcp_test_manager.config.test_duration * 1000 - elapsed) / 1000;
+    }
+    
+    // 统计活跃连接
+    int active_connections = 0;
+    for (int i = 0; i < g_tcp_test_manager.config.connection_count; i++) {
+        if (g_tcp_test_manager.connections[i].connected) {
+            active_connections++;
+        }
+    }
+    
+    TCP_MUTEX_LOCK(g_tcp_stats_mutex);
+    
+    char bytes_buf[64];
+    printf("\n=== 实时统计 (已运行: %ds, 剩余: %ds) ===\n", elapsed/1000, remaining);
+    printf("活跃连接: %d\n", active_connections);
+    printf("成功连接: %d\n", g_tcp_test_manager.global_stats.successful_connections);
+    printf("失败连接: %d\n", g_tcp_test_manager.global_stats.failed_connections);
+    printf("发送包数: %llu\n", g_tcp_test_manager.global_stats.total_packets_sent);
+    printf("接收包数: %llu\n", g_tcp_test_manager.global_stats.total_packets_received);
+    printf("发送数据: %s\n", tcp_test_format_bytes(g_tcp_test_manager.global_stats.total_bytes_sent, 
+                                                   bytes_buf, sizeof(bytes_buf)));
+    
+    // 计算当前吞吐量
+    if (elapsed > 0) {
+        uint64_t throughput = (g_tcp_test_manager.global_stats.total_bytes_sent * 1000) / elapsed;
+        printf("平均吞吐量: %s/s\n", tcp_test_format_bytes(throughput, bytes_buf, sizeof(bytes_buf)));
+    }
+    
+    printf("错误总数: %d\n", g_tcp_test_manager.global_stats.total_errors);
+    printf("==========================================\n");
+    
+    TCP_MUTEX_UNLOCK(g_tcp_stats_mutex);
+}
+
+/**
+ * @brief 获取当前时间(毫秒) - 导出函数
+ */
+uint32_t tcp_test_get_time_ms(void)
+{
+#ifdef USE_LWIP_SOCKET
+    /* 在lwIP环境中尝试使用真实的时间函数 */
+    #ifdef OSAL_TIME_AVAILABLE
+        /* 如果OSAL时间函数可用,使用它 */
+        return osal_get_time_ms();
+    #else
+        /* 否则使用简化的时间模拟 */
+        static uint32_t start_time = 0;
+        static uint32_t last_time = 0;
+        
+        if (start_time == 0) {
+            start_time = 1000; /* 从1秒开始 */
+            last_time = start_time;
+        }
+        
+        /* 每次调用增加约1-10ms的随机时间 */
+        last_time += (rand() % 10 + 1);
+        return last_time;
+    #endif
+#else
+    /* 在POSIX环境中使用标准gettimeofday */
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+#endif
+}
+
+/**
+ * @brief 信号处理函数
+ */
+static void tcp_test_signal_handler(int signum)
+{
+    printf("\n收到信号 %d,正在停止测试...\n", signum);
+    tcp_test_stop();
+}
+
+/**
+ * @brief 格式化字节数显示
+ */
+const char* tcp_test_format_bytes(uint64_t bytes, char *buffer, size_t buffer_size)
+{
+    if (!buffer || buffer_size == 0) {
+        return "N/A";
+    }
+    
+    if (bytes < 1024) {
+        snprintf(buffer, buffer_size, "%llu B", bytes);
+    } else if (bytes < 1024 * 1024) {
+        snprintf(buffer, buffer_size, "%.1f KB", bytes / 1024.0);
+    } else if (bytes < 1024ULL * 1024 * 1024) {
+        snprintf(buffer, buffer_size, "%.1f MB", bytes / (1024.0 * 1024));
+    } else {
+        snprintf(buffer, buffer_size, "%.1f GB", bytes / (1024.0 * 1024 * 1024));
+    }
+    
+    return buffer;
+}
+
+/**
+ * @brief 打印测试报告
+ */
+ppp_error_t tcp_test_print_report(void)
+{
+    uint32_t total_duration = g_tcp_test_manager.global_stats.end_time - 
+                             g_tcp_test_manager.global_stats.start_time;
+    
+    printf("\n========================================\n");
+    printf("                最终测试报告\n");
+    printf("========================================\n");
+    
+    printf("测试配置:\n");
+    printf("  服务器地址: %s:%d\n", g_tcp_test_manager.config.server_host, 
+           g_tcp_test_manager.config.server_port);
+    printf("  测试时长: %d 秒 (实际: %.2f 秒)\n", 
+           g_tcp_test_manager.config.test_duration, total_duration / 1000.0);
+    printf("  并发连接数: %d\n", g_tcp_test_manager.config.connection_count);
+    
+    printf("\n连接统计:\n");
+    printf("  成功连接: %d\n", g_tcp_test_manager.global_stats.successful_connections);
+    printf("  失败连接: %d\n", g_tcp_test_manager.global_stats.failed_connections);
+    
+    if (g_tcp_test_manager.config.connection_count > 0) {
+        printf("  连接成功率: %.1f%%\n", 
+               (float)g_tcp_test_manager.global_stats.successful_connections / 
+               g_tcp_test_manager.config.connection_count * 100);
+    }
+    
+    printf("\n数据传输统计:\n");
+    printf("  发送包数: %llu\n", g_tcp_test_manager.global_stats.total_packets_sent);
+    printf("  接收包数: %llu\n", g_tcp_test_manager.global_stats.total_packets_received);
+    
+    if (g_tcp_test_manager.global_stats.total_packets_sent > 0) {
+        printf("  包传输成功率: %.1f%%\n",
+               (float)g_tcp_test_manager.global_stats.total_packets_received / 
+               g_tcp_test_manager.global_stats.total_packets_sent * 100);
+    }
+    
+    char bytes_buf[64];
+    printf("  发送数据总量: %s\n", 
+           tcp_test_format_bytes(g_tcp_test_manager.global_stats.total_bytes_sent, 
+                                bytes_buf, sizeof(bytes_buf)));
+    printf("  接收数据总量: %s\n",
+           tcp_test_format_bytes(g_tcp_test_manager.global_stats.total_bytes_received, 
+                                bytes_buf, sizeof(bytes_buf)));
+    
+    if (total_duration > 0) {
+        uint64_t avg_throughput = (g_tcp_test_manager.global_stats.total_bytes_sent * 1000) / total_duration;
+        float avg_pps = (float)g_tcp_test_manager.global_stats.total_packets_sent * 1000 / total_duration;
+        
+        printf("\n性能统计:\n");
+        printf("  平均吞吐量: %s/s\n", tcp_test_format_bytes(avg_throughput, bytes_buf, sizeof(bytes_buf)));
+        printf("  平均包速率: %.1f 包/秒\n", avg_pps);
+        
+        if (g_tcp_test_manager.global_stats.total_packets_sent > 0) {
+            printf("  平均包大小: %.1f 字节\n", 
+                   (float)g_tcp_test_manager.global_stats.total_bytes_sent / 
+                   g_tcp_test_manager.global_stats.total_packets_sent);
+        }
+    }
+    
+    printf("\n错误统计:\n");
+    printf("  传输错误: %d\n", g_tcp_test_manager.global_stats.total_errors);
+    printf("  数据校验错误: %d\n", g_tcp_test_manager.global_stats.data_verification_errors);
+    
+    if (g_tcp_test_manager.global_stats.total_packets_sent > 0) {
+        printf("  错误率: %.3f%%\n",
+               (float)g_tcp_test_manager.global_stats.total_errors / 
+               g_tcp_test_manager.global_stats.total_packets_sent * 100);
+    }
+    
+    printf("========================================\n");
+    
+    return PPP_ERR_OK;
+} 
\ No newline at end of file
diff --git a/code/sdk/zhihui/ppp/example/ppp_tcp_test_main.c b/code/sdk/zhihui/ppp/example/ppp_tcp_test_main.c
new file mode 100644 (file)
index 0000000..bb45519
--- /dev/null
@@ -0,0 +1,264 @@
+/**
+ * @file ppp_tcp_test_main.c
+ * @brief PPP TCP性能测试客户端主程序
+ * 
+ * 提供命令行参数解析和测试程序入口
+ * 支持与Python版本相同的参数格式
+ */
+
+#include "ppp_tcp_test.h"
+#include "ppp_debug.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+
+/**
+ * @brief 打印使用帮助
+ */
+void tcp_test_print_help(void)
+{
+    printf("TCP性能测试客户端\n");
+    printf("用法: tcp_test [选项]\n\n");
+    printf("选项:\n");
+    printf("  -H, --host <地址>      服务器地址 (默认: %s)\n", TCP_TEST_DEFAULT_HOST);
+    printf("  -P, --port <端口>      服务器端口 (默认: %d)\n", TCP_TEST_DEFAULT_PORT);
+    printf("  -t, --time <秒数>      测试时间(秒) (默认: %d)\n", TCP_TEST_DEFAULT_TIME);
+    printf("  -c, --connections <数量> 并发连接数 (默认: %d, 最大: %d)\n", 
+           TCP_TEST_DEFAULT_CONNECTIONS, TCP_TEST_MAX_CONNECTIONS);
+    printf("  -v, --verbose          详细输出模式\n");
+    printf("  -i, --interval <毫秒>  发送间隔(毫秒) (默认: 自动)\n");
+    printf("  --min-size <字节>      最小数据包大小 (默认: %d)\n", TCP_TEST_MIN_DATA_SIZE);
+    printf("  --max-size <字节>      最大数据包大小 (默认: %d)\n", TCP_TEST_MAX_DATA_SIZE);
+    printf("  -h, --help             显示此帮助信息\n\n");
+    printf("示例:\n");
+    printf("  tcp_test --host 192.168.1.100 --port 8080 --connections 5 --time 60\n");
+    printf("  tcp_test -H 110.42.224.129 -P 8910 -c 10 -t 30 -v\n");
+    printf("  tcp_test --host echo.server.com --port 7777 --verbose\n\n");
+    printf("说明:\n");
+    printf("  - 测试需要服务器支持TCP回显(echo)功能\n");
+    printf("  - 程序会发送测试数据并验证服务器返回的回显数据\n");
+    printf("  - 使用Ctrl+C可以提前终止测试\n");
+}
+
+/**
+ * @brief 解析命令行参数
+ */
+ppp_error_t tcp_test_parse_args(int argc, char *argv[], tcp_test_config_t *config)
+{
+    if (!config) {
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    // 设置默认值
+    strncpy(config->server_host, TCP_TEST_DEFAULT_HOST, sizeof(config->server_host) - 1);
+    config->server_host[sizeof(config->server_host) - 1] = '\0';
+    config->server_port = TCP_TEST_DEFAULT_PORT;
+    config->test_duration = TCP_TEST_DEFAULT_TIME;
+    config->connection_count = TCP_TEST_DEFAULT_CONNECTIONS;
+    config->verbose = false;
+    config->send_interval_ms = 0; // 自动
+    config->data_min_size = TCP_TEST_MIN_DATA_SIZE;
+    config->data_max_size = TCP_TEST_MAX_DATA_SIZE;
+    
+    // 长选项定义
+    static struct option long_options[] = {
+        {"host",        required_argument, 0, 'H'},
+        {"port",        required_argument, 0, 'P'},
+        {"time",        required_argument, 0, 't'},
+        {"connections", required_argument, 0, 'c'},
+        {"verbose",     no_argument,       0, 'v'},
+        {"interval",    required_argument, 0, 'i'},
+        {"min-size",    required_argument, 0, 1000},
+        {"max-size",    required_argument, 0, 1001},
+        {"help",        no_argument,       0, 'h'},
+        {0, 0, 0, 0}
+    };
+    
+    int option_index = 0;
+    int c;
+    
+    while ((c = getopt_long(argc, argv, "H:P:t:c:vi:h", long_options, &option_index)) != -1) {
+        switch (c) {
+        case 'H':
+            strncpy(config->server_host, optarg, sizeof(config->server_host) - 1);
+            config->server_host[sizeof(config->server_host) - 1] = '\0';
+            break;
+            
+        case 'P':
+            {
+                int port = atoi(optarg);
+                if (port < 1 || port > 65535) {
+                    fprintf(stderr, "错误: 端口号必须在 1-65535 范围内\n");
+                    return PPP_ERR_INVALID_PARAM;
+                }
+                config->server_port = (uint16_t)port;
+            }
+            break;
+            
+        case 't':
+            {
+                int time = atoi(optarg);
+                if (time < 1) {
+                    fprintf(stderr, "错误: 测试时间必须大于0秒\n");
+                    return PPP_ERR_INVALID_PARAM;
+                }
+                config->test_duration = (uint32_t)time;
+            }
+            break;
+            
+        case 'c':
+            {
+                int connections = atoi(optarg);
+                if (connections < 1 || connections > TCP_TEST_MAX_CONNECTIONS) {
+                    fprintf(stderr, "错误: 连接数必须在 1-%d 范围内\n", TCP_TEST_MAX_CONNECTIONS);
+                    return PPP_ERR_INVALID_PARAM;
+                }
+                config->connection_count = (uint16_t)connections;
+            }
+            break;
+            
+        case 'v':
+            config->verbose = true;
+            break;
+            
+        case 'i':
+            {
+                int interval = atoi(optarg);
+                if (interval < 0) {
+                    fprintf(stderr, "错误: 发送间隔不能为负数\n");
+                    return PPP_ERR_INVALID_PARAM;
+                }
+                config->send_interval_ms = (uint32_t)interval;
+            }
+            break;
+            
+        case 1000: // --min-size
+            {
+                int min_size = atoi(optarg);
+                if (min_size < 1 || min_size > TCP_TEST_MAX_DATA_SIZE) {
+                    fprintf(stderr, "错误: 最小数据包大小必须在 1-%d 范围内\n", TCP_TEST_MAX_DATA_SIZE);
+                    return PPP_ERR_INVALID_PARAM;
+                }
+                config->data_min_size = (uint32_t)min_size;
+            }
+            break;
+            
+        case 1001: // --max-size
+            {
+                int max_size = atoi(optarg);
+                if (max_size < 1 || max_size > TCP_TEST_MAX_DATA_SIZE) {
+                    fprintf(stderr, "错误: 最大数据包大小必须在 1-%d 范围内\n", TCP_TEST_MAX_DATA_SIZE);
+                    return PPP_ERR_INVALID_PARAM;
+                }
+                config->data_max_size = (uint32_t)max_size;
+            }
+            break;
+            
+        case 'h':
+            tcp_test_print_help();
+            exit(0);
+            break;
+            
+        case '?':
+            fprintf(stderr, "未知选项。使用 -h 或 --help 查看帮助信息。\n");
+            return PPP_ERR_INVALID_PARAM;
+            
+        default:
+            return PPP_ERR_INVALID_PARAM;
+        }
+    }
+    
+    // 验证参数逻辑
+    if (config->data_min_size > config->data_max_size) {
+        fprintf(stderr, "错误: 最小数据包大小不能大于最大数据包大小\n");
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    if (config->data_min_size < sizeof(tcp_test_packet_header_t)) {
+        fprintf(stderr, "错误: 最小数据包大小至少需要 %lu 字节 (包头大小)\n", 
+                sizeof(tcp_test_packet_header_t));
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 打印配置信息
+ */
+static void print_config(const tcp_test_config_t *config)
+{
+    printf("测试配置:\n");
+    printf("  服务器: %s:%d\n", config->server_host, config->server_port);
+    printf("  测试时间: %d 秒\n", config->test_duration);
+    printf("  并发连接: %d\n", config->connection_count);
+    printf("  数据包大小: %d-%d 字节\n", config->data_min_size, config->data_max_size);
+    printf("  详细输出: %s\n", config->verbose ? "是" : "否");
+    
+    if (config->send_interval_ms > 0) {
+        printf("  发送间隔: %d 毫秒\n", config->send_interval_ms);
+    } else {
+        printf("  发送间隔: 自动(1-10毫秒随机)\n");
+    }
+    printf("\n");
+}
+
+/**
+ * @brief 主函数
+ */
+int main(int argc, char *argv[])
+{
+    tcp_test_config_t config;
+    ppp_error_t ret;
+    
+    printf("PPP TCP性能测试客户端 v1.0\n");
+    printf("基于Python版本tcp_test_client.py实现\n\n");
+    
+    // 解析命令行参数
+    ret = tcp_test_parse_args(argc, argv, &config);
+    if (ret != PPP_ERR_OK) {
+        fprintf(stderr, "参数解析失败\n");
+        return 1;
+    }
+    
+    // 显示配置
+    print_config(&config);
+    
+    // 初始化TCP测试
+    ret = tcp_test_init();
+    if (ret != PPP_ERR_OK) {
+        fprintf(stderr, "TCP测试初始化失败: %d\n", ret);
+        return 1;
+    }
+    
+    // 启动测试
+    ret = tcp_test_start(&config);
+    if (ret != PPP_ERR_OK) {
+        fprintf(stderr, "TCP测试启动失败: %d\n", ret);
+        tcp_test_deinit();
+        return 1;
+    }
+    
+    // 等待测试完成
+    printf("测试运行中,使用 Ctrl+C 可提前停止...\n\n");
+    
+    // 等待测试时间结束
+    uint32_t test_end_time = time(NULL) + config.test_duration;
+    while (tcp_test_is_running() && time(NULL) < test_end_time) {
+        sleep(1);
+    }
+    
+    // 停止测试
+    if (tcp_test_is_running()) {
+        printf("\n测试时间到达,正在停止...\n");
+        tcp_test_stop();
+    }
+    
+    // 清理资源
+    tcp_test_deinit();
+    
+    printf("\nTCP性能测试完成。\n");
+    return 0;
+} 
\ No newline at end of file
index a2f9704..188bdb6 100644 (file)
@@ -30,7 +30,7 @@ extern "C" {
 #define PPP_UART_BAUDRATE          2000000
 
 /* 支持的波特率列表(自适应模式) */
-#define PPP_BAUDRATE_AUTO_LIST      {9600, 57600, 115200, 921600}
+#define PPP_BAUDRATE_AUTO_LIST      {9600, 57600, 115200}
 #define PPP_BAUDRATE_AUTO_COUNT     4
 
 /* 支持的固定波特率列表 */
@@ -63,7 +63,7 @@ extern "C" {
 
 /* 调试配置 */
 #define PPP_DEBUG_ENABLE            1                   // 启用调试输出
-#define PPP_DEBUG_LEVEL             PPP_DEBUG_LEVEL_DEBUG // 默认只显示警告和错误 (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
+#define PPP_DEBUG_LEVEL             PPP_DEBUG_LEVEL_WARN // 默认只显示警告和错误 (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
 
 /*
  * 调试级别说明:
index 5971ea3..ecf7b4a 100644 (file)
@@ -18,37 +18,40 @@ extern "C" {
 
 #if PPP_DEBUG_ENABLE
 
+/* 前向声明动态调试级别函数 */
+extern int ppp_debug_get_level(void);
+
 #define PPP_DEBUG_ERROR(fmt, ...) \
     do { \
-        if (PPP_DEBUG_LEVEL >= PPP_DEBUG_LEVEL_ERROR) { \
+        if (ppp_debug_get_level() >= PPP_DEBUG_LEVEL_ERROR) { \
             PRINT("[PPP ERROR] " fmt "\r\n", ##__VA_ARGS__); \
         } \
     } while(0)
 
 #define PPP_DEBUG_WARN(fmt, ...) \
     do { \
-        if (PPP_DEBUG_LEVEL >= PPP_DEBUG_LEVEL_WARN) { \
+        if (ppp_debug_get_level() >= PPP_DEBUG_LEVEL_WARN) { \
             PRINT("[PPP WARN] " fmt "\r\n", ##__VA_ARGS__); \
         } \
     } while(0)
 
 #define PPP_DEBUG_INFO(fmt, ...) \
     do { \
-        if (PPP_DEBUG_LEVEL >= PPP_DEBUG_LEVEL_INFO) { \
+        if (ppp_debug_get_level() >= PPP_DEBUG_LEVEL_INFO) { \
             PRINT("[PPP INFO] " fmt "\r\n", ##__VA_ARGS__); \
         } \
     } while(0)
 
 #define PPP_DEBUG_DEBUG(fmt, ...) \
     do { \
-        if (PPP_DEBUG_LEVEL >= PPP_DEBUG_LEVEL_DEBUG) { \
+        if (ppp_debug_get_level() >= PPP_DEBUG_LEVEL_DEBUG) { \
             PRINT("[PPP DEBUG] " fmt "\r\n", ##__VA_ARGS__); \
         } \
     } while(0)
 
 #define PPP_DEBUG_HEXDUMP(data, len) \
     do { \
-        if (PPP_DEBUG_LEVEL >= PPP_DEBUG_LEVEL_DEBUG) { \
+        if (ppp_debug_get_level() >= PPP_DEBUG_LEVEL_DEBUG) { \
             ppp_debug_hexdump(data, len); \
         } \
     } while(0)
@@ -56,7 +59,7 @@ extern "C" {
 /* 兼容性宏 - 用于旧代码 */
 #define PPP_DEBUG_PRINT(fmt, ...) \
     do { \
-    if (PPP_DEBUG_LEVEL >= PPP_DEBUG_LEVEL_INFO) { \
+    if (ppp_debug_get_level() >= PPP_DEBUG_LEVEL_INFO) { \
         print_str(fmt, ##__VA_ARGS__); \
     } \
     } while(0)  
diff --git a/code/sdk/zhihui/ppp/include/ppp_debug_manager.h b/code/sdk/zhihui/ppp/include/ppp_debug_manager.h
new file mode 100644 (file)
index 0000000..a92f872
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * @file ppp_debug_manager.h
+ * @brief PPP调试级别动态管理模块头文件
+ */
+
+#ifndef PPP_DEBUG_MANAGER_H
+#define PPP_DEBUG_MANAGER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "ppp_types.h"
+
+/**
+ * @brief 获取当前动态调试级别
+ * @return 当前调试级别
+ */
+int ppp_debug_get_level(void);
+
+/**
+ * @brief 设置动态调试级别
+ * @param level 调试级别 (0-4)
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t ppp_debug_set_level(int level);
+
+/**
+ * @brief 获取调试级别名称
+ * @param level 调试级别
+ * @return 级别名称字符串
+ */
+const char* ppp_debug_get_level_name(int level);
+
+/**
+ * @brief 根据名称设置调试级别
+ * @param level_name 级别名称 ("NONE", "ERROR", "WARN", "INFO", "DEBUG")
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t ppp_debug_set_level_by_name(const char* level_name);
+
+/**
+ * @brief 重置调试级别为默认值
+ * @return PPP_ERR_OK-成功
+ */
+ppp_error_t ppp_debug_reset_level(void);
+
+/**
+ * @brief 检查指定级别是否启用
+ * @param level 要检查的级别
+ * @return true-启用,false-未启用
+ */
+bool ppp_debug_is_level_enabled(int level);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PPP_DEBUG_MANAGER_H */ 
\ No newline at end of file
index f31b3a9..b5c44bc 100644 (file)
@@ -102,6 +102,30 @@ ppp_error_t ppp_lwip_get_network_info(ppp_lwip_network_info_t *info);
  */
 struct netif *ppp_lwip_get_netif(void);
 
+
+/**
+ * @brief 获取本地IP地址字符串
+ * @return IP地址字符串(静态缓冲区,非线程安全)
+ */
+const char* ppp_lwip_get_ip_address(void);
+
+/**
+ * @brief 获取子网掩码字符串
+ * @return 子网掩码字符串(静态缓冲区,非线程安全)
+ */
+const char* ppp_lwip_get_netmask(void);
+
+/**
+ * @brief 获取网关地址字符串
+ * @return 网关地址字符串(静态缓冲区,非线程安全)
+ */
+const char* ppp_lwip_get_gateway(void);
+
+/**
+ * @brief 获取DNS服务器地址字符串(主/备,用逗号分隔)
+ * @return DNS地址字符串(静态缓冲区,非线程安全)
+ */
+const char* ppp_lwip_get_dns(void);
 #ifdef __cplusplus
 }
 #endif
diff --git a/code/sdk/zhihui/ppp/include/ppp_tcp_lwip_compat.h b/code/sdk/zhihui/ppp/include/ppp_tcp_lwip_compat.h
new file mode 100644 (file)
index 0000000..eb7f039
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+ * @file ppp_tcp_lwip_compat.h
+ * @brief lwIP socket接口兼容性定义
+ * 
+ * 处理lwIP socket接口中可能缺失的定义和兼容性问题
+ */
+
+#ifndef PPP_TCP_LWIP_COMPAT_H
+#define PPP_TCP_LWIP_COMPAT_H
+
+#ifdef USE_LWIP_SOCKET
+
+#include "lwip/sockets.h"
+#include "lwip/netdb.h"
+
+/* 确保必要的socket结构体可用 */
+#ifndef AF_INET
+#define AF_INET         2
+#endif
+
+#ifndef SOCK_STREAM
+#define SOCK_STREAM     1
+#endif
+
+#ifndef SOL_SOCKET
+#define SOL_SOCKET      1
+#endif
+
+/* 如果lwIP没有定义这些错误码,提供默认值 */
+#ifndef EAGAIN
+#define EAGAIN          11
+#endif
+
+#ifndef EWOULDBLOCK
+#define EWOULDBLOCK     EAGAIN
+#endif
+
+#ifndef EINTR
+#define EINTR           4
+#endif
+
+#ifndef ECONNRESET
+#define ECONNRESET      104
+#endif
+
+#ifndef ETIMEDOUT
+#define ETIMEDOUT       110
+#endif
+
+/* 如果lwIP没有定义这些socket选项,提供默认值 */
+#ifndef SO_RCVTIMEO
+#define SO_RCVTIMEO     20
+#endif
+
+#ifndef SO_SNDTIMEO
+#define SO_SNDTIMEO     21
+#endif
+
+/* 如果lwIP没有定义inet_pton,提供简化实现 */
+#ifndef LWIP_INET_PTON
+static inline int lwip_inet_pton_simple(int af, const char *src, void *dst)
+{
+    if (af != AF_INET) {
+        return -1;
+    }
+    
+    /* 简化的IPv4地址解析 */
+    unsigned int a, b, c, d;
+    if (sscanf(src, "%u.%u.%u.%u", &a, &b, &c, &d) == 4) {
+        if (a <= 255 && b <= 255 && c <= 255 && d <= 255) {
+            uint32_t *addr = (uint32_t*)dst;
+            *addr = (a << 24) | (b << 16) | (c << 8) | d;
+            *addr = lwip_htonl(*addr);
+            return 1;
+        }
+    }
+    return 0;
+}
+#define lwip_inet_pton lwip_inet_pton_simple
+#endif
+
+/* 确保必要的字节序转换函数存在 */
+// #ifndef lwip_htons
+// #define lwip_htons(x) htons(x)
+// #endif
+
+// #ifndef lwip_htonl
+// #define lwip_htonl(x) htonl(x)
+// #endif
+
+// #ifndef lwip_ntohs
+// #define lwip_ntohs(x) ntohs(x)
+// #endif
+
+// #ifndef lwip_ntohl
+// #define lwip_ntohl(x) ntohl(x)
+// #endif
+
+/* errno处理 */
+#ifndef errno
+extern int errno;
+#endif
+
+#endif /* USE_LWIP_SOCKET */
+
+#endif /* PPP_TCP_LWIP_COMPAT_H */ 
\ No newline at end of file
diff --git a/code/sdk/zhihui/ppp/include/ppp_tcp_test.h b/code/sdk/zhihui/ppp/include/ppp_tcp_test.h
new file mode 100644 (file)
index 0000000..fe92f1b
--- /dev/null
@@ -0,0 +1,266 @@
+/**
+ * @file ppp_tcp_test.h
+ * @brief PPP TCP性能测试客户端头文件
+ * 
+ * 功能:
+ * - 支持参数配置:服务器地址、端口、测试时间、连接数
+ * - 多连接并发测试
+ * - 性能统计和报告
+ * - 数据发送和接收验证
+ */
+
+#ifndef PPP_TCP_TEST_H
+#define PPP_TCP_TEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include "ppp_types.h"
+#define USE_LWIP_SOCKET 
+
+/* Socket接口兼容性宏定义 */
+#ifdef USE_LWIP_SOCKET
+    /* 使用lwIP的socket接口 */
+    #include "lwip/sockets.h"
+    #include "lwip/netdb.h"
+    #include "lwip/sys.h"
+    #include "ppp_tcp_lwip_compat.h"  /* 兼容性定义 */
+    
+    #define TCP_SOCKET(domain, type, protocol)  lwip_socket(domain, type, protocol)
+    #define TCP_CONNECT(s, name, namelen)       lwip_connect(s, name, namelen)
+    #define TCP_SEND(s, dataptr, size, flags)   lwip_send(s, dataptr, size, flags)
+    #define TCP_RECV(s, mem, len, flags)        lwip_recv(s, mem, len, flags)
+    #define TCP_CLOSE(s)                        lwip_close(s)
+    #define TCP_SETSOCKOPT(s, level, optname, optval, optlen) lwip_setsockopt(s, level, optname, optval, optlen)
+    #define TCP_GETSOCKOPT(s, level, optname, optval, optlen) lwip_getsockopt(s, level, optname, optval, optlen)
+    #define TCP_INET_PTON(af, src, dst)         lwip_inet_pton(af, src, dst)
+    #define TCP_HTONS(n)                        lwip_htons(n)
+    #define TCP_HTONL(n)                        lwip_htonl(n)
+    #define TCP_NTOHS(n)                        lwip_ntohs(n)
+    #define TCP_NTOHL(n)                        lwip_ntohl(n)
+    
+    /* lwIP错误码定义 */
+    #define TCP_EAGAIN          EAGAIN
+    #define TCP_EWOULDBLOCK     EWOULDBLOCK
+    #define TCP_EINTR           EINTR
+    #define TCP_ECONNRESET      ECONNRESET
+    #define TCP_ETIMEDOUT       ETIMEDOUT
+    
+    /* lwIP socket选项 */
+    #define TCP_SOL_SOCKET      SOL_SOCKET
+    #define TCP_SO_RCVTIMEO     SO_RCVTIMEO
+    #define TCP_SO_SNDTIMEO     SO_SNDTIMEO
+    #define TCP_AF_INET         AF_INET
+    #define TCP_SOCK_STREAM     SOCK_STREAM
+    
+    /* 获取错误号 */
+    #define TCP_GET_ERRNO()     errno
+    
+#else
+    /* 使用标准socket接口 */
+    #include <sys/socket.h>
+    #include <netinet/in.h>
+    #include <arpa/inet.h>
+    #include <netdb.h>
+    #include <errno.h>
+    #include <unistd.h>
+    
+    #define TCP_SOCKET(domain, type, protocol)  socket(domain, type, protocol)
+    #define TCP_CONNECT(s, name, namelen)       connect(s, name, namelen)
+    #define TCP_SEND(s, dataptr, size, flags)   send(s, dataptr, size, flags)
+    #define TCP_RECV(s, mem, len, flags)        recv(s, mem, len, flags)
+    #define TCP_CLOSE(s)                        close(s)
+    #define TCP_SETSOCKOPT(s, level, optname, optval, optlen) setsockopt(s, level, optname, optval, optlen)
+    #define TCP_GETSOCKOPT(s, level, optname, optval, optlen) getsockopt(s, level, optname, optval, optlen)
+    #define TCP_INET_PTON(af, src, dst)         inet_pton(af, src, dst)
+    #define TCP_HTONS(n)                        htons(n)
+    #define TCP_HTONL(n)                        htonl(n)
+    #define TCP_NTOHS(n)                        ntohs(n)
+    #define TCP_NTOHL(n)                        ntohl(n)
+    
+    /* 标准错误码定义 */
+    #define TCP_EAGAIN          EAGAIN
+    #define TCP_EWOULDBLOCK     EWOULDBLOCK
+    #define TCP_EINTR           EINTR
+    #define TCP_ECONNRESET      ECONNRESET
+    #define TCP_ETIMEDOUT       ETIMEDOUT
+    
+    /* 标准socket选项 */
+    #define TCP_SOL_SOCKET      SOL_SOCKET
+    #define TCP_SO_RCVTIMEO     SO_RCVTIMEO
+    #define TCP_SO_SNDTIMEO     SO_SNDTIMEO
+    #define TCP_AF_INET         AF_INET
+    #define TCP_SOCK_STREAM     SOCK_STREAM
+    
+    /* 获取错误号 */
+    #define TCP_GET_ERRNO()     errno
+    
+#endif
+
+/* TCP测试配置 */
+#define TCP_TEST_MAX_CONNECTIONS    50      // 最大连接数
+#define TCP_TEST_MIN_DATA_SIZE      1       // 最小数据包大小
+#define TCP_TEST_MAX_DATA_SIZE      4096    // 最大数据包大小
+#define TCP_TEST_STATS_INTERVAL     5       // 统计报告间隔(秒)
+#define TCP_TEST_CONNECT_TIMEOUT    10      // 连接超时时间(秒)
+#define TCP_TEST_RECV_TIMEOUT       1       // 接收超时时间(秒)
+#define TCP_TEST_DEFAULT_HOST       "110.42.224.129"
+#define TCP_TEST_DEFAULT_PORT       8910
+#define TCP_TEST_DEFAULT_TIME       30
+#define TCP_TEST_DEFAULT_CONNECTIONS 10
+
+/* TCP测试配置结构体 */
+typedef struct {
+    char server_host[256];              // 服务器地址
+    uint16_t server_port;               // 服务器端口
+    uint32_t test_duration;             // 测试时间(秒)
+    uint16_t connection_count;          // 连接数
+    bool verbose;                       // 详细输出
+    uint32_t send_interval_ms;          // 发送间隔(毫秒)
+    uint32_t data_min_size;             // 最小数据包大小
+    uint32_t data_max_size;             // 最大数据包大小
+} tcp_test_config_t;
+
+/* 单个连接统计信息 */
+typedef struct {
+    uint16_t conn_id;                   // 连接ID
+    int socket_fd;                      // socket文件描述符
+    bool connected;                     // 连接状态
+    uint32_t connect_time_ms;           // 连接耗时(毫秒)
+    uint32_t packets_sent;              // 发送包数
+    uint32_t packets_received;          // 接收包数
+    uint64_t bytes_sent;                // 发送字节数
+    uint64_t bytes_received;            // 接收字节数
+    uint32_t errors;                    // 错误数
+    uint32_t data_errors;               // 数据校验错误数
+    uint32_t last_activity_time;        // 最后活动时间
+    uint64_t throughput_bps;            // 当前吞吐量(字节/秒)
+    uint64_t max_throughput_bps;        // 最大吞吐量(字节/秒)
+    bool thread_running;                // 线程运行状态
+} tcp_connection_stats_t;
+
+/* 全局测试统计信息 */
+typedef struct {
+    uint32_t start_time;                // 测试开始时间
+    uint32_t end_time;                  // 测试结束时间
+    uint16_t successful_connections;    // 成功连接数
+    uint16_t failed_connections;        // 失败连接数
+    uint64_t total_packets_sent;        // 总发送包数
+    uint64_t total_packets_received;    // 总接收包数
+    uint64_t total_bytes_sent;          // 总发送字节数
+    uint64_t total_bytes_received;      // 总接收字节数
+    uint32_t total_errors;              // 总错误数
+    uint32_t data_verification_errors;  // 数据校验错误数
+    uint64_t max_throughput_bps;        // 最大吞吐量(字节/秒)
+    uint64_t avg_throughput_bps;        // 平均吞吐量(字节/秒)
+    bool test_running;                  // 测试运行状态
+} tcp_global_stats_t;
+
+/* TCP测试管理器 */
+typedef struct {
+    tcp_test_config_t config;           // 配置信息
+    tcp_connection_stats_t connections[TCP_TEST_MAX_CONNECTIONS]; // 连接统计
+    tcp_global_stats_t global_stats;    // 全局统计
+    volatile bool stop_flag;            // 停止标志
+    uint32_t stats_timer_id;            // 统计定时器ID
+} tcp_test_manager_t;
+
+/* 测试数据包头结构 */
+typedef struct {
+    uint16_t conn_id;                   // 连接ID
+    uint32_t packet_id;                 // 包ID
+    uint16_t data_size;                 // 数据大小
+    uint32_t timestamp;                 // 时间戳
+    uint32_t checksum;                  // 校验和
+} __attribute__((packed)) tcp_test_packet_header_t;
+
+/**
+ * @brief 初始化TCP测试
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t tcp_test_init(void);
+
+/**
+ * @brief 反初始化TCP测试
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t tcp_test_deinit(void);
+
+/**
+ * @brief 启动TCP测试
+ * @param config 测试配置
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t tcp_test_start(const tcp_test_config_t *config);
+
+/**
+ * @brief 停止TCP测试
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t tcp_test_stop(void);
+
+/**
+ * @brief 获取测试状态
+ * @return true-正在运行,false-已停止
+ */
+bool tcp_test_is_running(void);
+
+/**
+ * @brief 获取全局统计信息
+ * @param stats 统计信息输出
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t tcp_test_get_stats(tcp_global_stats_t *stats);
+
+/**
+ * @brief 获取连接统计信息
+ * @param conn_id 连接ID
+ * @param stats 连接统计信息输出
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t tcp_test_get_connection_stats(uint16_t conn_id, tcp_connection_stats_t *stats);
+
+/**
+ * @brief 打印测试报告
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t tcp_test_print_report(void);
+
+/**
+ * @brief 格式化字节数显示
+ * @param bytes 字节数
+ * @param buffer 输出缓冲区
+ * @param buffer_size 缓冲区大小
+ * @return 格式化后的字符串
+ */
+const char* tcp_test_format_bytes(uint64_t bytes, char *buffer, size_t buffer_size);
+
+/**
+ * @brief 获取当前时间(毫秒) - 导出给AT命令使用
+ * @return 当前时间(毫秒)
+ */
+uint32_t tcp_test_get_time_ms(void);
+
+/**
+ * @brief 解析命令行参数
+ * @param argc 参数个数
+ * @param argv 参数数组
+ * @param config 配置输出
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t tcp_test_parse_args(int argc, char *argv[], tcp_test_config_t *config);
+
+/**
+ * @brief 打印使用帮助
+ */
+void tcp_test_print_help(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PPP_TCP_TEST_H */ 
\ No newline at end of file
diff --git a/code/sdk/zhihui/ppp/src/ppp_debug_manager.c b/code/sdk/zhihui/ppp/src/ppp_debug_manager.c
new file mode 100644 (file)
index 0000000..afbc2f1
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * @file ppp_debug_manager.c
+ * @brief PPP调试级别动态管理模块
+ * 
+ * 提供运行时动态调整PPP调试输出级别的功能
+ */
+
+#include "ppp_debug_manager.h"
+#include "ppp_debug.h"
+#include "ppp_config.h"
+#include <string.h>
+
+/* 全局调试级别变量 */
+static volatile int g_ppp_dynamic_debug_level = PPP_DEBUG_LEVEL;
+
+/**
+ * @brief 获取当前动态调试级别
+ * @return 当前调试级别
+ */
+int ppp_debug_get_level(void)
+{
+    return g_ppp_dynamic_debug_level;
+}
+
+/**
+ * @brief 设置动态调试级别
+ * @param level 调试级别 (0-4)
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t ppp_debug_set_level(int level)
+{
+    if (level < PPP_DEBUG_LEVEL_NONE || level > PPP_DEBUG_LEVEL_DEBUG) {
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    g_ppp_dynamic_debug_level = level;
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 获取调试级别名称
+ * @param level 调试级别
+ * @return 级别名称字符串
+ */
+const char* ppp_debug_get_level_name(int level)
+{
+    switch (level) {
+        case PPP_DEBUG_LEVEL_NONE:  return "NONE";
+        case PPP_DEBUG_LEVEL_ERROR: return "ERROR";
+        case PPP_DEBUG_LEVEL_WARN:  return "WARN";
+        case PPP_DEBUG_LEVEL_INFO:  return "INFO";
+        case PPP_DEBUG_LEVEL_DEBUG: return "DEBUG";
+        default: return "UNKNOWN";
+    }
+}
+
+/**
+ * @brief 根据名称设置调试级别
+ * @param level_name 级别名称 ("NONE", "ERROR", "WARN", "INFO", "DEBUG")
+ * @return PPP_ERR_OK-成功,其他-失败
+ */
+ppp_error_t ppp_debug_set_level_by_name(const char* level_name)
+{
+    if (!level_name) {
+        return PPP_ERR_INVALID_PARAM;
+    }
+    
+    if (strcasecmp(level_name, "NONE") == 0) {
+        return ppp_debug_set_level(PPP_DEBUG_LEVEL_NONE);
+    } else if (strcasecmp(level_name, "ERROR") == 0) {
+        return ppp_debug_set_level(PPP_DEBUG_LEVEL_ERROR);
+    } else if (strcasecmp(level_name, "WARN") == 0) {
+        return ppp_debug_set_level(PPP_DEBUG_LEVEL_WARN);
+    } else if (strcasecmp(level_name, "INFO") == 0) {
+        return ppp_debug_set_level(PPP_DEBUG_LEVEL_INFO);
+    } else if (strcasecmp(level_name, "DEBUG") == 0) {
+        return ppp_debug_set_level(PPP_DEBUG_LEVEL_DEBUG);
+    } else {
+        return PPP_ERR_INVALID_PARAM;
+    }
+}
+
+/**
+ * @brief 重置调试级别为默认值
+ * @return PPP_ERR_OK-成功
+ */
+ppp_error_t ppp_debug_reset_level(void)
+{
+    g_ppp_dynamic_debug_level = PPP_DEBUG_LEVEL;
+    return PPP_ERR_OK;
+}
+
+/**
+ * @brief 检查指定级别是否启用
+ * @param level 要检查的级别
+ * @return true-启用,false-未启用
+ */
+bool ppp_debug_is_level_enabled(int level)
+{
+    return g_ppp_dynamic_debug_level >= level;
+} 
\ No newline at end of file
index a734b8b..74c6536 100644 (file)
@@ -16,6 +16,7 @@
 #include "lwip/dns.h"
 #include "netif/ppp/ppp.h"
 #include "netif/ppp/pppos.h"
+#include "netif/ppp/pppapi.h"  // 添加pppapi头文件,用于线程安全的PPP API
 #include "lwip/sio.h"  // 添加SIO头文件
 #endif
 
@@ -79,11 +80,12 @@ ppp_error_t ppp_lwip_init(const ppp_lwip_config_t *config)
 
     memset_s(g_lwip_ctx.netif, sizeof(struct netif), 0, sizeof(struct netif));
 
-    /* 创建PPPoS接口 */
-    g_lwip_ctx.ppp_pcb = pppos_create(g_lwip_ctx.netif,
-                                      ppp_lwip_output_callback,
-                                      ppp_lwip_link_status_callback,
-                                      &g_lwip_ctx);
+    /* 创建PPPoS接口 - 使用线程安全的API */
+    PPP_DEBUG_INFO("Creating PPPoS interface using thread-safe API...");
+    g_lwip_ctx.ppp_pcb = pppapi_pppos_create(g_lwip_ctx.netif,
+                                             ppp_lwip_output_callback,
+                                             ppp_lwip_link_status_callback,
+                                             &g_lwip_ctx);
 
     if (!g_lwip_ctx.ppp_pcb) {
         PPP_DEBUG_ERROR("Failed to create PPPoS interface");
@@ -213,7 +215,7 @@ void ppp_lwip_deinit(void)
     /* 删除PPP控制块 */
     if (g_lwip_ctx.ppp_pcb) {
         PPP_DEBUG_INFO("Freeing PPP control block");
-        ppp_free(g_lwip_ctx.ppp_pcb);
+        pppapi_free(g_lwip_ctx.ppp_pcb);
         g_lwip_ctx.ppp_pcb = NULL;
     }
 
@@ -250,12 +252,12 @@ ppp_error_t ppp_lwip_connect(void)
     PPP_DEBUG_PRINT("Initiating PPP connection with lwIP...\n");
     PPP_DEBUG_PRINT("This will trigger LCP and IPCP negotiation\n");
 
-    /* 启动PPP连接 */
-    err_t err = ppp_connect(g_lwip_ctx.ppp_pcb, 0);
+    PPP_DEBUG_INFO("Starting PPP connection...");
+    
+    err_t err = pppapi_connect(g_lwip_ctx.ppp_pcb, 0);
     if (err != ERR_OK) {
         PPP_DEBUG_ERROR("Failed to start PPP connection: %d", err);
-        PPP_DEBUG_PRINT("=== PPP Connection FAILED ===\n");
-        return PPP_ERR_DIAL_FAILED;
+        return PPP_ERR_UNKNOWN;
     }
 
     PPP_DEBUG_PRINT("PPP connection initiated successfully\n");
@@ -282,13 +284,12 @@ ppp_error_t ppp_lwip_disconnect(void)
         return PPP_ERR_OK;
     }
 
-    PPP_DEBUG_INFO("Disconnecting PPP");
-
-    /* 关闭PPP连接 */
-    err_t err = ppp_close(g_lwip_ctx.ppp_pcb, 0);
+    PPP_DEBUG_INFO("Disconnecting PPP connection...");
+    
+    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);
-        return PPP_ERR_DIAL_FAILED;
+        return PPP_ERR_UNKNOWN;
     }
 
     g_lwip_ctx.connected = false;
@@ -310,87 +311,21 @@ ppp_error_t ppp_lwip_input(const uint8_t *data, uint32_t length)
         return PPP_ERR_INVALID_PARAM;
     }
 
-    PPP_DEBUG_PRINT("=== PPP Protocol Input ===\n");
-    PPP_DEBUG_PRINT("PPP RX: %u bytes\n", length);
-    
-    /* 解析PPP协议包 */
-    if (length >= 4) {
-        /* 跳过PPP Flag (0x7E) 如果存在 */
-        uint32_t offset = 0;
-        if (data[0] == 0x7E) {
-            offset = 1;
-        }
-        
-        /* 检查Address/Control字段 */
-        if (offset + 3 < length && data[offset] == 0xFF && data[offset + 1] == 0x03) {
-            offset += 2;  /* 跳过Address/Control */
-            
-            /* 解析协议字段 */
-            if (offset + 1 < length) {
-                uint16_t protocol = (data[offset] << 8) | data[offset + 1];
-                offset += 2;
-                
-                PPP_DEBUG_PRINT("Protocol: 0x%04X (%s)\n", protocol, ppp_get_protocol_name(protocol));
-                
-                /* 解析LCP/IPCP包 */
-                if ((protocol == 0xC021 || protocol == 0x8021) && offset + 3 < length) {
-                    uint8_t code = data[offset];
-                    uint8_t id = data[offset + 1];
-                    uint16_t pkt_length = (data[offset + 2] << 8) | data[offset + 3];
-                    
-                    PPP_DEBUG_PRINT("  Code: %u (%s)\n", code, ppp_get_lcp_code_name(code));
-                    PPP_DEBUG_PRINT("  ID: %u\n", id);
-                    PPP_DEBUG_PRINT("  Length: %u\n", pkt_length);
-                    
-                    /* 解析Configure-Request/Ack/Nak的选项 */
-                    if ((code >= 1 && code <= 4) && offset + 4 < length) {  /* Configure packets */
-                        uint32_t opt_offset = offset + 4;
-                        PPP_DEBUG_PRINT("  Options:\n");
-                        
-                        while (opt_offset + 1 < length && opt_offset < offset + pkt_length) {
-                            uint8_t opt_type = data[opt_offset];
-                            uint8_t opt_len = data[opt_offset + 1];
-                            
-                            if (opt_len < 2 || opt_offset + opt_len > length) break;
-                            
-                            PPP_DEBUG_PRINT("    Type: %u, Length: %u", opt_type, opt_len);
-                            
-                            /* 解析常见选项 */
-                            if (protocol == 0x8021 && opt_type == 3 && opt_len == 6) {  /* IPCP IP Address */
-                                PPP_DEBUG_PRINT(" (IP Address: %u.%u.%u.%u)", 
-                                               data[opt_offset + 2], data[opt_offset + 3],
-                                               data[opt_offset + 4], data[opt_offset + 5]);
-                            } else if (protocol == 0x8021 && opt_type == 129 && opt_len == 6) {  /* Primary DNS */
-                                PPP_DEBUG_PRINT(" (Primary DNS: %u.%u.%u.%u)", 
-                                               data[opt_offset + 2], data[opt_offset + 3],
-                                               data[opt_offset + 4], data[opt_offset + 5]);
-                            } else if (protocol == 0x8021 && opt_type == 131 && opt_len == 6) {  /* Secondary DNS */
-                                PPP_DEBUG_PRINT(" (Secondary DNS: %u.%u.%u.%u)", 
-                                               data[opt_offset + 2], data[opt_offset + 3],
-                                               data[opt_offset + 4], data[opt_offset + 5]);
-                            }
-                            
-                            PPP_DEBUG_PRINT("\n");
-                            opt_offset += opt_len;
-                        }
-                    }
-                }
-            }
-        }
-    }
-    
-    /* 打印原始数据 */
-    PPP_DEBUG_PRINT("Raw Data: ");
-    for (uint32_t i = 0; i < length && i < 32; i++) {
-        PPP_DEBUG_PRINT("%02X ", data[i]);
-    }
-    if (length > 32) {
-        PPP_DEBUG_PRINT("... (total %u bytes)", length);
-    }
-    PPP_DEBUG_PRINT("\n");
+    PPP_DEBUG_PRINT("=== PPP Input Data ===\n");
+    PPP_DEBUG_PRINT("Length: %d bytes\n", length);
+    // PPP_DEBUG_HEXDUMP("RX", data, length > 32 ? 32 : length);
 
-    /* 将数据传递给PPPoS */
+#if !NO_SYS && !PPP_INPROC_IRQ_SAFE
+    /* 在多线程环境中使用线程安全的输入函数 */
+    err_t 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;
+    }
+#else
+    /* 在单线程或中断安全环境中使用直接输入 */
     pppos_input(g_lwip_ctx.ppp_pcb, (u8_t *)data, length);
+#endif
 
     PPP_DEBUG_PRINT("=== PPP Input Processed ===\n");
     return PPP_ERR_OK;
@@ -453,23 +388,23 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx)
     (void)ctx;
 
     PPP_DEBUG_INFO("PPP status callback: err_code=%d", err_code);
-    
-    /* æ\89\93å\8d°PPPé\98¶æ®µä¿¡æ\81¯ */
+
+    /* è¿\99é\87\8cå\8fªå¤\84ç\90\86PPPé\98¶æ®µå\8f\98å\8c\96ï¼\8cä¸\8då¤\84ç\90\86é\94\99误 */
     const char* phase_str = "UNKNOWN";
     switch (err_code) {
-        case PPPERR_NONE: phase_str = "CONNECTED"; break;
-        case PPPERR_PARAM: phase_str = "PARAM_ERROR"; break;
-        case PPPERR_OPEN: phase_str = "OPEN_ERROR"; break;
-        case PPPERR_DEVICE: phase_str = "DEVICE_ERROR"; break;
-        case PPPERR_ALLOC: phase_str = "ALLOC_ERROR"; break;
-        case PPPERR_USER: phase_str = "USER_ERROR"; break;
-        case PPPERR_CONNECT: phase_str = "CONNECT_ERROR"; break;
-        case PPPERR_AUTHFAIL: phase_str = "AUTH_FAIL"; break;
-        case PPPERR_PROTOCOL: phase_str = "PROTOCOL_ERROR"; break;
-        case PPPERR_PEERDEAD: phase_str = "PEER_DEAD"; break;
-        case PPPERR_IDLETIMEOUT: phase_str = "IDLE_TIMEOUT"; break;
-        case PPPERR_CONNECTTIME: phase_str = "CONNECT_TIMEOUT"; break;
-        case PPPERR_LOOPBACK: phase_str = "LOOPBACK"; break;
+        case PPP_PHASE_DEAD: phase_str = "DEAD"; break;
+        case PPP_PHASE_MASTER: phase_str = "MASTER"; break;
+        case PPP_PHASE_HOLDOFF: phase_str = "HOLDOFF"; break;
+        case PPP_PHASE_INITIALIZE: phase_str = "INITIALIZE"; break;
+        case PPP_PHASE_SERIALCONN: phase_str = "SERIALCONN"; break;
+        case PPP_PHASE_DORMANT: phase_str = "DORMANT"; break;
+        case PPP_PHASE_ESTABLISH: phase_str = "ESTABLISH"; break;
+        case PPP_PHASE_AUTHENTICATE: phase_str = "AUTHENTICATE"; break;
+        case PPP_PHASE_CALLBACK: phase_str = "CALLBACK"; break;
+        case PPP_PHASE_NETWORK: phase_str = "NETWORK"; break;
+        case PPP_PHASE_RUNNING: phase_str = "RUNNING"; break;
+        case PPP_PHASE_TERMINATE: phase_str = "TERMINATE"; break;
+        case PPP_PHASE_DISCONNECT: phase_str = "DISCONNECT"; break;
         default: phase_str = "OTHER"; break;
     }
     PPP_DEBUG_INFO("PPP Phase: %s (%d)", phase_str, err_code);
@@ -478,8 +413,8 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx)
     memset_s(&event, sizeof(event), 0, sizeof(event));
 
     switch (err_code) {
-        case PPPERR_NONE:
-            /* 连接成功 */
+        case PPP_PHASE_RUNNING:
+            /* 连接成功 - PPP协议栈运行中 */
             g_lwip_ctx.connected = true;
             event.type = PPP_LWIP_EVENT_CONNECTED;
             PPP_DEBUG_CRITICAL("PPP connection established successfully");
@@ -490,10 +425,10 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx)
                 PPP_DEBUG_INFO("netif->gw: 0x%08x", ip4_addr_get_u32(&g_lwip_ctx.netif->gw));
                 PPP_DEBUG_INFO("netif->netmask: 0x%08x", ip4_addr_get_u32(&g_lwip_ctx.netif->netmask));
                 PPP_DEBUG_INFO("netif flags: 0x%02x", g_lwip_ctx.netif->flags);
-                
+
                 g_lwip_ctx.local_ip = ip4_addr_get_u32(&g_lwip_ctx.netif->ip_addr);
                 g_lwip_ctx.remote_ip = ip4_addr_get_u32(&g_lwip_ctx.netif->gw);
-                
+
                 /* 获取DNS服务器地址 */
                 const ip_addr_t *dns1 = dns_getserver(0);
                 const ip_addr_t *dns2 = dns_getserver(1);
@@ -505,7 +440,7 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx)
                     g_lwip_ctx.secondary_dns = ip4_addr_get_u32(ip_2_ip4(dns2));
                     PPP_DEBUG_INFO("DNS2: 0x%08x", g_lwip_ctx.secondary_dns);
                 }
-                
+
                 PPP_DEBUG_INFO("PPP connected - Local IP: %u.%u.%u.%u", 
                               (g_lwip_ctx.local_ip >> 0) & 0xFF,
                               (g_lwip_ctx.local_ip >> 8) & 0xFF,
@@ -516,7 +451,7 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx)
                               (g_lwip_ctx.remote_ip >> 8) & 0xFF,
                               (g_lwip_ctx.remote_ip >> 16) & 0xFF,
                               (g_lwip_ctx.remote_ip >> 24) & 0xFF);
-                
+
                 /* 设置PPP接口为默认网络接口 */
                 if (g_lwip_ctx.netif->ip_addr.addr != 0) {
                     PPP_DEBUG_INFO("Setting PPP interface as default...");
@@ -525,43 +460,26 @@ static void ppp_lwip_status_callback(ppp_pcb *pcb, int err_code, void *ctx)
                 } else {
                     PPP_DEBUG_INFO("PPP IP address is 0, IPCP negotiation may still be in progress");
                     PPP_DEBUG_INFO("Network interface will be set as default when IP is assigned via netif callback");
-                    
-                    /* 确保网络接口处于激活状态 */
                     netif_set_up(g_lwip_ctx.netif);
                     netif_set_link_up(g_lwip_ctx.netif);
-                    
-                    /* 启动备用定时器检查(2秒后检查一次) */
-                    PPP_DEBUG_INFO("Starting fallback timer to ensure default interface is set");
-                    // 注意:这里使用简单的延迟检查,避免复杂的定时器管理
                 }
             } else {
                 PPP_DEBUG_ERROR("PPP netif is NULL!");
             }
             break;
 
-        case PPPERR_PARAM:
-        case PPPERR_OPEN:
-        case PPPERR_DEVICE:
-        case PPPERR_ALLOC:
-        case PPPERR_USER:
-        case PPPERR_CONNECT:
-        case PPPERR_AUTHFAIL:
-        case PPPERR_PROTOCOL:
-        case PPPERR_PEERDEAD:
-        case PPPERR_IDLETIMEOUT:
-        case PPPERR_CONNECTTIME:
-        case PPPERR_LOOPBACK:
-            /* 连接错误 */
+        case PPP_PHASE_DISCONNECT:
+            /* 正常断开 - 这是阶段,不是错误 */
             g_lwip_ctx.connected = false;
-            event.type = PPP_LWIP_EVENT_ERROR;
-            event.error_code = err_code;
-            PPP_DEBUG_ERROR("PPP connection error: %d", err_code);
+            event.type = PPP_LWIP_EVENT_DISCONNECTED;
+            PPP_DEBUG_INFO("PPP connection disconnected (phase DISCONNECT)");
             break;
 
         default:
-            /* 其他状态 */
+            /* 其他阶段,仅通知状态变化 */
             event.type = PPP_LWIP_EVENT_STATUS_CHANGE;
             event.error_code = err_code;
+            PPP_DEBUG_INFO("PPP status change: %d", err_code);
             break;
     }
 
@@ -864,4 +782,86 @@ static u32_t ppp_lwip_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void
     PPP_DEBUG_PRINT("=== PPP Output SUCCESS ===\n");
     return len;
 }
+
+const char* ppp_lwip_get_ip_address(void)
+{
+#ifdef LWIP_PPP_SUPPORT
+    if (!g_lwip_ctx.initialized) {
+        return "0.0.0.0";
+    }
+    static char ip_str[16];
+    uint32_t ip = g_lwip_ctx.local_ip;
+    snprintf(ip_str, sizeof(ip_str), "%u.%u.%u.%u",
+             (ip >> 0) & 0xFF,
+             (ip >> 8) & 0xFF,
+             (ip >> 16) & 0xFF,
+             (ip >> 24) & 0xFF);
+    return ip_str;
+#else
+    return "0.0.0.0";
+#endif
+}
+
+const char* ppp_lwip_get_netmask(void)
+{
+#ifdef LWIP_PPP_SUPPORT
+    if (!g_lwip_ctx.initialized || !g_lwip_ctx.netif) {
+        return "0.0.0.0";
+    }
+    static char netmask_str[16];
+    ip4addr_ntoa_r(ip_2_ip4(&g_lwip_ctx.netif->netmask), netmask_str, sizeof(netmask_str));
+    return netmask_str;
+#else
+    return "0.0.0.0";
+#endif
+}
+
+const char* ppp_lwip_get_gateway(void)
+{
+#ifdef LWIP_PPP_SUPPORT
+    if (!g_lwip_ctx.initialized) {
+        return "0.0.0.0";
+    }
+    static char gw_str[16];
+    uint32_t ip = g_lwip_ctx.remote_ip;
+    snprintf(gw_str, sizeof(gw_str), "%u.%u.%u.%u",
+             (ip >> 0) & 0xFF,
+             (ip >> 8) & 0xFF,
+             (ip >> 16) & 0xFF,
+             (ip >> 24) & 0xFF);
+    return gw_str;
+#else
+    return "0.0.0.0";
+#endif
+}
+
+const char* ppp_lwip_get_dns(void)
+{
+#ifdef LWIP_PPP_SUPPORT
+    if (!g_lwip_ctx.initialized) {
+        return "0.0.0.0";
+    }
+    static char dns_str[32];
+    char dns1_str[16] = "0.0.0.0";
+    char dns2_str[16] = "0.0.0.0";
+    uint32_t dns1 = g_lwip_ctx.primary_dns;
+    uint32_t dns2 = g_lwip_ctx.secondary_dns;
+    snprintf(dns1_str, sizeof(dns1_str), "%u.%u.%u.%u",
+             (dns1 >> 0) & 0xFF,
+             (dns1 >> 8) & 0xFF,
+             (dns1 >> 16) & 0xFF,
+             (dns1 >> 24) & 0xFF);
+    snprintf(dns2_str, sizeof(dns2_str), "%u.%u.%u.%u",
+             (dns2 >> 0) & 0xFF,
+             (dns2 >> 8) & 0xFF,
+             (dns2 >> 16) & 0xFF,
+             (dns2 >> 24) & 0xFF);
+    snprintf(dns_str, sizeof(dns_str), "%s,%s", dns1_str, dns2_str);
+    return dns_str;
+#else
+    return "0.0.0.0";
+#endif
+}
+
+
 #endif /* LWIP_PPP_SUPPORT */ 
\ No newline at end of file