A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
default-power-save-manager.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
10
11#include "sta-wifi-mac.h"
12#include "wifi-mpdu.h"
13#include "wifi-phy.h"
14
15#include "ns3/log.h"
16#include "ns3/simulator.h"
17
18namespace ns3
19{
20
21NS_LOG_COMPONENT_DEFINE("DefaultPowerSaveManager");
22
24
27{
28 static TypeId tid =
29 TypeId("ns3::DefaultPowerSaveManager")
31 .SetGroupName("Wifi")
32 .AddConstructor<DefaultPowerSaveManager>()
33 .AddAttribute("PsmTimeout",
34 "The length of the extra time during which the PHY is kept in active "
35 "state before being put to sleep state. If channel access is requested "
36 "(to transmit a frame) during such extra time, the PHY is kept in active "
37 "state to attempt to gain channel access and transmit. See the TGax "
38 "Simulation Scenarios document IEEE 802.11-14/0980r16.",
39 TimeValue(Time{0}),
42 .AddAttribute("ListenAdvance",
43 "The amount of time the STA wakes up in advance prior to the Target "
44 "Beacon Transmission Time.",
45 TimeValue(Time{0}),
48 return tid;
49}
50
55
60
61void
63{
64 NS_LOG_FUNCTION(this << linkId);
65
66 if (!GetStaMac()->IsAssociated())
67 {
68 NS_LOG_DEBUG("STA is not associated");
69 return;
70 }
71
72 if (GetStaMac()->GetPmMode(linkId) == WIFI_PM_ACTIVE)
73 {
74 NS_LOG_DEBUG("STA on link " << +linkId << " is in active mode");
75 return;
76 }
77
78 if (GetStaMac()->GetWifiPhy(linkId)->IsStateSleep())
79 {
80 NS_LOG_DEBUG("PHY operating on link " << +linkId << " is already in sleep state");
81 return;
82 }
83
84 auto& staInfo = GetStaInfo(linkId);
85
86 if (staInfo.beaconInterval.IsZero() || staInfo.lastBeaconTimestamp.IsZero())
87 {
88 NS_LOG_DEBUG("No Beacon received yet, cannot put PHY to sleep");
89 return;
90 }
91
92 if (staInfo.pendingUnicast)
93 {
94 NS_LOG_DEBUG("AP has pending unicast frames, do not put PHY to sleep");
95 return;
96 }
97
98 if (staInfo.pendingGroupcast)
99 {
100 NS_LOG_DEBUG("AP has pending groupcast frames, do not put PHY to sleep");
101 return;
102 }
103
104 if (HasRequestedOrGainedChannel(linkId))
105 {
106 NS_LOG_DEBUG("Channel access requested or gained, do not put PHY to sleep");
107 return;
108 }
109
110 if (m_sleepEvents[linkId].IsPending())
111 {
112 NS_LOG_DEBUG("Already scheduled a sleep event, do nothing");
113 return;
114 }
115
116 auto putToSleep = [=, this] {
117 NS_LOG_DEBUG("PHY operating on link " << +linkId << " is put to sleep");
118 GetStaMac()->GetWifiPhy(linkId)->SetSleepMode(true);
119
120 if (auto it = m_wakeUpEvents.find(linkId); it != m_wakeUpEvents.cend())
121 {
122 it->second.Cancel();
123 }
124
125 // schedule wakeup before next Beacon frame in listen interval periods
127
128 auto delay = (Simulator::Now() - staInfo.lastBeaconTimestamp) % staInfo.beaconInterval;
129 delay = staInfo.beaconInterval - delay;
130 delay += (GetListenInterval() - 1) * staInfo.beaconInterval;
131 delay -= m_listenAdvance;
132 delay = Max(delay, Time{0});
133
134 NS_LOG_DEBUG("Scheduling PHY on link " << +linkId << " to wake up in "
135 << delay.As(Time::US));
136 m_wakeUpEvents[linkId] =
137 Simulator::Schedule(delay, &WifiPhy::ResumeFromSleep, GetStaMac()->GetWifiPhy(linkId));
138 };
139
140 NS_LOG_DEBUG("Scheduling sleep state for PHY on link " << +linkId << "at time "
142 m_sleepEvents[linkId] = Simulator::Schedule(m_psmTimeout, putToSleep);
143}
144
145void
147{
148 NS_LOG_FUNCTION(this);
149
150 const auto linkIds = GetStaMac()->GetSetupLinkIds();
151 for (const auto linkId : linkIds)
152 {
153 NS_LOG_DEBUG("PM mode for link " << +linkId << ": " << GetStaMac()->GetPmMode(linkId));
154 if (GetStaMac()->GetPmMode(linkId) == WifiPowerManagementMode::WIFI_PM_POWERSAVE)
155 {
156 GoToSleepIfPossible(linkId);
157 }
158 }
159}
160
161void
163{
164 NS_LOG_FUNCTION(this);
165
166 // base class has resumed PHYs from sleep; here we have to cancel timers
167 for (auto& [linkId, event] : m_wakeUpEvents)
168 {
169 event.Cancel();
170 }
171 for (auto& [linkId, event] : m_sleepEvents)
172 {
173 event.Cancel();
174 }
175}
176
177void
179{
180 NS_LOG_FUNCTION(this << pmMode << linkId);
181
183 {
184 // base class has resumed the PHY from sleep; here we have to cancel the timers
185 if (const auto it = m_wakeUpEvents.find(linkId); it != m_wakeUpEvents.cend())
186 {
187 it->second.Cancel();
188 }
189 if (const auto it = m_sleepEvents.find(linkId); it != m_sleepEvents.cend())
190 {
191 it->second.Cancel();
192 }
193 }
194}
195
196void
198{
199 NS_LOG_FUNCTION(this << beacon << linkId);
200
201 if (GetStaMac()->GetPmMode(linkId) != WIFI_PM_POWERSAVE)
202 {
203 return;
204 }
205
206 if (GetStaInfo(linkId).pendingUnicast)
207 {
208 GetStaMac()->EnqueuePsPoll(linkId);
209 }
210 else
211 {
212 GoToSleepIfPossible(linkId);
213 }
214}
215
216void
218{
219 NS_LOG_FUNCTION(this << mpdu << linkId);
220
221 if (GetStaInfo(linkId).pendingUnicast)
222 {
223 NS_LOG_LOGIC("Waiting for more unicast frames; enqueue a PS-Poll frame");
224 GetStaMac()->EnqueuePsPoll(linkId);
225 }
226 else
227 {
228 GoToSleepIfPossible(linkId);
229 }
230}
231
232void
239
240void
242{
243 NS_LOG_FUNCTION(this << txop << linkId);
244
245 m_sleepEvents[linkId].Cancel();
246
247 // if channel access is being requested, it means that the MAC has frames to transmit on the
248 // given link, hence wake up the PHY if it is in sleep state
249 if (auto phy = GetStaMac()->GetWifiPhy(linkId); phy->IsStateSleep())
250 {
251 NS_LOG_DEBUG("Resume from sleep STA operating on link " << +linkId);
252 phy->ResumeFromSleep();
253 if (auto it = m_wakeUpEvents.find(linkId); it != m_wakeUpEvents.cend())
254 {
255 it->second.Cancel();
256 }
257 }
258}
259
260void
262{
263 NS_LOG_FUNCTION(this << txop << linkId);
264
265 GoToSleepIfPossible(linkId);
266}
267
268void
270{
271 NS_LOG_FUNCTION(this << reason << *mpdu);
272
273 if (mpdu->GetHeader().IsPsPoll())
274 {
275 auto addr2 = mpdu->GetHeader().GetAddr2();
276 const auto linkId = GetStaMac()->GetLinkIdByAddress(addr2);
277 NS_ASSERT_MSG(linkId.has_value(), addr2 << " is not a link address");
278
279 NS_LOG_DEBUG("PS-Poll dropped. Give up polling the AP on link " << +linkId.value());
280
281 if (auto& staInfo = GetStaInfo(*linkId); staInfo.pendingUnicast)
282 {
283 staInfo.pendingUnicast = false;
284 }
285 }
286
287 for (const auto& id : GetStaMac()->GetLinkIds())
288 {
290 }
291}
292
293} // namespace ns3
#define Max(a, b)
DefaultPowerSaveManager is the default power save manager.
void DoNotifyReceivedFrameAfterPsPoll(Ptr< const WifiMpdu > mpdu, linkId_t linkId) override
Notify subclasses of the reception of a frame in response to a PS-Poll frame on the given link.
void DoNotifyRequestAccess(Ptr< Txop > txop, linkId_t linkId) override
Notify subclasses that the given TXOP is requesting channel access on the given link.
std::map< linkId_t, EventId > m_sleepEvents
events scheduled to set PHYs to sleep
std::map< linkId_t, EventId > m_wakeUpEvents
events scheduled to wake up PHYs
Time m_listenAdvance
the amount of time the STA wakes up in advance prior to the TBTT
void DoNotifyDisassociation() override
Notify subclasses that the non-AP STA/MLD has disassociated.
void DoNotifyReceivedGroupcast(Ptr< const WifiMpdu > mpdu, linkId_t linkId) override
Notify subclasses of the reception of a groupcast frame (possibly after a DTIM) on the given link.
void DoNotifyPmModeChanged(WifiPowerManagementMode pmMode, linkId_t linkId) override
Notify subclasses that the Power Management mode of the non-AP STA operating on the given link has ch...
void DoNotifyAssocCompleted() override
Notify subclasses that the non-AP STA/MLD has completed association with an AP.
void DoNotifyReceivedBeacon(const MgtBeaconHeader &beacon, linkId_t linkId) override
Notify subclasses that a Beacon frame has been received from the associated AP on the given link.
void GoToSleepIfPossible(linkId_t linkId)
Put the PHY operating on the given link to sleep, if no reason to stay awake.
void DoTxDropped(WifiMacDropReason reason, Ptr< const WifiMpdu > mpdu) override
Notify subclasses that the given MPDU has been discarded for the given reason.
static TypeId GetTypeId()
Get the type ID.
void DoNotifyChannelReleased(Ptr< Txop > txop, linkId_t linkId) override
Notify subclasses that the given TXOP is releasing the channel on the given link.
Time m_psmTimeout
the extra time during which the PHY is kept in active state before being put to sleep state
Implement the header for management frames of type beacon.
PowerSaveManager is an abstract base class.
Ptr< StaWifiMac > GetStaMac() const
uint32_t GetListenInterval() const
StaInfo & GetStaInfo(linkId_t linkId)
Get the information about the STA operating on the given link.
bool HasRequestedOrGainedChannel(linkId_t linkId) const
Get whether any Access Category has requested (or gained) the channel on the given link.
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
@ US
microsecond
Definition nstime.h:108
AttributeValue implementation for Time.
Definition nstime.h:1375
a unique identifier for an interface.
Definition type-id.h:50
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
void ResumeFromSleep()
Resume from sleep mode.
Definition wifi-phy.cc:1460
#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
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
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:1376
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1396
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:274
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#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
WifiMacDropReason
The reason why an MPDU was dropped.
Definition wifi-mac.h:71
WifiPowerManagementMode
Enumeration for power management modes.
@ WIFI_PM_POWERSAVE
@ WIFI_PM_ACTIVE
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint8_t linkId_t
IEEE 802.11be D7.0 Figure 9-207e—Link ID Info field format.
Definition wifi-utils.h:74
bool pendingUnicast
AP has buffered unicast frame(s) (set from last TIM and updated as frames are received from the AP).