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