Browse Source

Update network configuration and add IP endpoint management

master
root 2 days ago
parent
commit
4281f6543f
  1. 1
      CoreAgent.API/Program.cs
  2. 1
      CoreAgent.API/Startup.cs
  3. 53
      CoreAgent.Domain/Interfaces/Network/ICellularNetworkContext.cs
  4. 7
      CoreAgent.Domain/Interfaces/Network/INetworkConfigCopier.cs
  5. 35
      CoreAgent.Domain/Interfaces/Network/INetworkIPEndPointManager.cs
  6. 9
      CoreAgent.Domain/Models/Network/CnIPEndPoint.cs
  7. 9
      CoreAgent.Domain/Models/Network/ImsIPEndPoint.cs
  8. 17
      CoreAgent.Domain/Models/Network/NetworkIPEndPoint.cs
  9. 22
      CoreAgent.Domain/Models/Network/NetworkIPEndPoints.cs
  10. 17
      CoreAgent.Domain/Models/Network/RanIPEndPoint.cs
  11. 15
      CoreAgent.Infrastructure/Contexts/CellularNetworkContext.cs
  12. 4
      CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs
  13. 25
      CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs
  14. 134
      CoreAgent.Infrastructure/Services/Network/NetworkConfigCopier.cs
  15. 116
      CoreAgent.Infrastructure/Services/Network/NetworkIPEndPointManager.cs

1
CoreAgent.API/Program.cs

@ -1,5 +1,4 @@
using CoreAgent.API;
using CoreAgent.Domain.Contexts;
using CoreAgent.Domain.Interfaces.Network;
using CoreAgent.Domain.Models.System;
using CoreAgent.Infrastructure.Logging;

1
CoreAgent.API/Startup.cs

@ -3,7 +3,6 @@ using Serilog;
using CoreAgent.Infrastructure.Extensions.Logging;
using CoreAgent.Infrastructure.Extensions.ServiceCollection;
using CoreAgent.Infrastructure.Middleware.GlobalException;
using CoreAgent.Domain.Contexts;
using CoreAgent.Domain.Models.System;
using Microsoft.Extensions.Configuration;
using CoreAgent.Domain.Interfaces.Network;

53
CoreAgent.Domain/Interfaces/Network/ICellularNetworkContext.cs

@ -8,6 +8,8 @@ namespace CoreAgent.Domain.Interfaces.Network;
/// </summary>
public interface ICellularNetworkContext
{
#region 基础属性
/// <summary>
/// 获取取消令牌源
/// </summary>
@ -18,12 +20,35 @@ public interface ICellularNetworkContext
/// </summary>
bool IsInitialized { get; }
/// <summary>
/// 网络IP端点管理器
/// </summary>
INetworkIPEndPointManager NetworkIPEndPointManager { get; }
#endregion
#region 生命周期管理
/// <summary>
/// 初始化上下文
/// </summary>
/// <param name="neConfigKey">网络配置键</param>
void Initialize(string neConfigKey);
/// <summary>
/// 重置上下文状态
/// </summary>
void Reset();
/// <summary>
/// 取消操作
/// </summary>
void Cancel();
#endregion
#region 网络配置管理
/// <summary>
/// 获取网络命令配置
/// </summary>
@ -35,6 +60,15 @@ public interface ICellularNetworkContext
/// </summary>
string GetNeConfigKey();
/// <summary>
/// 获取应用设置
/// </summary>
AppSettings GetAppSettings();
#endregion
#region 命令管理
/// <summary>
/// 获取指定类型的命令配置
/// </summary>
@ -48,24 +82,15 @@ public interface ICellularNetworkContext
/// <returns>命令类型数组</returns>
NetworkCommandType[] GetCommandTypes();
#endregion
#region 状态管理
/// <summary>
/// 获取网络状态
/// </summary>
/// <returns>网络状态</returns>
CellularNetworkState GetNetworkState();
/// <summary>
/// 重置上下文状态
/// </summary>
void Reset();
/// <summary>
/// 取消操作
/// </summary>
void Cancel();
/// <summary>
/// 获取应用设置
/// </summary>
AppSettings GetAppSettings();
#endregion
}

