Merge new tests of RLC entities
authorManuel Requena <manuel.requena@cttc.es>
Wed, 08 Feb 2012 17:14:58 +0100
changeset 8629 859fa94888fc
parent 8628 b86b82c76693 (diff)
parent 8609 db24d2db55d4 (current diff)
child 8630 676af6bab0d7
Merge new tests of RLC entities
--- a/src/lte/model/lte-rlc-am-header.cc	Wed Feb 08 13:42:00 2012 +0100
+++ b/src/lte/model/lte-rlc-am-header.cc	Wed Feb 08 17:14:58 2012 +0100
@@ -89,9 +89,9 @@
 }
 
 void
-LteRlcAmHeader::SetSequenceNumber (uint16_t sequenceNumber)
+LteRlcAmHeader::SetSequenceNumber (SequenceNumber10 sequenceNumber)
 {
-  m_sequenceNumber = sequenceNumber & 0x03FF;
+  m_sequenceNumber = sequenceNumber;
 }
 
 uint8_t
@@ -100,7 +100,7 @@
   return m_framingInfo;
 }
 
-uint16_t
+SequenceNumber10
 LteRlcAmHeader::GetSequenceNumber () const
 {
   return m_sequenceNumber;
@@ -209,12 +209,12 @@
 
 
 void
-LteRlcAmHeader::SetAckSn (uint16_t ackSn)
+LteRlcAmHeader::SetAckSn (SequenceNumber10 ackSn)
 {
-  m_ackSn = ackSn & 0x03FF;
+  m_ackSn = ackSn;
 }
 
-uint16_t
+SequenceNumber10
 LteRlcAmHeader::GetAckSn (void) const
 {
   return m_ackSn;
@@ -303,8 +303,8 @@
                   ((m_pollingBit << 5) & 0x20) |
                   ((m_framingInfo << 3) & 0x18) |
                   (((*it1) << 2) & 0x04) |
-                  ((m_sequenceNumber >> 8) & 0x0003) );
-      i.WriteU8 ( m_sequenceNumber & 0x00FF );
+                  ((m_sequenceNumber.GetValue () >> 8) & 0x0003) );
+      i.WriteU8 ( m_sequenceNumber.GetValue () & 0x00FF );
       i.WriteU8 ( ((m_lastSegmentFlag << 7) & 0x80) |
                   ((m_segmentOffset >> 8) & 0x007F) );
       i.WriteU8 ( m_segmentOffset & 0x00FF );
@@ -346,8 +346,8 @@
     {
       i.WriteU8 ( ((CONTROL_PDU << 7) & 0x80) |
                   ((m_controlPduType << 4) & 0x70) |
-                  ((m_ackSn >> 6) & 0x0F) );
-      i.WriteU8 ( ((m_ackSn << 2) & 0xC0) );
+                  ((m_ackSn.GetValue () >> 6) & 0x0F) );
+      i.WriteU8 ( ((m_ackSn.GetValue () << 2) & 0xFC) );
     }
 }
 
@@ -378,7 +378,7 @@
 
       m_lastSegmentFlag    = (byte_3 & 0x80) >> 7;
       m_segmentOffset      = (byte_3 & 0x7F) | byte_4;
-           
+
       extensionBit = (byte_1 & 0x04) >> 2;
       m_extensionBits.push_back (extensionBit);
 
--- a/src/lte/model/lte-rlc-am-header.h	Wed Feb 08 13:42:00 2012 +0100
+++ b/src/lte/model/lte-rlc-am-header.h	Wed Feb 08 17:14:58 2012 +0100
@@ -22,6 +22,7 @@
 #define LTE_RLC_AM_HEADER_H
 
 #include "ns3/header.h"
+#include "ns3/lte-rlc-sequence-number.h"
 
 #include <list>
 
@@ -65,8 +66,8 @@
   // DATA PDU
   //
 
-  void SetSequenceNumber (uint16_t sequenceNumber);
-  uint16_t GetSequenceNumber () const;
+  void SetSequenceNumber (SequenceNumber10 sequenceNumber);
+  SequenceNumber10 GetSequenceNumber () const;
 
   void SetFramingInfo (uint8_t framingInfo);
   uint8_t GetFramingInfo () const;
@@ -124,8 +125,8 @@
   // CONTROL PDU
   //
 
-  void SetAckSn (uint16_t ackSn);
-  uint16_t GetAckSn () const;
+  void SetAckSn (SequenceNumber10 ackSn);
+  SequenceNumber10 GetAckSn () const;
 
 
   static TypeId GetTypeId (void);
@@ -143,7 +144,7 @@
   uint8_t  m_resegmentationFlag;
   uint8_t  m_pollingBit;
   uint8_t  m_framingInfo;      //  2 bits
-  uint16_t m_sequenceNumber;   // 10 bits
+  SequenceNumber10 m_sequenceNumber;
   uint8_t  m_lastSegmentFlag;
   uint16_t m_segmentOffset;
   uint16_t m_lastOffset;
@@ -155,8 +156,8 @@
   uint8_t  m_controlPduType;
 
   // Status PDU fields
-  uint16_t m_ackSn;
-  uint16_t m_nackSn;
+  SequenceNumber10 m_ackSn;
+  SequenceNumber10 m_nackSn;
 
   std::list <uint8_t> m_extensionBits1; // Includes E1 after ACK_SN
   std::list <uint8_t> m_extensionBits2;
--- a/src/lte/model/lte-rlc-am.cc	Wed Feb 08 13:42:00 2012 +0100
+++ b/src/lte/model/lte-rlc-am.cc	Wed Feb 08 17:14:58 2012 +0100
@@ -38,9 +38,9 @@
 
   // Buffers
   m_txonBufferSize = 0;
-  m_retxBuffer.resize (512);
+  m_retxBuffer.resize (1024);
   m_retxBufferSize = 0;
-  m_txedBuffer.resize (512);
+  m_txedBuffer.resize (1024);
   m_txedBufferSize = 0;
 
   m_statusPduRequested = false;
@@ -129,7 +129,7 @@
   Time retxQueueHolDelay (0);
   if ( m_retxBufferSize )
     {
-      m_retxBuffer.front ().m_pdu->PeekPacketTag (retxQueueHolTimeTag);
+//MRE      m_retxBuffer.front ().m_pdu->PeekPacketTag (retxQueueHolTimeTag);
       retxQueueHolDelay = now - retxQueueHolTimeTag.GetSenderTimestamp ();
     }
 
@@ -186,10 +186,25 @@
       params.lcid = m_lcid;
 
       m_macSapProvider->TransmitPdu (params);
+      return;
     }
   else if ( m_retxBufferSize > 0 )
     {
       NS_LOG_LOGIC ("Sending data from Retransmission Buffer");
+
+      Ptr<Packet> packet = m_retxBuffer.at (m_vtA.GetValue ()).m_pdu;
+
+      if ( packet->GetSize () <= bytes )
+        {
+          // Send RLC PDU to MAC layer
+          LteMacSapProvider::TransmitPduParameters params;
+          params.pdu = packet;
+          params.rnti = m_rnti;
+          params.lcid = m_lcid;
+
+          m_macSapProvider->TransmitPdu (params);
+          return;
+        }
     }
   else if ( m_txonBufferSize > 0 )
     {
@@ -212,7 +227,7 @@
   rlcAmHeader.SetDataPdu ();
 
   // Build Data field
-  uint32_t nextSegmentSize = bytes - 2;
+  uint32_t nextSegmentSize = bytes - 4;
   uint32_t nextSegmentId = 1;
   uint32_t dataFieldTotalSize = 0;
   uint32_t dataFieldAddedSize = 0;
@@ -304,7 +319,7 @@
           dataFieldAddedSize = firstSegment->GetSize ();
           dataFieldTotalSize += dataFieldAddedSize;
           dataField.push_back (firstSegment);
-          firstSegment = 0; // TODO how to put a null ptr to Packet?
+          firstSegment = 0;
 
           // ExtensionBit (Next_Segment - 1) = 0
           rlcAmHeader.PushExtensionBit (LteRlcAmHeader::DATA_FIELD_FOLLOWS);
@@ -320,9 +335,9 @@
               NS_LOG_LOGIC ("        First SDU buffer  = " << *(m_txonBuffer.begin()));
               NS_LOG_LOGIC ("        First SDU size    = " << (*(m_txonBuffer.begin()))->GetSize ());
             }
-          NS_LOG_LOGIC ("        Next segment size = " << nextSegmentSize << " (should be 0)");
+          NS_LOG_LOGIC ("        Next segment size = " << nextSegmentSize);
 
-          // nextSegmentSize MUST be zero
+          // nextSegmentSize MUST be zero (only if txonBuffer is not empty)
 
           // (NO more segments) → exit
           // break;
@@ -341,7 +356,7 @@
           // LengthIndicator (Next_Segment)  = txBuffer.FirstBuffer.length()
           rlcAmHeader.PushLengthIndicator (firstSegment->GetSize ());
 
-          nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize; // TODO???
+          nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
           nextSegmentId++;
 
           NS_LOG_LOGIC ("        SDUs in TxBuffer  = " << m_txonBuffer.size ());
@@ -366,9 +381,7 @@
   // Build RLC header
   //
 
-  rlcAmHeader.SetSequenceNumber ( m_vtS );
-  m_vtS = (m_vtS + 1) % 1024;
-
+  rlcAmHeader.SetSequenceNumber ( m_vtS++ );
   rlcAmHeader.SetResegmentationFlag (LteRlcAmHeader::PDU);
   rlcAmHeader.SetLastSegmentFlag (LteRlcAmHeader::LAST_PDU_SEGMENT);
   rlcAmHeader.SetSegmentOffset (0);
@@ -444,7 +457,7 @@
         {
           NS_LOG_LOGIC ("Start PollRetransmit timer");
 
-          m_pollRetransmitTimer = Simulator::Schedule (Time ("1.0s"),
+          m_pollRetransmitTimer = Simulator::Schedule (Time ("0.1s"),
                                                        &LteRlcAm::ExpirePollRetransmitTimer, this);
         }
       else
@@ -452,7 +465,7 @@
           NS_LOG_LOGIC ("Restart PollRetransmit timer");
 
           m_pollRetransmitTimer.Cancel ();
-          m_pollRetransmitTimer = Simulator::Schedule (Time ("1.0s"),
+          m_pollRetransmitTimer = Simulator::Schedule (Time ("0.1s"),
                                                        &LteRlcAm::ExpirePollRetransmitTimer, this);
         }
     }
@@ -465,7 +478,7 @@
   // Store new PDU into the Transmitted PDU Buffer
   NS_LOG_LOGIC ("Put transmitted PDU in the txedBuffer");
   m_txedBufferSize += packet->GetSize ();
-  m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber () ) = packet;
+  m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ) = packet;
 
   // Send RLC PDU to MAC layer
   LteMacSapProvider::TransmitPduParameters params;
@@ -544,7 +557,7 @@
       // - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).
 
 
