LTE用户文档
(如有不当的地方,欢迎指正!)
18 X2-based handover
正如 3GPP 定义的,切换是改变用户服务小区的连接方式的过程。这一过程中涉及的两个基站通常称为源基站和目标基站。
为了使能仿真中 X2 切换的执行,有三个条件必须要满足。首先,仿真中必须使能 EPC(见 Evolved Packet Core (EPC) )。
其次,两个基站之间必须配置 X2 接口,这一点必须在仿真程序中明确交待:
lteHelper->AddX2Interface (enbNodes);
其中,enbNodes 是一个包含两个基站(基站之间配置有 X2 接口)的 NodeContainer (节点容器)。如果容器包含的基站超过两个,函数会在容器的每一对基站之间创建 X2 接口 。
最后,目标基站必须将 X2 切换请求(HANDOVER REQUES)配置为“open”。每个基站默认为开启的,因此大多数情况下不需要额外的命令。 然而,用户可以通过将布尔属性 LteEnbRrc::AdmitHandoverRequest 设为 false 来设置基站“closed” 。例如,你可以运行 lena-x2-handover 程序并按照下列方式设置属性:
NS_LOG=EpcX2:LteEnbRrc ./waf --run lena-x2-handover --command="%s --ns3::LteEnbRrc::AdmitHandoverRequest=false"
在满足上述三个要求后,切换过程就可以自动或手动触发了。下面的小节将一一阐述。
18.1 Manual handover trigger(手动切换触发)
通过调度明确的切换事件来“手动”触发仿真程序中的切换事件。LteHelper 对象为切换事件的调度提供了一个方便的方法。例如,让我们假定 ueLteDevs 为一个 NetDeviceContainer ,包含即将被切换的用户;enbLteDevs 为另一个 NetDeviceContainer ,包含源基站和目标基站。然后,在 0.1 s ,调度切换如下:
lteHelper->HandoverRequest (Seconds (0.100), ueLteDevs.Get (0), enbLteDevs.Get (0), enbLteDevs.Get (1));
注意,用户需要已经连接到源基站,否则仿真会出错终止。
本小节完整的代码参见 src/lte/examples/ lena-x2-handover.cc 。
18.2 Automatic handover trigger(自动切换触发)
切换过程也可以通过用户的服务基站“自动”触发。触发背后的逻辑依赖于当前活跃在基站 RRC 实体中的切换算法。用户可以选择和配置仿真中将使用的切换算法,本节下面将阐述这一点。用户也可以选择自己编写切换算法,详情见设计文档的 Handover algorithm 这一章节。
切换算法的选择是通过 LteHelper 对象和它的 SetHandoverAlgorithmType 方法实现的:
Ptr<LteHelper> lteHelper = CreateObject<LteHelper> (); lteHelper->SetHandoverAlgorithmType ("ns3::A2A4RsrqHandoverAlgorithm");
选定的切换算法也可以提供几种配置属性,如下:
lteHelper->SetHandoverAlgorithmAttribute ("ServingCellThreshold", UintegerValue (30)); lteHelper->SetHandoverAlgorithmAttribute ("NeighbourCellOffset", UintegerValue (1));
LTE 模块中有三种切换算法可供选择。第一种是 A2-A4-RSRQ 切换算法(命名为 ns3::A2A4RsrqHandoverAlgorithm),它是默认算法,使用方法如上。
第二种是最强小区切换算法 strongest cell handover algorithm (命名为 ns3::A3RsrpHandoverAlgorithm),配置方式如下:
lteHelper->SetHandoverAlgorithmType ("ns3::A3RsrpHandoverAlgorithm"); lteHelper->SetHandoverAlgorithmAttribute ("Hysteresis", DoubleValue (3.0)); lteHelper->SetHandoverAlgorithmAttribute ("TimeToTrigger", TimeValue (MilliSeconds (256)));
第三种是最特别的一个,称为 no-op 切换算法,基本上禁用自动切换。当手动切换触发需要专门地控制所有的切换决策时,该算法就会特别有用。它并没有任何配置属性,使用方式如下:
lteHelper->SetHandoverAlgorithmType ("ns3::NoOpHandoverAlgorithm");
每种切换算法的决策策略和属性,请参考设计文档的 Handover algorithm 这一章节。
最后,LteHelper 的 InstallEnbDevice 函数会实例化每个基站设备所选的切换算法。换句话说,在最终确定下列代码前要确保选择正确的切换算法:
NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes);
本小节完整的代码参见 src/lte/examples/lena-x2-handover-measures.cc。
18.3 Tuning simulation with handover
正如设计文档中提及的,当切换失败时,当前切换模型的实现可能产生不可预期的后果。本小节将描述用户在仿真中使用切换时应考虑的几点步骤。
造成切换失败的主要原因是在执行切换过程中传输切换相关的信令发生错误。从设计文档的这个图 Sequence diagram of the X2-based handover 可以明显看出,存在很多信令,并且它们使用不同的接口和协议。为了简单起见,我们可以假定X2接口(源基站和目标基站之间)与 S1 接口(目标基站与 SGW/PGW之间)十分稳定。因此我们重点关注 RRC 协议(在用户和基站之间)和随机接入过程——一般通过空中传输,信道条件容易下降。
减小传输误差的一般建议是确保每个用户有足够高的 SINR。这可以通过合适地计划网络拓扑来最小化网络覆盖空洞。如果拓扑已经有了覆盖空洞,那么应该避免把用户配置在该区域。
另一种方法是避免 too-late handovers 。 换句话说,切换应该发生在用户的 SINR 变得太低之前,否则用户可能不能从源基站那接收到切换命令。切换算法有办法控制什么时候执行切换决策。例如,A2-A4-RSRQ 切换算法可以配置成一个更高的阈值来更早决定切换。相似的,更小的滞后现象或者最强小区切换算法中更短时间的触发通常会导致过早地切换。为了找到这些参数的合适值,应该考虑用户移动速度这一参数。一般而言,一个移动越快的用户需要执行的切换会越早。一些研究作品已经提出了一些推荐值,例如 [Lee2010] 。
上述要点已经足够正常的仿真使用,但是当一些特殊的情况出现时,还要考虑一些极端的措施。例如,用户可能考虑禁用信道误差模型( disabling the channel error models),确保所有切换相关的信令消息成功传输,而不管距离和信道条件。然而,这也会影响所有其他的与切换无关的数据或控制数据包,这可能是不必要的副作用。另外,用户可以使用下列方式实现:
Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false)); Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
通过使用上述代码,我们同时在控制和数据信道以及上行和下行方向上禁用误差模型。这是必要的,因为切换相关的信令消息通过使用这些信道来传输。例外是当仿真使用理想的 RRC 协议时,这种情况下,只需考虑随机接入过程。该过程包含控制消息,因此,我们只需要禁用控制信道的误差模型。
18.4 Handover traces
RRC 模型,特别是 LteEnbRrc 和 LteUeRrc 对象,会提供一些有用的 traces 用于连接一些自定义的函数,以便在用户侧和基站侧、在整个切换执行过程的开始和结束,这些函数都能被调用。例如,在你的仿真程序中,你可以声明下列方法:
void NotifyHandoverStartUe (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, uint16_t targetCellId) { std::cout << Simulator::Now ().GetSeconds () << " " << context << " UE IMSI " << imsi << ": previously connected to CellId " << cellId << " with RNTI " << rnti << ", doing handover to CellId " << targetCellId << std::endl; } void NotifyHandoverEndOkUe (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti) { std::cout << Simulator::Now ().GetSeconds () << " " << context << " UE IMSI " << imsi << ": successful handover to CellId " << cellId << " with RNTI " << rnti << std::endl; } void NotifyHandoverStartEnb (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, uint16_t targetCellId) { std::cout << Simulator::Now ().GetSeconds () << " " << context << " eNB CellId " << cellId << ": start handover of UE with IMSI " << imsi << " RNTI " << rnti << " to CellId " << targetCellId << std::endl; } void NotifyHandoverEndOkEnb (std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti) { std::cout << Simulator::Now ().GetSeconds () << " " << context << " eNB CellId " << cellId << ": completed handover of UE with IMSI " << imsi << " RNTI " << rnti << std::endl; }
然后,你可以把这些方法连接到(hook up)相应的 trace sources ,类似于:
Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverStart", MakeCallback (&NotifyHandoverStartEnb)); Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/HandoverStart", MakeCallback (&NotifyHandoverStartUe)); Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverEndOk", MakeCallback (&NotifyHandoverEndOkEnb)); Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/HandoverEndOk", MakeCallback (&NotifyHandoverEndOkUe));
示例程序 src/lte/examples/lena-x2-handover.cc 表明上述所有指令如何整合到一个仿真程序中。你可以像这样运行程序:
./waf --run lena-x2-handover
并且它将输出由自定义切换 trace hooks print 的消息。为了额外可视化一些有用的日志信息,你可以像这样运行程序:
NS_LOG=LteEnbRrc:LteUeRrc:EpcX2 ./waf --run lena-x2-handover
参考文献
https://www.nsnam.org/docs/models/html/lte-user.html