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
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);
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
151 NS_ASSERT(apInfo.m_linkId < m_scanParams.channelList.size());
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
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
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
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>();
264 }
265 else
266 {
267 auto probeResp = std::get_if<MgtProbeResponseHeader>(&m_apList.begin()->m_frame);
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();
297
298 // A non-AP MLD that performs multi-link (re)setup on at least two links with an AP MLD
299 // that sets the TID-To-Link Mapping Negotiation Support subfield of the MLD Capabilities
300 // field of the Basic Multi-Link element to a nonzero value shall support TID-to-link
301 // mapping negotiation with the TID-To-Link Mapping Negotiation Support subfield of the
302 // MLD Capabilities field of the Basic Multi-Link element it transmits to at least 1.
303 // (Sec. 35.3.7.1.1 of 802.11be D3.1)
304 if (mldCapabilities->tidToLinkMappingSupport > 0 &&
306 {
307 NS_LOG_DEBUG("AP MLD supports TID-to-Link Mapping negotiation, while we don't");
308 return false;
309 }
310 }
311
312 return true;
313}
314
315std::optional<WifiAssocManager::RnrLinkInfo>
317{
319
320 while (nbrApInfoId < rnr.GetNNbrApInfoFields())
321 {
322 if (!rnr.HasMldParameters(nbrApInfoId))
323 {
324 // this Neighbor AP Info field is not suitable to setup a link
325 nbrApInfoId++;
326 continue;
327 }
328
329 std::size_t tbttInfoFieldIndex = 0;
330 while (tbttInfoFieldIndex < rnr.GetNTbttInformationFields(nbrApInfoId) &&
331 rnr.GetMldParameters(nbrApInfoId, tbttInfoFieldIndex).apMldId != 0)
332 {
334 }
335
336 if (tbttInfoFieldIndex < rnr.GetNTbttInformationFields(nbrApInfoId))
337 {
338 // this Neighbor AP Info field contains an AP affiliated to the
339 // same AP MLD as the reporting AP
341 }
342 nbrApInfoId++;
343 }
344
345 return std::nullopt;
346}
347
348std::list<WifiAssocManager::RnrLinkInfo>
350{
351 std::list<WifiAssocManager::RnrLinkInfo> apList;
352 std::size_t nbrApInfoId = 0;
353 std::optional<WifiAssocManager::RnrLinkInfo> next;
354
355 while ((next = GetNextAffiliatedAp(rnr, nbrApInfoId)).has_value())
356 {
357 apList.push_back({*next});
358 nbrApInfoId = next->m_nbrApInfoId + 1;
359 }
360
361 return apList;
362}
363
364} // namespace ns3
A container for one type of attribute.
A base class which provides memory management and object aggregation.
Definition object.h:78
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
The Reduced Neighbor Report element.
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
bool IsBroadcast() const
Check if the SSID is broadcast.
Definition ssid.cc:61
a unique identifier for an interface.
Definition type-id.h:49
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
std::optional< std::reference_wrapper< const MultiLinkElement > > OptMleConstRef
typedef for an optional const reference to a MultiLinkElement object
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::list< StaWifiMac::ApInfo::SetupLinksInfo > & GetSetupLinks(const StaWifiMac::ApInfo &apInfo)
Get a reference to the list of the links to setup with the given AP.
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...
std::optional< std::reference_wrapper< const ReducedNeighborReport > > OptRnrConstRef
typedef for an optional const reference to a ReducedNeighborReport object
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
#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
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static unsigned int value(char c)
Struct to hold information regarding observed AP through active/passive scanning.
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.
Structure holding scan parameters.
std::vector< ChannelList > channelList
list of channels to scan, for each link
Ssid ssid
desired SSID or wildcard SSID