Applicable VersionsNetSim StandardNetSim Pro

The LTE standard supports several parameters to trigger the handover and select the target cells, such as hysteresis margin and Time-to-Trigger (TTT).

When applying Time-to-Trigger, the handover is initiated only if the triggering requirement is fulfilled for a time interval. This parameter can decrease the number of unnecessary handovers and effectively avoid Ping-Pong effects. But it can also delay the handover which then increases the probability of handover failures.


The steps involved in modifying the underlying source codes vary depending on the version of NetSim. Refer to the appropriate section below based on the version of NetSim you are using.


Applicable Releasesv12.2


The following procedure can be followed to involve the Time-to-Trigger parameter in NetSim LTE Simulations:

1. Open NetSim source code in Visual Studio 2019 by going to Open Simulation ->Workspace Options and clicking on the Open Code button.

2. Go to the LTE_NR project through the solution explorer and open the file LTE_NR.h. Add the lines of code highlighted in red as shown below:


#ifndef _NETSIM_LTE_NR_H_

#define _NETSIM_LTE_NR_H_


#include "List.h"


#ifdef  __cplusplus

extern "C" {

#endif

    typedef struct stru_LTE_Handover_Status

        LTE_Handover;

    struct stru_LTE_Handover_Status

    {

        bool status;

        double time;

        NETSIM_ID targetENB;

    };

    LTE_Handover** devices;

    typedef enum enum_LTE_NR_DEVICE_TYPE

    {

        LTENR_DEVICETYPE_UE = 0,

        LTENR_DEVICETYPE_GNB = 1,

        LTENR_DEVICETYPE_ENB = 1,

        LTENR_DEVICETYPE_EPC = 2,

        LTENR_DEVICETYPE_LAST, //Keep me at last

    }LTENR_DEVICETYPE;


 

3. Now open the file LTE_NR.c. Add the lines of code highlighted in red in fn_NetSim_LTE_NR_Init() as shown below:

_declspec(dllexport) int fn_NetSim_LTE_NR_Init()

{

    int i;

    devices = calloc(NETWORK->nDeviceCount + 1, sizeof * devices);

    for (i = 0; i < NETWORK->nDeviceCount + 1; i++)

    {

        devices[i] = (LTE_Handover*)malloc(1 * sizeof(struct stru_LTE_Handover_Status));

        devices[i]->status = false;

        devices[i]->targetENB = 0;

        devices[i]->time = 0.0;

    }

    return fn_NetSim_LTE_NR_Init_F();

}

4. Next open the file LTENR_GNBRRC.h. Add the line of code highlighted in red as shown below:

#ifndef _NETSIM_LTENR_GNBRRC_H_

#define _NETSIM_LTENR_GNBRRC_H_

#include "LTENR_Msg.h"

#include "LTENR_PDCP.h"

#include "LTENR_RLC.h"


#ifdef  __cplusplus

extern "C" {

#endif


    //Default Timer

#define LTENR_MSG_MIB_REGENERATION_TIME        80*MILLISECOND

#define    LTENR_MSG_SIB1_REGENERATION_TIME    160*MILLISECOND

#define LTENR_MSG_UE_MEASUREMENT_REPORT_PERIOD_TIME 120*MILLISECOND

#define HANDOVER_DIFF 3//db

#define TIME_TO_TRIGGER 5000000

    //Default packet size

#define LTENR_MSG_MIB_SIZE                    3    // Bytes


5. Now open the file LTENR_GNBRRC .c. In the function fn_NetSim_LTENR_RRC_UE_MEASUREMENT_RECV() replace the entire function definition with the following since it involves code modifications in multiple places.

void fn_NetSim_LTENR_RRC_UE_MEASUREMENT_RECV(NETSIM_ID gnbID, NETSIM_ID gnbIF, NETSIM_ID ueID, NETSIM_ID ueIF, ptrLTENR_RRC_UE_MEASUREMENT_REPORT report)

{

    //modification start

    int i, count = 0;

    double tempfavourablesnr = 0;

    NETSIM_ID tempfavourabledevice = 0;

    NETSIM_ID enbid;

    NETSIM_ID ueid;

    //modification end

    double serveingSINR = 0;

    double serveringRSRP = 0;

    double serveringRSRQ = 0;

    double targetSINR = INT_MIN;

    NETSIM_ID target = 0;

    ptrLTENR_RRC_UE_MEASUREMENT_REPORT report1 = report;

    while (report1)

    {

        if (report1->cellID == gnbID)

        {

            //modification start

            enbid = report1->cellID;

            ueid = report1->ueID;

            //modification end

            serveingSINR = report1->sinr;

            serveringRSRP = report1->rsrp;

            serveringRSRQ = report1->rsrq;

        }

        if (targetSINR < report1->sinr)

        {

            targetSINR = report1->sinr;

            target = report1->cellID;

            tempfavourabledevice = report1->cellID;

        }

        report1 = LIST_NEXT(report1);

    }

    ptrLTENR_HANDOVER_Hdr msg = calloc(1, sizeof * msg);

    //modification start

    report1 = report;

    while (report1)

    {

        if (report1->cellID != pstruEventDetails->nDeviceId)

        {

            double d = report1->sinr;

            if (d >= serveingSINR + HANDOVER_DIFF)

            {

                if (d > targetSINR)

                {

                    tempfavourabledevice = report->cellID;

                    targetSINR = d;

                }

            }

        }

        report1 = LIST_NEXT(report1);

    }


    if (devices[ueid]->targetENB == 0)

    {

        devices[ueid]->targetENB = enbid;

    }

    if (targetSINR <= serveingSINR + HANDOVER_DIFF)

    {

        devices[ueid]->time = pstruEventDetails->dEventTime;

    }

    else if (targetSINR > serveingSINR)

    {

        if (devices[ueid]->targetENB == tempfavourabledevice)

        {

            if (targetSINR >= serveingSINR + HANDOVER_DIFF && devices[ueid]->time)

            {

                if (pstruEventDetails->dEventTime - devices[ueid]->time >= TIME_TO_TRIGGER)

                {

                    devices[ueid]->status = true;

                    devices[ueid]->time = pstruEventDetails->dEventTime;

                }

            }

        }

        else

        {

            report1 = report;

            while (report1)

            {

                if (report1->cellID == devices[ueid]->targetENB)

                {

                    double d = report1->sinr;

                    if (d >= serveingSINR + HANDOVER_DIFF)

                    {

                        if (pstruEventDetails->dEventTime - devices[ueid]->time >= TIME_TO_TRIGGER && devices[ueid]->time)

                        {

                            devices[ueid]->status = true;

                            devices[ueid]->targetENB = tempfavourabledevice;

                            devices[ueid]->time = pstruEventDetails->dEventTime;

                            break;

                        }

                    }

                    else if (d >= serveingSINR && d < serveingSINR + HANDOVER_DIFF && (pstruEventDetails->nDeviceId, report1->cellID))

                    {

                        devices[ueid]->targetENB = tempfavourabledevice;

                    }

                }

                report1 = LIST_NEXT(report1);

            }

        }


    }


    if (devices[ueid]->status == true && devices[ueid]->targetENB)

    {

        if (serveingSINR + HANDOVER_DIFF < targetSINR && gnbID != devices[ueid]->targetENB) {

            //call nas for handover request

            msg->serveringCellID = gnbID;

            msg->serveringCellIF = gnbIF;

            ptrLTENR_GNBMAC mac = LTENR_GNBMAC_GET(gnbID, gnbIF);

            msg->AMFID = mac->epcId;

            msg->AMFIF = mac->epcIf;

            msg->targetCellID = devices[ueid]->targetENB;

            msg->targetCellIF = fn_NetSim_Get_LTENR_INTERFACE_ID_FROM_DEVICE_ID(devices[ueid]->targetENB, LTENR_DEVICETYPE_GNB);

            msg->UEID = ueID;

            msg->UEIF = ueIF;

            fn_NetSim_LTENR_NAS_HANDOVER_REQUEST(msg);

        }

    }

}


6. The new constant TIME_TO_TRIGGER that we have added to the code can be customized as per the requirement and is currently set to 5 Seconds. Based on the value set, Handover will happen if the difference in signal strength between the target and serving cell is greater than the Handover Margin(HANDOVER_DIFF) for a time period greater than TIME_TO_TRIGGER.

7. After setting HANDOVER_DIFF and TIME_TO_TRIGGER parameters as per the requirement, right-click on the LTE module in the solution explorer and select rebuild.

10. Now upon running LTE simulations involving UE handovers, handover will be initiated only if the difference in signal strength is more than the HANDOVER_DIFF for a time period greater than TIME_TO_TRIGGER  specified by you.

11. You can then run multiple simulations of the same network scenario varying certain parameters such as seed values, the velocity of devices, etc and take the average Number of Handovers and Throughput. 

12. Record the results of every test case in an excel file and once all the test cases are complete plot graphs of Number of Handovers versus Speed and Throughput versus speed.


Applicable Releasesv10v11.1v12.0
v12.1

The following procedure can be followed to involve Time-to-Trigger parameter in NetSim LTE Simulations:

1. Open NetSim source code in Visual Studio 2015/2017/2019 by double-clicking on the NetSim.sln file present in “<NetSim_Install_Directory>/src/Simulation” folder. (from NetSim v11.1 or higher versions, source codes should be opened using Open Code option only)

2. Go to the LTE project through the solution explorer and open the file LTE.h. Add the lines of code highlighted in red as shown below:


#define MAX_HARQ_PROCESS 8
#define TARGET_BER 1.0e-5

/**** Structure typedefs *****/
typedef struct stru_LTE_ENB_Phy LTE_ENB_PHY;
typedef struct stru_LTE_UE_Phy LTE_UE_PHY;
typedef struct stru_LTE_ENB_MAC LTE_ENB_MAC;
typedef struct stru_LTE_UE_MACLTE_UE_MAC;
typedef struct stru_LTE_AssociateUEInfoLTE_ASSOCIATEUE_INFO;
typedef struct stru_LTE_QueueLTE_QUEUE;
typedef struct stru_LTE_Mac_PacketLTE_MAC_PACKET;
typedef struct stru_LTE_Phy_PacketLTE_PHY_PACKET;
typedef struct stru_LTE_RRC_Connection_RequestRRC_CONNECTION_REQUEST;
typedef struct stru_LTE_RRC_Connection_SetupRRC_CONNECTION_SETUP;
typedef struct stru_LTE_RRC_Connection_Setup_CompleteRRC_CONNECTION_SETUP_COMPLETE;
typedef struct stru_LTE_PDCP_HeaderLTE_PDCP_HEADER;
typedef struct stru_LTE_MME_HLRLTE_HLR;
typedef struct stru_LTE_MMELTE_MME;
typedef struct stru_LTE_MeasurementReportLTE_MEASUREMENT_REPORT;
typedef struct stru_LTE_HOInfoLTE_HO_INFO;
typedef struct stru_LTE_MetricsLTE_METRICS;
typedef struct stru_LTE_ACKLTE_ACK;

typedef struct stru_LTE_Handover_Status
LTE_Handover;
struct stru_LTE_Handover_Status
{
bool status;
double time;
NETSIM_ID targetENB;
};
LTE_Handover ** devices;


/* 3GPP TS 36.213
*7.1.7.2.1 Transport blocks not mapped to two or more layer spatial multiplexing
*For 110 1≤ NPRB ≤ , the TBS is given by the ( TBS I ,NPRB ) entry of Table 7.1.7.2.1-1.
*
*Table 7.1.7.2.1-1: Transport block size table (dimension 27×110)
*/
#define LTE_TBS_INDEX_MAX27


 

3. Go to LTE project through the solution explorer and open the file LTE.c. Add the lines of code highlighted in red in fn_NetSim_LTE_Init() as shown below:

_declspec(dllexport) int fn_NetSim_LTE_Init()
{
int i;
devices = calloc(NETWORK->nDeviceCount + 1, sizeof * devices);
for (i = 0; i < NETWORK->nDeviceCount + 1; i++)
{
devices[i] = (LTE_Handover*)malloc(1 * sizeof(struct stru_LTE_Handover_Status));
devices[i]->status = false;
devices[i]->targetENB = 0;
devices[i]->time = 0.0;
}

return fn_NetSim_LTE_Init_F();
}

4. Go to LTE project through the solution explorer and open the file NAS.c. Add the line of code highlighted in red as shown below:

#include "main.h"
#include "LTE.h"
#define MEASUREMENT_REPORT_SIZE 184/8.0
#define HO_REQUEST_SIZE 288/8.0
#define HO_CONFIRM_SIZE 112/8.0
#define HANDOVER_DIFF3 //db
#define TIME_TO_TRIGGER 5000000.0
int fn_NetSim_LTE_InitHandover(NETSIM_ID ueId, NETSIM_ID nENBId)

5. Go to LTE project through the solution explorer and open the file NAS.c. In the function fn_NetSim_LTE_DecideHandover() replace the entire function defention with the following since it involves code modifications in multiple places.

int fn_NetSim_LTE_DecideHandover()
{
//code modification
int i, count = 0;
double tempfavourablesnr = 0;
NETSIM_ID tempfavourabledevice;
NETSIM_ID enbid;
NETSIM_ID ueid;
//code modification
double dSNR = 0;
double dTargetSNR = 0;
NETSIM_ID target = 0;
NETSIM_ID ueId = 0;
LTE_MEASUREMENT_REPORT* report = (LTE_MEASUREMENT_REPORT*)((LTE_MAC_PACKET*)pstruEventDetails->pPacket->pstruMacData->Packet_MACProtocol)->MessageVar;
while (report)
{
if (report->nENBId == pstruEventDetails->nDeviceId)
{
//code modification
enbid = report->nENBId;
ueid = report->nUEId;
//code modification
dSNR = min_elementd(report->dSNR_DL, report->carrier_count);
ueId = report->nUEId;
break;
}
report = LIST_NEXT(report);
}

report = (LTE_MEASUREMENT_REPORT*)((LTE_MAC_PACKET*)pstruEventDetails->pPacket->pstruMacData->Packet_MACProtocol)->MessageVar;
while (report)
{
if (report->nENBId != pstruEventDetails->nDeviceId)
{
double d = min_elementd(report->dSNR_DL, report->carrier_count);
if (d >= dSNR + HANDOVER_DIFF)
{
if (d > dTargetSNR && isPartofSameMME(pstruEventDetails->nDeviceId, report->nENBId))
{
tempfavourabledevice = report->nENBId;
dTargetSNR = d;
}
}
}
report = LIST_NEXT(report);
}
if (devices[ueid]->targetENB == 0)
{
devices[ueid]->targetENB = enbid;
}
if (dTargetSNR <= dSNR)
{
devices[ueid]->time = pstruEventDetails->dEventTime;
}
else if (dTargetSNR > dSNR)
{
if (devices[ueid]->targetENB == tempfavourabledevice)
{
if (dTargetSNR >= dSNR + HANDOVER_DIFF&&isPartofSameMME(pstruEventDetails->nDeviceId, tempfavourabledevice))
{
if (pstruEventDetails->dEventTime - devices[ueid]->time >= TIME_TO_TRIGGER)
{
devices[ueid]->status = true;
devices[ueid]->time = pstruEventDetails->dEventTime;
}
}
}
else
{
report = (LTE_MEASUREMENT_REPORT*)((LTE_MAC_PACKET*)pstruEventDetails->pPacket->pstruMacData->Packet_MACProtocol)->MessageVar;

while (report)
{
if (report->nENBId == devices[ueid]->targetENB)
{
double d = min_elementd(report->dSNR_DL, report->carrier_count);
if (d >= dSNR + HANDOVER_DIFF &&
isPartofSameMME(pstruEventDetails->nDeviceId,
report->nENBId))
{
if (pstruEventDetails->dEventTime - devices[ueid]->time >= TIME_TO_TRIGGER)
{
devices[ueid]->status = true;
devices[ueid]->targetENB = tempfavourabledevice;
devices[ueid]->time = pstruEventDetails->dEventTime;
break;
}
}
else if (d >= dSNR && d < dSNR + HANDOVER_DIFF && isPartofSameMME(pstruEventDetails->nDeviceId, report->nENBId))
{
devices[ueid]->targetENB = tempfavourabledevice;
}
}
report = LIST_NEXT(report);
}
}

}
//Free measurement report packet
fn_NetSim_Packet_FreePacket(pstruEventDetails->pPacket);
if (devices[ueid]->status == true && devices[ueid]->targetENB && pstruEventDetails->nDeviceType != RELAY)
{
NetSim_BUFFER* buffer;
NetSim_PACKET* packet;
LTE_MAC_PACKET* macPacket = (LTE_MAC_PACKET*)calloc(1, sizeof* macPacket);
LTE_HO_INFO* request = (LTE_HO_INFO*)calloc(1, sizeof* request);
packet = fn_NetSim_LTE_CreateCtrlPacket(pstruEventDetails->dEventTime,
LTEPacket_HandoverRequest,
devices[ueid]->targetENB,
pstruEventDetails->nDeviceId,
devices[ueid]->targetENB,
HO_REQUEST_SIZE);
macPacket->logicalChannel = LogicalChannel_CCCH;
macPacket->MessageType = LTEPacket_HandoverRequest;
packet->pstruMacData->Packet_MACProtocol = macPacket;
packet->pstruMacData->dontFree = true;
macPacket->MessageVar = request;
request->nSourceENB = pstruEventDetails->nDeviceId;
request->nTargetENB = devices[ueid]->targetENB;
request->nUEId = ueId;
request->info = fn_NetSim_LTE_FindInfo(DEVICE_MACVAR(pstruEventDetails->nDeviceId, 1), ueId);
((LTE_HO_INFO*)macPacket->MessageVar)->sourceMac = DEVICE_MACVAR(pstruEventDetails->nDeviceId, 1);

//Add macout event
buffer = NETWORK->ppstruDeviceList[pstruEventDetails->nDeviceId - 1]->ppstruInterfaceList[1]->pstruAccessInterface->pstruAccessBuffer;


if (!fn_NetSim_GetBufferStatus(buffer))
{
//Add the MAC out event
pstruEventDetails->dPacketSize = HO_REQUEST_SIZE;
pstruEventDetails->nEventType = MAC_OUT_EVENT;
pstruEventDetails->nPacketId = packet->nPacketId;
pstruEventDetails->nProtocolId = fn_NetSim_Stack_GetMacProtocol(pstruEventDetails->nDeviceId, 2);
pstruEventDetails->nSubEventType = 0;
pstruEventDetails->pPacket = NULL;
pstruEventDetails->szOtherDetails = NULL;
pstruEventDetails->nApplicationId = 0;
pstruEventDetails->nInterfaceId = 2;
pstruEventDetails->nSegmentId = 0;
fnpAddEvent(pstruEventDetails);
}
fn_NetSim_Packet_AddPacketToList(buffer, packet, 0);
devices[ueid]->status = false;
}
return 1;

}


6. The new constant TIME_TO_TRIGGER that we have added to the code can be customized as per the requirement and is currently set to 5 Seconds. Based on the value set, Handover will happen if the difference in signal strength between the target and serving cell is greater than the Handover Margin(HANDOVER_DIFF) for a time period greater than TIME_TO_TRIGGER.

7. After setting HANDOVER_DIFF and TIME_TO_TRIGGER parameters as per the requirement, right-click on the LTE module in the solution explorer and select rebuild.

8. Upon a successful build, you will get a new libLTE.dll file in the “<NetSim_Install_Directory>/src/Simulation/DLL” folder. (this step can be ignored in case of NetSim v11.1 or higher versions)

9. Copy this newly-built DLL file and replace it in the bin folder of NetSim after you rename the original libLTE.dll file which is already existing there(as a backup). (this step can be ignored in case of NetSim v11.1 or higher versions)

10. Now upon running LTE simulations involving UE handovers, handover will be initiated only if the difference in signal strength is more than the HANDOVER_DIFF for a time period greater than TIME_TO_TRIGGER  specified by you.

11. You can then run multiple simulations of the same network scenario varying certain parameters such as seed values, the velocity of devices, etc and take the average Number of Handovers and Throughput. 

12. Record the results of every test case in an excel file and once all the test cases are complete plot graphs of Number of Handovers versus Speed and Throughput versus speed.


Sample results:


A sample graph that was obtained upon running several simulations with the above code modifications is shown below: