diff --git a/src/lte/model/lte-rlc-am.cc b/src/lte/model/lte-rlc-am.cc index be1fb4f0b..1b6d76f43 100644 --- a/src/lte/model/lte-rlc-am.cc +++ b/src/lte/model/lte-rlc-am.cc @@ -98,7 +98,7 @@ LteRlcAm::GetTypeId (void) void LteRlcAm::DoTransmitPdcpPdu (Ptr 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 @@ LteRlcAm::DoTransmitPdcpPdu (Ptr p) 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 @@ LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer) 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 @@ LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer) { 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 @@ LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer) 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 newSegment = firstSegment->CreateFragment (0, nextSegmentSize); + Ptr 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 @@ LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer) 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); - 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 ); + m_txonBuffer.insert (m_txonBuffer.begin (), firstSegment); + m_txonBufferSize += (*(m_txonBuffer.begin()))->GetSize (); + + 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 @@ LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer) 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 @@ LteRlcAm::DoNotifyHarqDeliveryFailure () void LteRlcAm::DoReceivePdu (Ptr 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 @@ LteRlcAm::DoReceivePdu (Ptr p) // 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 () ) {