最近几天在Ns-2下添加了接口信道录用率的一个小模块。(PS:具体的MCMI多信道多接口添加方案见http://liujian.viviti.com/ns2 上面有下载链接)
这个接口信道利用率的基本思想是:mac每0.000001s检查mac接口是否为idle,如果正在使用则计数器count++。然后每1s统计一下count。所得的count/1000000.0即为chan util。思想很简单,下面是实现方法。
1. mac802_11.h 文件
....................
/* ======================================================================
The following destination class is used for duplicate detection.
====================================================================== */
class Host {
public:
LIST_ENTRY(Host) link;
u_int32_t index;
u_int32_t seqno;
};
//Timer for channel utilization
class ChanUtil_Timer : public TimerHandler {
public:
ChanUtil_Timer(Mac802_11 *a) : TimerHandler() { a_ = a;}
void expire(Event *e);
protected:
Mac802_11 *a_;
};
//Timer for Calculate channel utilization
class CalChanUtil_Timer : public TimerHandler {
public:
CalChanUtil_Timer(Mac802_11 *a) : TimerHandler() { a_ = a;}
void expire(Event *e);
protected:
Mac802_11 *a_;
};
/* ======================================================================
The actual 802.11 MAC class.
====================================================================== */
class Mac802_11 : public Mac {
friend class DeferTimer;
friend class BeaconTimer;
friend class ProbeTimer;
friend class BackoffTimer;
friend class IFTimer;
friend class NavTimer;
friend class RxTimer;
friend class TxTimer;
//liujian
friend class ChanUtil_Timer;
friend class CalChanUtil_Timer;
//liujian end
public:
Mac802_11();
void recv(Packet *p, Handler *h);
inline int hdr_dst(char* hdr, int dst = -2);
inline int hdr_src(char* hdr, int src = -2);
inline int hdr_type(char* hdr, u_int16_t type = 0);
inline double idle_rate(){return mhNav_.rtime;}//liujian
inline int bss_id() { return bss_id_; }
// Added by Sushmita to support event tracing
void trace_event(char *, Packet *);
EventTrace *et_;
//liujian2010-3-20
FILE *fp;
ChanUtil_Timer ChanUtil_Timer_;
CalChanUtil_Timer CalChanUtil_Timer_;
void ChanUtil_Calculate(); //function for recording channel utilization
void CalChanUtil_Calculate(); //function for calculating channel utilization
void increaseChanUtil()
{
channel_id=netif_->channel()->index();
chanutilcount[channel_id]++;
}
void resetChanUtil() {for(int i=0;i<20;i++)chanutilcount[i]=0;}
int getChanUtil(int i){return chanutilcount[i];}
protected:
void backoffHandler(void);
void deferHandler(void);
void BeaconHandler(void);
void ProbeHandler(void);
void navHandler(void);
void recvHandler(void);
void sendHandler(void);
void txHandler(void);
private:
void update_client_table(int num, int auth_status, int assoc_status);
void push(int num, int auth_status, int assoc_status);
int find_client(int num);
void update_ap_table(int num, double power);
void push_ap(int num, double power);
int strongest_ap();
int find_ap(int num, double power);
void deletelist();
void passive_scan();
void active_scan();
int end();
void shift_priority_queue();
void checkAssocAuthStatus();
int command(int argc, const char*const* argv);
/* In support of bug fix described at
* http://www.dei.unipd.it/wdyn/?IDsezione=2435
*/
int bugFix_timer_;
int infra_mode_;
double BeaconTxtime_;
int associated;
int authenticated;
int handoff;
double Pr;
int ap_temp;
int ap_addr;
int associating_node_;
int authenticating_node_;
int ScanType_;
int OnMinChannelTime;
int OnMaxChannelTime;
int Recv_Busy_;
//liujian
int chanutilcount[20];
int channel_id;
/*
* Called by the timers.
*/
void recv_timer(void);
void send_timer(void);
int check_pktCTRL();
2. mac802_11.cc文件
....................
//Timer for recording channel utilzation
void ChanUtil_Timer::expire(Event *)
{
a_->ChanUtil_Calculate();
//Traffic timer expires for every node or the node specified
resched(0.000001);
}
//Timer for calculating channel utilzation
void CalChanUtil_Timer::expire(Event *)
{
//printf("%lf---############",NOW);
a_->CalChanUtil_Calculate();
//Traffic timer expires for every node or the node specified
resched(1);
}
....................
Mac802_11::Mac802_11() :
Mac(), phymib_(this), macmib_(this), mhIF_(this), mhNav_(this),
mhRecv_(this), mhSend_(this),
mhDefer_(this), mhBackoff_(this), mhBeacon_(this), mhProbe_(this),ChanUtil_Timer_(this),CalChanUtil_Timer_(this)//liujian
{
nav_ = 0.0;
tx_state_ = rx_state_ = MAC_IDLE;
tx_active_ = 0;
eotPacket_ = NULL;
pktRTS_ = 0;
pktCTRL_ = 0;
pktBEACON_ = 0;
pktASSOCREP_ = 0;
pktASSOCREQ_ = 0;
pktAUTHENTICATE_ = 0;
pktPROBEREQ_ = 0;
pktPROBEREP_ = 0;
BeaconTxtime_ = 0;
infra_mode_ = 0;
cw_ = phymib_.getCWMin();
ssrc_ = slrc_ = 0;
// Added by Sushmita
et_ = new EventTrace();
sta_seqno_ = 1;
cache_ = 0;
cache_node_count_ = 0;
client_list = NULL;
ap_list = NULL;
Pr = 0;
ap_temp = -1;
head = 0;
ap_addr = -1;
associated = 0;
authenticated = 0;
OnMinChannelTime = 0;
OnMaxChannelTime = 0;
Recv_Busy_ = 0;
handoff= 0;
// ssid_ = "0";
memset(priority_queue, 0, sizeof(priority_queue));
//liujian
for(int i=0;i<20;i++)
chanutilcount[i]=0;
ChanUtil_Timer_.sched(0.000001);
CalChanUtil_Timer_.sched(0.01);
// chk if basic/data rates are set
....................
int
Mac802_11::command(int argc, const char*const* argv)
{
if (argc == 3) {
if (strcmp(argv[1], "eot-target") == 0) {
EOTtarget_ = (NsObject*) TclObject::lookup(argv[2]);
if (EOTtarget_ == 0)
return TCL_ERROR;
return TCL_OK;
}
if (strcmp(argv[1], "ap") == 0) {
ap_addr = addr();
bss_id_ = addr();
infra_mode_ = 1;
mhBeacon_.start((Random::random() % cw_) *
phymib_.getSlotTime());
return TCL_OK;
}
if (strcmp(argv[1], "ScanType") == 0) {
if (strcmp(argv[2], "ACTIVE") == 0) {
ScanType_ = ACTIVE;
infra_mode_ = 1;
ap_list = NULL;
mhProbe_.start(macmib_.getProbeDelay());
} else if (strcmp(argv[2], "PASSIVE") == 0) {
ScanType_ = PASSIVE;
mhProbe_.start(macmib_.getChannelTime());
infra_mode_ = 1;
}
return TCL_OK;
} else if (strcmp(argv[1], "log-target") == 0) {
logtarget_ = (NsObject*) TclObject::lookup(argv[2]);
if(logtarget_ == 0)
return TCL_ERROR;
return TCL_OK;
} else if(strcmp(argv[1], "nodes") == 0) {
if(cache_) return TCL_ERROR;
cache_node_count_ = atoi(argv[2]);
cache_ = new Host[cache_node_count_ + 1];
assert(cache_);
bzero(cache_, sizeof(Host) * (cache_node_count_+1 ));
return TCL_OK;
} else if(strcmp(argv[1], "eventtrace") == 0) {
// command added to support event tracing by Sushmita
et_ = (EventTrace *)TclObject::lookup(argv[2]);
return (TCL_OK);
}
}
return Mac::command(argc, argv);
}
//liujian
void
Mac802_11::ChanUtil_Calculate()
{
//if mac is not idle
if(!is_idle()){
//increase channel utilization counter
increaseChanUtil();
}
}
void
Mac802_11::CalChanUtil_Calculate()
{
if (((fp = fopen("Chanfile", "a")) != NULL) )
{
fprintf(fp, "[time]-%lf [node]-%d [chan_id]-%d [chanUtil]-%lf \n",NOW,((MobileNode*)(netif_->node())) ->nodeid(),channel_id,getChanUtil(channel_id)/1000000.0);
fclose(fp);
resetChanUtil();
} else {
printf("fail to open file");
}
}