-      uint16_t seqNumber = rlcAmHeader.GetSequenceNumber ();
+      SequenceNumber10 seqNumber = rlcAmHeader.GetSequenceNumber ();
 
       if ( rlcAmHeader.GetResegmentationFlag () == LteRlcAmHeader::SEGMENT )
         {
@@ -640,8 +653,8 @@
       else
         {
           NS_LOG_LOGIC ("Place AMD PDU in the reception buffer ( SN = " << seqNumber << " )");
-          m_rxonBuffer[ seqNumber ].m_byteSegments.push_back (p);
-          m_rxonBuffer[ seqNumber ].m_pduComplete = true;
+          m_rxonBuffer[ seqNumber.GetValue () ].m_byteSegments.push_back (p);
+          m_rxonBuffer[ seqNumber.GetValue () ].m_pduComplete = true;
 
           // - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before:
           //         - discard the duplicate byte segments.
@@ -656,7 +669,7 @@
 
       if ( seqNumber >= m_vrH )
         {
-          m_vrH = (seqNumber + 1) % 1024;
+          m_vrH = seqNumber + 1;
           NS_LOG_LOGIC ("New VR(H)  = " << m_vrH);
         }
 
@@ -664,11 +677,12 @@
       //     - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for
       //       which not all byte segments have been received;
 
-      if ( m_rxonBuffer[ m_vrMs ].m_pduComplete )
+      if ( m_rxonBuffer[ m_vrMs.GetValue () ].m_pduComplete )
         {
-          while ( m_rxonBuffer[ m_vrMs ].m_pduComplete )
+          while ( m_rxonBuffer[ m_vrMs.GetValue () ].m_pduComplete )
             {
-              m_vrMs = (m_vrMs + 1) % 1024;
+              m_vrMs++;
+              NS_LOG_LOGIC ("Incr VR(MS) = " << m_vrMs);
             }
           NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
         }
@@ -681,21 +695,28 @@
 
       if ( seqNumber == m_vrR )
         {
-          if ( m_rxonBuffer[ seqNumber ].m_pduComplete )
+          if ( m_rxonBuffer[ seqNumber.GetValue () ].m_pduComplete )
             {
-              while ( m_rxonBuffer[ m_vrR ].m_pduComplete )
+              while ( m_rxonBuffer[ m_vrR.GetValue () ].m_pduComplete )
                 {
-                  m_vrR = (m_vrR + 1) % 1024;
+                  NS_LOG_LOGIC ("Reassemble and Deliver ( SN = " << m_vrR << " )");
+                  NS_ASSERT_MSG (m_rxonBuffer[ m_vrR.GetValue () ].m_byteSegments.size () == 1,
+                                "Too many segments. PDU Reassembly process didn't work");
+                  ReassembleAndDeliver (m_rxonBuffer[ m_vrR.GetValue () ].m_byteSegments.front ());
+                  m_rxonBuffer.erase (m_vrR.GetValue ());
+
+                  m_vrR++;
                 }
               NS_LOG_LOGIC ("New VR(R)  = " << m_vrR);
               m_vrMr = m_vrR + m_windowSize;
               NS_LOG_LOGIC ("New VR(MR) = " << m_vrMr);
             }
 
-          NS_LOG_LOGIC ("Reassemble and Deliver ( SN = " << seqNumber << " )");
-          NS_ASSERT_MSG (m_rxonBuffer[ seqNumber ].m_byteSegments.size () == 1,
-                         "Too many segments. PDU Reassembly process didn't work");
-          ReassembleAndDeliver (m_rxonBuffer[ seqNumber ].m_byteSegments.front ());
+//           NS_LOG_LOGIC ("Reassemble and Deliver ( SN = " << seqNumber << " )");
+//           NS_ASSERT_MSG (m_rxonBuffer[ seqNumber.GetValue () ].m_byteSegments.size () == 1,
+//                          "Too many segments. PDU Reassembly process didn't work");
+//           ReassembleAndDeliver (m_rxonBuffer[ seqNumber.GetValue () ].m_byteSegments.front ());
+//           m_rxonBuffer.erase (seqNumber.GetValue ());
         }
 
       // - if t-Reordering is running:
@@ -727,7 +748,7 @@
           if ( m_vrH > m_vrR )
             {
               NS_LOG_LOGIC ("Start reordering timer");
-              m_reorderingTimer = Simulator::Schedule (Time ("1.0s"),
+              m_reorderingTimer = Simulator::Schedule (Time ("0.1s"),
                                                        &LteRlcAm::ExpireReorderingTimer ,this);
               m_vrX = m_vrH;
               NS_LOG_LOGIC ("New VR(X) = " << m_vrX);
@@ -831,46 +852,67 @@
     {
       NS_LOG_INFO ("Control AM RLC PDU");
 
-      uint16_t ackSn = rlcAmHeader.GetAckSn ();
-      uint16_t seqNumber = m_vtA;
+      SequenceNumber10 ackSn = rlcAmHeader.GetAckSn ();
+//       SequenceNumber10 seqNumber = m_vtA;
 
-      while (seqNumber < ackSn)
+      NS_LOG_INFO ("ackSn     = " << ackSn);
+      NS_LOG_INFO ("VT(A)     = " << m_vtA);
+      NS_LOG_INFO ("VT(S)     = " << m_vtS);
+      while (m_vtA < ackSn && m_vtA < m_vtS)
         {
-          NS_LOG_INFO ("seqNumber = " << seqNumber);
-          NS_LOG_INFO ("ackSn     = " << ackSn);
-          NS_LOG_INFO ("m_txedBuffer(seqNumber).size = " << m_txedBuffer.size ());
-          if (m_txedBuffer.at (seqNumber))
+//           NS_LOG_INFO ("seqNumber = " << seqNumber);
+//           NS_LOG_INFO ("m_txedBuffer( VT(A) ).size = " << m_txedBuffer.size ());
+
+          uint16_t seqNumberValue = m_vtA.GetValue ();
+          if (m_txedBuffer.at (seqNumberValue))
             {
-              NS_LOG_INFO ("m_txedBuffer(seqNumber)->GetSize = " << m_txedBuffer.at (seqNumber)->GetSize ());
-              m_txedBufferSize -= m_txedBuffer.at (seqNumber)->GetSize ();
-              m_txedBuffer.at (seqNumber) = 0;
+              NS_LOG_INFO ("ACKed SN = " << seqNumberValue << " from txedBuffer");
+//               NS_LOG_INFO ("m_txedBuffer( " << m_vtA << " )->GetSize = " << m_txedBuffer.at (m_vtA.GetValue ())->GetSize ());
+              m_txedBufferSize -= m_txedBuffer.at (seqNumberValue)->GetSize ();
+              m_txedBuffer.at (seqNumberValue) = 0;
             }
-          seqNumber++;
+
+          if (m_retxBuffer.at (seqNumberValue).m_pdu)
+            {
+              NS_LOG_INFO ("ACKed SN = " << seqNumberValue << " from retxBuffer");
+              m_retxBufferSize -= m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
+              m_retxBuffer.at (seqNumberValue).m_pdu = 0;
+              m_retxBuffer.at (seqNumberValue).m_retxCount = 0;
+            }
+
+          m_vtA++;
         }
 
+      NS_LOG_INFO ("New VT(A) = " << m_vtA);
+
+      SequenceNumber10 seqNumber = m_vtA;
+      uint16_t seqNumberValue;
       while (seqNumber < m_vtS)
         {
-          if (m_txedBuffer.at (seqNumber))
+          seqNumberValue = seqNumber.GetValue ();
+          if (m_txedBuffer.at (seqNumberValue))
             {
-              m_retxBuffer.at (seqNumber).m_pdu = m_txedBuffer.at (seqNumber);
-              m_retxBuffer.at (seqNumber).m_retxCount = 0;
-              m_retxBufferSize += m_retxBuffer.at (seqNumber).m_pdu->GetSize ();
+              NS_LOG_INFO ("Move SN = " << seqNumberValue << " to retxBuffer");
+              m_retxBuffer.at (seqNumberValue).m_pdu = m_txedBuffer.at (seqNumberValue);
+              m_retxBuffer.at (seqNumberValue).m_retxCount = 0;
+              m_retxBufferSize += m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
 
-              m_txedBufferSize -= m_txedBuffer.at (seqNumber)->GetSize ();
-              m_txedBuffer.at (seqNumber) = 0;
+              m_txedBufferSize -= m_txedBuffer.at (seqNumberValue)->GetSize ();
+              m_txedBuffer.at (seqNumberValue) = 0;
             }
-          else if (m_retxBuffer.at (seqNumber).m_pdu)
+          else if (m_retxBuffer.at (seqNumberValue).m_pdu)
             {
-              m_retxBuffer.at (seqNumber).m_retxCount++;
-              if (m_retxBuffer.at (seqNumber).m_retxCount >= m_maxRetxThreshold)
+              m_retxBuffer.at (seqNumberValue).m_retxCount++;
+              NS_LOG_INFO ("Incr RETX_COUNT for SN = " << seqNumberValue);
+              if (m_retxBuffer.at (seqNumberValue).m_retxCount >= m_maxRetxThreshold)
                 {
-                  NS_LOG_INFO ("Max RETX_COUNT for SN = " << seqNumber);
+                  NS_LOG_INFO ("Max RETX_COUNT for SN = " << seqNumberValue);
                 }
             }
 
           seqNumber++;
         }
-      
+
       return;
     }
   else
@@ -901,16 +943,24 @@
 
 
 bool
-LteRlcAm::IsInsideReceivingWindow (uint16_t seqNumber)
+LteRlcAm::IsInsideReceivingWindow (SequenceNumber10 seqNumber)
 {
-  if  ( ( ((m_vrR - m_vrR) % 1024) <= ((seqNumber - m_vrR) % 1024) ) &&
-        ( ((seqNumber - m_vrR) % 1024) < ((m_vrMr - m_vrR) % 1024) )
-      )
+  NS_LOG_FUNCTION (this << seqNumber);
+  NS_LOG_LOGIC ("Receiving Window: " <<
+                m_vrR << " <= " << seqNumber << " <= " << m_vrMr);
+
+  m_vrR.SetModulusBase (m_vrR);
+  m_vrMr.SetModulusBase (m_vrR);
+  seqNumber.SetModulusBase (m_vrR);
+
+  if ( (m_vrR <= seqNumber) && (seqNumber < m_vrMr ) )
     {
+      NS_LOG_LOGIC (seqNumber << " is INSIDE the receiving window");
       return true;
     }
   else
     {
+      NS_LOG_LOGIC (seqNumber << " is OUTSIDE the receiving window");
       return false;
     }
 }
@@ -922,20 +972,20 @@
   LteRlcAmHeader rlcAmHeader;
   packet->RemoveHeader (rlcAmHeader);
   uint8_t framingInfo = rlcAmHeader.GetFramingInfo ();
-  uint16_t currSeqNumber = rlcAmHeader.GetSequenceNumber ();
+  SequenceNumber10 currSeqNumber = rlcAmHeader.GetSequenceNumber ();
   bool expectedSnLost;
 
   if ( currSeqNumber != m_expectedSeqNumber )
     {
       expectedSnLost = true;
       NS_LOG_LOGIC ("There are losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
-      m_expectedSeqNumber = (currSeqNumber + 1) % 1024;
+      m_expectedSeqNumber = currSeqNumber + 1;
     }
   else
     {
       expectedSnLost = false;
       NS_LOG_LOGIC ("No losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
-      m_expectedSeqNumber = (m_expectedSeqNumber + 1) % 1024;
+      m_expectedSeqNumber = m_expectedSeqNumber + 1;
     }
 
   // Build list of SDUs
@@ -1387,7 +1437,6 @@
 // }
 
 
-// TODO To check
 void
 LteRlcAm::ExpireReorderingTimer (void)
 {
@@ -1402,23 +1451,22 @@
   //    - set VR(X) to VR(H).
 
   m_vrMs = m_vrX;
-  while ( m_rxonBuffer[ m_vrMs ].m_pduComplete )
+  while ( m_rxonBuffer[ m_vrMs.GetValue () ].m_pduComplete )
     {
-      m_vrMs = (m_vrMs + 1) % 1024;
+      m_vrMs++;
     }
   NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
 
   if ( m_vrH > m_vrMs )
     {
       NS_LOG_LOGIC ("Start reordering timer");
-      m_reorderingTimer = Simulator::Schedule (Time ("1.0s"),
+      m_reorderingTimer = Simulator::Schedule (Time ("0.1s"),
                                               &LteRlcAm::ExpireReorderingTimer ,this);
       m_vrX = m_vrH;
       NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
     }
 }
 
-// TODO To check
 void
 LteRlcAm::ExpirePollRetransmitTimer (void)
 {
--- a/src/lte/model/lte-rlc-am.h	Wed Feb 08 13:42:00 2012 +0100
+++ b/src/lte/model/lte-rlc-am.h	Wed Feb 08 17:14:58 2012 +0100
@@ -21,6 +21,8 @@
 #ifndef LTE_RLC_AM_H
 #define LTE_RLC_AM_H
 
+#include "ns3/lte-rlc-sequence-number.h"
+
 #include "ns3/lte-rlc.h"
 
 #include <vector>
@@ -61,7 +63,7 @@
   void ExpireReorderingTimer (void);
   void ExpirePollRetransmitTimer (void);
 
-  bool IsInsideReceivingWindow (uint16_t seqNumber);
+  bool IsInsideReceivingWindow (SequenceNumber10 seqNumber);
 // 
 //   void ReassembleOutsideWindow (void);
 //   void ReassembleSnLessThan (uint16_t seqNumber);
@@ -89,7 +91,7 @@
 
     struct PduBuffer
     {
-      uint16_t  m_seqNumber;
+      SequenceNumber10  m_seqNumber;
       std::list < Ptr<Packet> >  m_byteSegments;
 
       bool      m_pduComplete;
@@ -110,17 +112,17 @@
    * State variables. See section 7.1 in TS 36.322
    */
   // Transmitting side
-  uint16_t m_vtA;                   // VT(A)
-  uint16_t m_vtMs;                  // VT(MS)
-  uint16_t m_vtS;                   // VT(S)
-  uint16_t m_pollSn;                // POLL_SN
+  SequenceNumber10 m_vtA;                   // VT(A)
+  SequenceNumber10 m_vtMs;                  // VT(MS)
+  SequenceNumber10 m_vtS;                   // VT(S)
+  SequenceNumber10 m_pollSn;                // POLL_SN
 
   // Receiving side
-  uint16_t m_vrR;                   // VR(R)
-  uint16_t m_vrMr;                  // VR(MR)
-  uint16_t m_vrX;                   // VR(X)
-  uint16_t m_vrMs;                  // VR(MS)
-  uint16_t m_vrH;                   // VR(H)
+  SequenceNumber10 m_vrR;                   // VR(R)
+  SequenceNumber10 m_vrMr;                  // VR(MR)
+  SequenceNumber10 m_vrX;                   // VR(X)
+  SequenceNumber10 m_vrMs;                  // VR(MS)
+  SequenceNumber10 m_vrH;                   // VR(H)
 
   /**
    * Counters. See section 7.1 in TS 36.322
@@ -159,7 +161,7 @@
   /**
    * Expected Sequence Number
    */
-  uint16_t m_expectedSeqNumber;
+  SequenceNumber10 m_expectedSeqNumber;
 
 };
 
--- a/src/lte/model/lte-rlc-sequence-number.h	Wed Feb 08 13:42:00 2012 +0100
+++ b/src/lte/model/lte-rlc-sequence-number.h	Wed Feb 08 17:14:58 2012 +0100
@@ -125,6 +125,11 @@
     return (!this->operator> (other));
   }
 
+  bool operator >= (const SequenceNumber10 &other) const
+  {
+    return (this->operator> (other) || this->operator== (other));
+  }
+
   bool operator < (const SequenceNumber10 &other) const
   {
     return !this->operator> (other) && m_value != other.m_value;
--- a/src/lte/model/lte-rlc-um.cc	Wed Feb 08 13:42:00 2012 +0100
+++ b/src/lte/model/lte-rlc-um.cc	Wed Feb 08 17:14:58 2012 +0100
@@ -69,7 +69,7 @@
 void
 LteRlcUm::DoTransmitPdcpPdu (Ptr<Packet> p)
 {
-  NS_LOG_FUNCTION (this);
+  NS_LOG_FUNCTION (this << p->GetSize ());
 
   /** Store arrival time */
   RlcTag timeTag (Simulator::Now ());
@@ -488,6 +488,12 @@
       ReassembleSnLessThan (m_vrUr);
     }
 
+  // m_vrUh can change previously, set new modulus base
+  // for the t-Reordering timer-related comparisons
+  m_vrUr.SetModulusBase (m_vrUh - m_windowSize);
+  m_vrUx.SetModulusBase (m_vrUh - m_windowSize);
+  m_vrUh.SetModulusBase (m_vrUh - m_windowSize);
+
   // - if t-Reordering is running:
   //    - if VR(UX) <= VR(UR); or
   //    - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
@@ -512,11 +518,11 @@
     {
       NS_LOG_LOGIC ("Reordering timer is not running");
 
-      if ( m_vrUx > m_vrUr )
+      if ( m_vrUh > m_vrUr )
         {
-          NS_LOG_LOGIC ("VR(UX) > VR(UR). " << m_vrUx << " > " << m_vrUr);
+          NS_LOG_LOGIC ("VR(UH) > VR(UR)");
           NS_LOG_LOGIC ("Start reordering timer");
-          m_reorderingTimer = Simulator::Schedule (Time ("1.0s"),
+          m_reorderingTimer = Simulator::Schedule (Time ("0.1s"),
                                                    &LteRlcUm::ExpireReorderingTimer ,this);
           m_vrUx = m_vrUh;
           NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
@@ -547,12 +553,12 @@
 
   if ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh))
     {
-      NS_LOG_LOGIC (seqNumber << "is INSIDE the reordering window");
+      NS_LOG_LOGIC (seqNumber << " is INSIDE the reordering window");
       return true;
     }
   else
     {
-      NS_LOG_LOGIC (seqNumber << "is OUTSIDE the reordering window");
+      NS_LOG_LOGIC (seqNumber << " is OUTSIDE the reordering window");
       return false;
     }
 }
@@ -1062,7 +1068,7 @@
 void
 LteRlcUm::ExpireReorderingTimer (void)
 {
-  NS_LOG_LOGIC ("TODO: Reordering Timer has expired...");
+  NS_LOG_LOGIC ("Reordering timer has expired");
 
   // 5.1.2.2.4 Actions when t-Reordering expires
   // When t-Reordering expires, the receiving UM RLC entity shall:
@@ -1081,15 +1087,17 @@
       newVrUr++;
     }
   m_vrUr = newVrUr;
+  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
 
   ReassembleSnLessThan (m_vrUr);
 
   if ( m_vrUh > m_vrUr)
     {
       NS_LOG_LOGIC ("Start reordering timer");
-      m_reorderingTimer = Simulator::Schedule (Time ("1.0s"),
+      m_reorderingTimer = Simulator::Schedule (Time ("0.1s"),
                                                &LteRlcUm::ExpireReorderingTimer, this);
       m_vrUx = m_vrUh;
+      NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
     }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-simple-helper.cc	Wed Feb 08 17:14:58 2012 +0100
@@ -0,0 +1,336 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Manuel Requena <manuel.requena@cttc.es> (Based on lte-helper.cc)
+ */
+
+#include "ns3/lte-simple-helper.h"
+#include "ns3/log.h"
+#include "ns3/callback.h"
+#include "ns3/config.h"
+#include "ns3/simple-channel.h"
+#include "ns3/error-model.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("LteSimpleHelper");
+
+namespace ns3 {
+
+
+NS_OBJECT_ENSURE_REGISTERED (LteSimpleHelper);
+
+LteSimpleHelper::LteSimpleHelper (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_enbDeviceFactory.SetTypeId (LteSimpleNetDevice::GetTypeId ());
+  m_ueDeviceFactory.SetTypeId (LteSimpleNetDevice::GetTypeId ());
+}
+
+void
+LteSimpleHelper::DoStart (void)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_phyChannel = CreateObject<SimpleChannel> ();
+
+  Object::DoStart ();
+}
+
+LteSimpleHelper::~LteSimpleHelper (void)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+TypeId LteSimpleHelper::GetTypeId (void)
+{
+  static TypeId
+  tid =
+    TypeId ("ns3::LteSimpleHelper")
+    .SetParent<Object> ()
+    .AddConstructor<LteSimpleHelper> ()
+    .AddAttribute ("RlcEntity",
+                   "Specify which type of RLC will be used. ",
+                   EnumValue (RLC_UM),
+                   MakeEnumAccessor (&LteSimpleHelper::m_lteRlcEntityType),
+                   MakeEnumChecker (RLC_UM, "RlcUm",
+                                    RLC_AM, "RlcAm"))
+  ;
+  return tid;
+}
+
+void
+LteSimpleHelper::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  m_phyChannel = 0;
+
+  m_enbMac->Dispose ();
+  m_enbMac = 0;
+  m_ueMac->Dispose ();
+  m_ueMac = 0;
+
+  Object::DoDispose ();
+}
+
+
+NetDeviceContainer
+LteSimpleHelper::InstallEnbDevice (NodeContainer c)
+{
+  NS_LOG_FUNCTION (this);
+  Start ();  // will run DoStart () if necessary
+  NetDeviceContainer devices;
+  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+    {
+      Ptr<Node> node = *i;
+      Ptr<NetDevice> device = InstallSingleEnbDevice (node);
+      devices.Add (device);
+    }
+  return devices;
+}
+
+NetDeviceContainer
+LteSimpleHelper::InstallUeDevice (NodeContainer c)
+{
+  NS_LOG_FUNCTION (this);
+  NetDeviceContainer devices;
+  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+    {
+      Ptr<Node> node = *i;
+      Ptr<NetDevice> device = InstallSingleUeDevice (node);
+      devices.Add (device);
+    }
+  return devices;
+}
+
+
+Ptr<NetDevice>
+LteSimpleHelper::InstallSingleEnbDevice (Ptr<Node> n)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_enbRrc = CreateObject<LteTestRrc> ();
+  m_enbPdcp = CreateObject<LtePdcp> ();
+
+  if (m_lteRlcEntityType == RLC_UM)
+    {
+      m_enbRlc = CreateObject<LteRlcUm> ();
+    }
+  else // m_lteRlcEntityType == RLC_AM
+    {
+      m_enbRlc = CreateObject<LteRlcAm> ();
+    }
+
+  m_enbRlc->SetRnti (11);
+  m_enbRlc->SetLcId (12);
+
+  Ptr<LteSimpleNetDevice> enbDev = m_enbDeviceFactory.Create<LteSimpleNetDevice> ();
+  enbDev->SetAddress (Mac48Address::Allocate ());
+  enbDev->SetChannel (m_phyChannel);
+
+  n->AddDevice (enbDev);
+
+  m_enbMac = CreateObject<LteTestMac> ();
+  m_enbMac->SetDevice (enbDev);
+
+  enbDev->SetReceiveCallback (MakeCallback (&LteTestMac::Receive, m_enbMac));
+
+  // Connect SAPs: RRC <-> PDCP <-> RLC <-> MAC
+
+  m_enbRrc->SetLtePdcpSapProvider (m_enbPdcp->GetLtePdcpSapProvider ());
+  m_enbPdcp->SetLtePdcpSapUser (m_enbRrc->GetLtePdcpSapUser ());
+
+  m_enbPdcp->SetLteRlcSapProvider (m_enbRlc->GetLteRlcSapProvider ());
+  m_enbRlc->SetLteRlcSapUser (m_enbPdcp->GetLteRlcSapUser ());
+
+  m_enbRlc->SetLteMacSapProvider (m_enbMac->GetLteMacSapProvider ());
+  m_enbMac->SetLteMacSapUser (m_enbRlc->GetLteMacSapUser ());
+
+  return enbDev;
+}
+
+Ptr<NetDevice>
+LteSimpleHelper::InstallSingleUeDevice (Ptr<Node> n)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_ueRrc = CreateObject<LteTestRrc> ();
+  m_uePdcp = CreateObject<LtePdcp> ();
+
+  if (m_lteRlcEntityType == RLC_UM)
+    {
+      m_ueRlc = CreateObject<LteRlcUm> ();
+    }
+  else // m_lteRlcEntityType == RLC_AM
+    {
+      m_ueRlc = CreateObject<LteRlcAm> ();
+    }
+
+  m_ueRlc->SetRnti (21);
+  m_ueRlc->SetLcId (22);
+
+  Ptr<LteSimpleNetDevice> ueDev = m_ueDeviceFactory.Create<LteSimpleNetDevice> ();
+  ueDev->SetAddress (Mac48Address::Allocate ());
+  ueDev->SetChannel (m_phyChannel);
+
+  n->AddDevice (ueDev);
+
+  m_ueMac = CreateObject<LteTestMac> ();
+  m_ueMac->SetDevice (ueDev);
+
+  ueDev->SetReceiveCallback (MakeCallback (&LteTestMac::Receive, m_ueMac));
+
+  // Connect SAPs: RRC <-> PDCP <-> RLC <-> MAC
+
+  m_ueRrc->SetLtePdcpSapProvider (m_uePdcp->GetLtePdcpSapProvider ());
+  m_uePdcp->SetLtePdcpSapUser (m_ueRrc->GetLtePdcpSapUser ());
+
+  m_uePdcp->SetLteRlcSapProvider (m_ueRlc->GetLteRlcSapProvider ());
+  m_ueRlc->SetLteRlcSapUser (m_uePdcp->GetLteRlcSapUser ());
+
+  m_ueRlc->SetLteMacSapProvider (m_ueMac->GetLteMacSapProvider ());
+  m_ueMac->SetLteMacSapUser (m_ueRlc->GetLteMacSapUser ());
+
+  return ueDev;
+}
+
+
+void
+LteSimpleHelper::EnableLogComponents (void)
+{
+  LogLevel level = (LogLevel) (LOG_LEVEL_ALL | LOG_PREFIX_TIME | LOG_PREFIX_NODE | LOG_PREFIX_FUNC);
+
+  LogComponentEnable ("Config", level);
+  LogComponentEnable ("LteSimpleHelper", level);
+  LogComponentEnable ("LteTestEntities", level);
+  LogComponentEnable ("LtePdcp", level);
+  LogComponentEnable ("LteRlc", level);
+  LogComponentEnable ("LteRlcUm", level);
+  LogComponentEnable ("LteRlcAm", level);
+  LogComponentEnable ("LteSimpleNetDevice", level);
+  LogComponentEnable ("SimpleNetDevice", level);
+  LogComponentEnable ("SimpleChannel", level);
+}
+
+void
+LteSimpleHelper::EnableTraces (void)
+{
+//   EnableMacTraces ();
+  EnableRlcTraces ();
+  EnablePdcpTraces ();
+}
+
+void
+LteSimpleHelper::EnableRlcTraces (void)
+{
+  EnableDlRlcTraces ();
+  EnableUlRlcTraces ();
+}
+
+
+void
+LteSimpleHelperDlTxPduCallback (Ptr<RadioBearerStatsCalculator> rlcStats, std::string path,
+                 uint16_t rnti, uint8_t lcid, uint32_t packetSize)
+{
+  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize);
+  uint64_t imsi = 111;
+  uint16_t cellId = 222;
+  rlcStats->DlTxPdu (cellId, imsi, rnti, lcid, packetSize);
+}
+
+void
+LteSimpleHelperDlRxPduCallback (Ptr<RadioBearerStatsCalculator> rlcStats, std::string path,
+                 uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
+{
+  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize << delay);
+  uint64_t imsi = 333;
+  rlcStats->DlRxPdu (imsi, rnti, lcid, packetSize, delay);
+}
+
+void
+LteSimpleHelper::EnableDlRlcTraces (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+                //   Config::Connect ("/NodeList/*/DeviceList/*/LteRlc/TxPDU",
+                //                    MakeBoundCallback (&LteSimpleHelperDlTxPduCallback, m_rlcStats));
+                //   Config::Connect ("/NodeList/*/DeviceList/*/LteRlc/RxPDU",
+                //                    MakeBoundCallback (&LteSimpleHelperDlRxPduCallback, m_rlcStats));
+}
+
+void
+LteSimpleHelperUlTxPduCallback (Ptr<RadioBearerStatsCalculator> rlcStats, std::string path,
+                 uint16_t rnti, uint8_t lcid, uint32_t packetSize)
+{
+  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize);
+  uint64_t imsi = 1111;
+  rlcStats->UlTxPdu (imsi, rnti, lcid, packetSize);
+}
+
+void
+LteSimpleHelperUlRxPduCallback (Ptr<RadioBearerStatsCalculator> rlcStats, std::string path,
+                 uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
+{
+  NS_LOG_FUNCTION (rlcStats << path << rnti << (uint16_t)lcid << packetSize << delay);
+  uint64_t imsi = 444;
+  uint16_t cellId = 555;
+  rlcStats->UlRxPdu (cellId, imsi, rnti, lcid, packetSize, delay);
+}
+
+
+void
+LteSimpleHelper::EnableUlRlcTraces (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+                  //   Config::Connect ("/NodeList/*/DeviceList/*/LteRlc/TxPDU",
+                  //                    MakeBoundCallback (&LteSimpleHelperUlTxPduCallback, m_rlcStats));
+                  //   Config::Connect ("/NodeList/*/DeviceList/*/LteRlc/RxPDU",
+                  //                    MakeBoundCallback (&LteSimpleHelperUlRxPduCallback, m_rlcStats));
+}
+
+
+void
+LteSimpleHelper::EnablePdcpTraces (void)
+{
+  EnableDlPdcpTraces ();
+  EnableUlPdcpTraces ();
+}
+
+void
+LteSimpleHelper::EnableDlPdcpTraces (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+                  //   Config::Connect ("/NodeList/*/DeviceList/*/LtePdcp/TxPDU",
+                  //                    MakeBoundCallback (&LteSimpleHelperDlTxPduCallback, m_pdcpStats));
+                  //   Config::Connect ("/NodeList/*/DeviceList/*/LtePdcp/RxPDU",
+                  //                    MakeBoundCallback (&LteSimpleHelperDlRxPduCallback, m_pdcpStats));
+}
+
+void
+LteSimpleHelper::EnableUlPdcpTraces (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+                  //   Config::Connect ("/NodeList/*/DeviceList/*/LtePdcp/TxPDU",
+                  //                    MakeBoundCallback (&LteSimpleHelperUlTxPduCallback, m_pdcpStats));
+                  //   Config::Connect ("/NodeList/*/DeviceList/*/LtePdcp/RxPDU",
+                  //                    MakeBoundCallback (&LteSimpleHelperUlRxPduCallback, m_pdcpStats));
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-simple-helper.h	Wed Feb 08 17:14:58 2012 +0100
@@ -0,0 +1,154 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Manuel Requena <manuel.requena@cttc.es> (Based on lte-helper.h)
+ */
+
+#ifndef LTE_SIMPLE_HELPER_H
+#define LTE_SIMPLE_HELPER_H
+
+#include "ns3/net-device-container.h"
+#include "ns3/simple-channel.h"
+#include "ns3/node-container.h"
+#include "ns3/radio-bearer-stats-calculator.h"
+#include "ns3/lte-simple-net-device.h"
+
+#include "ns3/lte-test-entities.h"
+#include "ns3/lte-pdcp.h"
+#include "ns3/lte-rlc.h"
+#include "ns3/lte-rlc-um.h"
+#include "ns3/lte-rlc-am.h"
+
+namespace ns3 {
+
+
+/**
+ * Creation and configuration of LTE entities
+ *
+ */
+class LteSimpleHelper : public Object
+{
+public:
+  LteSimpleHelper (void);
+  virtual ~LteSimpleHelper (void);
+
+  static TypeId GetTypeId (void);
+  virtual void DoDispose (void);
+
+
+  /**
+   * create a set of eNB devices
+   *
+   * \param c the node container where the devices are to be installed
+   *
+   * \return the NetDeviceContainer with the newly created devices
+   */
+  NetDeviceContainer InstallEnbDevice (NodeContainer c);
+
+  /**
+   * create a set of UE devices
+   *
+   * \param c the node container where the devices are to be installed
+   *
+   * \return the NetDeviceContainer with the newly created devices
+   */
+  NetDeviceContainer InstallUeDevice (NodeContainer c);
+
+
+  /**
+   * Enables logging for all components of the LENA architecture
+   *
+   */
+  void EnableLogComponents (void);
+
+  /**
+   * Enables trace sinks for MAC, RLC and PDCP
+   */
+  void EnableTraces (void);
+
+
+  /**
+   * Enable trace sinks for RLC layer
+   */
+  void EnableRlcTraces (void);
+
+  /**
+   * Enable trace sinks for DL RLC layer
+   */
+  void EnableDlRlcTraces (void);
+
+  /**
+   * Enable trace sinks for UL RLC layer
+   */
+  void EnableUlRlcTraces (void);
+
+
+  /**
+   * Enable trace sinks for PDCP layer
+   */
+  void EnablePdcpTraces (void);
+
+  /**
+   * Enable trace sinks for DL PDCP layer
+   */
+  void EnableDlPdcpTraces (void);
+
+  /**
+   * Enable trace sinks for UL PDCP layer
+   */
+  void EnableUlPdcpTraces (void);
+
+
+protected:
+  // inherited from Object
+  virtual void DoStart (void);
+
+private:
+  Ptr<NetDevice> InstallSingleEnbDevice (Ptr<Node> n);
+  Ptr<NetDevice> InstallSingleUeDevice (Ptr<Node> n);
+
+  Ptr<SimpleChannel> m_phyChannel;
+
+public:
+
+  Ptr<LteTestRrc> m_enbRrc;
+  Ptr<LteTestRrc> m_ueRrc;
+
+  Ptr<LteTestMac> m_enbMac;
+  Ptr<LteTestMac> m_ueMac;
+
+private:
+
+  Ptr<LtePdcp>    m_enbPdcp;
+  Ptr<LteRlc>     m_enbRlc;
+
+  Ptr<LtePdcp>    m_uePdcp;
+  Ptr<LteRlc>     m_ueRlc;
+
+  ObjectFactory   m_enbDeviceFactory;
+  ObjectFactory   m_ueDeviceFactory;
+
+  enum LteRlcEntityType_t {RLC_UM = 1,
+                           RLC_AM = 2 } m_lteRlcEntityType;
+
+};
+
+
+} // namespace ns3
+
+
+#endif // LTE_SIMPLE_HELPER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-simple-net-device.cc	Wed Feb 08 17:14:58 2012 +0100
@@ -0,0 +1,86 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Manuel Requena <manuel.requena@cttc.es>
+ */
+
+#include "ns3/simulator.h"
+#include "ns3/pointer.h"
+#include "ns3/log.h"
+#include "ns3/lte-simple-net-device.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteSimpleNetDevice");
+
+namespace ns3 {
+
+
+NS_OBJECT_ENSURE_REGISTERED (LteSimpleNetDevice);
+
+
+TypeId LteSimpleNetDevice::GetTypeId (void)
+{
+  static TypeId
+    tid =
+    TypeId ("ns3::LteSimpleNetDevice")
+    .SetParent<SimpleNetDevice> ()
+    .AddConstructor<LteSimpleNetDevice> ()
+  ;
+
+  return tid;
+}
+
+
+LteSimpleNetDevice::LteSimpleNetDevice (void)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+LteSimpleNetDevice::LteSimpleNetDevice (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (this);
+  SetNode (node);
+}
+
+LteSimpleNetDevice::~LteSimpleNetDevice (void)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteSimpleNetDevice::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  SimpleNetDevice::DoDispose ();
+}
+
+
+void
+LteSimpleNetDevice::DoStart (void)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+bool
+LteSimpleNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+  NS_LOG_FUNCTION (this << dest << protocolNumber);
+  return SimpleNetDevice::Send (packet, dest, protocolNumber);
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-simple-net-device.h	Wed Feb 08 17:14:58 2012 +0100
@@ -0,0 +1,64 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Manuel Requena <manuel.requena@cttc.es>
+ */
+
+#ifndef LTE_SIMPLE_NET_DEVICE_H
+#define LTE_SIMPLE_NET_DEVICE_H
+
+#include "ns3/event-id.h"
+#include "ns3/node.h"
+#include "ns3/error-model.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/lte-rlc.h"
+
+namespace ns3 {
+
+
+/**
+ * \ingroup lte
+ * The LteSimpleNetDevice class implements the LTE simple net device
+ */
+class LteSimpleNetDevice : public SimpleNetDevice
+{
+
+public:
+  static TypeId GetTypeId (void);
+
+  LteSimpleNetDevice (void);
+  LteSimpleNetDevice (Ptr<Node> node);
+
+  virtual ~LteSimpleNetDevice (void);
+  virtual void DoDispose ();
+
+
+  // inherited from NetDevice
+  virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+
+
+protected:
+  // inherited from Object
+  virtual void DoStart (void);
+
+};
+
+} // namespace ns3
+
+
+#endif // LTE_SIMPLE_NET_DEVICE_H
--- a/src/lte/test/lte-test-entities.cc	Wed Feb 08 13:42:00 2012 +0100
+++ b/src/lte/test/lte-test-entities.cc	Wed Feb 08 17:14:58 2012 +0100
@@ -48,8 +48,14 @@
 LteTestRrc::LteTestRrc ()
 {
   NS_LOG_FUNCTION (this);
+
+  m_txPdus = 0;
+  m_txBytes = 0;
+  m_rxPdus = 0;
+  m_rxBytes = 0;
+
   m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser<LteTestRrc> (this);
-  Simulator::ScheduleNow (&LteTestRrc::Start, this);
+//   Simulator::ScheduleNow (&LteTestRrc::Start, this);
 }
 
 LteTestRrc::~LteTestRrc ()
@@ -81,8 +87,51 @@
 LteTestRrc::GetDataReceived (void)
 {
   NS_LOG_FUNCTION (this);
+  return m_receivedData;
+}
 
-  return m_receivedData;
+// Stats
+uint32_t
+LteTestRrc::GetTxPdus (void)
+{
+  NS_LOG_FUNCTION (this << m_txPdus);
+  return m_txPdus;
+}
+
+uint32_t
+LteTestRrc::GetTxBytes (void)
+{
+  NS_LOG_FUNCTION (this << m_txBytes);
+  return m_txBytes;
+}
+
+uint32_t
+LteTestRrc::GetRxPdus (void)
+{
+  NS_LOG_FUNCTION (this << m_rxPdus);
+  return m_rxPdus;
+}
+
+uint32_t
+LteTestRrc::GetRxBytes (void)
+{
+  NS_LOG_FUNCTION (this << m_rxBytes);
+  return m_rxBytes;
+}
+
+
+void
+LteTestRrc::SetArrivalTime (Time arrivalTime)
+{
+  NS_LOG_FUNCTION (this << arrivalTime);
+  m_arrivalTime = arrivalTime;
+}
+
+void
+LteTestRrc::SetPduSize (uint32_t pduSize)
+{
+  NS_LOG_FUNCTION (this << pduSize);
+  m_pduSize = pduSize;
 }
 
 
@@ -95,14 +144,19 @@
 {
   NS_LOG_FUNCTION (this << params.rrcPdu->GetSize ());
   Ptr<Packet> p = params.rrcPdu;
-  NS_LOG_LOGIC ("PDU received = " << (*p));
+//   NS_LOG_LOGIC ("PDU received = " << (*p));
 
   uint32_t dataLen = p->GetSize ();
   uint8_t *buf = new uint8_t[dataLen];
+
+  // Stats
+  m_rxPdus++;
+  m_rxBytes += dataLen;
+
   p->CopyData (buf, dataLen);
   m_receivedData = std::string ((char *)buf, dataLen);
 
-  NS_LOG_LOGIC (m_receivedData);
+//   NS_LOG_LOGIC (m_receivedData);
 
   delete [] buf;
 }
@@ -115,6 +169,27 @@
 LteTestRrc::Start ()
 {
   NS_LOG_FUNCTION (this);
+  NS_ASSERT_MSG (m_arrivalTime != 0, "Arrival time must be different from 0");
+
+  // Stats
+  m_txPdus++;
+  m_txBytes += m_pduSize;
+
+  LtePdcpSapProvider::TransmitRrcPduParameters p;
+  p.rnti = 1111;
+  p.lcid = 222;
+  p.rrcPdu = Create<Packet> (m_pduSize);
+
+  Simulator::ScheduleNow (&LtePdcpSapProvider::TransmitRrcPdu, m_pdcpSapProvider, p);
+  m_nextPdu = Simulator::Schedule (m_arrivalTime, &LteTestRrc::Start, this);
+//   Simulator::Run ();
+}
+
+void
+LteTestRrc::Stop ()
+{
+  NS_LOG_FUNCTION (this);
+  m_nextPdu.Cancel ();
 }
 
 void
@@ -122,11 +197,18 @@
 {
   NS_LOG_FUNCTION (this << at << dataToSend.length () << dataToSend);
 
+  // Stats
+  m_txPdus++;
+  m_txBytes += dataToSend.length ();
+
   LtePdcpSapProvider::TransmitRrcPduParameters p;
   p.rnti = 1111;
   p.lcid = 222;
 
+  NS_LOG_LOGIC ("Data(" << dataToSend.length () << ") = " << dataToSend.data ());
   p.rrcPdu = Create<Packet> ((uint8_t *) dataToSend.data (), dataToSend.length ());
+
+  NS_LOG_LOGIC ("Packet(" << p.rrcPdu->GetSize () << ")");
   Simulator::Schedule (at, &LtePdcpSapProvider::TransmitRrcPdu, m_pdcpSapProvider, p);
 }
 
@@ -223,7 +305,10 @@
   p.rnti = 1111;
   p.lcid = 222;
 
+  NS_LOG_LOGIC ("Data(" << dataToSend.length () << ") = " << dataToSend.data ());
   p.pdcpPdu = Create<Packet> ((uint8_t *) dataToSend.data (), dataToSend.length ());
+
+  NS_LOG_LOGIC ("Packet(" << p.pdcpPdu->GetSize () << ")");
   Simulator::Schedule (time, &LteRlcSapProvider::TransmitPdcpPdu, m_rlcSapProvider, p);
 }
 
@@ -243,12 +328,21 @@
 LteTestMac::LteTestMac ()
 {
   NS_LOG_FUNCTION (this);
+  m_device = 0;
   m_macSapProvider = new EnbMacMemberLteMacSapProvider<LteTestMac> (this);
   m_macSapUser = 0;
   m_macLoopback = 0;
   m_pdcpHeaderPresent = false;
   m_rlcHeaderType = UM_RLC_HEADER;
   m_txOpportunityMode = MANUAL_MODE;
+  m_txOppTime = Seconds (0.001);
+  m_txOppSize = 0;
+
+  m_txPdus = 0;
+  m_txBytes = 0;
+  m_rxPdus = 0;
+  m_rxBytes = 0;
+
 //   m_cmacSapProvider = new EnbMacMemberLteEnbCmacSapProvider (this);
 //   m_schedSapUser = new EnbMacMemberFfMacSchedSapUser (this);
 //   m_cschedSapUser = new EnbMacMemberFfMacCschedSapUser (this);
@@ -269,6 +363,14 @@
 //   delete m_schedSapUser;
 //   delete m_cschedSapUser;
 //   delete m_enbPhySapUser;
+
+  m_device = 0;
+}
+
+void
+LteTestMac::SetDevice (Ptr<NetDevice> device)
+{
+  m_device = device;
 }
 
 void
@@ -293,37 +395,94 @@
 LteTestMac::GetDataReceived (void)
 {
   NS_LOG_FUNCTION (this);
-
   return m_receivedData;
 }
 
+// Stats
+uint32_t
+LteTestMac::GetTxPdus (void)
+{
+  NS_LOG_FUNCTION (this << m_txPdus);
+  return m_txPdus;
+}
+
+uint32_t
+LteTestMac::GetTxBytes (void)
+{
+  NS_LOG_FUNCTION (this << m_txBytes);
+  return m_txBytes;
+}
+
+uint32_t
+LteTestMac::GetRxPdus (void)
+{
+  NS_LOG_FUNCTION (this << m_rxPdus);
+  return m_rxPdus;
+}
+
+uint32_t
+LteTestMac::GetRxBytes (void)
+{
+  NS_LOG_FUNCTION (this << m_rxBytes);
+  return m_rxBytes;
+}
+
+
 void
 LteTestMac::SendTxOpportunity (Time time, uint32_t bytes)
 {
   NS_LOG_FUNCTION (this << time << bytes);
-
   Simulator::Schedule (time, &LteMacSapUser::NotifyTxOpportunity, m_macSapUser, bytes);
+  if (m_txOpportunityMode == RANDOM_MODE)
+    {
+      if (m_txOppTime != Seconds (0))
+        {
+          Simulator::Schedule (m_txOppTime, &LteTestMac::SendTxOpportunity, this, m_txOppTime, m_txOppSize);
+        }
+    }
 }
 
 void
 LteTestMac::SetPdcpHeaderPresent (bool present)
 {
-  NS_LOG_FUNCTION (this);
+  NS_LOG_FUNCTION (this << present);
   m_pdcpHeaderPresent = present;
 }
 
 void
 LteTestMac::SetRlcHeaderType (uint8_t rlcHeaderType)
 {
-  NS_LOG_FUNCTION (this);
+  NS_LOG_FUNCTION (this << rlcHeaderType);
   m_rlcHeaderType = rlcHeaderType;
 }
 
 void
 LteTestMac::SetTxOpportunityMode (uint8_t mode)
 {
-  NS_LOG_FUNCTION (this);
+  NS_LOG_FUNCTION (this << (uint32_t)mode);
   m_txOpportunityMode = mode;
+
+  if (m_txOpportunityMode == RANDOM_MODE)
+    {
+      if (m_txOppTime != Seconds (0.0))
+        {
+          SendTxOpportunity (m_txOppTime, m_txOppSize);
+        }
+    }
+}
+
+void
+LteTestMac::SetTxOppTime (Time txOppTime)
+{
+  NS_LOG_FUNCTION (this << txOppTime);
+  m_txOppTime = txOppTime;
+}
+
+void
+LteTestMac::SetTxOppSize (uint32_t txOppSize)
+{
+  NS_LOG_FUNCTION (this << txOppSize);
+  m_txOppSize = txOppSize;
 }
 
 
@@ -336,46 +495,51 @@
 {
   NS_LOG_FUNCTION (this << params.pdu->GetSize ());
 
-  if (m_macLoopback)
-    {
-      Simulator::Schedule (Seconds (0.1), &LteMacSapUser::ReceivePdu,
-                           m_macLoopback->m_macSapUser, params.pdu);
-    }
-  else
-    {
-      LtePdcpHeader pdcpHeader;
+  m_txPdus++;
+  m_txBytes += params.pdu->GetSize ();
+
+  m_device->Send (params.pdu, m_device->GetBroadcast (), 0);
 
-      if (m_rlcHeaderType == AM_RLC_HEADER)
-        {
-          // Remove AM RLC header
-          LteRlcAmHeader rlcAmHeader;
-          params.pdu->RemoveHeader (rlcAmHeader);
-          NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader);
-        }
-      else // if (m_rlcHeaderType == UM_RLC_HEADER)
-        {
-          // Remove UM RLC header
-          LteRlcHeader rlcHeader;
-          params.pdu->RemoveHeader (rlcHeader);
-          NS_LOG_LOGIC ("UM RLC header: " << rlcHeader);
-        }
-
-      // Remove PDCP header, if present
-      if (m_pdcpHeaderPresent)
-        {
-          params.pdu->RemoveHeader (pdcpHeader);
-          NS_LOG_LOGIC ("PDCP header: " << pdcpHeader);
-        }
-
-      // Copy data to a string
-      uint32_t dataLen = params.pdu->GetSize ();
-      uint8_t *buf = new uint8_t[dataLen];
-      params.pdu->CopyData (buf, dataLen);
-      m_receivedData = std::string ((char *)buf, dataLen);
-
-      NS_LOG_LOGIC ("Data = " << m_receivedData);
-      delete [] buf;
-    }
+//   if (m_macLoopback)
+//     {
+//       Simulator::Schedule (Seconds (0.1), &LteMacSapUser::ReceivePdu,
+//                            m_macLoopback->m_macSapUser, params.pdu);
+//     }
+//   else
+//     {
+//       LtePdcpHeader pdcpHeader;
+// 
+//       if (m_rlcHeaderType == AM_RLC_HEADER)
+//         {
+//           // Remove AM RLC header
+//           LteRlcAmHeader rlcAmHeader;
+//           params.pdu->RemoveHeader (rlcAmHeader);
+//           NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader);
+//         }
+//       else // if (m_rlcHeaderType == UM_RLC_HEADER)
+//         {
+//           // Remove UM RLC header
+//           LteRlcHeader rlcHeader;
+//           params.pdu->RemoveHeader (rlcHeader);
+//           NS_LOG_LOGIC ("UM RLC header: " << rlcHeader);
+//         }
+// 
+//       // Remove PDCP header, if present
+//       if (m_pdcpHeaderPresent)
+//         {
+//           params.pdu->RemoveHeader (pdcpHeader);
+//           NS_LOG_LOGIC ("PDCP header: " << pdcpHeader);
+//         }
+// 
+//       // Copy data to a string
+//       uint32_t dataLen = params.pdu->GetSize ();
+//       uint8_t *buf = new uint8_t[dataLen];
+//       params.pdu->CopyData (buf, dataLen);
+//       m_receivedData = std::string ((char *)buf, dataLen);
+// 
+//       NS_LOG_LOGIC ("Data (" << dataLen << ") = " << m_receivedData);
+//       delete [] buf;
+//     }
 }
 
 void
@@ -401,5 +565,18 @@
                                m_macSapUser, params.retxQueueSize + 2);
         }
     }
+}
 