7
CoreAgent.Domain/Interfaces/Network/INetworkConfigCopier.cs

@ -16,4 +16,11 @@ public interface INetworkConfigCopier
/// <param name="appSettings">应用设置</param>
/// <returns>复制结果</returns>
Task<NetworkConfigCopyResult> CopyConfigValuesToTempAsync(NetworkConfiguration networkConfig, AppSettings appSettings);
/// <summary>
/// 获取所有配置文件的 IP 端点信息
/// </summary>
/// <param name="networkConfig">网络配置</param>
/// <returns>(EndPoints: IP 端点信息集合, HasAnyEndPoint: 是否成功获取到任何端点信息)</returns>
Task<(NetworkIPEndPoints EndPoints, bool HasAnyEndPoint)> GetComAddrInfoAsync(NetworkConfiguration networkConfig);
}

35
CoreAgent.Domain/Interfaces/Network/INetworkIPEndPointManager.cs

@ -0,0 +1,35 @@
using CoreAgent.Domain.Models.Network;
namespace CoreAgent.Domain.Interfaces.Network;
/// <summary>
/// 网络 IP 端点管理器接口
/// </summary>
public interface INetworkIPEndPointManager
{
/// <summary>
/// 更新 IP 端点信息
/// </summary>
/// <param name="endPoints">IP 端点信息集合</param>
void UpdateEndPoints(NetworkIPEndPoints endPoints);
/// <summary>
/// 获取 RAN 端点信息
/// </summary>
RanIPEndPoint GetRanEndPoint();
/// <summary>
/// 获取 CN 端点列表
/// </summary>
List<CnIPEndPoint> GetCnEndPoints();
/// <summary>
/// 获取 IMS 端点列表
/// </summary>
List<ImsIPEndPoint> GetImsEndPoints();
/// <summary>
/// 清除所有端点信息
/// </summary>
void Clear();
}

9
CoreAgent.Domain/Models/Network/CnIPEndPoint.cs

@ -0,0 +1,9 @@
namespace CoreAgent.Domain.Models.Network;
/// <summary>
/// CN网络IP端点模型
/// </summary>
public class CnIPEndPoint : NetworkIPEndPoint
{
// CN特有的属性
}

9
CoreAgent.Domain/Models/Network/ImsIPEndPoint.cs

@ -0,0 +1,9 @@
namespace CoreAgent.Domain.Models.Network;
/// <summary>
/// IMS网络IP端点模型
/// </summary>
public class ImsIPEndPoint : NetworkIPEndPoint
{
// IMS特有的属性
}

17
CoreAgent.Domain/Models/Network/NetworkIPEndPoint.cs

@ -0,0 +1,17 @@
namespace CoreAgent.Domain.Models.Network;
/// <summary>
/// 网络IP端点基础模型
/// </summary>
public class NetworkIPEndPoint
{
/// <summary>
/// PLMN标识
/// </summary>
public string Plmn { get; set; }
/// <summary>
/// 通信地址
/// </summary>
public string ComAddr { get; set; }
}

22
CoreAgent.Domain/Models/Network/NetworkIPEndPoints.cs

@ -0,0 +1,22 @@
namespace CoreAgent.Domain.Models.Network;
/// <summary>
/// 网络 IP 端点集合
/// </summary>
public class NetworkIPEndPoints
{
/// <summary>
/// IMS 网络 IP 端点列表
/// </summary>
public List<ImsIPEndPoint> ImsEndPoints { get; set; } = new();
/// <summary>
/// 核心网络 IP 端点列表
/// </summary>
public List<CnIPEndPoint> CnEndPoints { get; set; } = new();
/// <summary>
/// RAN 网络 IP 端点
/// </summary>
public RanIPEndPoint RanEndPoint { get; set; }
}

17
CoreAgent.Domain/Models/Network/RanIPEndPoint.cs

