1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2011,2012 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: Manuel Requena <manuel.requena@cttc.es>
19 * Nicola Baldo <nbaldo@cttc.es>
20 */
21
22 #include "ns3/simulator.h"
23 #include "ns3/log.h"
24
25 #include "ns3/lte-rlc-tm.h"
26
27 namespace ns3 {
28
29 NS_LOG_COMPONENT_DEFINE ("LteRlcTm");
30
31 NS_OBJECT_ENSURE_REGISTERED (LteRlcTm);
32
LteRlcTm()33 LteRlcTm::LteRlcTm ()
34 : m_maxTxBufferSize (0),
35 m_txBufferSize (0)
36 {
37 NS_LOG_FUNCTION (this);
38 }
39
~LteRlcTm()40 LteRlcTm::~LteRlcTm ()
41 {
42 NS_LOG_FUNCTION (this);
43 }
44
45 TypeId
GetTypeId(void)46 LteRlcTm::GetTypeId (void)
47 {
48 static TypeId tid = TypeId ("ns3::LteRlcTm")
49 .SetParent<LteRlc> ()
50 .SetGroupName("Lte")
51 .AddConstructor<LteRlcTm> ()
52 .AddAttribute ("MaxTxBufferSize",
53 "Maximum Size of the Transmission Buffer (in Bytes)",
54 UintegerValue (2 * 1024 * 1024),
55 MakeUintegerAccessor (&LteRlcTm::m_maxTxBufferSize),
56 MakeUintegerChecker<uint32_t> ())
57 ;
58 return tid;
59 }
60
61 void
DoDispose()62 LteRlcTm::DoDispose ()
63 {
64 NS_LOG_FUNCTION (this);
65 m_rbsTimer.Cancel ();
66 m_txBuffer.clear ();
67
68 LteRlc::DoDispose ();
69 }
70
71
72 /**
73 * RLC SAP
74 */
75
76 void
DoTransmitPdcpPdu(Ptr<Packet> p)77 LteRlcTm::DoTransmitPdcpPdu (Ptr<Packet> p)
78 {
79 NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
80
81 if (m_txBufferSize + p->GetSize () <= m_maxTxBufferSize)
82 {
83 NS_LOG_LOGIC ("Tx Buffer: New packet added");
84 m_txBuffer.push_back (TxPdu (p, Simulator::Now ()));
85 m_txBufferSize += p->GetSize ();
86 NS_LOG_LOGIC ("NumOfBuffers = " << m_txBuffer.size() );
87 NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
88 }
89 else
90 {
91 // Discard full RLC SDU
92 NS_LOG_LOGIC ("TxBuffer is full. RLC SDU discarded");
93 NS_LOG_LOGIC ("MaxTxBufferSize = " << m_maxTxBufferSize);
94 NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
95 NS_LOG_LOGIC ("packet size = " << p->GetSize ());
96 }
97
98 /** Report Buffer Status */
99 DoReportBufferStatus ();
100 m_rbsTimer.Cancel ();
101 }
102
103
104 /**
105 * MAC SAP
106 */
107
108 void
DoNotifyTxOpportunity(LteMacSapUser::TxOpportunityParameters txOpParams)109 LteRlcTm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpParams)
110 {
111 NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << txOpParams.bytes << (uint32_t) txOpParams.layer << (uint32_t) txOpParams.harqId);
112
113 // 5.1.1.1 Transmit operations
114 // 5.1.1.1.1 General
115 // When submitting a new TMD PDU to lower layer, the transmitting TM RLC entity shall:
116 // - submit a RLC SDU without any modification to lower layer.
117
118
119 if ( m_txBuffer.size () == 0 )
120 {
121 NS_LOG_LOGIC ("No data pending");
122 return;
123 }
124
125 Ptr<Packet> packet = m_txBuffer.begin ()->m_pdu->Copy ();
126
127 if (txOpParams.bytes < packet->GetSize ())
128 {
129 NS_LOG_WARN ("TX opportunity too small = " << txOpParams.bytes <<
130 " (PDU size: " << packet->GetSize () << ")");
131 return;
132 }
133
134 m_txBufferSize -= packet->GetSize ();
135 m_txBuffer.erase (m_txBuffer.begin ());
136
137 m_txPdu (m_rnti, m_lcid, packet->GetSize ());
138
139 // Send RLC PDU to MAC layer
140 LteMacSapProvider::TransmitPduParameters params;
141 params.pdu = packet;
142 params.rnti = m_rnti;
143 params.lcid = m_lcid;
144 params.layer = txOpParams.layer;
145 params.harqProcessId = txOpParams.harqId;
146 params.componentCarrierId = txOpParams.componentCarrierId;
147
148 m_macSapProvider->TransmitPdu (params);
149
150 if (! m_txBuffer.empty ())
151 {
152 m_rbsTimer.Cancel ();
153 m_rbsTimer = Simulator::Schedule (MilliSeconds (10), &LteRlcTm::ExpireRbsTimer, this);
154 }
155 }
156
157 void
DoNotifyHarqDeliveryFailure()158 LteRlcTm::DoNotifyHarqDeliveryFailure ()
159 {
160 NS_LOG_FUNCTION (this);
161 }
162
163 void
DoReceivePdu(LteMacSapUser::ReceivePduParameters rxPduParams)164 LteRlcTm::DoReceivePdu (LteMacSapUser::ReceivePduParameters rxPduParams)
165 {
166 NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << rxPduParams.p->GetSize ());
167
168 m_rxPdu (m_rnti, m_lcid, rxPduParams.p->GetSize (), 0);
169
170 // 5.1.1.2 Receive operations
171 // 5.1.1.2.1 General
172 // When receiving a new TMD PDU from lower layer, the receiving TM RLC entity shall:
173 // - deliver the TMD PDU without any modification to upper layer.
174
175 m_rlcSapUser->ReceivePdcpPdu (rxPduParams.p);
176 }
177
178
179 void
DoReportBufferStatus(void)180 LteRlcTm::DoReportBufferStatus (void)
181 {
182 Time holDelay (0);
183 uint32_t queueSize = 0;
184
185 if (! m_txBuffer.empty ())
186 {
187 holDelay = Simulator::Now () - m_txBuffer.front ().m_waitingSince;
188
189 queueSize = m_txBufferSize; // just data in tx queue (no header overhead for RLC TM)
190 }
191
192 LteMacSapProvider::ReportBufferStatusParameters r;
193 r.rnti = m_rnti;
194 r.lcid = m_lcid;
195 r.txQueueSize = queueSize;
196 r.txQueueHolDelay = holDelay.GetMilliSeconds () ;
197 r.retxQueueSize = 0;
198 r.retxQueueHolDelay = 0;
199 r.statusPduSize = 0;
200
201 NS_LOG_LOGIC ("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay );
202 m_macSapProvider->ReportBufferStatus (r);
203 }
204
205 void
ExpireRbsTimer(void)206 LteRlcTm::ExpireRbsTimer (void)
207 {
208 NS_LOG_LOGIC ("RBS Timer expires");
209
210 if (! m_txBuffer.empty ())
211 {
212 DoReportBufferStatus ();
213 m_rbsTimer = Simulator::Schedule (MilliSeconds (10), &LteRlcTm::ExpireRbsTimer, this);
214 }
215 }
216
217 } // namespace ns3
218