change airtime metric to work with new wifi remote station manager
authorKirill Andreev <andreev@iitp.ru>
Thu, 25 Feb 2010 14:57:20 +0100
changeset 6069 c21754b56036
parent 6068 a2127017ecb4
child 6070 a971811bb21a
change airtime metric to work with new wifi remote station manager
src/devices/mesh/dot11s/airtime-metric.cc
src/devices/mesh/dot11s/airtime-metric.h
src/devices/mesh/dot11s/hwmp-protocol.cc
src/devices/mesh/mesh-wifi-interface-mac.cc
src/devices/mesh/mesh-wifi-interface-mac.h
src/devices/wifi/wifi-remote-station-manager.cc
src/devices/wifi/wifi-remote-station-manager.h
--- a/src/devices/mesh/dot11s/airtime-metric.cc	Thu Feb 25 14:17:21 2010 +0100
+++ b/src/devices/mesh/dot11s/airtime-metric.cc	Thu Feb 25 14:57:20 2010 +0100
@@ -34,15 +34,15 @@
                     "Rate should be estimated using test length.",
                      UintegerValue (1024),
                      MakeUintegerAccessor (
-                         &AirtimeLinkMetricCalculator::m_testLength),
+                         &AirtimeLinkMetricCalculator::SetTestLength),
                      MakeUintegerChecker<uint16_t> (1)
                   )
-    .AddAttribute ( "Dot11MacHeaderLength",
-                    "Length of the 802.11 header",
-                    UintegerValue (36),
+    .AddAttribute ( "Dot11MetricTid",
+                    "TID used to calculate metric (data rate)",
+                    UintegerValue (0),
                     MakeUintegerAccessor (
-                        &AirtimeLinkMetricCalculator::m_headerLength),
-                    MakeUintegerChecker<uint16_t> (0)
+                        &AirtimeLinkMetricCalculator::SetHeaderTid),
+                    MakeUintegerChecker<uint8_t> (0)
                   )
     .AddAttribute ( "Dot11sMeshHeaderLength",
                     "Length of the mesh header",
@@ -56,36 +56,26 @@
 }
 AirtimeLinkMetricCalculator::AirtimeLinkMetricCalculator () :
   m_overheadNanosec (0)
-{}
+{
+}
 void
