add block ack headers
authorMirko Banchi <mk.banchi@gmail.com>
Wed, 03 Feb 2010 20:34:48 +0100
changeset 5948 34bd93988e2b
parent 5947 e0fcc8ffcaad
child 5949 66f939e7aaec
add block ack headers
src/devices/wifi/ctrl-headers.cc
src/devices/wifi/ctrl-headers.h
src/devices/wifi/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/ctrl-headers.cc	Wed Feb 03 20:34:48 2010 +0100
@@ -0,0 +1,681 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 MIRKO BANCHI
+ *
+ * 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: Mirko Banchi <mk.banchi@gmail.com>
+ */
+#include "ns3/fatal-error.h"
+
+#include "ctrl-headers.h"
+
+namespace ns3 {
+
+/***********************************
+ *       Block ack request
+ ***********************************/
+
+NS_OBJECT_ENSURE_REGISTERED (CtrlBAckRequestHeader);
+
+CtrlBAckRequestHeader::CtrlBAckRequestHeader ()
+  : m_barAckPolicy (false),
+    m_multiTid (false),
+    m_compressed (false)
+{}
+
+CtrlBAckRequestHeader::~CtrlBAckRequestHeader ()
+{}
+
+TypeId
+CtrlBAckRequestHeader::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CtrlBAckRequestHeader")
+    .SetParent<Header> ()
+    .AddConstructor<CtrlBAckRequestHeader> ()
+  ;
+  return tid;
+}
+
+TypeId
+CtrlBAckRequestHeader::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void
+CtrlBAckRequestHeader::Print (std::ostream &os) const
+{
+  os << "TID_INFO=" << m_tidInfo << ", StartingSeq=" << std::hex << m_startingSeq;
+}
+
+uint32_t
+CtrlBAckRequestHeader::GetSerializedSize () const
+{
+  uint32_t size = 0;
+  size += 2; //Bar control
+  if (!m_multiTid)
+    {
+      size += 2; //Starting sequence control
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          size += (2 + 2) * (m_tidInfo + 1);  //Multi-tid block ack
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+  return size;
+}
+
+void
+CtrlBAckRequestHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteHtolsbU16 (GetBarControl ());
+  if (!m_multiTid)
+    {
+      i.WriteHtolsbU16 (GetStartingSequenceControl ());
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+}
+
+uint32_t
+CtrlBAckRequestHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  SetBarControl (i.ReadLsbtohU16 ());
+  if (!m_multiTid)
+    {
+      SetStartingSequenceControl (i.ReadLsbtohU16 ());
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+  return i.GetDistanceFrom (start);
+} 
+
+uint16_t
+CtrlBAckRequestHeader::GetBarControl (void) const
+{
+  uint16_t res = 0;
+  if (m_barAckPolicy)
+    {
+      res |= 0x1;
+    }
+  if (m_multiTid)
+    {
+      res |= (0x1<<1);
+    }
+  if (m_compressed)
+    {
+      res |= (0x1<<2);
+    }
+  res |= (m_tidInfo << 12) & (0xf<<12);
+  return res;
+}
+
+void
+CtrlBAckRequestHeader::SetBarControl (uint16_t bar)
+{
+  m_barAckPolicy = ((bar & 0x01) == 1)?true:false;
+  m_multiTid = (((bar >> 1) & 0x01) == 1)?true:false;
+  m_compressed = (((bar >> 2) & 0x01) == 1)?true:false;
+  m_tidInfo = (bar >> 12) & 0x0f;
+}
+
+uint16_t
+CtrlBAckRequestHeader::GetStartingSequenceControl (void) const
+{
+  return (m_startingSeq << 4) & 0xfff0;
+}
+
+void
+CtrlBAckRequestHeader::SetStartingSequenceControl (uint16_t seqControl)
+{
+  m_startingSeq = (seqControl >> 4) & 0x0fff;
+}
+
+void
+CtrlBAckRequestHeader::SetHtImmediateAck (bool immediateAck)
+{
+  m_barAckPolicy = immediateAck;
+}
+
+void
+CtrlBAckRequestHeader::SetType (enum BlockAckType type)
+{
+  switch (type) {
+    case BASIC_BLOCK_ACK:
+      m_multiTid = false;
+      m_compressed = false;
+      break;
+    case COMPRESSED_BLOCK_ACK:
+      m_multiTid = false;
+      m_compressed = true;
+      break;
+    case MULTI_TID_BLOCK_ACK:
+      m_multiTid = true;
+      m_compressed = true;
+      break;
+    default:
+      NS_FATAL_ERROR ("Invalid variant type");
+      break;
+  }
+}
+
+void
+CtrlBAckRequestHeader::SetTidInfo (uint8_t tid)
+{
+  m_tidInfo = static_cast<uint16_t> (tid);
+}
+
+void
+CtrlBAckRequestHeader::SetStartingSequence (uint16_t seq)
+{
+  m_startingSeq = seq;
+}
+
+bool
+CtrlBAckRequestHeader::MustSendHtImmediateAck (void) const
+{
+  return m_barAckPolicy;
+}
+
+uint8_t
+CtrlBAckRequestHeader::GetTidInfo (void) const
+{
+  uint8_t tid = static_cast<uint8_t> (m_tidInfo);
+  return tid;
+}
+
+uint16_t
+CtrlBAckRequestHeader::GetStartingSequence (void) const
+{
+  return m_startingSeq;
+}
+
+bool
+CtrlBAckRequestHeader::IsBasic (void) const
+{
+  return (!m_multiTid && !m_compressed)?true:false;
+}
+
+bool
+CtrlBAckRequestHeader::IsCompressed (void) const
+{
+  return (!m_multiTid && m_compressed)?true:false;
+}
+
+bool
+CtrlBAckRequestHeader::IsMultiTid (void) const
+{
+  return (m_multiTid && m_compressed)?true:false;
+}
+
+/***********************************
+ *       Block ack response
+ ***********************************/
+
+NS_OBJECT_ENSURE_REGISTERED (CtrlBAckResponseHeader);
+
+CtrlBAckResponseHeader::CtrlBAckResponseHeader ()
+  : m_baAckPolicy (false),
+    m_multiTid (false),
+    m_compressed (false)
+{
+  memset (&bitmap, 0, sizeof (bitmap));
+}
+
+CtrlBAckResponseHeader::~CtrlBAckResponseHeader ()
+{}
+
+TypeId
+CtrlBAckResponseHeader::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CtrlBAckResponseHeader")
+    .SetParent<Header> ()
+    .AddConstructor<CtrlBAckResponseHeader> ()
+  ;
+  return tid; 
+}
+
+TypeId
+CtrlBAckResponseHeader::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void
+CtrlBAckResponseHeader::Print (std::ostream &os) const
+{
+  os << "TID_INFO=" << m_tidInfo << ", StartingSeq=" << std::hex << m_startingSeq;
+}
+
+uint32_t
+CtrlBAckResponseHeader::GetSerializedSize (void) const
+{
+  uint32_t size = 0;
+  size += 2; //Bar control
+  if (!m_multiTid)
+    {
+      if (!m_compressed)
+        {
+          size += (2 + 128); //Basic block ack
+        }
+      else
+        {
+          size += (2 + 8); //Compressed block ack
+        }
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          size += (2 + 2 + 8) * (m_tidInfo + 1); //Multi-tid block ack
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+  return size;
+}
+
+void
+CtrlBAckResponseHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteHtolsbU16 (GetBaControl ());
+  if (!m_multiTid)
+    {
+      i.WriteHtolsbU16 (GetStartingSequenceControl ());
+      i = SerializeBitmap (i);
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+}
+
+uint32_t
+CtrlBAckResponseHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  SetBaControl (i.ReadLsbtohU16 ());
+  if (!m_multiTid)
+    {
+      SetStartingSequenceControl (i.ReadLsbtohU16 ());
+      i = DeserializeBitmap (i);
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+  return i.GetDistanceFrom (start);
+}
+
+void
+CtrlBAckResponseHeader::SetHtImmediateAck (bool immediateAck)
+{
+  m_baAckPolicy = immediateAck;
+}
+
+void
+CtrlBAckResponseHeader::SetType (enum BlockAckType type)
+{
+  switch (type) {
+    case BASIC_BLOCK_ACK:
+      m_multiTid = false;
+      m_compressed = false;
+      break;
+    case COMPRESSED_BLOCK_ACK:
+      m_multiTid = false;
+      m_compressed = true;
+      break;
+    case MULTI_TID_BLOCK_ACK:
+      m_multiTid = true;
+      m_compressed = true;
+      break;
+    default:
+      NS_FATAL_ERROR ("Invalid variant type");
+      break;
+  }
+}
+
+void
+CtrlBAckResponseHeader::SetTidInfo (uint8_t tid)
+{
+  m_tidInfo = static_cast<uint16_t> (tid);
+}
+
+void
+CtrlBAckResponseHeader::SetStartingSequence (uint16_t seq)
+{
+  m_startingSeq = seq;
+}
+
+bool
+CtrlBAckResponseHeader::MustSendHtImmediateAck (void) const
+{
+  return (m_baAckPolicy)?true:false;
+}
+
+uint8_t
+CtrlBAckResponseHeader::GetTidInfo (void) const
+{
+  uint8_t tid = static_cast<uint8_t> (m_tidInfo);
+  return tid;
+}
+
+uint16_t
+CtrlBAckResponseHeader::GetStartingSequence (void) const
+{
+  return m_startingSeq;
+}
+
+bool
+CtrlBAckResponseHeader::IsBasic (void) const
+{
+  return (!m_multiTid && !m_compressed)?true:false;
+}
+
+bool
+CtrlBAckResponseHeader::IsCompressed (void) const
+{
+  return (!m_multiTid && m_compressed)?true:false;
+}
+
+bool
+CtrlBAckResponseHeader::IsMultiTid (void) const
+{
+  return (m_multiTid && m_compressed)?true:false;
+}
+
+uint16_t
+CtrlBAckResponseHeader::GetBaControl (void) const
+{
+  uint16_t res = 0;
+  if (m_baAckPolicy) 
+    {
+      res |= 0x1;
+    }
+  if (m_multiTid)
+    {
+      res |= (0x1<<1);
+    }
+  if (m_compressed)
+    {
+      res |= (0x1<<2);
+    }
+  res |= (m_tidInfo << 12) & (0xf<<12);
+  return res;
+}
+
+void
+CtrlBAckResponseHeader::SetBaControl (uint16_t ba)
+{
+  m_baAckPolicy = ((ba & 0x01) == 1)?true:false;
+  m_multiTid = (((ba >> 1) & 0x01) == 1)?true:false;
+  m_compressed = (((ba >> 2) & 0x01) == 1)?true:false;
+  m_tidInfo = (ba >> 12) & 0x0f;
+}
+
+uint16_t
+CtrlBAckResponseHeader::GetStartingSequenceControl (void) const
+{
+  return (m_startingSeq << 4) & 0xfff0;
+}
+
+void
+CtrlBAckResponseHeader::SetStartingSequenceControl (uint16_t seqControl)
+{
+  m_startingSeq = (seqControl >> 4) & 0x0fff;
+}
+
+Buffer::Iterator
+CtrlBAckResponseHeader::SerializeBitmap (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  if (!m_multiTid)
+    {
+      if (!m_compressed)
+        {
+          for (uint32_t j = 0; j < 64; j++)
+            {
+              i.WriteHtolsbU16 (bitmap.m_bitmap[j]);
+            }
+        }
+      else
+        {
+          i.WriteHtolsbU64 (bitmap.m_compressedBitmap);
+        }
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+  return i;
+}
+
+Buffer::Iterator
+CtrlBAckResponseHeader::DeserializeBitmap (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  if (!m_multiTid)
+    {
+      if (!m_compressed)
+        {
+          for (uint32_t j = 0; j < 64; j++)
+            {
+              bitmap.m_bitmap[j] = i.ReadLsbtohU16 ();
+            }
+        }
+      else
+        {
+          bitmap.m_compressedBitmap = i.ReadLsbtohU64 ();
+        }
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+  return i;
+}
+
+void
+CtrlBAckResponseHeader::SetReceivedPacket (uint16_t seq)
+{
+  if (!m_multiTid)
+    {
+      if (!m_compressed)
+        {
+          /* To set correctly basic block ack bitmap we need fragment number too.
+             So if it's not specified, we consider packet not fragmented. */
+          bitmap.m_bitmap[IndexInBitmap (seq)] |= 0x0001;
+        }
+      else
+        {
+          bitmap.m_compressedBitmap |= (0x0000000000000001 << IndexInBitmap (seq));
+        }
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+}
+
+void
+CtrlBAckResponseHeader::SetReceivedFragment (uint16_t seq, uint8_t frag)
+{
+  NS_ASSERT (frag < 16);
+  if (!m_multiTid)
+    {
+      if (!m_compressed)
+        {
+          bitmap.m_bitmap[IndexInBitmap (seq)] |= (0x0001<<frag);
+        }
+      else
+        {
+          /* We can ignore this...compressed block ack doesn't support
+             acknowledgement of single fragments */
+        }
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+}
+
+bool
+CtrlBAckResponseHeader::IsPacketReceived (uint16_t seq) const
+{
+  if (!m_multiTid)
+    {
+      if (!m_compressed)
+        {
+          /*It's impossible to say if an entire packet was correctly received. */
+          return false; 
+        }
+      else
+        {
+          uint64_t mask = 0x0000000000000001;
+          return (((bitmap.m_compressedBitmap >> IndexInBitmap (seq)) & mask) == 1)?true:false;
+        }
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+  return false;
+}
+
+bool
+CtrlBAckResponseHeader::IsFragmentReceived (uint16_t seq, uint8_t frag) const
+{
+  NS_ASSERT (frag < 16);
+  if (!m_multiTid)
+    {
+      if (!m_compressed)
+        {
+          return ((bitmap.m_bitmap[IndexInBitmap (seq)] & (0x0001<<frag)) != 0x0000)?true:false;
+        }
+      else
+        {
+          /* Although this could make no sense, if packet with sequence number
+             equal to <i>seq</i> was correctly received, also all of its fragments 
+             were correctly received. */
+          uint64_t mask = 0x0000000000000001;
+          return (((bitmap.m_compressedBitmap >> IndexInBitmap (seq)) & mask) == 1)?true:false;
+        }
+    }
+  else
+    {
+      if (m_compressed)
+        {
+          NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
+        }
+      else
+        {
+          NS_FATAL_ERROR ("Reserved configuration.");
+        }
+    }
+  return false;
+}
+
+uint8_t
+CtrlBAckResponseHeader::IndexInBitmap (uint16_t seq) const
+{
+  if (seq >= m_startingSeq)
+    {
+      return (seq - m_startingSeq);
+    }
+  else
+    {
+      return (4096 - m_startingSeq + seq);
+    }
+}
+
+}  //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/ctrl-headers.h	Wed Feb 03 20:34:48 2010 +0100
@@ -0,0 +1,159 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 MIRKO BANCHI
+ *
+ * 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: Mirko Banchi <mk.banchi@gmail.com>
+ */
+#ifndef CTRL_HEADERS_H
+#define CTRL_HEADERS_H
+
+#include "ns3/header.h"
+
+namespace ns3 {
+
+/** Headers for Block ack request and response.
+ *  802.11n standard includes three types of block ack:
+ *    - Basic block ack (unique type in 802.11e)
+ *    - Compressed block ack
+ *    - Multi-TID block ack
+ *  For now only basic block ack and compressed block ack 
+ *  are supported.
+ *  Basic block ack is also default variant.
+ */
+enum BlockAckType
+{
+  BASIC_BLOCK_ACK,
+  COMPRESSED_BLOCK_ACK,
+  MULTI_TID_BLOCK_ACK
+};
+
+class CtrlBAckRequestHeader : public Header {
+public:
+  CtrlBAckRequestHeader ();
+  ~CtrlBAckRequestHeader ();
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual void Print (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  void SetHtImmediateAck (bool immediateAck);
+  void SetType (enum BlockAckType type);
+  void SetTidInfo (uint8_t tid);
+  void SetStartingSequence (uint16_t seq);
+
+  bool MustSendHtImmediateAck (void) const;
+  uint8_t GetTidInfo (void) const;
+  uint16_t GetStartingSequence (void) const;
+  bool IsBasic (void) const;
+  bool IsCompressed (void) const;
+  bool IsMultiTid (void) const;
+
+  uint16_t GetStartingSequenceControl (void) const;
+  
+private:
+  
+  void SetStartingSequenceControl (uint16_t seqControl);
+  uint16_t GetBarControl (void) const;
+  void SetBarControl (uint16_t bar);
+  
+  /**
+   * The lsb bit of the BAR control field is used only for the
+   * HT (High Throughput) delayed block ack configuration.
+   * For now only non HT immediate block ack is implemented so this field
+   * is here only for a future implementation of HT delayed variant.
+   */
+  bool m_barAckPolicy;
+  bool m_multiTid;
+  bool m_compressed;
+  uint16_t m_tidInfo;
+  uint16_t m_startingSeq;
+};
+
+class CtrlBAckResponseHeader : public Header {
+public:
+  CtrlBAckResponseHeader ();
+  ~CtrlBAckResponseHeader ();
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual void Print (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  void SetHtImmediateAck (bool immeadiateAck);
+  void SetType (enum BlockAckType type);
+  void SetTidInfo (uint8_t tid);
+  void SetStartingSequence (uint16_t seq);
+
+  bool MustSendHtImmediateAck (void) const;
+  uint8_t GetTidInfo (void) const;
+  uint16_t GetStartingSequence (void) const;
+  bool IsBasic (void) const;
+  bool IsCompressed (void) const;
+  bool IsMultiTid (void) const;
+
+  void SetReceivedPacket (uint16_t seq);
+  void SetReceivedFragment (uint16_t seq, uint8_t frag);
+  bool IsPacketReceived (uint16_t seq) const;
+  bool IsFragmentReceived (uint16_t seq, uint8_t frag) const;
+
+  uint16_t GetStartingSequenceControl (void) const;
+  void SetStartingSequenceControl (uint16_t seqControl);
+  
+private:
+  
+  uint16_t GetBaControl (void) const;
+  void SetBaControl (uint16_t bar);
+  
+  Buffer::Iterator SerializeBitmap (Buffer::Iterator start) const;
+  Buffer::Iterator DeserializeBitmap (Buffer::Iterator start);
+
+  /**
+   * This function is used to correctly index in both bitmap
+   * and compressed bitmap, one bit or one block of 16 bits respectly.
+   * If we are using basic block ack, return value represents index of 
+   * block of 16 bits for packet having sequence number equals to <i>seq</i>.
+   * If we are using compressed block ack, return value represents bit 
+   * to set to 1 in the compressed bitmap to indicate that packet having 
+   * sequence number equals to <i>seq</i> was correctly received.
+   *
+   * for more details see 7.2.1.8 in IEEE 802.11n/D4.00
+   */
+  uint8_t IndexInBitmap (uint16_t seq) const;
+
+  /**
+   * The lsb bit of the BA control field is used only for the
+   * HT (High Throughput) delayed block ack configuration.
+   * For now only non HT immediate block ack is implemented so this field
+   * is here only for a future implementation of HT delayed variant.
+   */
+  bool m_baAckPolicy;
+  bool m_multiTid;
+  bool m_compressed;
+  uint16_t m_tidInfo;
+  uint16_t m_startingSeq;
+
+  union {
+    uint16_t m_bitmap[64];
+    uint64_t m_compressedBitmap;
+  } bitmap;
+};
+
+} //namespace ns3
+
+#endif /* CTRL_HEADERS_H */
--- a/src/devices/wifi/wscript	Wed Feb 03 18:09:25 2010 +0000
+++ b/src/devices/wifi/wscript	Wed Feb 03 20:34:48 2010 +0100
@@ -55,6 +55,7 @@
         'msdu-standard-aggregator.cc',
         'minstrel-wifi-manager.cc',
         'dcf.cc',
+        'ctrl-headers.cc',
         ]
     headers = bld.new_task_gen('ns3header')
     headers.module = 'wifi'
@@ -103,6 +104,7 @@
         'mac-low.h',
         'minstrel-wifi-manager.h',
         'dcf.h',
+        'ctrl-headers.h',
         ]
 
     if bld.env['ENABLE_GSL']: