blob: aa21ff26dc6739101ec51116a30105996420a7d4 [file] [log] [blame]
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2011 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
19 * Ilya Moiseenko <iliamo@cs.ucla.edu>
20 */
21
22#include "per-fib-limits.h"
23
24#include "ns3/ndn-interest-header.h"
25#include "ns3/ndn-content-object-header.h"
26#include "ns3/ndn-pit.h"
27#include "ns3/ndn-pit-entry.h"
28
29#include "ns3/assert.h"
30#include "ns3/log.h"
31#include "ns3/simulator.h"
Alexander Afanasyev6a3bb132012-08-15 09:47:35 -070032#include "ns3/random-variable.h"
Alexander Afanasyevccbd8342012-08-16 16:54:39 -070033#include "ns3/double.h"
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -070034
35#include <boost/foreach.hpp>
36#include <boost/lambda/lambda.hpp>
37#include <boost/lambda/bind.hpp>
38namespace ll = boost::lambda;
39
40NS_LOG_COMPONENT_DEFINE ("ndn.fw.PerFibLimits");
41
42namespace ns3 {
43namespace ndn {
44namespace fw {
45
46NS_OBJECT_ENSURE_REGISTERED (PerFibLimits);
47
48TypeId
49PerFibLimits::GetTypeId (void)
50{
51 static TypeId tid = TypeId ("ns3::ndn::fw::PerFibLimits")
52 .SetGroupName ("Ndn")
53 .SetParent <FwStats> ()
54 .AddConstructor <PerFibLimits> ()
Alexander Afanasyevccbd8342012-08-16 16:54:39 -070055
56 .AddAttribute ("Threshold", "Minimum number of incoming interests to enable dropping decision",
57 DoubleValue (0.25),
58 MakeDoubleAccessor (&PerFibLimits::m_threshold),
59 MakeDoubleChecker<double> ())
60
61 .AddAttribute ("GraceAcceptProbability", "Probability to accept Interest even though stats telling that satisfaction ratio is 0",
62 DoubleValue (0.01),
63 MakeDoubleAccessor (&PerFibLimits::m_graceAcceptProbability),
64 MakeDoubleChecker<double> ())
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -070065 ;
66 return tid;
67}
68
69PerFibLimits::PerFibLimits ()
70{
71}
72
73void
74PerFibLimits::DoDispose ()
75{
76 BestRoute::DoDispose ();
77 m_decayLimitsEvent.Cancel ();
78}
79
80bool
81PerFibLimits::WillSendOutInterest (const Ptr<Face> &outgoingFace,
82 Ptr<InterestHeader> header,
83 Ptr<pit::Entry> pitEntry)
84{
85 NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
86 // override all (if any) parent processing
87
88 pit::Entry::out_iterator outgoing =
89 pitEntry->GetOutgoing ().find (outgoingFace);
90
91 if (outgoing != pitEntry->GetOutgoing ().end ())
92 {
93 return false;
94 }
95
Alexander Afanasyev70426a02012-08-15 15:39:18 -070096 // check stats
97 Ptr<Face> inFace = pitEntry->GetIncoming ().begin ()->m_face;
98 // const ndnSIM::LoadStatsFace &stats = GetStatsTree ()[header->GetName ()].incoming ().find (inFace)->second;
99 const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
100
Alexander Afanasyevccbd8342012-08-16 16:54:39 -0700101 if (stats.count ().GetStats ().get<0> () >= m_threshold * pitEntry->GetFibEntry ()->GetLimits ().GetMaxLimit ())
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700102 {
103 double ratio = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
104 // NS_ASSERT_MSG (ratio > 0, "If count is a reasonable value, ratio cannot be negative");
105 UniformVariable randAccept (0, 1);
106 double dice = randAccept.GetValue ();
Alexander Afanasyevccbd8342012-08-16 16:54:39 -0700107 if (ratio < 0 || dice < ratio + m_graceAcceptProbability)
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700108 {
109 // ok, accepting the interests
110 }
111 else
112 {
113 // boo. bad luck
114 return false;
115 }
116 }
117
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -0700118 if (pitEntry->GetFibEntry ()->GetLimits ().IsBelowLimit ())
119 {
Alexander Afanasyev6a3bb132012-08-15 09:47:35 -0700120 if (outgoingFace->GetLimits ().IsBelowLimit ())
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -0700121 {
122 pitEntry->AddOutgoing (outgoingFace);
123 return true;
124 }
125 else
126 {
Alexander Afanasyev6a3bb132012-08-15 09:47:35 -0700127 NS_LOG_DEBUG ("Face limit. Reverting back per-prefix allowance");
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -0700128 pitEntry->GetFibEntry ()->GetLimits ().RemoveOutstanding ();
129 }
130 }
131
132 return false;
133}
134
135void
136PerFibLimits::WillEraseTimedOutPendingInterest (Ptr<pit::Entry> pitEntry)
137{
138 NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
139
140 for (pit::Entry::out_container::iterator face = pitEntry->GetOutgoing ().begin ();
141 face != pitEntry->GetOutgoing ().end ();
142 face ++)
143 {
Alexander Afanasyev6a3bb132012-08-15 09:47:35 -0700144 face->m_face->GetLimits ().RemoveOutstanding ();
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -0700145 // face->m_face->GetLimits ()->DecreaseLimit (); !!! do not decrease per-face limit. it doesn't make sense !!!
146 }
147
148 pitEntry->GetFibEntry ()->GetLimits ().RemoveOutstanding ();
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700149 // pitEntry->GetFibEntry ()->GetLimits ().DecreaseLimit (); // multiplicative decrease
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -0700150
151 if (!m_decayLimitsEvent.IsRunning ())
Alexander Afanasyev6a3bb132012-08-15 09:47:35 -0700152 {
153 UniformVariable rand (0,5);
154 m_decayLimitsEvent = Simulator::Schedule (Seconds (1.0) + Seconds (0.001 * rand.GetValue ()), &PerFibLimits::DecayLimits, this);
155 }
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -0700156}
157
158
159void
160PerFibLimits::WillSatisfyPendingInterest (const Ptr<Face> &incomingFace,
161 Ptr<pit::Entry> pitEntry)
162{
163 NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
164
165 super::WillSatisfyPendingInterest (incomingFace, pitEntry);
166
167 for (pit::Entry::out_container::iterator face = pitEntry->GetOutgoing ().begin ();
168 face != pitEntry->GetOutgoing ().end ();
169 face ++)
170 {
Alexander Afanasyev6a3bb132012-08-15 09:47:35 -0700171 face->m_face->GetLimits ().RemoveOutstanding ();
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -0700172 // face->m_face->GetLimits ()->IncreaseLimit (); !!! do not increase (as do not decrease) per-face limit. again, it doesn't make sense
173 }
174
175 pitEntry->GetFibEntry ()->GetLimits ().RemoveOutstanding ();
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700176 // pitEntry->GetFibEntry ()->GetLimits ().IncreaseLimit (); // additive increase
Alexander Afanasyevea9b3e62012-08-13 19:02:54 -0700177}
178
179
180// void
181// PerFibLimits::DidReceiveValidNack (const Ptr<Face> &incomingFace,
182// uint32_t nackCode,
183// Ptr<pit::Entry> pitEntry)
184// {
185// // super::DidReceiveValidNack (incomingFace, nackCode, pitEntry);
186
187// // ??
188// }
189
190void
191PerFibLimits::DecayLimits ()
192{
193 for (Ptr<fib::Entry> entry = m_fib->Begin ();
194 entry != m_fib->End ();
195 entry = m_fib->Next (entry))
196 {
197 entry->GetLimits ().DecayCurrentLimit ();
198 }
199
200 m_decayLimitsEvent = Simulator::Schedule (Seconds (1.0), &PerFibLimits::DecayLimits, this);
201}
202
203
204} // namespace fw
205} // namespace ndn
206} // namespace ns3