33 #include <ndn-cxx/lp/empty-value.hpp> 34 #include <ndn-cxx/lp/prefix-announcement-header.hpp> 35 #include <ndn-cxx/lp/tags.hpp> 37 #include <boost/range/adaptor/reversed.hpp> 45 const time::milliseconds SelfLearningStrategy::ROUTE_RENEW_LIFETIME(600_s);
52 BOOST_THROW_EXCEPTION(std::invalid_argument(
"SelfLearningStrategy does not accept parameters"));
55 BOOST_THROW_EXCEPTION(std::invalid_argument(
56 "SelfLearningStrategy does not support version " + to_string(*parsed.
version)));
64 static Name strategyName(
"/localhost/nfd/strategy/self-learning/%FD%01");
70 const shared_ptr<pit::Entry>& pitEntry)
75 bool isNonDiscovery = interest.getTag<lp::NonDiscoveryTag>() !=
nullptr;
76 auto inRecordInfo = pitEntry->getInRecord(inFace)->insertStrategyInfo<
InRecordInfo>().first;
79 if (nexthops.empty()) {
80 NFD_LOG_DEBUG(
"NACK non-discovery Interest=" << interest <<
" from=" << inFace.getId() <<
" noNextHop");
81 lp::NackHeader nackHeader;
82 nackHeader.setReason(lp::NackReason::NO_ROUTE);
83 this->
sendNack(pitEntry, inFace, nackHeader);
87 multicastInterest(interest, inFace, pitEntry, nexthops);
91 inRecordInfo->isNonDiscoveryInterest =
false;
92 if (nexthops.empty()) {
93 broadcastInterest(interest, inFace, pitEntry);
96 interest.setTag(make_shared<lp::NonDiscoveryTag>(lp::EmptyValue{}));
97 multicastInterest(interest, inFace, pitEntry, nexthops);
104 const Face& inFace,
const Data& data)
108 if (!needPrefixAnn(pitEntry)) {
112 asyncProcessData(pitEntry, inFace, data);
116 auto paTag = data.getTag<lp::PrefixAnnouncementTag>();
117 if (paTag !=
nullptr) {
118 addRoute(pitEntry, inFace, data, *paTag->get().getPrefixAnn());
128 const shared_ptr<pit::Entry>& pitEntry)
130 NFD_LOG_DEBUG(
"Nack for " << nack.getInterest() <<
" from=" << inFace.getId() <<
": " << nack.getReason());
131 if (nack.getReason() == lp::NackReason::NO_ROUTE) {
134 this->
sendNacks(pitEntry, nack.getHeader());
135 renewRoute(nack.getInterest().getName(), inFace.getId(), 0_ms);
140 SelfLearningStrategy::broadcastInterest(
const Interest& interest,
const Face& inFace,
141 const shared_ptr<pit::Entry>& pitEntry)
143 for (
auto& outFace : this->
getFaceTable() | boost::adaptors::reversed) {
144 if ((outFace.getId() == inFace.getId() && outFace.getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) ||
145 wouldViolateScope(inFace, interest, outFace) || outFace.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
150 NFD_LOG_DEBUG(
"send discovery Interest=" << interest <<
" from=" 151 << inFace.getId() <<
" to=" << outFace.getId());
156 SelfLearningStrategy::multicastInterest(
const Interest& interest,
const Face& inFace,
157 const shared_ptr<pit::Entry>& pitEntry,
160 for (
const auto& nexthop : nexthops) {
161 Face& outFace = nexthop.getFace();
162 if ((outFace.getId() == inFace.getId() && outFace.getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) ||
168 NFD_LOG_DEBUG(
"send non-discovery Interest=" << interest <<
" from=" 169 << inFace.getId() <<
" to=" << outFace.getId());
174 SelfLearningStrategy::asyncProcessData(
const shared_ptr<pit::Entry>& pitEntry,
const Face& inFace,
const Data& data)
181 runOnRibIoService([pitEntryWeak = weak_ptr<pit::Entry>{pitEntry}, inFaceId = inFace.getId(), data,
this] {
183 [pitEntryWeak, inFaceId, data,
this] (optional<ndn::PrefixAnnouncement> paOpt) {
186 auto pitEntry = pitEntryWeak.lock();
187 auto inFace = this->
getFace(inFaceId);
188 if (pitEntry && inFace) {
189 NFD_LOG_DEBUG(
"found PrefixAnnouncement=" << pa.getAnnouncedName());
190 data.setTag(make_shared<lp::PrefixAnnouncementTag>(lp::PrefixAnnouncementHeader(pa)));
204 SelfLearningStrategy::needPrefixAnn(
const shared_ptr<pit::Entry>& pitEntry)
206 bool hasDiscoveryInterest =
false;
207 bool directToConsumer =
true;
209 auto now = time::steady_clock::now();
210 for (
const auto& inRecord : pitEntry->getInRecords()) {
211 if (inRecord.getExpiry() > now) {
214 hasDiscoveryInterest =
true;
216 if (inRecord.getFace().getScope() != ndn::nfd::FACE_SCOPE_LOCAL) {
217 directToConsumer =
false;
221 return hasDiscoveryInterest && !directToConsumer;
225 SelfLearningStrategy::addRoute(
const shared_ptr<pit::Entry>& pitEntry,
const Face& inFace,
226 const Data& data,
const ndn::PrefixAnnouncement& pa)
228 runOnRibIoService([pitEntryWeak = weak_ptr<pit::Entry>{pitEntry}, inFaceId = inFace.getId(), data, pa] {
231 NFD_LOG_DEBUG(
"Add route via PrefixAnnouncement with result=" << res);
237 SelfLearningStrategy::renewRoute(
const Name& name,
FaceId inFaceId, time::milliseconds maxLifetime)
void setInstanceName(const Name &name)
set strategy instance name
static Service & get()
Get a reference to the only instance of this class.
void slFindAnn(const Name &name, const SlFindAnnCallback &cb) const
Retrieve an outgoing prefix announcement for self-learning strategy.
void sendNacks(const shared_ptr< pit::Entry > &pitEntry, const lp::NackHeader &header, std::initializer_list< const Face * > exceptFaces=std::initializer_list< const Face * >())
send Nack to every face that has an in-record, except those in exceptFaces
const FaceTable & getFaceTable() const
RibManager & getRibManager()
void afterReceiveInterest(const Face &inFace, const Interest &interest, const shared_ptr< pit::Entry > &pitEntry) override
trigger after Interest is received
void runOnRibIoService(const std::function< void()> &f)
run a function on the RIB io_service instance
void afterReceiveNack(const Face &inFace, const lp::Nack &nack, const shared_ptr< pit::Entry > &pitEntry) override
trigger after Nack is received
bool isNonDiscoveryInterest
void sendInterest(const shared_ptr< pit::Entry > &pitEntry, Face &outFace, const Interest &interest)
send Interest to outFace
void sendNack(const shared_ptr< pit::Entry > &pitEntry, const Face &outFace, const lp::NackHeader &header)
send Nack to outFace
bool isNonDiscoveryInterest
static Name makeInstanceName(const Name &input, const Name &strategyName)
construct a strategy instance name
static const Name & getStrategyName()
void runOnMainIoService(const std::function< void()> &f)
run a function on the main io_service instance
StrategyInfo on pit::InRecord.
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
void afterReceiveData(const shared_ptr< pit::Entry > &pitEntry, const Face &inFace, const Data &data) override
trigger after Data is received
StrategyInfo on pit::OutRecord.
void sendDataToAll(const shared_ptr< pit::Entry > &pitEntry, const Face &inFace, const Data &data)
send data to all matched and qualified faces
void slRenew(const Name &name, uint64_t faceId, time::milliseconds maxLifetime, const SlAnnounceCallback &cb)
Renew a route created by prefix announcement from self-learning strategy.
void setExpiryTimer(const shared_ptr< pit::Entry > &pitEntry, time::milliseconds duration)
Schedule the PIT entry to be erased after duration.
Represents a collection of nexthops.
PartialName parameters
parameter components
represents a forwarding strategy
This file contains common algorithms used by forwarding strategies.
#define NFD_LOG_INIT(name)
static ParsedInstanceName parseInstanceName(const Name &input)
parse a strategy instance name
void slAnnounce(const ndn::PrefixAnnouncement &pa, uint64_t faceId, time::milliseconds maxLifetime, const SlAnnounceCallback &cb)
Insert a route by prefix announcement from self-learning strategy.
SelfLearningStrategy(Forwarder &forwarder, const Name &name=getStrategyName())
uint64_t FaceId
identifies a face
NFD_REGISTER_STRATEGY(SelfLearningStrategy)
bool wouldViolateScope(const Face &inFace, const Interest &interest, const Face &outFace)
determine whether forwarding the Interest in pitEntry to outFace would violate scope ...
const NextHopList & getNextHops() const
Face * getFace(FaceId id) const
void rejectPendingInterest(const shared_ptr< pit::Entry > &pitEntry)
schedule the PIT entry for immediate deletion
const fib::Entry & lookupFib(const pit::Entry &pitEntry) const
performs a FIB lookup, considering Link object if present
optional< uint64_t > version
whether strategyName contains a version component