NS3中一些难以理解的常数

摘要:在NS3的学习中,PHY MAC中总有一些常数,需要理解才能修改。如帧间间隔等。那么,本文做个简单分析,帮助大家理解。针对802.11标准中MAC协议。

 

void
WifiMac::Configure80211b (void)
{
  SetSifs (MicroSeconds (10));
  SetSlot (MicroSeconds (20));
  SetEifsNoDifs (MicroSeconds (10 + 304));
  SetPifs (MicroSeconds (10 + 20));
  SetCtsTimeout (MicroSeconds (10 + 304 + 20 + GetDefaultMaxPropagationDelay ().GetMicroSeconds () * 2));
  SetAckTimeout (MicroSeconds (10 + 304 + 20 + GetDefaultMaxPropagationDelay ().GetMicroSeconds () * 2));
}

304是怎么来的呢??

 

1、PHY

采用DSSS,1Mbps模式下。在802.11-2012中,17.2.2.3节中,有PPDU format规定了帧格式。如下图:

其中,大家比较关心的2个参数就是 PLCP Preamble 和 PLCP Header,分别为144bits和48bits。也就是192us,英文为192 MicroSeconds。

计算时间的相关代码,在NS3中 wifi-phy.cc中,代码如下:

uint32_t
WifiPhy::GetPlcpHeaderDurationMicroSeconds (WifiMode payloadMode, WifiPreamble preamble)
{
  switch (payloadMode.GetModulationClass ())
    {
    case WIFI_MOD_CLASS_OFDM:
      {
        switch (payloadMode.GetBandwidth ())
          {
          case 20000000:
          default:
            // (Section 18.3.3 "PLCP preamble (SYNC))" and Figure 18-4 "OFDM training structure"; IEEE Std 802.11-2012)
            // also (Section 18.3.2.4 "Timing related parameters" Table 18-5 "Timing-related parameters"; IEEE Std 802.11-2012)
            // We return the duration of the SIGNAL field only, since the
            // SERVICE field (which strictly speaking belongs to the PLCP
            // header, see Section 18.3.2 and Figure 18-1) is sent using the
            // payload mode.
            return 4;
          case 10000000:
            // (Section 18.3.2.4 "Timing related parameters" Table 18-5 "Timing-related parameters"; IEEE Std 802.11-2012)
            return 8;
          case 5000000:
            // (Section 18.3.2.4 "Timing related parameters" Table 18-5 "Timing-related parameters"; IEEE Std 802.11-2012)
            return 16;
          }
      }
     //Added by Ghada to support 11n
    case WIFI_MOD_CLASS_HT:
      { //IEEE 802.11n Figure 20.1
         switch (preamble)
            {
             case WIFI_PREAMBLE_HT_MF:
               // L-SIG
               return 4;
             case WIFI_PREAMBLE_HT_GF:
               //L-SIG
               return 0;
             default:
               // L-SIG
               return 4;
            }
      }
    case WIFI_MOD_CLASS_ERP_OFDM:
      return 4;

    case WIFI_MOD_CLASS_DSSS:
      if (preamble == WIFI_PREAMBLE_SHORT)
        {
          // (Section 17.2.2.3 "Short PPDU format" and Figure 17-2 "Short PPDU format"; IEEE Std 802.11-2012)
          return 24;
        }
      else // WIFI_PREAMBLE_LONG
        {
          // (Section 17.2.2.2 "Long PPDU format" and Figure 17-1 "Short PPDU format"; IEEE Std 802.11-2012)
          return 48;
        }

    default:
      NS_FATAL_ERROR ("unsupported modulation class");
      return 0;
    }
}

