A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-assoc-manager.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
3
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 * Author: Stefano Avallone <stavallo@unina.it>
8 */
9
10#include "wifi-assoc-manager.h"
11
12#include "sta-wifi-mac.h"
13
14#include "ns3/attribute-container.h"
15#include "ns3/eht-configuration.h"
16#include "ns3/enum.h"
17#include "ns3/log.h"
18
19#include <algorithm>
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("WifiAssocManager");
25
26NS_OBJECT_ENSURE_REGISTERED(WifiAssocManager);
27
29 : m_manager(manager)
30{
31}
32
33bool
35 const StaWifiMac::ApInfo& rhs) const
36{
37 NS_ASSERT_MSG(lhs.m_bssid != rhs.m_bssid,
38 "Comparing two ApInfo objects with the same BSSID: " << lhs.m_bssid);
39
40 bool lhsBefore = m_manager.Compare(lhs, rhs);
41 if (lhsBefore)
42 {
43 return true;
44 }
45
46 bool rhsBefore = m_manager.Compare(rhs, lhs);
47 if (rhsBefore)
48 {
49 return false;
50 }
51
52 // the Compare method implemented by subclass may be such that the two ApInfo objects
53 // compare equal; in such a case, use the BSSID as tie breaker
54 return lhs.m_bssid < rhs.m_bssid;
55}
56
59{
60 static TypeId tid =
61 TypeId("ns3::WifiAssocManager")
63 .SetGroupName("Wifi")
64 .AddAttribute(
65 "AllowedLinks",
66 "Only Beacon and Probe Response frames received on a link belonging to the given "
67 "set are processed. An empty set is equivalent to the set of all links.",
71 return tid;
72}
73
75 : m_scanParams(), // zero-initialization
77{
78}
79
84
85void
87{
88 NS_LOG_FUNCTION(this);
89 m_mac = nullptr;
90}
91
92void
98
101{
102 return m_apList;
103}
104
105const WifiScanParams&
107{
108 return m_scanParams;
109}
110
111bool
113{
114 NS_LOG_FUNCTION(this << apInfo);
115
117 {
118 // we need to check if AP's advertised SSID matches the requested SSID
119 Ssid apSsid;
120 if (auto beacon = std::get_if<MgtBeaconHeader>(&apInfo.m_frame); beacon)
121 {
122 apSsid = beacon->Get<Ssid>().value();
123 }
124 else
125 {
126 auto probeResp = std::get_if<MgtProbeResponseHeader>(&apInfo.m_frame);
127 NS_ASSERT(probeResp);
128 apSsid = probeResp->Get<Ssid>().value();
129 }
130 if (!apSsid.IsEqual(m_scanParams.ssid))
131 {
132 NS_LOG_DEBUG("AP " << apInfo.m_bssid << " does not advertise our SSID " << apSsid
133 << " " << m_scanParams.ssid);
134 return false;
135 }
136 }
137
138 // we need to check if the AP is operating on a requested channel
139 auto channelMatch = [&apInfo](auto&& channel) {
140 if (channel.number != 0 && channel.number != apInfo.m_channel.number)
141 {
142 return false;
143 }
144 if (channel.band != WIFI_PHY_BAND_UNSPECIFIED && channel.band != apInfo.m_channel.band)
145 {
146 return false;
147 }
148 return true;
149 };
150
152 if (std::find_if(m_scanParams.channelList[apInfo.m_linkId].cbegin(),
153 m_scanParams.channelList[apInfo.m_linkId].cend(),
154 channelMatch) == m_scanParams.channelList[apInfo.m_linkId].cend())
155 {
156 NS_LOG_DEBUG("AP " << apInfo.m_bssid << " is not operating on a requested channel");
157 return false;
158 }
159
160 return true;
161}
162
163void
165{
166 NS_LOG_FUNCTION(this);
167 m_scanParams = std::move(scanParams);
168
169 // remove stored AP information not matching the scanning parameters or related to APs
170 // that are not reachable on an allowed link
171 for (auto ap = m_apList.begin(); ap != m_apList.end();)
172 {
173 if (!MatchScanParams(*ap) ||
174 (!m_allowedLinks.empty() && !m_allowedLinks.contains(ap->m_linkId)))
175 {
176 // remove AP info from list
177 m_apListIt.erase(ap->m_bssid);
178 ap = m_apList.erase(ap);
179 }
180 else
181 {
182 ++ap;
183 }
184 }
185
187}
188
189void
191{
192 NS_LOG_FUNCTION(this << apInfo);
193
194 if (!CanBeInserted(apInfo) || !MatchScanParams(apInfo) ||
195 (!m_allowedLinks.empty() && !m_allowedLinks.contains(apInfo.m_linkId)))
196 {
197 return;
198 }
199
200 // check if an ApInfo object with the same BSSID is already present in the
201 // sorted list of ApInfo objects. This is done by trying to insert the BSSID
202 // in the hash table (insertion fails if the BSSID is already present)
203 auto [hashIt, hashInserted] = m_apListIt.insert({apInfo.m_bssid, {}});
204 if (!hashInserted)
205 {
206 // an element with the searched BSSID is already present in the hash table.
207 // Remove the corresponding ApInfo object from the sorted list.
208 m_apList.erase(hashIt->second);
209 }
210 // insert the ApInfo object
211 auto [listIt, listInserted] = m_apList.insert(std::move(apInfo));
212 // update the hash table entry
213 NS_ASSERT_MSG(listInserted,
214 "An entry (" << listIt->m_apAddr << ", " << listIt->m_bssid << ", "
215 << +listIt->m_linkId
216 << ") prevented insertion of given ApInfo object");
217 hashIt->second = listIt;
218}
219
220void
222{
223 NS_LOG_FUNCTION(this);
224
225 StaWifiMac::ApInfo bestAp;
226
227 do
228 {
229 if (m_apList.empty())
230 {
231 m_mac->ScanningTimeout(std::nullopt);
232 return;
233 }
234
235 bestAp = std::move(m_apList.extract(m_apList.begin()).value());
236 m_apListIt.erase(bestAp.m_bssid);
237 } while (!CanBeReturned(bestAp));
238
239 m_mac->ScanningTimeout(std::move(bestAp));
240}
241
242std::list<StaWifiMac::ApInfo::SetupLinksInfo>&
244{
245 return const_cast<std::list<StaWifiMac::ApInfo::SetupLinksInfo>&>(apInfo.m_setupLinks);
246}
247
248bool
250{
251 NS_LOG_FUNCTION(this);
252
253 if (m_mac->GetNLinks() == 1 || GetSortedList().empty())
254 {
255 return false;
256 }
257
258 // Get the Multi-Link Element and the RNR element, if present,
259 // from Beacon or Probe Response
260 if (auto beacon = std::get_if<MgtBeaconHeader>(&m_apList.begin()->m_frame); beacon)
261 {
262 mle = beacon->Get<MultiLinkElement>();
263 rnr = beacon->Get<ReducedNeighborReport>();
264 }
265 else
266 {
267 auto probeResp = std::get_if<MgtProbeResponseHeader>(&m_apList.begin()->m_frame);
268 NS_ASSERT(probeResp);
269 mle = probeResp->Get<MultiLinkElement>();
270 rnr = probeResp->Get<ReducedNeighborReport>();
271 }
272
273 if (!mle.has_value())
274 {
275 NS_LOG_DEBUG("No Multi-Link Element in Beacon/Probe Response");
276 return false;
277 }
278
279 if (!rnr.has_value() || rnr->get().GetNNbrApInfoFields() == 0)
280 {
281 NS_LOG_DEBUG("No Reduced Neighbor Report Element in Beacon/Probe Response");
282 return false;
283 }
284
285 // The Multi-Link Element must contain the MLD MAC Address subfield and the
286 // Link ID Info subfield
287 if (!mle->get().HasLinkIdInfo())
288 {
289 NS_LOG_DEBUG("No Link ID Info subfield in the Multi-Link Element");
290 return false;
291 }
292
293 if (const auto& mldCapabilities = mle->get().GetCommonInfoBasic().m_mldCapabilities)
294 {
295 auto ehtConfig = m_mac->GetEhtConfiguration();
296 NS_ASSERT(ehtConfig);
298 ehtConfig->GetAttributeFailSafe("TidToLinkMappingNegSupport", negSupport);
299
300 // A non-AP MLD that performs multi-link (re)setup on at least two links with an AP MLD
301 // that sets the TID-To-Link Mapping Negotiation Support subfield of the MLD Capabilities
302 // field of the Basic Multi-Link element to a nonzero value shall support TID-to-link
303 // mapping negotiation with the TID-To-Link Mapping Negotiation Support subfield of the
304 // MLD Capabilities field of the Basic Multi-Link element it transmits to at least 1.
305 // (Sec. 35.3.7.1.1 of 802.11be D3.1)
306 if (mldCapabilities->tidToLinkMappingSupport > 0 &&
308 {
309 NS_LOG_DEBUG("AP MLD supports TID-to-Link Mapping negotiation, while we don't");
310 return false;
311 }
312 }
313
314 return true;
315}
316
317std::optional<WifiAssocManager::RnrLinkInfo>
319{
320 NS_LOG_FUNCTION(nbrApInfoId);
321
322 while (nbrApInfoId < rnr.GetNNbrApInfoFields())
323 {
324 if (!rnr.HasMldParameters(nbrApInfoId))
325 {
326 // this Neighbor AP Info field is not suitable to setup a link
327 nbrApInfoId++;
328 continue;
329 }
330
331 std::size_t tbttInfoFieldIndex = 0;
332 while (tbttInfoFieldIndex < rnr.GetNTbttInformationFields(nbrApInfoId) &&
333 rnr.GetMldId(nbrApInfoId, tbttInfoFieldIndex) != 0)
334 {
335 tbttInfoFieldIndex++;
336 }
337
338 if (tbttInfoFieldIndex < rnr.GetNTbttInformationFields(nbrApInfoId))
339 {
340 // this Neighbor AP Info field contains an AP affiliated to the
341 // same AP MLD as the reporting AP
342 return RnrLinkInfo{nbrApInfoId, tbttInfoFieldIndex};
343 }
344 nbrApInfoId++;
345 }
346
347 return std::nullopt;
348}
349
350std::list<WifiAssocManager::RnrLinkInfo>
352{
353 std::list<WifiAssocManager::RnrLinkInfo> apList;
354 std::size_t nbrApInfoId = 0;
355 std::optional<WifiAssocManager::RnrLinkInfo> next;
356
357 while ((next = GetNextAffiliatedAp(rnr, nbrApInfoId)).has_value())
358 {
359 apList.push_back({*next});
360 nbrApInfoId = next->m_nbrApInfoId + 1;
361 }
362
363 return apList;
364}
365
366} // namespace ns3
A container for one type of attribute.
Hold variables of type enum.
Definition enum.h:52
T Get() const
Definition enum.h:87
A base class which provides memory management and object aggregation.
Definition object.h:78
Smart pointer class similar to boost::intrusive_ptr.
The Reduced Neighbor Report element.
std::size_t GetNNbrApInfoFields() const
Get the number of Neighbor AP Information fields.
std::size_t GetNTbttInformationFields(std::size_t nbrApInfoId) const
Get the number of TBTT Information fields included in the TBTT Information Set field of the given Nei...
uint8_t GetMldId(std::size_t nbrApInfoId, std::size_t index) const
Get the MLD ID value in the MLD Parameters subfield (must be present) in the i-th TBTT Information fi...
bool HasMldParameters(std::size_t nbrApInfoId) const
Return true if the MLD Parameters subfield is present in all the TBTT Information fields of the given...
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
bool IsEqual(const Ssid &o) const
Check if the two SSIDs are equal.
Definition ssid.cc:50
bool IsBroadcast() const
Check if the SSID is broadcast.
Definition ssid.cc:61
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Abstract base class for the Association Manager, which manages scanning and association for single li...
const SortedList & GetSortedList() const
virtual void NotifyApInfo(const StaWifiMac::ApInfo &&apInfo)
STA wifi MAC received a Beacon frame or Probe Response frame while scanning and notifies us the AP in...
Ptr< StaWifiMac > m_mac
pointer to the STA wifi MAC
virtual void DoStartScanning()=0
Start a scanning procedure.
void SetStaWifiMac(Ptr< StaWifiMac > mac)
Set the pointer to the STA wifi MAC.
std::optional< std::reference_wrapper< const MultiLinkElement > > OptMleConstRef
typedef for an optional const reference to a MultiLinkElement object
std::list< StaWifiMac::ApInfo::SetupLinksInfo > & GetSetupLinks(const StaWifiMac::ApInfo &apInfo)
Get a reference to the list of the links to setup with the given AP.
std::optional< std::reference_wrapper< const ReducedNeighborReport > > OptRnrConstRef
typedef for an optional const reference to a ReducedNeighborReport object
void ScanningTimeout()
Extract the best AP to associate with from the sorted list and return it, if any, to the STA wifi MAC...
virtual bool CanBeInserted(const StaWifiMac::ApInfo &apInfo) const =0
Allow subclasses to choose whether the given ApInfo shall be considered and hence inserted in the sor...
SortedList m_apList
sorted list of candidate APs
static std::optional< WifiAssocManager::RnrLinkInfo > GetNextAffiliatedAp(const ReducedNeighborReport &rnr, std::size_t nbrApInfoId)
Search the given RNR element for APs affiliated to the same AP MLD as the reporting AP.
WifiScanParams m_scanParams
scanning parameters
virtual bool CanBeReturned(const StaWifiMac::ApInfo &apInfo) const =0
Allow subclasses to choose whether the given ApInfo shall be returned or discarded when the STA wifi ...
void StartScanning(WifiScanParams &&scanParams)
Request the Association Manager to start a scanning procedure according to the given scanning paramet...
std::set< StaWifiMac::ApInfo, ApInfoCompare > SortedList
typedef for the sorted list of ApInfo objects
std::set< uint8_t > m_allowedLinks
"Only Beacon and Probe Response frames received on a link belonging to the this set are processed
static std::list< WifiAssocManager::RnrLinkInfo > GetAllAffiliatedAps(const ReducedNeighborReport &rnr)
Find all the APs affiliated to the same AP MLD as the reporting AP that sent the given RNR element.
static TypeId GetTypeId()
Get the type ID.
const WifiScanParams & GetScanParams() const
void DoDispose() override
Destructor implementation.
std::unordered_map< Mac48Address, SortedList::const_iterator, WifiAddressHash > m_apListIt
hash table to help locate ApInfo objects in the sorted list based on the BSSID
bool CanSetupMultiLink(OptMleConstRef &mle, OptRnrConstRef &rnr)
Check whether 11be Multi-Link setup can be established with the current best AP.
WifiAssocManager()
Constructor (protected as this is an abstract base class)
bool MatchScanParams(const StaWifiMac::ApInfo &apInfo) const
Check whether the given AP information match the current scanning parameters.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< AttributeChecker > MakeAttributeContainerChecker()
Make uninitialized AttributeContainerChecker using explicit types.
Ptr< const AttributeAccessor > MakeAttributeContainerAccessor(T1 a1)
Make AttributeContainerAccessor using explicit types.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Struct to hold information regarding observed AP through active/passive scanning.
MgtFrameType m_frame
The body of the management frame used to update AP info.
WifiScanParams::Channel m_channel
The channel the management frame was received on.
std::list< SetupLinksInfo > m_setupLinks
information about the links to setup between MLDs
uint8_t m_linkId
ID of the link used to communicate with the AP.
Mac48Address m_bssid
BSSID.
Struct providing a function call operator to compare two ApInfo objects.
ApInfoCompare(const WifiAssocManager &manager)
Constructor.
bool operator()(const StaWifiMac::ApInfo &lhs, const StaWifiMac::ApInfo &rhs) const
Function call operator.
WifiPhyBand band
PHY band.
uint16_t number
channel number
Structure holding scan parameters.
std::vector< ChannelList > channelList
list of channels to scan, for each link
Ssid ssid
desired SSID or wildcard SSID