A Discrete-Event Network Simulator
QKDNetSim v2.0 (NS-3 v3.41) @ (+)
API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Stefano Avallone <stavallo@unina.it>
19  */
20 
21 #include "wifi-assoc-manager.h"
22 
23 #include "sta-wifi-mac.h"
24 
25 #include "ns3/attribute-container.h"
26 #include "ns3/eht-configuration.h"
27 #include "ns3/enum.h"
28 #include "ns3/log.h"
29 
30 #include <algorithm>
31 
32 namespace ns3
33 {
34 
35 NS_LOG_COMPONENT_DEFINE("WifiAssocManager");
36 
37 NS_OBJECT_ENSURE_REGISTERED(WifiAssocManager);
38 
40  : m_manager(manager)
41 {
42 }
43 
44 bool
46  const StaWifiMac::ApInfo& rhs) const
47 {
48  NS_ASSERT_MSG(lhs.m_bssid != rhs.m_bssid,
49  "Comparing two ApInfo objects with the same BSSID: " << lhs.m_bssid);
50 
51  bool lhsBefore = m_manager.Compare(lhs, rhs);
52  if (lhsBefore)
53  {
54  return true;
55  }
56 
57  bool rhsBefore = m_manager.Compare(rhs, lhs);
58  if (rhsBefore)
59  {
60  return false;
61  }
62 
63  // the Compare method implemented by subclass may be such that the two ApInfo objects
64  // compare equal; in such a case, use the BSSID as tie breaker
65  return lhs.m_bssid < rhs.m_bssid;
66 }
67 
68 TypeId
70 {
71  static TypeId tid =
72  TypeId("ns3::WifiAssocManager")
73  .SetParent<Object>()
74  .SetGroupName("Wifi")
75  .AddAttribute(
76  "AllowedLinks",
77  "Only Beacon and Probe Response frames received on a link belonging to the given "
78  "set are processed. An empty set is equivalent to the set of all links.",
80  MakeAttributeContainerAccessor<UintegerValue>(&WifiAssocManager::m_allowedLinks),
81  MakeAttributeContainerChecker<UintegerValue>(MakeUintegerChecker<uint8_t>()));
82  return tid;
83 }
84 
86  : m_scanParams(), // zero-initialization
87  m_apList(ApInfoCompare(*this))
88 {
89 }
90 
92 {
93  NS_LOG_FUNCTION(this);
94 }
95 
96 void
98 {
99  NS_LOG_FUNCTION(this);
100  m_mac = nullptr;
101 }
102 
103 void
105 {
106  NS_LOG_FUNCTION(this << mac);
107  m_mac = mac;
108 }
109 
112 {
113  return m_apList;
114 }
115 
116 const WifiScanParams&
118 {
119  return m_scanParams;
120 }
121 
122 bool
124 {
125  NS_LOG_FUNCTION(this << apInfo);
126 
128  {
129  // we need to check if AP's advertised SSID matches the requested SSID
130  Ssid apSsid;
131  if (auto beacon = std::get_if<MgtBeaconHeader>(&apInfo.m_frame); beacon)
132  {
133  apSsid = beacon->Get<Ssid>().value();
134  }
135  else
136  {
137  auto probeResp = std::get_if<MgtProbeResponseHeader>(&apInfo.m_frame);
138  NS_ASSERT(probeResp);
139  apSsid = probeResp->Get<Ssid>().value();
140  }
141  if (!apSsid.IsEqual(m_scanParams.ssid))
142  {
143  NS_LOG_DEBUG("AP " << apInfo.m_bssid << " does not advertise our SSID " << apSsid
144  << " " << m_scanParams.ssid);
145  return false;
146  }
147  }
148 
149  // we need to check if the AP is operating on a requested channel
150  auto channelMatch = [&apInfo](auto&& channel) {
151  if (channel.number != 0 && channel.number != apInfo.m_channel.number)
152  {
153  return false;
154  }
155  if (channel.band != WIFI_PHY_BAND_UNSPECIFIED && channel.band != apInfo.m_channel.band)
156  {
157  return false;
158  }
159  return true;
160  };
161 
162  NS_ASSERT(apInfo.m_linkId < m_scanParams.channelList.size());
163  if (std::find_if(m_scanParams.channelList[apInfo.m_linkId].cbegin(),
164  m_scanParams.channelList[apInfo.m_linkId].cend(),
165  channelMatch) == m_scanParams.channelList[apInfo.m_linkId].cend())
166  {
167  NS_LOG_DEBUG("AP " << apInfo.m_bssid << " is not operating on a requested channel");
168  return false;
169  }
170 
171  return true;
172 }
173 
174 void
176 {
177  NS_LOG_FUNCTION(this);
178  m_scanParams = std::move(scanParams);
179 
180  // remove stored AP information not matching the scanning parameters or related to APs
181  // that are not reachable on an allowed link
182  for (auto ap = m_apList.begin(); ap != m_apList.end();)
183  {
184  if (!MatchScanParams(*ap) ||
185  (!m_allowedLinks.empty() && m_allowedLinks.count(ap->m_linkId) == 0))
186  {
187  // remove AP info from list
188  m_apListIt.erase(ap->m_bssid);
189  ap = m_apList.erase(ap);
190  }
191  else
192  {
193  ++ap;
194  }
195  }
196 
197  DoStartScanning();
198 }
199 
200 void
202 {
203  NS_LOG_FUNCTION(this << apInfo);
204 
205  if (!CanBeInserted(apInfo) || !MatchScanParams(apInfo) ||
206  (!m_allowedLinks.empty() && m_allowedLinks.count(apInfo.m_linkId) == 0))
207  {
208  return;
209  }
210 
211  // check if an ApInfo object with the same BSSID is already present in the
212  // sorted list of ApInfo objects. This is done by trying to insert the BSSID
213  // in the hash table (insertion fails if the BSSID is already present)
214  auto [hashIt, hashInserted] = m_apListIt.insert({apInfo.m_bssid, {}});
215  if (!hashInserted)
216  {
217  // an element with the searched BSSID is already present in the hash table.
218  // Remove the corresponding ApInfo object from the sorted list.
219  m_apList.erase(hashIt->second);
220  }
221  // insert the ApInfo object
222  auto [listIt, listInserted] = m_apList.insert(std::move(apInfo));
223  // update the hash table entry
224  NS_ASSERT_MSG(listInserted,
225  "An entry (" << listIt->m_apAddr << ", " << listIt->m_bssid << ", "
226  << +listIt->m_linkId
227  << ") prevented insertion of given ApInfo object");
228  hashIt->second = listIt;
229 }
230 
231 void
233 {
234  NS_LOG_FUNCTION(this);
235 
236  StaWifiMac::ApInfo bestAp;
237 
238  do
239  {
240  if (m_apList.empty())
241  {
242  m_mac->ScanningTimeout(std::nullopt);
243  return;
244  }
245 
246  bestAp = std::move(m_apList.extract(m_apList.begin()).value());
247  m_apListIt.erase(bestAp.m_bssid);
248  } while (!CanBeReturned(bestAp));
249 
250  m_mac->ScanningTimeout(std::move(bestAp));
251 }
252 
253 std::list<StaWifiMac::ApInfo::SetupLinksInfo>&
255 {
256  return const_cast<std::list<StaWifiMac::ApInfo::SetupLinksInfo>&>(apInfo.m_setupLinks);
257 }
258 
259 bool
261 {
262  NS_LOG_FUNCTION(this);
263 
264  if (m_mac->GetNLinks() == 1 || GetSortedList().empty())
265  {
266  return false;
267  }
268 
269  // Get the Multi-Link Element and the RNR element, if present,
270  // from Beacon or Probe Response
271  if (auto beacon = std::get_if<MgtBeaconHeader>(&m_apList.begin()->m_frame); beacon)
272  {
273  mle = beacon->Get<MultiLinkElement>();
274  rnr = beacon->Get<ReducedNeighborReport>();
275  }
276  else
277  {
278  auto probeResp = std::get_if<MgtProbeResponseHeader>(&m_apList.begin()->m_frame);
279  NS_ASSERT(probeResp);
280  mle = probeResp->Get<MultiLinkElement>();
281  rnr = probeResp->Get<ReducedNeighborReport>();
282  }
283 
284  if (!mle.has_value())
285  {
286  NS_LOG_DEBUG("No Multi-Link Element in Beacon/Probe Response");
287  return false;
288  }
289 
290  if (!rnr.has_value() || rnr->get().GetNNbrApInfoFields() == 0)
291  {
292  NS_LOG_DEBUG("No Reduced Neighbor Report Element in Beacon/Probe Response");
293  return false;
294  }
295 
296  // The Multi-Link Element must contain the MLD MAC Address subfield and the
297  // Link ID Info subfield
298  if (!mle->get().HasLinkIdInfo())
299  {
300  NS_LOG_DEBUG("No Link ID Info subfield in the Multi-Link Element");
301  return false;
302  }
303 
304  if (const auto& mldCapabilities = mle->get().GetCommonInfoBasic().m_mldCapabilities)
305  {
306  auto ehtConfig = m_mac->GetEhtConfiguration();
307  NS_ASSERT(ehtConfig);
309  ehtConfig->GetAttributeFailSafe("TidToLinkMappingNegSupport", negSupport);
310 
311  // A non-AP MLD that performs multi-link (re)setup on at least two links with an AP MLD
312  // that sets the TID-To-Link Mapping Negotiation Support subfield of the MLD Capabilities
313  // field of the Basic Multi-Link element to a nonzero value shall support TID-to-link
314  // mapping negotiation with the TID-To-Link Mapping Negotiation Support subfield of the
315  // MLD Capabilities field of the Basic Multi-Link element it transmits to at least 1.
316  // (Sec. 35.3.7.1.1 of 802.11be D3.1)
317  if (mldCapabilities->tidToLinkMappingSupport > 0 && negSupport.Get() == 0)
318  {
319  NS_LOG_DEBUG("AP MLD supports TID-to-Link Mapping negotiation, while we don't");
320  return false;
321  }
322  }
323 
324  return true;
325 }
326 
327 std::optional<WifiAssocManager::RnrLinkInfo>
329 {
330  NS_LOG_FUNCTION(nbrApInfoId);
331 
332  while (nbrApInfoId < rnr.GetNNbrApInfoFields())
333  {
334  if (!rnr.HasMldParameters(nbrApInfoId))
335  {
336  // this Neighbor AP Info field is not suitable to setup a link
337  nbrApInfoId++;
338  continue;
339  }
340 
341  std::size_t tbttInfoFieldIndex = 0;
342  while (tbttInfoFieldIndex < rnr.GetNTbttInformationFields(nbrApInfoId) &&
343  rnr.GetMldId(nbrApInfoId, tbttInfoFieldIndex) != 0)
344  {
345  tbttInfoFieldIndex++;
346  }
347 
348  if (tbttInfoFieldIndex < rnr.GetNTbttInformationFields(nbrApInfoId))
349  {
350  // this Neighbor AP Info field contains an AP affiliated to the
351  // same AP MLD as the reporting AP
352  return RnrLinkInfo{nbrApInfoId, tbttInfoFieldIndex};
353  }
354  nbrApInfoId++;
355  }
356 
357  return std::nullopt;
358 }
359 
360 std::list<WifiAssocManager::RnrLinkInfo>
362 {
363  std::list<WifiAssocManager::RnrLinkInfo> apList;
364  std::size_t nbrApInfoId = 0;
365  std::optional<WifiAssocManager::RnrLinkInfo> next;
366 
367  while ((next = GetNextAffiliatedAp(rnr, nbrApInfoId)).has_value())
368  {
369  apList.push_back({*next});
370  nbrApInfoId = next->m_nbrApInfoId + 1;
371  }
372 
373  return apList;
374 }
375 
376 } // namespace ns3
A container for one type of attribute.
Hold variables of type enum.
Definition: enum.h:62
T Get() const
Definition: enum.h:102
A base class which provides memory management and object aggregation.
Definition: object.h:89
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:36
bool IsEqual(const Ssid &o) const
Check if the two SSIDs are equal.
Definition: ssid.cc:61
bool IsBroadcast() const
Check if the SSID is broadcast.
Definition: ssid.cc:72
void ScanningTimeout(const std::optional< ApInfo > &bestAp)
This method is called after wait beacon timeout or wait probe request timeout has occurred.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
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.
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition: wifi-mac.cc:933
Ptr< EhtConfiguration > GetEhtConfiguration() const
Definition: wifi-mac.cc:1755
#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
#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:86
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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:46
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
Definition: wifi-phy-band.h:43
Every class exported by the ns3 library is enclosed in the ns3 namespace.
channel
Definition: third.py:88
mac
Definition: third.py:92
Struct to hold information regarding observed AP through active/passive scanning.
Definition: sta-wifi-mac.h:158
MgtFrameType m_frame
The body of the management frame used to update AP info.
Definition: sta-wifi-mac.h:172
WifiScanParams::Channel m_channel
The channel the management frame was received on.
Definition: sta-wifi-mac.h:173
std::list< SetupLinksInfo > m_setupLinks
information about the links to setup between MLDs
Definition: sta-wifi-mac.h:176
uint8_t m_linkId
ID of the link used to communicate with the AP.
Definition: sta-wifi-mac.h:174
Mac48Address m_bssid
BSSID.
Definition: sta-wifi-mac.h:169
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.
Definition: sta-wifi-mac.h:70
uint16_t number
channel number
Definition: sta-wifi-mac.h:69
Structure holding scan parameters.
Definition: sta-wifi-mac.h:60
std::vector< ChannelList > channelList
list of channels to scan, for each link
Definition: sta-wifi-mac.h:78
Ssid ssid
desired SSID or wildcard SSID
Definition: sta-wifi-mac.h:77