仿真,主要模拟的就是网络实体的处理速率与链路之间的时延。
ns3的网卡处理速率反映在NetDevice这个类中,而链路时延则反映在Channel中。上层的数据包发送速率可能比NetDevice处理速率要快,因此类NetDevice要有一个队列,缓存下来不及发送的数据包。
数据包进入队列处理逻辑
bool
PointToPointNetDevice::Send (
Ptr<Packet> packet,
const Address &dest,
uint16_t protocolNumber)
{
if (m_queue->Enqueue (packet))
{
//
// If the channel is ready for transition we send the packet right now
//
if (m_txMachineState == READY)
{
packet = m_queue->Dequeue ();
m_snifferTrace (packet);
m_promiscSnifferTrace (packet);
bool ret = TransmitStart (packet);
return ret;
}
return true;
}
// Enqueue may fail (overflow)
m_macTxDropTrace (packet);
return false;
}
void PointToPointNetDevice::TransmitStart (Ptr<Packet> p)
{
m_txMachineState = BUSY;/设置发送状态
Time txTime = m_bps.CalculateBytesTxTime (p->GetSize ());//模拟链路发送时延
Time txCompleteTime = txTime + m_tInterframeGap;
Simulator::Schedule (txCompleteTime, &PointToPointNetDevice::TransmitComplete, this);//数据成功发送后的回调
bool result = m_channel->TransmitStart (p, this, txTime);//发送到channel中模拟链路传输时延
}
void PointToPointNetDevice::TransmitComplete (void)
{
m_txMachineState = READY;
Ptr<Packet> p = m_queue->Dequeue ();//弹出缓冲队列中的数据包
TransmitStart (p);//数据包发送
}
channel中的TransmitStart函数:
bool
PointToPointChannel::TransmitStart (
Ptr<const Packet> p,
Ptr<PointToPointNetDevice> src,
Time txTime)
{
Simulator::ScheduleWithContext (m_link[wire].m_dst->GetNode ()->GetId (),txTime + m_delay, &PointToPointNetDevice::Receive, m_link[wire].m_dst, p->Copy ());//经过txTime + m_delay时延后,通过回调进行数据上传
}
而且此处ScheduleWithContext对应的模板函数是:
template <typename MEM, typename OBJ,
typename T1>
void Simulator::ScheduleWithContext (uint32_t context, Time const &delay, MEM mem_ptr, OBJ obj, T1 a1)
{
return ScheduleWithContext (context, delay, MakeEvent (mem_ptr, obj, a1));
}