7886
|
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 "ue-net-device.h"
|
|
31 |
#include "lte-mac-tag.h"
|
|
32 |
#include <ns3/ff-mac-common.h>
|
|
33 |
#include <ns3/ideal-control-messages.h>
|
|
34 |
|
|
35 |
|
|
36 |
NS_LOG_COMPONENT_DEFINE ("LteUeMac");
|
|
37 |
|
|
38 |
namespace ns3 {
|
|
39 |
|
|
40 |
NS_OBJECT_ENSURE_REGISTERED (LteUeMac);
|
|
41 |
|
|
42 |
|
|
43 |
|
|
44 |
int BufferSizeLevelBsr[64] = {
|
|
45 |
|
|
46 |
0, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146,
|
|
47 |
171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132, 1326, 1552,
|
|
48 |
1817, 2127, 2490, 2915, 3413, 3995, 4677, 5476, 6411, 7505, 8787, 10287,
|
|
49 |
12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304, 42502, 49759, 58255,
|
|
50 |
68201, 79846, 93749, 109439, 128125, 150000, 150000
|
|
51 |
|
|
52 |
};
|
|
53 |
|
|
54 |
|
|
55 |
///////////////////////////////////////////////////////////
|
|
56 |
// SAP forwarders
|
|
57 |
///////////////////////////////////////////////////////////
|
|
58 |
|
|
59 |
|
|
60 |
class UeMemberLteUeCmacSapProvider : public LteUeCmacSapProvider
|
|
61 |
{
|
|
62 |
public:
|
|
63 |
UeMemberLteUeCmacSapProvider (LteUeMac* mac);
|
|
64 |
|
|
65 |
// inherited from LteUeCmacSapProvider
|
|
66 |
virtual void ConfigureUe (uint16_t rnti);
|
|
67 |
virtual void AddLc (uint8_t lcId, LteMacSapUser* msu);
|
|
68 |
virtual void RemoveLc (uint8_t lcId);
|
|
69 |
|
|
70 |
private:
|
|
71 |
LteUeMac* m_mac;
|
|
72 |
};
|
|
73 |
|
|
74 |
|
|
75 |
UeMemberLteUeCmacSapProvider::UeMemberLteUeCmacSapProvider (LteUeMac* mac)
|
|
76 |
: m_mac (mac)
|
|
77 |
{
|
|
78 |
}
|
|
79 |
|
|
80 |
void
|
|
81 |
UeMemberLteUeCmacSapProvider::ConfigureUe (uint16_t rnti)
|
|
82 |
{
|
|
83 |
m_mac->DoConfigureUe (rnti);
|
|
84 |
}
|
|
85 |
|
|
86 |
void
|
|
87 |
UeMemberLteUeCmacSapProvider::AddLc (uint8_t lcId, LteMacSapUser* msu)
|
|
88 |
{
|
|
89 |
m_mac->DoAddLc (lcId, msu);
|
|
90 |
}
|
|
91 |
|
|
92 |
void
|
|
93 |
UeMemberLteUeCmacSapProvider::RemoveLc (uint8_t lcid)
|
|
94 |
{
|
|
95 |
m_mac->DoRemoveLc (lcid);
|
|
96 |
}
|
|
97 |
|
|
98 |
|
|
99 |
|
|
100 |
class UeMemberLteMacSapProvider : public LteMacSapProvider
|
|
101 |
{
|
|
102 |
public:
|
|
103 |
UeMemberLteMacSapProvider (LteUeMac* mac);
|
|
104 |
|
|
105 |
// inherited from LteMacSapProvider
|
|
106 |
virtual void TransmitPdu (TransmitPduParameters params);
|
|
107 |
virtual void ReportBufferStatus (ReportBufferStatusParameters params);
|
|
108 |
|
|
109 |
private:
|
|
110 |
LteUeMac* m_mac;
|
|
111 |
};
|
|
112 |
|
|
113 |
|
|
114 |
UeMemberLteMacSapProvider::UeMemberLteMacSapProvider (LteUeMac* mac)
|
|
115 |
: m_mac (mac)
|
|
116 |
{
|
|
117 |
}
|
|
118 |
|
|
119 |
void
|
|
120 |
UeMemberLteMacSapProvider::TransmitPdu (TransmitPduParameters params)
|
|
121 |
{
|
|
122 |
m_mac->DoTransmitPdu (params);
|
|
123 |
}
|
|
124 |
|
|
125 |
|
|
126 |
void
|
|
127 |
UeMemberLteMacSapProvider::ReportBufferStatus (ReportBufferStatusParameters params)
|
|
128 |
{
|
|
129 |
m_mac->DoReportBufferStatus (params);
|
|
130 |
}
|
|
131 |
|
|
132 |
|
|
133 |
|
|
134 |
|
|
135 |
class UeMemberUeLtePhySapUser : public LteUePhySapUser
|
|
136 |
{
|
|
137 |
public:
|
|
138 |
UeMemberUeLtePhySapUser (LteUeMac* mac);
|
|
139 |
|
|
140 |
// inherited from LtePhySapUser
|
|
141 |
virtual void ReceivePhyPdu (Ptr<Packet> p);
|
|
142 |
virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo);
|
|
143 |
virtual void ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg);
|
|
144 |
|
|
145 |
private:
|
|
146 |
LteUeMac* m_mac;
|
|
147 |
};
|
|
148 |
|
|
149 |
UeMemberUeLtePhySapUser::UeMemberUeLtePhySapUser (LteUeMac* mac) : m_mac (mac)
|
|
150 |
{
|
|
151 |
|
|
152 |
}
|
|
153 |
|
|
154 |
void
|
|
155 |
UeMemberUeLtePhySapUser::ReceivePhyPdu (Ptr<Packet> p)
|
|
156 |
{
|
|
157 |
m_mac->DoReceivePhyPdu (p);
|
|
158 |
}
|
|
159 |
|
|
160 |
|
|
161 |
void
|
|
162 |
UeMemberUeLtePhySapUser::SubframeIndication (uint32_t frameNo, uint32_t subframeNo)
|
|
163 |
{
|
|
164 |
NS_LOG_LOGIC (this << " UE-MAC does not yet support this primitive");
|
|
165 |
}
|
|
166 |
|
|
167 |
void
|
|
168 |
UeMemberUeLtePhySapUser::ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg)
|
|
169 |
{
|
|
170 |
m_mac->DoReceiveIdealControlMessage (msg);
|
|
171 |
}
|
|
172 |
|
|
173 |
|
|
174 |
|
|
175 |
|
|
176 |
//////////////////////////////////////////////////////////
|
|
177 |
// LteUeMac methods
|
|
178 |
///////////////////////////////////////////////////////////
|
|
179 |
|
|
180 |
|
|
181 |
TypeId
|
|
182 |
LteUeMac::GetTypeId (void)
|
|
183 |
{
|
|
184 |
static TypeId tid = TypeId ("ns3::LteUeMac")
|
|
185 |
.SetParent<Object> ()
|
|
186 |
.AddConstructor<LteUeMac> ();
|
|
187 |
return tid;
|
|
188 |
}
|
|
189 |
|
|
190 |
|
|
191 |
LteUeMac::LteUeMac ()
|
|
192 |
{
|
|
193 |
m_macSapProvider = new UeMemberLteMacSapProvider (this);
|
|
194 |
m_cmacSapProvider = new UeMemberLteUeCmacSapProvider (this);
|
|
195 |
m_uePhySapUser = new UeMemberUeLtePhySapUser (this);
|
|
196 |
}
|
|
197 |
|
|
198 |
|
|
199 |
LteUeMac::~LteUeMac ()
|
|
200 |
{
|
|
201 |
}
|
|
202 |
|
|
203 |
void
|
|
204 |
LteUeMac::DoDispose ()
|
|
205 |
{
|
|
206 |
delete m_macSapProvider;
|
|
207 |
delete m_cmacSapProvider;
|
|
208 |
Object::DoDispose ();
|
|
209 |
}
|
|
210 |
|
|
211 |
|
|
212 |
LteUePhySapUser*
|
|
213 |
LteUeMac::GetLteUePhySapUser (void)
|
|
214 |
{
|
|
215 |
return m_uePhySapUser;
|
|
216 |
}
|
|
217 |
|
|
218 |
void
|
|
219 |
LteUeMac::SetLteUePhySapProvider (LteUePhySapProvider* s)
|
|
220 |
{
|
|
221 |
m_uePhySapProvider = s;
|
|
222 |
}
|
|
223 |
|
|
224 |
|
|
225 |
LteMacSapProvider*
|
|
226 |
LteUeMac::GetLteMacSapProvider (void)
|
|
227 |
{
|
|
228 |
return m_macSapProvider;
|
|
229 |
}
|
|
230 |
|
|
231 |
void
|
|
232 |
LteUeMac::SetLteUeCmacSapUser (LteUeCmacSapUser* s)
|
|
233 |
{
|
|
234 |
m_cmacSapUser = s;
|
|
235 |
}
|
|
236 |
|
|
237 |
LteUeCmacSapProvider*
|
|
238 |
LteUeMac::GetLteUeCmacSapProvider (void)
|
|
239 |
{
|
|
240 |
return m_cmacSapProvider;
|
|
241 |
}
|
|
242 |
|
|
243 |
|
|
244 |
void
|
|
245 |
LteUeMac::DoTransmitPdu (LteMacSapProvider::TransmitPduParameters params)
|
|
246 |
{
|
|
247 |
NS_LOG_FUNCTION (this);
|
|
248 |
NS_ASSERT_MSG (m_rnti == params.rnti, "RNTI mismatch between RLC and MAC");
|
|
249 |
LteMacTag tag (params.rnti, params.lcid);
|
|
250 |
params.pdu->AddPacketTag (tag);
|
|
251 |
// Ptr<PacketBurst> pb = CreateObject<PacketBurst> ();
|
|
252 |
// pb->AddPacket (params.pdu);
|
|
253 |
m_uePhySapProvider->SendMacPdu (params.pdu);
|
|
254 |
// Uplink not implemented yet, so we wait can wait for the PHY SAP
|
|
255 |
// to be defined before we implement the transmission method.
|
|
256 |
}
|
|
257 |
|
|
258 |
void
|
|
259 |
LteUeMac::DoReportBufferStatus (LteMacSapProvider::ReportBufferStatusParameters params)
|
|
260 |
{
|
|
261 |
NS_LOG_FUNCTION (this);
|
|
262 |
MacCeListElement_s bsr;
|
|
263 |
bsr.m_rnti = m_rnti;
|
|
264 |
bsr.m_macCeType = MacCeListElement_s::BSR;
|
|
265 |
// short BSR
|
|
266 |
int queue = params.txQueueSize;
|
|
267 |
int index = 0;
|
|
268 |
if (BufferSizeLevelBsr[63] < queue)
|
|
269 |
{
|
|
270 |
index = 63;
|
|
271 |
}
|
|
272 |
else
|
|
273 |
{
|
|
274 |
while (BufferSizeLevelBsr[index] < queue)
|
|
275 |
{
|
|
276 |
index++;
|
|
277 |
}
|
|
278 |
}
|
|
279 |
bsr.m_macCeValue.m_bufferStatus.push_back (index);
|
|
280 |
|
|
281 |
// create the feedback to eNB
|
|
282 |
Ptr<BsrIdealControlMessage> msg = Create<BsrIdealControlMessage> ();
|
|
283 |
msg->SetBsr (bsr);
|
|
284 |
m_uePhySapProvider->SendIdealControlMessage (msg);
|
|
285 |
|
|
286 |
}
|
|
287 |
|
|
288 |
void
|
|
289 |
LteUeMac::DoConfigureUe (uint16_t rnti)
|
|
290 |
{
|
|
291 |
NS_LOG_FUNCTION (this << " rnti" << rnti);
|
|
292 |
m_rnti = rnti;
|
|
293 |
}
|
|
294 |
|
|
295 |
void
|
|
296 |
LteUeMac::DoAddLc (uint8_t lcId, LteMacSapUser* msu)
|
|
297 |
{
|
|
298 |
NS_LOG_FUNCTION (this << " lcId" << lcId);
|
|
299 |
NS_ASSERT_MSG (m_macSapUserMap.find (lcId) == m_macSapUserMap.end (), "cannot add channel because LCID " << lcId << " is already present");
|
|
300 |
m_macSapUserMap[lcId] = msu;
|
|
301 |
}
|
|
302 |
|
|
303 |
void
|
|
304 |
LteUeMac::DoRemoveLc (uint8_t lcId)
|
|
305 |
{
|
|
306 |
NS_LOG_FUNCTION (this << " lcId" << lcId);
|
|
307 |
NS_ASSERT_MSG (m_macSapUserMap.find (lcId) == m_macSapUserMap.end (), "could not find LCID " << lcId);
|
|
308 |
m_macSapUserMap.erase (lcId);
|
|
309 |
}
|
|
310 |
|
|
311 |
|
|
312 |
void
|
|
313 |
LteUeMac::DoReceivePhyPdu (Ptr<Packet> p)
|
|
314 |
{
|
|
315 |
LteMacTag tag;
|
|
316 |
p->RemovePacketTag (tag);
|
|
317 |
if (tag.GetRnti () == m_rnti)
|
|
318 |
{
|
|
319 |
// packet is for the current user
|
|
320 |
std::map <uint8_t, LteMacSapUser*>::const_iterator it = m_macSapUserMap.find (tag.GetLcid ());
|
|
321 |
NS_ASSERT_MSG (it != m_macSapUserMap.end (), "received packet with unknown lcid");
|
|
322 |
it->second->ReceivePdu (p);
|
|
323 |
}
|
|
324 |
}
|
|
325 |
|
|
326 |
|
|
327 |
void
|
|
328 |
LteUeMac::DoReceiveIdealControlMessage (Ptr<IdealControlMessage> msg)
|
|
329 |
{
|
|
330 |
NS_LOG_FUNCTION (this);
|
|
331 |
if (msg->GetMessageType () == IdealControlMessage::UL_DCI)
|
|
332 |
{
|
|
333 |
Ptr<UlDciIdealControlMessage> msg2 = DynamicCast<UlDciIdealControlMessage> (msg);
|
|
334 |
UlDciListElement_s dci = msg2->GetDci ();
|
|
335 |
std::map <uint8_t, LteMacSapUser*>::iterator it;
|
|
336 |
it = m_macSapUserMap.begin (); // use only the first LC --> UE-SCHEDULER??
|
|
337 |
(*it).second->NotifyTxOpportunity (dci.m_tbSize);
|
|
338 |
|
|
339 |
}
|
|
340 |
else
|
|
341 |
{
|
|
342 |
NS_LOG_FUNCTION (this << " IdealControlMessage not recognized");
|
|
343 |
}
|
|
344 |
}
|
|
345 |
|
|
346 |
|
|
347 |
} // namespace ns3
|