Skip to content

lte: Fix PDU delivering at the edge of reordering window

Nat requested to merge natale-p/ns-3-dev:lte-rlc-fix-pdu-delivering into master

Line 473 of lte-rlc-um.cc:

  // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
  // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity shall:

  // - if x falls outside of the reordering window:
  //    - update VR(UH) to x + 1;
  //    - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering window, remove
  //      RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in ascending order of the
  //      RLC SN if not delivered before;
  //    - if VR(UR) falls outside of the reordering window:
  //        - set VR(UR) to (VR(UH) - UM_Window_Size);

  if ( ! IsInsideReorderingWindow (seqNumber))
    {
      NS_LOG_LOGIC ("SN is outside the reordering window");

      m_vrUh = seqNumber + 1;
      NS_LOG_LOGIC ("New VR(UH) = " << m_vrUh);

      ReassembleOutsideWindow ();

      if ( ! IsInsideReorderingWindow (m_vrUr) )
        {
          m_vrUr = m_vrUh - m_windowSize;
          NS_LOG_LOGIC ("VR(UR) is outside the reordering window");
          NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
        }
    }

As an example, let's put seqNumber to 3, and m_vrUh to 2. A reasonable setup in which this combination of values can arise is when you have packet 0 received, packet 1 received, packet 2 loss, and packet 3 received. We are now checking with the function IsInsideReorderingWindow that 3 is inside. The function returns false, and we enter the if block (if you wonder why IsInsideReorderingWindow (3) is false, check at line 581: if ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh)), where we have m_windowSize that is 512: clearly the condition seqNumber < m_vrUh is false, as m_vrUh is 2 and seqNumber is 3). Now, inside the block, we update m_vrUh to be 4 and then enter the function ReassembleOutsideWindow:

void
LteRlcUm::ReassembleOutsideWindow (void)
{
  NS_LOG_LOGIC ("Reassemble Outside Window");

  std::map <uint16_t, Ptr<Packet> >::iterator it;
  it = m_rxBuffer.begin ();

  while ( (it != m_rxBuffer.end ()) && ! IsInsideReorderingWindow (SequenceNumber10 (it->first)) )
    {
      NS_LOG_LOGIC ("SN = " << it->first);

      // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
      ReassembleAndDeliver (it->second);

      std::map <uint16_t, Ptr<Packet> >::iterator it_tmp = it;
      ++it;
      m_rxBuffer.erase (it_tmp);
    }
 ...

As you can see, in the while we have (again) the check about the fact that the seqNumber is (or not) inside the reordering window. But the state on which this fact is calculated has changed!!!!! m_vrUh is now 4, not 2, and so sequence number 3 is now inside the reordering window, and is not delivered (the while block is not entered and ReassembleAndDeliver not called).

The patch just inverts the order of delivering the packets to PDCP with updating the window edges.

Merge request reports