blob: e427ae626ec4106db2ead0d08ef64c4f2ce4a91c [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/*
Davide Pesavento264af772021-02-09 21:48:24 -05003 * Copyright (c) 2014-2021, 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
Davide Pesavento0498ce82021-06-14 02:02:21 -040035/**
36 * \brief Represents a forwarding strategy
Junxiao Shid3c792f2014-01-30 00:46:13 -070037 */
Junxiao Shic34d1672016-12-09 15:57:59 +000038class Strategy : noncopyable
Junxiao Shid3c792f2014-01-30 00:46:13 -070039{
Junxiao Shic34d1672016-12-09 15:57:59 +000040public: // registry
Eric Newberryc68b2e82020-04-16 12:40:30 -070041 /** \brief Register a strategy type
Junxiao Shic34d1672016-12-09 15:57:59 +000042 * \tparam S subclass of Strategy
Junxiao Shi18739c42016-12-22 08:03:00 +000043 * \param strategyName strategy program name, must contain version
Junxiao Shic34d1672016-12-09 15:57:59 +000044 * \note It is permitted to register the same strategy type under multiple names,
45 * which is useful in tests and for creating aliases.
46 */
47 template<typename S>
48 static void
Junxiao Shi037f4ab2016-12-13 04:27:06 +000049 registerType(const Name& strategyName = S::getStrategyName())
Junxiao Shic34d1672016-12-09 15:57:59 +000050 {
Junxiao Shi91f6ee02016-12-29 21:44:44 +000051 BOOST_ASSERT(strategyName.size() > 1);
Junxiao Shi18739c42016-12-22 08:03:00 +000052 BOOST_ASSERT(strategyName.at(-1).isVersion());
Junxiao Shic34d1672016-12-09 15:57:59 +000053 Registry& registry = getRegistry();
54 BOOST_ASSERT(registry.count(strategyName) == 0);
Davide Pesavento3dade002019-03-19 11:29:56 -060055 registry[strategyName] = [] (auto&&... args) {
56 return make_unique<S>(std::forward<decltype(args)>(args)...);
57 };
Junxiao Shic34d1672016-12-09 15:57:59 +000058 }
59
Eric Newberryc68b2e82020-04-16 12:40:30 -070060 /** \return Whether a strategy instance can be created from \p instanceName
Junxiao Shi18739c42016-12-22 08:03:00 +000061 * \param instanceName strategy instance name, may contain version and parameters
Junxiao Shic34d1672016-12-09 15:57:59 +000062 * \note This function finds a strategy type using same rules as \p create ,
63 * but does not attempt to construct an instance.
64 */
65 static bool
Junxiao Shi18739c42016-12-22 08:03:00 +000066 canCreate(const Name& instanceName);
Junxiao Shic34d1672016-12-09 15:57:59 +000067
Eric Newberryc68b2e82020-04-16 12:40:30 -070068 /** \return A strategy instance created from \p instanceName
Junxiao Shi18739c42016-12-22 08:03:00 +000069 * \retval nullptr if !canCreate(instanceName)
70 * \throw std::invalid_argument strategy type constructor does not accept
71 * specified version or parameters
Junxiao Shic34d1672016-12-09 15:57:59 +000072 */
73 static unique_ptr<Strategy>
Junxiao Shi18739c42016-12-22 08:03:00 +000074 create(const Name& instanceName, Forwarder& forwarder);
Junxiao Shic34d1672016-12-09 15:57:59 +000075
Eric Newberryc68b2e82020-04-16 12:40:30 -070076 /** \return Whether \p instanceNameA and \p instanceNameA will initiate same strategy type
Junxiao Shi55e21b92017-01-23 03:27:47 +000077 */
78 static bool
79 areSameType(const Name& instanceNameA, const Name& instanceNameB);
80
Eric Newberryc68b2e82020-04-16 12:40:30 -070081 /** \return Registered versioned strategy names
Junxiao Shic34d1672016-12-09 15:57:59 +000082 */
83 static std::set<Name>
84 listRegistered();
85
Ju Pan2feb4592019-09-16 20:56:38 +000086public: // constructor, destructor, strategy info
Davide Pesavento3dade002019-03-19 11:29:56 -060087 /** \brief Construct a strategy instance.
Junxiao Shi18739c42016-12-22 08:03:00 +000088 * \param forwarder a reference to the forwarder, used to enable actions and accessors.
Davide Pesavento3dade002019-03-19 11:29:56 -060089 * \note Strategy subclass constructor must not retain a reference to \p forwarder.
Junxiao Shie93d6a32014-09-07 16:13:22 -070090 */
Junxiao Shi18739c42016-12-22 08:03:00 +000091 explicit
92 Strategy(Forwarder& forwarder);
Junxiao Shidbe71732014-02-21 22:23:28 -070093
Junxiao Shid3c792f2014-01-30 00:46:13 -070094 virtual
95 ~Strategy();
Junxiao Shidbe71732014-02-21 22:23:28 -070096
Junxiao Shi037f4ab2016-12-13 04:27:06 +000097#ifdef DOXYGEN
Eric Newberryc68b2e82020-04-16 12:40:30 -070098 /** \return Strategy program name
Junxiao Shi18739c42016-12-22 08:03:00 +000099 *
100 * The strategy name is defined by the strategy program.
101 * It must end with a version component.
Junxiao Shi037f4ab2016-12-13 04:27:06 +0000102 */
103 static const Name&
104 getStrategyName();
105#endif
106
Eric Newberryc68b2e82020-04-16 12:40:30 -0700107 /** \return Strategy instance name
Junxiao Shi18739c42016-12-22 08:03:00 +0000108 *
109 * The instance name is assigned during instantiation.
110 * It contains a version component, and may have extra parameter components.
Junxiao Shib9420cf2016-08-13 04:38:52 +0000111 */
Junxiao Shibb5105f2014-03-03 12:06:45 -0700112 const Name&
Junxiao Shi18739c42016-12-22 08:03:00 +0000113 getInstanceName() const
Junxiao Shib9420cf2016-08-13 04:38:52 +0000114 {
115 return m_name;
116 }
Junxiao Shibb5105f2014-03-03 12:06:45 -0700117
Junxiao Shi679e9272014-02-15 20:10:21 -0700118public: // triggers
Davide Pesavento0498ce82021-06-14 02:02:21 -0400119 /**
120 * \brief Trigger after an Interest is received.
Junxiao Shi679e9272014-02-15 20:10:21 -0700121 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400122 * The Interest:
Eric Newberryc68b2e82020-04-16 12:40:30 -0700123 * - has not exceeded HopLimit
Junxiao Shi679e9272014-02-15 20:10:21 -0700124 * - does not violate Scope
125 * - is not looped
126 * - cannot be satisfied by ContentStore
127 * - is under a namespace managed by this strategy
128 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400129 * The PIT entry is set to expire after InterestLifetime has elapsed at each downstream.
Teng Liang7003e0b2018-03-03 16:03:30 -0700130 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400131 * The strategy should decide whether and where to forward this Interest.
Junxiao Shi679e9272014-02-15 20:10:21 -0700132 * - If the strategy decides to forward this Interest,
Davide Pesavento0498ce82021-06-14 02:02:21 -0400133 * invoke sendInterest() for each upstream, either now or shortly after via a scheduler event,
134 * but before the PIT entry expires.
135 * Optionally, the strategy can invoke setExpiryTimer() to adjust how long it would wait for a response.
136 * - If the strategy has already forwarded this Interest previously and decides to continue
137 * waiting, do nothing.
138 * Optionally, the strategy can invoke setExpiryTimer() to adjust how long it would wait for a response.
Teng Liang7003e0b2018-03-03 16:03:30 -0700139 * - If the strategy concludes that this Interest cannot be satisfied,
Davide Pesavento0498ce82021-06-14 02:02:21 -0400140 * invoke rejectPendingInterest() to erase the PIT entry.
Junxiao Shi82e7f582014-09-07 15:15:40 -0700141 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400142 * \warning The strategy must not retain a copy of the \p pitEntry shared_ptr after this function
143 * returns, otherwise undefined behavior may occur. However, the strategy is allowed to
144 * construct and keep a weak_ptr to \p pitEntry.
Junxiao Shi679e9272014-02-15 20:10:21 -0700145 */
Junxiao Shid3c792f2014-01-30 00:46:13 -0700146 virtual void
Davide Pesavento0498ce82021-06-14 02:02:21 -0400147 afterReceiveInterest(const Interest& interest, const FaceEndpoint& ingress,
Junxiao Shi15e98b02016-08-12 11:21:44 +0000148 const shared_ptr<pit::Entry>& pitEntry) = 0;
Junxiao Shidbe71732014-02-21 22:23:28 -0700149
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400150
151 /** \brief trigger after a looped Interest is received
Junxiao Shi22be22c2014-02-16 22:53:48 -0700152 *
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400153 * The Interest:
154 * - does not violate Scope
155 * - IS looped
156 * - cannot be satisfied by ContentStore
157 * - is under a namespace managed by this strategy
Junxiao Shi22be22c2014-02-16 22:53:48 -0700158 */
159 virtual void
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400160 afterReceiveLoopedInterest(const FaceEndpoint& ingress, const Interest& interest,
161 pit::Entry& pitEntry);
Junxiao Shidbe71732014-02-21 22:23:28 -0700162
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400163 /** \brief trigger before PIT entry is satisfied
Teng Liang85a36632018-03-21 05:59:34 -0700164 *
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400165 * This trigger is invoked when an incoming Data satisfies more than one PIT entry.
166 * The strategy can collect measurements information, but cannot manipulate Data forwarding.
167 * When an incoming Data satisfies only one PIT entry, \c afterReceiveData is invoked instead
168 * and given full control over Data forwarding. If a strategy does not override \c afterReceiveData,
169 * the default implementation invokes \c beforeSatisfyInterest.
Davide Pesavento0498ce82021-06-14 02:02:21 -0400170 *
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400171 * Normally, PIT entries would be erased after receiving the first matching Data.
172 * If the strategy wishes to collect responses from additional upstream nodes,
173 * it should invoke \c setExpiryTimer within this function to prolong the PIT entry lifetime.
174 * If a Data arrives from another upstream during the extended PIT entry lifetime, this trigger will be invoked again.
175 * At that time, this function must invoke \c setExpiryTimer again to continue collecting more responses.
Davide Pesavento0498ce82021-06-14 02:02:21 -0400176 *
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400177 * In this base class this method does nothing.
Davide Pesavento0498ce82021-06-14 02:02:21 -0400178 *
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400179 * \warning The strategy must not retain shared_ptr<pit::Entry>, otherwise undefined behavior
180 * may occur. However, the strategy is allowed to store weak_ptr<pit::Entry>.
Teng Liang85a36632018-03-21 05:59:34 -0700181 */
182 virtual void
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400183 beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
184 const FaceEndpoint& ingress, const Data& data);
Teng Liang85a36632018-03-21 05:59:34 -0700185
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400186 /** \brief trigger after a Data is matched in CS
Teng Liang43bb2312018-03-26 04:16:42 -0700187 *
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400188 * In the base class this method sends \p data to \p ingress
189 */
190 virtual void
191 afterContentStoreHit(const shared_ptr<pit::Entry>& pitEntry,
192 const FaceEndpoint& ingress, const Data& data);
193
194 /** \brief trigger after Data is received
Teng Liang43bb2312018-03-26 04:16:42 -0700195 *
Alexander Afanasyeva646b422019-07-29 11:45:37 -0400196 * This trigger is invoked when an incoming Data satisfies exactly one PIT entry,
197 * and gives the strategy full control over Data forwarding.
198 *
199 * When this trigger is invoked:
Teng Liang43bb2312018-03-26 04:16:42 -0700200 * - The Data has been verified to satisfy the PIT entry.
201 * - The PIT entry expiry timer is set to now
202 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400203 * Inside this function:
204 * - A strategy should return Data to downstream nodes via sendData() or sendDataToAll().
Teng Liang43bb2312018-03-26 04:16:42 -0700205 * - A strategy can modify the Data as long as it still satisfies the PIT entry, such as
206 * adding or removing congestion marks.
Davide Pesavento0498ce82021-06-14 02:02:21 -0400207 * - A strategy can delay Data forwarding by prolonging the PIT entry lifetime via setExpiryTimer(),
208 * and later forward the Data before the PIT entry is erased.
Teng Liang43bb2312018-03-26 04:16:42 -0700209 * - A strategy can collect measurements about the upstream.
210 * - A strategy can collect responses from additional upstream nodes by prolonging the PIT entry
Davide Pesavento0498ce82021-06-14 02:02:21 -0400211 * lifetime via setExpiryTimer() every time a Data is received. Note that only one Data should
Teng Liang43bb2312018-03-26 04:16:42 -0700212 * be returned to each downstream node.
213 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400214 * In the base class, this method invokes beforeSatisfyInterest() and then returns the Data
215 * to all downstream faces via sendDataToAll().
216 *
217 * \warning The strategy must not retain a copy of the \p pitEntry shared_ptr after this function
218 * returns, otherwise undefined behavior may occur. However, the strategy is allowed to
219 * construct and keep a weak_ptr to \p pitEntry.
Teng Liang43bb2312018-03-26 04:16:42 -0700220 */
221 virtual void
Davide Pesavento0498ce82021-06-14 02:02:21 -0400222 afterReceiveData(const Data& data, const FaceEndpoint& ingress,
Junxiao Shi15e98b02016-08-12 11:21:44 +0000223 const shared_ptr<pit::Entry>& pitEntry);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700224
Davide Pesavento0498ce82021-06-14 02:02:21 -0400225 /**
226 * \brief Trigger after a Nack is received.
Eric Newberry41aba102017-11-01 16:42:13 -0700227 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400228 * This trigger is invoked when an incoming Nack is received in response to
229 * an forwarded Interest.
230 * The Nack has been confirmed to be a response to the last Interest forwarded
231 * to that upstream, i.e. the PIT out-record exists and has a matching Nonce.
232 * The NackHeader has been recorded in the PIT out-record.
233 *
234 * If the PIT entry is not yet satisfied, its expiry timer remains unchanged.
235 * Otherwise, the PIT entry will normally expire immediately after this function returns.
236 *
237 * If the strategy wishes to collect responses from additional upstream nodes,
238 * it should invoke setExpiryTimer() within this function to prolong the PIT entry lifetime.
239 * If a Nack arrives from another upstream during the extended PIT entry lifetime, this trigger
240 * will be invoked again. At that time, the strategy must invoke setExpiryTimer() again to
241 * continue collecting more responses.
242 *
243 * In the base class, this method does nothing.
244 *
245 * \warning The strategy must not retain a copy of the \p pitEntry shared_ptr after this function
246 * returns, otherwise undefined behavior may occur. However, the strategy is allowed to
247 * construct and keep a weak_ptr to \p pitEntry.
Eric Newberry41aba102017-11-01 16:42:13 -0700248 */
249 virtual void
Davide Pesavento0498ce82021-06-14 02:02:21 -0400250 afterReceiveNack(const lp::Nack& nack, const FaceEndpoint& ingress,
251 const shared_ptr<pit::Entry>& pitEntry);
Eric Newberry41aba102017-11-01 16:42:13 -0700252
Davide Pesavento0498ce82021-06-14 02:02:21 -0400253 /**
254 * \brief Trigger after an Interest is dropped (e.g., for exceeding allowed retransmissions).
Ju Pan2feb4592019-09-16 20:56:38 +0000255 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400256 * In the base class, this method does nothing.
257 */
258 virtual void
259 onDroppedInterest(const Interest& interest, Face& egress);
260
261 /**
262 * \brief Trigger after a new nexthop is added.
263 *
264 * The strategy should decide whether to send the buffered Interests to the new nexthop.
265 *
266 * In the base class, this method does nothing.
Ju Pan2feb4592019-09-16 20:56:38 +0000267 */
268 virtual void
269 afterNewNextHop(const fib::NextHop& nextHop, const shared_ptr<pit::Entry>& pitEntry);
270
Junxiao Shid3c792f2014-01-30 00:46:13 -0700271protected: // actions
Davide Pesavento0498ce82021-06-14 02:02:21 -0400272 /**
273 * \brief Send an Interest packet.
274 * \param interest the Interest packet
275 * \param egress face through which to send out the Interest
276 * \param pitEntry the PIT entry
277 * \return A pointer to the out-record created or nullptr if the Interest was dropped
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700278 */
Davide Pesavento264af772021-02-09 21:48:24 -0500279 NFD_VIRTUAL_WITH_TESTS pit::OutRecord*
Davide Pesavento0498ce82021-06-14 02:02:21 -0400280 sendInterest(const Interest& interest, Face& egress, const shared_ptr<pit::Entry>& pitEntry);
Junxiao Shidbe71732014-02-21 22:23:28 -0700281
Davide Pesavento0498ce82021-06-14 02:02:21 -0400282 /**
283 * \brief Send a Data packet.
284 * \param data the Data packet
285 * \param egress face through which to send out the Data
286 * \param pitEntry the PIT entry
287 * \return Whether the Data was sent (true) or dropped (false)
Teng Liang85a36632018-03-21 05:59:34 -0700288 */
Davide Pesavento264af772021-02-09 21:48:24 -0500289 NFD_VIRTUAL_WITH_TESTS bool
Davide Pesavento0498ce82021-06-14 02:02:21 -0400290 sendData(const Data& data, Face& egress, const shared_ptr<pit::Entry>& pitEntry);
Teng Liang85a36632018-03-21 05:59:34 -0700291
Davide Pesavento0498ce82021-06-14 02:02:21 -0400292 /**
293 * \brief Send a Data packet to all matched and qualified faces.
Teng Liang43bb2312018-03-26 04:16:42 -0700294 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400295 * A matched face qualifies if it is ad-hoc OR it is NOT \p inFace.
Teng Liang43bb2312018-03-26 04:16:42 -0700296 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400297 * \param data the Data packet
298 * \param pitEntry the PIT entry
299 * \param inFace face on which the Data arrived
Teng Liang43bb2312018-03-26 04:16:42 -0700300 */
Davide Pesavento264af772021-02-09 21:48:24 -0500301 NFD_VIRTUAL_WITH_TESTS void
Davide Pesavento0498ce82021-06-14 02:02:21 -0400302 sendDataToAll(const Data& data, const shared_ptr<pit::Entry>& pitEntry, const Face& inFace);
Teng Liang85a36632018-03-21 05:59:34 -0700303
Davide Pesavento0498ce82021-06-14 02:02:21 -0400304 /**
305 * \brief Schedule the PIT entry for immediate deletion.
Junxiao Shi679e9272014-02-15 20:10:21 -0700306 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400307 * This helper function sets the PIT entry expiry time to zero.
308 * The strategy should invoke this function when it concludes that the Interest cannot
309 * be forwarded and it does not want to wait for responses from existing upstream nodes.
Junxiao Shid3c792f2014-01-30 00:46:13 -0700310 */
Davide Pesavento264af772021-02-09 21:48:24 -0500311 NFD_VIRTUAL_WITH_TESTS void
Junxiao Shib9420cf2016-08-13 04:38:52 +0000312 rejectPendingInterest(const shared_ptr<pit::Entry>& pitEntry)
313 {
Teng Liang7003e0b2018-03-03 16:03:30 -0700314 this->setExpiryTimer(pitEntry, 0_ms);
Junxiao Shib9420cf2016-08-13 04:38:52 +0000315 }
Junxiao Shidbe71732014-02-21 22:23:28 -0700316
Davide Pesavento0498ce82021-06-14 02:02:21 -0400317 /**
318 * \brief Send a Nack packet.
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700319 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400320 * The egress face must have a PIT in-record, otherwise this method has no effect.
Teng Liangebc20f62020-06-23 16:55:20 -0700321 *
Davide Pesavento0498ce82021-06-14 02:02:21 -0400322 * \param header the Nack header
323 * \param egress face through which to send out the Nack
324 * \param pitEntry the PIT entry
325 * \return Whether the Nack was sent (true) or dropped (false)
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700326 */
Davide Pesavento264af772021-02-09 21:48:24 -0500327 NFD_VIRTUAL_WITH_TESTS bool
Davide Pesavento0498ce82021-06-14 02:02:21 -0400328 sendNack(const lp::NackHeader& header, Face& egress, const shared_ptr<pit::Entry>& pitEntry)
Junxiao Shib9420cf2016-08-13 04:38:52 +0000329 {
Davide Pesavento0498ce82021-06-14 02:02:21 -0400330 return m_forwarder.onOutgoingNack(header, egress, pitEntry);
Junxiao Shib9420cf2016-08-13 04:38:52 +0000331 }
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700332
Davide Pesavento0498ce82021-06-14 02:02:21 -0400333 /**
334 * \brief Send Nack to every face that has an in-record, except those in \p exceptFaces
335 * \param header the Nack header
336 * \param pitEntry the PIT entry
337 * \param exceptFaces list of faces that should be excluded from sending Nacks
338 * \note This is not an action, but a helper that invokes the sendNack() action.
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700339 */
340 void
Davide Pesavento0498ce82021-06-14 02:02:21 -0400341 sendNacks(const lp::NackHeader& header, const shared_ptr<pit::Entry>& pitEntry,
Teng Liangebc20f62020-06-23 16:55:20 -0700342 std::initializer_list<const Face*> exceptFaces = {});
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700343
Davide Pesavento0498ce82021-06-14 02:02:21 -0400344 /**
345 * \brief Schedule the PIT entry to be erased after \p duration.
Teng Liang7003e0b2018-03-03 16:03:30 -0700346 */
347 void
348 setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
349 {
350 m_forwarder.setExpiryTimer(pitEntry, duration);
351 }
352
Junxiao Shidbe71732014-02-21 22:23:28 -0700353protected: // accessors
Davide Pesavento0498ce82021-06-14 02:02:21 -0400354 /**
355 * \brief Performs a FIB lookup, considering Link object if present.
Junxiao Shicf0f3ce2016-09-02 13:01:59 +0000356 */
Junxiao Shi8d843142016-07-11 22:42:42 +0000357 const fib::Entry&
Junxiao Shicf0f3ce2016-09-02 13:01:59 +0000358 lookupFib(const pit::Entry& pitEntry) const;
Junxiao Shi8d843142016-07-11 22:42:42 +0000359
Junxiao Shidbe71732014-02-21 22:23:28 -0700360 MeasurementsAccessor&
Junxiao Shib9420cf2016-08-13 04:38:52 +0000361 getMeasurements()
362 {
363 return m_measurements;
364 }
Junxiao Shidbe71732014-02-21 22:23:28 -0700365
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000366 Face*
Junxiao Shib9420cf2016-08-13 04:38:52 +0000367 getFace(FaceId id) const
368 {
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400369 return getFaceTable().get(id);
Junxiao Shib9420cf2016-08-13 04:38:52 +0000370 }
Junxiao Shi2d9bdc82014-03-02 20:55:42 -0700371
Junxiao Shi49e11e72014-12-14 19:46:05 -0700372 const FaceTable&
Junxiao Shib9420cf2016-08-13 04:38:52 +0000373 getFaceTable() const
374 {
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400375 return m_forwarder.m_faceTable;
Junxiao Shib9420cf2016-08-13 04:38:52 +0000376 }
Junxiao Shi49e11e72014-12-14 19:46:05 -0700377
Junxiao Shi18739c42016-12-22 08:03:00 +0000378protected: // instance name
379 struct ParsedInstanceName
380 {
381 Name strategyName; ///< strategy name without parameters
Davide Pesavento87fc0f82018-04-11 23:43:51 -0400382 optional<uint64_t> version; ///< whether strategyName contains a version component
Junxiao Shi18739c42016-12-22 08:03:00 +0000383 PartialName parameters; ///< parameter components
384 };
385
Eric Newberryc68b2e82020-04-16 12:40:30 -0700386 /** \brief Parse a strategy instance name
Junxiao Shi18739c42016-12-22 08:03:00 +0000387 * \param input strategy instance name, may contain version and parameters
388 * \throw std::invalid_argument input format is unacceptable
389 */
390 static ParsedInstanceName
391 parseInstanceName(const Name& input);
392
Eric Newberryc68b2e82020-04-16 12:40:30 -0700393 /** \brief Construct a strategy instance name
Junxiao Shi18739c42016-12-22 08:03:00 +0000394 * \param input strategy instance name, may contain version and parameters
395 * \param strategyName strategy name with version but without parameters;
396 * typically this should be \p getStrategyName()
397 *
398 * If \p input contains a version component, return \p input unchanged.
399 * Otherwise, return \p input plus the version component taken from \p strategyName.
400 * This allows a strategy instance to be constructed with an unversioned name,
401 * but its final instance name should contain the version.
402 */
403 static Name
404 makeInstanceName(const Name& input, const Name& strategyName);
405
Eric Newberryc68b2e82020-04-16 12:40:30 -0700406 /** \brief Set strategy instance name
Junxiao Shi18739c42016-12-22 08:03:00 +0000407 * \note This must be called by strategy subclass constructor.
408 */
409 void
410 setInstanceName(const Name& name)
411 {
412 m_name = name;
413 }
Junxiao Shi49e11e72014-12-14 19:46:05 -0700414
Junxiao Shic34d1672016-12-09 15:57:59 +0000415private: // registry
Davide Pesavento0498ce82021-06-14 02:02:21 -0400416 using CreateFunc = std::function<unique_ptr<Strategy>(Forwarder&, const Name& /*strategyName*/)>;
417 using Registry = std::map<Name, CreateFunc>; // indexed by strategy name
Junxiao Shic34d1672016-12-09 15:57:59 +0000418
419 static Registry&
420 getRegistry();
421
422 static Registry::const_iterator
Junxiao Shi18739c42016-12-22 08:03:00 +0000423 find(const Name& instanceName);
424
425protected: // accessors
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400426 signal::Signal<FaceTable, Face>& afterAddFace;
427 signal::Signal<FaceTable, Face>& beforeRemoveFace;
Junxiao Shic34d1672016-12-09 15:57:59 +0000428
429private: // instance fields
Junxiao Shibb5105f2014-03-03 12:06:45 -0700430 Name m_name;
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700431 Forwarder& m_forwarder;
Junxiao Shidbe71732014-02-21 22:23:28 -0700432 MeasurementsAccessor m_measurements;
Junxiao Shid3c792f2014-01-30 00:46:13 -0700433};
434
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700435} // namespace fw
Junxiao Shid3c792f2014-01-30 00:46:13 -0700436} // namespace nfd
437
Eric Newberryc68b2e82020-04-16 12:40:30 -0700438/** \brief Registers a strategy
Junxiao Shic34d1672016-12-09 15:57:59 +0000439 *
440 * This macro should appear once in .cpp of each strategy.
441 */
442#define NFD_REGISTER_STRATEGY(S) \
443static class NfdAuto ## S ## StrategyRegistrationClass \
444{ \
445public: \
446 NfdAuto ## S ## StrategyRegistrationClass() \
447 { \
448 ::nfd::fw::Strategy::registerType<S>(); \
449 } \
450} g_nfdAuto ## S ## StrategyRegistrationVariable
451
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700452#endif // NFD_DAEMON_FW_STRATEGY_HPP