diff -r b5bc10de166d examples/routing/olsr-hna.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/routing/olsr-hna.cc Sat Mar 13 22:39:08 2010 +0530 @@ -0,0 +1,263 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +// +// This script, adapted from examples/wireless/wifi-simple-adhoc illustrates +// the use of OLSR HNA. +// +// Network Topology: +// +// |------ OLSR ------| |---- non-OLSR ----| +// A )))) (((( B ------------------- C +// 10.1.1.1 10.1.1.2 172.16.1.2 172.16.1.1 +// +// Node A needs to send a UDP packet to node C. This can be done only after +// A receives an HNA message from B, in which B announces 172.16.1.0/24 +// as an associated network. +// +// If no HNA message is generated by B, a will not be able to form a route to C. +// This can be verified as follows: +// +// ./waf --run olsr-hna +// +// There are two ways to make a node to generate HNA messages. +// +// One way is to use olsr::RoutingProtocol::SetRoutingTableAssociation () +// to use which you may run: +// +// ./waf --run "olsr-hna --assocMethod1=1" +// +// The other way is to use olsr::RoutingProtocol::AddHostNetworkAssociation () +// to use which you may run: +// +// ./waf --run "olsr-hna --assocMethod2=1" +// + +#include "ns3/core-module.h" +#include "ns3/common-module.h" +#include "ns3/node-module.h" +#include "ns3/helper-module.h" +#include "ns3/mobility-module.h" +#include "ns3/contrib-module.h" +#include "ns3/wifi-module.h" +#include "ns3/ipv4-list-routing.h" +#include "ns3/olsr-routing-protocol.h" + +#include +#include +#include +#include + +NS_LOG_COMPONENT_DEFINE ("OlsrHna"); + +using namespace ns3; + +void ReceivePacket (Ptr socket) +{ + NS_LOG_UNCOND ("Received one packet!"); +} + +static void GenerateTraffic (Ptr socket, uint32_t pktSize, + uint32_t pktCount, Time pktInterval ) +{ + if (pktCount > 0) + { + socket->Send (Create (pktSize)); + Simulator::Schedule (pktInterval, &GenerateTraffic, + socket, pktSize,pktCount-1, pktInterval); + } + else + { + socket->Close (); + } +} + + +int main (int argc, char *argv[]) +{ + std::string phyMode ("wifib-1mbs"); + double rss = -80; // -dBm + uint32_t packetSize = 1000; // bytes + uint32_t numPackets = 1; + double interval = 1.0; // seconds + bool verbose = false; + bool assocMethod1 = false; + bool assocMethod2 = false; + + CommandLine cmd; + + cmd.AddValue ("phyMode", "Wifi Phy mode", phyMode); + cmd.AddValue ("rss", "received signal strength", rss); + cmd.AddValue ("packetSize", "size of application packet sent", packetSize); + cmd.AddValue ("numPackets", "number of packets generated", numPackets); + cmd.AddValue ("interval", "interval (seconds) between packets", interval); + cmd.AddValue ("verbose", "turn on all WifiNetDevice log components", verbose); + cmd.AddValue ("assocMethod1", "Use SetRoutingTableAssociation () method", assocMethod1); + cmd.AddValue ("assocMethod2", "Use AddHostNetworkAssociation () method", assocMethod2); + + cmd.Parse (argc, argv); + // Convert to time object + Time interPacketInterval = Seconds (interval); + + // disable fragmentation for frames below 2200 bytes + Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200")); + // turn off RTS/CTS for frames below 2200 bytes + Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200")); + // Fix non-unicast data rate to be the same as that of unicast + Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode", + StringValue (phyMode)); + + NodeContainer olsrNodes; + olsrNodes.Create (2); + + NodeContainer csmaNodes; + csmaNodes.Create (1); + + // The below set of helpers will help us to put together the wifi NICs we want + WifiHelper wifi; + if (verbose) + { + wifi.EnableLogComponents (); // Turn on all Wifi logging + } + wifi.SetStandard (WIFI_PHY_STANDARD_80211b); + + YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default (); + // This is one parameter that matters when using FixedRssLossModel + // set it to zero; otherwise, gain will be added + wifiPhy.Set ("RxGain", DoubleValue (0) ); + // ns-3 supports RadioTap and Prism tracing extensions for 802.11b + wifiPhy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO); + + YansWifiChannelHelper wifiChannel ; + wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel"); + // The below FixedRssLossModel will cause the rss to be fixed regardless + // of the distance between the two stations, and the transmit power + wifiChannel.AddPropagationLoss ("ns3::FixedRssLossModel","Rss",DoubleValue(rss)); + wifiPhy.SetChannel (wifiChannel.Create ()); + + // Add a non-QoS upper mac, and disable rate control + NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default (); + wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", + "DataMode",StringValue(phyMode), + "ControlMode",StringValue(phyMode)); + // Set it to adhoc mode + wifiMac.SetType ("ns3::AdhocWifiMac"); + NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, olsrNodes); + + CsmaHelper csma; + csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000))); + csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2))); + NetDeviceContainer csmaDevices = csma.Install (NodeContainer (csmaNodes.Get(0), olsrNodes.Get(1))); + + // Note that with FixedRssLossModel, the positions below are not + // used for received signal strength. + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector (0.0, 0.0, 0.0)); + positionAlloc->Add (Vector (5.0, 0.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (olsrNodes); + + OlsrHelper olsr; + + // Specify Node B's csma device as a non-OLSR device. + olsr.ExcludeInterface (olsrNodes.Get (1), 2); + + Ipv4StaticRoutingHelper staticRouting; + + Ipv4ListRoutingHelper list; + list.Add (staticRouting, 0); + list.Add (olsr, 10); + + InternetStackHelper internet_olsr; + internet_olsr.SetRoutingHelper (list); + internet_olsr.Install (olsrNodes); + + InternetStackHelper internet_csma; + internet_csma.Install (csmaNodes); + + Ipv4AddressHelper ipv4; + NS_LOG_INFO ("Assign IP Addresses."); + ipv4.SetBase ("10.1.1.0", "255.255.255.0"); + ipv4.Assign (devices); + + ipv4.SetBase ("172.16.1.0", "255.255.255.0"); + ipv4.Assign (csmaDevices); + + TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); + Ptr recvSink = Socket::CreateSocket (csmaNodes.Get(0), tid); + InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80); + recvSink->Bind (local); + recvSink->SetRecvCallback (MakeCallback (&ReceivePacket)); + + Ptr source = Socket::CreateSocket (olsrNodes.Get (0), tid); + InetSocketAddress remote = InetSocketAddress (Ipv4Address ("172.16.1.1"), 80); + source->Connect (remote); + + // Obtain olsr::RoutingProtocol instance of gateway node + // (namely, node B) and add the required association + Ptr stack = olsrNodes.Get (1) -> GetObject (); + Ptr rp_Gw = (stack->GetRoutingProtocol ()); + Ptr lrp_Gw = DynamicCast (rp_Gw); + + Ptr olsrrp_Gw; + + for (uint32_t i = 0; i < lrp_Gw->GetNRoutingProtocols (); i++) + { + int16_t priority; + Ptr temp = lrp_Gw->GetRoutingProtocol (i, priority); + if (DynamicCast (temp)) + { + olsrrp_Gw = DynamicCast (temp); + } + } + + // Create a special Ipv4StaticRouting instance for RoutingTableAssociation + // Even the Ipv4StaticRouting instance added to list may be used + Ptr hnaEntries = Create (); + + if (assocMethod1) + { + // Add the required routes into the Ipv4StaticRouting Protocol instance + // and have the node generate HNA messages for all these routes + // which are associated with non-OLSR interfaces specified above. + hnaEntries->AddNetworkRouteTo (Ipv4Address ("172.16.1.0"), Ipv4Mask ("255.255.255.0"), uint32_t(2), uint32_t(1)); + olsrrp_Gw->SetRoutingTableAssociation (hnaEntries); + } + + if (assocMethod2) + { + // Specify the required associations directly. + olsrrp_Gw->AddHostNetworkAssociation (Ipv4Address ("172.16.1.0"), Ipv4Mask ("255.255.255.0")); + } + + // Tracing + wifiPhy.EnablePcap ("olsr-hna", devices); + csma.EnablePcap ("olsr-hna", csmaDevices, false); + + Simulator::ScheduleWithContext (source->GetNode ()->GetId (), + Seconds (15.0), &GenerateTraffic, + source, packetSize, numPackets, interPacketInterval); + + Simulator::Stop (Seconds (20.0)); + Simulator::Run (); + Simulator::Destroy (); + + return 0; +} diff -r b5bc10de166d examples/routing/wscript --- a/examples/routing/wscript Fri Mar 12 14:36:38 2010 -0500 +++ b/examples/routing/wscript Sat Mar 13 22:39:08 2010 +0530 @@ -33,6 +33,10 @@ ['point-to-point', 'internet-stack', 'olsr']) obj.source = 'simple-point-to-point-olsr.cc' + obj = bld.create_ns3_program('olsr-hna', + ['core', 'simulator', 'mobility', 'wifi']) + obj.source = 'olsr-hna.cc' + obj = bld.create_ns3_program('nix-simple', ['point-to-point', 'internet-stack', 'nix-vector-routing']) obj.source = 'nix-simple.cc' diff -r b5bc10de166d src/helper/olsr-helper.cc --- a/src/helper/olsr-helper.cc Fri Mar 12 14:36:38 2010 -0500 +++ b/src/helper/olsr-helper.cc Sat Mar 13 22:39:08 2010 +0530 @@ -33,6 +33,7 @@ OlsrHelper::OlsrHelper (const OlsrHelper &o) : m_agentFactory (o.m_agentFactory) { + m_interfaceExclusions = o.m_interfaceExclusions; } OlsrHelper* @@ -41,10 +42,36 @@ return new OlsrHelper (*this); } +void +OlsrHelper::ExcludeInterface (Ptr node, uint32_t interface) +{ + std::map< Ptr, std::set >::iterator it = m_interfaceExclusions.find (node); + + if(it == m_interfaceExclusions.end ()) + { + std::set interfaces; + interfaces.insert (interface); + + m_interfaceExclusions.insert (std::make_pair (node, std::set (interfaces) )); + } + else + { + it->second.insert (interface); + } +} + Ptr OlsrHelper::Create (Ptr node) const { Ptr agent = m_agentFactory.Create (); + + std::map, std::set >::const_iterator it = m_interfaceExclusions.find (node); + + if(it != m_interfaceExclusions.end ()) + { + agent->SetInterfaceExclusions (it->second); + } + node->AggregateObject (agent); return agent; } diff -r b5bc10de166d src/helper/olsr-helper.h --- a/src/helper/olsr-helper.h Fri Mar 12 14:36:38 2010 -0500 +++ b/src/helper/olsr-helper.h Sat Mar 13 22:39:08 2010 +0530 @@ -24,6 +24,8 @@ #include "ns3/node.h" #include "node-container.h" #include "ipv4-routing-helper.h" +#include +#include namespace ns3 { @@ -57,6 +59,14 @@ */ OlsrHelper* Copy (void) const; + /** + * \param node the node for which an exception is to be defined + * \param interface an interface of node on which OLSR is not to be installed + * + * This method allows the user to specify an interface on which OLSR is not to be installed on + */ + void ExcludeInterface (Ptr node, uint32_t interface); + /** * \param node the node on which the routing protocol will run * \returns a newly-created routing protocol @@ -72,6 +82,7 @@ * This method controls the attributes of ns3::olsr::RoutingProtocol */ void Set (std::string name, const AttributeValue &value); + private: /** * \internal @@ -80,6 +91,8 @@ */ OlsrHelper &operator = (const OlsrHelper &o); ObjectFactory m_agentFactory; + + std::map< Ptr, std::set > m_interfaceExclusions; }; } // namespace ns3 diff -r b5bc10de166d src/routing/olsr/olsr-repositories.h --- a/src/routing/olsr/olsr-repositories.h Fri Mar 12 14:36:38 2010 -0500 +++ b/src/routing/olsr/olsr-repositories.h Sat Mar 13 22:39:08 2010 +0530 @@ -231,6 +231,61 @@ return os; } +/// Association +struct Association +{ + Ipv4Address networkAddr; + Ipv4Mask netmask; +}; + +static inline bool +operator == (const Association &a, const Association &b) +{ + return (a.networkAddr == b.networkAddr + && a.netmask == b.netmask); +} + +static inline std::ostream& +operator << (std::ostream &os, const Association &tuple) +{ + os << "Association(networkAddr=" << tuple.networkAddr + << ", netmask=" << tuple.netmask + << ")"; + return os; +} + +/// An Association Tuple +struct AssociationTuple +{ + /// Main address of the gateway. + Ipv4Address gatewayAddr; + /// Network Address of network reachable through gatewayAddr + Ipv4Address networkAddr; + /// Netmask of network reachable through gatewayAddr + Ipv4Mask netmask; + /// Time at which this tuple expires and must be removed + Time expirationTime; +}; + +static inline bool +operator == (const AssociationTuple &a, const AssociationTuple &b) +{ + return (a.gatewayAddr == b.gatewayAddr + && a.networkAddr == b.networkAddr + && a.netmask == b.netmask); +} + +static inline std::ostream& +operator << (std::ostream &os, const AssociationTuple &tuple) +{ + os << "AssociationTuple(gatewayAddr=" << tuple.gatewayAddr + << ", networkAddr=" << tuple.networkAddr + << ", netmask=" << tuple.netmask + << ", expirationTime=" << tuple.expirationTime + << ")"; + return os; +} + typedef std::set MprSet; ///< MPR Set type. typedef std::vector MprSelectorSet; ///< MPR Selector Set type. @@ -240,6 +295,8 @@ typedef std::vector TopologySet; ///< Topology Set type. typedef std::vector DuplicateSet; ///< Duplicate Set type. typedef std::vector IfaceAssocSet; ///< Interface Association Set type. +typedef std::vector AssociationSet; ///< Association Set type. +typedef std::vector Associations; ///< Association Set type. }}; // namespace ns3, olsr diff -r b5bc10de166d src/routing/olsr/olsr-routing-protocol.cc --- a/src/routing/olsr/olsr-routing-protocol.cc Fri Mar 12 14:36:38 2010 -0500 +++ b/src/routing/olsr/olsr-routing-protocol.cc Sat Mar 13 22:39:08 2010 +0530 @@ -41,6 +41,7 @@ #include "ns3/random-variable.h" #include "ns3/inet-socket-address.h" #include "ns3/ipv4-routing-protocol.h" +#include "ns3/ipv4-routing-table-entry.h" #include "ns3/ipv4-route.h" #include "ns3/boolean.h" #include "ns3/uinteger.h" @@ -79,7 +80,8 @@ #define OLSR_DUP_HOLD_TIME Seconds (30) /// MID holding time. #define OLSR_MID_HOLD_TIME (Scalar (3) * m_midInterval) - +/// HNA holding time. +#define OLSR_HNA_HOLD_TIME (Scalar (3) * m_hnaInterval) /********** Link types **********/ @@ -165,6 +167,10 @@ TimeValue (Seconds (5)), MakeTimeAccessor (&RoutingProtocol::m_midInterval), MakeTimeChecker ()) + .AddAttribute ("HnaInterval", "HNA messages emission interval. Normally it is equal to TcInterval.", + TimeValue (Seconds (5)), + MakeTimeAccessor (&RoutingProtocol::m_hnaInterval), + MakeTimeChecker ()) .AddAttribute ("Willingness", "Willingness of a node to carry and forward traffic for other nodes.", EnumValue (OLSR_WILL_DEFAULT), MakeEnumAccessor (&RoutingProtocol::m_willingness), @@ -185,12 +191,16 @@ RoutingProtocol::RoutingProtocol () - : m_ipv4 (0), + : m_routingTableAssociation (0), + m_ipv4 (0), m_helloTimer (Timer::CANCEL_ON_DESTROY), m_tcTimer (Timer::CANCEL_ON_DESTROY), m_midTimer (Timer::CANCEL_ON_DESTROY), + m_hnaTimer (Timer::CANCEL_ON_DESTROY), m_queuedMessagesTimer (Timer::CANCEL_ON_DESTROY) -{} +{ + m_hnaRoutingTable = Create (); +} RoutingProtocol::~RoutingProtocol () {} @@ -204,6 +214,7 @@ m_helloTimer.SetFunction (&RoutingProtocol::HelloTimerExpire, this); m_tcTimer.SetFunction (&RoutingProtocol::TcTimerExpire, this); m_midTimer.SetFunction (&RoutingProtocol::MidTimerExpire, this); + m_hnaTimer.SetFunction (&RoutingProtocol::HnaTimerExpire, this); m_queuedMessagesTimer.SetFunction (&RoutingProtocol::SendQueuedMessages, this); m_packetSequenceNumber = OLSR_MAX_SEQ_NUM; @@ -213,11 +224,15 @@ m_linkTupleTimerFirstTime = true; m_ipv4 = ipv4; + + m_hnaRoutingTable->SetIpv4 (ipv4); } void RoutingProtocol::DoDispose () { m_ipv4 = 0; + m_hnaRoutingTable = 0; + m_routingTableAssociation = 0; for (std::map< Ptr, Ipv4InterfaceAddress >::iterator iter = m_socketAddresses.begin (); iter != m_socketAddresses.end (); iter++) @@ -251,6 +266,8 @@ NS_LOG_DEBUG ("Starting OLSR on node " << m_mainAddress); Ipv4Address loopback ("127.0.0.1"); + + bool canRunOlsr = false; for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++) { Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal (); @@ -269,6 +286,9 @@ NS_ASSERT (GetMainAddress (addr) == m_mainAddress); } + if(m_interfaceExclusions.find (i) != m_interfaceExclusions.end ()) + continue; + // Create a socket to listen only on this interface Ptr socket = Socket::CreateSocket (GetObject (), UdpSocketFactory::GetTypeId()); @@ -279,13 +299,19 @@ } socket->Connect (InetSocketAddress (Ipv4Address (0xffffffff), OLSR_PORT_NUMBER)); m_socketAddresses[socket] = m_ipv4->GetAddress (i, 0); + + canRunOlsr = true; } - HelloTimerExpire (); - TcTimerExpire (); - MidTimerExpire (); + if(canRunOlsr) + { + HelloTimerExpire (); + TcTimerExpire (); + MidTimerExpire (); + HnaTimerExpire (); - NS_LOG_DEBUG ("OLSR on node " << m_mainAddress << " started"); + NS_LOG_DEBUG ("OLSR on node " << m_mainAddress << " started"); + } } void RoutingProtocol::SetMainInterface (uint32_t interface) @@ -293,6 +319,10 @@ m_mainAddress = m_ipv4->GetAddress (interface, 0).GetLocal (); } +void RoutingProtocol::SetInterfaceExclusions (std::set exceptions) +{ + m_interfaceExclusions = exceptions; +} // // \brief Processes an incoming %OLSR packet following RFC 3626 specification. @@ -397,6 +427,12 @@ << " received MID message of size " << messageHeader.GetSerializedSize ()); ProcessMid (messageHeader, senderIfaceAddr); break; + case olsr::MessageHeader::HNA_MESSAGE: + NS_LOG_DEBUG (Simulator::Now ().GetSeconds () + << "s OLSR node " << m_mainAddress + << " received HNA message of size " << messageHeader.GetSerializedSize ()); + ProcessHna (messageHeader, senderIfaceAddr); + break; default: NS_LOG_DEBUG ("OLSR message type " << @@ -1039,6 +1075,53 @@ } } + // 5. For each tuple in the association set, + // If there is no entry in the routing table with: + // R_dest_addr == A_network_addr/A_netmask + // then a new routing entry is created. + const AssociationSet &associationSet = m_state.GetAssociationSet (); + for (AssociationSet::const_iterator it = associationSet.begin (); + it != associationSet.end (); it++) + { + AssociationTuple const &tuple = *it; + RoutingTableEntry gatewayEntry; + + bool gatewayEntryExists = Lookup (tuple.gatewayAddr, gatewayEntry); + bool addRoute = false; + + uint32_t routeIndex = 0; + + for (routeIndex = 0; routeIndex < m_hnaRoutingTable->GetNRoutes (); routeIndex++) + { + Ipv4RoutingTableEntry route = m_hnaRoutingTable->GetRoute (routeIndex); + if (route.GetDestNetwork () == tuple.networkAddr && + route.GetDestNetworkMask () == tuple.netmask) + { + break; + } + } + + if (routeIndex == m_hnaRoutingTable->GetNRoutes ()) + { + addRoute = true; + } + else if(gatewayEntryExists && m_hnaRoutingTable->GetMetric (routeIndex) > gatewayEntry.distance) + { + m_hnaRoutingTable->RemoveRoute(routeIndex); + addRoute = true; + } + + if(addRoute && gatewayEntryExists) + { + m_hnaRoutingTable->AddNetworkRouteTo (tuple.networkAddr, + tuple.netmask, + gatewayEntry.nextAddr, + gatewayEntry.interface, + gatewayEntry.distance); + + } + } + NS_LOG_DEBUG ("Node " << m_mainAddress << ": RoutingTableComputation end."); m_routingTableChanged (GetSize ()); } @@ -1280,6 +1363,67 @@ NS_LOG_DEBUG ("Node " << m_mainAddress << " ProcessMid from " << senderIface << " -> END."); } +/// +/// \brief Processes a HNA message following RFC 3626 specification. +/// +/// The Host Network Association Set is updated (if needed) with the information +/// of the received HNA message. +/// +/// \param msg the %OLSR message which contains the HNA message. +/// \param sender_iface the address of the interface where the message was sent from. +/// +void +RoutingProtocol::ProcessHna (const olsr::MessageHeader &msg, + const Ipv4Address &senderIface) +{ + + const olsr::MessageHeader::Hna &hna = msg.GetHna (); + Time now = Simulator::Now (); + + // 1. If the sender interface of this message is not in the symmetric + // 1-hop neighborhood of this node, the message MUST be discarded. + const LinkTuple *link_tuple = m_state.FindSymLinkTuple (senderIface, now); + if (link_tuple == NULL) + return; + + // 2. Otherwise, for each (network address, netmask) pair in the + // message: + + for (std::vector::const_iterator it = hna.associations.begin(); + it != hna.associations.end() ; it++) + { + AssociationTuple *tuple = m_state.FindAssociationTuple(msg.GetOriginatorAddress(),it->address,it->mask); + + // 2.1 if an entry in the association set already exists, where: + // A_gateway_addr == originator address + // A_network_addr == network address + // A_netmask == netmask + // then the holding time for that tuple MUST be set to: + // A_time = current time + validity time + if(tuple != NULL) + { + tuple->expirationTime = now + msg.GetVTime (); + } + + // 2.2 otherwise, a new tuple MUST be recorded with: + // A_gateway_addr = originator address + // A_network_addr = network address + // A_netmask = netmask + // A_time = current time + validity time + else + { + const AssociationTuple &assocTuple = (AssociationTuple){msg.GetOriginatorAddress(),it->address,it->mask,now + msg.GetVTime ()}; + + AddAssociationTuple (assocTuple); + + //Schedule Association Tuple deletion + Simulator::Schedule (DELAY (assocTuple.expirationTime), + &RoutingProtocol::AssociationTupleTimerExpire, this, + assocTuple.gatewayAddr,assocTuple.networkAddr,assocTuple.netmask); + } + + } +} /// /// \brief OLSR's default forwarding algorithm. @@ -1447,7 +1591,7 @@ RoutingProtocol::SendHello () { NS_LOG_FUNCTION (this); - + olsr::MessageHeader msg; Time now = Simulator::Now (); @@ -1569,6 +1713,7 @@ olsr::MessageHeader::Tc &tc = msg.GetTc (); tc.ansn = m_ansn; + for (MprSelectorSet::const_iterator mprsel_tuple = m_state.GetMprSelectors ().begin(); mprsel_tuple != m_state.GetMprSelectors ().end(); mprsel_tuple++) { @@ -1622,6 +1767,94 @@ } /// +/// \brief Creates a new %OLSR HNA message which is buffered for being sent later on. +/// +void +RoutingProtocol::SendHna () +{ + + olsr::MessageHeader msg; + + msg.SetVTime (OLSR_HNA_HOLD_TIME); + msg.SetOriginatorAddress (m_mainAddress); + msg.SetTimeToLive (255); + msg.SetHopCount (0); + msg.SetMessageSequenceNumber (GetMessageSequenceNumber ()); + olsr::MessageHeader::Hna &hna = msg.GetHna (); + + std::vector + &associations = hna.associations; + + if (m_routingTableAssociation != 0) + { + // Add (NetworkAddr, Netmask) entries from Associated Routing Table to HNA message. + for (uint32_t i = 0; i < m_routingTableAssociation->GetNRoutes (); i++) + { + Ipv4RoutingTableEntry route = m_routingTableAssociation->GetRoute (i); + + std::set::const_iterator ci = m_interfaceExclusions.find (route.GetInterface ()); + + if (ci != m_interfaceExclusions.end ()) + { + olsr::MessageHeader::Hna::Association assoc = {route.GetDestNetwork (), route.GetDestNetworkMask ()}; + associations.push_back(assoc); + } + } + } + + int size = associations.size (); + + // Add (NetworkAddr, Netmask) entries specified using AddHostNetworkAssociation () to HNA message. + for (Associations::const_iterator it = m_state.GetAssociations ().begin (); + it != m_state.GetAssociations ().end (); it++) + { + // Check if the entry has already been added from the Associated Routing Table + std::vector::const_iterator ci = associations.begin (); + bool found = false; + for (int i = 0; i < size; i++) + { + if (it->networkAddr == ci->address && it->netmask == ci->mask) + { + found = true; + break; + } + ci++; + } + + if(!found) + { + olsr::MessageHeader::Hna::Association assoc = {it->networkAddr,it->netmask}; + associations.push_back(assoc); + } + } + + if(associations.size () == 0) + return; + + QueueMessage (msg, JITTER); +} + +/// +/// \brief Injects a (networkAddr, netmask) tuple for which the node +/// can generate an HNA message for +/// +void +RoutingProtocol::AddHostNetworkAssociation (Ipv4Address networkAddr, Ipv4Mask netmask) +{ + m_state.InsertAssociation ((Association) {networkAddr, netmask}); +} + +/// +/// \brief Adds an Ipv4StaticRouting protocol Association +/// can generate an HNA message for +/// +void +RoutingProtocol::SetRoutingTableAssociation (Ptr routingTable) +{ + m_routingTableAssociation = routingTable; +} + +/// /// \brief Updates Link Set according to a new received HELLO message (following RFC 3626 /// specification). Neighbor Set is also updated if needed. void @@ -2301,6 +2534,29 @@ m_state.EraseIfaceAssocTuple (tuple); } +/// +/// \brief Adds a host network association tuple to the Association Set. +/// +/// \param tuple the host network association tuple to be added. +/// +void +RoutingProtocol::AddAssociationTuple (const AssociationTuple &tuple) +{ + m_state.InsertAssociationTuple (tuple); +} + +/// +/// \brief Removes a host network association tuple from the Association Set. +/// +/// \param tuple the host network association tuple to be removed. +/// +void +RoutingProtocol::RemoveAssociationTuple (const AssociationTuple &tuple) +{ + m_state.EraseAssociationTuple (tuple); +} + + uint16_t RoutingProtocol::GetPacketSequenceNumber () { @@ -2358,6 +2614,24 @@ } /// +/// \brief Sends an HNA message (if the node has associated hosts/networks) and reschedules the HNA timer. +/// \param e The event which has expired. +/// +void +RoutingProtocol::HnaTimerExpire () +{ + if (m_state.GetAssociations ().size () > 0 || m_routingTableAssociation !=0) + { + SendHna (); + } + else + { + NS_LOG_DEBUG ("Not sending any HNA, no associations to advertise."); + } + m_hnaTimer.Schedule (m_hnaInterval); +} + +/// /// \brief Removes tuple if expired. Else timer is rescheduled to expire at tuple.expirationTime. /// /// The task of actually removing the tuple is left to the OLSR agent. @@ -2537,6 +2811,29 @@ } } +/// \brief Removes tuple_ if expired. Else timer is rescheduled to expire at tuple_->time(). +/// \param e The event which has expired. +/// +void +RoutingProtocol::AssociationTupleTimerExpire (Ipv4Address gatewayAddr, Ipv4Address networkAddr, Ipv4Mask netmask) +{ + AssociationTuple *tuple = m_state.FindAssociationTuple (gatewayAddr, networkAddr, netmask); + if (tuple == NULL) + { + return; + } + if (tuple->expirationTime < Simulator::Now ()) + { + RemoveAssociationTuple (*tuple); + } + else + { + m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime), + &RoutingProtocol::AssociationTupleTimerExpire, + this, gatewayAddr, networkAddr, netmask)); + } +} + /// /// \brief Clears the routing table and frees the memory assigned to each one of its entries. /// @@ -2612,6 +2909,8 @@ NS_LOG_FUNCTION (this << " " << m_ipv4->GetObject ()->GetId() << " " << header.GetDestination () << " " << oif); Ptr rtentry; RoutingTableEntry entry1, entry2; + bool found = false; + if (Lookup (header.GetDestination (), entry1) != 0) { bool foundSendEntry = FindSendEntry (entry1, entry2); @@ -2654,10 +2953,23 @@ NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": RouteOutput for dest=" << header.GetDestination () << " --> nextHop=" << entry2.nextAddr - << " interface=" << entry2.interface); NS_LOG_DEBUG ("Found route to " << rtentry->GetDestination () << " via nh " << rtentry->GetGateway () << " with source addr " << rtentry->GetSource () << " and output dev " << rtentry->GetOutputDevice()); + << " interface=" << entry2.interface); + NS_LOG_DEBUG ("Found route to " << rtentry->GetDestination () << " via nh " << rtentry->GetGateway () << " with source addr " << rtentry->GetSource () << " and output dev " << rtentry->GetOutputDevice()); + found = true; } else { + rtentry = m_hnaRoutingTable->RouteOutput (p, header, oif, sockerr); + + if (rtentry) + { + found = true; + NS_LOG_DEBUG ("Found route to " << rtentry->GetDestination () << " via nh " << rtentry->GetGateway () << " with source addr " << rtentry->GetSource () << " and output dev " << rtentry->GetOutputDevice()); + } + } + + if (!found) + { NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": RouteOutput for dest=" << header.GetDestination () << " No route to host"); @@ -2729,18 +3041,30 @@ } else { + if(m_hnaRoutingTable->RouteInput (p, header, idev, ucb, mcb, lcb, ecb)) + { + return true; + } + else + { + #ifdef NS3_LOG_ENABLE - NS_LOG_DEBUG ("Olsr node " << m_mainAddress + NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": RouteInput for dest=" << header.GetDestination () - << " --> NOT FOUND; ** Dumping routing table..."); for (std::map::const_iterator iter = m_table.begin (); - iter != m_table.end (); iter++) - { NS_LOG_DEBUG ("dest=" << iter->first << " --> next=" << iter->second.nextAddr + << " --> NOT FOUND; ** Dumping routing table..."); + + for (std::map::const_iterator iter = m_table.begin (); + iter != m_table.end (); iter++) + { + NS_LOG_DEBUG ("dest=" << iter->first << " --> next=" << iter->second.nextAddr << " via interface " << iter->second.interface); + } + + NS_LOG_DEBUG ("** Routing table dump end."); +#endif // NS3_LOG_ENABLE + + return false; } - - NS_LOG_DEBUG ("** Routing table dump end."); -#endif // NS3_LOG_ENABLE - return false; } } void diff -r b5bc10de166d src/routing/olsr/olsr-routing-protocol.h --- a/src/routing/olsr/olsr-routing-protocol.h Fri Mar 12 14:36:38 2010 -0500 +++ b/src/routing/olsr/olsr-routing-protocol.h Sat Mar 13 22:39:08 2010 +0530 @@ -38,6 +38,7 @@ #include "ns3/traced-callback.h" #include "ns3/ipv4.h" #include "ns3/ipv4-routing-protocol.h" +#include "ns3/ipv4-static-routing.h" #include #include @@ -105,11 +106,30 @@ **/ std::vector GetRoutingTableEntries () const; +private: + std::set m_interfaceExclusions; + Ptr m_routingTableAssociation; + +public: + std::set GetInterfaceExclusions () const + { + return m_interfaceExclusions; + } + void SetInterfaceExclusions (std::set exceptions); + + /// Inject Association to be sent in HNA message + void AddHostNetworkAssociation (Ipv4Address networkAddr, Ipv4Mask netmask); + + /// Inject Associations from an Ipv4StaticRouting instance + void SetRoutingTableAssociation (Ptr routingTable); + protected: virtual void DoStart (void); private: std::map m_table; ///< Data structure for the routing table. + Ptr m_hnaRoutingTable; + EventGarbageCollector m_events; /// Address of the routing agent. @@ -128,6 +148,8 @@ Time m_tcInterval; /// MID messages' emission interval. Time m_midInterval; + /// HNA messages' emission interval. + Time m_hnaInterval; /// Willingness for forwarding packets on behalf of other nodes. uint8_t m_willingness; @@ -189,6 +211,9 @@ Timer m_midTimer; void MidTimerExpire (); + Timer m_hnaTimer; + void HnaTimerExpire (); + void DupTupleTimerExpire (Ipv4Address address, uint16_t sequenceNumber); bool m_linkTupleTimerFirstTime; void LinkTupleTimerExpire (Ipv4Address neighborIfaceAddr); @@ -196,6 +221,7 @@ void MprSelTupleTimerExpire (Ipv4Address mainAddr); void TopologyTupleTimerExpire (Ipv4Address destAddr, Ipv4Address lastAddr); void IfaceAssocTupleTimerExpire (Ipv4Address ifaceAddr); + void AssociationTupleTimerExpire (Ipv4Address gatewayAddr, Ipv4Address networkAddr, Ipv4Mask netmask); void IncrementAnsn (); @@ -212,6 +238,7 @@ void SendHello (); void SendTc (); void SendMid (); + void SendHna (); void NeighborLoss (const LinkTuple &tuple); void AddDuplicateTuple (const DuplicateTuple &tuple); @@ -229,6 +256,8 @@ void RemoveTopologyTuple (const TopologyTuple &tuple); void AddIfaceAssocTuple (const IfaceAssocTuple &tuple); void RemoveIfaceAssocTuple (const IfaceAssocTuple &tuple); + void AddAssociationTuple (const AssociationTuple &tuple); + void RemoveAssociationTuple (const AssociationTuple &tuple); void ProcessHello (const olsr::MessageHeader &msg, const Ipv4Address &receiverIface, @@ -237,6 +266,8 @@ const Ipv4Address &senderIface); void ProcessMid (const olsr::MessageHeader &msg, const Ipv4Address &senderIface); + void ProcessHna (const olsr::MessageHeader &msg, + const Ipv4Address &senderIface); void LinkSensing (const olsr::MessageHeader &msg, const olsr::MessageHeader::Hello &hello, diff -r b5bc10de166d src/routing/olsr/olsr-state.cc --- a/src/routing/olsr/olsr-state.cc Fri Mar 12 14:36:38 2010 -0500 +++ b/src/routing/olsr/olsr-state.cc Sat Mar 13 22:39:08 2010 +0530 @@ -487,4 +487,60 @@ return retval; } +/********** Host-Network Association Set Manipulation **********/ + +AssociationTuple* +OlsrState::FindAssociationTuple (const Ipv4Address &gatewayAddr, const Ipv4Address &networkAddr, const Ipv4Mask &netmask) +{ + for (AssociationSet::iterator it = m_associationSet.begin (); + it != m_associationSet.end (); it++) + { + if (it->gatewayAddr == gatewayAddr and it->networkAddr == networkAddr and it->netmask == netmask) + { + return &(*it); + } + } + return NULL; +} + +void +OlsrState::EraseAssociationTuple (const AssociationTuple &tuple) +{ + for (AssociationSet::iterator it = m_associationSet.begin (); + it != m_associationSet.end (); it++) + { + if (*it == tuple) + { + m_associationSet.erase (it); + break; + } + } +} + +void +OlsrState::InsertAssociationTuple (const AssociationTuple &tuple) +{ + m_associationSet.push_back (tuple); +} + +void +OlsrState::EraseAssociation (const Association &tuple) +{ + for (Associations::iterator it = m_associations.begin (); + it != m_associations.end (); it++) + { + if (*it == tuple) + { + m_associations.erase (it); + break; + } + } +} + +void +OlsrState::InsertAssociation (const Association &tuple) +{ + m_associations.push_back(tuple); +} + } // namespace ns3 diff -r b5bc10de166d src/routing/olsr/olsr-state.h --- a/src/routing/olsr/olsr-state.h Fri Mar 12 14:36:38 2010 -0500 +++ b/src/routing/olsr/olsr-state.h Sat Mar 13 22:39:08 2010 +0530 @@ -45,6 +45,8 @@ MprSelectorSet m_mprSelectorSet; ///< MPR Selector Set (RFC 3626, section 4.3.4). DuplicateSet m_duplicateSet; ///< Duplicate Set (RFC 3626, section 3.4). IfaceAssocSet m_ifaceAssocSet; ///< Interface Association Set (RFC 3626, section 4.1). + AssociationSet m_associationSet; ///< Association Set (RFC 3626, section12.2). Associations obtained from HNA messages generated by other nodes. + Associations m_associations; ///< The node's local Host Network Associations that will be advertised using HNA messages. public: @@ -147,6 +149,25 @@ void EraseIfaceAssocTuple (const IfaceAssocTuple &tuple); void InsertIfaceAssocTuple (const IfaceAssocTuple &tuple); + // Host-Network Association + const AssociationSet & GetAssociationSet () const // Associations known to the node + { + return m_associationSet; + } + + const Associations & GetAssociations () const // Set of associations that the node has + { + return m_associations; + } + + AssociationTuple* FindAssociationTuple (const Ipv4Address &gatewayAddr,\ + const Ipv4Address &networkAddr,\ + const Ipv4Mask &netmask); + void EraseAssociationTuple (const AssociationTuple &tuple); + void InsertAssociationTuple (const AssociationTuple &tuple); + void EraseAssociation (const Association &tuple); + void InsertAssociation (const Association &tuple); + // Returns a vector of all interfaces of a given neighbor, with the // exception of the "main" one. std::vector