src/devices/wifi/mac-low.cc
changeset 2146 40ad60ac9912
parent 2088 a651a0131bfe
child 2147 b6243a53c93f
--- a/src/devices/wifi/mac-low.cc	Mon Nov 19 16:20:30 2007 +0100
+++ b/src/devices/wifi/mac-low.cc	Mon Nov 19 16:53:05 2007 +0100
@@ -35,7 +35,8 @@
 NS_LOG_COMPONENT_DEFINE ("MacLow");
 
 #define MY_DEBUG(x) \
-  NS_LOG_DEBUG (Simulator::Now () << " " << m_device->GetNode ()->GetId () << " " << x)
+  NS_LOG_DEBUG (Simulator::Now () << " " << m_device->GetNode ()->GetId () << ":" << \
+                m_device->GetIfIndex () << " " << x)
 
 namespace ns3 {
 
@@ -305,6 +306,11 @@
 {
   m_device = device;
 }
+Ptr<NetDevice> 
+MacLow::GetDevice (void) const
+{
+  return m_device;
+}
 void
 MacLow::SetPhy (Ptr<WifiPhy> phy)
 {
@@ -405,12 +411,17 @@
   WifiMacHeader hdr;
   packet.RemoveHeader (hdr);
   
-  bool isPrevNavZero = IsNavZero (Simulator::Now ());
+  bool isPrevNavZero = IsNavZero ();
   MY_DEBUG ("duration/id=" << hdr.GetDuration ());
-  NotifyNav (Simulator::Now (), &hdr);
+  NotifyNav (hdr, txMode, preamble);
   if (hdr.IsRts ()) 
     {
-      /* XXX see section 9.9.2.2.1 802.11e/D12.1 */
+      /* see section 9.2.5.7 802.11-1999
+       * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS 
+       * period if the NAV at the STA receiving the RTS frame indicates that the medium is 
+       * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle, 
+       * that STA shall not respond to the RTS frame.
+       */
       if (isPrevNavZero &&
           hdr.GetAddr1 () == m_device->GetSelfAddress ()) 
         {
@@ -656,56 +667,82 @@
   return txTime;
 }
 
+void
+MacLow::NotifyNav (const WifiMacHeader &hdr, WifiMode txMode, WifiPreamble preamble)
+{
+  NS_ASSERT (m_lastNavStart <= Simulator::Now ());
+  Time duration = hdr.GetDuration ();
+
+  if (hdr.IsCfpoll () &&
+      hdr.GetAddr2 () == m_device->GetBssid ()) 
+    {
+      // see section 9.3.2.2 802.11-1999
+      DoNavResetNow (duration);
+      return;
+    }
+  // XXX Note that we should also handle CF_END specially here
+  // but we don't for now because we do not generate them.
+  else if (hdr.GetAddr1 () == m_device->GetSelfAddress ())
+    {
+      // see section 9.2.5.4 802.11-1999
+      bool navUpdated = DoNavStartNow (duration);
+      if (hdr.IsRts () && navUpdated)
+        {
+          /**
+           * A STA that used information from an RTS frame as the most recent basis to update its NAV setting 
+           * is permitted to reset its NAV if no PHY-RXSTART.indication is detected from the PHY during a 
+           * period with a duration of (2 * aSIFSTime) + (CTS_Time) + (2 * aSlotTime) starting at the 
+           * PHY-RXEND.indication corresponding to the detection of the RTS frame. The “CTS_Time” shall 
+           * be calculated using the length of the CTS frame and the data rate at which the RTS frame 
+           * used for the most recent NAV update was received.
+           */
+          WifiMacHeader cts;
+          cts.SetType (WIFI_MAC_CTL_CTS);
+          Time navCounterResetCtsMissedDelay = 
+            m_phy->CalculateTxDuration (cts.GetSerializedSize (), txMode, preamble) +
+            Scalar (2) * m_parameters->GetSifs () + Scalar (2) * m_parameters->GetSlotTime ();
+          m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
+                                                            &MacLow::NavCounterResetCtsMissed, this,
+                                                            Simulator::Now ());
+        }
+    }
+}
 
 void
-MacLow::NotifyNav (Time at, WifiMacHeader const *hdr)
+MacLow::NavCounterResetCtsMissed (Time rtsEndRxTime)
+{
+  if (m_phy->GetLastRxStartTime () > rtsEndRxTime)
+    {
+      DoNavResetNow (Seconds (0.0));
+    }
+}
+
+void
+MacLow::DoNavResetNow (Time duration)
 {
-  /* XXX
-   * We might need to do something special for the
-   * subtle case of RTS/CTS. I don't know what.
-   *
-   * See section 9.9.2.2.1, 802.11e/D12.1
-   */
-  NS_ASSERT (m_lastNavStart < at);
-  Time oldNavStart = m_lastNavStart;
-  Time oldNavEnd = oldNavStart + m_lastNavDuration;
-  Time newNavStart = at;
-  Time duration = hdr->GetDuration ();
-
-  if (hdr->IsCfpoll () &&
-      hdr->GetAddr2 () == m_device->GetBssid ()) 
+  for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++) 
     {
-      m_lastNavStart = newNavStart;
+      (*i)->NavReset (duration);
+    }
+  m_lastNavStart = Simulator::Now ();
+  m_lastNavStart = duration;
+}
+bool
+MacLow::DoNavStartNow (Time duration)
+{
+  for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++) 
+    {
+      (*i)->NavStart (duration);
+    }
+  Time newNavEnd = Simulator::Now () + duration;
+  Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
+  if (newNavEnd > oldNavEnd)
+    {
+      m_lastNavStart = Simulator::Now ();
       m_lastNavDuration = duration;
-      for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++) 
-        {
-          // XXX !!!!!!!
-          (*i)->NavReset (newNavStart, duration);
-        }
-      return;
+      return true;
     }
