bool
WimaxMacQueue::Enqueue (Ptr<Packet> packet, const MacHeaderType &hdrType,
                        const GenericMacHeader &hdr)
{

  if (m_queue.size () == m_maxSize)
    {

      m_traceDrop (packet);
      return false;
    }

  m_traceEnqueue (packet);
  QueueElement element (packet, hdrType, hdr, Simulator::Now ());
  m_queue.push_back (element);

  if (hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
    {
      m_nrDataPackets++;
    }
  else
    {
      m_nrRequestPackets++;
    }

  m_bytes += element.GetSize ();
  return true;
}
Ptr<Packet>
WimaxMacQueue::Dequeue (MacHeaderType::HeaderType packetType)
{
  if (!IsEmpty ())
    {
      QueueElement element = Front (packetType);
      Pop (packetType);

      if (element.m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
        {
          NS_LOG_INFO ("Enqueued Packet IS A data packet");
          NS_ASSERT_MSG (m_nrDataPackets >= 1,
                         "Can not enqueue more packets: no space left in the queue");
          m_nrDataPackets--;
        }
      else
        {
          NS_LOG_INFO ("Enqueued Packet IS A Request BW packet");
          NS_ASSERT_MSG (m_nrRequestPackets >= 1,
                         "Can not enqueue more packets: no space left in the queue");
          m_nrRequestPackets--;
        }

      Ptr<Packet> packet = element.m_packet;

      if (!element.m_fragmentation)
        {
          NS_LOG_INFO ("FRAG_DEBUG: Enqueued Packet IS NOT a fragment" << std::endl);
          /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
            has already been added to the packet) in which case Generic MAC Header will not be added to it.
            this will only happen in the case of SS as only SS sends the bandwidth request packet. */
          m_bytes -= element.GetSize ();
          if (element.m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
            {
              packet->AddHeader (element.m_hdr);
            }
          packet->AddHeader (element.m_hdrType);

          m_traceDequeue (packet);
          return packet;
        }
      else
        {
          /*
           The enqueued packet is a fragment (the latest fragment)
           We must modify type field of the m_hdr and add a fragmentation Subhdr
           */
          NS_LOG_INFO ("\t Enqueued Packet IS a fragment, add subhdr" << std::endl);

          // Create a fragment
          uint32_t fragmentOffset = element.m_fragmentOffset;
          uint32_t fragmentSize = element.m_packet->GetSize () - fragmentOffset;

          NS_LOG_INFO ("\t Create a fragment"
                       "\n\t\t fragmentOffset=" << fragmentOffset <<
                       "\n\t\t packetSize=" << element.m_packet->GetSize () <<
                       "\n\t\t fragmentSize=" << fragmentSize << std::endl);

          Ptr<Packet> fragment = packet->CreateFragment (fragmentOffset,fragmentSize);

          FragmentationSubheader fragmentSubhdr;
          NS_LOG_INFO ("\t Latest Fragment" << std::endl);
          fragmentSubhdr.SetFc (2);   // This is the latest fragment
          fragmentSubhdr.SetFsn (element.m_fragmentNumber);

          NS_LOG_INFO ("\t FragmentSize=" << fragment->GetSize () << std::endl);
          fragment->AddHeader (fragmentSubhdr);

          /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
          has already been added to the packet) in which case Generic MAC Header will not be added to it.
          this will only happen in the case of SS as only SS sends the bandwidth request packet. */
          if (element.m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
            {
              uint8_t tmpType = element.m_hdr.GetType ();
              tmpType |= 4;
              element.m_hdr.SetType (tmpType);

              uint32_t length = fragmentSize + element.m_hdr.GetSerializedSize ()
                + fragmentSubhdr.GetSerializedSize ();
              element.m_hdr.SetLen ((uint16_t)length);

              fragment->AddHeader (element.m_hdr);
            }
          fragment->AddHeader (element.m_hdrType);
          m_bytes -= fragmentSize;

          m_traceDequeue (fragment);
          return fragment;
        }
    }
  return 0;
}