OLD | NEW |
(Empty) | |
| 1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| 2 /* |
| 3 * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) |
| 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: Marco Miozzo <marco.miozzo@cttc.es> // original version |
| 19 * Modification: Dizhi Zhou <dizhi.zhou@gmail.com> // modify codes related to
downlink scheduler |
| 20 * |
| 21 */ |
| 22 |
| 23 #ifdef __FreeBSD__ |
| 24 #define log2(x) (log(x) / M_LN2) |
| 25 #endif /* __FreeBSD__ */ |
| 26 |
| 27 #include <ns3/log.h> |
| 28 #include <ns3/pointer.h> |
| 29 #include <ns3/integer.h> |
| 30 |
| 31 #include <ns3/simulator.h> |
| 32 #include <ns3/lte-amc.h> |
| 33 #include <ns3/tdtbfq-ff-mac-scheduler.h> |
| 34 |
| 35 NS_LOG_COMPONENT_DEFINE ("TdTbfqFfMacScheduler"); |
| 36 |
| 37 // value for SINR outside the range defined by LTE, used to indicate that there |
| 38 // is no CQI for this element |
| 39 #define NO_SINR -5000 |
| 40 |
| 41 namespace ns3 { |
| 42 |
| 43 int TdTbfqType0AllocationRbg[4] = { |
| 44 10, // RGB size 1 |
| 45 26, // RGB size 2 |
| 46 63, // RGB size 3 |
| 47 110 // RGB size 4 |
| 48 }; // see table 7.1.6.1-1 of 36.213 |
| 49 |
| 50 |
| 51 NS_OBJECT_ENSURE_REGISTERED (TdTbfqFfMacScheduler); |
| 52 |
| 53 |
| 54 |
| 55 class TdTbfqSchedulerMemberCschedSapProvider : public FfMacCschedSapProvider |
| 56 { |
| 57 public: |
| 58 TdTbfqSchedulerMemberCschedSapProvider (TdTbfqFfMacScheduler* scheduler); |
| 59 |
| 60 // inherited from FfMacCschedSapProvider |
| 61 virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters&
params); |
| 62 virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& para
ms); |
| 63 virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& para
ms); |
| 64 virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& pa
rams); |
| 65 virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& pa
rams); |
| 66 |
| 67 private: |
| 68 TdTbfqSchedulerMemberCschedSapProvider (); |
| 69 TdTbfqFfMacScheduler* m_scheduler; |
| 70 }; |
| 71 |
| 72 TdTbfqSchedulerMemberCschedSapProvider::TdTbfqSchedulerMemberCschedSapProvider (
) |
| 73 { |
| 74 } |
| 75 |
| 76 TdTbfqSchedulerMemberCschedSapProvider::TdTbfqSchedulerMemberCschedSapProvider (
TdTbfqFfMacScheduler* scheduler) : m_scheduler (scheduler) |
| 77 { |
| 78 } |
| 79 |
| 80 |
| 81 void |
| 82 TdTbfqSchedulerMemberCschedSapProvider::CschedCellConfigReq (const struct Csched
CellConfigReqParameters& params) |
| 83 { |
| 84 m_scheduler->DoCschedCellConfigReq (params); |
| 85 } |
| 86 |
| 87 void |
| 88 TdTbfqSchedulerMemberCschedSapProvider::CschedUeConfigReq (const struct CschedUe
ConfigReqParameters& params) |
| 89 { |
| 90 m_scheduler->DoCschedUeConfigReq (params); |
| 91 } |
| 92 |
| 93 |
| 94 void |
| 95 TdTbfqSchedulerMemberCschedSapProvider::CschedLcConfigReq (const struct CschedLc
ConfigReqParameters& params) |
| 96 { |
| 97 m_scheduler->DoCschedLcConfigReq (params); |
| 98 } |
| 99 |
| 100 void |
| 101 TdTbfqSchedulerMemberCschedSapProvider::CschedLcReleaseReq (const struct CschedL
cReleaseReqParameters& params) |
| 102 { |
| 103 m_scheduler->DoCschedLcReleaseReq (params); |
| 104 } |
| 105 |
| 106 void |
| 107 TdTbfqSchedulerMemberCschedSapProvider::CschedUeReleaseReq (const struct CschedU
eReleaseReqParameters& params) |
| 108 { |
| 109 m_scheduler->DoCschedUeReleaseReq (params); |
| 110 } |
| 111 |
| 112 |
| 113 |
| 114 |
| 115 class TdTbfqSchedulerMemberSchedSapProvider : public FfMacSchedSapProvider |
| 116 { |
| 117 public: |
| 118 TdTbfqSchedulerMemberSchedSapProvider (TdTbfqFfMacScheduler* scheduler); |
| 119 |
| 120 // inherited from FfMacSchedSapProvider |
| 121 virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters&
params); |
| 122 virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParame
ters& params); |
| 123 virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters&
params); |
| 124 virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& para
ms); |
| 125 virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& pa
rams); |
| 126 virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& para
ms); |
| 127 virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& para
ms); |
| 128 virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenc
eReqParameters& params); |
| 129 virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params
); |
| 130 virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParamete
rs& params); |
| 131 virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& para
ms); |
| 132 |
| 133 |
| 134 private: |
| 135 TdTbfqSchedulerMemberSchedSapProvider (); |
| 136 TdTbfqFfMacScheduler* m_scheduler; |
| 137 }; |
| 138 |
| 139 |
| 140 |
| 141 TdTbfqSchedulerMemberSchedSapProvider::TdTbfqSchedulerMemberSchedSapProvider () |
| 142 { |
| 143 } |
| 144 |
| 145 |
| 146 TdTbfqSchedulerMemberSchedSapProvider::TdTbfqSchedulerMemberSchedSapProvider (Td
TbfqFfMacScheduler* scheduler) |
| 147 : m_scheduler (scheduler) |
| 148 { |
| 149 } |
| 150 |
| 151 void |
| 152 TdTbfqSchedulerMemberSchedSapProvider::SchedDlRlcBufferReq (const struct SchedDl
RlcBufferReqParameters& params) |
| 153 { |
| 154 m_scheduler->DoSchedDlRlcBufferReq (params); |
| 155 } |
| 156 |
| 157 void |
| 158 TdTbfqSchedulerMemberSchedSapProvider::SchedDlPagingBufferReq (const struct Sche
dDlPagingBufferReqParameters& params) |
| 159 { |
| 160 m_scheduler->DoSchedDlPagingBufferReq (params); |
| 161 } |
| 162 |
| 163 void |
| 164 TdTbfqSchedulerMemberSchedSapProvider::SchedDlMacBufferReq (const struct SchedDl
MacBufferReqParameters& params) |
| 165 { |
| 166 m_scheduler->DoSchedDlMacBufferReq (params); |
| 167 } |
| 168 |
| 169 void |
| 170 TdTbfqSchedulerMemberSchedSapProvider::SchedDlTriggerReq (const struct SchedDlTr
iggerReqParameters& params) |
| 171 { |
| 172 m_scheduler->DoSchedDlTriggerReq (params); |
| 173 } |
| 174 |
| 175 void |
| 176 TdTbfqSchedulerMemberSchedSapProvider::SchedDlRachInfoReq (const struct SchedDlR
achInfoReqParameters& params) |
| 177 { |
| 178 m_scheduler->DoSchedDlRachInfoReq (params); |
| 179 } |
| 180 |
| 181 void |
| 182 TdTbfqSchedulerMemberSchedSapProvider::SchedDlCqiInfoReq (const struct SchedDlCq
iInfoReqParameters& params) |
| 183 { |
| 184 m_scheduler->DoSchedDlCqiInfoReq (params); |
| 185 } |
| 186 |
| 187 void |
| 188 TdTbfqSchedulerMemberSchedSapProvider::SchedUlTriggerReq (const struct SchedUlTr
iggerReqParameters& params) |
| 189 { |
| 190 m_scheduler->DoSchedUlTriggerReq (params); |
| 191 } |
| 192 |
| 193 void |
| 194 TdTbfqSchedulerMemberSchedSapProvider::SchedUlNoiseInterferenceReq (const struct
SchedUlNoiseInterferenceReqParameters& params) |
| 195 { |
| 196 m_scheduler->DoSchedUlNoiseInterferenceReq (params); |
| 197 } |
| 198 |
| 199 void |
| 200 TdTbfqSchedulerMemberSchedSapProvider::SchedUlSrInfoReq (const struct SchedUlSrI
nfoReqParameters& params) |
| 201 { |
| 202 m_scheduler->DoSchedUlSrInfoReq (params); |
| 203 } |
| 204 |
| 205 void |
| 206 TdTbfqSchedulerMemberSchedSapProvider::SchedUlMacCtrlInfoReq (const struct Sched
UlMacCtrlInfoReqParameters& params) |
| 207 { |
| 208 m_scheduler->DoSchedUlMacCtrlInfoReq (params); |
| 209 } |
| 210 |
| 211 void |
| 212 TdTbfqSchedulerMemberSchedSapProvider::SchedUlCqiInfoReq (const struct SchedUlCq
iInfoReqParameters& params) |
| 213 { |
| 214 m_scheduler->DoSchedUlCqiInfoReq (params); |
| 215 } |
| 216 |
| 217 |
| 218 |
| 219 |
| 220 |
| 221 TdTbfqFfMacScheduler::TdTbfqFfMacScheduler () |
| 222 : m_cschedSapUser (0), |
| 223 m_schedSapUser (0), |
| 224 m_nextRntiUl (0), |
| 225 bankSize(0) |
| 226 { |
| 227 m_amc = CreateObject <LteAmc> (); |
| 228 m_cschedSapProvider = new TdTbfqSchedulerMemberCschedSapProvider (this); |
| 229 m_schedSapProvider = new TdTbfqSchedulerMemberSchedSapProvider (this); |
| 230 } |
| 231 |
| 232 TdTbfqFfMacScheduler::~TdTbfqFfMacScheduler () |
| 233 { |
| 234 NS_LOG_FUNCTION (this); |
| 235 } |
| 236 |
| 237 void |
| 238 TdTbfqFfMacScheduler::DoDispose () |
| 239 { |
| 240 NS_LOG_FUNCTION (this); |
| 241 delete m_cschedSapProvider; |
| 242 delete m_schedSapProvider; |
| 243 } |
| 244 |
| 245 TypeId |
| 246 TdTbfqFfMacScheduler::GetTypeId (void) |
| 247 { |
| 248 static TypeId tid = TypeId ("ns3::TdTbfqFfMacScheduler") |
| 249 .SetParent<FfMacScheduler> () |
| 250 .AddConstructor<TdTbfqFfMacScheduler> () |
| 251 .AddAttribute ("CqiTimerThreshold", |
| 252 "The number of TTIs a CQI is valid (default 1000 - 1 sec.)", |
| 253 UintegerValue (1000), |
| 254 MakeUintegerAccessor (&TdTbfqFfMacScheduler::m_cqiTimersThres
hold), |
| 255 MakeUintegerChecker<uint32_t> ()) |
| 256 .AddAttribute ("DebtLimit", |
| 257 "Flow debt limit (default -625000 bytes)", |
| 258 IntegerValue (-625000), |
| 259 MakeIntegerAccessor (&TdTbfqFfMacScheduler::m_debtLimit), |
| 260 MakeIntegerChecker<int> ()) |
| 261 .AddAttribute ("CreditLimit", |
| 262 "Flow credit limit (default 625000 bytes)", |
| 263 UintegerValue (625000), |
| 264 MakeUintegerAccessor (&TdTbfqFfMacScheduler::m_creditLimit), |
| 265 MakeUintegerChecker<uint32_t> ()) |
| 266 .AddAttribute ("TokenPoolSize", |
| 267 "The maximum value of flow token pool (default 1 bytes)", |
| 268 UintegerValue (1), |
| 269 MakeUintegerAccessor (&TdTbfqFfMacScheduler::m_tokenPoolSize)
, |
| 270 MakeUintegerChecker<uint32_t> ()) |
| 271 .AddAttribute ("Creditable Threshold", |
| 272 "Threshold of flow credit (default 0 bytes)", |
| 273 UintegerValue (0), |
| 274 MakeUintegerAccessor (&TdTbfqFfMacScheduler::m_creditableThre
shold), |
| 275 MakeUintegerChecker<uint32_t> ()) |
| 276 ; |
| 277 return tid; |
| 278 } |
| 279 |
| 280 |
| 281 |
| 282 void |
| 283 TdTbfqFfMacScheduler::SetFfMacCschedSapUser (FfMacCschedSapUser* s) |
| 284 { |
| 285 m_cschedSapUser = s; |
| 286 } |
| 287 |
| 288 void |
| 289 TdTbfqFfMacScheduler::SetFfMacSchedSapUser (FfMacSchedSapUser* s) |
| 290 { |
| 291 m_schedSapUser = s; |
| 292 } |
| 293 |
| 294 FfMacCschedSapProvider* |
| 295 TdTbfqFfMacScheduler::GetFfMacCschedSapProvider () |
| 296 { |
| 297 return m_cschedSapProvider; |
| 298 } |
| 299 |
| 300 FfMacSchedSapProvider* |
| 301 TdTbfqFfMacScheduler::GetFfMacSchedSapProvider () |
| 302 { |
| 303 return m_schedSapProvider; |
| 304 } |
| 305 |
| 306 void |
| 307 TdTbfqFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider
::CschedCellConfigReqParameters& params) |
| 308 { |
| 309 NS_LOG_FUNCTION (this); |
| 310 // Read the subset of parameters used |
| 311 m_cschedCellConfig = params; |
| 312 FfMacCschedSapUser::CschedUeConfigCnfParameters cnf; |
| 313 cnf.m_result = SUCCESS; |
| 314 m_cschedSapUser->CschedUeConfigCnf (cnf); |
| 315 return; |
| 316 } |
| 317 |
| 318 void |
| 319 TdTbfqFfMacScheduler::DoCschedUeConfigReq (const struct FfMacCschedSapProvider::
CschedUeConfigReqParameters& params) |
| 320 { |
| 321 NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)
params.m_transmissionMode); |
| 322 std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti); |
| 323 if (it==m_uesTxMode.end ()) |
| 324 { |
| 325 m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_tr
ansmissionMode)); |
| 326 } |
| 327 else |
| 328 { |
| 329 (*it).second = params.m_transmissionMode; |
| 330 } |
| 331 return; |
| 332 } |
| 333 |
| 334 void |
| 335 TdTbfqFfMacScheduler::DoCschedLcConfigReq (const struct FfMacCschedSapProvider::
CschedLcConfigReqParameters& params) |
| 336 { |
| 337 NS_LOG_FUNCTION (this << " New LC, rnti: " << params.m_rnti); |
| 338 |
| 339 std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator it; |
| 340 for (uint16_t i = 0; i < params.m_logicalChannelConfigList.size (); i++) |
| 341 { |
| 342 it = m_flowStatsDl.find (params.m_rnti); |
| 343 |
| 344 if (it == m_flowStatsDl.end ()) |
| 345 { |
| 346 // add rlc and pdcp header size in MBR |
| 347 uint64_t mbrDlInBytes = params.m_logicalChannelConfigList.at(i).m_eRab
MaximulBitrateDl / 8; // byte/s |
| 348 uint64_t mbrUlInBytes = params.m_logicalChannelConfigList.at(i).m_eRab
MaximulBitrateUl / 8; // byte/s |
| 349 |
| 350 tdtbfqsFlowPerf_t flowStatsDl; |
| 351 flowStatsDl.flowStart = Simulator::Now (); |
| 352 flowStatsDl.packetArrivalRate = 0; |
| 353 flowStatsDl.tokenGenerationRate = mbrDlInBytes; |
| 354 flowStatsDl.tokenPoolSize = 0; |
| 355 flowStatsDl.maxTokenPoolSize = m_tokenPoolSize; |
| 356 flowStatsDl.counter = 0; |
| 357 flowStatsDl.burstCredit = m_creditLimit; // bytes |
| 358 flowStatsDl.debtLimit = m_debtLimit; // bytes |
| 359 flowStatsDl.creditableThreshold = m_creditableThreshold; |
| 360 m_flowStatsDl.insert (std::pair<uint16_t, tdtbfqsFlowPerf_t> (params.m
_rnti, flowStatsDl)); |
| 361 tdtbfqsFlowPerf_t flowStatsUl; |
| 362 flowStatsUl.flowStart = Simulator::Now (); |
| 363 flowStatsUl.packetArrivalRate = 0; |
| 364 flowStatsUl.tokenGenerationRate = mbrUlInBytes; |
| 365 flowStatsUl.tokenPoolSize = 0; |
| 366 flowStatsUl.maxTokenPoolSize = m_tokenPoolSize; |
| 367 flowStatsUl.counter = 0; |
| 368 flowStatsUl.burstCredit = m_creditLimit; // bytes |
| 369 flowStatsUl.debtLimit = m_debtLimit; // bytes |
| 370 flowStatsUl.creditableThreshold = m_creditableThreshold; |
| 371 m_flowStatsUl.insert (std::pair<uint16_t, tdtbfqsFlowPerf_t> (params.m
_rnti, flowStatsUl)); |
| 372 |
| 373 } |
| 374 else |
| 375 { |
| 376 NS_LOG_ERROR ("RNTI already exists"); |
| 377 } |
| 378 } |
| 379 |
| 380 return; |
| 381 } |
| 382 |
| 383 void |
| 384 TdTbfqFfMacScheduler::DoCschedLcReleaseReq (const struct FfMacCschedSapProvider:
:CschedLcReleaseReqParameters& params) |
| 385 { |
| 386 NS_LOG_FUNCTION (this); |
| 387 // TODO: Implementation of the API |
| 388 return; |
| 389 } |
| 390 |
| 391 void |
| 392 TdTbfqFfMacScheduler::DoCschedUeReleaseReq (const struct FfMacCschedSapProvider:
:CschedUeReleaseReqParameters& params) |
| 393 { |
| 394 NS_LOG_FUNCTION (this); |
| 395 // TODO: Implementation of the API |
| 396 return; |
| 397 } |
| 398 |
| 399 |
| 400 void |
| 401 TdTbfqFfMacScheduler::DoSchedDlRlcBufferReq (const struct FfMacSchedSapProvider:
:SchedDlRlcBufferReqParameters& params) |
| 402 { |
| 403 NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelId
entity); |
| 404 // API generated by RLC for updating RLC parameters on a LC (tx and retx queue
s) |
| 405 |
| 406 std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::
iterator it; |
| 407 |
| 408 LteFlowId_t flow (params.m_rnti, params.m_logicalChannelIdentity); |
| 409 |
| 410 it = m_rlcBufferReq.find (flow); |
| 411 |
| 412 if (it == m_rlcBufferReq.end ()) |
| 413 { |
| 414 m_rlcBufferReq.insert (std::pair <LteFlowId_t, FfMacSchedSapProvider::Sche
dDlRlcBufferReqParameters> (flow, params)); |
| 415 } |
| 416 else |
| 417 { |
| 418 (*it).second = params; |
| 419 } |
| 420 |
| 421 return; |
| 422 } |
| 423 |
| 424 void |
| 425 TdTbfqFfMacScheduler::DoSchedDlPagingBufferReq (const struct FfMacSchedSapProvid
er::SchedDlPagingBufferReqParameters& params) |
| 426 { |
| 427 NS_LOG_FUNCTION (this); |
| 428 // TODO: Implementation of the API |
| 429 return; |
| 430 } |
| 431 |
| 432 void |
| 433 TdTbfqFfMacScheduler::DoSchedDlMacBufferReq (const struct FfMacSchedSapProvider:
:SchedDlMacBufferReqParameters& params) |
| 434 { |
| 435 NS_LOG_FUNCTION (this); |
| 436 // TODO: Implementation of the API |
| 437 return; |
| 438 } |
| 439 |
| 440 int |
| 441 TdTbfqFfMacScheduler::GetRbgSize (int dlbandwidth) |
| 442 { |
| 443 for (int i = 0; i < 4; i++) |
| 444 { |
| 445 if (dlbandwidth < TdTbfqType0AllocationRbg[i]) |
| 446 { |
| 447 return (i + 1); |
| 448 } |
| 449 } |
| 450 |
| 451 return (-1); |
| 452 } |
| 453 |
| 454 |
| 455 int· |
| 456 TdTbfqFfMacScheduler::LcActivePerFlow (uint16_t rnti) |
| 457 { |
| 458 std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::
iterator it; |
| 459 int lcActive = 0; |
| 460 for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++) |
| 461 { |
| 462 if (((*it).first.m_rnti == rnti) && (((*it).second.m_rlcTransmissionQueueS
ize > 0) |
| 463 || ((*it).second.m_rlcRetransmissionQ
ueueSize > 0) |
| 464 || ((*it).second.m_rlcStatusPduSize >
0) )) |
| 465 { |
| 466 lcActive++; |
| 467 } |
| 468 if ((*it).first.m_rnti > rnti) |
| 469 { |
| 470 break; |
| 471 } |
| 472 } |
| 473 return (lcActive); |
| 474 |
| 475 } |
| 476 |
| 477 |
| 478 void |
| 479 TdTbfqFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::S
chedDlTriggerReqParameters& params) |
| 480 { |
| 481 NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe
no. " << (0xF & params.m_sfnSf)); |
| 482 // API generated by RLC for triggering the scheduling of a DL subframe |
| 483 |
| 484 |
| 485 // evaluate the relative channel quality indicator for each UE per each RBG· |
| 486 // (since we are using allocation type 0 the small unit of allocation is RBG) |
| 487 // Resource allocation type 0 (see sec 7.1.6.1 of 36.213) |
| 488 RefreshDlCqiMaps (); |
| 489 |
| 490 // update token pool, counter and bank size |
| 491 std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itStats; |
| 492 for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStat
s++) |
| 493 { |
| 494 if ( (*itStats).second.tokenGenerationRate/1000 + (*itStats).second.token
PoolSize > (*itStats).second.maxTokenPoolSize )····· |
| 495 { |
| 496 (*itStats).second.counter += (*itStats).second.tokenGenerationRate/10
00 - ( (*itStats).second.maxTokenPoolSize - (*itStats).second.tokenPoolSize ); |
| 497 (*itStats).second.tokenPoolSize = (*itStats).second.maxTokenPoolSize; |
| 498 bankSize += (*itStats).second.tokenGenerationRate/1000 - ( (*itStats).
second.maxTokenPoolSize - (*itStats).second.tokenPoolSize );·· |
| 499 } |
| 500 else |
| 501 { |
| 502 (*itStats).second.tokenPoolSize += (*itStats).second.tokenGenerationRa
te/1000; |
| 503 } |
| 504 } |
| 505 |
| 506 int rbgSize = GetRbgSize (m_cschedCellConfig.m_dlBandwidth); |
| 507 int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize; |
| 508 std::map <uint16_t, std::vector <uint16_t> > allocationMap; |
| 509 |
| 510 // select UE with largest metric |
| 511 std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator it; |
| 512 std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itMax = m_flowStatsDl.end (); |
| 513 double metricMax; |
| 514 bool firstRnti = true; |
| 515 for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++) |
| 516 { |
| 517 if (LcActivePerFlow ((*it).first) == 0) |
| 518 { |
| 519 continue; |
| 520 } |
| 521 |
| 522 double metric = ( ( (double)(*it).second.counter ) / ( (double)(*it).secon
d.tokenGenerationRate ) );·· |
| 523 |
| 524 if (firstRnti == true) |
| 525 { |
| 526 metricMax = metric; |
| 527 itMax = it; |
| 528 firstRnti = false; |
| 529 continue; |
| 530 } |
| 531 if (metric > metricMax) |
| 532 { |
| 533 metricMax = metric; |
| 534 itMax = it; |
| 535 } |
| 536 } // end for m_flowStatsDl |
| 537 |
| 538 if (itMax == m_flowStatsDl.end()) |
| 539 { |
| 540 // no UE available for downlink· |
| 541 return; |
| 542 } |
| 543 else |
| 544 { |
| 545 // assign all RBGs to this UE |
| 546 std::vector <uint16_t> tempMap; |
| 547 for (int i = 0; i < rbgNum; i++) |
| 548 { |
| 549 tempMap.push_back (i); |
| 550 } |
| 551 allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itM
ax).first, tempMap)); |
| 552 } |
| 553 |
| 554 // generate the transmission opportunities by grouping the RBGs of the same RN
TI and |
| 555 // creating the correspondent DCIs |
| 556 FfMacSchedSapUser::SchedDlConfigIndParameters ret; |
| 557 std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.b
egin (); |
| 558 |
| 559 while (itMap != allocationMap.end ()) |
| 560 { |
| 561 // create new BuildDataListElement_s for this LC |
| 562 BuildDataListElement_s newEl; |
| 563 newEl.m_rnti = (*itMap).first; |
| 564 // create the DlDciListElement_s |
| 565 DlDciListElement_s newDci; |
| 566 std::vector <struct RlcPduListElement_s> newRlcPduLe; |
| 567 newDci.m_rnti = (*itMap).first; |
| 568 |
| 569 uint16_t lcActives = LcActivePerFlow ((*itMap).first); |
| 570 uint16_t RgbPerRnti = (*itMap).second.size (); |
| 571 std::map <uint16_t,SbMeasResult_s>::iterator itCqi; |
| 572 itCqi = m_a30CqiRxed.find ((*itMap).first); |
| 573 std::map <uint16_t,uint8_t>::iterator itTxMode; |
| 574 itTxMode = m_uesTxMode.find ((*itMap).first); |
| 575 if (itTxMode == m_uesTxMode.end()) |
| 576 { |
| 577 NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first
); |
| 578 } |
| 579 int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second)
; |
| 580 std::vector <uint8_t> worstCqi (2, 15); |
| 581 if (itCqi != m_a30CqiRxed.end ()) |
| 582 { |
| 583 for (uint16_t k = 0; k < (*itMap).second.size (); k++) |
| 584 { |
| 585 if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).secon
d.at (k)) |
| 586 { |
| 587 for (uint8_t j = 0; j < nLayer; j++)· |
| 588 { |
| 589 if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).sec
ond.at (k)).m_sbCqi.size ()> j) |
| 590 { |
| 591 if (((*itCqi).second.m_higherLayerSelected.at ((*itMap
).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j)) |
| 592 { |
| 593 worstCqi.at (j) = ((*itCqi).second.m_higherLayerSe
lected.at ((*itMap).second.at (k)).m_sbCqi.at (j)); |
| 594 } |
| 595 } |
| 596 else |
| 597 { |
| 598 // no CQI for this layer of this suband -> worst one |
| 599 worstCqi.at (j) = 1; |
| 600 } |
| 601 } |
| 602 } |
| 603 else |
| 604 { |
| 605 for (uint8_t j = 0; j < nLayer; j++) |
| 606 { |
| 607 worstCqi.at (j) = 1; // try with lowest MCS in RBG with no
info on channel |
| 608 } |
| 609 } |
| 610 } |
| 611 } |
| 612 else |
| 613 { |
| 614 for (uint8_t j = 0; j < nLayer; j++) |
| 615 { |
| 616 worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on
channel |
| 617 } |
| 618 } |
| 619 uint32_t bytesTxed = 0; |
| 620 for (uint8_t j = 0; j < nLayer; j++) |
| 621 { |
| 622 newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j))); |
| 623 int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (j), RgbPerRnti
* rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.2
13)· |
| 624 newDci.m_tbsSize.push_back (tbSize); |
| 625 bytesTxed += tbSize; |
| 626 } |
| 627 |
| 628 newDci.m_resAlloc = 0; // only allocation type 0 at this stage |
| 629 newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213) |
| 630 uint32_t rbgMask = 0; |
| 631 for (uint16_t k = 0; k < (*itMap).second.size (); k++) |
| 632 { |
| 633 rbgMask = rbgMask + (0x1 << (*itMap).second.at (k)); |
| 634 } |
| 635 newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213) |
| 636 |
| 637 // create the rlc PDUs -> equally divide resources among actives LCs |
| 638 std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameter
s>::iterator itBufReq; |
| 639 for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end ()
; itBufReq++) |
| 640 { |
| 641 if (((*itBufReq).first.m_rnti == (*itMap).first) && |
| 642 (((*itBufReq).second.m_rlcTransmissionQueueSize > 0) |
| 643 || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0) |
| 644 || ((*itBufReq).second.m_rlcStatusPduSize > 0) )) |
| 645 { |
| 646 for (uint8_t j = 0; j < nLayer; j++) |
| 647 { |
| 648 RlcPduListElement_s newRlcEl; |
| 649 newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId; |
| 650 newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives; |
| 651 newRlcPduLe.push_back (newRlcEl); |
| 652 UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChanne
lIdentity, newRlcEl.m_size); |
| 653 } |
| 654 } |
| 655 if ((*itBufReq).first.m_rnti > (*itMap).first) |
| 656 { |
| 657 break; |
| 658 } |
| 659 } |
| 660 newDci.m_ndi.push_back (1); // TBD (new data indicator) |
| 661 newDci.m_rv.push_back (0); // TBD (redundancy version) |
| 662 |
| 663 newEl.m_dci = newDci; |
| 664 // ...more parameters -> ingored in this version |
| 665 |
| 666 newEl.m_rlcPduList.push_back (newRlcPduLe); |
| 667 ret.m_buildDataList.push_back (newEl); |
| 668 |
| 669 // update UE stats |
| 670 std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator it; |
| 671 it = m_flowStatsDl.find ((*itMap).first); |
| 672 if (it != m_flowStatsDl.end ()) |
| 673 { |
| 674 if ( bytesTxed <= (*it).second.tokenPoolSize ) |
| 675 { |
| 676 (*it).second.tokenPoolSize -= bytesTxed; |
| 677 } |
| 678 else |
| 679 { |
| 680 (*it).second.counter = (*it).second.counter - ( bytesTxed - (*it)
.second.tokenPoolSize ); |
| 681 (*it).second.tokenPoolSize = 0; |
| 682 if (bankSize <= ( bytesTxed - (*it).second.tokenPoolSize )) |
| 683 bankSize = 0; |
| 684 else· |
| 685 bankSize = bankSize - ( bytesTxed - (*it).second.tokenPoolSize
); |
| 686 } |
| 687 } |
| 688 else |
| 689 { |
| 690 NS_LOG_DEBUG (this << " No Stats for this allocated UE"); |
| 691 } |
| 692 |
| 693 itMap++; |
| 694 } // end while allocation |
| 695 ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the D
CIs txed |
| 696 |
| 697 m_schedSapUser->SchedDlConfigInd (ret); |
| 698 |
| 699 · |
| 700 return; |
| 701 } |
| 702 |
| 703 void |
| 704 TdTbfqFfMacScheduler::DoSchedDlRachInfoReq (const struct FfMacSchedSapProvider::
SchedDlRachInfoReqParameters& params) |
| 705 { |
| 706 NS_LOG_FUNCTION (this); |
| 707 // TODO: Implementation of the API |
| 708 return; |
| 709 } |
| 710 |
| 711 void |
| 712 TdTbfqFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::S
chedDlCqiInfoReqParameters& params) |
| 713 { |
| 714 NS_LOG_FUNCTION (this); |
| 715 |
| 716 for (unsigned int i = 0; i < params.m_cqiList.size (); i++) |
| 717 { |
| 718 if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 ) |
| 719 { |
| 720 // wideband CQI reporting |
| 721 std::map <uint16_t,uint8_t>::iterator it; |
| 722 uint16_t rnti = params.m_cqiList.at (i).m_rnti; |
| 723 it = m_p10CqiRxed.find (rnti); |
| 724 if (it == m_p10CqiRxed.end ()) |
| 725 { |
| 726 // create the new entry |
| 727 m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (rnti, params.
m_cqiList.at (i).m_wbCqi.at (0)) ); // only codeword 0 at this stage (SISO) |
| 728 // generate correspondent timer |
| 729 m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cq
iTimersThreshold)); |
| 730 } |
| 731 else |
| 732 { |
| 733 // update the CQI value and refresh correspondent timer |
| 734 (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0); |
| 735 // update correspondent timer |
| 736 std::map <uint16_t,uint32_t>::iterator itTimers; |
| 737 itTimers = m_p10CqiTimers.find (rnti); |
| 738 (*itTimers).second = m_cqiTimersThreshold; |
| 739 } |
| 740 } |
| 741 else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 ) |
| 742 { |
| 743 // subband CQI reporting high layer configured |
| 744 std::map <uint16_t,SbMeasResult_s>::iterator it; |
| 745 uint16_t rnti = params.m_cqiList.at (i).m_rnti; |
| 746 it = m_a30CqiRxed.find (rnti); |
| 747 if (it == m_a30CqiRxed.end ()) |
| 748 { |
| 749 // create the new entry |
| 750 m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti,
params.m_cqiList.at (i).m_sbMeasResult) ); |
| 751 m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cq
iTimersThreshold)); |
| 752 } |
| 753 else |
| 754 { |
| 755 // update the CQI value and refresh correspondent timer |
| 756 (*it).second = params.m_cqiList.at (i).m_sbMeasResult; |
| 757 std::map <uint16_t,uint32_t>::iterator itTimers; |
| 758 itTimers = m_a30CqiTimers.find (rnti); |
| 759 (*itTimers).second = m_cqiTimersThreshold; |
| 760 } |
| 761 } |
| 762 else |
| 763 { |
| 764 NS_LOG_ERROR (this << " CQI type unknown"); |
| 765 } |
| 766 } |
| 767 |
| 768 return; |
| 769 } |
| 770 |
| 771 |
| 772 double |
| 773 TdTbfqFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb) |
| 774 { |
| 775 std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnt
i); |
| 776 if (itCqi == m_ueCqi.end ()) |
| 777 { |
| 778 // no cqi info about this UE |
| 779 return (NO_SINR); |
| 780 |
| 781 } |
| 782 else |
| 783 { |
| 784 // take the average SINR value among the available |
| 785 double sinrSum = 0; |
| 786 int sinrNum = 0; |
| 787 for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++) |
| 788 { |
| 789 double sinr = (*itCqi).second.at (i); |
| 790 if (sinr != NO_SINR) |
| 791 { |
| 792 sinrSum += sinr; |
| 793 sinrNum++; |
| 794 } |
| 795 } |
| 796 double estimatedSinr = sinrSum / (double)sinrNum; |
| 797 // store the value |
| 798 (*itCqi).second.at (rb) = estimatedSinr; |
| 799 return (estimatedSinr); |
| 800 } |
| 801 } |
| 802 |
| 803 void |
| 804 TdTbfqFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::S
chedUlTriggerReqParameters& params) |
| 805 { |
| 806 NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subf
rame no. " << (0xF & params.m_sfnSf)); |
| 807 · |
| 808 RefreshUlCqiMaps (); |
| 809 |
| 810 std::map <uint16_t,uint32_t>::iterator it;· |
| 811 int nflows = 0; |
| 812 |
| 813 for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++) |
| 814 { |
| 815 // remove old entries of this UE-LC |
| 816 if ((*it).second > 0) |
| 817 { |
| 818 nflows++; |
| 819 } |
| 820 } |
| 821 |
| 822 if (nflows == 0) |
| 823 { |
| 824 return ; // no flows to be scheduled |
| 825 } |
| 826 |
| 827 |
| 828 // Divide the resource equally among the active users |
| 829 int rbPerFlow = m_cschedCellConfig.m_ulBandwidth / nflows; |
| 830 if (rbPerFlow == 0) |
| 831 { |
| 832 rbPerFlow = 1; // at least 1 rbg per flow (till available res
ource) |
| 833 } |
| 834 int rbAllocated = 0; |
| 835 |
| 836 FfMacSchedSapUser::SchedUlConfigIndParameters ret; |
| 837 std::vector <uint16_t> rbgAllocationMap; |
| 838 //std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itStats; |
| 839 if (m_nextRntiUl != 0) |
| 840 { |
| 841 for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++) |
| 842 { |
| 843 if ((*it).first == m_nextRntiUl) |
| 844 { |
| 845 break; |
| 846 } |
| 847 } |
| 848 if (it == m_ceBsrRxed.end ()) |
| 849 { |
| 850 NS_LOG_ERROR (this << " no user found"); |
| 851 } |
| 852 } |
| 853 else |
| 854 { |
| 855 it = m_ceBsrRxed.begin (); |
| 856 m_nextRntiUl = (*it).first; |
| 857 } |
| 858 do |
| 859 { |
| 860 if (rbAllocated + rbPerFlow > m_cschedCellConfig.m_ulBandwidth) |
| 861 { |
| 862 // limit to physical resources last resource assignment |
| 863 rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated; |
| 864 } |
| 865 ····· |
| 866 UlDciListElement_s uldci; |
| 867 uldci.m_rnti = (*it).first; |
| 868 uldci.m_rbStart = rbAllocated; |
| 869 uldci.m_rbLen = rbPerFlow; |
| 870 std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find
((*it).first); |
| 871 int cqi = 0; |
| 872 if (itCqi == m_ueCqi.end ()) |
| 873 { |
| 874 // no cqi info about this UE |
| 875 uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD |
| 876 // NS_LOG_DEBUG (this << " UE does not have ULCQI " << (*it).first ); |
| 877 } |
| 878 else |
| 879 { |
| 880 // take the lowest CQI value (worst RB) |
| 881 double minSinr = (*itCqi).second.at (uldci.m_rbStart); |
| 882 if (minSinr == NO_SINR) |
| 883 { |
| 884 minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart); |
| 885 } |
| 886 for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen
; i++) |
| 887 { |
| 888 // NS_LOG_DEBUG (this << " UE " << (*it).first << " has SINR " <<
(*itCqi).second.at(i)); |
| 889 double sinr = (*itCqi).second.at (i); |
| 890 if (sinr == NO_SINR) |
| 891 { |
| 892 sinr = EstimateUlSinr ((*it).first, i); |
| 893 } |
| 894 if ((*itCqi).second.at (i) < minSinr) |
| 895 { |
| 896 minSinr = (*itCqi).second.at (i); |
| 897 } |
| 898 } |
| 899 |
| 900 // translate SINR -> cqi: WILD ACK: same as DL |
| 901 double s = log2 ( 1 + ( |
| 902 pow (10, minSinr / 10 ) / |
| 903 ( (-log (5.0 * 0.00005 )) / 1.5) )); |
| 904 cqi = m_amc->GetCqiFromSpectralEfficiency (s); |
| 905 if (cqi == 0) |
| 906 { |
| 907 it++; |
| 908 if (it == m_ceBsrRxed.end ()) |
| 909 { |
| 910 // restart from the first |
| 911 it = m_ceBsrRxed.begin (); |
| 912 } |
| 913 continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 3
6.213) |
| 914 } |
| 915 uldci.m_mcs = m_amc->GetMcsFromCqi (cqi); |
| 916 // NS_LOG_DEBUG (this << " UE " << (*it).first << " minsinr " << minS
inr << " -> mcs " << (uint16_t)uldci.m_mcs); |
| 917 |
| 918 } |
| 919 ······ |
| 920 rbAllocated += rbPerFlow; |
| 921 // store info on allocation for managing ul-cqi interpretation |
| 922 for (int i = 0; i < rbPerFlow; i++) |
| 923 { |
| 924 rbgAllocationMap.push_back ((*it).first); |
| 925 } |
| 926 uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); |
| 927 NS_LOG_DEBUG (this <<" "<<Simulator::Now()<< " UE " << (*it).first << " s
tartPRB " << (uint32_t)uldci.m_rbStart << " nPRB " << (uint32_t)uldci.m_rbLen <<
" CQI " << cqi << " MCS " << (uint32_t)uldci.m_mcs << " TBsize " << uldci.m_tbS
ize << " RbAlloc " << rbAllocated); |
| 928 UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize); |
| 929 uldci.m_ndi = 1; |
| 930 uldci.m_cceIndex = 0; |
| 931 uldci.m_aggrLevel = 1; |
| 932 uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF |
| 933 uldci.m_hopping = false; |
| 934 uldci.m_n2Dmrs = 0; |
| 935 uldci.m_tpc = 0; // no power control |
| 936 uldci.m_cqiRequest = false; // only period CQI at this stage |
| 937 uldci.m_ulIndex = 0; // TDD parameter |
| 938 uldci.m_dai = 1; // TDD parameter |
| 939 uldci.m_freqHopping = 0; |
| 940 uldci.m_pdcchPowerOffset = 0; // not used |
| 941 ret.m_dciList.push_back (uldci); |
| 942 |
| 943 it++; |
| 944 if (it == m_ceBsrRxed.end ()) |
| 945 { |
| 946 // restart from the first |
| 947 it = m_ceBsrRxed.begin (); |
| 948 } |
| 949 if (rbAllocated == m_cschedCellConfig.m_ulBandwidth) |
| 950 { |
| 951 // Stop allocation: no more PRBs |
| 952 m_nextRntiUl = (*it).first; |
| 953 break; |
| 954 } |
| 955 } |
| 956 while ((*it).first != m_nextRntiUl); |
| 957 |
| 958 m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params
.m_sfnSf, rbgAllocationMap)); |
| 959 m_schedSapUser->SchedUlConfigInd (ret); |
| 960 return; |
| 961 } |
| 962 |
| 963 void |
| 964 TdTbfqFfMacScheduler::DoSchedUlNoiseInterferenceReq (const struct FfMacSchedSapP
rovider::SchedUlNoiseInterferenceReqParameters& params) |
| 965 { |
| 966 NS_LOG_FUNCTION (this); |
| 967 // TODO: Implementation of the API |
| 968 return; |
| 969 } |
| 970 |
| 971 void |
| 972 TdTbfqFfMacScheduler::DoSchedUlSrInfoReq (const struct FfMacSchedSapProvider::Sc
hedUlSrInfoReqParameters& params) |
| 973 { |
| 974 NS_LOG_FUNCTION (this); |
| 975 // TODO: Implementation of the API |
| 976 return; |
| 977 } |
| 978 |
| 979 void |
| 980 TdTbfqFfMacScheduler::DoSchedUlMacCtrlInfoReq (const struct FfMacSchedSapProvide
r::SchedUlMacCtrlInfoReqParameters& params) |
| 981 { |
| 982 NS_LOG_FUNCTION (this); |
| 983 |
| 984 std::map <uint16_t,uint32_t>::iterator it; |
| 985 ·· |
| 986 for (unsigned int i = 0; i < params.m_macCeList.size (); i++) |
| 987 { |
| 988 if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR ) |
| 989 { |
| 990 // buffer status report |
| 991 uint16_t rnti = params.m_macCeList.at (i).m_rnti; |
| 992 it = m_ceBsrRxed.find (rnti); |
| 993 if (it == m_ceBsrRxed.end ()) |
| 994 { |
| 995 // create the new entry |
| 996 uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at
(0); |
| 997 int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId); |
| 998 m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer)); //
only 1 buffer status is working now |
| 999 } |
| 1000 else |
| 1001 { |
| 1002 // update the CQI value |
| 1003 (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.
at (i).m_macCeValue.m_bufferStatus.at (0)); |
| 1004 } |
| 1005 } |
| 1006 } |
| 1007 ·· |
| 1008 return; |
| 1009 } |
| 1010 |
| 1011 void |
| 1012 TdTbfqFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::S
chedUlCqiInfoReqParameters& params) |
| 1013 { |
| 1014 NS_LOG_FUNCTION (this); |
| 1015 // NS_LOG_DEBUG (this << " RX SFNID " << params.m_sfnSf); |
| 1016 // retrieve the allocation for this subframe |
| 1017 std::map <uint16_t, std::vector <uint16_t> >::iterator itMap; |
| 1018 std::map <uint16_t, std::vector <double> >::iterator itCqi; |
| 1019 itMap = m_allocationMaps.find (params.m_sfnSf); |
| 1020 if (itMap == m_allocationMaps.end ()) |
| 1021 { |
| 1022 //NS_LOG_DEBUG (this << " Does not find info on allocation, size : " << m_
allocationMaps.size ()); |
| 1023 return; |
| 1024 } |
| 1025 for (uint32_t i = 0; i < (*itMap).second.size (); i++) |
| 1026 { |
| 1027 // convert from fixed point notation Sxxxxxxxxxxx.xxx to double |
| 1028 // NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.si
ze () << " mapSIze " << (*itMap).second.size ()); |
| 1029 double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at
(i)); |
| 1030 //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINRfp " <<
params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr); |
| 1031 itCqi = m_ueCqi.find ((*itMap).second.at (i)); |
| 1032 if (itCqi == m_ueCqi.end ()) |
| 1033 { |
| 1034 // create a new entry |
| 1035 std::vector <double> newCqi; |
| 1036 for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++) |
| 1037 { |
| 1038 if (i == j) |
| 1039 { |
| 1040 newCqi.push_back (sinr); |
| 1041 } |
| 1042 else |
| 1043 { |
| 1044 // initialize with NO_SINR value. |
| 1045 newCqi.push_back (NO_SINR); |
| 1046 } |
| 1047 |
| 1048 } |
| 1049 m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).
second.at (i), newCqi)); |
| 1050 // generate correspondent timer |
| 1051 m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second
.at (i), m_cqiTimersThreshold)); |
| 1052 } |
| 1053 else |
| 1054 { |
| 1055 // update the value |
| 1056 (*itCqi).second.at (i) = sinr; |
| 1057 // update correspondent timer |
| 1058 std::map <uint16_t, uint32_t>::iterator itTimers; |
| 1059 itTimers = m_ueCqiTimers.find ((*itMap).second.at (i)); |
| 1060 (*itTimers).second = m_cqiTimersThreshold; |
| 1061 ·········· |
| 1062 } |
| 1063 |
| 1064 } |
| 1065 // remove obsolete info on allocation |
| 1066 m_allocationMaps.erase (itMap); |
| 1067 |
| 1068 return; |
| 1069 } |
| 1070 |
| 1071 void |
| 1072 TdTbfqFfMacScheduler::RefreshDlCqiMaps(void) |
| 1073 { |
| 1074 // refresh DL CQI P01 Map |
| 1075 std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin (); |
| 1076 while (itP10!=m_p10CqiTimers.end ()) |
| 1077 { |
| 1078 // NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " <
< (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold); |
| 1079 if ((*itP10).second == 0) |
| 1080 { |
| 1081 // delete correspondent entries |
| 1082 std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP
10).first); |
| 1083 NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI repor
t for user " << (*itP10).first); |
| 1084 NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first); |
| 1085 m_p10CqiRxed.erase (itMap); |
| 1086 std::map <uint16_t,uint32_t>::iterator temp = itP10; |
| 1087 itP10++; |
| 1088 m_p10CqiTimers.erase (temp); |
| 1089 } |
| 1090 else |
| 1091 { |
| 1092 (*itP10).second--; |
| 1093 itP10++; |
| 1094 } |
| 1095 } |
| 1096 ·· |
| 1097 // refresh DL CQI A30 Map |
| 1098 std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin (); |
| 1099 while (itA30!=m_a30CqiTimers.end ()) |
| 1100 { |
| 1101 // NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " <
< (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold); |
| 1102 if ((*itA30).second == 0) |
| 1103 { |
| 1104 // delete correspondent entries |
| 1105 std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find
((*itA30).first); |
| 1106 NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI repor
t for user " << (*itA30).first); |
| 1107 NS_LOG_INFO (this << " A30-CQI exired for user " << (*itA30).first); |
| 1108 m_a30CqiRxed.erase (itMap); |
| 1109 std::map <uint16_t,uint32_t>::iterator temp = itA30; |
| 1110 itA30++; |
| 1111 m_a30CqiTimers.erase (temp); |
| 1112 } |
| 1113 else |
| 1114 { |
| 1115 (*itA30).second--; |
| 1116 itA30++; |
| 1117 } |
| 1118 } |
| 1119 ···· |
| 1120 return; |
| 1121 } |
| 1122 |
| 1123 |
| 1124 void |
| 1125 TdTbfqFfMacScheduler::RefreshUlCqiMaps(void) |
| 1126 { |
| 1127 // refresh UL CQI Map |
| 1128 std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin (); |
| 1129 while (itUl!=m_ueCqiTimers.end ()) |
| 1130 { |
| 1131 // NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " <<
(uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold); |
| 1132 if ((*itUl).second == 0) |
| 1133 { |
| 1134 // delete correspondent entries |
| 1135 std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.f
ind ((*itUl).first); |
| 1136 NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for
user " << (*itUl).first); |
| 1137 NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first); |
| 1138 (*itMap).second.clear (); |
| 1139 m_ueCqi.erase (itMap); |
| 1140 std::map <uint16_t,uint32_t>::iterator temp = itUl; |
| 1141 itUl++; |
| 1142 m_ueCqiTimers.erase (temp); |
| 1143 } |
| 1144 else |
| 1145 { |
| 1146 (*itUl).second--; |
| 1147 itUl++; |
| 1148 } |
| 1149 } |
| 1150 ···· |
| 1151 return; |
| 1152 } |
| 1153 |
| 1154 void |
| 1155 TdTbfqFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16
_t size) |
| 1156 { |
| 1157 std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::i
terator it; |
| 1158 LteFlowId_t flow (rnti, lcid); |
| 1159 it = m_rlcBufferReq.find (flow); |
| 1160 if (it!=m_rlcBufferReq.end ()) |
| 1161 { |
| 1162 //NS_LOG_DEBUG (this << " UE " << rnti << " LC " << (uint16_t)lcid << " t
xqueue " << (*it).second.m_rlcTransmissionQueueSize << " retxqueue " << (*it).se
cond.m_rlcRetransmissionQueueSize << " status " << (*it).second.m_rlcStatusPduSi
ze << " decrease " << size); |
| 1163 // Update queues: RLC tx order Status, ReTx, Tx |
| 1164 // Update status queue |
| 1165 if ((*it).second.m_rlcStatusPduSize <= size) |
| 1166 { |
| 1167 size -= (*it).second.m_rlcStatusPduSize; |
| 1168 (*it).second.m_rlcStatusPduSize = 0; |
| 1169 } |
| 1170 else |
| 1171 { |
| 1172 (*it).second.m_rlcStatusPduSize -= size; |
| 1173 return; |
| 1174 } |
| 1175 // update retransmission queue·· |
| 1176 if ((*it).second.m_rlcRetransmissionQueueSize <= size) |
| 1177 { |
| 1178 size -= (*it).second.m_rlcRetransmissionQueueSize; |
| 1179 (*it).second.m_rlcRetransmissionQueueSize = 0; |
| 1180 } |
| 1181 else |
| 1182 { |
| 1183 (*it).second.m_rlcRetransmissionQueueSize -= size; |
| 1184 return; |
| 1185 } |
| 1186 // update transmission queue |
| 1187 if ((*it).second.m_rlcTransmissionQueueSize <= size) |
| 1188 { |
| 1189 size -= (*it).second.m_rlcTransmissionQueueSize; |
| 1190 (*it).second.m_rlcTransmissionQueueSize = 0; |
| 1191 } |
| 1192 else |
| 1193 { |
| 1194 (*it).second.m_rlcTransmissionQueueSize -= size; |
| 1195 return; |
| 1196 } |
| 1197 } |
| 1198 else |
| 1199 { |
| 1200 NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti
); |
| 1201 } |
| 1202 } |
| 1203 |
| 1204 void |
| 1205 TdTbfqFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size) |
| 1206 { |
| 1207 ·· |
| 1208 ·· |
| 1209 std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti); |
| 1210 if (it!=m_ceBsrRxed.end ()) |
| 1211 { |
| 1212 // NS_LOG_DEBUG (this << " UE " << rnti << " size " << size << " BSR " <<
(*it).second);······ |
| 1213 if ((*it).second >= size) |
| 1214 { |
| 1215 (*it).second -= size; |
| 1216 } |
| 1217 else |
| 1218 { |
| 1219 (*it).second = 0; |
| 1220 } |
| 1221 } |
| 1222 else |
| 1223 { |
| 1224 NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti); |
| 1225 } |
| 1226 ·· |
| 1227 } |
| 1228 |
| 1229 void |
| 1230 TdTbfqFfMacScheduler::TransmissionModeConfigurationUpdate (uint16_t rnti, uint8_
t txMode) |
| 1231 { |
| 1232 NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode); |
| 1233 FfMacCschedSapUser::CschedUeConfigUpdateIndParameters params; |
| 1234 params.m_rnti = rnti; |
| 1235 params.m_transmissionMode = txMode; |
| 1236 m_cschedSapUser->CschedUeConfigUpdateInd (params); |
| 1237 } |
| 1238 |
| 1239 |
| 1240 } |
OLD | NEW |