A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
wifi-mac-header.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2006, 2009 INRIA
4  * Copyright (c) 2009 MIRKO BANCHI
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  * Author: Mirko Banchi <mk.banchi@gmail.com>
21  */
22 #include "ns3/assert.h"
23 #include "ns3/address-utils.h"
24 #include "wifi-mac-header.h"
25 
26 namespace ns3 {
27 
28 NS_OBJECT_ENSURE_REGISTERED (WifiMacHeader);
29 
30 enum
31 {
32  TYPE_MGT = 0,
33  TYPE_CTL = 1,
35 };
36 
37 enum
38 {
44 };
45 
47  : m_ctrlPwrMgt (0),
48  m_ctrlMoreData (0),
49  m_ctrlWep (0),
50  m_ctrlOrder (1),
51  m_amsduPresent (0)
52 {
53 }
55 {
56 }
57 
58 void
60 {
61  m_ctrlFromDs = 1;
62 }
63 void
65 {
66  m_ctrlFromDs = 0;
67 }
68 void
70 {
71  m_ctrlToDs = 1;
72 }
73 void
75 {
76  m_ctrlToDs = 0;
77 }
78 
79 void
81 {
82  m_addr1 = address;
83 }
84 void
86 {
87  m_addr2 = address;
88 }
89 void
91 {
92  m_addr3 = address;
93 }
94 void
96 {
97  m_addr4 = address;
98 }
99 void
101 {
103  m_ctrlSubtype = 0;
104 }
105 void
107 {
109  m_ctrlSubtype = 1;
110 }
111 void
113 {
115  m_ctrlSubtype = 4;
116 }
117 void
119 {
121  m_ctrlSubtype = 5;
122 }
123 void
125 {
127  m_ctrlSubtype = 8;
128 }
129 void
131 {
133  m_ctrlSubtype = 8;
134 }
135 void
137 {
139  m_ctrlSubtype = 9;
140 }
141 
142 void
144 {
146  m_ctrlSubtype = 0;
147 }
148 void
150 {
152  m_ctrlSubtype = 0x0D;
153 }
154 void
156 {
158  m_ctrlSubtype = 0x0F;
159 }
160 void
162 {
163  switch (type)
164  {
168  break;
172  break;
173  case WIFI_MAC_CTL_RTS:
176  break;
177  case WIFI_MAC_CTL_CTS:
180  break;
181  case WIFI_MAC_CTL_ACK:
184  break;
187  m_ctrlSubtype = 0;
188  break;
191  m_ctrlSubtype = 1;
192  break;
195  m_ctrlSubtype = 2;
196  break;
199  m_ctrlSubtype = 3;
200  break;
203  m_ctrlSubtype = 4;
204  break;
207  m_ctrlSubtype = 5;
208  break;
209  case WIFI_MAC_MGT_BEACON:
211  m_ctrlSubtype = 8;
212  break;
215  m_ctrlSubtype = 10;
216  break;
219  m_ctrlSubtype = 11;
220  break;
223  m_ctrlSubtype = 12;
224  case WIFI_MAC_MGT_ACTION:
226  m_ctrlSubtype = 13;
229  m_ctrlSubtype = 14;
232  m_ctrlSubtype = 15;
233  break;
234 
235  case WIFI_MAC_DATA:
237  m_ctrlSubtype = 0;
238  break;
239  case WIFI_MAC_DATA_CFACK:
241  m_ctrlSubtype = 1;
242  break;
245  m_ctrlSubtype = 2;
246  break;
249  m_ctrlSubtype = 3;
250  break;
251  case WIFI_MAC_DATA_NULL:
253  m_ctrlSubtype = 4;
254  break;
257  m_ctrlSubtype = 5;
258  break;
261  m_ctrlSubtype = 6;
262  break;
265  m_ctrlSubtype = 7;
266  break;
267  case WIFI_MAC_QOSDATA:
269  m_ctrlSubtype = 8;
270  break;
273  m_ctrlSubtype = 9;
274  break;
277  m_ctrlSubtype = 10;
278  break;
281  m_ctrlSubtype = 11;
282  break;
285  m_ctrlSubtype = 12;
286  break;
289  m_ctrlSubtype = 14;
290  break;
293  m_ctrlSubtype = 15;
294  break;
295  }
296  m_ctrlToDs = 0;
297  m_ctrlFromDs = 0;
298 }
299 void
300 WifiMacHeader::SetRawDuration (uint16_t duration)
301 {
302  m_duration = duration;
303 }
304 void
306 {
307  int64_t duration_us = duration.GetMicroSeconds ();
308  NS_ASSERT (duration_us >= 0 && duration_us <= 0x7fff);
309  m_duration = static_cast<uint16_t> (duration_us);
310 }
311 
312 void WifiMacHeader::SetId (uint16_t id)
313 {
314  m_duration = id;
315 }
317 {
318  m_seqSeq = seq;
319 }
321 {
322  m_seqFrag = frag;
323 }
325 {
326  m_ctrlMoreFrag = 0;
327 }
329 {
330  m_ctrlMoreFrag = 1;
331 }
333 {
334  m_ctrlRetry = 1;
335 }
337 {
338  m_ctrlRetry = 0;
339 }
340 void WifiMacHeader::SetQosTid (uint8_t tid)
341 {
342  m_qosTid = tid;
343 }
345 {
346  m_qosEosp = 1;
347 }
349 {
350  m_qosEosp = 0;
351 }
353 {
354  switch (policy)
355  {
356  case NORMAL_ACK:
357  m_qosAckPolicy = 0;
358  break;
359  case NO_ACK:
360  m_qosAckPolicy = 1;
361  break;
362  case NO_EXPLICIT_ACK:
363  m_qosAckPolicy = 2;
364  break;
365  case BLOCK_ACK:
366  m_qosAckPolicy = 3;
367  break;
368  }
369 }
370 void
372 {
373  m_qosAckPolicy = 0;
374 }
375 void
377 {
378  m_qosAckPolicy = 3;
379 }
380 void
382 {
383  m_qosAckPolicy = 1;
384 }
386 {
387  m_amsduPresent = 1;
388 }
390 {
391  m_amsduPresent = 0;
392 }
394 {
395  m_qosStuff = txop;
396 }
397 
400 {
401  return m_addr1;
402 }
405 {
406  return m_addr2;
407 }
410 {
411  return m_addr3;
412 }
415 {
416  return m_addr4;
417 }
418 
419 enum WifiMacType
421 {
422  switch (m_ctrlType)
423  {
424  case TYPE_MGT:
425  switch (m_ctrlSubtype)
426  {
427  case 0:
429  break;
430  case 1:
432  break;
433  case 2:
435  break;
436  case 3:
438  break;
439  case 4:
441  break;
442  case 5:
444  break;
445  case 8:
446  return WIFI_MAC_MGT_BEACON;
447  break;
448  case 10:
450  break;
451  case 11:
453  break;
454  case 12:
456  break;
457  case 13:
458  return WIFI_MAC_MGT_ACTION;
459  break;
460  case 14:
462  break;
463  case 15:
465  break;
466 
467  }
468  break;
469  case TYPE_CTL:
470  switch (m_ctrlSubtype)
471  {
472  case SUBTYPE_CTL_BACKREQ:
473  return WIFI_MAC_CTL_BACKREQ;
474  break;
476  return WIFI_MAC_CTL_BACKRESP;
477  break;
478  case SUBTYPE_CTL_RTS:
479  return WIFI_MAC_CTL_RTS;
480  break;
481  case SUBTYPE_CTL_CTS:
482  return WIFI_MAC_CTL_CTS;
483  break;
484  case SUBTYPE_CTL_ACK:
485  return WIFI_MAC_CTL_ACK;
486  break;
487  }
488  break;
489  case TYPE_DATA:
490  switch (m_ctrlSubtype)
491  {
492  case 0:
493  return WIFI_MAC_DATA;
494  break;
495  case 1:
496  return WIFI_MAC_DATA_CFACK;
497  break;
498  case 2:
499  return WIFI_MAC_DATA_CFPOLL;
500  break;
501  case 3:
503  break;
504  case 4:
505  return WIFI_MAC_DATA_NULL;
506  break;
507  case 5:
509  break;
510  case 6:
512  break;
513  case 7:
515  break;
516  case 8:
517  return WIFI_MAC_QOSDATA;
518  break;
519  case 9:
520  return WIFI_MAC_QOSDATA_CFACK;
521  break;
522  case 10:
524  break;
525  case 11:
527  break;
528  case 12:
529  return WIFI_MAC_QOSDATA_NULL;
530  break;
531  case 14:
533  break;
534  case 15:
536  break;
537 
538  }
539  break;
540  }
541  // NOTREACHED
542  NS_ASSERT (false);
543  return (enum WifiMacType)-1;
544 }
545 bool
547 {
548  return m_ctrlFromDs == 1;
549 }
550 bool
552 {
553  return m_ctrlToDs == 1;
554 }
555 
556 bool
558 {
559  return (m_ctrlType == TYPE_DATA);
560 
561 }
562 bool
564 {
565  return (m_ctrlType == TYPE_DATA && (m_ctrlSubtype & 0x08));
566 }
567 bool
569 {
570  return (m_ctrlType == TYPE_CTL);
571 }
572 bool
574 {
575  return (m_ctrlType == TYPE_MGT);
576 }
577 bool
579 {
580  switch (GetType ())
581  {
590  return true;
591  break;
592  default:
593  return false;
594  break;
595  }
596 }
597 bool
599 {
600  return (GetType () == WIFI_MAC_CTL_RTS);
601 }
602 bool
604 {
605  return (GetType () == WIFI_MAC_CTL_CTS);
606 }
607 bool
609 {
610  return (GetType () == WIFI_MAC_CTL_ACK);
611 }
612 bool
614 {
616 }
617 bool
619 {
621 }
622 bool
624 {
626 }
627 bool
629 {
631 }
632 bool
634 {
635  return (GetType () == WIFI_MAC_MGT_PROBE_REQUEST);
636 }
637 bool
639 {
640  return (GetType () == WIFI_MAC_MGT_PROBE_RESPONSE);
641 }
642 bool
644 {
645  return (GetType () == WIFI_MAC_MGT_BEACON);
646 }
647 bool
649 {
650  return (GetType () == WIFI_MAC_MGT_DISASSOCIATION);
651 }
652 bool
654 {
655  return (GetType () == WIFI_MAC_MGT_AUTHENTICATION);
656 }
657 bool
659 {
660  return (GetType () == WIFI_MAC_MGT_DEAUTHENTICATION);
661 }
662 bool
664 {
665  return (GetType () == WIFI_MAC_MGT_ACTION);
666 }
667 bool
669 {
670  return (GetType () == WIFI_MAC_MGT_MULTIHOP_ACTION);
671 }
672 bool
674 {
675  return (GetType () == WIFI_MAC_CTL_BACKREQ) ? true : false;
676 }
677 bool
679 {
680  return (GetType () == WIFI_MAC_CTL_BACKRESP) ? true : false;
681 }
682 
683 
684 uint16_t
686 {
687  return m_duration;
688 }
689 Time
691 {
692  return MicroSeconds (m_duration);
693 }
694 uint16_t
696 {
697  return (m_seqSeq << 4) | m_seqFrag;
698 }
699 uint16_t
701 {
702  return m_seqSeq;
703 }
704 uint16_t
706 {
707  return m_seqFrag;
708 }
709 bool
711 {
712  return (m_ctrlRetry == 1);
713 }
714 bool
716 {
717  return (m_ctrlMoreFrag == 1);
718 }
719 bool
721 {
722  NS_ASSERT (IsQosData ());
723  return (m_qosAckPolicy == 3);
724 }
725 bool
727 {
728  NS_ASSERT (IsQosData ());
729  return (m_qosAckPolicy == 1);
730 }
731 bool
733 {
734  NS_ASSERT (IsQosData ());
735  return (m_qosAckPolicy == 0);
736 }
737 bool
739 {
740  NS_ASSERT (IsQosData ());
741  return (m_qosEosp == 1);
742 }
743 bool
745 {
746  NS_ASSERT (IsQosData ());
747  return (m_amsduPresent == 1);
748 }
749 uint8_t
751 {
752  NS_ASSERT (IsQosData ());
753  return m_qosTid;
754 }
757 {
758  switch (m_qosAckPolicy)
759  {
760  case 0:
761  return NORMAL_ACK;
762  break;
763  case 1:
764  return NO_ACK;
765  break;
766  case 2:
767  return NO_EXPLICIT_ACK;
768  break;
769  case 3:
770  return BLOCK_ACK;
771  break;
772  }
773  // NOTREACHED
774  NS_ASSERT (false);
775  return (enum QosAckPolicy)-1;
776 }
777 
778 uint8_t
780 {
781  NS_ASSERT (IsQosData ());
782  return m_qosStuff;
783 }
784 
785 uint16_t
787 {
788  uint16_t val = 0;
789  val |= (m_ctrlType << 2) & (0x3 << 2);
790  val |= (m_ctrlSubtype << 4) & (0xf << 4);
791  val |= (m_ctrlToDs << 8) & (0x1 << 8);
792  val |= (m_ctrlFromDs << 9) & (0x1 << 9);
793  val |= (m_ctrlMoreFrag << 10) & (0x1 << 10);
794  val |= (m_ctrlRetry << 11) & (0x1 << 11);
795  val |= (m_ctrlMoreData << 13) & (0x1 << 13);
796  val |= (m_ctrlWep << 14) & (0x1 << 14);
797  val |= (m_ctrlOrder << 15) & (0x1 << 15);
798  return val;
799 }
800 
801 uint16_t
803 {
804  uint16_t val = 0;
805  val |= m_qosTid;
806  val |= m_qosEosp << 4;
807  val |= m_qosAckPolicy << 5;
808  val |= m_amsduPresent << 7;
809  val |= m_qosStuff << 8;
810  return val;
811 }
812 
813 void
815 {
816  m_ctrlType = (ctrl >> 2) & 0x03;
817  m_ctrlSubtype = (ctrl >> 4) & 0x0f;
818  m_ctrlToDs = (ctrl >> 8) & 0x01;
819  m_ctrlFromDs = (ctrl >> 9) & 0x01;
820  m_ctrlMoreFrag = (ctrl >> 10) & 0x01;
821  m_ctrlRetry = (ctrl >> 11) & 0x01;
822  m_ctrlMoreData = (ctrl >> 13) & 0x01;
823  m_ctrlWep = (ctrl >> 14) & 0x01;
824  m_ctrlOrder = (ctrl >> 15) & 0x01;
825 }
826 void
828 {
829  m_seqFrag = seq & 0x0f;
830  m_seqSeq = (seq >> 4) & 0x0fff;
831 }
832 void
834 {
835  m_qosTid = qos & 0x000f;
836  m_qosEosp = (qos >> 4) & 0x0001;
837  m_qosAckPolicy = (qos >> 5) & 0x0003;
838  m_amsduPresent = (qos >> 7) & 0x0001;
839  m_qosStuff = (qos >> 8) & 0x00ff;
840 }
841 
842 uint32_t
844 {
845  uint32_t size = 0;
846  switch (m_ctrlType)
847  {
848  case TYPE_MGT:
849  size = 2 + 2 + 6 + 6 + 6 + 2;
850  break;
851  case TYPE_CTL:
852  switch (m_ctrlSubtype)
853  {
854  case SUBTYPE_CTL_RTS:
855  size = 2 + 2 + 6 + 6;
856  break;
857  case SUBTYPE_CTL_CTS:
858  case SUBTYPE_CTL_ACK:
859  size = 2 + 2 + 6;
860  break;
861  case SUBTYPE_CTL_BACKREQ:
863  size = 2 + 2 + 6 + 6;
864  break;
865  }
866  break;
867  case TYPE_DATA:
868  size = 2 + 2 + 6 + 6 + 6 + 2;
869  if (m_ctrlToDs && m_ctrlFromDs)
870  {
871  size += 6;
872  }
873  if (m_ctrlSubtype & 0x08)
874  {
875  size += 2;
876  }
877  break;
878  }
879  return size;
880 }
881 const char *
883 {
884 #define FOO(x) \
885 case WIFI_MAC_ ## x: \
886  return # x; \
887  break;
888 
889  switch (GetType ())
890  {
891  FOO (CTL_RTS);
892  FOO (CTL_CTS);
893  FOO (CTL_ACK);
894  FOO (CTL_BACKREQ);
895  FOO (CTL_BACKRESP);
896 
897  FOO (MGT_BEACON);
898  FOO (MGT_ASSOCIATION_REQUEST);
899  FOO (MGT_ASSOCIATION_RESPONSE);
900  FOO (MGT_DISASSOCIATION);
901  FOO (MGT_REASSOCIATION_REQUEST);
902  FOO (MGT_REASSOCIATION_RESPONSE);
903  FOO (MGT_PROBE_REQUEST);
904  FOO (MGT_PROBE_RESPONSE);
905  FOO (MGT_AUTHENTICATION);
906  FOO (MGT_DEAUTHENTICATION);
907  FOO (MGT_ACTION);
908  FOO (MGT_ACTION_NO_ACK);
909  FOO (MGT_MULTIHOP_ACTION);
910 
911  FOO (DATA);
912  FOO (DATA_CFACK);
913  FOO (DATA_CFPOLL);
914  FOO (DATA_CFACK_CFPOLL);
915  FOO (DATA_NULL);
916  FOO (DATA_NULL_CFACK);
917  FOO (DATA_NULL_CFPOLL);
918  FOO (DATA_NULL_CFACK_CFPOLL);
919  FOO (QOSDATA);
920  FOO (QOSDATA_CFACK);
921  FOO (QOSDATA_CFPOLL);
922  FOO (QOSDATA_CFACK_CFPOLL);
923  FOO (QOSDATA_NULL);
924  FOO (QOSDATA_NULL_CFPOLL);
925  FOO (QOSDATA_NULL_CFACK_CFPOLL);
926  default:
927  return "ERROR";
928  }
929 #undef FOO
930  // needed to make gcc 4.0.1 ppc darwin happy.
931  return "BIG_ERROR";
932 }
933 
934 TypeId
936 {
937  static TypeId tid = TypeId ("ns3::WifiMacHeader")
938  .SetParent<Header> ()
939  .AddConstructor<WifiMacHeader> ()
940  ;
941  return tid;
942 }
943 
944 TypeId
946 {
947  return GetTypeId ();
948 }
949 
950 void
951 WifiMacHeader::PrintFrameControl (std::ostream &os) const
952 {
953  os << "ToDS=" << std::hex << (int) m_ctrlToDs << ", FromDS=" << std::hex << (int) m_ctrlFromDs
954  << ", MoreFrag=" << std::hex << (int) m_ctrlMoreFrag << ", Retry=" << std::hex << (int) m_ctrlRetry
955  << ", MoreData=" << std::hex << (int) m_ctrlMoreData << std::dec
956  ;
957 }
958 
959 void
960 WifiMacHeader::Print (std::ostream &os) const
961 {
962  os << GetTypeString () << " ";
963  switch (GetType ())
964  {
965  case WIFI_MAC_CTL_RTS:
966  os << "Duration/ID=" << m_duration << "us"
967  << ", RA=" << m_addr1 << ", TA=" << m_addr2;
968  break;
969  case WIFI_MAC_CTL_CTS:
970  case WIFI_MAC_CTL_ACK:
971  os << "Duration/ID=" << m_duration << "us"
972  << ", RA=" << m_addr1;
973  break;
975  break;
977  break;
978 
979  case WIFI_MAC_MGT_BEACON:
989  PrintFrameControl (os);
990  os << " Duration/ID=" << m_duration << "us"
991  << ", DA=" << m_addr1 << ", SA=" << m_addr2
992  << ", BSSID=" << m_addr3 << ", FragNumber=" << std::hex << (int) m_seqFrag << std::dec
993  << ", SeqNumber=" << m_seqSeq;
994  break;
995  case WIFI_MAC_MGT_ACTION:
997  PrintFrameControl (os);
998  os << " Duration/ID=" << m_duration << "us"
999  << "DA=" << m_addr1 << ", SA=" << m_addr2 << ", BSSID=" << m_addr3
1000  << ", FragNumber=" << std::hex << (int) m_seqFrag << std::dec << ", SeqNumber=" << m_seqSeq;
1002  os << " Duration/ID=" << m_duration << "us"
1003  << "RA=" << m_addr1 << ", TA=" << m_addr2 << ", DA=" << m_addr3
1004  << ", FragNumber=" << std::hex << (int) m_seqFrag << std::dec << ", SeqNumber=" << m_seqSeq;
1005  case WIFI_MAC_DATA:
1006  PrintFrameControl (os);
1007  os << " Duration/ID=" << m_duration << "us";
1008  if (!m_ctrlToDs && !m_ctrlFromDs)
1009  {
1010  os << "DA=" << m_addr1 << ", SA=" << m_addr2 << ", BSSID=" << m_addr3;
1011  }
1012  else if (!m_ctrlToDs && m_ctrlFromDs)
1013  {
1014  os << "DA=" << m_addr1 << ", SA=" << m_addr3 << ", BSSID=" << m_addr2;
1015  }
1016  else if (m_ctrlToDs && !m_ctrlFromDs)
1017  {
1018  os << "DA=" << m_addr3 << ", SA=" << m_addr2 << ", BSSID=" << m_addr1;
1019  }
1020  else if (m_ctrlToDs && m_ctrlFromDs)
1021  {
1022  os << "DA=" << m_addr3 << ", SA=" << m_addr4 << ", RA=" << m_addr1 << ", TA=" << m_addr2;
1023  }
1024  else
1025  {
1026  NS_FATAL_ERROR ("Impossible ToDs and FromDs flags combination");
1027  }
1028  os << ", FragNumber=" << std::hex << (int) m_seqFrag << std::dec
1029  << ", SeqNumber=" << m_seqSeq;
1030  break;
1031  case WIFI_MAC_DATA_CFACK:
1032  case WIFI_MAC_DATA_CFPOLL:
1034  case WIFI_MAC_DATA_NULL:
1038  case WIFI_MAC_QOSDATA:
1042  case WIFI_MAC_QOSDATA_NULL:
1045  break;
1046  }
1047 }
1048 uint32_t
1050 {
1051  return GetSize ();
1052 }
1053 void
1055 {
1058  WriteTo (i, m_addr1);
1059  switch (m_ctrlType)
1060  {
1061  case TYPE_MGT:
1062  WriteTo (i, m_addr2);
1063  WriteTo (i, m_addr3);
1065  break;
1066  case TYPE_CTL:
1067  switch (m_ctrlSubtype)
1068  {
1069  case SUBTYPE_CTL_RTS:
1070  WriteTo (i, m_addr2);
1071  break;
1072  case SUBTYPE_CTL_CTS:
1073  case SUBTYPE_CTL_ACK:
1074  break;
1075  case SUBTYPE_CTL_BACKREQ:
1076  case SUBTYPE_CTL_BACKRESP:
1077  WriteTo (i, m_addr2);
1078  break;
1079  default:
1080  //NOTREACHED
1081  NS_ASSERT (false);
1082  break;
1083  }
1084  break;
1085  case TYPE_DATA:
1086  {
1087  WriteTo (i, m_addr2);
1088  WriteTo (i, m_addr3);
1090  if (m_ctrlToDs && m_ctrlFromDs)
1091  {
1092  WriteTo (i, m_addr4);
1093  }
1094  if (m_ctrlSubtype & 0x08)
1095  {
1097  }
1098  } break;
1099  default:
1100  //NOTREACHED
1101  NS_ASSERT (false);
1102  break;
1103  }
1104 }
1105 uint32_t
1107 {
1108  Buffer::Iterator i = start;
1109  uint16_t frame_control = i.ReadLsbtohU16 ();
1110  SetFrameControl (frame_control);
1111  m_duration = i.ReadLsbtohU16 ();
1112  ReadFrom (i, m_addr1);
1113  switch (m_ctrlType)
1114  {
1115  case TYPE_MGT:
1116  ReadFrom (i, m_addr2);
1117  ReadFrom (i, m_addr3);
1119  break;
1120  case TYPE_CTL:
1121  switch (m_ctrlSubtype)
1122  {
1123  case SUBTYPE_CTL_RTS:
1124  ReadFrom (i, m_addr2);
1125  break;
1126  case SUBTYPE_CTL_CTS:
1127  case SUBTYPE_CTL_ACK:
1128  break;
1129  case SUBTYPE_CTL_BACKREQ:
1130  case SUBTYPE_CTL_BACKRESP:
1131  ReadFrom (i, m_addr2);
1132  break;
1133  }
1134  break;
1135  case TYPE_DATA:
1136  ReadFrom (i, m_addr2);
1137  ReadFrom (i, m_addr3);
1139  if (m_ctrlToDs && m_ctrlFromDs)
1140  {
1141  ReadFrom (i, m_addr4);
1142  }
1143  if (m_ctrlSubtype & 0x08)
1144  {
1146  }
1147  break;
1148  }
1149  return i.GetDistanceFrom (start);
1150 }
1151 
1152 } // namespace ns3