+
+bool
+LteTestMac::Receive (Ptr<NetDevice> nd, Ptr<const Packet> p, uint16_t protocol, const Address& addr)
+{
+  NS_LOG_FUNCTION (this << addr << protocol << p->GetSize ());
+
+  m_rxPdus++;
+  m_rxBytes += p->GetSize ();
+
+  Ptr<Packet> packet = p->Copy ();
+  m_macSapUser->ReceivePdu (packet);
+  return true;
 }
--- a/src/lte/test/lte-test-entities.h	Wed Feb 08 13:42:00 2012 +0100
+++ b/src/lte/test/lte-test-entities.h	Wed Feb 08 17:14:58 2012 +0100
@@ -21,6 +21,7 @@
 #ifndef LTE_TEST_ENTITIES_H
 #define LTE_TEST_ENTITIES_H
 
+#include "ns3/simulator.h"
 #include "ns3/test.h"
 // #include "ns3/type-id.h"
 
@@ -28,6 +29,7 @@
 #include "ns3/lte-rlc-sap.h"
 #include "ns3/lte-pdcp-sap.h"
 
+#include "ns3/net-device.h"
 
 using namespace ns3;
 
@@ -64,10 +66,20 @@
     LtePdcpSapUser* GetLtePdcpSapUser (void);
 
     void Start ();