@ -0,0 +1,17 @@
namespace CoreAgent.Domain.Models.Network;
/// <summary>
/// RAN 网络 IP 端点信息
/// </summary>
public class RanIPEndPoint
{
/// <summary>
/// 通信地址
/// </summary>
public string ComAddr { get; set; }
/// <summary>
/// PLMN 列表
/// </summary>
public List<string> Plmns { get; set; } = new();
}

15
CoreAgent.Domain/Contexts/CellularNetworkContext.cs → CoreAgent.Infrastructure/Contexts/CellularNetworkContext.cs

@ -1,9 +1,10 @@
using CoreAgent.Domain.Interfaces;
using CoreAgent.Domain.Interfaces.Network;
using CoreAgent.Domain.Models.Network;
using CoreAgent.Domain.Models.System;
using Microsoft.Extensions.Options;
namespace CoreAgent.Domain.Contexts;
namespace CoreAgent.Infrastructure.Contexts;
/// <summary>
/// 蜂窝网络领域上下文
@ -18,6 +19,7 @@ public class CellularNetworkContext : ICellularNetworkContext, IDisposable
private CancellationTokenSource _token;
private bool _isDisposed;
private bool _isInitialized;
private readonly INetworkIPEndPointManager _networkIPEndPointManager;
/// <summary>
/// 获取取消令牌源
@ -29,15 +31,22 @@ public class CellularNetworkContext : ICellularNetworkContext, IDisposable
/// </summary>
public bool IsInitialized => _isInitialized;
/// <summary>
/// 网络IP端点管理器
/// </summary>
public INetworkIPEndPointManager NetworkIPEndPointManager => _networkIPEndPointManager;
public CellularNetworkContext(
IOptions<NetworkCommandConfig> networkCommandConfig,
IOptions<AppSettings> appSettings)
IOptions<AppSettings> appSettings,
INetworkIPEndPointManager networkIPEndPointManager)
{
_isDisposed = false;
_isInitialized = false;
_token = new CancellationTokenSource();
_networkCommandConfig = networkCommandConfig?.Value ?? throw new ArgumentNullException(nameof(networkCommandConfig));
_appSettings = appSettings?.Value ?? throw new ArgumentNullException(nameof(appSettings));
_networkIPEndPointManager = networkIPEndPointManager ?? throw new ArgumentNullException(nameof(networkIPEndPointManager));
}
/// <summary>
@ -63,6 +72,7 @@ public class CellularNetworkContext : ICellularNetworkContext, IDisposable
lock (_lock)
{
_networkIPEndPointManager.Clear();
_neConfigKey = neConfigKey;
_networkState = new CellularNetworkState(_neConfigKey);
_isInitialized = true;
@ -181,6 +191,7 @@ public class CellularNetworkContext : ICellularNetworkContext, IDisposable
_neConfigKey = string.Empty;
_isInitialized = false;
_networkState = new CellularNetworkState(string.Empty);
_networkIPEndPointManager.Clear();
}
}

4
CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs

