整合UWALOHA和VBF

昨天遗留的问题,之所以出现浮点数错误是因为从node中获取到的信息:node->CX_,node->CY_,node->CZ_为0,而传进来的p1是通过vbh获得的,而奇怪的是这些都为零。

这些数据说明了,节点位置未正确设置。
(1)脚本设置不成功,正常情况下讲,节点位置是在u脚本中设置的。
(2)在中途修改了,昨天修改了node和god。

替换node.cc、node.h、god.cc、god.h等文件就好了,说明昨天修改底层修改坏了哈,最好不能手贱乱改了。

泊松分布随机丢包,如果在node4丢包的话,那么后边肯定会接收不到了
更加奇怪的现象是:直接ns 1_aloha.tcl和调试的情况下,差别很大。

还有个问题一直未解决:
(1)一旦丢包不回复ACK时貌似并未重传。
实验中的确doBackoff了,但是并未发生重传,甚至没进入processPassive函数内。
目前所有检测到的doBackoff实质是主动的backoff,而非因为没等到的backoff,ack超时的处理函数是:
UWALOHA_WaitACKTimer::expire(Event *e)
发送数据是在processPassive做的,但是因为状态原因,UWALOHA_Status == PASSIVE,而未能进入到sendDataPkt(),换言之并没有重发。
(2)解决UWALOHA_Status == PASSIVE

弄清楚什么条件会重发,并重现重发的原理,搞懂算法:

一、RecvProcess
区分接收到的包是ACK还是DATA包,分别处理,如果是DATA包则交给上层处理。
(1)如果是包类型是ACK,自身是该包的DA,且UWALOHA_Status为Wait_ACK,进行如下操作:
WaitACKTimer.cancel(),收到ACK就不在继续等待
bo_counter=0,已经回退的次数重置为0
free(PktQ_.front()),PktQ_.pop(),释放队列首包
UWALOHA_Status = PASSIVE
processPassive()
(2)如果来的是数据包
如果recver是自身或者recver是Mac_Broadcast,则进行以下步骤:
cmh->size() -= hdr_UWALOHA.size(),从cmh的size减去hdr_uwaloha.size();
sendUp(pkt->copy()),向上发送交由vbf来处理;
如果ACKon(启用ACK机制),并且recver不为Mac_Broadcast,则回复ACK,否则调用processPassive()
释放Pkt。

二、replyACK
nsaddr_t Data_Sender = hdr_UWALOHA::access(pkt)->SA,提取发送该包的源节点;
sendPkt(makeACK(Data_Sender)),制作ACK包并且发送之,和普通包的发送过程是一样的;
bo_counter = 0,回退次数重置为0。

三、processPassive:处理被动的状态
如果UWALOHA_Status为Passive并且blocked为false,并且PktQ_.empty()不为空,则发送数据。这种Passive的状态意味着什么?blocked为Passive有意味着什么?

四、StatusProcess(bool is_ack),mac层状态处理函数
UnderwaterSensorNode* n=(UnderwaterSensorNode*) node_,这里node_在underwatermac.h中定义,原型为node_,将其强制转化为UnderwaterSensorNode;
if(blocked==true),阻塞在这,等待ACK
    blocked = fasle,解阻塞
    processPassive,处理被动
if(ackon == false)
    Uwaloha_status = passive
    processPassive
else if(ACKon ==1 && is_ack==false),sendPkt会修改is_ack的值
    Uwaloha_status = WAIT_ACK

五、TxProcess,发送包
cmh = HDR_CMN(pkt)
uwalohah = hdr_UWALOHA::access(pkt)
cmh->size() += hdr_UWALOHA::size(),为公共包头加上uwaloha的size
cmh->txtime() = getTxTime(cmh->size()),传输时间
cmh->error() = 0,错误率
cmh->direction() = hdr_cmn::DOWN,设置向下传输
UWALOHAh->SA = index_
UWALOHAh->packet_type = DATA
UWALOHAh->DA = cmh->next_hop,uwalohah的DA为公共头的下一跳
PktQ_.push(pkt),将pkt压到队列中,mac对象根据此队列判断包是否已经发完
if(UWALOHA_status == PASSIVE && PktQ_.size()==1 && !blocked),当mac状态为Passive且PktQ_长度为1,blocked为false才会sendDataPkt。


六、sendDataPkt,发送数据包
首先产生随机数P,修改UWALOHA_Status为Send_Data,比较p和Persistent值,小则发送当前PktQ_.front()包,大则bo_counter--(不是回退次数么,怎么会减1呢?),然后回退(这里并不对PktQ_做任何操作)。

七、sendPkt,真正的发送数据包
cmh,UWALOHAh包,
uwsn *node = (uwsn*) node_;强转
txtime = cmh->txtime();在TxProcess中设置了cmh->txtime()值,这里取出来
根据节点当前的传输状态(并非UWALOHA_status),来处理
case sleep:    poweron()
case idle:
设置节点传输状态为SEND
cmh->timestamp() = NOW
cmh->direction() = DOWN
如果是数据包:
    如果DA不是MAC_bcst,且 ACKon==1
        将UWALOHA_Status = WAIT_ACK
        重新调度WaitACKTimer,将expire时间设置为WaitACKTimer + txtime(传输时间)
    否则
        free掉当前包
        从队列PktQ_.pop()弹出
        Uwaloha_Status设置为Passive(passive应该是可以进行下一次传输吧?)
    status_handler.is_ack() = false(貌似又不是等待ACK的意思,这个is_ack有什么作用)
