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 m_mac->GetProbeRequest(linkId),
96 linkId,
99 }
101 Simulator::Schedule(GetScanParams().probeDelay + GetScanParams().maxChannelTime,
103 this);
104 }
105 else
106 {
109 this);
110 }
111}
112
113void
115{
116 NS_LOG_FUNCTION(this);
117
118 OptMleConstRef mle;
119 OptRnrConstRef rnr;
120 std::list<WifiAssocManager::RnrLinkInfo> apList;
121
122 // If multi-link setup is not possible, just call ScanningTimeout() and return
123 if (!CanSetupMultiLink(mle, rnr) || (apList = GetAllAffiliatedAps(*rnr)).empty())
124 {
126 return;
127 }
128
129 auto& bestAp = *GetSortedList().begin();
130 auto& setupLinks = GetSetupLinks(bestAp);
131
132 setupLinks.clear();
133 setupLinks.emplace_back(StaWifiMac::ApInfo::SetupLinksInfo{bestAp.m_linkId,
134 mle->get().GetLinkIdInfo(),
135 bestAp.m_bssid});
136
137 // sort local PHY objects so that radios with constrained PHY band comes first,
138 // then radios with no constraint
139 std::list<uint8_t> localLinkIds;
140
141 for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
142 {
143 if (linkId == bestAp.m_linkId)
144 {
145 // this link has been already added (it is the link on which the Beacon/Probe
146 // Response was received)
147 continue;
148 }
149
150 if (m_mac->GetWifiPhy(linkId)->HasFixedPhyBand())
151 {
152 localLinkIds.push_front(linkId);
153 }
154 else
155 {
156 localLinkIds.push_back(linkId);
157 }
158 }
159
160 // iterate over all the local links and find if we can setup a link for each of them
161 for (const auto& linkId : localLinkIds)
162 {
163 auto phy = m_mac->GetWifiPhy(linkId);
164 auto apIt = apList.begin();
165
166 while (apIt != apList.end())
167 {
168 auto apChannel = rnr->get().GetOperatingChannel(apIt->m_nbrApInfoId);
169
170 // we cannot setup a link with this affiliated AP if this PHY object is
171 // constrained to operate in the current PHY band and this affiliated AP
172 // is operating in a different PHY band than this PHY object
173 if (phy->HasFixedPhyBand() && phy->GetPhyBand() != apChannel.GetPhyBand())
174 {
175 apIt++;
176 continue;
177 }
178
179 bool needChannelSwitch = false;
180 if (phy->GetOperatingChannel() != apChannel)
181 {
182 needChannelSwitch = true;
183 }
184
185 if (needChannelSwitch && phy->IsStateSwitching())
186 {
187 // skip this affiliated AP, which is operating on a different channel
188 // than ours, because we are already switching channel and cannot
189 // schedule another channel switch to match the affiliated AP channel
190 apIt++;
191 continue;
192 }
193
194 // if we get here, it means we can setup a link with this affiliated AP
195 // set the BSSID for this link
196 Mac48Address bssid = rnr->get().GetBssid(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId);
197 setupLinks.emplace_back(StaWifiMac::ApInfo::SetupLinksInfo{
198 linkId,
199 rnr->get().GetMldParameters(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId).linkId,
200 bssid});
201
202 if (needChannelSwitch)
203 {
204 if (phy->IsStateSleep())
205 {
206 // switching channel while a PHY is in sleep state fails
207 phy->ResumeFromSleep();
208 }
209 // switch this link to using the channel used by a reported AP (or its primary80
210 // in case the reported AP is using a 160 MHz and the non-AP MLD does not support
211 // 160 MHz operations)
212 if (apChannel.GetTotalWidth() > MHz_u{80} &&
213 !phy->GetDevice()->GetVhtConfiguration()->m_160MHzSupported)
214 {
215 apChannel = apChannel.GetPrimaryChannel(MHz_u{80});
216 }
217
218 NS_LOG_DEBUG("Switch link " << +linkId << " to using " << apChannel);
219 phy->SetOperatingChannel(apChannel);
220 // actual channel switching may be delayed, thus setup a channel switch timer
221 m_channelSwitchInfo.resize(m_mac->GetNLinks());
222 m_channelSwitchInfo[linkId].timer.Cancel();
223 m_channelSwitchInfo[linkId].timer =
226 this,
227 linkId);
228 m_channelSwitchInfo[linkId].apLinkAddress = bssid;
229 m_channelSwitchInfo[linkId].apMldAddress = mle->get().GetMldMacAddress();
230 }
231
232 // remove the affiliated AP with which we are going to setup a link and move
233 // to the next local linkId
234 apList.erase(apIt);
235 break;
236 }
237 }
238
239 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
240 return info.timer.IsPending();
241 }))
242 {
243 // we are done
245 }
246}
247
248void
250{
251 NS_LOG_FUNCTION(this << +linkId);
252 if (m_channelSwitchInfo.size() > linkId && m_channelSwitchInfo[linkId].timer.IsPending())
253 {
254 // we were waiting for this notification
255 m_channelSwitchInfo[linkId].timer.Cancel();
256
257 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
258 return info.timer.IsPending();
259 }))
260 {
261 // we are done
263 }
264 }
265}
266
267void
269{
270 NS_LOG_FUNCTION(this << +linkId);
271
272 // we give up setting up this link
273 auto& bestAp = *GetSortedList().begin();
274 auto& setupLinks = GetSetupLinks(bestAp);
275 auto it = std::find_if(setupLinks.begin(), setupLinks.end(), [&linkId](auto&& linkIds) {
276 return linkIds.localLinkId == linkId;
277 });
278 NS_ASSERT(it != setupLinks.end());
279 setupLinks.erase(it);
280
281 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
282 return info.timer.IsPending();
283 }))
284 {
285 // we are done
287 }
288}
289
290bool
295
296bool
298{
299 return true;
300}
301
302} // 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 Mac48Address GetBroadcast()
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:595
void EnqueueProbeRequest(const MgtProbeRequestHeader &probeReq, uint8_t linkId, const Mac48Address &addr1=Mac48Address::GetBroadcast(), const Mac48Address &addr3=Mac48Address::GetBroadcast())
Enqueue the given probe request packet for transmission on the given link.
AttributeValue implementation for Time.
Definition nstime.h:1432
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
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:1433
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1453
#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:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
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.