@ -1,8 +1,9 @@
using CoreAgent.Domain.Contexts;
using CoreAgent.Domain.Interfaces;
using CoreAgent.Domain.Interfaces.Network;
using CoreAgent.Domain.Interfaces.System.Command;
using CoreAgent.Infrastructure.Command.Factories;
using CoreAgent.Infrastructure.Contexts;
using CoreAgent.Infrastructure.Repositories;
using CoreAgent.Infrastructure.Services;
using CoreAgent.Infrastructure.Services.Network;
@ -22,6 +23,7 @@ public static class CommandServiceExtensions
/// <returns>服务集合</returns>
public static IServiceCollection AddCommandCustomService(this IServiceCollection services)
{
services.AddSingleton<INetworkIPEndPointManager, NetworkIPEndPointManager>();
services.AddSingleton<ICellularNetworkContext, CellularNetworkContext>();
// 注册命令执行器工厂
services.AddSingleton<ISystemCommandExecutorFactory, SystemCommandExecutorFactory>();

25
CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs

@ -1,5 +1,4 @@
using CliWrap;
using CoreAgent.Domain.Contexts;
using CoreAgent.Domain.Entities;
using CoreAgent.Domain.Interfaces;
using CoreAgent.Domain.Interfaces.Network;
@ -24,12 +23,8 @@ public class CellularNetworkService : ICellularNetworkService
private readonly INetworkConfigCopier _configCopier;
private readonly INetworkInterfaceManager _interfaceManager;
private static readonly SemaphoreSlim _startLock = new(1, 1);
private const int MaxConnectionAttempts = 30;
private const int ConnectionCheckDelayMs = 1000;
private const int LockTimeoutSeconds = 5;
private const string NULL_CONFIG = "NULL";
private const string KILL_COMMAND_TEMPLATE = "ps -ef | grep {0} | grep -v grep | awk '{{print $2}}' | xargs kill -9";
private const string COM_ADDR_TEMPLATE = "cat {0} | grep com_addr | awk -F'\"' '{{print $4}}'";
private const int LockTimeoutSeconds = 60;
public CellularNetworkService(
ILogger<CellularNetworkService> logger,
@ -223,7 +218,19 @@ public class CellularNetworkService : ICellularNetworkService
return CellularNetworkOperationResult.Failure(message);
}
// 4. 启动网络配置
// 4. 获取 IP 端点信息
var (endPoints, hasAnyEndPoint) = await _configCopier.GetComAddrInfoAsync(config);
if (!hasAnyEndPoint)
{
var message = "未获取到任何有效的 IP 端点信息";
_logger.LogError(message);
return CellularNetworkOperationResult.Failure(message);
}
// 5. 更新 IP 端点管理器
_context.NetworkIPEndPointManager.UpdateEndPoints(endPoints);
// 6. 启动网络配置
_logger.LogInformation("正在启动蜂窝网络配置: {ConfigKey}", key);
var enableResult = await _interfaceManager.EnableAsync(config);
if (!enableResult.IsSuccess)
@ -233,7 +240,7 @@ public class CellularNetworkService : ICellularNetworkService
return CellularNetworkOperationResult.Failure(message);
}
// 5. 更新状态
// 7. 更新状态
var state = _context.GetNetworkState();
state.MarkAsStarted();
_logger.LogInformation("蜂窝网络配置 {ConfigKey} 启动成功", key);

134
CoreAgent.Infrastructure/Services/Network/NetworkConfigCopier.cs

