blob: 37b1553a44dd631d80c9f464bc9adf9e140ec3b8 [file] [log] [blame]
Junxiao Shid3c792f2014-01-30 00:46:13 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Eric Newberry41aba102017-11-01 16:42:13 -07002/*
Eric Newberryc68b2e82020-04-16 12:40:30 -07003 * Copyright (c) 2014-2020, Regents of the University of California,
Junxiao Shifaf3eb02015-02-16 10:50:36 -07004 * 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.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
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/>.
Junxiao Shi82e7f582014-09-07 15:15:40 -070024 */
Junxiao Shid3c792f2014-01-30 00:46:13 -070025
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070026#ifndef NFD_DAEMON_FW_STRATEGY_HPP
27#define NFD_DAEMON_FW_STRATEGY_HPP
Junxiao Shid3c792f2014-01-30 00:46:13 -070028
Junxiao Shi2d9bdc82014-03-02 20:55:42 -070029#include "forwarder.hpp"
Junxiao Shidbe71732014-02-21 22:23:28 -070030#include "table/measurements-accessor.hpp"
Junxiao Shid3c792f2014-01-30 00:46:13 -070031
32namespace nfd {
Junxiao Shi8c8d2182014-01-30 22:33:00 -070033namespace fw {
34
Eric Newberryc68b2e82020-04-16 12:40:30 -070035/** \brief Represents a forwarding strategy
Junxiao Shid3c792f2014-01-30 00:46:13 -070036 */
Junxiao Shic34d1672016-12-09 15:57:59 +000037class Strategy : noncopyable
Junxiao Shid3c792f2014-01-30 00:46:13 -070038{
Junxiao Shic34d1672016-12-09 15:57:59 +000039public: // registry
Eric Newberryc68b2e82020-04-16 12:40:30 -070040 /** \brief Register a strategy type
Junxiao Shic34d1672016-12-09 15:57:59 +000041 * \tparam S subclass of Strategy
Junxiao Shi18739c42016-12-22 08:03:00 +000042 * \param strategyName strategy program name, must contain version
Junxiao Shic34d1672016-12-09 15:57:59 +000043 * \note It is permitted to register the same strategy type under multiple names,
44 * which is useful in tests and for creating aliases.
45 */
46 template<typename S>
47 static void
Junxiao Shi037f4ab2016-12-13 04:27:06 +000048 registerType(const Name& strategyName = S::getStrategyName())
Junxiao Shic34d1672016-12-09 15:57:59 +000049 {
Junxiao Shi91f6ee02016-12-29 21:44:44 +000050 BOOST_ASSERT(strategyName.size() > 1);
Junxiao Shi18739c42016-12-22 08:03:00 +000051 BOOST_ASSERT(strategyName.at(-1).isVersion());
Junxiao Shic34d1672016-12-09 15:57:59 +000052 Registry& registry = getRegistry();
53 BOOST_ASSERT(registry.count(strategyName) == 0);
Davide Pesavento3dade002019-03-19 11:29:56 -060054 registry[strategyName] = [] (auto&&... args) {
55 return make_unique<S>(std::forward<decltype(args)>(args)...);
56 };
Junxiao Shic34d1672016-12-09 15:57:59 +000057 }
58
Eric Newberryc68b2e82020-04-16 12:40:30 -070059 /** \return Whether a strategy instance can be created from \p instanceName
Junxiao Shi18739c42016-12-22 08:03:00 +000060 * \param instanceName strategy instance name, may contain version and parameters
Junxiao Shic34d1672016-12-09 15:57:59 +000061 * \note This function finds a strategy type using same rules as \p create ,
62 * but does not attempt to construct an instance.
63 */
64 static bool
Junxiao Shi18739c42016-12-22 08:03:00 +000065 canCreate(const Name& instanceName);
Junxiao Shic34d1672016-12-09 15:57:59 +000066
Eric Newberryc68b2e82020-04-16 12:40:30 -070067 /** \return A strategy instance created from \p instanceName
Junxiao Shi18739c42016-12-22 08:03:00 +000068 * \retval nullptr if !canCreate(instanceName)
69 * \throw std::invalid_argument strategy type constructor does not accept
70 * specified version or parameters
Junxiao Shic34d1672016-12-09 15:57:59 +000071 */
72 static unique_ptr<Strategy>
Junxiao Shi18739c42016-12-22 08:03:00 +000073 create(const Name& instanceName, Forwarder& forwarder);
Junxiao Shic34d1672016-12-09 15:57:59 +000074
Eric Newberryc68b2e82020-04-16 12:40:30 -070075 /** \return Whether \p instanceNameA and \p instanceNameA will initiate same strategy type
Junxiao Shi55e21b92017-01-23 03:27:47 +000076 */
77 static bool
78 areSameType(const Name& instanceNameA, const Name& instanceNameB);
79
Eric Newberryc68b2e82020-04-16 12:40:30 -070080 /** \return Registered versioned strategy names
Junxiao Shic34d1672016-12-09 15:57:59 +000081 */
82 static std::set<Name>
83 listRegistered();
84
Ju Pan2feb4592019-09-16 20:56:38 +000085public: // constructor, destructor, strategy info
Davide Pesavento3dade002019-03-19 11:29:56 -060086 /** \brief Construct a strategy instance.
Junxiao Shi18739c42016-12-22 08:03:00 +000087 * \param forwarder a reference to the forwarder, used to enable actions and accessors.
Davide Pesavento3dade002019-03-19 11:29:56 -060088 * \note Strategy subclass constructor must not retain a reference to \p forwarder.
Junxiao Shie93d6a32014-09-07 16:13:22 -070089 */
Junxiao Shi18739c42016-12-22 08:03:00 +000090 explicit
91 Strategy(Forwarder& forwarder);
Junxiao Shidbe71732014-02-21 22:23:28 -070092
Junxiao Shid3c792f2014-01-30 00:46:13 -070093 virtual
94 ~Strategy();
Junxiao Shidbe71732014-02-21 22:23:28 -070095
Junxiao Shi037f4ab2016-12-13 04:27:06 +000096#ifdef DOXYGEN
Eric Newberryc68b2e82020-04-16 12:40:30 -070097 /** \return Strategy program name
Junxiao Shi18739c42016-12-22 08:03:00 +000098 *
99 * The strategy name is defined by the strategy program.
100 * It must end with a version component.
Junxiao Shi037f4ab2016-12-13 04:27:06 +0000101 */
102 static const Name&
103 getStrategyName();
104#endif
105
Eric Newberryc68b2e82020-04-16 12:40:30 -0700106 /** \return Strategy instance name
Junxiao Shi18739c42016-12-22 08:03:00 +0000107 *
108 * The instance name is assigned during instantiation.
109 * It contains a version component, and may have extra parameter components.
Junxiao Shib9420cf2016-08-13 04:38:52 +0000110 */
Junxiao Shibb5105f2014-03-03 12:06:45 -0700111 const Name&
Junxiao Shi18739c42016-12-22 08:03:00 +0000112 getInstanceName() const
Junxiao Shib9420cf2016-08-13 04:38:52 +0000113 {
114 return m_name;
115 }
Junxiao Shibb5105f2014-03-03 12:06:45 -0700116
Eric Newberryc68b2e82020-04-16 12:40:30 -0700117 /** \return Whether the afterNewNextHop trigger should be invoked for this strategy.
Ju Pan2feb4592019-09-16 20:56:38 +0000118 */
119 bool
120 wantNewNextHopTrigger() const
121 {
122 return m_wantNewNextHopTrigger;
123 }
124
Junxiao Shi679e9272014-02-15 20:10:21 -0700125public: // triggers
Eric Newberryc68b2e82020-04-16 12:40:30 -0700126 /** \brief Trigger after Interest is received
Junxiao Shi679e9272014-02-15 20:10:21 -0700127 *
128 * The Interest:
Eric Newberryc68b2e82020-04-16 12:40:30 -0700129 * - has not exceeded HopLimit
Junxiao Shi679e9272014-02-15 20:10:21 -0700130 * - does not violate Scope
131 * - is not looped
132 * - cannot be satisfied by ContentStore
133 * - is under a namespace managed by this strategy
134 *
Teng Liang7003e0b2018-03-03 16:03:30 -0700135 * The PIT entry is set to expire after InterestLifetime has elapsed at each downstream.
136 *
Junxiao Shi679e9272014-02-15 20:10:21 -0700137 * The strategy should decide whether and where to forward this Interest.
138 * - If the strategy decides to forward this Interest,
Teng Liang7003e0b2018-03-03 16:03:30 -0700139 * invoke \c sendInterest for each upstream, either now or shortly after via a scheduler event,
140 * but before PIT entry expires.
141 * Optionally, the strategy can invoke \c setExpiryTimer to adjust how long it would wait for a response.
142 * - If the strategy has already forwarded this Interest previously and decides to continue waiting,
143 * do nothing.
144 * Optionally, the strategy can invoke \c setExpiryTimer to adjust how long it would wait for a response.
145 * - If the strategy concludes that this Interest cannot be satisfied,
146 * invoke \c rejectPendingInterest to erase the PIT entry.
Junxiao Shi82e7f582014-09-07 15:15:40 -0700147 *
Junxiao Shi15e98b02016-08-12 11:21:44 +0000148 * \warning The strategy must not retain shared_ptr<pit::Entry>, otherwise undefined behavior
149 * may occur. However, the strategy is allowed to store weak_ptr<pit::Entry>.
Junxiao Shi679e9272014-02-15 20:10:21 -0700150 */
Junxiao Shid3c792f2014-01-30 00:46:13 -0700151 virtual void
ashiqopuc7079482019-02-20 05:34:37 +0000152 afterReceiveInterest(const FaceEndpoint& ingress, const Interest& interest,
Junxiao Shi15e98b02016-08-12 11:21:44 +0000153 const shared_ptr<pit::Entry>& pitEntry) = 0;
Junxiao Shidbe71732014-02-21 22:23:28 -0700154
Eric Newberryc68b2e82020-04-16 12:40:30 -0700155 /** \brief Trigger before PIT entry is satisfied
Junxiao Shi22be22c2014-02-16 22:53:48 -0700156 *
Teng Liang43bb2312018-03-26 04:16:42 -0700157 * This trigger is invoked when an incoming Data satisfies more than one PIT entry.
158 * The strategy can collect measurements information, but cannot manipulate Data forwarding.
159 * When an incoming Data satisfies only one PIT entry, \c afterReceiveData is invoked instead
160 * and given full control over Data forwarding. If a strategy does not override \c afterReceiveData,
161 * the default implementation invokes \c beforeSatisfyInterest.
Teng Liang7003e0b2018-03-03 16:03:30 -0700162 *
Teng Liang43bb2312018-03-26 04:16:42 -0700163 * Normally, PIT entries would be erased after receiving the first matching Data.
Teng Liang7003e0b2018-03-03 16:03:30 -0700164 * If the strategy wishes to collect responses from additional upstream nodes,
Teng Liang43bb2312018-03-26 04:16:42 -0700165 * it should invoke \c setExpiryTimer within this function to prolong the PIT entry lifetime.
Teng Liang7003e0b2018-03-03 16:03:30 -0700166 * If a Data arrives from another upstream during the extended PIT entry lifetime, this trigger will be invoked again.
167 * At that time, this function must invoke \c setExpiryTimer again to continue collecting more responses.
Junxiao Shi82e7f582014-09-07 15:15:40 -0700168 *
Junxiao Shi22be22c2014-02-16 22:53:48 -0700169 * In this base class this method does nothing.
Junxiao Shi82e7f582014-09-07 15:15:40 -0700170 *
Junxiao Shi15e98b02016-08-12 11:21:44 +0000171 * \warning The strategy must not retain shared_ptr<pit::Entry>, otherwise undefined behavior
172 * may occur. However, the strategy is allowed to store weak_ptr<pit::Entry>.
Junxiao Shi22be22c2014-02-16 22:53:48 -0700173 */
174 virtual void
Junxiao Shi15e98b02016-08-12 11:21:44 +0000175 beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
ashiqopuc7079482019-02-20 05:34:37 +0000176 const FaceEndpoint& ingress, const Data& data);
Junxiao Shidbe71732014-02-21 22:23:28 -0700177
Eric Newberryc68b2e82020-04-16 12:40:30 -0700178 /** \brief Trigger after a Data is matched in CS
Teng Liang85a36632018-03-21 05:59:34 -0700179 *
ashiqopuc7079482019-02-20 05:34:37 +0000180 * In the base class this method sends \p data to \p ingress
Teng Liang85a36632018-03-21 05:59:34 -0700181 */
182 virtual void
183 afterContentStoreHit(const shared_ptr<pit::Entry>& pitEntry,
ashiqopuc7079482019-02-20 05:34:37 +0000184 const FaceEndpoint& ingress, const Data& data);
Teng Liang85a36632018-03-21 05:59:34 -0700185
Eric Newberryc68b2e82020-04-16 12:40:30 -0700186 /** \brief Trigger after Data is received
Teng Liang43bb2312018-03-26 04:16:42 -0700187 *
188 * This trigger is invoked when an incoming Data satisfies exactly one PIT entry,
189 * and gives the strategy full control over Data forwarding.
190 *
191 * When this trigger is invoked:
192 * - The Data has been verified to satisfy the PIT entry.
193 * - The PIT entry expiry timer is set to now
194 *
195 * Within this function:
196 * - A strategy should return Data to downstream nodes via \c sendData or \c sendDataToAll.
197 * - A strategy can modify the Data as long as it still satisfies the PIT entry, such as
198 * adding or removing congestion marks.
199 * - A strategy can delay Data forwarding by prolonging the PIT entry lifetime via \c setExpiryTimer,
200 * and forward Data before the PIT entry is erased.
201 * - A strategy can collect measurements about the upstream.
202 * - A strategy can collect responses from additional upstream nodes by prolonging the PIT entry
203 * lifetime via \c setExpiryTimer every time a Data is received. Note that only one Data should
204 * be returned to each downstream node.
205 *
206 * In the base class this method invokes \c beforeSatisfyInterest trigger and then returns
207 * the Data to downstream faces via \c sendDataToAll.
208 */
209 virtual void
210 afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
ashiqopuc7079482019-02-20 05:34:37 +0000211 const FaceEndpoint& ingress, const Data& data);
Teng Liang43bb2312018-03-26 04:16:42 -0700212
Eric Newberryc68b2e82020-04-16 12:40:30 -0700213 /** \brief Trigger after Nack is received
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700214 *
215 * This trigger is invoked when an incoming Nack is received in response to
216 * an forwarded Interest.
217 * The Nack has been confirmed to be a response to the last Interest forwarded
218 * to that upstream, i.e. the PIT out-record exists and has a matching Nonce.
219 * The NackHeader has been recorded in the PIT out-record.
220 *
Teng Liang7003e0b2018-03-03 16:03:30 -0700221 * If the PIT entry is not yet satisfied, its expiry timer remains unchanged.
222 * Otherwise, the PIT entry normally would expire immediately after this function returns.
223 *
224 * If the strategy wishes to collect responses from additional upstream nodes,
225 * it should invoke \c setExpiryTimer within this function to retain the PIT entry.
226 * If a Nack arrives from another upstream during the extended PIT entry lifetime, this trigger will be invoked again.
227 * At that time, this function must invoke \c setExpiryTimer again to continue collecting more responses.
228 *
Teng Liang85a36632018-03-21 05:59:34 -0700229 * In the base class this method does nothing.
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700230 *
Junxiao Shi15e98b02016-08-12 11:21:44 +0000231 * \warning The strategy must not retain shared_ptr<pit::Entry>, otherwise undefined behavior
232 * may occur. However, the strategy is allowed to store weak_ptr<pit::Entry>.
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700233 */
234 virtual void
ashiqopuc7079482019-02-20 05:34:37 +0000235 afterReceiveNack(const FaceEndpoint& ingress, const lp::Nack& nack,
Junxiao Shi15e98b02016-08-12 11:21:44 +0000236 const shared_ptr<pit::Entry>& pitEntry);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700237
Eric Newberryc68b2e82020-04-16 12:40:30 -0700238 /** \brief Trigger after Interest dropped (e.g., for exceeding allowed retransmissions)
Eric Newberry41aba102017-11-01 16:42:13 -0700239 *
240 * In the base class this method does nothing.
241 */
242 virtual void
Teng Liangebc20f62020-06-23 16:55:20 -0700243 onDroppedInterest(const Face& egress, const Interest& interest);
Eric Newberry41aba102017-11-01 16:42:13 -0700244
Eric Newberryc68b2e82020-04-16 12:40:30 -0700245 /** \brief Trigger after new nexthop is added
Ju Pan2feb4592019-09-16 20:56:38 +0000246 *
247 * The strategy should decide whether to send the buffered Interests to the new nexthop.
248 * In the base class, this method does nothing.
249 */
250 virtual void
251 afterNewNextHop(const fib::NextHop& nextHop, const shared_ptr<pit::Entry>& pitEntry);
252
Junxiao Shid3c792f2014-01-30 00:46:13 -0700253protected: // actions
Teng Liangebc20f62020-06-23 16:55:20 -0700254 /** \brief Send an Interest packet.
255 * \param pitEntry the PIT entry
256 * \param egress face through which to send out the Interest
Junxiao Shic5f651f2016-11-17 22:58:12 +0000257 * \param interest the Interest packet
Eric Newberry2377ada2020-09-28 22:40:14 -0700258 * \return A pointer to the out-record created or nullptr if the Interest was dropped
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700259 */
Eric Newberry2377ada2020-09-28 22:40:14 -0700260 VIRTUAL_WITH_TESTS pit::OutRecord*
Teng Liangebc20f62020-06-23 16:55:20 -0700261 sendInterest(const shared_ptr<pit::Entry>& pitEntry, Face& egress,
262 const Interest& interest);
Junxiao Shidbe71732014-02-21 22:23:28 -0700263
Teng Liangebc20f62020-06-23 16:55:20 -0700264 /** \brief Send a Data packet.
265 * \param pitEntry the PIT entry
Teng Liang85a36632018-03-21 05:59:34 -0700266 * \param data the Data packet
Teng Liangebc20f62020-06-23 16:55:20 -0700267 * \param egress face through which to send out the Data
Eric Newberry2377ada2020-09-28 22:40:14 -0700268 * \return Whether the Data was sent (true) or dropped (false)
Teng Liang85a36632018-03-21 05:59:34 -0700269 */
Eric Newberry2377ada2020-09-28 22:40:14 -0700270 VIRTUAL_WITH_TESTS bool
Teng Liangebc20f62020-06-23 16:55:20 -0700271 sendData(const shared_ptr<pit::Entry>& pitEntry, const Data& data, Face& egress);
Teng Liang85a36632018-03-21 05:59:34 -0700272
Teng Liangebc20f62020-06-23 16:55:20 -0700273 /** \brief Send a Data packet to all matched and qualified faces.
Teng Liang43bb2312018-03-26 04:16:42 -0700274 *
Teng Liangebc20f62020-06-23 16:55:20 -0700275 * A matched face is qualified if it is ad-hoc or it is NOT \p inFace.
Teng Liang43bb2312018-03-26 04:16:42 -0700276 *
Teng Liangebc20f62020-06-23 16:55:20 -0700277 * \param pitEntry the PIT entry
278 * \param inFace face on which the Data arrived
Teng Liang43bb2312018-03-26 04:16:42 -0700279 * \param data the Data packet
280 */
281 VIRTUAL_WITH_TESTS void
Teng Liangebc20f62020-06-23 16:55:20 -0700282 sendDataToAll(const shared_ptr<pit::Entry>& pitEntry, const Face& inFace, const Data& data);
Teng Liang85a36632018-03-21 05:59:34 -0700283
Teng Liangebc20f62020-06-23 16:55:20 -0700284 /** \brief Schedule the PIT entry for immediate deletion.
Junxiao Shi679e9272014-02-15 20:10:21 -0700285 *
Teng Liang7003e0b2018-03-03 16:03:30 -0700286 * This helper function sets the PIT entry expiry time to zero.
287 * The strategy should invoke this function when it concludes that the Interest cannot
288 * be forwarded and it does not want to wait for responses from existing upstream nodes.
Junxiao Shid3c792f2014-01-30 00:46:13 -0700289 */
Junxiao Shi727ed292014-02-19 23:26:45 -0700290 VIRTUAL_WITH_TESTS void
Junxiao Shib9420cf2016-08-13 04:38:52 +0000291 rejectPendingInterest(const shared_ptr<pit::Entry>& pitEntry)
292 {
Teng Liang7003e0b2018-03-03 16:03:30 -0700293 this->setExpiryTimer(pitEntry, 0_ms);
Junxiao Shib9420cf2016-08-13 04:38:52 +0000294 }
Junxiao Shidbe71732014-02-21 22:23:28 -0700295
Teng Liangebc20f62020-06-23 16:55:20 -0700296 /** \brief Send a Nack packet.
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700297 *
Teng Liangebc20f62020-06-23 16:55:20 -0700298 * The egress face must have a PIT in-record, otherwise this method has no effect.
299 *
300 * \param pitEntry the PIT entry
301 * \param egress face through which to send out the Nack
302 * \param header the Nack header
Eric Newberry2377ada2020-09-28 22:40:14 -0700303 * \return Whether the Nack was sent (true) or dropped (false)
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700304 */
Eric Newberry2377ada2020-09-28 22:40:14 -0700305 VIRTUAL_WITH_TESTS bool
Teng Liangebc20f62020-06-23 16:55:20 -0700306 sendNack(const shared_ptr<pit::Entry>& pitEntry, Face& egress,
307 const lp::NackHeader& header)
Junxiao Shib9420cf2016-08-13 04:38:52 +0000308 {
Eric Newberry2377ada2020-09-28 22:40:14 -0700309 return m_forwarder.onOutgoingNack(pitEntry, egress, header);
Junxiao Shib9420cf2016-08-13 04:38:52 +0000310 }
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700311
Teng Liangebc20f62020-06-23 16:55:20 -0700312 /** \brief Send Nack to every face that has an in-record, except those in \p exceptFaces
313 * \param pitEntry the PIT entry
314 * \param header the Nack header
315 * \param exceptFaces list of faces that should be excluded from sending Nacks
316 * \note This is not an action, but a helper that invokes the sendNack() action.
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700317 */
318 void
Junxiao Shib9420cf2016-08-13 04:38:52 +0000319 sendNacks(const shared_ptr<pit::Entry>& pitEntry, const lp::NackHeader& header,
Teng Liangebc20f62020-06-23 16:55:20 -0700320 std::initializer_list<const Face*> exceptFaces = {});
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700321
Teng Liangebc20f62020-06-23 16:55:20 -0700322 /** \brief Schedule the PIT entry to be erased after \p duration.
Teng Liang7003e0b2018-03-03 16:03:30 -0700323 */
324 void
325 setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
326 {
327 m_forwarder.setExpiryTimer(pitEntry, duration);
328 }
329
Junxiao Shidbe71732014-02-21 22:23:28 -0700330protected: // accessors
Teng Liangebc20f62020-06-23 16:55:20 -0700331 /** \brief Performs a FIB lookup, considering Link object if present.
Junxiao Shicf0f3ce2016-09-02 13:01:59 +0000332 */
Junxiao Shi8d843142016-07-11 22:42:42 +0000333 const fib::Entry&
Junxiao Shicf0f3ce2016-09-02 13:01:59 +0000334 lookupFib(const pit::Entry& pitEntry) const;
Junxiao Shi8d843142016-07-11 22:42:42 +0000335
Junxiao Shidbe71732014-02-21 22:23:28 -0700336 MeasurementsAccessor&
Junxiao Shib9420cf2016-08-13 04:38:52 +0000337 getMeasurements()
338 {
339 return m_measurements;
340 }
Junxiao Shidbe71732014-02-21 22:23:28 -0700341
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000342 Face*
Junxiao Shib9420cf2016-08-13 04:38:52 +0000343 getFace(FaceId id) const
344 {
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400345 return getFaceTable().get(id);
Junxiao Shib9420cf2016-08-13 04:38:52 +0000346 }
Junxiao Shi2d9bdc82014-03-02 20:55:42 -0700347
Junxiao Shi49e11e72014-12-14 19:46:05 -0700348 const FaceTable&
Junxiao Shib9420cf2016-08-13 04:38:52 +0000349 getFaceTable() const
350 {
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400351 return m_forwarder.m_faceTable;
Junxiao Shib9420cf2016-08-13 04:38:52 +0000352 }
Junxiao Shi49e11e72014-12-14 19:46:05 -0700353
Junxiao Shi18739c42016-12-22 08:03:00 +0000354protected: // instance name
355 struct ParsedInstanceName
356 {
357 Name strategyName; ///< strategy name without parameters
Davide Pesavento87fc0f82018-04-11 23:43:51 -0400358 optional<uint64_t> version; ///< whether strategyName contains a version component
Junxiao Shi18739c42016-12-22 08:03:00 +0000359 PartialName parameters; ///< parameter components
360 };
361
Eric Newberryc68b2e82020-04-16 12:40:30 -0700362 /** \brief Parse a strategy instance name
Junxiao Shi18739c42016-12-22 08:03:00 +0000363 * \param input strategy instance name, may contain version and parameters
364 * \throw std::invalid_argument input format is unacceptable
365 */
366 static ParsedInstanceName
367 parseInstanceName(const Name& input);
368
Eric Newberryc68b2e82020-04-16 12:40:30 -0700369 /** \brief Construct a strategy instance name
Junxiao Shi18739c42016-12-22 08:03:00 +0000370 * \param input strategy instance name, may contain version and parameters
371 * \param strategyName strategy name with version but without parameters;
372 * typically this should be \p getStrategyName()
373 *
374 * If \p input contains a version component, return \p input unchanged.
375 * Otherwise, return \p input plus the version component taken from \p strategyName.
376 * This allows a strategy instance to be constructed with an unversioned name,
377 * but its final instance name should contain the version.
378 */
379 static Name
380 makeInstanceName(const Name& input, const Name& strategyName);
381
Eric Newberryc68b2e82020-04-16 12:40:30 -0700382 /** \brief Set strategy instance name
Junxiao Shi18739c42016-12-22 08:03:00 +0000383 * \note This must be called by strategy subclass constructor.
384 */
385 void
386 setInstanceName(const Name& name)
387 {
388 m_name = name;
389 }
Junxiao Shi49e11e72014-12-14 19:46:05 -0700390
Ju Pan2feb4592019-09-16 20:56:38 +0000391PUBLIC_WITH_TESTS_ELSE_PROTECTED: // setter
Eric Newberryc68b2e82020-04-16 12:40:30 -0700392 /** \brief Set whether the afterNewNextHop trigger should be invoked for this strategy
Ju Pan2feb4592019-09-16 20:56:38 +0000393 */
394 void
395 enableNewNextHopTrigger(bool enabled)
396 {
397 m_wantNewNextHopTrigger = enabled;
398 }
399
Junxiao Shic34d1672016-12-09 15:57:59 +0000400private: // registry
401 typedef std::function<unique_ptr<Strategy>(Forwarder& forwarder, const Name& strategyName)> CreateFunc;
402 typedef std::map<Name, CreateFunc> Registry; // indexed by strategy name
403
404 static Registry&
405 getRegistry();
406
407 static Registry::const_iterator
Junxiao Shi18739c42016-12-22 08:03:00 +0000408 find(const Name& instanceName);
409
410protected: // accessors
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400411 signal::Signal<FaceTable, Face>& afterAddFace;
412 signal::Signal<FaceTable, Face>& beforeRemoveFace;
Junxiao Shic34d1672016-12-09 15:57:59 +0000413
414private: // instance fields
Junxiao Shibb5105f2014-03-03 12:06:45 -0700415 Name m_name;
416
Eric Newberryc68b2e82020-04-16 12:40:30 -0700417 /** \brief Reference to the forwarder
Junxiao Shi679e9272014-02-15 20:10:21 -0700418 *
419 * Triggers can access forwarder indirectly via actions.
420 */
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700421 Forwarder& m_forwarder;
Junxiao Shidbe71732014-02-21 22:23:28 -0700422
423 MeasurementsAccessor m_measurements;
Ju Pan2feb4592019-09-16 20:56:38 +0000424
425 bool m_wantNewNextHopTrigger = false;
Junxiao Shid3c792f2014-01-30 00:46:13 -0700426};
427
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700428} // namespace fw
Junxiao Shid3c792f2014-01-30 00:46:13 -0700429} // namespace nfd
430
Eric Newberryc68b2e82020-04-16 12:40:30 -0700431/** \brief Registers a strategy
Junxiao Shic34d1672016-12-09 15:57:59 +0000432 *
433 * This macro should appear once in .cpp of each strategy.
434 */
435#define NFD_REGISTER_STRATEGY(S) \
436static class NfdAuto ## S ## StrategyRegistrationClass \
437{ \
438public: \
439 NfdAuto ## S ## StrategyRegistrationClass() \
440 { \
441 ::nfd::fw::Strategy::registerType<S>(); \
442 } \
443} g_nfdAuto ## S ## StrategyRegistrationVariable
444
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700445#endif // NFD_DAEMON_FW_STRATEGY_HPP