+    void Stop ();
 
     void SendData (Time at, std::string dataToSend);
     std::string GetDataReceived (void);
 
+    // Stats
+    uint32_t GetTxPdus (void);
+    uint32_t GetTxBytes (void);
+    uint32_t GetRxPdus (void);
+    uint32_t GetRxBytes (void);
+
+    void SetArrivalTime (Time arrivalTime);
+    void SetPduSize (uint32_t pduSize);
+
   private:
     // Interface forwarded by LtePdcpSapUser
     virtual void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params);
@@ -77,6 +89,14 @@
 
     std::string m_receivedData;
 
+    uint32_t m_txPdus;
+    uint32_t m_txBytes;
+    uint32_t m_rxPdus;
+    uint32_t m_rxBytes;
+
+    EventId m_nextPdu;
+    Time m_arrivalTime;
+    uint32_t m_pduSize;
 };
 
 /////////////////////////////////////////////////////////////////////
@@ -125,7 +145,6 @@
     LteRlcSapProvider* m_rlcSapProvider;
 
     std::string m_receivedData;
-
 };
 
 /////////////////////////////////////////////////////////////////////
@@ -148,9 +167,13 @@
     virtual ~LteTestMac (void);
     virtual void DoDispose (void);
 
-    void SendTxOpportunity (Time time, uint32_t bytes);
+    void SetDevice (Ptr<NetDevice> device);
+
+    void SendTxOpportunity (Time, uint32_t);
     std::string GetDataReceived (void);
 
