A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
lte-ue-mac.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: 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 
29 #include "lte-ue-mac.h"
30 #include "lte-ue-net-device.h"
31 #include "lte-radio-bearer-tag.h"
32 #include <ns3/ff-mac-common.h>
33 #include <ns3/ideal-control-messages.h>
34 #include <ns3/simulator.h>
35 #include <ns3/lte-common.h>
36 
37 
38 NS_LOG_COMPONENT_DEFINE ("LteUeMac");
39 
40 namespace ns3 {
41 
43 
44 
46 // SAP forwarders
48 
49 
51 {
52 public:
54 
55  // inherited from LteUeCmacSapProvider
56  virtual void ConfigureUe (uint16_t rnti);
57  virtual void AddLc (uint8_t lcId, LteMacSapUser* msu);
58  virtual void RemoveLc (uint8_t lcId);
59  virtual void RrcUpdateConfigurationReq (LteUeConfig_t params);
60 
61 private:
63 };
64 
65 
67  : m_mac (mac)
68 {
69 }
70 
71 void
73 {
74  m_mac->DoConfigureUe (rnti);
75 }
76 
77 void
79 {
80  m_mac->DoAddLc (lcId, msu);
81 }
82 
83 void
85 {
86  m_mac->DoRemoveLc (lcid);
87 }
88 
89 void
91 {
93 }
94 
95 
97 {
98 public:
100 
101  // inherited from LteMacSapProvider
102  virtual void TransmitPdu (TransmitPduParameters params);
103  virtual void ReportBufferStatus (ReportBufferStatusParameters params);
104 
105 private:
107 };
108 
109 
111  : m_mac (mac)
112 {
113 }
114 
115 void
117 {
118  m_mac->DoTransmitPdu (params);
119 }
120 
121 
122 void
124 {
125  m_mac->DoReportBufferStatus (params);
126 }
127 
128 
129 
130 
132 {
133 public:
135 
136  // inherited from LtePhySapUser
137  virtual void ReceivePhyPdu (Ptr<Packet> p);
138  virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo);
140 
141 private:
143 };
144 
146 {
147 
148 }
149 
150 void
152 {
153  m_mac->DoReceivePhyPdu (p);
154 }
155 
156 
157 void
158 UeMemberLteUePhySapUser::SubframeIndication (uint32_t frameNo, uint32_t subframeNo)
159 {
160  m_mac->DoSubframeIndication (frameNo, subframeNo);
161 }
162 
163 void
165 {
167 }
168 
169 
170 
171 
173 // LteUeMac methods
175 
176 
177 TypeId
179 {
180  static TypeId tid = TypeId ("ns3::LteUeMac")
181  .SetParent<Object> ()
182  .AddConstructor<LteUeMac> ();
183  return tid;
184 }
185 
186 
188  : m_bsrPeriodicity (MilliSeconds (1)), // ideal behavior
189  m_bsrLast (MilliSeconds (0)),
190  m_freshUlBsr (false)
191 
192 {
193  NS_LOG_FUNCTION (this);
197 }
198 
199 
201 {
202  NS_LOG_FUNCTION (this);
203 }
204 
205 void
207 {
208  NS_LOG_FUNCTION (this);
209  delete m_macSapProvider;
210  delete m_cmacSapProvider;
211  delete m_uePhySapUser;
213 }
214 
215 
218 {
219  return m_uePhySapUser;
220 }
221 
222 void
224 {
225  m_uePhySapProvider = s;
226 }
227 
228 
231 {
232  return m_macSapProvider;
233 }
234 
235 void
237 {
238  m_cmacSapUser = s;
239 }
240 
243 {
244  return m_cmacSapProvider;
245 }
246 
247 
248 void
250 {
251  NS_LOG_FUNCTION (this);
252  NS_ASSERT_MSG (m_rnti == params.rnti, "RNTI mismatch between RLC and MAC");
253  LteRadioBearerTag tag (params.rnti, params.lcid, 0 /* UE works in SISO mode*/);
254  params.pdu->AddPacketTag (tag);
255 // Ptr<PacketBurst> pb = CreateObject<PacketBurst> ();
256 // pb->AddPacket (params.pdu);
258  // Uplink not implemented yet, so we wait can wait for the PHY SAP
259  // to be defined before we implement the transmission method.
260 }
261 
262 void
264 {
265  NS_LOG_FUNCTION (this);
266 
267  std::map <uint8_t, uint64_t>::iterator it;
268 
269 
270  it = m_ulBsrReceived.find (params.lcid);
271  if (it!=m_ulBsrReceived.end ())
272  {
273  // update entry
274  (*it).second = params.txQueueSize + params.retxQueueSize + params.statusPduSize;
275  }
276  else
277  {
278  m_ulBsrReceived.insert (std::pair<uint8_t, uint64_t> (params.lcid, params.txQueueSize + params.retxQueueSize + params.statusPduSize));
279  }
280  m_freshUlBsr = true;
281 }
282 
283 
284 void
286 {
287  NS_LOG_FUNCTION (this);
288  if (m_ulBsrReceived.size () == 0)
289  {
290  return; // No BSR report to transmit
291  }
292  MacCeListElement_s bsr;
293  bsr.m_rnti = m_rnti;
295 
296  // BSR is reported for each LCG. As a simplification, we consider that all LCs belong to the first LCG.
297  std::map <uint8_t, uint64_t>::iterator it;
298  int queue = 0;
299  for (it = m_ulBsrReceived.begin (); it != m_ulBsrReceived.end (); it++)
300  {
301  queue += (*it).second;
302 
303  }
304  int index = BufferSizeLevelBsr::BufferSize2BsrId (queue);
305  bsr.m_macCeValue.m_bufferStatus.push_back (index);
306  // FF API says that all 4 LCGs are always present
307  // we do so but reporting a 0 size for all other LCGs
311 
312  // create the feedback to eNB
313  Ptr<BsrIdealControlMessage> msg = Create<BsrIdealControlMessage> ();
314  msg->SetBsr (bsr);
316 
317 }
318 
319 void
320 LteUeMac::DoConfigureUe (uint16_t rnti)
321 {
322  NS_LOG_FUNCTION (this << " rnti" << rnti);
323  m_rnti = rnti;
324 }
325 
326 void
327 LteUeMac::DoAddLc (uint8_t lcId, LteMacSapUser* msu)
328 {
329  NS_LOG_FUNCTION (this << " lcId" << (uint16_t) lcId);
330  NS_ASSERT_MSG (m_macSapUserMap.find (lcId) == m_macSapUserMap.end (), "cannot add channel because LCID " << lcId << " is already present");
331  m_macSapUserMap[lcId] = msu;
332 }
333 
334 void
335 LteUeMac::DoRemoveLc (uint8_t lcId)
336 {
337  NS_LOG_FUNCTION (this << " lcId" << lcId);
338  NS_ASSERT_MSG (m_macSapUserMap.find (lcId) == m_macSapUserMap.end (), "could not find LCID " << lcId);
339  m_macSapUserMap.erase (lcId);
340 }
341 
342 void
344 {
345  NS_LOG_FUNCTION (this << " txMode " << (uint8_t) params.m_transmissionMode);
346  // forward info to PHY layer
348 }
349 
350 
351 void
353 {
354  LteRadioBearerTag tag;
355  p->RemovePacketTag (tag);
356  if (tag.GetRnti () == m_rnti)
357  {
358  // packet is for the current user
359  std::map <uint8_t, LteMacSapUser*>::const_iterator it = m_macSapUserMap.find (tag.GetLcid ());
360  NS_ASSERT_MSG (it != m_macSapUserMap.end (), "received packet with unknown lcid");
361  it->second->ReceivePdu (p);
362  }
363 }
364 
365 
366 void
368 {
369  NS_LOG_FUNCTION (this);
371  {
372  Ptr<UlDciIdealControlMessage> msg2 = DynamicCast<UlDciIdealControlMessage> (msg);
373  UlDciListElement_s dci = msg2->GetDci ();
374  std::map <uint8_t, uint64_t>::iterator itBsr;
375  NS_ASSERT_MSG (m_ulBsrReceived.size () <=4, " Too many LCs (max is 4)");
376  uint16_t activeLcs = 0;
377  for (itBsr = m_ulBsrReceived.begin (); itBsr != m_ulBsrReceived.end (); itBsr++)
378  {
379  if ((*itBsr).second > 0)
380  {
381  activeLcs++;
382  }
383  }
384  if (activeLcs == 0)
385  {
386  NS_LOG_ERROR (this << " No active flows for this UL-DCI");
387  return;
388  }
389  std::map <uint8_t, LteMacSapUser*>::iterator it;
390  NS_LOG_FUNCTION (this << " UE: UL-CQI notified TxOpportunity of " << dci.m_tbSize);
391  for (it = m_macSapUserMap.begin (); it!=m_macSapUserMap.end (); it++)
392  {
393  itBsr = m_ulBsrReceived.find ((*it).first);
394  if (itBsr!=m_ulBsrReceived.end ())
395  {
396  NS_LOG_FUNCTION (this << "\t" << dci.m_tbSize / m_macSapUserMap.size () << " bytes to LC " << (uint16_t)(*it).first << " queue " << (*itBsr).second);
397  (*it).second->NotifyTxOpportunity (dci.m_tbSize / activeLcs, 0);
398  if ((*itBsr).second >= static_cast<uint64_t> (dci.m_tbSize / activeLcs))
399  {
400  (*itBsr).second -= dci.m_tbSize / activeLcs;
401  }
402  else
403  {
404  (*itBsr).second = 0;
405  }
406  }
407  }
408 
409  }
410  else
411  {
412  NS_LOG_FUNCTION (this << " IdealControlMessage not recognized");
413  }
414 }
415 
416 
417 void
418 LteUeMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo)
419 {
420  NS_LOG_FUNCTION (this);
421  if ((Simulator::Now () >= m_bsrLast + m_bsrPeriodicity) && (m_freshUlBsr==true))
422  {
425  m_freshUlBsr = false;
426  }
427 }
428 
429 
430 } // namespace ns3