asf-probing-module.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "asf-probing-module.hpp"
27 
28 #include "core/random.hpp"
29 
30 #include <boost/random/uniform_real_distribution.hpp>
31 
32 namespace nfd {
33 namespace fw {
34 namespace asf {
35 
36 constexpr time::seconds ProbingModule::DEFAULT_PROBING_INTERVAL;
37 
38 static_assert(ProbingModule::DEFAULT_PROBING_INTERVAL < AsfMeasurements::MEASUREMENTS_LIFETIME,
39  "ProbingModule::DEFAULT_PROBING_INTERVAL must be less than AsfMeasurements::MEASUREMENTS_LIFETIME");
40 
42  : m_probingInterval(DEFAULT_PROBING_INTERVAL)
43  , m_measurements(measurements)
44 {
45 }
46 
47 void
48 ProbingModule::scheduleProbe(const fib::Entry& fibEntry, const time::milliseconds& interval)
49 {
50  Name prefix = fibEntry.getPrefix();
51 
52  // Set the probing flag for the namespace to true after passed interval of time
53  scheduler::schedule(interval, [this, prefix] {
54  NamespaceInfo* info = m_measurements.getNamespaceInfo(prefix);
55 
56  if (info == nullptr) {
57  // fib::Entry with the passed prefix has been removed or the fib::Entry has
58  // a name that is not controlled by the AsfStrategy
59  return;
60  }
61  else {
62  info->setIsProbingDue(true);
63  }
64  });
65 }
66 
67 Face*
68 ProbingModule::getFaceToProbe(const Face& inFace,
69  const Interest& interest,
70  const fib::Entry& fibEntry,
71  const Face& faceUsed)
72 {
73  FaceInfoFacePairSet rankedFaces(
74  [] (FaceInfoFacePair pairLhs, FaceInfoFacePair pairRhs) -> bool {
75  // Sort by RTT
76  // If a face has timed-out, rank it behind non-timed-out faces
77  FaceInfo& lhs = *pairLhs.first;
78  FaceInfo& rhs = *pairRhs.first;
79 
80  return (!lhs.isTimeout() && rhs.isTimeout()) ||
81  (lhs.isTimeout() == rhs.isTimeout() && lhs.getSrtt() < rhs.getSrtt());
82  });
83 
84  // Put eligible faces into rankedFaces. If a face does not have an RTT measurement,
85  // immediately pick the face for probing
86  for (const fib::NextHop& hop : fibEntry.getNextHops()) {
87  Face& hopFace = hop.getFace();
88 
89  // Don't send probe Interest back to the incoming face or use the same face
90  // as the forwarded Interest
91  if (hopFace.getId() == inFace.getId() || hopFace.getId() == faceUsed.getId()) {
92  continue;
93  }
94 
95  FaceInfo* info = m_measurements.getFaceInfo(fibEntry, interest, hopFace);
96 
97  // If no RTT has been recorded, probe this face
98  if (info == nullptr || !info->hasSrttMeasurement()) {
99  return &hopFace;
100  }
101 
102  // Add FaceInfo to container sorted by RTT
103  rankedFaces.insert(std::make_pair(info, &hopFace));
104  }
105 
106  if (rankedFaces.empty()) {
107  // No Face to probe
108  return nullptr;
109  }
110 
111  return getFaceBasedOnProbability(rankedFaces);
112 }
113 
114 bool
115 ProbingModule::isProbingNeeded(const fib::Entry& fibEntry, const Interest& interest)
116 {
117  // Return the probing status flag for a namespace
118  NamespaceInfo& info = m_measurements.getOrCreateNamespaceInfo(fibEntry, interest);
119 
120  // If a first probe has not been scheduled for a namespace
121  if (!info.isFirstProbeScheduled()) {
122  // Schedule first probe between 0 and 5 seconds
123  uint64_t interval = getRandomNumber(0, 5000);
124  scheduleProbe(fibEntry, time::milliseconds(interval));
125 
127  }
128 
129  return info.isProbingDue();
130 }
131 
132 void
133 ProbingModule::afterForwardingProbe(const fib::Entry& fibEntry, const Interest& interest)
134 {
135  // After probing is done, need to set probing flag to false and
136  // schedule another future probe
137  NamespaceInfo& info = m_measurements.getOrCreateNamespaceInfo(fibEntry, interest);
138  info.setIsProbingDue(false);
139 
140  scheduleProbe(fibEntry, m_probingInterval);
141 }
142 
143 Face*
144 ProbingModule::getFaceBasedOnProbability(const FaceInfoFacePairSet& rankedFaces)
145 {
146  double randomNumber = getRandomNumber(0, 1);
147  uint64_t rankSum = ((rankedFaces.size() + 1) * rankedFaces.size()) / 2;
148 
149  uint64_t rank = 1;
150  double offset = 0.0;
151 
152  for (const FaceInfoFacePair pair : rankedFaces) {
153  double probability = getProbingProbability(rank++, rankSum, rankedFaces.size());
154 
155  // Is the random number within the bounds of this face's probability + the previous faces'
156  // probability?
157  //
158  // e.g. (FaceId: 1, p=0.5), (FaceId: 2, p=0.33), (FaceId: 3, p=0.17)
159  // randomNumber = 0.92
160  //
161  // The face with FaceId: 3 should be picked
162  // (0.68 < 0.5 + 0.33 + 0.17) == true
163  //
164  if (randomNumber <= offset + probability) {
165  // Found face to probe
166  return pair.second;
167  }
168 
169  offset += probability;
170  }
171 
172  // Given a set of Faces, this method should always select a Face to probe
173  BOOST_ASSERT(false);
174  return nullptr;
175 }
176 
177 double
178 ProbingModule::getProbingProbability(uint64_t rank, uint64_t rankSum, uint64_t nFaces)
179 {
180  // p = n + 1 - j ; n: # faces
181  // ---------
182  // sum(ranks)
183  return static_cast<double>(nFaces + 1 - rank) / rankSum;
184 }
185 
186 double
187 ProbingModule::getRandomNumber(double start, double end)
188 {
189  boost::random::uniform_real_distribution<double> distribution(start, end);
190  return distribution(getGlobalRng());
191 }
192 
193 } // namespace asf
194 } // namespace fw
195 } // namespace nfd
void scheduleProbe(const fib::Entry &fibEntry, const time::milliseconds &interval)
void afterForwardingProbe(const fib::Entry &fibEntry, const Interest &interest)
bool hasSrttMeasurement() const
ProbingModule(AsfMeasurements &measurements)
NamespaceInfo * getNamespaceInfo(const Name &prefix)
represents a FIB entry
Definition: fib-entry.hpp:51
RttStats::Rtt getSrtt() const
void setIsProbingDue(bool isProbingDue)
FaceInfo * getFaceInfo(const fib::Entry &fibEntry, const Interest &interest, const Face &face)
const Name & getPrefix() const
Definition: fib-entry.hpp:58
static constexpr time::microseconds MEASUREMENTS_LIFETIME
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
Definition: algorithm.hpp:32
static constexpr time::seconds DEFAULT_PROBING_INTERVAL
NamespaceInfo & getOrCreateNamespaceInfo(const fib::Entry &fibEntry, const Interest &interest)
void setHasFirstProbeBeenScheduled(bool hasBeenScheduled)
bool isProbingNeeded(const fib::Entry &fibEntry, const Interest &interest)
boost::random::mt19937 & getGlobalRng()
Definition: random.cpp:34
stores stategy information about each face in this namespace
EventId schedule(const time::nanoseconds &after, const Scheduler::Event &event)
schedule an event
Definition: scheduler.cpp:47
Face * getFaceToProbe(const Face &inFace, const Interest &interest, const fib::Entry &fibEntry, const Face &faceUsed)
represents a nexthop record in FIB entry
Definition: fib-nexthop.hpp:38
const NextHopList & getNextHops() const
Definition: fib-entry.hpp:64
Strategy information for each face in a namespace.
Helper class to retrieve and create strategy measurements.