src/devices/wifi/wifi-remote-station-manager.cc
changeset 6372 0fafd9716f44
parent 6360 d8975477ff6a
child 6473 86a4a149eb0f
--- a/src/devices/wifi/wifi-remote-station-manager.cc	Wed Jun 23 06:43:21 2010 +0200
+++ b/src/devices/wifi/wifi-remote-station-manager.cc	Wed Jun 23 08:47:29 2010 +0100
@@ -205,6 +205,12 @@
 void
 WifiRemoteStationManager::SetupPhy (Ptr<WifiPhy> phy)
 {
+  // We need to track our PHY because it is the object that knows the
+  // full set of transmit rates that are supported. We need to know
+  // this in order to find the relevant mandatory rates when chosing a
+  // transmit rate for automatic control responses like
+  // acknowledgements.
+  m_wifiPhy = phy;
   m_defaultTxMode = phy->GetMode (0);
   Reset ();
 }
@@ -255,7 +261,7 @@
 {
   NS_ASSERT (!address.IsGroup ());
   WifiRemoteStationState *state = LookupState (address);
-  state->m_modes.clear ();
+  state->m_operationalRateSet.clear ();
   AddSupportedMode (address, GetDefaultMode ());
 }
 void
@@ -263,7 +269,7 @@
 {
   NS_ASSERT (!address.IsGroup ());
   WifiRemoteStationState *state = LookupState (address);
-  for (WifiRemoteStationState::SupportedModes::const_iterator i = state->m_modes.begin (); i != state->m_modes.end (); i++)
+  for (WifiModeListIterator i = state->m_operationalRateSet.begin (); i != state->m_operationalRateSet.end (); i++)
     {
       if ((*i) == mode)
         {
@@ -271,7 +277,7 @@
           return;
         }
     }
-  state->m_modes.push_back (mode);
+  state->m_operationalRateSet.push_back (mode);
 }
 bool
 WifiRemoteStationManager::IsBrandNew (Mac48Address address) const
@@ -533,39 +539,105 @@
 WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode reqMode)
 {
   /**
-   * see ieee 802.11e, section 9.6:
-   * 
-   * To allow the transmitting STA to calculate the contents of 
-   * the Duration/ID field, a STA responding to a received frame 
-   * shall transmit its Control Response frame (either CTS or ACK) 
-   * frames, other than the Block-Ack control frame, at the highest 
-   * rate in the BSSBasicRateSet parameter that is less than or equal 
-   * to the rate of the immediately previous frame in the frame 
-   * exchange sequence (as defined in 9.79.12) and that is of the
-   * same modulation type as the received frame. If no rate in the 
-   * basic rate set meets these conditions, then the control frame 
-   * sent in response to a received frame shall be transmitted at 
-   * the highest mandatory rate of the PHY that is less than or equal 
-   * to the rate of the received frame, and that is of the same 
-   * modulation type as the received frame. In addition, the Control 
-   * Response frame shall be sent using the same PHY options as the
-   * received frame, unless they conflict with the requirement to use 
-   * the BSSBasicRateSet parameter.
+   * The standard has relatively unambiguous rules for selecting a
+   * control response rate (the below is quoted from IEEE 802.11-2007,
+   * Section 9.6):
+   *
+   *   To allow the transmitting STA to calculate the contents of the
+   *   Duration/ID field, a STA responding to a received frame shall
+   *   transmit its Control Response frame (either CTS or ACK), other
+   *   than the BlockAck control frame, at the highest rate in the
+   *   BSSBasicRateSet parameter that is less than or equal to the
+   *   rate of the immediately previous frame in the frame exchange
+   *   sequence (as defined in 9.12) and that is of the same
+   *   modulation class (see 9.6.1) as the received frame...
    */
   WifiMode mode = GetDefaultMode ();
+  bool found = false;
 
   // First, search the BSS Basic Rate set
-  for (WifiRemoteStationManager::BasicModesIterator i = BeginBasicModes (); i != EndBasicModes (); i++)
+  for (WifiModeListIterator i = m_bssBasicRateSet.begin ();
+       i != m_bssBasicRateSet.end (); i++)
     {
-      if (i->GetPhyRate () > mode.GetPhyRate () &&
-          i->GetPhyRate () <= reqMode.GetPhyRate () &&
-          i->GetModulationClass () == reqMode.GetModulationClass ())
+      if ((!found || i->GetPhyRate () > mode.GetPhyRate ())
+          && i->GetPhyRate () <= reqMode.GetPhyRate ()
+          && i->GetModulationClass () == reqMode.GetModulationClass ())
         {
           mode = *i;
+          // We've found a potentially-suitable transmit rate, but we
+          // need to continue and consider all the basic rates before
+          // we can be sure we've got the right one.
+          found = true;
         }
     }
-  // no need to search Mandatory rate set because it is included
-  // within the Basic rate set.
+
+  // If we found a suitable rate in the BSSBasicRateSet, then we are
+  // done and can return that mode.
+  if (found)
+    {
+      return mode;
+    }
+
+  /**
+   * If no suitable basic rate was found, we search the mandatory
+   * rates. The standard (IEEE 802.11-2007, Section 9.6) says:
+   *
+   *   ...If no rate contained in the BSSBasicRateSet parameter meets
+   *   these conditions, then the control frame sent in response to a
+   *   received frame shall be transmitted at the highest mandatory
+   *   rate of the PHY that is less than or equal to the rate of the
+   *   received frame, and that is of the same modulation class as the
+   *   received frame. In addition, the Control Response frame shall
+   *   be sent using the same PHY options as the received frame,
+   *   unless they conflict with the requirement to use the
+   *   BSSBasicRateSet parameter.
+   *
+   * TODO: Note that we're ignoring the last sentence for now, because
+   * there is not yet any manipulation here of PHY options.
+   */
+  for (uint32_t idx = 0; idx < m_wifiPhy->GetNModes (); idx++)
+    {
+      WifiMode thismode = m_wifiPhy->GetMode (idx);
+
+      /* If the rate:
+       *
+       *  - is a mandatory rate for the PHY, and
+       *  - is equal to or faster than our current best choice, and
+       *  - is less than or equal to the rate of the received frame, and
+       *  - is of the same modulation class as the received frame
+       *
+       * ...then it's our best choice so far.
+       */
+      if (thismode.IsMandatory ()
+          && (!found || thismode.GetPhyRate () > mode.GetPhyRate ())
+          && thismode.GetPhyRate () <= reqMode.GetPhyRate ()
+          && thismode.GetModulationClass () == reqMode.GetModulationClass ())
+        {
+          mode = thismode;
+          // As above; we've found a potentially-suitable transmit
+          // rate, but we need to continue and consider all the
+          // mandatory rates before we can be sure we've got the right
+          // one.
+          found = true;
+        }
+    }
+
+  /**
+   * If we still haven't found a suitable rate for the response then
+   * someone has messed up the simulation config. This probably means
+   * that the WifiPhyStandard is not set correctly, or that a rate that
+   * is not supported by the PHY has been explicitly requested in a
+   * WifiRemoteStationManager (or descendant) configuration.
+   *
+   * Either way, it is serious - we can either disobey the standard or
+   * fail, and I have chosen to do the latter...
+   */
+  if (!found)
+    {
+      NS_FATAL_ERROR ("Can't find response rate for " << reqMode
+                      << ". Check standard and selected rates match.");
+    }
+
   return mode;
 }
 
