A Discrete-Event Network Simulator
API
tdtbfq-ff-mac-scheduler.cc
Go to the documentation of this file.
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>
19 * Modification: Dizhi Zhou <dizhi.zhou@gmail.com> // modify codes related to downlink scheduler
20 */
21
22#include <ns3/log.h>
23#include <ns3/pointer.h>
24#include <ns3/math.h>
25
26#include <ns3/simulator.h>
27#include <ns3/lte-amc.h>
28#include <ns3/tdtbfq-ff-mac-scheduler.h>
29#include <ns3/lte-vendor-specific-parameters.h>
30#include <ns3/boolean.h>
31#include <ns3/integer.h>
32#include <set>
33#include <cfloat>
34
35namespace ns3 {
36
37NS_LOG_COMPONENT_DEFINE ("TdTbfqFfMacScheduler");
38
40static const int TdTbfqType0AllocationRbg[4] = {
41 10, // RGB size 1
42 26, // RGB size 2
43 63, // RGB size 3
44 110 // RGB size 4
45}; // see table 7.1.6.1-1 of 36.213
46
47
48NS_OBJECT_ENSURE_REGISTERED (TdTbfqFfMacScheduler);
49
50
51
53 : m_cschedSapUser (0),
54 m_schedSapUser (0),
55 m_nextRntiUl (0),
56 bankSize (0)
57{
58 m_amc = CreateObject <LteAmc> ();
63}
64
66{
67 NS_LOG_FUNCTION (this);
68}
69
70void
72{
73 NS_LOG_FUNCTION (this);
77 m_dlInfoListBuffered.clear ();
82 delete m_schedSapProvider;
83 delete m_ffrSapUser;
84}
85
88{
89 static TypeId tid = TypeId ("ns3::TdTbfqFfMacScheduler")
91 .SetGroupName("Lte")
92 .AddConstructor<TdTbfqFfMacScheduler> ()
93 .AddAttribute ("CqiTimerThreshold",
94 "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
95 UintegerValue (1000),
97 MakeUintegerChecker<uint32_t> ())
98 .AddAttribute ("DebtLimit",
99 "Flow debt limit (default -625000 bytes)",
100 IntegerValue (-625000),
102 MakeIntegerChecker<int> ())
103 .AddAttribute ("CreditLimit",
104 "Flow credit limit (default 625000 bytes)",
105 UintegerValue (625000),
107 MakeUintegerChecker<uint32_t> ())
108 .AddAttribute ("TokenPoolSize",
109 "The maximum value of flow token pool (default 1 bytes)",
110 UintegerValue (1),
112 MakeUintegerChecker<uint32_t> ())
113 .AddAttribute ("CreditableThreshold",
114 "Threshold of flow credit (default 0 bytes)",
115 UintegerValue (0),
117 MakeUintegerChecker<uint32_t> ())
118
119 .AddAttribute ("HarqEnabled",
120 "Activate/Deactivate the HARQ [by default is active].",
121 BooleanValue (true),
124 .AddAttribute ("UlGrantMcs",
125 "The MCS of the UL grant, must be [0..15] (default 0)",
126 UintegerValue (0),
128 MakeUintegerChecker<uint8_t> ())
129 ;
130 return tid;
131}
132
133
134
135void
137{
138 m_cschedSapUser = s;
139}
140
141void
143{
144 m_schedSapUser = s;
145}
146
149{
150 return m_cschedSapProvider;
151}
152
155{
156 return m_schedSapProvider;
157}
158
159void
161{
163}
164
167{
168 return m_ffrSapUser;
169}
170
171void
173{
174 NS_LOG_FUNCTION (this);
175 // Read the subset of parameters used
176 m_cschedCellConfig = params;
179 cnf.m_result = SUCCESS;
181 return;
182}
183
184void
186{
187 NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
188 std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
189 if (it == m_uesTxMode.end ())
190 {
191 m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
192 // generate HARQ buffers
193 m_dlHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
194 DlHarqProcessesStatus_t dlHarqPrcStatus;
195 dlHarqPrcStatus.resize (8,0);
196 m_dlHarqProcessesStatus.insert (std::pair <uint16_t, DlHarqProcessesStatus_t> (params.m_rnti, dlHarqPrcStatus));
197 DlHarqProcessesTimer_t dlHarqProcessesTimer;
198 dlHarqProcessesTimer.resize (8,0);
199 m_dlHarqProcessesTimer.insert (std::pair <uint16_t, DlHarqProcessesTimer_t> (params.m_rnti, dlHarqProcessesTimer));
201 dlHarqdci.resize (8);
202 m_dlHarqProcessesDciBuffer.insert (std::pair <uint16_t, DlHarqProcessesDciBuffer_t> (params.m_rnti, dlHarqdci));
203 DlHarqRlcPduListBuffer_t dlHarqRlcPdu;
204 dlHarqRlcPdu.resize (2);
205 dlHarqRlcPdu.at (0).resize (8);
206 dlHarqRlcPdu.at (1).resize (8);
207 m_dlHarqProcessesRlcPduListBuffer.insert (std::pair <uint16_t, DlHarqRlcPduListBuffer_t> (params.m_rnti, dlHarqRlcPdu));
208 m_ulHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
209 UlHarqProcessesStatus_t ulHarqPrcStatus;
210 ulHarqPrcStatus.resize (8,0);
211 m_ulHarqProcessesStatus.insert (std::pair <uint16_t, UlHarqProcessesStatus_t> (params.m_rnti, ulHarqPrcStatus));
213 ulHarqdci.resize (8);
214 m_ulHarqProcessesDciBuffer.insert (std::pair <uint16_t, UlHarqProcessesDciBuffer_t> (params.m_rnti, ulHarqdci));
215 }
216 else
217 {
218 (*it).second = params.m_transmissionMode;
219 }
220 return;
221}
222
223void
225{
226 NS_LOG_FUNCTION (this << " New LC, rnti: " << params.m_rnti);
227
228 std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator it;
229 for (uint16_t i = 0; i < params.m_logicalChannelConfigList.size (); i++)
230 {
231 it = m_flowStatsDl.find (params.m_rnti);
232
233 if (it == m_flowStatsDl.end ())
234 {
235 uint64_t mbrDlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabMaximulBitrateDl / 8; // byte/s
236 uint64_t mbrUlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabMaximulBitrateUl / 8; // byte/s
237
238 tdtbfqsFlowPerf_t flowStatsDl;
239 flowStatsDl.flowStart = Simulator::Now ();
240 flowStatsDl.packetArrivalRate = 0;
241 flowStatsDl.tokenGenerationRate = mbrDlInBytes;
242 flowStatsDl.tokenPoolSize = 0;
243 flowStatsDl.maxTokenPoolSize = m_tokenPoolSize;
244 flowStatsDl.counter = 0;
245 flowStatsDl.burstCredit = m_creditLimit; // bytes
246 flowStatsDl.debtLimit = m_debtLimit; // bytes
248 m_flowStatsDl.insert (std::pair<uint16_t, tdtbfqsFlowPerf_t> (params.m_rnti, flowStatsDl));
249 tdtbfqsFlowPerf_t flowStatsUl;
250 flowStatsUl.flowStart = Simulator::Now ();
251 flowStatsUl.packetArrivalRate = 0;
252 flowStatsUl.tokenGenerationRate = mbrUlInBytes;
253 flowStatsUl.tokenPoolSize = 0;
254 flowStatsUl.maxTokenPoolSize = m_tokenPoolSize;
255 flowStatsUl.counter = 0;
256 flowStatsUl.burstCredit = m_creditLimit; // bytes
257 flowStatsUl.debtLimit = m_debtLimit; // bytes
259 m_flowStatsUl.insert (std::pair<uint16_t, tdtbfqsFlowPerf_t> (params.m_rnti, flowStatsUl));
260 }
261 else
262 {
263 // update MBR and GBR from UeManager::SetupDataRadioBearer ()
264 uint64_t mbrDlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabMaximulBitrateDl / 8; // byte/s
265 uint64_t mbrUlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabMaximulBitrateUl / 8; // byte/s
266 m_flowStatsDl[(*it).first].tokenGenerationRate = mbrDlInBytes;
267 m_flowStatsUl[(*it).first].tokenGenerationRate = mbrUlInBytes;
268
269 }
270 }
271
272 return;
273}
274
275void
277{
278 NS_LOG_FUNCTION (this);
279 for (uint16_t i = 0; i < params.m_logicalChannelIdentity.size (); i++)
280 {
281 std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
282 std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator temp;
283 while (it!=m_rlcBufferReq.end ())
284 {
285 if (((*it).first.m_rnti == params.m_rnti) && ((*it).first.m_lcId == params.m_logicalChannelIdentity.at (i)))
286 {
287 temp = it;
288 it++;
289 m_rlcBufferReq.erase (temp);
290 }
291 else
292 {
293 it++;
294 }
295 }
296 }
297 return;
298}
299
300void
302{
303 NS_LOG_FUNCTION (this);
304
305 m_uesTxMode.erase (params.m_rnti);
306 m_dlHarqCurrentProcessId.erase (params.m_rnti);
307 m_dlHarqProcessesStatus.erase (params.m_rnti);
308 m_dlHarqProcessesTimer.erase (params.m_rnti);
309 m_dlHarqProcessesDciBuffer.erase (params.m_rnti);
311 m_ulHarqCurrentProcessId.erase (params.m_rnti);
312 m_ulHarqProcessesStatus.erase (params.m_rnti);
313 m_ulHarqProcessesDciBuffer.erase (params.m_rnti);
314 m_flowStatsDl.erase (params.m_rnti);
315 m_flowStatsUl.erase (params.m_rnti);
316 m_ceBsrRxed.erase (params.m_rnti);
317 std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
318 std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator temp;
319 while (it!=m_rlcBufferReq.end ())
320 {
321 if ((*it).first.m_rnti == params.m_rnti)
322 {
323 temp = it;
324 it++;
325 m_rlcBufferReq.erase (temp);
326 }
327 else
328 {
329 it++;
330 }
331 }
332 if (m_nextRntiUl == params.m_rnti)
333 {
334 m_nextRntiUl = 0;
335 }
336
337 return;
338}
339
340
341void
343{
344 NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
345 // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
346
347 std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
348
349 LteFlowId_t flow (params.m_rnti, params.m_logicalChannelIdentity);
350
351 it = m_rlcBufferReq.find (flow);
352
353 if (it == m_rlcBufferReq.end ())
354 {
355 m_rlcBufferReq.insert (std::pair <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters> (flow, params));
356 }
357 else
358 {
359 (*it).second = params;
360 }
361
362 return;
363}
364
365void
367{
368 NS_LOG_FUNCTION (this);
369 NS_FATAL_ERROR ("method not implemented");
370 return;
371}
372
373void
375{
376 NS_LOG_FUNCTION (this);
377 NS_FATAL_ERROR ("method not implemented");
378 return;
379}
380
381int
383{
384 for (int i = 0; i < 4; i++)
385 {
386 if (dlbandwidth < TdTbfqType0AllocationRbg[i])
387 {
388 return (i + 1);
389 }
390 }
391
392 return (-1);
393}
394
395
396unsigned int
398{
399 std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
400 unsigned int lcActive = 0;
401 for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
402 {
403 if (((*it).first.m_rnti == rnti) && (((*it).second.m_rlcTransmissionQueueSize > 0)
404 || ((*it).second.m_rlcRetransmissionQueueSize > 0)
405 || ((*it).second.m_rlcStatusPduSize > 0) ))
406 {
407 lcActive++;
408 }
409 if ((*it).first.m_rnti > rnti)
410 {
411 break;
412 }
413 }
414 return (lcActive);
415
416}
417
418
419uint8_t
421{
422 NS_LOG_FUNCTION (this << rnti);
423
424 std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
425 if (it == m_dlHarqCurrentProcessId.end ())
426 {
427 NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
428 }
429 std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
430 if (itStat == m_dlHarqProcessesStatus.end ())
431 {
432 NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
433 }
434 uint8_t i = (*it).second;
435 do
436 {
437 i = (i + 1) % HARQ_PROC_NUM;
438 }
439 while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
440 if ((*itStat).second.at (i) == 0)
441 {
442 return (true);
443 }
444 else
445 {
446 return (false); // return a not valid harq proc id
447 }
448}
449
450
451
452uint8_t
454{
455 NS_LOG_FUNCTION (this << rnti);
456
457 if (m_harqOn == false)
458 {
459 return (0);
460 }
461
462
463 std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
464 if (it == m_dlHarqCurrentProcessId.end ())
465 {
466 NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
467 }
468 std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
469 if (itStat == m_dlHarqProcessesStatus.end ())
470 {
471 NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
472 }
473 uint8_t i = (*it).second;
474 do
475 {
476 i = (i + 1) % HARQ_PROC_NUM;
477 }
478 while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
479 if ((*itStat).second.at (i) == 0)
480 {
481 (*it).second = i;
482 (*itStat).second.at (i) = 1;
483 }
484 else
485 {
486 NS_FATAL_ERROR ("No HARQ process available for RNTI " << rnti << " check before update with HarqProcessAvailability");
487 }
488
489 return ((*it).second);
490}
491
492
493void
495{
496 NS_LOG_FUNCTION (this);
497
498 std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itTimers;
499 for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers ++)
500 {
501 for (uint16_t i = 0; i < HARQ_PROC_NUM; i++)
502 {
503 if ((*itTimers).second.at (i) == HARQ_DL_TIMEOUT)
504 {
505 // reset HARQ process
506
507 NS_LOG_DEBUG (this << " Reset HARQ proc " << i << " for RNTI " << (*itTimers).first);
508 std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find ((*itTimers).first);
509 if (itStat == m_dlHarqProcessesStatus.end ())
510 {
511 NS_FATAL_ERROR ("No Process Id Status found for this RNTI " << (*itTimers).first);
512 }
513 (*itStat).second.at (i) = 0;
514 (*itTimers).second.at (i) = 0;
515 }
516 else
517 {
518 (*itTimers).second.at (i)++;
519 }
520 }
521 }
522
523}
524
525
526void
528{
529 NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
530 // API generated by RLC for triggering the scheduling of a DL subframe
531
532
533 // evaluate the relative channel quality indicator for each UE per each RBG
534 // (since we are using allocation type 0 the small unit of allocation is RBG)
535 // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
536
538
540 int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
541 std::map <uint16_t, std::vector <uint16_t> > allocationMap; // RBs map per RNTI
542 std::vector <bool> rbgMap; // global RBGs map
543 uint16_t rbgAllocatedNum = 0;
544 std::set <uint16_t> rntiAllocated;
545 rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
546
548 for (std::vector<bool>::iterator it = rbgMap.begin (); it != rbgMap.end (); it++)
549 {
550 if ((*it) == true )
551 {
552 rbgAllocatedNum++;
553 }
554 }
555
557
558 // update UL HARQ proc id
559 std::map <uint16_t, uint8_t>::iterator itProcId;
560 for (itProcId = m_ulHarqCurrentProcessId.begin (); itProcId != m_ulHarqCurrentProcessId.end (); itProcId++)
561 {
562 (*itProcId).second = ((*itProcId).second + 1) % HARQ_PROC_NUM;
563 }
564
565 // RACH Allocation
566 uint16_t rbAllocatedNum = 0;
567 std::vector <bool> ulRbMap;
568 ulRbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
570 uint8_t maxContinuousUlBandwidth = 0;
571 uint8_t tmpMinBandwidth = 0;
572 uint16_t ffrRbStartOffset = 0;
573 uint16_t tmpFfrRbStartOffset = 0;
574 uint16_t index = 0;
575
576 for (std::vector<bool>::iterator it = ulRbMap.begin (); it != ulRbMap.end (); it++)
577 {
578 if ((*it) == true )
579 {
580 rbAllocatedNum++;
581 if (tmpMinBandwidth > maxContinuousUlBandwidth)
582 {
583 maxContinuousUlBandwidth = tmpMinBandwidth;
584 ffrRbStartOffset = tmpFfrRbStartOffset;
585 }
586 tmpMinBandwidth = 0;
587 }
588 else
589 {
590 if (tmpMinBandwidth == 0)
591 {
592 tmpFfrRbStartOffset = index;
593 }
594 tmpMinBandwidth++;
595 }
596 index++;
597 }
598
599 if (tmpMinBandwidth > maxContinuousUlBandwidth)
600 {
601 maxContinuousUlBandwidth = tmpMinBandwidth;
602 ffrRbStartOffset = tmpFfrRbStartOffset;
603 }
604
606 uint16_t rbStart = 0;
607 rbStart = ffrRbStartOffset;
608 std::vector <struct RachListElement_s>::iterator itRach;
609 for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
610 {
611 NS_ASSERT_MSG (m_amc->GetUlTbSizeFromMcs (m_ulGrantMcs, m_cschedCellConfig.m_ulBandwidth) > (*itRach).m_estimatedSize, " Default UL Grant MCS does not allow to send RACH messages");
613 newRar.m_rnti = (*itRach).m_rnti;
614 // DL-RACH Allocation
615 // Ideal: no needs of configuring m_dci
616 // UL-RACH Allocation
617 newRar.m_grant.m_rnti = newRar.m_rnti;
618 newRar.m_grant.m_mcs = m_ulGrantMcs;
619 uint16_t rbLen = 1;
620 uint16_t tbSizeBits = 0;
621 // find lowest TB size that fits UL grant estimated size
622 while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < (ffrRbStartOffset + maxContinuousUlBandwidth)))
623 {
624 rbLen++;
625 tbSizeBits = m_amc->GetUlTbSizeFromMcs (m_ulGrantMcs, rbLen);
626 }
627 if (tbSizeBits < (*itRach).m_estimatedSize)
628 {
629 // no more allocation space: finish allocation
630 break;
631 }
632 newRar.m_grant.m_rbStart = rbStart;
633 newRar.m_grant.m_rbLen = rbLen;
634 newRar.m_grant.m_tbSize = tbSizeBits / 8;
635 newRar.m_grant.m_hopping = false;
636 newRar.m_grant.m_tpc = 0;
637 newRar.m_grant.m_cqiRequest = false;
638 newRar.m_grant.m_ulDelay = false;
639 NS_LOG_INFO (this << " UL grant allocated to RNTI " << (*itRach).m_rnti << " rbStart " << rbStart << " rbLen " << rbLen << " MCS " << m_ulGrantMcs << " tbSize " << newRar.m_grant.m_tbSize);
640 for (uint16_t i = rbStart; i < rbStart + rbLen; i++)
641 {
642 m_rachAllocationMap.at (i) = (*itRach).m_rnti;
643 }
644
645 if (m_harqOn == true)
646 {
647 // generate UL-DCI for HARQ retransmissions
648 UlDciListElement_s uldci;
649 uldci.m_rnti = newRar.m_rnti;
650 uldci.m_rbLen = rbLen;
651 uldci.m_rbStart = rbStart;
652 uldci.m_mcs = m_ulGrantMcs;
653 uldci.m_tbSize = tbSizeBits / 8;
654 uldci.m_ndi = 1;
655 uldci.m_cceIndex = 0;
656 uldci.m_aggrLevel = 1;
657 uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
658 uldci.m_hopping = false;
659 uldci.m_n2Dmrs = 0;
660 uldci.m_tpc = 0; // no power control
661 uldci.m_cqiRequest = false; // only period CQI at this stage
662 uldci.m_ulIndex = 0; // TDD parameter
663 uldci.m_dai = 1; // TDD parameter
664 uldci.m_freqHopping = 0;
665 uldci.m_pdcchPowerOffset = 0; // not used
666
667 uint8_t harqId = 0;
668 std::map <uint16_t, uint8_t>::iterator itProcId;
669 itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
670 if (itProcId == m_ulHarqCurrentProcessId.end ())
671 {
672 NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
673 }
674 harqId = (*itProcId).second;
675 std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
676 if (itDci == m_ulHarqProcessesDciBuffer.end ())
677 {
678 NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
679 }
680 (*itDci).second.at (harqId) = uldci;
681 }
682
683 rbStart = rbStart + rbLen;
684 ret.m_buildRarList.push_back (newRar);
685 }
686 m_rachList.clear ();
687
688
689 // Process DL HARQ feedback
691 // retrieve past HARQ retx buffered
692 if (m_dlInfoListBuffered.size () > 0)
693 {
694 if (params.m_dlInfoList.size () > 0)
695 {
696 NS_LOG_INFO (this << " Received DL-HARQ feedback");
697 m_dlInfoListBuffered.insert (m_dlInfoListBuffered.end (), params.m_dlInfoList.begin (), params.m_dlInfoList.end ());
698 }
699 }
700 else
701 {
702 if (params.m_dlInfoList.size () > 0)
703 {
705 }
706 }
707 if (m_harqOn == false)
708 {
709 // Ignore HARQ feedback
710 m_dlInfoListBuffered.clear ();
711 }
712 std::vector <struct DlInfoListElement_s> dlInfoListUntxed;
713 for (uint16_t i = 0; i < m_dlInfoListBuffered.size (); i++)
714 {
715 std::set <uint16_t>::iterator itRnti = rntiAllocated.find (m_dlInfoListBuffered.at (i).m_rnti);
716 if (itRnti != rntiAllocated.end ())
717 {
718 // RNTI already allocated for retx
719 continue;
720 }
721 uint8_t nLayers = m_dlInfoListBuffered.at (i).m_harqStatus.size ();
722 std::vector <bool> retx;
723 NS_LOG_INFO (this << " Processing DLHARQ feedback");
724 if (nLayers == 1)
725 {
726 retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
727 retx.push_back (false);
728 }
729 else
730 {
731 retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
732 retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (1) == DlInfoListElement_s::NACK);
733 }
734 if (retx.at (0) || retx.at (1))
735 {
736 // retrieve HARQ process information
737 uint16_t rnti = m_dlInfoListBuffered.at (i).m_rnti;
738 uint8_t harqId = m_dlInfoListBuffered.at (i).m_harqProcessId;
739 NS_LOG_INFO (this << " HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
740 std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itHarq = m_dlHarqProcessesDciBuffer.find (rnti);
741 if (itHarq == m_dlHarqProcessesDciBuffer.end ())
742 {
743 NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << rnti);
744 }
745
746 DlDciListElement_s dci = (*itHarq).second.at (harqId);
747 int rv = 0;
748 if (dci.m_rv.size () == 1)
749 {
750 rv = dci.m_rv.at (0);
751 }
752 else
753 {
754 rv = (dci.m_rv.at (0) > dci.m_rv.at (1) ? dci.m_rv.at (0) : dci.m_rv.at (1));
755 }
756
757 if (rv == 3)
758 {
759 // maximum number of retx reached -> drop process
760 NS_LOG_INFO ("Maximum number of retransmissions reached -> drop process");
761 std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (rnti);
762 if (it == m_dlHarqProcessesStatus.end ())
763 {
764 NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << m_dlInfoListBuffered.at (i).m_rnti);
765 }
766 (*it).second.at (harqId) = 0;
767 std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
768 if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
769 {
770 NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
771 }
772 for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
773 {
774 (*itRlcPdu).second.at (k).at (harqId).clear ();
775 }
776 continue;
777 }
778 // check the feasibility of retransmitting on the same RBGs
779 // translate the DCI to Spectrum framework
780 std::vector <int> dciRbg;
781 uint32_t mask = 0x1;
782 NS_LOG_INFO ("Original RBGs " << dci.m_rbBitmap << " rnti " << dci.m_rnti);
783 for (int j = 0; j < 32; j++)
784 {
785 if (((dci.m_rbBitmap & mask) >> j) == 1)
786 {
787 dciRbg.push_back (j);
788 NS_LOG_INFO ("\t" << j);
789 }
790 mask = (mask << 1);
791 }
792 bool free = true;
793 for (uint8_t j = 0; j < dciRbg.size (); j++)
794 {
795 if (rbgMap.at (dciRbg.at (j)) == true)
796 {
797 free = false;
798 break;
799 }
800 }
801 if (free)
802 {
803 // use the same RBGs for the retx
804 // reserve RBGs
805 for (uint8_t j = 0; j < dciRbg.size (); j++)
806 {
807 rbgMap.at (dciRbg.at (j)) = true;
808 NS_LOG_INFO ("RBG " << dciRbg.at (j) << " assigned");
809 rbgAllocatedNum++;
810 }
811
812 NS_LOG_INFO (this << " Send retx in the same RBGs");
813 }
814 else
815 {
816 // find RBGs for sending HARQ retx
817 uint8_t j = 0;
818 uint8_t rbgId = (dciRbg.at (dciRbg.size () - 1) + 1) % rbgNum;
819 uint8_t startRbg = dciRbg.at (dciRbg.size () - 1);
820 std::vector <bool> rbgMapCopy = rbgMap;
821 while ((j < dciRbg.size ())&&(startRbg != rbgId))
822 {
823 if (rbgMapCopy.at (rbgId) == false)
824 {
825 rbgMapCopy.at (rbgId) = true;
826 dciRbg.at (j) = rbgId;
827 j++;
828 }
829 rbgId = (rbgId + 1) % rbgNum;
830 }
831 if (j == dciRbg.size ())
832 {
833 // find new RBGs -> update DCI map
834 uint32_t rbgMask = 0;
835 for (uint16_t k = 0; k < dciRbg.size (); k++)
836 {
837 rbgMask = rbgMask + (0x1 << dciRbg.at (k));
838 rbgAllocatedNum++;
839 }
840 dci.m_rbBitmap = rbgMask;
841 rbgMap = rbgMapCopy;
842 NS_LOG_INFO (this << " Move retx in RBGs " << dciRbg.size ());
843 }
844 else
845 {
846 // HARQ retx cannot be performed on this TTI -> store it
847 dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
848 NS_LOG_INFO (this << " No resource for this retx -> buffer it");
849 }
850 }
851 // retrieve RLC PDU list for retx TBsize and update DCI
853 std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
854 if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
855 {
856 NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << rnti);
857 }
858 for (uint8_t j = 0; j < nLayers; j++)
859 {
860 if (retx.at (j))
861 {
862 if (j >= dci.m_ndi.size ())
863 {
864 // for avoiding errors in MIMO transient phases
865 dci.m_ndi.push_back (0);
866 dci.m_rv.push_back (0);
867 dci.m_mcs.push_back (0);
868 dci.m_tbsSize.push_back (0);
869 NS_LOG_INFO (this << " layer " << (uint16_t)j << " no txed (MIMO transition)");
870 }
871 else
872 {
873 dci.m_ndi.at (j) = 0;
874 dci.m_rv.at (j)++;
875 (*itHarq).second.at (harqId).m_rv.at (j)++;
876 NS_LOG_INFO (this << " layer " << (uint16_t)j << " RV " << (uint16_t)dci.m_rv.at (j));
877 }
878 }
879 else
880 {
881 // empty TB of layer j
882 dci.m_ndi.at (j) = 0;
883 dci.m_rv.at (j) = 0;
884 dci.m_mcs.at (j) = 0;
885 dci.m_tbsSize.at (j) = 0;
886 NS_LOG_INFO (this << " layer " << (uint16_t)j << " no retx");
887 }
888 }
889 for (uint16_t k = 0; k < (*itRlcPdu).second.at (0).at (dci.m_harqProcess).size (); k++)
890 {
891 std::vector <struct RlcPduListElement_s> rlcPduListPerLc;
892 for (uint8_t j = 0; j < nLayers; j++)
893 {
894 if (retx.at (j))
895 {
896 if (j < dci.m_ndi.size ())
897 {
898 NS_LOG_INFO (" layer " << (uint16_t)j << " tb size " << dci.m_tbsSize.at (j));
899 rlcPduListPerLc.push_back ((*itRlcPdu).second.at (j).at (dci.m_harqProcess).at (k));
900 }
901 }
902 else
903 { // if no retx needed on layer j, push an RlcPduListElement_s object with m_size=0 to keep the size of rlcPduListPerLc vector = 2 in case of MIMO
904 NS_LOG_INFO (" layer " << (uint16_t)j << " tb size "<<dci.m_tbsSize.at (j));
905 RlcPduListElement_s emptyElement;
906 emptyElement.m_logicalChannelIdentity = (*itRlcPdu).second.at (j).at (dci.m_harqProcess).at (k).m_logicalChannelIdentity;
907 emptyElement.m_size = 0;
908 rlcPduListPerLc.push_back (emptyElement);
909 }
910 }
911
912 if (rlcPduListPerLc.size () > 0)
913 {
914 newEl.m_rlcPduList.push_back (rlcPduListPerLc);
915 }
916 }
917 newEl.m_rnti = rnti;
918 newEl.m_dci = dci;
919 (*itHarq).second.at (harqId).m_rv = dci.m_rv;
920 // refresh timer
921 std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (rnti);
922 if (itHarqTimer== m_dlHarqProcessesTimer.end ())
923 {
924 NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)rnti);
925 }
926 (*itHarqTimer).second.at (harqId) = 0;
927 ret.m_buildDataList.push_back (newEl);
928 rntiAllocated.insert (rnti);
929 }
930 else
931 {
932 // update HARQ process status
933 NS_LOG_INFO (this << " HARQ received ACK for UE " << m_dlInfoListBuffered.at (i).m_rnti);
934 std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (m_dlInfoListBuffered.at (i).m_rnti);
935 if (it == m_dlHarqProcessesStatus.end ())
936 {
937 NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << m_dlInfoListBuffered.at (i).m_rnti);
938 }
939 (*it).second.at (m_dlInfoListBuffered.at (i).m_harqProcessId) = 0;
940 std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (m_dlInfoListBuffered.at (i).m_rnti);
941 if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
942 {
943 NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
944 }
945 for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
946 {
947 (*itRlcPdu).second.at (k).at (m_dlInfoListBuffered.at (i).m_harqProcessId).clear ();
948 }
949 }
950 }
951 m_dlInfoListBuffered.clear ();
952 m_dlInfoListBuffered = dlInfoListUntxed;
953
954 if (rbgAllocatedNum == rbgNum)
955 {
956 // all the RBGs are already allocated -> exit
957 if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0))
958 {
960 }
961 return;
962 }
963
964
965 // update token pool, counter and bank size
966 std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itStats;
967 for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
968 {
969 if ( (*itStats).second.tokenGenerationRate / 1000 + (*itStats).second.tokenPoolSize > (*itStats).second.maxTokenPoolSize )
970 {
971 (*itStats).second.counter += (*itStats).second.tokenGenerationRate / 1000 - ( (*itStats).second.maxTokenPoolSize - (*itStats).second.tokenPoolSize );
972 (*itStats).second.tokenPoolSize = (*itStats).second.maxTokenPoolSize;
973 bankSize += (*itStats).second.tokenGenerationRate / 1000 - ( (*itStats).second.maxTokenPoolSize - (*itStats).second.tokenPoolSize );
974 }
975 else
976 {
977 (*itStats).second.tokenPoolSize += (*itStats).second.tokenGenerationRate / 1000;
978 }
979 }
980
981
982 // select UE with largest metric
983 std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator it;
984 std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itMax = m_flowStatsDl.end ();
985 double metricMax = 0.0;
986 bool firstRnti = true;
987 for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
988 {
989 std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
990 if ((itRnti != rntiAllocated.end ())||(!HarqProcessAvailability ((*it).first)))
991 {
992 // UE already allocated for HARQ or without HARQ process available -> drop it
993 if (itRnti != rntiAllocated.end ())
994 {
995 NS_LOG_DEBUG (this << " RNTI discared for HARQ tx" << (uint16_t)(*it).first);
996 }
997 if (!HarqProcessAvailability ((*it).first))
998 {
999 NS_LOG_DEBUG (this << " RNTI discared for HARQ id" << (uint16_t)(*it).first);
1000 }
1001 continue;
1002 }
1003
1004
1005 // check first the channel conditions for this UE, if CQI!=0
1006 std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1007 itCqi = m_a30CqiRxed.find ((*it).first);
1008 std::map <uint16_t,uint8_t>::iterator itTxMode;
1009 itTxMode = m_uesTxMode.find ((*it).first);
1010 if (itTxMode == m_uesTxMode.end ())
1011 {
1012 NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first);
1013 }
1014 int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1015
1016 uint8_t cqiSum = 0;
1017 for (int k = 0; k < rbgNum; k++)
1018 {
1019 for (uint8_t j = 0; j < nLayer; j++)
1020 {
1021 if (itCqi == m_a30CqiRxed.end ())
1022 {
1023 cqiSum += 1; // no info on this user -> lowest MCS
1024 }
1025 else
1026 {
1027 cqiSum += (*itCqi).second.m_higherLayerSelected.at (k).m_sbCqi.at(j);
1028 }
1029 }
1030 }
1031
1032 if (cqiSum == 0)
1033 {
1034 NS_LOG_INFO ("Skip this flow, CQI==0, rnti:"<<(*it).first);
1035 continue;
1036 }
1037
1038
1039 /*
1040 if (LcActivePerFlow ((*it).first) == 0)
1041 {
1042 continue;
1043 }
1044 */
1045
1046 double metric = ( ( (double)(*it).second.counter ) / ( (double)(*it).second.tokenGenerationRate ) );
1047
1048 if (firstRnti == true)
1049 {
1050 metricMax = metric;
1051 itMax = it;
1052 firstRnti = false;
1053 continue;
1054 }
1055 if (metric > metricMax)
1056 {
1057 metricMax = metric;
1058 itMax = it;
1059 }
1060 } // end for m_flowStatsDl
1061
1062 if (itMax == m_flowStatsDl.end ())
1063 {
1064 // all UEs are allocated RBG or all UEs already allocated for HARQ or without HARQ process available
1065 return;
1066 }
1067 else
1068 {
1069 // assign all RBGs to this UE
1070 std::vector <uint16_t> tempMap;
1071 for (int i = 0; i < rbgNum; i++)
1072 {
1073 if ( rbgMap.at (i) == true) // this RBG is allocated in RACH procedure
1074 continue;
1075
1076 if ((m_ffrSapProvider->IsDlRbgAvailableForUe (i, (*itMax).first)) == false)
1077 continue;
1078
1079 tempMap.push_back (i);
1080 rbgMap.at (i) = true;
1081 }
1082 if (tempMap.size() > 0)
1083 {
1084 allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax).first, tempMap));
1085 }
1086 }
1087
1088
1089
1090 // generate the transmission opportunities by grouping the RBGs of the same RNTI and
1091 // creating the correspondent DCIs
1092 std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
1093 while (itMap != allocationMap.end ())
1094 {
1095 // create new BuildDataListElement_s for this LC
1097 newEl.m_rnti = (*itMap).first;
1098 // create the DlDciListElement_s
1099 DlDciListElement_s newDci;
1100 newDci.m_rnti = (*itMap).first;
1101 newDci.m_harqProcess = UpdateHarqProcessId ((*itMap).first);
1102
1103 uint16_t lcActives = LcActivePerFlow ((*itMap).first);
1104 NS_LOG_INFO (this << "Allocate user " << newEl.m_rnti << " rbg " << lcActives);
1105 if (lcActives == 0)
1106 {
1107 // Set to max value, to avoid divide by 0 below
1108 lcActives = (uint16_t)65535; // UINT16_MAX;
1109 }
1110 uint16_t RgbPerRnti = (*itMap).second.size ();
1111 std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1112 itCqi = m_a30CqiRxed.find ((*itMap).first);
1113 std::map <uint16_t,uint8_t>::iterator itTxMode;
1114 itTxMode = m_uesTxMode.find ((*itMap).first);
1115 if (itTxMode == m_uesTxMode.end ())
1116 {
1117 NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
1118 }
1119 int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1120 std::vector <uint8_t> worstCqi (2, 15);
1121 if (itCqi != m_a30CqiRxed.end ())
1122 {
1123 for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1124 {
1125 if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
1126 {
1127 for (uint8_t j = 0; j < nLayer; j++)
1128 {
1129 if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
1130 {
1131 if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
1132 {
1133 worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
1134 }
1135 }
1136 else
1137 {
1138 // no CQI for this layer of this suband -> worst one
1139 worstCqi.at (j) = 1;
1140 }
1141 }
1142 }
1143 else
1144 {
1145 for (uint8_t j = 0; j < nLayer; j++)
1146 {
1147 worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1148 }
1149 }
1150 }
1151 }
1152 else
1153 {
1154 for (uint8_t j = 0; j < nLayer; j++)
1155 {
1156 worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1157 }
1158 }
1159 uint32_t bytesTxed = 0;
1160 for (uint8_t j = 0; j < nLayer; j++)
1161 {
1162 newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
1163 int tbSize = (m_amc->GetDlTbSizeFromMcs (newDci.m_mcs.at (j), RgbPerRnti * rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213)
1164 newDci.m_tbsSize.push_back (tbSize);
1165 bytesTxed += tbSize;
1166 }
1167
1168 newDci.m_resAlloc = 0; // only allocation type 0 at this stage
1169 newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
1170 uint32_t rbgMask = 0;
1171 for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1172 {
1173 rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
1174 NS_LOG_INFO (this << " Allocated RBG " << (*itMap).second.at (k));
1175 }
1176 newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1177
1178 // create the rlc PDUs -> equally divide resources among actives LCs
1179 std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
1180 for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
1181 {
1182 if (((*itBufReq).first.m_rnti == (*itMap).first)
1183 && (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
1184 || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
1185 || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
1186 {
1187 std::vector <struct RlcPduListElement_s> newRlcPduLe;
1188 for (uint8_t j = 0; j < nLayer; j++)
1189 {
1190 RlcPduListElement_s newRlcEl;
1191 newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
1192 newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
1193 NS_LOG_INFO (this << " LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << newRlcEl.m_size << " layer " << (uint16_t)j);
1194 newRlcPduLe.push_back (newRlcEl);
1195 UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
1196 if (m_harqOn == true)
1197 {
1198 // store RLC PDU list for HARQ
1199 std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*itMap).first);
1200 if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1201 {
1202 NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*itMap).first);
1203 }
1204 (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1205 }
1206 }
1207 newEl.m_rlcPduList.push_back (newRlcPduLe);
1208 }
1209 if ((*itBufReq).first.m_rnti > (*itMap).first)
1210 {
1211 break;
1212 }
1213 }
1214 for (uint8_t j = 0; j < nLayer; j++)
1215 {
1216 newDci.m_ndi.push_back (1);
1217 newDci.m_rv.push_back (0);
1218 }
1219
1220 newDci.m_tpc = m_ffrSapProvider->GetTpc ((*itMap).first);
1221
1222 newEl.m_dci = newDci;
1223
1224 if (m_harqOn == true)
1225 {
1226 // store DCI for HARQ
1227 std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1228 if (itDci == m_dlHarqProcessesDciBuffer.end ())
1229 {
1230 NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1231 }
1232 (*itDci).second.at (newDci.m_harqProcess) = newDci;
1233 // refresh timer
1234 std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1235 if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1236 {
1237 NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1238 }
1239 (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1240 }
1241
1242
1243 // update UE stats
1244 if ( bytesTxed <= (*itMax).second.tokenPoolSize )
1245 {
1246 (*itMax).second.tokenPoolSize -= bytesTxed;
1247 }
1248 else
1249 {
1250 (*itMax).second.counter = (*itMax).second.counter - ( bytesTxed - (*itMax).second.tokenPoolSize );
1251 (*itMax).second.tokenPoolSize = 0;
1252 if (bankSize <= ( bytesTxed - (*itMax).second.tokenPoolSize ))
1253 bankSize = 0;
1254 else
1255 bankSize = bankSize - ( bytesTxed - (*itMax).second.tokenPoolSize );
1256 }
1257
1258
1259 // ...more parameters -> ignored in this version
1260
1261 ret.m_buildDataList.push_back (newEl);
1262
1263 itMap++;
1264 } // end while allocation
1265 ret.m_nrOfPdcchOfdmSymbols = 1;
1266
1268
1269
1270 return;
1271}
1272
1273void
1275{
1276 NS_LOG_FUNCTION (this);
1277
1278 m_rachList = params.m_rachList;
1279
1280 return;
1281}
1282
1283void
1285{
1286 NS_LOG_FUNCTION (this);
1288
1289 for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1290 {
1291 if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1292 {
1293 NS_LOG_LOGIC ("wideband CQI " << (uint32_t) params.m_cqiList.at (i).m_wbCqi.at (0) << " reported");
1294 std::map <uint16_t,uint8_t>::iterator it;
1295 uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1296 it = m_p10CqiRxed.find (rnti);
1297 if (it == m_p10CqiRxed.end ())
1298 {
1299 // create the new entry
1300 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)
1301 // generate correspondent timer
1302 m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1303 }
1304 else
1305 {
1306 // update the CQI value and refresh correspondent timer
1307 (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1308 // update correspondent timer
1309 std::map <uint16_t,uint32_t>::iterator itTimers;
1310 itTimers = m_p10CqiTimers.find (rnti);
1311 (*itTimers).second = m_cqiTimersThreshold;
1312 }
1313 }
1314 else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1315 {
1316 // subband CQI reporting high layer configured
1317 std::map <uint16_t,SbMeasResult_s>::iterator it;
1318 uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1319 it = m_a30CqiRxed.find (rnti);
1320 if (it == m_a30CqiRxed.end ())
1321 {
1322 // create the new entry
1323 m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
1324 m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1325 }
1326 else
1327 {
1328 // update the CQI value and refresh correspondent timer
1329 (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
1330 std::map <uint16_t,uint32_t>::iterator itTimers;
1331 itTimers = m_a30CqiTimers.find (rnti);
1332 (*itTimers).second = m_cqiTimersThreshold;
1333 }
1334 }
1335 else
1336 {
1337 NS_LOG_ERROR (this << " CQI type unknown");
1338 }
1339 }
1340
1341 return;
1342}
1343
1344
1345double
1346TdTbfqFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
1347{
1348 std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
1349 if (itCqi == m_ueCqi.end ())
1350 {
1351 // no cqi info about this UE
1352 return (NO_SINR);
1353
1354 }
1355 else
1356 {
1357 // take the average SINR value among the available
1358 double sinrSum = 0;
1359 unsigned int sinrNum = 0;
1360 for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1361 {
1362 double sinr = (*itCqi).second.at (i);
1363 if (sinr != NO_SINR)
1364 {
1365 sinrSum += sinr;
1366 sinrNum++;
1367 }
1368 }
1369 double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
1370 // store the value
1371 (*itCqi).second.at (rb) = estimatedSinr;
1372 return (estimatedSinr);
1373 }
1374}
1375
1376void
1378{
1379 NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1380
1383
1384 // Generate RBs map
1386 std::vector <bool> rbMap;
1387 uint16_t rbAllocatedNum = 0;
1388 std::set <uint16_t> rntiAllocated;
1389 std::vector <uint16_t> rbgAllocationMap;
1390 // update with RACH allocation map
1391 rbgAllocationMap = m_rachAllocationMap;
1392 //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1393 m_rachAllocationMap.clear ();
1395
1396 rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1397
1399
1400 for (std::vector<bool>::iterator it = rbMap.begin (); it != rbMap.end (); it++)
1401 {
1402 if ((*it) == true )
1403 {
1404 rbAllocatedNum++;
1405 }
1406 }
1407
1408 uint8_t minContinuousUlBandwidth = m_ffrSapProvider->GetMinContinuousUlBandwidth ();
1409 uint8_t ffrUlBandwidth = m_cschedCellConfig.m_ulBandwidth - rbAllocatedNum;
1410
1411 // remove RACH allocation
1412 for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1413 {
1414 if (rbgAllocationMap.at (i) != 0)
1415 {
1416 rbMap.at (i) = true;
1417 NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1418 }
1419 }
1420
1421
1422 if (m_harqOn == true)
1423 {
1424 // Process UL HARQ feedback
1425 for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1426 {
1427 if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1428 {
1429 // retx correspondent block: retrieve the UL-DCI
1430 uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1431 std::map <uint16_t, uint8_t>::iterator itProcId = m_ulHarqCurrentProcessId.find (rnti);
1432 if (itProcId == m_ulHarqCurrentProcessId.end ())
1433 {
1434 NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1435 }
1436 uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1437 NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId << " i " << i << " size " << params.m_ulInfoList.size ());
1438 std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1439 if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1440 {
1441 NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1442 continue;
1443 }
1444 UlDciListElement_s dci = (*itHarq).second.at (harqId);
1445 std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1446 if (itStat == m_ulHarqProcessesStatus.end ())
1447 {
1448 NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1449 }
1450 if ((*itStat).second.at (harqId) >= 3)
1451 {
1452 NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1453 continue;
1454 }
1455 bool free = true;
1456 for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1457 {
1458 if (rbMap.at (j) == true)
1459 {
1460 free = false;
1461 NS_LOG_INFO (this << " BUSY " << j);
1462 }
1463 }
1464 if (free)
1465 {
1466 // retx on the same RBs
1467 for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1468 {
1469 rbMap.at (j) = true;
1470 rbgAllocationMap.at (j) = dci.m_rnti;
1471 NS_LOG_INFO ("\tRB " << j);
1472 rbAllocatedNum++;
1473 }
1474 NS_LOG_INFO (this << " Send retx in the same RBs " << (uint16_t)dci.m_rbStart << " to " << dci.m_rbStart + dci.m_rbLen << " RV " << (*itStat).second.at (harqId) + 1);
1475 }
1476 else
1477 {
1478 NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1479 continue;
1480 }
1481 dci.m_ndi = 0;
1482 // Update HARQ buffers with new HarqId
1483 (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1484 (*itStat).second.at (harqId) = 0;
1485 (*itHarq).second.at ((*itProcId).second) = dci;
1486 ret.m_dciList.push_back (dci);
1487 rntiAllocated.insert (dci.m_rnti);
1488 }
1489 else
1490 {
1491 NS_LOG_INFO (this << " HARQ-ACK feedback from RNTI " << params.m_ulInfoList.at (i).m_rnti);
1492 }
1493 }
1494 }
1495
1496 std::map <uint16_t,uint32_t>::iterator it;
1497 int nflows = 0;
1498
1499 for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1500 {
1501 std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1502 // select UEs with queues not empty and not yet allocated for HARQ
1503 if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1504 {
1505 nflows++;
1506 }
1507 }
1508
1509 if (nflows == 0)
1510 {
1511 if (ret.m_dciList.size () > 0)
1512 {
1513 m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1515 }
1516
1517 return; // no flows to be scheduled
1518 }
1519
1520
1521 // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1522 uint16_t tempRbPerFlow = (ffrUlBandwidth) / (nflows + rntiAllocated.size ());
1523 uint16_t rbPerFlow = (minContinuousUlBandwidth < tempRbPerFlow) ? minContinuousUlBandwidth : tempRbPerFlow;
1524
1525 if (rbPerFlow < 3)
1526 {
1527 rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
1528 }
1529 int rbAllocated = 0;
1530
1531 std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itStats;
1532 if (m_nextRntiUl != 0)
1533 {
1534 for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1535 {
1536 if ((*it).first == m_nextRntiUl)
1537 {
1538 break;
1539 }
1540 }
1541 if (it == m_ceBsrRxed.end ())
1542 {
1543 NS_LOG_ERROR (this << " no user found");
1544 }
1545 }
1546 else
1547 {
1548 it = m_ceBsrRxed.begin ();
1549 m_nextRntiUl = (*it).first;
1550 }
1551 do
1552 {
1553 std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1554 if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
1555 {
1556 // UE already allocated for UL-HARQ -> skip it
1557 NS_LOG_DEBUG (this << " UE already allocated in HARQ -> discared, RNTI " << (*it).first);
1558 it++;
1559 if (it == m_ceBsrRxed.end ())
1560 {
1561 // restart from the first
1562 it = m_ceBsrRxed.begin ();
1563 }
1564 continue;
1565 }
1566 if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1567 {
1568 // limit to physical resources last resource assignment
1569 rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1570 // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1571 if (rbPerFlow < 3)
1572 {
1573 // terminate allocation
1574 rbPerFlow = 0;
1575 }
1576 }
1577
1578 rbAllocated = 0;
1579 UlDciListElement_s uldci;
1580 uldci.m_rnti = (*it).first;
1581 uldci.m_rbLen = rbPerFlow;
1582 bool allocated = false;
1583 NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1584 while ((!allocated)&&((rbAllocated + rbPerFlow - m_cschedCellConfig.m_ulBandwidth) < 1) && (rbPerFlow != 0))
1585 {
1586 // check availability
1587 bool free = true;
1588 for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1589 {
1590 if (rbMap.at (j) == true)
1591 {
1592 free = false;
1593 break;
1594 }
1595 if ((m_ffrSapProvider->IsUlRbgAvailableForUe (j, (*it).first)) == false)
1596 {
1597 free = false;
1598 break;
1599 }
1600 }
1601 if (free)
1602 {
1603 NS_LOG_INFO (this << "RNTI: "<< (*it).first<< " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1604 uldci.m_rbStart = rbAllocated;
1605
1606 for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1607 {
1608 rbMap.at (j) = true;
1609 // store info on allocation for managing ul-cqi interpretation
1610 rbgAllocationMap.at (j) = (*it).first;
1611 }
1612 rbAllocated += rbPerFlow;
1613 allocated = true;
1614 break;
1615 }
1616 rbAllocated++;
1617 if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1618 {
1619 // limit to physical resources last resource assignment
1620 rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1621 // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1622 if (rbPerFlow < 3)
1623 {
1624 // terminate allocation
1625 rbPerFlow = 0;
1626 }
1627 }
1628 }
1629 if (!allocated)
1630 {
1631 // unable to allocate new resource: finish scheduling
1632// m_nextRntiUl = (*it).first;
1633// if (ret.m_dciList.size () > 0)
1634// {
1635// m_schedSapUser->SchedUlConfigInd (ret);
1636// }
1637// m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1638// return;
1639 break;
1640 }
1641
1642
1643
1644 std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1645 int cqi = 0;
1646 if (itCqi == m_ueCqi.end ())
1647 {
1648 // no cqi info about this UE
1649 uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1650 }
1651 else
1652 {
1653 // take the lowest CQI value (worst RB)
1654 NS_ABORT_MSG_IF ((*itCqi).second.size() == 0, "CQI of RNTI = " << (*it).first << " has expired");
1655 double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1656 if (minSinr == NO_SINR)
1657 {
1658 minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
1659 }
1660 for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1661 {
1662 double sinr = (*itCqi).second.at (i);
1663 if (sinr == NO_SINR)
1664 {
1665 sinr = EstimateUlSinr ((*it).first, i);
1666 }
1667 if (sinr < minSinr)
1668 {
1669 minSinr = sinr;
1670 }
1671 }
1672
1673 // translate SINR -> cqi: WILD ACK: same as DL
1674 double s = log2 ( 1 + (
1675 std::pow (10, minSinr / 10 ) /
1676 ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1677 cqi = m_amc->GetCqiFromSpectralEfficiency (s);
1678 if (cqi == 0)
1679 {
1680 it++;
1681 if (it == m_ceBsrRxed.end ())
1682 {
1683 // restart from the first
1684 it = m_ceBsrRxed.begin ();
1685 }
1686 NS_LOG_DEBUG (this << " UE discarded for CQI = 0, RNTI " << uldci.m_rnti);
1687 // remove UE from allocation map
1688 for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1689 {
1690 rbgAllocationMap.at (i) = 0;
1691 }
1692 continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1693 }
1694 uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1695 }
1696
1697 uldci.m_tbSize = (m_amc->GetUlTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
1698 UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1699 uldci.m_ndi = 1;
1700 uldci.m_cceIndex = 0;
1701 uldci.m_aggrLevel = 1;
1702 uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1703 uldci.m_hopping = false;
1704 uldci.m_n2Dmrs = 0;
1705 uldci.m_tpc = 0; // no power control
1706 uldci.m_cqiRequest = false; // only period CQI at this stage
1707 uldci.m_ulIndex = 0; // TDD parameter
1708 uldci.m_dai = 1; // TDD parameter
1709 uldci.m_freqHopping = 0;
1710 uldci.m_pdcchPowerOffset = 0; // not used
1711 ret.m_dciList.push_back (uldci);
1712 // store DCI for HARQ_PERIOD
1713 uint8_t harqId = 0;
1714 if (m_harqOn == true)
1715 {
1716 std::map <uint16_t, uint8_t>::iterator itProcId;
1717 itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
1718 if (itProcId == m_ulHarqCurrentProcessId.end ())
1719 {
1720 NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
1721 }
1722 harqId = (*itProcId).second;
1723 std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
1724 if (itDci == m_ulHarqProcessesDciBuffer.end ())
1725 {
1726 NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
1727 }
1728 (*itDci).second.at (harqId) = uldci;
1729 // Update HARQ process status (RV 0)
1730 std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (uldci.m_rnti);
1731 if (itStat == m_ulHarqProcessesStatus.end ())
1732 {
1733 NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << uldci.m_rnti);
1734 }
1735 (*itStat).second.at (harqId) = 0;
1736 }
1737
1738 NS_LOG_INFO (this << " UE Allocation RNTI " << (*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 << " harqId " << (uint16_t)harqId);
1739
1740 it++;
1741 if (it == m_ceBsrRxed.end ())
1742 {
1743 // restart from the first
1744 it = m_ceBsrRxed.begin ();
1745 }
1746 if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
1747 {
1748 // Stop allocation: no more PRBs
1749 m_nextRntiUl = (*it).first;
1750 break;
1751 }
1752 }
1753 while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
1754
1755
1756 m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1758
1759 return;
1760}
1761
1762void
1764{
1765 NS_LOG_FUNCTION (this);
1766 return;
1767}
1768
1769void
1771{
1772 NS_LOG_FUNCTION (this);
1773 return;
1774}
1775
1776void
1778{
1779 NS_LOG_FUNCTION (this);
1780
1781 std::map <uint16_t,uint32_t>::iterator it;
1782
1783 for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1784 {
1785 if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1786 {
1787 // buffer status report
1788 // note that this scheduler does not differentiate the
1789 // allocation according to which LCGs have more/less bytes
1790 // to send.
1791 // Hence the BSR of different LCGs are just summed up to get
1792 // a total queue size that is used for allocation purposes.
1793
1794 uint32_t buffer = 0;
1795 for (uint8_t lcg = 0; lcg < 4; ++lcg)
1796 {
1797 uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
1798 buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1799 }
1800
1801 uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1802 NS_LOG_LOGIC (this << "RNTI=" << rnti << " buffer=" << buffer);
1803 it = m_ceBsrRxed.find (rnti);
1804 if (it == m_ceBsrRxed.end ())
1805 {
1806 // create the new entry
1807 m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1808 }
1809 else
1810 {
1811 // update the buffer size value
1812 (*it).second = buffer;
1813 }
1814 }
1815 }
1816
1817 return;
1818}
1819
1820void
1822{
1823 NS_LOG_FUNCTION (this);
1824// retrieve the allocation for this subframe
1825 switch (m_ulCqiFilter)
1826 {
1828 {
1829 // filter all the CQIs that are not SRS based
1830 if (params.m_ulCqi.m_type != UlCqi_s::SRS)
1831 {
1832 return;
1833 }
1834 }
1835 break;
1837 {
1838 // filter all the CQIs that are not SRS based
1839 if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
1840 {
1841 return;
1842 }
1843 }
1844 break;
1845 default:
1846 NS_FATAL_ERROR ("Unknown UL CQI type");
1847 }
1848
1849 switch (params.m_ulCqi.m_type)
1850 {
1851 case UlCqi_s::PUSCH:
1852 {
1853 std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1854 std::map <uint16_t, std::vector <double> >::iterator itCqi;
1855 NS_LOG_DEBUG (this << " Collect PUSCH CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
1856 itMap = m_allocationMaps.find (params.m_sfnSf);
1857 if (itMap == m_allocationMaps.end ())
1858 {
1859 return;
1860 }
1861 for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1862 {
1863 // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1864 double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1865 itCqi = m_ueCqi.find ((*itMap).second.at (i));
1866 if (itCqi == m_ueCqi.end ())
1867 {
1868 // create a new entry
1869 std::vector <double> newCqi;
1870 for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1871 {
1872 if (i == j)
1873 {
1874 newCqi.push_back (sinr);
1875 }
1876 else
1877 {
1878 // initialize with NO_SINR value.
1879 newCqi.push_back (NO_SINR);
1880 }
1881
1882 }
1883 m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1884 // generate correspondent timer
1885 m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1886 }
1887 else
1888 {
1889 // update the value
1890 (*itCqi).second.at (i) = sinr;
1891 NS_LOG_DEBUG (this << " RNTI " << (*itMap).second.at (i) << " RB " << i << " SINR " << sinr);
1892 // update correspondent timer
1893 std::map <uint16_t, uint32_t>::iterator itTimers;
1894 itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1895 (*itTimers).second = m_cqiTimersThreshold;
1896
1897 }
1898
1899 }
1900 // remove obsolete info on allocation
1901 m_allocationMaps.erase (itMap);
1902 }
1903 break;
1904 case UlCqi_s::SRS:
1905 {
1906 // get the RNTI from vendor specific parameters
1907 uint16_t rnti = 0;
1908 NS_ASSERT (params.m_vendorSpecificList.size () > 0);
1909 for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
1910 {
1911 if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
1912 {
1913 Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
1914 rnti = vsp->GetRnti ();
1915 }
1916 }
1917 std::map <uint16_t, std::vector <double> >::iterator itCqi;
1918 itCqi = m_ueCqi.find (rnti);
1919 if (itCqi == m_ueCqi.end ())
1920 {
1921 // create a new entry
1922 std::vector <double> newCqi;
1923 for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1924 {
1925 double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1926 newCqi.push_back (sinr);
1927 NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
1928
1929 }
1930 m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
1931 // generate correspondent timer
1932 m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1933 }
1934 else
1935 {
1936 // update the values
1937 for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1938 {
1939 double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1940 (*itCqi).second.at (j) = sinr;
1941 NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
1942 }
1943 // update correspondent timer
1944 std::map <uint16_t, uint32_t>::iterator itTimers;
1945 itTimers = m_ueCqiTimers.find (rnti);
1946 (*itTimers).second = m_cqiTimersThreshold;
1947
1948 }
1949
1950
1951 }
1952 break;
1953 case UlCqi_s::PUCCH_1:
1954 case UlCqi_s::PUCCH_2:
1955 case UlCqi_s::PRACH:
1956 {
1957 NS_FATAL_ERROR ("TdTbfqFfMacScheduler supports only PUSCH and SRS UL-CQIs");
1958 }
1959 break;
1960 default:
1961 NS_FATAL_ERROR ("Unknown type of UL-CQI");
1962 }
1963 return;
1964}
1965
1966void
1968{
1969 // refresh DL CQI P01 Map
1970 std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1971 while (itP10 != m_p10CqiTimers.end ())
1972 {
1973 NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1974 if ((*itP10).second == 0)
1975 {
1976 // delete correspondent entries
1977 std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1978 NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1979 NS_LOG_INFO (this << " P10-CQI expired for user " << (*itP10).first);
1980 m_p10CqiRxed.erase (itMap);
1981 std::map <uint16_t,uint32_t>::iterator temp = itP10;
1982 itP10++;
1983 m_p10CqiTimers.erase (temp);
1984 }
1985 else
1986 {
1987 (*itP10).second--;
1988 itP10++;
1989 }
1990 }
1991
1992 // refresh DL CQI A30 Map
1993 std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
1994 while (itA30 != m_a30CqiTimers.end ())
1995 {
1996 NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1997 if ((*itA30).second == 0)
1998 {
1999 // delete correspondent entries
2000 std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
2001 NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
2002 NS_LOG_INFO (this << " A30-CQI expired for user " << (*itA30).first);
2003 m_a30CqiRxed.erase (itMap);
2004 std::map <uint16_t,uint32_t>::iterator temp = itA30;
2005 itA30++;
2006 m_a30CqiTimers.erase (temp);
2007 }
2008 else
2009 {
2010 (*itA30).second--;
2011 itA30++;
2012 }
2013 }
2014
2015 return;
2016}
2017
2018
2019void
2021{
2022 // refresh UL CQI Map
2023 std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
2024 while (itUl != m_ueCqiTimers.end ())
2025 {
2026 NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2027 if ((*itUl).second == 0)
2028 {
2029 // delete correspondent entries
2030 std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
2031 NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
2032 NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
2033 (*itMap).second.clear ();
2034 m_ueCqi.erase (itMap);
2035 std::map <uint16_t,uint32_t>::iterator temp = itUl;
2036 itUl++;
2037 m_ueCqiTimers.erase (temp);
2038 }
2039 else
2040 {
2041 (*itUl).second--;
2042 itUl++;
2043 }
2044 }
2045
2046 return;
2047}
2048
2049void
2050TdTbfqFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
2051{
2052 std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
2053 LteFlowId_t flow (rnti, lcid);
2054 it = m_rlcBufferReq.find (flow);
2055 if (it != m_rlcBufferReq.end ())
2056 {
2057 NS_LOG_INFO (this << " UE " << rnti << " LC " << (uint16_t)lcid << " txqueue " << (*it).second.m_rlcTransmissionQueueSize << " retxqueue " << (*it).second.m_rlcRetransmissionQueueSize << " status " << (*it).second.m_rlcStatusPduSize << " decrease " << size);
2058 // Update queues: RLC tx order Status, ReTx, Tx
2059 // Update status queue
2060 if (((*it).second.m_rlcStatusPduSize > 0) && (size >= (*it).second.m_rlcStatusPduSize))
2061 {
2062 (*it).second.m_rlcStatusPduSize = 0;
2063 }
2064 else if (((*it).second.m_rlcRetransmissionQueueSize > 0) && (size >= (*it).second.m_rlcRetransmissionQueueSize))
2065 {
2066 (*it).second.m_rlcRetransmissionQueueSize = 0;
2067 }
2068 else if ((*it).second.m_rlcTransmissionQueueSize > 0)
2069 {
2070 uint32_t rlcOverhead;
2071 if (lcid == 1)
2072 {
2073 // for SRB1 (using RLC AM) it's better to
2074 // overestimate RLC overhead rather than
2075 // underestimate it and risk unneeded
2076 // segmentation which increases delay
2077 rlcOverhead = 4;
2078 }
2079 else
2080 {
2081 // minimum RLC overhead due to header
2082 rlcOverhead = 2;
2083 }
2084 // update transmission queue
2085 if ((*it).second.m_rlcTransmissionQueueSize <= size - rlcOverhead)
2086 {
2087 (*it).second.m_rlcTransmissionQueueSize = 0;
2088 }
2089 else
2090 {
2091 (*it).second.m_rlcTransmissionQueueSize -= size - rlcOverhead;
2092 }
2093 }
2094 }
2095 else
2096 {
2097 NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
2098 }
2099}
2100
2101void
2103{
2104
2105 size = size - 2; // remove the minimum RLC overhead
2106 std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
2107 if (it != m_ceBsrRxed.end ())
2108 {
2109 NS_LOG_INFO (this << " UE " << rnti << " size " << size << " BSR " << (*it).second);
2110 if ((*it).second >= size)
2111 {
2112 (*it).second -= size;
2113 }
2114 else
2115 {
2116 (*it).second = 0;
2117 }
2118 }
2119 else
2120 {
2121 NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
2122 }
2123
2124}
2125
2126void
2128{
2129 NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
2131 params.m_rnti = rnti;
2132 params.m_transmissionMode = txMode;
2134}
2135
2136
2137}
AttributeValue implementation for Boolean.
Definition: boolean.h:37
static uint32_t BsrId2BufferSize(uint8_t val)
Convert BSR ID to buffer size.
Definition: lte-common.cc:184
Provides the CSCHED SAP.
FfMacCschedSapUser class.
virtual void CschedUeConfigUpdateInd(const struct CschedUeConfigUpdateIndParameters &params)=0
CSCHED_UE_UPDATE_IND.
virtual void CschedUeConfigCnf(const struct CschedUeConfigCnfParameters &params)=0
CSCHED_UE_CONFIG_CNF.
Provides the SCHED SAP.
FfMacSchedSapUser class.
virtual void SchedUlConfigInd(const struct SchedUlConfigIndParameters &params)=0
SCHED_UL_CONFIG_IND.
virtual void SchedDlConfigInd(const struct SchedDlConfigIndParameters &params)=0
SCHED_DL_CONFIG_IND.
This abstract base class identifies the interface by means of which the helper object can plug on the...
UlCqiFilter_t m_ulCqiFilter
UL CQI filter.
Hold a signed integer type.
Definition: integer.h:44
static double fpS11dot3toDouble(uint16_t val)
Convert from fixed point S11.3 notation to double.
Definition: lte-common.cc:155
Service Access Point (SAP) offered by the Frequency Reuse algorithm instance to the MAC Scheduler ins...
Definition: lte-ffr-sap.h:40
virtual uint8_t GetTpc(uint16_t rnti)=0
GetTpc.
virtual void ReportUlCqiInfo(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)=0
ReportUlCqiInfo.
virtual std::vector< bool > GetAvailableUlRbg()=0
Get vector of available RB in UL for this Cell.
virtual bool IsUlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in UL.
virtual std::vector< bool > GetAvailableDlRbg()=0
Get vector of available RBG in DL for this Cell.
virtual uint16_t GetMinContinuousUlBandwidth()=0
Get the minimum continuous Ul bandwidth.
virtual bool IsDlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in DL.
virtual void ReportDlCqiInfo(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)=0
ReportDlCqiInfo.
Service Access Point (SAP) offered by the eNodeB RRC instance to the Frequency Reuse algorithm instan...
Definition: lte-ffr-sap.h:139
Template for the implementation of the LteFfrSapUser as a member of an owner class of type C to which...
Definition: lte-ffr-sap.h:256
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Implements the SCHED SAP and CSCHED SAP for a Time Domain Token Bank Fair Queue scheduler.
uint16_t m_nextRntiUl
RNTI of the next user to be served next scheduling in UL.
void DoSchedDlRachInfoReq(const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters &params)
Sched DL RACH info request.
void DoSchedDlCqiInfoReq(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)
Sched DL CQI info request.
void DoSchedUlNoiseInterferenceReq(const struct FfMacSchedSapProvider::SchedUlNoiseInterferenceReqParameters &params)
Sched UL noise interference request.
void DoSchedDlMacBufferReq(const struct FfMacSchedSapProvider::SchedDlMacBufferReqParameters &params)
Sched DL MAC buffer request.
std::map< uint16_t, DlHarqProcessesTimer_t > m_dlHarqProcessesTimer
DL HARQ process timer.
void UpdateDlRlcBufferInfo(uint16_t rnti, uint8_t lcid, uint16_t size)
Update DL RLC buffer info function.
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
void UpdateUlRlcBufferInfo(uint16_t rnti, uint16_t size)
Update UL RLC buffer info function.
virtual void DoDispose(void)
Destructor implementation.
FfMacSchedSapProvider * m_schedSapProvider
Sched SAP provider.
std::map< uint16_t, UlHarqProcessesDciBuffer_t > m_ulHarqProcessesDciBuffer
UL HARQ process DCI buffer.
FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig
CSched cell config.
virtual void SetFfMacCschedSapUser(FfMacCschedSapUser *s)
set the user part of the FfMacCschedSap that this Scheduler will interact with.
FfMacSchedSapUser * m_schedSapUser
A=Sched SAP user.
void DoSchedDlPagingBufferReq(const struct FfMacSchedSapProvider::SchedDlPagingBufferReqParameters &params)
Sched DL paging buffer request.
unsigned int LcActivePerFlow(uint16_t rnti)
LC active flow size.
std::map< uint16_t, DlHarqProcessesDciBuffer_t > m_dlHarqProcessesDciBuffer
DL HARQ process DCI buffer.
virtual FfMacCschedSapProvider * GetFfMacCschedSapProvider()
std::map< uint16_t, DlHarqRlcPduListBuffer_t > m_dlHarqProcessesRlcPduListBuffer
DL HARQ process RLC PDU list buffer.
uint32_t m_creditLimit
flow credit limit (byte)
uint8_t UpdateHarqProcessId(uint16_t rnti)
Update and return a new process Id for the RNTI specified.
void DoCschedLcReleaseReq(const struct FfMacCschedSapProvider::CschedLcReleaseReqParameters &params)
CSched LC release request.
std::vector< uint16_t > m_rachAllocationMap
RACH allocation map.
LteFfrSapUser * m_ffrSapUser
FFR SAP user.
int GetRbgSize(int dlbandwidth)
Get RBG size.
std::map< uint16_t, uint8_t > m_ulHarqCurrentProcessId
UL HARQ current process ID.
void DoSchedDlRlcBufferReq(const struct FfMacSchedSapProvider::SchedDlRlcBufferReqParameters &params)
Sched DL RLC buffer request.
uint8_t HarqProcessAvailability(uint16_t rnti)
Return the availability of free process for the RNTI specified.
void DoSchedUlCqiInfoReq(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)
Sched UL CQI info request.
uint8_t m_ulGrantMcs
MCS for UL grant (default 0)
uint32_t m_creditableThreshold
threshold of flow credit
static TypeId GetTypeId(void)
Get the type ID.
std::map< uint16_t, uint32_t > m_p10CqiTimers
Map of UE's timers on DL CQI P01 received.
std::map< uint16_t, tdtbfqsFlowPerf_t > m_flowStatsUl
Map of UE statistics (per RNTI basis)
std::map< uint16_t, uint8_t > m_p10CqiRxed
Map of UE's DL CQI P01 received.
void TransmissionModeConfigurationUpdate(uint16_t rnti, uint8_t txMode)
Transmission mde configuration update function.
friend class MemberCschedSapProvider< TdTbfqFfMacScheduler >
allow MemberCschedSapProvider<TdTbfqFfMacScheduler> class friend access
std::map< LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters > m_rlcBufferReq
Vectors of UE's LC info.
FfMacCschedSapProvider * m_cschedSapProvider
CSched SAP provider.
void DoSchedUlTriggerReq(const struct FfMacSchedSapProvider::SchedUlTriggerReqParameters &params)
Sched UL trigger request.
void RefreshUlCqiMaps(void)
Refresh UL CQI maps function.
int m_debtLimit
flow debt limit (byte)
std::map< uint16_t, uint8_t > m_uesTxMode
txMode of the UEs
std::map< uint16_t, uint32_t > m_a30CqiTimers
Map of UE's timers on DL CQI A30 received.
double EstimateUlSinr(uint16_t rnti, uint16_t rb)
Estimate UL SINR function.
void DoCschedUeReleaseReq(const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters &params)
CSched UE release request.
void DoCschedLcConfigReq(const struct FfMacCschedSapProvider::CschedLcConfigReqParameters &params)
CSched LC config request.
void DoSchedUlSrInfoReq(const struct FfMacSchedSapProvider::SchedUlSrInfoReqParameters &params)
Sched UL SR info request.
LteFfrSapProvider * m_ffrSapProvider
FFR SAP provider.
virtual void SetFfMacSchedSapUser(FfMacSchedSapUser *s)
set the user part of the FfMacSchedSap that this Scheduler will interact with.
friend class MemberSchedSapProvider< TdTbfqFfMacScheduler >
allow MemberSchedSapProvider<TdTbfqFfMacScheduler> class friend access
void DoCschedCellConfigReq(const struct FfMacCschedSapProvider::CschedCellConfigReqParameters &params)
CSched cell config request.
uint32_t m_tokenPoolSize
maximum size of token pool (byte)
std::map< uint16_t, DlHarqProcessesStatus_t > m_dlHarqProcessesStatus
DL HARQ process status.
virtual LteFfrSapUser * GetLteFfrSapUser()
FfMacCschedSapUser * m_cschedSapUser
CSched SAP user.
std::map< uint16_t, std::vector< double > > m_ueCqi
Map of UEs' UL-CQI per RBG.
std::map< uint16_t, uint32_t > m_ueCqiTimers
Map of UEs' timers on UL-CQI per RBG.
virtual void SetLteFfrSapProvider(LteFfrSapProvider *s)
Set the Provider part of the LteFfrSap that this Scheduler will interact with.
std::map< uint16_t, SbMeasResult_s > m_a30CqiRxed
Map of UE's DL CQI A30 received.
virtual ~TdTbfqFfMacScheduler()
Destructor.
void DoSchedUlMacCtrlInfoReq(const struct FfMacSchedSapProvider::SchedUlMacCtrlInfoReqParameters &params)
Sched UL MAC control info request.
std::map< uint16_t, uint8_t > m_dlHarqCurrentProcessId
DL HARQ current process ID.
void DoSchedDlTriggerReq(const struct FfMacSchedSapProvider::SchedDlTriggerReqParameters &params)
Sched DL trigger request.
std::map< uint16_t, uint32_t > m_ceBsrRxed
Map of UE's buffer status reports received.
std::map< uint16_t, std::vector< uint16_t > > m_allocationMaps
Map of previous allocated UE per RBG (used to retrieve info from UL-CQI)
void RefreshHarqProcesses()
Refresh HARQ processes according to the timers.
void RefreshDlCqiMaps(void)
Refresh DL CQI maps function.
std::vector< struct RachListElement_s > m_rachList
RACH list.
std::vector< DlInfoListElement_s > m_dlInfoListBuffered
HARQ retx buffered.
std::map< uint16_t, UlHarqProcessesStatus_t > m_ulHarqProcessesStatus
UL HARQ process status.
void DoCschedUeConfigReq(const struct FfMacCschedSapProvider::CschedUeConfigReqParameters &params)
CSched UE config request.
std::map< uint16_t, tdtbfqsFlowPerf_t > m_flowStatsDl
Map of UE statistics (per RNTI basis) in downlink.
uint64_t bankSize
the number of bytes in token bank
bool m_harqOn
m_harqOn when false inhibit the HARQ mechanisms (by default active)
static uint8_t TxMode2LayerNum(uint8_t txMode)
Transmit mode 2 layer number.
Definition: lte-common.cc:212
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
#define NO_SINR
#define HARQ_PROC_NUM
#define HARQ_DL_TIMEOUT
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:85
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Definition: integer.h:45
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:45
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
#define HARQ_PERIOD
Definition: lte-common.h:30
#define SRS_CQI_RNTI_VSP
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::vector< UlDciListElement_s > UlHarqProcessesDciBuffer_t
UL HARQ process DCI buffer vector.
static const int TdTbfqType0AllocationRbg[4]
TDTBFQ type 0 allocation RBG.
std::vector< uint8_t > DlHarqProcessesTimer_t
DL HARQ process timer vector typedef.
std::vector< uint8_t > DlHarqProcessesStatus_t
DL HARQ process status vector typedef.
std::vector< RlcPduList_t > DlHarqRlcPduListBuffer_t
vector of the 8 HARQ processes per UE
@ SUCCESS
Definition: ff-mac-common.h:62
std::vector< DlDciListElement_s > DlHarqProcessesDciBuffer_t
DL HARQ process DCI buffer vector typedef.
std::vector< uint8_t > UlHarqProcessesStatus_t
UL HARQ process status vector.
See section 4.3.8 builDataListElement.
struct DlDciListElement_s m_dci
DCI.
std::vector< std::vector< struct RlcPduListElement_s > > m_rlcPduList
RLC PDU list.
See section 4.3.10 buildRARListElement.
See section 4.3.1 dlDciListElement.
Definition: ff-mac-common.h:94
std::vector< uint8_t > m_ndi
New data indicator.
uint8_t m_harqProcess
HARQ process.
uint32_t m_rbBitmap
RB bitmap.
Definition: ff-mac-common.h:96
std::vector< uint8_t > m_mcs
MCS.
uint8_t m_resAlloc
The type of resource allocation.
Definition: ff-mac-common.h:98
std::vector< uint16_t > m_tbsSize
The TBs size.
Definition: ff-mac-common.h:99
std::vector< uint8_t > m_rv
Redundancy version.
uint8_t m_tpc
Tx power control command.
Parameters of the CSCHED_LC_CONFIG_REQ primitive.
std::vector< struct LogicalChannelConfigListElement_s > m_logicalChannelConfigList
logicalChannelConfigList
Parameters of the CSCHED_LC_RELEASE_REQ primitive.
std::vector< uint8_t > m_logicalChannelIdentity
logical channel identity
Parameters of the CSCHED_UE_CONFIG_REQ primitive.
Parameters of the CSCHED_UE_RELEASE_REQ primitive.
Parameters of the CSCHED_UE_CONFIG_CNF primitive.
Parameters of the CSCHED_UE_CONFIG_UPDATE_IND primitive.
Parameters of the SCHED_DL_CQI_INFO_REQ primitive.
std::vector< struct CqiListElement_s > m_cqiList
CQI list.
Parameters of the SCHED_DL_MAC_BUFFER_REQ primitive.
Parameters of the SCHED_DL_PAGING_BUFFER_REQ primitive.
Parameters of the SCHED_DL_RACH_INFO_REQ primitive.
std::vector< struct RachListElement_s > m_rachList
RACH list.
Parameters of the SCHED_DL_TRIGGER_REQ primitive.
std::vector< struct DlInfoListElement_s > m_dlInfoList
DL info list.
Parameters of the SCHED_UL_CQI_INFO_REQ primitive.
std::vector< struct VendorSpecificListElement_s > m_vendorSpecificList
vendor specific list
Parameters of the SCHED_UL_MAC_CTRL_INFO_REQ primitive.
std::vector< struct MacCeListElement_s > m_macCeList
MAC CE list.
Parameters of the SCHED_UL_NOISE_INTERFERENCE_REQ primitive.
Parameters of the SCHED_UL_SR_INFO_REQ primitive.
Parameters of the SCHED_UL_TRIGGER_REQ primitive.
std::vector< struct UlInfoListElement_s > m_ulInfoList
UL info list.
uint8_t m_nrOfPdcchOfdmSymbols
number of PDCCH OFDM symbols
std::vector< struct BuildDataListElement_s > m_buildDataList
build data list
std::vector< struct BuildRarListElement_s > m_buildRarList
build rar list
Parameters of the SCHED_UL_CONFIG_IND primitive.
std::vector< struct UlDciListElement_s > m_dciList
DCI list.
LteFlowId structure.
Definition: lte-common.h:37
See section 4.3.9 rlcPDU_ListElement.
uint8_t m_logicalChannelIdentity
logical channel identity
std::vector< uint16_t > m_sinr
SINR.
See section 4.3.2 ulDciListElement.
int8_t m_pdcchPowerOffset
CCH power offset.
int8_t m_tpc
Tx power control command.
uint8_t m_dai
DL assignment index.
uint8_t m_cceIndex
Control Channel Element index.
uint8_t m_ulIndex
UL index.
uint8_t m_ueTxAntennaSelection
UE antenna selection.
bool m_cqiRequest
CQI request.
uint8_t m_n2Dmrs
n2 DMRS
uint8_t m_freqHopping
freq hopping
uint8_t m_aggrLevel
The aggregation level.
bool m_ulDelay
UL delay?
int8_t m_tpc
Tx power control command.
bool m_cqiRequest
CQI request?
bool m_hopping
hopping?
uint16_t m_tbSize
size
uint8_t m_rbLen
length
uint8_t m_mcs
MCS.
uint8_t m_rbStart
start
uint16_t m_rnti
RNTI.
uint32_t tokenPoolSize
current size of token pool (byte)
int debtLimit
counter threshold that the flow cannot further borrow tokens from bank
uint32_t maxTokenPoolSize
maximum size of token pool (byte)
int counter
the number of token borrow or given to token bank
uint32_t creditableThreshold
the flow cannot borrow token from bank until the number of token it has deposited to bank reaches thi...
uint64_t packetArrivalRate
packet arrival rate( byte/s)
uint64_t tokenGenerationRate
token generation rate ( byte/s )
Time flowStart
flow start time
uint32_t burstCredit
the maximum number of tokens connection i can borrow from the bank each time