blob: 63c9049f6db744ae5614d6ef0a27d73cc2bb0314 [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 Afanasyev52e9aa92011-11-15 20:23:20 -080041#include "ccnx-net-device-face.h"
42
Alexander Afanasyev56f79ea2011-08-17 23:54:27 -070043#include <boost/foreach.hpp>
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070044
45NS_LOG_COMPONENT_DEFINE ("CcnxL3Protocol");
46
47namespace ns3 {
48
Alexander Afanasyev7112f482011-08-17 14:05:57 -070049const uint16_t CcnxL3Protocol::ETHERNET_FRAME_TYPE = 0x7777;
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070050
51NS_OBJECT_ENSURE_REGISTERED (CcnxL3Protocol);
52
53TypeId
54CcnxL3Protocol::GetTypeId (void)
55{
56 static TypeId tid = TypeId ("ns3::CcnxL3Protocol")
57 .SetParent<Ccnx> ()
Alexander Afanasyev070aa482011-08-20 00:38:25 -070058 .SetGroupName ("Ccnx")
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070059 .AddConstructor<CcnxL3Protocol> ()
Alexander Afanasyev7112f482011-08-17 14:05:57 -070060 // .AddTraceSource ("Tx", "Send ccnx packet to outgoing interface.",
61 // MakeTraceSourceAccessor (&CcnxL3Protocol::m_txTrace))
62 // .AddTraceSource ("Rx", "Receive ccnx packet from incoming interface.",
63 // MakeTraceSourceAccessor (&CcnxL3Protocol::m_rxTrace))
64 // .AddTraceSource ("Drop", "Drop ccnx packet",
65 // MakeTraceSourceAccessor (&CcnxL3Protocol::m_dropTrace))
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -070066 // .AddAttribute ("InterfaceList", "The set of Ccnx interfaces associated to this Ccnx stack.",
67 // ObjectVectorValue (),
68 // MakeObjectVectorAccessor (&CcnxL3Protocol::m_faces),
69 // MakeObjectVectorChecker<CcnxFace> ())
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070070
Alexander Afanasyev7112f482011-08-17 14:05:57 -070071 // .AddTraceSource ("SendOutgoing", "A newly-generated packet by this node is about to be queued for transmission",
72 // MakeTraceSourceAccessor (&CcnxL3Protocol::m_sendOutgoingTrace))
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070073
74 ;
75 return tid;
76}
77
78CcnxL3Protocol::CcnxL3Protocol()
Alexander Afanasyevab1d5602011-08-17 19:17:18 -070079: m_faceCounter (0)
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070080{
81 NS_LOG_FUNCTION (this);
Alexander Afanasyevcf133f02011-09-06 12:13:48 -070082
83 m_rit = CreateObject<CcnxRit> ();
84 m_pit = CreateObject<CcnxPit> ();
85 m_contentStore = CreateObject<CcnxContentStore> ();
Alexander Afanasyev08d984e2011-08-13 19:20:22 -070086}
87
88CcnxL3Protocol::~CcnxL3Protocol ()
89{
90 NS_LOG_FUNCTION (this);
91}
92
93void
94CcnxL3Protocol::SetNode (Ptr<Node> node)
95{
96 m_node = node;
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -070097 m_fib = m_node->GetObject<CcnxFib> ();
98 NS_ASSERT_MSG (m_fib != 0, "FIB should be created and aggregated to a node before calling Ccnx::SetNode");
99
100 m_pit->SetFib (m_fib);
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700101}
102
103/*
104 * This method is called by AddAgregate and completes the aggregation
105 * by setting the node in the ccnx stack
106 */
107void
108CcnxL3Protocol::NotifyNewAggregate ()
109{
110 if (m_node == 0)
111 {
112 Ptr<Node>node = this->GetObject<Node>();
113 // verify that it's a valid node and that
114 // the node has not been set before
115 if (node != 0)
116 {
117 this->SetNode (node);
118 }
119 }
120 Object::NotifyNewAggregate ();
121}
122
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700123void
124CcnxL3Protocol::DoDispose (void)
125{
126 NS_LOG_FUNCTION (this);
127
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700128 for (CcnxFaceList::iterator i = m_faces.begin (); i != m_faces.end (); ++i)
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700129 {
130 *i = 0;
131 }
Alexander Afanasyev98256102011-08-14 01:00:02 -0700132 m_faces.clear ();
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700133 m_node = 0;
Alexander Afanasyevd02a5d62011-11-21 11:01:51 -0800134
135 // Force delete on objects
Alexander Afanasyev18252852011-11-21 13:35:31 -0800136 m_forwardingStrategy = 0; // there is a reference to PIT stored in here
Alexander Afanasyevd02a5d62011-11-21 11:01:51 -0800137 m_rit = 0;
138 m_pit = 0;
139 m_contentStore = 0;
Alexander Afanasyev18252852011-11-21 13:35:31 -0800140 m_fib = 0;
141
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700142 // m_forwardingStrategy = 0;
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700143 Object::DoDispose ();
144}
145
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700146void
147CcnxL3Protocol::SetForwardingStrategy (Ptr<CcnxForwardingStrategy> forwardingStrategy)
148{
149 NS_LOG_FUNCTION (this);
150 m_forwardingStrategy = forwardingStrategy;
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700151 // m_forwardingStrategy->SetCcnx (this);
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700152}
153
154Ptr<CcnxForwardingStrategy>
155CcnxL3Protocol::GetForwardingStrategy (void) const
156{
157 return m_forwardingStrategy;
158}
159
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700160uint32_t
Alexander Afanasyev7112f482011-08-17 14:05:57 -0700161CcnxL3Protocol::AddFace (const Ptr<CcnxFace> &face)
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700162{
Alexander Afanasyev56f79ea2011-08-17 23:54:27 -0700163 NS_LOG_FUNCTION (this << &face);
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700164
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700165 face->SetNode (m_node);
Alexander Afanasyevab1d5602011-08-17 19:17:18 -0700166 face->SetId (m_faceCounter); // sets a unique ID of the face. This ID serves only informational purposes
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700167
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700168 // ask face to register in lower-layer stack
Alexander Afanasyev56f79ea2011-08-17 23:54:27 -0700169 face->RegisterProtocolHandler (MakeCallback (&CcnxL3Protocol::Receive, this));
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700170
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700171 m_faces.push_back (face);
Alexander Afanasyevab1d5602011-08-17 19:17:18 -0700172 m_faceCounter ++;
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700173 return face->GetId ();
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700174}
175
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700176void
177CcnxL3Protocol::RemoveFace (Ptr<CcnxFace> face)
178{
179 // ask face to register in lower-layer stack
180 face->RegisterProtocolHandler (MakeNullCallback<void,const Ptr<CcnxFace>&,const Ptr<const Packet>&> ());
181 CcnxFaceList::iterator face_it = find (m_faces.begin(), m_faces.end(), face);
182 NS_ASSERT_MSG (face_it != m_faces.end (), "Attempt to remove face that doesn't exist");
183 m_faces.erase (face_it);
184}
185
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700186Ptr<CcnxFace>
Alexander Afanasyev98256102011-08-14 01:00:02 -0700187CcnxL3Protocol::GetFace (uint32_t index) const
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700188{
Alexander Afanasyev56f79ea2011-08-17 23:54:27 -0700189 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 -0700190 {
Alexander Afanasyev56f79ea2011-08-17 23:54:27 -0700191 if (face->GetId () == index)
192 return face;
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700193 }
194 return 0;
195}
196
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800197Ptr<CcnxFace>
198CcnxL3Protocol::GetFaceByNetDevice (Ptr<NetDevice> netDevice) const
199{
200 BOOST_FOREACH (const Ptr<CcnxFace> &face, m_faces) // this function is not supposed to be called often, so linear search is fine
201 {
202 Ptr<CcnxNetDeviceFace> netDeviceFace = DynamicCast<CcnxNetDeviceFace> (face);
203 if (netDeviceFace == 0) continue;
204
205 if (netDeviceFace->GetNetDevice () == netDevice)
206 return face;
207 }
208 return 0;
209}
210
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700211uint32_t
Alexander Afanasyev98256102011-08-14 01:00:02 -0700212CcnxL3Protocol::GetNFaces (void) const
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700213{
Alexander Afanasyev98256102011-08-14 01:00:02 -0700214 return m_faces.size ();
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700215}
216
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700217void
218CcnxL3Protocol::TransmittedDataTrace (Ptr<Packet> packet,
219 ContentObjectSource type,
220 Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
221{
222 // a "small" inefficiency for logging purposes
223 Ptr<CcnxContentObjectHeader> header = Create<CcnxContentObjectHeader> ();
224 static CcnxContentObjectTail tail;
225 packet->RemoveHeader (*header);
226 packet->RemoveTrailer (tail);
227
228 m_transmittedDataTrace (header, packet/*payload*/, type, ccnx, face);
229
230 packet->AddHeader (*header);
231 packet->AddTrailer (tail);
232}
233
234
Alexander Afanasyev98256102011-08-14 01:00:02 -0700235// Callback from lower layer
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700236void
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700237CcnxL3Protocol::Receive (const Ptr<CcnxFace> &face, const Ptr<const Packet> &p)
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700238{
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700239 if (!face->IsUp ())
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700240 {
241 NS_LOG_LOGIC ("Dropping received packet -- interface is down");
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700242 // m_dropTrace (p, INTERFACE_DOWN, m_node->GetObject<Ccnx> ()/*this*/, face);
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700243 return;
244 }
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700245 NS_LOG_LOGIC ("Packet from face " << *face << " received on node " << m_node->GetId ());
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700246
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700247 Ptr<Packet> packet = p->Copy (); // give upper layers a rw copy of the packet
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700248 try
249 {
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700250 CcnxHeaderHelper::Type type = CcnxHeaderHelper::GetCcnxHeaderType (p);
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700251 switch (type)
252 {
253 case CcnxHeaderHelper::INTEREST:
254 {
255 Ptr<CcnxInterestHeader> header = Create<CcnxInterestHeader> ();
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700256
257 // Deserialization. Exception may be thrown
258 packet->RemoveHeader (*header);
259 NS_ASSERT_MSG (packet->GetSize () == 0, "Payload of Interests should be zero");
260
261 OnInterest (face, header, p/*original packet*/);
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700262 break;
263 }
264 case CcnxHeaderHelper::CONTENT_OBJECT:
265 {
266 Ptr<CcnxContentObjectHeader> header = Create<CcnxContentObjectHeader> ();
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700267
268 static CcnxContentObjectTail contentObjectTrailer; //there is no data in this object
269
270 // Deserialization. Exception may be thrown
271 packet->RemoveHeader (*header);
272 packet->RemoveTrailer (contentObjectTrailer);
273
274 OnData (face, header, packet/*payload*/, p/*original packet*/);
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700275 break;
276 }
277 }
278
279 // exception will be thrown if packet is not recognized
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700280 }
281 catch (CcnxUnknownHeaderException)
282 {
283 NS_ASSERT_MSG (false, "Unknown CCNx header. Should not happen");
284 }
Alexander Afanasyev98256102011-08-14 01:00:02 -0700285}
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700286
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700287// Processing Interests
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700288void CcnxL3Protocol::OnInterest (const Ptr<CcnxFace> &incomingFace,
289 Ptr<CcnxInterestHeader> &header,
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700290 const Ptr<const Packet> &packet)
Alexander Afanasyev98256102011-08-14 01:00:02 -0700291{
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700292 NS_LOG_LOGIC ("Receiving interest from " << &incomingFace);
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700293 m_receivedInterestsTrace (header, m_node->GetObject<Ccnx> (), incomingFace);
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700294
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800295
296 if( header->IsNack () )
297 {
298 NS_LOG_INFO("============");
299 NS_LOG_INFO("NACK");
300 NS_LOG_INFO("==========");
301 /*if( header->IsCongested () == false )
302 m_pit->LeakBucket(incomingFace,1);
303
304
305 m_droppedInterestsTrace (header, DROP_CONGESTION,
306 m_node->GetObject<Ccnx> (), incomingFace);
307
308 m_pit->modify(pitEntry, CcnxPitEntry::DeleteOutgoing(incomingFace));*/
309 }
310
311
312
313
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700314 // Lookup of Pit and Fib entries for this Interest
315 CcnxFibEntryContainer::type::iterator fibEntry;
316 CcnxPitEntryContainer::type::iterator pitEntry = m_pit->Lookup (*header, fibEntry);
317
318 // No matter is it duplicate or not, if it is a NACK message, remove all possible incoming
319 // entries for this interface (NACK means that neighbor gave up trying and there is no
320 // point of sending data in this direction)
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700321 NS_LOG_INFO("Before (header->IsNack()) && (pitEntry != m_pit->end ())");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700322 if ((header->IsNack()) && (pitEntry != m_pit->end ()))
323 {
324 //m_pit->erase (pitEntry);
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700325 NS_LOG_INFO("TRUE");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700326 m_pit->modify(pitEntry, CcnxPitEntry::DeleteIncoming(incomingFace));
327 }
328
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700329 NS_LOG_INFO("Before WasRecentlySatisfied");
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800330 /*if (m_rit->WasRecentlySatisfied (*header))
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700331 {
332 return;
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800333 }*/
334 if (m_rit->WasRecentlySatisfied (*header))
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700335 {
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800336 NS_LOG_INFO("------------");
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700337 NS_LOG_INFO("Entering WasRecentlySatisfied");
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800338 NS_LOG_INFO("------------");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700339 // duplicate interests (same nonce) from applications are just ignored
340 if (incomingFace->IsLocal() == true)
341 return;
342
343 // Update metric status for the incoming interface in the corresponding FIB entry
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800344 /*if (fibEntry != m_fib->end())
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700345 m_fib->modify (m_fib->iterator_to (pitEntry->m_fibEntry),
346 CcnxFibEntry::UpdateStatus(incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
347
348 //Trace duplicate interest
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700349 m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST,
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700350 m_node->GetObject<Ccnx> (), incomingFace);
351
352 bool isMine = false;
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700353 //TypeId tid = TypeId ("ns3::CcnxProducer");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700354 for(uint32_t i=0; i<m_node->GetNApplications();i++)
355 {
356 Ptr<Application> app = m_node->GetApplication(i);
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700357 NS_LOG_INFO("ApplicationName = " << app->GetTypeId().GetName());
358 if(app->GetTypeId().GetName() == "ns3::CcnxProducer")
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700359 {
360 if((DynamicCast<CcnxProducer>(app))->GetPrefix () == header->GetName ())
361 {
362 isMine = true;
363 break;
364 }
365 }
366 }
367
368 Ptr<Packet> contentObject = m_contentStore->Lookup (header);
369 if ((isMine == true) || (contentObject != NULL))
370 {
371 //never respond with NACK to NACK
372 if(header->IsNack () )
373 return;
374
375 // always return a duplicate packet
376 header->SetNack(true);
377 //Trace duplicate interest
378 m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST,
379 m_node->GetObject<Ccnx> (), incomingFace);
380
381 SendInterest(incomingFace, header, packet->Copy());
382
383 return;
384 }
385
386
387 // check PIT. or there is no outgoing entry for this interface,
388 // silently drop the duplicate packet
389
390 // If no entry found, silently drop
391 if( pitEntry == m_pit->end() )
392 return;
393
394 // If PIT entry timed out, silently drop
395 if( pitEntry->m_timerExpired == true )
396 return;
397
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700398 // loop?
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700399
400 // Check if there is no outgoing entry for the interface or different nonce
401 // (i.e., got a duplicate packet, but we haven't sent interest to this
402 // interface)
403 //
404 // This case means that there is a loop in the network.
405 // So, prune this link, but do not remove PIT entry
406
407 // Alex, check this condition!!
408 if(pitEntry->m_outgoing.size () == 0)
409 {
410 //never respond with NACK to NACK
411 if(header->IsNack () )
412 return;
413
414 // always return a duplicate packet
415 header->SetNack(true);
416 //Trace duplicate interest
417 m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST,
418 m_node->GetObject<Ccnx> (), incomingFace);
419
420 SendInterest(incomingFace, header, packet->Copy());
421 return;
422 }
423
424
425 // At this point:
426 // - there is a non-expired PIT entry,
427 // - there is an outgoing interest to the interface, and
428 // - a nonce in outgoing entry is equal to a nonce in the received duplicate packet
429
430 // Should perform:
431 // Cleaning outgoing entry
432 // If there are no outgoing interests and available interfaces left (pe->availableInterfaces),
433 // prune all incoming interests, otherwise allow forwarding of the interest
434 if( header->IsNack () )
435 {
436 if( header->IsCongested () == false )
437 m_pit->LeakBucket(incomingFace,1);
438
439 m_pit->modify(pitEntry, CcnxPitEntry::DeleteOutgoing(incomingFace));
440 }
441 else
442 {
443 //poit->waitingInVain = true;
444 }
445
446
447 // prune all incoming interests
448 if((pitEntry->m_outgoing.size() ==0) && (pitEntry->m_fibEntry.m_faces.size() == 0))
449 {
450 BOOST_FOREACH (const CcnxPitEntryIncomingFace face, pitEntry->m_incoming)
451 {
452 if(face.m_face->IsLocal() == false)
453 {
454 // check all entries if the name of RIT entry matches the name of interest
455 for (CcnxRitByNonce::type::iterator it = m_rit->begin(); it != m_rit->end(); it++)
456 {
457 if (it->m_prefix == pitEntry->GetPrefix() )
458 {
459
460 header->SetNonce(it->m_nonce);
461 header->SetNack(true);
462 SendInterest(face.m_face, header, packet->Copy());
463 break;
464 }
465 }
466 }
467 }
468
469 // Finally, remote the PIT entry
470 m_pit->erase (pitEntry);
471
472 return; // stop processing
473 }
474
475 if(pitEntry->m_fibEntry.m_faces.size() == 0)
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800476 return;*/
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700477 return;
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800478 }
479
480
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700481
482 // Otherwise,
483 // propagate the interest
484 //
485 // method `propagateInterest' can/should try different interface
486 // from `availableInterfaces' list
487
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700488 NS_LOG_INFO("Before SetRecentlySatisfied");
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700489 m_rit->SetRecentlySatisfied (*header);
490
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700491 NS_LOG_INFO("Cache Lookup for " << header->GetName());
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700492 Ptr<Packet> contentObject = m_contentStore->Lookup (header);
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700493 if (contentObject != NULL)
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700494 {
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700495 NS_LOG_INFO("Found in cache");
496
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700497 TransmittedDataTrace (contentObject, CACHED,
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700498 m_node->GetObject<Ccnx> (), incomingFace);
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700499 incomingFace->Send (contentObject);
500 return;
501 }
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700502
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700503 // Data is not in cache
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700504 NS_LOG_INFO("Before inFace and OutFace");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700505 CcnxPitEntryIncomingFaceContainer::type::iterator inFace = pitEntry->m_incoming.find (incomingFace);
506 CcnxPitEntryOutgoingFaceContainer::type::iterator outFace = pitEntry->m_outgoing.find (incomingFace);
507
Alexander Afanasyevd02a5d62011-11-21 11:01:51 -0800508 NS_LOG_INFO("Before (pitEntry != m_pit->end()) && (pitEntry->m_timerExpired == false)");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700509 if ((pitEntry != m_pit->end()) && (pitEntry->m_timerExpired == false))
510 {
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700511 NS_LOG_INFO("Entering (pitEntry != m_pit->end()) && (pitEntry->m_timerExpired == false)");
512
Alexander Afanasyevd02a5d62011-11-21 11:01:51 -0800513 if(inFace->m_face == 0)
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700514 NS_LOG_INFO("in face is null");
Alexander Afanasyevd02a5d62011-11-21 11:01:51 -0800515 if(outFace->m_face == 0)
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700516 NS_LOG_INFO("outface is null");
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800517 if(outFace == pitEntry->m_outgoing.end())
518 NS_LOG_INFO("OUTFACE = END");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700519
520 // If we're expecting data from the interface we got the interest from ("producer" asks us for "his own" data)
521 // Give up this interface, but keep a small hope when the returned packet doesn't have PRUNE status
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800522 if(outFace != pitEntry->m_outgoing.end()) // this is correct
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700523 {
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700524 NS_LOG_INFO("Entering outFace != pitEntry->m_outgoing.end()");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700525 if( header->IsCongested() == true )
526 {
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700527 NS_LOG_INFO("Entering header->IsCongested() == true");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700528 m_pit->LeakBucket(incomingFace, 1);
529 m_pit->modify (pitEntry, CcnxPitEntry::DeleteOutgoing(outFace->m_face));
530 }
531 //else
532 // poit->waitingInVain = true;
533
534 // Update metric status for the incoming interface in the corresponding FIB entry
535 if(fibEntry != m_fib->end())
536 m_fib->modify(m_fib->iterator_to (pitEntry->m_fibEntry),
537 CcnxFibEntry::UpdateStatus(incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
538 }
539 }
540
Ilya Moiseenkob405d9b2011-10-28 16:23:11 -0700541 NS_LOG_INFO("Before (pitEntry->m_outgoing.size() == 0) && (pitEntry->m_fibEntry.m_faces.size() == 0)");
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700542 if((pitEntry->m_outgoing.size() == 0) && (pitEntry->m_fibEntry.m_faces.size() == 0))
543 // prune all incoming interests
544 {
545
546 for(CcnxPitEntryContainer::type::iterator iter = m_pit->begin();
547 iter != m_pit->end();
548 iter++)
549 {
550 /*for(CcnxPitEntryIncomingFaceContainer::type::iterator face = iter->m_incoming.begin();
551 face != iter->m_incoming.end();
552 face++)*/
553 BOOST_FOREACH (const CcnxPitEntryIncomingFace face, iter->m_incoming)
554 {
555 if(face.m_face->IsLocal() == true)
556 {
557 //returnInterestToApp( pkt, -piit->interfaceIndex );
558 //continue;
559 }
560
561 // check all entries if the name of RIT entry matches the name of interest
562 for (CcnxRitByNonce::type::iterator it = m_rit->begin(); it != m_rit->end(); it++)
563 {
564 if (it->m_prefix == iter->GetPrefix() )
565 {
566 header->SetNonce(it->m_nonce);
567 header->SetNack(true);
568 SendInterest(face.m_face, header, packet->Copy());
569 }
570 }
571 }
572
573 }
574
575 m_pit->erase(pitEntry);
576
577 return; // there is nothing else to do
578 }
579
580 // Suppress this interest only if we're still expecting data from some other interface
581 if( pitEntry->m_outgoing.size() > 0 )
582 {
583 return; //ok. Now we can suppress this interest
584 }
585
586
587 // Prune and delete PIT entry if there are no available interfaces to propagate interest
588 if( pitEntry->m_fibEntry.m_faces.size() == 0)
589 {
590 //if no match is found in the FIB, drop packet
591 //printf( "Node %d: cannot process Interest packet %s (no interfaces left)\n", _node->nodeId, pkt->contentName );
592
593 if(incomingFace->IsLocal() == false)
594 {
595 header->SetNack(true);
596 m_droppedInterestsTrace (header, NDN_SUPPRESSED_INTEREST,
597 m_node->GetObject<Ccnx> (), incomingFace);
598 SendInterest(incomingFace, header, packet->Copy());
599 }
600
601 m_pit->erase(pitEntry);
602
603 }
604
605
606
607 // otherwise, try one of the available interfaces
608
609 // suppress interest if
610 /*if (pitEntry->m_incoming.size () != 0 && // not a new PIT entry and
611 inFace != pitEntry->m_incoming.end ()) // existing entry, but interest received via different face
612 {
613 m_droppedInterestsTrace (header, NDN_SUPPRESSED_INTEREST,
614 m_node->GetObject<Ccnx> (), incomingFace);
615 return;
616 }*/
617
618
619 //just in case of bug
620 header->SetNack(false);
621 header->SetCongested(false);
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700622
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800623 NS_ASSERT_MSG (m_forwardingStrategy != 0, "Need a forwarding protocol object to process packets");
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700624
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800625 m_pit->modify (pitEntry, CcnxPitEntry::AddIncoming(incomingFace));
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700626
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800627 bool propagated = m_forwardingStrategy->
628 PropagateInterest (pitEntry, fibEntry,incomingFace, header, packet,
629 MakeCallback (&CcnxL3Protocol::SendInterest, this)
630 );
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700631
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800632 // If interest wasn't propagated further (probably, a limit is reached),
633 // prune and delete PIT entry if there are no outstanding interests.
634 // Stop processing otherwise.
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800635 if( (!propagated) && (pitEntry->m_outgoing.size() == 0)) // this line works
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800636 {
637 BOOST_FOREACH (const CcnxPitEntryIncomingFace face, pitEntry->m_incoming)
638 {
639 header->SetNack(true);
640 header->SetCongested(true);
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800641 NS_LOG_INFO("Sending CONGESTION packet");
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800642 SendInterest (face.m_face, header, packet->Copy());
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700643
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800644 m_droppedInterestsTrace (header, DROP_CONGESTION,
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700645 m_node->GetObject<Ccnx> (), incomingFace);
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800646 }
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700647
648 m_pit->erase (pitEntry);
Ilya Moiseenko00b30482011-11-15 17:58:00 -0800649 }
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700650 /*}
651 else
652 {
653 m_droppedInterestsTrace (header, NDN_PIT_TIMER_EXPIRED,
654 m_node->GetObject<Ccnx> (), incomingFace);
655 return;
656 }*/
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700657}
658
659// Processing ContentObjects
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700660void CcnxL3Protocol::OnData (const Ptr<CcnxFace> &incomingFace,
661 Ptr<CcnxContentObjectHeader> &header,
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700662 Ptr<Packet> &payload,
663 const Ptr<const Packet> &packet)
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700664{
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700665
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700666 NS_LOG_LOGIC ("Receiving contentObject from " << &incomingFace);
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700667 m_receivedDataTrace (header, payload, m_node->GetObject<Ccnx> ()/*this*/, incomingFace);
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700668
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700669 // 1. Lookup PIT entry
670 try
671 {
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700672 const CcnxPitEntry &pitEntry = m_pit->Lookup (*header);
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700673
674 // Note that with MultiIndex we need to modify entries indirectly
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700675
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700676 // Update metric status for the incoming interface in the corresponding FIB entry
677 m_fib->modify (m_fib->iterator_to (pitEntry.m_fibEntry),
678 CcnxFibEntry::UpdateStatus (incomingFace, CcnxFibFaceMetric::NDN_FIB_GREEN));
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700679
680 // Add or update entry in the content store
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700681 NS_LOG_INFO("Cached " << header->GetName());
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700682 m_contentStore->Add (header, payload);
Alexander Afanasyevc74a6022011-08-15 20:01:35 -0700683
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700684 CcnxPitEntryOutgoingFaceContainer::type::iterator
685 out = pitEntry.m_outgoing.find (incomingFace);
686
687 // If we have sent interest for this data via this face, then update stats.
688 if (out != pitEntry.m_outgoing.end ())
689 {
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700690 m_pit->modify (m_pit->iterator_to (pitEntry),
691 CcnxPitEntry::EstimateRttAndRemoveFace(out, m_fib));
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700692 // face will be removed in the above call
693 }
694 else
695 {
696 NS_LOG_WARN ("Node "<< m_node->GetId() <<
697 ". PIT entry for "<< header->GetName ()<<" is valid, "
698 "but outgoing entry for interface "<< incomingFace <<" doesn't exist\n");
699 }
700
701 //satisfy all pending incoming Interests
702 BOOST_FOREACH (const CcnxPitEntryIncomingFace &interest, pitEntry.m_incoming)
703 {
704 if (interest.m_face == incomingFace) continue;
705
706 // may not work either because of 'const' thing
707 interest.m_face->Send (packet->Copy ()); // unfortunately, we have to copy packet...
708 m_transmittedDataTrace (header, payload, FORWARDED, m_node->GetObject<Ccnx> (), interest.m_face);
709 }
710
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700711 m_pit->modify (m_pit->iterator_to (pitEntry), CcnxPitEntry::ClearIncoming()); // satisfy all incoming interests
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700712
713 if( pitEntry.m_outgoing.size()==0 ) // remove PIT when all outgoing interests are "satisfied"
714 {
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700715 m_pit->erase (m_pit->iterator_to (pitEntry));
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700716 }
717
718 }
719 catch (CcnxPitEntryNotFound)
720 {
721 // 2. Drop data packet if PIT entry is not found
722 // (unsolicited data packets should not "poison" content store)
723
724 //drop dulicated or not requested data packet
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700725 m_droppedDataTrace (header, payload, NDN_UNSOLICITED_DATA, m_node->GetObject<Ccnx> (), incomingFace);
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700726 return; // do not process unsoliced data packets
727 }
728}
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700729
730void
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700731CcnxL3Protocol::SendInterest (const Ptr<CcnxFace> &face,
732 const Ptr<CcnxInterestHeader> &header,
733 const Ptr<Packet> &packet)
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700734{
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700735 NS_LOG_FUNCTION (this << "packet: " << &packet << ", face: "<< &face);
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700736 NS_ASSERT_MSG (face != 0, "Face should never be NULL");
737
738 if (face->IsUp ())
739 {
740 NS_LOG_LOGIC ("Sending via face " << &face); //
Alexander Afanasyevcf133f02011-09-06 12:13:48 -0700741 m_transmittedInterestsTrace (header, m_node->GetObject<Ccnx> (), face);
742 face->Send (packet);
743 }
744 else
745 {
746 NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << &face);
747 m_droppedInterestsTrace (header, INTERFACE_DOWN, m_node->GetObject<Ccnx> (), face);
748 }
749}
750
751void
752CcnxL3Protocol::SendContentObject (const Ptr<CcnxFace> &face,
753 const Ptr<CcnxContentObjectHeader> &header,
754 const Ptr<Packet> &packet)
755{
756 NS_LOG_FUNCTION (this << "packet: " << &packet << ", face: "<< &face);
757 NS_ASSERT_MSG (face != 0, "Face should never be NULL");
758
759 NS_ASSERT_MSG (false, "Should not be called for now");
760
761 if (face->IsUp ())
762 {
763 NS_LOG_LOGIC ("Sending via face " << &face); //
Alexander Afanasyeva67e28c2011-08-31 21:16:25 -0700764 // m_txTrace (packet, m_node->GetObject<Ccnx> (), face);
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700765 face->Send (packet);
766 }
767 else
768 {
769 NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << &face);
Alexander Afanasyev78cf0c92011-09-01 19:57:14 -0700770 // m_dropTrace (packet, INTERFACE_DOWN, m_node->GetObject<Ccnx> (), face);
Alexander Afanasyev070aa482011-08-20 00:38:25 -0700771 }
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700772}
773
Ilya Moiseenko172763c2011-10-28 13:21:53 -0700774Ptr<CcnxPit>
775CcnxL3Protocol::GetPit()
776{
777 return m_pit;
778}
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800779
780void
781CcnxL3Protocol::ScheduleLeakage()
782{
783 m_pit->LeakBuckets();
784 Time interval = MilliSeconds (NDN_INTEREST_RESET_PERIOD);
785 Simulator::Schedule (interval, &CcnxL3Protocol::ScheduleLeakage, this);
786}
Alexander Afanasyev08d984e2011-08-13 19:20:22 -0700787} //namespace ns3