ns-3_ Day 5

理解ns-3的网络模拟方法:离散事件

还是以first.cc中的PPP网络为例。
一个分组从n0到n1的过程可以理解成:
image.png

  • T1:n0开始向信道发送分组(第一个字节)。
  • T2:分组的最后一个字节被发送,网络设备释放。
  • T3:分组被n1接收(事实上没有考虑n1的传输延迟,也就是只考虑n1完全接收分组的时刻)。

可以看出,T2-T1就是传输延迟,T3-T2就是传播延迟。
ns-3不关注过程,仅关注事件发生的时刻。因此上述过程在ns-3的眼里就是3个事件:

  1. 事件T1:n0发送分组。注意代码并不模拟逐字节发送的过程,而是认为n0一次性将整个分组发送给PPP信道,并锁定网络设备。然后,n0计划一个新事件T2。计划事件用的就是Simulator::Schedule函数。
bool PointToPointNetDevice::TransmitStart (Ptr<Packet> p)
{
  NS_LOG_FUNCTION (this << p);
  NS_LOG_LOGIC ("UID is " << p->GetUid () << ")");
  NS_ASSERT_MSG (m_txMachineState == READY, "Must be READY to transmit");
	//锁定网络设备
  m_txMachineState = BUSY;
  m_currentPkt = p;
  m_phyTxBeginTrace (m_currentPkt);

  Time txTime = m_bps.CalculateBytesTxTime (p->GetSize ());
  Time txCompleteTime = txTime + m_tInterframeGap;

  NS_LOG_LOGIC ("Schedule TransmitCompleteEvent in " << txCompleteTime.GetSeconds () << "sec");
	//计划事件T2
  Simulator::Schedule (txCompleteTime, &PointToPointNetDevice::TransmitComplete, this);
	//将分组一次性转交给信道
  bool result = m_channel->TransmitStart (p, this, txTime);
  if (result == false)
    {
      m_phyTxDropTrace (p);
    }
  return result;
}
  1. 事件T2:解锁网络设备,因为分组已经发送完毕。
void PointToPointNetDevice::TransmitComplete (void)
{
  NS_LOG_FUNCTION (this);
  NS_ASSERT_MSG (m_txMachineState == BUSY, "Must be BUSY if transmitting");
	//解锁网络设备
  m_txMachineState = READY;

  NS_ASSERT_MSG (m_currentPkt != 0, "PointToPointNetDevice::TransmitComplete(): m_currentPkt zero");

  m_phyTxEndTrace (m_currentPkt);
  m_currentPkt = 0;

  Ptr<Packet> p = m_queue->Dequeue ();
  if (p == 0)
    {
      NS_LOG_LOGIC ("No pending packets in device queue after tx complete");
      return;
    }
  m_snifferTrace (p);
  m_promiscSnifferTrace (p);
  TransmitStart (p);
}
  1. 事件T3:PPP信道把分组转交给n1
bool PointToPointChannel::TransmitStart (Ptr<const Packet> p,Ptr<PointToPointNetDevice> src,Time txTime)
{
  NS_LOG_FUNCTION (this << p << src);
  NS_LOG_LOGIC ("UID is " << p->GetUid () << ")");

  NS_ASSERT (m_link[0].m_state != INITIALIZING);
  NS_ASSERT (m_link[1].m_state != INITIALIZING);

  uint32_t wire = src == m_link[0].m_src ? 0 : 1;
	//计划分组接收事件
  Simulator::ScheduleWithContext (m_link[wire].m_dst->GetNode ()->GetId (), txTime + m_delay, &PointToPointNetDevice::Receive, m_link[wire].m_dst, p->Copy ());
  m_txrxPointToPoint (p, src, m_link[wire].m_dst, txTime, txTime + m_delay);
  return true;
}

ns-3按顺序执行上述事件,事件之间并没有时间间隔而是立刻发生。具体的代码参见src/point-to-point/model/point-to-point-net-device.ccsrc/point-to-point/model/point-to-point-channel.cc
在更复杂的场景下,同一时间会有多个节点争夺信道资源,需要更多计划事件操作和状态变量。

posted on 2023-01-08 10:33  LeewayTang  阅读(125)  评论(0)    收藏  举报

导航