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