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