blob: f323cdb79b08a926999f7b54e9ab2a7beb3a7153 [file] [log] [blame]
Alexander Afanasyev6f95e702012-10-31 16:27:31 -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 "ndn-limits-rate.h"
22
23#include "ns3/log.h"
24#include "ns3/simulator.h"
25#include "ns3/random-variable.h"
Alexander Afanasyev7e4235a2012-10-31 16:58:44 -070026#include "ns3/ndn-face.h"
27#include "ns3/node.h"
Alexander Afanasyev6f95e702012-10-31 16:27:31 -070028
29NS_LOG_COMPONENT_DEFINE ("ndn.Limits.Rate");
30
31namespace ns3 {
32namespace ndn {
33
34NS_OBJECT_ENSURE_REGISTERED (LimitsRate);
35
36TypeId
37LimitsRate::GetTypeId ()
38{
39 static TypeId tid = TypeId ("ns3::ndn::Limits::Rate")
40 .SetGroupName ("Ndn")
41 .SetParent <Limits> ()
42 .AddConstructor <LimitsRate> ()
43
44 ;
45 return tid;
46}
47
48void
Alexander Afanasyev7e4235a2012-10-31 16:58:44 -070049LimitsRate::NotifyNewAggregate ()
50{
51 super::NotifyNewAggregate ();
52
53 if (!m_isLeakScheduled)
54 {
55 if (GetObject<Face> () != 0)
56 {
57 NS_ASSERT_MSG (GetObject<Face> ()->GetNode () != 0, "Node object should exist on the face");
58
59 m_isLeakScheduled = true;
Alexander Afanasyev08ab5722012-11-06 17:22:25 -080060 UniformVariable r (0.0, 1.0);
Alexander Afanasyev7e4235a2012-10-31 16:58:44 -070061 Simulator::ScheduleWithContext (GetObject<Face> ()->GetNode ()->GetId (),
62 Seconds (r.GetValue ()), &LimitsRate::LeakBucket, this, 0.0);
63 }
64 }
65}
66
Alexander Afanasyevccd5bb42012-10-31 17:27:49 -070067void
68LimitsRate::SetLimits (double rate, double delay)
69{
70 super::SetLimits (rate, delay);
71
72 // maximum allowed burst
73 m_bucketMax = GetMaxRate () * GetMaxDelay ();
74
75 // amount of packets allowed every second (leak rate)
76 m_bucketLeak = GetMaxRate ();
77}
78
Alexander Afanasyev7e4235a2012-10-31 16:58:44 -070079
80void
Alexander Afanasyev6f95e702012-10-31 16:27:31 -070081LimitsRate::UpdateCurrentLimit (double limit)
82{
83 NS_ASSERT_MSG (limit >= 0.0, "Limit should be greater or equal to zero");
84
85 m_bucketLeak = std::min (limit, GetMaxRate ());
86 m_bucketMax = m_bucketLeak * GetMaxDelay ();
87}
88
89bool
90LimitsRate::IsBelowLimit ()
91{
92 if (!IsEnabled ()) return true;
93
94 return (m_bucketMax - m_bucket >= 1.0);
95}
96
97void
98LimitsRate::BorrowLimit ()
99{
100 if (!IsEnabled ()) return;
101
102 NS_ASSERT_MSG (m_bucketMax - m_bucket >= 1.0, "Should not be possible, unless we IsBelowLimit was not checked correctly");
103 m_bucket += 1;
104}
105
106void
107LimitsRate::ReturnLimit ()
108{
109 // do nothing
110}
111
112void
113LimitsRate::LeakBucket (double interval)
114{
115 const double leak = m_bucketLeak * interval;
116
Alexander Afanasyev7e4235a2012-10-31 16:58:44 -0700117#ifdef NS3_LOG_ENABLE
118 if (m_bucket>1)
119 {
120 NS_LOG_DEBUG ("Leak from " << m_bucket << " to " << std::max (0.0, m_bucket - leak));
121 }
122#endif
Alexander Afanasyev08ab5722012-11-06 17:22:25 -0800123
124 double bucketOld = m_bucket;
Alexander Afanasyev7e4235a2012-10-31 16:58:44 -0700125
Alexander Afanasyev6f95e702012-10-31 16:27:31 -0700126 m_bucket = std::max (0.0, m_bucket - leak);
Alexander Afanasyev7e4235a2012-10-31 16:58:44 -0700127
128 // calculate interval so next time we will leak by 1.001, unless such interval would be more than 1 second
129 double newInterval = 1.0;
130 if (m_bucketLeak > 1.0)
131 {
132 newInterval = 1.001 / m_bucketLeak;
133 }
Alexander Afanasyev08ab5722012-11-06 17:22:25 -0800134
135 if (m_bucketMax - bucketOld < 1.0 &&
136 m_bucketMax - m_bucket >= 1.0) // limit number of times this stuff is called
137 {
138 this->FireAvailableSlotCallback ();
139 }
Alexander Afanasyev7e4235a2012-10-31 16:58:44 -0700140
141 Simulator::Schedule (Seconds (newInterval), &LimitsRate::LeakBucket, this, newInterval);
Alexander Afanasyev6f95e702012-10-31 16:27:31 -0700142}
143
144} // namespace ndn
145} // namespace ns3