--- a/src/lte/model/lte-rlc-am.cc Wed May 16 17:50:13 2012 +0200
+++ b/src/lte/model/lte-rlc-am.cc Thu May 17 16:09:36 2012 +0200
@@ -98,7 +98,7 @@
void
LteRlcAm::DoTransmitPdcpPdu (Ptr<Packet> p)
{
- NS_LOG_FUNCTION (this << p->GetSize ());
+ NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
/** Store arrival time */
Time now = Simulator::Now ();
@@ -164,8 +164,14 @@
void
LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer)
{
- NS_LOG_FUNCTION (this << bytes);
- NS_ASSERT_MSG (bytes > 2, "Tx opportunity too small = " << bytes);
+ NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << bytes);
+
+ if (bytes <= 2)
+ {
+ // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
+ NS_LOG_LOGIC ("TX opportunity too small = " << bytes);
+ return;
+ }
if ( m_statusPduRequested && ! m_statusProhibitTimer.IsRunning () )
{
@@ -176,7 +182,7 @@
rlcAmHeader.SetControlPdu (LteRlcAmHeader::STATUS_PDU);
rlcAmHeader.SetAckSn (m_vrR);
- NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader);
+ NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
packet->AddHeader (rlcAmHeader);
// Send RLC PDU to MAC layer
@@ -198,7 +204,7 @@
{
LteRlcAmHeader rlcAmHeader;
packet->PeekHeader (rlcAmHeader);
- NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader);
+ NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
// Send RLC PDU to MAC layer
LteMacSapProvider::TransmitPduParameters params;
@@ -263,20 +269,30 @@
while ( firstSegment && (firstSegment->GetSize () > 0) && (nextSegmentSize > 0) )
{
- NS_LOG_LOGIC ("WHILE .. firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 ..");
- NS_LOG_LOGIC (" FirstSegment size = " << firstSegment->GetSize ());
- NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
- if ( firstSegment->GetSize () > nextSegmentSize )
+ NS_LOG_LOGIC ("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
+ NS_LOG_LOGIC (" firstSegment size = " << firstSegment->GetSize ());
+ NS_LOG_LOGIC (" nextSegmentSize = " << nextSegmentSize);
+ if ( (firstSegment->GetSize () > nextSegmentSize) ||
+ // Segment larger than 2047 octets can only be mapped to the end of the Data field
+ (firstSegment->GetSize () > 2047)
+ )
{
- NS_LOG_LOGIC (" IF firstSegment > NextSegmentSize");
+ // Take the minimum size, due to the 2047-bytes 3GPP exception
+ // This exception is due to the length of the LI field (just 11 bits)
+ uint32_t currSegmentSize = std::min (firstSegment->GetSize (), nextSegmentSize);
+
+ NS_LOG_LOGIC (" IF ( firstSegment > nextSegmentSize ||");
+ NS_LOG_LOGIC (" firstSegment > 2047 )");
+
// Segment txBuffer.FirstBuffer and
// Give back the remaining segment to the transmission buffer
- Ptr<Packet> newSegment = firstSegment->CreateFragment (0, nextSegmentSize);
+ Ptr<Packet> newSegment = firstSegment->CreateFragment (0, currSegmentSize);
+ NS_LOG_LOGIC (" newSegment size = " << newSegment->GetSize ());
// Status tag of the new and remaining segments
// Note: This is the only place where a PDU is segmented and
// therefore its status can change
- LteRlcSduStatusTag oldTag, newTag; // TODO CreateFragment copy the tag???
+ LteRlcSduStatusTag oldTag, newTag;
firstSegment->RemovePacketTag (oldTag);
newSegment->RemovePacketTag (newTag);
if (oldTag.GetStatus () == LteRlcSduStatusTag::FULL_SDU)
@@ -289,25 +305,46 @@
newTag.SetStatus (LteRlcSduStatusTag::MIDDLE_SEGMENT);
//oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
}
- firstSegment->AddPacketTag (oldTag);
- newSegment->AddPacketTag (newTag); // TODO What happens if we add two tags???
// Give back the remaining segment to the transmission buffer
- firstSegment->RemoveAtStart (nextSegmentSize);
- m_txonBuffer.insert (m_txonBuffer.begin (), firstSegment);
- m_txonBufferSize += (*(m_txonBuffer.begin()))->GetSize ();
- firstSegment = 0; // TODO how to put a null ptr to Packet?
+ firstSegment->RemoveAtStart (currSegmentSize);
+ NS_LOG_LOGIC (" firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize ());
+ if (firstSegment->GetSize () > 0)
+ {
+ firstSegment->AddPacketTag (oldTag);
+
+ m_txonBuffer.insert (m_txonBuffer.begin (), firstSegment);
+ m_txonBufferSize += (*(m_txonBuffer.begin()))->GetSize ();
- NS_LOG_LOGIC (" TX buffer: Give back the remaining segment");
- NS_LOG_LOGIC (" TX buffers = " << m_txonBuffer.size ());
- NS_LOG_LOGIC (" Front buffer size = " << (*(m_txonBuffer.begin()))->GetSize ());
- NS_LOG_LOGIC (" txBufferSize = " << m_txonBufferSize );
+ NS_LOG_LOGIC (" Txon buffer: Give back the remaining segment");
+ NS_LOG_LOGIC (" Txon buffers = " << m_txonBuffer.size ());
+ NS_LOG_LOGIC (" Front buffer size = " << (*(m_txonBuffer.begin()))->GetSize ());
+ NS_LOG_LOGIC (" txonBufferSize = " << m_txonBufferSize );
+ }
+ else
+ {
+ // Whole segment was taken, so adjust tag
+ if (newTag.GetStatus () == LteRlcSduStatusTag::FIRST_SEGMENT)
+ {
+ newTag.SetStatus (LteRlcSduStatusTag::FULL_SDU);
+ }
+ else if (newTag.GetStatus () == LteRlcSduStatusTag::MIDDLE_SEGMENT)
+ {
+ newTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
+ }
+ }
+ // Segment is completely taken or
+ // the remaining segment is given back to the transmission buffer
+ firstSegment = 0;
+
+ // Put status tag once it has been adjusted
+ newSegment->AddPacketTag (newTag);
// Add Segment to Data field
dataFieldAddedSize = newSegment->GetSize ();
dataFieldTotalSize += dataFieldAddedSize;
dataField.push_back (newSegment);
- newSegment = 0; // TODO how to put a null ptr to Packet?
+ newSegment = 0;
// ExtensionBit (Next_Segment - 1) = 0
rlcAmHeader.PushExtensionBit (LteRlcAmHeader::DATA_FIELD_FOLLOWS);
@@ -317,7 +354,7 @@
nextSegmentSize -= dataFieldAddedSize;
nextSegmentId++;
- // nextSegmentSize MUST be zero
+ // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
// (NO more segments) → exit
// break;
@@ -514,7 +551,7 @@
void
LteRlcAm::DoReceivePdu (Ptr<Packet> p)
{
- NS_LOG_FUNCTION (this << p->GetSize ());
+ NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
// Receiver timestamp
RlcTag rlcTag;
@@ -528,7 +565,7 @@
// Get RLC header parameters
LteRlcAmHeader rlcAmHeader;
p->PeekHeader (rlcAmHeader);
- NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader);
+ NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
if ( rlcAmHeader.IsDataPdu () )
{