blob: 01e2970bcd5ec66ce62fac6639f213ce6402b5cc [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 Afanasyev2b4c9472012-08-09 15:00:38 -070035NS_LOG_COMPONENT_DEFINE ("ndn.fib.Entry");
Alexander Afanasyev78057c32012-07-06 15:18:46 -070036
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070037namespace ns3 {
38namespace ndn {
39namespace fib {
Alexander Afanasyev78057c32012-07-06 15:18:46 -070040
41//////////////////////////////////////////////////////////////////////
42// Helpers
43//////////////////////////////////////////////////////////////////////
Alexander Afanasyev78057c32012-07-06 15:18:46 -070044
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070045struct FaceMetricByFace
Alexander Afanasyev78057c32012-07-06 15:18:46 -070046{
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070047 typedef FaceMetricContainer::type::index<i_face>::type
Alexander Afanasyev78057c32012-07-06 15:18:46 -070048 type;
49};
50
Alexander Afanasyev78057c32012-07-06 15:18:46 -070051
52void
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070053FaceMetric::UpdateRtt (const Time &rttSample)
Alexander Afanasyev78057c32012-07-06 15:18:46 -070054{
55 // const Time & this->m_rttSample
56
57 //update srtt and rttvar (RFC 2988)
58 if (m_sRtt.IsZero ())
59 {
60 //first RTT measurement
61 NS_ASSERT_MSG (m_rttVar.IsZero (), "SRTT is zero, but variation is not");
62
63 m_sRtt = rttSample;
64 m_rttVar = Time (m_sRtt / 2.0);
65 }
66 else
67 {
68 m_rttVar = Time ((1 - NDN_RTO_BETA) * m_rttVar + NDN_RTO_BETA * Abs(m_sRtt - rttSample));
69 m_sRtt = Time ((1 - NDN_RTO_ALPHA) * m_sRtt + NDN_RTO_ALPHA * rttSample);
70 }
71}
72
73/////////////////////////////////////////////////////////////////////
74
75void
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070076Entry::UpdateFaceRtt (Ptr<Face> face, const Time &sample)
Alexander Afanasyev78057c32012-07-06 15:18:46 -070077{
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070078 FaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
Alexander Afanasyev78057c32012-07-06 15:18:46 -070079 NS_ASSERT_MSG (record != m_faces.get<i_face> ().end (),
80 "Update status can be performed only on existing faces of CcxnFibEntry");
81
82 m_faces.modify (record,
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070083 ll::bind (&FaceMetric::UpdateRtt, ll::_1, sample));
Alexander Afanasyev78057c32012-07-06 15:18:46 -070084
85 // reordering random access index same way as by metric index
86 m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
87}
88
89void
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070090Entry::UpdateStatus (Ptr<Face> face, FaceMetric::Status status)
Alexander Afanasyev78057c32012-07-06 15:18:46 -070091{
92 NS_LOG_FUNCTION (this << boost::cref(*face) << status);
93
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070094 FaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
Alexander Afanasyev78057c32012-07-06 15:18:46 -070095 NS_ASSERT_MSG (record != m_faces.get<i_face> ().end (),
96 "Update status can be performed only on existing faces of CcxnFibEntry");
97
98 m_faces.modify (record,
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070099 (&ll::_1)->*&FaceMetric::m_status = status);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700100
101 // reordering random access index same way as by metric index
102 m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
103}
104
105void
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700106Entry::AddOrUpdateRoutingMetric (Ptr<Face> face, int32_t metric)
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700107{
108 NS_LOG_FUNCTION (this);
109 NS_ASSERT_MSG (face != NULL, "Trying to Add or Update NULL face");
110
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700111 FaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700112 if (record == m_faces.get<i_face> ().end ())
113 {
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700114 m_faces.insert (FaceMetric (face, metric));
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700115 }
116 else
117 {
118 // don't update metric to higher value
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700119 if (record->m_routingCost > metric || record->m_status == FaceMetric::NDN_FIB_RED)
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700120 {
121 m_faces.modify (record,
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700122 (&ll::_1)->*&FaceMetric::m_routingCost = metric);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700123
124 m_faces.modify (record,
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700125 (&ll::_1)->*&FaceMetric::m_status = FaceMetric::NDN_FIB_YELLOW);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700126 }
127 }
128
129 // reordering random access index same way as by metric index
130 m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
131}
132
133void
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700134Entry::Invalidate ()
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700135{
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700136 for (FaceMetricByFace::type::iterator face = m_faces.begin ();
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700137 face != m_faces.end ();
138 face++)
139 {
140 m_faces.modify (face,
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700141 (&ll::_1)->*&FaceMetric::m_routingCost = std::numeric_limits<uint16_t>::max ());
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700142
143 m_faces.modify (face,
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700144 (&ll::_1)->*&FaceMetric::m_status = FaceMetric::NDN_FIB_RED);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700145 }
146}
147
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700148const FaceMetric &
149Entry::FindBestCandidate (uint32_t skip/* = 0*/) const
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700150{
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700151 if (m_faces.size () == 0) throw Entry::NoFaces ();
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700152 skip = skip % m_faces.size();
153 return m_faces.get<i_nth> () [skip];
154}
155
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700156std::ostream& operator<< (std::ostream& os, const Entry &entry)
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700157{
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700158 for (FaceMetricContainer::type::index<i_nth>::type::iterator metric =
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700159 entry.m_faces.get<i_nth> ().begin ();
160 metric != entry.m_faces.get<i_nth> ().end ();
161 metric++)
162 {
163 if (metric != entry.m_faces.get<i_nth> ().begin ())
164 os << ", ";
165
166 os << *metric;
167 }
168 return os;
169}
170
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700171std::ostream& operator<< (std::ostream& os, const FaceMetric &metric)
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700172{
173 static const std::string statusString[] = {"","g","y","r"};
174
175 os << *metric.m_face << "(" << metric.m_routingCost << ","<< statusString [metric.m_status] << "," << metric.m_face->GetMetric () << ")";
176 return os;
177}
178
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700179} // namespace fib
180} // namespace ndn
181} // namespace ns3