Adding a New Protocol IN NS2 (NETWORK SIMULATOR)

My Advice to implement new protocol in ns2 is

          1)Study the implementation of protocols in ns2
                 Eg: If u wanna implement new MAC protocol in the ns2 study the 802.11 MAC implementation in   ns2.
          2) Take a Clone of the source protocol(the older one)  
          3)Modify the clone according to your needs
We are taking 802.11 MAC as an example

Step 1: Study the implementation of protocols in ns2

                                        MAC in ns-2




1. The general structure of MAC

related sourcecode:  mac.cc,  mac.h

MAC class is derived from Bi-Connector class.

Local Variables:
  • pktTx_ 
  • pktRx_
  • Macstate_ :
  • index_  : mac address

Basic functions of General MAC class.
  • recv (packet, handler)
    • This is the entry from upper target (a callback handler is given as a parameter) to send a packet to MAC. After the MAC transmit this packet successfully, it will use this callback handler to inform the upper target that MAC is idle and  give another packet if there are packets buffered.
  • SendUp
    • entry for receiving a packet. Sendup is function is directly called by the lower target of MAC, might be "netif" or "phy". And this function directly calls the upper_target. Because the uplink  to upper_target does not involve any phsical transmission delay, it does not need any timer and state change here. The question is that when the MAC is in MAC_RECV state? The answer is: The MAC here is supposed to be full-duplex and receive can be happened simultaneously. it does not care about collisions etc. This is a general MAC class
  • SendDown
    • used to sending packet down. Called by recv().init a timer for tx, and the timer handler is defined to call resume().
  • Handler* callback_;
    • when MAC is idle, the upper target has to be callback.
  • Resume()
    • When tx timer out, reset MAC as idle state and callback.
  • Discard
    • When a packet has to be drop, the drop_ (NsObject*) of bi-connector class has to be called to handle this, usually drop (p, why) is used. Why is a string of drop reason, in cmu-trace.h. three-character string is defined to describe those reasons in the trace file, such as "BSY", "CBK"....
mac_state

2. The 802.11 MAC

it is implemented by CMU. It is a subclass of MAC.

related sourcecode : mac-802_11.cc, mac-802_11.h, mac-timer.cc, mac-timer.h

State Machine: 


The tx_state and rx_state are two member variables. Although, actually mac cannot transmit and receive at the same time. we still hold two variables for them. The possible state is MAC_SEND, MAC_IDLE, MAC_RECV, MAC_COLL, MAC_RTS, MAC_CTS, MAC_ACK.

Local Variables:
  • pktTx_ (inherited from Mac class): 
  • pktRx_(inherited from Mac class):
  • pktCtrl_
  • pktRTS_

Basic functions:

  • recv(): the recv() function of MAC class has been overridden. Here, recv() means an incoming packet from both physical layer and upper layer.
  • send(): this function is called by recv() when it get a packet supposed to sending down.  Similarly, a callback handler is given as a parameter. Immediately, the sendDATA(p) function is called to generate an appropriate mac_header for this packet, and set this to pktTx_. Then,  follew the CSMA/CA procedures to get this packet sent.
  • sendDATA(). to compose a DATA MAC frame and set it as pktTx_
  • recvDATA(). When heard a DATA MAC frame, hand it to upper layer.

Callback to IFQ in MAC 802.11

The callback is set when a packet comes from upper layer and be handled by send(p,h). The callback is used and reset to zero in tx_resume() function of mac-802_11.cc:

void
Mac802_11::tx_resume()
{
 .....
else if(callback_) {
        Handler *h = callback_;
        callback_ = 0;
        h->handle((Event*) 0);
    }
    // change wrt Mike's code
    //SET_TX_STATE(MAC_IDLE);
   setTxState(MAC_IDLE);
}
The callback will reactivate the interface queue between mac_ and ll_ objects, see queue/queue.cc
void QueueHandler::handle(Event*)
{
        queue_.resume();
}

void Queue::resume()
{
        Packet* p = deque();
        if (p != 0) {
                target_->recv(p, &qh_);
        } else {
                if (unblock_on_resume_)
                        blocked_ = 0;
                else
                        blocked_ = 1;
        }
}
See that the queue is blocked if not "callback", thus, callback is essential to make queue work properly.Backoff
The backoff implementation in mac-802_11.cc does not comply with the standard. Basically, this is due to the introduction of a defer timer. The defertimer is set in send() and after a packet transmission finishes. The deferred time value is usually (DIFS+rTime) where rTime is as same as the selection of backoff timeslots from CW (Contention Window). However, the defertimer is never paused or resumed.
So, after a packet transmission, according to the IEEE 802.11 standard, the node should do backoff immediately. here in ns-code, the defertime is first set. And after timer out, in check_pktTx() function. if the channel is not idle, a backoff timer is set. Therefore, here exists a double backoff problem. Also, according to IEEE 802.11 standard, a node should access channel directly if it sense the channel idle and still idle after at least DIFS time. Here, ns-code also deviates from the standard and add an additional rTime before sending DATA or RTS.
 
Determine the transmission time 


