A Discrete-Event Network Simulator
API
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/log.h"
26 
27 #include <algorithm>
28 
29 namespace ns3
30 {
31 
32 NS_LOG_COMPONENT_DEFINE("WifiAssocManager");
33 
34 NS_OBJECT_ENSURE_REGISTERED(WifiAssocManager);
35 
37  : m_manager(manager)
38 {
39 }
40 
41 bool
43  const StaWifiMac::ApInfo& rhs) const
44 {
45  NS_ASSERT_MSG(lhs.m_bssid != rhs.m_bssid,
46  "Comparing two ApInfo objects with the same BSSID: " << lhs.m_bssid);
47 
48  bool lhsBefore = m_manager.Compare(lhs, rhs);
49  if (lhsBefore)
50  {
51  return true;
52  }
53 
54  bool rhsBefore = m_manager.Compare(rhs, lhs);
55  if (rhsBefore)
56  {
57  return false;
58  }
59 
60  // the Compare method implemented by subclass may be such that the two ApInfo objects
61  // compare equal; in such a case, use the BSSID as tie breaker
62  return lhs.m_bssid < rhs.m_bssid;
63 }
64 
65 TypeId
67 {
68  static TypeId tid = TypeId("ns3::WifiAssocManager").SetParent<Object>().SetGroupName("Wifi");
69  return tid;
70 }
71 
73  : m_scanParams(), // zero-initialization
74  m_apList(ApInfoCompare(*this))
75 {
76 }
77 
79 {
80  NS_LOG_FUNCTION(this);
81 }
82 
83 void
85 {
86  NS_LOG_FUNCTION(this);
87  m_mac = nullptr;
88 }
89 
90 void
92 {
93  NS_LOG_FUNCTION(this << mac);
94  m_mac = mac;
95 }
96 
99 {
100  return m_apList;
101 }
102 
103 const WifiScanParams&
105 {
106  return m_scanParams;
107 }
108 
109 bool
111 {
112  NS_LOG_FUNCTION(this << apInfo);
113 
115  {
116  // we need to check if AP's advertised SSID matches the requested SSID
117  Ssid apSsid;
118  if (auto beacon = std::get_if<MgtBeaconHeader>(&apInfo.m_frame); beacon)
119  {
120  apSsid = beacon->GetSsid();
121  }
122  else
123  {
124  auto probeResp = std::get_if<MgtProbeResponseHeader>(&apInfo.m_frame);
125  NS_ASSERT(probeResp);
126  apSsid = probeResp->GetSsid();
127  }
128  if (!apSsid.IsEqual(m_scanParams.ssid))
129  {
130  NS_LOG_DEBUG("AP " << apInfo.m_bssid << " does not advertise our SSID " << apSsid
131  << " " << m_scanParams.ssid);
132  return false;
133  }
134  }
135 
136  // we need to check if the AP is operating on a requested channel
137  auto channelMatch = [&apInfo](auto&& channel) {
138  if (channel.number != 0 && channel.number != apInfo.m_channel.number)
139  {
140  return false;
141  }
142  if (channel.band != WIFI_PHY_BAND_UNSPECIFIED && channel.band != apInfo.m_channel.band)
143  {
144  return false;
145  }
146  return true;
147  };
148 
149  NS_ASSERT(apInfo.m_linkId < m_scanParams.channelList.size());
150  if (std::find_if(m_scanParams.channelList[apInfo.m_linkId].cbegin(),
151  m_scanParams.channelList[apInfo.m_linkId].cend(),
152  channelMatch) == m_scanParams.channelList[apInfo.m_linkId].cend())
153  {
154  NS_LOG_DEBUG("AP " << apInfo.m_bssid << " is not operating on a requested channel");
155  return false;
156  }
157 
158  return true;
159 }
160 
161 void
163 {
164  NS_LOG_FUNCTION(this);
165  m_scanParams = std::move(scanParams);
166 
167  // remove stored AP information not matching the scanning parameters
168  for (auto ap = m_apList.begin(); ap != m_apList.end();)
169  {
170  if (!MatchScanParams(*ap))
171  {
172  // remove AP info from list
173  m_apListIt.erase(ap->m_bssid);
174  ap = m_apList.erase(ap);
175  }
176  else
177  {
178  ++ap;
179  }
180  }
181 
182  DoStartScanning();
183 }
184 
185 void
187 {
188  NS_LOG_FUNCTION(this << apInfo);
189 
190  if (!CanBeInserted(apInfo) || !MatchScanParams(apInfo))
191  {
192  return;
193  }
194 
195  // check if an ApInfo object with the same BSSID is already present in the
196  // sorted list of ApInfo objects. This is done by trying to insert the BSSID
197  // in the hash table (insertion fails if the BSSID is already present)
198  auto [hashIt, hashInserted] = m_apListIt.insert({apInfo.m_bssid, {}});
199  if (!hashInserted)
200  {
201  // an element with the searched BSSID is already present in the hash table.
202  // Remove the corresponding ApInfo object from the sorted list.
203  m_apList.erase(hashIt->second);
204  }
205  // insert the ApInfo object
206  auto [listIt, listInserted] = m_apList.insert(std::move(apInfo));
207  // update the hash table entry
208  NS_ASSERT_MSG(listInserted,
209  "An entry (" << listIt->m_apAddr << ", " << listIt->m_bssid << ", "
210  << +listIt->m_linkId
211  << ") prevented insertion of given ApInfo object");
212  hashIt->second = listIt;
213 }
214 
215 void
217 {
218  NS_LOG_FUNCTION(this);
219 
220  StaWifiMac::ApInfo bestAp;
221 
222  do
223  {
224  if (m_apList.empty())
225  {
226  m_mac->ScanningTimeout(std::nullopt);
227  return;
228  }
229 
230  bestAp = std::move(m_apList.extract(m_apList.begin()).value());
231  m_apListIt.erase(bestAp.m_bssid);
232  } while (!CanBeReturned(bestAp));
233 
234  m_mac->ScanningTimeout(std::move(bestAp));
235 }
236 
237 std::list<std::pair<std::uint8_t, uint8_t>>&
239 {
240  return const_cast<std::list<std::pair<std::uint8_t, uint8_t>>&>(apInfo.m_setupLinks);
241 }
242 
243 bool
245 {
246  NS_LOG_FUNCTION(this);
247 
248  if (m_mac->GetNLinks() == 1 || GetSortedList().empty())
249  {
250  return false;
251  }
252 
253  // Get the Multi-Link Element and the RNR element, if present,
254  // from Beacon or Probe Response
255  if (auto beacon = std::get_if<MgtBeaconHeader>(&m_apList.begin()->m_frame); beacon)
256  {
257  mle = beacon->GetMultiLinkElement();
258  rnr = beacon->GetReducedNeighborReport();
259  }
260  else
261  {
262  auto probeResp = std::get_if<MgtProbeResponseHeader>(&m_apList.begin()->m_frame);
263  NS_ASSERT(probeResp);
264  mle = probeResp->GetMultiLinkElement();
265  rnr = probeResp->GetReducedNeighborReport();
266  }
267 
268  if (!mle.has_value())
269  {
270  NS_LOG_DEBUG("No Multi-Link Element in Beacon/Probe Response");
271  return false;
272  }
273 
274  if (!rnr.has_value() || rnr->get().GetNNbrApInfoFields() == 0)
275  {
276  NS_LOG_DEBUG("No Reduced Neighbor Report Element in Beacon/Probe Response");
277  return false;
278  }
279 
280  // The Multi-Link Element must contain the MLD MAC Address subfield and the
281  // Link ID Info subfield
282  if (!mle->get().HasLinkIdInfo())
283  {
284  NS_LOG_DEBUG("No Link ID Info subfield in the Multi-Link Element");
285  return false;
286  }
287 
288  return true;
289 }
290 
291 std::optional<WifiAssocManager::RnrLinkInfo>
293 {
294  NS_LOG_FUNCTION(nbrApInfoId);
295 
296  while (nbrApInfoId < rnr.GetNNbrApInfoFields())
297  {
298  if (!rnr.HasMldParameters(nbrApInfoId))
299  {
300  // this Neighbor AP Info field is not suitable to setup a link
301  nbrApInfoId++;
302  continue;
303  }
304 
305  std::size_t tbttInfoFieldIndex = 0;
306  while (tbttInfoFieldIndex < rnr.GetNTbttInformationFields(nbrApInfoId) &&
307  rnr.GetMldId(nbrApInfoId, tbttInfoFieldIndex) != 0)
308  {
309  tbttInfoFieldIndex++;
310  }
311 
312  if (tbttInfoFieldIndex < rnr.GetNTbttInformationFields(nbrApInfoId))
313  {
314  // this Neighbor AP Info field contains an AP affiliated to the
315  // same AP MLD as the reporting AP
316  return RnrLinkInfo{nbrApInfoId, tbttInfoFieldIndex};
317  }
318  nbrApInfoId++;
319  }
320 
321  return std::nullopt;
322 }
323 
324 std::list<WifiAssocManager::RnrLinkInfo>
326 {
327  std::list<WifiAssocManager::RnrLinkInfo> apList;
328  std::size_t nbrApInfoId = 0;
329  std::optional<WifiAssocManager::RnrLinkInfo> next;
330 
331  while ((next = GetNextAffiliatedAp(rnr, nbrApInfoId)).has_value())
332  {
333  apList.push_back({*next});
334  nbrApInfoId = next->m_nbrApInfoId + 1;
335  }
336 
337  return apList;
338 }
339 
340 } // namespace ns3
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:55
bool IsBroadcast() const
Check if the SSID is broadcast.
Definition: ssid.cc:70
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:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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.
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
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)
std::list< std::pair< std::uint8_t, uint8_t > > & GetSetupLinks(const StaWifiMac::ApInfo &apInfo)
Get a reference to the list of the links to setup with the given AP.
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:906
#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:81
mac
Definition: third.py:85
Struct to hold information regarding observed AP through active/passive scanning.
Definition: sta-wifi-mac.h:144
std::list< std::pair< std::uint8_t, uint8_t > > m_setupLinks
list of (local link ID, AP link ID) pairs identifying the links to setup between MLDs
Definition: sta-wifi-mac.h:152
MgtFrameType m_frame
The body of the management frame used to update AP info.
Definition: sta-wifi-mac.h:148
WifiScanParams::Channel m_channel
The channel the management frame was received on.
Definition: sta-wifi-mac.h:149
uint8_t m_linkId
ID of the link used to communicate with the AP.
Definition: sta-wifi-mac.h:150
Mac48Address m_bssid
BSSID.
Definition: sta-wifi-mac.h:145
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:60
uint16_t number
channel number
Definition: sta-wifi-mac.h:59
Structure holding scan parameters.
Definition: sta-wifi-mac.h:50
std::vector< ChannelList > channelList
list of channels to scan, for each link
Definition: sta-wifi-mac.h:73
Ssid ssid
desired SSID or wildcard SSID
Definition: sta-wifi-mac.h:72