38 , m_rttEstimatorOpts(make_shared<RttEstimator::Options>())
39 , m_removeFaceConn(beforeRemoveFace.connect([this] (const
Face& face) { m_fit.erase(face.getId()); }))
42 if (!parsed.parameters.empty()) {
43 NDN_THROW(std::invalid_argument(
"AccessStrategy does not accept parameters"));
45 if (parsed.version && *parsed.version !=
getStrategyName()[-1].toVersion()) {
46 NDN_THROW(std::invalid_argument(
"AccessStrategy does not support version " +
47 std::to_string(*parsed.version)));
55 static const auto strategyName = Name(
"/localhost/nfd/strategy/access").appendVersion(1);
61 const shared_ptr<pit::Entry>& pitEntry)
65 return afterReceiveNewInterest(interest, ingress, pitEntry);
67 return afterReceiveRetxInterest(interest, ingress, pitEntry);
75AccessStrategy::afterReceiveNewInterest(
const Interest& interest,
const FaceEndpoint& ingress,
76 const shared_ptr<pit::Entry>& pitEntry)
78 const auto& fibEntry = this->
lookupFib(*pitEntry);
79 auto [miName, mi] = this->findPrefixMeasurements(*pitEntry);
86 bool isSentToLastNexthop = this->sendToLastNexthop(interest, ingress, pitEntry, *mi, fibEntry);
87 if (isSentToLastNexthop) {
98 size_t nMulticastSent = this->multicast(interest, ingress.
face, pitEntry, fibEntry);
100 if (nMulticastSent == 0) {
106AccessStrategy::afterReceiveRetxInterest(
const Interest& interest,
const FaceEndpoint& ingress,
107 const shared_ptr<pit::Entry>& pitEntry)
110 const auto& fibEntry = this->
lookupFib(*pitEntry);
111 this->multicast(interest, ingress.face, pitEntry, fibEntry);
115AccessStrategy::sendToLastNexthop(
const Interest& interest,
const FaceEndpoint& ingress,
116 const shared_ptr<pit::Entry>& pitEntry, MtInfo& mi,
117 const fib::Entry& fibEntry)
124 if (mi.lastNexthop == ingress.face.getId()) {
129 Face* outFace = this->
getFace(mi.lastNexthop);
130 if (outFace ==
nullptr || !fibEntry.hasNextHop(*outFace)) {
140 auto rto = mi.rtt.getEstimatedRto();
142 << time::duration_cast<time::microseconds>(rto).count() <<
"us");
144 if (!this->
sendInterest(interest, *outFace, pitEntry)) {
149 PitInfo* pi = pitEntry->insertStrategyInfo<PitInfo>().first;
151 [
this, pitWeak = weak_ptr<pit::Entry>(pitEntry), face = ingress.face.getId(), nh = mi.lastNexthop] {
152 afterRtoTimeout(pitWeak, face, nh);
159AccessStrategy::afterRtoTimeout(
const weak_ptr<pit::Entry>& pitWeak,
160 FaceId inFaceId, FaceId firstOutFaceId)
162 shared_ptr<pit::Entry> pitEntry = pitWeak.lock();
164 BOOST_ASSERT(pitEntry !=
nullptr);
166 Face* inFace = this->
getFace(inFaceId);
167 if (inFace ==
nullptr) {
168 NFD_LOG_DEBUG(pitEntry->getName() <<
" timeout from=" << firstOutFaceId
169 <<
" in-face-gone=" << inFaceId);
173 auto inRecord = pitEntry->findInRecord(*inFace);
177 BOOST_ASSERT(inRecord != pitEntry->in_end());
179 const Interest& interest = inRecord->getInterest();
180 const fib::Entry& fibEntry = this->
lookupFib(*pitEntry);
182 NFD_LOG_DEBUG(pitEntry->getName() <<
" timeout from=" << firstOutFaceId <<
" multicast");
183 this->multicast(interest, *inFace, pitEntry, fibEntry, firstOutFaceId);
187AccessStrategy::multicast(
const Interest& interest,
const Face& inFace,
188 const shared_ptr<pit::Entry>& pitEntry,
const fib::Entry& fibEntry,
192 for (
const auto& nexthop : fibEntry.getNextHops()) {
193 Face& outFace = nexthop.getFace();
194 if (&outFace == &inFace || outFace.getId() == exceptFace ||
198 NFD_LOG_DEBUG(interest.getName() <<
" nonce=" << interest.getNonce()
199 <<
" multicast to=" << outFace.getId());
209 const shared_ptr<pit::Entry>& pitEntry)
211 PitInfo* pi = pitEntry->getStrategyInfo<PitInfo>();
213 pi->rtoTimer.cancel();
216 if (!pitEntry->hasInRecords()) {
221 auto outRecord = pitEntry->findOutRecord(ingress.
face);
222 if (outRecord == pitEntry->out_end()) {
227 auto rtt = time::steady_clock::now() - outRecord->getLastRenewed();
228 NFD_LOG_DATA_FROM(data, ingress,
"rtt=" << time::duration_cast<time::microseconds>(rtt).count() <<
"us");
229 this->updateMeasurements(ingress.
face, data, rtt);
233AccessStrategy::updateMeasurements(
const Face& inFace,
const Data& data, time::nanoseconds rtt)
235 FaceInfo& fi = m_fit.try_emplace(inFace.
getId(), m_rttEstimatorOpts).first->second;
236 fi.rtt.addMeasurement(rtt);
238 MtInfo* mi = this->addPrefixMeasurements(data);
239 if (mi->lastNexthop != inFace.
getId()) {
240 mi->lastNexthop = inFace.
getId();
244 mi->rtt.addMeasurement(rtt);
248std::tuple<Name, AccessStrategy::MtInfo*>
249AccessStrategy::findPrefixMeasurements(
const pit::Entry& pitEntry)
253 return {Name{},
nullptr};
260 return {me->getName(), mi};
263AccessStrategy::MtInfo*
264AccessStrategy::addPrefixMeasurements(
const Data& data)
266 measurements::Entry* me =
nullptr;
267 if (!data.getName().empty()) {
273 BOOST_ASSERT(me !=
nullptr);
277 return me->insertStrategyInfo<MtInfo>(m_rttEstimatorOpts).first;