uint32_t
WifiPhy::GetPlcpPreambleDurationMicroSeconds (WifiMode payloadMode, WifiPreamble preamble)
{
  switch (payloadMode.GetModulationClass ())
    {
    case WIFI_MOD_CLASS_OFDM:
      {
        switch (payloadMode.GetBandwidth ())
          {
          case 20000000:
          default:
            // (Section 18.3.3 "PLCP preamble (SYNC))" Figure 18-4 "OFDM training structure"
            // also Section 18.3.2.3 "Modulation-dependent parameters" Table 18-4 "Modulation-dependent parameters"; IEEE Std 802.11-2012)
            return 16;
          case 10000000:
            // (Section 18.3.3 "PLCP preamble (SYNC))" Figure 18-4 "OFDM training structure"
            // also Section 18.3.2.3 "Modulation-dependent parameters" Table 18-4 "Modulation-dependent parameters"; IEEE Std 802.11-2012)
            return 32;
          case 5000000:
            // (Section 18.3.3 "PLCP preamble (SYNC))" Figure 18-4 "OFDM training structure"
            // also Section 18.3.2.3 "Modulation-dependent parameters" Table 18-4 "Modulation-dependent parameters"; IEEE Std 802.11-2012)
            return 64;
          }
      }
    case WIFI_MOD_CLASS_HT:
      { //IEEE 802.11n Figure 20.1 the training symbols before L_SIG or HT_SIG
           return 16;
      }
    case WIFI_MOD_CLASS_ERP_OFDM:
      return 16;

    case WIFI_MOD_CLASS_DSSS:
      if (preamble == WIFI_PREAMBLE_SHORT)
        {
          // (Section 17.2.2.3 "Short PPDU format)" Figure 17-2 "Short PPDU format"; IEEE Std 802.11-2012)
          return 72;
        }
      else // WIFI_PREAMBLE_LONG
        {
          // (Section 17.2.2.2 "Long PPDU format)" Figure 17-1 "Long PPDU format"; IEEE Std 802.11-2012)
          return 144;
        }
    default:
      NS_FATAL_ERROR ("unsupported modulation class");
      return 0;
    }
}

double
WifiPhy::GetPayloadDurationMicroSeconds (uint32_t size, WifiTxVector txvector)
{
  WifiMode payloadMode=txvector.GetMode();

  NS_LOG_FUNCTION (size << payloadMode);

  switch (payloadMode.GetModulationClass ())
    {
    case WIFI_MOD_CLASS_OFDM:
    case WIFI_MOD_CLASS_ERP_OFDM:
      {
        // (Section 18.3.2.4 "Timing related parameters" Table 18-5 "Timing-related parameters"; IEEE Std 802.11-2012
        // corresponds to T_{SYM} in the table)
        uint32_t symbolDurationUs;

        switch (payloadMode.GetBandwidth ())
          {
          case 20000000:
          default:
            symbolDurationUs = 4;
            break;
          case 10000000:
            symbolDurationUs = 8;
            break;
          case 5000000:
            symbolDurationUs = 16;
            break;
          }

        // (Section 18.3.2.3 "Modulation-dependent parameters" Table 18-4 "Modulation-dependent parameters"; IEEE Std 802.11-2012)
        // corresponds to N_{DBPS} in the table
        double numDataBitsPerSymbol = payloadMode.GetDataRate () * symbolDurationUs / 1e6;

        // (Section 18.3.5.4 "Pad bits (PAD)" Equation 18-11; IEEE Std 802.11-2012)
        uint32_t numSymbols = lrint (ceil ((16 + size * 8.0 + 6.0) / numDataBitsPerSymbol));

        // Add signal extension for ERP PHY
        if (payloadMode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM)
          {
            return numSymbols * symbolDurationUs + 6;
          }
        else
          {
            return numSymbols * symbolDurationUs;
          }
      }
    case WIFI_MOD_CLASS_HT:
      {
         double symbolDurationUs;
         double m_Stbc;
        //if short GI data rate is used then symbol duration is 3.6us else symbol duration is 4us
        //In the future has to create a stationmanager that only uses these data rates if sender and reciever support GI
         if (payloadMode.GetUniqueName() == "OfdmRate135MbpsBW40MHzShGi" || payloadMode.GetUniqueName() == "OfdmRate65MbpsBW20MHzShGi" )
           {
             symbolDurationUs=3.6;
           }
         else
           {
             switch (payloadMode.GetDataRate ()/ (txvector.GetNss()))
               { //shortGi
                  case 7200000:
                  case 14400000:
                  case 21700000:
                  case 28900000:
                  case 43300000:
                  case 57800000:
                  case 72200000:
                  case 15000000:
                  case 30000000:
                  case 45000000:
                  case 60000000:
                  case 90000000:
                  case 120000000:
                  case 150000000:
                    symbolDurationUs=3.6;
                    break;
                 default:
                    symbolDurationUs=4;
              }
           }
         if  (txvector.IsStbc())
            m_Stbc=2;
         else
           m_Stbc=1;
         double numDataBitsPerSymbol = payloadMode.GetDataRate () *txvector.GetNss()  * symbolDurationUs / 1e6;
         //check tables 20-35 and 20-36 in the standard to get cases when nes =2
         double Nes=1;
        // IEEE Std 802.11n, section 20.3.11, equation (20-32)
        uint32_t numSymbols = lrint (m_Stbc*ceil ((16 + size * 8.0 + 6.0*Nes) / (m_Stbc* numDataBitsPerSymbol)));

        return numSymbols * symbolDurationUs;

      }
    case WIFI_MOD_CLASS_DSSS:
      // (Section 17.2.3.6 "Long PLCP LENGTH field"; IEEE Std 802.11-2012)
      NS_LOG_LOGIC (" size=" << size
                             << " mode=" << payloadMode
                             << " rate=" << payloadMode.GetDataRate () );
      return lrint (ceil ((size * 8.0) / (payloadMode.GetDataRate () / 1.0e6)));

    default:
      NS_FATAL_ERROR ("unsupported modulation class");
      return 0;
    }
}