-AirtimeLinkMetricCalculator::SetPhyStandard (WifiPhyStandard standard)
+AirtimeLinkMetricCalculator::SetHeaderTid (uint8_t tid)
 {
-  switch (standard) {
-  case WIFI_PHY_STANDARD_80211a:
-  case WIFI_PHY_STANDARD_holland:
-    // 2 * PREAMBLE + DIFS + SIFS + ACK
-    m_overheadNanosec = (2 * 16 + 34 + 16 + 44) * 1000;
-    break;
-  case WIFI_PHY_STANDARD_80211b:
-    m_overheadNanosec = (2 * 144 + 50 + 16 + 304) * 1000;
-    break;
-  case WIFI_PHY_STANDARD_80211_10Mhz: 
-    m_overheadNanosec = (2 * 32 + 58 + 32 + 88) * 1000;
-    break;
-  case WIFI_PHY_STANDARD_80211_5Mhz:
-    m_overheadNanosec = (2 * 64 + 106 + 64 + 176) * 1000;
-    break;
-  default:
-    NS_ASSERT (false);
-    break;
-  }
+  m_testHeader.SetDsFrom ();
+  m_testHeader.SetDsTo ();
+  m_testHeader.SetQosTid (tid);
+}
+void
+AirtimeLinkMetricCalculator::SetTestLength (uint16_t testLength)
+{
+  m_testFrame = Create<Packet> (testLength + 6 /*Mesh header*/ + 36/*802.11 header*/);
 }
 uint32_t
 AirtimeLinkMetricCalculator::CalculateMetric (Mac48Address peerAddress, Ptr<MeshWifiInterfaceMac> mac)
 {
   /* Airtime link metric is defined in 11B.10 of 802.11s Draft D3.0 as:
    *
-   * airtime = (O + Bt/r)* (1 + average retry counter), where
+   * airtime = (O + Bt/r) /  (1 - frame error rate), where
    * o  -- the PHY dependent channel access which includes frame headers, training sequences,
    *       access protocol frames, etc.
    * bt -- the test packet length in bits (8192 by default),
@@ -93,22 +83,23 @@
    *
    * Final result is expressed in units of 0.01 Time Unit = 10.24 us (as required by 802.11s draft)
    */
-
-  //const double sec2ns = 1e9; // seconds -> nanoseconds conversion factor
-  //const double ns2tu = 10240; // nanoseconds -> 0.01 TU conversion factor
-
-  //  WifiRemoteStation * station = mac->GetStationManager ()->Lookup (peerAddress);
-  //NS_ASSERT (station != 0);
-  //NS_ASSERT (m_overheadNanosec != 0);
-  //Ptr<Packet> test_frame = Create<Packet> (m_testLength + m_meshHeaderLength);
-  //uint32_t rate = station->GetDataMode (peerAddress, test_frame, m_testLength + m_meshHeaderLength).GetDataRate ();
-  //uint32_t payload_nanosec = (uint32_t) ((double) ((m_testLength + m_meshHeaderLength) * 8 /*octets -> bits*/) * sec2ns / ((double) rate));
-  //uint32_t header_nanosec = (uint32_t) ((double) (m_headerLength * 8 /*octets -> bits*/* sec2ns)
-  //                                      / ((double) mac->GetStationManager () -> GetBasicMode (0).GetDataRate ()));
-  //uint32_t metric = (uint32_t) (((double) (payload_nanosec + header_nanosec + m_overheadNanosec)) / ns2tu
-  //                       * (station->GetAvgSlrc () + 1));
-  //return metric;
-  return 0;
+  NS_ASSERT (!peerAddress.IsGroup ());
+  //obtain current rate:
+  WifiMode mode = mac->GetStationManager ()->GetDataMode (peerAddress, &m_testHeader, m_testFrame, m_testFrame->GetSize ());
+  //obtain frame error rate:
+  double failAvg = mac->GetStationManager ()->Lookup (peerAddress, &m_testHeader)->m_state->m_info.GetFrameErrorRate ();
+  NS_ASSERT (failAvg < 1.0);
+  //calculate metric
+  uint32_t metric = (uint32_t)((double)(/*Overhead + payload*/
+      mac->GetPifs () + mac->GetSlot () + mac->GetEifsNoDifs () + //DIFS + SIFS + AckTxTime = PIFS + SLOT + EifsNoDifs
+      mac->GetWifiPhy () ->CalculateTxDuration (m_testFrame->GetSize (), mode, WIFI_PREAMBLE_LONG)
+      ).GetMicroSeconds () / (10.24 * (1.0 - failAvg)));
+  std::cout << "pure overhead is " << (uint32_t)((double)(/*Overhead + payload*/
+      mac->GetPifs () + mac->GetSlot () + mac->GetEifsNoDifs ()
+      ).GetMicroSeconds ()/10.24) << "\n";
+  std::cout << "mode is:" << mode.GetDataRate () << "\n";
+  std::cout << "Metric is :" << metric << "\n";
+  return metric;
 }
 } //namespace dot11s
 } //namespace ns3
--- a/src/devices/mesh/dot11s/airtime-metric.h	Thu Feb 25 14:17:21 2010 +0100
+++ b/src/devices/mesh/dot11s/airtime-metric.h	Thu Feb 25 14:57:20 2010 +0100
@@ -44,8 +44,9 @@
 public:
   AirtimeLinkMetricCalculator ();
   static TypeId GetTypeId ();
-  void SetPhyStandard (WifiPhyStandard standard);
   uint32_t CalculateMetric (Mac48Address peerAddress, Ptr<MeshWifiInterfaceMac> mac);
+  void SetTestLength (uint16_t testLength);
+  void SetHeaderTid (uint8_t tid);
 private:
   /// Overhead expressed in nanoseconds:DIFS + SIFS + 2 * PREAMBLE + ACK
   uint32_t m_overheadNanosec;
@@ -55,6 +56,8 @@
   uint16_t m_headerLength;
   /// meshHeader length (minimum 6 octets)
   uint16_t m_meshHeaderLength;
+  Ptr<Packet> m_testFrame;
+  WifiMacHeader m_testHeader;
 };
 } //namespace dot11s
 } //namespace ns3
--- a/src/devices/mesh/dot11s/hwmp-protocol.cc	Thu Feb 25 14:17:21 2010 +0100
+++ b/src/devices/mesh/dot11s/hwmp-protocol.cc	Thu Feb 25 14:57:20 2010 +0100
@@ -710,7 +710,6 @@
       //Installing airtime link metric:
       Ptr<AirtimeLinkMetricCalculator> metric = CreateObject <AirtimeLinkMetricCalculator> ();
       mac->SetLinkMetricCallback (MakeCallback (&AirtimeLinkMetricCalculator::CalculateMetric, metric));
-      metric->SetPhyStandard (mac->GetPhyStandard ());
     }
   mp->SetRoutingProtocol (this);
   // Mesh point aggregates all installed protocols
--- a/src/devices/mesh/mesh-wifi-interface-mac.cc	Thu Feb 25 14:17:21 2010 +0100
+++ b/src/devices/mesh/mesh-wifi-interface-mac.cc	Thu Feb 25 14:57:20 2010 +0100
@@ -196,6 +196,11 @@
   m_dcfManager->SetupPhyListener (phy);
   m_low->SetPhy (phy);
 }
