face: Acks acknowledge TxSequence instead of Sequence
refs #3931
Change-Id: I83919fe815c2a43e47eb09d754f77166c051d013
diff --git a/daemon/face/lp-reliability.hpp b/daemon/face/lp-reliability.hpp
index b3627a9..d1f4622 100644
--- a/daemon/face/lp-reliability.hpp
+++ b/daemon/face/lp-reliability.hpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
@@ -79,11 +79,11 @@
const GenericLinkService*
getLinkService() const;
- /** \brief observe outgoing fragment(s) of a network packet
+ /** \brief observe outgoing fragment(s) of a network packet and store for potential retransmission
* \param frags fragments of network packet
*/
void
- observeOutgoing(const std::vector<lp::Packet>& frags);
+ handleOutgoing(std::vector<lp::Packet>& frags);
/** \brief extract and parse all Acks and add Ack for contained Fragment (if any) to AckQueue
* \param pkt incoming LpPacket
@@ -99,6 +99,19 @@
piggyback(lp::Packet& pkt, ssize_t mtu);
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ class UnackedFrag;
+ class NetPkt;
+ using UnackedFrags = std::map<lp::Sequence, UnackedFrag>;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /** \brief assign TxSequence number to a fragment
+ * \param frag fragment to assign TxSequence to
+ * \return assigned TxSequence number
+ * \throw std::length_error assigned TxSequence is equal to the start of the existing window
+ */
+ lp::Sequence
+ assignTxSequence(lp::Packet& frag);
+
/** \brief start the idle Ack timer
*
* This timer requests an IDLE packet to acknowledge pending fragments not already piggybacked.
@@ -113,44 +126,46 @@
void
stopIdleAckTimer();
-private:
- /** \brief find and mark as lost fragments where a configurable number of Acks have been received
- * for greater sequence numbers
- * \param ackSeq sequence number of received Ack
- * \return vector containing sequence numbers marked lost by this mechanism
+ /** \brief find and mark as lost fragments where a configurable number of Acks
+ * (\p m_options.seqNumLossThreshold) have been received for greater TxSequence numbers
+ * \param ackIt iterator pointing to acknowledged fragment
+ * \return vector containing iterators to fragments marked lost by this mechanism
*/
- std::vector<lp::Sequence>
- findLostLpPackets(lp::Sequence ackSeq);
+ std::vector<UnackedFrags::iterator>
+ findLostLpPackets(UnackedFrags::iterator ackIt);
- /** \brief resend (or declare as lost) a lost fragment
+ /** \brief resend (or give up on) a lost fragment
*/
void
- onLpPacketLost(lp::Sequence seq);
-
- class UnackedFrag;
- class NetPkt;
+ onLpPacketLost(UnackedFrags::iterator txSeqIt);
/** \brief remove the fragment with the given sequence number from the map of unacknowledged
- * fragments as well as its associated network packet
- * \param fragIt iterator to fragment to be removed
+ * fragments, as well as its associated network packet (if any)
+ * \param fragIt iterator to acknowledged fragment
*
- * If the given sequence marks the beginning of the send window, the window will be incremented.
+ * If the given TxSequence marks the beginning of the send window, the window will be incremented.
* If the associated network packet has been fully transmitted, it will be removed.
*/
void
- onLpPacketAcknowledged(std::map<lp::Sequence, UnackedFrag>::iterator fragIt,
- std::map<lp::Sequence, NetPkt>::iterator netPktIt);
+ onLpPacketAcknowledged(UnackedFrags::iterator fragIt);
- std::map<lp::Sequence, NetPkt>::iterator
- getNetPktByFrag(lp::Sequence seq);
+ /** \brief delete a fragment from UnackedFrags and advance acknowledge window if necessary
+ * \param fragIt iterator to an UnackedFrag, must be dereferencable
+ * \post fragIt is not in m_unackedFrags
+ * \post if was equal to m_firstUnackedFrag,
+ * m_firstUnackedFrag is set to the UnackedFrag after fragIt with consideration of
+ * TxSequence number wraparound, or set to m_unackedFrags.end() if m_unackedFrags is empty
+ */
+ void
+ deleteUnackedFrag(UnackedFrags::iterator fragIt);
-private:
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief contains a sent fragment that has not been acknowledged and associated data
*/
class UnackedFrag
{
public:
- // Allows implicit conversion from an lp::Packet
+ explicit
UnackedFrag(lp::Packet pkt);
public:
@@ -159,7 +174,7 @@
time::steady_clock::TimePoint sendTime;
size_t retxCount;
size_t nGreaterSeqAcks; //!< number of Acks received for sequences greater than this fragment
- bool wasTimedOutBySeq; //!< whether this fragment has been timed out by the sequence number mechanic
+ shared_ptr<NetPkt> netPkt;
};
/** \brief contains a network-layer packet with unacknowledged fragments
@@ -167,20 +182,26 @@
class NetPkt
{
public:
- NetPkt();
-
- public:
- std::set<lp::Sequence> unackedFrags;
- bool didRetx;
+ std::vector<UnackedFrags::iterator> unackedFrags;
+ bool didRetx = false;
};
+public:
+ /// TxSequence TLV-TYPE (3 octets) + TxSequence TLV-LENGTH (1 octet) + sizeof(lp::Sequence)
+ static constexpr size_t RESERVED_HEADER_SPACE = 3 + 1 + sizeof(lp::Sequence);
+
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Options m_options;
GenericLinkService* m_linkService;
- std::map<lp::Sequence, UnackedFrag> m_unackedFrags;
- std::map<lp::Sequence, UnackedFrag>::iterator m_firstUnackedFrag;
- std::map<lp::Sequence, NetPkt> m_netPkts;
+ UnackedFrags m_unackedFrags;
+ /** An iterator that points to the first unacknowledged fragment in the current window. The window
+ * can wrap around so that the beginning of the window is at a TxSequence greater than other
+ * fragments in the window. When the window is moved past the last item in the iterator, the
+ * first fragment in the map will become the start of the window.
+ */
+ UnackedFrags::iterator m_firstUnackedFrag;
std::queue<lp::Sequence> m_ackQueue;
+ lp::Sequence m_lastTxSeqNo;
scheduler::ScopedEventId m_idleAckTimer;
bool m_isIdleAckTimerRunning;
RttEstimator m_rto;