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);
264 params.
layer = layer;
278 NS_LOG_LOGIC (
"Sending data from Retransmission Buffer");
285 uint16_t seqNumberValue = sn.
GetValue ();
293 if (( packet->
GetSize () <= bytes )
307 <<
" packet->GetSize ()=" << packet->
GetSize ());
345 params.
layer = layer;
351 NS_LOG_INFO (
"Incr RETX_COUNT for SN = " << seqNumberValue);
354 NS_LOG_INFO (
"Max RETX_COUNT for SN = " << seqNumberValue);
357 NS_LOG_INFO (
"Move SN = " << seqNumberValue <<
" back to txedBuffer");
372 NS_LOG_LOGIC (
"TxOpportunity (size = " << bytes <<
") too small for retransmission of the packet (size = " << packet->
GetSize () <<
")");
378 NS_ASSERT_MSG (found,
"m_retxBufferSize > 0, but no PDU considered for retx found");
385 NS_LOG_LOGIC (
"TxOpportunity (size = " << bytes <<
") too small for DATA PDU");
386 NS_ASSERT_MSG (
false,
"TxOpportunity (size = " << bytes <<
") too small for DATA PDU\n"
387 <<
"Your MAC scheduler is assigned too few resource blocks.");
394 NS_LOG_INFO (
"cannot transmit new RLC PDU due to window stalling");
417 uint32_t nextSegmentSize = bytes - 4;
418 uint32_t nextSegmentId = 1;
419 uint32_t dataFieldTotalSize = 0;
420 uint32_t dataFieldAddedSize = 0;
421 std::vector < Ptr<Packet> > dataField;
434 NS_LOG_LOGIC (
"Next segment size = " << nextSegmentSize);
441 while ( firstSegment && (firstSegment->
GetSize () > 0) && (nextSegmentSize > 0) )
443 NS_LOG_LOGIC (
"WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
445 NS_LOG_LOGIC (
" nextSegmentSize = " << nextSegmentSize);
446 if ( (firstSegment->
GetSize () > nextSegmentSize) ||
448 (firstSegment->
GetSize () > 2047)
453 uint32_t currSegmentSize = std::min (firstSegment->
GetSize (), nextSegmentSize);
455 NS_LOG_LOGIC (
" IF ( firstSegment > nextSegmentSize ||");
483 if (firstSegment->
GetSize () > 0)
490 NS_LOG_LOGIC (
" Txon buffer: Give back the remaining segment");
515 dataFieldAddedSize = newSegment->
GetSize ();
516 dataFieldTotalSize += dataFieldAddedSize;
517 dataField.push_back (newSegment);
525 nextSegmentSize -= dataFieldAddedSize;
533 else if ( (nextSegmentSize - firstSegment->
GetSize () <= 2) || (
m_txonBuffer.size () == 0) )
535 NS_LOG_LOGIC (
" IF nextSegmentSize - firstSegment->GetSize () <= 2 || txonBuffer.size == 0");
538 dataFieldAddedSize = firstSegment->
GetSize ();
539 dataFieldTotalSize += dataFieldAddedSize;
540 dataField.push_back (firstSegment);
548 nextSegmentSize -= dataFieldAddedSize;
557 NS_LOG_LOGIC (
" Next segment size = " << nextSegmentSize);
566 NS_LOG_LOGIC (
" IF firstSegment < NextSegmentSize && txonBuffer.size > 0");
568 dataFieldAddedSize = firstSegment->
GetSize ();
569 dataFieldTotalSize += dataFieldAddedSize;
570 dataField.push_back (firstSegment);
576 rlcAmHeader.PushLengthIndicator (firstSegment->
GetSize ());
578 nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
587 NS_LOG_LOGIC (
" Next segment size = " << nextSegmentSize);
603 rlcAmHeader.SetSequenceNumber (
m_vtS++ );
606 rlcAmHeader.SetSegmentOffset (0);
612 uint8_t framingInfo = 0;
613 std::vector< Ptr<Packet> >::iterator it;
614 it = dataField.begin ();
618 (*it)->RemovePacketTag (tag);
629 (*it)->AddPacketTag (tag);
632 while (it < dataField.end ())
634 NS_LOG_LOGIC (
"Adding SDU/segment to packet, length = " << (*it)->GetSize ());
642 (*it)->RemovePacketTag (tag);
652 (*it)->AddPacketTag (tag);
655 rlcAmHeader.SetFramingInfo (framingInfo);
705 m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_pdu = packet->
Copy ();
706 m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_retxCount = 0;
718 params.layer = layer;
719 params.harqProcessId = harqId;
750 if ( rlcAmHeader.IsDataPdu () )
808 NS_LOG_LOGIC (
"PDU segment received ( SN = " << seqNumber <<
" )");
812 NS_LOG_LOGIC (
"PDU received ( SN = " << seqNumber <<
" )");
816 NS_ASSERT_MSG (
false,
"Neither a PDU segment nor a PDU received");
866 NS_ASSERT (it->second.m_byteSegments.size () > 0);
867 NS_ASSERT_MSG (it->second.m_byteSegments.size () == 1,
"re-segmentation not supported");
868 NS_LOG_LOGIC (
"PDU segment already received, discarded");
872 NS_LOG_LOGIC (
"Place PDU in the reception buffer ( SN = " << seqNumber <<
" )");
887 if ( seqNumber >=
m_vrH )
889 m_vrH = seqNumber + 1;
899 it->second.m_pduComplete )
903 it->second.m_pduComplete )
920 if ( seqNumber ==
m_vrR )
924 it->second.m_pduComplete )
929 it->second.m_pduComplete )
933 "Too many segments. PDU Reassembly process didn't work");
990 else if ( rlcAmHeader.IsControlPdu () )
1009 bool incrementVtA =
true;
1011 for (sn =
m_vtA; sn < ackSn && sn <
m_vtS; sn++)
1015 uint16_t seqNumberValue = sn.
GetValue ();
1023 if (rlcAmHeader.IsNackPresent (sn))
1027 incrementVtA =
false;
1031 NS_LOG_INFO (
"Move SN = " << seqNumberValue <<
" to retxBuffer");
1050 NS_LOG_INFO (
"ACKed SN = " << seqNumberValue <<
" from txedBuffer");
1059 NS_LOG_INFO (
"ACKed SN = " << seqNumberValue <<
" from retxBuffer");
1077 m_vtS.SetModulusBase (
m_vtA);
1101 m_vrR <<
" <= " << seqNumber <<
" <= " <<
m_vrMr);
1107 if ( (
m_vrR <= seqNumber) && (seqNumber <
m_vrMr ) )
1109 NS_LOG_LOGIC (seqNumber <<
" is INSIDE the receiving window");
1114 NS_LOG_LOGIC (seqNumber <<
" is OUTSIDE the receiving window");
1127 bool expectedSnLost;
1131 expectedSnLost =
true;
1137 expectedSnLost =
false;
1143 uint8_t extensionBit;
1144 uint16_t lengthIndicator;
1150 if ( extensionBit == 0 )
1160 if ( lengthIndicator >= packet->
GetSize () )
1162 NS_LOG_LOGIC (
"INTERNAL ERROR: Not enough data in the packet (" << packet->
GetSize () <<
"). Needed LI=" << lengthIndicator);
1173 while ( extensionBit == 1 );
1175 std::list < Ptr<Packet> >::iterator it;
1180 else NS_LOG_LOGIC (
"Reassembling State = Unknown state");
1183 NS_LOG_LOGIC (
"Framing Info = " << (uint16_t)framingInfo);
1187 if (!expectedSnLost)
1192 switch (framingInfo)
1232 NS_LOG_LOGIC (
"INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1238 switch (framingInfo)
1303 NS_LOG_LOGIC (
"INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1318 switch (framingInfo)
1408 NS_LOG_LOGIC (
"INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1414 switch (framingInfo)
1525 NS_LOG_LOGIC (
"INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1552 Time txonQueueHolDelay (0);
1555 RlcTag txonQueueHolTimeTag;
1556 m_txonBuffer.front ()->PeekPacketTag (txonQueueHolTimeTag);
1561 Time retxQueueHolDelay;
1562 RlcTag retxQueueHolTimeTag;
1577 retxQueueHolDelay =
Seconds (0);
1629 it->second.m_pduComplete )
1680 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.
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Simulation virtual time values and global simulation resolution.
EventId m_statusProhibitTimer
#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
AttributeValue implementation for Boolean.
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
virtual void DoReceivePdu(Ptr< Packet > p)
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
virtual void DoNotifyTxOpportunity(uint32_t bytes, uint8_t layer, uint8_t harqId)
MAC SAP.
uint32_t m_statusPduBufferSize
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
void DoReportBufferStatus()
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Time m_reorderingTimerValue
#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
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
EventId m_reorderingTimer
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)
std::vector< RetxPdu > m_txedBuffer
Buffer for transmitted and retransmitted PDUs that have not been acked but are not considered for ret...
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
uint16_t rnti
the C-RNTI identifying the UE
EventId m_pollRetransmitTimer
Timers.
void SetModulusBase(SequenceNumber10 modulusBase)
void ExpireRbsTimer(void)
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
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.
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
LteRlcSapUser * m_rlcSapUser
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
std::map< uint16_t, PduBuffer > m_rxonBuffer
AttributeValue implementation for Time.
uint16_t rnti
the C-RNTI identifying the UE
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
virtual void DoDispose()
Destructor implementation.
SequenceNumber10 m_pollSn
LteMacSapProvider * m_macSapProvider
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
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.
uint8_t layer
the layer value that was passed by the MAC in the call to NotifyTxOpportunity that generated this PDU...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::list< Ptr< Packet > > m_sdusBuffer
Ptr< const AttributeChecker > MakeBooleanChecker(void)
bool m_pollRetransmitTimerJustExpired
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...
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
Time m_statusProhibitTimerValue
virtual void DoNotifyHarqDeliveryFailure()
uint16_t m_maxRetxThreshold
Configurable parameters.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
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)
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)
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
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
void ReassembleAndDeliver(Ptr< Packet > packet)
uint16_t m_windowSize
Constants.
uint8_t harqProcessId
the HARQ process id that was passed by the MAC in the call to NotifyTxOpportunity that generated this...
bool m_txOpportunityForRetxAlwaysBigEnough
virtual void TransmitPdu(TransmitPduParameters params)=0
send an RLC PDU to the MAC for transmission.
ReassemblingState_t m_reassemblingState
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
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
TypeId SetParent(TypeId tid)
static TypeId GetTypeId(void)
bool m_statusPduRequested
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.
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Parameters for LteMacSapProvider::TransmitPdu.