+Ptr<WifiPhy>
+MeshWifiInterfaceMac::GetWifiPhy () const
+{
+  return m_phy;
+}
 void
 MeshWifiInterfaceMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager)
 {
--- a/src/devices/mesh/mesh-wifi-interface-mac.h	Thu Feb 25 14:17:21 2010 +0100
+++ b/src/devices/mesh/mesh-wifi-interface-mac.h	Thu Feb 25 14:57:20 2010 +0100
@@ -91,7 +91,8 @@
   virtual void  SetAddress (Mac48Address address);
   virtual void  SetSsid (Ssid ssid);
   //\}
-
+  ///Needed to obtain phy to calculate TX-duration
+  Ptr<WifiPhy> GetWifiPhy () const;
   ///\name Each mesh point interfaces must know the mesh point address
   //\{
   void SetMeshPointAddress (Mac48Address);
--- a/src/devices/wifi/wifi-remote-station-manager.cc	Thu Feb 25 14:17:21 2010 +0100
+++ b/src/devices/wifi/wifi-remote-station-manager.cc	Thu Feb 25 14:57:20 2010 +0100
@@ -19,6 +19,7 @@
  */
 
 #include "wifi-remote-station-manager.h"
+#include "ns3/simulator.h"
 #include "ns3/assert.h"
 #include "ns3/log.h"
 #include "ns3/tag.h"
@@ -177,10 +178,6 @@
     .AddTraceSource ("MacTxFinalDataFailed", 
                      "The transmission of a data packet has exceeded the maximum number of attempts",
                      MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalDataFailed))
-    .AddAttribute("AvgSlrcCoefficient", "The weigh of the slrc count in the slrc avg calculation",
-                  DoubleValue (0.9),
-                  MakeDoubleAccessor (&WifiRemoteStationManager::m_avgSlrcCoefficient),
-                  MakeDoubleChecker<double> ())
     ;
   return tid;
 }
@@ -397,6 +394,7 @@
 {
   NS_ASSERT (!address.IsGroup ());
   WifiRemoteStation *station = Lookup (address, header);
+  station->m_state->m_info.NotifyTxSuccess (station->m_ssrc);
   station->m_ssrc = 0;
   DoReportRtsOk (station, ctsSnr, ctsMode, rtsSnr);
 }
@@ -406,7 +404,7 @@
 {
   NS_ASSERT (!address.IsGroup ());
   WifiRemoteStation *station = Lookup (address, header);
-  station->m_avgSlrc = station->m_avgSlrc * m_avgSlrcCoefficient + (double) station->m_slrc * (1 - m_avgSlrcCoefficient);
+  station->m_state->m_info.NotifyTxSuccess (station->m_slrc);
   station->m_slrc = 0;
   DoReportDataOk (station, ackSnr, ackMode, dataSnr);
 }
@@ -415,6 +413,7 @@
 {
   NS_ASSERT (!address.IsGroup ());
   WifiRemoteStation *station = Lookup (address, header);
+  station->m_state->m_info.NotifyTxFailed ();
   station->m_ssrc = 0;
   m_macTxFinalRtsFailed (address);
   DoReportFinalRtsFailed (station);
@@ -424,6 +423,7 @@
 {
   NS_ASSERT (!address.IsGroup ());
   WifiRemoteStation *station = Lookup (address, header);
+  station->m_state->m_info.NotifyTxFailed ();
   station->m_slrc = 0;
   m_macTxFinalDataFailed (address);
   DoReportFinalDataFailed (station);
@@ -576,14 +576,6 @@
   NS_ASSERT (!address.IsGroup ());
   return GetControlAnswerMode (address, dataMode);
 }
-double
-WifiRemoteStationManager::GetAvgSlrc (Mac48Address address) const
-{
-  NS_FATAL_ERROR ("XXX");
-  NS_ASSERT (!address.IsGroup ());
-  WifiRemoteStation *station = Lookup (address, (uint8_t)0);
-  return station->m_avgSlrc;
-}
 
 WifiRemoteStationState *
 WifiRemoteStationManager::LookupState (Mac48Address address) const
@@ -633,7 +625,6 @@
   station->m_state = state;
   station->m_ssrc = 0;
   station->m_slrc = 0;
-  station->m_avgSlrc = 0;
   // XXX
   const_cast<WifiRemoteStationManager *> (this)->m_stations.push_back (station);
   return station;
@@ -741,5 +732,40 @@
   return station->m_state->m_modes.size ();
 }
 
