ns2代码分析(一)-数据包指针进入队列

来源:互联网 发布:mac的邮箱怎么设置 编辑:程序博客网 时间:2024/06/08 14:24

   我发现一个现象,也就在中国,会有某某代码分析,某某代码走读。国外似乎就没有这种现象。

   没有法子,想在ns2上做点自己东西,不添加C++代码估计是办不到的。之前我分析了quic中一个小仿真器的大致原理[1]。switch对象中的队列长度为什么增长?进的数据包多,而发送数据包少。就是交换机对象的发送队列在每次发包的之后会检测,上次发送数据包需要耗费的时间,就是网卡的处理能力(packet_length/bandwidth)。我上传的quic_simulator[1],queue.cc在收到一个数据包,文件中有这样一行代码Schedule(clock_->Now()+tx_port_->TimeUntilAvailable());就是经过上次数据包处理延时,本次数据包才能进入网卡,发送到链路上Queue::Act(){tx_port_->AcceptPacket(...)}。

   quic仿真器是这样的工作原理,ns2也不例外。

    仿真数据包传递流程,node->queue->delaylink。  ns2仿真链路上的队列ns-2.35\queue\queue.cc接收数据包函数

void Queue::recv(Packet* p, Handler*){double now = Scheduler::instance().clock();enque(p);if (!blocked_) {/* * We're not blocked.  Get a packet and send it on. * We perform an extra check because the queue * might drop the packet even if it was * previously empty!  (e.g., RED can do this.) */p = deque();if (p != 0) {utilUpdate(last_change_, now, blocked_);last_change_ = now;blocked_ = 1;target_->recv(p, &qh_);}}}
    第一次接收到数据包,enque(p)将数据包加入队列,之后p = deque()将数据包弹出队列,blocked_ = 1设置为阻塞,target_->recv(p, &qh_);将数据包发送到延时链路上,同时这个函数传递个一个队列句柄指针qh_。

ns-2.35\link\delay.cc

void LinkDelay::recv(Packet* p, Handler* h){double txt = txtime(p);Scheduler& s = Scheduler::instance();if (dynamic_) {Event* e = (Event*)p;e->time_= txt + delay_;itq_->enque(p); // for convinience, use a queue to store packets in transits.schedule(this, p, txt + delay_);} else if (avoidReordering_) {// code from Andrei Gurtov, to prevent reordering on//   bandwidth or delay changes double now_ = Scheduler::instance().clock(); if (txt + delay_ < latest_time_ - now_ && latest_time_ > 0) { latest_time_+=txt; s.schedule(target_, p, latest_time_ - now_ ); } else { latest_time_ = now_ + txt + delay_; s.schedule(target_, p, txt + delay_); }} else {s.schedule(target_, p, txt + delay_);}s.schedule(h, &intr_, txt);}

    数据包进入链路后,链路会计算数据在网卡上的发送时间。在recv函数中,将数据包的网卡处理时延和这个句柄注册到scheduler(s.schedule(h, &intr_, txt);)。

    这个时刻到来,调度器回调队列句柄,进行出队操作。ns-2.35\queue\queue.cc:

void QueueHandler::handle(Event*){queue_.resume();}void Queue::resume(){double now = Scheduler::instance().clock();Packet* p = deque();if (p != 0) {target_->recv(p, &qh_);} else {if (unblock_on_resume_) {utilUpdate(last_change_, now, blocked_);last_change_ = now;blocked_ = 0;}else {utilUpdate(last_change_, now, blocked_);last_change_ = now;blocked_ = 1;}}}

  如果在这个网卡处理时延之间有数据包到来,就到进队等待,队列长度就会增加。

[1]谷歌quic协议自带网络仿真器代码分析(一)

[2]NS 发送一个 cbr 数据包的过程

原创粉丝点击