A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 * Author: Stefano Avallone <stavallo@unina.it>
8 */
9
11
12#include "sta-wifi-mac.h"
13#include "wifi-net-device.h"
14#include "wifi-phy.h"
15
16#include "ns3/log.h"
17#include "ns3/simulator.h"
18#include "ns3/vht-configuration.h"
19
20#include <algorithm>
21
22namespace ns3
23{
24
25NS_LOG_COMPONENT_DEFINE("WifiDefaultAssocManager");
26
27NS_OBJECT_ENSURE_REGISTERED(WifiDefaultAssocManager);
28
29TypeId
31{
32 static TypeId tid =
33 TypeId("ns3::WifiDefaultAssocManager")
35 .AddConstructor<WifiDefaultAssocManager>()
36 .SetGroupName("Wifi")
37 .AddAttribute("ChannelSwitchTimeout",
38 "After requesting a channel switch on a link to setup that link, "
39 "wait at most this amount of time. If a channel switch is not "
40 "notified within this amount of time, we give up setting up that link.",
44 return tid;
45}
46
51
56
57void
65
66bool
68{
69 return lhs.m_snr > rhs.m_snr;
70}
71
72void
74{
75 NS_LOG_FUNCTION(this);
76
77 // if there are entries in the sorted list of AP information, reuse them and
78 // do not perform scanning
79 if (!GetSortedList().empty())
80 {
82 return;
83 }
84
87
89 {
90 for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
91 {
94 m_mac,
95 linkId);
96 }
98 Simulator::Schedule(GetScanParams().probeDelay + GetScanParams().maxChannelTime,
100 this);
101 }
102 else
103 {
106 this);
107 }
108}
109
110void
112{
113 NS_LOG_FUNCTION(this);
114
115 OptMleConstRef mle;
116 OptRnrConstRef rnr;
117 std::list<WifiAssocManager::RnrLinkInfo> apList;
118
119 // If multi-link setup is not possible, just call ScanningTimeout() and return
120 if (!CanSetupMultiLink(mle, rnr) || (apList = GetAllAffiliatedAps(*rnr)).empty())
121 {
123 return;
124 }
125
126 auto& bestAp = *GetSortedList().begin();
127 auto& setupLinks = GetSetupLinks(bestAp);
128
129 setupLinks.clear();
130 setupLinks.emplace_back(StaWifiMac::ApInfo::SetupLinksInfo{bestAp.m_linkId,
131 mle->get().GetLinkIdInfo(),
132 bestAp.m_bssid});
133
134 // sort local PHY objects so that radios with constrained PHY band comes first,
135 // then radios with no constraint
136 std::list<uint8_t> localLinkIds;
137
138 for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
139 {
140 if (linkId == bestAp.m_linkId)
141 {
142 // this link has been already added (it is the link on which the Beacon/Probe
143 // Response was received)
144 continue;
145 }
146
147 if (m_mac->GetWifiPhy(linkId)->HasFixedPhyBand())
148 {
149 localLinkIds.push_front(linkId);
150 }
151 else
152 {
153 localLinkIds.push_back(linkId);
154 }
155 }
156
157 // iterate over all the local links and find if we can setup a link for each of them
158 for (const auto& linkId : localLinkIds)
159 {
160 auto phy = m_mac->GetWifiPhy(linkId);
161 auto apIt = apList.begin();
162
163 while (apIt != apList.end())
164 {
165 auto apChannel = rnr->get().GetOperatingChannel(apIt->m_nbrApInfoId);
166
167 // we cannot setup a link with this affiliated AP if this PHY object is
168 // constrained to operate in the current PHY band and this affiliated AP
169 // is operating in a different PHY band than this PHY object
170 if (phy->HasFixedPhyBand() && phy->GetPhyBand() != apChannel.GetPhyBand())
171 {
172 apIt++;
173 continue;
174 }
175
176 bool needChannelSwitch = false;
177 if (phy->GetOperatingChannel() != apChannel)
178 {
179 needChannelSwitch = true;
180 }
181
182 if (needChannelSwitch && phy->IsStateSwitching())
183 {
184 // skip this affiliated AP, which is operating on a different channel
185 // than ours, because we are already switching channel and cannot
186 // schedule another channel switch to match the affiliated AP channel
187 apIt++;
188 continue;
189 }
190
191 // if we get here, it means we can setup a link with this affiliated AP
192 // set the BSSID for this link
193 Mac48Address bssid = rnr->get().GetBssid(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId);
194 setupLinks.emplace_back(StaWifiMac::ApInfo::SetupLinksInfo{
195 linkId,
196 rnr->get().GetLinkId(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId),
197 bssid});
198
199 if (needChannelSwitch)
200 {
201 if (phy->IsStateSleep())
202 {
203 // switching channel while a PHY is in sleep state fails
204 phy->ResumeFromSleep();
205 }
206 // switch this link to using the channel used by a reported AP (or its primary80
207 // in case the reported AP is using a 160 MHz and the non-AP MLD does not support
208 // 160 MHz operations)
209 if (apChannel.GetTotalWidth() > 80 &&
210 !phy->GetDevice()->GetVhtConfiguration()->Get160MHzOperationSupported())
211 {
212 apChannel = apChannel.GetPrimaryChannel(80);
213 }
214
215 NS_LOG_DEBUG("Switch link " << +linkId << " to using " << apChannel);
216 phy->SetOperatingChannel(apChannel);
217 // actual channel switching may be delayed, thus setup a channel switch timer
218 m_channelSwitchInfo.resize(m_mac->GetNLinks());
219 m_channelSwitchInfo[linkId].timer.Cancel();
220 m_channelSwitchInfo[linkId].timer =
223 this,
224 linkId);
225 m_channelSwitchInfo[linkId].apLinkAddress = bssid;
226 m_channelSwitchInfo[linkId].apMldAddress = mle->get().GetMldMacAddress();
227 }
228
229 // remove the affiliated AP with which we are going to setup a link and move
230 // to the next local linkId
231 apList.erase(apIt);
232 break;
233 }
234 }
235
236 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
237 return info.timer.IsPending();
238 }))
239 {
240 // we are done
242 }
243}
244
245void
247{
248 NS_LOG_FUNCTION(this << +linkId);
249 if (m_channelSwitchInfo.size() > linkId && m_channelSwitchInfo[linkId].timer.IsPending())
250 {
251 // we were waiting for this notification
252 m_channelSwitchInfo[linkId].timer.Cancel();
253
254 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
255 return info.timer.IsPending();
256 }))
257 {
258 // we are done
260 }
261 }
262}
263
264void
266{
267 NS_LOG_FUNCTION(this << +linkId);
268
269 // we give up setting up this link
270 auto& bestAp = *GetSortedList().begin();
271 auto& setupLinks = GetSetupLinks(bestAp);
272 auto it = std::find_if(setupLinks.begin(), setupLinks.end(), [&linkId](auto&& linkIds) {
273 return linkIds.localLinkId == linkId;
274 });
275 NS_ASSERT(it != setupLinks.end());
276 setupLinks.erase(it);
277
278 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
279 return info.timer.IsPending();
280 }))
281 {
282 // we are done
284 }
285}
286
287bool
292
293bool
295{
296 return true;
297}
298
299} // namespace ns3
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
an EUI-48 address
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:594
void SendProbeRequest(uint8_t linkId)
Enqueue a probe request packet for transmission on the given link.
AttributeValue implementation for Time.
Definition nstime.h:1395
a unique identifier for an interface.
Definition type-id.h:48
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
Ptr< StaWifiMac > m_mac
pointer to the STA wifi MAC
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...
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 ...
#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
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1396
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1416
#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
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Struct to hold information regarding observed AP through active/passive scanning.
double m_snr
SNR in linear scale.