+//WifiRemoteStationInfo constructor
+WifiRemoteStationInfo::WifiRemoteStationInfo () :
+  m_memoryTime (Seconds (1.0)),
+  m_lastUpdate (Seconds (0.0)),
+  m_failAvg (0.0)
+{}
 
+double
+WifiRemoteStationInfo::CalculateAveragingCoeffitient ()
+{
+  double retval = exp((double)
+      (m_lastUpdate.GetMicroSeconds () - Simulator::Now ().GetMicroSeconds()) / (double)m_memoryTime.GetMicroSeconds ()
+      );
+  m_lastUpdate = Simulator::Now ();
+  return retval;
+}
+
+void
+WifiRemoteStationInfo::NotifyTxSuccess (uint32_t retryCounter)
+{
+  double coefficient = CalculateAveragingCoeffitient ();
+  m_failAvg = (double)retryCounter / (1 + (double) retryCounter) * (1.0 - coefficient) + coefficient * m_failAvg;
+}
+
+void
+WifiRemoteStationInfo::NotifyTxFailed ()
+{
+  double coefficient = CalculateAveragingCoeffitient ();
+  m_failAvg = (1.0 - coefficient) + coefficient * m_failAvg;
+}
+
+double
+WifiRemoteStationInfo::GetFrameErrorRate () const
+{
+  return m_failAvg;
+}
 } // namespace ns3
--- a/src/devices/wifi/wifi-remote-station-manager.h	Thu Feb 25 14:17:21 2010 +0100
+++ b/src/devices/wifi/wifi-remote-station-manager.h	Thu Feb 25 14:57:20 2010 +0100
@@ -26,6 +26,7 @@
 #include "ns3/traced-callback.h"
 #include "ns3/packet.h"
 #include "ns3/object.h"
+#include "ns3/nstime.h"
 #include "wifi-mode.h"
 
 namespace ns3 {
@@ -233,11 +234,8 @@
    *          handshake.
    */
   WifiMode GetAckMode (Mac48Address address, WifiMode dataMode);
-  /**
-   * \return exponentially weighted average SLRC, this is used by Airtime link metric of 802.11s
-   */
-  double GetAvgSlrc (Mac48Address address) const;
-
+  /// Find a remote station by its remote address and TID taken from MAC header
+  WifiRemoteStation *Lookup (Mac48Address address, const WifiMacHeader *header) const;
 protected:
   virtual void DoDispose (void);
   // for convenience
@@ -336,7 +334,6 @@
                              double rxSnr, WifiMode txMode) = 0;
 
   WifiRemoteStationState *LookupState (Mac48Address address) const;
-  WifiRemoteStation *Lookup (Mac48Address address, const WifiMacHeader *header) const;
   WifiRemoteStation *Lookup (Mac48Address address, uint8_t tid) const;
   WifiMode GetControlAnswerMode (Mac48Address address, WifiMode reqMode);
   uint32_t GetNFragments (Ptr<const Packet> packet);
@@ -375,6 +372,41 @@
   TracedCallback<Mac48Address> m_macTxFinalDataFailed;
 
 };
+/**
+ * \brief Tid independent remote station statistics
+ *
+ * Structure is similar to struct sta_info in Linux kernel (see
+ * net/mac80211/sta_info.h)
+ */
+class WifiRemoteStationInfo
+{
+public:
+  WifiRemoteStationInfo ();
+  /**
+   * \brief Updates average frame error rate when data or RTS
+   * was transmitted successfully.
+   * \param retryCounter is slrc or ssrc value at the moment of
+   * success transmission.
+   */
+  void NotifyTxSuccess (uint32_t retryCounter);
+  /// Updates average frame error rate when final data or RTS has failed.
+  void NotifyTxFailed ();
+  /// Returns frame error rate (probability that frame is corrupted due to transmission error).
+  double GetFrameErrorRate () const;
+private:
+  /**
+   * \brief Calculate averaging coefficient for frame error rate. Depends on time of the last update.
+   * \attention Calling this method twice gives different results,
+   * because it resets time of last update.
+   */
+  double CalculateAveragingCoeffitient ();
+  ///averaging coefficient depends on the memory time
+  Time m_memoryTime;
+  ///when last update has occured
+  Time m_lastUpdate;
+  /// moving percentage of failed frames
+  double m_failAvg;
+};
 
 struct WifiRemoteStationState
 {
@@ -388,6 +420,7 @@
     } m_state;
   SupportedModes m_modes;
   Mac48Address m_address;
+  WifiRemoteStationInfo m_info;
 };
 
 /**
@@ -403,7 +436,6 @@
   struct WifiRemoteStationState *m_state;
   uint32_t m_ssrc;
   uint32_t m_slrc;
-  double m_avgSlrc;
   uint8_t m_tid;
 };