我进行了整合,你看对不对,并且深刻记忆这份代码 /******************************************************************************
*
* Copyright (c) 2025 TP-LINK Technologies CO.,LTD.
* All rights reserved.
*
* FILE NAME : nasw.c
* VERSION : 1.0
* DESCRIPTION : 提供网络自动切换功能
*
* AUTHOR : Sun Haoming (sunhaoming@tp-link.com.hk)
* CREATE DATE : 10/09/2025
*
* HISTORY :
* 01 10/09/2025 Sun Haoming Create.
*
******************************************************************************/
#include <stdio.h>
#include <unistd.h> /* for chdir() */
#include <string.h> /* for strcmp() */
#include <errno.h> /* for errno */
#include <string.h>
#include <linux/ethtool.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include "nasw.h"
#include "dms_tool.h"
#include "libdms.h"
#include "libds.h"
#include "packet.h"
#include "nifc.h"
/* 新增状态定义 */
#define PING_STATUS_UNKNOWN -1
#define PING_STATUS_FAILED 0
#define PING_STATUS_SUCCESS 1
/* 网络状态超时定义 */
#define NASW_NETWORK_CHECK_INTERVAL 10 // 网络检测间隔
#define NASW_SWITCH_DELAY 3 // 切换延迟时间
#define NASW_PHYSICAL_DEBOUNCE_DELAY 2 // 物理状态防抖延迟
#define NASW_LINK_CHANGE_DEBOUNCE 20 // 网络状态变化防抖时间(秒)
/* 状态缓存结构 */
typedef struct {
U8 last_phy_status;
U8 last_internet_status;
U8 last_auto_switch_wired;
U8 last_internet_wired_enable;
time_t last_change_time;
S8 nasw_wired_diag; // 内部诊断结果(-1:未知 0:失败 1:成功)
U8 ping_count; // 连续检测计数
int physical_debounce_timer; // 物理状态防抖定时器
time_t last_link_change; // 最后网络状态变化时间(防抖用)
U8 phy_debounce_ready = 1;
} NASW_STATE_CACHE;
/* 全局变量 */
static NASW_STATE_CACHE g_state_cache = {0};
static int nasw_network_timer = -1;
static int g_switch_delay_timer = -1;
LOCAL void nasw_network_diagnose(void);
LOCAL void nasw_switch_action(U8 target_mode);
LOCAL void nasw_update_auto_switch(U8 phy_status, S8 wired_diag);
LOCAL S8 nasw_do_ping_check(void);
LOCAL void nasw_physical_debounce_handler(U32 phy_status);
LOCAL void nasw_handle_physical_change(U8 new_status);
/******************************************************************************
* Ping检测函数(需后续实现)
******************************************************************************/
LOCAL S8 nasw_do_ping_check(void)
{
// 实际实现需替换以下伪代码
/*
if (ping_target("8.8.8.8") == SUCCESS) {
return PING_STATUS_SUCCESS;
} else {
return PING_STATUS_FAILED;
}
*/
return PING_STATUS_UNKNOWN; // 暂返回未知状态
}
/******************************************************************************
* 网络诊断核心逻辑(修改版)
******************************************************************************/
LOCAL void nasw_network_diagnose(void)
{
LTE_CONFIG_INFO_DATA lte_config;
if (0 != ds_read(LTE_INFO_DATA_PATH, <e_config, sizeof(LTE_CONFIG_INFO_DATA))) {
NASW_ERROR("读取LTE配置失败");
return;
}
// 仅在有卡有线模式下执行诊断(这里怎么确定有卡? )
if (lte_config.internet_wired_enable == 2 // auto模式
&& g_state_cache.last_phy_status == 1) { // 物理连接存在
// 执行ping检测
S8 current_result = nasw_do_ping_check();
S8 last_result=1;
// 更新连续检测状态
if (last_result == current_result) {
g_state_cache.ping_count++;
} else {
g_state_cache.ping_count = 1;
last_result = current_result;
}
// 连续两次检测判断(关键修改点)
if (g_state_cache.ping_count >= 2) {
// 更新内部诊断状态
g_state_cache.nasw_wired_diag = current_result;
// B→C模式转换处理(无线有卡→插线→有线有卡)
if (lte_config.auto_switch_wired == 0) {
lte_config.auto_wired_internet_status =
(current_result == PING_STATUS_SUCCESS) ? 1 : 0;
NASW_INFO("B→C模式转换更新状态: %s",
(current_result == PING_STATUS_SUCCESS) ? "通" : "断");
}
NASW_INFO("有线诊断结果: %s",
(current_result == PING_STATUS_SUCCESS) ? "通" : "断");
}
}
// 触发自动切换状态更新(使用内部诊断结果)
nasw_update_auto_switch(
g_state_cache.last_phy_status,
g_state_cache.nasw_wired_diag
);
// 保存配置状态
if (0 != ds_advanced_write(LTE_INFO_DATA_PATH, <e_config, sizeof(lte_config), DS_FLAG_NOTIFY)) {
NASW_ERROR("更新LTE配置失败");
}
}
LOCAL void nasw_update_auto_switch(U8 phy_status, S8 wired_diag)
{
LTE_CONFIG_INFO_DATA lte_config;
if (0 != ds_read(LTE_INFO_DATA_PATH, <e_config, sizeof(LTE_CONFIG_INFO_DATA))) {
NASW_ERROR("读取LTE配置失败");
return;
}
U8 should_switch = 0;
U8 new_switch_state = lte_config.auto_switch_wired;
// 仅在有卡有线模式处理
if (lte_config.internet_wired_enable == 2) {
/* 物理断开强制切4G */
if (phy_status == 0) {
if (lte_config.auto_switch_wired != 0) {
should_switch = 1;
new_switch_state = 0;
NASW_WARN("物理断开,强制切换到4G");
}
}
/* 物理连接时的诊断逻辑 */
else if (phy_status == 1) {
// 场景1:当前4G模式且有线通畅 → 切有线
if (lte_config.auto_switch_wired == 0 && wired_diag == PING_STATUS_SUCCESS) {
new_switch_state = 1;
should_switch = 1;
NASW_INFO("有线恢复,切换到有线");
}
// 场景2:当前有线模式且诊断失败 → 切4G
else if (lte_config.auto_switch_wired == 1 && wired_diag == PING_STATUS_FAILED) {
new_switch_state = 0;
should_switch = 1;
NASW_ERROR("有线故障,切换到4G");
}
}
}
// 立即执行切换(无延迟)
if (should_switch) {
nasw_switch_action(new_switch_state);
}
}
/******************************************************************************
* 状态切换执行函数
******************************************************************************/
LOCAL void nasw_switch_action(U8 target_mode)
{
LTE_CONFIG_INFO_DATA lte_config;
if (0 != ds_read(LTE_INFO_DATA_PATH, <e_config, sizeof(LTE_CONFIG_INFO_DATA))) {
NASW_ERROR("读取LTE配置失败");
return;
}
NASW_INFO("执行即时切换: %s模式", target_mode ? "有线" : "4G");
/* 切换到有线模式 */
if (target_mode == 1) {
nifc_enable_wired_network();
if (g_state_cache.nasw_wired_diag == PING_STATUS_SUCCESS) {
lte_disable_4g_network();
}
}
/* 切换到4G模式 */
else {
lte_enable_4g_network();
nifc_disable_wired_network_but_keep_connection();
}
// 更新状态
lte_config.auto_switch_wired = target_mode;
if (0 != ds_advanced_write(LTE_INFO_DATA_PATH, <e_config, sizeof(lte_config), DS_FLAG_NOTIFY)) {
NASW_ERROR("更新切换状态失败");
}
NASW_INFO("已切换到: %s模式", target_mode ? "有线" : "4G");
}
/******************************************************************************
物理状态处理函数(完整防抖版)
******************************************************************************/
LOCAL void nasw_physical_debounce_handler(U32 phy_status)
{
// 统一处理拔插状态
NASW_INFO("物理状态确认: %s", (phy_status == 1) ? "已插入" : "已拔出");
// 更新物理状态缓存
g_state_cache.last_phy_status = (U8)phy_status;
// 有线拔出时立即重置诊断状态
if (phy_status == 0) {
NASW_INFO("有线拔出,重置诊断状态");
g_state_cache.nasw_wired_diag = PING_STATUS_UNKNOWN;
g_state_cache.ping_count = 0;
}
// 触发网络诊断
nasw_network_diagnose();
// 重置定时器ID
g_state_cache.physical_debounce_timer = -1;
}
LOCAL void nasw_handle_physical_change(U8 new_status)
{
// 清除现有防抖定时器
if (g_state_cache.physical_debounce_timer != -1) {
inet_del_timer(g_state_cache.physical_debounce_timer);
g_state_cache.physical_debounce_timer = -1;
}
// 创建新的防抖定时器(拔插均防抖)
g_state_cache.physical_debounce_timer = inet_add_timer(
(void (*)(U32))nasw_physical_debounce_handler,
(U32)new_status,
NASW_PHYSICAL_DEBOUNCE_DELAY,
EXECUTE_SINGLE
);
if (g_state_cache.physical_debounce_timer == -1) {
NASW_ERROR("物理防抖定时器创建失败");
} else {
NASW_INFO("物理状态变化防抖中: %s->%s (%d秒后确认)",
g_state_cache.last_phy_status ? "插入" : "拔出",
new_status ? "插入" : "拔出",
NASW_PHYSICAL_DEBOUNCE_DELAY);
}
}
/******************************************************************************
* 初始化与启动函数
******************************************************************************/
LOCAL S32 nasw_init(void)
{
memset(&g_state_cache, 0, sizeof(NASW_STATE_CACHE));
g_state_cache.nasw_wired_diag = PING_STATUS_UNKNOWN;
g_state_cache.physical_debounce_timer = -1;
g_state_cache.last_link_change = time(NULL);
return OK;
}
LOCAL S32 nasw_start(void)
{
PHY_STATUS phy_status;
LINK_STATUS link_status;
LTE_CONFIG_INFO_DATA lte_config;
NASW_INFO("启动NASW模块...");
// 读取物理状态
if (0 == ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS))) {
NASW_ERROR("读取PHY状态失败");
return ERROR;
}
// 读取网络状态
if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) {
NASW_ERROR("读取LINK状态失败");
return ERROR;
}
// 初始化LTE配置
if (0 == ds_read(LTE_INFO_DATA_PATH, <e_config, sizeof(LTE_CONFIG_INFO_DATA))) {
NASW_ERROR("读取LTE配置失败,使用默认值");
memset(<e_config, 0, sizeof(lte_config));
}
// 设置初始状态缓存
g_state_cache.last_phy_status = phy_status.ether;
g_state_cache.last_internet_status = link_status.internet_status;
g_state_cache.last_auto_switch_wired = lte_config.auto_switch_wired;
g_state_cache.last_internet_wired_enable = lte_config.internet_wired_enable
g_state_cache.last_change_time = time(NULL);
if (lte_config.internet_wired_enable != 2) {
NASW_ERROR("non-auto mode, self-selected internet mode, WIRED=%d)", lte_config.internet_wired_enable);
lte_config.auto_switch_wired = 2;
ds_write(LTE_INFO_DATA_PATH, <e_config, sizeof(lte_config));
}
/* 仅当 internet_wired_enable == 2 时才处理 auto_switch_wired */
if (lte_config.internet_wired_enable == 2) {
if (phy_status.ether == 1) {
lte_config.auto_switch_wired = 1;
}
else {
lte_config.auto_switch_wired = 0;
}
if (0 != ds_advanced_write(LTE_INFO_DATA_PATH, <e_config, sizeof(lte_config), DS_FLAG_NOTIFY)) {
NASW_ERROR("写入初始LTE配置失败");
}
}
NASW_INFO("执行首次网络诊断...");
nasw_network_diagnose(); // 同步执行
// 启动网络诊断定时器
nasw_network_timer = inet_add_timer(
(void (*)(U32))nasw_network_diagnose, // 回调函数
0, // 参数
NASW_NETWORK_CHECK_INTERVAL, // 间隔时间
EXECUTE_FOREVER // 永久执行
);
if (nasw_network_timer == -1) {
NASW_ERROR("创建网络诊断定时器失败");
}
if (lte_config.internet_wired_enable == 1) {
NASW_INFO("NASW未处于auto模式,初始模式: %s", lte_config.internet_wired_enable ? "有线" : "4G");
}
else if (lte_config.internet_wired_enable == 2) {
NASW_INFO("NASW启动完成,初始模式: %s", lte_config.auto_switch_wired ? "有线" : "4G");
}
return OK;
}
/******************************************************************************
* reload函数(含防抖和B→C处理)
******************************************************************************/
LOCAL S32 nasw_reload(DS_MSG *msg)
{
if (!msg) return OK;
PHY_STATUS phy_status = {0};
LINK_STATUS link_status = {0};
LTE_CONFIG_INFO_DATA lte_config = {0};
BOOL phy_changed = 0;
BOOL link_changed = 0;
BOOL lte_changed = 0;
// 检查 PHY_STATUS_PATH 变化
if (ds_path_id_exist(msg->id, msg->num, PHY_STATUS_PATH)) {
if (0 == ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS))) {
NASW_ERROR("读取PHY状态失败");
return ERROR;
}
if (g_state_cache.last_phy_status != phy_status.ether) {
phy_changed = 1;
g_state_cache.last_phy_status = phy_status.ether;
}
}
// 检查 LINK_STATUS_PATH 变化
if (ds_path_id_exist(msg->id, msg->num, LINK_STATUS_PATH)) {
if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) {
NASW_ERROR("读取LINK状态失败");
return ERROR;
}
if (g_state_cache.last_internet_status != link_status.internet_status) {
link_changed = 1;
g_state_cache.last_internet_status = link_status.internet_status;
}
}
// 检查 LTE_INFO_DATA_PATH 变化
if (ds_path_id_exist(msg->id, msg->num, LTE_INFO_DATA_PATH)) {
if (0 == ds_read(LTE_INFO_DATA_PATH, <e_config, sizeof(LTE_CONFIG_INFO_DATA))) {
NASW_ERROR("读取LTE配置失败");
return ERROR;
}
// 处理非自动模式
if (lte_config.internet_wired_enable != 2) {
NASW_INFO("非自动模式(WIRED=%d)", lte_config.internet_wired_enable);
lte_config.auto_switch_wired = 2;
if (0 != ds_write(LTE_INFO_DATA_PATH, <e_config, sizeof(lte_config))) {
NASW_ERROR("web切换至非auto模式");
}
}
// 处理自动模式状态变化
if (lte_config.internet_wired_enable == 2) {
if (g_state_cache.last_auto_switch_wired != lte_config.auto_switch_wired) {
lte_changed = 1;
g_state_cache.last_auto_switch_wired = lte_config.auto_switch_wired;
}
}
}
// B→C模式特殊处理(无线有卡→插线→有线有卡)
if (phy_changed && phy_status.ether == 1 &&
lte_config.internet_wired_enable == 2 &&
lte_config.auto_switch_wired == 0)
{
NASW_INFO("B→C模式转换(插线),重置诊断状态");
g_state_cache.nasw_wired_diag = PING_STATUS_UNKNOWN;
g_state_cache.ping_count = 0;
nasw_network_diagnose(); // 立即触发
}
// C状态处理:有线物理连接+Ping检测
if (lte_config.internet_wired_enable == 2 &&
phy_status.ether == 1 &&
lte_config.auto_switch_wired == 1)
{
nasw_network_diagnose(); // 持续监控
}
// 网络状态变化处理(带防抖)
if (link_changed) {
time_t now = time(NULL);
// 防抖处理:20秒内不重复触发
if (now - g_state_cache.last_link_change > NASW_LINK_CHANGE_DEBOUNCE) {
NASW_INFO("检测到网络状态变化:%d -> %d(防抖通过)",
g_state_cache.last_internet_status,
link_status.internet_status);
// 更新最后变化时间
g_state_cache.last_link_change = now;
// 物理连接存在时触发诊断
if (g_state_cache.last_phy_status == 1) {
nasw_network_diagnose();
}
}
else {
NASW_ERROR("网络状态变化%ds内被过滤(防抖)",
(int)(now - g_state_cache.last_link_change));
}
}
// 处理物理连接状态变化(有线插入/拔出)
if (phy_changed) {
NASW_INFO("物理连接状态变化:%d -> %d",
g_state_cache.last_phy_status,
phy_status.ether);
// 触发物理状态变化处理(带防抖机制)
nasw_handle_physical_change(phy_status.ether);
// 有线拔出时立即重置诊断状态
if (phy_status.ether == 0) {
NASW_INFO("检测到有线拔出,重置诊断状态");
g_state_cache.nasw_wired_diag = PING_STATUS_UNKNOWN;
g_state_cache.ping_count = 0;
}
}
// 处理切换模式变化
if (lte_changed) {
NASW_INFO("切换模式变更:%d -> %d",
g_state_cache.last_auto_switch_wired,
lte_config.auto_switch_wired);
// 立即触发诊断(确保状态同步)
nasw_network_diagnose();
}
return OK;
}
/******************************************************************************
* 停止函数(完整清理资源)
******************************************************************************/
LOCAL S32 nasw_stop(void)
{
NASW_INFO("正在停止NASW模块...");
// 1. 清理网络诊断定时器
if (nasw_network_timer != -1) {
inet_del_timer(nasw_network_timer);
nasw_network_timer = -1;
NASW_INFO("网络诊断定时器已清理");
}
// 2. 清理切换延迟定时器
if (g_switch_delay_timer != -1) {
inet_del_timer(g_switch_delay_timer);
g_switch_delay_timer = -1;
NASW_INFO("切换延迟定时器已清理");
}
// 3. 清理物理防抖定时器
if (g_state_cache.physical_debounce_timer != -1) {
inet_del_timer(g_state_cache.physical_debounce_timer);
g_state_cache.physical_debounce_timer = -1;
NASW_INFO("物理防抖定时器已清理");
}
// 4. 重置状态缓存(包括诊断状态)
memset(&g_state_cache, 0, sizeof(NASW_STATE_CACHE));
g_state_cache.nasw_wired_diag = PING_STATUS_UNKNOWN;
NASW_INFO("NASW模块已完全停止");
return OK;
}
LOCAL void nasw_main()
{
DS_DAT_MON_DESC nasw_data_monitor[] =
{
DS_DAT_MON(LINK_STATUS_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(PHY_STATUS_PATH, DATA_ATTRI_NOTIFY),
#ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT
DS_DAT_MON(LTE_INFO_DATA_PATH, DATA_ATTRI_NOTIFY),
#endif
};
DS_MOD_DESC nasw_module =
DS_STRUCT_MOD("nasw", nasw_init, NULL, nasw_reload, nasw_start, nasw_stop,
NULL, nasw_data_monitor);
MODULE *module_node = ds_register_module("nasw", &nasw_module);
SDM_ASSERT(NULL != module_node);
}
NSD_INIT(nasw_main);
最新发布