A Discrete-Event Network Simulator
API
ctrl-headers.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 MIRKO BANCHI
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: Mirko Banchi <mk.banchi@gmail.com>
19  */
20 
21 #include "ns3/fatal-error.h"
22 #include "ns3/log.h"
23 #include "ctrl-headers.h"
24 
25 namespace ns3 {
26 
27 NS_LOG_COMPONENT_DEFINE ("CtrlHeaders");
28 
29 /***********************************
30  * Block ack request
31  ***********************************/
32 
33 NS_OBJECT_ENSURE_REGISTERED (CtrlBAckRequestHeader);
34 
36  : m_barAckPolicy (false),
37  m_multiTid (false),
38  m_compressed (false)
39 {
40  NS_LOG_FUNCTION (this);
41 }
42 
44 {
45  NS_LOG_FUNCTION (this);
46 }
47 
48 TypeId
50 {
52  static TypeId tid = TypeId ("ns3::CtrlBAckRequestHeader")
53  .SetParent<Header> ()
54  .SetGroupName ("Wifi")
55  .AddConstructor<CtrlBAckRequestHeader> ()
56  ;
57  return tid;
58 }
59 
60 TypeId
62 {
63  NS_LOG_FUNCTION (this);
64  return GetTypeId ();
65 }
66 
67 void
68 CtrlBAckRequestHeader::Print (std::ostream &os) const
69 {
70  NS_LOG_FUNCTION (this << &os);
71  os << "TID_INFO=" << m_tidInfo << ", StartingSeq=" << std::hex << m_startingSeq << std::dec;
72 }
73 
74 uint32_t
76 {
77  NS_LOG_FUNCTION (this);
78  uint32_t size = 0;
79  size += 2; //Bar control
80  if (!m_multiTid)
81  {
82  size += 2; //Starting sequence control
83  }
84  else
85  {
86  if (m_compressed)
87  {
88  size += (2 + 2) * (m_tidInfo + 1); //Multi-tid block ack
89  }
90  else
91  {
92  NS_FATAL_ERROR ("Reserved configuration.");
93  }
94  }
95  return size;
96 }
97 
98 void
100 {
101  NS_LOG_FUNCTION (this << &start);
104  if (!m_multiTid)
105  {
107  }
108  else
109  {
110  if (m_compressed)
111  {
112  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
113  }
114  else
115  {
116  NS_FATAL_ERROR ("Reserved configuration.");
117  }
118  }
119 }
120 
121 uint32_t
123 {
124  NS_LOG_FUNCTION (this << &start);
127  if (!m_multiTid)
128  {
130  }
131  else
132  {
133  if (m_compressed)
134  {
135  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
136  }
137  else
138  {
139  NS_FATAL_ERROR ("Reserved configuration.");
140  }
141  }
142  return i.GetDistanceFrom (start);
143 }
144 
145 uint16_t
147 {
148  NS_LOG_FUNCTION (this);
149  uint16_t res = 0;
150  if (m_barAckPolicy)
151  {
152  res |= 0x1;
153  }
154  if (m_multiTid)
155  {
156  res |= (0x1 << 1);
157  }
158  if (m_compressed)
159  {
160  res |= (0x1 << 2);
161  }
162  res |= (m_tidInfo << 12) & (0xf << 12);
163  return res;
164 }
165 
166 void
168 {
169  NS_LOG_FUNCTION (this << bar);
170  m_barAckPolicy = ((bar & 0x01) == 1) ? true : false;
171  m_multiTid = (((bar >> 1) & 0x01) == 1) ? true : false;
172  m_compressed = (((bar >> 2) & 0x01) == 1) ? true : false;
173  m_tidInfo = (bar >> 12) & 0x0f;
174 }
175 
176 uint16_t
178 {
179  NS_LOG_FUNCTION (this);
180  return (m_startingSeq << 4) & 0xfff0;
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION (this << seqControl);
187  m_startingSeq = (seqControl >> 4) & 0x0fff;
188 }
189 
190 void
192 {
193  NS_LOG_FUNCTION (this << immediateAck);
194  m_barAckPolicy = immediateAck;
195 }
196 
197 void
199 {
200  NS_LOG_FUNCTION (this << type);
201  switch (type)
202  {
203  case BASIC_BLOCK_ACK:
204  m_multiTid = false;
205  m_compressed = false;
206  break;
208  m_multiTid = false;
209  m_compressed = true;
210  break;
211  case MULTI_TID_BLOCK_ACK:
212  m_multiTid = true;
213  m_compressed = true;
214  break;
215  default:
216  NS_FATAL_ERROR ("Invalid variant type");
217  break;
218  }
219 }
220 
221 void
223 {
224  NS_LOG_FUNCTION (this << static_cast<uint32_t> (tid));
225  m_tidInfo = static_cast<uint16_t> (tid);
226 }
227 
228 void
230 {
231  NS_LOG_FUNCTION (this << seq);
232  m_startingSeq = seq;
233 }
234 
235 bool
237 {
238  NS_LOG_FUNCTION (this);
239  return m_barAckPolicy;
240 }
241 
242 uint8_t
244 {
245  NS_LOG_FUNCTION (this);
246  uint8_t tid = static_cast<uint8_t> (m_tidInfo);
247  return tid;
248 }
249 
250 uint16_t
252 {
253  NS_LOG_FUNCTION (this);
254  return m_startingSeq;
255 }
256 
257 bool
259 {
260  NS_LOG_FUNCTION (this);
261  return (!m_multiTid && !m_compressed) ? true : false;
262 }
263 
264 bool
266 {
267  NS_LOG_FUNCTION (this);
268  return (!m_multiTid && m_compressed) ? true : false;
269 }
270 
271 bool
273 {
274  NS_LOG_FUNCTION (this);
275  return (m_multiTid && m_compressed) ? true : false;
276 }
277 
278 
279 /***********************************
280  * Block ack response
281  ***********************************/
282 
284 
286  : m_baAckPolicy (false),
287  m_multiTid (false),
288  m_compressed (false)
289 {
290  NS_LOG_FUNCTION (this);
291  memset (&bitmap, 0, sizeof (bitmap));
292 }
293 
295 {
296  NS_LOG_FUNCTION (this);
297 }
298 
299 TypeId
301 {
302  static TypeId tid = TypeId ("ns3::CtrlBAckResponseHeader")
303  .SetParent<Header> ()
304  .SetGroupName ("Wifi")
305  .AddConstructor<CtrlBAckResponseHeader> ()
306  ;
307  return tid;
308 }
309 
310 TypeId
312 {
313  return GetTypeId ();
314 }
315 
316 void
317 CtrlBAckResponseHeader::Print (std::ostream &os) const
318 {
319  NS_LOG_FUNCTION (this << &os);
320  os << "TID_INFO=" << m_tidInfo << ", StartingSeq=" << std::hex << m_startingSeq << std::dec;
321 }
322 
323 uint32_t
325 {
326  NS_LOG_FUNCTION (this);
327  uint32_t size = 0;
328  size += 2; //Bar control
329  if (!m_multiTid)
330  {
331  if (!m_compressed)
332  {
333  size += (2 + 128); //Basic block ack
334  }
335  else
336  {
337  size += (2 + 8); //Compressed block ack
338  }
339  }
340  else
341  {
342  if (m_compressed)
343  {
344  size += (2 + 2 + 8) * (m_tidInfo + 1); //Multi-tid block ack
345  }
346  else
347  {
348  NS_FATAL_ERROR ("Reserved configuration.");
349  }
350  }
351  return size;
352 }
353 
354 void
356 {
357  NS_LOG_FUNCTION (this << &start);
360  if (!m_multiTid)
361  {
363  i = SerializeBitmap (i);
364  }
365  else
366  {
367  if (m_compressed)
368  {
369  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
370  }
371  else
372  {
373  NS_FATAL_ERROR ("Reserved configuration.");
374  }
375  }
376 }
377 
378 uint32_t
380 {
381  NS_LOG_FUNCTION (this << &start);
384  if (!m_multiTid)
385  {
387  i = DeserializeBitmap (i);
388  }
389  else
390  {
391  if (m_compressed)
392  {
393  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
394  }
395  else
396  {
397  NS_FATAL_ERROR ("Reserved configuration.");
398  }
399  }
400  return i.GetDistanceFrom (start);
401 }
402 
403 void
405 {
406  NS_LOG_FUNCTION (this << immediateAck);
407  m_baAckPolicy = immediateAck;
408 }
409 
410 void
412 {
413  NS_LOG_FUNCTION (this << type);
414  switch (type)
415  {
416  case BASIC_BLOCK_ACK:
417  m_multiTid = false;
418  m_compressed = false;
419  break;
421  m_multiTid = false;
422  m_compressed = true;
423  break;
424  case MULTI_TID_BLOCK_ACK:
425  m_multiTid = true;
426  m_compressed = true;
427  break;
428  default:
429  NS_FATAL_ERROR ("Invalid variant type");
430  break;
431  }
432 }
433 
434 void
436 {
437  NS_LOG_FUNCTION (this << static_cast<uint32_t> (tid));
438  m_tidInfo = static_cast<uint16_t> (tid);
439 }
440 
441 void
443 {
444  NS_LOG_FUNCTION (this << seq);
445  m_startingSeq = seq;
446 }
447 
448 bool
450 {
451  NS_LOG_FUNCTION (this);
452  return (m_baAckPolicy) ? true : false;
453 }
454 
455 uint8_t
457 {
458  NS_LOG_FUNCTION (this);
459  uint8_t tid = static_cast<uint8_t> (m_tidInfo);
460  return tid;
461 }
462 
463 uint16_t
465 {
466  NS_LOG_FUNCTION (this);
467  return m_startingSeq;
468 }
469 
470 bool
472 {
473  NS_LOG_FUNCTION (this);
474  return (!m_multiTid && !m_compressed) ? true : false;
475 }
476 
477 bool
479 {
480  NS_LOG_FUNCTION (this);
481  return (!m_multiTid && m_compressed) ? true : false;
482 }
483 
484 bool
486 {
487  NS_LOG_FUNCTION (this);
488  return (m_multiTid && m_compressed) ? true : false;
489 }
490 
491 uint16_t
493 {
494  NS_LOG_FUNCTION (this);
495  uint16_t res = 0;
496  if (m_baAckPolicy)
497  {
498  res |= 0x1;
499  }
500  if (m_multiTid)
501  {
502  res |= (0x1 << 1);
503  }
504  if (m_compressed)
505  {
506  res |= (0x1 << 2);
507  }
508  res |= (m_tidInfo << 12) & (0xf << 12);
509  return res;
510 }
511 
512 void
514 {
515  NS_LOG_FUNCTION (this << ba);
516  m_baAckPolicy = ((ba & 0x01) == 1) ? true : false;
517  m_multiTid = (((ba >> 1) & 0x01) == 1) ? true : false;
518  m_compressed = (((ba >> 2) & 0x01) == 1) ? true : false;
519  m_tidInfo = (ba >> 12) & 0x0f;
520 }
521 
522 uint16_t
524 {
525  NS_LOG_FUNCTION (this);
526  return (m_startingSeq << 4) & 0xfff0;
527 }
528 
529 void
531 {
532  NS_LOG_FUNCTION (this << seqControl);
533  m_startingSeq = (seqControl >> 4) & 0x0fff;
534 }
535 
538 {
539  NS_LOG_FUNCTION (this << &start);
541  if (!m_multiTid)
542  {
543  if (!m_compressed)
544  {
545  for (uint32_t j = 0; j < 64; j++)
546  {
547  i.WriteHtolsbU16 (bitmap.m_bitmap[j]);
548  }
549  }
550  else
551  {
552  i.WriteHtolsbU64 (bitmap.m_compressedBitmap);
553  }
554  }
555  else
556  {
557  if (m_compressed)
558  {
559  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
560  }
561  else
562  {
563  NS_FATAL_ERROR ("Reserved configuration.");
564  }
565  }
566  return i;
567 }
568 
571 {
572  NS_LOG_FUNCTION (this << &start);
574  if (!m_multiTid)
575  {
576  if (!m_compressed)
577  {
578  for (uint32_t j = 0; j < 64; j++)
579  {
580  bitmap.m_bitmap[j] = i.ReadLsbtohU16 ();
581  }
582  }
583  else
584  {
585  bitmap.m_compressedBitmap = i.ReadLsbtohU64 ();
586  }
587  }
588  else
589  {
590  if (m_compressed)
591  {
592  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
593  }
594  else
595  {
596  NS_FATAL_ERROR ("Reserved configuration.");
597  }
598  }
599  return i;
600 }
601 
602 void
604 {
605  NS_LOG_FUNCTION (this << seq);
606  if (!IsInBitmap (seq))
607  {
608  return;
609  }
610  if (!m_multiTid)
611  {
612  if (!m_compressed)
613  {
614  /* To set correctly basic block ack bitmap we need fragment number too.
615  So if it's not specified, we consider packet not fragmented. */
616  bitmap.m_bitmap[IndexInBitmap (seq)] |= 0x0001;
617  }
618  else
619  {
620  bitmap.m_compressedBitmap |= (uint64_t (0x0000000000000001) << IndexInBitmap (seq));
621  }
622  }
623  else
624  {
625  if (m_compressed)
626  {
627  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
628  }
629  else
630  {
631  NS_FATAL_ERROR ("Reserved configuration.");
632  }
633  }
634 }
635 
636 void
638 {
639  NS_LOG_FUNCTION (this << seq << static_cast<uint32_t> (frag));
640  NS_ASSERT (frag < 16);
641  if (!IsInBitmap (seq))
642  {
643  return;
644  }
645  if (!m_multiTid)
646  {
647  if (!m_compressed)
648  {
649  bitmap.m_bitmap[IndexInBitmap (seq)] |= (0x0001 << frag);
650  }
651  else
652  {
653  /* We can ignore this...compressed block ack doesn't support
654  acknowledgement of single fragments */
655  }
656  }
657  else
658  {
659  if (m_compressed)
660  {
661  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
662  }
663  else
664  {
665  NS_FATAL_ERROR ("Reserved configuration.");
666  }
667  }
668 }
669 
670 bool
672 {
673  NS_LOG_FUNCTION (this << seq);
674  if (!IsInBitmap (seq))
675  {
676  return false;
677  }
678  if (!m_multiTid)
679  {
680  if (!m_compressed)
681  {
682  /*It's impossible to say if an entire packet was correctly received. */
683  return false;
684  }
685  else
686  {
687  uint64_t mask = uint64_t (0x0000000000000001);
688  return (((bitmap.m_compressedBitmap >> IndexInBitmap (seq)) & mask) == 1) ? true : false;
689  }
690  }
691  else
692  {
693  if (m_compressed)
694  {
695  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
696  }
697  else
698  {
699  NS_FATAL_ERROR ("Reserved configuration.");
700  }
701  }
702  return false;
703 }
704 
705 bool
706 CtrlBAckResponseHeader::IsFragmentReceived (uint16_t seq, uint8_t frag) const
707 {
708  NS_LOG_FUNCTION (this << seq << static_cast<uint32_t> (frag));
709  NS_ASSERT (frag < 16);
710  if (!IsInBitmap (seq))
711  {
712  return false;
713  }
714  if (!m_multiTid)
715  {
716  if (!m_compressed)
717  {
718  return ((bitmap.m_bitmap[IndexInBitmap (seq)] & (0x0001 << frag)) != 0x0000) ? true : false;
719  }
720  else
721  {
722  /* Although this could make no sense, if packet with sequence number
723  equal to <i>seq</i> was correctly received, also all of its fragments
724  were correctly received. */
725  uint64_t mask = uint64_t (0x0000000000000001);
726  return (((bitmap.m_compressedBitmap >> IndexInBitmap (seq)) & mask) == 1) ? true : false;
727  }
728  }
729  else
730  {
731  if (m_compressed)
732  {
733  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
734  }
735  else
736  {
737  NS_FATAL_ERROR ("Reserved configuration.");
738  }
739  }
740  return false;
741 }
742 
743 uint8_t
745 {
746  NS_LOG_FUNCTION (this << seq);
747  uint8_t index;
748  if (seq >= m_startingSeq)
749  {
750  index = seq - m_startingSeq;
751  }
752  else
753  {
754  index = 4096 - m_startingSeq + seq;
755  }
756  NS_ASSERT (index <= 63);
757  return index;
758 }
759 
760 bool
762 {
763  NS_LOG_FUNCTION (this << seq);
764  return (seq - m_startingSeq + 4096) % 4096 < 64;
765 }
766 
767 const uint16_t*
769 {
770  NS_LOG_FUNCTION (this);
771  return bitmap.m_bitmap;
772 }
773 
774 uint64_t
776 {
777  NS_LOG_FUNCTION (this);
778  return bitmap.m_compressedBitmap;
779 }
780 
781 void
783 {
784  NS_LOG_FUNCTION (this);
785  memset (&bitmap, 0, sizeof (bitmap));
786 }
787 
788 } //namespace ns3
Protocol header serialization and deserialization.
Definition: header.h:42
void SetType(enum BlockAckType type)
Set the block ACK type.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
Definition: ctrl-headers.cc:61
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
def start()
Definition: core.py:1482
void SetStartingSequenceControl(uint16_t seqControl)
Set the starting sequence control with the given sequence control value.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
bool IsMultiTid(void) const
Check if the current ACK policy has multiple TID.
void SetBarControl(uint16_t bar)
Set the Block ACK control.
bool IsPacketReceived(uint16_t seq) const
Check if the packet with the given sequence number was ACKed in this Block ACK response.
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
void SetHtImmediateAck(bool immediateAck)
Enable or disable HT immediate ACK.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
BlockAckType
Enumeration for different block ACK policies.
Definition: ctrl-headers.h:31
bool m_baAckPolicy
The lsb bit of the BA control field is used only for the HT (High Throughput) delayed block ack confi...
Definition: ctrl-headers.h:395
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
uint32_t GetDistanceFrom(Iterator const &o) const
Definition: buffer.cc:783
iterator in a Buffer instance
Definition: buffer.h:98
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
virtual void Print(std::ostream &os) const
Definition: ctrl-headers.cc:68
void SetBaControl(uint16_t bar)
Set the block ACK control.
uint16_t GetBaControl(void) const
Return the block ACK control.
bool m_barAckPolicy
The lsb bit of the BAR control field is used only for the HT (High Throughput) delayed block ack conf...
Definition: ctrl-headers.h:166
virtual uint32_t GetSerializedSize(void) const
Definition: ctrl-headers.cc:75
uint8_t IndexInBitmap(uint16_t seq) const
This function is used to correctly index in both bitmap and compressed bitmap, one bit or one block o...
Headers for Block ack response.
Definition: ctrl-headers.h:186
static TypeId GetTypeId(void)
Definition: ctrl-headers.cc:49
uint16_t GetStartingSequenceControl(void) const
Return the starting sequence control.
bool IsFragmentReceived(uint16_t seq, uint8_t frag) const
Check if the packet with the given sequence number and fragment number was ACKed in this Block ACK re...
virtual uint32_t GetSerializedSize(void) const
Buffer::Iterator SerializeBitmap(Buffer::Iterator start) const
Serialize bitmap to the given buffer.
virtual uint32_t Deserialize(Buffer::Iterator start)
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Buffer::Iterator DeserializeBitmap(Buffer::Iterator start)
Deserialize bitmap from the given buffer.
static TypeId GetTypeId(void)
void SetType(enum BlockAckType type)
Set the block ACK type.
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
uint16_t GetStartingSequenceControl(void) const
Return the starting sequence control.
virtual void Serialize(Buffer::Iterator start) const
void ResetBitmap(void)
Reset the bitmap to 0.
bool IsInBitmap(uint16_t seq) const
Checks if sequence number seq can be acknowledged in the bitmap.
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:910
void SetReceivedFragment(uint16_t seq, uint8_t frag)
Set the bitmap that the packet with the given sequence number and fragment number was received...
virtual void Serialize(Buffer::Iterator start) const
Definition: ctrl-headers.cc:99
void SetStartingSequenceControl(uint16_t seqControl)
Set the starting sequence control with the given sequence control value.
void SetReceivedPacket(uint16_t seq)
Set the bitmap that the packet with the given sequence number was received.
uint16_t GetBarControl(void) const
Return the Block ACK control.
bool MustSendHtImmediateAck(void) const
Check if the current ACK policy is immediate.
union ns3::CtrlBAckResponseHeader::@83 bitmap
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:926
const uint16_t * GetBitmap(void) const
Return the bitmap from the block ACK response header.
virtual uint32_t Deserialize(Buffer::Iterator start)
void SetHtImmediateAck(bool immediateAck)
Enable or disable HT immediate ACK.
uint16_t ReadLsbtohU16(void)
Definition: buffer.cc:1065
virtual void Print(std::ostream &os) const
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
bool MustSendHtImmediateAck(void) const
Check if the current ACK policy is immediate.
uint64_t ReadLsbtohU64(void)
Definition: buffer.cc:1093
Headers for Block ack request.
Definition: ctrl-headers.h:50
a unique identifier for an interface.
Definition: type-id.h:58
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:904
bool IsMultiTid(void) const
Check if the current ACK policy has multiple TID.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
uint64_t GetCompressedBitmap(void) const
Return the compressed bitmap from the block ACK response header.