blob: b3627a987ff6737bf3bf89d13bb325fa8d532b31 [file] [log] [blame]
Eric Newberry185ab292017-03-28 06:45:39 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2017, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#ifndef NFD_DAEMON_FACE_LP_RELIABILITY_HPP
27#define NFD_DAEMON_FACE_LP_RELIABILITY_HPP
28
Eric Newberry185ab292017-03-28 06:45:39 +000029#include "core/rtt-estimator.hpp"
30#include "core/scheduler.hpp"
31
Eric Newberry185ab292017-03-28 06:45:39 +000032#include <ndn-cxx/lp/packet.hpp>
33#include <ndn-cxx/lp/sequence.hpp>
34
35#include <queue>
36
37namespace nfd {
38namespace face {
39
40class GenericLinkService;
41
42/** \brief provides for reliable sending and receiving of link-layer packets
43 * \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
44 */
45class LpReliability : noncopyable
46{
47public:
48 struct Options
49 {
50 /** \brief enables link-layer reliability
51 */
52 bool isEnabled = false;
53
54 /** \brief maximum number of retransmissions for an LpPacket
55 */
56 size_t maxRetx = 3;
57
58 /** \brief period between sending pending Acks in an IDLE packet
59 */
60 time::nanoseconds idleAckTimerPeriod = time::milliseconds(5);
61
62 /** \brief a fragment is considered lost if this number of fragments with greater sequence
63 * numbers are acknowledged
64 */
65 size_t seqNumLossThreshold = 3;
66 };
67
68 LpReliability(const Options& options, GenericLinkService* linkService);
69
70 /** \brief set options for reliability
71 */
72 void
73 setOptions(const Options& options);
74
75 /** \return GenericLinkService that owns this instance
76 *
77 * This is only used for logging, and may be nullptr.
78 */
79 const GenericLinkService*
80 getLinkService() const;
81
82 /** \brief observe outgoing fragment(s) of a network packet
83 * \param frags fragments of network packet
84 */
85 void
86 observeOutgoing(const std::vector<lp::Packet>& frags);
87
88 /** \brief extract and parse all Acks and add Ack for contained Fragment (if any) to AckQueue
89 * \param pkt incoming LpPacket
90 */
91 void
92 processIncomingPacket(const lp::Packet& pkt);
93
94 /** \brief called by GenericLinkService to attach Acks onto an outgoing LpPacket
95 * \param pkt outgoing LpPacket to attach Acks to
96 * \param mtu MTU of the Transport
97 */
98 void
99 piggyback(lp::Packet& pkt, ssize_t mtu);
100
101PUBLIC_WITH_TESTS_ELSE_PRIVATE:
102 /** \brief start the idle Ack timer
103 *
104 * This timer requests an IDLE packet to acknowledge pending fragments not already piggybacked.
105 * It is called regularly on a period configured in Options::idleAckTimerPeriod. This allows Acks
106 * to be returned to the sender, even if the link goes idle.
107 */
108 void
109 startIdleAckTimer();
110
111 /** \brief cancel the idle Ack timer
112 */
113 void
114 stopIdleAckTimer();
115
116private:
117 /** \brief find and mark as lost fragments where a configurable number of Acks have been received
118 * for greater sequence numbers
119 * \param ackSeq sequence number of received Ack
120 * \return vector containing sequence numbers marked lost by this mechanism
121 */
122 std::vector<lp::Sequence>
123 findLostLpPackets(lp::Sequence ackSeq);
124
125 /** \brief resend (or declare as lost) a lost fragment
126 */
127 void
128 onLpPacketLost(lp::Sequence seq);
129
130 class UnackedFrag;
131 class NetPkt;
132
133 /** \brief remove the fragment with the given sequence number from the map of unacknowledged
134 * fragments as well as its associated network packet
135 * \param fragIt iterator to fragment to be removed
136 *
137 * If the given sequence marks the beginning of the send window, the window will be incremented.
138 * If the associated network packet has been fully transmitted, it will be removed.
139 */
140 void
141 onLpPacketAcknowledged(std::map<lp::Sequence, UnackedFrag>::iterator fragIt,
142 std::map<lp::Sequence, NetPkt>::iterator netPktIt);
143
144 std::map<lp::Sequence, NetPkt>::iterator
145 getNetPktByFrag(lp::Sequence seq);
146
147private:
148 /** \brief contains a sent fragment that has not been acknowledged and associated data
149 */
150 class UnackedFrag
151 {
152 public:
153 // Allows implicit conversion from an lp::Packet
154 UnackedFrag(lp::Packet pkt);
155
156 public:
157 lp::Packet pkt;
158 scheduler::ScopedEventId rtoTimer;
159 time::steady_clock::TimePoint sendTime;
160 size_t retxCount;
161 size_t nGreaterSeqAcks; //!< number of Acks received for sequences greater than this fragment
162 bool wasTimedOutBySeq; //!< whether this fragment has been timed out by the sequence number mechanic
163 };
164
165 /** \brief contains a network-layer packet with unacknowledged fragments
166 */
167 class NetPkt
168 {
169 public:
170 NetPkt();
171
172 public:
173 std::set<lp::Sequence> unackedFrags;
174 bool didRetx;
175 };
176
177PUBLIC_WITH_TESTS_ELSE_PRIVATE:
178 Options m_options;
179 GenericLinkService* m_linkService;
180 std::map<lp::Sequence, UnackedFrag> m_unackedFrags;
181 std::map<lp::Sequence, UnackedFrag>::iterator m_firstUnackedFrag;
182 std::map<lp::Sequence, NetPkt> m_netPkts;
183 std::queue<lp::Sequence> m_ackQueue;
184 scheduler::ScopedEventId m_idleAckTimer;
185 bool m_isIdleAckTimerRunning;
186 RttEstimator m_rto;
187};
188
189} // namespace face
190} // namespace nfd
191
192#endif // NFD_DAEMON_FACE_LP_RELIABILITY_HPP