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