Merge branch 'header-tag-dev' into 'master'
Extend core API to tag byte ranges -- first use case: Avoid the use of PacketTag in LTE PDCP and RLC, ByteTagging only their headers See merge request nsnam/ns-3-dev!32
This commit is contained in:
@@ -116,6 +116,7 @@ us a note on ns-developers mailing list.</p>
|
||||
</ul>
|
||||
</li>
|
||||
<li> The default qdisc installed on single-queue devices (such as PointToPoint, Csma and Simple) is now FqCodel (instead of PfifoFast). On multi-queue devices (such as Wifi), the default root qdisc is now Mq with as many FqCoDel child qdiscs as the number of device queues. The new defaults are motivated by the willingness to align with the behavior of major Linux distributions and by the need to preserve the effectiveness of Wifi EDCA Functions in differentiating Access Categories (see issue #35).</li>
|
||||
<li>LTE RLC TM mode does not report anymore the layer-to-layer delay, as it misses (by standard) an header to which attach the timestamp tag. Users can switch to the PDCP layer delay measurements, which must be the same.</li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -178,6 +178,9 @@ LtePdcp::DoTransmitPdcpSdu (Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
|
||||
|
||||
// Sender timestamp
|
||||
PdcpTag pdcpTag (Simulator::Now ());
|
||||
|
||||
LtePdcpHeader pdcpHeader;
|
||||
pdcpHeader.SetSequenceNumber (m_txSequenceNumber);
|
||||
|
||||
@@ -191,10 +194,8 @@ LtePdcp::DoTransmitPdcpSdu (Ptr<Packet> p)
|
||||
|
||||
NS_LOG_LOGIC ("PDCP header: " << pdcpHeader);
|
||||
p->AddHeader (pdcpHeader);
|
||||
p->AddByteTag (pdcpTag, 1, pdcpHeader.GetSerializedSize ());
|
||||
|
||||
// Sender timestamp
|
||||
PdcpTag pdcpTag (Simulator::Now ());
|
||||
p->AddPacketTag (pdcpTag);
|
||||
m_txPdu (m_rnti, m_lcid, p->GetSize ());
|
||||
|
||||
LteRlcSapProvider::TransmitPdcpPduParameters params;
|
||||
@@ -213,8 +214,7 @@ LtePdcp::DoReceivePdu (Ptr<Packet> p)
|
||||
// Receiver timestamp
|
||||
PdcpTag pdcpTag;
|
||||
Time delay;
|
||||
NS_ASSERT_MSG (p->PeekPacketTag (pdcpTag), "PdcpTag is missing");
|
||||
p->RemovePacketTag (pdcpTag);
|
||||
p->FindFirstMatchingByteTag (pdcpTag);
|
||||
delay = Simulator::Now() - pdcpTag.GetSenderTimestamp ();
|
||||
m_rxPdu(m_rnti, m_lcid, p->GetSize (), delay.GetNanoSeconds ());
|
||||
|
||||
|
||||
@@ -157,11 +157,6 @@ LteRlcAm::DoTransmitPdcpPdu (Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
|
||||
|
||||
/** Store arrival time */
|
||||
Time now = Simulator::Now ();
|
||||
RlcTag timeTag (now);
|
||||
p->AddPacketTag (timeTag);
|
||||
|
||||
/** Store PDCP PDU */
|
||||
|
||||
LteRlcSduStatusTag tag;
|
||||
@@ -169,7 +164,7 @@ LteRlcAm::DoTransmitPdcpPdu (Ptr<Packet> p)
|
||||
p->AddPacketTag (tag);
|
||||
|
||||
NS_LOG_LOGIC ("Txon Buffer: New packet added");
|
||||
m_txonBuffer.push_back (p);
|
||||
m_txonBuffer.push_back (TxPdu (p, Simulator::Now ()));
|
||||
m_txonBufferSize += p->GetSize ();
|
||||
NS_LOG_LOGIC ("NumOfBuffers = " << m_txonBuffer.size() );
|
||||
NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
|
||||
@@ -258,8 +253,7 @@ LteRlcAm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
|
||||
// Sender timestamp
|
||||
RlcTag rlcTag (Simulator::Now ());
|
||||
NS_ASSERT_MSG (!packet->PeekPacketTag (rlcTag), "RlcTag is already present");
|
||||
packet->AddPacketTag (rlcTag);
|
||||
packet->AddByteTag (rlcTag, 1, rlcAmHeader.GetSerializedSize ());
|
||||
m_txPdu (m_rnti, m_lcid, packet->GetSize ());
|
||||
|
||||
// Send RLC PDU to MAC layer
|
||||
@@ -292,8 +286,7 @@ LteRlcAm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
NS_LOG_LOGIC ("SN = " << seqNumberValue << " m_pdu " << m_retxBuffer.at (seqNumberValue).m_pdu);
|
||||
|
||||
if (m_retxBuffer.at (seqNumberValue).m_pdu != 0)
|
||||
{
|
||||
|
||||
{
|
||||
Ptr<Packet> packet = m_retxBuffer.at (seqNumberValue).m_pdu->Copy ();
|
||||
|
||||
if (( packet->GetSize () <= txOpParams.bytes )
|
||||
@@ -340,12 +333,14 @@ LteRlcAm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
}
|
||||
|
||||
packet->AddHeader (rlcAmHeader);
|
||||
|
||||
RlcTag rlcTag;
|
||||
rlcTag.SetSenderTimestamp (Simulator::Now ());
|
||||
|
||||
packet->AddByteTag (rlcTag, 1, rlcAmHeader.GetSerializedSize ());
|
||||
|
||||
NS_LOG_LOGIC ("new AM RLC header: " << rlcAmHeader);
|
||||
|
||||
// Sender timestamp
|
||||
RlcTag rlcTag (Simulator::Now ());
|
||||
NS_ASSERT_MSG (packet->PeekPacketTag (rlcTag), "RlcTag is missing");
|
||||
packet->ReplacePacketTag (rlcTag);
|
||||
m_txPdu (m_rnti, m_lcid, packet->GetSize ());
|
||||
|
||||
// Send RLC PDU to MAC layer
|
||||
@@ -360,6 +355,7 @@ LteRlcAm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
m_macSapProvider->TransmitPdu (params);
|
||||
|
||||
m_retxBuffer.at (seqNumberValue).m_retxCount++;
|
||||
m_retxBuffer.at (seqNumberValue).m_waitingSince = Simulator::Now ();
|
||||
NS_LOG_INFO ("Incr RETX_COUNT for SN = " << seqNumberValue);
|
||||
if (m_retxBuffer.at (seqNumberValue).m_retxCount >= m_maxRetxThreshold)
|
||||
{
|
||||
@@ -369,11 +365,13 @@ LteRlcAm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
NS_LOG_INFO ("Move SN = " << seqNumberValue << " back to txedBuffer");
|
||||
m_txedBuffer.at (seqNumberValue).m_pdu = m_retxBuffer.at (seqNumberValue).m_pdu->Copy ();
|
||||
m_txedBuffer.at (seqNumberValue).m_retxCount = m_retxBuffer.at (seqNumberValue).m_retxCount;
|
||||
m_txedBuffer.at (seqNumberValue).m_waitingSince = m_retxBuffer.at (seqNumberValue).m_waitingSince;
|
||||
m_txedBufferSize += m_txedBuffer.at (seqNumberValue).m_pdu->GetSize ();
|
||||
|
||||
m_retxBufferSize -= m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
|
||||
m_retxBuffer.at (seqNumberValue).m_pdu = 0;
|
||||
m_retxBuffer.at (seqNumberValue).m_retxCount = 0;
|
||||
m_retxBuffer.at (seqNumberValue).m_waitingSince = MilliSeconds (0);
|
||||
|
||||
NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
|
||||
|
||||
@@ -441,12 +439,13 @@ LteRlcAm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
}
|
||||
|
||||
NS_LOG_LOGIC ("SDUs in TxonBuffer = " << m_txonBuffer.size ());
|
||||
NS_LOG_LOGIC ("First SDU buffer = " << *(m_txonBuffer.begin()));
|
||||
NS_LOG_LOGIC ("First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ());
|
||||
NS_LOG_LOGIC ("First SDU buffer = " << m_txonBuffer.begin ()->m_pdu);
|
||||
NS_LOG_LOGIC ("First SDU size = " << m_txonBuffer.begin ()->m_pdu->GetSize ());
|
||||
NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize);
|
||||
NS_LOG_LOGIC ("Remove SDU from TxBuffer");
|
||||
Ptr<Packet> firstSegment = (*(m_txonBuffer.begin ()))->Copy ();
|
||||
m_txonBufferSize -= (*(m_txonBuffer.begin()))->GetSize ();
|
||||
Time firstSegmentTime = m_txonBuffer.begin ()->m_waitingSince;
|
||||
Ptr<Packet> firstSegment = m_txonBuffer.begin ()->m_pdu->Copy ();
|
||||
m_txonBufferSize -= m_txonBuffer.begin ()->m_pdu->GetSize ();
|
||||
NS_LOG_LOGIC ("txBufferSize = " << m_txonBufferSize );
|
||||
m_txonBuffer.erase (m_txonBuffer.begin ());
|
||||
|
||||
@@ -496,12 +495,12 @@ LteRlcAm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
{
|
||||
firstSegment->AddPacketTag (oldTag);
|
||||
|
||||
m_txonBuffer.insert (m_txonBuffer.begin (), firstSegment);
|
||||
m_txonBufferSize += (*(m_txonBuffer.begin()))->GetSize ();
|
||||
m_txonBuffer.insert (m_txonBuffer.begin (), TxPdu (firstSegment, firstSegmentTime));
|
||||
m_txonBufferSize += m_txonBuffer.begin ()->m_pdu->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 (" Front buffer size = " << m_txonBuffer.begin ()->m_pdu->GetSize ());
|
||||
NS_LOG_LOGIC (" txonBufferSize = " << m_txonBufferSize );
|
||||
}
|
||||
else
|
||||
@@ -563,8 +562,8 @@ LteRlcAm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txonBuffer.size ());
|
||||
if (m_txonBuffer.size () > 0)
|
||||
{
|
||||
NS_LOG_LOGIC (" First SDU buffer = " << *(m_txonBuffer.begin()));
|
||||
NS_LOG_LOGIC (" First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ());
|
||||
NS_LOG_LOGIC (" First SDU buffer = " << m_txonBuffer.begin ()->m_pdu);
|
||||
NS_LOG_LOGIC (" First SDU size = " << m_txonBuffer.begin ()->m_pdu->GetSize ());
|
||||
}
|
||||
NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
|
||||
|
||||
@@ -593,15 +592,16 @@ LteRlcAm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txonBuffer.size ());
|
||||
if (m_txonBuffer.size () > 0)
|
||||
{
|
||||
NS_LOG_LOGIC (" First SDU buffer = " << *(m_txonBuffer.begin()));
|
||||
NS_LOG_LOGIC (" First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ());
|
||||
NS_LOG_LOGIC (" First SDU buffer = " << m_txonBuffer.begin ()->m_pdu);
|
||||
NS_LOG_LOGIC (" First SDU size = " << m_txonBuffer.begin ()->m_pdu->GetSize ());
|
||||
}
|
||||
NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
|
||||
NS_LOG_LOGIC (" Remove SDU from TxBuffer");
|
||||
|
||||
// (more segments)
|
||||
firstSegment = (*(m_txonBuffer.begin ()))->Copy ();
|
||||
m_txonBufferSize -= (*(m_txonBuffer.begin()))->GetSize ();
|
||||
firstSegment = m_txonBuffer.begin ()->m_pdu->Copy ();
|
||||
firstSegmentTime = m_txonBuffer.begin ()->m_waitingSince;
|
||||
m_txonBufferSize -= m_txonBuffer.begin ()->m_pdu->GetSize ();
|
||||
m_txonBuffer.erase (m_txonBuffer.begin ());
|
||||
NS_LOG_LOGIC (" txBufferSize = " << m_txonBufferSize );
|
||||
}
|
||||
@@ -716,17 +716,20 @@ LteRlcAm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
|
||||
// Build RLC PDU with DataField and Header
|
||||
NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader);
|
||||
|
||||
RlcTag rlcTag;
|
||||
rlcTag.SetSenderTimestamp (Simulator::Now ());
|
||||
|
||||
packet->AddHeader (rlcAmHeader);
|
||||
packet->AddByteTag (rlcTag, 1, rlcAmHeader.GetSerializedSize ());
|
||||
|
||||
// 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 ().GetValue () ).m_pdu = packet->Copy ();
|
||||
m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_retxCount = 0;
|
||||
m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_waitingSince = Simulator::Now ();
|
||||
|
||||
// Sender timestamp
|
||||
RlcTag rlcTag (Simulator::Now ());
|
||||
packet->ReplacePacketTag (rlcTag);
|
||||
m_txPdu (m_rnti, m_lcid, packet->GetSize ());
|
||||
|
||||
// Send RLC PDU to MAC layer
|
||||
@@ -753,19 +756,22 @@ LteRlcAm::DoReceivePdu (LteMacSapUser::ReceivePduParameters rxPduParams)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << rxPduParams.p->GetSize ());
|
||||
|
||||
// Receiver timestamp
|
||||
RlcTag rlcTag;
|
||||
Time delay;
|
||||
NS_ASSERT_MSG (rxPduParams.p->PeekPacketTag (rlcTag), "RlcTag is missing");
|
||||
rxPduParams.p->RemovePacketTag (rlcTag);
|
||||
delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
|
||||
m_rxPdu (m_rnti, m_lcid, rxPduParams.p->GetSize (), delay.GetNanoSeconds ());
|
||||
|
||||
// Get RLC header parameters
|
||||
LteRlcAmHeader rlcAmHeader;
|
||||
rxPduParams.p->PeekHeader (rlcAmHeader);
|
||||
NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
|
||||
|
||||
// Receiver timestamp
|
||||
Time delay;
|
||||
RlcTag rlcTag;
|
||||
|
||||
bool ret = rxPduParams.p->FindFirstMatchingByteTag (rlcTag);
|
||||
NS_ASSERT_MSG(ret, "RlcTag not found in RLC Header. The packet went into a real network?");
|
||||
|
||||
delay = Simulator::Now () - rlcTag.GetSenderTimestamp ();
|
||||
|
||||
m_rxPdu (m_rnti, m_lcid, rxPduParams.p->GetSize (), delay.GetNanoSeconds ());
|
||||
|
||||
if ( rlcAmHeader.IsDataPdu () )
|
||||
{
|
||||
|
||||
@@ -1050,11 +1056,13 @@ LteRlcAm::DoReceivePdu (LteMacSapUser::ReceivePduParameters rxPduParams)
|
||||
NS_LOG_INFO ("Move SN = " << seqNumberValue << " to retxBuffer");
|
||||
m_retxBuffer.at (seqNumberValue).m_pdu = m_txedBuffer.at (seqNumberValue).m_pdu->Copy ();
|
||||
m_retxBuffer.at (seqNumberValue).m_retxCount = m_txedBuffer.at (seqNumberValue).m_retxCount;
|
||||
m_retxBuffer.at (seqNumberValue).m_waitingSince = m_txedBuffer.at (seqNumberValue).m_waitingSince;
|
||||
m_retxBufferSize += m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
|
||||
|
||||
m_txedBufferSize -= m_txedBuffer.at (seqNumberValue).m_pdu->GetSize ();
|
||||
m_txedBuffer.at (seqNumberValue).m_pdu = 0;
|
||||
m_txedBuffer.at (seqNumberValue).m_retxCount = 0;
|
||||
m_txedBuffer.at (seqNumberValue).m_waitingSince = MilliSeconds (0);
|
||||
}
|
||||
|
||||
NS_ASSERT (m_retxBuffer.at (seqNumberValue).m_pdu != 0);
|
||||
@@ -1070,6 +1078,7 @@ LteRlcAm::DoReceivePdu (LteMacSapUser::ReceivePduParameters rxPduParams)
|
||||
// NS_LOG_INFO ("m_txedBuffer( " << m_vtA << " )->GetSize = " << m_txedBuffer.at (m_vtA.GetValue ())->GetSize ());
|
||||
m_txedBufferSize -= m_txedBuffer.at (seqNumberValue).m_pdu->GetSize ();
|
||||
m_txedBuffer.at (seqNumberValue).m_pdu = 0;
|
||||
m_txedBuffer.at (seqNumberValue).m_waitingSince = MilliSeconds (0);
|
||||
NS_ASSERT (m_retxBuffer.at (seqNumberValue).m_pdu == 0);
|
||||
}
|
||||
|
||||
@@ -1079,6 +1088,7 @@ LteRlcAm::DoReceivePdu (LteMacSapUser::ReceivePduParameters rxPduParams)
|
||||
m_retxBufferSize -= m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
|
||||
m_retxBuffer.at (seqNumberValue).m_pdu = 0;
|
||||
m_retxBuffer.at (seqNumberValue).m_retxCount = 0;
|
||||
m_retxBuffer.at (seqNumberValue).m_waitingSince = MilliSeconds (0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1140,7 +1150,12 @@ void
|
||||
LteRlcAm::ReassembleAndDeliver (Ptr<Packet> packet)
|
||||
{
|
||||
LteRlcAmHeader rlcAmHeader;
|
||||
RlcTag rlcTag;
|
||||
bool ret = packet->FindFirstMatchingByteTag (rlcTag);
|
||||
NS_ASSERT(ret);
|
||||
packet->RemoveHeader (rlcAmHeader);
|
||||
ret = packet->FindFirstMatchingByteTag (rlcTag);
|
||||
NS_ASSERT(!ret);
|
||||
uint8_t framingInfo = rlcAmHeader.GetFramingInfo ();
|
||||
SequenceNumber10 currSeqNumber = rlcAmHeader.GetSequenceNumber ();
|
||||
bool expectedSnLost;
|
||||
@@ -1572,25 +1587,23 @@ LteRlcAm::DoReportBufferStatus (void)
|
||||
Time txonQueueHolDelay (0);
|
||||
if ( m_txonBufferSize > 0 )
|
||||
{
|
||||
RlcTag txonQueueHolTimeTag;
|
||||
m_txonBuffer.front ()->PeekPacketTag (txonQueueHolTimeTag);
|
||||
txonQueueHolDelay = now - txonQueueHolTimeTag.GetSenderTimestamp ();
|
||||
txonQueueHolDelay = now - m_txonBuffer.front ().m_waitingSince;
|
||||
}
|
||||
|
||||
// Retransmission Queue HOL time
|
||||
Time retxQueueHolDelay;
|
||||
RlcTag retxQueueHolTimeTag;
|
||||
if ( m_retxBufferSize > 0 )
|
||||
{
|
||||
Time senderTimestamp;
|
||||
if (m_retxBuffer.at (m_vtA.GetValue ()).m_pdu != 0)
|
||||
{
|
||||
m_retxBuffer.at (m_vtA.GetValue ()).m_pdu->PeekPacketTag (retxQueueHolTimeTag);
|
||||
senderTimestamp = m_retxBuffer.at (m_vtA.GetValue ()).m_waitingSince;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_txedBuffer.at (m_vtA.GetValue ()).m_pdu->PeekPacketTag (retxQueueHolTimeTag);
|
||||
}
|
||||
retxQueueHolDelay = now - retxQueueHolTimeTag.GetSenderTimestamp ();
|
||||
senderTimestamp = m_txedBuffer.at (m_vtA.GetValue ()).m_waitingSince;
|
||||
}
|
||||
retxQueueHolDelay = now - senderTimestamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1700,11 +1713,13 @@ LteRlcAm::ExpirePollRetransmitTimer (void)
|
||||
NS_LOG_INFO ("Move PDU " << sn << " from txedBuffer to retxBuffer");
|
||||
m_retxBuffer.at (snValue).m_pdu = m_txedBuffer.at (snValue).m_pdu->Copy ();
|
||||
m_retxBuffer.at (snValue).m_retxCount = m_txedBuffer.at (snValue).m_retxCount;
|
||||
m_retxBuffer.at (snValue).m_waitingSince = m_txedBuffer.at (snValue).m_waitingSince;
|
||||
m_retxBufferSize += m_retxBuffer.at (snValue).m_pdu->GetSize ();
|
||||
|
||||
m_txedBufferSize -= m_txedBuffer.at (snValue).m_pdu->GetSize ();
|
||||
m_txedBuffer.at (snValue).m_pdu = 0;
|
||||
m_txedBuffer.at (snValue).m_retxCount = 0;
|
||||
m_txedBuffer.at (snValue).m_waitingSince = MilliSeconds (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,14 +107,36 @@ private:
|
||||
void DoReportBufferStatus ();
|
||||
|
||||
private:
|
||||
std::vector < Ptr<Packet> > m_txonBuffer; ///< Transmission buffer
|
||||
/**
|
||||
* \brief Store an incoming (from layer above us) PDU, waiting to transmit it
|
||||
*/
|
||||
struct TxPdu
|
||||
{
|
||||
/**
|
||||
* \brief TxPdu default constructor
|
||||
* \param pdu the PDU
|
||||
* \param time the arrival time
|
||||
*/
|
||||
TxPdu (const Ptr<Packet> &pdu, const Time &time) :
|
||||
m_pdu (pdu),
|
||||
m_waitingSince (time)
|
||||
{ }
|
||||
|
||||
/// RetxPdu structure
|
||||
struct RetxPdu
|
||||
{
|
||||
Ptr<Packet> m_pdu; ///< PDU
|
||||
uint16_t m_retxCount; ///< retransmit count
|
||||
};
|
||||
TxPdu () = delete;
|
||||
|
||||
Ptr<Packet> m_pdu; ///< PDU
|
||||
Time m_waitingSince; ///< Layer arrival time
|
||||
};
|
||||
|
||||
std::vector < TxPdu > m_txonBuffer; ///< Transmission buffer
|
||||
|
||||
/// RetxPdu structure
|
||||
struct RetxPdu
|
||||
{
|
||||
Ptr<Packet> m_pdu; ///< PDU
|
||||
uint16_t m_retxCount; ///< retransmit count
|
||||
Time m_waitingSince; ///!< Layer arrival time
|
||||
};
|
||||
|
||||
std::vector <RetxPdu> m_txedBuffer; ///< Buffer for transmitted and retransmitted PDUs
|
||||
///< that have not been acked but are not considered
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "ns3/log.h"
|
||||
|
||||
#include "ns3/lte-rlc-tm.h"
|
||||
#include "ns3/lte-rlc-tag.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -81,12 +80,8 @@ LteRlcTm::DoTransmitPdcpPdu (Ptr<Packet> p)
|
||||
|
||||
if (m_txBufferSize + p->GetSize () <= m_maxTxBufferSize)
|
||||
{
|
||||
/** Store arrival time */
|
||||
RlcTag timeTag (Simulator::Now ());
|
||||
p->AddPacketTag (timeTag);
|
||||
|
||||
NS_LOG_LOGIC ("Tx Buffer: New packet added");
|
||||
m_txBuffer.push_back (p);
|
||||
m_txBuffer.push_back (TxPdu (p, Simulator::Now ()));
|
||||
m_txBufferSize += p->GetSize ();
|
||||
NS_LOG_LOGIC ("NumOfBuffers = " << m_txBuffer.size() );
|
||||
NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
|
||||
@@ -127,20 +122,18 @@ LteRlcTm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
return;
|
||||
}
|
||||
|
||||
Ptr<Packet> packet = (*(m_txBuffer.begin ()))->Copy ();
|
||||
Ptr<Packet> packet = m_txBuffer.begin ()->m_pdu->Copy ();
|
||||
|
||||
if (txOpParams.bytes < packet->GetSize ())
|
||||
{
|
||||
NS_LOG_WARN ("TX opportunity too small = " << txOpParams.bytes << " (PDU size: " << packet->GetSize () << ")");
|
||||
NS_LOG_WARN ("TX opportunity too small = " << txOpParams.bytes <<
|
||||
" (PDU size: " << packet->GetSize () << ")");
|
||||
return;
|
||||
}
|
||||
|
||||
m_txBufferSize -= (*(m_txBuffer.begin()))->GetSize ();
|
||||
m_txBufferSize -= packet->GetSize ();
|
||||
m_txBuffer.erase (m_txBuffer.begin ());
|
||||
|
||||
// Sender timestamp
|
||||
RlcTag rlcTag (Simulator::Now ());
|
||||
packet->ReplacePacketTag (rlcTag);
|
||||
|
||||
m_txPdu (m_rnti, m_lcid, packet->GetSize ());
|
||||
|
||||
// Send RLC PDU to MAC layer
|
||||
@@ -172,13 +165,7 @@ LteRlcTm::DoReceivePdu (LteMacSapUser::ReceivePduParameters rxPduParams)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << rxPduParams.p->GetSize ());
|
||||
|
||||
// Receiver timestamp
|
||||
RlcTag rlcTag;
|
||||
Time delay;
|
||||
NS_ASSERT_MSG (rxPduParams.p->PeekPacketTag (rlcTag), "RlcTag is missing");
|
||||
rxPduParams.p->RemovePacketTag (rlcTag);
|
||||
delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
|
||||
m_rxPdu (m_rnti, m_lcid, rxPduParams.p->GetSize (), delay.GetNanoSeconds ());
|
||||
m_rxPdu (m_rnti, m_lcid, rxPduParams.p->GetSize (), 0);
|
||||
|
||||
// 5.1.1.2 Receive operations
|
||||
// 5.1.1.2.1 General
|
||||
@@ -197,10 +184,7 @@ LteRlcTm::DoReportBufferStatus (void)
|
||||
|
||||
if (! m_txBuffer.empty ())
|
||||
{
|
||||
RlcTag holTimeTag;
|
||||
NS_ASSERT_MSG (m_txBuffer.front ()->PeekPacketTag (holTimeTag), "RlcTag is missing");
|
||||
m_txBuffer.front ()->PeekPacketTag (holTimeTag);
|
||||
holDelay = Simulator::Now () - holTimeTag.GetSenderTimestamp ();
|
||||
holDelay = Simulator::Now () - m_txBuffer.front ().m_waitingSince;
|
||||
|
||||
queueSize = m_txBufferSize; // just data in tx queue (no header overhead for RLC TM)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,10 @@ namespace ns3 {
|
||||
|
||||
/**
|
||||
* LTE RLC Transparent Mode (TM), see 3GPP TS 36.322
|
||||
*
|
||||
* Please note that, as in TM it is not possible to add any header, the delay
|
||||
* measurements gathered from the trace source "RxPDU" of LteRlc are invalid
|
||||
* (they will be always 0)
|
||||
*/
|
||||
class LteRlcTm : public LteRlc
|
||||
{
|
||||
@@ -70,12 +74,33 @@ private:
|
||||
void DoReportBufferStatus ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Store an incoming (from layer above us) PDU, waiting to transmit it
|
||||
*/
|
||||
struct TxPdu
|
||||
{
|
||||
/**
|
||||
* \brief TxPdu default constructor
|
||||
* \param pdu the PDU
|
||||
* \param time the arrival time
|
||||
*/
|
||||
TxPdu (const Ptr<Packet> &pdu, const Time &time) :
|
||||
m_pdu (pdu),
|
||||
m_waitingSince (time)
|
||||
{ }
|
||||
|
||||
TxPdu () = delete;
|
||||
|
||||
Ptr<Packet> m_pdu; ///< PDU
|
||||
Time m_waitingSince; ///< Layer arrival time
|
||||
};
|
||||
|
||||
std::vector < TxPdu > m_txBuffer; ///< Transmission buffer
|
||||
|
||||
uint32_t m_maxTxBufferSize; ///< maximum transmit buffer size
|
||||
uint32_t m_txBufferSize; ///< transmit buffer size
|
||||
std::vector < Ptr<Packet> > m_txBuffer; ///< Transmission buffer
|
||||
|
||||
EventId m_rbsTimer; ///< RBS timer
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -88,18 +88,13 @@ LteRlcUm::DoTransmitPdcpPdu (Ptr<Packet> p)
|
||||
|
||||
if (m_txBufferSize + p->GetSize () <= m_maxTxBufferSize)
|
||||
{
|
||||
/** Store arrival time */
|
||||
RlcTag timeTag (Simulator::Now ());
|
||||
p->AddPacketTag (timeTag);
|
||||
|
||||
/** Store PDCP PDU */
|
||||
|
||||
LteRlcSduStatusTag tag;
|
||||
tag.SetStatus (LteRlcSduStatusTag::FULL_SDU);
|
||||
p->AddPacketTag (tag);
|
||||
|
||||
NS_LOG_LOGIC ("Tx Buffer: New packet added");
|
||||
m_txBuffer.push_back (p);
|
||||
m_txBuffer.push_back (TxPdu (p, Simulator::Now ()));
|
||||
m_txBufferSize += p->GetSize ();
|
||||
NS_LOG_LOGIC ("NumOfBuffers = " << m_txBuffer.size() );
|
||||
NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
|
||||
@@ -153,13 +148,15 @@ LteRlcUm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
return;
|
||||
}
|
||||
|
||||
Ptr<Packet> firstSegment = m_txBuffer.begin ()->m_pdu->Copy ();
|
||||
Time firstSegmentTime = m_txBuffer.begin ()->m_waitingSince;
|
||||
|
||||
NS_LOG_LOGIC ("SDUs in TxBuffer = " << m_txBuffer.size ());
|
||||
NS_LOG_LOGIC ("First SDU buffer = " << *(m_txBuffer.begin()));
|
||||
NS_LOG_LOGIC ("First SDU size = " << (*(m_txBuffer.begin()))->GetSize ());
|
||||
NS_LOG_LOGIC ("First SDU buffer = " << firstSegment);
|
||||
NS_LOG_LOGIC ("First SDU size = " << firstSegment->GetSize ());
|
||||
NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize);
|
||||
NS_LOG_LOGIC ("Remove SDU from TxBuffer");
|
||||
Ptr<Packet> firstSegment = (*(m_txBuffer.begin ()))->Copy ();
|
||||
m_txBufferSize -= (*(m_txBuffer.begin()))->GetSize ();
|
||||
m_txBufferSize -= firstSegment->GetSize ();
|
||||
NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize );
|
||||
m_txBuffer.erase (m_txBuffer.begin ());
|
||||
|
||||
@@ -209,12 +206,12 @@ LteRlcUm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
{
|
||||
firstSegment->AddPacketTag (oldTag);
|
||||
|
||||
m_txBuffer.insert (m_txBuffer.begin (), firstSegment);
|
||||
m_txBufferSize += (*(m_txBuffer.begin()))->GetSize ();
|
||||
m_txBuffer.insert (m_txBuffer.begin (), TxPdu (firstSegment, firstSegmentTime));
|
||||
m_txBufferSize += m_txBuffer.begin()->m_pdu->GetSize ();
|
||||
|
||||
NS_LOG_LOGIC (" TX buffer: Give back the remaining segment");
|
||||
NS_LOG_LOGIC (" TX buffers = " << m_txBuffer.size ());
|
||||
NS_LOG_LOGIC (" Front buffer size = " << (*(m_txBuffer.begin()))->GetSize ());
|
||||
NS_LOG_LOGIC (" Front buffer size = " << m_txBuffer.begin()->m_pdu->GetSize ());
|
||||
NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
|
||||
}
|
||||
else
|
||||
@@ -275,8 +272,8 @@ LteRlcUm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
|
||||
if (m_txBuffer.size () > 0)
|
||||
{
|
||||
NS_LOG_LOGIC (" First SDU buffer = " << *(m_txBuffer.begin()));
|
||||
NS_LOG_LOGIC (" First SDU size = " << (*(m_txBuffer.begin()))->GetSize ());
|
||||
NS_LOG_LOGIC (" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
|
||||
NS_LOG_LOGIC (" First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize ());
|
||||
}
|
||||
NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
|
||||
|
||||
@@ -305,15 +302,16 @@ LteRlcUm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
|
||||
if (m_txBuffer.size () > 0)
|
||||
{
|
||||
NS_LOG_LOGIC (" First SDU buffer = " << *(m_txBuffer.begin()));
|
||||
NS_LOG_LOGIC (" First SDU size = " << (*(m_txBuffer.begin()))->GetSize ());
|
||||
NS_LOG_LOGIC (" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
|
||||
NS_LOG_LOGIC (" First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize ());
|
||||
}
|
||||
NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
|
||||
NS_LOG_LOGIC (" Remove SDU from TxBuffer");
|
||||
|
||||
// (more segments)
|
||||
firstSegment = (*(m_txBuffer.begin ()))->Copy ();
|
||||
m_txBufferSize -= (*(m_txBuffer.begin()))->GetSize ();
|
||||
firstSegment = m_txBuffer.begin ()->m_pdu->Copy ();
|
||||
firstSegmentTime = m_txBuffer.begin ()->m_waitingSince;
|
||||
m_txBufferSize -= firstSegment->GetSize ();
|
||||
m_txBuffer.erase (m_txBuffer.begin ());
|
||||
NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
|
||||
}
|
||||
@@ -379,7 +377,7 @@ LteRlcUm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
|
||||
// Sender timestamp
|
||||
RlcTag rlcTag (Simulator::Now ());
|
||||
packet->ReplacePacketTag (rlcTag);
|
||||
packet->AddByteTag (rlcTag, 1, rlcHeader.GetSerializedSize ());
|
||||
m_txPdu (m_rnti, m_lcid, packet->GetSize ());
|
||||
|
||||
// Send RLC PDU to MAC layer
|
||||
@@ -414,8 +412,10 @@ LteRlcUm::DoReceivePdu (LteMacSapUser::ReceivePduParameters rxPduParams)
|
||||
// Receiver timestamp
|
||||
RlcTag rlcTag;
|
||||
Time delay;
|
||||
NS_ASSERT_MSG (rxPduParams.p->PeekPacketTag (rlcTag), "RlcTag is missing");
|
||||
rxPduParams.p->RemovePacketTag (rlcTag);
|
||||
|
||||
bool ret = rxPduParams.p->FindFirstMatchingByteTag (rlcTag);
|
||||
NS_ASSERT_MSG (ret, "RlcTag is missing");
|
||||
|
||||
delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
|
||||
m_rxPdu (m_rnti, m_lcid, rxPduParams.p->GetSize (), delay.GetNanoSeconds ());
|
||||
|
||||
@@ -1123,10 +1123,7 @@ LteRlcUm::DoReportBufferStatus (void)
|
||||
|
||||
if (! m_txBuffer.empty ())
|
||||
{
|
||||
RlcTag holTimeTag;
|
||||
NS_ASSERT_MSG (m_txBuffer.front ()->PeekPacketTag (holTimeTag), "RlcTag is missing");
|
||||
m_txBuffer.front ()->PeekPacketTag (holTimeTag);
|
||||
holDelay = Simulator::Now () - holTimeTag.GetSenderTimestamp ();
|
||||
holDelay = Simulator::Now () - m_txBuffer.front().m_waitingSince;
|
||||
|
||||
queueSize = m_txBufferSize + 2 * m_txBuffer.size (); // Data in tx queue + estimated headers size
|
||||
}
|
||||
|
||||
@@ -97,7 +97,28 @@ private:
|
||||
private:
|
||||
uint32_t m_maxTxBufferSize; ///< maximum transmit buffer status
|
||||
uint32_t m_txBufferSize; ///< transmit buffer size
|
||||
std::vector < Ptr<Packet> > m_txBuffer; ///< Transmission buffer
|
||||
/**
|
||||
* \brief Store an incoming (from layer above us) PDU, waiting to transmit it
|
||||
*/
|
||||
struct TxPdu
|
||||
{
|
||||
/**
|
||||
* \brief TxPdu default constructor
|
||||
* \param pdu the PDU
|
||||
* \param time the arrival time
|
||||
*/
|
||||
TxPdu (const Ptr<Packet> &pdu, const Time &time) :
|
||||
m_pdu (pdu),
|
||||
m_waitingSince (time)
|
||||
{ }
|
||||
|
||||
TxPdu () = delete;
|
||||
|
||||
Ptr<Packet> m_pdu; ///< PDU
|
||||
Time m_waitingSince; ///< Layer arrival time
|
||||
};
|
||||
|
||||
std::vector < TxPdu > m_txBuffer; ///< Transmission buffer
|
||||
std::map <uint16_t, Ptr<Packet> > m_rxBuffer; ///< Reception buffer
|
||||
std::vector < Ptr<Packet> > m_reasBuffer; ///< Reassembling buffer
|
||||
|
||||
|
||||
@@ -32,6 +32,80 @@ namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("LteRlc");
|
||||
|
||||
/**
|
||||
* Tag to calculate the per-PDU delay from eNb RLC to UE RLC
|
||||
*/
|
||||
|
||||
class RlcSmHeader : public Header
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
virtual TypeId GetInstanceTypeId (void) const;
|
||||
|
||||
/**
|
||||
* Create an empty RLC tag
|
||||
*/
|
||||
RlcSmHeader ();
|
||||
|
||||
virtual void Serialize (Buffer::Iterator i) const;
|
||||
virtual uint32_t Deserialize (Buffer::Iterator i);
|
||||
virtual uint32_t GetSerializedSize () const;
|
||||
virtual void Print (std::ostream &os) const;
|
||||
};
|
||||
|
||||
RlcSmHeader::RlcSmHeader () : Header ()
|
||||
{
|
||||
// Nothing to do here
|
||||
}
|
||||
|
||||
|
||||
TypeId
|
||||
RlcSmHeader::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::RlcSmTag")
|
||||
.SetParent<Header> ()
|
||||
.SetGroupName("Lte")
|
||||
.AddConstructor<RlcSmHeader> ();
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
RlcSmHeader::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
RlcSmHeader::GetSerializedSize (void) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
RlcSmHeader::Serialize (Buffer::Iterator i) const
|
||||
{
|
||||
// Arbitrary value. It is not used anywhere.
|
||||
i.WriteU8 (8U);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
RlcSmHeader::Deserialize (Buffer::Iterator i)
|
||||
{
|
||||
uint8_t v = i.ReadU8 ();
|
||||
NS_UNUSED (v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
RlcSmHeader::Print (std::ostream &os) const
|
||||
{
|
||||
os << "RlcSmTag";
|
||||
}
|
||||
|
||||
|
||||
/// LteRlcSpecificLteMacSapUser class
|
||||
class LteRlcSpecificLteMacSapUser : public LteMacSapUser
|
||||
@@ -223,8 +297,8 @@ LteRlcSm::DoReceivePdu (LteMacSapUser::ReceivePduParameters rxPduParams)
|
||||
// RLC Performance evaluation
|
||||
RlcTag rlcTag;
|
||||
Time delay;
|
||||
NS_ASSERT_MSG (rxPduParams.p->PeekPacketTag (rlcTag), "RlcTag is missing");
|
||||
rxPduParams.p->RemovePacketTag (rlcTag);
|
||||
bool ret = rxPduParams.p->FindFirstMatchingByteTag (rlcTag);
|
||||
NS_ASSERT_MSG (ret, "RlcTag is missing");
|
||||
delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
|
||||
NS_LOG_LOGIC (" RNTI=" << m_rnti
|
||||
<< " LCID=" << (uint32_t) m_lcid
|
||||
@@ -238,7 +312,13 @@ LteRlcSm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
{
|
||||
NS_LOG_FUNCTION (this << txOpParams.bytes);
|
||||
LteMacSapProvider::TransmitPduParameters params;
|
||||
params.pdu = Create<Packet> (txOpParams.bytes);
|
||||
RlcSmHeader header;
|
||||
RlcTag tag (Simulator::Now ());
|
||||
|
||||
params.pdu = Create<Packet> (txOpParams.bytes - header.GetSerializedSize ());
|
||||
params.pdu->AddHeader (header);
|
||||
params.pdu->AddByteTag (tag, 1, header.GetSerializedSize ());
|
||||
|
||||
params.rnti = m_rnti;
|
||||
params.lcid = m_lcid;
|
||||
params.layer = txOpParams.layer;
|
||||
@@ -246,8 +326,6 @@ LteRlcSm::DoNotifyTxOpportunity (LteMacSapUser::TxOpportunityParameters txOpPara
|
||||
params.componentCarrierId = txOpParams.componentCarrierId;
|
||||
|
||||
// RLC Performance evaluation
|
||||
RlcTag tag (Simulator::Now());
|
||||
params.pdu->AddPacketTag (tag);
|
||||
NS_LOG_LOGIC (" RNTI=" << m_rnti
|
||||
<< " LCID=" << (uint32_t) m_lcid
|
||||
<< " size=" << txOpParams.bytes);
|
||||
|
||||
@@ -820,11 +820,22 @@ Packet::AddByteTag (const Tag &tag) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
|
||||
ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
|
||||
TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
|
||||
TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
|
||||
0,
|
||||
GetSize ());
|
||||
tag.Serialize (buffer);
|
||||
}
|
||||
void
|
||||
Packet::AddByteTag (const Tag &tag, uint32_t start, uint32_t end) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
|
||||
NS_ABORT_MSG_IF (end < start, "Invalid byte range");
|
||||
ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
|
||||
TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
|
||||
static_cast<int32_t> (start),
|
||||
static_cast<int32_t> (end));
|
||||
tag.Serialize (buffer);
|
||||
}
|
||||
ByteTagIterator
|
||||
Packet::GetByteTagIterator (void) const
|
||||
{
|
||||
|
||||
@@ -571,6 +571,27 @@ public:
|
||||
* packet).
|
||||
*/
|
||||
void AddByteTag (const Tag &tag) const;
|
||||
|
||||
/**
|
||||
* \brief Tag the indicated byte range of this packet with a new byte tag.
|
||||
*
|
||||
* As parameters for this method, we do not use indexes, but byte position.
|
||||
* Moreover, as there is no 0-th position, the first position is 1.
|
||||
*
|
||||
* As example, if you want to tag the first 10 bytes, you have to call
|
||||
* the method in this way:
|
||||
*
|
||||
* \code{.cpp}
|
||||
Ptr<Packet> p = ... ;
|
||||
SomeTag tag;
|
||||
p->AddByteTag (tag, 1, 10);
|
||||
\endcode
|
||||
*
|
||||
* \param tag the new tag to add to this packet
|
||||
* \param start the position of the first byte tagged by this tag
|
||||
* \param end the position of the last byte tagged by this tag
|
||||
*/
|
||||
void AddByteTag (const Tag &tag, uint32_t start, uint32_t end) const;
|
||||
/**
|
||||
* \brief Returns an iterator over the set of byte tags included in this packet
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user