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-stream.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 namespace ns3 {
41 
42 NS_LOG_COMPONENT_DEFINE ("LteUeMac");
43 
44 NS_OBJECT_ENSURE_REGISTERED (LteUeMac);
45 
46 
47 ///////////////////////////////////////////////////////////
48 // SAP forwarders
49 ///////////////////////////////////////////////////////////
50 
51 /// UeMemberLteUeCmacSapProvider class
52 class UeMemberLteUeCmacSapProvider : public LteUeCmacSapProvider
53 {
54 public:
55   /**
56    * Constructor
57    *
58    * \param mac the UE MAC
59    */
60   UeMemberLteUeCmacSapProvider (LteUeMac* mac);
61 
62   // inherited from LteUeCmacSapProvider
63   virtual void ConfigureRach (RachConfig rc);
64   virtual void StartContentionBasedRandomAccessProcedure ();
65   virtual void StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask);
66   virtual void SetRnti (uint16_t rnti);
67   virtual void AddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu);
68   virtual void RemoveLc (uint8_t lcId);
69   virtual void Reset ();
70   virtual void NotifyConnectionSuccessful ();
71   virtual void SetImsi (uint64_t imsi);
72 
73 private:
74   LteUeMac* m_mac; ///< the UE MAC
75 };
76 
77 
UeMemberLteUeCmacSapProvider(LteUeMac * mac)78 UeMemberLteUeCmacSapProvider::UeMemberLteUeCmacSapProvider (LteUeMac* mac)
79   : m_mac (mac)
80 {
81 }
82 
83 void
ConfigureRach(RachConfig rc)84 UeMemberLteUeCmacSapProvider::ConfigureRach (RachConfig rc)
85 {
86   m_mac->DoConfigureRach (rc);
87 }
88 
89   void
StartContentionBasedRandomAccessProcedure()90 UeMemberLteUeCmacSapProvider::StartContentionBasedRandomAccessProcedure ()
91 {
92   m_mac->DoStartContentionBasedRandomAccessProcedure ();
93 }
94 
95  void
StartNonContentionBasedRandomAccessProcedure(uint16_t rnti,uint8_t preambleId,uint8_t prachMask)96 UeMemberLteUeCmacSapProvider::StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
97 {
98   m_mac->DoStartNonContentionBasedRandomAccessProcedure (rnti, preambleId, prachMask);
99 }
100 
101  void
SetRnti(uint16_t rnti)102  UeMemberLteUeCmacSapProvider::SetRnti (uint16_t rnti)
103  {
104    m_mac->DoSetRnti (rnti);
105  }
106 
107 void
AddLc(uint8_t lcId,LogicalChannelConfig lcConfig,LteMacSapUser * msu)108 UeMemberLteUeCmacSapProvider::AddLc (uint8_t lcId, LogicalChannelConfig lcConfig, LteMacSapUser* msu)
109 {
110   m_mac->DoAddLc (lcId, lcConfig, msu);
111 }
112 
113 void
RemoveLc(uint8_t lcid)114 UeMemberLteUeCmacSapProvider::RemoveLc (uint8_t lcid)
115 {
116   m_mac->DoRemoveLc (lcid);
117 }
118 
119 void
Reset()120 UeMemberLteUeCmacSapProvider::Reset ()
121 {
122   m_mac->DoReset ();
123 }
124 
125 void
NotifyConnectionSuccessful()126 UeMemberLteUeCmacSapProvider::NotifyConnectionSuccessful ()
127 {
128   m_mac->DoNotifyConnectionSuccessful ();
129 }
130 
131 void
SetImsi(uint64_t imsi)132  UeMemberLteUeCmacSapProvider::SetImsi (uint64_t imsi)
133  {
134    m_mac->DoSetImsi (imsi);
135  }
136 
137 
138 /// UeMemberLteMacSapProvider class
139 class UeMemberLteMacSapProvider : public LteMacSapProvider
140 {
141 public:
142   /**
143    * Constructor
144    *
145    * \param mac the UE MAC
146    */
147   UeMemberLteMacSapProvider (LteUeMac* mac);
148 
149   // inherited from LteMacSapProvider
150   virtual void TransmitPdu (TransmitPduParameters params);
151   virtual void ReportBufferStatus (ReportBufferStatusParameters params);
152 
153 private:
154   LteUeMac* m_mac; ///< the UE MAC
155 };
156 
157 
UeMemberLteMacSapProvider(LteUeMac * mac)158 UeMemberLteMacSapProvider::UeMemberLteMacSapProvider (LteUeMac* mac)
159   : m_mac (mac)
160 {
161 }
162 
163 void
TransmitPdu(TransmitPduParameters params)164 UeMemberLteMacSapProvider::TransmitPdu (TransmitPduParameters params)
165 {
166   m_mac->DoTransmitPdu (params);
167 }
168 
169 
170 void
ReportBufferStatus(ReportBufferStatusParameters params)171 UeMemberLteMacSapProvider::ReportBufferStatus (ReportBufferStatusParameters params)
172 {
173   m_mac->DoReportBufferStatus (params);
174 }
175 
176 
177 
178 /**
179  * UeMemberLteUePhySapUser
180  */
181 class UeMemberLteUePhySapUser : public LteUePhySapUser
182 {
183 public:
184   /**
185    * Constructor
186    *
187    * \param mac the UE MAC
188    */
189   UeMemberLteUePhySapUser (LteUeMac* mac);
190 
191   // inherited from LtePhySapUser
192   virtual void ReceivePhyPdu (Ptr<Packet> p);
193   virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo);
194   virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg);
195 
196 private:
197   LteUeMac* m_mac; ///< the UE MAC
198 };
199 
UeMemberLteUePhySapUser(LteUeMac * mac)200 UeMemberLteUePhySapUser::UeMemberLteUePhySapUser (LteUeMac* mac) : m_mac (mac)
201 {
202 
203 }
204 
205 void
ReceivePhyPdu(Ptr<Packet> p)206 UeMemberLteUePhySapUser::ReceivePhyPdu (Ptr<Packet> p)
207 {
208   m_mac->DoReceivePhyPdu (p);
209 }
210 
211 
212 void
SubframeIndication(uint32_t frameNo,uint32_t subframeNo)213 UeMemberLteUePhySapUser::SubframeIndication (uint32_t frameNo, uint32_t subframeNo)
214 {
215   m_mac->DoSubframeIndication (frameNo, subframeNo);
216 }
217 
218 void
ReceiveLteControlMessage(Ptr<LteControlMessage> msg)219 UeMemberLteUePhySapUser::ReceiveLteControlMessage (Ptr<LteControlMessage> msg)
220 {
221   m_mac->DoReceiveLteControlMessage (msg);
222 }
223 
224 
225 
226 
227 //////////////////////////////////////////////////////////
228 // LteUeMac methods
229 ///////////////////////////////////////////////////////////
230 
231 
232 TypeId
GetTypeId(void)233 LteUeMac::GetTypeId (void)
234 {
235   static TypeId tid = TypeId ("ns3::LteUeMac")
236     .SetParent<Object> ()
237     .SetGroupName("Lte")
238     .AddConstructor<LteUeMac> ()
239     .AddTraceSource ("RaResponseTimeout",
240                      "trace fired upon RA response timeout",
241                      MakeTraceSourceAccessor (&LteUeMac::m_raResponseTimeoutTrace),
242                      "ns3::LteUeMac::RaResponseTimeoutTracedCallback")
243 
244     ;
245   return tid;
246 }
247 
248 
LteUeMac()249 LteUeMac::LteUeMac ()
250   :  m_bsrPeriodicity (MilliSeconds (1)), // ideal behavior
251      m_bsrLast (MilliSeconds (0)),
252      m_freshUlBsr (false),
253      m_harqProcessId (0),
254      m_rnti (0),
255      m_imsi (0),
256      m_rachConfigured (false),
257      m_waitingForRaResponse (false)
258 
259 {
260   NS_LOG_FUNCTION (this);
261   m_miUlHarqProcessesPacket.resize (HARQ_PERIOD);
262   for (uint8_t i = 0; i < m_miUlHarqProcessesPacket.size (); i++)
263     {
264       Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
265       m_miUlHarqProcessesPacket.at (i) = pb;
266     }
267   m_miUlHarqProcessesPacketTimer.resize (HARQ_PERIOD, 0);
268 
269   m_macSapProvider = new UeMemberLteMacSapProvider (this);
270   m_cmacSapProvider = new UeMemberLteUeCmacSapProvider (this);
271   m_uePhySapUser = new UeMemberLteUePhySapUser (this);
272   m_raPreambleUniformVariable = CreateObject<UniformRandomVariable> ();
273   m_componentCarrierId = 0;
274 }
275 
276 
~LteUeMac()277 LteUeMac::~LteUeMac ()
278 {
279   NS_LOG_FUNCTION (this);
280 }
281 
282 void
DoDispose()283 LteUeMac::DoDispose ()
284 {
285   NS_LOG_FUNCTION (this);
286   m_miUlHarqProcessesPacket.clear ();
287   delete m_macSapProvider;
288   delete m_cmacSapProvider;
289   delete m_uePhySapUser;
290   Object::DoDispose ();
291 }
292 
293 
294 LteUePhySapUser*
GetLteUePhySapUser(void)295 LteUeMac::GetLteUePhySapUser (void)
296 {
297   return m_uePhySapUser;
298 }
299 
300 void
SetLteUePhySapProvider(LteUePhySapProvider * s)301 LteUeMac::SetLteUePhySapProvider (LteUePhySapProvider* s)
302 {
303   m_uePhySapProvider = s;
304 }
305 
306 
307 LteMacSapProvider*
GetLteMacSapProvider(void)308 LteUeMac::GetLteMacSapProvider (void)
309 {
310   return m_macSapProvider;
311 }
312 
313 void
SetLteUeCmacSapUser(LteUeCmacSapUser * s)314 LteUeMac::SetLteUeCmacSapUser (LteUeCmacSapUser* s)
315 {
316   m_cmacSapUser = s;
317 }
318 
319 LteUeCmacSapProvider*
GetLteUeCmacSapProvider(void)320 LteUeMac::GetLteUeCmacSapProvider (void)
321 {
322   return m_cmacSapProvider;
323 }
324 
325 void
SetComponentCarrierId(uint8_t index)326 LteUeMac::SetComponentCarrierId (uint8_t index)
327 {
328   m_componentCarrierId = index;
329 }
330 
331 void
DoTransmitPdu(LteMacSapProvider::TransmitPduParameters params)332 LteUeMac::DoTransmitPdu (LteMacSapProvider::TransmitPduParameters params)
333 {
334   NS_LOG_FUNCTION (this);
335   NS_ASSERT_MSG (m_rnti == params.rnti, "RNTI mismatch between RLC and MAC");
336   LteRadioBearerTag tag (params.rnti, params.lcid, 0 /* UE works in SISO mode*/);
337   params.pdu->AddPacketTag (tag);
338   // store pdu in HARQ buffer
339   m_miUlHarqProcessesPacket.at (m_harqProcessId)->AddPacket (params.pdu);
340   m_miUlHarqProcessesPacketTimer.at (m_harqProcessId) = HARQ_PERIOD;
341   m_uePhySapProvider->SendMacPdu (params.pdu);
342 }
343 
344 void
DoReportBufferStatus(LteMacSapProvider::ReportBufferStatusParameters params)345 LteUeMac::DoReportBufferStatus (LteMacSapProvider::ReportBufferStatusParameters params)
346 {
347   NS_LOG_FUNCTION (this << (uint32_t) params.lcid);
348 
349   std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator it;
350 
351 
352   it = m_ulBsrReceived.find (params.lcid);
353   if (it != m_ulBsrReceived.end ())
354     {
355       // update entry
356       (*it).second = params;
357     }
358   else
359     {
360       m_ulBsrReceived.insert (std::pair<uint8_t, LteMacSapProvider::ReportBufferStatusParameters> (params.lcid, params));
361     }
362   m_freshUlBsr = true;
363 }
364 
365 
366 void
SendReportBufferStatus(void)367 LteUeMac::SendReportBufferStatus (void)
368 {
369   NS_LOG_FUNCTION (this);
370 
371   if (m_rnti == 0)
372     {
373       NS_LOG_INFO ("MAC not initialized, BSR deferred");
374       return;
375     }
376 
377   if (m_ulBsrReceived.size () == 0)
378     {
379       NS_LOG_INFO ("No BSR report to transmit");
380       return;
381     }
382   MacCeListElement_s bsr;
383   bsr.m_rnti = m_rnti;
384   bsr.m_macCeType = MacCeListElement_s::BSR;
385 
386   // BSR is reported for each LCG
387   std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator it;
388   std::vector<uint32_t> queue (4, 0); // one value per each of the 4 LCGs, initialized to 0
389   for (it = m_ulBsrReceived.begin (); it != m_ulBsrReceived.end (); it++)
390     {
391       uint8_t lcid = it->first;
392       std::map <uint8_t, LcInfo>::iterator lcInfoMapIt;
393       lcInfoMapIt = m_lcInfoMap.find (lcid);
394       NS_ASSERT (lcInfoMapIt !=  m_lcInfoMap.end ());
395       NS_ASSERT_MSG ((lcid != 0) || (((*it).second.txQueueSize == 0)
396                                      && ((*it).second.retxQueueSize == 0)
397                                      && ((*it).second.statusPduSize == 0)),
398                      "BSR should not be used for LCID 0");
399       uint8_t lcg = lcInfoMapIt->second.lcConfig.logicalChannelGroup;
400       queue.at (lcg) += ((*it).second.txQueueSize + (*it).second.retxQueueSize + (*it).second.statusPduSize);
401     }
402 
403   // FF API says that all 4 LCGs are always present
404   bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (0)));
405   bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (1)));
406   bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (2)));
407   bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (3)));
408 
409   // create the feedback to eNB
410   Ptr<BsrLteControlMessage> msg = Create<BsrLteControlMessage> ();
411   msg->SetBsr (bsr);
412   m_uePhySapProvider->SendLteControlMessage (msg);
413 
414 }
415 
416 void
RandomlySelectAndSendRaPreamble()417 LteUeMac::RandomlySelectAndSendRaPreamble ()
418 {
419   NS_LOG_FUNCTION (this);
420   // 3GPP 36.321 5.1.1
421   NS_ASSERT_MSG (m_rachConfigured, "RACH not configured");
422   // assume that there is no Random Access Preambles group B
423   m_raPreambleId = m_raPreambleUniformVariable->GetInteger (0, m_rachConfig.numberOfRaPreambles - 1);
424   bool contention = true;
425   SendRaPreamble (contention);
426 }
427 
428 void
SendRaPreamble(bool contention)429 LteUeMac::SendRaPreamble (bool contention)
430 {
431   NS_LOG_FUNCTION (this << (uint32_t) m_raPreambleId << contention);
432   // Since regular UL LteControlMessages need m_ulConfigured = true in
433   // order to be sent by the UE, the rach preamble needs to be sent
434   // with a dedicated primitive (not
435   // m_uePhySapProvider->SendLteControlMessage (msg)) so that it can
436   // bypass the m_ulConfigured flag. This is reasonable, since In fact
437   // the RACH preamble is sent on 6RB bandwidth so the uplink
438   // bandwidth does not need to be configured.
439   NS_ASSERT (m_subframeNo > 0); // sanity check for subframe starting at 1
440   m_raRnti = m_subframeNo - 1;
441   m_uePhySapProvider->SendRachPreamble (m_raPreambleId, m_raRnti);
442   NS_LOG_INFO (this << " sent preamble id " << (uint32_t) m_raPreambleId << ", RA-RNTI " << (uint32_t) m_raRnti);
443   // 3GPP 36.321 5.1.4
444   Time raWindowBegin = MilliSeconds (3);
445   Time raWindowEnd = MilliSeconds (3 + m_rachConfig.raResponseWindowSize);
446   Simulator::Schedule (raWindowBegin, &LteUeMac::StartWaitingForRaResponse, this);
447   m_noRaResponseReceivedEvent = Simulator::Schedule (raWindowEnd, &LteUeMac::RaResponseTimeout, this, contention);
448 }
449 
450 void
StartWaitingForRaResponse()451 LteUeMac::StartWaitingForRaResponse ()
452 {
453    NS_LOG_FUNCTION (this);
454    m_waitingForRaResponse = true;
455 }
456 
457 void
RecvRaResponse(BuildRarListElement_s raResponse)458 LteUeMac::RecvRaResponse (BuildRarListElement_s raResponse)
459 {
460   NS_LOG_FUNCTION (this);
461   m_waitingForRaResponse = false;
462   m_noRaResponseReceivedEvent.Cancel ();
463   NS_LOG_INFO ("got RAR for RAPID " << (uint32_t) m_raPreambleId << ", setting T-C-RNTI = " << raResponse.m_rnti);
464   m_rnti = raResponse.m_rnti;
465   m_cmacSapUser->SetTemporaryCellRnti (m_rnti);
466   // in principle we should wait for contention resolution,
467   // but in the current LTE model when two or more identical
468   // preambles are sent no one is received, so there is no need
469   // for contention resolution
470   m_cmacSapUser->NotifyRandomAccessSuccessful ();
471   // trigger tx opportunity for Message 3 over LC 0
472   // this is needed since Message 3's UL GRANT is in the RAR, not in UL-DCIs
473   const uint8_t lc0Lcid = 0;
474   std::map <uint8_t, LcInfo>::iterator lc0InfoIt = m_lcInfoMap.find (lc0Lcid);
475   NS_ASSERT (lc0InfoIt != m_lcInfoMap.end ());
476   std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator lc0BsrIt
477     = m_ulBsrReceived.find (lc0Lcid);
478   if ((lc0BsrIt != m_ulBsrReceived.end ())
479       && (lc0BsrIt->second.txQueueSize > 0))
480     {
481       NS_ASSERT_MSG (raResponse.m_grant.m_tbSize > lc0BsrIt->second.txQueueSize,
482                      "segmentation of Message 3 is not allowed");
483       // this function can be called only from primary carrier
484       if (m_componentCarrierId > 0)
485         {
486           NS_FATAL_ERROR ("Function called on wrong componentCarrier");
487         }
488       LteMacSapUser::TxOpportunityParameters txOpParams;
489       txOpParams.bytes = raResponse.m_grant.m_tbSize;
490       txOpParams.layer = 0;
491       txOpParams.harqId = 0;
492       txOpParams.componentCarrierId = m_componentCarrierId;
493       txOpParams.rnti = m_rnti;
494       txOpParams.lcid = lc0Lcid;
495       lc0InfoIt->second.macSapUser->NotifyTxOpportunity (txOpParams);
496       lc0BsrIt->second.txQueueSize = 0;
497     }
498 }
499 
500 void
RaResponseTimeout(bool contention)501 LteUeMac::RaResponseTimeout (bool contention)
502 {
503   NS_LOG_FUNCTION (this << contention);
504   m_waitingForRaResponse = false;
505   // 3GPP 36.321 5.1.4
506   ++m_preambleTransmissionCounter;
507   //fire RA response timeout trace
508   m_raResponseTimeoutTrace (m_imsi, contention, m_preambleTransmissionCounter,
509                             m_rachConfig.preambleTransMax + 1);
510   if (m_preambleTransmissionCounter == m_rachConfig.preambleTransMax + 1)
511     {
512       NS_LOG_INFO ("RAR timeout, preambleTransMax reached => giving up");
513       m_cmacSapUser->NotifyRandomAccessFailed ();
514     }
515   else
516     {
517       NS_LOG_INFO ("RAR timeout, re-send preamble");
518       if (contention)
519         {
520           RandomlySelectAndSendRaPreamble ();
521         }
522       else
523         {
524           SendRaPreamble (contention);
525         }
526     }
527 }
528 
529 void
DoConfigureRach(LteUeCmacSapProvider::RachConfig rc)530 LteUeMac::DoConfigureRach (LteUeCmacSapProvider::RachConfig rc)
531 {
532   NS_LOG_FUNCTION (this);
533   m_rachConfig = rc;
534   m_rachConfigured = true;
535 }
536 
537 void
DoStartContentionBasedRandomAccessProcedure()538 LteUeMac::DoStartContentionBasedRandomAccessProcedure ()
539 {
540   NS_LOG_FUNCTION (this);
541 
542   // 3GPP 36.321 5.1.1
543   NS_ASSERT_MSG (m_rachConfigured, "RACH not configured");
544   m_preambleTransmissionCounter = 0;
545   m_backoffParameter = 0;
546   RandomlySelectAndSendRaPreamble ();
547 }
548 
549 void
DoSetRnti(uint16_t rnti)550 LteUeMac::DoSetRnti (uint16_t rnti)
551 {
552   NS_LOG_FUNCTION (this);
553   m_rnti = rnti;
554 }
555 
556 void
DoSetImsi(uint64_t imsi)557 LteUeMac::DoSetImsi (uint64_t imsi)
558 {
559   NS_LOG_FUNCTION (this);
560   m_imsi = imsi;
561 }
562 
563 
564 void
DoStartNonContentionBasedRandomAccessProcedure(uint16_t rnti,uint8_t preambleId,uint8_t prachMask)565 LteUeMac::DoStartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
566 {
567   NS_LOG_FUNCTION (this << rnti << (uint16_t) preambleId << (uint16_t) prachMask);
568   NS_ASSERT_MSG (prachMask == 0, "requested PRACH MASK = " << (uint32_t) prachMask << ", but only PRACH MASK = 0 is supported");
569   m_rnti = rnti;
570   m_raPreambleId = preambleId;
571   m_preambleTransmissionCounter = 0;
572   bool contention = false;
573   SendRaPreamble (contention);
574 }
575 
576 void
DoAddLc(uint8_t lcId,LteUeCmacSapProvider::LogicalChannelConfig lcConfig,LteMacSapUser * msu)577 LteUeMac::DoAddLc (uint8_t lcId,  LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu)
578 {
579   NS_LOG_FUNCTION (this << " lcId" << (uint32_t) lcId);
580   NS_ASSERT_MSG (m_lcInfoMap.find (lcId) == m_lcInfoMap.end (), "cannot add channel because LCID " << (uint16_t)lcId << " is already present");
581 
582   LcInfo lcInfo;
583   lcInfo.lcConfig = lcConfig;
584   lcInfo.macSapUser = msu;
585   m_lcInfoMap[lcId] = lcInfo;
586 }
587 
588 void
DoRemoveLc(uint8_t lcId)589 LteUeMac::DoRemoveLc (uint8_t lcId)
590 {
591   NS_LOG_FUNCTION (this << " lcId" << lcId);
592   NS_ASSERT_MSG (m_lcInfoMap.find (lcId) != m_lcInfoMap.end (), "could not find LCID " << lcId);
593   m_lcInfoMap.erase (lcId);
594   m_ulBsrReceived.erase(lcId); //empty BSR buffer for this lcId
595 }
596 
597 void
DoReset()598 LteUeMac::DoReset ()
599 {
600   NS_LOG_FUNCTION (this);
601   std::map <uint8_t, LcInfo>::iterator it = m_lcInfoMap.begin ();
602   while (it != m_lcInfoMap.end ())
603     {
604       // don't delete CCCH)
605       if (it->first == 0)
606         {
607           ++it;
608         }
609       else
610         {
611           // note: use of postfix operator preserves validity of iterator
612           m_lcInfoMap.erase (it++);
613         }
614     }
615   // note: rnti will be assigned by the eNB using RA response message
616   m_rnti = 0;
617   m_noRaResponseReceivedEvent.Cancel ();
618   m_rachConfigured = false;
619   m_freshUlBsr = false;
620   m_ulBsrReceived.clear ();
621 }
622 
623 void
DoNotifyConnectionSuccessful()624 LteUeMac::DoNotifyConnectionSuccessful ()
625 {
626   NS_LOG_FUNCTION (this);
627   m_uePhySapProvider->NotifyConnectionSuccessful ();
628 }
629 
630 void
DoReceivePhyPdu(Ptr<Packet> p)631 LteUeMac::DoReceivePhyPdu (Ptr<Packet> p)
632 {
633   LteRadioBearerTag tag;
634   p->RemovePacketTag (tag);
635   if (tag.GetRnti () == m_rnti)
636     {
637       // packet is for the current user
638       std::map <uint8_t, LcInfo>::const_iterator it = m_lcInfoMap.find (tag.GetLcid ());
639       if (it != m_lcInfoMap.end ())
640         {
641           LteMacSapUser::ReceivePduParameters rxPduParams;
642           rxPduParams.p = p;
643           rxPduParams.rnti = m_rnti;
644           rxPduParams.lcid = tag.GetLcid ();
645           it->second.macSapUser->ReceivePdu (rxPduParams);
646         }
647       else
648         {
649           NS_LOG_WARN ("received packet with unknown lcid " << (uint32_t) tag.GetLcid ());
650         }
651     }
652 }
653 
654 
655 void
DoReceiveLteControlMessage(Ptr<LteControlMessage> msg)656 LteUeMac::DoReceiveLteControlMessage (Ptr<LteControlMessage> msg)
657 {
658   NS_LOG_FUNCTION (this);
659   if (msg->GetMessageType () == LteControlMessage::UL_DCI)
660     {
661       Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
662       UlDciListElement_s dci = msg2->GetDci ();
663       if (dci.m_ndi == 1)
664         {
665           // New transmission -> empty pkt buffer queue (for deleting eventual pkts not acked )
666           Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
667           m_miUlHarqProcessesPacket.at (m_harqProcessId) = pb;
668           // Retrieve data from RLC
669           std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator itBsr;
670           uint16_t activeLcs = 0;
671           uint32_t statusPduMinSize = 0;
672           for (itBsr = m_ulBsrReceived.begin (); itBsr != m_ulBsrReceived.end (); itBsr++)
673             {
674               if (((*itBsr).second.statusPduSize > 0) || ((*itBsr).second.retxQueueSize > 0) || ((*itBsr).second.txQueueSize > 0))
675                 {
676                   activeLcs++;
677                   if (((*itBsr).second.statusPduSize != 0)&&((*itBsr).second.statusPduSize < statusPduMinSize))
678                     {
679                       statusPduMinSize = (*itBsr).second.statusPduSize;
680                     }
681                   if (((*itBsr).second.statusPduSize != 0)&&(statusPduMinSize == 0))
682                     {
683                       statusPduMinSize = (*itBsr).second.statusPduSize;
684                     }
685                 }
686             }
687           if (activeLcs == 0)
688             {
689               NS_LOG_ERROR (this << " No active flows for this UL-DCI");
690               return;
691             }
692           std::map <uint8_t, LcInfo>::iterator it;
693           uint32_t bytesPerActiveLc = dci.m_tbSize / activeLcs;
694           bool statusPduPriority = false;
695           if ((statusPduMinSize != 0)&&(bytesPerActiveLc < statusPduMinSize))
696             {
697               // send only the status PDU which has highest priority
698               statusPduPriority = true;
699               NS_LOG_DEBUG (this << " Reduced resource -> send only Status, b ytes " << statusPduMinSize);
700               if (dci.m_tbSize < statusPduMinSize)
701                 {
702                   NS_FATAL_ERROR ("Insufficient Tx Opportunity for sending a status message");
703                 }
704             }
705           NS_LOG_LOGIC (this << " UE " << m_rnti << ": UL-CQI notified TxOpportunity of " << dci.m_tbSize << " => " << bytesPerActiveLc << " bytes per active LC" << " statusPduMinSize " << statusPduMinSize);
706 
707           LteMacSapUser::TxOpportunityParameters txOpParams;
708 
709           for (it = m_lcInfoMap.begin (); it != m_lcInfoMap.end (); it++)
710             {
711               itBsr = m_ulBsrReceived.find ((*it).first);
712               NS_LOG_DEBUG (this << " Processing LC " << (uint32_t)(*it).first << " bytesPerActiveLc " << bytesPerActiveLc);
713               if ( (itBsr != m_ulBsrReceived.end ())
714                    && ( ((*itBsr).second.statusPduSize > 0)
715                         || ((*itBsr).second.retxQueueSize > 0)
716                         || ((*itBsr).second.txQueueSize > 0)) )
717                 {
718                   if ((statusPduPriority) && ((*itBsr).second.statusPduSize == statusPduMinSize))
719                     {
720                       txOpParams.bytes = (*itBsr).second.statusPduSize;
721                       txOpParams.layer = 0;
722                       txOpParams.harqId = 0;
723                       txOpParams.componentCarrierId = m_componentCarrierId;
724                       txOpParams.rnti = m_rnti;
725                       txOpParams.lcid = (*it).first;
726                       (*it).second.macSapUser->NotifyTxOpportunity (txOpParams);
727                       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);
728                       (*itBsr).second.statusPduSize = 0;
729                       break;
730                     }
731                   else
732                     {
733                       uint32_t bytesForThisLc = bytesPerActiveLc;
734                       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);
735                       if (((*itBsr).second.statusPduSize > 0) && (bytesForThisLc > (*itBsr).second.statusPduSize))
736                         {
737                           txOpParams.bytes = (*itBsr).second.statusPduSize;
738                           txOpParams.layer = 0;
739                           txOpParams.harqId = 0;
740                           txOpParams.componentCarrierId = m_componentCarrierId;
741                           txOpParams.rnti = m_rnti;
742                           txOpParams.lcid = (*it).first;
743                           (*it).second.macSapUser->NotifyTxOpportunity (txOpParams);
744                           bytesForThisLc -= (*itBsr).second.statusPduSize;
745                           NS_LOG_DEBUG (this << " serve STATUS " << (*itBsr).second.statusPduSize);
746                           (*itBsr).second.statusPduSize = 0;
747                         }
748                       else
749                         {
750                           if ((*itBsr).second.statusPduSize > bytesForThisLc)
751                             {
752                               NS_FATAL_ERROR ("Insufficient Tx Opportunity for sending a status message");
753                             }
754                         }
755 
756                       if ((bytesForThisLc > 7)    // 7 is the min TxOpportunity useful for Rlc
757                           && (((*itBsr).second.retxQueueSize > 0)
758                               || ((*itBsr).second.txQueueSize > 0)))
759                         {
760                           if ((*itBsr).second.retxQueueSize > 0)
761                             {
762                               NS_LOG_DEBUG (this << " serve retx DATA, bytes " << bytesForThisLc);
763                               txOpParams.bytes = bytesForThisLc;
764                               txOpParams.layer = 0;
765                               txOpParams.harqId = 0;
766                               txOpParams.componentCarrierId = m_componentCarrierId;
767                               txOpParams.rnti = m_rnti;
768                               txOpParams.lcid = (*it).first;
769                               (*it).second.macSapUser->NotifyTxOpportunity (txOpParams);
770                               if ((*itBsr).second.retxQueueSize >= bytesForThisLc)
771                                 {
772                                   (*itBsr).second.retxQueueSize -= bytesForThisLc;
773                                 }
774                               else
775                                 {
776                                   (*itBsr).second.retxQueueSize = 0;
777                                 }
778                             }
779                           else if ((*itBsr).second.txQueueSize > 0)
780                             {
781                               uint16_t lcid = (*it).first;
782                               uint32_t rlcOverhead;
783                               if (lcid == 1)
784                                 {
785                                   // for SRB1 (using RLC AM) it's better to
786                                   // overestimate RLC overhead rather than
787                                   // underestimate it and risk unneeded
788                                   // segmentation which increases delay
789                                   rlcOverhead = 4;
790                                 }
791                               else
792                                 {
793                                   // minimum RLC overhead due to header
794                                   rlcOverhead = 2;
795                                 }
796                               NS_LOG_DEBUG (this << " serve tx DATA, bytes " << bytesForThisLc << ", RLC overhead " << rlcOverhead);
797                               txOpParams.bytes = bytesForThisLc;
798                               txOpParams.layer = 0;
799                               txOpParams.harqId = 0;
800                               txOpParams.componentCarrierId = m_componentCarrierId;
801                               txOpParams.rnti = m_rnti;
802                               txOpParams.lcid = (*it).first;
803                               (*it).second.macSapUser->NotifyTxOpportunity (txOpParams);
804                               if ((*itBsr).second.txQueueSize >= bytesForThisLc - rlcOverhead)
805                                 {
806                                   (*itBsr).second.txQueueSize -= bytesForThisLc - rlcOverhead;
807                                 }
808                               else
809                                 {
810                                   (*itBsr).second.txQueueSize = 0;
811                                 }
812                             }
813                         }
814                       else
815                         {
816                           if ( ((*itBsr).second.retxQueueSize > 0) || ((*itBsr).second.txQueueSize > 0))
817                             {
818                               // resend BSR info for updating eNB peer MAC
819                               m_freshUlBsr = true;
820                             }
821                         }
822                       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);
823                     }
824 
825                 }
826             }
827         }
828       else
829         {
830           // HARQ retransmission -> retrieve data from HARQ buffer
831           NS_LOG_DEBUG (this << " UE MAC RETX HARQ " << (uint16_t)m_harqProcessId);
832           Ptr<PacketBurst> pb = m_miUlHarqProcessesPacket.at (m_harqProcessId);
833           for (std::list<Ptr<Packet> >::const_iterator j = pb->Begin (); j != pb->End (); ++j)
834             {
835               Ptr<Packet> pkt = (*j)->Copy ();
836               m_uePhySapProvider->SendMacPdu (pkt);
837             }
838           m_miUlHarqProcessesPacketTimer.at (m_harqProcessId) = HARQ_PERIOD;
839         }
840 
841     }
842   else if (msg->GetMessageType () == LteControlMessage::RAR)
843     {
844       if (m_waitingForRaResponse)
845         {
846           Ptr<RarLteControlMessage> rarMsg = DynamicCast<RarLteControlMessage> (msg);
847           uint16_t raRnti = rarMsg->GetRaRnti ();
848           NS_LOG_LOGIC (this << "got RAR with RA-RNTI " << (uint32_t) raRnti << ", expecting " << (uint32_t) m_raRnti);
849           if (raRnti == m_raRnti) // RAR corresponds to TX subframe of preamble
850             {
851               for (std::list<RarLteControlMessage::Rar>::const_iterator it = rarMsg->RarListBegin ();
852                    it != rarMsg->RarListEnd ();
853                    ++it)
854                 {
855                   if (it->rapId == m_raPreambleId) // RAR is for me
856                     {
857                       RecvRaResponse (it->rarPayload);
858                       /// \todo RRC generates the RecvRaResponse messaged
859                       /// for avoiding holes in transmission at PHY layer
860                       /// (which produce erroneous UL CQI evaluation)
861                     }
862                 }
863             }
864         }
865     }
866   else
867     {
868       NS_LOG_WARN (this << " LteControlMessage not recognized");
869     }
870 }
871 
872 void
RefreshHarqProcessesPacketBuffer(void)873 LteUeMac::RefreshHarqProcessesPacketBuffer (void)
874 {
875   NS_LOG_FUNCTION (this);
876 
877   for (uint16_t i = 0; i < m_miUlHarqProcessesPacketTimer.size (); i++)
878     {
879       if (m_miUlHarqProcessesPacketTimer.at (i) == 0)
880         {
881           if (m_miUlHarqProcessesPacket.at (i)->GetSize () > 0)
882             {
883               // timer expired: drop packets in buffer for this process
884               NS_LOG_INFO (this << " HARQ Proc Id " << i << " packets buffer expired");
885               Ptr<PacketBurst> emptyPb = CreateObject <PacketBurst> ();
886               m_miUlHarqProcessesPacket.at (i) = emptyPb;
887             }
888         }
889       else
890         {
891           m_miUlHarqProcessesPacketTimer.at (i)--;
892         }
893     }
894 }
895 
896 
897 void
DoSubframeIndication(uint32_t frameNo,uint32_t subframeNo)898 LteUeMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo)
899 {
900   NS_LOG_FUNCTION (this);
901   m_frameNo = frameNo;
902   m_subframeNo = subframeNo;
903   RefreshHarqProcessesPacketBuffer ();
904   if ((Simulator::Now () >= m_bsrLast + m_bsrPeriodicity) && (m_freshUlBsr == true))
905     {
906       if (m_componentCarrierId == 0)
907         {
908           //Send BSR through primary carrier
909           SendReportBufferStatus ();
910         }
911       m_bsrLast = Simulator::Now ();
912       m_freshUlBsr = false;
913     }
914   m_harqProcessId = (m_harqProcessId + 1) % HARQ_PERIOD;
915 
916 }
917 
918 int64_t
AssignStreams(int64_t stream)919 LteUeMac::AssignStreams (int64_t stream)
920 {
921   NS_LOG_FUNCTION (this << stream);
922   m_raPreambleUniformVariable->SetStream (stream);
923   return 1;
924 }
925 
926 } // namespace ns3
927