22 #include "ns3/simulator.h"
25 #include "ns3/lte-rlc-am-header.h"
26 #include "ns3/lte-rlc-am.h"
27 #include "ns3/lte-rlc-sdu-status-tag.h"
28 #include "ns3/lte-rlc-tag.h"
94 .AddAttribute (
"PollRetransmitTimer",
95 "Value of the t-PollRetransmit timer (See section 7.3 of 3GPP TS 36.322)",
99 .AddAttribute (
"ReorderingTimer",
100 "Value of the t-Reordering timer (See section 7.3 of 3GPP TS 36.322)",
104 .AddAttribute (
"StatusProhibitTimer",
105 "Value of the t-StatusProhibit timer (See section 7.3 of 3GPP TS 36.322)",
109 .AddAttribute (
"ReportBufferStatusTimer",
110 "How much to wait to issue a new Report Buffer Status since the last time "
111 "a new SDU was received",
115 .AddAttribute (
"TxOpportunityForRetxAlwaysBigEnough",
116 "If true, always pretend that the size of a TxOpportunity is big enough "
117 "for retransmission. If false (default and realistic behavior), no retx "
118 "is performed unless the corresponding TxOpportunity is big enough.",
197 NS_LOG_LOGIC (
"TxOpportunity (size = " << bytes <<
") too small");
198 NS_ASSERT_MSG (
false,
"TxOpportunity (size = " << bytes <<
") too small.\n"
199 <<
"Your MAC scheduler is assigned too few resource blocks.");
210 <<
"Your MAC scheduler is assigned too few resource blocks.");
223 std::map<uint16_t, PduBuffer>::iterator pduIt;
227 if (!rlcAmHeader.OneMoreNackWouldFitIn (bytes))
233 if (pduIt ==
m_rxonBuffer.end () || (!(pduIt->second.m_pduComplete)))
236 rlcAmHeader.PushNack (sn.GetValue ());
244 while ((sn < m_vrMs) && (pduIt !=
m_rxonBuffer.end ()) && (pduIt->second.m_pduComplete))
246 NS_LOG_LOGIC (
"SN = " << sn <<
" < " << m_vrMs <<
" = " << (sn < m_vrMs));
252 NS_ASSERT_MSG (sn <= m_vrMs,
"first SN not reported as missing = " << sn <<
", VR(MS) = " << m_vrMs);
253 rlcAmHeader.SetAckSn (sn);
270 params.layer = layer;
271 params.harqProcessId = harqId;
272 params.componentCarrierId = componentCarrierId;
285 NS_LOG_LOGIC (
"Sending data from Retransmission Buffer");
291 uint16_t seqNumberValue = sn.
GetValue ();
299 if (( packet->
GetSize () <= bytes )
312 <<
" packet->GetSize ()=" << packet->
GetSize ());
356 params.layer = layer;
357 params.harqProcessId = harqId;
358 params.componentCarrierId = componentCarrierId;
363 NS_LOG_INFO (
"Incr RETX_COUNT for SN = " << seqNumberValue);
366 NS_LOG_INFO (
"Max RETX_COUNT for SN = " << seqNumberValue);
369 NS_LOG_INFO (
"Move SN = " << seqNumberValue <<
" back to txedBuffer");
384 NS_LOG_LOGIC (
"TxOpportunity (size = " << bytes <<
") too small for retransmission of the packet (size = " << packet->
GetSize () <<
")");
390 NS_ASSERT_MSG (
false,
"m_retxBufferSize > 0, but no PDU considered for retx found");
397 NS_LOG_LOGIC (
"TxOpportunity (size = " << bytes <<
") too small for DATA PDU");
398 NS_ASSERT_MSG (
false,
"TxOpportunity (size = " << bytes <<
") too small for DATA PDU\n"
399 <<
"Your MAC scheduler is assigned too few resource blocks.");
406 NS_LOG_INFO (
"cannot transmit new RLC PDU due to window stalling");
429 uint32_t nextSegmentSize = bytes - 4;
430 uint32_t nextSegmentId = 1;
431 uint32_t dataFieldTotalSize = 0;
432 uint32_t dataFieldAddedSize = 0;
433 std::vector < Ptr<Packet> > dataField;
446 NS_LOG_LOGIC (
"Next segment size = " << nextSegmentSize);
453 while ( firstSegment && (firstSegment->
GetSize () > 0) && (nextSegmentSize > 0) )
455 NS_LOG_LOGIC (
"WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
457 NS_LOG_LOGIC (
" nextSegmentSize = " << nextSegmentSize);
458 if ( (firstSegment->
GetSize () > nextSegmentSize) ||
460 (firstSegment->
GetSize () > 2047)
465 uint32_t currSegmentSize =
std::min (firstSegment->
GetSize (), nextSegmentSize);
467 NS_LOG_LOGIC (
" IF ( firstSegment > nextSegmentSize ||");
495 if (firstSegment->
GetSize () > 0)
502 NS_LOG_LOGIC (
" Txon buffer: Give back the remaining segment");
527 dataFieldAddedSize = newSegment->
GetSize ();
528 dataFieldTotalSize += dataFieldAddedSize;
529 dataField.push_back (newSegment);
537 nextSegmentSize -= dataFieldAddedSize;
545 else if ( (nextSegmentSize - firstSegment->
GetSize () <= 2) || (
m_txonBuffer.size () == 0) )
547 NS_LOG_LOGIC (
" IF nextSegmentSize - firstSegment->GetSize () <= 2 || txonBuffer.size == 0");
550 dataFieldAddedSize = firstSegment->
GetSize ();
551 dataFieldTotalSize += dataFieldAddedSize;
552 dataField.push_back (firstSegment);
560 nextSegmentSize -= dataFieldAddedSize;
569 NS_LOG_LOGIC (
" Next segment size = " << nextSegmentSize);
578 NS_LOG_LOGIC (
" IF firstSegment < NextSegmentSize && txonBuffer.size > 0");
580 dataFieldAddedSize = firstSegment->
GetSize ();
581 dataFieldTotalSize += dataFieldAddedSize;
582 dataField.push_back (firstSegment);
588 rlcAmHeader.PushLengthIndicator (firstSegment->
GetSize ());
590 nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
599 NS_LOG_LOGIC (
" Next segment size = " << nextSegmentSize);
615 rlcAmHeader.SetSequenceNumber (
m_vtS++ );
618 rlcAmHeader.SetSegmentOffset (0);
624 uint8_t framingInfo = 0;
625 std::vector< Ptr<Packet> >::iterator it;
626 it = dataField.begin ();
630 NS_ASSERT_MSG ((*it)->PeekPacketTag (tag),
"LteRlcSduStatusTag is missing");
631 (*it)->PeekPacketTag (tag);
644 while (it < dataField.end ())
646 NS_LOG_LOGIC (
"Adding SDU/segment to packet, length = " << (*it)->GetSize ());
648 NS_ASSERT_MSG ((*it)->PeekPacketTag (tag),
"LteRlcSduStatusTag is missing");
649 (*it)->RemovePacketTag (tag);
674 rlcAmHeader.SetFramingInfo (framingInfo);
724 m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_pdu = packet->
Copy ();
725 m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_retxCount = 0;
737 params.layer = layer;
738 params.harqProcessId = harqId;
739 params.componentCarrierId = componentCarrierId;
769 if ( rlcAmHeader.IsDataPdu () )
827 NS_LOG_LOGIC (
"PDU segment received ( SN = " << seqNumber <<
" )");
831 NS_LOG_LOGIC (
"PDU received ( SN = " << seqNumber <<
" )");
835 NS_ASSERT_MSG (
false,
"Neither a PDU segment nor a PDU received");
885 NS_ASSERT (it->second.m_byteSegments.size () > 0);
886 NS_ASSERT_MSG (it->second.m_byteSegments.size () == 1,
"re-segmentation not supported");
887 NS_LOG_LOGIC (
"PDU segment already received, discarded");
891 NS_LOG_LOGIC (
"Place PDU in the reception buffer ( SN = " << seqNumber <<
" )");
906 if ( seqNumber >=
m_vrH )
908 m_vrH = seqNumber + 1;
918 it->second.m_pduComplete )
922 it->second.m_pduComplete )
939 if ( seqNumber ==
m_vrR )
943 it->second.m_pduComplete )
948 it->second.m_pduComplete )
952 "Too many segments. PDU Reassembly process didn't work");
1009 else if ( rlcAmHeader.IsControlPdu () )
1028 bool incrementVtA =
true;
1030 for (sn =
m_vtA; sn < ackSn && sn <
m_vtS; sn++)
1034 uint16_t seqNumberValue = sn.
GetValue ();
1042 if (rlcAmHeader.IsNackPresent (sn))
1046 incrementVtA =
false;
1050 NS_LOG_INFO (
"Move SN = " << seqNumberValue <<
" to retxBuffer");
1069 NS_LOG_INFO (
"ACKed SN = " << seqNumberValue <<
" from txedBuffer");
1078 NS_LOG_INFO (
"ACKed SN = " << seqNumberValue <<
" from retxBuffer");
1096 m_vtS.SetModulusBase (
m_vtA);
1120 m_vrR <<
" <= " << seqNumber <<
" <= " <<
m_vrMr);
1126 if ( (
m_vrR <= seqNumber) && (seqNumber <
m_vrMr ) )
1128 NS_LOG_LOGIC (seqNumber <<
" is INSIDE the receiving window");
1133 NS_LOG_LOGIC (seqNumber <<
" is OUTSIDE the receiving window");
1146 bool expectedSnLost;
1150 expectedSnLost =
true;
1156 expectedSnLost =
false;
1162 uint8_t extensionBit;
1163 uint16_t lengthIndicator;
1169 if ( extensionBit == 0 )
1179 if ( lengthIndicator >= packet->
GetSize () )
1181 NS_LOG_LOGIC (
"INTERNAL ERROR: Not enough data in the packet (" << packet->
GetSize () <<
"). Needed LI=" << lengthIndicator);
1192 while ( extensionBit == 1 );
1194 std::list < Ptr<Packet> >::iterator it;
1199 else NS_LOG_LOGIC (
"Reassembling State = Unknown state");
1202 NS_LOG_LOGIC (
"Framing Info = " << (uint16_t)framingInfo);
1206 if (!expectedSnLost)
1211 switch (framingInfo)
1251 NS_LOG_LOGIC (
"INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1257 switch (framingInfo)
1322 NS_LOG_LOGIC (
"INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1337 switch (framingInfo)
1427 NS_LOG_LOGIC (
"INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1433 switch (framingInfo)
1544 NS_LOG_LOGIC (
"INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1571 Time txonQueueHolDelay (0);
1574 RlcTag txonQueueHolTimeTag;
1575 m_txonBuffer.front ()->PeekPacketTag (txonQueueHolTimeTag);
1580 Time retxQueueHolDelay;
1581 RlcTag retxQueueHolTimeTag;
1596 retxQueueHolDelay =
Seconds (0);
1648 it->second.m_pduComplete )
1694 bool pduAvailable =
m_txedBuffer.at (sn.GetValue ()).m_pdu != 0;
1698 uint16_t snValue = sn.GetValue ();
1699 NS_LOG_INFO (
"Move PDU " << sn <<
" from txedBuffer to retxBuffer");
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
TracedCallback< uint16_t, uint8_t, uint32_t > m_txPdu
Used to inform of a PDU delivery to the MAC SAP provider.
Simulation virtual time values and global simulation resolution.
EventId m_statusProhibitTimer
status prohibit timer
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint32_t m_byteWithoutPoll
byte without poll
AttributeValue implementation for Boolean.
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
EventId m_rbsTimer
RBS timer.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
uint32_t m_statusPduBufferSize
status PDU buffer size
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
SequenceNumber10 m_vtS
VT(S)
virtual void DoReceivePdu(Ptr< Packet > p, uint16_t rnti, uint8_t lcid)
Receive PDU function.
void DoReportBufferStatus()
Report buffer status.
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
SequenceNumber10 m_vtMs
VT(MS)
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Time m_reorderingTimerValue
reordering timer value
SequenceNumber10 m_vrMs
VR(MS)
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time m_pollRetransmitTimerValue
poll retransmit time value
SequenceNumber10 m_vrR
VR(R)
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
EventId m_reorderingTimer
reordering timer
Time m_rbsTimerValue
RBS timer value.
uint32_t retxQueueSize
the current size of the RLC retransmission queue in bytes
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
bool IsInsideReceivingWindow(SequenceNumber10 seqNumber)
method called when the T_status_prohibit timer expires
std::vector< RetxPdu > m_txedBuffer
Buffer for transmitted and retransmitted PDUs that have not been acked but are not considered for ret...
uint16_t rnti
the C-RNTI identifying the UE
EventId m_pollRetransmitTimer
Timers.
void SetModulusBase(SequenceNumber10 modulusBase)
Set modulus base.
void ExpireRbsTimer(void)
Expire RBS timer.
Parameters for LteMacSapProvider::ReportBufferStatus.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
uint32_t m_txonBufferSize
transmit on buffer size
uint16_t txQueueHolDelay
the Head Of Line delay of the transmission queue
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
LteRlcSapUser * m_rlcSapUser
RLC SAP user.
NS_ASSERT_MSG(false,"Ipv4AddressGenerator::MaskToIndex(): Impossible")
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
virtual void DoNotifyTxOpportunity(uint32_t bytes, uint8_t layer, uint8_t harqId, uint8_t componentCarrierId, uint16_t rnti, uint8_t lcid)
MAC SAP.
std::map< uint16_t, PduBuffer > m_rxonBuffer
Reception buffer.
AttributeValue implementation for Time.
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
uint16_t m_pollPdu
poll PDU
virtual void ReceivePdcpPdu(Ptr< Packet > p)=0
Called by the RLC entity to notify the PDCP entity of the reception of a new PDCP PDU...
uint8_t GetStatus(void) const
Get status function.
Ptr< Packet > m_keepS0
keep S0
virtual void DoDispose()
Destructor implementation.
SequenceNumber10 m_pollSn
POLL_SN.
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::list< Ptr< Packet > > m_sdusBuffer
List of SDUs in a packet (PDU)
uint16_t m_pollByte
poll byte
SequenceNumber10 m_vrH
VR(H)
Ptr< const AttributeChecker > MakeBooleanChecker(void)
bool m_pollRetransmitTimerJustExpired
poll retransmit timer just expired?
SequenceNumber10 m_vrMr
VR(MR)
Time GetSenderTimestamp(void) const
Get the instant when the RLC delivers the PDU to the MAC SAP provider.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
SequenceNumber10 m_vrX
VR(X)
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
uint32_t m_pduWithoutPoll
Counters.
uint32_t txQueueSize
the current size of the RLC transmission queue
static Time Now(void)
Return the current simulation virtual time.
uint32_t m_txedBufferSize
transmit ed buffer size
Time m_statusProhibitTimerValue
status prohibit timer value
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
virtual void DoNotifyHarqDeliveryFailure()
Notify HARQ delivery failure.
uint16_t m_maxRetxThreshold
Configurable parameters.
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
uint16_t statusPduSize
the current size of the pending STATUS RLC PDU message in bytes
This class implements a tag that carries the status of a RLC SDU for the fragmentation process Status...
virtual void DoDispose()
Destructor implementation.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
void ExpireStatusProhibitTimer(void)
method called when the T_status_prohibit timer expires
void ExpirePollRetransmitTimer(void)
Expire poll retransmitter.
SequenceNumber10 m_vtA
State variables.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Time Seconds(double value)
Construct a Time in the indicated unit.
std::vector< RetxPdu > m_retxBuffer
Buffer for PDUs considered for retransmission.
void SetStatus(uint8_t status)
Set status function.
uint16_t retxQueueHolDelay
the Head Of Line delay of the retransmission queue
Ptr< Packet > pdu
the RLC PDU
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
virtual void ReportBufferStatus(ReportBufferStatusParameters params)=0
Report the RLC buffer status to the MAC.
std::vector< Ptr< Packet > > m_txonBuffer
Transmission buffer.
TracedCallback< uint16_t, uint8_t, uint32_t, uint64_t > m_rxPdu
Used to inform of a PDU reception from the MAC SAP user.
LTE RLC Acknowledged Mode (AM), see 3GPP TS 36.322.
Ptr< Packet > m_controlPduBuffer
Control PDU buffer (just one PDU)
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver.
uint16_t m_windowSize
Constants.
bool m_txOpportunityForRetxAlwaysBigEnough
transmit opportunity for retransmit?
virtual void TransmitPdu(TransmitPduParameters params)=0
send an RLC PDU to the MAC for transmission.
ReassemblingState_t m_reassemblingState
reassembling state
This abstract base class defines the API to interact with the Radio Link Control (LTE_RLC) in LTE...
a unique identifier for an interface.
uint32_t m_retxBufferSize
retransmit buffer size
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
static TypeId GetTypeId(void)
Get the type ID.
bool m_statusPduRequested
status PDU requested
void ExpireReorderingTimer(void)
This method will schedule a timeout at WaitReplyTimeout interval in the future, unless a timer is alr...
virtual void DoTransmitPdcpPdu(Ptr< Packet > p)
RLC SAP.
void AddHeader(const Header &header)
Add header to this packet.
Parameters for LteMacSapProvider::TransmitPdu.