NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
best-route-strategy2.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "best-route-strategy2.hpp"
27 #include "core/logger.hpp"
28 
29 namespace nfd {
30 namespace fw {
31 
32 NFD_LOG_INIT("BestRouteStrategy2");
33 
34 const Name BestRouteStrategy2::STRATEGY_NAME("ndn:/localhost/nfd/strategy/best-route/%FD%02");
36 const time::milliseconds BestRouteStrategy2::MIN_RETRANSMISSION_INTERVAL(100);
37 
39  : Strategy(forwarder, name)
40 {
41 }
42 
48 static inline bool
49 predicate_NextHop_eligible(const shared_ptr<pit::Entry>& pitEntry,
50  const fib::NextHop& nexthop, FaceId currentDownstream,
51  bool wantUnused = false,
52  time::steady_clock::TimePoint now = time::steady_clock::TimePoint::min())
53 {
54  shared_ptr<Face> upstream = nexthop.getFace();
55 
56  // upstream is current downstream
57  if (upstream->getId() == currentDownstream)
58  return false;
59 
60  // forwarding would violate scope
61  if (pitEntry->violatesScope(*upstream))
62  return false;
63 
64  if (wantUnused) {
65  // NextHop must not have unexpired OutRecord
66  pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(*upstream);
67  if (outRecord != pitEntry->getOutRecords().end() &&
68  outRecord->getExpiry() > now) {
69  return false;
70  }
71  }
72 
73  return true;
74 }
75 
76 static inline bool
78 {
79  return a.getLastRenewed() < b.getLastRenewed();
80 }
81 
85 static inline fib::NextHopList::const_iterator
86 findEligibleNextHopWithEarliestOutRecord(const shared_ptr<pit::Entry>& pitEntry,
87  const fib::NextHopList& nexthops,
88  FaceId currentDownstream)
89 {
90  fib::NextHopList::const_iterator found = nexthops.end();
91  time::steady_clock::TimePoint earliestRenewed = time::steady_clock::TimePoint::max();
92  for (fib::NextHopList::const_iterator it = nexthops.begin(); it != nexthops.end(); ++it) {
93  if (!predicate_NextHop_eligible(pitEntry, *it, currentDownstream))
94  continue;
95  pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(*it->getFace());
96  BOOST_ASSERT(outRecord != pitEntry->getOutRecords().end());
97  if (outRecord->getLastRenewed() < earliestRenewed) {
98  found = it;
99  earliestRenewed = outRecord->getLastRenewed();
100  }
101  }
102  return found;
103 }
104 
105 void
107  const Interest& interest,
108  shared_ptr<fib::Entry> fibEntry,
109  shared_ptr<pit::Entry> pitEntry)
110 {
111  const fib::NextHopList& nexthops = fibEntry->getNextHops();
112  fib::NextHopList::const_iterator it = nexthops.end();
113 
114  bool isNewPitEntry = !pitEntry->hasUnexpiredOutRecords();
115  if (isNewPitEntry) {
116  // forward to nexthop with lowest cost except downstream
117  it = std::find_if(nexthops.begin(), nexthops.end(),
118  bind(&predicate_NextHop_eligible, pitEntry, _1, inFace.getId(),
119  false, time::steady_clock::TimePoint::min()));
120 
121  if (it == nexthops.end()) {
122  NFD_LOG_DEBUG(interest << " from=" << inFace.getId() << " noNextHop");
123  this->rejectPendingInterest(pitEntry);
124  return;
125  }
126 
127  shared_ptr<Face> outFace = it->getFace();
128  this->sendInterest(pitEntry, outFace);
129  NFD_LOG_DEBUG(interest << " from=" << inFace.getId()
130  << " newPitEntry-to=" << outFace->getId());
131  return;
132  }
133 
134  // when was the last outgoing Interest?
135  const pit::OutRecordCollection& outRecords = pitEntry->getOutRecords();
136  pit::OutRecordCollection::const_iterator lastOutgoing = std::max_element(
137  outRecords.begin(), outRecords.end(), &compare_OutRecord_lastRenewed);
138  BOOST_ASSERT(lastOutgoing != outRecords.end()); // otherwise it's new PIT entry
139 
140  time::steady_clock::TimePoint now = time::steady_clock::now();
141  time::steady_clock::Duration sinceLastOutgoing = now - lastOutgoing->getLastRenewed();
142  bool shouldRetransmit = sinceLastOutgoing >= MIN_RETRANSMISSION_INTERVAL;
143  if (!shouldRetransmit) {
144  NFD_LOG_DEBUG(interest << " from=" << inFace.getId()
145  << " dontRetransmit sinceLastOutgoing=" << sinceLastOutgoing.count());
146  return;
147  }
148 
149  // find an unused upstream with lowest cost except downstream
150  it = std::find_if(nexthops.begin(), nexthops.end(),
151  bind(&predicate_NextHop_eligible, pitEntry, _1, inFace.getId(), true, now));
152  if (it != nexthops.end()) {
153  shared_ptr<Face> outFace = it->getFace();
154  this->sendInterest(pitEntry, outFace);
155  NFD_LOG_DEBUG(interest << " from=" << inFace.getId()
156  << " retransmit-unused-to=" << outFace->getId());
157  return;
158  }
159 
160  // find an eligible upstream that is used earliest
161  it = findEligibleNextHopWithEarliestOutRecord(pitEntry, nexthops, inFace.getId());
162  if (it == nexthops.end()) {
163  NFD_LOG_DEBUG(interest << " from=" << inFace.getId() << " retransmitNoNextHop");
164  }
165  else {
166  shared_ptr<Face> outFace = it->getFace();
167  this->sendInterest(pitEntry, outFace);
168  NFD_LOG_DEBUG(interest << " from=" << inFace.getId()
169  << " retransmit-retry-to=" << outFace->getId());
170  }
171 }
172 
173 } // namespace fw
174 } // namespace nfd
virtual void afterReceiveInterest(const Face &inFace, const Interest &interest, shared_ptr< fib::Entry > fibEntry, shared_ptr< pit::Entry > pitEntry) 1
trigger after Interest is received
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:36
time::steady_clock::TimePoint getLastRenewed() const
main class of NFD
Definition: forwarder.hpp:54
represents a face
Definition: face.hpp:59
static bool compare_OutRecord_lastRenewed(const pit::OutRecord &a, const pit::OutRecord &b)
std::vector< fib::NextHop > NextHopList
Definition: fib-entry.hpp:48
identifies a face
void rejectPendingInterest(shared_ptr< pit::Entry > pitEntry)
decide that a pending Interest cannot be forwarded
Definition: strategy.hpp:168
represents a forwarding strategy
Definition: strategy.hpp:37
const shared_ptr< Face > & getFace() const
Definition: fib-nexthop.cpp:38
std::list< OutRecord > OutRecordCollection
represents an unordered collection of OutRecords
Definition: pit-entry.hpp:49
static bool predicate_NextHop_eligible(const shared_ptr< pit::Entry > &pitEntry, const fib::NextHop &nexthop, FaceId currentDownstream, bool wantUnused=false, time::steady_clock::TimePoint now=time::steady_clock::TimePoint::min())
determines whether a NextHop is eligible
#define NFD_LOG_INIT(name)
Definition: logger.hpp:33
contains information about an Interest toward an outgoing face
void sendInterest(shared_ptr< pit::Entry > pitEntry, shared_ptr< Face > outFace, bool wantNewNonce=false)
send Interest to outFace
Definition: strategy.hpp:160
BestRouteStrategy2(Forwarder &forwarder, const Name &name=STRATEGY_NAME)
FaceId getId() const
Definition: face.cpp:51
static const time::milliseconds MIN_RETRANSMISSION_INTERVAL
static fib::NextHopList::const_iterator findEligibleNextHopWithEarliestOutRecord(const shared_ptr< pit::Entry > &pitEntry, const fib::NextHopList &nexthops, FaceId currentDownstream)
pick an eligible NextHop with earliest OutRecord
represents a nexthop record in FIB entry
Definition: fib-nexthop.hpp:38