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