blob: c0c575ab46e70c4ecc0bd51ae670a938af7dc6d8 [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
21#include "ccnx-fib-entry.h"
22
23#include "ns3/ccnx-name-components.h"
24#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
35NS_LOG_COMPONENT_DEFINE ("CcnxFibEntry");
36
37namespace ns3
38{
39
40//////////////////////////////////////////////////////////////////////
41// Helpers
42//////////////////////////////////////////////////////////////////////
43namespace __ccnx_private {
44
45struct CcnxFibFaceMetricByFace
46{
47 typedef CcnxFibFaceMetricContainer::type::index<i_face>::type
48 type;
49};
50
51}
52//////////////////////////////////////////////////////////////////////
53//////////////////////////////////////////////////////////////////////
54
55using namespace __ccnx_private;
56
57void
58CcnxFibFaceMetric::UpdateRtt (const Time &rttSample)
59{
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
81CcnxFibEntry::UpdateFaceRtt (Ptr<CcnxFace> face, const Time &sample)
82{
83 CcnxFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
84 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,
88 ll::bind (&CcnxFibFaceMetric::UpdateRtt, ll::_1, sample));
89
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
95CcnxFibEntry::UpdateStatus (Ptr<CcnxFace> face, CcnxFibFaceMetric::Status status)
96{
97 NS_LOG_FUNCTION (this << boost::cref(*face) << status);
98
99 CcnxFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
100 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,
104 (&ll::_1)->*&CcnxFibFaceMetric::m_status = status);
105
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
111CcnxFibEntry::AddOrUpdateRoutingMetric (Ptr<CcnxFace> face, int32_t metric)
112{
113 NS_LOG_FUNCTION (this);
114 NS_ASSERT_MSG (face != NULL, "Trying to Add or Update NULL face");
115
116 CcnxFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
117 if (record == m_faces.get<i_face> ().end ())
118 {
119 m_faces.insert (CcnxFibFaceMetric (face, metric));
120 }
121 else
122 {
123 // don't update metric to higher value
124 if (record->m_routingCost > metric || record->m_status == CcnxFibFaceMetric::NDN_FIB_RED)
125 {
126 m_faces.modify (record,
127 (&ll::_1)->*&CcnxFibFaceMetric::m_routingCost = metric);
128
129 m_faces.modify (record,
130 (&ll::_1)->*&CcnxFibFaceMetric::m_status = CcnxFibFaceMetric::NDN_FIB_YELLOW);
131 }
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
139CcnxFibEntry::Invalidate ()
140{
141 for (CcnxFibFaceMetricByFace::type::iterator face = m_faces.begin ();
142 face != m_faces.end ();
143 face++)
144 {
145 m_faces.modify (face,
146 (&ll::_1)->*&CcnxFibFaceMetric::m_routingCost = std::numeric_limits<uint16_t>::max ());
147
148 m_faces.modify (face,
149 (&ll::_1)->*&CcnxFibFaceMetric::m_status = CcnxFibFaceMetric::NDN_FIB_RED);
150 }
151}
152
153const CcnxFibFaceMetric &
154CcnxFibEntry::FindBestCandidate (uint32_t skip/* = 0*/) const
155{
156 if (m_faces.size () == 0) throw CcnxFibEntry::NoFaces ();
157 skip = skip % m_faces.size();
158 return m_faces.get<i_nth> () [skip];
159}
160
161std::ostream& operator<< (std::ostream& os, const CcnxFibEntry &entry)
162{
163 for (CcnxFibFaceMetricContainer::type::index<i_nth>::type::iterator metric =
164 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
176std::ostream& operator<< (std::ostream& os, const CcnxFibFaceMetric &metric)
177{
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