A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
wimax-mac-queue.cc
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 NS_LOG_COMPONENT_DEFINE ("WimaxMacQueue");
31 
32 namespace ns3 {
33 
34 NS_OBJECT_ENSURE_REGISTERED (WimaxMacQueue);
35 
36 WimaxMacQueue::QueueElement::QueueElement (void)
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 
48 WimaxMacQueue::QueueElement::QueueElement (Ptr<Packet> packet,
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
62 WimaxMacQueue::QueueElement::GetSize (void) const
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
78 WimaxMacQueue::GetTypeId (void)
79 {
80  static TypeId tid = TypeId ("ns3::WimaxMacQueue")
81  .SetParent<Object> ()
82  .AddAttribute (
83  "MaxSize",
84  "Maximum size",
85  UintegerValue (1024),
86  MakeUintegerAccessor (&WimaxMacQueue::GetMaxSize,
88  MakeUintegerChecker<uint32_t> ())
89  .AddTraceSource ("Enqueue",
90  "Enqueue trace",
91  MakeTraceSourceAccessor (&WimaxMacQueue::m_traceEnqueue))
92  .AddTraceSource ("Dequeue",
93  "Dequeue trace",
94  MakeTraceSourceAccessor (&WimaxMacQueue::m_traceDequeue))
95  .AddTraceSource ("Drop",
96  "Drop trace",
97  MakeTraceSourceAccessor (&WimaxMacQueue::m_traceDrop))
98  ;
99  return tid;
100 }
101 
102 WimaxMacQueue::WimaxMacQueue (void)
103  : m_maxSize (0),
104  m_bytes (0),
105  m_nrDataPackets (0),
106  m_nrRequestPackets (0)
107 {
108 }
109 
110 WimaxMacQueue::WimaxMacQueue (uint32_t maxSize)
111  : m_maxSize (maxSize),
112  m_bytes (0),
113  m_nrDataPackets (0),
114  m_nrRequestPackets (0)
115 {
116 }
117 
118 WimaxMacQueue::~WimaxMacQueue (void)
119 {
120 }
121 
122 void
123 WimaxMacQueue::SetMaxSize (uint32_t maxSize)
124 {
125  m_maxSize = maxSize;
126 }
127 
128 uint32_t
130 {
131  return m_maxSize;
132 }
133 
134 bool
136  const GenericMacHeader &hdr)
137 {
138 
139  if (m_queue.size () == m_maxSize)
140  {
141 
142  m_traceDrop (packet);
143  return false;
144  }
145 
146  m_traceEnqueue (packet);
147  QueueElement element (packet, hdrType, hdr, Simulator::Now ());
148  m_queue.push_back (element);
149 
150  if (hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
151  {
152  m_nrDataPackets++;
153  }
154  else
155  {
156  m_nrRequestPackets++;
157  }
158 
159  m_bytes += element.GetSize ();
160  return true;
161 }
162 
165 {
166  if (!IsEmpty ())
167  {
168  QueueElement element = Front (packetType);
169  Pop (packetType);
170 
171  if (element.m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
172  {
173  NS_LOG_INFO ("Enqueued Packet IS A data packet");
174  NS_ASSERT_MSG (m_nrDataPackets >= 1,
175  "Can not enqueue more packets: no space left in the queue");
176  m_nrDataPackets--;
177  }
178  else
179  {
180  NS_LOG_INFO ("Enqueued Packet IS A Request BW packet");
181  NS_ASSERT_MSG (m_nrRequestPackets >= 1,
182  "Can not enqueue more packets: no space left in the queue");
183  m_nrRequestPackets--;
184  }
185 
186  Ptr<Packet> packet = element.m_packet;
187 
188  if (!element.m_fragmentation)
189  {
190  NS_LOG_INFO ("FRAG_DEBUG: Enqueued Packet IS NOT a fragment" << std::endl);
191  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
192  has already been added to the packet) in which case Generic MAC Header will not be added to it.
193  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
194  m_bytes -= element.GetSize ();
195  if (element.m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
196  {
197  packet->AddHeader (element.m_hdr);
198  }
199  packet->AddHeader (element.m_hdrType);
200 
201  m_traceDequeue (packet);
202  return packet;
203  }
204  else
205  {
206  /*
207  The enqueued packet is a fragment (the latest fragment)
208  We must modify type field of the m_hdr and add a fragmentation Subhdr
209  */
210  NS_LOG_INFO ("\t Enqueued Packet IS a fragment, add subhdr" << std::endl);
211 
212  // Create a fragment
213  uint32_t fragmentOffset = element.m_fragmentOffset;
214  uint32_t fragmentSize = element.m_packet->GetSize () - fragmentOffset;
215 
216  NS_LOG_INFO ("\t Create a fragment"
217  "\n\t\t fragmentOffset=" << fragmentOffset <<
218  "\n\t\t packetSize=" << element.m_packet->GetSize () <<
219  "\n\t\t fragmentSize=" << fragmentSize << std::endl);
220 
221  Ptr<Packet> fragment = packet->CreateFragment (fragmentOffset,fragmentSize);
222 
223  FragmentationSubheader fragmentSubhdr;
224  NS_LOG_INFO ("\t Latest Fragment" << std::endl);
225  fragmentSubhdr.SetFc (2); // This is the latest fragment
226  fragmentSubhdr.SetFsn (element.m_fragmentNumber);
227 
228  NS_LOG_INFO ("\t FragmentSize=" << fragment->GetSize () << std::endl);
229  fragment->AddHeader (fragmentSubhdr);
230 
231  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
232  has already been added to the packet) in which case Generic MAC Header will not be added to it.
233  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
234  if (element.m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
235  {
236  uint8_t tmpType = element.m_hdr.GetType ();
237  tmpType |= 4;
238  element.m_hdr.SetType (tmpType);
239 
240  uint32_t length = fragmentSize + element.m_hdr.GetSerializedSize ()
241  + fragmentSubhdr.GetSerializedSize ();
242  element.m_hdr.SetLen ((uint16_t)length);
243 
244  fragment->AddHeader (element.m_hdr);
245  }
246  fragment->AddHeader (element.m_hdrType);
247  m_bytes -= fragmentSize;
248 
249  m_traceDequeue (fragment);
250  return fragment;
251  }
252  }
253  return 0;
254 }
255 
257 WimaxMacQueue::Dequeue (MacHeaderType::HeaderType packetType, uint32_t availableByte)
258 {
259  if (!IsEmpty ())
260  {
261  NS_LOG_INFO ("FRAG_DEBUG: Dequeue function" << std::endl);
262  QueueElement element = Front (packetType);
263 
264  uint32_t headerSize = 2 + element.m_hdr.GetSerializedSize () +
265  element.m_hdrType.GetSerializedSize ();
266 
267  // Create a fragment
268  uint32_t maxFragmentSize = availableByte - headerSize;
269  uint32_t fragmentOffset = element.m_fragmentOffset; // It is the latest byte sent.
270 
271  Ptr<Packet> packet = element.m_packet->Copy ();
272  NS_LOG_INFO ("\t Create a fragment"
273  "\n\t\t availableByte=" << availableByte <<
274  "\n\t\t headerSize=" << headerSize <<
275  "\n\t\t maxFragmentSize=" << maxFragmentSize << ""
276  "\n\t\t fragmentOffset=" << fragmentOffset <<
277  "\n\t\t payloadSize=" << packet->GetSize ()
278  << std::endl);
279  Ptr<Packet> fragment = packet->CreateFragment (fragmentOffset,
280  maxFragmentSize);
281  m_bytes -= maxFragmentSize;
282 
283  FragmentationSubheader fragmentSubhdr;
284  if (!element.m_fragmentation)
285  {
286  NS_LOG_INFO ("\t First Fragment" << std::endl);
287  SetFragmentation (packetType);
288  fragmentSubhdr.SetFc (1);
289  }
290  else
291  {
292  NS_LOG_INFO ("\t Middle Fragment" << std::endl);
293  fragmentSubhdr.SetFc (3);
294  }
295  fragmentSubhdr.SetFsn (element.m_fragmentNumber);
296  NS_LOG_INFO ("\t FragmentSize=" << fragment->GetSize () << std::endl);
297  fragment->AddHeader (fragmentSubhdr);
298 
299  SetFragmentNumber (packetType);
300  SetFragmentOffset (packetType, maxFragmentSize);
301 
302  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
303  has already been added to the packet) in which case Generic MAC Header will not be added to it.
304  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
305  if (element.m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
306  {
307  uint8_t tmpType = element.m_hdr.GetType ();
308  tmpType |= 4;
309  element.m_hdr.SetType (tmpType);
310 
311  uint32_t length = maxFragmentSize + element.m_hdr.GetSerializedSize ()
312  + fragmentSubhdr.GetSerializedSize ();
313  element.m_hdr.SetLen ((uint16_t)length);
314 
315  fragment->AddHeader (element.m_hdr);
316  }
317  fragment->AddHeader (element.m_hdrType);
318 
319  m_traceDequeue (fragment);
320  return fragment;
321  }
322  return 0;
323 }
324 
327 {
328  if (!IsEmpty ())
329  {
330  QueueElement element = m_queue.front ();
331  hdr = element.m_hdr;
332  Ptr<Packet> packet = element.m_packet->Copy ();
333 
334  // this function must not be used by SS as it may be then a bandwidth request header
335  packet->AddHeader (element.m_hdr);
336  return packet;
337  }
338 
339  return 0;
340 }
341 
343 WimaxMacQueue::Peek (GenericMacHeader &hdr, Time &timeStamp) const
344 {
345  if (!IsEmpty ())
346  {
347  QueueElement element = m_queue.front ();
348  hdr = element.m_hdr;
349  timeStamp = element.m_timeStamp;
350  Ptr<Packet> packet = element.m_packet->Copy ();
351 
352  // this function must not be used for by SS as it may be then a bandwidth request header
353  packet->AddHeader (element.m_hdr);
354  return packet;
355  }
356 
357  return 0;
358 }
359 
360 Ptr<Packet>
362 {
363  if (!IsEmpty ())
364  {
365  QueueElement element = Front (packetType);
366  Ptr<Packet> packet = element.m_packet->Copy ();
367 
368  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
369  has already been added to the packet) in which case Generic MAC Header will not be added to it.
370  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
371  if (element.m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
372  {
373  packet->AddHeader (element.m_hdr);
374  }
375  return packet;
376  }
377 
378  return 0;
379 }
380 
383  Time &timeStamp) const
384 {
385  if (!IsEmpty ())
386  {
387  QueueElement element = Front (packetType);
388  timeStamp = element.m_timeStamp;
389  Ptr<Packet> packet = element.m_packet->Copy ();
390 
391  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
392  has already been added to the packet) in which case Generic MAC Header will not be added to it.
393  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
394  if (element.m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
395  {
396  packet->AddHeader (element.m_hdr);
397  }
398  return packet;
399  }
400 
401  return 0;
402 }
403 
404 uint32_t
405 WimaxMacQueue::GetSize (void) const
406 {
407  return m_queue.size ();
408 }
409 
410 uint32_t
411 WimaxMacQueue::GetNBytes (void) const
412 {
413  return m_bytes;
414 }
415 
416 uint32_t WimaxMacQueue::GetQueueLengthWithMACOverhead (void)
417 {
418  uint32_t queueSize = GetNBytes ();
419  // Add MAC Overhead
420  queueSize += GetSize () * 6;
421  MacHeaderType::HeaderType packetType = MacHeaderType::HEADER_TYPE_GENERIC;
422  if (CheckForFragmentation (packetType))
423  {
424  queueSize += 2;
425  }
426  return queueSize;
427 }
428 
429 WimaxMacQueue::QueueElement
430 WimaxMacQueue::Front (MacHeaderType::HeaderType packetType) const
431 {
432  QueueElement element;
433 
434  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
435  != m_queue.end (); ++iter)
436  {
437  element = *iter;
438  if (element.m_hdrType.GetType () == packetType)
439  {
440  break;
441  }
442  }
443 
444  return element;
445 }
446 
447 void
448 WimaxMacQueue::Pop (MacHeaderType::HeaderType packetType)
449 {
450  QueueElement element;
451 
452  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
453  != m_queue.end (); ++iter)
454  {
455  element = *iter;
456  if (element.m_hdrType.GetType () == packetType)
457  {
458  m_queue.erase (iter);
459  break;
460  }
461  }
462 }
463 
464 bool
465 WimaxMacQueue::IsEmpty (void) const
466 {
467  return m_queue.empty ();
468 }
469 
470 bool
471 WimaxMacQueue::IsEmpty (MacHeaderType::HeaderType packetType) const
472 {
473  if (packetType == MacHeaderType::HEADER_TYPE_GENERIC)
474  {
475  return m_nrDataPackets == 0;
476  }
477  else
478  {
479  return m_nrRequestPackets == 0;
480  }
481 
482  return true;
483 }
484 
485 const WimaxMacQueue::PacketQueue &
486 WimaxMacQueue::GetPacketQueue (void) const
487 {
488  return m_queue;
489 }
490 
491 bool
493 {
494  QueueElement element;
495  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
496  != m_queue.end (); ++iter)
497  {
498  element = *iter;
499  if (element.m_hdrType.GetType () == packetType)
500  {
501  break;
502  }
503  }
504 
505  if (element.m_fragmentation)
506  {
507  NS_LOG_INFO ("FRAG_DEBUG: CheckForFragmentation"
508  "\n\t\t m_fragmentation is true " << std::endl);
509  }
510 
511  return element.m_fragmentation;
512 }
513 
514 uint32_t
515 WimaxMacQueue::GetFirstPacketHdrSize (MacHeaderType::HeaderType packetType)
516 {
517  QueueElement element;
518  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
519  != m_queue.end (); ++iter)
520  {
521  element = *iter;
522  if (element.m_hdrType.GetType () == packetType)
523  {
524  break;
525  }
526  }
527 
528  NS_LOG_INFO ("\t\t GetFirstPacketHdrSize ()");
529 
530  uint32_t hdrSize = 0;
531  if (element.m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
532  {
533  hdrSize += element.m_hdr.GetSerializedSize ();
534  NS_LOG_INFO ("\t\t\t m_hdr.GetSerializedSize=" <<
535  element.m_hdr.GetSerializedSize ());
536  }
537 
538  hdrSize += element.m_hdrType.GetSerializedSize ();
539  NS_LOG_INFO ("\t\t\t m_hdrType.GetSerializedSize=" <<
540  element.m_hdrType.GetSerializedSize ());
541 
542  if (CheckForFragmentation (packetType))
543  {
544  NS_LOG_INFO ("\t\t\t fragSubhdrSize=2");
545  hdrSize += 2;
546  }
547 
548  NS_LOG_INFO ("\t\t hdrSize=" << hdrSize);
549 
550  return hdrSize;
551 }
552 
553 uint32_t
554 WimaxMacQueue::GetFirstPacketPayloadSize (MacHeaderType::HeaderType packetType)
555 {
556  QueueElement element;
557  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
558  != m_queue.end (); ++iter)
559  {
560  element = *iter;
561  if (element.m_hdrType.GetType () == packetType)
562  {
563  break;
564  }
565  }
566 
567  NS_LOG_INFO ("\t\t GetFirstPacketPayloadSize ()");
568 
569  if (CheckForFragmentation (packetType))
570  {
571  NS_LOG_INFO ("\t\t\t fullPayloadSize=" << element.m_packet->GetSize ()
572  << "\n\t\t\t fragmentOffset=" << element.m_fragmentOffset
573  << "\n\t\t\t (fragment)payloadSize=" <<
574  element.m_packet->GetSize () - element.m_fragmentOffset);
575 
576  return element.m_packet->GetSize () - element.m_fragmentOffset;
577  }
578  NS_LOG_INFO ("\t\t payloadSize=" <<
579  element.m_packet->GetSize ());
580 
581  return element.m_packet->GetSize ();
582 }
583 
584 uint32_t
585 WimaxMacQueue::GetFirstPacketRequiredByte (MacHeaderType::HeaderType packetType)
586 {
587  NS_LOG_INFO ("\t GetFirstPacketRequiredByte ()");
588 
589  uint32_t requiredByte = GetFirstPacketPayloadSize (packetType) +
590  GetFirstPacketHdrSize (packetType);
591 
592  NS_LOG_INFO ("\t Required Bytes = " << requiredByte << std::endl);
593 
594  return requiredByte;
595 }
596 
597 void
598 WimaxMacQueue::SetFragmentation (MacHeaderType::HeaderType packetType)
599 {
600  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
601  != m_queue.end (); ++iter)
602  {
603  if (iter->m_hdrType.GetType () == packetType)
604  {
605  iter->SetFragmentation ();
606  break;
607  }
608  }
609 }
610 
611 void
612 WimaxMacQueue::SetFragmentNumber (MacHeaderType::HeaderType packetType)
613 {
614  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
615  != m_queue.end (); ++iter)
616  {
617  if (iter->m_hdrType.GetType () == packetType)
618  {
619  iter->SetFragmentNumber ();
620  break;
621  }
622  }
623 }
624 
625 void
626 WimaxMacQueue::SetFragmentOffset (MacHeaderType::HeaderType packetType, uint32_t offset)
627 {
628  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
629  != m_queue.end (); ++iter)
630  {
631  if (iter->m_hdrType.GetType () == packetType)
632  {
633  iter->SetFragmentOffset (offset);
634  break;
635  }
636  }
637 }
638 
639 void
640 WimaxMacQueue::QueueElement::SetFragmentation ()
641 {
642  m_fragmentation = true;
643 }
644 
645 void
646 WimaxMacQueue::QueueElement::SetFragmentNumber ()
647 {
648  m_fragmentNumber++;
649 }
650 
651 void
652 WimaxMacQueue::QueueElement::SetFragmentOffset (uint32_t offset)
653 {
654  m_fragmentOffset += offset;
655 }
656 } // namespace ns3
HeaderType
this class implements the mac header type field.
keep track of time unit.
Definition: nstime.h:149
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
Ptr< Packet > Peek(GenericMacHeader &hdr) const
Same as Dequeue but does not pop from queue.
#define NS_LOG_INFO(msg)
Definition: log.h:264
this class implements the Generic mac Header as described by IEEE Standard for Local and metropolitan...
uint32_t GetSerializedSize(void) const
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Definition: packet.cc:243
uint32_t GetSerializedSize(void) const
bool CheckForFragmentation(MacHeaderType::HeaderType packetType)
Fragmentation utilities.
bool Enqueue(Ptr< Packet > packet, const MacHeaderType &hdrType, const GenericMacHeader &hdr)
Enqueue a packet.
Represents the HT (Header Type) field of generic MAC and bandwidth request headers.
Ptr< Packet > Copy(void) const
Definition: packet.cc:131
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
uint32_t GetSerializedSize(void) const
static Time Now(void)
Definition: simulator.cc:179
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)
Definition: assert.h:86
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
Ptr< Packet > Dequeue(MacHeaderType::HeaderType packetType)
Dequeue a packet of type packetType from the queue.
void AddHeader(const Header &header)
Definition: packet.cc:270