blob: 4d39beaba1c14f53e9d53a1bc427852396e2202e [file] [log] [blame]
Alexander Afanasyev60a7b622014-12-20 17:04:07 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2011-2015 Regents of the University of California.
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -07004 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -08005 * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
6 * contributors.
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -07007 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -08008 * ndnSIM is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070011 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -080012 * ndnSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070015 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -080016 * You should have received a copy of the GNU General Public License along with
17 * ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 **/
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070019
Alexander Afanasyev0c395372014-12-20 15:54:02 -080020#include "ndn-consumer.hpp"
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -070021#include "ns3/ptr.h"
Alexander Afanasyev19426ef2011-11-23 20:55:28 -080022#include "ns3/log.h"
23#include "ns3/simulator.h"
24#include "ns3/packet.h"
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -070025#include "ns3/callback.h"
Alexander Afanasyeva46844b2011-11-21 19:13:26 -080026#include "ns3/string.h"
Alexander Afanasyev19426ef2011-11-23 20:55:28 -080027#include "ns3/boolean.h"
28#include "ns3/uinteger.h"
Alexander Afanasyeva89bc102013-07-16 10:17:31 -070029#include "ns3/integer.h"
Alexander Afanasyevb3e4b852011-12-23 15:58:20 -080030#include "ns3/double.h"
Alexander Afanasyev19426ef2011-11-23 20:55:28 -080031
Mickey Sweatt89046c12014-11-16 20:32:27 -080032#include "utils/ndn-ns3-packet-tag.hpp"
33#include "model/ndn-app-face.hpp"
34#include "utils/ndn-rtt-mean-deviation.hpp"
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070035
Mickey Sweatt89046c12014-11-16 20:32:27 -080036#include <boost/lexical_cast.hpp>
Alexander Afanasyev19426ef2011-11-23 20:55:28 -080037#include <boost/ref.hpp>
Alexander Afanasyev781ea812011-12-15 22:42:09 -080038
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080039NS_LOG_COMPONENT_DEFINE("ndn.Consumer");
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070040
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070041namespace ns3 {
42namespace ndn {
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -080043
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080044NS_OBJECT_ENSURE_REGISTERED(Consumer);
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -080045
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070046TypeId
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080047Consumer::GetTypeId(void)
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070048{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080049 static TypeId tid =
50 TypeId("ns3::ndn::Consumer")
51 .SetGroupName("Ndn")
52 .SetParent<App>()
53 .AddAttribute("StartSeq", "Initial sequence number", IntegerValue(0),
54 MakeIntegerAccessor(&Consumer::m_seq), MakeIntegerChecker<int32_t>())
Alexander Afanasyev011b8592011-12-21 14:45:27 -080055
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080056 .AddAttribute("Prefix", "Name of the Interest", StringValue("/"),
57 MakeNameAccessor(&Consumer::m_interestName), MakeNameChecker())
58 .AddAttribute("LifeTime", "LifeTime for interest packet", StringValue("2s"),
59 MakeTimeAccessor(&Consumer::m_interestLifeTime), MakeTimeChecker())
Alexander Afanasyev781ea812011-12-15 22:42:09 -080060
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080061 .AddAttribute("RetxTimer",
62 "Timeout defining how frequent retransmission timeouts should be checked",
63 StringValue("50ms"),
64 MakeTimeAccessor(&Consumer::GetRetxTimer, &Consumer::SetRetxTimer),
65 MakeTimeChecker())
Alexander Afanasyev781ea812011-12-15 22:42:09 -080066
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080067 .AddTraceSource("LastRetransmittedInterestDataDelay",
68 "Delay between last retransmitted Interest and received Data",
Alexander Afanasyevd6453cd2015-08-20 21:45:36 -070069 MakeTraceSourceAccessor(&Consumer::m_lastRetransmittedInterestDataDelay),
70 "ns3::ndn::Consumer::LastRetransmittedInterestDataDelayCallback")
Alexander Afanasyevedf24d92013-01-18 13:35:06 -080071
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080072 .AddTraceSource("FirstInterestDataDelay",
73 "Delay between first transmitted Interest and received Data",
Alexander Afanasyevd6453cd2015-08-20 21:45:36 -070074 MakeTraceSourceAccessor(&Consumer::m_firstInterestDataDelay),
75 "ns3::ndn::Consumer::FirstInterestDataDelayCallback");
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070076
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -080077 return tid;
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070078}
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -080079
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080080Consumer::Consumer()
Alexander Afanasyevd6453cd2015-08-20 21:45:36 -070081 : m_rand(CreateObject<UniformRandomVariable>())
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080082 , m_seq(0)
83 , m_seqMax(0) // don't request anything
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070084{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080085 NS_LOG_FUNCTION_NOARGS();
Alexander Afanasyev011b8592011-12-21 14:45:27 -080086
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080087 m_rtt = CreateObject<RttMeanDeviation>();
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -070088}
Alexander Afanasyev781ea812011-12-15 22:42:09 -080089
90void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080091Consumer::SetRetxTimer(Time retxTimer)
Alexander Afanasyev781ea812011-12-15 22:42:09 -080092{
93 m_retxTimer = retxTimer;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080094 if (m_retxEvent.IsRunning()) {
95 // m_retxEvent.Cancel (); // cancel any scheduled cleanup events
96 Simulator::Remove(m_retxEvent); // slower, but better for memory
97 }
Alexander Afanasyev781ea812011-12-15 22:42:09 -080098
99 // schedule even with new timeout
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800100 m_retxEvent = Simulator::Schedule(m_retxTimer, &Consumer::CheckRetxTimeout, this);
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800101}
102
103Time
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800104Consumer::GetRetxTimer() const
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800105{
106 return m_retxTimer;
107}
108
109void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800110Consumer::CheckRetxTimeout()
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800111{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800112 Time now = Simulator::Now();
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800113
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800114 Time rto = m_rtt->RetransmitTimeout();
Alexander Afanasyev8a237522013-02-01 13:33:38 -0800115 // NS_LOG_DEBUG ("Current RTO: " << rto.ToDouble (Time::S) << "s");
Alexander Afanasyevbdc0d982011-12-16 01:15:26 -0800116
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800117 while (!m_seqTimeouts.empty()) {
118 SeqTimeoutsContainer::index<i_timestamp>::type::iterator entry =
119 m_seqTimeouts.get<i_timestamp>().begin();
120 if (entry->time + rto <= now) // timeout expired?
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800121 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800122 uint32_t seqNo = entry->seq;
123 m_seqTimeouts.get<i_timestamp>().erase(entry);
124 OnTimeout(seqNo);
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800125 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800126 else
127 break; // nothing else to do. All later packets need not be retransmitted
128 }
Alexander Afanasyev3183b5a2011-12-23 20:48:20 -0800129
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800130 m_retxEvent = Simulator::Schedule(m_retxTimer, &Consumer::CheckRetxTimeout, this);
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800131}
132
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -0700133// Application Methods
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -0800134void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800135Consumer::StartApplication() // Called at time specified by Start
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -0700136{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800137 NS_LOG_FUNCTION_NOARGS();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700138
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800139 // do base stuff
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800140 App::StartApplication();
Alexander Afanasyev011b8592011-12-21 14:45:27 -0800141
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800142 ScheduleNextPacket();
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -0700143}
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -0800144
145void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800146Consumer::StopApplication() // Called at time specified by Stop
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -0700147{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800148 NS_LOG_FUNCTION_NOARGS();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700149
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800150 // cancel periodic packet generation
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800151 Simulator::Cancel(m_sendEvent);
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700152
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800153 // cleanup base stuff
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800154 App::StopApplication();
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -0700155}
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -0800156
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -0700157void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800158Consumer::SendPacket()
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -0700159{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800160 if (!m_active)
161 return;
Alexander Afanasyev3183b5a2011-12-23 20:48:20 -0800162
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800163 NS_LOG_FUNCTION_NOARGS();
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800164
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800165 uint32_t seq = std::numeric_limits<uint32_t>::max(); // invalid
Alexander Afanasyev1ec705f2012-01-23 12:35:10 -0800166
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800167 while (m_retxSeqs.size()) {
168 seq = *m_retxSeqs.begin();
169 m_retxSeqs.erase(m_retxSeqs.begin());
170 break;
171 }
172
173 if (seq == std::numeric_limits<uint32_t>::max()) {
174 if (m_seqMax != std::numeric_limits<uint32_t>::max()) {
175 if (m_seq >= m_seqMax) {
176 return; // we are totally done
177 }
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800178 }
Alexander Afanasyev1ec705f2012-01-23 12:35:10 -0800179
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800180 seq = m_seq++;
181 }
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -0800182
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800183 //
Spyridon Mastorakis53e922f2014-10-17 17:29:26 -0700184 shared_ptr<Name> nameWithSequence = make_shared<Name>(m_interestName);
Mickey Sweatt89046c12014-11-16 20:32:27 -0800185 nameWithSequence->appendSequenceNumber(seq);
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800186 //
187
Mickey Sweatt89046c12014-11-16 20:32:27 -0800188 // shared_ptr<Interest> interest = make_shared<Interest> ();
Spyridon Mastorakis53e922f2014-10-17 17:29:26 -0700189 shared_ptr<Interest> interest = make_shared<Interest>();
Alexander Afanasyevd6453cd2015-08-20 21:45:36 -0700190 interest->setNonce(m_rand->GetValue(0, std::numeric_limits<uint32_t>::max()));
Mickey Sweatt89046c12014-11-16 20:32:27 -0800191 interest->setName(*nameWithSequence);
192 time::milliseconds interestLifeTime(m_interestLifeTime.GetMilliSeconds());
193 interest->setInterestLifetime(interestLifeTime);
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -0800194
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700195 // NS_LOG_INFO ("Requesting Interest: \n" << *interest);
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800196 NS_LOG_INFO("> Interest for " << seq);
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700197
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800198 WillSendOutInterest(seq);
Alexander Afanasyeve1aa9b92012-10-11 10:40:02 -0700199
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800200 m_transmittedInterests(interest, this, m_face);
Mickey Sweatt89046c12014-11-16 20:32:27 -0800201 m_face->onReceiveInterest(*interest);
Alexander Afanasyeve1aa9b92012-10-11 10:40:02 -0700202
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800203 ScheduleNextPacket();
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -0700204}
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700205
Alexander Afanasyev011b8592011-12-21 14:45:27 -0800206///////////////////////////////////////////////////
207// Process incoming packets //
208///////////////////////////////////////////////////
209
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -0700210void
Spyridon Mastorakis53e922f2014-10-17 17:29:26 -0700211Consumer::OnData(shared_ptr<const Data> data)
Ilya Moiseenko8196d2e2011-08-29 13:03:22 -0700212{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800213 if (!m_active)
214 return;
Alexander Afanasyev3183b5a2011-12-23 20:48:20 -0800215
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800216 App::OnData(data); // tracing inside
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -0800217
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800218 NS_LOG_FUNCTION(this << data);
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800219
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700220 // NS_LOG_INFO ("Received content object: " << boost::cref(*data));
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -0800221
Mickey Sweatt89046c12014-11-16 20:32:27 -0800222 // This could be a problem......
223 uint32_t seq = data->getName().at(-1).toSequenceNumber();
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800224 NS_LOG_INFO("< DATA for " << seq);
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800225
Alexander Afanasyev18d8bc92015-08-13 18:26:40 -0700226 int hopCount = 0;
Mickey Sweatt89046c12014-11-16 20:32:27 -0800227 auto ns3PacketTag = data->getTag<Ns3PacketTag>();
Alexander Afanasyev18d8bc92015-08-13 18:26:40 -0700228 if (ns3PacketTag != nullptr) { // e.g., packet came from local node's cache
Mickey Sweatt89046c12014-11-16 20:32:27 -0800229 FwHopCountTag hopCountTag;
230 if (ns3PacketTag->getPacket()->PeekPacketTag(hopCountTag)) {
231 hopCount = hopCountTag.Get();
232 NS_LOG_DEBUG("Hop count: " << hopCount);
233 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800234 }
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -0800235
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800236 SeqTimeoutsContainer::iterator entry = m_seqLastDelay.find(seq);
237 if (entry != m_seqLastDelay.end()) {
238 m_lastRetransmittedInterestDataDelay(this, seq, Simulator::Now() - entry->time, hopCount);
239 }
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800240
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800241 entry = m_seqFullDelay.find(seq);
242 if (entry != m_seqFullDelay.end()) {
Mickey Sweatt89046c12014-11-16 20:32:27 -0800243 m_firstInterestDataDelay(this, seq, Simulator::Now() - entry->time, m_seqRetxCounts[seq], hopCount);
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800244 }
Alexander Afanasyev400aae12013-01-19 13:27:52 -0800245
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800246 m_seqRetxCounts.erase(seq);
247 m_seqFullDelay.erase(seq);
248 m_seqLastDelay.erase(seq);
Alexander Afanasyev3a3ce1a2013-01-31 11:26:11 -0800249
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800250 m_seqTimeouts.erase(seq);
251 m_retxSeqs.erase(seq);
Alexander Afanasyev359bfb72012-01-09 18:42:50 -0800252
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800253 m_rtt->AckSeq(SequenceNumber32(seq));
Alexander Afanasyev781ea812011-12-15 22:42:09 -0800254}
255
256void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800257Consumer::OnTimeout(uint32_t sequenceNumber)
Alexander Afanasyev359bfb72012-01-09 18:42:50 -0800258{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800259 NS_LOG_FUNCTION(sequenceNumber);
260 // std::cout << Simulator::Now () << ", TO: " << sequenceNumber << ", current RTO: " <<
261 // m_rtt->RetransmitTimeout ().ToDouble (Time::S) << "s\n";
Alexander Afanasyevb7ad2322012-01-17 22:54:49 -0800262
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800263 m_rtt->IncreaseMultiplier(); // Double the next RTO
264 m_rtt->SentSeq(SequenceNumber32(sequenceNumber),
265 1); // make sure to disable RTT calculation for this sample
266 m_retxSeqs.insert(sequenceNumber);
267 ScheduleNextPacket();
Alexander Afanasyev359bfb72012-01-09 18:42:50 -0800268}
269
Alexander Afanasyev79b2fb32013-04-12 11:24:55 -0700270void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800271Consumer::WillSendOutInterest(uint32_t sequenceNumber)
Alexander Afanasyev79b2fb32013-04-12 11:24:55 -0700272{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800273 NS_LOG_DEBUG("Trying to add " << sequenceNumber << " with " << Simulator::Now() << ". already "
274 << m_seqTimeouts.size() << " items");
Alexander Afanasyev79b2fb32013-04-12 11:24:55 -0700275
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800276 m_seqTimeouts.insert(SeqTimeout(sequenceNumber, Simulator::Now()));
277 m_seqFullDelay.insert(SeqTimeout(sequenceNumber, Simulator::Now()));
Alexander Afanasyev79b2fb32013-04-12 11:24:55 -0700278
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800279 m_seqLastDelay.erase(sequenceNumber);
280 m_seqLastDelay.insert(SeqTimeout(sequenceNumber, Simulator::Now()));
Alexander Afanasyev79b2fb32013-04-12 11:24:55 -0700281
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800282 m_seqRetxCounts[sequenceNumber]++;
Alexander Afanasyev79b2fb32013-04-12 11:24:55 -0700283
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800284 m_rtt->SentSeq(SequenceNumber32(sequenceNumber), 1);
Alexander Afanasyev79b2fb32013-04-12 11:24:55 -0700285}
286
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700287} // namespace ndn
Alexander Afanasyev09c7deb2011-11-23 14:50:10 -0800288} // namespace ns3