blob: a0274eded49f573ebc32d18ac64686784ca2ef11 [file] [log] [blame]
Alexander Afanasyevcaeade22012-09-04 16:31:12 -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 */
20
21#include "dynamic-limits.h"
22
23#include "ns3/ndn-l3-protocol.h"
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"
32#include "ns3/random-variable.h"
33#include "ns3/double.h"
34
35#include <boost/foreach.hpp>
36#include <boost/lexical_cast.hpp>
37#include <boost/lambda/lambda.hpp>
38#include <boost/lambda/bind.hpp>
39namespace ll = boost::lambda;
40
41NS_LOG_COMPONENT_DEFINE ("ndn.fw.DynamicLimits");
42
43namespace ns3 {
44namespace ndn {
45namespace fw {
46
47NS_OBJECT_ENSURE_REGISTERED (DynamicLimits);
48
49TypeId
50DynamicLimits::GetTypeId (void)
51{
52 static TypeId tid = TypeId ("ns3::ndn::fw::DynamicLimits")
53 .SetGroupName ("Ndn")
54 .SetParent <super> ()
55 .AddConstructor <DynamicLimits> ()
56
57 .AddAttribute ("AnnounceLimits", "Enable limit announcement using scope 0 interests",
58 BooleanValue (false),
59 MakeBooleanAccessor (&DynamicLimits::m_announceLimits),
60 MakeBooleanChecker ())
61
62 ;
63 return tid;
64}
65
66DynamicLimits::DynamicLimits ()
67{
68}
69
70void
71DynamicLimits::DoDispose ()
72{
73 m_announceEvent.Cancel ();
74
75 super::DoDispose ();
76}
77
78void
79DynamicLimits::NotifyNewAggregate ()
80{
81 super::NotifyNewAggregate ();
82
83 if (m_announceLimits)
84 {
85 if (m_pit != 0 && m_fib != 0)
86 {
Alexander Afanasyev048c4ad2012-09-09 01:57:38 -070087 if (!m_announceEvent.IsRunning ())
88 {
89 m_announceEvent = Simulator::Schedule (Seconds (1.0),
90 &DynamicLimits::AnnounceLimits, this);
91 }
Alexander Afanasyevcaeade22012-09-04 16:31:12 -070092 }
93 }
94}
95
96void
97DynamicLimits::OnInterest (Ptr<Face> face,
98 Ptr<const InterestHeader> header,
99 Ptr<const Packet> origPacket)
100{
101 if (header->GetScope () != 0)
102 super::OnInterest (face, header, origPacket);
103 else
104 ApplyAnnouncedLimit (face, header);
105}
106
107
108void
109DynamicLimits::AnnounceLimits ()
110{
111 Ptr<L3Protocol> l3 = GetObject<L3Protocol> ();
112 NS_ASSERT (l3 != 0);
113
114 if (l3->GetNFaces () < 2)
115 {
116 m_announceEvent = Simulator::Schedule (Seconds (1.0),
117 &DynamicLimits::AnnounceLimits, this);
118 return;
119 }
120
121 double sumOfWeights = 0;
122 double weightNormalization = 1.0;
123 for (uint32_t faceId = 0; faceId < l3->GetNFaces (); faceId ++)
124 {
125 Ptr<Face> inFace = l3->GetFace (faceId);
126
127 const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
128 double weight = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
129 if (weight < 0) weight = 0.5;
130
131 sumOfWeights += weight;
132 }
133 if (sumOfWeights >= 1)
134 {
135 // disable normalization (not necessary)
136 weightNormalization = 1.0;
137 }
138 else
139 {
140 // sumOfWeights /= (l3->GetNFaces ());
141 weightNormalization = 1 / sumOfWeights;
142 }
143
144 for (Ptr<fib::Entry> entry = m_fib->Begin ();
145 entry != m_fib->End ();
146 entry = m_fib->Next (entry))
147 {
148 InterestHeader announceInterest;
149 announceInterest.SetScope (0); // link-local
150
151 uint32_t totalAllowance = 0;
152 for (fib::FaceMetricContainer::type::iterator fibFace = entry->m_faces.begin ();
153 fibFace != entry->m_faces.end ();
154 fibFace ++)
155 {
156 totalAllowance += fibFace->m_face->GetLimits ().GetMaxLimit ();
157 }
158
159 if (totalAllowance == 0)
160 {
161 // don't announce anything, there is no limit
162 continue;
163 }
164
165 for (uint32_t faceId = 0; faceId < l3->GetNFaces (); faceId ++)
166 {
167 Ptr<Face> inFace = l3->GetFace (faceId);
168
169 const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
170 double weight = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
171 if (weight < 0) weight = 0.5;
172
173 Ptr<NameComponents> prefixWithLimit = Create<NameComponents> (entry->GetPrefix ());
174 (*prefixWithLimit)
175 ("limit")
176 (static_cast<uint32_t> (std::max (1.0, weightNormalization * weight * totalAllowance)));
177
178 announceInterest.SetName (prefixWithLimit);
179 // lifetime is 0
180
181 Ptr<Packet> pkt = Create<Packet> ();
182 pkt->AddHeader (announceInterest);
183
184 inFace->Send (pkt);
185 }
186 }
187
188 m_announceEvent = Simulator::Schedule (Seconds (1.0),
189 &DynamicLimits::AnnounceLimits, this);
190}
191
192void
193DynamicLimits::ApplyAnnouncedLimit (Ptr<Face> inFace,
194 Ptr<const InterestHeader> header)
195{
196 // Ptr<fib::Entry> fibEntry = m_fib->LongestPrefixMatch (header);
197 // if (fibEntry == 0)
198 // return;
199
200 uint32_t limit = boost::lexical_cast<uint32_t> (header->GetName ().GetLastComponent ());
201 inFace->GetLimits ().SetMaxLimit (limit);
202
203 // if (Simulator::GetContext () == 6 || Simulator::GetContext () == 4)
204 // {
205 // std::cerr << Simulator::Now ().ToDouble (Time::S) << "s from:" << *inFace << " " << *header << std::endl;
206 // std::cerr << header->GetName ().GetLastComponent () << ", " << boost::lexical_cast<uint32_t> (header->GetName ().GetLastComponent ()) << std::endl;
207 // }
208}
209
210
211} // namespace fw
212} // namespace ndn
213} // namespace ns3