A Discrete-Event Network Simulator
API
wifi-information-element.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010 Dean Armstrong
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: Dean Armstrong <deanarm@gmail.com>
18  */
19 
21 
22 namespace ns3
23 {
24 
26 {
27 }
28 
29 void
30 WifiInformationElement::Print(std::ostream& os) const
31 {
32 }
33 
34 uint16_t
36 {
37  uint16_t size = GetInformationFieldSize();
38 
39  if (size <= 255) // size includes the Element ID Extension field
40  {
41  return (2 + size);
42  }
43 
44  // the element needs to be fragmented (Sec. 10.28.11 of 802.11-2020)
45  // Let M be the number of IEs of maximum size
46  uint16_t m = size / 255;
47  // N equals 1 if an IE not of maximum size is present at the end, 0 otherwise
48  uint8_t remainder = size % 255;
49  uint8_t n = (remainder > 0) ? 1 : 0;
50 
51  return m * (2 + 255) + n * (2 + remainder);
52 }
53 
56 {
57  return 0;
58 }
59 
62 {
63  auto size = GetInformationFieldSize();
64 
65  if (size > 255)
66  {
67  return SerializeFragments(i, size);
68  }
69 
70  i.WriteU8(ElementId());
71  i.WriteU8(size);
72  if (ElementId() == IE_EXTENSION)
73  {
74  i.WriteU8(ElementIdExt());
76  i.Next(size - 1);
77  }
78  else
79  {
81  i.Next(size);
82  }
83  return i;
84 }
85 
88 {
89  NS_ASSERT(size > 255);
90  // let the subclass serialize the IE in a temporary buffer
91  Buffer buffer;
92  buffer.AddAtStart(size);
93  Buffer::Iterator source = buffer.Begin();
95 
96  // Let M be the number of IEs of maximum size
97  uint16_t m = size / 255;
98 
99  for (uint16_t index = 0; index < m; index++)
100  {
101  i.WriteU8((index == 0) ? ElementId() : IE_FRAGMENT);
102  i.WriteU8(255);
103  uint8_t length = 255;
104  if (index == 0 && ElementId() == IE_EXTENSION)
105  {
106  i.WriteU8(ElementIdExt());
107  length = 254;
108  }
109  for (uint8_t count = 0; count < length; count++)
110  {
111  i.WriteU8(source.ReadU8());
112  }
113  }
114 
115  // last fragment
116  uint8_t remainder = size % 255;
117 
118  if (remainder > 0)
119  {
120  i.WriteU8(IE_FRAGMENT);
121  i.WriteU8(remainder);
122  for (uint8_t count = 0; count < remainder; count++)
123  {
124  i.WriteU8(source.ReadU8());
125  }
126  }
127 
128  return i;
129 }
130 
133 {
135  i = DeserializeIfPresent(i);
136  // This IE was not optional, so confirm that we did actually
137  // deserialise something.
139  return i;
140 }
141 
144 {
145  if (i.IsEnd())
146  {
147  return i;
148  }
150  uint8_t elementId = i.ReadU8();
151 
152  // If the element here isn't the one we're after then we immediately
153  // return the iterator we were passed indicating that we haven't
154  // taken anything from the buffer.
155  if (elementId != ElementId())
156  {
157  return start;
158  }
159 
160  uint16_t length = i.ReadU8();
161  if (ElementId() == IE_EXTENSION)
162  {
163  uint8_t elementIdExt = i.ReadU8();
164  // If the element here isn't the one we're after then we immediately
165  // return the iterator we were passed indicating that we haven't
166  // taken anything from the buffer.
167  if (elementIdExt != ElementIdExt())
168  {
169  return start;
170  }
171  length--;
172  }
173 
174  return DoDeserialize(i, length);
175 }
176 
179 {
180  uint16_t limit = (ElementId() == IE_EXTENSION) ? 254 : 255;
181 
182  auto tmp = i;
183  tmp.Next(length); // tmp points to past the last byte of the IE/first fragment
184 
185  if (length < limit || tmp.IsEnd() || (tmp.PeekU8() != IE_FRAGMENT))
186  {
187  // no fragments
188  DeserializeInformationField(i, length);
189  return tmp;
190  }
191 
192  NS_ASSERT(length == limit);
193 
194  // the IE is fragmented, create a new buffer for the subclass to deserialize from.
195  // Such a destination buffer will not contain the Element ID and Length fields
196  Buffer buffer; // destination buffer
197  buffer.AddAtStart(length); // size of the first fragment
198  Buffer::Iterator bufferIt = buffer.Begin();
199 
200  uint16_t count = length;
201  length = 0; // reset length
202 
203  // Loop invariant:
204  // - i points to the first byte of the fragment to copy (current fragment)
205  // - bufferIt points to the first location of the destination buffer to write
206  // - there is room in the destination buffer to write the current fragment
207  // - count is the size in bytes of the current fragment
208  // - length is the number of bytes written into the destination buffer
209  while (true)
210  {
211  for (uint16_t index = 0; index < count; index++)
212  {
213  bufferIt.WriteU8(i.ReadU8());
214  }
215  length += count;
216 
217  if (i.IsEnd() || (i.PeekU8() != IE_FRAGMENT))
218  {
219  break;
220  }
221  i.Next(1); // skip the Element ID byte
222  count = i.ReadU8(); // length of the next fragment
223 
224  buffer.AddAtEnd(count);
225  bufferIt = buffer.Begin();
226  bufferIt.Next(length);
227  }
228 
229  DeserializeInformationField(buffer.Begin(), length);
230  return i;
231 }
232 
233 bool
235 {
236  if (ElementId() != a.ElementId())
237  {
238  return false;
239  }
240 
241  if (ElementIdExt() != a.ElementIdExt())
242  {
243  return false;
244  }
245 
246  uint32_t ieSize = GetSerializedSize();
247 
248  if (ieSize != a.GetSerializedSize())
249  {
250  return false;
251  }
252 
253  Buffer myIe;
254  Buffer hisIe;
255  myIe.AddAtEnd(ieSize);
256  hisIe.AddAtEnd(ieSize);
257 
258  Serialize(myIe.Begin());
259  a.Serialize(hisIe.Begin());
260 
261  return (memcmp(myIe.PeekData(), hisIe.PeekData(), ieSize) == 0);
262 }
263 
264 std::ostream&
265 operator<<(std::ostream& os, const WifiInformationElement& element)
266 {
267  element.Print(os);
268  return os;
269 }
270 
271 } // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
uint8_t PeekU8()
Definition: buffer.h:1006
bool IsEnd() const
Definition: buffer.cc:796
uint32_t GetDistanceFrom(const Iterator &o) const
Definition: buffer.cc:780
void Next()
go forward by one byte
Definition: buffer.h:853
automatically resized byte buffer
Definition: buffer.h:94
void AddAtStart(uint32_t start)
Definition: buffer.cc:314
Buffer::Iterator Begin() const
Definition: buffer.h:1074
void AddAtEnd(uint32_t end)
Definition: buffer.cc:360
const uint8_t * PeekData() const
Definition: buffer.cc:703
Information element, as defined in 802.11-2007 standard.
virtual WifiInformationElementId ElementId() const =0
Get the wifi information element ID.
uint16_t GetSerializedSize() const
Get the size of the serialized IE including Element ID and length fields (for every element this IE i...
Buffer::Iterator Deserialize(Buffer::Iterator i)
Deserialize entire IE (which may possibly be fragmented into multiple elements), which must be presen...
Buffer::Iterator Serialize(Buffer::Iterator i) const
Serialize entire IE including Element ID and length fields.
virtual uint16_t DeserializeInformationField(Buffer::Iterator start, uint16_t length)=0
Deserialize information (i.e., the body of the IE, not including the Element ID and length octets)
Buffer::Iterator DeserializeIfPresent(Buffer::Iterator i)
Deserialize entire IE (which may possibly be fragmented into multiple elements) if it is present.
Buffer::Iterator SerializeFragments(Buffer::Iterator i, uint16_t size) const
Serialize an IE that needs to be fragmented.
virtual void Print(std::ostream &os) const
Generate human-readable form of IE.
virtual void SerializeInformationField(Buffer::Iterator start) const =0
Serialize information (i.e., the body of the IE, not including the Element ID and length octets)
virtual uint16_t GetInformationFieldSize() const =0
Length of serialized information (i.e., the length of the body of the IE, not including the Element I...
virtual WifiInformationElementId ElementIdExt() const
Get the wifi information element ID extension.
Buffer::Iterator DoDeserialize(Buffer::Iterator i, uint16_t length)
Deserialize the Information field of an IE.
virtual bool operator==(const WifiInformationElement &a) const
Compare two IEs for equality by ID & Length, and then through memcmp of serialised version.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
uint8_t WifiInformationElementId
This type is used to represent an Information Element ID.
#define IE_FRAGMENT
#define IE_EXTENSION