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(10_min);
52 NDN_THROW(std::invalid_argument(
"SelfLearningStrategy does not accept parameters"));
55 NDN_THROW(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(ingress.
face)->insertStrategyInfo<
InRecordInfo>().first;
79 if (nexthops.empty()) {
80 NFD_LOG_DEBUG(
"NACK non-discovery Interest=" << interest <<
" from=" << ingress <<
" noNextHop");
81 lp::NackHeader nackHeader;
82 nackHeader.setReason(lp::NackReason::NO_ROUTE);
87 multicastInterest(interest, ingress.
face, pitEntry, nexthops);
91 inRecordInfo->isNonDiscoveryInterest =
false;
92 if (nexthops.empty()) {
93 broadcastInterest(interest, ingress.
face, pitEntry);
96 interest.setTag(make_shared<lp::NonDiscoveryTag>(lp::EmptyValue{}));
97 multicastInterest(interest, ingress.
face, pitEntry, nexthops);
106 auto outRecord = pitEntry->getOutRecord(ingress.
face);
107 if (outRecord == pitEntry->out_end()) {
108 NFD_LOG_DEBUG(
"Data " << data.getName() <<
" from=" << ingress <<
" no out-record");
114 if (!needPrefixAnn(pitEntry)) {
118 asyncProcessData(pitEntry, ingress.
face, data);
122 auto paTag = data.getTag<lp::PrefixAnnouncementTag>();
123 if (paTag !=
nullptr) {
124 addRoute(pitEntry, ingress.
face, data, *paTag->get().getPrefixAnn());
134 const shared_ptr<pit::Entry>& pitEntry)
136 NFD_LOG_DEBUG(
"Nack for " << nack.getInterest() <<
" from=" << ingress
137 <<
" reason=" << nack.getReason());
138 if (nack.getReason() == lp::NackReason::NO_ROUTE) {
141 this->
sendNacks(pitEntry, nack.getHeader());
142 renewRoute(nack.getInterest().getName(), ingress.
face.
getId(), 0_ms);
147 SelfLearningStrategy::broadcastInterest(
const Interest& interest,
const Face& inFace,
148 const shared_ptr<pit::Entry>& pitEntry)
150 for (
auto& outFace : this->
getFaceTable() | boost::adaptors::reversed) {
151 if ((outFace.getId() == inFace.
getId() && outFace.getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) ||
153 outFace.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
158 " to=" << outFace.getId());
159 auto outRecord = this->
sendInterest(pitEntry, outFace, interest);
160 if (outRecord !=
nullptr) {
167 SelfLearningStrategy::multicastInterest(
const Interest& interest,
const Face& inFace,
168 const shared_ptr<pit::Entry>& pitEntry,
171 for (
const auto& nexthop : nexthops) {
176 Face& outFace = nexthop.getFace();
177 NFD_LOG_DEBUG(
"send non-discovery Interest=" << interest <<
" from=" << inFace.
getId() <<
178 " to=" << outFace.
getId());
179 auto outRecord = this->
sendInterest(pitEntry, outFace, interest);
180 if (outRecord !=
nullptr) {
187 SelfLearningStrategy::asyncProcessData(
const shared_ptr<pit::Entry>& pitEntry,
const Face& inFace,
const Data& data)
194 runOnRibIoService([pitEntryWeak = weak_ptr<pit::Entry>{pitEntry}, inFaceId = inFace.
getId(), data,
this] {
196 [pitEntryWeak, inFaceId, data,
this] (optional<ndn::PrefixAnnouncement> paOpt) {
199 auto pitEntry = pitEntryWeak.lock();
200 auto inFace = this->
getFace(inFaceId);
201 if (pitEntry && inFace) {
202 NFD_LOG_DEBUG(
"found PrefixAnnouncement=" << pa.getAnnouncedName());
203 data.setTag(make_shared<lp::PrefixAnnouncementTag>(lp::PrefixAnnouncementHeader(pa)));
217 SelfLearningStrategy::needPrefixAnn(
const shared_ptr<pit::Entry>& pitEntry)
219 bool hasDiscoveryInterest =
false;
220 bool directToConsumer =
true;
222 auto now = time::steady_clock::now();
223 for (
const auto& inRecord : pitEntry->getInRecords()) {
224 if (inRecord.getExpiry() > now) {
227 hasDiscoveryInterest =
true;
229 if (inRecord.getFace().getScope() != ndn::nfd::FACE_SCOPE_LOCAL) {
230 directToConsumer =
false;
234 return hasDiscoveryInterest && !directToConsumer;
238 SelfLearningStrategy::addRoute(
const shared_ptr<pit::Entry>& pitEntry,
const Face& inFace,
239 const Data& data,
const ndn::PrefixAnnouncement& pa)
244 NFD_LOG_DEBUG(
"Add route via PrefixAnnouncement with result=" << res);
250 SelfLearningStrategy::renewRoute(
const Name& name,
FaceId inFaceId, time::milliseconds maxLifetime)
Main class of NFD's forwarding engine.
void setInstanceName(const Name &name)
Set strategy instance name.
static Service & get()
Get a reference to the only instance of this class.
bool sendNack(const shared_ptr< pit::Entry > &pitEntry, Face &egress, const lp::NackHeader &header)
Send a Nack packet.
RibManager & getRibManager()
void afterReceiveData(const shared_ptr< pit::Entry > &pitEntry, const FaceEndpoint &ingress, const Data &data) override
Trigger after Data is received.
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.
void runOnRibIoService(const std::function< void()> &f)
Run a function on the RIB io_service instance.
bool isNonDiscoveryInterest
bool isNonDiscoveryInterest
static Name makeInstanceName(const Name &input, const Name &strategyName)
Construct a strategy instance name.
static const Name & getStrategyName()
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 runOnMainIoService(const std::function< void()> &f)
Run a function on the main io_service instance.
const fib::Entry & lookupFib(const pit::Entry &pitEntry) const
Performs a FIB lookup, considering Link object if present.
StrategyInfo on pit::InRecord.
Represents a face-endpoint pair in the forwarder.
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
void slFindAnn(const Name &name, const SlFindAnnCallback &cb) const
Retrieve an outgoing prefix announcement for self-learning strategy.
bool isNextHopEligible(const Face &inFace, const Interest &interest, const fib::NextHop &nexthop, const shared_ptr< pit::Entry > &pitEntry, bool wantUnused, time::steady_clock::TimePoint now)
determines whether a NextHop is eligible i.e.
StrategyInfo on pit::OutRecord.
void sendDataToAll(const shared_ptr< pit::Entry > &pitEntry, const Face &inFace, const Data &data)
Send a Data packet to all matched and qualified faces.
generalization of a network interface
void setExpiryTimer(const shared_ptr< pit::Entry > &pitEntry, time::milliseconds duration)
Schedule the PIT entry to be erased after duration.
void sendNacks(const shared_ptr< pit::Entry > &pitEntry, const lp::NackHeader &header, std::initializer_list< const Face *> exceptFaces={})
Send Nack to every face that has an in-record, except those in exceptFaces.
Represents a collection of nexthops.
PartialName parameters
parameter components
Represents a forwarding strategy.
This file contains common algorithms used by forwarding strategies.
const NextHopList & getNextHops() const
#define NFD_LOG_INIT(name)
static ParsedInstanceName parseInstanceName(const Name &input)
Parse a strategy instance name.
void afterReceiveNack(const FaceEndpoint &ingress, const lp::Nack &nack, const shared_ptr< pit::Entry > &pitEntry) override
Trigger after Nack is received.
const FaceTable & getFaceTable() const
void afterReceiveInterest(const FaceEndpoint &ingress, const Interest &interest, const shared_ptr< pit::Entry > &pitEntry) override
Trigger after Interest is received.
SelfLearningStrategy(Forwarder &forwarder, const Name &name=getStrategyName())
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 ...
uint64_t FaceId
Identifies a face.
Face * getFace(FaceId id) const
void rejectPendingInterest(const shared_ptr< pit::Entry > &pitEntry)
Schedule the PIT entry for immediate deletion.
pit::OutRecord * sendInterest(const shared_ptr< pit::Entry > &pitEntry, Face &egress, const Interest &interest)
Send an Interest packet.
optional< uint64_t > version
whether strategyName contains a version component