@@ -602,7 +674,7 @@
   WifiRemoteStationState *state = new WifiRemoteStationState ();
   state->m_state = WifiRemoteStationState::BRAND_NEW;
   state->m_address = address;
-  state->m_modes.push_back (GetDefaultMode ());
+  state->m_operationalRateSet.push_back (GetDefaultMode ());
   const_cast<WifiRemoteStationManager *> (this)->m_states.push_back (state);
   return state;
 }
@@ -657,8 +729,8 @@
       delete (*i);
     }
   m_stations.clear ();
-  m_basicModes.clear ();
-  m_basicModes.push_back (m_defaultTxMode);
+  m_bssBasicRateSet.clear ();
+  m_bssBasicRateSet.push_back (m_defaultTxMode);
   NS_ASSERT (m_defaultTxMode.IsMandatory ());
 }
 void 
@@ -671,30 +743,19 @@
           return;
         }
     }
-  m_basicModes.push_back (mode);
+  m_bssBasicRateSet.push_back (mode);
 }
 uint32_t 
 WifiRemoteStationManager::GetNBasicModes (void) const
 {
-  return m_basicModes.size ();
+  return m_bssBasicRateSet.size ();
 }
 WifiMode 
 WifiRemoteStationManager::GetBasicMode (uint32_t i) const
 {
-  NS_ASSERT (i < m_basicModes.size ());
-  return m_basicModes[i];
+  NS_ASSERT (i < m_bssBasicRateSet.size ());
+  return m_bssBasicRateSet[i];
 }
-WifiRemoteStationManager::BasicModesIterator 
-WifiRemoteStationManager::BeginBasicModes (void) const
-{
-  return m_basicModes.begin ();
-}
-WifiRemoteStationManager::BasicModesIterator 
-WifiRemoteStationManager::EndBasicModes (void) const
-{
-  return m_basicModes.end ();
-}
-
 WifiMode
 WifiRemoteStationManager::GetNonUnicastMode (void) const
 {
@@ -737,12 +798,12 @@
 WifiRemoteStationManager::GetSupported (const WifiRemoteStation *station, uint32_t i) const
 {
   NS_ASSERT (i < GetNSupported (station));
-  return station->m_state->m_modes[i];
+  return station->m_state->m_operationalRateSet[i];
 }
 uint32_t 
 WifiRemoteStationManager::GetNSupported (const WifiRemoteStation *station) const
 {
-  return station->m_state->m_modes.size ();
+  return station->m_state->m_operationalRateSet.size ();
 }
 
 //WifiRemoteStationInfo constructor