1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
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
21 #include "ns3/log.h"
22 #include "ns3/abort.h"
23 #include "multi-user-scheduler.h"
24 #include "ns3/qos-txop.h"
25 #include "he-configuration.h"
26 #include "he-frame-exchange-manager.h"
27 #include "ns3/wifi-protection.h"
28 #include "ns3/wifi-acknowledgment.h"
29 #include "ns3/wifi-mac-trailer.h"
30
31 namespace ns3 {
32
33 NS_LOG_COMPONENT_DEFINE ("MultiUserScheduler");
34
35 NS_OBJECT_ENSURE_REGISTERED (MultiUserScheduler);
36
37 TypeId
GetTypeId(void)38 MultiUserScheduler::GetTypeId (void)
39 {
40 static TypeId tid = TypeId ("ns3::MultiUserScheduler")
41 .SetParent<Object> ()
42 .SetGroupName ("Wifi")
43 ;
44 return tid;
45 }
46
MultiUserScheduler()47 MultiUserScheduler::MultiUserScheduler ()
48 {
49 }
50
~MultiUserScheduler()51 MultiUserScheduler::~MultiUserScheduler ()
52 {
53 NS_LOG_FUNCTION_NOARGS ();
54 }
55
56 void
DoDispose(void)57 MultiUserScheduler::DoDispose (void)
58 {
59 NS_LOG_FUNCTION (this);
60 m_apMac = 0;
61 m_heFem = 0;
62 m_edca = 0;
63 m_dlInfo.psduMap.clear ();
64 m_dlInfo.txParams.Clear ();
65 m_ulInfo.txParams.Clear ();
66 m_ulInfo.trigger = 0;
67 Object::DoDispose ();
68 }
69
70 void
NotifyNewAggregate()71 MultiUserScheduler::NotifyNewAggregate ()
72 {
73 NS_LOG_FUNCTION (this);
74 if (m_apMac == 0)
75 {
76 Ptr<ApWifiMac> apMac = this->GetObject<ApWifiMac> ();
77 //verify that it's a valid AP mac and that
78 //the AP mac was not set before
79 if (apMac != 0)
80 {
81 this->SetWifiMac (apMac);
82 }
83 }
84 Object::NotifyNewAggregate ();
85 }
86
87 void
DoInitialize(void)88 MultiUserScheduler::DoInitialize (void)
89 {
90 // compute the size in bytes of 8 QoS Null frames. It can be used by subclasses
91 // when responding to a BSRP Trigger Frame
92 WifiMacHeader header;
93 header.SetType (WIFI_MAC_QOSDATA_NULL);
94 header.SetDsTo ();
95 header.SetDsNotFrom ();
96 uint32_t headerSize = header.GetSerializedSize ();
97
98 m_sizeOf8QosNull = 0;
99 for (uint8_t i = 0; i < 8; i++)
100 {
101 m_sizeOf8QosNull = MpduAggregator::GetSizeIfAggregated (headerSize + WIFI_MAC_FCS_LENGTH, m_sizeOf8QosNull);
102 }
103 }
104
105 void
SetWifiMac(Ptr<ApWifiMac> mac)106 MultiUserScheduler::SetWifiMac (Ptr<ApWifiMac> mac)
107 {
108 NS_LOG_FUNCTION (this << mac);
109 m_apMac = mac;
110
111 // When VHT DL MU-MIMO will be supported, we will have to lower this requirement
112 // and allow a Multi-user scheduler to be installed on a VHT AP.
113 NS_ABORT_MSG_IF (m_apMac == 0 || m_apMac->GetHeConfiguration () == 0,
114 "MultiUserScheduler can only be installed on HE APs");
115
116 m_heFem = DynamicCast<HeFrameExchangeManager> (m_apMac->GetFrameExchangeManager ());
117 m_heFem->SetMultiUserScheduler (this);
118 }
119
120 Ptr<WifiRemoteStationManager>
GetWifiRemoteStationManager(void) const121 MultiUserScheduler::GetWifiRemoteStationManager (void) const
122 {
123 return m_apMac->GetWifiRemoteStationManager ();
124 }
125
126 MultiUserScheduler::TxFormat
NotifyAccessGranted(Ptr<QosTxop> edca,Time availableTime,bool initialFrame)127 MultiUserScheduler::NotifyAccessGranted (Ptr<QosTxop> edca, Time availableTime, bool initialFrame)
128 {
129 NS_LOG_FUNCTION (this << edca << availableTime << initialFrame);
130
131 m_edca = edca;
132 m_availableTime = availableTime;
133 m_initialFrame = initialFrame;
134
135 TxFormat txFormat = SelectTxFormat ();
136
137 if (txFormat == DL_MU_TX)
138 {
139 m_dlInfo = ComputeDlMuInfo ();
140 }
141 else if (txFormat == UL_MU_TX)
142 {
143 NS_ABORT_MSG_IF (m_heFem == 0, "UL MU PPDUs are only supported by HE APs");
144 m_ulInfo = ComputeUlMuInfo ();
145 }
146
147 if (txFormat != NO_TX)
148 {
149 m_lastTxFormat = txFormat;
150 }
151 return txFormat;
152 }
153
154 MultiUserScheduler::TxFormat
GetLastTxFormat(void) const155 MultiUserScheduler::GetLastTxFormat (void) const
156 {
157 return m_lastTxFormat;
158 }
159
160 MultiUserScheduler::DlMuInfo&
GetDlMuInfo(void)161 MultiUserScheduler::GetDlMuInfo (void)
162 {
163 NS_ABORT_MSG_IF (m_lastTxFormat != DL_MU_TX, "Next transmission is not DL MU");
164
165 #ifdef NS3_BUILD_PROFILE_DEBUG
166 // check that all the addressed stations support HE
167 for (auto& psdu : m_dlInfo.psduMap)
168 {
169 NS_ABORT_MSG_IF (!GetWifiRemoteStationManager ()->GetHeSupported (psdu.second->GetAddr1 ()),
170 "Station " << psdu.second->GetAddr1 () << " does not support HE");
171 }
172 #endif
173
174 return m_dlInfo;
175 }
176
177 MultiUserScheduler::UlMuInfo&
GetUlMuInfo(void)178 MultiUserScheduler::GetUlMuInfo (void)
179 {
180 NS_ABORT_MSG_IF (m_lastTxFormat != UL_MU_TX, "Next transmission is not UL MU");
181
182 return m_ulInfo;
183 }
184
185 } //namespace ns3
186