Introduction
First, an introduction on "how ns-2 handle the 802.11 rate":
There is a file ns-mac.tcl in ./tcl/lib directory, in this file the MAC/802-11 set datarate_ as 1Mb, and basicRate_ as 1Mb. change these two values could change rate.
We have to consider following questions:
Atomic operations:
- The sender determine the rate (how??). calculate NAV, assuming ACK use the same rate( or basic rate??). Send DATA
- How to let the receiver know the rate? We have to use PLCP header. The SIGNAL field in PLCP header is used for this purpose.
- Why the receiver needs to know the rate? because it wants to correct receive it and might send ACK with same rate.
- Using Short PLCP? Two major changes, PLCP preamble is 72 instead of 144 bits (still sent with 1Mbps) The PLCP header is sent with 2Mbps.
Control & Feedback for auto-rate
- Receiver-based Autorate (RBAR). RTS/CTS is necessary, RTS send with lowest rate (1Mbps), the receiver put something in the CTS to tell the sender use which rate (CTS is still sent with lowest rate)
- ARF (auto-rate fallback), for every 2nd ACK miss( transmission failure) following good transmission, fallback to lower rate and set a timer. Whenever the consecutive 10 good transmission or timer expired, upgrade to higher rate. Then, if miss ACK, fallback to lower rate.
- Fixed Rate. Assume every node is not moving, the benefits of adaptive autorate is very small. So, for every node pair, we set a fixed rate to follow, either 1,2,5.5,11
Rate .vs. Range
- Each rate corresponding to a different transmission range. This is to be reflected.
- Carrier-Sense threshold does not change for different rate. So this is a fixed vaue.
Implementation
- set rate
- short preamble
- receive threshold
- AutoRate Scheme 1: ARF
baisc multirate codes (only Implement Feature 1 & 2) (download zip file)
And also, there is 8db SNR difference from the 1Mbps and 11Mbps rate. It means that the 1Mbps frames will be decoded in a distance more than 250 meters.
it is a baisc multirate setting with rate info attached as Pxtinfo txinfo
there is no auto rate selection.
Advanced multirate code:
Implement Feature 1,2 3
Auto multi-rate codes: (Implement Feature 1,2 3 and a feasible Autorate Scheme)
in addition to basic multirate, auto rate and channel access estimation.
The design is integrated with a new cross-layer MAC design entity which a new structure of Node_Info is involved. (Link to Design of Cross-layer MAC).
For both versions, 6 files need to modified:
in ~/mac directoty:
- mac-802_11.h
- mac-802-11.cc
- wireless-phy.cc.
- wireless-phy.h
in ~/common directory
- mobilenode.cc .allow node to change its rate. It should has its will to stay in a lower rate as wish.
- packet-stamp.h This is a HACK! The receiver cannot know the rate before decoding the PLCP header, but here we put rate as same as SNR.
Note that whenever switch from versions of multi-rate to non-mulitrate ns codes, make clean & make due to problems with packet-stamp.h otherwise, "segmentation fault" occurs.
Based on the feature, Modifications are described in detail
Set Rate in TCL for each node:
rate is given in tcl code, and no matter what happens, the node has to use this rate as a fixed value. No matter a received DATA is another rate or not, datarate_ does not change. Only if an auto-rate scheme is in effect.............
in mac-802.11.cc
getTxrate helps to get the rate info and calculate the timeouts,
setTxrate is only used for autorate..............
in mobilenode.cc:
#include "wireless-phy.h"
#include "mac-802_11.h"
Mac802_11* macptr;
......
//Zhibin - To have an access to change rate!
else if (strcmp(argv[1], "change_rate") == 0) {
macptr = (Mac802_11*) ifhead_.lh_first->uptarget();
if (macptr) {
// Keep attention: supposes only 1
// interface present!
macptr->setRate(atoi(argv[2]));
fprintf(stderr, "Rate changed to: %d\n\n",\
atoi(argv[2]));
return TCL_OK;
} else {
fprintf(stderr, "Error.. Mac not found..\n");
return(TCL_ERROR);
};
return TCL_OK;
}
............
in mac-802_11.h
//zhibin-multirate inline double setRate(double newvalue){ return dataRate_ = newvalue;}; //-----------------
Short Preamble header & different rate for ACK/RTS/CTS/DATA
in mac-802_11.h
// Zhibin- To introduce the short preamble, variables will be bind from ns-default.tcl u_int32_t ShortPreambleLength; double ShortPLCPDataRate; double ShortPLCPHeaderThreshold; // we keep this parameter as part of MIB inline double getEIFS(double r) { // see (802.11-1999, 9.2.10) return(SIFSTime + getDIFS() + (8 * getACKlen(r))/PLCPDataRate); } inline double getShortPLCPHeaderThreshold() { return ShortPLCPHeaderThreshold ; } inline u_int32_t getShortPreambleLength() { return(ShortPreambleLength); } inline double getShortPLCPDataRate() { return(ShortPLCPDataRate); } inline u_int32_t getPLCPHeaderLength() { return(PLCPHeaderLength); } inline u_int32_t getPLCPhdrLen(double r) { return ((r>ShortPLCPHeaderThreshold ) ?((ShortPreambleLength >> 3)+(PLCPHeaderLength >> 3)) :((PreambleLength >> 3)+(PLCPHeaderLength >> 3))); } inline u_int32_t getHdrLen11(double r) { return(getPLCPhdrLen(r) + sizeof(struct hdr_mac802_11) + ETHER_FCS_LEN); } inline u_int32_t getRTSlen(double r) { return(getPLCPhdrLen(r) + sizeof(struct rts_frame)); } inline u_int32_t getCTSlen(double r) { return(getPLCPhdrLen(r) + sizeof(struct cts_frame)); } inline u_int32_t getACKlen(double r) { return(getPLCPhdrLen(r) + sizeof(struct ack_frame)); }in ns-default.tcl
Mac/802_11 set ShortPreambleLength_ 72 ;
# DataRate of Short PLCP Header. PLCP preample is always sent at DSSS_PLCPDataRate
Mac/802_11 set ShortPLCPDataRate_ 2.0e6 ;
#-------zhibinwu ----------------
Mac/802_11 set ShortPLCPHeaderThreshold_ 1.0e6;
in mac-802_11.cc
parent->bind("ShortPreambleLength_", &ShortPreambleLength); parent->bind("ShortPLCPHeaderThreshold_", &ShortPLCPHeaderThreshold); parent->bind_bw("ShortPLCPDataRate_", &ShortPLCPDataRate);Has to assume all ACK and RTS/CTS are in basic rate. Thus, probablay 1mbps,
Change :
getCTSlen() ----> getRTSlen(basicRate_);
getRTSlen() ----> getCTSlen(basicRate_);
getACKlen() ----> getACKlen(basicRate_);
getEIFS ----> getEIFS(basicRate_);
getHdrlen11() ----->getHdrlen11(p->txinfo_.getTxRate())
double Mac802_11::txtime(double psz, double drt) { // change wrt Mike's code // double dsz = psz - PLCP_HDR_LEN; // int plcp_hdr = PLCP_HDR_LEN << 3; // double dsz = psz - phymib_.getPLCPhdrLen(); // int plcp_hdr = phymib_.getPLCPhdrLen() << 3; double dsz = psz - phymib_.getPLCPhdrLen(drt); int plcp_hdr = phymib_.getPLCPhdrLen(drt) << 3; int datalen = (int)dsz << 3; // change wrt Mike's code // double t = (((double)plcp_hdr)/phymib_->PLCPDataRate) + (((double)datalen)/drt); // double t = (((double)plcp_hdr)/phymib_.getPLCPDataRate()) // + (((double)datalen)/drt); double t = 0; if ( drt >phymib_.getShortPLCPHeaderThreshold() ) { /* Zhibin - In this case the are sent at 1 Mbps while * ShortPLCPHeader at 2Mbps and the rest at dataRate_ */ t = (((double)phymib_.getShortPreambleLength())/(phymib_.getPLCPDataRate())) + (((double)phymib_.getPLCPHeaderLength())/(phymib_.getShortPLCPDataRate())) + (((double)datalen)/drt); } else { t = (((double)plcp_hdr)/phymib_.getPLCPDataRate()) + (((double)datalen)/drt); }; return(t); }
Attach and Read Rate information with DATA frame
in packet-stamp.h
inline double getTxRate() {return txRate;} inline void setTxRate(double r) {txRate = r;}in 802.11.cc
void Mac802_11::sendDATA(Packet *p) { .... if((u_int32_t)ETHER_ADDR(dh->dh_ra) != MAC_BROADCAST) { p->txinfo_.setTxRate(dataRate_); if((u_int32_t)ETHER_ADDR(dh->dh_ra) != MAC_BROADCAST) { ch->size() += phymib_.getHdrLen11(dataRate_); }else{ // GgX - Broadcast packets are always sent at basicRate_ ch->size() += phymib_.getHdrLen11(basicRate_); }; ..... }
SNR of different Rates ( Drop packets of higher rate if SNR is low)
In wireless-phy.cc
IN sendup fucntion, first get the rate information of the packet. ( The default rate is 1M,if unset in MAC layer)
double rate = p->txinfo_.getTxRate();
int rate_index;
//zhibinwu, find the rate index in rate table
for ( int rate_index=0; rate_index< NUM_RATE_80211b; i++)
{
if ( rate == RXRate_[rate_index]) break;
}
if (rate_index==4) printf ("ERROR! RATE NOT FOUND!\N");
if (Pr < RXThresh_[rate_index]) {
/*
* We can detect, but not successfully receive
* this packet.
*/
hdr_cmn *hdr = HDR_CMN(p);
hdr->error() = 1;
#if DEBUG > 3
printf("SM %f.9 _%d_ drop pkt from %d low POWER %e/%e\n",
Scheduler::instance().clock(), node()->index(),
p->txinfo_.getNode()->index(),
Pr,RXThresh_[rate_index]);
#endif
}
And
RXRate_[0]= 1000000; RXrate_[1]= 2000000; RxRate_[2]= 5500000; RxRate_[3]= 11000000; RXThresh_[0] = 0.1; // receive power threshold (W) for each rate RXThresh_[1] = 0.2; // receive power threshold (W) for each rate RXThresh_[2] = 0.3; // receive power threshold (W) for each rate RXThresh_[3] = 0.4; // receive power threshold (W) for each ratein wireless-phy.h
#define NUM_RATE_80211b 4; double RXRate_[NUM_RATE_80211b]; double RXThresh_[NUM_RATE_80211b]; // receive power threshold (W) for each rate
ARF
ARF relies on MAC retransmission (set retry limit as 7 will be good)- Define rate array in MAC;
- set a varible in MAC to flag miss ACK event.
- Set a conunter to counter consecutive transmissions
- In retransmit data, downgrade-rate, reset ch->size() and ch->txtime();
- In recvACK, prepare upgrade-rate
//zhibinwu optRate_[0] = 1000000; optRate_[1] = 2000000; optRate_[2] = 5500000; optRate_[3] = 11000000; missACK = false; ACKcounter = 0; void Mac802_11::recvACK(Packet *p) { //zhibinwu ----------ARF---- missACK_ = false; ACKcounter_++; if ( ACKcounter_ >10 ) { //upgrade datarate int m; for (m=0;m<4;m++) { if ( optRate_[m] == dataRate_ && m!=3) { dataRate_ = optRate_[m+1]; break; } } //printf(" the new datarate is %f\n", dataRate_); ACKcounter_ = 0; } //-------------------------------
} void Mac802_11::RetransmitDATA() { //zhibinwu's code to do ARF (AutoRate Fallback) ACKcounter_ = 0; // no successive ACKs if (missACK_ == false)) missACK_ = true; //first missed ACK does not trigger fallback else if ( dataRate_ == basicRate_) { //already fallback to lowest } else { //previous rate is datarate_ as same as getTxRate ch->size() -= phymib_.getHdrLen11(pktTx_->txinfo_.getTxRate()); // assert pktTx and change size int m; for (m=0;m<4;m++) { if ( optRate_[m] == dataRate_ && m!=0) { dataRate_ = optRate_[m-1]; } } //calculate new size ch->size() += phymib_.getHdrLen11(dataRate_); ch->txtime() = txtime(ch->size(), dataRate_); pktTx_->txinfo_.setTxRate(dataRate_); } // =============ARF---end========= }
Appendix: PHY Model
In ns-2, the model is TwoRayground. It is for long range. Basically it means the attenuation factor 4 is used instead of 2.
Pr = PtGtGrht2hr2 / (Ld4)
The original setting is:
Tx Power | 0.2818W (24.5dbm) | |
CSThreshold | 1.559e-11 W (-102.5db) | 550m |
RxThreshold | 3.652e-10 W (-91.1db) | 250m |
2.2*250 = 550
Modified model for 802.11b
TxPower | 0.031622777 W (15dbm) | Rate | distance |
CST | -100dbm (1e-13 W) | 1124m | |
RxThreshold[0] | -94dbm 3.9811e-13 W | 1Mbps | 796 |
RxThreshold[1] | -91dbm 7.9433e-13W | 2Mbps | 669 |
RxThreshold[2] | -87dbm 1.9953e-12 W | 5.5Mbps | 532m |
RxThreshold[3] | -82dbm 6.3096e-12 W | 11Mbps | 399m |