Time
WifiPhy::CalculateTxDuration (uint32_t size, WifiTxVector txvector, WifiPreamble preamble)
{
  WifiMode payloadMode=txvector.GetMode();
  double duration = GetPlcpPreambleDurationMicroSeconds (payloadMode, preamble)
    + GetPlcpHeaderDurationMicroSeconds (payloadMode, preamble)
    + GetPlcpHtSigHeaderDurationMicroSeconds (payloadMode, preamble)
    + GetPlcpHtTrainingSymbolDurationMicroSeconds (payloadMode, preamble,txvector)
    + GetPayloadDurationMicroSeconds (size, txvector);
  return MicroSeconds (duration);
}

在函数CalculateTxDuration中,duration的计算方法。

那么,假如你开启4次握手机制,那么rts的duration如何计算呢?

也就是当你生成pacp文件,用wiresharp打开时,看到rts帧中,那个duration是怎么得到的呢?

如下图中17342 是怎么得到的呢?

你需要知道应用层的包是如何封装的,这涉及到计算机网络的知识。这里以上面的包大小举例说明,packet =2000bytes.

上图中可以看到:data—>udp(8)—>ip(20)—>llc(8)—>mac (28)包封装过程

ip和udp封装包头大小,一般计算机网络书中有介绍。llc 这个没搞懂为啥是8个。mac数据帧可以看下图:

一共40字节,但是地址4,qos,ht不用。ns3中使用的是non qos mac。

好了,我们开始计算,但是还需要看一个代码在mac-low.cc:

void
MacLow::SendRtsForPacket (void)
{
  NS_LOG_FUNCTION (this);
  /* send an RTS for this packet. */
  WifiMacHeader rts;
  rts.SetType (WIFI_MAC_CTL_RTS);
  rts.SetDsNotFrom ();
  rts.SetDsNotTo ();
  rts.SetNoRetry ();
  rts.SetNoMoreFragments ();
  rts.SetAddr1 (m_currentHdr.GetAddr1 ());
  rts.SetAddr2 (m_self);
  WifiTxVector rtsTxVector = GetRtsTxVector (m_currentPacket, &m_currentHdr);
  Time duration = Seconds (0);

  WifiPreamble preamble;
  //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
  if ( m_phy->GetGreenfield()&& m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
    preamble= WIFI_PREAMBLE_HT_GF;
  else if (rtsTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
    preamble= WIFI_PREAMBLE_HT_MF;
  else
    preamble=WIFI_PREAMBLE_LONG;

  if (m_txParams.HasDurationId ())
    {
      duration += m_txParams.GetDurationId ();
    }
  else
    {
      WifiTxVector dataTxVector = GetDataTxVector (m_currentPacket, &m_currentHdr);
      duration += GetSifs ();
      duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector);
      duration += GetSifs ();
      duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr),
                                              dataTxVector, preamble);
      duration += GetSifs ();
      duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
    }
  rts.SetDuration (duration);

  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble);
  Time timerDelay = txDuration + GetCtsTimeout ();

  NS_ASSERT (m_ctsTimeoutEvent.IsExpired ());
  NotifyCtsTimeoutStartNow (timerDelay);
  m_ctsTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::CtsTimeout, this);

  Ptr<Packet> packet = Create<Packet> ();
  packet->AddHeader (rts);
  WifiMacTrailer fcs;
  packet->AddTrailer (fcs);

  ForwardDown (packet, &rts, rtsTxVector,preamble);
}

 

公式就是上面这个代码中提取出来的。sifs查这个802.11-2012中上图

duration += GetSifs ();  10

duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector);  cts:14*8+192=304

duration += GetSifs (); 10

duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxVector, preamble); 2064*8+192=16704

duration += GetSifs ();10

duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector); ack:14*8+192=304

duration = 10+304+10+16704+10+304=17342

结果符合wiresharp中那个duration。

 

时间: 2024-10-14 00:00:34

NS3中一些难以理解的常数的相关文章

通过原型链解析js函数一些难以理解的的作用域问题

基本原理 js函数在执行时,系统会创建一个隐式的属性scope,scope中存储的是函数的作用域链. 通过对这个scope的分析,就能解释JavaScript中许多难以理解的问题: 例1: function demo(){} demo(); scope属性是在函数执行时创建,如果这个函数是一个全局函数,他的scope里会保存一个Global object和一个activation object. global object保存的是全局的信息,而activition object保存的是函数内部的

