blob: 4b832a4e5687ea50f00014090cf78e913b849f8e [file] [log] [blame]
Alexander Afanasyevc74a6022011-08-15 20:01:35 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Alexander Afanasyevab1d5602011-08-17 19:17:18 -07002/*
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>
Ilya Moiseenko172763c2011-10-28 13:21:53 -070019 * Ilya Moiseenko <iliamo@cs.ucla.edu>
Alexander Afanasyevab1d5602011-08-17 19:17:18 -070020 */
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070021
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070022#include "ccnx-l3-protocol.h"
23
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070024#include "ns3/packet.h"
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070025#include "ns3/node.h"
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070026#include "ns3/log.h"
27#include "ns3/callback.h"
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070028#include "ns3/uinteger.h"
29#include "ns3/trace-source-accessor.h"
30#include "ns3/object-vector.h"
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070031#include "ns3/boolean.h"
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070032
Alexander Afanasyevc74a6022011-08-15 20:01:35 -070033#include "ns3/ccnx-header-helper.h"
34
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070035#include "ccnx-face.h"
36#include "ccnx-route.h"
Alexander Afanasyevc74a6022011-08-15 20:01:35 -070037#include "ccnx-forwarding-strategy.h"
38#include "ccnx-interest-header.h"
39#include "ccnx-content-object-header.h"
40
Alexander Afanasyev56f79ea2011-08-17 23:54:27 -070041#include <boost/foreach.hpp>
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070042
43NS_LOG_COMPONENT_DEFINE ("CcnxL3Protocol");
44
45namespace ns3 {
46
Alexander Afanasyev7112f482011-08-17 14:05:57 -070047const uint16_t CcnxL3Protocol::ETHERNET_FRAME_TYPE = 0x7777;
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070048
49NS_OBJECT_ENSURE_REGISTERED (CcnxL3Protocol);
50
51TypeId
52CcnxL3Protocol::GetTypeId (void)
53{
54 static TypeId tid = TypeId ("ns3::CcnxL3Protocol")
55 .SetParent<Ccnx> ()
Alexander Afanasyev070aa482011-08-20 00:38:25 -070056 .SetGroupName ("Ccnx")
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070057 .AddConstructor<CcnxL3Protocol> ()
Alexander Afanasyev7112f482011-08-17 14:05:57 -070058 // .AddTraceSource ("Tx", "Send ccnx packet to outgoing interface.",
59 // MakeTraceSourceAccessor (&CcnxL3Protocol::m_txTrace))
60 // .AddTraceSource ("Rx", "Receive ccnx packet from incoming interface.",
61 // MakeTraceSourceAccessor (&CcnxL3Protocol::m_rxTrace))
62 // .AddTraceSource ("Drop", "Drop ccnx packet",
63 // MakeTraceSourceAccessor (&CcnxL3Protocol::m_dropTrace))
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -070064 // .AddAttribute ("InterfaceList", "The set of Ccnx interfaces associated to this Ccnx stack.",
65 // ObjectVectorValue (),
66 // MakeObjectVectorAccessor (&CcnxL3Protocol::m_faces),
67 // MakeObjectVectorChecker<CcnxFace> ())
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070068
Alexander Afanasyev7112f482011-08-17 14:05:57 -070069 // .AddTraceSource ("SendOutgoing", "A newly-generated packet by this node is about to be queued for transmission",
70 // MakeTraceSourceAccessor (&CcnxL3Protocol::m_sendOutgoingTrace))
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070071
72 ;
73 return tid;
74}
75
76CcnxL3Protocol::CcnxL3Protocol()
Alexander Afanasyevab1d5602011-08-17 19:17:18 -070077: m_faceCounter (0)
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070078{
79 NS_LOG_FUNCTION (this);
Alexander Afanasyevcf133f02011-09-06 12:13:48 -070080
81 m_rit = CreateObject<CcnxRit> ();
82 m_pit = CreateObject<CcnxPit> ();
83 m_contentStore = CreateObject<CcnxContentStore> ();
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070084}
85
86CcnxL3Protocol::~CcnxL3Protocol ()
87{
88 NS_LOG_FUNCTION (this);
89}
90
91void
92CcnxL3Protocol::SetNode (Ptr<Node> node)
93{
94 m_node = node;
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -070095 m_fib = m_node->GetObject<CcnxFib> ();
96 NS_ASSERT_MSG (m_fib != 0, "FIB should be created and aggregated to a node before calling Ccnx::SetNode");
97
98 m_pit->SetFib (m_fib);
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070099}
100
101/*
102 * This method is called by AddAgregate and completes the aggregation
103 * by setting the node in the ccnx stack
104 */
105void
106CcnxL3Protocol::NotifyNewAggregate ()
107{
108 if (m_node == 0)
109 {
110 Ptr<Node>node = this->GetObject<Node>();
111 // verify that it's a valid node and that
112 // the node has not been set before
113 if (node != 0)
114 {
115 this->SetNode (node);
116 }
117 }
118 Object::NotifyNewAggregate ();
119}
120
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700121void
122CcnxL3Protocol::DoDispose (void)
123{
124 NS_LOG_FUNCTION (this);
125
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700126 for (CcnxFaceList::iterator i = m_faces.begin (); i != m_faces.end (); ++i)
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700127 {
128 *i = 0;
129 }
Alexander Afanasyev98256102011-08-14 01:00:02 -0700130 m_faces.clear ();
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700131 m_node = 0;
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700132 // m_forwardingStrategy = 0;
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700133 Object::DoDispose ();
134}
135
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700136void
137CcnxL3Protocol::SetForwardingStrategy (Ptr<CcnxForwardingStrategy> forwardingStrategy)
138{
139 NS_LOG_FUNCTION (this);
140 m_forwardingStrategy = forwardingStrategy;
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700141 // m_forwardingStrategy->SetCcnx (this);
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700142}
143
144Ptr<CcnxForwardingStrategy>
145CcnxL3Protocol::GetForwardingStrategy (void) const
146{
147 return m_forwardingStrategy;
148}
149
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700150uint32_t
Alexander Afanasyev7112f482011-08-17 14:05:57 -0700151CcnxL3Protocol::AddFace (const Ptr<CcnxFace> &face)
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700152{
Alexander Afanasyev56f79ea2011-08-17 23:54:27 -0700153 NS_LOG_FUNCTION (this << &face);
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700154
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700155 face->SetNode (m_node);
Alexander Afanasyevab1d5602011-08-17 19:17:18 -0700156 face->SetId (m_faceCounter); // sets a unique ID of the face. This ID serves only informational purposes
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700157
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700158 // ask face to register in lower-layer stack
Alexander Afanasyev56f79ea2011-08-17 23:54:27 -0700159 face->RegisterProtocolHandler (MakeCallback (&CcnxL3Protocol::Receive, this));
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700160
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700161 m_faces.push_back (face);
Alexander Afanasyevab1d5602011-08-17 19:17:18 -0700162 m_faceCounter ++;
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700163 return face->GetId ();
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700164}
165
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700166void
167CcnxL3Protocol::RemoveFace (Ptr<CcnxFace> face)
168{
169 // ask face to register in lower-layer stack
170 face->RegisterProtocolHandler (MakeNullCallback<void,const Ptr<CcnxFace>&,const Ptr<const Packet>&> ());
171 CcnxFaceList::iterator face_it = find (m_faces.begin(), m_faces.end(), face);
172 NS_ASSERT_MSG (face_it != m_faces.end (), "Attempt to remove face that doesn't exist");
173 m_faces.erase (face_it);
174}
175
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700176Ptr<CcnxFace>
Alexander Afanasyev98256102011-08-14 01:00:02 -0700177CcnxL3Protocol::GetFace (uint32_t index) const
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700178{
Alexander Afanasyev56f79ea2011-08-17 23:54:27 -0700179 BOOST_FOREACH (const Ptr<CcnxFace> &face, m_faces) // this function is not supposed to be called often, so linear search is fine
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700180 {
Alexander Afanasyev56f79ea2011-08-17 23:54:27 -0700181 if (face->GetId () == index)
182 return face;
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700183 }
184 return 0;
185}
186
187uint32_t
Alexander Afanasyev98256102011-08-14 01:00:02 -0700188CcnxL3Protocol::GetNFaces (void) const
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700189{
Alexander Afanasyev98256102011-08-14 01:00:02 -0700190 return m_faces.size ();
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700191}
192
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700193void
194CcnxL3Protocol::TransmittedDataTrace (Ptr<Packet> packet,
195 ContentObjectSource type,
196 Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
197{
198 // a "small" inefficiency for logging purposes
199 Ptr<CcnxContentObjectHeader> header = Create<CcnxContentObjectHeader> ();
200 static CcnxContentObjectTail tail;
201 packet->RemoveHeader (*header);
202 packet->RemoveTrailer (tail);
203
204 m_transmittedDataTrace (header, packet/*payload*/, type, ccnx, face);
205
206 packet->AddHeader (*header);
207 packet->AddTrailer (tail);
208}
209
210
Alexander Afanasyev98256102011-08-14 01:00:02 -0700211// Callback from lower layer
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700212void
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700213CcnxL3Protocol::Receive (const Ptr<CcnxFace> &face, const Ptr<const Packet> &p)
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700214{
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700215 if (!face->IsUp ())
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700216 {
217 NS_LOG_LOGIC ("Dropping received packet -- interface is down");
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700218 // m_dropTrace (p, INTERFACE_DOWN, m_node->GetObject<Ccnx> ()/*this*/, face);
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700219 return;
220 }
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700221 NS_LOG_LOGIC ("Packet from face " << *face << " received on node " << m_node->GetId ());
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700222
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700223 Ptr<Packet> packet = p->Copy (); // give upper layers a rw copy of the packet
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700224 try
225 {
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700226 CcnxHeaderHelper::Type type = CcnxHeaderHelper::GetCcnxHeaderType (p);
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700227 switch (type)
228 {
229 case CcnxHeaderHelper::INTEREST:
230 {
231 Ptr<CcnxInterestHeader> header = Create<CcnxInterestHeader> ();
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700232
233 // Deserialization. Exception may be thrown
234 packet->RemoveHeader (*header);
235 NS_ASSERT_MSG (packet->GetSize () == 0, "Payload of Interests should be zero");
236
237 OnInterest (face, header, p/*original packet*/);
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700238 break;
239 }
240 case CcnxHeaderHelper::CONTENT_OBJECT:
241 {
242 Ptr<CcnxContentObjectHeader> header = Create<CcnxContentObjectHeader> ();
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700243
244 static CcnxContentObjectTail contentObjectTrailer; //there is no data in this object
245
246 // Deserialization. Exception may be thrown
247 packet->RemoveHeader (*header);
248 packet->RemoveTrailer (contentObjectTrailer);
249
250 OnData (face, header, packet/*payload*/, p/*original packet*/);
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700251 break;
252 }
253 }
254
255 // exception will be thrown if packet is not recognized
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700256 }
257 catch (CcnxUnknownHeaderException)
258 {
259 NS_ASSERT_MSG (false, "Unknown CCNx header. Should not happen");
260 }
Alexander Afanasyev98256102011-08-14 01:00:02 -0700261}
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700262
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700263// Processing Interests
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700264void CcnxL3Protocol::OnInterest (const Ptr<CcnxFace> &incomingFace,
265 Ptr<CcnxInterestHeader> &header,
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700266 const Ptr<const Packet> &packet)
Alexander Afanasyev98256102011-08-14 01:00:02 -0700267{
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700268 NS_LOG_LOGIC ("Receiving interest from " << &incomingFace);
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700269 m_receivedInterestsTrace (header, m_node->GetObject<Ccnx> (), incomingFace);
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700270
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700271 // Lookup of Pit and Fib entries for this Interest
272 CcnxFibEntryContainer::type::iterator fibEntry;
273 CcnxPitEntryContainer::type::iterator pitEntry = m_pit->Lookup (*header, fibEntry);
274
275 // No matter is it duplicate or not, if it is a NACK message, remove all possible incoming
276 // entries for this interface (NACK means that neighbor gave up trying and there is no
277 // point of sending data in this direction)
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700278 NS_LOG_INFO("Before (header->IsNack()) && (pitEntry != m_pit->end ())");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700279 if ((header->IsNack()) && (pitEntry != m_pit->end ()))
280 {
281 //m_pit->erase (pitEntry);
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700282 NS_LOG_INFO("TRUE");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700283 m_pit->modify(pitEntry, CcnxPitEntry::DeleteIncoming(incomingFace));
284 }
285
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700286 NS_LOG_INFO("Before WasRecentlySatisfied");
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700287 if (m_rit->WasRecentlySatisfied (*header))
288 {
289 return;
290 }
291 /*if (m_rit->WasRecentlySatisfied (*header))
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700292 {
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700293 NS_LOG_INFO("Entering WasRecentlySatisfied");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700294 // duplicate interests (same nonce) from applications are just ignored
295 if (incomingFace->IsLocal() == true)
296 return;
297
298 // Update metric status for the incoming interface in the corresponding FIB entry
299 if (fibEntry != m_fib->end())
300 m_fib->modify (m_fib->iterator_to (pitEntry->m_fibEntry),
301 CcnxFibEntry::UpdateStatus(incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
302
303 //Trace duplicate interest
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700304 m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST,
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700305 m_node->GetObject<Ccnx> (), incomingFace);
306
307 bool isMine = false;
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700308 //TypeId tid = TypeId ("ns3::CcnxProducer");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700309 for(uint32_t i=0; i<m_node->GetNApplications();i++)
310 {
311 Ptr<Application> app = m_node->GetApplication(i);
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700312 NS_LOG_INFO("ApplicationName = " << app->GetTypeId().GetName());
313 if(app->GetTypeId().GetName() == "ns3::CcnxProducer")
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700314 {
315 if((DynamicCast<CcnxProducer>(app))->GetPrefix () == header->GetName ())
316 {
317 isMine = true;
318 break;
319 }
320 }
321 }
322
323 Ptr<Packet> contentObject = m_contentStore->Lookup (header);
324 if ((isMine == true) || (contentObject != NULL))
325 {
326 //never respond with NACK to NACK
327 if(header->IsNack () )
328 return;
329
330 // always return a duplicate packet
331 header->SetNack(true);
332 //Trace duplicate interest
333 m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST,
334 m_node->GetObject<Ccnx> (), incomingFace);
335
336 SendInterest(incomingFace, header, packet->Copy());
337
338 return;
339 }
340
341
342 // check PIT. or there is no outgoing entry for this interface,
343 // silently drop the duplicate packet
344
345 // If no entry found, silently drop
346 if( pitEntry == m_pit->end() )
347 return;
348
349 // If PIT entry timed out, silently drop
350 if( pitEntry->m_timerExpired == true )
351 return;
352
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700353 // loop?
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700354
355 // Check if there is no outgoing entry for the interface or different nonce
356 // (i.e., got a duplicate packet, but we haven't sent interest to this
357 // interface)
358 //
359 // This case means that there is a loop in the network.
360 // So, prune this link, but do not remove PIT entry
361
362 // Alex, check this condition!!
363 if(pitEntry->m_outgoing.size () == 0)
364 {
365 //never respond with NACK to NACK
366 if(header->IsNack () )
367 return;
368
369 // always return a duplicate packet
370 header->SetNack(true);
371 //Trace duplicate interest
372 m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST,
373 m_node->GetObject<Ccnx> (), incomingFace);
374
375 SendInterest(incomingFace, header, packet->Copy());
376 return;
377 }
378
379
380 // At this point:
381 // - there is a non-expired PIT entry,
382 // - there is an outgoing interest to the interface, and
383 // - a nonce in outgoing entry is equal to a nonce in the received duplicate packet
384
385 // Should perform:
386 // Cleaning outgoing entry
387 // If there are no outgoing interests and available interfaces left (pe->availableInterfaces),
388 // prune all incoming interests, otherwise allow forwarding of the interest
389 if( header->IsNack () )
390 {
391 if( header->IsCongested () == false )
392 m_pit->LeakBucket(incomingFace,1);
393
394 m_pit->modify(pitEntry, CcnxPitEntry::DeleteOutgoing(incomingFace));
395 }
396 else
397 {
398 //poit->waitingInVain = true;
399 }
400
401
402 // prune all incoming interests
403 if((pitEntry->m_outgoing.size() ==0) && (pitEntry->m_fibEntry.m_faces.size() == 0))
404 {
405 BOOST_FOREACH (const CcnxPitEntryIncomingFace face, pitEntry->m_incoming)
406 {
407 if(face.m_face->IsLocal() == false)
408 {
409 // check all entries if the name of RIT entry matches the name of interest
410 for (CcnxRitByNonce::type::iterator it = m_rit->begin(); it != m_rit->end(); it++)
411 {
412 if (it->m_prefix == pitEntry->GetPrefix() )
413 {
414
415 header->SetNonce(it->m_nonce);
416 header->SetNack(true);
417 SendInterest(face.m_face, header, packet->Copy());
418 break;
419 }
420 }
421 }
422 }
423
424 // Finally, remote the PIT entry
425 m_pit->erase (pitEntry);
426
427 return; // stop processing
428 }
429
430 if(pitEntry->m_fibEntry.m_faces.size() == 0)
431 return;
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700432 }*/
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700433
434 // Otherwise,
435 // propagate the interest
436 //
437 // method `propagateInterest' can/should try different interface
438 // from `availableInterfaces' list
439
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700440 NS_LOG_INFO("Before SetRecentlySatisfied");
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700441 m_rit->SetRecentlySatisfied (*header);
442
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700443 NS_LOG_INFO("Cache Lookup for " << header->GetName());
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700444 Ptr<Packet> contentObject = m_contentStore->Lookup (header);
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700445 if (contentObject != NULL)
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700446 {
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700447 NS_LOG_INFO("Found in cache");
448
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700449 TransmittedDataTrace (contentObject, CACHED,
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700450 m_node->GetObject<Ccnx> (), incomingFace);
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700451 incomingFace->Send (contentObject);
452 return;
453 }
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700454
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700455 // Data is not in cache
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700456 NS_LOG_INFO("Before inFace and OutFace");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700457 CcnxPitEntryIncomingFaceContainer::type::iterator inFace = pitEntry->m_incoming.find (incomingFace);
458 CcnxPitEntryOutgoingFaceContainer::type::iterator outFace = pitEntry->m_outgoing.find (incomingFace);
459
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700460 NS_LOG_INFO("Before (pitEntry != m_pit->end()) && (pitEntry->m_timerExpired == false)");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700461 if ((pitEntry != m_pit->end()) && (pitEntry->m_timerExpired == false))
462 {
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700463 NS_LOG_INFO("Entering (pitEntry != m_pit->end()) && (pitEntry->m_timerExpired == false)");
464
465 if(inFace->m_face == NULL)
466 NS_LOG_INFO("in face is null");
467 if(outFace->m_face == NULL)
468 NS_LOG_INFO("outface is null");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700469
470 // If we're expecting data from the interface we got the interest from ("producer" asks us for "his own" data)
471 // Give up this interface, but keep a small hope when the returned packet doesn't have PRUNE status
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700472 if( outFace != pitEntry->m_outgoing.end())
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700473 {
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700474 NS_LOG_INFO("Entering outFace != pitEntry->m_outgoing.end()");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700475 if( header->IsCongested() == true )
476 {
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700477 NS_LOG_INFO("Entering header->IsCongested() == true");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700478 m_pit->LeakBucket(incomingFace, 1);
479 m_pit->modify (pitEntry, CcnxPitEntry::DeleteOutgoing(outFace->m_face));
480 }
481 //else
482 // poit->waitingInVain = true;
483
484 // Update metric status for the incoming interface in the corresponding FIB entry
485 if(fibEntry != m_fib->end())
486 m_fib->modify(m_fib->iterator_to (pitEntry->m_fibEntry),
487 CcnxFibEntry::UpdateStatus(incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
488 }
489 }
490
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700491 NS_LOG_INFO("Before (pitEntry->m_outgoing.size() == 0) && (pitEntry->m_fibEntry.m_faces.size() == 0)");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700492 if((pitEntry->m_outgoing.size() == 0) && (pitEntry->m_fibEntry.m_faces.size() == 0))
493 // prune all incoming interests
494 {
495
496 for(CcnxPitEntryContainer::type::iterator iter = m_pit->begin();
497 iter != m_pit->end();
498 iter++)
499 {
500 /*for(CcnxPitEntryIncomingFaceContainer::type::iterator face = iter->m_incoming.begin();
501 face != iter->m_incoming.end();
502 face++)*/
503 BOOST_FOREACH (const CcnxPitEntryIncomingFace face, iter->m_incoming)
504 {
505 if(face.m_face->IsLocal() == true)
506 {
507 //returnInterestToApp( pkt, -piit->interfaceIndex );
508 //continue;
509 }
510
511 // check all entries if the name of RIT entry matches the name of interest
512 for (CcnxRitByNonce::type::iterator it = m_rit->begin(); it != m_rit->end(); it++)
513 {
514 if (it->m_prefix == iter->GetPrefix() )
515 {
516 header->SetNonce(it->m_nonce);
517 header->SetNack(true);
518 SendInterest(face.m_face, header, packet->Copy());
519 }
520 }
521 }
522
523 }
524
525 m_pit->erase(pitEntry);
526
527 return; // there is nothing else to do
528 }
529
530 // Suppress this interest only if we're still expecting data from some other interface
531 if( pitEntry->m_outgoing.size() > 0 )
532 {
533 return; //ok. Now we can suppress this interest
534 }
535
536
537 // Prune and delete PIT entry if there are no available interfaces to propagate interest
538 if( pitEntry->m_fibEntry.m_faces.size() == 0)
539 {
540 //if no match is found in the FIB, drop packet
541 //printf( "Node %d: cannot process Interest packet %s (no interfaces left)\n", _node->nodeId, pkt->contentName );
542
543 if(incomingFace->IsLocal() == false)
544 {
545 header->SetNack(true);
546 m_droppedInterestsTrace (header, NDN_SUPPRESSED_INTEREST,
547 m_node->GetObject<Ccnx> (), incomingFace);
548 SendInterest(incomingFace, header, packet->Copy());
549 }
550
551 m_pit->erase(pitEntry);
552
553 }
554
555
556
557 // otherwise, try one of the available interfaces
558
559 // suppress interest if
560 /*if (pitEntry->m_incoming.size () != 0 && // not a new PIT entry and
561 inFace != pitEntry->m_incoming.end ()) // existing entry, but interest received via different face
562 {
563 m_droppedInterestsTrace (header, NDN_SUPPRESSED_INTEREST,
564 m_node->GetObject<Ccnx> (), incomingFace);
565 return;
566 }*/
567
568
569 //just in case of bug
570 header->SetNack(false);
571 header->SetCongested(false);
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700572
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700573 NS_ASSERT_MSG (m_forwardingStrategy != 0, "Need a forwarding protocol object to process packets");
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700574
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700575 m_pit->modify (pitEntry, CcnxPitEntry::AddIncoming(incomingFace));
576
577 bool propagated = m_forwardingStrategy->
578 PropagateInterest (pitEntry, fibEntry,incomingFace, header, packet,
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700579 MakeCallback (&CcnxL3Protocol::SendInterest, this)
580 );
581
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700582 // If interest wasn't propagated further (probably, a limit is reached),
583 // prune and delete PIT entry if there are no outstanding interests.
584 // Stop processing otherwise.
585 if( (!propagated) && (pitEntry->m_outgoing.size() == 0))
586 {
587 BOOST_FOREACH (const CcnxPitEntryIncomingFace face, pitEntry->m_incoming)
588 {
589
590
591 header->SetNack(true);
592 header->SetCongested(true);
593 SendInterest (face.m_face, header, packet->Copy());
594
595 m_droppedInterestsTrace (header, DROP_CONGESTION,
596 m_node->GetObject<Ccnx> (), incomingFace);
597 }
598
599 m_pit->erase (pitEntry);
600 }
601 /*}
602 else
603 {
604 m_droppedInterestsTrace (header, NDN_PIT_TIMER_EXPIRED,
605 m_node->GetObject<Ccnx> (), incomingFace);
606 return;
607 }*/
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700608}
609
610// Processing ContentObjects
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700611void CcnxL3Protocol::OnData (const Ptr<CcnxFace> &incomingFace,
612 Ptr<CcnxContentObjectHeader> &header,
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700613 Ptr<Packet> &payload,
614 const Ptr<const Packet> &packet)
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700615{
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700616
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700617 NS_LOG_LOGIC ("Receiving contentObject from " << &incomingFace);
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700618 m_receivedDataTrace (header, payload, m_node->GetObject<Ccnx> ()/*this*/, incomingFace);
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700619
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700620 // 1. Lookup PIT entry
621 try
622 {
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700623 const CcnxPitEntry &pitEntry = m_pit->Lookup (*header);
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700624
625 // Note that with MultiIndex we need to modify entries indirectly
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700626
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700627 // Update metric status for the incoming interface in the corresponding FIB entry
628 m_fib->modify (m_fib->iterator_to (pitEntry.m_fibEntry),
629 CcnxFibEntry::UpdateStatus (incomingFace, CcnxFibFaceMetric::NDN_FIB_GREEN));
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700630
631 // Add or update entry in the content store
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700632 NS_LOG_INFO("Cached " << header->GetName());
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700633 m_contentStore->Add (header, payload);
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700634
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700635 CcnxPitEntryOutgoingFaceContainer::type::iterator
636 out = pitEntry.m_outgoing.find (incomingFace);
637
638 // If we have sent interest for this data via this face, then update stats.
639 if (out != pitEntry.m_outgoing.end ())
640 {
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700641 m_pit->modify (m_pit->iterator_to (pitEntry),
642 CcnxPitEntry::EstimateRttAndRemoveFace(out, m_fib));
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700643 // face will be removed in the above call
644 }
645 else
646 {
647 NS_LOG_WARN ("Node "<< m_node->GetId() <<
648 ". PIT entry for "<< header->GetName ()<<" is valid, "
649 "but outgoing entry for interface "<< incomingFace <<" doesn't exist\n");
650 }
651
652 //satisfy all pending incoming Interests
653 BOOST_FOREACH (const CcnxPitEntryIncomingFace &interest, pitEntry.m_incoming)
654 {
655 if (interest.m_face == incomingFace) continue;
656
657 // may not work either because of 'const' thing
658 interest.m_face->Send (packet->Copy ()); // unfortunately, we have to copy packet...
659 m_transmittedDataTrace (header, payload, FORWARDED, m_node->GetObject<Ccnx> (), interest.m_face);
660 }
661
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700662 m_pit->modify (m_pit->iterator_to (pitEntry), CcnxPitEntry::ClearIncoming()); // satisfy all incoming interests
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700663
664 if( pitEntry.m_outgoing.size()==0 ) // remove PIT when all outgoing interests are "satisfied"
665 {
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700666 m_pit->erase (m_pit->iterator_to (pitEntry));
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700667 }
668
669 }
670 catch (CcnxPitEntryNotFound)
671 {
672 // 2. Drop data packet if PIT entry is not found
673 // (unsolicited data packets should not "poison" content store)
674
675 //drop dulicated or not requested data packet
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700676 m_droppedDataTrace (header, payload, NDN_UNSOLICITED_DATA, m_node->GetObject<Ccnx> (), incomingFace);
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700677 return; // do not process unsoliced data packets
678 }
679}
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700680
681void
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700682CcnxL3Protocol::SendInterest (const Ptr<CcnxFace> &face,
683 const Ptr<CcnxInterestHeader> &header,
684 const Ptr<Packet> &packet)
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700685{
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700686 NS_LOG_FUNCTION (this << "packet: " << &packet << ", face: "<< &face);
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700687 NS_ASSERT_MSG (face != 0, "Face should never be NULL");
688
689 if (face->IsUp ())
690 {
691 NS_LOG_LOGIC ("Sending via face " << &face); //
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700692 m_transmittedInterestsTrace (header, m_node->GetObject<Ccnx> (), face);
693 face->Send (packet);
694 }
695 else
696 {
697 NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << &face);
698 m_droppedInterestsTrace (header, INTERFACE_DOWN, m_node->GetObject<Ccnx> (), face);
699 }
700}
701
702void
703CcnxL3Protocol::SendContentObject (const Ptr<CcnxFace> &face,
704 const Ptr<CcnxContentObjectHeader> &header,
705 const Ptr<Packet> &packet)
706{
707 NS_LOG_FUNCTION (this << "packet: " << &packet << ", face: "<< &face);
708 NS_ASSERT_MSG (face != 0, "Face should never be NULL");
709
710 NS_ASSERT_MSG (false, "Should not be called for now");
711
712 if (face->IsUp ())
713 {
714 NS_LOG_LOGIC ("Sending via face " << &face); //
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700715 // m_txTrace (packet, m_node->GetObject<Ccnx> (), face);
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700716 face->Send (packet);
717 }
718 else
719 {
720 NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << &face);
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700721 // m_dropTrace (packet, INTERFACE_DOWN, m_node->GetObject<Ccnx> (), face);
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700722 }
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700723}
724
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700725Ptr<CcnxPit>
726CcnxL3Protocol::GetPit()
727{
728 return m_pit;
729}
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700730} //namespace ns3