-
-  if (oldNavEnd > newNavStart) 
-    {
-      Time newNavEnd = newNavStart + duration;
-      /* The two NAVs overlap */
-      if (newNavEnd > oldNavEnd) 
-        {
-          for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++) 
-            {
-              (*i)->NavContinue (newNavStart, duration);
-            }
-        }
-    } 
-  else 
-    {
-      m_lastNavStart = newNavStart;
-      m_lastNavDuration = duration;
-      for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++) 
-        {
-          (*i)->NavStart (newNavStart, duration);
-        }
-    }
+  return false;
 }
 
 void
@@ -719,11 +756,13 @@
             ", duration=" << hdr->GetDuration () <<
             ", seq=0x"<< std::hex << m_currentHdr.GetSequenceControl () << std::dec);
   m_phy->SendPacket (packet, txMode, WIFI_PREAMBLE_LONG, 0);
-  /* Note that it is really important to notify the NAV 
-   * thing _after_ forwarding the packet to the PHY.
+  /* 
+   * We have to notify the NAV of transmitted packets because of the 802.11e
+   * requirement from section 9.9.1.4 that each EDCAF update its NAV from the
+   * transmission of any other EDCAF within the same QSTA.
    */
   Time txDuration = m_phy->CalculateTxDuration (packet.GetSize (), txMode, WIFI_PREAMBLE_LONG);
-  NotifyNav (Simulator::Now ()+txDuration, hdr);
+  Simulator::Schedule (txDuration, &MacLow::NotifyNav, this, *hdr, txMode, WIFI_PREAMBLE_LONG);
 }
 
 void
@@ -904,9 +943,9 @@
 }
 
 bool 
-MacLow::IsNavZero (Time now)
+MacLow::IsNavZero (void) const
 {
-  if (m_lastNavStart + m_lastNavDuration > now) 
+  if (m_lastNavStart + m_lastNavDuration > Simulator::Now ()) 
     {
       return false;
     }