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