blob: f20ff3a18fd67eb74c672af7765e1d423df06868 [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 {
87 m_announceEvent = Simulator::Schedule (Seconds (1.0),
88 &DynamicLimits::AnnounceLimits, this);
89 }
90 }
91}
92
93void
94DynamicLimits::OnInterest (Ptr<Face> face,
95 Ptr<const InterestHeader> header,
96 Ptr<const Packet> origPacket)
97{
98 if (header->GetScope () != 0)
99 super::OnInterest (face, header, origPacket);
100 else
101 ApplyAnnouncedLimit (face, header);
102}
103
104
105void
106DynamicLimits::AnnounceLimits ()
107{
108 Ptr<L3Protocol> l3 = GetObject<L3Protocol> ();
109 NS_ASSERT (l3 != 0);
110
111 if (l3->GetNFaces () < 2)
112 {
113 m_announceEvent = Simulator::Schedule (Seconds (1.0),
114 &DynamicLimits::AnnounceLimits, this);
115 return;
116 }
117
118 double sumOfWeights = 0;
119 double weightNormalization = 1.0;
120 for (uint32_t faceId = 0; faceId < l3->GetNFaces (); faceId ++)
121 {
122 Ptr<Face> inFace = l3->GetFace (faceId);
123
124 const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
125 double weight = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
126 if (weight < 0) weight = 0.5;
127
128 sumOfWeights += weight;
129 }
130 if (sumOfWeights >= 1)
131 {
132 // disable normalization (not necessary)
133 weightNormalization = 1.0;
134 }
135 else
136 {
137 // sumOfWeights /= (l3->GetNFaces ());
138 weightNormalization = 1 / sumOfWeights;
139 }
140
141 for (Ptr<fib::Entry> entry = m_fib->Begin ();
142 entry != m_fib->End ();
143 entry = m_fib->Next (entry))
144 {
145 InterestHeader announceInterest;
146 announceInterest.SetScope (0); // link-local
147
148 uint32_t totalAllowance = 0;
149 for (fib::FaceMetricContainer::type::iterator fibFace = entry->m_faces.begin ();
150 fibFace != entry->m_faces.end ();
151 fibFace ++)
152 {
153 totalAllowance += fibFace->m_face->GetLimits ().GetMaxLimit ();
154 }
155
156 if (totalAllowance == 0)
157 {
158 // don't announce anything, there is no limit
159 continue;
160 }
161
162 for (uint32_t faceId = 0; faceId < l3->GetNFaces (); faceId ++)
163 {
164 Ptr<Face> inFace = l3->GetFace (faceId);
165
166 const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
167 double weight = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
168 if (weight < 0) weight = 0.5;
169
170 Ptr<NameComponents> prefixWithLimit = Create<NameComponents> (entry->GetPrefix ());
171 (*prefixWithLimit)
172 ("limit")
173 (static_cast<uint32_t> (std::max (1.0, weightNormalization * weight * totalAllowance)));
174
175 announceInterest.SetName (prefixWithLimit);
176 // lifetime is 0
177
178 Ptr<Packet> pkt = Create<Packet> ();
179 pkt->AddHeader (announceInterest);
180
181 inFace->Send (pkt);
182 }
183 }
184
185 m_announceEvent = Simulator::Schedule (Seconds (1.0),
186 &DynamicLimits::AnnounceLimits, this);
187}
188
189void
190DynamicLimits::ApplyAnnouncedLimit (Ptr<Face> inFace,
191 Ptr<const InterestHeader> header)
192{
193 // Ptr<fib::Entry> fibEntry = m_fib->LongestPrefixMatch (header);
194 // if (fibEntry == 0)
195 // return;
196
197 uint32_t limit = boost::lexical_cast<uint32_t> (header->GetName ().GetLastComponent ());
198 inFace->GetLimits ().SetMaxLimit (limit);
199
200 // if (Simulator::GetContext () == 6 || Simulator::GetContext () == 4)
201 // {
202 // std::cerr << Simulator::Now ().ToDouble (Time::S) << "s from:" << *inFace << " " << *header << std::endl;
203 // std::cerr << header->GetName ().GetLastComponent () << ", " << boost::lexical_cast<uint32_t> (header->GetName ().GetLastComponent ()) << std::endl;
204 // }
205}
206
207
208} // namespace fw
209} // namespace ndn
210} // namespace ns3