1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Piotr Gawlowicz
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: Piotr Gawlowicz <gawlowicz.p@gmail.com>
19  *
20  */
21 
22 #include "lte-fr-hard-algorithm.h"
23 #include <ns3/log.h>
24 
25 namespace ns3 {
26 
27 NS_LOG_COMPONENT_DEFINE ("LteFrHardAlgorithm");
28 
29 NS_OBJECT_ENSURE_REGISTERED (LteFrHardAlgorithm);
30 
31 /// FrHardDownlinkDefaultConfiguration structure
32 static const struct FrHardDownlinkDefaultConfiguration
33 {
34   uint8_t m_cellId; ///< cell ID
35   uint8_t m_dlBandwidth; ///< DL bandwidth
36   uint8_t m_dlOffset; ///< DL offset
37   uint8_t m_dlSubBand; ///< DL subband
38 } g_frHardDownlinkDefaultConfiguration[] = {
39   { 1, 15, 0, 4},
40   { 2, 15, 4, 4},
41   { 3, 15, 8, 6},
42   { 1, 25, 0, 8},
43   { 2, 25, 8, 8},
44   { 3, 25, 16, 9},
45   { 1, 50, 0, 16},
46   { 2, 50, 16, 16},
47   { 3, 50, 32, 18},
48   { 1, 75, 0, 24},
49   { 2, 75, 24, 24},
50   { 3, 75, 48, 27},
51   { 1, 100, 0, 32},
52   { 2, 100, 32, 32},
53   { 3, 100, 64, 36}
54 }; ///< the hard downlink default configuration
55 
56 /// FrHardUplinkDefaultConfiguration structure
57 static const struct FrHardUplinkDefaultConfiguration
58 {
59   uint8_t m_cellId; ///< cell ID
60   uint8_t m_ulBandwidth; ///< UL bandwidth
61   uint8_t m_ulOffset; ///< Ul offset
62   uint8_t m_ulSubBand; ///< UL subband
63 } g_frHardUplinkDefaultConfiguration[] = {
64   { 1, 15, 0, 5},
65   { 2, 15, 5, 5},
66   { 3, 15, 10, 5},
67   { 1, 25, 0, 8},
68   { 2, 25, 8, 8},
69   { 3, 25, 16, 9},
70   { 1, 50, 0, 16},
71   { 2, 50, 16, 16},
72   { 3, 50, 32, 18},
73   { 1, 75, 0, 24},
74   { 2, 75, 24, 24},
75   { 3, 75, 48, 27},
76   { 1, 100, 0, 32},
77   { 2, 100, 32, 32},
78   { 3, 100, 64, 36}
79 }; ///< the hard uplink default configuration
80 
81 /** \returns number of downlink configurations */
82 const uint16_t NUM_DOWNLINK_CONFS (sizeof (g_frHardDownlinkDefaultConfiguration) / sizeof (FrHardDownlinkDefaultConfiguration));
83 /** \returns number of uplink configurations */
84 const uint16_t NUM_UPLINK_CONFS (sizeof (g_frHardUplinkDefaultConfiguration) / sizeof (FrHardUplinkDefaultConfiguration));
85 
LteFrHardAlgorithm()86 LteFrHardAlgorithm::LteFrHardAlgorithm ()
87   : m_ffrSapUser (0),
88     m_ffrRrcSapUser (0),
89     m_dlOffset (0),
90     m_dlSubBand (0),
91     m_ulOffset (0),
92     m_ulSubBand (0)
93 {
94   NS_LOG_FUNCTION (this);
95   m_ffrSapProvider = new MemberLteFfrSapProvider<LteFrHardAlgorithm> (this);
96   m_ffrRrcSapProvider = new MemberLteFfrRrcSapProvider<LteFrHardAlgorithm> (this);
97 }
98 
99 
~LteFrHardAlgorithm()100 LteFrHardAlgorithm::~LteFrHardAlgorithm ()
101 {
102   NS_LOG_FUNCTION (this);
103 }
104 
105 
106 void
DoDispose()107 LteFrHardAlgorithm::DoDispose ()
108 {
109   NS_LOG_FUNCTION (this);
110   delete m_ffrSapProvider;
111   delete m_ffrRrcSapProvider;
112 }
113 
114 
115 TypeId
GetTypeId()116 LteFrHardAlgorithm::GetTypeId ()
117 {
118   static TypeId tid = TypeId ("ns3::LteFrHardAlgorithm")
119     .SetParent<LteFfrAlgorithm> ()
120     .SetGroupName("Lte")
121     .AddConstructor<LteFrHardAlgorithm> ()
122     .AddAttribute ("UlSubBandOffset",
123                    "Uplink Offset in number of Resource Block Groups",
124                    UintegerValue (0),
125                    MakeUintegerAccessor (&LteFrHardAlgorithm::m_ulOffset),
126                    MakeUintegerChecker<uint8_t> ())
127     .AddAttribute ("UlSubBandwidth",
128                    "Uplink Transmission SubBandwidth Configuration in number of Resource Block Groups",
129                    UintegerValue (25),
130                    MakeUintegerAccessor (&LteFrHardAlgorithm::m_ulSubBand),
131                    MakeUintegerChecker<uint8_t> ())
132     .AddAttribute ("DlSubBandOffset",
133                    "Downlink Offset in number of Resource Block Groups",
134                    UintegerValue (0),
135                    MakeUintegerAccessor (&LteFrHardAlgorithm::m_dlOffset),
136                    MakeUintegerChecker<uint8_t> ())
137     .AddAttribute ("DlSubBandwidth",
138                    "Downlink Transmission SubBandwidth Configuration in number of Resource Block Groups",
139                    UintegerValue (25),
140                    MakeUintegerAccessor (&LteFrHardAlgorithm::m_dlSubBand),
141                    MakeUintegerChecker<uint8_t> ())
142   ;
143   return tid;
144 }
145 
146 
147 void
SetLteFfrSapUser(LteFfrSapUser * s)148 LteFrHardAlgorithm::SetLteFfrSapUser (LteFfrSapUser* s)
149 {
150   NS_LOG_FUNCTION (this << s);
151   m_ffrSapUser = s;
152 }
153 
154 
155 LteFfrSapProvider*
GetLteFfrSapProvider()156 LteFrHardAlgorithm::GetLteFfrSapProvider ()
157 {
158   NS_LOG_FUNCTION (this);
159   return m_ffrSapProvider;
160 }
161 
162 void
SetLteFfrRrcSapUser(LteFfrRrcSapUser * s)163 LteFrHardAlgorithm::SetLteFfrRrcSapUser (LteFfrRrcSapUser* s)
164 {
165   NS_LOG_FUNCTION (this << s);
166   m_ffrRrcSapUser = s;
167 }
168 
169 
170 LteFfrRrcSapProvider*
GetLteFfrRrcSapProvider()171 LteFrHardAlgorithm::GetLteFfrRrcSapProvider ()
172 {
173   NS_LOG_FUNCTION (this);
174   return m_ffrRrcSapProvider;
175 }
176 
177 
178 void
DoInitialize()179 LteFrHardAlgorithm::DoInitialize ()
180 {
181   NS_LOG_FUNCTION (this);
182   LteFfrAlgorithm::DoInitialize ();
183 
184   NS_ASSERT_MSG (m_dlBandwidth > 14,"DlBandwidth must be at least 15 to use FFR algorithms");
185   NS_ASSERT_MSG (m_ulBandwidth > 14,"UlBandwidth must be at least 15 to use FFR algorithms");
186 
187   if (m_frCellTypeId != 0)
188     {
189       SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
190       SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
191     }
192 
193 }
194 
195 void
Reconfigure()196 LteFrHardAlgorithm::Reconfigure ()
197 {
198   NS_LOG_FUNCTION (this);
199   if (m_frCellTypeId != 0)
200     {
201       SetDownlinkConfiguration (m_frCellTypeId, m_dlBandwidth);
202       SetUplinkConfiguration (m_frCellTypeId, m_ulBandwidth);
203     }
204   InitializeDownlinkRbgMaps ();
205   InitializeUplinkRbgMaps ();
206   m_needReconfiguration = false;
207 }
208 
209 void
SetDownlinkConfiguration(uint16_t cellId,uint8_t bandwidth)210 LteFrHardAlgorithm::SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth)
211 {
212   NS_LOG_FUNCTION (this);
213   for (uint16_t i = 0; i < NUM_DOWNLINK_CONFS; ++i)
214     {
215       if ((g_frHardDownlinkDefaultConfiguration[i].m_cellId == cellId)
216           && g_frHardDownlinkDefaultConfiguration[i].m_dlBandwidth == m_dlBandwidth)
217         {
218           m_dlOffset = g_frHardDownlinkDefaultConfiguration[i].m_dlOffset;
219           m_dlSubBand = g_frHardDownlinkDefaultConfiguration[i].m_dlSubBand;
220         }
221     }
222 }
223 
224 void
SetUplinkConfiguration(uint16_t cellId,uint8_t bandwidth)225 LteFrHardAlgorithm::SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth)
226 {
227   NS_LOG_FUNCTION (this);
228   for (uint16_t i = 0; i < NUM_UPLINK_CONFS; ++i)
229     {
230       if ((g_frHardUplinkDefaultConfiguration[i].m_cellId == cellId)
231           && g_frHardUplinkDefaultConfiguration[i].m_ulBandwidth == m_ulBandwidth)
232         {
233           m_ulOffset = g_frHardUplinkDefaultConfiguration[i].m_ulOffset;
234           m_ulSubBand = g_frHardUplinkDefaultConfiguration[i].m_ulSubBand;
235         }
236     }
237 }
238 
239 void
InitializeDownlinkRbgMaps()240 LteFrHardAlgorithm::InitializeDownlinkRbgMaps ()
241 {
242   m_dlRbgMap.clear ();
243 
244   int rbgSize = GetRbgSize (m_dlBandwidth);
245   m_dlRbgMap.resize (m_dlBandwidth / rbgSize, true);
246 
247   NS_ASSERT_MSG (m_dlOffset <= m_dlBandwidth,"DlOffset higher than DlBandwidth");
248   NS_ASSERT_MSG (m_dlSubBand <= m_dlBandwidth,"DlBandwidth higher than DlBandwidth");
249   NS_ASSERT_MSG ((m_dlOffset + m_dlSubBand) <= m_dlBandwidth,
250                  "(DlOffset+DlSubBand) higher than DlBandwidth");
251 
252   for (uint8_t i = m_dlOffset / rbgSize; i < (m_dlOffset / rbgSize + m_dlSubBand / rbgSize); i++)
253     {
254       m_dlRbgMap[i] = false;
255 
256     }
257 }
258 
259 void
InitializeUplinkRbgMaps()260 LteFrHardAlgorithm::InitializeUplinkRbgMaps ()
261 {
262   m_ulRbgMap.clear ();
263 
264   if (!m_enabledInUplink)
265     {
266       m_ulRbgMap.resize (m_ulBandwidth, false);
267       return;
268     }
269 
270   m_ulRbgMap.resize (m_ulBandwidth, true);
271 
272   NS_ASSERT_MSG (m_ulOffset <= m_ulBandwidth,"UlOffset higher than UlBandwidth");
273   NS_ASSERT_MSG (m_ulSubBand <= m_ulBandwidth,"UlBandwidth higher than UlBandwidth");
274   NS_ASSERT_MSG ((m_ulOffset + m_ulSubBand) <= m_ulBandwidth,
275                  "(UlOffset+UlSubBand) higher than UlBandwidth");
276 
277   for (uint8_t i = m_ulOffset; i < (m_ulOffset + m_ulSubBand); i++)
278     {
279       m_ulRbgMap[i] = false;
280     }
281 }
282 
283 std::vector <bool>
DoGetAvailableDlRbg()284 LteFrHardAlgorithm::DoGetAvailableDlRbg ()
285 {
286   NS_LOG_FUNCTION (this);
287 
288   if (m_needReconfiguration)
289     {
290       Reconfigure ();
291     }
292 
293   if (m_dlRbgMap.empty ())
294     {
295       InitializeDownlinkRbgMaps ();
296     }
297 
298   return m_dlRbgMap;
299 }
300 
301 bool
DoIsDlRbgAvailableForUe(int rbId,uint16_t rnti)302 LteFrHardAlgorithm::DoIsDlRbgAvailableForUe (int rbId, uint16_t rnti)
303 {
304   NS_LOG_FUNCTION (this);
305   return !m_dlRbgMap[rbId];
306 }
307 
308 std::vector <bool>
DoGetAvailableUlRbg()309 LteFrHardAlgorithm::DoGetAvailableUlRbg ()
310 {
311   NS_LOG_FUNCTION (this);
312 
313   if (m_ulRbgMap.empty ())
314     {
315       InitializeUplinkRbgMaps ();
316     }
317 
318   return m_ulRbgMap;
319 }
320 
321 bool
DoIsUlRbgAvailableForUe(int rbId,uint16_t rnti)322 LteFrHardAlgorithm::DoIsUlRbgAvailableForUe (int rbId, uint16_t rnti)
323 {
324   NS_LOG_FUNCTION (this);
325 
326   if (!m_enabledInUplink)
327     {
328       return true;
329     }
330 
331   return !m_ulRbgMap[rbId];
332 }
333 
334 void
DoReportDlCqiInfo(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters & params)335 LteFrHardAlgorithm::DoReportDlCqiInfo (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
336 {
337   NS_LOG_FUNCTION (this);
338   NS_LOG_WARN ("Method should not be called, because it is empty");
339 }
340 
341 void
DoReportUlCqiInfo(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters & params)342 LteFrHardAlgorithm::DoReportUlCqiInfo (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
343 {
344   NS_LOG_FUNCTION (this);
345   NS_LOG_WARN ("Method should not be called, because it is empty");
346 }
347 
348 void
DoReportUlCqiInfo(std::map<uint16_t,std::vector<double>> ulCqiMap)349 LteFrHardAlgorithm::DoReportUlCqiInfo (std::map <uint16_t, std::vector <double> > ulCqiMap)
350 {
351   NS_LOG_FUNCTION (this);
352   NS_LOG_WARN ("Method should not be called, because it is empty");
353 }
354 
355 uint8_t
DoGetTpc(uint16_t rnti)356 LteFrHardAlgorithm::DoGetTpc (uint16_t rnti)
357 {
358   NS_LOG_FUNCTION (this);
359   return 1; // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213 Table 5.1.1.1-2
360 }
361 
362 uint16_t
DoGetMinContinuousUlBandwidth()363 LteFrHardAlgorithm::DoGetMinContinuousUlBandwidth ()
364 {
365   NS_LOG_FUNCTION (this);
366 
367   if (!m_enabledInUplink)
368     {
369       return m_ulBandwidth;
370     }
371 
372   return m_ulSubBand;
373 }
374 
375 void
DoReportUeMeas(uint16_t rnti,LteRrcSap::MeasResults measResults)376 LteFrHardAlgorithm::DoReportUeMeas (uint16_t rnti,
377                                     LteRrcSap::MeasResults measResults)
378 {
379   NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
380   NS_LOG_WARN ("Method should not be called, because it is empty");
381 }
382 
383 void
DoRecvLoadInformation(EpcX2Sap::LoadInformationParams params)384 LteFrHardAlgorithm::DoRecvLoadInformation (EpcX2Sap::LoadInformationParams params)
385 {
386   NS_LOG_FUNCTION (this);
387   NS_LOG_WARN ("Method should not be called, because it is empty");
388 }
389 
390 } // end of namespace ns3
391