否则
    status_handler.is_ack() = true    
sendDown();由底层的phy层来处理了
blocked = true(阻塞为true有什么作用)
s.schedule(&status_handler,&status_event,txtime+0.01),这里调度status_handler将在txtime+0.01的事件响应status_event事件
break
case RECV:
    当前正在接收,而却要腾出空来发送数据包,会造成冲突(话说没有缓冲机制么?)
    如果是ACK的话
        采取retryACK的手段
    否则
        free掉pkt
    Uwaloha_Status设置为Passive
    break
default(SEND状态):
    send too fast
    如果是ACK
        retryACK(pkt)
    否则
        free(pkt)
    Uwaloha_Status设置为Passive

八、retryACK,重发ACK,但是应用场景是在sendPkt中节点传输状态为RECV或者SEND,并且接收到的包为ACK,既然无法处理包为啥还要retryACK呢?
Uwaloha_ACK_RetryTimer * timer = new UWALOHA_ACK_RetryTimer(this,ack),如果是ACK的话就必须要发送,创建一个定时器
timer->resched(MAXACKRetryInterval*Random::uniform()),随机设置一个定时时间
RetryTimerMap_[timer->id()] = timer,将timer加到RetryTimerMap中去,按id索引,应该是个hash表,有必要加到这个表吗?

这里不得不提Uwaloha_ACK_RetryTimer了,当它到点时调用

九、UWALOHA_ACK_RetryTimer::expire
mac_->processRetryTimer(this);

十、processRetryTimer(UWALOHA_ACK_RetryTimer* timer)函数
Packet* pkt = timer->pkt(),在sendPkt中无法立即发送包则延迟发送,有retryACK(pkt)
从RetryTimerMap_找到该timer,通过timer->id,如果count不为0,则erase之,如果没找到就算了,最后delete timer,然后重新发送pkt(此时pkt是ACK):
sendPkt(pkt)

十一、 UWALOHA_WaitACKTimer::expire(Event *e)
    printf("Time out: waitACK\n");
    mac_->doBackoff();    
所定义变量,WaitACKTimer在sendPkt中有用到,发送完数据包后会调度WaitACKTimer在WaitACKTime + txtime时间后到点调用该函数,但是在此时间之前的时间内都是有可能接收到ACK包的,因此还在RecvProcess()中有用到,当接收到的数据包为ACK类型时,WaitACKTimer.cacel会被调用,于是该定时器被提前终结。换言之如果该定时器一直挺到expire说明一直没来ACK,因此要backoff一个随机时间继续等待。

十二、doBackoff()函数
如果要doBackoff(),那显然状态不能为Passive,而应该为Backoff
计算随机backoff的时间
bo_counter++,backoff数加1,我记得这个数在某个地方是要被置零的(RecvProcess接收到ACK包取消timer时重置,replyACK时置零,此时刚回复了ACK)
如果bo_counter小于MaximumCounter
    修改UWALOHA_Status = BACKOFF
    BackoffTimer.resched(BackoffTime);
否则
    重置bo_counter为0
    按理说backoff是为了重发,事实上在sendDataPkt中从PktQ_中取出front项,但是并不pop,就是为了重发,事实上只有在接收到ACK之后,WaitACKTimer.cancel后,才将其pop掉,还没重发就pop掉显得很不合理阿(这里需要测试)。

这块的确是有问题哈,程序会通过多种渠道进入到sendDataPkt中,主要包括:
(1)sendDataPkt()策略调用doBackoff(),如果还没有达到最大回退数,调用BackoffTimer继续等待;
(2)uwaloha_waitacktimer::expire调用doBackoff调用processPassive调用sendDataPkt调用doBackoff
BackoffTimer和WaitACKTimer两者的基本作用搞清楚了,但是CallBack_handler和status_handler还没有,继续。

十三、CallBack_handler
在TxProcess中用到了,    Scheduler::instance().schedule(&CallBack_handler, &callback_event, CALLBACK_DELAY);

十四、status_handler
在sendPkt中用到,
如果发送的包是DATA
    status_handler.is_ack() = false
否则
    status_handler.is_ack() = true
然后
s.schedule(&status_handler,&status_event,txtime+0.01);

至今,对于schedule是啥意思还是不太清楚,研究下吧:

仿真器是时间驱动的,4种,linked-list,heap,calendar queue,"real-time",调度器通过选择next earliest event,执行直到完成,返回执行下一个事件等完成。调度器用的时间单位是second,单线程,给定时间只能执行一个线程,同一时间多个事件执行,根据first scheduled-first dispatched原则,所有计划的调度对于相同的输入应该给出相同的输出。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值