txtime is calculated from the "size" variable in common header. Because all headers are present in the packet no matter what layer it is. Thus, the only way to know the packet size is to add or subtract some bytes in hdr_cmn->size(); In 802.11 MAC code, in recvDATA(), the 802.11 header size will be subtracted. And in SendDATA(), a 80211_hdr_length will be added.

Transmission Failure:
In both RetransmitRTS and RetransmitDATA functions, it is necessary to deal a packet drop :
if(ssrc_ >= macmib_.getShortRetryLimit()) {
  discard(pktRTS_, DROP_MAC_RETRY_COUNT_EXCEEDED); pktRTS_ = 0;
  /* tell the callback the send operation failed 
     before discarding the packet */
  hdr_cmn *ch = HDR_CMN(pktTx_);
  if (ch->xmit_failure_) {
                        /*
                         *  Need to remove the MAC header so that 
                         *  re-cycled packets don't keep getting
                         *  bigger.
                         */
   // change wrt Mike's code
                        //ch->size() -= ETHER_HDR_LEN11;
   ch->size() -= phymib_.getHdrLen11();
                        ch->xmit_reason_ = XMIT_REASON_RTS;
                        ch->xmit_failure_(pktTx_->copy(),
                                          ch->xmit_failure_data_);  //callback by upperlayer
                }
  //printf("(%d)....discarding RTS:%x\n",index_,pktRTS_);
  discard(pktTx_, DROP_MAC_RETRY_COUNT_EXCEEDED); pktTx_ = 0;
  ssrc_ = 0;
  rst_cw();
 } 
So, it is a way to let upper layer , such as DSR routing to know there is a route-error and need to send a route-error message.

Frame Formats in ns-2

The 802.11 header in ns-2 is not conform to the 802.11 standard. It is a different one. Thus, this overhead cannot be regarded as authentic as that of
the experiment. And the throughput measurements also seems different.

Other IEEE 802.11 features

1. Carrier Sense

This is normally done by the physical layer source code. The state of 802.11 MAC is  controlled by  some timers. Such as the  Backoff_timer. By checking if those timers are still busy, the MAC will arrange its operations correspondingly.

2. Virtual Carrier SenseRTS/CTS is an important part of code. There are functions like sendRTS ( is to form a RTS ctrl packrt) , retransmitRTS...... Basically it has to compare with RTSThreshold first, if the size is small than the threshold, there is no" virtual carrier sense" scheme used.



Take a Clone of the source protocol(the older one)


