一. Mac802_11定时器相关类介绍
类图如下:
http://120.img.pp.sohu.com/images/blog/2007/12/3/16/16/1173b4c9ccf.jpg
图1 NS2中Mac802_11定时器相关类结构图
PS:在~ns\Common\Timer-handler.[h,cc]中定义了一个TimerHandler类,该类是ns中的通用定时器,不过MAC中并未使用它,而是自行定义一些功能和机制与其相似的timer。
重要类介绍(以下类定义位置均在 ~ns\Mac\Mac-timers.[h,cc]):
1. MacTimer : Handler
作用概述:
1)Mac802_11中timer的共同父类;
2)派生自Handler类,因此定时器就可以作为Scheduler::schedule(Handler*, Event*, double delay)方法中的Handler*参数传递给事件调度器,从而作为超时后的事件处理器。
重要属性/方法:
1) protected Mac802_11 *mac;
用于timer调用mac的对应超时处理方法,timer的构造函数以Mac802_11类实例的指针为参数,并将其赋值给mac。
2) public virtual void start(double time)
{
... //设置timer状态,记录时间
s.schedule(this, &intr, rtime);
//this为timer自己的引用;rtime为timer的计时时长;&intr为Event类型,用于标记此定时器事件
}
start()最终调用schedule(),使事件调度器在经过rtime时间之后通知timer处理超时,以此实现了定时和超时通知的,即定时器的能力实际是由基于时间的事件调度器来实现的。
3) public virtual void stop()
主要调用了Scheduler::cancel(&intr)方法,取消调度器中的该定时器事件,并重置timer状态。
4) public inline double expire()
{
return ((stime + rtime) - Scheduler::instance().clock());
}
区别于NS的通用定时器TimerHandler::expire(),此方法仅用于返回距离定时器超时还有多久时间。
2. BackoffTimer : MacTimer
作用概述(结合IEEE802.11中的描述,参见图1.2):
图1.2 IEEE802.11定时机制示意图
1) 用于竞争退避机制:在检测到介质持续空闲了一个DIFS(DCF InterFrame Space)或EIFS(Extended InterFrame Space)时长后,如果此时站点STA的回退计时器backoff timer为零,则STA将产生一个随机回退时间而不是立即接入,从而减少多个等待的STA在DIFS后同时接入而产生冲突;不为零时则继续按照回退计时器内容等待。
2) Backoff Time = Random() × aSlotTime;
3) Random()——返回[0,CW]之间的一个随机整数,CW为当前竞争窗口大小;
4) 在DIFS或EIFS结束后STA继续检测介质,每检测完一个空闲aSlotTime时长回退计时器就减一;若在回退计时器还在计时工作的期间检测到介质忙,则暂停回退计时器,待介质重新空闲且持续DIFS或EIFS后,回退计时器才继续。
5) 回退计时器减为零时,立即开始信道占用。
重要属性/方法:
1) public void handle(Event *e)
{
... // 重置timer状态
mac->backoffHandler() // 调用Mac802_11对应超时处理方法
}
BackoffTimer超时的处理方法,将真正的backoff超时处理交给Mac802_11完成。
2) public void start(int cw, int idle)
{
...
rtime = (Random::random() % cw) * mac->phymib_.getSlotTime(); // 生成随机回退时间
...
if(idle == 0)
paused_ = 1; // 当前信道不空闲,则暂停BackoffTimer,实际最终会触发pause()方法
else {
assert(rtime >= 0.0);
s.schedule(this, &intr, rtime); // 信道为空闲,开始回退计时
}
}
该方法即可用于启动新的回退计时,也可用于“暂停”当前回退计时。
3) public void pause()
{
... // 计算剩余回退时隙数slots
rtime -= (slots * mac->phymib_.getSlotTime()); // 修改超时时间
s.cancel(&intr); //取消调度器中的该定时事件,从而达到暂停计时的目的
}
该方法为暂停BackoffTimer所做的实际操作。
4) public void resume(double difs)
{
...
difs_wait = difs; // 重置difs间隔时长
s.schedule(this, &intr, rtime + difs_wait); // 恢复回退计时
}
该方法用于重置difs间隔并恢复BackoffTimer的计时;
3. DeferTimer : MacTimer
作用概述(结合IEEE802.11中的描述,参见图1.2):
1) 用于表示接入信道需要延迟的时间(不包括回退时间)
2) 当STA监听信道时正确接收到了RTS/CTS等信息时,会得知当前信道将被占用的时长,该时长加上DIFS或EIFS时长即为需要延迟接入的时间defer time。
4. NavTimer : MacTimer
作用概述(结合IEEE802.11中的描述,参见图1.2):
1) Nav是一个由每个基站各自维护的指示器,它指示基站不能在无线介质上发起传输的时间段,无论基站是否检测到介质忙;
2) MAC采用的是虚拟载波监听(区别于物理层的物理载波监听),因此需要NAV以及物理载波监听结果来联合决定介质的空闲与否;
3) NAV就像一个以恒定速率递减的计数器,当计数器不为零时,虚拟载波监听认为介质忙,为零时认为空闲。
4) STA通过接收其它STA发送的帧里的Duration/ID域来更新NAV——当该值大于当前STA的NAV值且该帧不是发给这个STA的时候,就以新的值设置NAV。
5) NAV用于实现虚拟载波监听,它关注介质的忙状态(它在介质忙的时候递减);而backoff timer用于实现回退机制以减少冲突,它关注介质的空闲状态(它在介质空闲的时候递减)。
5. RxTimer : MacTimer
作用概述:
1) Mac802_11定义的定时器,用于模拟接收一个完整分组所花的接收时延;
2) 在接收分组时启动,Mac802_11进入MAC_RECV状态,在定时器超时前若又有其它分组到来则会改变mac状态;在定时器超时后检查mac状态即可得知分组是否正确接收完。
6. TxTimer : MacTimer
作用概述:
1) 发送方发出一个消息后需要得到相应回复,如CTS/ACK等;该定时器即被发送方用于对回复信息的计时;
2) 在Mac802_11::transmit()方法中启动,定时器超时后表示在规定时间内没有收到回复,调用Mac802_11::sendHandler(),进而调用Mac802_11::send_timer(),根据发送状态判断是否需要重传以及重传何种类型的消息(RTS/CTS/DATA/ACK)。
7. IFTimer : MacTimer
作用概述:
1) Mac802_11定义的定时器,用于模拟发送一个完整分组所花的发送时延;
2) 在Mac802_11::transmit()方法中启动,定时器超时后表示分组已经发送成功,调用Mac802_11::txHandler(),其中调用mac层trace对象EOTtarget_->recv(eotPacket_, (Handler *) 0),并设置mac的发送状态tx_active_为0。
上述3至7号timer的属性/方法较简单且相似,统一介绍如下:
1)public void handle(Event *e)
{
... // 重置timer状态
mac->XXXHandler() // 调用Mac802_11对应超时处理方法,XXX通常为timer名称
}
XXXTimer超时的处理方法,将实际的超时处理交给Mac802_11:: XXXHandler()方法完成。
二. 总结
NS中定时器工作机制总结如下:
1. 先通过定时器的start(time)方法,向Scheduler中加入延迟为time的事件,事件的处理器为Timer自己;
2. 延迟time时间之后,Scheduler调度Timer的handle()方法,表示定时器超时,进而实现定时器超时处理;
3. 超时前可以调用Timer的stop方法,进而调用Scheduler::cancel(e)方法,取消定时器计时事件。