Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | |
2 /* | |
3 * Copyright (c) 2010 Hemanth Narra, ITTC, KU | |
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 * Authors: Hemanth Narra <hemanth@ittc.ku.com> | |
19 * Yufei Cheng <yfcheng@ittc.ku.edu> | |
20 * Thanks to the students and our professor Dr.James P.G. Sterbenz in the Resili Nets group | |
21 * at The University of Kansas, https://wiki.ittc.ku.edu/resilinets/Main_Page | |
22 */ | |
23 | |
24 #include "dsdv-routing-protocol.h" | |
25 #include "ns3/log.h" | |
26 #include "ns3/random-variable.h" | |
27 #include "ns3/inet-socket-address.h" | |
28 #include "ns3/trace-source-accessor.h" | |
29 #include "ns3/udp-socket-factory.h" | |
30 #include "ns3/wifi-net-device.h" | |
31 #include "ns3/boolean.h" | |
32 #include "ns3/double.h" | |
33 #include "ns3/uinteger.h" | |
34 | |
35 NS_LOG_COMPONENT_DEFINE ("DsdvRoutingProtocol"); | |
36 | |
37 namespace ns3 { | |
38 namespace dsdv { | |
39 NS_OBJECT_ENSURE_REGISTERED (RoutingProtocol); | |
40 | |
41 // / UDP Port for DSDV control traffic | |
42 const uint32_t RoutingProtocol::DSDV_PORT = 269; | |
43 #define holddownTime (Scalar (Holdtimes) * PeriodicUpdateInterval) | |
Tom Henderson
2010/06/24 22:52:07
suggest you make this a function instead of a macr
| |
44 | |
45 // / Tag used by DSDV implementation | |
46 struct DeferredRouteOutputTag : public Tag | |
47 { | |
48 // / Positive if output device is fixed in RouteOutput | |
49 int32_t oif; | |
50 | |
51 DeferredRouteOutputTag (int32_t o = -1) | |
52 : Tag (), | |
53 oif (o) | |
54 { | |
55 } | |
56 | |
57 static TypeId | |
58 GetTypeId () | |
59 { | |
60 static TypeId tid = TypeId ("ns3::dsdv::DeferredRouteOutputTag").SetParent<T ag> (); | |
61 return tid; | |
62 } | |
63 | |
64 TypeId | |
65 GetInstanceTypeId () const | |
66 { | |
67 return GetTypeId (); | |
68 } | |
69 | |
70 uint32_t | |
71 GetSerializedSize () const | |
72 { | |
73 return sizeof(int32_t); | |
74 } | |
75 | |
76 void | |
77 Serialize (TagBuffer i) const | |
78 { | |
79 i.WriteU32 (oif); | |
80 } | |
81 | |
82 void | |
83 Deserialize (TagBuffer i) | |
84 { | |
85 oif = i.ReadU32 (); | |
86 } | |
87 | |
88 void | |
89 Print (std::ostream &os) const | |
90 { | |
91 os << "DeferredRouteOutputTag: output interface = " << oif; | |
92 } | |
93 }; | |
94 | |
95 RoutingProtocol::RoutingProtocol () | |
96 : m_routingTable (), | |
97 m_advRoutingTable (), | |
98 m_requestId (0), | |
99 m_seqNo (0), | |
100 m_madeAttempts (0), | |
101 MaxQueueLen (250), | |
Tom Henderson
2010/06/24 22:52:07
these member initializers are immediately overridd
| |
102 MaxQueuedPacketsPerDst (5), | |
103 MaxQueueTime (Seconds (30)), | |
104 m_queue (MaxQueueLen,MaxQueuedPacketsPerDst,MaxQueueTime), | |
105 EnableBuffering (true), | |
106 EnableWST (true), | |
107 Holdtimes (3), | |
108 EnableRouteAggregation (true), | |
109 RouteAggregationTime (1), | |
110 m_periodicUpdateTimer (Timer::CANCEL_ON_DESTROY) | |
111 { | |
112 } | |
113 | |
114 TypeId | |
115 RoutingProtocol::GetTypeId (void) | |
116 { | |
117 static TypeId tid = TypeId ("ns3::dsdv::RoutingProtocol") | |
118 .SetParent<Ipv4RoutingProtocol> () | |
119 .AddConstructor<RoutingProtocol> () | |
120 .AddAttribute ("PeriodicUpdateInterval","Periodic interval between exchang e of full routing tables among nodes. ", | |
121 TimeValue (Seconds (15)), | |
122 MakeTimeAccessor (&RoutingProtocol::PeriodicUpdateInterval) , | |
123 MakeTimeChecker ()) | |
Tom Henderson
2010/06/24 22:52:07
Good use of attribute system. Note that you can e
| |
124 .AddAttribute ("SettlingTime", "Minimum time an update is to be stored in adv table before sending out" | |
125 "in case of change in metric (in seconds)", | |
126 TimeValue (Seconds (6)), | |
127 MakeTimeAccessor (&RoutingProtocol::SettlingTime), | |
128 MakeTimeChecker ()) | |
129 .AddAttribute ("MaxQueueLen", "Maximum number of packets that we allow a r outing protocol to buffer.", | |
130 UintegerValue (500/*assuming maximum nodes in simulation is 100*/), | |
131 MakeUintegerAccessor (&RoutingProtocol::MaxQueueLen), | |
132 MakeUintegerChecker<uint32_t> ()) | |
133 .AddAttribute ("MaxQueuedPacketsPerDst", "Maximum number of packets that w e allow per destination to buffer.", | |
134 UintegerValue (5), | |
135 MakeUintegerAccessor (&RoutingProtocol::MaxQueuedPacketsPer Dst), | |
136 MakeUintegerChecker<uint32_t> ()) | |
137 .AddAttribute ("MaxQueueTime","Maximum time packets can be queued (in seco nds)", | |
138 TimeValue (Seconds (30)), | |
139 MakeTimeAccessor (&RoutingProtocol::MaxQueueTime), | |
140 MakeTimeChecker ()) | |
141 .AddAttribute ("EnableBuffering","Enables buffering of data packets if no route to destination is available", | |
142 BooleanValue (true), | |
143 MakeBooleanAccessor (&RoutingProtocol::SetEnableBufferFlag, | |
144 &RoutingProtocol::GetEnableBufferFlag ), | |
145 MakeBooleanChecker ()) | |
146 .AddAttribute ("EnableWST","Enables Weighted Settling Time for the updates before advertising", | |
147 BooleanValue (true), | |
148 MakeBooleanAccessor (&RoutingProtocol::SetWSTFlag, | |
149 &RoutingProtocol::GetWSTFlag), | |
150 MakeBooleanChecker ()) | |
151 .AddAttribute ("Holdtimes","Times the forwarding Interval to purge the rou te.", | |
152 UintegerValue (3), | |
153 MakeUintegerAccessor (&RoutingProtocol::Holdtimes), | |
154 MakeUintegerChecker<uint32_t> ()) | |
155 .AddAttribute ("WeightedFactor","WeightedFactor for the settling time if W eighted Settling Time is enabled", | |
156 DoubleValue (0.875), | |
157 MakeDoubleAccessor (&RoutingProtocol::WeightedFactor), | |
158 MakeDoubleChecker<double> ()) | |
159 .AddAttribute ("EnableRouteAggregation","Enables Weighted Settling Time fo r the updates before advertising", | |
160 BooleanValue (false), | |
161 MakeBooleanAccessor (&RoutingProtocol::SetEnableRAFlag, | |
162 &RoutingProtocol::GetEnableRAFlag), | |
163 MakeBooleanChecker ()) | |
164 .AddAttribute ("RouteAggregationTime","Time to aggregate updates before se nding them out (in seconds)", | |
165 TimeValue (Seconds (1)), | |
166 MakeTimeAccessor (&RoutingProtocol::RouteAggregationTime), | |
167 MakeTimeChecker ()); | |
168 return tid; | |
169 } | |
170 | |
171 RoutingProtocol::~RoutingProtocol () | |
172 { | |
173 } | |
174 | |
175 void | |
176 RoutingProtocol::DoDispose () | |
177 { | |
178 m_ipv4 = 0; | |
179 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::iterator iter = m_socketAddr esses.begin (); iter | |
180 != m_socketAddresses.end (); iter++) | |
181 { | |
182 iter->first->Close (); | |
183 } | |
184 m_socketAddresses.clear (); | |
185 Ipv4RoutingProtocol::DoDispose (); | |
186 } | |
187 | |
188 void | |
189 RoutingProtocol::Start () | |
190 { | |
191 m_scb = MakeCallback (&RoutingProtocol::Send,this); | |
192 m_ecb = MakeCallback (&RoutingProtocol::Drop,this); | |
193 m_periodicUpdateTimer.SetFunction (&RoutingProtocol::SendPeriodicUpdate,this); | |
194 m_periodicUpdateTimer.Schedule (MicroSeconds (UniformVariable ().GetInteger (0 ,1000))); | |
195 } | |
196 | |
197 Ptr<Ipv4Route> | |
198 RoutingProtocol::RouteOutput (Ptr<Packet> p, | |
199 const Ipv4Header &header, | |
200 Ptr<NetDevice> oif, | |
201 Socket::SocketErrno &sockerr) | |
202 { | |
Tom Henderson
2010/06/24 22:52:07
For merged code we would like to see use of the NS
| |
203 if (m_socketAddresses.empty ()) | |
204 { | |
205 sockerr = Socket::ERROR_NOROUTETOHOST; | |
206 NS_LOG_LOGIC ("No dsdv interfaces"); | |
207 Ptr<Ipv4Route> route; | |
208 return route; | |
209 } | |
210 std::map<Ipv4Address, RoutingTableEntry> removedAddresses; | |
211 sockerr = Socket::ERROR_NOTERROR; | |
212 Ptr<Ipv4Route> route; | |
213 Ipv4Address dst = header.GetDestination (); | |
214 NS_LOG_DEBUG ("Packet Size: " << p->GetSize () | |
215 << ", Packet id: " << p->GetUid () << ", Destinat ion address in Packet: " << dst); | |
216 RoutingTableEntry rt; | |
217 m_routingTable.Purge (holddownTime,removedAddresses); | |
218 for (std::map<Ipv4Address, RoutingTableEntry>::iterator rmItr = removedAddress es.begin (); | |
219 rmItr != removedAddresses.end (); ++rmItr) | |
220 { | |
221 rmItr->second.SetEntriesChanged (true); | |
222 rmItr->second.SetSeqNo (rmItr->second.GetSeqNo () + 1); | |
223 m_advRoutingTable.AddRoute (rmItr->second); | |
224 } | |
225 if (!removedAddresses.empty ()) | |
226 { | |
227 Simulator::Schedule (MicroSeconds (UniformVariable ().GetInteger (0,1000)) ,&RoutingProtocol::SendTriggeredUpdate,this); | |
228 } | |
229 if (m_routingTable.LookupRoute (dst,rt)) | |
230 { | |
231 if (EnableBuffering) | |
232 { | |
233 LookForQueuedPackets (); | |
234 } | |
235 if (rt.GetHop () == 1) | |
236 { | |
237 route = rt.GetRoute (); | |
238 NS_ASSERT (route != 0); | |
239 NS_LOG_DEBUG ("A route exists from " << route->GetSource () | |
240 << " to neighboring destination " | |
241 << route->GetDestination ()); | |
242 if (oif != 0 && route->GetOutputDevice () != oif) | |
243 { | |
244 NS_LOG_DEBUG ("Output device doesn't match. Dropped."); | |
245 sockerr = Socket::ERROR_NOROUTETOHOST; | |
246 return Ptr<Ipv4Route> (); | |
247 } | |
248 return route; | |
249 } | |
250 else | |
251 { | |
252 RoutingTableEntry newrt; | |
253 if (m_routingTable.LookupRoute (rt.GetNextHop (),newrt)) | |
254 { | |
255 route = newrt.GetRoute (); | |
256 NS_ASSERT (route != 0); | |
257 NS_LOG_DEBUG ("A route exists from " << route->GetSource () | |
258 << " to destination " << dst << " via " | |
259 << rt.GetNextHop ()); | |
260 if (oif != 0 && route->GetOutputDevice () != oif) | |
261 { | |
262 NS_LOG_DEBUG ("Output device doesn't match. Dropped."); | |
263 sockerr = Socket::ERROR_NOROUTETOHOST; | |
264 return Ptr<Ipv4Route> (); | |
265 } | |
266 return route; | |
267 } | |
268 } | |
269 } | |
270 | |
271 if (EnableBuffering) | |
272 { | |
273 uint32_t iif = (oif ? m_ipv4->GetInterfaceForDevice (oif) : -1); | |
274 DeferredRouteOutputTag tag (iif); | |
275 if (!p->PeekPacketTag (tag)) | |
276 { | |
277 p->AddPacketTag (tag); | |
278 } | |
279 } | |
280 return LoopbackRoute (header); | |
281 } | |
282 | |
283 void | |
284 RoutingProtocol::SendTriggeredUpdate () | |
285 { | |
286 std::map<Ipv4Address, RoutingTableEntry> allRoutes; | |
287 m_advRoutingTable.GetListOfAllRoutes (allRoutes); | |
288 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketA ddresses.begin (); j | |
289 != m_socketAddresses.end (); ++j) | |
290 { | |
291 DsdvHeader dsdvHeader; | |
292 Ptr<Socket> socket = j->first; | |
293 Ipv4InterfaceAddress iface = j->second; | |
294 Ptr<Packet> packet = Create<Packet> (); | |
295 for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = allRoute s.begin (); i != allRoutes.end (); ++i) | |
296 { | |
297 NS_LOG_LOGIC ("Destination: " << i->second.GetDestination () | |
298 << " SeqNo:" << i->second.GetSeqNo () << " HopCount:" | |
299 << i->second.GetHop ()+1); | |
300 RoutingTableEntry temp = i->second; | |
301 if ((i->second.GetEntriesChanged () == true) && (not m_advRoutingTable .AnyRunningEvent (temp.GetDestination ()))) | |
302 { | |
303 dsdvHeader.SetDst (i->second.GetDestination ()); | |
304 dsdvHeader.SetDstSeqno (i->second.GetSeqNo ()); | |
305 dsdvHeader.SetHopCount (i->second.GetHop () + 1); | |
306 temp.SetFlag (VALID); | |
307 temp.SetEntriesChanged (false); | |
308 m_advRoutingTable.DeleteIpv4Event (temp.GetDestination ()); | |
309 if (!(temp.GetSeqNo () % 2)) | |
310 { | |
311 m_routingTable.Update (temp); | |
312 } | |
313 packet->AddHeader (dsdvHeader); | |
314 m_advRoutingTable.DeleteRoute (temp.GetDestination ()); | |
315 NS_LOG_DEBUG ("Deleted this route from the advertised table"); | |
316 } | |
317 else | |
318 { | |
319 NS_LOG_DEBUG ("Event not expired,waiting in adv table"); | |
320 } | |
321 } | |
322 if (packet->GetSize () >= 12) | |
323 { | |
324 RoutingTableEntry temp2; | |
325 m_routingTable.LookupRoute (m_ipv4->GetAddress (1, 0).GetBroadcast (), temp2); | |
326 dsdvHeader.SetDst (m_ipv4->GetAddress (1, 0).GetLocal ()); | |
327 dsdvHeader.SetDstSeqno (temp2.GetSeqNo ()); | |
328 dsdvHeader.SetHopCount (temp2.GetHop () + 1); | |
329 NS_LOG_DEBUG ("Adding my update as well to the packet"); | |
330 packet->AddHeader (dsdvHeader); | |
331 socket->Send (packet); | |
332 NS_LOG_DEBUG ("Sent Triggered Update from " | |
333 << dsdvHeader.GetDst () | |
334 << " with packet id : " << packet->GetUid () << " and packet Size: " << packet->GetSize ()); | |
335 } | |
336 else | |
337 { | |
338 NS_LOG_DEBUG ("Update not sent as there are no updates to be triggered "); | |
339 } | |
340 } | |
341 } | |
342 | |
343 void | |
344 RoutingProtocol::SendPeriodicUpdate (Ipv4Address dst) | |
345 { | |
346 std::map<Ipv4Address, RoutingTableEntry> removedAddresses, allRoutes; | |
347 m_routingTable.Purge (holddownTime,removedAddresses); | |
348 MergeTriggerPeriodicUpdates (); | |
349 m_routingTable.GetListOfAllRoutes (allRoutes); | |
350 if (allRoutes.size () < 0) | |
351 { | |
352 return; | |
353 } | |
354 NS_LOG_DEBUG (m_mainAddress<< " is sending out its periodic update"); | |
355 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketA ddresses.begin (); j | |
356 != m_socketAddresses.end (); ++j) | |
357 { | |
358 Ptr<Socket> socket = j->first; | |
359 Ipv4InterfaceAddress iface = j->second; | |
360 Ptr<Packet> packet = Create<Packet> (); | |
361 for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = allRoute s.begin (); i != allRoutes.end (); ++i) | |
362 { | |
363 DsdvHeader dsdvHeader; | |
364 if (i->second.GetHop () == 0) | |
365 { | |
366 RoutingTableEntry ownEntry; | |
367 dsdvHeader.SetDst (m_ipv4->GetAddress (1,0).GetLocal ()); | |
368 dsdvHeader.SetDstSeqno (i->second.GetSeqNo () + 2); | |
369 dsdvHeader.SetHopCount (i->second.GetHop () + 1); | |
370 m_routingTable.LookupRoute (m_ipv4->GetAddress (1,0).GetBroadcast (),ownEntry); | |
371 ownEntry.SetSeqNo (dsdvHeader.GetDstSeqno ()); | |
372 m_routingTable.Update (ownEntry); | |
373 packet->AddHeader (dsdvHeader); | |
374 } | |
375 else | |
376 { | |
377 dsdvHeader.SetDst (i->second.GetDestination ()); | |
378 dsdvHeader.SetDstSeqno ((i->second.GetSeqNo ())); | |
379 dsdvHeader.SetHopCount (i->second.GetHop () + 1); | |
380 packet->AddHeader (dsdvHeader); | |
381 } | |
382 NS_LOG_DEBUG ("Forwarding the update for " << i->first); | |
383 NS_LOG_DEBUG ("Forwarding details are, Destination: " << dsdvHeader.Ge tDst () | |
384 << ", SeqNo:" << dsdvHeader.GetDstSeqno () | |
385 << ", HopCount:" << dsdvHeader.GetHopCou nt () | |
386 << ", LifeTime: "<< i->second.GetLifeTim e().GetSeconds()); | |
387 } | |
388 for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator rmItr = remo vedAddresses.begin (); rmItr | |
389 != removedAddresses.end (); ++rmItr) | |
390 { | |
391 DsdvHeader removedHeader; | |
392 removedHeader.SetDst (rmItr->second.GetDestination ()); | |
393 removedHeader.SetDstSeqno (rmItr->second.GetSeqNo () + 1); | |
394 removedHeader.SetHopCount (rmItr->second.GetHop () + 1); | |
395 packet->AddHeader (removedHeader); | |
396 NS_LOG_DEBUG ("Update for removed record is: Destination: " << removed Header.GetDst () | |
397 << " SeqNo:" << removedHeader.GetDstSeqn o () | |
398 << " HopCount:" << removedHeader.GetHopC ount ()); | |
399 } | |
400 socket->Send (packet); | |
401 NS_LOG_DEBUG ("Forwarding Packet UID is : " << packet->GetUid ()); | |
402 } | |
403 m_periodicUpdateTimer.Schedule (PeriodicUpdateInterval + MicroSeconds (25 * Un iformVariable ().GetInteger (0,1000))); | |
404 } | |
405 | |
406 bool | |
407 RoutingProtocol::RouteInput (Ptr<const Packet> p, | |
408 const Ipv4Header &header, | |
409 Ptr<const NetDevice> idev, | |
410 UnicastForwardCallback ucb, | |
411 MulticastForwardCallback mcb, | |
412 LocalDeliverCallback lcb, | |
413 ErrorCallback ecb) | |
414 { | |
415 NS_LOG_INFO (m_mainAddress << " received packet " << p->GetUid () | |
416 << " from " << header.GetSource () | |
417 << " on interface " << idev->GetAddress () | |
418 << " to destination " << header.GetDestination()); | |
419 if (m_socketAddresses.empty ()) | |
420 { | |
421 NS_LOG_DEBUG ("No dsdv interfaces"); | |
422 return false; | |
423 } | |
424 NS_ASSERT (m_ipv4 != 0); | |
425 // Check if input device supports IP | |
426 NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0); | |
427 int32_t iif = m_ipv4->GetInterfaceForDevice (idev); | |
428 | |
429 Ipv4Address dst = header.GetDestination (); | |
430 Ipv4Address origin = header.GetSource (); | |
431 | |
432 // Deferred route request | |
433 if (EnableBuffering == true && idev == m_lo) | |
434 { | |
435 DeferredRouteOutputTag tag; | |
436 if (p->PeekPacketTag (tag)) | |
437 { | |
438 DeferredRouteOutput (p,header,ucb,ecb); | |
439 return true; | |
440 } | |
441 } | |
442 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = | |
443 m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) | |
444 { | |
445 Ipv4InterfaceAddress iface = j->second; | |
446 if (origin == iface.GetLocal ()) | |
447 return true; | |
448 } | |
449 //LOCAL DELIVARY TO DSDV INTERFACES | |
450 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketA ddresses.begin (); j | |
451 != m_socketAddresses.end (); ++j) | |
452 { | |
453 Ipv4InterfaceAddress iface = j->second; | |
454 if (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()) == iif) | |
455 { | |
456 if (dst == iface.GetBroadcast ()) | |
457 { | |
458 NS_LOG_LOGIC ("Broadcast local delivery to " << iface.GetLocal ()) ; | |
459 Ptr<Packet> packet = p->Copy (); | |
460 lcb (p,header,iif); | |
461 if (header.GetTtl () > 1) | |
462 { | |
463 NS_LOG_LOGIC ("Forward broadcast. TTL " | |
464 << (uint16_t) header.GetTtl ()); | |
465 RoutingTableEntry toBroadcast; | |
466 if (m_routingTable.LookupRoute (dst,toBroadcast,true)) | |
467 { | |
468 Ptr<Ipv4Route> route = toBroadcast.GetRoute (); | |
469 ucb (route,packet,header); | |
470 } | |
471 else | |
472 { | |
473 NS_LOG_DEBUG ("No route to forward. Drop packet " | |
474 << p->GetUid ()); | |
475 } | |
476 } | |
477 return true; | |
478 } | |
479 } | |
480 } | |
481 | |
482 if (m_ipv4->IsDestinationAddress (dst, iif)) | |
483 { | |
484 NS_LOG_LOGIC ("Unicast local delivery to " << dst); | |
485 lcb (p, header, iif); | |
486 return true; | |
487 } | |
488 RoutingTableEntry toDst; | |
489 if (m_routingTable.LookupRoute (dst,toDst)) | |
490 { | |
491 RoutingTableEntry ne; | |
492 if (m_routingTable.LookupRoute (toDst.GetNextHop (),ne)) | |
493 { | |
494 Ptr<Ipv4Route> route = ne.GetRoute (); | |
495 NS_LOG_LOGIC (m_mainAddress << " is forwarding packet " << p->GetUid ( ) | |
496 << " to " << dst | |
497 << " from " << header.GetSource () | |
498 << " via nexthop neighbor " << toDst.GetNextHop ()) ; | |
499 ucb (route,p,header); | |
500 return true; | |
501 } | |
502 } | |
503 NS_LOG_LOGIC ("Drop packet " << p->GetUid () | |
504 << " as there is no route to forward it."); | |
505 return false; | |
506 } | |
507 | |
508 Ptr<Ipv4Route> | |
509 RoutingProtocol::LoopbackRoute (const Ipv4Header & hdr) const | |
510 { | |
511 NS_ASSERT (m_lo != 0); | |
512 Ptr<Ipv4Route> rt = Create<Ipv4Route> (); | |
513 rt->SetDestination (hdr.GetDestination ()); | |
514 rt->SetSource (hdr.GetSource ()); | |
515 rt->SetGateway (Ipv4Address ("127.0.0.1")); | |
516 rt->SetOutputDevice (m_lo); | |
517 return rt; | |
518 } | |
519 | |
520 void | |
521 RoutingProtocol::RecvDsdv (Ptr<Socket> socket) | |
522 { | |
523 Address sourceAddress; | |
524 Ptr<Packet> advpacket = Create<Packet> (); | |
525 Ptr<Packet> packet = socket->RecvFrom (sourceAddress); | |
526 InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddre ss); | |
527 Ipv4Address sender = inetSourceAddr.GetIpv4 (); | |
528 Ipv4Address receiver = m_socketAddresses[socket].GetLocal (); | |
529 Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (rec eiver)); | |
530 uint32_t packetSize = packet->GetSize (); | |
531 NS_LOG_DEBUG (m_mainAddress << " received dsdv packet of size: " << packetSize | |
532 << " and packet id: " << packet->GetUid ()); | |
533 uint32_t count = 0; | |
534 for (; packetSize > 0; packetSize = packetSize - 12) | |
535 { | |
536 NS_LOG_DEBUG("Processing new update"); | |
537 count=0; | |
538 DsdvHeader dsdvHeader, tempDsdvHeader; | |
539 packet->RemoveHeader (dsdvHeader); | |
540 /*Verifying if the packets sent by me were returned back to me. If yes, di scarding them!*/ | |
541 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_soc ketAddresses.begin (); j | |
542 != m_socketAddresses.end (); ++j) | |
543 { | |
544 Ipv4InterfaceAddress interface = j->second; | |
545 if (dsdvHeader.GetDst () == interface.GetLocal ()) | |
546 { | |
547 if (dsdvHeader.GetDstSeqno () % 2 == 1) | |
548 { | |
549 NS_LOG_DEBUG ( | |
550 "Sent Dsdv update back to the same Destination, " | |
551 "with infinite metric. Time left to send fwd update: " | |
552 << m_periodicUpdateTimer.GetDelayLeft ()); | |
553 count++; | |
554 } | |
555 else | |
556 { | |
557 NS_LOG_DEBUG ("Received update for my address. Discarding this ."); | |
558 count++; | |
559 } | |
560 } | |
561 } | |
562 if (count > 0) | |
563 { | |
564 continue; | |
565 } | |
566 NS_LOG_DEBUG ("Received a DSDV packet from " | |
567 << sender << " to " << receiver << ". Details a re: Destination: " << dsdvHeader.GetDst () << ", Seq No: " | |
568 << dsdvHeader.GetDstSeqno () << ", HopCount: " << dsdvHeader.GetHopCount ()); | |
569 RoutingTableEntry fwdTableEntry, advTableEntry; | |
570 EventId event; | |
571 bool permanentTableVerifier = m_routingTable.LookupRoute (dsdvHeader.GetDs t (),fwdTableEntry); | |
572 if (permanentTableVerifier == false) | |
573 { | |
574 if (dsdvHeader.GetDstSeqno () % 2 != 1) | |
575 { | |
576 NS_LOG_DEBUG ("Received New Valid Route!"); | |
577 RoutingTableEntry newEntry ( | |
578 /*device=*/dev, /*dst=*/ | |
579 dsdvHeader.GetDst (), /*seqno=*/ | |
580 dsdvHeader.GetDstSeqno (), | |
581 /*iface=*/m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiv er), 0), | |
582 /*hops=*/dsdvHeader.GetHopCount (), /*next hop=*/ | |
583 sender, /*lifetime=*/ | |
584 Simulator::Now (), /*settlingTime*/ | |
585 SettlingTime, /*entries changed*/ | |
586 true); | |
587 newEntry.SetFlag (VALID); | |
588 m_routingTable.AddRoute (newEntry); | |
589 NS_LOG_DEBUG("New Route added to adv table:"); | |
590 m_advRoutingTable.AddRoute (newEntry); | |
591 } | |
592 else | |
593 { | |
594 //received update not present in main routing table and also with in finite metric | |
595 NS_LOG_DEBUG("Discarding this update as this route is not present in " | |
596 "main routing table and received with infinite metric"); | |
597 } | |
598 } | |
599 else | |
600 { | |
601 if (!m_advRoutingTable.LookupRoute (dsdvHeader.GetDst (),advTableEntry )) | |
602 { | |
603 RoutingTableEntry tr; | |
604 std::map<Ipv4Address, RoutingTableEntry> allRoutes; | |
605 m_advRoutingTable.GetListOfAllRoutes (allRoutes); | |
606 for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = allRoutes.begin (); i != allRoutes.end (); ++i) | |
607 { | |
608 NS_LOG_DEBUG ("ADV table routes are:" << i->second.GetDestinat ion ()); | |
609 } | |
610 // present in fwd table and not in advtable | |
611 m_advRoutingTable.AddRoute (fwdTableEntry); | |
612 m_advRoutingTable.LookupRoute (dsdvHeader.GetDst (),advTableEntry) ; | |
613 } | |
614 if (dsdvHeader.GetDstSeqno () % 2 != 1) | |
615 { | |
616 if (dsdvHeader.GetDstSeqno () > advTableEntry.GetSeqNo ()) | |
617 { | |
618 // Received update with better seq number. Clear any old event s that are running | |
619 if (m_advRoutingTable.ForceDeleteIpv4Event (dsdvHeader.GetDst ())) | |
620 { | |
621 NS_LOG_DEBUG ("Canceling the timer to update route with be tter seq number"); | |
622 } | |
623 //if its a changed metric *nomatter* where the update came fro m, wait for WST | |
624 if (dsdvHeader.GetHopCount () != advTableEntry.GetHop ()) | |
625 { | |
626 advTableEntry.SetSeqNo (dsdvHeader.GetDstSeqno ()); | |
627 advTableEntry.SetLifeTime (Simulator::Now ()); | |
628 advTableEntry.SetFlag (VALID); | |
629 advTableEntry.SetEntriesChanged (true); | |
630 advTableEntry.SetNextHop (sender); | |
631 advTableEntry.SetHop (dsdvHeader.GetHopCount ()); | |
632 NS_LOG_DEBUG ("Received update with better sequence number and changed metric.Waiting for WST"); | |
633 Time tempSettlingtime = GetSettlingTime (dsdvHeader.GetDst ()); | |
634 advTableEntry.SetSettlingTime (tempSettlingtime); | |
635 NS_LOG_DEBUG ("Added Settling Time:" << tempSettlingtime.G etSeconds () | |
636 << "s as there is no event running for this route"); | |
637 event = Simulator::Schedule (tempSettlingtime,&RoutingProt ocol::SendTriggeredUpdate,this); | |
638 m_advRoutingTable.AddIpv4Event (dsdvHeader.GetDst (),event ); | |
639 NS_LOG_DEBUG ("EventCreated EventUID: " << event.GetUid () ); | |
640 // if received changed metric, use it but adv it only afte r wst | |
641 m_routingTable.Update (advTableEntry); | |
642 m_advRoutingTable.Update (advTableEntry); | |
643 } | |
644 else | |
645 { | |
646 // Received update with better seq number and same metric. | |
647 advTableEntry.SetSeqNo (dsdvHeader.GetDstSeqno ()); | |
648 advTableEntry.SetLifeTime (Simulator::Now ()); | |
649 advTableEntry.SetFlag (VALID); | |
650 advTableEntry.SetEntriesChanged (true); | |
651 advTableEntry.SetNextHop (sender); | |
652 advTableEntry.SetHop (dsdvHeader.GetHopCount ()); | |
653 m_advRoutingTable.Update (advTableEntry); | |
654 NS_LOG_DEBUG ("Route with better sequence number and same metric received. Advertised without WST"); | |
655 } | |
656 } | |
657 else if (dsdvHeader.GetDstSeqno () == advTableEntry.GetSeqNo ()) | |
658 { | |
659 if (dsdvHeader.GetHopCount () < advTableEntry.GetHop ()) | |
660 { | |
661 /*Received update with same seq number and better hop coun t. | |
662 * As the metric is changed, we will have to wait for WST before sending out this update. | |
663 */ | |
664 NS_LOG_DEBUG ("Canceling any existing timer to update rout e with same sequence number " | |
665 "and better hop count"); | |
666 m_advRoutingTable.ForceDeleteIpv4Event (dsdvHeader.GetDst ()); | |
667 advTableEntry.SetSeqNo (dsdvHeader.GetDstSeqno ()); | |
668 advTableEntry.SetLifeTime (Simulator::Now ()); | |
669 advTableEntry.SetFlag (VALID); | |
670 advTableEntry.SetEntriesChanged (true); | |
671 advTableEntry.SetNextHop (sender); | |
672 advTableEntry.SetHop (dsdvHeader.GetHopCount ()); | |
673 Time tempSettlingtime = GetSettlingTime (dsdvHeader.GetDst ()); | |
674 advTableEntry.SetSettlingTime (tempSettlingtime); | |
675 NS_LOG_DEBUG ("Added Settling Time," << tempSettlingtime.G etSeconds() | |
676 << " as there is no c urrent event running for this route"); | |
677 event = Simulator::Schedule (tempSettlingtime,&RoutingProt ocol::SendTriggeredUpdate,this); | |
678 m_advRoutingTable.AddIpv4Event (dsdvHeader.GetDst (),event ); | |
679 NS_LOG_DEBUG ("EventCreated EventUID: " << event.GetUid () ); | |
680 // if received changed metric, use it but adv it only afte r wst | |
681 m_routingTable.Update (advTableEntry); | |
682 m_advRoutingTable.Update (advTableEntry); | |
683 } | |
684 else | |
685 { | |
686 /*Received update with same seq number but with same or gr eater hop count. | |
687 * Discard that update. | |
688 */ | |
689 if (not m_advRoutingTable.AnyRunningEvent (dsdvHeader.GetD st ())) | |
690 { | |
691 /*update the timer only if nexthop address matches thu s discarding | |
692 * updates to that destination from other nodes. | |
693 */ | |
694 if(advTableEntry.GetNextHop()==sender){ | |
695 advTableEntry.SetLifeTime (Simulator::Now ()); | |
696 m_routingTable.Update (advTableEntry); | |
697 } | |
698 m_advRoutingTable.DeleteRoute ( | |
699 dsdvHeader.GetDst ()); | |
700 } | |
701 NS_LOG_DEBUG ("Received update with same seq number and " | |
702 "same/worst metric for, "<<dsdvHeader.GetDst ()<<". Discarding the update."); | |
703 } | |
704 } | |
705 else | |
706 { | |
707 // Received update with an old sequence number. Discard the up date | |
708 if (not m_advRoutingTable.AnyRunningEvent (dsdvHeader.GetDst ( ))) | |
709 { | |
710 m_advRoutingTable.DeleteRoute (dsdvHeader.GetDst ()); | |
711 } | |
712 NS_LOG_DEBUG (dsdvHeader.GetDst () << " : Received update with old seq number. Discarding the update."); | |
713 } | |
714 } | |
715 else | |
716 { | |
717 NS_LOG_DEBUG ("Route with infinite metric received for " | |
718 << dsdvHeader.GetDst () << " from " << sender); | |
719 // Delete route only if update was received from my nexthop neighb or | |
720 if (sender == advTableEntry.GetNextHop ()) | |
721 { | |
722 NS_LOG_DEBUG ("Triggering an update for this unreachable route :"); | |
723 std::map<Ipv4Address, RoutingTableEntry> dstsWithNextHopSrc; | |
724 m_routingTable.GetListOfDestinationWithNextHop (dsdvHeader.Get Dst (),dstsWithNextHopSrc); | |
725 m_routingTable.DeleteRoute (dsdvHeader.GetDst ()); | |
726 advTableEntry.SetSeqNo (dsdvHeader.GetDstSeqno ()); | |
727 advTableEntry.SetEntriesChanged (true); | |
728 m_advRoutingTable.Update (advTableEntry); | |
729 for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = ds tsWithNextHopSrc.begin (); i | |
730 != dstsWithNextHopSrc.end (); ++i) | |
731 { | |
732 i->second.SetSeqNo (i->second.GetSeqNo () + 1); | |
733 i->second.SetEntriesChanged (true); | |
734 m_advRoutingTable.AddRoute (i->second); | |
735 m_routingTable.DeleteRoute (i->second.GetDestination ()); | |
736 } | |
737 } | |
738 else | |
739 { | |
740 if (not m_advRoutingTable.AnyRunningEvent (dsdvHeader.GetDst ( ))) | |
741 { | |
742 m_advRoutingTable.DeleteRoute (dsdvHeader.GetDst ()); | |
743 } | |
744 NS_LOG_DEBUG (dsdvHeader.GetDst () << | |
745 " : Discard this link break update as it was rec eived from a different neighbor " | |
746 "and I can reach the destination"); | |
747 } | |
748 } | |
749 } | |
750 } | |
751 std::map<Ipv4Address, RoutingTableEntry> allRoutes; | |
752 m_advRoutingTable.GetListOfAllRoutes (allRoutes); | |
753 NS_LOG_DEBUG("Adv Table size: "<<allRoutes.size()); | |
754 if (EnableRouteAggregation && allRoutes.size () > 0) | |
755 { | |
756 Simulator::Schedule (RouteAggregationTime,&RoutingProtocol::SendTriggeredU pdate,this); | |
757 } | |
758 else | |
759 { | |
760 Simulator::Schedule (MicroSeconds (UniformVariable ().GetInteger (0,1000)) ,&RoutingProtocol::SendTriggeredUpdate,this); | |
761 } | |
762 } | |
763 | |
764 void | |
765 RoutingProtocol::SetIpv4 (Ptr<Ipv4> ipv4) | |
766 { | |
767 NS_ASSERT (ipv4 != 0); | |
768 NS_ASSERT (m_ipv4 == 0); | |
769 m_ipv4 = ipv4; | |
770 // Create lo route. It is asserted that the only one interface up for now is l oopback | |
771 NS_ASSERT (m_ipv4->GetNInterfaces () == 1 && m_ipv4->GetAddress (0, 0).GetLoca l () == Ipv4Address ("127.0.0.1")); | |
772 m_lo = m_ipv4->GetNetDevice (0); | |
773 NS_ASSERT (m_lo != 0); | |
774 // Remember lo route | |
775 RoutingTableEntry rt ( | |
776 /*device=*/ m_lo, /*dst=*/ | |
777 Ipv4Address::GetLoopback (), /*seqno=*/ | |
778 0, | |
779 /*iface=*/ Ipv4InterfaceAddress (Ipv4Address::GetLoopback (),Ipv4Mask ("255. 0.0.0")), | |
780 /*hops=*/ 0, /*next hop=*/ | |
781 Ipv4Address::GetLoopback (), | |
782 /*lifetime=*/ Simulator::GetMaximumSimulationTime ()); | |
783 rt.SetFlag (INVALID); | |
784 rt.SetEntriesChanged(false); | |
785 m_routingTable.AddRoute (rt); | |
786 Simulator::ScheduleNow (&RoutingProtocol::Start,this); | |
787 } | |
788 | |
789 void | |
790 RoutingProtocol::NotifyInterfaceUp (uint32_t i) | |
791 { | |
792 NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal () | |
793 << " interface is up"); | |
794 Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); | |
795 Ipv4InterfaceAddress iface = l3->GetAddress (i,0); | |
796 if (iface.GetLocal () == Ipv4Address ("127.0.0.1")) | |
797 { | |
798 return; | |
799 } | |
800 // Create a socket to listen only on this interface | |
801 Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),UdpSocketFactory ::GetTypeId ()); | |
802 NS_ASSERT (socket != 0); | |
803 socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvDsdv,this)); | |
804 socket->Bind (InetSocketAddress (iface.GetLocal (),DSDV_PORT)); | |
805 socket->Connect (InetSocketAddress (iface.GetBroadcast (),DSDV_PORT)); | |
806 socket->SetAttribute ("IpTtl",UintegerValue (1)); | |
807 m_socketAddresses.insert (std::make_pair (socket,iface)); | |
808 // Add local broadcast record to the routing table | |
809 Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (ifa ce.GetLocal ())); | |
810 RoutingTableEntry rt (/*device=*/ dev, /*dst=*/iface.GetBroadcast (), /*seqno= */0,/*iface=*/ iface,/*hops=*/0, | |
811 /*next hop=*/iface.GetBroadcast (), /*lifetime=*/Simulat or::GetMaximumSimulationTime ()); | |
812 m_routingTable.AddRoute (rt); | |
813 m_mainAddress = iface.GetLocal(); | |
814 NS_ASSERT (m_mainAddress != Ipv4Address ()); | |
815 } | |
816 | |
817 void | |
818 RoutingProtocol::NotifyInterfaceDown (uint32_t i) | |
819 { | |
820 Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); | |
821 Ptr<NetDevice> dev = l3->GetNetDevice (i); | |
822 Ptr<Socket> socket = FindSocketWithInterfaceAddress (m_ipv4->GetAddress (i,0)) ; | |
823 NS_ASSERT (socket); | |
824 socket->Close (); | |
825 m_socketAddresses.erase (socket); | |
826 if (m_socketAddresses.empty ()) | |
827 { | |
828 NS_LOG_LOGIC ("No dsdv interfaces"); | |
829 m_routingTable.Clear (); | |
830 return; | |
831 } | |
832 m_routingTable.DeleteAllRoutesFromInterface (m_ipv4->GetAddress (i,0)); | |
833 m_advRoutingTable.DeleteAllRoutesFromInterface (m_ipv4->GetAddress (i,0)); | |
834 } | |
835 | |
836 void | |
837 RoutingProtocol::NotifyAddAddress (uint32_t i, | |
838 Ipv4InterfaceAddress address) | |
839 { | |
840 NS_LOG_FUNCTION (this << " interface " << i << " address " << address); | |
841 Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); | |
842 if (!l3->IsUp (i)) | |
843 { | |
844 return; | |
845 } | |
846 Ipv4InterfaceAddress iface = l3->GetAddress (i,0); | |
847 Ptr<Socket> socket = FindSocketWithInterfaceAddress (iface); | |
848 if (!socket) | |
849 { | |
850 if (iface.GetLocal () == Ipv4Address ("127.0.0.1")) | |
851 return; | |
852 Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),UdpSocketFac tory::GetTypeId ()); | |
853 NS_ASSERT (socket != 0); | |
854 socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvDsdv,this)); | |
855 socket->Bind (InetSocketAddress (iface.GetLocal (),DSDV_PORT)); | |
856 socket->Connect (InetSocketAddress (iface.GetBroadcast (),DSDV_PORT)); | |
857 m_socketAddresses.insert (std::make_pair (socket,iface)); | |
858 Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (iface.GetLocal ())); | |
859 RoutingTableEntry rt (/*device=*/ dev, /*dst=*/iface.GetBroadcast (),/*seq no=*/ 0, /*iface=*/iface,/*hops=*/0, | |
860 /*next hop=*/ iface.GetBroadcast (), /*lifetime=*/Si mulator::GetMaximumSimulationTime ()); | |
861 m_routingTable.AddRoute (rt); | |
862 } | |
863 } | |
864 | |
865 void | |
866 RoutingProtocol::NotifyRemoveAddress (uint32_t i, | |
867 Ipv4InterfaceAddress address) | |
868 { | |
869 Ptr<Socket> socket = FindSocketWithInterfaceAddress (address); | |
870 if (socket) | |
871 { | |
872 m_socketAddresses.erase (socket); | |
873 Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); | |
874 if (l3->GetNAddresses (i)) | |
875 { | |
876 Ipv4InterfaceAddress iface = l3->GetAddress (i,0); | |
877 // Create a socket to listen only on this interface | |
878 Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),UdpSocke tFactory::GetTypeId ()); | |
879 NS_ASSERT (socket != 0); | |
880 socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvDsdv,this )); | |
881 socket->Bind (InetSocketAddress (iface.GetLocal (),DSDV_PORT)); | |
882 socket->Connect (InetSocketAddress (iface.GetBroadcast (),DSDV_PORT)); | |
883 m_socketAddresses.insert (std::make_pair (socket,iface)); | |
884 } | |
885 } | |
886 } | |
887 | |
888 Ptr<Socket> | |
889 RoutingProtocol::FindSocketWithInterfaceAddress (Ipv4InterfaceAddress addr) cons t | |
890 { | |
891 for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketA ddresses.begin (); j | |
892 != m_socketAddresses.end (); ++j) | |
893 { | |
894 Ptr<Socket> socket = j->first; | |
895 Ipv4InterfaceAddress iface = j->second; | |
896 if (iface == addr) | |
897 { | |
898 return socket; | |
899 } | |
900 } | |
901 Ptr<Socket> socket; | |
902 return socket; | |
903 } | |
904 | |
905 void | |
906 RoutingProtocol::Send (Ptr<Ipv4Route> route, | |
907 Ptr<const Packet> packet, | |
908 const Ipv4Header & header) | |
909 { | |
910 Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> (); | |
911 NS_ASSERT (l3 != 0); | |
912 Ptr<Packet> p = packet->Copy (); | |
913 l3->Send (p,route->GetSource (),header.GetDestination (),header.GetProtocol () ,route); | |
914 } | |
915 | |
916 void | |
917 RoutingProtocol::DeferredRouteOutput (Ptr<const Packet> p, | |
918 const Ipv4Header & header, | |
919 UnicastForwardCallback ucb, | |
920 ErrorCallback ecb) | |
921 { | |
922 NS_ASSERT (p != 0 && p != Ptr<Packet> ()); | |
923 | |
924 QueueEntry newEntry (p,header,ucb,ecb); | |
925 bool result = m_queue.Enqueue (newEntry); | |
926 if (result) | |
927 NS_LOG_DEBUG ("Added packet " << p->GetUid () << " to queue."); | |
928 } | |
929 | |
930 void | |
931 RoutingProtocol::Drop (Ptr<const Packet> packet, | |
932 const Ipv4Header & header, | |
933 Socket::SocketErrno err) | |
934 { | |
935 NS_LOG_DEBUG (m_mainAddress << " drop packet " << packet->GetUid () << " to " | |
936 << header.GetDestination () << " from queue. Error " << err ); | |
937 } | |
938 | |
939 void | |
940 RoutingProtocol::LookForQueuedPackets () | |
941 { | |
942 Ptr<Ipv4Route> route; | |
943 std::map<Ipv4Address, RoutingTableEntry> allRoutes; | |
944 m_routingTable.GetListOfAllRoutes (allRoutes); | |
945 for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = allRoutes.be gin (); i != allRoutes.end (); ++i) | |
946 { | |
947 RoutingTableEntry rt; | |
948 rt = i->second; | |
949 if (m_queue.Find (rt.GetDestination ())) | |
950 { | |
951 if (rt.GetHop () == 1) | |
952 { | |
953 route = rt.GetRoute (); | |
954 NS_LOG_LOGIC ("A route exists from " << route->GetSource () | |
955 << " to neighboring destinati on " | |
956 << route->GetDestination ()); | |
957 NS_ASSERT (route != 0); | |
958 } | |
959 else | |
960 { | |
961 RoutingTableEntry newrt; | |
962 m_routingTable.LookupRoute (rt.GetNextHop (),newrt); | |
963 route = newrt.GetRoute (); | |
964 NS_LOG_LOGIC ("A route exists from " << route->GetSource () | |
965 << " to destination " << rout e->GetDestination () << " via " | |
966 << rt.GetNextHop ()); | |
967 NS_ASSERT (route != 0); | |
968 } | |
969 SendPacketFromQueue (rt.GetDestination (),route); | |
970 } | |
971 } | |
972 } | |
973 | |
974 void | |
975 RoutingProtocol::SendPacketFromQueue (Ipv4Address dst, | |
976 Ptr<Ipv4Route> route) | |
977 { | |
978 QueueEntry queueEntry; | |
979 if (m_queue.Dequeue (dst,queueEntry)) | |
980 { | |
981 DeferredRouteOutputTag tag; | |
982 Ptr<Packet> p = ConstCast<Packet> (queueEntry.GetPacket ()); | |
983 if (p->RemovePacketTag (tag)) | |
984 { | |
985 if (tag.oif != -1 && tag.oif != m_ipv4->GetInterfaceForDevice (route-> GetOutputDevice ())) | |
986 { | |
987 NS_LOG_DEBUG ("Output device doesn't match. Dropped."); | |
988 return; | |
989 } | |
990 } | |
991 UnicastForwardCallback ucb = queueEntry.GetUnicastForwardCallback (); | |
992 Ipv4Header header = queueEntry.GetIpv4Header (); | |
993 header.SetSource (route->GetSource ()); | |
994 header.SetTtl (header.GetTtl () + 1); // compensate extra TTL decrement by fake loopback routing | |
995 ucb (route,p,header); | |
996 if (m_queue.GetSize () != 0 && m_queue.Find (dst)) | |
997 { | |
998 Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,10 0)), | |
999 &RoutingProtocol::SendPacketFromQueue,this,dst,ro ute); | |
1000 } | |
1001 } | |
1002 } | |
1003 | |
1004 Time | |
1005 RoutingProtocol::GetSettlingTime (Ipv4Address address) | |
1006 { | |
1007 RoutingTableEntry mainrt; | |
1008 Time weightedTime; | |
1009 m_routingTable.LookupRoute (address,mainrt); | |
1010 if (EnableWST) | |
1011 { | |
1012 if (mainrt.GetSettlingTime () == Seconds (0)) | |
1013 { | |
1014 return Seconds (0); | |
1015 } | |
1016 else | |
1017 { | |
1018 NS_LOG_DEBUG ("Route SettlingTime: " << mainrt.GetSettlingTime ().GetS econds() | |
1019 << " and LifeTime:" << mainrt.Get LifeTime ().GetSeconds()); | |
1020 weightedTime = (Scalar (WeightedFactor) * mainrt.GetSettlingTime ()) + (Scalar (1.0 - WeightedFactor) | |
1021 * mainrt.GetLifeTime ()); | |
1022 NS_LOG_DEBUG ("Calculated weightedTime:" << weightedTime.GetSeconds()) ; | |
1023 return weightedTime; | |
1024 } | |
1025 } | |
1026 return mainrt.GetSettlingTime (); | |
1027 } | |
1028 | |
1029 void | |
1030 RoutingProtocol::MergeTriggerPeriodicUpdates () | |
1031 { | |
1032 std::map<Ipv4Address, RoutingTableEntry> allRoutes; | |
1033 m_advRoutingTable.GetListOfAllRoutes (allRoutes); | |
1034 if (allRoutes.size () > 0) | |
1035 { | |
1036 for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = allRoute s.begin (); i != allRoutes.end (); ++i) | |
1037 { | |
1038 RoutingTableEntry advEntry = i->second; | |
1039 if ((advEntry.GetEntriesChanged () == true) && (not m_advRoutingTable. AnyRunningEvent (advEntry.GetDestination ()))) | |
1040 { | |
1041 if (!(advEntry.GetSeqNo () % 2)) | |
1042 { | |
1043 advEntry.SetFlag (VALID); | |
1044 advEntry.SetEntriesChanged (false); | |
1045 m_routingTable.Update (advEntry); | |
1046 NS_LOG_DEBUG ("Merged update for " << advEntry.GetDestination () << " with main routing Table"); | |
1047 } | |
1048 m_advRoutingTable.DeleteRoute (advEntry.GetDestination ()); | |
1049 } | |
1050 else | |
1051 { | |
1052 NS_LOG_DEBUG ("Event currently running. Cannot Merge Routing Table s"); | |
1053 } | |
1054 } | |
1055 } | |
1056 } | |
1057 } | |
1058 } | |
OLD | NEW |