+    bool Receive (Ptr<NetDevice> nd, Ptr<const Packet> p, uint16_t protocol, const Address& addr);
+
     /**
      * \brief Set the MAC SAP user
      * \param s a pointer to the MAC SAP user
@@ -190,9 +213,19 @@
 
     typedef enum {
       MANUAL_MODE     = 0,
-      AUTOMATIC_MODE  = 1
+      AUTOMATIC_MODE  = 1,
+      RANDOM_MODE     = 2
     } TxOpportunityMode_t;
 
+    void SetTxOppTime (Time txOppTime);
+    void SetTxOppSize (uint32_t txOppSize);
+
+    // Stats
+    uint32_t GetTxPdus (void);
+    uint32_t GetTxBytes (void);
+    uint32_t GetRxPdus (void);
+    uint32_t GetRxBytes (void);
+
   private:
     // forwarded from LteMacSapProvider
     void DoTransmitPdu (LteMacSapProvider::TransmitPduParameters);
@@ -206,7 +239,20 @@
 
     uint8_t m_rlcHeaderType;
     bool m_pdcpHeaderPresent;
-    bool m_txOpportunityMode;
+    uint8_t m_txOpportunityMode;
+
+    Ptr<NetDevice> m_device;
+
+    // TxOpportunity configuration
+    EventId m_nextTxOpp;
+    Time m_txOppTime;
+    uint32_t m_txOppSize;
+
+    // Stats
+    uint32_t m_txPdus;
+    uint32_t m_txBytes;
+    uint32_t m_rxPdus;
+    uint32_t m_rxBytes;
 
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-rlc-am-e2e.cc	Wed Feb 08 17:14:58 2012 +0100
@@ -0,0 +1,216 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Manuel Requena <manuel.requena@cttc.es>
+ */
+
+#include "ns3/config.h"
+#include "ns3/simulator.h"
+#include "ns3/pointer.h"
+#include "ns3/log.h"
+#include "ns3/packet.h"
+#include "ns3/node-container.h"
+#include "ns3/net-device-container.h"
+#include "ns3/lte-simple-helper.h"
+#include "ns3/error-model.h"
+
+#include "ns3/radio-bearer-stats-calculator.h"
+
+#include "ns3/lte-rlc-header.h"
+#include "ns3/lte-rlc-um.h"
+
+#include "ns3/lte-test-entities.h"
+#include "ns3/lte-test-rlc-am-e2e.h"
+
+#include "ns3/config-store.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("LteRlcAmE2eTest");
+
+using namespace ns3;
+
+
+/**
+ * Test x.x.x RLC AM: End-to-end flow
+ */
+
+/**
+ * TestSuite
+ */
+
+LteRlcAmE2eTestSuite::LteRlcAmE2eTestSuite ()
+  : TestSuite ("lte-rlc-am-e2e", SYSTEM)
+{
+  // NS_LOG_INFO ("Creating LteRlcAmE2eTestSuite");
+
+  double losses[] = {0.0, 0.10, 0.25, 0.50, 0.75, 0.90, 0.95};
+  uint32_t seeds[] = {1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, 10101};
+
+  for ( uint32_t l = 0 ; l < (sizeof (losses) / sizeof (double)) ; l++ )
+    {
+      for ( uint32_t s = 0 ; s < (sizeof (seeds) / sizeof (uint32_t)) ; s++ )
+        {
+          std::ostringstream name;
+          name << " Losses = " << losses[l] << "%. Seed = " << seeds[s];
+          AddTestCase (new LteRlcAmE2eTestCase (name.str (), seeds[s], losses[l]));
+        }
+    }
+}
+
+static LteRlcAmE2eTestSuite lteRlcAmE2eTestSuite;
+
+
+/**
+ * TestCase
+ */
+
+LteRlcAmE2eTestCase::LteRlcAmE2eTestCase (std::string name, uint32_t seed, double losses)
+  : TestCase (name)
+{
+  // NS_LOG_UNCOND ("Creating LteRlcAmTestingTestCase: " + name);
+
+  m_seed = seed;
+  m_losses = losses;
+
+  m_dlDrops = 0;
+  m_ulDrops = 0;
+}
+
+LteRlcAmE2eTestCase::~LteRlcAmE2eTestCase ()
+{
+}
+
+
+void
+LteRlcAmE2eTestCase::DlDropEvent (Ptr<const Packet> p)
+{
+  // NS_LOG_FUNCTION (this);
+  m_dlDrops++;
+}
+
+void
+LteRlcAmE2eTestCase::UlDropEvent (Ptr<const Packet> p)
+{
+  // NS_LOG_FUNCTION (this);
+  m_ulDrops++;
+}
+
+void
+LteRlcAmE2eTestCase::DoRun (void)
+{
+  uint16_t numberOfNodes = 1;
+
+  LogLevel level = (LogLevel) (LOG_LEVEL_ALL | LOG_PREFIX_TIME | LOG_PREFIX_NODE | LOG_PREFIX_FUNC);
+  LogComponentEnable ("LteRlcAmE2eTest", level);
+  // LogComponentEnable ("ErrorModel", level);
+  // LogComponentEnable ("LteSimpleHelper", level);
+  // LogComponentEnable ("LteSimpleNetDevice", level);
+  // LogComponentEnable ("SimpleNetDevice", level);
+  // LogComponentEnable ("SimpleChannel", level);
+  // LogComponentEnable ("LteTestEntities", level);
+  // LogComponentEnable ("LtePdcp", level);
+  // LogComponentEnable ("LteRlc", level);
+  // LogComponentEnable ("LteRlcUm", level);
+  // LogComponentEnable ("LteRlcAm", level);
+
+  SeedManager::SetSeed (m_seed);
+
+  Ptr<LteSimpleHelper> lteSimpleHelper = CreateObject<LteSimpleHelper> ();
+  // lteSimpleHelper->EnableLogComponents ();
+  // lteSimpleHelper->EnableTraces ();
+
+  lteSimpleHelper->SetAttribute ("RlcEntity", StringValue ("RlcAm"));
+
+  // eNB and UE nodes
+  NodeContainer ueNodes;
+  NodeContainer enbNodes;
+  enbNodes.Create (numberOfNodes);
+  ueNodes.Create (numberOfNodes);
+
+  // Install LTE Devices to the nodes
+  NetDeviceContainer enbLteDevs = lteSimpleHelper->InstallEnbDevice (enbNodes);
+  NetDeviceContainer ueLteDevs = lteSimpleHelper->InstallUeDevice (ueNodes);
+
+  // Note: Just one eNB and UE is supported. Everything is done in InstallEnbDevice and InstallUeDevice
+
+  // Attach one UE per eNodeB
+  // for (uint16_t i = 0; i < numberOfNodes; i++)
+  //   {
+  //     lteSimpleHelper->Attach (ueLteDevs.Get(i), enbLteDevs.Get(i));
+  //   }
+
+  //   lteSimpleHelper->ActivateEpsBearer (ueLteDevs, EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), EpcTft::Default ());
+
+
+  // Error models: downlink and uplink
+  Ptr<RateErrorModel> dlEm = CreateObjectWithAttributes<RateErrorModel> ("RanVar", RandomVariableValue (UniformVariable (0.0, 1.0)));
+  dlEm->SetAttribute ("ErrorRate", DoubleValue (m_losses));
+  dlEm->SetAttribute ("ErrorUnit", StringValue ("EU_PKT"));
+
+//   Ptr<RateErrorModel> ueEm = CreateObjectWithAttributes<RateErrorModel> ("RanVar", RandomVariableValue (UniformVariable (0.0, 1.0)));
+//   ueEm->SetAttribute ("ErrorRate", DoubleValue (m_losses));
+//   ueEm->SetAttribute ("ErrorUnit", StringValue ("EU_PKT"));
+
+  // The below hooks will cause drops and receptions to be counted
+  ueLteDevs.Get (0)->SetAttribute ("ReceiveErrorModel", PointerValue (dlEm));
+  ueLteDevs.Get (0)->TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (&LteRlcAmE2eTestCase::DlDropEvent, this));
+//   enbLteDevs.Get (0)->SetAttribute ("ReceiveErrorModel", PointerValue (enbEm));
+//   enbLteDevs.Get (0)->TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (&LteRlcAmE2eTestCase::EnbDropEvent, this));
+
+  // Sending packets from RRC layer
+  lteSimpleHelper->m_enbRrc->SetArrivalTime (Seconds (0.010));
+  lteSimpleHelper->m_enbRrc->SetPduSize (100);
+
+  // MAC sends transmission opportunities (TxOpp)
+  lteSimpleHelper->m_enbMac->SetTxOppSize (150);
+  lteSimpleHelper->m_enbMac->SetTxOppTime (Seconds (0.005));
+  lteSimpleHelper->m_enbMac->SetTxOpportunityMode (LteTestMac::RANDOM_MODE);
+
+  // MAC sends transmission opportunities (TxOpp)
+  lteSimpleHelper->m_ueMac->SetTxOppSize (140);
+  lteSimpleHelper->m_ueMac->SetTxOppTime (Seconds (0.015));
+  lteSimpleHelper->m_ueMac->SetTxOpportunityMode (LteTestMac::RANDOM_MODE);
+
+  // Start/Stop pseudo-application at RRC layer
+  Simulator::Schedule (Seconds (0.100), &LteTestRrc::Start, lteSimpleHelper->m_enbRrc);
+  Simulator::Schedule (Seconds (1.100), &LteTestRrc::Stop, lteSimpleHelper->m_enbRrc);
+
+
+  Simulator::Stop (Seconds (15.000));
+  Simulator::Run ();
+
+  uint32_t txEnbRrcPdus = lteSimpleHelper->m_enbRrc->GetTxPdus ();
+  uint32_t rxUeRrcPdus = lteSimpleHelper->m_ueRrc->GetRxPdus ();
+
+  // NS_LOG_INFO ("Seed = " << m_seed);
+  // NS_LOG_INFO ("Losses (%) = " << uint32_t (m_losses * 100));
+
+  // NS_LOG_INFO ("dl dev drops = " << m_dlDrops);
+  // NS_LOG_INFO ("ul dev drops = " << m_ulDrops);
+
+  // NS_LOG_INFO ("eNB tx RRC count = " << txEnbRrcPdus);
+  // NS_LOG_INFO ("eNB rx RRC count = " << rxEnbRrcPdus);
+  // NS_LOG_INFO ("UE tx RRC count = " << txUeRrcPdus);
+  // NS_LOG_INFO ("UE rx RRC count = " << rxUeRrcPdus);
+
+  NS_LOG_INFO (m_seed << "\t" << m_losses << "\t" << txEnbRrcPdus << "\t" << rxUeRrcPdus << "\t" << m_dlDrops);
+
+  NS_TEST_ASSERT_MSG_EQ (txEnbRrcPdus, rxUeRrcPdus,
+                         "TX PDUs (" << txEnbRrcPdus << ") != RX PDUs (" << rxUeRrcPdus << ")");
+
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-rlc-am-e2e.h	Wed Feb 08 17:14:58 2012 +0100
@@ -0,0 +1,61 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Manuel Requena <manuel.requena@cttc.es>
+ */
+
+#ifndef LTE_TEST_RLC_AM_E2E_H
+#define LTE_TEST_RLC_AM_E2E_H
+
+#include "ns3/test.h"
+
+
+using namespace ns3;
+
+
+/**
+ * Test x.x.x RLC AM: End-to-end flow
+ */
+class LteRlcAmE2eTestSuite : public TestSuite
+{
+public:
+  LteRlcAmE2eTestSuite ();
+};
+
+
+class LteRlcAmE2eTestCase : public TestCase
+{
+  public:
+    LteRlcAmE2eTestCase (std::string name, uint32_t seed, double losses);
+    LteRlcAmE2eTestCase ();
+    virtual ~LteRlcAmE2eTestCase ();
+
+  private:
+    virtual void DoRun (void);
+
+    void DlDropEvent (Ptr<const Packet> p);
+    void UlDropEvent (Ptr<const Packet> p);
+
+    uint32_t m_dlDrops;
+    uint32_t m_ulDrops;
+
+    uint32_t m_seed;
+    double   m_losses;
+};
+
+
+#endif // LTE_TEST_RLC_AM_E2E_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-rlc-um-e2e.cc	Wed Feb 08 17:14:58 2012 +0100
@@ -0,0 +1,226 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Manuel Requena <manuel.requena@cttc.es>
+ */
+
+#include "ns3/config.h"
+#include "ns3/simulator.h"
+#include "ns3/pointer.h"
+#include "ns3/log.h"
+#include "ns3/packet.h"
+#include "ns3/node-container.h"
+#include "ns3/net-device-container.h"
+#include "ns3/lte-simple-helper.h"
+#include "ns3/error-model.h"
+#include "ns3/radio-bearer-stats-calculator.h"
+
+#include "ns3/lte-rlc-header.h"
+#include "ns3/lte-rlc-um.h"
+
+#include "ns3/lte-test-entities.h"
+#include "ns3/lte-test-rlc-um-e2e.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("LteRlcUmE2eTest");
+
+using namespace ns3;
+
+
+/**
+ * Test x.x.x RLC UM: End-to-end flow
+ */
+
+/**
+ * TestSuite
+ */
+
+LteRlcUmE2eTestSuite::LteRlcUmE2eTestSuite ()
+  : TestSuite ("lte-rlc-um-e2e", SYSTEM)
+{
+  // NS_LOG_INFO ("Creating LteRlcUmE2eTestSuite");
+
+  double losses[] = {0.0, 0.10, 0.25, 0.50, 0.75, 0.90, 1.00};
+  uint32_t seeds[] = {1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, 10101};
+
+  for ( uint32_t l = 0 ; l < (sizeof (losses) / sizeof (double)) ; l++ )
+    {
+      for ( uint32_t s = 0 ; s < (sizeof (seeds) / sizeof (uint32_t)) ; s++ )
+        {
+          std::ostringstream name;
+          name << " Losses = " << losses[l] << "%. Seed = " << seeds[s];
+          AddTestCase (new LteRlcUmE2eTestCase (name.str (), seeds[s], losses[l]));
+        }
+    }
+}
+
+static LteRlcUmE2eTestSuite lteRlcUmE2eTestSuite;
+
+
+/**
+ * TestCase
+ */
+
+LteRlcUmE2eTestCase::LteRlcUmE2eTestCase (std::string name, uint32_t seed, double losses)
+  : TestCase (name)
+{
+  // NS_LOG_UNCOND ("Creating LteRlcUmTestingTestCase: " + name);
+
+  m_seed = seed;
+  m_losses = losses;
+
+  m_dlDrops = 0;
+  m_ulDrops = 0;
+}
+
+LteRlcUmE2eTestCase::~LteRlcUmE2eTestCase ()
+{
+}
+
+
+void
+LteRlcUmE2eTestCase::DlDropEvent (Ptr<const Packet> p)
+{
+  // NS_LOG_FUNCTION (this);
+  m_dlDrops++;
+}
+
+void
+LteRlcUmE2eTestCase::UlDropEvent (Ptr<const Packet> p)
+{
+  // NS_LOG_FUNCTION (this);
+  m_ulDrops++;
+}
+
+void
+LteRlcUmE2eTestCase::DoRun (void)
+{
+  uint16_t numberOfNodes = 1;
+
+  LogLevel level = (LogLevel) (LOG_LEVEL_ALL | LOG_PREFIX_TIME | LOG_PREFIX_NODE | LOG_PREFIX_FUNC);
+  LogComponentEnable ("LteRlcUmE2eTest", level);
+  // LogComponentEnable ("ErrorModel", level);
+  // LogComponentEnable ("LteSimpleHelper", level);
+  // LogComponentEnable ("LteSimpleNetDevice", level);
+  // LogComponentEnable ("SimpleNetDevice", level);
+  // LogComponentEnable ("SimpleChannel", level);
+  // LogComponentEnable ("LteTestEntities", level);
+  // LogComponentEnable ("LtePdcp", level);
+  // LogComponentEnable ("LteRlc", level);
+  // LogComponentEnable ("LteRlcUm", level);
+  // LogComponentEnable ("LteRlcAm", level);
+
+  SeedManager::SetSeed (m_seed);
+
+  Ptr<LteSimpleHelper> lteSimpleHelper = CreateObject<LteSimpleHelper> ();
+  // lteSimpleHelper->EnableLogComponents ();
+  // lteSimpleHelper->EnableTraces ();
+
+  lteSimpleHelper->SetAttribute ("RlcEntity", StringValue ("RlcUm"));
+
+  // eNB and UE nodes
+  NodeContainer ueNodes;
+  NodeContainer enbNodes;
+  enbNodes.Create (numberOfNodes);
+  ueNodes.Create (numberOfNodes);
+
+  // Install LTE Devices to the nodes
+  NetDeviceContainer enbLteDevs = lteSimpleHelper->InstallEnbDevice (enbNodes);
+  NetDeviceContainer ueLteDevs = lteSimpleHelper->InstallUeDevice (ueNodes);
+
+  // Note: Just one eNB and UE are supported. Everything is done in InstallEnbDevice and InstallUeDevice
+
+  // Attach one UE per eNodeB
+  // for (uint16_t i = 0; i < numberOfNodes; i++)
+  //   {
+  //     lteSimpleHelper->Attach (ueLteDevs.Get(i), enbLteDevs.Get(i));
+  //   }
+
+  // lteSimpleHelper->ActivateEpsBearer (ueLteDevs, EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), EpcTft::Default ());
+
+  // Error models: downlink and uplink
+  Ptr<RateErrorModel> dlEm = CreateObjectWithAttributes<RateErrorModel> ("RanVar", RandomVariableValue (UniformVariable (0.0, 1.0)));
+  dlEm->SetAttribute ("ErrorRate", DoubleValue (m_losses));
+  dlEm->SetAttribute ("ErrorUnit", StringValue ("EU_PKT"));
+
+  Ptr<RateErrorModel> ulEm = CreateObjectWithAttributes<RateErrorModel> ("RanVar", RandomVariableValue (UniformVariable (0.0, 1.0)));
+  ulEm->SetAttribute ("ErrorRate", DoubleValue (m_losses));
+  ulEm->SetAttribute ("ErrorUnit", StringValue ("EU_PKT"));
+
+  // The below hooks will cause drops to be counted at simple phy layer
+  ueLteDevs.Get (0)->SetAttribute ("ReceiveErrorModel", PointerValue (dlEm));
+  ueLteDevs.Get (0)->TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (&LteRlcUmE2eTestCase::DlDropEvent, this));
+  enbLteDevs.Get (0)->SetAttribute ("ReceiveErrorModel", PointerValue (ulEm));
+  enbLteDevs.Get (0)->TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (&LteRlcUmE2eTestCase::UlDropEvent, this));
+
+  // Sending packets from eNB RRC layer (eNB -> UE)
+  lteSimpleHelper->m_enbRrc->SetArrivalTime (Seconds (0.010));
+  lteSimpleHelper->m_enbRrc->SetPduSize (100);
+
+  // MAC sends transmission opportunities (TxOpp)
+  lteSimpleHelper->m_enbMac->SetTxOppSize (150);
+  lteSimpleHelper->m_enbMac->SetTxOppTime (Seconds (0.005));
+  lteSimpleHelper->m_enbMac->SetTxOpportunityMode (LteTestMac::RANDOM_MODE);
+
+  // Sending packets from UE RRC layer (UE -> eNB)
+  lteSimpleHelper->m_ueRrc->SetArrivalTime (Seconds (0.010));
+  lteSimpleHelper->m_ueRrc->SetPduSize (100);
+
+  // MAC sends transmission opportunities (TxOpp)
+  lteSimpleHelper->m_ueMac->SetTxOppSize (150);
+  lteSimpleHelper->m_ueMac->SetTxOppTime (Seconds (0.005));
+  lteSimpleHelper->m_ueMac->SetTxOpportunityMode (LteTestMac::RANDOM_MODE);
+
+  // Start/Stop pseudo-application at eNB RRC
+  Simulator::Schedule (Seconds (0.100), &LteTestRrc::Start, lteSimpleHelper->m_enbRrc);
+  Simulator::Schedule (Seconds (10.100), &LteTestRrc::Stop, lteSimpleHelper->m_enbRrc);
+
+  // Start/Stop pseudo-application at UE RRC
+  Simulator::Schedule (Seconds (20.100), &LteTestRrc::Start, lteSimpleHelper->m_ueRrc);
+  Simulator::Schedule (Seconds (30.100), &LteTestRrc::Stop, lteSimpleHelper->m_ueRrc);
+
+
+  Simulator::Stop (Seconds (31.000));
+  Simulator::Run ();
+
+  uint32_t txEnbRrcPdus = lteSimpleHelper->m_enbRrc->GetTxPdus ();
+  uint32_t rxUeRrcPdus = lteSimpleHelper->m_ueRrc->GetRxPdus ();
+
+  uint32_t txUeRrcPdus = lteSimpleHelper->m_ueRrc->GetTxPdus ();
+  uint32_t rxEnbRrcPdus = lteSimpleHelper->m_enbRrc->GetRxPdus ();
+
+  // NS_LOG_INFO ("Seed = " << m_seed);
+  // NS_LOG_INFO ("Losses (%) = " << uint32_t (m_losses * 100));
+
+  // NS_LOG_INFO ("dl dev drops = " << m_dlDrops);
+  // NS_LOG_INFO ("ul dev drops = " << m_ulDrops);
+
+  // NS_LOG_INFO ("eNB tx RRC count = " << txEnbRrcPdus);
+  // NS_LOG_INFO ("eNB rx RRC count = " << rxEnbRrcPdus);
+  // NS_LOG_INFO ("UE tx RRC count = " << txUeRrcPdus);
+  // NS_LOG_INFO ("UE rx RRC count = " << rxUeRrcPdus);
+
+  NS_LOG_INFO (m_seed << "\t" << m_losses << "\t" << txEnbRrcPdus << "\t" << rxUeRrcPdus << "\t" << m_dlDrops);
+  NS_LOG_INFO (m_seed << "\t" << m_losses << "\t" << txUeRrcPdus << "\t" << rxEnbRrcPdus << "\t" << m_ulDrops);
+
+  NS_TEST_ASSERT_MSG_EQ (txEnbRrcPdus, rxUeRrcPdus + m_dlDrops,
+                         "Downlink: TX PDUs (" << txEnbRrcPdus << ") != RX PDUs (" << rxUeRrcPdus << ") + DROPS (" << m_dlDrops << ")");
+  NS_TEST_ASSERT_MSG_EQ (txUeRrcPdus, rxEnbRrcPdus + m_ulDrops,
+                         "Uplink: TX PDUs (" << txUeRrcPdus << ") != RX PDUs (" << rxEnbRrcPdus << ") + DROPS (" << m_ulDrops << ")");
+
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-rlc-um-e2e.h	Wed Feb 08 17:14:58 2012 +0100
@@ -0,0 +1,61 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Manuel Requena <manuel.requena@cttc.es>
+ */
+
+#ifndef LTE_TEST_RLC_UM_E2E_H
+#define LTE_TEST_RLC_UM_E2E_H
+
+#include "ns3/test.h"
+
+
+using namespace ns3;
+
+
+/**
+ * Test x.x.x RLC UM: End-to-end flow
+ */
+class LteRlcUmE2eTestSuite : public TestSuite
+{
+public:
+  LteRlcUmE2eTestSuite ();
+};
+
+
+class LteRlcUmE2eTestCase : public TestCase
+{
+  public:
+    LteRlcUmE2eTestCase (std::string name, uint32_t seed, double losses);
+    LteRlcUmE2eTestCase ();
+    virtual ~LteRlcUmE2eTestCase ();
+
+  private:
+    virtual void DoRun (void);
+
+    void DlDropEvent (Ptr<const Packet> p);
+    void UlDropEvent (Ptr<const Packet> p);
+
+    uint32_t m_dlDrops;
+    uint32_t m_ulDrops;
+
+    uint32_t m_seed;
+    double   m_losses;
+};
+
+
+#endif // LTE_TEST_RLC_UM_E2E_H
--- a/src/lte/wscript	Wed Feb 08 13:42:00 2012 +0100
+++ b/src/lte/wscript	Wed Feb 08 17:14:58 2012 +0100
@@ -79,8 +79,12 @@
         'test/lte-test-spectrum-value-helper.cc',
         'test/lte-test-pathloss-model.cc',
         'test/lte-test-entities.cc',
+        'test/lte-simple-helper.cc',
+        'test/lte-simple-net-device.cc',
         'test/lte-test-rlc-um-transmitter.cc',
         'test/lte-test-rlc-am-transmitter.cc',
+        'test/lte-test-rlc-um-e2e.cc',
+        'test/lte-test-rlc-am-e2e.cc',
         'test/epc-test-gtpu.cc',
         'test/test-epc-tft-classifier.cc',
         'test/epc-test-s1u-downlink.cc',
@@ -162,8 +166,12 @@
         'test/lte-test-pathloss-model.h',
         'test/epc-test-gtpu.h',
         'test/lte-test-entities.h',
+        'test/lte-simple-net-device.h',
+        'test/lte-simple-helper.h',
         'test/lte-test-rlc-um-transmitter.h',
         'test/lte-test-rlc-am-transmitter.h',
+        'test/lte-test-rlc-um-e2e.h',
+        'test/lte-test-rlc-am-e2e.h',
         'model/epc-tft.h',
         'model/epc-tft-classifier.h',
         'model/lte-mi-error-model.h'