为什么你的代码如此难以理解

“我到底在想什么?!?” 凌晨1:30分,我正盯着不到一个月前我写的一段代码.当时它看起来像是件艺术品,全部是可理解的,优雅.简单.让人叹为观止.这一切都不再了,明天是我的最后期限,数小时前我发现了一个bug.当时看起来的简单和逻辑再也说不通了.可以肯定的是,如果我写代码,我应该足以聪明到理解代码? 经过了多次这种经历以后,我开始认真思考,为什么我的代码在我编写的时候很清楚.而当我数周或数月后回头看的时候,它们却那么费解. 问题1,过度复杂的心智模型 为了理解当你间隔一段时间返回到你的代码.却发

js中的闭包理解一

闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的理解以及js内部解释器的运作方式的描述,都是可以看出你js实际水平的.即使你没答对,也能让考官对你的水平有个评估.那么我先来说说我对js中的闭包的理解. 闭包是很多语言都具备的特性,在js中,闭包主要涉及到js的几个其他的特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等. 在理解闭包以前.最好能

为什么你的代码如此难以理解(转)

英文原文:Why your code is so hard to understand “我到底在想什么?!?” 凌晨1:30 分,我正盯着不到一个月前我写的一段代码.当时它看起来像是件艺术品,全部是可理解的,优雅.简单.让人叹为观止.这一切都不再了,明天是我的最后期限,数小时前我发现了一个 bug.当时看起来的简单和逻辑再也说不通了.可以肯定的是,如果我写代码,我应该足以聪明到理解代码? 经过了多次这种经历以后,我开始认真思考,为什么我的代码在我编写的时候很清楚.而当我数周或数月后回头看的时候

委托,曾将让我头疼难以理解

刚开始学习C#的时候,基本语法什么的看一遍,写个demo,就理解了,下回用的时候,就上手了,这个委托看了很多,一直不知道他在何时何地会发挥作用!只记住一个关键词——“delegate”和概念——“ 是表示对具有特定参数列表和返回类型的方法的引用的类型”. 心痒难挠啊啊啊啊啊啊!!!!!!!!!! 最近想起来了,把自己最新的认识写出来,希望大家指正补充..... 基础 关键词:delegate 声明语法: public delegate 返回值类型 委托名称(参数列表); 实例化:委托名称 实例名

关于Python中的列表理解及用法

在Python中,列表理解通常用于编写单行语句,这些语句通过可迭代对象进行迭代以创建新的列表或字典.本文首先介绍for循环如何在Python中工作,然后解释如何在Python中使用列表理解. Python中的for循环 Python中的for循环语句按顺序遍历任何对象.列表.字符串等的成员.与其他编程语言相比,它的语法更加简洁,不需要手工定义迭代步骤,也不需要开始迭代.尽管有几种方法可以使它的行为与其他编程语言相同(本文将不详细讨论).还可以使用continue.break.pass等语句控制f

BGP中正则表达式的理解

今天不经意和网上一个朋友聊到H3CTE 考试,不过很遗憾的上我考挂了,所以才和他讨论的,当时讨论BGP 的路由属性控制MED 和LOCAL-PECR ,突然帽出来个正则表达式,很郁闷的是,我一直都没怎么在乎这个东西,以前只是看到过,以为不怎么重要,今天他突然和我讲了下重要性,而且当时考H3CTE 就需要用上这个,汗~~~居然都不知道.和他聊完我立即找这相关方面的资料,找到了一点点,郁闷很难看懂啊,都是一些符号不好理解啊.没法呀,得学习^_^ 下面是对BGP 正则表达式的介绍 . 匹配任意单个字符

畅销书对Java中Iterator的理解误区

声明:本博客为原创博客,未经允许,不得转载!原文链接为http://blog.csdn.net/bettarwang/article/details/28110615 最近放假,闲来无事,便翻看以前看过的一些书,竟然发现有些书本(甚至是一些畅销书)对Java中Iterator有很大的误解,比如某畅销书在Collection那一章有这么一句话:"当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对集

NS3之路---在NS3中添加openflow模块

如何在NS3中安装openflow模块 Note:目前NS3中虽然支持openflow(貌似仅为V0.89),但是并不支持外部控制器,仅使用内部封装的一个控制器(ofi::Controller). 模型描述 该模型依赖于建立一个外部的openflow switch库(Openflow software implementation distribution, OFSID),然后编译ns3封装器来调用该openflow库函数.ns3的封装源码位于“src/openflow/model”路径下. 设