@ -16,6 +16,7 @@ public class NetworkConfigCopier : INetworkConfigCopier
private readonly ILogger<NetworkConfigCopier> _logger;
private readonly ISystemCommandExecutor _commandExecutor;
private const string COM_ADDR_TEMPLATE = "cat {0} | grep com_addr | awk -F'\"' '{{print $4}}'";
private const string PLMN_TEMPLATE = "cat {0} | grep plmn | awk -F'\"' '{{print $4}}'";
public NetworkConfigCopier(
ILogger<NetworkConfigCopier> logger,
@ -38,13 +39,6 @@ public class NetworkConfigCopier : INetworkConfigCopier
// 复制 RAG 配置文件
if (!string.IsNullOrEmpty(networkConfig.RagConfig))
{
// 获取com_addr值
var (isSuccess, comAddr, errorMessage) = await GetComAddrValueAsync(networkConfig.RagConfig, "RAG");
if (!isSuccess)
{
return NetworkConfigCopyResult.Failure($"RAG配置文件验证失败: {errorMessage}");
}
if (!CopyConfigFile(networkConfig.RagConfig, appSettings.RanConfigDirectory,
path => networkConfig.RagConfig = path, "RAG"))
{
@ -57,13 +51,6 @@ public class NetworkConfigCopier : INetworkConfigCopier
{
if (!string.IsNullOrEmpty(config.CoreNetworkConfig))
{
// 获取CN com_addr值
var (isSuccess, comAddr, errorMessage) = await GetComAddrValueAsync(config.CoreNetworkConfig, "CN");
if (!isSuccess)
{
return NetworkConfigCopyResult.Failure($"CN配置文件验证失败: {errorMessage}");
}
if (!CopyConfigFile(config.CoreNetworkConfig, appSettings.MmeConfigDirectory,
path => config.CoreNetworkConfig = path, "核心网络"))
{
@ -73,13 +60,6 @@ public class NetworkConfigCopier : INetworkConfigCopier
if (!string.IsNullOrEmpty(config.ImsConfig))
{
// 获取IMS com_addr值
var (isSuccess, comAddr, errorMessage) = await GetComAddrValueAsync(config.ImsConfig, "IMS");
if (!isSuccess)
{
return NetworkConfigCopyResult.Failure($"IMS配置文件验证失败: {errorMessage}");
}
if (!CopyConfigFile(config.ImsConfig, appSettings.MmeConfigDirectory,
path => config.ImsConfig = path, "IMS"))
{
@ -132,6 +112,48 @@ public class NetworkConfigCopier : INetworkConfigCopier
}
}
/// <summary>
/// 获取配置文件中的 plmn 值
/// </summary>
private async Task<(bool IsSuccess, List<string> Plmns, string ErrorMessage)> GetPlmnValuesAsync(string configPath, string configType)
{
if (string.IsNullOrEmpty(configPath))
{
return (false, null, $"{configType}配置文件路径为空");
}
if (!File.Exists(configPath))
{
return (false, null, $"{configType}配置文件不存在: {configPath}");
}
var result = await _commandExecutor.ExecuteCommandAsync(
string.Format(PLMN_TEMPLATE, configPath),
new CancellationTokenSource());
if (result.IsSuccess)
{
var plmns = result.Output
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
.Select(p => p.Trim())
.Where(p => !string.IsNullOrEmpty(p))
.Distinct()
.ToList();
if (plmns.Count == 0)
{
return (false, null, $"{configType}配置文件中未找到 plmn 值");
}
_logger.LogInformation("获取到{ConfigType} plmn值: {Plmns}", configType, string.Join(", ", plmns));
return (true, plmns, null);
}
else
{
return (false, null, $"获取{configType} plmn值失败: {result.Error}");
}
}
private void EnsureDirectoriesExist(AppSettings appSettings)
{
if (!Directory.Exists(appSettings.TempDirectory))
@ -177,4 +199,74 @@ public class NetworkConfigCopier : INetworkConfigCopier
return true;
}
/// <summary>
/// 获取所有配置文件的 IP 端点信息
/// </summary>
/// <param name="networkConfig">网络配置</param>
/// <returns>(EndPoints: IP 端点信息集合, HasAnyEndPoint: 是否成功获取到任何端点信息)</returns>
public async Task<(NetworkIPEndPoints EndPoints, bool HasAnyEndPoint)> GetComAddrInfoAsync(NetworkConfiguration networkConfig)
{
var endPoints = new NetworkIPEndPoints();
bool hasAnyEndPoint = false;
try
{
// 获取 RAN com_addr 和 plmn
if (!string.IsNullOrEmpty(networkConfig.RagConfig))
{
var (isSuccess, comAddr, _) = await GetComAddrValueAsync(networkConfig.RagConfig, "RAG");
var (plmnSuccess, plmns, _) = await GetPlmnValuesAsync(networkConfig.RagConfig, "RAG");
if (isSuccess && plmnSuccess)
{
endPoints.RanEndPoint = new RanIPEndPoint
{
ComAddr = comAddr,
Plmns = plmns
};
hasAnyEndPoint = true;
}
}
// 获取 CN 和 IMS com_addr
foreach (var config in networkConfig.CoreOrImsConfigs)
{
if (!string.IsNullOrEmpty(config.CoreNetworkConfig))
{
var (isSuccess, comAddr, _) = await GetComAddrValueAsync(config.CoreNetworkConfig, "CN");
if (isSuccess)
{
endPoints.CnEndPoints.Add(new CnIPEndPoint
{
ComAddr = comAddr,
Plmn = config.Plmn
});
hasAnyEndPoint = true;
}
}
if (!string.IsNullOrEmpty(config.ImsConfig))
{
var (isSuccess, comAddr, _) = await GetComAddrValueAsync(config.ImsConfig, "IMS");
if (isSuccess)
{
endPoints.ImsEndPoints.Add(new ImsIPEndPoint
{
ComAddr = comAddr,
Plmn = config.Plmn
});
hasAnyEndPoint = true;
}
}
}
return (EndPoints: endPoints, HasAnyEndPoint: hasAnyEndPoint);
}
catch (Exception ex)
{
_logger.LogError(ex, "获取 IP 端点信息时发生错误");
return (EndPoints: endPoints, HasAnyEndPoint: false);
}
}
}

116
CoreAgent.Infrastructure/Services/Network/NetworkIPEndPointManager.cs

@ -0,0 +1,116 @@
using CoreAgent.Domain.Interfaces.Network;
using CoreAgent.Domain.Models.Network;
using Microsoft.Extensions.Logging;
namespace CoreAgent.Infrastructure.Services.Network;
/// <summary>
/// 网络 IP 端点管理器实现
/// </summary>
public class NetworkIPEndPointManager : INetworkIPEndPointManager
{
private readonly ILogger<NetworkIPEndPointManager> _logger;
private readonly object _lock = new();
private RanIPEndPoint _ranEndPoint;
private readonly List<CnIPEndPoint> _cnEndPoints = new();
private readonly List<ImsIPEndPoint> _imsEndPoints = new();
public NetworkIPEndPointManager(ILogger<NetworkIPEndPointManager> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
/// <summary>
/// 更新 IP 端点信息
/// </summary>
/// <param name="endPoints">IP 端点信息集合</param>
public void UpdateEndPoints(NetworkIPEndPoints endPoints)
{
if (endPoints == null)
{
_logger.LogWarning("更新 IP 端点信息失败:端点信息集合为 null");
return;
}
lock (_lock)
{
// 更新 RAN 端点
_ranEndPoint = endPoints.RanEndPoint;
if (_ranEndPoint == null)
{
_logger.LogInformation("RAN 端点信息为空");
}
// 更新 CN 端点列表
_cnEndPoints.Clear();
if (endPoints.CnEndPoints != null && endPoints.CnEndPoints.Any())
{
_cnEndPoints.AddRange(endPoints.CnEndPoints);
_logger.LogInformation("更新 CN 端点列表,共 {Count} 个端点", endPoints.CnEndPoints.Count);
}
else
{
_logger.LogInformation("CN 端点列表为空");
}
// 更新 IMS 端点列表
_imsEndPoints.Clear();
if (endPoints.ImsEndPoints != null && endPoints.ImsEndPoints.Any())
{
_imsEndPoints.AddRange(endPoints.ImsEndPoints);
_logger.LogInformation("更新 IMS 端点列表,共 {Count} 个端点", endPoints.ImsEndPoints.Count);
}
else
{
_logger.LogInformation("IMS 端点列表为空");
}
}
}
/// <summary>
/// 获取 RAN 端点信息
/// </summary>
public RanIPEndPoint GetRanEndPoint()
{
lock (_lock)
{
return _ranEndPoint;
}
}
/// <summary>
/// 获取 CN 端点列表
/// </summary>
public List<CnIPEndPoint> GetCnEndPoints()
{
lock (_lock)
{
return new List<CnIPEndPoint>(_cnEndPoints);
}
}
/// <summary>
/// 获取 IMS 端点列表
/// </summary>
public List<ImsIPEndPoint> GetImsEndPoints()
{
lock (_lock)
{
return new List<ImsIPEndPoint>(_imsEndPoints);
}
}
/// <summary>
/// 清除所有端点信息
/// </summary>
public void Clear()
{
lock (_lock)
{
_ranEndPoint = null;
_cnEndPoints.Clear();
_imsEndPoints.Clear();
_logger.LogInformation("已清除所有 IP 端点信息");
}
}
}
Loading…
Cancel
Save