Applicable VersionsNetSim Standard NetSim Pro


Applicable Releases
v14.4


When developing and integrating custom protocols in NetSim, there may be scenarios where two independent modules (for example, OLSR at the network layer and DTDMA at the MAC layer) need to exchange information dynamically.
For instance, OLSR might need to instantly inform DTDMA when a TC (Topology Control) message is transmitted or received, or when a link is lost.

NetSim supports multiple ways to achieve this inter-protocol data exchange. This article discusses two recommended methods:


Method 1: Using Internal Events (INTERNAL_NETSIM_EVENT)


This method is ideal when you want to trigger an event in another protocol instantly during simulation runtime, such as notifying the MAC layer when a routing event occurs at the network layer.


How It Works


An internal event is generated by creating a temporary NetSim_EVENTDETAILS structure, setting the event type to INTERNAL_NETSIM_EVENT, and specifying the target protocol ID.


Example implementation in OLSR source code:


 image.png


NetSim_EVENTDETAILS pevent;
memcpy(&pevent, pstruEventDetails, sizeof pevent);
pstruEventDetails->nEventType = INTERNAL_NETSIM_EVENT;
pstruEventDetails->nProtocolId = MAC_PROTOCOL_DTDMA;
pstruEventDetails->nSubEventType = 0;
pstruEventDetails->szOtherDetails = NULL;
//Call the local network protocol
fnCallProtocol(MAC_PROTOCOL_DTDMA);
memcpy(pstruEventDetails, &pevent, sizeof * pstruEventDetails);
If you need to share additional data with DTDMA (for example, neighbor metrics or link status), you can attach it via:
pstruEventDetails->szOtherDetails = <pointer_to_data>;

Handling the Event in DTDMA:

In DTDMA source code project, we add the event type INTERNAL_NETSIM_EVENT to the switch case in the run() function and access the data added to the pstruEventDetails->szOtherDetails, if any or execute a function or code to handle this event trigger.

In the DTDMA source code, handle this event type inside the fn_NetSim_DTDMA_Run() function:

image.png
_declspec (dllexport) int fn_NetSim_DTDMA_Run()
{
  NETSIM_ID d = pstruEventDetails->nDeviceId;
  NETSIM_ID in = pstruEventDetails->nInterfaceId;

  switch(pstruEventDetails->nEventType)
  {
.
case INTERNAL_NETSIM_EVENT:
{
  switch(pstruEventDetails->nSubEventType)
  {
  case 0:
    fprintf(stderr, "\nInternal event in DTDMA protocol triggered\n");
    _getch();
    break;

  default:
    fnNetSimError("Unknown subevent %d for Internal event in DTDMA protocol\n",pstruEventDetails->nSubEventType);
    break;
  }
}
break;
default:


You can define multiple sub-event types (e.g., LINK_LOSS_EVENT, TC_MESSAGE_EVENT) by assigning different values to nSubEventType, allowing for differentiated responses to various triggers.


Method 2: Using Function/Variable Export and Import Across Modules


This method is suitable when two protocols need shared access to functions, APIs, or variables, rather than one-time events.


In this case, one project (e.g., OLSR) exports the necessary functions or data, while the other project (e.g., DTDMA) imports and uses them.


Exporting from the Source Module


To export functions or variables from the OLSR project, mark them using the __declspec(dllexport) keyword:

_declspec(dllexport) int get_olsr_neighbor_count(NETSIM_ID nodeId);
_declspec(dllexport) NEIGHBOR_INFO* get_olsr_neighbors(NETSIM_ID nodeId);

The corresponding header file should include the same declaration.


When you build OLSR, both a .dll and a .lib file are generated.

These files are used by other protocols to link against OLSR’s exported symbols.


Importing into Another Project


In the importing module (e.g., DTDMA)


1. Link against the OLSR library:

#pragma comment(lib, "OLSR.lib")

2. Include the OLSR header file containing the exported declarations:

#include "OLSR.h"

3. Directly call the exported functions:

int neighborCount = get_olsr_neighbor_count(nodeId);

Example: Existing Imports in DTDMA


If you inspect DTDMA.h, you’ll notice similar import statements for other NetSim modules:

#pragma comment(lib,"Metrics.lib")
#pragma comment(lib,"NetworkStack.lib")
#pragma comment(lib,"Mobility.lib")
#pragma comment(lib,"PropagationModel.lib")

#include "List.h"
#include "ErrorModel.h"
#include "PropagationModel.h"

The PropagationModel module exports functions such as:

_declspec(dllexport) double propagation_get_Pathloss(PPROPAGATION_INFO info, double time);
_declspec(dllexport) double propagation_get_Shadowloss(PPROPAGATION_INFO info, double time);
_declspec(dllexport) double propagation_get_Fadingloss(PPROPAGATION_INFO info, double time);
_declspec(dllexport) double propagation_get_Totalloss(PPROPAGATION_INFO info, double time);

These functions are called in DTDMAPhy.c for link calculations:

sprintf(dtdma_measurement, "%lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %e",
    TxFrequency,
    MW_TO_DBM(phy->dTXPower),
    propagation_get_Pathloss(txinfo, pstruEventDetails->dEventTime),
    propagation_get_Shadowloss(txinfo, pstruEventDetails->dEventTime),
    fadingloss,
    propagation_get_Totalloss(txinfo, pstruEventDetails->dEventTime),
    txinfo->txInfo.dTxGain,
    txinfo->txInfo.dRxGain,
    receivedpower,
    interferencePower_dBm,
    sinr,
    pb);

By following this same mechanism, you can export and share functions or variables from OLSR to DTDMA (e.g., neighbor table, route table, link metrics, etc.).