39 , m_rttEstimatorOpts(make_shared<
RttEstimator::Options>())
40 , m_removeFaceConn(beforeRemoveFace.connect([this] (const
Face& face) { m_fit.erase(face.getId()); }))
43 if (!parsed.parameters.empty()) {
44 NDN_THROW(std::invalid_argument(
"AccessStrategy does not accept parameters"));
46 if (parsed.version && *parsed.version !=
getStrategyName()[-1].toVersion()) {
47 NDN_THROW(std::invalid_argument(
"AccessStrategy does not support version " +
to_string(*parsed.version)));
55 static Name strategyName(
"/localhost/nfd/strategy/access/%FD%01");
61 const shared_ptr<pit::Entry>& pitEntry)
64 switch (suppressResult) {
66 return afterReceiveNewInterest(ingress, interest, pitEntry);
68 return afterReceiveRetxInterest(ingress, interest, pitEntry);
70 NFD_LOG_DEBUG(interest <<
" interestFrom " << ingress <<
" retx-suppress");
77 const shared_ptr<pit::Entry>& pitEntry)
79 const auto& fibEntry = this->
lookupFib(*pitEntry);
82 std::tie(miName, mi) = this->findPrefixMeasurements(*pitEntry);
86 NFD_LOG_DEBUG(interest <<
" interestFrom " << ingress <<
" new-interest mi=" << miName);
89 bool isSentToLastNexthop = this->sendToLastNexthop(ingress, interest, pitEntry, *mi, fibEntry);
90 if (isSentToLastNexthop) {
95 NFD_LOG_DEBUG(interest <<
" interestFrom " << ingress <<
" new-interest no-mi");
101 size_t nMulticastSent = this->multicast(ingress.
face, interest, pitEntry, fibEntry);
103 if (nMulticastSent == 0) {
109 AccessStrategy::afterReceiveRetxInterest(
const FaceEndpoint& ingress,
const Interest& interest,
110 const shared_ptr<pit::Entry>& pitEntry)
112 const auto& fibEntry = this->
lookupFib(*pitEntry);
113 NFD_LOG_DEBUG(interest <<
" interestFrom " << ingress <<
" retx-forward");
114 this->multicast(ingress.face, interest, pitEntry, fibEntry);
118 AccessStrategy::sendToLastNexthop(
const FaceEndpoint& ingress,
const Interest& interest,
119 const shared_ptr<pit::Entry>& pitEntry, MtInfo& mi,
120 const fib::Entry& fibEntry)
123 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" no-last-nexthop");
127 if (mi.lastNexthop == ingress.face.getId()) {
128 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" last-nexthop-is-downstream");
133 if (outFace ==
nullptr || !fibEntry.hasNextHop(*outFace)) {
134 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" last-nexthop-gone");
139 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" last-nexthop-violates-scope");
143 auto rto = mi.rtt.getEstimatedRto();
144 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" interestTo " << mi.lastNexthop
145 <<
" last-nexthop rto=" << time::duration_cast<time::microseconds>(rto).count());
147 this->
sendInterest(pitEntry, FaceEndpoint(*outFace, 0), interest);
150 PitInfo* pi = pitEntry->insertStrategyInfo<PitInfo>().first;
152 [
this, pitWeak = weak_ptr<pit::Entry>(pitEntry), face = ingress.face.getId(),
153 endpoint = ingress.endpoint, lastNexthop = mi.lastNexthop] {
154 afterRtoTimeout(pitWeak, face, endpoint, lastNexthop);
161 AccessStrategy::afterRtoTimeout(
const weak_ptr<pit::Entry>& pitWeak,
164 shared_ptr<pit::Entry> pitEntry = pitWeak.lock();
166 BOOST_ASSERT(pitEntry !=
nullptr);
169 if (inFace ==
nullptr) {
170 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" timeoutFrom " << firstOutFaceId
171 <<
" inFace-gone " << inFaceId);
175 auto inRecord = pitEntry->getInRecord(*inFace);
179 BOOST_ASSERT(inRecord != pitEntry->in_end());
181 const Interest& interest = inRecord->getInterest();
182 const fib::Entry& fibEntry = this->
lookupFib(*pitEntry);
184 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" timeoutFrom " << firstOutFaceId
185 <<
" multicast-except " << firstOutFaceId);
186 this->multicast(*inFace, interest, pitEntry, fibEntry, firstOutFaceId);
190 AccessStrategy::multicast(
const Face& inFace,
const Interest& interest,
191 const shared_ptr<pit::Entry>& pitEntry,
const fib::Entry& fibEntry,
195 for (
const auto& nexthop : fibEntry.getNextHops()) {
196 Face& outFace = nexthop.getFace();
197 if (&outFace == &inFace || outFace.getId() == exceptFace ||
201 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" interestTo " << outFace.getId() <<
" multicast");
202 this->
sendInterest(pitEntry, FaceEndpoint(outFace, 0), interest);
212 PitInfo* pi = pitEntry->getStrategyInfo<PitInfo>();
214 pi->rtoTimer.cancel();
217 if (!pitEntry->hasInRecords()) {
218 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" dataFrom " << ingress <<
" not-fastest");
222 auto outRecord = pitEntry->getOutRecord(ingress.
face);
223 if (outRecord == pitEntry->out_end()) {
224 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" dataFrom " << ingress <<
" no-out-record");
229 NFD_LOG_DEBUG(pitEntry->getInterest() <<
" dataFrom " << ingress
230 <<
" rtt=" << time::duration_cast<time::microseconds>(rtt).count());
231 this->updateMeasurements(ingress.
face, data, rtt);
235 AccessStrategy::updateMeasurements(
const Face& inFace,
const Data& data, time::nanoseconds rtt)
237 auto ret = m_fit.emplace(std::piecewise_construct,
238 std::forward_as_tuple(inFace.
getId()),
239 std::forward_as_tuple(m_rttEstimatorOpts));
240 FaceInfo& fi = ret.first->second;
241 fi.rtt.addMeasurement(rtt);
243 MtInfo* mi = this->addPrefixMeasurements(data);
244 if (mi->lastNexthop != inFace.
getId()) {
245 mi->lastNexthop = inFace.
getId();
249 mi->rtt.addMeasurement(rtt);
253 std::tuple<Name, AccessStrategy::MtInfo*>
254 AccessStrategy::findPrefixMeasurements(
const pit::Entry& pitEntry)
258 return std::make_tuple(
Name(),
nullptr);
261 MtInfo* mi = me->getStrategyInfo<MtInfo>();
262 BOOST_ASSERT(mi !=
nullptr);
265 return std::make_tuple(me->getName(), mi);
268 AccessStrategy::MtInfo*
269 AccessStrategy::addPrefixMeasurements(
const Data& data)
271 measurements::Entry* me =
nullptr;
272 if (!data.getName().empty()) {
278 BOOST_ASSERT(me !=
nullptr);
282 return me->insertStrategyInfo<MtInfo>(m_rttEstimatorOpts).first;