A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
22namespace ns3
23{
24
26{
27}
28
29void
30WifiInformationElement::Print(std::ostream& os) const
31{
32}
33
34uint16_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 {
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 {
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 {
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{
134 Buffer::Iterator start = i;
136 // This IE was not optional, so confirm that we did actually
137 // deserialise something.
138 NS_ASSERT(i.GetDistanceFrom(start) != 0);
139 return i;
140}
141
144{
145 if (i.IsEnd())
146 {
147 return i;
148 }
149 Buffer::Iterator start = i;
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
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
233bool
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
264std::ostream&
265operator<<(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