# HG changeset patch # User Budiarto Herman # Date 1377433665 -10800 # Node ID e6f604c8cb6c91471f29fbb7cde319a5995796bf # Parent 0083a28333f2a1ddf6d064c17bdee5cfca254d43 Updated user documentation of handover diff -r 0083a28333f2 -r e6f604c8cb6c src/lte/doc/source/lte-user.rst --- a/src/lte/doc/source/lte-user.rst Sun Aug 25 15:27:21 2013 +0300 +++ b/src/lte/doc/source/lte-user.rst Sun Aug 25 15:27:45 2013 +0300 @@ -759,6 +759,7 @@ +.. _sec-evolved-packet-core: Evolved Packet Core (EPC) ------------------------- @@ -1026,14 +1027,12 @@ #. developing a new handover algorithm. -This section will cover the first and second methods, while the third method is -covered in :ref:`sec-handover-algorithm`. +This section will cover the first method only. The second method is covered in +:ref:`sec-automatic-handover`, while the third method is explained in length in +Section :ref:`sec-handover-algorithm` of the design documentation. -Direct configuration in eNodeB RRC entity -***************************************** - -Users may add their custom UE measurement configuration by creating a new -``LteRrcSap::ReportConfigEutra`` instance and pass it to the +Direct configuration in eNodeB RRC works as follows. User begins by creating a +new ``LteRrcSap::ReportConfigEutra`` instance and pass it to the ``LteEnbRrc::AddUeMeasReportConfig`` function. The function will return the ``measId`` (measurement identity) which is a unique reference of the configuration in the eNodeB instance. This function must be called before the @@ -1049,29 +1048,29 @@ The code sample below configures Event A1 RSRP measurement to every eNodeB within the container ``devs``:: - LteRrcSap::ReportConfigEutra config; - config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1; - config.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRP; - config.threshold1.range = 41; - config.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRP; - config.reportInterval = LteRrcSap::ReportConfigEutra::MS480; - - std::vector measIdList; + LteRrcSap::ReportConfigEutra config; + config.eventId = LteRrcSap::ReportConfigEutra::EVENT_A1; + config.threshold1.choice = LteRrcSap::ThresholdEutra::THRESHOLD_RSRP; + config.threshold1.range = 41; + config.triggerQuantity = LteRrcSap::ReportConfigEutra::RSRP; + config.reportInterval = LteRrcSap::ReportConfigEutra::MS480; + + std::vector measIdList; - NetDeviceContainer::Iterator it; - for (it = devs.Begin (); it != devs.End (); it++) - { - Ptr dev = *it; - Ptr enbDev = dev->GetObject (); - Ptr enbRrc = enbDev->GetRrc (); + NetDeviceContainer::Iterator it; + for (it = devs.Begin (); it != devs.End (); it++) + { + Ptr dev = *it; + Ptr enbDev = dev->GetObject (); + Ptr enbRrc = enbDev->GetRrc (); - uint8_t measId = enbRrc->AddUeMeasReportConfig (config); - measIdList.push_back (measId); // remember the measId created + uint8_t measId = enbRrc->AddUeMeasReportConfig (config); + measIdList.push_back (measId); // remember the measId created - enbRrc->TraceConnect ("RecvMeasurementReport", - "context", - MakeCallback (&RecvMeasurementReportCallback)); - } + enbRrc->TraceConnect ("RecvMeasurementReport", + "context", + MakeCallback (&RecvMeasurementReportCallback)); + } Note that thresholds are expressed as range. In the example above, the range 41 for RSRP corresponds to -100 dBm. The conversion from and to the range format is @@ -1080,12 +1079,12 @@ The corresponding callback function would have a definition similar as below:: - void - RecvMeasurementReportCallback (std::string context, - uint64_t imsi, - uint16_t cellId, - uint16_t rnti, - LteRrcSap::MeasurementReport measReport); + void + RecvMeasurementReportCallback (std::string context, + uint64_t imsi, + uint16_t cellId, + uint16_t rnti, + LteRrcSap::MeasurementReport measReport); This method will register the callback function as a consumer of UE measurements. In the case where there are more than one consumers in the @@ -1118,18 +1117,6 @@ - *measurement gaps* are not supported, because it is only applicable for inter-frequency settings; -Configuring existing handover algorithm -*************************************** - -Each handover algorithm subclass has its own set of attributes. Similar with -how FF MAC Scheduler is configured, custom values can be provided to these -attributes by calling ``LteHelper::SetHandoverAlgorithmAttribute``. - -The updated attributes may change the measurement configuration that the -handover algorithm requires from the UE. For example, the Strongest Cell -handover algorithm has attributes for `A3Offset` and `TimeToTrigger`, and will -request UE measurement according to the value of these attributes. - .. _sec-x2-based-handover: @@ -1137,70 +1124,120 @@ X2-based handover ----------------- -The execution of an X2-based handover between two eNBs requires the -configuration of an X2 interface between the two eNBs. This needs to -be done explicitly within the simulation program like this:: +As defined by 3GPP, handover is a procedure for changing the serving cell of a +UE in CONNECTED mode. The two eNodeBs involved in the process are typically +called the *source eNodeB* and the *target eNodeB*. + +In order to enable the execution of X2-based handover in simulation, there are +two requirements that must be met. Firstly, EPC must be enabled in the +simulation (see :ref:`sec-evolved-packet-core`). + +Secondly, an X2 interface must be configured between the two eNodeBs, which +needs to be done explicitly within the simulation program:: + + lteHelper->AddX2Interface (enbNodes); - lteHelper->AddX2Interface (enbNodes); +where ``enbNodes`` is a ``NodeContainer`` that contains the two eNodeBs between +which the X2 interface is to be configured. If the container has more than two +eNodeBs, the function will create an X2 interface between every pair of eNodeBs +in the container. -where ``enbNodes`` is a ``NodeContainer`` that contains the two eNBs -between which the X2 interface is to be configured. +Lastly, the target eNodeB must be configured as "open" to X2 HANDOVER REQUEST. +Every eNodeB is open by default, so no extra instruction is needed in most +cases. However, users may set the eNodeB to "closed" by setting the boolean +attribute ``LteEnbRrc::AdmitHandoverRequest`` to `false`. As an example, you can +run the ``lena-x2-handover`` program and setting the attribute in this way:: + + NS_LOG=EpcX2:LteEnbRrc ./waf --run lena-x2-handover --command="%s --ns3::LteEnbRrc::AdmitHandoverRequest=false" + +After the above three requirements are fulfilled, the handover procedure can be +triggered manually or automatically. Each will be presented in the following +subsections. Manual handover trigger *********************** -Handover event can be triggered "manually" within the simulation -program by scheduling an explicit handover event. The ``LteHelper`` -provides a convenient method for the scheduling of a handover -event. As an example, let us assume that ``ueLteDevs``` is a -``NetDeviceContainer`` that contains the UE that is to be handed over, -and that ``enbLteDevs`` is another ``NetDeviceContainer`` that -contains the source and the target eNB. Then, an handover at 0.1s can be +Handover event can be triggered "manually" within the simulation program by +scheduling an explicit handover event. The ``LteHelper`` object provides a +convenient method for the scheduling of a handover event. As an example, let us +assume that ``ueLteDevs`` is a ``NetDeviceContainer`` that contains the UE that +is to be handed over, and that ``enbLteDevs`` is another ``NetDeviceContainer`` +that contains the source and the target eNB. Then, a handover at 0.1s can be scheduled like this:: - lteHelper->HandoverRequest (Seconds (0.100), - ueLteDevs.Get (0), - enbLteDevs.Get (0), - enbLteDevs.Get (1)); + lteHelper->HandoverRequest (Seconds (0.100), + ueLteDevs.Get (0), + enbLteDevs.Get (0), + enbLteDevs.Get (1)); +Note that the UE needs to be already connected to the source eNB, otherwise the +simulation will terminate with an error message. -Note that the UE needs to be already connected to the source eNB, -otherwise the simulation will terminate with an error message. +For an example with full source code, please refer to the ``lena-x2-handover`` +example program. Automatic handover trigger ************************** -Handover procedure can be triggered "automatically" by the serving eNB of -the UE. It is also known as the source eNB in the handover procedure. In -order to control when the handover procedure is initiated, you can configure -the parameters of the handover algorithm in your simulation program -through the ns-3 attributes of the eNB RRC entity:: +Handover procedure can also be triggered "automatically" by the serving eNodeB +of the UE. The logic behind the trigger depends on the handover algorithm +currently active in the eNodeB RRC entity. Users may select and configure the +handover algorithm that will be used in the simulation, which will be explained +shortly in this section. Users may also opt to write their own implementation of +handover algorithm, as described in Section :ref:`sec-handover-algorithm` of the +design documentation. +Selecting a handover algorithm is done via the ``LteHelper`` object and its +``SetHandoverAlgorithmType`` method as shown below:: - Config::SetDefault ("ns3::LteEnbRrc::ServingCellHandoverThreshold", - UintegerValue (30)); + Ptr lteHelper = CreateObject (); + lteHelper->SetHandoverAlgorithmType ("ns3::A2A4RsrqHandoverAlgorithm"); + +The selected handover algorithm may also provide several configurable +attributes, which can be set as follows:: - Config::SetDefault ("ns3::LteEnbRrc::NeighbourCellHandoverOffset", - UintegerValue (1)); + lteHelper->SetHandoverAlgorithmAttribute ("ServingCellThreshold", + UintegerValue (30)); + lteHelper->SetHandoverAlgorithmAttribute ("NeighbourCellOffset", + UintegerValue (1)); +Three options of handover algorithm are included in the LTE module. The *legacy* +handover algorithm (named as ``ns3::A2A4RsrqHandoverAlgorithm``) is the default +option, and the usage has already been shown above. -The UE measurements are used in the automatic handover algorithm. You can -configure the parameters of the UE measurements in your simulation program -through the ns-3 attributes of the eNB RRC entity. You can set the thresholds -of events A2 and A4:: +Another option is the *strongest cell* handover algorithm (named as +``ns3::A3RsrpHandoverAlgorithm``), which can be selected and configured by the +following code:: + lteHelper->SetHandoverAlgorithmType ("ns3::A3RsrpHandoverAlgorithm"); + lteHelper->SetHandoverAlgorithmAttribute ("Hysteresis", + DoubleValue (3.0)); + lteHelper->SetHandoverAlgorithmAttribute ("TimeToTrigger", + TimeValue (MilliSeconds (256))); + +The last option is a special one, called the *no-op* handover algorithm, which +basically disables automatic handover trigger. This is useful for example in +cases where manual handover trigger need an exclusive control of all handover +decision. It does not have any configurable attributes. The usage is as +follows:: - Config::SetDefault ("ns3::LteEnbRrc::EventA2Threshold", - UintegerValue (32)); + lteHelper->SetHandoverAlgorithmType ("ns3::NoOpHandoverAlgorithm"); + +For more information on each handover algorithm's decision policy and their +attributes, please refer to their respective subsections in Section +:ref:`sec-handover-algorithm` of the design documentation. - Config::SetDefault ("ns3::LteEnbRrc::EventA4Threshold", - UintegerValue (2)); +Finally, the ``InstallEnbDevice`` function of ``LteHelper`` will instantiate one +instance of the selected handover algorithm for each eNodeB device. In other +words, make sure to select the right handover algorithm before finalizing it in +the following line of code:: + NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes); -You can find more info about events A2 and A4 in Subsections 5.5.4.3 and 5.5.4.5 -of [TS36331]_. +Example with full source code of using automatic handover trigger can be found +in the ``lena-x2-handover-measures`` example program. Handover traces @@ -1212,76 +1249,73 @@ handover execution phase at both the UE and eNB side. As an example, in your simulation program you can declare the following methods:: - - void - NotifyHandoverStartUe (std::string context, - uint64_t imsi, - uint16_t cellid, - uint16_t rnti, - uint16_t targetCellId) - { - std::cout << 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 << context - << " UE IMSI " << imsi - << ": successful handover to CellId " << cellid - << " with RNTI " << rnti - << std::endl; - } - - void - NotifyHandoverStartEnb (std::string context, + void + NotifyHandoverStartUe (std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti, uint16_t targetCellId) - { - std::cout << context - << " eNB CellId " << cellid - << ": start handover of UE with IMSI " << imsi - << " RNTI " << rnti - << " to CellId " << targetCellId - << std::endl; - } + { + 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 - NotifyHandoverEndOkEnb (std::string context, + void + NotifyHandoverEndOkUe (std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti) - { - std::cout << context - << " eNB CellId " << cellid - << ": completed handover of UE with IMSI " << imsi - << " RNTI " << rnti - << std::endl; - } + { + 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; + } Then, you can hook up these methods to the corresponding trace sources like this:: - 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)); - + 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)); The example program ``src/lte/examples/lena-x2-handover.cc`` illustrates how the all above instructions can be integrated in a @@ -1296,14 +1330,6 @@ NS_LOG=LteEnbRrc:LteUeRrc:EpcX2 ./waf --run lena-x2-handover -Whether a target eNB will accept or not an incoming X2 HANDOVER -REQUEST is controlled by the boolean attribute -``LteEnbRrc::AdmitHandoverRequest`` (default: true). As an example, -you can run the ``lena-x2-handover`` program setting the attribute to -false in this way:: - - NS_LOG=EpcX2:LteEnbRrc ./waf --run lena-x2-handover - --command="%s --ns3::LteEnbRrc::AdmitHandoverRequest=false"