blob: 965886fb5c6804298eb457c55c4df2eab99b2aa7 [file] [log] [blame]
Alexander Afanasyev78057c32012-07-06 15:18:46 -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
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070021#include "ndn-fib-entry.h"
Alexander Afanasyev78057c32012-07-06 15:18:46 -070022
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070023#include "ns3/ndn-name-components.h"
Alexander Afanasyev78057c32012-07-06 15:18:46 -070024#include "ns3/log.h"
25
26#define NDN_RTO_ALPHA 0.125
27#define NDN_RTO_BETA 0.25
28#define NDN_RTO_K 4
29
30#include <boost/ref.hpp>
31#include <boost/lambda/lambda.hpp>
32#include <boost/lambda/bind.hpp>
33namespace ll = boost::lambda;
34
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070035NS_LOG_COMPONENT_DEFINE ("NdnFibEntry");
Alexander Afanasyev78057c32012-07-06 15:18:46 -070036
37namespace ns3
38{
39
40//////////////////////////////////////////////////////////////////////
41// Helpers
42//////////////////////////////////////////////////////////////////////
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070043namespace __ndn_private {
Alexander Afanasyev78057c32012-07-06 15:18:46 -070044
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070045struct NdnFibFaceMetricByFace
Alexander Afanasyev78057c32012-07-06 15:18:46 -070046{
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070047 typedef NdnFibFaceMetricContainer::type::index<i_face>::type
Alexander Afanasyev78057c32012-07-06 15:18:46 -070048 type;
49};
50
51}
52//////////////////////////////////////////////////////////////////////
53//////////////////////////////////////////////////////////////////////
54
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070055using namespace __ndn_private;
Alexander Afanasyev78057c32012-07-06 15:18:46 -070056
57void
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070058NdnFibFaceMetric::UpdateRtt (const Time &rttSample)
Alexander Afanasyev78057c32012-07-06 15:18:46 -070059{
60 // const Time & this->m_rttSample
61
62 //update srtt and rttvar (RFC 2988)
63 if (m_sRtt.IsZero ())
64 {
65 //first RTT measurement
66 NS_ASSERT_MSG (m_rttVar.IsZero (), "SRTT is zero, but variation is not");
67
68 m_sRtt = rttSample;
69 m_rttVar = Time (m_sRtt / 2.0);
70 }
71 else
72 {
73 m_rttVar = Time ((1 - NDN_RTO_BETA) * m_rttVar + NDN_RTO_BETA * Abs(m_sRtt - rttSample));
74 m_sRtt = Time ((1 - NDN_RTO_ALPHA) * m_sRtt + NDN_RTO_ALPHA * rttSample);
75 }
76}
77
78/////////////////////////////////////////////////////////////////////
79
80void
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070081NdnFibEntry::UpdateFaceRtt (Ptr<NdnFace> face, const Time &sample)
Alexander Afanasyev78057c32012-07-06 15:18:46 -070082{
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070083 NdnFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
Alexander Afanasyev78057c32012-07-06 15:18:46 -070084 NS_ASSERT_MSG (record != m_faces.get<i_face> ().end (),
85 "Update status can be performed only on existing faces of CcxnFibEntry");
86
87 m_faces.modify (record,
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070088 ll::bind (&NdnFibFaceMetric::UpdateRtt, ll::_1, sample));
Alexander Afanasyev78057c32012-07-06 15:18:46 -070089
90 // reordering random access index same way as by metric index
91 m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
92}
93
94void
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070095NdnFibEntry::UpdateStatus (Ptr<NdnFace> face, NdnFibFaceMetric::Status status)
Alexander Afanasyev78057c32012-07-06 15:18:46 -070096{
97 NS_LOG_FUNCTION (this << boost::cref(*face) << status);
98
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070099 NdnFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700100 NS_ASSERT_MSG (record != m_faces.get<i_face> ().end (),
101 "Update status can be performed only on existing faces of CcxnFibEntry");
102
103 m_faces.modify (record,
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700104 (&ll::_1)->*&NdnFibFaceMetric::m_status = status);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700105
106 // reordering random access index same way as by metric index
107 m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
108}
109
110void
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700111NdnFibEntry::AddOrUpdateRoutingMetric (Ptr<NdnFace> face, int32_t metric)
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700112{
113 NS_LOG_FUNCTION (this);
114 NS_ASSERT_MSG (face != NULL, "Trying to Add or Update NULL face");
115
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700116 NdnFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700117 if (record == m_faces.get<i_face> ().end ())
118 {
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700119 m_faces.insert (NdnFibFaceMetric (face, metric));
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700120 }
121 else
122 {
123 // don't update metric to higher value
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700124 if (record->m_routingCost > metric || record->m_status == NdnFibFaceMetric::NDN_FIB_RED)
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700125 {
126 m_faces.modify (record,
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700127 (&ll::_1)->*&NdnFibFaceMetric::m_routingCost = metric);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700128
129 m_faces.modify (record,
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700130 (&ll::_1)->*&NdnFibFaceMetric::m_status = NdnFibFaceMetric::NDN_FIB_YELLOW);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700131 }
132 }
133
134 // reordering random access index same way as by metric index
135 m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
136}
137
138void
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700139NdnFibEntry::Invalidate ()
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700140{
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700141 for (NdnFibFaceMetricByFace::type::iterator face = m_faces.begin ();
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700142 face != m_faces.end ();
143 face++)
144 {
145 m_faces.modify (face,
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700146 (&ll::_1)->*&NdnFibFaceMetric::m_routingCost = std::numeric_limits<uint16_t>::max ());
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700147
148 m_faces.modify (face,
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700149 (&ll::_1)->*&NdnFibFaceMetric::m_status = NdnFibFaceMetric::NDN_FIB_RED);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700150 }
151}
152
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700153const NdnFibFaceMetric &
154NdnFibEntry::FindBestCandidate (uint32_t skip/* = 0*/) const
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700155{
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700156 if (m_faces.size () == 0) throw NdnFibEntry::NoFaces ();
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700157 skip = skip % m_faces.size();
158 return m_faces.get<i_nth> () [skip];
159}
160
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700161std::ostream& operator<< (std::ostream& os, const NdnFibEntry &entry)
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700162{
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700163 for (NdnFibFaceMetricContainer::type::index<i_nth>::type::iterator metric =
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700164 entry.m_faces.get<i_nth> ().begin ();
165 metric != entry.m_faces.get<i_nth> ().end ();
166 metric++)
167 {
168 if (metric != entry.m_faces.get<i_nth> ().begin ())
169 os << ", ";
170
171 os << *metric;
172 }
173 return os;
174}
175
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700176std::ostream& operator<< (std::ostream& os, const NdnFibFaceMetric &metric)
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700177{
178 static const std::string statusString[] = {"","g","y","r"};
179
180 os << *metric.m_face << "(" << metric.m_routingCost << ","<< statusString [metric.m_status] << "," << metric.m_face->GetMetric () << ")";
181 return os;
182}
183
184
185} // ns3