Development

RNS module was developed in a manner that would allow it to be usable with any routing protocol or application. Templates allow independence from the identification type used by the protocol.

New template arguments

In every network there must be a way of uniquely identifying every node. Some examples of such identification tags could be: Ipv4 or Ipv6 address, MAC address or just unique integer number. Implementing RNS to be used with just one type of identification would limit its usability and therefore it is represented by a template argument in almost all of the RNS code. It’s up to the user to define what kind of identification their network is using.

So far only two IdTypes (not to be mixed with TypeId‘s) have been implemented: Ipv4Address and uint32_t. Most features of RNS implementation are not IdType-dependent, but there are some parts that require explicit definition, usually due to simulator’s requirements.

GetTypeId function

Every class in ns-3 that derives from class ns3::Object is assigned a unique TypeId metadata class, to allow usage of aggregation. Every instantation of a template class is treated as a separate object type. For this reason a separate GetTypeId function has to be written for every possible template argument. They are placed in rns-specialization.cc file. Their declarations need to be put in rns.h file, along with a type definition of each instantation. For example::

template <> TypeId Rns<Ipv4Address>::GetTypeId(void);
typedef class Rns<Ipv4Address> RnsIpv4AddressImpl;

Start function

Identification types are inevitably correlated with routing protocols. Therefore the Start function (see User Documentation) expects to find different aggregated objects, depending on the IdType. For example, there’s no point to look for Ipv4 object if the IdType is Ipv6Address. Start function needs to be specialized for each template argument.

Sending function

There are generic functions for sending and receiving data using the underlying protocol. However they have to refer, at some point, to functions specific for the recognized protocol.

For this reason there must be a specific sending function added for each IdType (such as Ipv4Send) and it must be called in the RnsSendMessage function.

The sending function should receive a prepared RnsHeader object and pass pass it to the proper lower layer.

Receiving function

Furthermore, a receiving function also has to be implemented specifically. An example would be the Ipv4Receive function. In case of Ipv4 protocols this receiving function has to be registered as a callback function when obtaining a socket for communication.

Receiving function has to accept an incoming message, extract and return the RNS header.

Header specialization

Header specialization is more complicated. The size of each template parameter might differ and they do need to be attached to the header, as they are forwarded to all two hops neighbors. The soultion is to specialize Serialize and Deserialize functions as well as GetSerializedSize. The specializations should be put in rns-specialization.cc.

Helper specialization

Only a constructor has to be specified for every new template argument in file rns-specialization.cc. The reason is that a helper’s constructor set the TypeId of the produced objects. In case of RNS the objects are instantations of template class and each of them has a unique TypeId.

Neighbor and NeighborsTable classes

Niether Neighbor nor NeighborsTable classes are aggregated so no additional steps need to be taken when a new template argument is used.

Routing Protocol’s Support for RNS

There are five steps that need to be taken to enable RNS usage with a new protocol.

1. Protocol’s attribute

RNS is just an optional enhancement to any routing protocol and is not required for its correct performance. The suggested way to add RNS functionality as an option to the protocol is to add an attribute EnableRns that would set a boolean type parameter. It is best to set the default value to false, so users had to explicitly request that RNS module is taken into consideration.

2. Access to the RNS module

The module that uses RNS needs to be able to access it and the most convenient way is to allow this is to create a Pointer to an RNS module, e.g.::

Ptr<Rns<Ipv4Address> > m_rns

3. Setting the RNS module pointer

To set the abovementioned pointer to the right object a SetRns function is required. It should take the pointer as a call argument and assign it to the m_rns pointer.

If it is possible, the best place to call SetRns function is within the Start function, after a correct user’s module is detected.

4. Create UpdateRns() function

RNS module could work without any help from the user, but in many cases it would unneccessarily increase the network’s traffic. It is suggested that UpdateRns function is used to update RNS module’s neighbors table with any information obtained in normal communication. This allows:

  • fewer RNS headers broadcasts,
  • more accurate and less frequent calculations of the algorithm
  • in some cases, if the protocol provides location information, shorter RNS header

UpdateRns function should create a neighbor object, even if it would only contain neighbor’s Id and pass it to RNS using UpdateNeighbor function.

5. Place UpdateRns calls appropiately

The UpdateRns function should be called whenever a new node is added to the routing table or when any information confirming node’s position, range, neighborhood or at least existance is obtained. How and when this is done is specific for each protocol.

Using RNS

After the protocol is able to cooperate with RNS all it has to do is use the additional knowledge it provides. A good idea is to periodically check if the node is redundant using m_rns->IsRedundant function and take appropriate steps to decrease this nodes part in network’s communication or measurements. Another possibility is to check redundancy only in some specific occassions, such as sending large measurement data or electing a cluster head (then being redundant can be an advantage).

How RNS is used is highly specific to the protocol. Some examples could involve dropping some packets that should be forwarded, switching to listening mode, turning off communication or measurement peripherals peventing periodic updates or completely turning of for a period of time.

RNS protocol-dependent parameters

There are some RNS parameters tha depend on the protocol’s operation. It is highly recommended to rely on the protocol to maximum possible extent.

First of all, the so called geographical routing protocols (like GAF or MECN) can share the information on node’s position with RNS. This allows RNS to send shorter headers as the position information does not need to be included. To use this fact for node’s benefit the PositionInHeader parameter should be set to false.

RNS will also be able to save some energy if it can be sure that the underlying protocol will periodically send some kind of update messages and refresh the age of RNS neighbors entries. In case the postion of the node is not changing and RNS is sure other nodes are alive and working because the protocol refreshes their metrics, a very long time can flow before any RNS header will be sent due to position, range or status change.

It is also possible to leave sending RNS broadcasts to the routing protocol. Such situation might take place when the protocol has some refined synchronisation method and knows the exact period when collision is least probable. Then time-insensitive data, such as RNS Header, can be send in those time windows instead of being sent periodically. This feature is controlled by EventTrigerredBroadcast parameter.

Phy Support for RNS

Most existing ns-3 network routing protocols do not provide directly any information on the node’s range. Additionally, the range does not necessarily have to be fixed. Unfortunately this information is essential for RNS proper operation.

The only way to obtain the necessary information is to access the Phy aggregated to the NetDevice. All Phy objects in ns-3 need to use some sort of PropagationLossModel. Such objects define a public CalcRx function which calculates the received power based on the distance and transmit power of a node. Some phy’s also provide a function that returns the minimum power necessary for correct message reception (such as GetEdThreshold in YansWifiPhy) and the current transmission power level (for example GetTxPowerStart in YansWifiPhy). This data is sufficient to estimate the range of the node by solving an equation:

CalcRxPower(txPowerDbm, distance) = minimumPowerDbm

for distance. In other words: it is possible to estimate at what distance the communication will no longer be possible. In RNS this is done in EstimateRange function using Newton’s method and it requires access to a Phy which provides necessary information as well as to PropagationLossModel used by the channel.

Currently all existing PropagationLossModels can be supported as they all provide the CalcRx function.

Only YansWifiPhy has been found to allow public access to both its received power treshold and current transmission level.