blob: bfcb9610dfce866059847861605b7816ab669339 [file] [log] [blame]
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -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 "ccnx-fib.h"
22
23#include "ccnx.h"
24#include "ccnx-face.h"
25#include "ccnx-interest-header.h"
26
27#include "ns3/node.h"
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -070028#include "ns3/assert.h"
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -070029#include "ns3/names.h"
Ilya Moiseenko00b30482011-11-15 17:58:00 -080030#include "ns3/log.h"
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -070031
32#define NDN_RTO_ALPHA 0.125
33#define NDN_RTO_BETA 0.25
34#define NDN_RTO_K 4
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -070035
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -070036#include <boost/ref.hpp>
Alexander Afanasyeva46844b2011-11-21 19:13:26 -080037#include <boost/lambda/lambda.hpp>
Alexander Afanasyev19426ef2011-11-23 20:55:28 -080038#include <boost/lambda/bind.hpp>
39namespace ll = boost::lambda;
Alexander Afanasyeva46844b2011-11-21 19:13:26 -080040
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -070041namespace ns3 {
42
43
44//////////////////////////////////////////////////////////////////////
45// Helpers
46//////////////////////////////////////////////////////////////////////
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -070047namespace __ccnx_private {
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -070048
49struct CcnxFibFaceMetricByFace
50{
51 typedef CcnxFibFaceMetricContainer::type::index<i_face>::type
52 type;
53};
54
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -070055}
56//////////////////////////////////////////////////////////////////////
57//////////////////////////////////////////////////////////////////////
Ilya Moiseenko00b30482011-11-15 17:58:00 -080058NS_LOG_COMPONENT_DEFINE ("CcnxFib");
59
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -070060using namespace __ccnx_private;
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -070061
Alexander Afanasyevcf133f02011-09-06 12:13:48 -070062TypeId
63CcnxFib::GetTypeId (void)
64{
65 static TypeId tid = TypeId ("ns3::CcnxFib")
66 .SetParent<Object> ()
67 .SetGroupName ("Ccnx")
68 .AddConstructor<CcnxFib> ()
69
70 ;
71 return tid;
72}
73
Alexander Afanasyeva46844b2011-11-21 19:13:26 -080074/////////////////////////////////////////////////////////////////////
75
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -070076void
Alexander Afanasyeva46844b2011-11-21 19:13:26 -080077CcnxFibFaceMetric::UpdateRtt (const Time &rttSample)
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -070078{
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -070079 // const Time & this->m_rttSample
80
81 //update srtt and rttvar (RFC 2988)
Alexander Afanasyeva46844b2011-11-21 19:13:26 -080082 if (m_sRtt.IsZero ())
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -070083 {
84 //first RTT measurement
Alexander Afanasyeva46844b2011-11-21 19:13:26 -080085 NS_ASSERT_MSG (m_rttVar.IsZero (), "SRTT is zero, but variation is not");
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -070086
Alexander Afanasyeva46844b2011-11-21 19:13:26 -080087 m_sRtt = rttSample;
88 m_rttVar = Time (m_sRtt / 2.0);
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -070089 }
90 else
91 {
Alexander Afanasyeva46844b2011-11-21 19:13:26 -080092 m_rttVar = Time ((1 - NDN_RTO_BETA) * m_rttVar + NDN_RTO_BETA * Abs(m_sRtt - rttSample));
93 m_sRtt = Time ((1 - NDN_RTO_ALPHA) * m_sRtt + NDN_RTO_ALPHA * rttSample);
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -070094 }
95}
96
Alexander Afanasyeva46844b2011-11-21 19:13:26 -080097/////////////////////////////////////////////////////////////////////
98
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -070099void
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800100CcnxFibEntry::UpdateFaceRtt (Ptr<CcnxFace> face, const Time &sample)
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700101{
Alexander Afanasyeva46844b2011-11-21 19:13:26 -0800102 CcnxFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
103 NS_ASSERT_MSG (record != m_faces.get<i_face> ().end (),
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700104 "Update status can be performed only on existing faces of CcxnFibEntry");
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700105
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800106 m_faces.modify (record,
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800107 ll::bind (&CcnxFibFaceMetric::UpdateRtt, ll::_1, sample));
Alexander Afanasyeva98cdd22011-08-29 17:32:37 -0700108
109 // reordering random access index same way as by metric index
Alexander Afanasyeva46844b2011-11-21 19:13:26 -0800110 m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700111}
112
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800113void
114CcnxFibEntry::UpdateStatus (Ptr<CcnxFace> face, CcnxFibFaceMetric::Status status)
Alexander Afanasyeva98cdd22011-08-29 17:32:37 -0700115{
Alexander Afanasyev23d2b542011-12-07 18:54:46 -0800116 NS_LOG_FUNCTION (this << boost::cref(*face) << status);
117
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800118 CcnxFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
119 NS_ASSERT_MSG (record != m_faces.get<i_face> ().end (),
120 "Update status can be performed only on existing faces of CcxnFibEntry");
121
122 m_faces.modify (record,
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800123 (&ll::_1)->*&CcnxFibFaceMetric::m_status = status);
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800124
125 // reordering random access index same way as by metric index
126 m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
127}
128
129void
130CcnxFibEntry::AddOrUpdateRoutingMetric (Ptr<CcnxFace> face, int32_t metric)
131{
132 NS_LOG_FUNCTION (this);
133 NS_ASSERT_MSG (face != NULL, "Trying to Add or Update NULL face");
134
135 CcnxFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
136 if (record == m_faces.get<i_face> ().end ())
137 {
138 m_faces.insert (CcnxFibFaceMetric (face, metric));
139 }
140 else
141 {
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700142 // don't update metric to higher value
143 if (record->m_routingCost > metric || record->m_status == CcnxFibFaceMetric::NDN_FIB_RED)
144 {
145 m_faces.modify (record,
146 (&ll::_1)->*&CcnxFibFaceMetric::m_routingCost = metric);
147
148 m_faces.modify (record,
149 (&ll::_1)->*&CcnxFibFaceMetric::m_status = CcnxFibFaceMetric::NDN_FIB_YELLOW);
150 }
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800151 }
152
153 // reordering random access index same way as by metric index
154 m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
155}
156
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700157void
158CcnxFibEntry::Invalidate ()
159{
160 for (CcnxFibFaceMetricByFace::type::iterator face = m_faces.begin ();
161 face != m_faces.end ();
162 face++)
163 {
164 m_faces.modify (face,
165 (&ll::_1)->*&CcnxFibFaceMetric::m_routingCost = std::numeric_limits<uint16_t>::max ());
166
167 m_faces.modify (face,
168 (&ll::_1)->*&CcnxFibFaceMetric::m_status = CcnxFibFaceMetric::NDN_FIB_RED);
169 }
170}
171
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800172const CcnxFibFaceMetric &
173CcnxFibEntry::FindBestCandidate (uint32_t skip/* = 0*/) const
174{
175 if (m_faces.size () == 0) throw CcnxFibEntry::NoFaces ();
Alexander Afanasyeva98cdd22011-08-29 17:32:37 -0700176 skip = skip % m_faces.size();
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800177 return m_faces.get<i_nth> () [skip];
Alexander Afanasyeva98cdd22011-08-29 17:32:37 -0700178}
179
180
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700181CcnxFib::CcnxFib ()
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700182{
183}
184
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700185void
186CcnxFib::NotifyNewAggregate ()
187{
188 if (m_node == 0)
189 m_node = this->GetObject<Node>();
190 Object::NotifyNewAggregate ();
191}
192
193void
194CcnxFib::DoDispose (void)
195{
Alexander Afanasyev07827182011-12-13 01:07:32 -0800196 m_fib.clear ();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700197 m_node = 0;
198 Object::DoDispose ();
199}
200
201
202CcnxFibEntryContainer::type::iterator
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700203CcnxFib::LongestPrefixMatch (const CcnxInterestHeader &interest) const
204{
205 const CcnxNameComponents &name = interest.GetName ();
Alexander Afanasyeva174aa52011-12-13 01:30:32 -0800206 for (size_t componentsCount = name.GetComponents ().size ()+1;
207 componentsCount > 0;
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700208 componentsCount--)
209 {
Alexander Afanasyeva174aa52011-12-13 01:30:32 -0800210 CcnxNameComponents subPrefix (name.GetSubComponents (componentsCount-1));
Alexander Afanasyev07827182011-12-13 01:07:32 -0800211 CcnxFibEntryContainer::type::iterator match = m_fib.find (subPrefix);
212 if (match != m_fib.end())
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700213 return match;
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700214 }
215
Alexander Afanasyev07827182011-12-13 01:07:32 -0800216 return m_fib.end ();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700217}
218
219
220CcnxFibEntryContainer::type::iterator
221CcnxFib::Add (const CcnxNameComponents &prefix, Ptr<CcnxFace> face, int32_t metric)
222{
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700223 return Add (Create<CcnxNameComponents> (prefix), face, metric);
224}
225
226CcnxFibEntryContainer::type::iterator
227CcnxFib::Add (const Ptr<const CcnxNameComponents> &prefix, Ptr<CcnxFace> face, int32_t metric)
228{
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700229// CcnxFibFaceMetric
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700230 NS_LOG_FUNCTION(this->GetObject<Node> ()->GetId () << boost::cref(*prefix) << boost::cref(*face) << metric);
231 CcnxFibEntryContainer::type::iterator entry = m_fib.find (*prefix);
Alexander Afanasyev07827182011-12-13 01:07:32 -0800232 if (entry == m_fib.end ())
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700233 {
Alexander Afanasyev07827182011-12-13 01:07:32 -0800234 entry = m_fib.insert (m_fib.end (), CcnxFibEntry (prefix));
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700235 // insert new
236 }
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700237
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800238 NS_ASSERT_MSG (face != NULL, "Trying to modify NULL face");
Alexander Afanasyev07827182011-12-13 01:07:32 -0800239 m_fib.modify (entry,
240 ll::bind (&CcnxFibEntry::AddOrUpdateRoutingMetric, ll::_1, face, metric));
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800241
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700242 return entry;
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700243}
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700244
245void
246CcnxFib::Remove (const Ptr<const CcnxNameComponents> &prefix)
247{
248 NS_LOG_FUNCTION (this->GetObject<Node> ()->GetId () << boost::cref(*prefix));
249 CcnxFibEntryContainer::type::iterator entry = m_fib.find (*prefix);
250 if (entry != m_fib.end ())
251 m_fib.erase (entry);
252}
253
254void
255CcnxFib::Invalidate (const Ptr<const CcnxNameComponents> &prefix)
256{
257 NS_LOG_FUNCTION (this->GetObject<Node> ()->GetId () << boost::cref(*prefix));
258
259 CcnxFibEntryContainer::type::iterator entry = m_fib.find (*prefix);
260 if (entry == m_fib.end ())
261 return; // nothing to invalidate
262
263 m_fib.modify (entry,
264 ll::bind (&CcnxFibEntry::Invalidate, ll::_1));
265}
266
267void
268CcnxFib::InvalidateAll ()
269{
270 NS_LOG_FUNCTION (this->GetObject<Node> ()->GetId ());
271
272 for (CcnxFibEntryContainer::type::iterator entry = m_fib.begin ();
273 entry != m_fib.end ();
274 entry ++)
275 {
276 m_fib.modify (entry,
277 ll::bind (&CcnxFibEntry::Invalidate, ll::_1));
278 }
279}
280
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800281void
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800282CcnxFib::Remove (const CcnxFibEntry &entry, Ptr<CcnxFace> face)
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800283{
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800284 NS_LOG_FUNCTION (this);
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800285
Alexander Afanasyev07827182011-12-13 01:07:32 -0800286 m_fib.modify (m_fib.iterator_to (entry),
287 ll::bind (&CcnxFibEntry::RemoveFace, ll::_1, face));
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800288 if (entry.m_faces.size () == 0)
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800289 {
Alexander Afanasyev07827182011-12-13 01:07:32 -0800290 m_fib.erase (m_fib.iterator_to (entry));
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800291 }
292}
293
294void
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800295CcnxFib::RemoveFromAll (Ptr<CcnxFace> face)
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800296{
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800297 NS_LOG_FUNCTION (this);
298
Alexander Afanasyev07827182011-12-13 01:07:32 -0800299 for_each (m_fib.begin (), m_fib.end (),
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700300 ll::bind (static_cast< void (CcnxFib::*) (const CcnxFibEntry &, Ptr<CcnxFace>) > (&CcnxFib::Remove),
301 this, ll::_1, face));
Alexander Afanasyev07827182011-12-13 01:07:32 -0800302}
303
304/**
305 * \brief Get number of FIB entry (for python bindings)
306 */
307uint32_t
308CcnxFib::GetCcnxFibEntryCount () const
309{
310 return m_fib.size ();
311}
312
313/**
314 * \brief Get FIB entry by index (for python bindings)
315 */
316const CcnxFibEntry &
317CcnxFib::GetCcnxFibEntry (uint32_t index)
318{
319 NS_ASSERT (0 <= index && index < m_fib.size ());
320 return m_fib.get <i_nth> () [index];
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800321}
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700322
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800323
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700324std::ostream& operator<< (std::ostream& os, const CcnxFib &fib)
325{
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700326 os << "Node " << Names::FindName (fib.m_node) << "\n";
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700327 os << " Dest prefix Interfaces(Costs) \n";
328 os << "+-------------+--------------------------------------+\n";
329
Alexander Afanasyev07827182011-12-13 01:07:32 -0800330 for (CcnxFibEntryContainer::type::iterator entry = fib.m_fib.begin ();
331 entry != fib.m_fib.end ();
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700332 entry++)
333 {
Alexander Afanasyev07827182011-12-13 01:07:32 -0800334 os << entry->GetPrefix () << "\t" << *entry << "\n";
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700335 }
336 return os;
337}
338
339std::ostream& operator<< (std::ostream& os, const CcnxFibEntry &entry)
340{
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700341 for (CcnxFibFaceMetricContainer::type::index<i_nth>::type::iterator metric =
342 entry.m_faces.get<i_nth> ().begin ();
343 metric != entry.m_faces.get<i_nth> ().end ();
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700344 metric++)
345 {
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700346 if (metric != entry.m_faces.get<i_nth> ().begin ())
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700347 os << ", ";
348
349 os << *metric;
350 }
351 return os;
352}
353
354std::ostream& operator<< (std::ostream& os, const CcnxFibFaceMetric &metric)
355{
356 static const std::string statusString[] = {"","g","y","r"};
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700357
Alexander Afanasyev3661e232012-01-20 17:36:15 -0800358 os << *metric.m_face << "(" << metric.m_routingCost << ","<< statusString [metric.m_status] << "," << metric.m_face->GetMetric () << ")";
Alexander Afanasyev7fd74f92011-08-25 19:40:17 -0700359 return os;
360}
361
362// void CcnxFib::resetProbing()
363// {
364// for(FibRangeIterator fib = _fib.begin(); fib != _fib.end(); fib++)
365// VALUE(fib).needsProbing = true;
366// }
367
368// void CcnxFib::updateInterfaceStatus( int interface, int status )
369// {
370// for( FibRangeIterator fib = _fib.begin(); fib!=_fib.end(); fib++ )
371// {
372// VALUE(fib).updateStatus( interface, status );
373// }
374// }
375
376} // namespace ns3