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/boolean.h"
17#include "ns3/log.h"
18#include "ns3/simulator.h"
19#include "ns3/vht-configuration.h"
20
21#include <algorithm>
22
23namespace ns3
24{
25
26NS_LOG_COMPONENT_DEFINE("WifiDefaultAssocManager");
27
28NS_OBJECT_ENSURE_REGISTERED(WifiDefaultAssocManager);
29
30TypeId
32{
33 static TypeId tid =
34 TypeId("ns3::WifiDefaultAssocManager")
36 .AddConstructor<WifiDefaultAssocManager>()
37 .SetGroupName("Wifi")
38 .AddAttribute("ChannelSwitchTimeout",
39 "After requesting a channel switch on a link to setup that link, "
40 "wait at most this amount of time. If a channel switch is not "
41 "notified within this amount of time, we give up setting up that link.",
45 .AddAttribute(
46 "SkipAssocIncompatibleChannelWidth",
47 "If set to true, it does not include APs with incompatible channel width with the "
48 "STA in the list of candidate APs. An incompatible channel width is one that the "
49 "STA cannot advertise to the AP, unless AP operates on a channel width that is "
50 "equal or lower than that channel width.",
51 BooleanValue(false),
54 return tid;
55}
56
61
66
67void
75
76bool
78{
79 return lhs.m_snr > rhs.m_snr;
80}
81
82void
84{
85 NS_LOG_FUNCTION(this);
86
87 // if there are entries in the sorted list of AP information, reuse them and
88 // do not perform scanning
89 if (!GetSortedList().empty())
90 {
92 return;
93 }
94
97
99 {
100 for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
101 {
104 m_mac,
105 m_mac->GetProbeRequest(linkId),
106 linkId,
109 }
111 Simulator::Schedule(GetScanParams().probeDelay + GetScanParams().maxChannelTime,
113 this);
114 }
115 else
116 {
119 this);
120 }
121}
122
123void
125{
126 NS_LOG_FUNCTION(this);
127
128 OptMleConstRef mle;
129 OptRnrConstRef rnr;
130 std::list<WifiAssocManager::RnrLinkInfo> apList;
131
132 // If multi-link setup is not possible, just call ScanningTimeout() and return
133 if (!CanSetupMultiLink(mle, rnr) || (apList = GetAllAffiliatedAps(*rnr)).empty())
134 {
136 return;
137 }
138
139 auto& bestAp = *GetSortedList().begin();
140 auto& setupLinks = GetSetupLinks(bestAp);
141
142 setupLinks.clear();
143 setupLinks.emplace_back(StaWifiMac::ApInfo::SetupLinksInfo{bestAp.m_linkId,
144 mle->get().GetLinkIdInfo(),
145 bestAp.m_bssid});
146
147 // sort local PHY objects so that radios with constrained PHY band comes first,
148 // then radios with no constraint
149 std::list<uint8_t> localLinkIds;
150
151 for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
152 {
153 if (linkId == bestAp.m_linkId)
154 {
155 // this link has been already added (it is the link on which the Beacon/Probe
156 // Response was received)
157 continue;
158 }
159
160 if (m_mac->GetWifiPhy(linkId)->HasFixedPhyBand())
161 {
162 localLinkIds.push_front(linkId);
163 }
164 else
165 {
166 localLinkIds.push_back(linkId);
167 }
168 }
169
170 // iterate over all the local links and find if we can setup a link for each of them
171 for (const auto& linkId : localLinkIds)
172 {
173 auto phy = m_mac->GetWifiPhy(linkId);
174 auto apIt = apList.begin();
175
176 while (apIt != apList.end())
177 {
178 auto apChannel = rnr->get().GetOperatingChannel(apIt->m_nbrApInfoId);
179
180 // we cannot setup a link with this affiliated AP if this PHY object is
181 // constrained to operate in the current PHY band and this affiliated AP
182 // is operating in a different PHY band than this PHY object
183 if (phy->HasFixedPhyBand() && phy->GetPhyBand() != apChannel.GetPhyBand())
184 {
185 apIt++;
186 continue;
187 }
188
189 bool needChannelSwitch = false;
190 if (phy->GetOperatingChannel() != apChannel)
191 {
192 needChannelSwitch = true;
193 }
194
195 if (needChannelSwitch && phy->IsStateSwitching())
196 {
197 // skip this affiliated AP, which is operating on a different channel
198 // than ours, because we are already switching channel and cannot
199 // schedule another channel switch to match the affiliated AP channel
200 apIt++;
201 continue;
202 }
203
204 // if we get here, it means we can setup a link with this affiliated AP
205 // set the BSSID for this link
206 Mac48Address bssid = rnr->get().GetBssid(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId);
207 setupLinks.emplace_back(StaWifiMac::ApInfo::SetupLinksInfo{
208 linkId,
209 rnr->get().GetMldParameters(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId).linkId,
210 bssid});
211
212 if (needChannelSwitch)
213 {
214 if (phy->IsStateSleep())
215 {
216 // switching channel while a PHY is in sleep state fails
217 phy->ResumeFromSleep();
218 }
219
220 // switch this link to using the channel used by a reported AP (or one of its
221 // primary subchannels in case the reported AP has larger channel width than the one
222 // supported by the non-AP MLD)
223 if (apChannel.GetTotalWidth() > phy->GetChannelWidth())
224 {
225 apChannel = apChannel.GetPrimaryChannel(phy->GetChannelWidth());
226 }
227
228 NS_LOG_DEBUG("Switch link " << +linkId << " to using " << apChannel);
229 phy->SetOperatingChannel(apChannel);
230 // actual channel switching may be delayed, thus setup a channel switch timer
231 m_channelSwitchInfo.resize(m_mac->GetNLinks());
232 m_channelSwitchInfo[linkId].timer.Cancel();
233 m_channelSwitchInfo[linkId].timer =
236 this,
237 linkId);
238 m_channelSwitchInfo[linkId].apLinkAddress = bssid;
239 m_channelSwitchInfo[linkId].apMldAddress = mle->get().GetMldMacAddress();
240 }
241
242 // remove the affiliated AP with which we are going to setup a link and move
243 // to the next local linkId
244 apList.erase(apIt);
245 break;
246 }
247 }
248
249 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
250 return info.timer.IsPending();
251 }))
252 {
253 // we are done
255 }
256}
257
258void
260{
261 NS_LOG_FUNCTION(this << +linkId);
262 if (m_channelSwitchInfo.size() > linkId && m_channelSwitchInfo[linkId].timer.IsPending())
263 {
264 // we were waiting for this notification
265 m_channelSwitchInfo[linkId].timer.Cancel();
266
267 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
268 return info.timer.IsPending();
269 }))
270 {
271 // we are done
273 }
274 }
275}
276
277void
279{
280 NS_LOG_FUNCTION(this << +linkId);
281
282 // we give up setting up this link
283 auto& bestAp = *GetSortedList().begin();
284 auto& setupLinks = GetSetupLinks(bestAp);
285 auto it = std::find_if(setupLinks.begin(), setupLinks.end(), [&linkId](auto&& linkIds) {
286 return linkIds.localLinkId == linkId;
287 });
288 NS_ASSERT(it != setupLinks.end());
289 setupLinks.erase(it);
290
291 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
292 return info.timer.IsPending();
293 }))
294 {
295 // we are done
297 }
298}
299
300bool
306
307bool
309{
310 return true;
311}
312
313} // namespace ns3
AttributeValue implementation for Boolean.
Definition boolean.h:26
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
bool IsChannelWidthCompatible(const StaWifiMac::ApInfo &apInfo) const
Check whether the channel width of the STA is compatible with the channel width of the operating chan...
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.
bool m_skipAssocIncompatibleChannelWidth
flag whether to skip APs with incompatible channel width
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 AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
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.