A Discrete-Event Network Simulator
API
wimax-mac-queue.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007,2008 INRIA, UDcast
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
18  * Mohamed Amine Ismail <Amine.Ismail@sophia.inria.fr>
19  * <Amine.Ismail@UDcast.com>
20  */
21 
22 #include "wimax-mac-queue.h"
23 
24 #include "ns3/log.h"
25 #include "ns3/packet.h"
26 #include "ns3/simulator.h"
27 #include "ns3/trace-source-accessor.h"
28 #include "ns3/uinteger.h"
29 
30 namespace ns3
31 {
32 
33 NS_LOG_COMPONENT_DEFINE("WimaxMacQueue");
34 
35 NS_OBJECT_ENSURE_REGISTERED(WimaxMacQueue);
36 
38  : m_packet(Create<Packet>()),
39  m_hdrType(MacHeaderType()),
40  m_hdr(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,
51  Time timeStamp)
52  : m_packet(packet),
53  m_hdrType(hdrType),
54  m_hdr(hdr),
55  m_timeStamp(timeStamp),
56  m_fragmentation(false),
57  m_fragmentNumber(0),
58  m_fragmentOffset(0)
59 {
60 }
61 
62 uint32_t
64 {
65  uint32_t size = m_packet->GetSize() + m_hdrType.GetSerializedSize();
66 
67  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request
68  Header has already been added to the packet) in which case Generic MAC Header will not be added
69  to it. this will only happen in the case of SS as only SS sends the bandwidth request packet.
70  */
71  if (m_hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
72  {
73  size += m_hdr.GetSerializedSize();
74  }
75 
76  return size;
77 }
78 
79 TypeId
81 {
82  static TypeId tid = TypeId("ns3::WimaxMacQueue")
83  .SetParent<Object>()
84  .SetGroupName("Wimax")
85  .AddAttribute("MaxSize",
86  "Maximum size",
87  UintegerValue(1024),
90  MakeUintegerChecker<uint32_t>())
91  .AddTraceSource("Enqueue",
92  "Enqueue trace",
94  "ns3::Packet::TracedCallback")
95  .AddTraceSource("Dequeue",
96  "Dequeue trace",
98  "ns3::Packet::TracedCallback")
99  .AddTraceSource("Drop",
100  "Drop trace",
102  "ns3::Packet::TracedCallback");
103  return tid;
104 }
105 
107  : m_maxSize(0),
108  m_bytes(0),
109  m_nrDataPackets(0),
111 {
112 }
113 
115  : m_maxSize(maxSize),
116  m_bytes(0),
117  m_nrDataPackets(0),
118  m_nrRequestPackets(0)
119 {
120 }
121 
123 {
124 }
125 
126 void
127 WimaxMacQueue::SetMaxSize(uint32_t maxSize)
128 {
129  m_maxSize = maxSize;
130 }
131 
132 uint32_t
134 {
135  return m_maxSize;
136 }
137 
138 bool
140  const MacHeaderType& hdrType,
141  const GenericMacHeader& hdr)
142 {
143  if (m_queue.size() == m_maxSize)
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
195  Request Header has already been added to the packet) in which case Generic MAC Header
196  will not be added to it. this will only happen in the case of SS as only SS sends the
197  bandwidth request packet. */
198  m_bytes -= element.GetSize();
200  {
201  packet->AddHeader(element.m_hdr);
202  }
203  packet->AddHeader(element.m_hdrType);
204 
205  m_traceDequeue(packet);
206  return packet;
207  }
208  else
209  {
210  /*
211  The enqueued packet is a fragment (the latest fragment)
212  We must modify type field of the m_hdr and add a fragmentation Subhdr
213  */
214  NS_LOG_INFO("\t Enqueued Packet IS a fragment, add subhdr" << std::endl);
215 
216  // Create a fragment
217  uint32_t fragmentOffset = element.m_fragmentOffset;
218  uint32_t fragmentSize = element.m_packet->GetSize() - fragmentOffset;
219 
220  NS_LOG_INFO("\t Create a fragment"
221  "\n\t\t fragmentOffset="
222  << fragmentOffset << "\n\t\t packetSize=" << element.m_packet->GetSize()
223  << "\n\t\t fragmentSize=" << fragmentSize << std::endl);
224 
225  Ptr<Packet> fragment = packet->CreateFragment(fragmentOffset, fragmentSize);
226 
227  FragmentationSubheader fragmentSubhdr;
228  NS_LOG_INFO("\t Latest Fragment" << std::endl);
229  fragmentSubhdr.SetFc(2); // This is the latest fragment
230  fragmentSubhdr.SetFsn(element.m_fragmentNumber);
231 
232  NS_LOG_INFO("\t FragmentSize=" << fragment->GetSize() << std::endl);
233  fragment->AddHeader(fragmentSubhdr);
234 
235  /*check because may be it is a bandwidth request packet (in which case a Bandwidth
236  Request Header has already been added to the packet) in which case Generic MAC Header
237  will not be added to it. this will only happen in the case of SS as only SS sends the
238  bandwidth request packet. */
240  {
241  uint8_t tmpType = element.m_hdr.GetType();
242  tmpType |= 4;
243  element.m_hdr.SetType(tmpType);
244 
245  uint32_t length = fragmentSize + element.m_hdr.GetSerializedSize() +
246  fragmentSubhdr.GetSerializedSize();
247  element.m_hdr.SetLen((uint16_t)length);
248 
249  fragment->AddHeader(element.m_hdr);
250  }
251  fragment->AddHeader(element.m_hdrType);
252  m_bytes -= fragmentSize;
253 
254  m_traceDequeue(fragment);
255  return fragment;
256  }
257  }
258  return nullptr;
259 }
260 
262 WimaxMacQueue::Dequeue(MacHeaderType::HeaderType packetType, uint32_t availableByte)
263 {
264  if (!IsEmpty())
265  {
266  NS_LOG_INFO("FRAG_DEBUG: Dequeue function" << std::endl);
267  QueueElement element = Front(packetType);
268 
269  uint32_t headerSize =
270  2 + element.m_hdr.GetSerializedSize() + element.m_hdrType.GetSerializedSize();
271 
272  // Create a fragment
273  uint32_t maxFragmentSize = availableByte - headerSize;
274  uint32_t fragmentOffset = element.m_fragmentOffset; // It is the latest byte sent.
275 
276  Ptr<Packet> packet = element.m_packet->Copy();
277  NS_LOG_INFO("\t Create a fragment"
278  "\n\t\t availableByte="
279  << availableByte << "\n\t\t headerSize=" << headerSize
280  << "\n\t\t maxFragmentSize=" << maxFragmentSize
281  << ""
282  "\n\t\t fragmentOffset="
283  << fragmentOffset << "\n\t\t payloadSize=" << packet->GetSize() << std::endl);
284  Ptr<Packet> fragment = packet->CreateFragment(fragmentOffset, maxFragmentSize);
285  m_bytes -= maxFragmentSize;
286 
287  FragmentationSubheader fragmentSubhdr;
288  if (!element.m_fragmentation)
289  {
290  NS_LOG_INFO("\t First Fragment" << std::endl);
291  SetFragmentation(packetType);
292  fragmentSubhdr.SetFc(1);
293  }
294  else
295  {
296  NS_LOG_INFO("\t Middle Fragment" << std::endl);
297  fragmentSubhdr.SetFc(3);
298  }
299  fragmentSubhdr.SetFsn(element.m_fragmentNumber);
300  NS_LOG_INFO("\t FragmentSize=" << fragment->GetSize() << std::endl);
301  fragment->AddHeader(fragmentSubhdr);
302 
303  SetFragmentNumber(packetType);
304  SetFragmentOffset(packetType, maxFragmentSize);
305 
306  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request
307  Header has already been added to the packet) in which case Generic MAC Header will not be
308  added to it. this will only happen in the case of SS as only SS sends the bandwidth
309  request packet. */
311  {
312  uint8_t tmpType = element.m_hdr.GetType();
313  tmpType |= 4;
314  element.m_hdr.SetType(tmpType);
315 
316  uint32_t length = maxFragmentSize + element.m_hdr.GetSerializedSize() +
317  fragmentSubhdr.GetSerializedSize();
318  element.m_hdr.SetLen((uint16_t)length);
319 
320  fragment->AddHeader(element.m_hdr);
321  }
322  fragment->AddHeader(element.m_hdrType);
323 
324  m_traceDequeue(fragment);
325  return fragment;
326  }
327  return nullptr;
328 }
329 
332 {
333  if (!IsEmpty())
334  {
335  QueueElement element = m_queue.front();
336  hdr = element.m_hdr;
337  Ptr<Packet> packet = element.m_packet->Copy();
338 
339  // this function must not be used by SS as it may be then a bandwidth request header
340  packet->AddHeader(element.m_hdr);
341  return packet;
342  }
343 
344  return nullptr;
345 }
346 
349 {
350  if (!IsEmpty())
351  {
352  QueueElement element = m_queue.front();
353  hdr = element.m_hdr;
354  timeStamp = element.m_timeStamp;
355  Ptr<Packet> packet = element.m_packet->Copy();
356 
357  // this function must not be used for by SS as it may be then a bandwidth request header
358  packet->AddHeader(element.m_hdr);
359  return packet;
360  }
361 
362  return nullptr;
363 }
364 
367 {
368  if (!IsEmpty())
369  {
370  QueueElement element = Front(packetType);
371  Ptr<Packet> packet = element.m_packet->Copy();
372 
373  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request
374  Header has already been added to the packet) in which case Generic MAC Header will not be
375  added to it. this will only happen in the case of SS as only SS sends the bandwidth request
376  packet. */
378  {
379  packet->AddHeader(element.m_hdr);
380  }
381  return packet;
382  }
383 
384  return nullptr;
385 }
386 
389 {
390  if (!IsEmpty())
391  {
392  QueueElement element = Front(packetType);
393  timeStamp = element.m_timeStamp;
394  Ptr<Packet> packet = element.m_packet->Copy();
395 
396  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request
397  Header has already been added to the packet) in which case Generic MAC Header will not be
398  added to it. this will only happen in the case of SS as only SS sends the bandwidth request
399  packet. */
401  {
402  packet->AddHeader(element.m_hdr);
403  }
404  return packet;
405  }
406 
407  return nullptr;
408 }
409 
410 uint32_t
412 {
413  return m_queue.size();
414 }
415 
416 uint32_t
418 {
419  return m_bytes;
420 }
421 
422 uint32_t
424 {
425  uint32_t queueSize = GetNBytes();
426  // Add MAC Overhead
427  queueSize += GetSize() * 6;
429  if (CheckForFragmentation(packetType))
430  {
431  queueSize += 2;
432  }
433  return queueSize;
434 }
435 
438 {
439  QueueElement element;
440 
441  for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
442  {
443  element = *iter;
444  if (element.m_hdrType.GetType() == packetType)
445  {
446  break;
447  }
448  }
449 
450  return element;
451 }
452 
453 void
455 {
456  QueueElement element;
457 
458  for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
459  {
460  element = *iter;
461  if (element.m_hdrType.GetType() == packetType)
462  {
463  m_queue.erase(iter);
464  break;
465  }
466  }
467 }
468 
469 bool
471 {
472  return m_queue.empty();
473 }
474 
475 bool
477 {
478  if (packetType == MacHeaderType::HEADER_TYPE_GENERIC)
479  {
480  return m_nrDataPackets == 0;
481  }
482  else
483  {
484  return m_nrRequestPackets == 0;
485  }
486 
487  return true;
488 }
489 
492 {
493  return m_queue;
494 }
495 
496 bool
498 {
499  QueueElement element;
500  for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
501  {
502  element = *iter;
503  if (element.m_hdrType.GetType() == packetType)
504  {
505  break;
506  }
507  }
508 
509  if (element.m_fragmentation)
510  {
511  NS_LOG_INFO("FRAG_DEBUG: CheckForFragmentation"
512  "\n\t\t m_fragmentation is true "
513  << std::endl);
514  }
515 
516  return element.m_fragmentation;
517 }
518 
519 uint32_t
521 {
522  QueueElement element;
523  for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
524  {
525  element = *iter;
526  if (element.m_hdrType.GetType() == packetType)
527  {
528  break;
529  }
530  }
531 
532  NS_LOG_INFO("\t\t GetFirstPacketHdrSize ()");
533 
534  uint32_t hdrSize = 0;
536  {
537  hdrSize += element.m_hdr.GetSerializedSize();
538  NS_LOG_INFO("\t\t\t m_hdr.GetSerializedSize=" << element.m_hdr.GetSerializedSize());
539  }
540 
541  hdrSize += element.m_hdrType.GetSerializedSize();
542  NS_LOG_INFO("\t\t\t m_hdrType.GetSerializedSize=" << element.m_hdrType.GetSerializedSize());
543 
544  if (CheckForFragmentation(packetType))
545  {
546  NS_LOG_INFO("\t\t\t fragSubhdrSize=2");
547  hdrSize += 2;
548  }
549 
550  NS_LOG_INFO("\t\t hdrSize=" << hdrSize);
551 
552  return hdrSize;
553 }
554 
555 uint32_t
557 {
558  QueueElement element;
559  for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
560  {
561  element = *iter;
562  if (element.m_hdrType.GetType() == packetType)
563  {
564  break;
565  }
566  }
567 
568  NS_LOG_INFO("\t\t GetFirstPacketPayloadSize ()");
569 
570  if (CheckForFragmentation(packetType))
571  {
572  NS_LOG_INFO("\t\t\t fullPayloadSize="
573  << element.m_packet->GetSize() << "\n\t\t\t fragmentOffset="
574  << element.m_fragmentOffset << "\n\t\t\t (fragment)payloadSize="
575  << element.m_packet->GetSize() - element.m_fragmentOffset);
576 
577  return element.m_packet->GetSize() - element.m_fragmentOffset;
578  }
579  NS_LOG_INFO("\t\t payloadSize=" << element.m_packet->GetSize());
580 
581  return element.m_packet->GetSize();
582 }
583 
584 uint32_t
586 {
587  NS_LOG_INFO("\t GetFirstPacketRequiredByte ()");
588 
589  uint32_t requiredByte =
590  GetFirstPacketPayloadSize(packetType) + GetFirstPacketHdrSize(packetType);
591 
592  NS_LOG_INFO("\t Required Bytes = " << requiredByte << std::endl);
593 
594  return requiredByte;
595 }
596 
597 void
599 {
600  for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
601  {
602  if (iter->m_hdrType.GetType() == packetType)
603  {
604  iter->SetFragmentation();
605  break;
606  }
607  }
608 }
609 
610 void
612 {
613  for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
614  {
615  if (iter->m_hdrType.GetType() == packetType)
616  {
617  iter->SetFragmentNumber();
618  break;
619  }
620  }
621 }
622 
623 void
625 {
626  for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
627  {
628  if (iter->m_hdrType.GetType() == packetType)
629  {
630  iter->SetFragmentOffset(offset);
631  break;
632  }
633  }
634 }
635 
636 void
638 {
639  m_fragmentation = true;
640 }
641 
642 void
644 {
645  m_fragmentNumber++;
646 }
647 
648 void
650 {
651  m_fragmentOffset += offset;
652 }
653 } // namespace ns3
This class implements the fragmentation sub-header as described by IEEE Standard for Local and metrop...
uint32_t GetSerializedSize() const override
void SetFsn(uint8_t fsn)
Set FSN field.
void SetFc(uint8_t fc)
Set FC field.
This class implements the Generic mac Header as described by IEEE Standard for Local and metropolitan...
uint8_t GetType() const
Get type field.
void SetType(uint8_t type)
Set type field.
uint32_t GetSerializedSize() const override
void SetLen(uint16_t len)
Set length field.
This class Represents the HT (Header Type) field of generic MAC and bandwidth request headers.
HeaderType
Header type enumeration.
uint32_t GetSerializedSize() const override
uint8_t GetType() const
Get type field.
A base class which provides memory management and object aggregation.
Definition: object.h:89
network packets
Definition: packet.h:239
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
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:238
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Hold an unsigned integer type.
Definition: uinteger.h:45
std::deque< QueueElement > PacketQueue
PacketQueue typedef.
Ptr< Packet > Peek(GenericMacHeader &hdr) const
Exclusively for BS.
uint32_t GetFirstPacketPayloadSize(MacHeaderType::HeaderType packetType)
Get first packet payload size of the specified type.
WimaxMacQueue::QueueElement Front(MacHeaderType::HeaderType packetType) const
In the case of non-UGS service flows at the SS side the queue will store both data packets and bandwi...
void Pop(MacHeaderType::HeaderType packetType)
Pop function.
void SetMaxSize(uint32_t maxSize)
set the maximum queue size
TracedCallback< Ptr< const Packet > > m_traceDequeue
dequeue trace callback
uint32_t GetFirstPacketRequiredByte(MacHeaderType::HeaderType packetType)
Get required number of bytes to hold first packet of packetType.
Ptr< Packet > Dequeue(MacHeaderType::HeaderType packetType)
Dequeue a packet of type packetType from the queue.
TracedCallback< Ptr< const Packet > > m_traceEnqueue
enqueue trace callback
uint32_t GetNBytes() const
Get number of bytes in queue.
static TypeId GetTypeId()
Get the type ID.
uint32_t GetFirstPacketHdrSize(MacHeaderType::HeaderType packetType)
Get first packet header size of the specified type.
uint32_t m_bytes
bytes
void SetFragmentNumber(MacHeaderType::HeaderType packetType)
Set fragment number for first packet of type packetType.
void SetFragmentation(MacHeaderType::HeaderType packetType)
Set fragmentation function.
void SetFragmentOffset(MacHeaderType::HeaderType packetType, uint32_t offset)
Set fragment offset for first packet of type packetType.
bool CheckForFragmentation(MacHeaderType::HeaderType packetType)
Check for fragmentation of the first packet of the specified type.
uint32_t m_nrDataPackets
number data packets
uint32_t m_maxSize
maximum size
bool Enqueue(Ptr< Packet > packet, const MacHeaderType &hdrType, const GenericMacHeader &hdr)
Enqueue a packet.
PacketQueue m_queue
the queue
uint32_t m_nrRequestPackets
number request packets
uint32_t GetQueueLengthWithMACOverhead()
Get queue length considering also the MAC overhead.
bool IsEmpty() const
Check if queue is empty.
const WimaxMacQueue::PacketQueue & GetPacketQueue() const
Get packet queue function.
TracedCallback< Ptr< const Packet > > m_traceDrop
drop trace callback
uint32_t GetMaxSize() const
uint32_t GetSize() const
Get size of queue.
#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:86
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition: ptr.h:442
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
uint32_t m_fragmentNumber
incremented when a new fragment is sent
uint32_t GetSize() const
Get size function.
uint32_t m_fragmentOffset
tracks the start of the next fragment into the packet
bool m_fragmentation
To manage fragmentation feature, each QueueElement have 3 new fields: m_fragmentation that becomes tr...
void SetFragmentNumber()
Set fragment number.
MacHeaderType m_hdrType
header type
GenericMacHeader m_hdr
header
void SetFragmentOffset(uint32_t offset)
Set fragment offset.
void SetFragmentation()
Set fragmentation.
std::ofstream queueSize