You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
316 lines
13 KiB
316 lines
13 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using CoreAgent.ProtocolClient.Models;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace CoreAgent.ProtocolClient.Context.UeStateManager
|
|
{
|
|
/// <summary>
|
|
/// UeIdentifierManager TMSI匹配部分
|
|
/// </summary>
|
|
public partial class UeIdentifierManager
|
|
{
|
|
#region TMSI匹配方法
|
|
|
|
/// <summary>
|
|
/// 根据TMSI匹配生成请求UE ID和接收UE ID的对应关系
|
|
/// 使用TmsiMatchProcessor处理匹配逻辑
|
|
/// </summary>
|
|
/// <returns>TMSI匹配结果列表</returns>
|
|
public List<TmsiMatchResult> GenerateTmsiMatches()
|
|
{
|
|
try
|
|
{
|
|
var processor = new TmsiMatchProcessor(TmsiToUeId, RequestTmsiToUeId, ImsiToUeId);
|
|
var results = processor.GenerateTmsiMatches();
|
|
_logger?.LogDebug("生成TMSI匹配结果,共 {Count} 个匹配", results.Count);
|
|
return results;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger?.LogError(ex, "生成TMSI匹配失败");
|
|
throw new GeneralUeIdentifierManagerException("GenerateTmsiMatches", "生成TMSI匹配失败", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据UE ID获取对应的IMSI
|
|
/// 优先查找当前UE ID,如果未找到则查找整个UE链中的IMSI
|
|
/// </summary>
|
|
/// <param name="ueId">UE ID</param>
|
|
/// <returns>对应的IMSI,如果未找到则返回空字符串</returns>
|
|
private string GetImsiForUeId(int ueId)
|
|
{
|
|
if (ueId <= 0)
|
|
{
|
|
_logger?.LogWarning("尝试获取无效UE ID的IMSI: {UeId}", ueId);
|
|
return string.Empty;
|
|
}
|
|
|
|
try
|
|
{
|
|
// 1. 首先查找当前UE ID对应的IMSI
|
|
var currentImsiMapping = ImsiToUeId.FirstOrDefault(kvp => kvp.Value.Contains(ueId));
|
|
if (!string.IsNullOrEmpty(currentImsiMapping.Key))
|
|
{
|
|
return currentImsiMapping.Key;
|
|
}
|
|
|
|
// 2. 如果当前UE ID没有IMSI,查找整个UE链中的IMSI
|
|
var anyImsiMapping = ImsiToUeId.FirstOrDefault(kvp => !string.IsNullOrEmpty(kvp.Key));
|
|
return anyImsiMapping.Key ?? string.Empty;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger?.LogError(ex, "获取UE {UeId} 的IMSI失败", ueId);
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取UE链的统计信息
|
|
/// </summary>
|
|
/// <returns>UE链统计信息</returns>
|
|
public UeChainStats GetUeChainStats()
|
|
{
|
|
try
|
|
{
|
|
var processor = new TmsiMatchProcessor(TmsiToUeId, RequestTmsiToUeId, ImsiToUeId);
|
|
var stats = processor.GetUeChainStats();
|
|
_logger?.LogDebug("获取UE链统计信息成功");
|
|
return stats;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger?.LogError(ex, "获取UE链统计信息失败");
|
|
throw new GeneralUeIdentifierManagerException("GetUeChainStats", "获取UE链统计信息失败", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取所有UE链的详细信息
|
|
/// </summary>
|
|
/// <returns>UE链详细信息列表</returns>
|
|
public List<UeChainInfo> GetUeChainDetails()
|
|
{
|
|
try
|
|
{
|
|
var processor = new TmsiMatchProcessor(TmsiToUeId, RequestTmsiToUeId, ImsiToUeId);
|
|
var details = processor.GetUeChainDetails();
|
|
_logger?.LogDebug("获取UE链详细信息成功,共 {Count} 个链", details.Count);
|
|
return details;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger?.LogError(ex, "获取UE链详细信息失败");
|
|
throw new GeneralUeIdentifierManagerException("GetUeChainDetails", "获取UE链详细信息失败", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将 SrTmsiToUeId 平铺成 SrTmsiMapping 列表,并与 GenerateTmsiMatches 结果匹配更新 IMSI、Root UE ID 和 PLMN
|
|
/// 性能优化:使用LINQ提高查找效率
|
|
/// </summary>
|
|
/// <returns>平铺后的 SrTmsiMapping 列表,包含匹配的 IMSI、Root UE ID 和 PLMN 信息</returns>
|
|
public List<SrTmsiMapping> GenerateSrTmsiMappings(List<TmsiMatchResult> tmsiMatches)
|
|
{
|
|
if (tmsiMatches == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(tmsiMatches));
|
|
}
|
|
|
|
try
|
|
{
|
|
var srTmsiMappings = new List<SrTmsiMapping>();
|
|
|
|
// 1. 平铺 SrTmsiToUeId 字典数据
|
|
foreach (var kvp in SrTmsiToUeId)
|
|
{
|
|
uint tmsi = kvp.Key;
|
|
var ueIds = kvp.Value;
|
|
|
|
foreach (int ueId in ueIds)
|
|
{
|
|
var mapping = new SrTmsiMapping(string.Empty, tmsi, ueId);
|
|
srTmsiMappings.Add(mapping);
|
|
}
|
|
}
|
|
|
|
// 2. 获取 UE 链信息以获取最外层的 Root UE ID
|
|
var ueChainDetails = GetUeChainDetails();
|
|
|
|
// 3. 根据 TMSI 匹配结果更新 SrTmsiMapping 的 IMSI 和 Root UE ID
|
|
foreach (var srMapping in srTmsiMappings)
|
|
{
|
|
UpdateSrTmsiMapping(srMapping, tmsiMatches, ueChainDetails);
|
|
}
|
|
|
|
// 4. 根据 RootUeId 从 PlmnToUeId 映射表更新 PLMN 信息
|
|
foreach (var srMapping in srTmsiMappings)
|
|
{
|
|
UpdateSrTmsiMappingPlmn(srMapping, ueChainDetails);
|
|
}
|
|
|
|
_logger?.LogDebug("生成Service Request TMSI映射成功,共 {Count} 个映射", srTmsiMappings.Count);
|
|
return srTmsiMappings;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger?.LogError(ex, "生成Service Request TMSI映射失败");
|
|
throw new GeneralUeIdentifierManagerException("GenerateSrTmsiMappings", "生成Service Request TMSI映射失败", ex);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 私有辅助方法
|
|
|
|
/// <summary>
|
|
/// 更新 SrTmsiMapping 的 IMSI 和 Root UE ID
|
|
/// </summary>
|
|
/// <param name="srMapping">Service Request TMSI映射</param>
|
|
/// <param name="tmsiMatches">TMSI匹配结果</param>
|
|
/// <param name="ueChainDetails">UE链详细信息</param>
|
|
private void UpdateSrTmsiMapping(SrTmsiMapping srMapping, List<TmsiMatchResult> tmsiMatches, List<UeChainInfo> ueChainDetails)
|
|
{
|
|
// 查找匹配的 TMSI 结果
|
|
var matchingResult = tmsiMatches.FirstOrDefault(match => match.Tmsi == srMapping.Tmsi);
|
|
|
|
if (matchingResult != null && !string.IsNullOrEmpty(matchingResult.Imsi))
|
|
{
|
|
// 更新 IMSI
|
|
srMapping.Imsi = matchingResult.Imsi;
|
|
|
|
// 查找对应的最外层 Root UE ID
|
|
var chainInfo = ueChainDetails.FirstOrDefault(chain =>
|
|
chain.UeIds.Contains(srMapping.UeId));
|
|
|
|
if (chainInfo != null)
|
|
{
|
|
srMapping.RootUeId = chainInfo.RootUeId;
|
|
}
|
|
else
|
|
{
|
|
// 如果当前 UE ID 不在任何链中,尝试从匹配结果中查找
|
|
chainInfo = ueChainDetails.FirstOrDefault(chain =>
|
|
chain.UeIds.Contains(matchingResult.RequestUeId) ||
|
|
chain.UeIds.Contains(matchingResult.ReceiveUeId));
|
|
|
|
if (chainInfo != null)
|
|
{
|
|
srMapping.RootUeId = chainInfo.RootUeId;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 如果 TMSI 匹配中没有找到,尝试从 ImsiToUeId 映射中查找
|
|
string imsi = GetImsiForUeId(srMapping.UeId);
|
|
if (!string.IsNullOrEmpty(imsi))
|
|
{
|
|
srMapping.Imsi = imsi;
|
|
|
|
// 查找对应的最外层 Root UE ID
|
|
var chainInfo = ueChainDetails.FirstOrDefault(chain =>
|
|
chain.UeIds.Contains(srMapping.UeId));
|
|
|
|
if (chainInfo != null)
|
|
{
|
|
srMapping.RootUeId = chainInfo.RootUeId;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新 SrTmsiMapping 的 PLMN 信息
|
|
/// </summary>
|
|
/// <param name="srMapping">Service Request TMSI映射</param>
|
|
private void UpdateSrTmsiMappingPlmn(SrTmsiMapping srMapping, List<UeChainInfo> ueChainDetails)
|
|
{
|
|
try
|
|
{
|
|
_logger?.LogDebug("开始更新SrTmsiMapping PLMN信息 - TMSI: {Tmsi}, UeId: {UeId}, RootUeId: {RootUeId}",
|
|
srMapping.Tmsi, srMapping.UeId, srMapping.RootUeId);
|
|
|
|
if (srMapping.RootUeId > 0)
|
|
{
|
|
_logger?.LogDebug("使用RootUeId {RootUeId} 查找PLMN映射", srMapping.RootUeId);
|
|
|
|
// 查找包含 RootUeId 的 PLMN 映射
|
|
var plmnMapping = PlmnToUeId.FirstOrDefault(kvp => kvp.Value.Contains(srMapping.RootUeId));
|
|
if (!string.IsNullOrEmpty(plmnMapping.Key))
|
|
{
|
|
srMapping.Plmn = plmnMapping.Key;
|
|
_logger?.LogDebug("通过RootUeId找到PLMN: {Plmn}", plmnMapping.Key);
|
|
}
|
|
else
|
|
{
|
|
_logger?.LogDebug("未找到RootUeId {RootUeId} 对应的PLMN映射", srMapping.RootUeId);
|
|
}
|
|
}
|
|
else if (srMapping.UeId > 0)
|
|
{
|
|
_logger?.LogDebug("使用UeId {UeId} 和TMSI {Tmsi} 查找PLMN映射", srMapping.UeId, srMapping.Tmsi);
|
|
|
|
// 使用TryGetValue检查TMSI是否存在并获取对应的UeId
|
|
if (TmsiToUeId.TryGetValue(srMapping.Tmsi, out int filterUeId) && filterUeId > 0)
|
|
{
|
|
_logger?.LogDebug("找到TMSI {Tmsi} 对应的UeId: {FilterUeId}", srMapping.Tmsi, filterUeId);
|
|
|
|
// 如果 RootUeId 为空,尝试使用 UeId 查找 PLMN
|
|
var chainInfo = ueChainDetails?.FirstOrDefault(chain =>
|
|
chain?.UeIds?.Contains(filterUeId) == true);
|
|
|
|
if (chainInfo != null)
|
|
{
|
|
_logger?.LogDebug("找到包含UeId {FilterUeId} 的UE链,RootUeId: {ChainRootUeId}",
|
|
filterUeId, chainInfo.RootUeId);
|
|
|
|
var plmnMapping = PlmnToUeId.FirstOrDefault(kvp =>
|
|
kvp.Value?.Contains(filterUeId) == true);
|
|
|
|
if (!string.IsNullOrEmpty(plmnMapping.Key))
|
|
{
|
|
srMapping.Plmn = plmnMapping.Key;
|
|
srMapping.RootUeId = chainInfo.RootUeId;
|
|
_logger?.LogDebug("通过UeId找到PLMN: {Plmn}, 更新RootUeId: {RootUeId}",
|
|
plmnMapping.Key, chainInfo.RootUeId);
|
|
}
|
|
else
|
|
{
|
|
_logger?.LogDebug("未找到UeId {FilterUeId} 对应的PLMN映射", filterUeId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_logger?.LogDebug("未找到包含UeId {FilterUeId} 的UE链", filterUeId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_logger?.LogDebug("TMSI {Tmsi} 对应的UeId无效或为0", srMapping.Tmsi);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_logger?.LogDebug("SrTmsiMapping的UeId和RootUeId都无效,跳过PLMN更新");
|
|
}
|
|
|
|
_logger?.LogDebug("SrTmsiMapping PLMN信息更新完成 - TMSI: {Tmsi}, UeId: {UeId}, RootUeId: {RootUeId}, PLMN: {Plmn}",
|
|
srMapping.Tmsi, srMapping.UeId, srMapping.RootUeId, srMapping.Plmn);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger?.LogError(ex, "更新SrTmsiMapping PLMN信息失败 - TMSI: {Tmsi}, UeId: {UeId}, RootUeId: {RootUeId}",
|
|
srMapping.Tmsi, srMapping.UeId, srMapping.RootUeId);
|
|
throw new GeneralUeIdentifierManagerException("UpdateSrTmsiMappingPlmn", "更新SrTmsiMapping PLMN信息失败", ex);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
|