A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
lte-ue-mac.cc
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: Nicola Baldo <nbaldo@cttc.es>
19  * Author: Marco Miozzo <mmiozzo@cttc.es>
20  */
21 
22 
23 
24 #include <ns3/log.h>
25 #include <ns3/pointer.h>
26 #include <ns3/packet.h>
27 #include <ns3/packet-burst.h>
28 #include <ns3/random-variable.h>
29 
30 #include "lte-ue-mac.h"
31 #include "lte-ue-net-device.h"
32 #include "lte-radio-bearer-tag.h"
33 #include <ns3/ff-mac-common.h>
34 #include <ns3/lte-control-messages.h>
35 #include <ns3/simulator.h>
36 #include <ns3/lte-common.h>
37 
38 
39 
40 NS_LOG_COMPONENT_DEFINE ("LteUeMac");
41 
42 namespace ns3 {
43 
44 NS_OBJECT_ENSURE_REGISTERED (LteUeMac);
45 
46 
48 // SAP forwarders
50 
51 
53 {
54 public:
56 
57  // inherited from LteUeCmacSapProvider
58  virtual void ConfigureRach (RachConfig rc);
60  virtual void StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask);
61  virtual void AddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu);
62  virtual void RemoveLc (uint8_t lcId);
63  virtual void Reset ();
64 
65 private:
66  LteUeMac* m_mac;
67 };
68 
69 
70 UeMemberLteUeCmacSapProvider::UeMemberLteUeCmacSapProvider (LteUeMac* mac)
71  : m_mac (mac)
72 {
73 }
74 
75 void
76 UeMemberLteUeCmacSapProvider::ConfigureRach (RachConfig rc)
77 {
78  m_mac->DoConfigureRach (rc);
79 }
80 
81  void
83 {
84  m_mac->DoStartContentionBasedRandomAccessProcedure ();
85 }
86 
87  void
88 UeMemberLteUeCmacSapProvider::StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
89 {
90  m_mac->DoStartNonContentionBasedRandomAccessProcedure (rnti, preambleId, prachMask);
91 }
92 
93 
94 void
96 {
97  m_mac->DoAddLc (lcId, lcConfig, msu);
98 }
99 
100 void
102 {
103  m_mac->DoRemoveLc (lcid);
104 }
105 
106 void
108 {
109  m_mac->DoReset ();
110 }
111 
113 {
114 public:
116 
117  // inherited from LteMacSapProvider
118  virtual void TransmitPdu (TransmitPduParameters params);
119  virtual void ReportBufferStatus (ReportBufferStatusParameters params);
120 
121 private:
122  LteUeMac* m_mac;
123 };
124 
125 
126 UeMemberLteMacSapProvider::UeMemberLteMacSapProvider (LteUeMac* mac)
127  : m_mac (mac)
128 {
129 }
130 
131 void
133 {
134  m_mac->DoTransmitPdu (params);
135 }
136 
137 
138 void
140 {
141  m_mac->DoReportBufferStatus (params);
142 }
143 
144 
145 
146 
148 {
149 public:
151 
152  // inherited from LtePhySapUser
153  virtual void ReceivePhyPdu (Ptr<Packet> p);
154  virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo);
156 
157 private:
158  LteUeMac* m_mac;
159 };
160 
161 UeMemberLteUePhySapUser::UeMemberLteUePhySapUser (LteUeMac* mac) : m_mac (mac)
162 {
163 
164 }
165 
166 void
168 {
169  m_mac->DoReceivePhyPdu (p);
170 }
171 
172 
173 void
174 UeMemberLteUePhySapUser::SubframeIndication (uint32_t frameNo, uint32_t subframeNo)
175 {
176  m_mac->DoSubframeIndication (frameNo, subframeNo);
177 }
178 
179 void
181 {
182  m_mac->DoReceiveLteControlMessage (msg);
183 }
184 
185 
186 
187 
189 // LteUeMac methods
191 
192 
193 TypeId
194 LteUeMac::GetTypeId (void)
195 {
196  static TypeId tid = TypeId ("ns3::LteUeMac")
197  .SetParent<Object> ()
198  .AddConstructor<LteUeMac> ();
199  return tid;
200 }
201 
202 
203 LteUeMac::LteUeMac ()
204  : m_bsrPeriodicity (MilliSeconds (1)), // ideal behavior
205  m_bsrLast (MilliSeconds (0)),
206  m_freshUlBsr (false),
207  m_harqProcessId (0),
208  m_rnti (0),
209  m_rachConfigured (false),
210  m_waitingForRaResponse (false)
211 
212 {
213  NS_LOG_FUNCTION (this);
214  m_miUlHarqProcessesPacket.resize (HARQ_PERIOD);
215  for (uint8_t i = 0; i < m_miUlHarqProcessesPacket.size (); i++)
216  {
217  Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
218  m_miUlHarqProcessesPacket.at (i) = pb;
219  }
220  m_miUlHarqProcessesPacketTimer.resize (HARQ_PERIOD, 0);
221 
222  m_macSapProvider = new UeMemberLteMacSapProvider (this);
223  m_cmacSapProvider = new UeMemberLteUeCmacSapProvider (this);
224  m_uePhySapUser = new UeMemberLteUePhySapUser (this);
225  m_raPreambleUniformVariable = CreateObject<UniformRandomVariable> ();
226 }
227 
228 
229 LteUeMac::~LteUeMac ()
230 {
231  NS_LOG_FUNCTION (this);
232 }
233 
234 void
236 {
237  NS_LOG_FUNCTION (this);
238  m_miUlHarqProcessesPacket.clear ();
239  delete m_macSapProvider;
240  delete m_cmacSapProvider;
241  delete m_uePhySapUser;
243 }
244 
245 
248 {
249  return m_uePhySapUser;
250 }
251 
252 void
254 {
255  m_uePhySapProvider = s;
256 }
257 
258 
260 LteUeMac::GetLteMacSapProvider (void)
261 {
262  return m_macSapProvider;
263 }
264 
265 void
266 LteUeMac::SetLteUeCmacSapUser (LteUeCmacSapUser* s)
267 {
268  m_cmacSapUser = s;
269 }
270 
271 LteUeCmacSapProvider*
272 LteUeMac::GetLteUeCmacSapProvider (void)
273 {
274  return m_cmacSapProvider;
275 }
276 
277 
278 void
279 LteUeMac::DoTransmitPdu (LteMacSapProvider::TransmitPduParameters params)
280 {
281  NS_LOG_FUNCTION (this);
282  NS_ASSERT_MSG (m_rnti == params.rnti, "RNTI mismatch between RLC and MAC");
283  LteRadioBearerTag tag (params.rnti, params.lcid, 0 /* UE works in SISO mode*/);
284  params.pdu->AddPacketTag (tag);
285  // store pdu in HARQ buffer
286  m_miUlHarqProcessesPacket.at (m_harqProcessId)->AddPacket (params.pdu);
287  m_miUlHarqProcessesPacketTimer.at (m_harqProcessId) = HARQ_PERIOD;
288  m_uePhySapProvider->SendMacPdu (params.pdu);
289 }
290 
291 void
292 LteUeMac::DoReportBufferStatus (LteMacSapProvider::ReportBufferStatusParameters params)
293 {
294  NS_LOG_FUNCTION (this << (uint32_t) params.lcid);
295 
296  std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator it;
297 
298 
299  it = m_ulBsrReceived.find (params.lcid);
300  if (it!=m_ulBsrReceived.end ())
301  {
302  // update entry
303  (*it).second = params;
304  }
305  else
306  {
307  m_ulBsrReceived.insert (std::pair<uint8_t, LteMacSapProvider::ReportBufferStatusParameters> (params.lcid, params));
308  }
309  m_freshUlBsr = true;
310 }
311 
312 
313 void
314 LteUeMac::SendReportBufferStatus (void)
315 {
316  NS_LOG_FUNCTION (this);
317 
318  if (m_rnti == 0)
319  {
320  NS_LOG_INFO ("MAC not initialized, BSR deferred");
321  return;
322  }
323 
324  if (m_ulBsrReceived.size () == 0)
325  {
326  NS_LOG_INFO ("No BSR report to transmit");
327  return;
328  }
329  MacCeListElement_s bsr;
330  bsr.m_rnti = m_rnti;
331  bsr.m_macCeType = MacCeListElement_s::BSR;
332 
333  // BSR is reported for each LCG
334  std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator it;
335  std::vector<uint32_t> queue (4, 0); // one value per each of the 4 LCGs, initialized to 0
336  for (it = m_ulBsrReceived.begin (); it != m_ulBsrReceived.end (); it++)
337  {
338  uint8_t lcid = it->first;
339  std::map <uint8_t, LcInfo>::iterator lcInfoMapIt;
340  lcInfoMapIt = m_lcInfoMap.find (lcid);
341  NS_ASSERT (lcInfoMapIt != m_lcInfoMap.end ());
342  uint8_t lcg = lcInfoMapIt->second.lcConfig.logicalChannelGroup;
343  queue.at (lcg) += ((*it).second.txQueueSize + (*it).second.retxQueueSize + (*it).second.statusPduSize);
344  }
345 
346  // FF API says that all 4 LCGs are always present
347  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (0)));
348  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (1)));
349  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (2)));
350  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (3)));
351 
352  // create the feedback to eNB
353  Ptr<BsrLteControlMessage> msg = Create<BsrLteControlMessage> ();
354  msg->SetBsr (bsr);
355  m_uePhySapProvider->SendLteControlMessage (msg);
356 
357 }
358 
359 void
360 LteUeMac::RandomlySelectAndSendRaPreamble ()
361 {
362  NS_LOG_FUNCTION (this);
363  // 3GPP 36.321 5.1.1
364  NS_ASSERT_MSG (m_rachConfigured, "RACH not configured");
365  // assume that there is no Random Access Preambles group B
366  m_raPreambleId = m_raPreambleUniformVariable->GetInteger (0, m_rachConfig.numberOfRaPreambles - 1);
367  bool contention = true;
368  SendRaPreamble (contention);
369 }
370 
371 void
372 LteUeMac::SendRaPreamble (bool contention)
373 {
374  NS_LOG_FUNCTION (this << (uint32_t) m_raPreambleId << contention);
375  // Since regular UL LteControlMessages need m_ulConfigured = true in
376  // order to be sent by the UE, the rach preamble needs to be sent
377  // with a dedicated primitive (not
378  // m_uePhySapProvider->SendLteControlMessage (msg)) so that it can
379  // bypass the m_ulConfigured flag. This is reasonable, since In fact
380  // the RACH preamble is sent on 6RB bandwidth so the uplink
381  // bandwidth does not need to be configured.
382  NS_ASSERT (m_subframeNo > 0); // sanity check for subframe starting at 1
383  m_raRnti = m_subframeNo - 1;
384  m_uePhySapProvider->SendRachPreamble (m_raPreambleId, m_raRnti);
385  NS_LOG_INFO (this << " sent preamble id " << (uint32_t) m_raPreambleId << ", RA-RNTI " << (uint32_t) m_raRnti);
386  // 3GPP 36.321 5.1.4
387  Time raWindowBegin = MilliSeconds (3);
388  Time raWindowEnd = MilliSeconds (3 + m_rachConfig.raResponseWindowSize);
389  Simulator::Schedule (raWindowBegin, &LteUeMac::StartWaitingForRaResponse, this);
390  m_noRaResponseReceivedEvent = Simulator::Schedule (raWindowEnd, &LteUeMac::RaResponseTimeout, this, contention);
391 }
392 
393 void
394 LteUeMac::StartWaitingForRaResponse ()
395 {
396  NS_LOG_FUNCTION (this);
397  m_waitingForRaResponse = true;
398 }
399 
400 void
401 LteUeMac::RecvRaResponse (BuildRarListElement_s raResponse)
402 {
403  NS_LOG_FUNCTION (this);
404  m_waitingForRaResponse = false;
405  m_noRaResponseReceivedEvent.Cancel ();
406  NS_LOG_INFO ("got RAR for RAPID " << (uint32_t) m_raPreambleId << ", setting T-C-RNTI = " << raResponse.m_rnti);
407  m_rnti = raResponse.m_rnti;
408  m_cmacSapUser->SetTemporaryCellRnti (m_rnti);
409  // in principle we should wait for contention resolution,
410  // but in the current LTE model when two or more identical
411  // preambles are sent no one is received, so there is no need
412  // for contention resolution
413  m_cmacSapUser->NotifyRandomAccessSuccessful ();
414 }
415 
416 void
417 LteUeMac::RaResponseTimeout (bool contention)
418 {
419  NS_LOG_FUNCTION (this << contention);
420  m_waitingForRaResponse = false;
421  // 3GPP 36.321 5.1.4
422  ++m_preambleTransmissionCounter;
423  if (m_preambleTransmissionCounter == m_rachConfig.preambleTransMax + 1)
424  {
425  NS_LOG_INFO ("RAR timeout, preambleTransMax reached => giving up");
426  m_cmacSapUser->NotifyRandomAccessFailed ();
427  }
428  else
429  {
430  NS_LOG_INFO ("RAR timeout, re-send preamble");
431  if (contention)
432  {
433  RandomlySelectAndSendRaPreamble ();
434  }
435  else
436  {
437  SendRaPreamble (contention);
438  }
439  }
440 }
441 
442 void
443 LteUeMac::DoConfigureRach (LteUeCmacSapProvider::RachConfig rc)
444 {
445  NS_LOG_FUNCTION (this);
446  m_rachConfig = rc;
447  m_rachConfigured = true;
448 }
449 
450 void
451 LteUeMac::DoStartContentionBasedRandomAccessProcedure ()
452 {
453  NS_LOG_FUNCTION (this);
454 
455  // 3GPP 36.321 5.1.1
456  NS_ASSERT_MSG (m_rachConfigured, "RACH not configured");
457  m_preambleTransmissionCounter = 0;
458  m_backoffParameter = 0;
459  RandomlySelectAndSendRaPreamble ();
460 }
461 
462 void
463 LteUeMac::DoStartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
464 {
465  NS_LOG_FUNCTION (this << " rnti" << rnti);
466  NS_ASSERT_MSG (prachMask == 0, "requested PRACH MASK = " << (uint32_t) prachMask << ", but only PRACH MASK = 0 is supported");
467  m_rnti = rnti;
468  m_raPreambleId = preambleId;
469  bool contention = false;
470  SendRaPreamble (contention);
471 }
472 
473 void
474 LteUeMac::DoAddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu)
475 {
476  NS_LOG_FUNCTION (this << " lcId" << (uint32_t) lcId);
477  NS_ASSERT_MSG (m_lcInfoMap.find (lcId) == m_lcInfoMap.end (), "cannot add channel because LCID " << lcId << " is already present");
478 
479  LcInfo lcInfo;
480  lcInfo.lcConfig = lcConfig;
481  lcInfo.macSapUser = msu;
482  m_lcInfoMap[lcId] = lcInfo;
483 }
484 
485 void
486 LteUeMac::DoRemoveLc (uint8_t lcId)
487 {
488  NS_LOG_FUNCTION (this << " lcId" << lcId);
489  NS_ASSERT_MSG (m_lcInfoMap.find (lcId) == m_lcInfoMap.end (), "could not find LCID " << lcId);
490  m_lcInfoMap.erase (lcId);
491 }
492 
493 void
494 LteUeMac::DoReset ()
495 {
496  NS_LOG_FUNCTION (this);
497  std::map <uint8_t, LcInfo>::iterator it = m_lcInfoMap.begin ();
498  while (it != m_lcInfoMap.end ())
499  {
500  // don't delete CCCH)
501  if (it->first == 0)
502  {
503  ++it;
504  }
505  else
506  {
507  // note: use of postfix operator preserves validity of iterator
508  m_lcInfoMap.erase (it++);
509  }
510  }
511  m_rachConfigured = false;
512  m_freshUlBsr = false;
513  m_ulBsrReceived.clear ();
514 }
515 
516 void
517 LteUeMac::DoReceivePhyPdu (Ptr<Packet> p)
518 {
519  LteRadioBearerTag tag;
520  p->RemovePacketTag (tag);
521  if (tag.GetRnti () == m_rnti)
522  {
523  // packet is for the current user
524  std::map <uint8_t, LcInfo>::const_iterator it = m_lcInfoMap.find (tag.GetLcid ());
525  NS_ASSERT_MSG (it != m_lcInfoMap.end (), "received packet with unknown lcid");
526  it->second.macSapUser->ReceivePdu (p);
527  }
528 }
529 
530 
531 void
532 LteUeMac::DoReceiveLteControlMessage (Ptr<LteControlMessage> msg)
533 {
534  NS_LOG_FUNCTION (this);
535  if (msg->GetMessageType () == LteControlMessage::UL_DCI)
536  {
537  Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
538  UlDciListElement_s dci = msg2->GetDci ();
539  if (dci.m_ndi==1)
540  {
541  // New transmission -> emtpy pkt buffer queue (for deleting eventual pkts not acked )
542  Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
543  m_miUlHarqProcessesPacket.at (m_harqProcessId) = pb;
544  // Retrieve data from RLC
545  std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator itBsr;
546  uint16_t activeLcs = 0;
547  uint32_t statusPduMinSize = 0;
548  for (itBsr = m_ulBsrReceived.begin (); itBsr != m_ulBsrReceived.end (); itBsr++)
549  {
550  if (((*itBsr).second.statusPduSize > 0) || ((*itBsr).second.retxQueueSize > 0) || ((*itBsr).second.txQueueSize > 0))
551  {
552  activeLcs++;
553  if (((*itBsr).second.statusPduSize!=0)&&((*itBsr).second.statusPduSize < statusPduMinSize))
554  {
555  statusPduMinSize = (*itBsr).second.statusPduSize;
556  }
557  if (((*itBsr).second.statusPduSize!=0)&&(statusPduMinSize == 0))
558  {
559  statusPduMinSize = (*itBsr).second.statusPduSize;
560  }
561  }
562  }
563  if (activeLcs == 0)
564  {
565  NS_LOG_ERROR (this << " No active flows for this UL-DCI");
566  return;
567  }
568  std::map <uint8_t, LcInfo>::iterator it;
569  uint32_t bytesPerActiveLc = dci.m_tbSize / activeLcs;
570  bool statusPduPriority = false;
571  if ((statusPduMinSize != 0)&&(bytesPerActiveLc < statusPduMinSize))
572  {
573  // send only the status PDU which has highest priority
574  statusPduPriority = true;
575  NS_LOG_DEBUG (this << " Reduced resource -> send only Status, b ytes " << statusPduMinSize);
576  if (dci.m_tbSize < statusPduMinSize)
577  {
578  NS_FATAL_ERROR ("Insufficient Tx Opportunity for sending a status message");
579  }
580  }
581  NS_LOG_LOGIC (this << " UE " << m_rnti << ": UL-CQI notified TxOpportunity of " << dci.m_tbSize << " => " << bytesPerActiveLc << " bytes per active LC" << " statusPduMinSize " << statusPduMinSize);
582  for (it = m_lcInfoMap.begin (); it!=m_lcInfoMap.end (); it++)
583  {
584  itBsr = m_ulBsrReceived.find ((*it).first);
585  NS_LOG_DEBUG (this << " Processing LC " << (uint32_t)(*it).first << " bytesPerActiveLc " << bytesPerActiveLc);
586  if ( (itBsr!=m_ulBsrReceived.end ()) &&
587  ( ((*itBsr).second.statusPduSize > 0) ||
588  ((*itBsr).second.retxQueueSize > 0) ||
589  ((*itBsr).second.txQueueSize > 0)) )
590  {
591  if ((statusPduPriority) && ((*itBsr).second.statusPduSize == statusPduMinSize))
592  {
593  (*it).second.macSapUser->NotifyTxOpportunity ((*itBsr).second.statusPduSize, 0, 0);
594  NS_LOG_LOGIC (this << "\t" << bytesPerActiveLc << " send " << (*itBsr).second.statusPduSize << " status bytes to LC " << (uint32_t)(*it).first << " statusQueue " << (*itBsr).second.statusPduSize << " retxQueue" << (*itBsr).second.retxQueueSize << " txQueue" << (*itBsr).second.txQueueSize);
595  (*itBsr).second.statusPduSize = 0;
596  break;
597  }
598  else
599  {
600  uint32_t bytesForThisLc = bytesPerActiveLc;
601  NS_LOG_LOGIC (this << "\t" << bytesPerActiveLc << " bytes to LC " << (uint32_t)(*it).first << " statusQueue " << (*itBsr).second.statusPduSize << " retxQueue" << (*itBsr).second.retxQueueSize << " txQueue" << (*itBsr).second.txQueueSize);
602  if (((*itBsr).second.statusPduSize > 0) && (bytesForThisLc > (*itBsr).second.statusPduSize))
603  {
604  (*it).second.macSapUser->NotifyTxOpportunity ((*itBsr).second.statusPduSize, 0, 0);
605  bytesForThisLc -= (*itBsr).second.statusPduSize;
606  NS_LOG_DEBUG (this << " serve STATUS " << (*itBsr).second.statusPduSize);
607  (*itBsr).second.statusPduSize = 0;
608  }
609  else
610  {
611  if ((*itBsr).second.statusPduSize>bytesForThisLc)
612  {
613  NS_FATAL_ERROR ("Insufficient Tx Opportunity for sending a status message");
614  }
615  }
616 
617  if ((bytesForThisLc > 7) && // 7 is the min TxOpportunity useful for Rlc
618  (((*itBsr).second.retxQueueSize > 0) ||
619  ((*itBsr).second.txQueueSize > 0)))
620  {
621  if ((*itBsr).second.retxQueueSize > 0)
622  {
623  NS_LOG_DEBUG (this << " serve retx DATA, bytes " << bytesForThisLc);
624  (*it).second.macSapUser->NotifyTxOpportunity (bytesForThisLc, 0, 0);
625  if ((*itBsr).second.retxQueueSize >= bytesForThisLc)
626  {
627  (*itBsr).second.retxQueueSize -= bytesForThisLc;
628  }
629  else
630  {
631  (*itBsr).second.retxQueueSize = 0;
632  }
633  }
634  else if ((*itBsr).second.txQueueSize > 0)
635  {
636  NS_LOG_DEBUG (this << " serve tx DATA, bytes " << bytesForThisLc);
637  (*it).second.macSapUser->NotifyTxOpportunity (bytesForThisLc, 0, 0);
638  if ((*itBsr).second.txQueueSize >= bytesForThisLc - 2)
639  {
640  (*itBsr).second.txQueueSize -= bytesForThisLc - 2;
641  }
642  else
643  {
644  (*itBsr).second.txQueueSize = 0;
645  }
646  }
647  }
648  else
649  {
650  if ( ((*itBsr).second.retxQueueSize > 0) || ((*itBsr).second.txQueueSize > 0))
651  {
652  // resend BSR info for updating eNB peer MAC
653  m_freshUlBsr = true;
654  }
655  }
656  NS_LOG_LOGIC (this << "\t" << bytesPerActiveLc << "\t new queues " << (uint32_t)(*it).first << " statusQueue " << (*itBsr).second.statusPduSize << " retxQueue" << (*itBsr).second.retxQueueSize << " txQueue" << (*itBsr).second.txQueueSize);
657  }
658 
659  }
660  }
661  }
662  else
663  {
664  // HARQ retransmission -> retrieve data from HARQ buffer
665  NS_LOG_DEBUG (this << " UE MAC RETX HARQ " << (uint16_t)m_harqProcessId);
666  Ptr<PacketBurst> pb = m_miUlHarqProcessesPacket.at (m_harqProcessId);
667  for (std::list<Ptr<Packet> >::const_iterator j = pb->Begin (); j != pb->End (); ++j)
668  {
669  Ptr<Packet> pkt = (*j)->Copy ();
670  m_uePhySapProvider->SendMacPdu (pkt);
671  }
672  m_miUlHarqProcessesPacketTimer.at (m_harqProcessId) = HARQ_PERIOD;
673  }
674 
675  }
676  else if (msg->GetMessageType () == LteControlMessage::RAR)
677  {
678  if (m_waitingForRaResponse)
679  {
680  Ptr<RarLteControlMessage> rarMsg = DynamicCast<RarLteControlMessage> (msg);
681  uint16_t raRnti = rarMsg->GetRaRnti ();
682  NS_LOG_LOGIC (this << "got RAR with RA-RNTI " << (uint32_t) raRnti << ", expecting " << (uint32_t) m_raRnti);
683  if (raRnti == m_raRnti) // RAR corresponds to TX subframe of preamble
684  {
685  for (std::list<RarLteControlMessage::Rar>::const_iterator it = rarMsg->RarListBegin ();
686  it != rarMsg->RarListEnd ();
687  ++it)
688  {
689  if (it->rapId == m_raPreambleId) // RAR is for me
690  {
691  RecvRaResponse (it->rarPayload);
692  // TODO:: RRC generates the RecvRaResponse messaged
693  // for avoiding holes in transmission at PHY layer
694  // (which produce erroneous UL CQI evaluation)
695  }
696  }
697  }
698  }
699  }
700  else
701  {
702  NS_LOG_WARN (this << " LteControlMessage not recognized");
703  }
704 }
705 
706 void
707 LteUeMac::RefreshHarqProcessesPacketBuffer (void)
708 {
709  NS_LOG_FUNCTION (this);
710 
711  for (uint16_t i = 0; i < m_miUlHarqProcessesPacketTimer.size (); i++)
712  {
713  if (m_miUlHarqProcessesPacketTimer.at (i) == 0)
714  {
715  if (m_miUlHarqProcessesPacket.at (i)->GetSize () > 0)
716  {
717  // timer expired: drop packets in buffer for this process
718  NS_LOG_INFO (this << " HARQ Proc Id " << i << " packets buffer expired");
719  Ptr<PacketBurst> emptyPb = CreateObject <PacketBurst> ();
720  m_miUlHarqProcessesPacket.at (i) = emptyPb;
721  }
722  }
723  else
724  {
725  m_miUlHarqProcessesPacketTimer.at (i)--;
726  }
727  }
728 }
729 
730 
731 void
732 LteUeMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo)
733 {
734  NS_LOG_FUNCTION (this);
735  m_frameNo = frameNo;
736  m_subframeNo = subframeNo;
737  RefreshHarqProcessesPacketBuffer ();
738  if ((Simulator::Now () >= m_bsrLast + m_bsrPeriodicity) && (m_freshUlBsr==true))
739  {
740  SendReportBufferStatus ();
741  m_bsrLast = Simulator::Now ();
742  m_freshUlBsr = false;
743  m_harqProcessId = (m_harqProcessId + 1) % HARQ_PERIOD;
744  }
745 }
746 
747 int64_t
748 LteUeMac::AssignStreams (int64_t stream)
749 {
750  NS_LOG_FUNCTION (this << stream);
751  m_raPreambleUniformVariable->SetStream (stream);
752  return 1;
753 }
754 
755 } // namespace ns3
virtual void AddLc(uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser *msu)
Definition: lte-ue-mac.cc:95
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
virtual void TransmitPdu(TransmitPduParameters params)
Definition: lte-ue-mac.cc:132
uint32_t GetInteger(uint32_t min, uint32_t max)
Returns a random unsigned integer from a uniform distribution over the interval [min,max] including both ends.
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
virtual void ReportBufferStatus(ReportBufferStatusParameters params)
Definition: lte-ue-mac.cc:139
virtual void DoDispose(void)
Definition: object.cc:335
#define NS_LOG_INFO(msg)
Definition: log.h:264
void SetLteUePhySapProvider(LteUePhySapProvider *s)
Set the PHY SAP Provider.
Definition: lte-ue-mac.cc:253
virtual void SendRachPreamble(uint32_t prachId, uint32_t raRnti)=0
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
virtual void SubframeIndication(uint32_t frameNo, uint32_t subframeNo)
Trigger the start from a new frame (input from Phy layer)
Definition: lte-ue-mac.cc:174
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
virtual void StartContentionBasedRandomAccessProcedure()
Definition: lte-ue-mac.cc:82
virtual void SetTemporaryCellRnti(uint16_t rnti)=0
virtual void StartNonContentionBasedRandomAccessProcedure(uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
Definition: lte-ue-mac.cc:88
virtual void SendMacPdu(Ptr< Packet > p)=0
Send the MAC PDU to the channel.
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
virtual void NotifyRandomAccessSuccessful()=0
void DoSubframeIndication(uint32_t frameNo, uint32_t subframeNo)
Forwarded from LteUePhySapUser: trigger the start from a new frame.
Definition: lte-ue-mac.cc:732
virtual void SendLteControlMessage(Ptr< LteControlMessage > msg)=0
Send SendLteControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel.
LteUePhySapUser * GetLteUePhySapUser()
Get the PHY SAP user.
Definition: lte-ue-mac.cc:247
virtual void ReceivePhyPdu(Ptr< Packet > p)
Definition: lte-ue-mac.cc:167
static Time Now(void)
Definition: simulator.cc:179
virtual void RemoveLc(uint8_t lcId)
Definition: lte-ue-mac.cc:101
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
virtual void NotifyRandomAccessFailed()=0
#define NS_LOG_WARN(msg)
Definition: log.h:246
virtual void DoDispose(void)
Definition: lte-ue-mac.cc:235
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
void Cancel(void)
Definition: event-id.cc:47
Time MilliSeconds(uint64_t ms)
create ns3::Time instances in units of milliseconds.
Definition: nstime.h:601
virtual void ReceiveLteControlMessage(Ptr< LteControlMessage > msg)
Receive SendLteControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel.
Definition: lte-ue-mac.cc:180
#define NS_LOG_ERROR(msg)
Definition: log.h:237
a base class which provides memory management and object aggregation
Definition: object.h:63
int64_t AssignStreams(int64_t stream)
Definition: lte-ue-mac.cc:748
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471