From 522bd8dbccc4d75ebe3c4295ef42fbb46cac7be0 Mon Sep 17 00:00:00 2001 From: Pavel Boyko Date: Tue, 18 Aug 2009 15:07:25 +0400 Subject: [PATCH] Includes cleanup + layer 2 link failure detection (untested) --- src/internet-stack/ipv4-interface.cc | 15 +++++++- src/internet-stack/ipv4-interface.h | 7 +++- src/internet-stack/wscript | 5 +++ src/routing/aodv/aodv-neighbor.cc | 47 +++++++++++++++++++++-- src/routing/aodv/aodv-neighbor.h | 25 ++++++++++-- src/routing/aodv/aodv-routing-protocol.cc | 35 ++++++++++++++--- src/routing/aodv/aodv-routing-protocol.h | 4 +- 7 files changed, 122 insertions(+), 16 deletions(-) diff --git a/src/internet-stack/ipv4-interface.cc b/src/internet-stack/ipv4-interface.cc index c54155152..9ca20cfa2 100644 --- a/src/internet-stack/ipv4-interface.cc +++ b/src/internet-stack/ipv4-interface.cc @@ -42,7 +42,8 @@ Ipv4Interface::GetTypeId (void) .AddAttribute ("ArpCache", "The arp cache for this ipv4 interface", PointerValue (0), - MakePointerAccessor (&Ipv4Interface::m_cache), + MakePointerAccessor (&Ipv4Interface::SetArpCache, + &Ipv4Interface::GetArpCache), MakePointerChecker ()) ; ; @@ -128,6 +129,18 @@ Ipv4Interface::GetMetric (void) const return m_metric; } +void +Ipv4Interface::SetArpCache (Ptr a) +{ + m_cache = a; +} + +Ptr +Ipv4Interface::GetArpCache () const +{ + return m_cache; +} + /** * These are IP interface states and may be distinct from * NetDevice states, such as found in real implementations diff --git a/src/internet-stack/ipv4-interface.h b/src/internet-stack/ipv4-interface.h index 0dcf732bb..671d58f07 100644 --- a/src/internet-stack/ipv4-interface.h +++ b/src/internet-stack/ipv4-interface.h @@ -56,12 +56,17 @@ public: void SetNode (Ptr node); void SetDevice (Ptr device); + void SetArpCache (Ptr); /** * \returns the underlying NetDevice. This method cannot return zero. */ Ptr GetDevice (void) const; - + /** + * \return ARP cache used by this interface + */ + Ptr GetArpCache () const; + /** * \param metric configured routing metric (cost) of this interface * diff --git a/src/internet-stack/wscript b/src/internet-stack/wscript index 9d4ea3118..d6cabeb6a 100644 --- a/src/internet-stack/wscript +++ b/src/internet-stack/wscript @@ -108,6 +108,11 @@ def build(bld): 'tcp-header.h', 'sequence-number.h', 'icmpv4.h', + # used by routing + 'ipv4-interface.h', + 'ipv4-l3-protocol.h', + 'arp-cache.h', + 'sgi-hashmap.h', ] if bld.env['NSC_ENABLED']: diff --git a/src/routing/aodv/aodv-neighbor.cc b/src/routing/aodv/aodv-neighbor.cc index bbd95c82e..8d3037c8c 100644 --- a/src/routing/aodv/aodv-neighbor.cc +++ b/src/routing/aodv/aodv-neighbor.cc @@ -31,15 +31,17 @@ #include "ns3/log.h" #include +NS_LOG_COMPONENT_DEFINE ("AodvNeighbors"); + namespace ns3 { namespace aodv { - Neighbors::Neighbors (Time delay) : m_ntimer (Timer::CANCEL_ON_DESTROY) { m_ntimer.SetDelay(delay); m_ntimer.SetFunction(&Neighbors::Purge, this); + m_txErrorCallback = MakeCallback (& Neighbors::ProcessTxError, this); } bool @@ -62,7 +64,6 @@ Neighbors::GetExpireTime (Ipv4Address addr) return Seconds(0); } - void Neighbors::Update (Ipv4Address addr, Time expire ) { @@ -72,8 +73,20 @@ Neighbors::Update (Ipv4Address addr, Time expire ) i->m_expireTime = std::max(expire + Simulator::Now (), i->m_expireTime); return; } - struct Neighbor neighbor = - { addr, expire + Simulator::Now () }; + + // Lookup mac address + Mac48Address hwaddr; + for (std::vector >::const_iterator i = m_arp.begin(); i != m_arp.end(); ++i) + { + ArpCache::Entry * entry = (*i)->Lookup (addr); + if (entry != 0 && entry->IsAlive () && ! entry->IsExpired ()) + { + hwaddr = Mac48Address::ConvertFrom(entry->GetMacAddress ()); + break; + } + } + + Neighbor neighbor (addr, hwaddr, expire + Simulator::Now ()); m_nb.push_back (neighbor); Purge (); } @@ -102,6 +115,32 @@ Neighbors::ScheduleTimer () m_ntimer.Schedule(); } +void +Neighbors::AddArpCache (Ptr a) +{ + m_arp.push_back(a); +} + +void +Neighbors::DelArpCache (Ptr a) +{ + m_arp.erase(std::remove(m_arp.begin(), m_arp.end(), a), m_arp.end()); +} + + +void +Neighbors::ProcessTxError (WifiMacHeader const & hdr) +{ + Mac48Address addr = hdr.GetAddr1(); + + for (std::vector::iterator i = m_nb.begin (); i != m_nb.end (); ++i) + if (i->m_hardwareAddress == addr) + { + NS_LOG_LOGIC ("Close link to " << i->m_neighborAddress << " because of layer 2 TX error notification"); + i->m_expireTime = Simulator::Now(); + } + Purge(); +} #ifdef RUN_SELF_TESTS /// Unit test for neighbors diff --git a/src/routing/aodv/aodv-neighbor.h b/src/routing/aodv/aodv-neighbor.h index 22031d104..1e897dd9a 100644 --- a/src/routing/aodv/aodv-neighbor.h +++ b/src/routing/aodv/aodv-neighbor.h @@ -34,9 +34,9 @@ #include "ns3/timer.h" #include "ns3/ipv4-address.h" #include "ns3/callback.h" +#include "ns3/wifi-mac-header.h" +#include "ns3/arp-cache.h" #include -# - namespace ns3 { @@ -52,10 +52,14 @@ class Neighbors public: /// c-tor Neighbors (Time delay); + /// Neighbor description struct Neighbor { Ipv4Address m_neighborAddress; + Mac48Address m_hardwareAddress; Time m_expireTime; + + Neighbor(Ipv4Address ip, Mac48Address mac, Time t) : m_neighborAddress(ip), m_hardwareAddress(mac), m_expireTime(t) {} }; /// Return expire time for neighbor node with address addr, if exists, else return 0. Time GetExpireTime (Ipv4Address addr); @@ -69,6 +73,14 @@ public: void ScheduleTimer (); /// Remove all entries void Clear () { m_nb.clear (); } + + /// Add ARP cache to be used to allow layer 2 notifications processing + void AddArpCache (Ptr); + /// Don't use given ARP cache any more (interface is down) + void DelArpCache (Ptr); + /// Get callback to ProcessTxError + Callback GetTxErrorCallback () const { return m_txErrorCallback; } + ///\name Handle link failure callback //\{ void SetCallback (Callback cb) { m_handleLinleFailure = cb;} @@ -79,15 +91,22 @@ private: { bool operator()(const struct Neighbor & nb) const { - return (nb.m_expireTime < Simulator::Now()); + return (nb.m_expireTime <= Simulator::Now()); /*<= is important here*/ } }; /// link failure callback Callback m_handleLinleFailure; + /// TX error callback + Callback m_txErrorCallback; /// Timer for neighbor's list. Schedule Purge(). Timer m_ntimer; /// vector of entries std::vector m_nb; + /// list of ARP cached to be used for layer 2 notifications processing + std::vector > m_arp; + + /// Process layer 2 TX error notification + void ProcessTxError (WifiMacHeader const &); }; } diff --git a/src/routing/aodv/aodv-routing-protocol.cc b/src/routing/aodv/aodv-routing-protocol.cc index 59285c217..c2efaf447 100644 --- a/src/routing/aodv/aodv-routing-protocol.cc +++ b/src/routing/aodv/aodv-routing-protocol.cc @@ -41,9 +41,9 @@ #include "ns3/udp-header.h" #include "ns3/nstime.h" #include "ns3/net-device.h" - #include "ns3/udp-socket-factory.h" -#include "src/internet-stack/udp-l4-protocol.h" +#include "ns3/wifi-net-device.h" +#include "ns3/adhoc-wifi-mac.h" #include NS_LOG_COMPONENT_DEFINE ("AodvRoutingProtocol"); @@ -369,6 +369,7 @@ RoutingProtocol::NotifyInterfaceUp (uint32_t i ) Ipv4InterfaceAddress iface = interface->GetAddress (0); if (iface.GetLocal () == Ipv4Address ("127.0.0.1")) return; + // Create a socket to listen only on this interface Ptr socket = Socket::CreateSocket (GetObject (), UdpSocketFactory::GetTypeId()); NS_ASSERT (socket != 0); @@ -382,12 +383,38 @@ RoutingProtocol::NotifyInterfaceUp (uint32_t i ) RoutingTableEntry rt (/*device=*/dev, /*dst=*/iface.GetBroadcast (), /*know seqno=*/true, /*seqno=*/0, /*iface=*/iface, /*hops=*/1, /*next hop=*/iface.GetBroadcast (), /*lifetime=*/Seconds (1e9)); // TODO use infty m_routingTable.AddRoute (rt); + + // Allow neighbor manager use this interface for layer 2 feedback if possible + Ptr wifi = dev->GetObject (); + if (wifi == 0) return; + Ptr mac = wifi->GetMac ()->GetObject (); + if (mac == 0) return; + + mac->TraceConnectWithoutContext("TxErrHeader", m_nb.GetTxErrorCallback()); + m_nb.AddArpCache (interface->GetArpCache()); } void RoutingProtocol::NotifyInterfaceDown (uint32_t i ) { NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ()); + + // Discable layer 2 link state monitoring (if possible) + Ptr l3 = m_ipv4->GetObject (); + Ptr interface = l3->GetInterface (i); + Ptr dev = interface->GetDevice(); + Ptr wifi = dev->GetObject (); + if (wifi != 0) + { + Ptr mac = wifi->GetMac ()->GetObject (); + if (mac != 0) + { + mac->TraceDisconnectWithoutContext ("TxErrHeader", m_nb.GetTxErrorCallback()); + m_nb.DelArpCache (interface->GetArpCache()); + } + } + + // Close socket Ptr socket = FindSocketWithInterfaceAddress (m_ipv4->GetAddress (i, 0)); NS_ASSERT (socket); socket->Close (); @@ -1173,8 +1200,6 @@ RoutingProtocol::SendHello () } } - - void RoutingProtocol::SendPacketFromQueue (Ipv4Address dst, Ptr route ) { @@ -1330,7 +1355,7 @@ RoutingProtocol::SendRerrMessage (Ptr packet, std::vector p { Ptr socket = FindSocketWithInterfaceAddress (*i); NS_ASSERT (socket); - NS_LOG_LOGIC ("broadcast RERR meassage from interface " << i->GetLocal()); + NS_LOG_LOGIC ("broadcast RERR message from interface " << i->GetLocal()); socket->Send (packet); } diff --git a/src/routing/aodv/aodv-routing-protocol.h b/src/routing/aodv/aodv-routing-protocol.h index 5dcb78ea6..038911973 100644 --- a/src/routing/aodv/aodv-routing-protocol.h +++ b/src/routing/aodv/aodv-routing-protocol.h @@ -34,8 +34,6 @@ #include "id-cache.h" #include "aodv-neighbor.h" -#include "src/internet-stack/ipv4-l3-protocol.h" - #include "ns3/object.h" #include "ns3/packet.h" #include "ns3/node.h" @@ -43,6 +41,8 @@ #include "ns3/timer.h" #include "ns3/ipv4.h" #include "ns3/ipv4-routing-protocol.h" +#include "ns3/ipv4-interface.h" +#include "ns3/ipv4-l3-protocol.h" #include namespace ns3