Updated user documentation of handover
authorBudiarto Herman <budiarto.herman@magister.fi>
Sun, 25 Aug 2013 15:27:45 +0300
changeset 10334 e6f604c8cb6c
parent 10333 0083a28333f2
child 10335 bfbde955fd57
Updated user documentation of handover
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<uint8_t> 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<uint8_t> measIdList;
 
-  NetDeviceContainer::Iterator it;
-  for (it = devs.Begin (); it != devs.End (); it++)
-  {
-    Ptr<NetDevice> dev = *it;
-    Ptr<LteEnbNetDevice> enbDev = dev->GetObject<LteEnbNetDevice> ();
-    Ptr<LteEnbRrc> enbRrc = enbDev->GetRrc ();
+   NetDeviceContainer::Iterator it;
+   for (it = devs.Begin (); it != devs.End (); it++)
+   {
+     Ptr<NetDevice> dev = *it;
+     Ptr<LteEnbNetDevice> enbDev = dev->GetObject<LteEnbNetDevice> ();
+     Ptr<LteEnbRrc> 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> lteHelper = CreateObject<LteHelper> ();
+   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"