A Discrete-Event Network Simulator
API
wimax-mac-queue.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007,2008 INRIA, UDcast
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
19  * Mohamed Amine Ismail <Amine.Ismail@sophia.inria.fr>
20  * <Amine.Ismail@UDcast.com>
21  */
22 
23 #include "wimax-mac-queue.h"
24 #include "ns3/packet.h"
25 #include "ns3/trace-source-accessor.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/simulator.h"
28 #include "ns3/log.h"
29 
30 namespace ns3 {
31 
32 NS_LOG_COMPONENT_DEFINE ("WimaxMacQueue");
33 
34 NS_OBJECT_ENSURE_REGISTERED (WimaxMacQueue);
35 
37  : m_packet (Create<Packet> ()),
38  m_hdrType (MacHeaderType ()),
39  m_hdr (
40  GenericMacHeader ()),
41  m_timeStamp (Seconds (0)),
42  m_fragmentation (false),
43  m_fragmentNumber (0),
44  m_fragmentOffset (0)
45 {
46 }
47 
49  const MacHeaderType &hdrType,
50  const GenericMacHeader &hdr, Time timeStamp)
51  : m_packet (packet),
52  m_hdrType (hdrType),
53  m_hdr (hdr),
54  m_timeStamp (timeStamp),
55  m_fragmentation (false),
56  m_fragmentNumber (0),
57  m_fragmentOffset (0)
58 {
59 }
60 
61 uint32_t
63 {
64  uint32_t size = m_packet->GetSize () + m_hdrType.GetSerializedSize ();
65 
66  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
67  has already been added to the packet) in which case Generic MAC Header will not be added to it.
68  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
69  if (m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
70  {
71  size += m_hdr.GetSerializedSize ();
72  }
73 
74  return size;
75 }
76 
77 TypeId
79 {
80  static TypeId tid = TypeId ("ns3::WimaxMacQueue")
81  .SetParent<Object> ()
82  .AddAttribute (
83  "MaxSize",
84  "Maximum size",
85  UintegerValue (1024),
88  MakeUintegerChecker<uint32_t> ())
89  .AddTraceSource ("Enqueue",
90  "Enqueue trace",
92  "ns3::Packet::TracedCallback")
93  .AddTraceSource ("Dequeue",
94  "Dequeue trace",
96  "ns3::Packet::TracedCallback")
97  .AddTraceSource ("Drop",
98  "Drop trace",
100  "ns3::Packet::TracedCallback")
101  ;
102  return tid;
103 }
104 
106  : m_maxSize (0),
107  m_bytes (0),
108  m_nrDataPackets (0),
110 {
111 }
112 
114  : m_maxSize (maxSize),
115  m_bytes (0),
116  m_nrDataPackets (0),
117  m_nrRequestPackets (0)
118 {
119 }
120 
122 {
123 }
124 
125 void
126 WimaxMacQueue::SetMaxSize (uint32_t maxSize)
127 {
128  m_maxSize = maxSize;
129 }
130 
131 uint32_t
133 {
134  return m_maxSize;
135 }
136 
137 bool
139  const GenericMacHeader &hdr)
140 {
141 
142  if (m_queue.size () == m_maxSize)
143  {
144 
145  m_traceDrop (packet);
146  return false;
147  }
148 
149  m_traceEnqueue (packet);
150  QueueElement element (packet, hdrType, hdr, Simulator::Now ());
151  m_queue.push_back (element);
152 
154  {
155  m_nrDataPackets++;
156  }
157  else
158  {
160  }
161 
162  m_bytes += element.GetSize ();
163  return true;
164 }
165 
168 {
169  if (!IsEmpty ())
170  {
171  QueueElement element = Front (packetType);
172  Pop (packetType);
173 
175  {
176  NS_LOG_INFO ("Enqueued Packet IS A data packet");
178  "Can not enqueue more packets: no space left in the queue");
179  m_nrDataPackets--;
180  }
181  else
182  {
183  NS_LOG_INFO ("Enqueued Packet IS A Request BW packet");
185  "Can not enqueue more packets: no space left in the queue");
187  }
188 
189  Ptr<Packet> packet = element.m_packet;
190 
191  if (!element.m_fragmentation)
192  {
193  NS_LOG_INFO ("FRAG_DEBUG: Enqueued Packet IS NOT a fragment" << std::endl);
194  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
195  has already been added to the packet) in which case Generic MAC Header will not be added to it.
196  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
197  m_bytes -= element.GetSize ();
199  {
200  packet->AddHeader (element.m_hdr);
201  }
202  packet->AddHeader (element.m_hdrType);
203 
204  m_traceDequeue (packet);
205  return packet;
206  }
207  else
208  {
209  /*
210  The enqueued packet is a fragment (the latest fragment)
211  We must modify type field of the m_hdr and add a fragmentation Subhdr
212  */
213  NS_LOG_INFO ("\t Enqueued Packet IS a fragment, add subhdr" << std::endl);
214 
215  // Create a fragment
216  uint32_t fragmentOffset = element.m_fragmentOffset;
217  uint32_t fragmentSize = element.m_packet->GetSize () - fragmentOffset;
218 
219  NS_LOG_INFO ("\t Create a fragment"
220  "\n\t\t fragmentOffset=" << fragmentOffset <<
221  "\n\t\t packetSize=" << element.m_packet->GetSize () <<
222  "\n\t\t fragmentSize=" << fragmentSize << std::endl);
223 
224  Ptr<Packet> fragment = packet->CreateFragment (fragmentOffset,fragmentSize);
225 
226  FragmentationSubheader fragmentSubhdr;
227  NS_LOG_INFO ("\t Latest Fragment" << std::endl);
228  fragmentSubhdr.SetFc (2); // This is the latest fragment
229  fragmentSubhdr.SetFsn (element.m_fragmentNumber);
230 
231  NS_LOG_INFO ("\t FragmentSize=" << fragment->GetSize () << std::endl);
232  fragment->AddHeader (fragmentSubhdr);
233 
234  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
235  has already been added to the packet) in which case Generic MAC Header will not be added to it.
236  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
238  {
239  uint8_t tmpType = element.m_hdr.GetType ();
240  tmpType |= 4;
241  element.m_hdr.SetType (tmpType);
242 
243  uint32_t length = fragmentSize + element.m_hdr.GetSerializedSize ()
244  + fragmentSubhdr.GetSerializedSize ();
245  element.m_hdr.SetLen ((uint16_t)length);
246 
247  fragment->AddHeader (element.m_hdr);
248  }
249  fragment->AddHeader (element.m_hdrType);
250  m_bytes -= fragmentSize;
251 
252  m_traceDequeue (fragment);
253  return fragment;
254  }
255  }
256  return 0;
257 }
258 
260 WimaxMacQueue::Dequeue (MacHeaderType::HeaderType packetType, uint32_t availableByte)
261 {
262  if (!IsEmpty ())
263  {
264  NS_LOG_INFO ("FRAG_DEBUG: Dequeue function" << std::endl);
265  QueueElement element = Front (packetType);
266 
267  uint32_t headerSize = 2 + element.m_hdr.GetSerializedSize () +
268  element.m_hdrType.GetSerializedSize ();
269 
270  // Create a fragment
271  uint32_t maxFragmentSize = availableByte - headerSize;
272  uint32_t fragmentOffset = element.m_fragmentOffset; // It is the latest byte sent.
273 
274  Ptr<Packet> packet = element.m_packet->Copy ();
275  NS_LOG_INFO ("\t Create a fragment"
276  "\n\t\t availableByte=" << availableByte <<
277  "\n\t\t headerSize=" << headerSize <<
278  "\n\t\t maxFragmentSize=" << maxFragmentSize << ""
279  "\n\t\t fragmentOffset=" << fragmentOffset <<
280  "\n\t\t payloadSize=" << packet->GetSize ()
281  << std::endl);
282  Ptr<Packet> fragment = packet->CreateFragment (fragmentOffset,
283  maxFragmentSize);
284  m_bytes -= maxFragmentSize;
285 
286  FragmentationSubheader fragmentSubhdr;
287  if (!element.m_fragmentation)
288  {
289  NS_LOG_INFO ("\t First Fragment" << std::endl);
290  SetFragmentation (packetType);
291  fragmentSubhdr.SetFc (1);
292  }
293  else
294  {
295  NS_LOG_INFO ("\t Middle Fragment" << std::endl);
296  fragmentSubhdr.SetFc (3);
297  }
298  fragmentSubhdr.SetFsn (element.m_fragmentNumber);
299  NS_LOG_INFO ("\t FragmentSize=" << fragment->GetSize () << std::endl);
300  fragment->AddHeader (fragmentSubhdr);
301 
302  SetFragmentNumber (packetType);
303  SetFragmentOffset (packetType, maxFragmentSize);
304 
305  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
306  has already been added to the packet) in which case Generic MAC Header will not be added to it.
307  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
309  {
310  uint8_t tmpType = element.m_hdr.GetType ();
311  tmpType |= 4;
312  element.m_hdr.SetType (tmpType);
313 
314  uint32_t length = maxFragmentSize + element.m_hdr.GetSerializedSize ()
315  + fragmentSubhdr.GetSerializedSize ();
316  element.m_hdr.SetLen ((uint16_t)length);
317 
318  fragment->AddHeader (element.m_hdr);
319  }
320  fragment->AddHeader (element.m_hdrType);
321 
322  m_traceDequeue (fragment);
323  return fragment;
324  }
325  return 0;
326 }
327 
330 {
331  if (!IsEmpty ())
332  {
333  QueueElement element = m_queue.front ();
334  hdr = element.m_hdr;
335  Ptr<Packet> packet = element.m_packet->Copy ();
336 
337  // this function must not be used by SS as it may be then a bandwidth request header
338  packet->AddHeader (element.m_hdr);
339  return packet;
340  }
341 
342  return 0;
343 }
344 
346 WimaxMacQueue::Peek (GenericMacHeader &hdr, Time &timeStamp) const
347 {
348  if (!IsEmpty ())
349  {
350  QueueElement element = m_queue.front ();
351  hdr = element.m_hdr;
352  timeStamp = element.m_timeStamp;
353  Ptr<Packet> packet = element.m_packet->Copy ();
354 
355  // this function must not be used for by SS as it may be then a bandwidth request header
356  packet->AddHeader (element.m_hdr);
357  return packet;
358  }
359 
360  return 0;
361 }
362 
365 {
366  if (!IsEmpty ())
367  {
368  QueueElement element = Front (packetType);
369  Ptr<Packet> packet = element.m_packet->Copy ();
370 
371  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
372  has already been added to the packet) in which case Generic MAC Header will not be added to it.
373  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
375  {
376  packet->AddHeader (element.m_hdr);
377  }
378  return packet;
379  }
380 
381  return 0;
382 }
383 
386  Time &timeStamp) const
387 {
388  if (!IsEmpty ())
389  {
390  QueueElement element = Front (packetType);
391  timeStamp = element.m_timeStamp;
392  Ptr<Packet> packet = element.m_packet->Copy ();
393 
394  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
395  has already been added to the packet) in which case Generic MAC Header will not be added to it.
396  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
398  {
399  packet->AddHeader (element.m_hdr);
400  }
401  return packet;
402  }
403 
404  return 0;
405 }
406 
407 uint32_t
409 {
410  return m_queue.size ();
411 }
412 
413 uint32_t
415 {
416  return m_bytes;
417 }
418 
420 {
421  uint32_t queueSize = GetNBytes ();
422  // Add MAC Overhead
423  queueSize += GetSize () * 6;
425  if (CheckForFragmentation (packetType))
426  {
427  queueSize += 2;
428  }
429  return queueSize;
430 }
431 
434 {
435  QueueElement element;
436 
437  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
438  != m_queue.end (); ++iter)
439  {
440  element = *iter;
441  if (element.m_hdrType.GetType () == packetType)
442  {
443  break;
444  }
445  }
446 
447  return element;
448 }
449 
450 void
452 {
453  QueueElement element;
454 
455  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
456  != m_queue.end (); ++iter)
457  {
458  element = *iter;
459  if (element.m_hdrType.GetType () == packetType)
460  {
461  m_queue.erase (iter);
462  break;
463  }
464  }
465 }
466 
467 bool
469 {
470  return m_queue.empty ();
471 }
472 
473 bool
475 {
476  if (packetType == MacHeaderType::HEADER_TYPE_GENERIC)
477  {
478  return m_nrDataPackets == 0;
479  }
480  else
481  {
482  return m_nrRequestPackets == 0;
483  }
484 
485  return true;
486 }
487 
490 {
491  return m_queue;
492 }
493 
494 bool
496 {
497  QueueElement element;
498  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
499  != m_queue.end (); ++iter)
500  {
501  element = *iter;
502  if (element.m_hdrType.GetType () == packetType)
503  {
504  break;
505  }
506  }
507 
508  if (element.m_fragmentation)
509  {
510  NS_LOG_INFO ("FRAG_DEBUG: CheckForFragmentation"
511  "\n\t\t m_fragmentation is true " << std::endl);
512  }
513 
514  return element.m_fragmentation;
515 }
516 
517 uint32_t
519 {
520  QueueElement element;
521  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
522  != m_queue.end (); ++iter)
523  {
524  element = *iter;
525  if (element.m_hdrType.GetType () == packetType)
526  {
527  break;
528  }
529  }
530 
531  NS_LOG_INFO ("\t\t GetFirstPacketHdrSize ()");
532 
533  uint32_t hdrSize = 0;
535  {
536  hdrSize += element.m_hdr.GetSerializedSize ();
537  NS_LOG_INFO ("\t\t\t m_hdr.GetSerializedSize=" <<
538  element.m_hdr.GetSerializedSize ());
539  }
540 
541  hdrSize += element.m_hdrType.GetSerializedSize ();
542  NS_LOG_INFO ("\t\t\t m_hdrType.GetSerializedSize=" <<
543  element.m_hdrType.GetSerializedSize ());
544 
545  if (CheckForFragmentation (packetType))
546  {
547  NS_LOG_INFO ("\t\t\t fragSubhdrSize=2");
548  hdrSize += 2;
549  }
550 
551  NS_LOG_INFO ("\t\t hdrSize=" << hdrSize);
552 
553  return hdrSize;
554 }
555 
556 uint32_t
558 {
559  QueueElement element;
560  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
561  != m_queue.end (); ++iter)
562  {
563  element = *iter;
564  if (element.m_hdrType.GetType () == packetType)
565  {
566  break;
567  }
568  }
569 
570  NS_LOG_INFO ("\t\t GetFirstPacketPayloadSize ()");
571 
572  if (CheckForFragmentation (packetType))
573  {
574  NS_LOG_INFO ("\t\t\t fullPayloadSize=" << element.m_packet->GetSize ()
575  << "\n\t\t\t fragmentOffset=" << element.m_fragmentOffset
576  << "\n\t\t\t (fragment)payloadSize=" <<
577  element.m_packet->GetSize () - element.m_fragmentOffset);
578 
579  return element.m_packet->GetSize () - element.m_fragmentOffset;
580  }
581  NS_LOG_INFO ("\t\t payloadSize=" <<
582  element.m_packet->GetSize ());
583 
584  return element.m_packet->GetSize ();
585 }
586 
587 uint32_t
589 {
590  NS_LOG_INFO ("\t GetFirstPacketRequiredByte ()");
591 
592  uint32_t requiredByte = GetFirstPacketPayloadSize (packetType) +
593  GetFirstPacketHdrSize (packetType);
594 
595  NS_LOG_INFO ("\t Required Bytes = " << requiredByte << std::endl);
596 
597  return requiredByte;
598 }
599 
600 void
602 {
603  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
604  != m_queue.end (); ++iter)
605  {
606  if (iter->m_hdrType.GetType () == packetType)
607  {
608  iter->SetFragmentation ();
609  break;
610  }
611  }
612 }
613 
614 void
616 {
617  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
618  != m_queue.end (); ++iter)
619  {
620  if (iter->m_hdrType.GetType () == packetType)
621  {
622  iter->SetFragmentNumber ();
623  break;
624  }
625  }
626 }
627 
628 void
630 {
631  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
632  != m_queue.end (); ++iter)
633  {
634  if (iter->m_hdrType.GetType () == packetType)
635  {
636  iter->SetFragmentOffset (offset);
637  break;
638  }
639  }
640 }
641 
642 void
644 {
645  m_fragmentation = true;
646 }
647 
648 void
650 {
651  m_fragmentNumber++;
652 }
653 
654 void
656 {
657  m_fragmentOffset += offset;
658 }
659 } // namespace ns3
uint32_t GetFirstPacketHdrSize(MacHeaderType::HeaderType packetType)
void SetFragmentOffset(MacHeaderType::HeaderType packetType, uint32_t offset)
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:95
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
TracedCallback< Ptr< const Packet > > m_traceDrop
std::deque< QueueElement > PacketQueue
void SetType(uint8_t type)
TracedCallback< Ptr< const Packet > > m_traceDequeue
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t GetNBytes(void) const
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:766
Ptr< Packet > Peek(GenericMacHeader &hdr) const
Same as Dequeue but does not pop from queue.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:244
network packets
Definition: packet.h:226
void SetFragmentOffset(uint32_t offset)
this class implements the Generic mac Header as described by IEEE Standard for Local and metropolitan...
uint8_t GetType(void) const
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
uint32_t GetSerializedSize(void) const
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:228
uint32_t GetSize(void) const
uint32_t GetSerializedSize(void) const
Hold an unsigned integer type.
Definition: uinteger.h:44
TracedCallback< Ptr< const Packet > > m_traceEnqueue
uint32_t GetQueueLengthWithMACOverhead(void)
bool CheckForFragmentation(MacHeaderType::HeaderType packetType)
Fragmentation utilities.
bool Enqueue(Ptr< Packet > packet, const MacHeaderType &hdrType, const GenericMacHeader &hdr)
Enqueue a packet.
uint32_t GetFirstPacketRequiredByte(MacHeaderType::HeaderType packetType)
Represents the HT (Header Type) field of generic MAC and bandwidth request headers.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
bool IsEmpty(void) const
Every class exported by the ns3 library is enclosed in the ns3 namespace.
WimaxMacQueue::QueueElement Front(MacHeaderType::HeaderType packetType) const
void SetFragmentation(MacHeaderType::HeaderType packetType)
Ptr< T > Create(void)
Create class instances by constructors with varying numbers of arguments and return them by Ptr...
Definition: ptr.h:514
uint32_t GetSerializedSize(void) const
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:223
uint32_t GetMaxSize(void) const
this class implements the fragmentation sub-header as described by IEEE Standard for Local and metrop...
void SetMaxSize(uint32_t maxSize)
set the maximum queue size
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:84
const WimaxMacQueue::PacketQueue & GetPacketQueue(void) const
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:859
uint8_t GetType(void) const
static TypeId GetTypeId(void)
void Pop(MacHeaderType::HeaderType packetType)
void SetFragmentNumber(MacHeaderType::HeaderType packetType)
A base class which provides memory management and object aggregation.
Definition: object.h:87
Ptr< Packet > Dequeue(MacHeaderType::HeaderType packetType)
Dequeue a packet of type packetType from the queue.
uint32_t GetFirstPacketPayloadSize(MacHeaderType::HeaderType packetType)
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
a unique identifier for an interface.
Definition: type-id.h:51
TypeId SetParent(TypeId tid)
Definition: type-id.cc:631
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
void SetLen(uint16_t len)
HeaderType
this class implements the mac header type field.