A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tim.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
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: Davide Magrin <davide@magr.in>
18 */
19
20#include "tim.h"
21
22#include <algorithm>
23#include <cstdint>
24
25namespace ns3
26{
27
30{
31 return IE_TIM;
32}
33
34uint16_t
36{
37 // When the TIM is carried in a non-S1G PPDU, in the event that all bits other than bit 0 in
38 // the traffic indication virtual bitmap are 0, the Partial Virtual Bitmap field is encoded as
39 // a single octet equal to 0, the Bitmap Offset subfield is 0, and the Length field is 4.
40 // (Sec. 9.4.2.5.1 of 802.11-2020)
41 // The size of the information field is the size of the Partial Virtual Bitmap field,
42 // plus one octet each for the DTIM Count, DTIM Period, and Bitmap Control fields
43 uint16_t partialVirtualBitmapSize =
45 return partialVirtualBitmapSize + 3;
46}
47
48void
49Tim::AddAid(uint16_t aid)
50{
51 NS_ABORT_IF(aid > 2007);
52
53 m_aidValues.insert(aid);
54}
55
56bool
57Tim::HasAid(uint16_t aid) const
58{
59 return m_aidValues.find(aid) != m_aidValues.end();
60}
61
62std::set<uint16_t>
63Tim::GetAidSet(uint16_t aid) const
64{
65 auto start = m_aidValues.upper_bound(aid);
66 return std::set<uint16_t>(start, m_aidValues.cend());
67}
68
69void
71{
72 start.WriteU8(m_dtimCount);
73 start.WriteU8(m_dtimPeriod);
74
75 // the Bitmap Control field is optional if the TIM is carried in an S1G PPDU, while
76 // it is always present when the TIM is carried in a non-S1G PPDU
77 start.WriteU8(GetBitmapControl());
78 auto partialVirtualBitmap = GetPartialVirtualBitmap();
79 for (auto byte : partialVirtualBitmap)
80 {
81 start.WriteU8(byte);
82 }
83}
84
85uint16_t
87{
88 NS_ABORT_MSG_IF(length < 2, "Invalid length: " << length);
89
90 m_dtimCount = start.ReadU8();
91 m_dtimPeriod = start.ReadU8();
92
93 if (length == 2)
94 {
95 // no Bitmap Control field nor Partial Virtual Bitmap field
96 return 2;
97 }
98
99 // Bitmap control field: here we determine the presence of multicast traffic and the offset
100 auto bitmapControl = start.ReadU8();
101 // Least significant bit is the Traffic Indication field
102 m_hasMulticastPending = bitmapControl & 0x01;
103 // Other bits are the Bitmap Offset
104 uint8_t partialVirtualBitmapOffset = bitmapControl & 0xFE;
105 // Next, deserialize the partial virtual bitmap
106 uint16_t octetIndex;
107 // length is the length of the information fields, so we need to
108 // subtract 3 to get the length of the Partial Virtual Bitmap
109 for (octetIndex = partialVirtualBitmapOffset;
110 octetIndex < static_cast<uint16_t>(partialVirtualBitmapOffset + length - 3);
111 ++octetIndex)
112 {
113 if (auto octet = start.ReadU8(); octet > 0)
114 {
115 // Look for bits set to 1
116 for (uint8_t position = 0; position < 8; position++)
117 {
118 if ((octet >> position) & 0x1)
119 {
120 m_aidValues.insert(GetAidFromOctetIndexAndBitPosition(octetIndex, position));
121 }
122 }
123 }
124 }
125 return 3 + octetIndex - partialVirtualBitmapOffset;
126}
127
128uint8_t
129Tim::GetAidOctetIndex(uint16_t aid) const
130{
131 // bit number N (0 <= N <= 2007) in the bitmap corresponds to bit number (N mod 8) in octet
132 // number |_N / 8_| where the low order bit of each octet is bit number 0, and the high order
133 // bit is bit number 7 (Sec. 9.4.2.5.1 of 802.11-2020)
134 return (aid >> 3) & 0xff;
135}
136
137uint8_t
138Tim::GetAidBit(uint16_t aid) const
139{
140 // bit number N (0 <= N <= 2007) in the bitmap corresponds to bit number (N mod 8) in octet
141 // number |_N / 8_| where the low order bit of each octet is bit number 0, and the high order
142 // bit is bit number 7 (Sec. 9.4.2.5.1 of 802.11-2020)
143 return 0x01 << (aid & 0x07);
144}
145
146uint16_t
147Tim::GetAidFromOctetIndexAndBitPosition(uint16_t octet, uint8_t position) const
148{
149 return (octet << 3) + position;
150}
151
152uint8_t
154{
155 if (m_aidValues.empty())
156 {
157 return 0;
158 }
159 // N1 is the largest even number such that bits numbered 1 to (N1 * 8) – 1 in the traffic
160 // indication virtual bitmap are all 0 (Sec. 9.4.2.5.1 of 802.11-2020).
161 // Examples:
162 // first bit set = 53, which belongs to octet 53 / 8 = 6 -> N1 = 6 (all bits 1 - 47 are zero)
163 // first bit set = 61, which belongs to octet 61 / 8 = 7 -> N1 = 6 (all bits 1 - 47 are zero)
164 return GetAidOctetIndex(*m_aidValues.cbegin()) & 0xFE;
165}
166
167uint8_t
169{
170 if (m_aidValues.empty())
171 {
172 return 0;
173 }
174 // N2 is the smallest number such that bits numbered (N2 + 1) * 8 to 2007 in the traffic
175 // indication virtual bitmap are all 0 (Sec. 9.4.2.5.1 of 802.11-2020).
176 // Examples:
177 // last bit set = 53, which belongs to octet 53 / 8 = 6 -> N2 = 6 (all bits 56 - 2007 are zero)
178 // last bit set = 61, which belongs to octet 61 / 8 = 7 -> N2 = 7 (all bits 64 - 2007 are zero)
179 return GetAidOctetIndex(*m_aidValues.rbegin());
180}
181
182uint8_t
184{
185 // Note that setting the bitmapControl directly as the offset can be done because the least
186 // significant bit of the output of GetPartialVirtualBitmapOffset will always be zero, so we
187 // are already putting the relevant information in the appropriate part of the byte.
188 auto bitmapControl = GetPartialVirtualBitmapOffset();
189
190 // Set the multicast indication bit, if this is a DTIM
192 {
193 bitmapControl |= 0x01;
194 }
195
196 return bitmapControl;
197}
198
199std::vector<uint8_t>
201{
202 auto offset = GetPartialVirtualBitmapOffset(); // N1
203
204 // the Partial Virtual Bitmap field consists of octets numbered N1 to N2 of the traffic
205 // indication virtual bitmap (Sec. 9.4.2.5.1 of 802.11-2020)
206 std::vector<uint8_t> partialVirtualBitmap(GetLastNonZeroOctetIndex() - offset + 1, 0);
207
208 for (auto aid : m_aidValues)
209 {
210 partialVirtualBitmap.at(GetAidOctetIndex(aid) - offset) |= GetAidBit(aid);
211 }
212
213 return partialVirtualBitmap;
214}
215
216void
217Tim::Print(std::ostream& os) const
218{
219 os << "DTIM Count: " << +m_dtimCount << ", "
220 << "DTIM Period: " << +m_dtimPeriod << ", "
221 << "Has Multicast Pending: " << m_hasMulticastPending << ", AID values:";
222 for (uint16_t aid = 0; aid < 2008; ++aid)
223 {
224 if (HasAid(aid))
225 {
226 os << aid << " ";
227 }
228 }
229}
230
231} // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
std::set< uint16_t > m_aidValues
List of AID values included in this TIM.
Definition: tim.h:146
uint8_t GetAidBit(uint16_t aid) const
Obtain an octet with a set bit, corresponding to the provided AID value.
Definition: tim.cc:138
uint16_t DeserializeInformationField(Buffer::Iterator start, uint16_t length) override
Deserialize information (i.e., the body of the IE, not including the Element ID and length octets)
Definition: tim.cc:86
uint8_t m_dtimPeriod
The DTIM Period field.
Definition: tim.h:97
uint8_t GetPartialVirtualBitmapOffset() const
Get the Partial Virtual Bitmap offset, i.e., the number (denoted as N1 by the specs) of the first oct...
Definition: tim.cc:153
std::vector< uint8_t > GetPartialVirtualBitmap() const
Definition: tim.cc:200
uint8_t m_dtimCount
The DTIM Count field.
Definition: tim.h:96
uint16_t GetAidFromOctetIndexAndBitPosition(uint16_t octet, uint8_t position) const
Obtain the AID value represented by a certain octet index and bit position inside the Virtual Bitmap.
Definition: tim.cc:147
void AddAid(uint16_t aid)
Add the provided AID value to the list contained in the Virtual Bitmap.
Definition: tim.cc:49
void Print(std::ostream &os) const override
Generate human-readable form of IE.
Definition: tim.cc:217
uint8_t GetAidOctetIndex(uint16_t aid) const
Obtain the index of the octet where the provided AID value should be set in the Virtual Bitmap.
Definition: tim.cc:129
uint8_t GetLastNonZeroOctetIndex() const
Definition: tim.cc:168
WifiInformationElementId ElementId() const override
Get the wifi information element ID.
Definition: tim.cc:29
std::set< uint16_t > GetAidSet(uint16_t aid=0) const
Return the AID values, greater than the given AID value, whose corresponding bits are set in the virt...
Definition: tim.cc:63
bool m_hasMulticastPending
Whether there is Multicast / Broadcast data.
Definition: tim.h:98
void SerializeInformationField(Buffer::Iterator start) const override
Serialize information (i.e., the body of the IE, not including the Element ID and length octets)
Definition: tim.cc:70
bool HasAid(uint16_t aid) const
Check whether the bit corresponding to the provided AID is set in the Virtual Bitmap included in this...
Definition: tim.cc:57
uint8_t GetBitmapControl() const
The Bitmap Control field is optional if the TIM is carried in an S1G PPDU, while it is always present...
Definition: tim.cc:183
uint16_t GetInformationFieldSize() const override
Length of serialized information (i.e., the length of the body of the IE, not including the Element I...
Definition: tim.cc:35
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:76
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint8_t WifiInformationElementId
This type is used to represent an Information Element ID.
#define IE_TIM