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#include "wifi-phy.h"
14
15#include "ns3/attribute-container.h"
16#include "ns3/boolean.h"
17#include "ns3/eht-configuration.h"
18#include "ns3/enum.h"
19#include "ns3/log.h"
20
21#include <algorithm>
22
23namespace ns3
24{
25
26NS_LOG_COMPONENT_DEFINE("WifiAssocManager");
27
28NS_OBJECT_ENSURE_REGISTERED(WifiAssocManager);
29
31 : m_manager(manager)
32{
33}
34
35bool
37 const StaWifiMac::ApInfo& rhs) const
38{
39 NS_ASSERT_MSG(lhs.m_bssid != rhs.m_bssid,
40 "Comparing two ApInfo objects with the same BSSID: " << lhs.m_bssid);
41
42 bool lhsBefore = m_manager.Compare(lhs, rhs);
43 if (lhsBefore)
44 {
45 return true;
46 }
47
48 bool rhsBefore = m_manager.Compare(rhs, lhs);
49 if (rhsBefore)
50 {
51 return false;
52 }
53
54 // the Compare method implemented by subclass may be such that the two ApInfo objects
55 // compare equal; in such a case, use the BSSID as tie breaker
56 return lhs.m_bssid < rhs.m_bssid;
57}
58
61{
62 static TypeId tid =
63 TypeId("ns3::WifiAssocManager")
65 .SetGroupName("Wifi")
66 .AddAttribute(
67 "AllowedLinks",
68 "Only Beacon and Probe Response frames received on a link belonging to the given "
69 "set are processed. An empty set is equivalent to the set of all links.",
73 .AddAttribute("AllowAssocAllChannelWidths",
74 "If set to true, it bypasses the check on channel width compatibility "
75 "with the candidate AP. A channel width is compatible if the STA can "
76 "advertise it to the AP, or AP operates on a channel width that is equal "
77 "or lower than that channel width.",
78 BooleanValue(false),
81 return tid;
82}
83
85 : m_scanParams(), // zero-initialization
87{
88}
89
94
95void
97{
98 NS_LOG_FUNCTION(this);
99 m_mac = nullptr;
100}
101
102void
104{
105 NS_LOG_FUNCTION(this << mac);
106 m_mac = mac;
107}
108
111{
112 return m_apList;
113}
114
115const WifiScanParams&
117{
118 return m_scanParams;
119}
120
121bool
123{
124 NS_LOG_FUNCTION(this << apInfo);
125
127 {
128 // we need to check if AP's advertised SSID matches the requested SSID
129 Ssid apSsid;
130 if (auto beacon = std::get_if<MgtBeaconHeader>(&apInfo.m_frame); beacon)
131 {
132 apSsid = beacon->Get<Ssid>().value();
133 }
134 else
135 {
136 auto probeResp = std::get_if<MgtProbeResponseHeader>(&apInfo.m_frame);
137 NS_ASSERT(probeResp);
138 apSsid = probeResp->Get<Ssid>().value();
139 }
140 if (!apSsid.IsEqual(m_scanParams.ssid))
141 {
142 NS_LOG_DEBUG("AP " << apInfo.m_bssid << " does not advertise our SSID " << apSsid
143 << " " << m_scanParams.ssid);
144 return false;
145 }
146 }
147
148 // we need to check if the AP is operating on a requested channel
149 auto channelMatch = [&apInfo](auto&& channel) {
150 if (channel.number != 0 && channel.number != apInfo.m_channel.number)
151 {
152 return false;
153 }
154 if (channel.band != WIFI_PHY_BAND_UNSPECIFIED && channel.band != apInfo.m_channel.band)
155 {
156 return false;
157 }
158 return true;
159 };
160
162 if (std::find_if(m_scanParams.channelList[apInfo.m_linkId].cbegin(),
163 m_scanParams.channelList[apInfo.m_linkId].cend(),
164 channelMatch) == m_scanParams.channelList[apInfo.m_linkId].cend())
165 {
166 NS_LOG_DEBUG("AP " << apInfo.m_bssid << " is not operating on a requested channel");
167 return false;
168 }
169
170 return true;
171}
172
173void
175{
176 NS_LOG_FUNCTION(this);
177 m_scanParams = std::move(scanParams);
178
179 // remove stored AP information not matching the scanning parameters or related to APs
180 // that are not reachable on an allowed link
181 for (auto ap = m_apList.begin(); ap != m_apList.end();)
182 {
183 if (!MatchScanParams(*ap) ||
184 (!m_allowedLinks.empty() && !m_allowedLinks.contains(ap->m_linkId)))
185 {
186 // remove AP info from list
187 m_apListIt.erase(ap->m_bssid);
188 ap = m_apList.erase(ap);
189 }
190 else
191 {
192 ++ap;
193 }
194 }
195
197}
198
199void
201{
202 NS_LOG_FUNCTION(this << apInfo);
203
204 if (!CanBeInserted(apInfo) || !MatchScanParams(apInfo) ||
205 (!m_allowedLinks.empty() && !m_allowedLinks.contains(apInfo.m_linkId)))
206 {
207 return;
208 }
209
210 // check if an ApInfo object with the same BSSID is already present in the
211 // sorted list of ApInfo objects. This is done by trying to insert the BSSID
212 // in the hash table (insertion fails if the BSSID is already present)
213 auto [hashIt, hashInserted] = m_apListIt.insert({apInfo.m_bssid, {}});
214 if (!hashInserted)
215 {
216 // an element with the searched BSSID is already present in the hash table.
217 // Remove the corresponding ApInfo object from the sorted list.
218 m_apList.erase(hashIt->second);
219 }
220 // insert the ApInfo object
221 auto [listIt, listInserted] = m_apList.insert(std::move(apInfo));
222 // update the hash table entry
223 NS_ASSERT_MSG(listInserted,
224 "An entry (" << listIt->m_apAddr << ", " << listIt->m_bssid << ", "
225 << +listIt->m_linkId
226 << ") prevented insertion of given ApInfo object");
227 hashIt->second = listIt;
228}
229
230void
232{
233 NS_LOG_FUNCTION(this);
234
235 StaWifiMac::ApInfo bestAp;
236
237 do
238 {
239 if (m_apList.empty())
240 {
241 m_mac->ScanningTimeout(std::nullopt);
242 return;
243 }
244
245 bestAp = std::move(m_apList.extract(m_apList.begin()).value());
246 m_apListIt.erase(bestAp.m_bssid);
247 } while (!CanBeReturned(bestAp));
248
250 "Channel width of STA is not part of the channel width set that can be "
251 "advertised to the AP");
252
253 m_mac->ScanningTimeout(std::move(bestAp));
254}
255
256std::list<StaWifiMac::ApInfo::SetupLinksInfo>&
258{
259 return const_cast<std::list<StaWifiMac::ApInfo::SetupLinksInfo>&>(apInfo.m_setupLinks);
260}
261
262bool
264{
265 NS_LOG_FUNCTION(this);
266
267 if (m_mac->GetAssocType() == WifiAssocType::LEGACY || GetSortedList().empty())
268 {
269 return false;
270 }
271
272 // Get the Multi-Link Element and the RNR element, if present,
273 // from Beacon or Probe Response
274 if (auto beacon = std::get_if<MgtBeaconHeader>(&m_apList.begin()->m_frame); beacon)
275 {
276 mle = beacon->Get<MultiLinkElement>();
277 rnr = beacon->Get<ReducedNeighborReport>();
278 }
279 else
280 {
281 auto probeResp = std::get_if<MgtProbeResponseHeader>(&m_apList.begin()->m_frame);
282 NS_ASSERT(probeResp);
283 mle = probeResp->Get<MultiLinkElement>();
284 rnr = probeResp->Get<ReducedNeighborReport>();
285 }
286
287 if (!mle.has_value())
288 {
289 NS_LOG_DEBUG("No Multi-Link Element in Beacon/Probe Response");
290 return false;
291 }
292
293 if (!rnr.has_value() || rnr->get().GetNNbrApInfoFields() == 0)
294 {
295 NS_LOG_DEBUG("No Reduced Neighbor Report Element in Beacon/Probe Response");
296 return false;
297 }
298
299 // The Multi-Link Element must contain the MLD MAC Address subfield and the
300 // Link ID Info subfield
301 if (!mle->get().HasLinkIdInfo())
302 {
303 NS_LOG_DEBUG("No Link ID Info subfield in the Multi-Link Element");
304 return false;
305 }
306
307 if (const auto& mldCapabilities = mle->get().GetCommonInfoBasic().m_mldCapabilities)
308 {
309 auto ehtConfig = m_mac->GetEhtConfiguration();
310 NS_ASSERT(ehtConfig);
311
312 // A non-AP MLD that performs multi-link (re)setup on at least two links with an AP MLD
313 // that sets the TID-To-Link Mapping Negotiation Support subfield of the MLD Capabilities
314 // field of the Basic Multi-Link element to a nonzero value shall support TID-to-link
315 // mapping negotiation with the TID-To-Link Mapping Negotiation Support subfield of the
316 // MLD Capabilities field of the Basic Multi-Link element it transmits to at least 1.
317 // (Sec. 35.3.7.1.1 of 802.11be D3.1)
318 if (mldCapabilities->tidToLinkMappingSupport > 0 &&
319 ehtConfig->m_tidLinkMappingSupport == WifiTidToLinkMappingNegSupport::NOT_SUPPORTED)
320 {
321 NS_LOG_DEBUG("AP MLD supports TID-to-Link Mapping negotiation, while we don't");
322 return false;
323 }
324 }
325
326 return true;
327}
328
329std::optional<WifiAssocManager::RnrLinkInfo>
331{
332 NS_LOG_FUNCTION(nbrApInfoId);
333
334 while (nbrApInfoId < rnr.GetNNbrApInfoFields())
335 {
336 if (!rnr.HasMldParameters(nbrApInfoId))
337 {
338 // this Neighbor AP Info field is not suitable to setup a link
339 nbrApInfoId++;
340 continue;
341 }
342
343 std::size_t tbttInfoFieldIndex = 0;
344 while (tbttInfoFieldIndex < rnr.GetNTbttInformationFields(nbrApInfoId) &&
345 rnr.GetMldParameters(nbrApInfoId, tbttInfoFieldIndex).apMldId != 0)
346 {
347 tbttInfoFieldIndex++;
348 }
349
350 if (tbttInfoFieldIndex < rnr.GetNTbttInformationFields(nbrApInfoId))
351 {
352 // this Neighbor AP Info field contains an AP affiliated to the
353 // same AP MLD as the reporting AP
354 return RnrLinkInfo{nbrApInfoId, tbttInfoFieldIndex};
355 }
356 nbrApInfoId++;
357 }
358
359 return std::nullopt;
360}
361
362std::list<WifiAssocManager::RnrLinkInfo>
364{
365 std::list<WifiAssocManager::RnrLinkInfo> apList;
366 std::size_t nbrApInfoId = 0;
367 std::optional<WifiAssocManager::RnrLinkInfo> next;
368
369 while ((next = GetNextAffiliatedAp(rnr, nbrApInfoId)).has_value())
370 {
371 apList.push_back({*next});
372 nbrApInfoId = next->m_nbrApInfoId + 1;
373 }
374
375 return apList;
376}
377
378bool
380{
381 auto phy = m_mac->GetWifiPhy(apInfo.m_linkId);
382 return GetSupportedChannelWidthSet(phy->GetStandard(), apInfo.m_channel.band)
383 .contains(phy->GetChannelWidth()) ||
384 (phy->GetChannelWidth() >= m_mac->GetWifiRemoteStationManager(apInfo.m_linkId)
385 ->GetChannelWidthSupported(apInfo.m_bssid));
386}
387
388} // namespace ns3
A container for one type of attribute.
AttributeValue implementation for Boolean.
Definition boolean.h:26
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...
const MldParameters & GetMldParameters(std::size_t nbrApInfoId, std::size_t index) const
Get the MLD Parameters subfield (must be present) in the i-th TBTT Information field of the given Nei...
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: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
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.
bool IsChannelWidthCompatible(const StaWifiMac::ApInfo &apInfo) const
Check whether the channel width of the STA is compatible with the channel width of the operating chan...
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
bool m_allowAssocAllChannelWidths
flag whether the check on channel width compatibility with the candidate AP should be skipped
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.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#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.
std::set< MHz_u > GetSupportedChannelWidthSet(WifiStandard standard, WifiPhyBand band)
Get the supported channel width set that can be advertised in PHY capabilities.
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