A Discrete-Event Network Simulator
API
wifi-default-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 
22 
23 #include "sta-wifi-mac.h"
24 #include "wifi-phy.h"
25 
26 #include "ns3/log.h"
27 #include "ns3/simulator.h"
28 
29 #include <algorithm>
30 
31 namespace ns3
32 {
33 
34 NS_LOG_COMPONENT_DEFINE("WifiDefaultAssocManager");
35 
36 NS_OBJECT_ENSURE_REGISTERED(WifiDefaultAssocManager);
37 
38 TypeId
40 {
41  static TypeId tid =
42  TypeId("ns3::WifiDefaultAssocManager")
44  .AddConstructor<WifiDefaultAssocManager>()
45  .SetGroupName("Wifi")
46  .AddAttribute("ChannelSwitchTimeout",
47  "After requesting a channel switch on a link to setup that link, "
48  "wait at most this amount of time. If a channel switch is not "
49  "notified within this amount of time, we give up setting up that link.",
53  return tid;
54 }
55 
57 {
58  NS_LOG_FUNCTION(this);
59 }
60 
62 {
63  NS_LOG_FUNCTION(this);
64 }
65 
66 void
68 {
69  NS_LOG_FUNCTION(this);
73 }
74 
75 bool
77 {
78  return lhs.m_snr > rhs.m_snr;
79 }
80 
81 void
83 {
84  NS_LOG_FUNCTION(this);
85 
86  // if there are entries in the sorted list of AP information, reuse them and
87  // do not perform scanning
88  if (!GetSortedList().empty())
89  {
91  return;
92  }
93 
96 
98  {
99  for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
100  {
101  Simulator::Schedule(GetScanParams().probeDelay,
103  m_mac,
104  linkId);
105  }
107  Simulator::Schedule(GetScanParams().probeDelay + GetScanParams().maxChannelTime,
109  this);
110  }
111  else
112  {
115  this);
116  }
117 }
118 
119 void
121 {
122  NS_LOG_FUNCTION(this);
123 
124  OptMleConstRef mle;
125  OptRnrConstRef rnr;
126  std::list<WifiAssocManager::RnrLinkInfo> apList;
127 
128  // If multi-link setup is not possible, just call ScanningTimeout() and return
129  if (!CanSetupMultiLink(mle, rnr) || (apList = GetAllAffiliatedAps(*rnr)).empty())
130  {
131  ScanningTimeout();
132  return;
133  }
134 
135  auto& bestAp = *GetSortedList().begin();
136  auto& setupLinks = GetSetupLinks(bestAp);
137 
138  setupLinks.clear();
139  setupLinks.emplace_back(StaWifiMac::ApInfo::SetupLinksInfo{bestAp.m_linkId,
140  mle->get().GetLinkIdInfo(),
141  bestAp.m_bssid});
142 
143  // sort local PHY objects so that radios with constrained PHY band comes first,
144  // then radios with no constraint
145  std::list<uint8_t> localLinkIds;
146 
147  for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
148  {
149  if (linkId == bestAp.m_linkId)
150  {
151  // this link has been already added (it is the link on which the Beacon/Probe
152  // Response was received)
153  continue;
154  }
155 
156  if (m_mac->GetWifiPhy(linkId)->HasFixedPhyBand())
157  {
158  localLinkIds.push_front(linkId);
159  }
160  else
161  {
162  localLinkIds.push_back(linkId);
163  }
164  }
165 
166  // iterate over all the local links and find if we can setup a link for each of them
167  for (const auto& linkId : localLinkIds)
168  {
169  auto phy = m_mac->GetWifiPhy(linkId);
170  auto apIt = apList.begin();
171 
172  while (apIt != apList.end())
173  {
174  auto apChannel = rnr->get().GetOperatingChannel(apIt->m_nbrApInfoId);
175 
176  // we cannot setup a link with this affiliated AP if this PHY object is
177  // constrained to operate in the current PHY band and this affiliated AP
178  // is operating in a different PHY band than this PHY object
179  if (phy->HasFixedPhyBand() && phy->GetPhyBand() != apChannel.GetPhyBand())
180  {
181  apIt++;
182  continue;
183  }
184 
185  bool needChannelSwitch = false;
186  if (phy->GetOperatingChannel() != apChannel)
187  {
188  needChannelSwitch = true;
189  }
190 
191  if (needChannelSwitch && phy->IsStateSwitching())
192  {
193  // skip this affiliated AP, which is operating on a different channel
194  // than ours, because we are already switching channel and cannot
195  // schedule another channel switch to match the affiliated AP channel
196  apIt++;
197  continue;
198  }
199 
200  // if we get here, it means we can setup a link with this affiliated AP
201  // set the BSSID for this link
202  Mac48Address bssid = rnr->get().GetBssid(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId);
203  setupLinks.emplace_back(StaWifiMac::ApInfo::SetupLinksInfo{
204  linkId,
205  rnr->get().GetLinkId(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId),
206  bssid});
207 
208  if (needChannelSwitch)
209  {
210  if (phy->IsStateSleep())
211  {
212  // switching channel while a PHY is in sleep state fails
213  phy->ResumeFromSleep();
214  }
215  // switch this link to using the channel used by a reported AP
216  // TODO check if the STA only supports a narrower channel width
217  NS_LOG_DEBUG("Switch link " << +linkId << " to using " << apChannel);
218  WifiPhy::ChannelTuple chTuple{apChannel.GetNumber(),
219  apChannel.GetWidth(),
220  apChannel.GetPhyBand(),
221  apChannel.GetPrimaryChannelIndex(20)};
222  phy->SetOperatingChannel(chTuple);
223  // actual channel switching may be delayed, thus setup a channel switch timer
225  m_channelSwitchInfo[linkId].timer.Cancel();
226  m_channelSwitchInfo[linkId].timer =
229  this,
230  linkId);
231  m_channelSwitchInfo[linkId].apLinkAddress = bssid;
232  m_channelSwitchInfo[linkId].apMldAddress = mle->get().GetMldMacAddress();
233  }
234 
235  // remove the affiliated AP with which we are going to setup a link and move
236  // to the next local linkId
237  apList.erase(apIt);
238  break;
239  }
240  }
241 
242  if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
243  return info.timer.IsRunning();
244  }))
245  {
246  // we are done
247  ScanningTimeout();
248  }
249 }
250 
251 void
253 {
254  NS_LOG_FUNCTION(this << +linkId);
255  if (m_channelSwitchInfo.size() > linkId && m_channelSwitchInfo[linkId].timer.IsRunning())
256  {
257  // we were waiting for this notification
258  m_channelSwitchInfo[linkId].timer.Cancel();
259 
260  if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
261  return info.timer.IsRunning();
262  }))
263  {
264  // we are done
265  ScanningTimeout();
266  }
267  }
268 }
269 
270 void
272 {
273  NS_LOG_FUNCTION(this << +linkId);
274 
275  // we give up setting up this link
276  auto& bestAp = *GetSortedList().begin();
277  auto& setupLinks = GetSetupLinks(bestAp);
278  auto it = std::find_if(setupLinks.begin(), setupLinks.end(), [&linkId](auto&& linkIds) {
279  return linkIds.localLinkId == linkId;
280  });
281  NS_ASSERT(it != setupLinks.end());
282  setupLinks.erase(it);
283 
284  if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
285  return info.timer.IsRunning();
286  }))
287  {
288  // we are done
289  ScanningTimeout();
290  }
291 }
292 
293 bool
295 {
297 }
298 
299 bool
301 {
302  return true;
303 }
304 
305 } // namespace ns3
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
an EUI-48 address
Definition: mac48-address.h:46
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
void SendProbeRequest(uint8_t linkId)
Enqueue a probe request packet for transmission on the given link.
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
Ptr< StaWifiMac > m_mac
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...
std::optional< std::reference_wrapper< const ReducedNeighborReport > > OptRnrConstRef
typedef for an optional const reference to a ReducedNeighborReport object
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.
const WifiScanParams & GetScanParams() const
void DoDispose() override
Destructor implementation.
bool CanSetupMultiLink(OptMleConstRef &mle, OptRnrConstRef &rnr)
Check whether 11be Multi-Link setup can be established with the current best AP.
void EndScanning()
Perform operations to do at the end of a scanning procedure, such as identifying the links to setup i...
void DoDispose() override
Destructor implementation.
EventId m_probeRequestEvent
probe request event
void DoStartScanning() override
Start a scanning procedure.
bool CanBeInserted(const StaWifiMac::ApInfo &apInfo) const override
Allow subclasses to choose whether the given ApInfo shall be considered and hence inserted in the sor...
Time m_channelSwitchTimeout
maximum delay for channel switching
void NotifyChannelSwitched(uint8_t linkId) override
Notify that the given link has completed channel switching.
bool Compare(const StaWifiMac::ApInfo &lhs, const StaWifiMac::ApInfo &rhs) const override
Compare two ApInfo objects for the purpose of keeping a sorted list of ApInfo objects.
EventId m_waitBeaconEvent
wait beacon event
static TypeId GetTypeId()
Get the type ID.
void ChannelSwitchTimeout(uint8_t linkId)
Take action upon the expiration of the timer set when requesting channel switch on the given link.
std::vector< ChannelSwitchInfo > m_channelSwitchInfo
per-link channel switch info
bool CanBeReturned(const StaWifiMac::ApInfo &apInfo) const override
Allow subclasses to choose whether the given ApInfo shall be returned or discarded when the STA wifi ...
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition: wifi-mac.cc:933
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:1171
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:891
bool HasFixedPhyBand() const
Definition: wifi-phy.cc:1069
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1033
#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_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
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
phy
Definition: third.py:89
Struct to hold information regarding observed AP through active/passive scanning.
Definition: sta-wifi-mac.h:158
double m_snr
SNR in linear scale.
Definition: sta-wifi-mac.h:171