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
31namespace ns3
32{
33
34NS_LOG_COMPONENT_DEFINE("WifiDefaultAssocManager");
35
36NS_OBJECT_ENSURE_REGISTERED(WifiDefaultAssocManager);
37
38TypeId
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
66void
68{
69 NS_LOG_FUNCTION(this);
73}
74
75bool
77{
78 return lhs.m_snr > rhs.m_snr;
79}
80
81void
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 {
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
131 // store AP MLD MAC address in the WifiRemoteStationManager associated with
132 // the link on which the Beacon/Probe Response was received
133 m_mac->GetWifiRemoteStationManager(bestAp.m_linkId)
134 ->SetMldAddress(bestAp.m_apAddr, mle->get().GetMldMacAddress());
135 auto& setupLinks = GetSetupLinks(bestAp);
136
137 setupLinks.clear();
138 setupLinks.emplace_back(bestAp.m_linkId, mle->get().GetLinkIdInfo());
139
140 // sort local PHY objects so that radios with constrained PHY band comes first,
141 // then radios with no constraint
142 std::list<uint8_t> localLinkIds;
143
144 for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
145 {
146 if (linkId == bestAp.m_linkId)
147 {
148 // this link has been already added (it is the link on which the Beacon/Probe
149 // Response was received)
150 continue;
151 }
152
153 if (m_mac->GetWifiPhy(linkId)->HasFixedPhyBand())
154 {
155 localLinkIds.push_front(linkId);
156 }
157 else
158 {
159 localLinkIds.push_back(linkId);
160 }
161 }
162
163 // iterate over all the local links and find if we can setup a link for each of them
164 for (const auto& linkId : localLinkIds)
165 {
166 auto phy = m_mac->GetWifiPhy(linkId);
167 auto apIt = apList.begin();
168
169 while (apIt != apList.end())
170 {
171 auto apChannel = rnr->get().GetOperatingChannel(apIt->m_nbrApInfoId);
172
173 // we cannot setup a link with this affiliated AP if this PHY object is
174 // constrained to operate in the current PHY band and this affiliated AP
175 // is operating in a different PHY band than this PHY object
176 if (phy->HasFixedPhyBand() && phy->GetPhyBand() != apChannel.GetPhyBand())
177 {
178 apIt++;
179 continue;
180 }
181
182 bool needChannelSwitch = false;
183 if (const auto& channel = phy->GetOperatingChannel();
184 channel.GetNumber() != apChannel.GetNumber() ||
185 channel.GetWidth() != apChannel.GetWidth() ||
186 channel.GetPhyBand() != apChannel.GetPhyBand())
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 // store AP MLD MAC address in the WifiRemoteStationManager associated with
204 // the link requested to setup
206 bssid,
207 mle->get().GetMldMacAddress());
208 setupLinks.emplace_back(
209 linkId,
210 rnr->get().GetLinkId(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId));
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 // switch this link to using the channel used by a reported AP
220 // TODO check if the STA only supports a narrower channel width
221 NS_LOG_DEBUG("Switch link "
222 << +linkId << " to using channel " << +apChannel.GetNumber()
223 << " in band " << apChannel.GetPhyBand() << " frequency "
224 << apChannel.GetFrequency() << "MHz width " << apChannel.GetWidth()
225 << "MHz");
226 WifiPhy::ChannelTuple chTuple{apChannel.GetNumber(),
227 apChannel.GetWidth(),
228 apChannel.GetPhyBand(),
229 apChannel.GetPrimaryChannelIndex(20)};
230 phy->SetOperatingChannel(chTuple);
231 // actual channel switching may be delayed, thus setup a channel switch timer
233 m_channelSwitchInfo[linkId].timer.Cancel();
234 m_channelSwitchInfo[linkId].timer =
237 this,
238 linkId);
239 m_channelSwitchInfo[linkId].apLinkAddress = bssid;
240 m_channelSwitchInfo[linkId].apMldAddress = mle->get().GetMldMacAddress();
241 }
242
243 // remove the affiliated AP with which we are going to setup a link and move
244 // to the next local linkId
245 apList.erase(apIt);
246 break;
247 }
248 }
249
250 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
251 return info.timer.IsRunning();
252 }))
253 {
254 // we are done
256 }
257}
258
259void
261{
262 NS_LOG_FUNCTION(this << +linkId);
263 if (m_channelSwitchInfo.size() > linkId && m_channelSwitchInfo[linkId].timer.IsRunning())
264 {
265 // we were waiting for this notification
266 m_channelSwitchInfo[linkId].timer.Cancel();
267
268 // the remote station manager has been reset after switching, hence store
269 // information about AP link address and AP MLD address
271 m_channelSwitchInfo[linkId].apLinkAddress,
272 m_channelSwitchInfo[linkId].apMldAddress);
273
274 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
275 return info.timer.IsRunning();
276 }))
277 {
278 // we are done
280 }
281 }
282}
283
284void
286{
287 NS_LOG_FUNCTION(this << +linkId);
288
289 // we give up setting up this link
290 auto& bestAp = *GetSortedList().begin();
291 auto& setupLinks = GetSetupLinks(bestAp);
292 auto it = std::find_if(setupLinks.begin(), setupLinks.end(), [&linkId](auto&& linkIds) {
293 return linkIds.first == linkId;
294 });
295 NS_ASSERT(it != setupLinks.end());
296 setupLinks.erase(it);
297
298 if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) {
299 return info.timer.IsRunning();
300 }))
301 {
302 // we are done
304 }
305}
306
307bool
309{
311}
312
313bool
315{
316 return true;
317}
318
319} // 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:568
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:606
void SendProbeRequest()
Forward a probe request packet to the DCF.
AttributeValue implementation for Time.
Definition: nstime.h:1425
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
Ptr< StaWifiMac > m_mac
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...
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.
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.
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:901
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:949
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:881
bool HasFixedPhyBand() const
Definition: wifi-phy.cc:998
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:869
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:962
void SetMldAddress(const Mac48Address &address, const Mac48Address &mldAddress)
Set the address of the MLD the given station is affiliated with.
Empty class, used as a default parent class for SimpleRefCount.
#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
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1426
#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:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
channel
Definition: third.py:81
phy
Definition: third.py:82
Struct to hold information regarding observed AP through active/passive scanning.
Definition: sta-wifi-mac.h:140
double m_snr
SNR in linear scale.
Definition: sta-wifi-mac.h:143