II. STEPS
1) Check source code to be modified or added, maybe a backup is necessary for future diff.
Action->File to be modified
Modify-> ns-allinone-2.33\Makefile
Modify ->ns-allinone-2.33\dei80211mr-1.1.4\src\InitTCL.cc
Modify ->ns-allinone-2.33\ns-2.33\indep-utils\webtrace-conv\dec\my-endian.h
Modify ->ns-allinone-2.33\ns-2.33\tcl\lib\ns-mobilenode.tcl
Modify ->ns-allinone-2.33\ns-2.33\tcl\lib\ns-default.tcl
Modify ->ns-allinone-2.33\ns-2.33\tcl\lan\ns-mac-802 11.tcl
Modify ->ns-allinone-2.33\ns-2.33\tcl\lan\ns-mac.tcl
Add ->ns-allinone-2.33\ns-2.33\mac\mac-802 11new.cc
Add ->ns-allinone-2.33\ns-2.33\mac\mac-802 11new.h
Add ->ns-allinone-2.33\ns-2.33\mac\mac-timersnew.cc
Add ->ns-allinone-2.33\ns-2.33\mac\mac-timersnew.h
2) Modify Makefile by
a) adding ”mac-802 11new.o” next to existing ”mac-802 11.o” in OBJ CC section.
b) adding ”mac-timersnew.o” next to existing ”mac-timers.o” in OBJ CC section.
3) Modify InitTCL.c by adding following portion next to existing codes, from about line 70.
---BEGIN---
Mac/802_11new/Multirate set useShortPreamble_ false
Mac/802_11new/Multirate set gSyncInterval_ 0
Mac/802_11new/Multirate set bSyncInterval_ 0
Mac/802_11new/Multirate set CWMin_ 32
Mac/802_11new/Multirate set CWMax_ 1024
Mac/802_11new/Multirate set VerboseCounters_ 0
---END---
4) Modify my-endian.h by marking off first line and last line, this is to fix the compile error.
5) Modify ns-mobilenode.tcl by adding following 2 portions next to existing codes, from about line 500 and 700.
---BEGIN---
set god_ [God instance]
if {$mactype == "Mac/802_11new"} {
$mac nodes [$god_ num_nodes]
}
---END---
---BEGIN---
if {$mactype == "Mac/802_11new"} {
$self instvar mac_
set ns_ [Simulator instance]
set beacon_period [$ns_ delay_parse $beacon_period]
set cfp_duration [$ns_ delay_parse $cfp_duration]
$mac_(0) cfp $beacon_period $cfp_duration
}
---END---
6) Modify ns-default.tcl by adding following portion next to existing codes, from about line 700.
---BEGIN---
# Mac/802_11new
Mac/802_11new set CWMin_ 312
Mac/802_11new set CWMax_ 1023
Mac/802_11new set SlotTime_ 0.000020
Mac/802_11new set SIFS_ 0.000010
Mac/802_11new set PreambleLength_ 144
Mac/802_11new set PLCPHeaderLength_ 48
Mac/802_11new set PLCPDataRate_ 1.0e6
Mac/802_11new set RTSThreshold_ 0
Mac/802_11new set ShortRetryLimit_ 7
Mac/802_11new set LongRetryLimit_ 4
Mac/802_11new set bugFix_timer_ true
Mac/802_11new set BeaconInterval_ 0.1
Mac/802_11new set ScanType_ PASSIVE
Mac/802_11new set ProbeDelay_ 0.0001
Mac/802_11new set MaxChannelTime_ 0.011
Mac/802_11new set MinChannelTime_ 0.005
Mac/802_11new set ChannelTime_ 0.12
---END---
7) Modify ns-mac-802 11.tcl by adding following portion next to existing codes, from about line 50.
---BEGIN---
Mac/802_11new set debug_ false Mac/802_11new instproc init {} {
eval $self next
set ns [Simulator instance]
$ns create-eventtrace Event $self
}
---END---
8) Modify ns-mac.tcl by adding following portion next to existing codes, from about line 65.
---BEGIN---
# IEEE 802.11new MAC settings if [TclObject is-class Mac/802_11new]
{
Mac/802_11new set delay_ 64us
Mac/802_11new set ifs_ 16us
Mac/802_11new set slotTime_ 16us
Mac/802_11new set cwmin_ 16
Mac/802_11new set cwmax_ 1024
Mac/802_11new set rtxLimit_ 16
Mac/802_11new set bssId_ -1
Mac/802_11new set sifs_ 8us
Mac/802_11new set pifs_ 12us
Mac/802_11new set difs_ 16us
Mac/802_11new set rtxAckLimit_ 1
Mac/802_11new set rtxRtsLimit_ 3
Mac/802_11new set basicRate_ 1Mb
Mac/802_11new set dataRate_ 1Mb
}
---END---
9) mac-802 11new.cc
a) copy this file from ”mac-802 11.cc”
b) substitute ”Mac802 11” with ”Mac802 11new”, there are 83 instances. (match case, only full matched word)
c) substitute ”Mac802 11Class” with ”Mac802 11newClass”, there are 2 instances. (match case, only full matched
word)
d) substitute ”Mac/802 11” with ”Mac/802 11new”, there are 5 instances. (match case, only full matched word)
e) substitute ”mac-802 11” with ”mac-802 11new” in line 34.
f) substitute ”mac-timers.h” with ”mac-timersnew.h” in line 53.
g) substitute ”mac-802 11.h” with ”mac-802 11new.h” in line 54.
h) substitute ”class mac802 11” with ”class mac802 11new” in line 149.
i) substitute ”MAC 802 11” with ”MAC 802 11new” in line 1963.
10) mac-802 11new.h
a) copy this file from ”mac-802 11.h”
b) *substitute ”mac-802 11.h” with ”mac-802 11new.h” in line 34 and 37.
c) substitute ”ns mac 80211 h” with ”ns mac 80211new h” in line 40, 41 and 602.
d) substitute ”mac-timers.h” with ”mac-timersnew.h” in line 47.
e) substitute ”Mac802 11” with ”Mac802 11new”, there are 4 instances. (match case, only full matched word)
f) from line 356 to line 365, postfix the name of each timer class with ”NEW”, for example, substitute ”DeferTimer”
with ”DeferTimerNEW”3
g) from line 554 to line 562, postfix the name of each timer class with ”NEW”, for example, substitute ”IFTimer”
with ”IFTimerNEW”
11) mac-timersnew.cc
a) copy this file from ”mac-timers.cc”
b) substitute ”mac-timers.h” with ”mac-timersnew.h” in line 49.
c) substitute ”mac-802 11.h” with ”mac-802 11new.h” in line 50.
d) postfix the name of each timer class with ”NEW”, for example, substitute ”MacTimer” with ”MacTimerNEW” in line 79, 95, 114, 134, 157, 169, 183, 201, 215, 230, 245, 262, 277, 289, 315 and 349.
12) mac-timersnew.h
a) copy this file from ”mac-timers.h”
b) substitute ” mac timers h ” with ” mac timersnew h ” in line 36, 37 and 140.
c) substitute ”Mac802 11” with ”Mac802 11new”, there are 11 instances. (match case, only full matched word)
d) substitute ”MacTimer” with ”MacTimerNEW”, there are 18 instances. (match case, only full matched word)
e) postfix the name of each timer class with ”NEW”, for example, substitute ”BackoffTimer” with ”BackoffTimerNEW” in line 73/75, 87/89, 95/97, 103/105, 112/114, 119/121, 126/128 and 133/135.
13) Remake load by entering ”make” command under ”ns-allinone-2.33\ns-2.33\”.

Comments

Popular posts from this blog

Python Programming

how to free port 80 in windows