src/wifi/model/supported-rates.cc
changeset 6852 8f1a53d3f6ca
parent 6848 1f453ad50ef3
child 7141 072fb225b714
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/supported-rates.cc	Fri Mar 04 01:26:54 2011 +0000
@@ -0,0 +1,237 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "supported-rates.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("SupportedRates");
+
+namespace ns3 {
+
+SupportedRates::SupportedRates ()
+  : extended (this), m_nRates (0)
+{}
+
+void 
+SupportedRates::AddSupportedRate (uint32_t bs)
+{
+  NS_ASSERT (m_nRates < MAX_SUPPORTED_RATES);
+  if (IsSupportedRate (bs))
+    {
+      return;
+    }
+  m_rates[m_nRates] = bs/500000;
+  m_nRates++;
+  NS_LOG_DEBUG ("add rate="<<bs<<", n rates="<<(uint32_t)m_nRates);
+}
+void 
+SupportedRates::SetBasicRate (uint32_t bs)
+{
+  uint8_t rate = bs / 500000;
+  for (uint8_t i = 0; i < m_nRates; i++)
+    {
+      if ((rate | 0x80) == m_rates[i])
+        {
+          return;
+        }
+      if (rate == m_rates[i])
+        {
+          NS_LOG_DEBUG ("set basic rate="<<bs<<", n rates="<<(uint32_t)m_nRates);
+          m_rates[i] |= 0x80;
+          return;
+        }
+    }
+  AddSupportedRate (bs);
+  SetBasicRate (bs);
+}
+bool 
+SupportedRates::IsBasicRate (uint32_t bs) const
+{
+  uint8_t rate = (bs / 500000) | 0x80;
+  for (uint8_t i = 0; i < m_nRates; i++)
+    {
+      if (rate == m_rates[i])
+        {
+          return true;
+        }
+    }
+  return false;
+}
+bool 
+SupportedRates::IsSupportedRate (uint32_t bs) const
+{
+  uint8_t rate = bs / 500000;
+  for (uint8_t i = 0; i < m_nRates; i++) 
+    {
+      if (rate == m_rates[i] ||
+          (rate|0x80) == m_rates[i]) 
+        {
+          return true;
+        }
+    }
+  return false;
+}
+uint8_t 
+SupportedRates::GetNRates (void) const
+{
+  return m_nRates;
+}
+uint32_t 
+SupportedRates::GetRate (uint8_t i) const
+{
+  return (m_rates[i]&0x7f) * 500000;
+}
+
+WifiInformationElementId
+SupportedRates::ElementId () const
+{
+  return IE_SUPPORTED_RATES;
+}
+uint8_t
+SupportedRates::GetInformationFieldSize () const
+{
+  // The Supported Rates Information Element contains only the first 8
+  // supported rates - the remainder appear in the Extended Supported
+  // Rates Information Element.
+  return m_nRates > 8 ? 8 : m_nRates;
+}
+void
+SupportedRates::SerializeInformationField (Buffer::Iterator start) const
+{
+  // The Supported Rates Information Element contains only the first 8
+  // supported rates - the remainder appear in the Extended Supported
+  // Rates Information Element.
+  start.Write (m_rates, m_nRates > 8 ? 8 : m_nRates);
+}
+uint8_t
+SupportedRates::DeserializeInformationField (Buffer::Iterator start,
+                                        uint8_t length)
+{
+  NS_ASSERT (length <= 8);
+  m_nRates = length;
+  start.Read (m_rates, m_nRates);
+  return m_nRates;
+}
+
+ExtendedSupportedRatesIE::ExtendedSupportedRatesIE ()
+{}
+
+ExtendedSupportedRatesIE::ExtendedSupportedRatesIE (SupportedRates *sr)
+{
+  m_supportedRates = sr;
+}
+
+WifiInformationElementId
+ExtendedSupportedRatesIE::ElementId () const
+{
+  return IE_EXTENDED_SUPPORTED_RATES;
+}
+
+uint8_t
+ExtendedSupportedRatesIE::GetInformationFieldSize () const
+{
+  // If there are 8 or fewer rates then we don't need an Extended
+  // Supported Rates IE and so could return zero here, but we're
+  // overriding the GetSerializedSize() method, so if this function is
+  // invoked in that case then it indicates a programming error. Hence
+  // we have an assertion on that condition.
+  NS_ASSERT(m_supportedRates->m_nRates > 8);
+
+  // The number of rates we have beyond the initial 8 is the size of
+  // the information field.
+  return (m_supportedRates->m_nRates - 8);
+}
+
+void
+ExtendedSupportedRatesIE::SerializeInformationField (Buffer::Iterator start) const
+{
+  // If there are 8 or fewer rates then there should be no Extended
+  // Supported Rates Information Element at all so being here would
+  // seemingly indicate a programming error.
+  //
+  // Our overridden version of the Serialize() method should ensure
+  // that this routine is never invoked in that case (by ensuring that
+  // WifiInformationElement::Serialize() is not invoked).
+  NS_ASSERT(m_supportedRates->m_nRates > 8);
+  start.Write (m_supportedRates->m_rates + 8, m_supportedRates->m_nRates - 8);
+}
+
+Buffer::Iterator
+ExtendedSupportedRatesIE::Serialize (Buffer::Iterator start) const
+{
+  // If there are 8 or fewer rates then we don't need an Extended
+  // Supported Rates IE, so we don't serialise anything.
+  if (m_supportedRates->m_nRates <= 8)
+    {
+      return start;
+    }
+
+  // If there are more than 8 rates then we serialise as per normal.
+  return WifiInformationElement::Serialize (start);
+}
+
+uint16_t
+ExtendedSupportedRatesIE::GetSerializedSize () const
+{
+  // If there are 8 or fewer rates then we don't need an Extended
+  // Supported Rates IE, so it's serialised length will be zero.
+  if (m_supportedRates->m_nRates <= 8)
+    {
+      return 0;
+    }
+
+  // Otherwise, the size of it will be the number of supported rates
+  // beyond 8, plus 2 for the Element ID and Length.
+  return WifiInformationElement::GetSerializedSize ();
+}
+
+uint8_t
+ExtendedSupportedRatesIE::DeserializeInformationField (Buffer::Iterator start,
+                                                       uint8_t length)
+{
+  NS_ASSERT (length > 0);
+  NS_ASSERT (m_supportedRates->m_nRates + length <= MAX_SUPPORTED_RATES);
+  start.Read (m_supportedRates->m_rates + m_supportedRates->m_nRates, length);
+  m_supportedRates->m_nRates += length;
+  return length;
+}
+
+std::ostream &operator << (std::ostream &os, const SupportedRates &rates)
+{
+  os << "[";
+  for (uint8_t i = 0; i < rates.GetNRates (); i++)
+    {
+      uint32_t rate = rates.GetRate (i);
+      if (rates.IsBasicRate (rate))
+        {
+          os << "*";
+        }
+      os << rate / 1000000 << "mbs";
+      if (i < rates.GetNRates () - 1)
+        {
+          os << " ";
+        }
+    }
+  os << "]";
+  return os;
+}
+
+} // namespace ns3