merge with HEAD

This commit is contained in:
Mathieu Lacage
2007-10-16 14:44:36 +02:00
55 changed files with 5906 additions and 349 deletions

View File

@@ -6,3 +6,4 @@
08046b6aef37932507696a2f2f427b42d693781e release ns-3.0.5
267e2ebc28e4e4ae2f579e1cfc29902acade0c34 buffer-working-before-breaking
606df29888e7573b825fc891a002f0757166b616 release ns-3.0.6
36472385a1cc7c44d34fb7a5951b930010f4e8d2 release ns-3.0.7

10
README
View File

@@ -84,12 +84,12 @@ following set of platforms:
- linux x86 gcc 4.2, 4.1, and, 3.4.
- linux x86_64 gcc 4.0
- MacOS X ppc and x86
- cygwin
The current codebase is expected to fail to build on
the following platforms:
- gcc 3.3 and earlier
- optimized builds on linux x86 gcc 4.0
- cygwin
Other platforms may or may not work: we welcome
patches to improve the portability of the code to these
@@ -102,17 +102,17 @@ On recent Linux systems, once you have built ns-3, it
should be easy to run the sample programs with the
following command:
./waf --run simple-p2p
./waf --run simple-point-to-point
That program should generate a simple-p2p.tr text
trace file and a set of simple-p2p-xx-xx.pcap binary
That program should generate a simple-point-to-point.tr text
trace file and a set of simple-point-to-point-xx-xx.pcap binary
pcap trace files, which can be read by tcpdump.
5) Getting access to the ns-3 documentation
-------------------------------------------
Once you have verified that your build of ns-3 works by running
the simple-p2p example as outlined in 4) above, it is
the simple-point-to-point example as outlined in 4) above, it is
quite likely that you will want to get started on reading
some ns-3 documentation.

View File

@@ -3,6 +3,13 @@
This file contains ns-3 release notes (most recent releases first).
Release 3.0.7 (2007/10/15)
========================
- OLSR routing protocol
- A timer class
- Additional mobility models (random waypoint, random 2D walk)
- A mobility visualization tool
Release 3.0.6 (2007/09/15)
========================
- Static multicast IPv4 routing

View File

@@ -1 +1 @@
3.0.6
3.0.7

View File

@@ -3,79 +3,62 @@ build system (http://www.freehackers.org/~tnagy/waf.html)
=== Installing Waf ===
If this file is part of a development release tarball, the top-level
ns-3 directory should contain a current waf script.
However, the ns-3 Mercurial code repository does not contain the waf
script. Instead, developers should check it out from a subversion
repository:
svn checkout http://waf.googlecode.com/svn/tags/ns3/ waf
[ note: 'tags/ns3' is a tag that represents the last svn version
tested to work correctly with ns3, although 'trunk' will likely work
as well ]
Then it can be installed system-wide with 'sudo waf-light install'.
When preparing a distribution, the resulting 'waf' script, which is
self contained (no external files needed), can be easily included in
the tarball so that users downloading ns-3 can easily build it without
having Waf installed (although Python >= 2.3 is still needed).
The top-level ns-3 directory should contain a current waf script.
=== Building with Waf ===
To build ns-3 with waf type the commands:
1. waf configure [options]
2. waf
To build ns-3 with waf type the commands from the top-level directory:
1. ./waf configure [options]
2. ./waf
To see valid configure options, type waf --help. The most important
To see valid configure options, type ./waf --help. The most important
option is -d <debug level>. Valid debug levels (which are listed in
waf --help) are: ultradebug, debug, release, and optimized. It is
waf --help) are: "debug" or "optimized". It is
also possible to change the flags used for compilation with (e.g.):
CXXFLAGS="-O3" waf configure.
CXXFLAGS="-O3" ./waf configure.
[ Note: Unlike some other build tools, to change the build target,
the option must be supplied during the configure stage rather than
the build stage (i.e., "waf -d optimized" will not work; instead, do
"waf -d optimized configure; waf" ]
the build stage (i.e., "./waf -d optimized" will not work; instead, do
"./waf -d optimized configure; ./waf" ]
The resulting binaries are placed in build/<debuglevel>/srcpath.
Other waf usages include:
1. waf check
1. ./waf check
Runs the unit tests
2. waf --doxygen
2. ./waf --doxygen
Run doxygen to generate documentation
3. waf --lcov-report
3. ./waf --lcov-report
Run code coverage analysis (assuming the project was configured
with --enable-gcov)
4. waf --run "program [args]"
4. ./waf --run "program [args]"
Run a ns3 program, given its target name, with the given
arguments. This takes care of automatically modifying the the
path for finding the ns3 dynamic libraries in the environment
before running the program. Note: the "program [args]" string is
parsed using POSIX shell rules.
4.1 waf --run programname --command-template "... %s ..."
4.1 ./waf --run programname --command-template "... %s ..."
Same as --run, but uses a command template with %s replaced by the
actual program (whose name is given by --run). This can be use to
run ns-3 programs with helper tools. For example, to run unit
tests with valgrind, use the command:
waf --run run-tests --command-template "valgrind %s"
./waf --run run-tests --command-template "valgrind %s"
5. waf --shell
5. ./waf --shell
Starts a nested system shell with modified environment to run ns3 programs.
6. waf distclean
6. ./waf distclean
Cleans out the entire build/ directory
7. waf dist
7. ./waf dist
The command 'waf dist' can be used to create a distribution tarball.
It includes all files in the source directory, except some particular
extensions that are blacklisted, such as back files (ending in ~).

View File

@@ -472,6 +472,9 @@ RECURSIVE = YES
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE = \
src/routing/olsr/olsr-state.h \
src/routing/olsr/repositories.h \
src/routing/olsr/routing-table.h \
src/simulator/high-precision.h \
src/simulator/high-precision-128.h \
src/simulator/high-precision-double.h

View File

@@ -65,4 +65,4 @@
/**
* \defgroup constants Constants
* \brief Constants you can change
*/
*/

View File

@@ -1,24 +1,32 @@
Steps in doing an ns-3 release
0. check out a clean ns-3-dev somewhere
1. prepare the source files
- revise and check in AUTHORS, if needed
- revise and check in RELEASE_NOTES
- update and check in VERSION to the latest release number
2. make a new "architecture.pdf" document and place it in the doc/ directory
3. cd ns-3-dev; ./waf configure; ./waf dist
of the ns-3-dev working directory
3. ./waf configure; ./waf dist
- this will create a ns-3.0.x.tar.bz2 tarball
4. test tarball on release platforms (waf check and maybe some other scripts)
5. tag ns-3-dev with "release ns-3.0.X"
- hg tag "release ns-3.0.x"
- hg push
5. once you are happy with the tarball, tag ns-3-dev with "release ns-3.0.X"
- hg tag "release ns-3.0.x"
- hg push
6. clone the tagged ns-3-dev and place it on the repository
- ssh code.nsnam.org; sudo; su code;
- cp -r /home/code/repos/ns-3-dev /home/code/repos/ns-3.0.x
- cd /home/code/repos/ns-3.0.x/.hg and edit the hgrc appropriately
7. upload "ns-3.0.x.tar.bz2" to the releases/ directory on the server
- ssh code.nsnam.org; sudo; su code;
- cp -r /home/code/repos/ns-3-dev /home/code/repos/ns-3.0.x
- cd /home/code/repos/ns-3.0.x/.hg and edit the hgrc appropriately
7. upload "ns-3.0.x.tar.bz2" to the /var/www/html/releases/ directory on
the www.nsnam.org server
8. update web page
- add link to news.html
- update download.html
- update roadmap.html
- update getting_started.html
- update documents.html
- update roadmap on wiki
- build and update Doxygen directory on the server
-- ssh www.nsnam.org; sudo tcsh; su nsnam;
-- ~/bin/update-doxygen-release
- update and upload software architecture document (PDF, HTML)
-- note: HTML image generation is not currently automatic
9. announce to ns-developers, with summary of release notes

View File

@@ -0,0 +1,224 @@
/* -*- 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
*
*/
//
// Network topology
//
// n0
// \ 5 Mb/s, 2ms
// \ 1.5Mb/s, 10ms
// n2 ------------------------n3
// / /
// / 5 Mb/s, 2ms /
// n1--------------------------
// 1.5 Mb/s, 100ms
//
// this is a modification of simple-global-routing to allow for
// a single hop but higher-cost path between n1 and n3
//
// - Tracing of queues and packet receptions to file "simple-rerouting.tr"
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include "ns3/log.h"
#include "ns3/command-line.h"
#include "ns3/default-value.h"
#include "ns3/ptr.h"
#include "ns3/random-variable.h"
#include "ns3/simulator.h"
#include "ns3/nstime.h"
#include "ns3/data-rate.h"
#include "ns3/ascii-trace.h"
#include "ns3/pcap-trace.h"
#include "ns3/internet-node.h"
#include "ns3/point-to-point-channel.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv4.h"
#include "ns3/socket.h"
#include "ns3/inet-socket-address.h"
#include "ns3/ipv4-route.h"
#include "ns3/point-to-point-topology.h"
#include "ns3/onoff-application.h"
#include "ns3/packet-sink.h"
#include "ns3/global-route-manager.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("SimpleAlternateRoutingExample");
int
main (int argc, char *argv[])
{
// Users may find it convenient to turn on explicit debugging
// for selected modules; the below lines suggest how to do this
#if 0
LogComponentEnable("GlobalRouteManager", LOG_LOGIC);
LogComponentEnable("GlobalRouter", LOG_LOGIC);
LogComponentEnable("Object", LOG_LEVEL_ALL);
LogComponentEnable("Queue", LOG_LEVEL_ALL);
LogComponentEnable("DropTailQueue", LOG_LEVEL_ALL);
LogComponentEnable("Channel", LOG_LEVEL_ALL);
LogComponentEnable("CsmaChannel", LOG_LEVEL_ALL);
LogComponentEnable("NetDevice", LOG_LEVEL_ALL);
LogComponentEnable("CsmaNetDevice", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
LogComponentEnable("PacketSocket", LOG_LEVEL_ALL);
LogComponentEnable("Socket", LOG_LEVEL_ALL);
LogComponentEnable("UdpSocket", LOG_LEVEL_ALL);
LogComponentEnable("UdpL4Protocol", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4StaticRouting", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4Interface", LOG_LEVEL_ALL);
LogComponentEnable("ArpIpv4Interface", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4LoopbackInterface", LOG_LEVEL_ALL);
LogComponentEnable("OnOffApplication", LOG_LEVEL_ALL);
LogComponentEnable("PacketSinkApplication", LOG_LEVEL_ALL);
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_ALL);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_ALL);
#endif
// Set up some default values for the simulation. Use the
// DefaultValue::Bind () technique to tell the system what subclass of
// Queue to use, and what the queue limit is
// The below Bind command tells the queue factory which class to
// instantiate, when the queue factory is invoked in the topology code
DefaultValue::Bind ("Queue", "DropTailQueue");
DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
DefaultValue::Bind ("OnOffApplicationDataRate", "300b/s");
// The below metric, if set to 3 or higher, will cause packets between
// n1 and n3 to take the 2-hop route through n2
//
// Additionally, we plumb this metric into the default value / command
// line argument system as well, for exemplary purposes. This means
// that it can be resettable at the command-line to the program,
// rather than recompiling
// e.g. waf --run "simple-alternate-routing --AlternateCost=5"
uint16_t sampleMetric = 1;
CommandLine::AddArgValue ("AlternateCost",
"This metric is used in the example script between n3 and n1 ",
sampleMetric);
// Allow the user to override any of the defaults and the above
// DefaultValue::Bind ()s at run-time, via command-line arguments
CommandLine::Parse (argc, argv);
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
// We create the channels first without any IP addressing information
NS_LOG_INFO ("Create channels.");
Ptr<PointToPointChannel> channel0 =
PointToPointTopology::AddPointToPointLink (
n0, n2, DataRate (5000000), MilliSeconds (2));
Ptr<PointToPointChannel> channel1 =
PointToPointTopology::AddPointToPointLink (
n1, n2, DataRate (5000000), MilliSeconds (2));
Ptr<PointToPointChannel> channel2 =
PointToPointTopology::AddPointToPointLink (
n2, n3, DataRate (1500000), MilliSeconds (10));
Ptr<PointToPointChannel> channel3 =
PointToPointTopology::AddPointToPointLink (
n1, n3, DataRate (1500000), MilliSeconds (100));
// Later, we add IP addresses. The middle two octets correspond to
// the channel number.
NS_LOG_INFO ("Assign IP Addresses.");
PointToPointTopology::AddIpv4Addresses (
channel0, n0, Ipv4Address ("10.0.0.1"),
n2, Ipv4Address ("10.0.0.2"));
PointToPointTopology::AddIpv4Addresses (
channel1, n1, Ipv4Address ("10.1.1.1"),
n2, Ipv4Address ("10.1.1.2"));
PointToPointTopology::AddIpv4Addresses (
channel2, n2, Ipv4Address ("10.2.2.1"),
n3, Ipv4Address ("10.2.2.2"));
PointToPointTopology::AddIpv4Addresses (
channel3, n1, Ipv4Address ("10.3.3.1"),
n3, Ipv4Address ("10.3.3.2"));
PointToPointTopology::SetIpv4Metric (
channel3, n1, n3, sampleMetric);
// Create router nodes, initialize routing database and set up the routing
// tables in the nodes.
GlobalRouteManager::PopulateRoutingTables ();
// Create the OnOff application to send UDP datagrams
NS_LOG_INFO ("Create Application.");
uint16_t port = 9; // Discard port (RFC 863)
// Create a flow from n3 to n1, starting at time 1.1 seconds
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
n3,
InetSocketAddress ("10.1.1.1", port),
"Udp",
ConstantVariable (1),
ConstantVariable (0));
// Start the application
ooff->Start (Seconds (1.1));
ooff->Stop (Seconds (10.0));
// Create a packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
n1,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
// Start the sink
sink->Start (Seconds (1.1));
sink->Stop (Seconds (10.0));
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
// Trace output will be sent to the simple-alternate-routing.tr file
NS_LOG_INFO ("Configure Tracing.");
AsciiTrace asciitrace ("simple-alternate-routing.tr");
asciitrace.TraceAllQueues ();
asciitrace.TraceAllNetDeviceRx ();
// Also configure some tcpdump traces; each interface will be traced
// The output files will be named simple-p2p.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
PcapTrace pcaptrace ("simple-alternate-routing.pcap");
pcaptrace.TraceAllIp ();
NS_LOG_INFO ("Run Simulation.");
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Done.");
return 0;
}

View File

@@ -0,0 +1,233 @@
/* -*- 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
*
* ns-2 simple.tcl script (ported from ns-2)
* Originally authored by Steve McCanne, 12/19/1996
*/
// Port of ns-2/tcl/ex/simple.tcl to ns-3
//
// Network topology
//
// n0
// \ 5 Mb/s, 2ms
// \ 1.5Mb/s, 10ms
// n2 -------------------------n3
// /
// / 5 Mb/s, 2ms
// n1
//
// - all links are point-to-point links with indicated one-way BW/delay
// - CBR/UDP flows from n0 to n3, and from n3 to n1
// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
// (i.e., DataRate of 448,000 bps)
// - DropTail queues
// - Tracing of queues and packet receptions to file
// "simple-point-to-point.tr"
#include "ns3/log.h"
#include "ns3/command-line.h"
#include "ns3/default-value.h"
#include "ns3/ptr.h"
#include "ns3/random-variable.h"
#include "ns3/simulator.h"
#include "ns3/nstime.h"
#include "ns3/data-rate.h"
#include "ns3/ascii-trace.h"
#include "ns3/pcap-trace.h"
#include "ns3/internet-node.h"
#include "ns3/point-to-point-channel.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/ipv4-address.h"
#include "ns3/inet-socket-address.h"
#include "ns3/ipv4.h"
#include "ns3/socket.h"
#include "ns3/ipv4-route.h"
#include "ns3/point-to-point-topology.h"
#include "ns3/onoff-application.h"
#include "ns3/packet-sink.h"
#include "ns3/olsr.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("SimplePointToPointExample");
int
main (int argc, char *argv[])
{
// Users may find it convenient to turn on explicit debugging
// for selected modules; the below lines suggest how to do this
#if 0
LogComponentEnable ("SimplePointToPointExample", LOG_LEVEL_INFO);
LogComponentEnable("Object", LOG_LEVEL_ALL);
LogComponentEnable("Queue", LOG_LEVEL_ALL);
LogComponentEnable("DropTailQueue", LOG_LEVEL_ALL);
LogComponentEnable("Channel", LOG_LEVEL_ALL);
LogComponentEnable("CsmaChannel", LOG_LEVEL_ALL);
LogComponentEnable("NetDevice", LOG_LEVEL_ALL);
LogComponentEnable("CsmaNetDevice", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
LogComponentEnable("PacketSocket", LOG_LEVEL_ALL);
LogComponentEnable("Socket", LOG_LEVEL_ALL);
LogComponentEnable("UdpSocket", LOG_LEVEL_ALL);
LogComponentEnable("UdpL4Protocol", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4StaticRouting", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4Interface", LOG_LEVEL_ALL);
LogComponentEnable("ArpIpv4Interface", LOG_LEVEL_ALL);
LogComponentEnable("Ipv4LoopbackInterface", LOG_LEVEL_ALL);
LogComponentEnable("OnOffApplication", LOG_LEVEL_ALL);
LogComponentEnable("PacketSinkApplication", LOG_LEVEL_ALL);
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_ALL);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_ALL);
#endif
// Set up some default values for the simulation. Use the Bind()
// technique to tell the system what subclass of Queue to use,
// and what the queue limit is
// The below Bind command tells the queue factory which class to
// instantiate, when the queue factory is invoked in the topology code
DefaultValue::Bind ("Queue", "DropTailQueue");
DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
//DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);
// Allow the user to override any of the defaults and the above
// Bind()s at run-time, via command-line arguments
CommandLine::Parse (argc, argv);
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
NS_LOG_INFO ("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
// We create the channels first without any IP addressing information
NS_LOG_INFO ("Create channels.");
Ptr<PointToPointChannel> channel0 =
PointToPointTopology::AddPointToPointLink (
n0, n2, DataRate(5000000), MilliSeconds(2));
Ptr<PointToPointChannel> channel1 =
PointToPointTopology::AddPointToPointLink (
n1, n2, DataRate(5000000), MilliSeconds(2));
Ptr<PointToPointChannel> channel2 =
PointToPointTopology::AddPointToPointLink (
n2, n3, DataRate(1500000), MilliSeconds(10));
// Later, we add IP addresses.
NS_LOG_INFO ("Assign IP Addresses.");
PointToPointTopology::AddIpv4Addresses (
channel0, n0, Ipv4Address("10.1.1.1"),
n2, Ipv4Address("10.1.1.2"));
PointToPointTopology::AddIpv4Addresses (
channel1, n1, Ipv4Address("10.1.2.1"),
n2, Ipv4Address("10.1.2.2"));
PointToPointTopology::AddIpv4Addresses (
channel2, n2, Ipv4Address("10.1.3.1"),
n3, Ipv4Address("10.1.3.2"));
// Finally, we add static routes. These three steps (Channel and
// NetDevice creation, IP Address assignment, and routing) are
// separated because there may be a need to postpone IP Address
// assignment (emulation) or modify to use dynamic routing
NS_LOG_INFO ("Enabling OLSR Routing.");
olsr::EnableAllNodes ();
// Create the OnOff application to send UDP datagrams of size
// 210 bytes at a rate of 448 Kb/s
NS_LOG_INFO ("Create Applications.");
uint16_t port = 9; // Discard port (RFC 863)
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
n0,
InetSocketAddress ("10.1.3.2", port),
"Udp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
ooff->Start(Seconds(1.0));
ooff->Stop (Seconds(10.0));
// Create an optional packet sink to receive these packets
Ptr<PacketSink> sink = Create<PacketSink> (
n3,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
// Start the sink
sink->Start (Seconds (1.0));
sink->Stop (Seconds (10.0));
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
ooff = Create<OnOffApplication> (
n3,
InetSocketAddress ("10.1.2.1", port),
"Udp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
ooff->Start(Seconds(1.1));
ooff->Stop (Seconds(10.0));
// Create a packet sink to receive these packets
sink = Create<PacketSink> (
n1,
InetSocketAddress (Ipv4Address::GetAny (), port),
"Udp");
// Start the sink
sink->Start (Seconds (1.1));
sink->Stop (Seconds (10.0));
// Here, finish off packet routing configuration
// This will likely set by some global StaticRouting object in the future
NS_LOG_INFO ("Set Default Routes.");
Ptr<Ipv4> ipv4;
ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
ipv4 = n3->QueryInterface<Ipv4> (Ipv4::iid);
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
// Trace output will be sent to the simple-point-to-point.tr file
NS_LOG_INFO ("Configure Tracing.");
AsciiTrace asciitrace ("simple-point-to-point-olsr.tr");
asciitrace.TraceAllQueues ();
asciitrace.TraceAllNetDeviceRx ();
// Also configure some tcpdump traces; each interface will be traced
// The output files will be named
// simple-point-to-point.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
PcapTrace pcaptrace ("simple-point-to-point-olsr.pcap");
pcaptrace.TraceAllIp ();
NS_LOG_INFO ("Run Simulation.");
Simulator::StopAt (Seconds (10));
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Done.");
}

View File

@@ -227,6 +227,7 @@ main (int argc, char *argv[])
pcaptrace.TraceAllIp ();
NS_LOG_INFO ("Run Simulation.");
Simulator::StopAt (Seconds (10));
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Done.");

View File

@@ -6,6 +6,10 @@ def build(bld):
['point-to-point', 'internet-node', 'global-routing'])
obj.source = 'simple-global-routing.cc'
obj = bld.create_ns3_program('simple-alternate-routing',
['point-to-point', 'internet-node', 'global-routing'])
obj.source = 'simple-alternate-routing.cc'
obj = bld.create_ns3_program('simple-point-to-point',
['point-to-point', 'internet-node'])
obj.source = 'simple-point-to-point.cc'
@@ -33,3 +37,7 @@ def build(bld):
obj = bld.create_ns3_program( 'mixed-global-routing',
['point-to-point', 'internet-node', 'global-routing' , 'csma-cd'])
obj.source = 'mixed-global-routing.cc'
obj = bld.create_ns3_program('simple-point-to-point-olsr',
['point-to-point', 'internet-node', 'olsr'])
obj.source = 'simple-point-to-point-olsr.cc'

View File

@@ -244,6 +244,16 @@ public:
* A packet is allocated a new uid when it is created
* empty or with zero-filled payload.
*
* Note: This uid is an internal uid and cannot be counted on to
* provide an accurate counter of how many "simulated packets" of a
* particular protocol are in the system. It is not trivial to make
* this uid into such a counter, because of questions such as what
* should the uid be when the packet is sent over broadcast media, or
* when fragmentation occurs. If a user wants to trace actual packet
* counts, he or she should look at e.g. the IP ID field or transport
* sequence numbers, or other packet or frame counters at other
* protocol layers.
*
* \returns an integer identifier which uniquely
* identifies this packet.
*/

View File

@@ -496,6 +496,8 @@ DefaultValueTest::RunTests (void)
DefaultValueList::Remove ("bool-a");
DefaultValueList::Remove ("test-i");
DefaultValueList::Remove ("test-c");
DefaultValueList::Remove ("test-x");
DefaultValueList::Remove ("test-y");
DefaultValueList::Remove ("test-ui32");
return result;

View File

@@ -18,6 +18,8 @@
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
// What about print-list!!!!!!???????
#ifdef NS3_LOG_ENABLE
#include <list>
@@ -44,29 +46,33 @@ ComponentList *GetComponentList (void)
return &components;
}
void
LogComponentEnableEnvVar (void)
LogComponent::LogComponent (char const * name)
: m_levels (0), m_name (name)
{
static bool isFirstLog = true;
if (!isFirstLog)
EnvVarCheck (name);
ComponentList *components = GetComponentList ();
for (ComponentListI i = components->begin ();
i != components->end ();
i++)
{
return;
NS_ASSERT (i->first != name);
}
components->push_back (std::make_pair (name, this));
}
void
LogComponent::EnvVarCheck (char const * name)
{
#ifdef HAVE_GETENV
char *envVar = getenv("NS_LOG");
if (envVar == 0)
{
isFirstLog = false;
return;
}
std::string env = envVar;
if (env == "print-list")
{
LogComponentPrintList ();
isFirstLog = false;
return;
}
bool allFound = true;
std::string myName = name;
std::string::size_type cur = 0;
std::string::size_type next = 0;
while (true)
@@ -88,106 +94,101 @@ LogComponentEnableEnvVar (void)
}
std::string::size_type equal = tmp.find ("=");
std::string component;
int level;
if (equal == std::string::npos)
{
component = tmp;
level = LOG_DEBUG;
if (component == myName || component == "*")
{
Enable (LOG_DEBUG);
return;
}
}
else
{
component = tmp.substr (0, equal);
std::string::size_type cur_lev;
std::string::size_type next_lev = equal;
do
if (component == myName || component == "*")
{
cur_lev = next_lev + 1;
next_lev = tmp.find ("|", cur_lev);
std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
if (lev == "error")
int level = 0;
std::string::size_type cur_lev;
std::string::size_type next_lev = equal;
do
{
level |= LOG_ERROR;
}
else if (lev == "warn")
{
level |= LOG_WARN;
}
else if (lev == "debug")
{
level |= LOG_DEBUG;
}
else if (lev == "info")
{
level |= LOG_INFO;
}
else if (lev == "function")
{
level |= LOG_FUNCTION;
}
else if (lev == "param")
{
level |= LOG_PARAM;
}
else if (lev == "logic")
{
level |= LOG_LOGIC;
}
else if (lev == "all")
{
level |= LOG_ALL;
}
else if (lev == "errorlevel")
{
level |= LOG_LEVEL_ERROR;
}
else if (lev == "warnlevel")
{
level |= LOG_LEVEL_WARN;
}
else if (lev == "debuglevel")
{
level |= LOG_LEVEL_DEBUG;
}
else if (lev == "infolevel")
{
level |= LOG_LEVEL_INFO;
}
else if (lev == "functionlevel")
{
level |= LOG_LEVEL_FUNCTION;
}
else if (lev == "paramlevel")
{
level |= LOG_LEVEL_PARAM;
}
else if (lev == "logiclevel")
{
level |= LOG_LEVEL_LOGIC;
}
else if (lev == "alllevel")
{
level |= LOG_LEVEL_ALL;
}
} while (next_lev != std::string::npos);
}
bool found = false;
ComponentList *components = GetComponentList ();
for (ComponentListI i = components->begin ();
i != components->end ();
i++)
{
if (i->first.compare (component) == 0)
{
found = true;
i->second->Enable ((enum LogLevel)level);
break;
cur_lev = next_lev + 1;
next_lev = tmp.find ("|", cur_lev);
std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
if (lev == "error")
{
level |= LOG_ERROR;
}
else if (lev == "warn")
{
level |= LOG_WARN;
}
else if (lev == "debug")
{
level |= LOG_DEBUG;
}
else if (lev == "info")
{
level |= LOG_INFO;
}
else if (lev == "function")
{
level |= LOG_FUNCTION;
}
else if (lev == "param")
{
level |= LOG_PARAM;
}
else if (lev == "logic")
{
level |= LOG_LOGIC;
}
else if (lev == "all")
{
level |= LOG_ALL;
}
else if (lev == "prefix")
{
level |= LOG_PREFIX_ALL;
}
else if (lev == "level_error")
{
level |= LOG_LEVEL_ERROR;
}
else if (lev == "level_warn")
{
level |= LOG_LEVEL_WARN;
}
else if (lev == "level_debug")
{
level |= LOG_LEVEL_DEBUG;
}
else if (lev == "level_info")
{
level |= LOG_LEVEL_INFO;
}
else if (lev == "level_function")
{
level |= LOG_LEVEL_FUNCTION;
}
else if (lev == "level_param")
{
level |= LOG_LEVEL_PARAM;
}
else if (lev == "level_logic")
{
level |= LOG_LEVEL_LOGIC;
}
else if (lev == "level_all")
{
level |= LOG_LEVEL_ALL;
}
} while (next_lev != std::string::npos);
Enable ((enum LogLevel)level);
}
}
if (!found)
{
allFound = false;
}
if (next == std::string::npos)
{
break;
@@ -198,31 +199,14 @@ LogComponentEnableEnvVar (void)
break;
}
}
if (allFound)
{
isFirstLog = false;
}
#endif
}
LogComponent::LogComponent (char const * name)
: m_levels (0)
{
ComponentList *components = GetComponentList ();
for (ComponentListI i = components->begin ();
i != components->end ();
i++)
{
NS_ASSERT (i->first != name);
}
components->push_back (std::make_pair (name, this));
}
bool
LogComponent::IsEnabled (enum LogLevel level) const
{
LogComponentEnableEnvVar ();
// LogComponentEnableEnvVar ();
return (level & m_levels) ? 1 : 0;
}
@@ -244,6 +228,13 @@ LogComponent::Disable (enum LogLevel level)
m_levels &= ~level;
}
char const *
LogComponent::Name (void) const
{
return m_name;
}
void
LogComponentEnable (char const *name, enum LogLevel level)
{
@@ -260,6 +251,18 @@ LogComponentEnable (char const *name, enum LogLevel level)
}
}
void
LogComponentEnableAll (enum LogLevel level)
{
ComponentList *components = GetComponentList ();
for (ComponentListI i = components->begin ();
i != components->end ();
i++)
{
i->second->Enable (level);
}
}
void
LogComponentDisable (char const *name, enum LogLevel level)
{
@@ -276,6 +279,18 @@ LogComponentDisable (char const *name, enum LogLevel level)
}
}
void
LogComponentDisableAll (enum LogLevel level)
{
ComponentList *components = GetComponentList ();
for (ComponentListI i = components->begin ();
i != components->end ();
i++)
{
i->second->Disable (level);
}
}
void
LogComponentPrintList (void)
{

View File

@@ -32,22 +32,23 @@
* send information out on screen. All logging messages
* are disabled by default. To enable selected logging
* messages, use the ns3::LogComponentEnable
* function.
*
* Alternatively, you can use the NS_LOG
* environment variable to define a ';'-separated list of
* function or use the NS_LOG environment variable and
* ns3::LogComponentEnableEnvVar
*
* Use the environment variable NS_LOG to define a ';'-separated list of
* logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
* would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
* NS_LOG=* will enable all available log components.
*
* For each component, the "debug" log level is enabled by default
* but more components can be enabled selectively with the following
* syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
* This example would enable the 'func', 'param', and 'warn' log
* levels for 'Component1' and the 'error' and 'debug' log levels
* for 'Component2'.
* for 'Component2'. The wildcard can be used here as well. For example
* NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
* prints with the component and function names.
*
* The list of available log components can be printed on stdout
* with the NS_LOG=print-list syntax.
*/
/**
@@ -92,20 +93,25 @@
{ \
if (g_log.IsEnabled (level)) \
{ \
std::clog << __PRETTY_FUNCTION__ << " ==> " << \
msg << std::endl; \
if (g_log.IsEnabled (ns3::LOG_PREFIX_ALL)) \
{ \
std::clog << g_log.Name () << ":" << \
__FUNCTION__ << "(): "; \
} \
std::clog << msg << std::endl; \
} \
} \
while (false)
#define NS_LOG_F(level) \
do \
{ \
if (g_log.IsEnabled (level)) \
{ \
std::clog << __PRETTY_FUNCTION__ << std::endl;\
} \
} \
#define NS_LOG_F(level) \
do \
{ \
if (g_log.IsEnabled (level)) \
{ \
std::clog << g_log.Name () << ":" << __FUNCTION__ << \
"()" << std::endl; \
} \
} \
while (false)
#define NS_LOG_ERROR(msg) \
@@ -129,9 +135,6 @@
#define NS_LOG_LOGIC(msg) \
NS_LOG(ns3::LOG_LOGIC, msg)
#define NS_LOG_ALL(msg) \
NS_LOG(ns3::LOG_ALL, msg)
#define NS_LOG_UNCOND(msg) \
do \
{ \
@@ -150,7 +153,6 @@
#define NS_LOG_FUNCTION
#define NS_LOG_PARAM(msg)
#define NS_LOG_LOGIC(msg)
#define NS_LOG_ALL(msg)
#define NS_LOG_UNCOND(msg)
#endif
@@ -160,70 +162,95 @@ namespace ns3 {
#ifdef NS3_LOG_ENABLE
enum LogLevel {
LOG_ERROR = 0x0001, // serious error messages only
LOG_LEVEL_ERROR = 0x0001,
LOG_NONE = 0x00000000, // no logging
LOG_WARN = 0x0002, // warning messages
LOG_LEVEL_WARN = 0x0003,
LOG_ERROR = 0x00000001, // serious error messages only
LOG_LEVEL_ERROR = 0x00000001,
LOG_DEBUG = 0x0004, // rare ad-hoc debug messages
LOG_LEVEL_DEBUG = 0x0007,
LOG_WARN = 0x00000002, // warning messages
LOG_LEVEL_WARN = 0x00000003,
LOG_INFO = 0x0008, // informational messages (e.g., banners)
LOG_LEVEL_INFO = 0x000f,
LOG_DEBUG = 0x00000004, // rare ad-hoc debug messages
LOG_LEVEL_DEBUG = 0x00000007,
LOG_FUNCTION = 0x0010, // function tracing
LOG_LEVEL_FUNCTION = 0x001f,
LOG_INFO = 0x00000008, // informational messages (e.g., banners)
LOG_LEVEL_INFO = 0x0000000f,
LOG_PARAM = 0x0020, // parameters to functions
LOG_LEVEL_PARAM = 0x003f,
LOG_FUNCTION = 0x00000010, // function tracing
LOG_LEVEL_FUNCTION = 0x0000001f,
LOG_LOGIC = 0x0040, // control flow tracing within functions
LOG_LEVEL_LOGIC = 0x007f,
LOG_PARAM = 0x00000020, // parameters to functions
LOG_LEVEL_PARAM = 0x0000003f,
LOG_ALL = 0x4000, // print everything
LOG_LEVEL_ALL = 0x7fff
LOG_LOGIC = 0x00000040, // control flow tracing within functions
LOG_LEVEL_LOGIC = 0x0000007f,
LOG_ALL = 0x7fffffff, // print everything
LOG_LEVEL_ALL = LOG_ALL,
LOG_PREFIX_ALL = 0x80000000 // prefix all trace prints with function
};
#endif
#ifdef NS3_LOG_ENABLE
/**
* \param name a log component name
* \param level a logging level
* \param decorate whether or not to add function names to all logs
* \ingroup logging
*
* Enable the logging output associated with that log component.
* The logging output can be later disabled with a call
* to ns3::LogComponentDisable.
*/
#ifdef NS3_LOG_ENABLE
void LogComponentEnable (char const *name, enum LogLevel level);
#else
#define LogComponentEnable(a,b)
#endif
void LogComponentEnable (char const *name, enum LogLevel level);
/**
* \param level a logging level
* \param decorate whether or not to add function names to all logs
* \ingroup logging
*
* Enable the logging output for all registered log components.
*/
void LogComponentEnableAll (enum LogLevel level);
#else
#define LogComponentEnable(a,b)
#define LogComponentEnableAll(a)
#endif
#ifdef NS3_LOG_ENABLE
/**
* \param name a log component name
* \param level a logging level
* \ingroup logging
*
* Disable the logging output associated with that log component.
* The logging output can be later re-enabled with a call
* to ns3::LogComponentEnable.
*/
#ifdef NS3_LOG_ENABLE
void LogComponentDisable (char const *name, enum LogLevel level);
/**
* \param name a log component name
* \param level a logging level
* \ingroup logging
*
* Disable the logging output associated with that log component.
* The logging output can be later re-enabled with a call
* to ns3::LogComponentEnable.
*/
void LogComponentDisableAll (enum LogLevel level);
#else
#define LogComponentDisable(a,b)
#define LogComponentDisableAll(a)
#endif
/**
* \ingroup logging
*
* Print the list of logging messages available.
* The output of this function can be obtained by setting
* the NS_LOG environment variable to the special value
* 'print-list'.
*
* For example: NS_LOG=print-list
*/
#ifdef NS3_LOG_ENABLE
void LogComponentPrintList (void);
@@ -236,12 +263,17 @@ void LogComponentPrintList (void);
class LogComponent {
public:
LogComponent (char const *name);
void EnvVarCheck (char const *name);
bool IsEnabled (enum LogLevel level) const;
bool IsNoneEnabled (void) const;
void Enable (enum LogLevel level);
void Disable (enum LogLevel level);
bool Decorate (void) const;
char const *Name (void) const;
private:
int32_t m_levels;
int32_t m_levels;
char const *m_name;
bool m_decorate;
};
#endif

View File

@@ -96,7 +96,8 @@ CsmaIpv4Topology::AddIpv4Address(
Ptr<Node> node,
uint32_t netDeviceNumber,
const Ipv4Address address,
const Ipv4Mask mask)
const Ipv4Mask mask,
uint16_t metric)
{
Ptr<NetDevice> nd = node->GetDevice(netDeviceNumber);
@@ -105,6 +106,7 @@ CsmaIpv4Topology::AddIpv4Address(
ipv4->SetAddress (ifIndex, address);
ipv4->SetNetworkMask (ifIndex, mask);
ipv4->SetMetric (ifIndex, metric);
ipv4->SetUp (ifIndex);
return ifIndex;
}

View File

@@ -103,6 +103,7 @@ public:
* the address.
* \param address The Ipv4 Address for the interface.
* \param network The network mask for the interface
* \param metric (optional) metric (cost) to assign for routing calculations
*
* Add an Ipv4Address to the Ipv4 interface associated with the
* ndNum CsmaIpv4NetDevices on the provided CsmaIpv4Channel
@@ -110,7 +111,8 @@ public:
static uint32_t AddIpv4Address(Ptr<Node> node,
uint32_t netDeviceNumber,
const Ipv4Address address,
const Ipv4Mask mask);
const Ipv4Mask mask,
uint16_t metric = 1);
/**
* \param nd1 Node

View File

@@ -103,6 +103,59 @@ PointToPointTopology::AddIpv4Addresses(
}
void
PointToPointTopology::SetIpv4Metric(
Ptr<const PointToPointChannel> chan,
Ptr<Node> n1, Ptr<Node> n2, const uint16_t metric)
{
// The PointToPoint channel is used to find the relevant NetDevices
NS_ASSERT (chan->GetNDevices () == 2);
Ptr<NetDevice> nd1 = chan->GetDevice (0);
Ptr<NetDevice> nd2 = chan->GetDevice (1);
// Make sure that nd1 belongs to n1 and nd2 to n2
if ( (nd1->GetNode ()->GetId () == n2->GetId () ) &&
(nd2->GetNode ()->GetId () == n1->GetId () ) )
{
std::swap(nd1, nd2);
}
NS_ASSERT (nd1->GetNode ()->GetId () == n1->GetId ());
NS_ASSERT (nd2->GetNode ()->GetId () == n2->GetId ());
// The NetDevice ifIndex does not correspond to the
// ifIndex used by Ipv4. Therefore, we have to iterate
// through the NetDevices until we find the Ipv4 ifIndex
// that corresponds to NetDevice nd1
// Get interface indexes for both nodes corresponding to the right channel
uint32_t index = 0;
bool found = false;
Ptr<Ipv4> ip1 = n1->QueryInterface<Ipv4> (Ipv4::iid);
for (uint32_t i = 0; i < ip1->GetNInterfaces (); i++)
{
if (ip1 ->GetNetDevice (i) == nd1)
{
index = i;
found = true;
}
}
NS_ASSERT(found);
ip1->SetMetric (index, metric);
index = 0;
found = false;
Ptr<Ipv4> ip2 = n2->QueryInterface<Ipv4> (Ipv4::iid);
for (uint32_t i = 0; i < ip2->GetNInterfaces (); i++)
{
if (ip2 ->GetNetDevice (i) == nd2)
{
index = i;
found = true;
}
}
NS_ASSERT(found);
ip2->SetMetric (index, metric);
}
void
PointToPointTopology::AddIpv4Routes (
Ptr<Node> n1, Ptr<Node> n2, Ptr<const PointToPointChannel> chan)

View File

@@ -70,6 +70,20 @@ public:
Ptr<Node> n1, const Ipv4Address& addr1,
Ptr<Node> n2, const Ipv4Address& addr2);
/**
* \param chan PointToPointChannel to use
* \param n1 Node
* \param n2 Node
* \param metric link metric to assign on Ipv4Link on chan between n1 and n2
*
* Add a non-unit-cost link metric (bidirectionally) to the Ipv4
* interfaces associated with the two PointToPointNetDevices on the
* provided PointToPointChannel
*/
static void SetIpv4Metric(
Ptr<const PointToPointChannel> chan,
Ptr<Node> n1, Ptr<Node> n2, const uint16_t metric);
/**
* \param channel PointToPointChannel to use
* \param n1 Node

View File

@@ -201,6 +201,18 @@ Ipv4Impl::GetAddress (uint32_t i) const
return m_ipv4->GetAddress (i);
}
void
Ipv4Impl::SetMetric (uint32_t i, uint16_t metric)
{
m_ipv4->SetMetric (i, metric);
}
uint16_t
Ipv4Impl::GetMetric (uint32_t i) const
{
return m_ipv4->GetMetric (i);
}
bool
Ipv4Impl::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const
{

View File

@@ -88,6 +88,8 @@ public:
virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask);
virtual Ipv4Mask GetNetworkMask (uint32_t t) const;
virtual Ipv4Address GetAddress (uint32_t i) const;
virtual void SetMetric (uint32_t i, uint16_t metric);
virtual uint16_t GetMetric (uint32_t i) const;
virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const;
virtual bool GetIfIndexForDestination (Ipv4Address dest,
uint32_t &ifIndex) const;

View File

@@ -37,7 +37,8 @@ namespace ns3 {
*/
Ipv4Interface::Ipv4Interface (Ptr<NetDevice> nd)
: m_netdevice (nd),
m_ifup(false)
m_ifup(false),
m_metric(1)
{
NS_LOG_FUNCTION;
NS_LOG_PARAM ("(" << &nd << ")");
@@ -96,6 +97,21 @@ Ipv4Interface::GetNetworkMask (void) const
return m_netmask;
}
void
Ipv4Interface::SetMetric (uint16_t metric)
{
NS_LOG_FUNCTION;
NS_LOG_PARAM ("(" << metric << ")");
m_metric = metric;
}
uint16_t
Ipv4Interface::GetMetric (void) const
{
NS_LOG_FUNCTION;
return m_metric;
}
Ipv4Address
Ipv4Interface::GetAddress (void) const
{

View File

@@ -96,6 +96,14 @@ public:
* \returns the ipv4 netmask of this interface
*/
Ipv4Mask GetNetworkMask (void) const;
/**
* \param configured routing metric (cost) of this interface
*/
void SetMetric (uint16_t);
/**
* \returns configured routing metric (cost) of this interface
*/
uint16_t GetMetric (void) const;
/**
* \returns the ipv4 address of this interface
*/
@@ -147,6 +155,7 @@ private:
bool m_ifup;
Ipv4Address m_address;
Ipv4Mask m_netmask;
uint16_t m_metric;
};
}; // namespace ns3

View File

@@ -821,6 +821,24 @@ Ipv4L3Protocol::GetAddress (uint32_t i) const
return interface->GetAddress ();
}
void
Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
{
NS_LOG_FUNCTION;
NS_LOG_PARAM ("(" << i << ", " << metric << ")");
Ptr<Ipv4Interface> interface = GetInterface (i);
interface->SetMetric (metric);
}
uint16_t
Ipv4L3Protocol::GetMetric (uint32_t i) const
{
NS_LOG_FUNCTION;
NS_LOG_PARAM ("(" << i << ")");
Ptr<Ipv4Interface> interface = GetInterface (i);
return interface->GetMetric ();
}
bool
Ipv4L3Protocol::GetIfIndexForDestination (
Ipv4Address destination, uint32_t& ifIndex) const

View File

@@ -198,6 +198,8 @@ public:
void SetNetworkMask (uint32_t i, Ipv4Mask mask);
Ipv4Mask GetNetworkMask (uint32_t t) const;
Ipv4Address GetAddress (uint32_t i) const;
void SetMetric (uint32_t i, uint16_t metric);
uint16_t GetMetric (uint32_t i) const;
bool GetIfIndexForDestination (Ipv4Address destination,
uint32_t& ifIndex) const;
uint16_t GetMtu (uint32_t i) const;

View File

@@ -151,16 +151,6 @@ Ipv4Address::Set (char const *address)
m_address = AsciiToIpv4Host (address);
}
bool
Ipv4Address::IsEqual (Ipv4Address other) const
{
if (other.m_address == m_address) {
return true;
} else {
return false;
}
}
Ipv4Address
Ipv4Address::CombineMask (Ipv4Mask const &mask) const
{
@@ -296,19 +286,6 @@ Ipv4Address::GetLoopback (void)
return loopback;
}
bool operator == (Ipv4Address const &a, Ipv4Address const &b)
{
return a.IsEqual (b);
}
bool operator != (Ipv4Address const &a, Ipv4Address const &b)
{
return !a.IsEqual (b);
}
bool operator < (Ipv4Address const &addrA, Ipv4Address const &addrB)
{
return (addrA.GetHostOrder () < addrB.GetHostOrder ());
}
size_t Ipv4AddressHash::operator()(Ipv4Address const &x) const
{
return x.GetHostOrder ();

View File

@@ -73,7 +73,10 @@ public:
* \param other address to which to compare this address
* \return True if the addresses are equal. False otherwise.
*/
bool IsEqual (Ipv4Address other) const;
bool IsEqual (const Ipv4Address &other) const
{
return m_address == other.m_address;
}
/**
* \brief Get the host-order 32-bit IP address
@@ -142,6 +145,10 @@ private:
Address ConvertTo (void) const;
static uint8_t GetType (void);
uint32_t m_address;
friend bool operator == (Ipv4Address const &a, Ipv4Address const &b);
friend bool operator != (Ipv4Address const &a, Ipv4Address const &b);
friend bool operator < (Ipv4Address const &addrA, Ipv4Address const &addrB);
};
@@ -177,9 +184,19 @@ private:
std::ostream& operator<< (std::ostream& os, Ipv4Address const& address);
std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask);
bool operator == (Ipv4Address const &a, Ipv4Address const &b);
bool operator != (Ipv4Address const &a, Ipv4Address const &b);
bool operator < (Ipv4Address const &addrA, Ipv4Address const &addrB);
inline bool operator == (const Ipv4Address &a, const Ipv4Address &b)
{
return (a.m_address == b.m_address);
}
inline bool operator != (const Ipv4Address &a, const Ipv4Address &b)
{
return (a.m_address != b.m_address);
}
inline bool operator < (const Ipv4Address &a, const Ipv4Address &b)
{
return (a.m_address < b.m_address);
}
class Ipv4AddressHash : public std::unary_function<Ipv4Address, size_t> {
public:

View File

@@ -383,6 +383,20 @@ public:
*/
virtual Ipv4Mask GetNetworkMask (uint32_t i) const = 0;
/**
* \param i index of ipv4 interface
* \param metric routing metric (cost) associated to the underlying
* ipv4 interface
*/
virtual void SetMetric (uint32_t i, uint16_t metric) = 0;
/**
* \param i index of ipv4 interface
* \returns routing metric (cost) associated to the underlying
* ipv4 interface
*/
virtual uint16_t GetMetric (uint32_t i) const = 0;
/**
* \param i index of ipv4 interface
* \returns the address associated to the underlying ipv4 interface

View File

@@ -529,7 +529,8 @@ GlobalRouteManagerImpl::SPFNext (SPFVertex* v, CandidateQueue& candidate)
// Get w_lsa: In case of V is Router-LSA
if (v->GetVertexType () == SPFVertex::VertexRouter)
{
NS_LOG_LOGIC ("Examining " << v->GetVertexId () << "'s " <<
NS_LOG_LOGIC ("Examining link " << i << " of " <<
v->GetVertexId () << "'s " <<
v->GetLSA ()->GetNLinkRecords () << " link records");
//
// (a) If this is a link to a stub network, examine the next link in V's LSA.
@@ -637,7 +638,8 @@ GlobalRouteManagerImpl::SPFNext (SPFVertex* v, CandidateQueue& candidate)
candidate.Push (w);
NS_LOG_LOGIC ("Pushing " <<
w->GetVertexId () << ", parent vertexId: " <<
v->GetVertexId ());
v->GetVertexId () << ", distance: " <<
w->GetDistanceFromRoot ());
}
}
else if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_CANDIDATE)
@@ -688,7 +690,7 @@ GlobalRouteManagerImpl::SPFNext (SPFVertex* v, CandidateQueue& candidate)
}
//
// This method is derived from quagga ospf_next_hop_calculation() 16.1.1.
// This method is derived from quagga ospf_nexthop_calculation() 16.1.1.
//
// Calculate nexthop from root through V (parent) to vertex W (destination)
// with given distance from root->W.
@@ -784,11 +786,13 @@ GlobalRouteManagerImpl::SPFNexthopCalculation (
//
w->SetOutgoingInterfaceId (
FindOutgoingInterfaceId (l->GetLinkData ()));
w->SetDistanceFromRoot (distance);
w->SetParent (v);
NS_LOG_LOGIC ("Next hop from " <<
v->GetVertexId () << " to " << w->GetVertexId () <<
" goes through next hop " << w->GetNextHop () <<
" via outgoing interface " << w->GetOutgoingInterfaceId ());
" via outgoing interface " << w->GetOutgoingInterfaceId () <<
" with distance " << distance);
} // end W is a router vertes
else
{
@@ -804,7 +808,8 @@ GlobalRouteManagerImpl::SPFNexthopCalculation (
w->SetParent (v);
NS_LOG_LOGIC ("Next hop from " <<
v->GetVertexId () << " to network " << w->GetVertexId () <<
" via outgoing interface " << w->GetOutgoingInterfaceId ());
" via outgoing interface " << w->GetOutgoingInterfaceId () <<
" with distance " << distance);
return 1;
}
} // end v is the root
@@ -997,6 +1002,7 @@ GlobalRouteManagerImpl::SPFCalculate (Ipv4Address root)
m_spfroot= v;
v->SetDistanceFromRoot (0);
v->GetLSA ()->SetStatus (GlobalRoutingLSA::LSA_SPF_IN_SPFTREE);
NS_LOG_LOGIC ("Starting SPFCalculate for node " << root);
for (;;)
{

View File

@@ -50,7 +50,7 @@ GlobalRoutingLinkRecord::GlobalRoutingLinkRecord (
LinkType linkType,
Ipv4Address linkId,
Ipv4Address linkData,
uint32_t metric)
uint16_t metric)
:
m_linkId (linkId),
m_linkData (linkData),
@@ -110,7 +110,7 @@ GlobalRoutingLinkRecord::SetLinkType (
m_linkType = linkType;
}
uint32_t
uint16_t
GlobalRoutingLinkRecord::GetMetric (void) const
{
NS_LOG_FUNCTION;
@@ -118,7 +118,7 @@ GlobalRoutingLinkRecord::GetMetric (void) const
}
void
GlobalRoutingLinkRecord::SetMetric (uint32_t metric)
GlobalRoutingLinkRecord::SetMetric (uint16_t metric)
{
NS_LOG_FUNCTION;
m_metric = metric;
@@ -202,6 +202,7 @@ GlobalRoutingLSA::CopyLinkRecords (const GlobalRoutingLSA& lsa)
pDst->SetLinkType (pSrc->GetLinkType ());
pDst->SetLinkId (pSrc->GetLinkId ());
pDst->SetLinkData (pSrc->GetLinkData ());
pDst->SetMetric (pSrc->GetMetric ());
m_linkRecords.push_back(pDst);
pDst = 0;
@@ -397,6 +398,7 @@ GlobalRoutingLSA::Print (std::ostream &os) const
os << "----------" << std::endl;
os << "m_linkId = " << p->GetLinkId () << std::endl;
os << "m_linkData = " << p->GetLinkData () << std::endl;
os << "m_metric = " << p->GetMetric () << std::endl;
}
}
else if (m_lsType == GlobalRoutingLSA::NetworkLSA)
@@ -547,6 +549,7 @@ GlobalRouter::DiscoverLSAs (void)
Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
NS_LOG_LOGIC ("Working with local address " << addrLocal);
uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal);
//
// Now, we're going to walk over to the remote net device on the other end of
// the point-to-point channel we now know we have. This is where our adjacent
@@ -566,8 +569,7 @@ GlobalRouter::DiscoverLSAs (void)
Ipv4Address maskLocalAddr;
maskLocalAddr.Set(maskLocal.GetHostOrder ());
plr->SetLinkData (maskLocalAddr);
// Cost is interface's configured output cost (NOTYET)
plr->SetMetric (1);
plr->SetMetric (metricLocal);
pLSA->AddLinkRecord(plr);
plr = 0;
continue;
@@ -589,8 +591,7 @@ GlobalRouter::DiscoverLSAs (void)
plr->SetLinkId (desigRtr);
// Link Data is router's own IP address
plr->SetLinkData (addrLocal);
// Cost is interface's configured output cost (NOTYET)
plr->SetMetric (1);
plr->SetMetric (metricLocal);
pLSA->AddLinkRecord (plr);
plr = 0;
continue;
@@ -613,6 +614,7 @@ GlobalRouter::DiscoverLSAs (void)
Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
NS_LOG_LOGIC ("Working with local address " << addrLocal);
uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal);
//
// Now, we're going to walk over to the remote net device on the other end of
// the point-to-point channel we now know we have. This is where our adjacent
@@ -659,6 +661,7 @@ GlobalRouter::DiscoverLSAs (void)
plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint);
plr->SetLinkId (rtrIdRemote);
plr->SetLinkData (addrLocal);
plr->SetMetric (metricLocal);
pLSA->AddLinkRecord (plr);
plr = 0;
@@ -666,6 +669,7 @@ GlobalRouter::DiscoverLSAs (void)
plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
plr->SetLinkId (addrRemote);
plr->SetLinkData (Ipv4Address(maskRemote.GetHostOrder())); // Frown
plr->SetMetric (metricLocal);
pLSA->AddLinkRecord (plr);
plr = 0;
}

View File

@@ -82,7 +82,7 @@ public:
LinkType linkType,
Ipv4Address linkId,
Ipv4Address linkData,
uint32_t metric);
uint16_t metric);
/**
* @brief Destroy a Global Routing Link Record.
@@ -176,7 +176,7 @@ public:
*
* @returns The metric field of the Global Routing Link Record.
*/
uint32_t GetMetric(void) const;
uint16_t GetMetric(void) const;
/**
* @brief Set the Metric Data field of the Global Routing Link Record.
@@ -189,7 +189,7 @@ public:
*
* @param metric The new metric for the current Global Routing Link Record.
*/
void SetMetric(uint32_t metric);
void SetMetric(uint16_t metric);
private:
/**
@@ -230,7 +230,7 @@ private:
* of two hops relate to the cost of sending a packet); rather you should
* use something like delay.
*/
uint32_t m_metric;
uint16_t m_metric;
};
/**

View File

@@ -1,7 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INESC Porto
* All rights reserved.
*
* 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
@@ -34,17 +33,11 @@ EventGarbageCollector::EventGarbageCollector () :
void
EventGarbageCollector::Track (EventId event)
{
m_events.push_back (event);
m_events.insert (event);
if (m_events.size () >= m_nextCleanupSize)
Cleanup ();
}
inline bool
EventExpiredPredicate (const EventId &event)
{
return event.IsExpired ();
}
void
EventGarbageCollector::Grow ()
{
@@ -64,7 +57,15 @@ EventGarbageCollector::Shrink ()
void
EventGarbageCollector::Cleanup ()
{
m_events.remove_if (EventExpiredPredicate);
for (EventList::iterator iter = m_events.begin (); iter != m_events.end ();)
{
if ((*iter).IsExpired ())
{
m_events.erase (iter++);
}
else
break; // EventIds are sorted by timestamp => further events are not expired for sure
}
// If after cleanup we are still over the limit, increase the limit.
if (m_events.size () >= m_nextCleanupSize)
@@ -76,7 +77,7 @@ EventGarbageCollector::Cleanup ()
EventGarbageCollector::~EventGarbageCollector ()
{
for (std::list<EventId>::iterator event = m_events.begin ();
for (EventList::iterator event = m_events.begin ();
event != m_events.end (); event++)
{
Simulator::Cancel (*event);

View File

@@ -1,7 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INESC Porto
* All rights reserved.
*
* 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
@@ -21,9 +20,9 @@
#ifndef EVENT_GARBAGE_COLLECTOR_H
#define EVENT_GARBAGE_COLLECTOR_H
#include <list>
#include "event-id.h"
#include "simulator.h"
#include <set>
#include "ns3/event-id.h"
#include "ns3/simulator.h"
namespace ns3 {
@@ -49,8 +48,18 @@ public:
private:
std::list<EventId>::size_type m_nextCleanupSize;
std::list<EventId> m_events;
struct EventIdLessThanTs
{
bool operator () (const EventId &a, const EventId &b) const
{
return (a.GetTs () < b.GetTs ());
}
};
typedef std::multiset<EventId, EventIdLessThanTs> EventList;
EventList::size_type m_nextCleanupSize;
EventList m_events;
void Cleanup ();
void Grow ();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2004 Francisco J. Ros
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Authors: Francisco J. Ros <fjrm@dif.um.es>
* Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
#ifndef __OLSR_AGENT_IMPL_H__
#define __OLSR_AGENT_IMPL_H__
#include <vector>
#include "olsr-agent.h"
#include "olsr-header.h"
#include "olsr-state.h"
#include "routing-table.h"
#include "repositories.h"
#include "ns3/object.h"
#include "ns3/packet.h"
#include "ns3/node.h"
#include "ns3/socket.h"
#include "event-garbage-collector.h"
#include "ns3/timer.h"
namespace ns3 {
using namespace olsr;
class OlsrAgentImpl : public OlsrAgent
{
friend class OlsrTest;
public:
OlsrAgentImpl (Ptr<Node> node);
virtual void Start ();
virtual void SetMainInterface (uint32_t interface);
private:
EventGarbageCollector m_events;
/// Address of the routing agent.
Ipv4Address m_routingAgentAddr;
/// Packets sequence number counter.
uint16_t m_packetSequenceNumber;
/// Messages sequence number counter.
uint16_t m_messageSequenceNumber;
/// Advertised Neighbor Set sequence number.
uint16_t m_ansn;
/// HELLO messages' emission interval.
Time m_helloInterval;
/// TC messages' emission interval.
Time m_tcInterval;
/// MID messages' emission interval.
Time m_midInterval;
/// Willingness for forwarding packets on behalf of other nodes.
uint8_t m_willingness;
/// Determines if layer 2 notifications are enabled or not.
bool m_useL2Notifications;
/// Routing table.
Ptr<RoutingTable> m_routingTable;
/// Internal state with all needed data structs.
OlsrState m_state;
Ptr<Ipv4> m_ipv4;
protected:
void DoDispose ();
void SendPacket (Packet packet);
/// Increments packet sequence number and returns the new value.
inline uint16_t GetPacketSequenceNumber ();
/// Increments message sequence number and returns the new value.
inline uint16_t GetMessageSequenceNumber ();
void RecvOlsr (Ptr<Socket> socket,
const Packet &receivedPacket,
const Address &sourceAddress);
void MprComputation ();
void RoutingTableComputation ();
Ipv4Address GetMainAddress (Ipv4Address iface_addr);
// Timer handlers
Timer m_helloTimer;
void HelloTimerExpire ();
Timer m_tcTimer;
void TcTimerExpire ();
Timer m_midTimer;
void MidTimerExpire ();
void DupTupleTimerExpire (DuplicateTuple tuple);
bool m_linkTupleTimerFirstTime;
void LinkTupleTimerExpire (LinkTuple tuple);
void Nb2hopTupleTimerExpire (TwoHopNeighborTuple tuple);
void MprSelTupleTimerExpire (MprSelectorTuple tuple);
void TopologyTupleTimerExpire (TopologyTuple tuple);
void IfaceAssocTupleTimerExpire (IfaceAssocTuple tuple);
/// A list of pending messages which are buffered awaiting for being sent.
std::vector<OlsrMessageHeader> m_queuedMessages;
Timer m_queuedMessagesTimer; // timer for throttling outgoing messages
void ForwardDefault (OlsrMessageHeader olsrMessage,
DuplicateTuple *duplicated,
const Ipv4Address &localIface,
const Ipv4Address &senderAddress);
void QueueMessage (const OlsrMessageHeader &message, Time delay);
void SendQueuedMessages ();
void SendHello ();
void SendTc ();
void SendMid ();
void NeighborLoss (const LinkTuple &tuple);
void AddDuplicateTuple (const DuplicateTuple &tuple);
void RemoveDuplicateTuple (const DuplicateTuple &tuple);
LinkTuple & AddLinkTuple (const LinkTuple &tuple, uint8_t willingness);
void RemoveLinkTuple (const LinkTuple &tuple);
void LinkTupleUpdated (const LinkTuple &tuple);
void AddNeighborTuple (const NeighborTuple &tuple);
void RemoveNeighborTuple (const NeighborTuple &tuple);
void AddTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
void RemoveTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
void AddMprSelectorTuple (const MprSelectorTuple &tuple);
void RemoveMprSelectorTuple (const MprSelectorTuple &tuple);
void AddTopologyTuple (const TopologyTuple &tuple);
void RemoveTopologyTuple (const TopologyTuple &tuple);
void AddIfaceAssocTuple (const IfaceAssocTuple &tuple);
void RemoveIfaceAssocTuple (const IfaceAssocTuple &tuple);
void ProcessHello (const OlsrMessageHeader &msg,
const Ipv4Address &receiverIface,
const Ipv4Address &senderIface);
void ProcessTc (const OlsrMessageHeader &msg,
const Ipv4Address &senderIface);
void ProcessMid (const OlsrMessageHeader &msg,
const Ipv4Address &senderIface);
void LinkSensing (const OlsrMessageHeader &msg,
const OlsrMessageHeader::Hello &hello,
const Ipv4Address &receiverIface,
const Ipv4Address &sender_iface);
void PopulateNeighborSet (const OlsrMessageHeader &msg,
const OlsrMessageHeader::Hello &hello);
void PopulateTwoHopNeighborSet (const OlsrMessageHeader &msg,
const OlsrMessageHeader::Hello &hello);
void PopulateMprSelectorSet (const OlsrMessageHeader &msg,
const OlsrMessageHeader::Hello &hello);
int Degree (NeighborTuple const &tuple);
Ipv4Address m_mainAddress;
Ptr<Socket> m_receiveSocket; // UDP socket for receving OSLR packets
Ptr<Socket> m_sendSocket; // UDP socket for sending OSLR packets
};
} // namespace ns3
#endif

View File

@@ -0,0 +1,29 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
#include "olsr-agent.h"
#include "olsr-agent-impl.h"
namespace ns3 {
const InterfaceId OlsrAgent::iid = MakeInterfaceId ("OlsrAgent", Object::iid);
const ClassId OlsrAgent::cid = MakeClassId< OlsrAgentImpl, Ptr<Node> > ("OlsrAgent", OlsrAgent::iid);
}

View File

@@ -0,0 +1,81 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
#ifndef OLSR_AGENT_H
#define OLSR_AGENT_H
#include "ns3/node.h"
#include "ns3/component-manager.h"
namespace ns3 {
/**
* \brief Class implementing the OLSR state machine
*
* This class represents an instance of the OLSR protocol. It
* attaches itself to a Node, and its lifecycle is bound to that node.
* Normally the functions in the ns3::olsr namespace are more simple
* to use to start OLSR on nodes, but access to the underlying OLSR
* agent can be useful in order to customize the OLSR parameters.
* Example:
*
* \code
* Ptr<OlsrAgent> olsr = ComponentManager::Create<OlsrAgent, Ptr<Node> > (OlsrAgent::cid, OlsrAgent::iid, node);
* agent->SetMainInterface (2);
* agent->Start ();
* \endcode
*/
class OlsrAgent : public Object
{
public:
static const InterfaceId iid;
static const ClassId cid;
/**
* \brief Sets the main interface to be used by OLSR
*
* Normally OLSR supports multiple interfaces, but the protocol
* requires the definition of a "main interface". This interface's
* IPv4 address provides the identity of the node, and all outgoing
* OLSR routing messages must have the main interface address,
* regardless of the actual interface used to transmit the packet.
* This method allows one to explicitly select an interface as the
* main interface. It must be called before the agent starts, but
* calling it is optional; if not called, the agent tries to guess
* and uses a suitable interface.
*/
virtual void SetMainInterface (uint32_t interface) = 0;
/**
* \brief Starts the OLSR protocol operation
*
* Calling this method essentially bootstraps the OLSR protocol, and
* causes the agent to start broadcasting OLSR messages to
* neighbors, as well start listening to messages from neighbors.
*/
virtual void Start () = 0;
};
}; // namespace ns3
#endif /* OLSR_AGENT_H */

View File

@@ -0,0 +1,734 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
#include "ns3/assert.h"
#include "olsr-header.h"
#define IPV4_ADDRESS_SIZE 4
#define OLSR_MSG_HEADER_SIZE 12
#define OLSR_PKT_HEADER_SIZE 4
namespace ns3 {
/// Scaling factor used in RFC 3626.
#define OLSR_C 0.0625
///
/// \brief Converts a decimal number of seconds to the mantissa/exponent format.
///
/// \param seconds decimal number of seconds we want to convert.
/// \return the number of seconds in mantissa/exponent format.
///
uint8_t
OlsrSecondsToEmf (double seconds)
{
int a, b = 0;
// find the largest integer 'b' such that: T/C >= 2^b
for (b = 0; (seconds/OLSR_C) >= (1 << b); ++b)
;
NS_ASSERT ((seconds/OLSR_C) < (1 << b));
b--;
NS_ASSERT ((seconds/OLSR_C) >= (1 << b));
// compute the expression 16*(T/(C*(2^b))-1), which may not be a integer
double tmp = 16*(seconds/(OLSR_C*(1<<b))-1);
// round it up. This results in the value for 'a'
a = (int) ceil (tmp);
// if 'a' is equal to 16: increment 'b' by one, and set 'a' to 0
if (a == 16)
{
b += 1;
a = 0;
}
// now, 'a' and 'b' should be integers between 0 and 15,
NS_ASSERT (a >= 0 && a < 16);
NS_ASSERT (b >= 0 && b < 16);
// the field will be a byte holding the value a*16+b
return (uint8_t) ((a << 4) | b);
}
///
/// \brief Converts a number of seconds in the mantissa/exponent format to a decimal number.
///
/// \param olsr_format number of seconds in mantissa/exponent format.
/// \return the decimal number of seconds.
///
double
OlsrEmfToSeconds (uint8_t olsrFormat)
{
int a = (olsrFormat >> 4);
int b = (olsrFormat & 0xf);
// value = C*(1+a/16)*2^b [in seconds]
return OLSR_C * (1 + a/16.0) * (1 << b);
}
// ---------------- OLSR Packet -------------------------------
OlsrPacketHeader::OlsrPacketHeader ()
{}
OlsrPacketHeader::~OlsrPacketHeader ()
{}
uint32_t
OlsrPacketHeader::GetUid (void)
{
static uint32_t uid = AllocateUid<OlsrPacketHeader>
("OlsrPacketHeader.nsnam.org");
return uid;
}
uint32_t
OlsrPacketHeader::GetSerializedSize (void) const
{
return OLSR_PKT_HEADER_SIZE;
}
void
OlsrPacketHeader::Print (std::ostream &os) const
{
// TODO
}
void
OlsrPacketHeader::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
i.WriteHtonU16 (m_packetLength);
i.WriteHtonU16 (m_packetSequenceNumber);
}
uint32_t
OlsrPacketHeader::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
m_packetLength = i.ReadNtohU16 ();
m_packetSequenceNumber = i.ReadNtohU16 ();
return GetSerializedSize ();
}
// ---------------- OLSR Message -------------------------------
OlsrMessageHeader::OlsrMessageHeader ()
: m_messageType (OlsrMessageHeader::MessageType (0))
{}
OlsrMessageHeader::~OlsrMessageHeader ()
{}
uint32_t
OlsrMessageHeader::GetUid (void)
{
static uint32_t uid = AllocateUid<OlsrMessageHeader>
("OlsrMessageHeader.nsnam.org");
return uid;
}
uint32_t
OlsrMessageHeader::GetSerializedSize (void) const
{
uint32_t size = OLSR_MSG_HEADER_SIZE;
switch (m_messageType)
{
case MID_MESSAGE:
size += m_message.mid.GetSerializedSize ();
break;
case HELLO_MESSAGE:
size += m_message.hello.GetSerializedSize ();
break;
case TC_MESSAGE:
size += m_message.tc.GetSerializedSize ();
break;
case HNA_MESSAGE:
size += m_message.hna.GetSerializedSize ();
break;
default:
NS_ASSERT (false);
}
return size;
}
void
OlsrMessageHeader::Print (std::ostream &os) const
{
// TODO
}
void
OlsrMessageHeader::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
i.WriteU8 (m_messageType);
i.WriteU8 (m_vTime);
i.WriteHtonU16 (GetSerializedSize () - OLSR_MSG_HEADER_SIZE);
i.WriteHtonU32 (m_originatorAddress.GetHostOrder ());
i.WriteU8 (m_timeToLive);
i.WriteU8 (m_hopCount);
i.WriteHtonU16 (m_messageSequenceNumber);
switch (m_messageType)
{
case MID_MESSAGE:
m_message.mid.Serialize (i);
break;
case HELLO_MESSAGE:
m_message.hello.Serialize (i);
break;
case TC_MESSAGE:
m_message.tc.Serialize (i);
break;
case HNA_MESSAGE:
m_message.hna.Serialize (i);
break;
default:
NS_ASSERT (false);
}
}
uint32_t
OlsrMessageHeader::Deserialize (Buffer::Iterator start)
{
uint32_t size;
Buffer::Iterator i = start;
m_messageType = (MessageType) i.ReadU8 ();
NS_ASSERT (m_messageType >= HELLO_MESSAGE && m_messageType <= HNA_MESSAGE);
m_vTime = i.ReadU8 ();
m_messageSize = i.ReadNtohU16 ();
m_originatorAddress = Ipv4Address (i.ReadNtohU32 ());
m_timeToLive = i.ReadU8 ();
m_hopCount = i.ReadU8 ();
m_messageSequenceNumber = i.ReadNtohU16 ();
size = OLSR_MSG_HEADER_SIZE;
switch (m_messageType)
{
case MID_MESSAGE:
size += m_message.mid.Deserialize (i, m_messageSize);
break;
case HELLO_MESSAGE:
size += m_message.hello.Deserialize (i, m_messageSize);
break;
case TC_MESSAGE:
size += m_message.tc.Deserialize (i, m_messageSize);
break;
case HNA_MESSAGE:
size += m_message.hna.Deserialize (i, m_messageSize);
break;
default:
NS_ASSERT (false);
}
return size;
}
// ---------------- OLSR MID Message -------------------------------
uint32_t
OlsrMessageHeader::Mid::GetSerializedSize (void) const
{
return this->interfaceAddresses.size () * IPV4_ADDRESS_SIZE;
}
void
OlsrMessageHeader::Mid::Print (std::ostream &os) const
{
// TODO
}
void
OlsrMessageHeader::Mid::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
for (std::vector<Ipv4Address>::const_iterator iter = this->interfaceAddresses.begin ();
iter != this->interfaceAddresses.end (); iter++)
{
i.WriteHtonU32 (iter->GetHostOrder ());
}
}
uint32_t
OlsrMessageHeader::Mid::Deserialize (Buffer::Iterator start, uint32_t messageSize)
{
Buffer::Iterator i = start;
this->interfaceAddresses.clear ();
NS_ASSERT (messageSize >= 0);
NS_ASSERT (messageSize % IPV4_ADDRESS_SIZE == 0);
int numAddresses = messageSize / IPV4_ADDRESS_SIZE;
this->interfaceAddresses.erase (this->interfaceAddresses.begin(),
this->interfaceAddresses.end ());
for (int n = 0; n < numAddresses; ++n)
this->interfaceAddresses.push_back (Ipv4Address (i.ReadNtohU32 ()));
return GetSerializedSize ();
}
// ---------------- OLSR HELLO Message -------------------------------
uint32_t
OlsrMessageHeader::Hello::GetSerializedSize (void) const
{
uint32_t size = 4;
for (std::vector<LinkMessage>::const_iterator iter = this->linkMessages.begin ();
iter != this->linkMessages.end (); iter++)
{
const LinkMessage &lm = *iter;
size += 4;
size += IPV4_ADDRESS_SIZE * lm.neighborInterfaceAddresses.size ();
}
return size;
}
void
OlsrMessageHeader::Hello::Print (std::ostream &os) const
{
// TODO
}
void
OlsrMessageHeader::Hello::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
i.WriteU16 (0); // Reserved
i.WriteU8 (this->hTime);
i.WriteU8 (this->willingness);
for (std::vector<LinkMessage>::const_iterator iter = this->linkMessages.begin ();
iter != this->linkMessages.end (); iter++)
{
const LinkMessage &lm = *iter;
i.WriteU8 (lm.linkCode);
i.WriteU8 (0); // Reserved
// The size of the link message, counted in bytes and measured
// from the beginning of the "Link Code" field and until the
// next "Link Code" field (or - if there are no more link types
// - the end of the message).
i.WriteHtonU16 (4 + lm.neighborInterfaceAddresses.size () * IPV4_ADDRESS_SIZE);
for (std::vector<Ipv4Address>::const_iterator neigh_iter = lm.neighborInterfaceAddresses.begin ();
neigh_iter != lm.neighborInterfaceAddresses.end (); neigh_iter++)
{
i.WriteHtonU32 (neigh_iter->GetHostOrder ());
}
}
}
uint32_t
OlsrMessageHeader::Hello::Deserialize (Buffer::Iterator start, uint32_t messageSize)
{
Buffer::Iterator i = start;
NS_ASSERT (messageSize >= 4);
this->linkMessages.clear ();
uint16_t helloSizeLeft = messageSize;
i.ReadNtohU16 (); // Reserved
this->hTime = i.ReadU8 ();
this->willingness = i.ReadU8 ();
helloSizeLeft -= 4;
while (helloSizeLeft)
{
LinkMessage lm;
NS_ASSERT (helloSizeLeft >= 4);
lm.linkCode = i.ReadU8 ();
i.ReadU8 (); // Reserved
uint16_t lmSize = i.ReadNtohU16 ();
NS_ASSERT ((lmSize - 4) % IPV4_ADDRESS_SIZE == 0);
for (int n = (lmSize - 4) / IPV4_ADDRESS_SIZE; n; --n)
{
lm.neighborInterfaceAddresses.push_back (Ipv4Address (i.ReadNtohU32 ()));
}
helloSizeLeft -= lmSize;
this->linkMessages.push_back (lm);
}
return messageSize;
}
// ---------------- OLSR TC Message -------------------------------
uint32_t
OlsrMessageHeader::Tc::GetSerializedSize (void) const
{
return 4 + this->neighborAddresses.size () * IPV4_ADDRESS_SIZE;
}
void
OlsrMessageHeader::Tc::Print (std::ostream &os) const
{
// TODO
}
void
OlsrMessageHeader::Tc::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
i.WriteHtonU16 (this->ansn);
i.WriteHtonU16 (0); // Reserved
for (std::vector<Ipv4Address>::const_iterator iter = this->neighborAddresses.begin ();
iter != this->neighborAddresses.end (); iter++)
{
i.WriteHtonU32 (iter->GetHostOrder ());
}
}
uint32_t
OlsrMessageHeader::Tc::Deserialize (Buffer::Iterator start, uint32_t messageSize)
{
Buffer::Iterator i = start;
this->neighborAddresses.clear ();
NS_ASSERT (messageSize >= 4);
this->ansn = i.ReadNtohU16 ();
i.ReadNtohU16 (); // Reserved
NS_ASSERT ((messageSize - 4) % IPV4_ADDRESS_SIZE == 0);
int numAddresses = (messageSize - 4) / IPV4_ADDRESS_SIZE;
this->neighborAddresses.clear ();
for (int n = 0; n < numAddresses; ++n)
this->neighborAddresses.push_back (Ipv4Address (i.ReadNtohU32 ()));
return messageSize;
}
// ---------------- OLSR HNA Message -------------------------------
uint32_t
OlsrMessageHeader::Hna::GetSerializedSize (void) const
{
return 2*this->associations.size () * IPV4_ADDRESS_SIZE;
}
void
OlsrMessageHeader::Hna::Print (std::ostream &os) const
{
// TODO
}
void
OlsrMessageHeader::Hna::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
for (size_t n = 0; n < this->associations.size (); ++n)
{
i.WriteHtonU32 (this->associations[n].address.GetHostOrder ());
i.WriteHtonU32 (this->associations[n].mask.GetHostOrder ());
}
}
uint32_t
OlsrMessageHeader::Hna::Deserialize (Buffer::Iterator start, uint32_t messageSize)
{
Buffer::Iterator i = start;
NS_ASSERT (messageSize % (IPV4_ADDRESS_SIZE*2) == 0);
int numAddresses = messageSize / IPV4_ADDRESS_SIZE / 2;
this->associations.clear ();
for (int n = 0; n < numAddresses; ++n)
{
Ipv4Address address (i.ReadNtohU32 ());
Ipv4Mask mask (i.ReadNtohU32 ());
this->associations.push_back ((Association) {address, mask});
}
return messageSize;
}
}; // namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
#include "ns3/packet.h"
#include <math.h>
namespace ns3 {
class OlsrHeaderTest : public ns3::Test {
private:
public:
OlsrHeaderTest ();
virtual bool RunTests (void);
};
OlsrHeaderTest::OlsrHeaderTest ()
: ns3::Test ("OlsrHeader")
{}
bool
OlsrHeaderTest::RunTests (void)
{
bool result = true;
// Testing packet header + message header + MID message
{
Packet packet;
{
OlsrPacketHeader hdr;
OlsrMessageHeader msg1;
OlsrMessageHeader::Mid &mid1 = msg1.GetMid ();
OlsrMessageHeader msg2;
OlsrMessageHeader::Mid &mid2 = msg2.GetMid ();
// MID message #1
{
std::vector<Ipv4Address> &addresses = mid1.interfaceAddresses;
addresses.clear ();
addresses.push_back (Ipv4Address ("1.2.3.4"));
addresses.push_back (Ipv4Address ("1.2.3.5"));
}
msg1.SetTimeToLive (255);
msg1.SetOriginatorAddress (Ipv4Address ("11.22.33.44"));
msg1.SetVTime (Seconds (9));
msg1.SetMessageSequenceNumber (7);
// MID message #2
{
std::vector<Ipv4Address> &addresses = mid2.interfaceAddresses;
addresses.clear ();
addresses.push_back (Ipv4Address ("2.2.3.4"));
addresses.push_back (Ipv4Address ("2.2.3.5"));
}
msg2.SetTimeToLive (254);
msg2.SetOriginatorAddress (Ipv4Address ("12.22.33.44"));
msg2.SetVTime (Seconds (10));
msg2.SetMessageType (OlsrMessageHeader::MID_MESSAGE);
msg2.SetMessageSequenceNumber (7);
// Build an OLSR packet header
hdr.SetPacketLength (hdr.GetSerializedSize () + msg1.GetSerializedSize () + msg2.GetSerializedSize ());
hdr.SetPacketSequenceNumber (123);
// Now add all the headers in the correct order
packet.AddHeader (msg2);
packet.AddHeader (msg1);
packet.AddHeader (hdr);
}
{
OlsrPacketHeader hdr;
packet.RemoveHeader (hdr);
NS_TEST_ASSERT_EQUAL (hdr.GetPacketSequenceNumber (), 123);
uint32_t sizeLeft = hdr.GetPacketLength () - hdr.GetSerializedSize ();
{
OlsrMessageHeader msg1;
packet.RemoveHeader (msg1);
NS_TEST_ASSERT_EQUAL (msg1.GetTimeToLive (), 255);
NS_TEST_ASSERT_EQUAL (msg1.GetOriginatorAddress (), Ipv4Address ("11.22.33.44"));
NS_TEST_ASSERT_EQUAL (msg1.GetVTime (), Seconds (9));
NS_TEST_ASSERT_EQUAL (msg1.GetMessageType (), OlsrMessageHeader::MID_MESSAGE);
NS_TEST_ASSERT_EQUAL (msg1.GetMessageSequenceNumber (), 7);
OlsrMessageHeader::Mid &mid1 = msg1.GetMid ();
NS_TEST_ASSERT_EQUAL (mid1.interfaceAddresses.size (), 2);
NS_TEST_ASSERT_EQUAL (*mid1.interfaceAddresses.begin (), Ipv4Address ("1.2.3.4"));
sizeLeft -= msg1.GetSerializedSize ();
NS_TEST_ASSERT (sizeLeft > 0);
}
{
// now read the second message
OlsrMessageHeader msg2;
packet.RemoveHeader (msg2);
NS_TEST_ASSERT_EQUAL (msg2.GetTimeToLive (), 254);
NS_TEST_ASSERT_EQUAL (msg2.GetOriginatorAddress (), Ipv4Address ("12.22.33.44"));
NS_TEST_ASSERT_EQUAL (msg2.GetVTime (), Seconds (10));
NS_TEST_ASSERT_EQUAL (msg2.GetMessageType (), OlsrMessageHeader::MID_MESSAGE);
NS_TEST_ASSERT_EQUAL (msg2.GetMessageSequenceNumber (), 7);
OlsrMessageHeader::Mid mid2 = msg2.GetMid ();
NS_TEST_ASSERT_EQUAL (mid2.interfaceAddresses.size (), 2);
NS_TEST_ASSERT_EQUAL (*mid2.interfaceAddresses.begin (), Ipv4Address ("2.2.3.4"));
sizeLeft -= msg2.GetSerializedSize ();
NS_TEST_ASSERT_EQUAL (sizeLeft, 0);
}
}
}
// Test the HELLO message
{
Packet packet;
OlsrMessageHeader msgIn;
OlsrMessageHeader::Hello &helloIn = msgIn.GetHello ();
helloIn.SetHTime (Seconds (7));
helloIn.willingness = 66;
{
OlsrMessageHeader::Hello::LinkMessage lm1;
lm1.linkCode = 2;
lm1.neighborInterfaceAddresses.push_back (Ipv4Address ("1.2.3.4"));
lm1.neighborInterfaceAddresses.push_back (Ipv4Address ("1.2.3.5"));
helloIn.linkMessages.push_back (lm1);
OlsrMessageHeader::Hello::LinkMessage lm2;
lm2.linkCode = 3;
lm2.neighborInterfaceAddresses.push_back (Ipv4Address ("2.2.3.4"));
lm2.neighborInterfaceAddresses.push_back (Ipv4Address ("2.2.3.5"));
helloIn.linkMessages.push_back (lm2);
}
packet.AddHeader (msgIn);
OlsrMessageHeader msgOut;
packet.RemoveHeader (msgOut);
OlsrMessageHeader::Hello &helloOut = msgOut.GetHello ();
NS_TEST_ASSERT_EQUAL (helloOut.GetHTime (), Seconds (7));
NS_TEST_ASSERT_EQUAL (helloOut.willingness, 66);
NS_TEST_ASSERT_EQUAL (helloOut.linkMessages.size (), 2);
NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[0].linkCode, 2);
NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[0].neighborInterfaceAddresses[0],
Ipv4Address ("1.2.3.4"));
NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[0].neighborInterfaceAddresses[1],
Ipv4Address ("1.2.3.5"));
NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[1].linkCode, 3);
NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[1].neighborInterfaceAddresses[0],
Ipv4Address ("2.2.3.4"));
NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[1].neighborInterfaceAddresses[1],
Ipv4Address ("2.2.3.5"));
// check that all bytes of the message were read
NS_TEST_ASSERT_EQUAL (packet.GetSize (), 0);
}
// Test the TC message
{
Packet packet;
OlsrMessageHeader msgIn;
OlsrMessageHeader::Tc &tcIn = msgIn.GetTc ();
tcIn.ansn = 0x1234;
tcIn.neighborAddresses.push_back (Ipv4Address ("1.2.3.4"));
tcIn.neighborAddresses.push_back (Ipv4Address ("1.2.3.5"));
packet.AddHeader (msgIn);
OlsrMessageHeader msgOut;
packet.RemoveHeader (msgOut);
OlsrMessageHeader::Tc &tcOut = msgOut.GetTc ();
NS_TEST_ASSERT_EQUAL (tcOut.ansn, 0x1234);
NS_TEST_ASSERT_EQUAL (tcOut.neighborAddresses.size (), 2);
NS_TEST_ASSERT_EQUAL (tcOut.neighborAddresses[0],
Ipv4Address ("1.2.3.4"));
NS_TEST_ASSERT_EQUAL (tcOut.neighborAddresses[1],
Ipv4Address ("1.2.3.5"));
// check that all bytes of the message were read
NS_TEST_ASSERT_EQUAL (packet.GetSize (), 0);
}
// Test the HNA message
{
Packet packet;
OlsrMessageHeader msgIn;
OlsrMessageHeader::Hna &hnaIn = msgIn.GetHna ();
hnaIn.associations.push_back ((OlsrMessageHeader::Hna::Association)
{ Ipv4Address ("1.2.3.4"), Ipv4Mask ("255.255.255.0")});
hnaIn.associations.push_back ((OlsrMessageHeader::Hna::Association)
{Ipv4Address ("1.2.3.5"), Ipv4Mask ("255.255.0.0")});
packet.AddHeader (msgIn);
OlsrMessageHeader msgOut;
packet.RemoveHeader (msgOut);
OlsrMessageHeader::Hna &hnaOut = msgOut.GetHna ();
NS_TEST_ASSERT_EQUAL (hnaOut.associations.size (), 2);
NS_TEST_ASSERT_EQUAL (hnaOut.associations[0].address,
Ipv4Address ("1.2.3.4"));
NS_TEST_ASSERT_EQUAL (hnaOut.associations[0].mask,
Ipv4Mask ("255.255.255.0"));
NS_TEST_ASSERT_EQUAL (hnaOut.associations[1].address,
Ipv4Address ("1.2.3.5"));
NS_TEST_ASSERT_EQUAL (hnaOut.associations[1].mask,
Ipv4Mask ("255.255.0.0"));
// check that all bytes of the message were read
NS_TEST_ASSERT_EQUAL (packet.GetSize (), 0);
}
for (int time = 1; time <= 30; time++)
{
uint8_t emf = OlsrSecondsToEmf (time);
double seconds = OlsrEmfToSeconds (emf);
if (seconds < 0 || fabs (seconds - time) > 0.1)
{
result = false;
Failure () << "In " << time << " out " << seconds << std::endl;
}
}
return result;
}
static OlsrHeaderTest gOlsrHeaderTest;
}; // namespace
#endif /* RUN_SELF_TESTS */

View File

@@ -0,0 +1,440 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
#ifndef OLSR_HEADER_H
#define OLSR_HEADER_H
#include <stdint.h>
#include <vector>
#include "ns3/header.h"
#include "ns3/ipv4-address.h"
#include "ns3/nstime.h"
namespace ns3 {
double OlsrEmfToSeconds (uint8_t emf);
uint8_t OlsrSecondsToEmf (double seconds);
// 3.3. Packet Format
//
// The basic layout of any packet in OLSR is as follows (omitting IP and
// UDP headers):
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Packet Length | Packet Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Message Type | Vtime | Message Size |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Originator Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Time To Live | Hop Count | Message Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// : MESSAGE :
// | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Message Type | Vtime | Message Size |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Originator Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Time To Live | Hop Count | Message Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// : MESSAGE :
// | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// : :
// (etc.)
class OlsrPacketHeader : public Header
{
public:
OlsrPacketHeader ();
virtual ~OlsrPacketHeader ();
void SetPacketLength (uint16_t length)
{
m_packetLength = length;
}
uint16_t GetPacketLength () const
{
return m_packetLength;
}
void SetPacketSequenceNumber (uint16_t seqnum)
{
m_packetSequenceNumber = seqnum;
}
uint16_t GetPacketSequenceNumber () const
{
return m_packetSequenceNumber;
}
private:
uint16_t m_packetLength;
uint16_t m_packetSequenceNumber;
public:
static uint32_t GetUid (void);
virtual void Print (std::ostream &os) const;
virtual uint32_t GetSerializedSize (void) const;
virtual void Serialize (Buffer::Iterator start) const;
virtual uint32_t Deserialize (Buffer::Iterator start);
virtual std::string GetName (void) const { return "OlsrPacket"; }
};
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Message Type | Vtime | Message Size |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Originator Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Time To Live | Hop Count | Message Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
class OlsrMessageHeader : public Header
{
public:
enum MessageType {
HELLO_MESSAGE = 1,
TC_MESSAGE = 2,
MID_MESSAGE = 3,
HNA_MESSAGE = 4,
};
OlsrMessageHeader ();
virtual ~OlsrMessageHeader ();
void SetMessageType (MessageType messageType)
{
m_messageType = messageType;
}
MessageType GetMessageType () const
{
return m_messageType;
}
void SetVTime (Time time)
{
m_vTime = OlsrSecondsToEmf (time.GetSeconds ());
}
Time GetVTime () const
{
return Seconds (OlsrEmfToSeconds (m_vTime));
}
void SetOriginatorAddress (Ipv4Address originatorAddress)
{
m_originatorAddress = originatorAddress;
}
Ipv4Address GetOriginatorAddress () const
{
return m_originatorAddress;
}
void SetTimeToLive (uint8_t timeToLive)
{
m_timeToLive = timeToLive;
}
uint8_t GetTimeToLive () const
{
return m_timeToLive;
}
void SetHopCount (uint8_t hopCount)
{
m_hopCount = hopCount;
}
uint8_t GetHopCount () const
{
return m_hopCount;
}
void SetMessageSequenceNumber (uint16_t messageSequenceNumber)
{
m_messageSequenceNumber = messageSequenceNumber;
}
uint16_t GetMessageSequenceNumber () const
{
return m_messageSequenceNumber;
}
// void SetMessageSize (uint16_t messageSize)
// {
// m_messageSize = messageSize;
// }
// uint16_t GetMessageSize () const
// {
// return m_messageSize;
// }
private:
MessageType m_messageType;
uint8_t m_vTime;
Ipv4Address m_originatorAddress;
uint8_t m_timeToLive;
uint8_t m_hopCount;
uint16_t m_messageSequenceNumber;
uint16_t m_messageSize;
public:
static uint32_t GetUid (void);
virtual void Print (std::ostream &os) const;
virtual uint32_t GetSerializedSize (void) const;
virtual void Serialize (Buffer::Iterator start) const;
virtual uint32_t Deserialize (Buffer::Iterator start);
virtual std::string GetName (void) const { return "OlsrMessage"; }
// 5.1. MID Message Format
//
// The proposed format of a MID message is as follows:
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | OLSR Interface Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | OLSR Interface Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ... |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
struct Mid
{
std::vector<Ipv4Address> interfaceAddresses;
void Print (std::ostream &os) const;
uint32_t GetSerializedSize (void) const;
void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start, uint32_t messageSize);
};
// 6.1. HELLO Message Format
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Reserved | Htime | Willingness |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Link Code | Reserved | Link Message Size |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Neighbor Interface Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Neighbor Interface Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// : . . . :
// : :
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Link Code | Reserved | Link Message Size |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Neighbor Interface Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Neighbor Interface Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// : :
// : :
// (etc.)
struct Hello
{
struct LinkMessage {
uint8_t linkCode;
std::vector<Ipv4Address> neighborInterfaceAddresses;
};
uint8_t hTime;
void SetHTime (Time time)
{
this->hTime = OlsrSecondsToEmf (time.GetSeconds ());
}
Time GetHTime () const
{
return Seconds (OlsrEmfToSeconds (this->hTime));
}
uint8_t willingness;
std::vector<LinkMessage> linkMessages;
void Print (std::ostream &os) const;
uint32_t GetSerializedSize (void) const;
void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start, uint32_t messageSize);
};
// 9.1. TC Message Format
//
// The proposed format of a TC message is as follows:
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ANSN | Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Advertised Neighbor Main Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Advertised Neighbor Main Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ... |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
struct Tc
{
std::vector<Ipv4Address> neighborAddresses;
uint16_t ansn;
void Print (std::ostream &os) const;
uint32_t GetSerializedSize (void) const;
void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start, uint32_t messageSize);
};
// 12.1. HNA Message Format
//
// The proposed format of an HNA-message is:
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Network Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Netmask |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Network Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Netmask |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ... |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// Note: HNA stands for Host Network Association
struct Hna
{
struct Association
{
Ipv4Address address;
Ipv4Mask mask;
};
std::vector<Association> associations;
void Print (std::ostream &os) const;
uint32_t GetSerializedSize (void) const;
void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start, uint32_t messageSize);
};
private:
struct
{
Mid mid;
Hello hello;
Tc tc;
Hna hna;
} m_message; // union not allowed
public:
Mid& GetMid ()
{
if (m_messageType == 0)
{
m_messageType = MID_MESSAGE;
}
else
{
NS_ASSERT (m_messageType == MID_MESSAGE);
}
return m_message.mid;
}
Hello& GetHello ()
{
if (m_messageType == 0)
{
m_messageType = HELLO_MESSAGE;
}
else
{
NS_ASSERT (m_messageType == HELLO_MESSAGE);
}
return m_message.hello;
}
Tc& GetTc ()
{
if (m_messageType == 0)
{
m_messageType = TC_MESSAGE;
}
else
{
NS_ASSERT (m_messageType == TC_MESSAGE);
}
return m_message.tc;
}
Hna& GetHna ()
{
if (m_messageType == 0)
{
m_messageType = HNA_MESSAGE;
}
else
{
NS_ASSERT (m_messageType == HNA_MESSAGE);
}
return m_message.hna;
}
const Mid& GetMid () const
{
NS_ASSERT (m_messageType == MID_MESSAGE);
return m_message.mid;
}
const Hello& GetHello () const
{
NS_ASSERT (m_messageType == HELLO_MESSAGE);
return m_message.hello;
}
const Tc& GetTc () const
{
NS_ASSERT (m_messageType == TC_MESSAGE);
return m_message.tc;
}
const Hna& GetHna () const
{
NS_ASSERT (m_messageType == HNA_MESSAGE);
return m_message.hna;
}
};
}; // namespace ns3
#endif /* OLSR_HEADER_H */

View File

@@ -0,0 +1,436 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2004 Francisco J. Ros
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Authors: Francisco J. Ros <fjrm@dif.um.es>
* Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
///
/// \file OlsrState.cc
/// \brief Implementation of all functions needed for manipulating the internal
/// state of an OLSR node.
///
#include "olsr-state.h"
namespace ns3 {
/********** MPR Selector Set Manipulation **********/
MprSelectorTuple*
OlsrState::FindMprSelectorTuple (Ipv4Address const &mainAddr)
{
for (MprSelectorSet::iterator it = m_mprSelectorSet.begin ();
it != m_mprSelectorSet.end (); it++)
{
if (it->mainAddr == mainAddr)
return &(*it);
}
return NULL;
}
void
OlsrState::EraseMprSelectorTuple (const MprSelectorTuple &tuple)
{
for (MprSelectorSet::iterator it = m_mprSelectorSet.begin ();
it != m_mprSelectorSet.end (); it++)
{
if (*it == tuple)
{
m_mprSelectorSet.erase (it);
break;
}
}
}
void
OlsrState::EraseMprSelectorTuples (const Ipv4Address &mainAddr)
{
for (MprSelectorSet::iterator it = m_mprSelectorSet.begin ();
it != m_mprSelectorSet.end (); it++)
{
if (it->mainAddr == mainAddr)
{
it = m_mprSelectorSet.erase (it);
it--;
}
}
}
void
OlsrState::InsertMprSelectorTuple (MprSelectorTuple const &tuple)
{
m_mprSelectorSet.push_back (tuple);
}
/********** Neighbor Set Manipulation **********/
NeighborTuple*
OlsrState::FindNeighborTuple (Ipv4Address const &mainAddr)
{
for (NeighborSet::iterator it = m_neighborSet.begin ();
it != m_neighborSet.end (); it++)
{
if (it->neighborMainAddr == mainAddr)
return &(*it);
}
return NULL;
}
NeighborTuple*
OlsrState::FindSymNeighborTuple (Ipv4Address const &mainAddr)
{
for (NeighborSet::iterator it = m_neighborSet.begin ();
it != m_neighborSet.end (); it++)
{
if (it->neighborMainAddr == mainAddr && it->status == NeighborTuple::STATUS_SYM)
return &(*it);
}
return NULL;
}
NeighborTuple*
OlsrState::FindNeighborTuple (Ipv4Address const &mainAddr, uint8_t willingness)
{
for (NeighborSet::iterator it = m_neighborSet.begin ();
it != m_neighborSet.end (); it++)
{
if (it->neighborMainAddr == mainAddr && it->willingness == willingness)
return &(*it);
}
return NULL;
}
void
OlsrState::EraseNeighborTuple (const NeighborTuple &tuple)
{
for (NeighborSet::iterator it = m_neighborSet.begin ();
it != m_neighborSet.end (); it++)
{
if (*it == tuple)
{
m_neighborSet.erase (it);
break;
}
}
}
void
OlsrState::EraseNeighborTuple (const Ipv4Address &mainAddr)
{
for (NeighborSet::iterator it = m_neighborSet.begin ();
it != m_neighborSet.end (); it++)
{
if (it->neighborMainAddr == mainAddr)
{
it = m_neighborSet.erase (it);
break;
}
}
}
void
OlsrState::InsertNeighborTuple (NeighborTuple const &tuple)
{
m_neighborSet.push_back (tuple);
}
/********** Neighbor 2 Hop Set Manipulation **********/
TwoHopNeighborTuple*
OlsrState::FindTwoHopNeighborTuple (Ipv4Address const &neighborMainAddr,
Ipv4Address const &twoHopNeighborAddr)
{
for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
it != m_twoHopNeighborSet.end (); it++)
{
if (it->neighborMainAddr == neighborMainAddr
&& it->twoHopNeighborAddr == twoHopNeighborAddr)
{
return &(*it);
}
}
return NULL;
}
void
OlsrState::EraseTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
{
for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
it != m_twoHopNeighborSet.end (); it++)
{
if (*it == tuple)
{
m_twoHopNeighborSet.erase(it);
break;
}
}
}
void
OlsrState::EraseTwoHopNeighborTuples (const Ipv4Address &neighborMainAddr,
const Ipv4Address &twoHopNeighborAddr)
{
for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
it != m_twoHopNeighborSet.end (); it++)
{
if (it->neighborMainAddr == neighborMainAddr
&& it->twoHopNeighborAddr == twoHopNeighborAddr)
{
it = m_twoHopNeighborSet.erase (it);
it--; // FIXME: is this correct in the case 'it' pointed to the first element?
}
}
}
void
OlsrState::EraseTwoHopNeighborTuples (const Ipv4Address &neighborMainAddr)
{
for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
it != m_twoHopNeighborSet.end (); it++)
{
if (it->neighborMainAddr == neighborMainAddr) {
it = m_twoHopNeighborSet.erase (it);
it--;
}
}
}
void
OlsrState::InsertTwoHopNeighborTuple (TwoHopNeighborTuple const &tuple){
m_twoHopNeighborSet.push_back (tuple);
}
/********** MPR Set Manipulation **********/
bool
OlsrState::FindMprAddress (Ipv4Address const &addr)
{
MprSet::iterator it = m_mprSet.find (addr);
return (it != m_mprSet.end ());
}
void
OlsrState::InsertMprAddress (Ipv4Address const & addr)
{
m_mprSet.insert (addr);
}
void
OlsrState::ClearMprSet ()
{
m_mprSet.clear ();
}
/********** Duplicate Set Manipulation **********/
DuplicateTuple*
OlsrState::FindDuplicateTuple (Ipv4Address const &addr, uint16_t sequenceNumber)
{
for (DuplicateSet::iterator it = m_duplicateSet.begin ();
it != m_duplicateSet.end(); it++)
{
if (it->address == addr && it->sequenceNumber == sequenceNumber)
return &(*it);
}
return NULL;
}
void
OlsrState::EraseDuplicateTuple (const DuplicateTuple &tuple)
{
for (DuplicateSet::iterator it = m_duplicateSet.begin ();
it != m_duplicateSet.end (); it++)
{
if (*it == tuple)
{
m_duplicateSet.erase (it);
break;
}
}
}
void
OlsrState::InsertDuplicateTuple (DuplicateTuple const &tuple)
{
m_duplicateSet.push_back (tuple);
}
/********** Link Set Manipulation **********/
LinkTuple*
OlsrState::FindLinkTuple (Ipv4Address const & ifaceAddr)
{
for (LinkSet::iterator it = m_linkSet.begin ();
it != m_linkSet.end (); it++)
{
if (it->neighborIfaceAddr == ifaceAddr)
return &(*it);
}
return NULL;
}
LinkTuple*
OlsrState::FindSymLinkTuple (Ipv4Address const &ifaceAddr, Time now)
{
for (LinkSet::iterator it = m_linkSet.begin ();
it != m_linkSet.end (); it++)
{
if (it->neighborIfaceAddr == ifaceAddr)
{
if (it->symTime > now)
return &(*it);
else
break;
}
}
return NULL;
}
void
OlsrState::EraseLinkTuple (const LinkTuple &tuple)
{
for (LinkSet::iterator it = m_linkSet.begin ();
it != m_linkSet.end (); it++)
{
if (*it == tuple)
{
m_linkSet.erase (it);
break;
}
}
}
LinkTuple&
OlsrState::InsertLinkTuple (LinkTuple const &tuple)
{
m_linkSet.push_back (tuple);
return m_linkSet.back ();
}
/********** Topology Set Manipulation **********/
TopologyTuple*
OlsrState::FindTopologyTuple (Ipv4Address const &destAddr,
Ipv4Address const &lastAddr)
{
for (TopologySet::iterator it = m_topologySet.begin ();
it != m_topologySet.end (); it++)
{
if (it->destAddr == destAddr && it->lastAddr == lastAddr)
return &(*it);
}
return NULL;
}
TopologyTuple*
OlsrState::FindNewerTopologyTuple (Ipv4Address const & lastAddr, uint16_t ansn)
{
for (TopologySet::iterator it = m_topologySet.begin ();
it != m_topologySet.end (); it++)
{
if (it->lastAddr == lastAddr && it->sequenceNumber > ansn)
return &(*it);
}
return NULL;
}
void
OlsrState::EraseTopologyTuple(const TopologyTuple &tuple)
{
for (TopologySet::iterator it = m_topologySet.begin ();
it != m_topologySet.end (); it++)
{
if (*it == tuple)
{
m_topologySet.erase (it);
break;
}
}
}
void
OlsrState::EraseOlderTopologyTuples (const Ipv4Address &lastAddr, uint16_t ansn)
{
for (TopologySet::iterator it = m_topologySet.begin();
it != m_topologySet.end(); it++)
{
if (it->lastAddr == lastAddr && it->sequenceNumber < ansn)
{
it = m_topologySet.erase (it);
it--;
}
}
}
void
OlsrState::InsertTopologyTuple (TopologyTuple const &tuple)
{
m_topologySet.push_back (tuple);
}
/********** Interface Association Set Manipulation **********/
IfaceAssocTuple*
OlsrState::FindIfaceAssocTuple (Ipv4Address const &ifaceAddr)
{
for (IfaceAssocSet::iterator it = m_ifaceAssocSet.begin ();
it != m_ifaceAssocSet.end (); it++)
{
if (it->ifaceAddr == ifaceAddr)
return &(*it);
}
return NULL;
}
void
OlsrState::EraseIfaceAssocTuple (const IfaceAssocTuple &tuple)
{
for (IfaceAssocSet::iterator it = m_ifaceAssocSet.begin ();
it != m_ifaceAssocSet.end (); it++)
{
if (*it == tuple)
{
m_ifaceAssocSet.erase (it);
break;
}
}
}
void
OlsrState::InsertIfaceAssocTuple (const IfaceAssocTuple &tuple)
{
m_ifaceAssocSet.push_back (tuple);
}
std::vector<Ipv4Address>
OlsrState::FindNeighborInterfaces (const Ipv4Address &neighborMainAddr) const
{
std::vector<Ipv4Address> retval;
for (IfaceAssocSet::const_iterator it = m_ifaceAssocSet.begin ();
it != m_ifaceAssocSet.end (); it++)
{
if (it->mainAddr == neighborMainAddr)
retval.push_back (it->ifaceAddr);
}
return retval;
}
} // namespace ns3

View File

@@ -0,0 +1,144 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2004 Francisco J. Ros
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Authors: Francisco J. Ros <fjrm@dif.um.es>
* Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
/// \brief This header file declares and defines internal state of an OLSR node.
#ifndef __OLSR_STATE_H__
#define __OLSR_STATE_H__
#include "repositories.h"
namespace ns3 {
using namespace olsr;
/// This class encapsulates all data structures needed for maintaining internal state of an OLSR node.
class OlsrState
{
// friend class Olsr;
protected:
LinkSet m_linkSet; ///< Link Set (RFC 3626, section 4.2.1).
NeighborSet m_neighborSet; ///< Neighbor Set (RFC 3626, section 4.3.1).
TwoHopNeighborSet m_twoHopNeighborSet; ///< 2-hop Neighbor Set (RFC 3626, section 4.3.2).
TopologySet m_topologySet; ///< Topology Set (RFC 3626, section 4.4).
MprSet m_mprSet; ///< MPR Set (RFC 3626, section 4.3.3).
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).
public:
// MPR selector
const MprSelectorSet & GetMprSelectors () const
{
return m_mprSelectorSet;
}
MprSelectorTuple* FindMprSelectorTuple (const Ipv4Address &mainAddr);
void EraseMprSelectorTuple (const MprSelectorTuple &tuple);
void EraseMprSelectorTuples (const Ipv4Address &mainAddr);
void InsertMprSelectorTuple (const MprSelectorTuple &tuple);
// Neighbor
const NeighborSet & GetNeighbors () const
{
return m_neighborSet;
}
NeighborTuple* FindNeighborTuple (const Ipv4Address &mainAddr);
NeighborTuple* FindSymNeighborTuple (const Ipv4Address &mainAddr);
NeighborTuple* FindNeighborTuple (const Ipv4Address &mainAddr,
uint8_t willingness);
void EraseNeighborTuple (const NeighborTuple &neighborTuple);
void EraseNeighborTuple (const Ipv4Address &mainAddr);
void InsertNeighborTuple (const NeighborTuple &tuple);
// Two-hop neighbor
const TwoHopNeighborSet & GetTwoHopNeighbors () const
{
return m_twoHopNeighborSet;
}
TwoHopNeighborTuple* FindTwoHopNeighborTuple (const Ipv4Address &neighbor,
const Ipv4Address &twoHopNeighbor);
void EraseTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
void EraseTwoHopNeighborTuples (const Ipv4Address &neighbor);
void EraseTwoHopNeighborTuples (const Ipv4Address &neighbor,
const Ipv4Address &twoHopNeighbor);
void InsertTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
// MPR
bool FindMprAddress (const Ipv4Address &address);
void InsertMprAddress (const Ipv4Address &address);
void ClearMprSet ();
// Duplicate
DuplicateTuple* FindDuplicateTuple (const Ipv4Address &address,
uint16_t sequenceNumber);
void EraseDuplicateTuple (const DuplicateTuple &tuple);
void InsertDuplicateTuple (const DuplicateTuple &tuple);
// Link
const LinkSet & GetLinks () const
{
return m_linkSet;
}
LinkTuple* FindLinkTuple (const Ipv4Address &ifaceAddr);
LinkTuple* FindSymLinkTuple (const Ipv4Address &ifaceAddr, Time time);
void EraseLinkTuple (const LinkTuple &tuple);
LinkTuple& InsertLinkTuple (const LinkTuple &tuple);
// Topology
const TopologySet & GetTopologySet () const
{
return m_topologySet;
}
TopologyTuple* FindTopologyTuple (const Ipv4Address &destAddr,
const Ipv4Address &lastAddr);
TopologyTuple* FindNewerTopologyTuple (const Ipv4Address &lastAddr,
uint16_t ansn);
void EraseTopologyTuple (const TopologyTuple &tuple);
void EraseOlderTopologyTuples (const Ipv4Address &lastAddr,
uint16_t ansn);
void InsertTopologyTuple (const TopologyTuple &tuple);
// Interface association
const IfaceAssocSet & GetIfaceAssocSet () const
{
return m_ifaceAssocSet;
}
IfaceAssocSet & GetIfaceAssocSetMutable ()
{
return m_ifaceAssocSet;
}
IfaceAssocTuple* FindIfaceAssocTuple (const Ipv4Address &ifaceAddr);
void EraseIfaceAssocTuple (const IfaceAssocTuple &tuple);
void InsertIfaceAssocTuple (const IfaceAssocTuple &tuple);
// Returns a vector of all interfaces of a given neighbor, with the
// exception of the "main" one.
std::vector<Ipv4Address>
FindNeighborInterfaces (const Ipv4Address &neighborMainAddr) const;
};
} // namespace ns3
#endif

42
src/routing/olsr/olsr.cc Normal file
View File

@@ -0,0 +1,42 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
#include "olsr-agent.h"
#include "olsr.h"
namespace ns3 { namespace olsr {
void
EnableAllNodes (void)
{
EnableNodes <NodeList::Iterator> (NodeList::Begin (), NodeList::End ());
}
void
EnableNode (Ptr<Node> node)
{
ComponentManager::Create<OlsrAgent, Ptr<Node> >
(OlsrAgent::cid, OlsrAgent::iid, node)->Start ();
}
}} // namespace ns3, olsr

66
src/routing/olsr/olsr.h Normal file
View File

@@ -0,0 +1,66 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
#ifndef OLSR_H
#define OLSR_H
#include "ns3/node-list.h"
namespace ns3
{
/**
* \namespace ns3::olsr
* \brief Includes a set of utility functions to enable OLSR on
* certain nodes with default parameters. For finer grained control
* of OLSR parameters, see OlsrAgent.
*/
namespace olsr
{
/// \brief Start the OLSR routing agent on all nodes
void EnableAllNodes (void);
/// \brief Start the OLSR routing agent on a given list of nodes
template <typename InputIterator>
void EnableNodes (InputIterator begin, InputIterator end);
/// \brief Start the OLSR routing agent on the given node
void EnableNode (Ptr<Node> node);
}
}
// implementation
namespace ns3
{
namespace olsr
{
template <typename InputIterator>
void EnableNodes (InputIterator begin, InputIterator end)
{
for (InputIterator i = begin; i != end; i++)
{
EnableNode (*i);
}
}
}
}
#endif /* OLSR_H */

View File

@@ -0,0 +1,198 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2004 Francisco J. Ros
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Authors: Francisco J. Ros <fjrm@dif.um.es>
* Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
///
/// \file OLSR_repositories.h
/// \brief Here are defined all data structures needed by an OLSR node.
///
#ifndef __OLSR_REPOSITORIES_H__
#define __OLSR_REPOSITORIES_H__
#include <set>
#include <vector>
#include "ns3/ipv4-address.h"
#include "ns3/nstime.h"
namespace ns3 { namespace olsr {
/// An Interface Association Tuple.
struct IfaceAssocTuple
{
/// Interface address of a node.
Ipv4Address ifaceAddr;
/// Main address of the node.
Ipv4Address mainAddr;
/// Time at which this tuple expires and must be removed.
Time time;
};
static inline bool
operator == (const IfaceAssocTuple &a, const IfaceAssocTuple &b)
{
return (a.ifaceAddr == b.ifaceAddr
&& a.mainAddr == b.mainAddr);
}
/// A Link Tuple.
struct LinkTuple
{
/// Interface address of the local node.
Ipv4Address localIfaceAddr;
/// Interface address of the neighbor node.
Ipv4Address neighborIfaceAddr;
/// The link is considered bidirectional until this time.
Time symTime;
/// The link is considered unidirectional until this time.
Time asymTime;
/// The link is considered lost until this time (used for link layer notification).
Time lostTime;
/// Time at which this tuple expires and must be removed.
Time time;
};
static inline bool
operator == (const LinkTuple &a, const LinkTuple &b)
{
return (a.localIfaceAddr == b.localIfaceAddr
&& a.neighborIfaceAddr == b.neighborIfaceAddr);
}
/// A Neighbor Tuple.
struct NeighborTuple
{
/// Main address of a neighbor node.
Ipv4Address neighborMainAddr;
/// Neighbor Type and Link Type at the four less significative digits.
enum Status {
STATUS_NOT_SYM = 0, // "not symmetric"
STATUS_SYM = 1, // "symmetric"
} status;
/// A value between 0 and 7 specifying the node's willingness to carry traffic on behalf of other nodes.
uint8_t willingness;
};
static inline bool
operator == (const NeighborTuple &a, const NeighborTuple &b)
{
return (a.neighborMainAddr == b.neighborMainAddr
&& a.status == b.status
&& a.willingness == b.willingness);
}
/// A 2-hop Tuple.
struct TwoHopNeighborTuple
{
/// Main address of a neighbor.
Ipv4Address neighborMainAddr;
/// Main address of a 2-hop neighbor with a symmetric link to nb_main_addr.
Ipv4Address twoHopNeighborAddr;
/// Time at which this tuple expires and must be removed.
Time expirationTime; // previously called 'time_'
};
static inline bool
operator == (const TwoHopNeighborTuple &a, const TwoHopNeighborTuple &b)
{
return (a.neighborMainAddr == b.neighborMainAddr
&& a.twoHopNeighborAddr == b.twoHopNeighborAddr);
}
/// An MPR-Selector Tuple.
struct MprSelectorTuple
{
/// Main address of a node which have selected this node as a MPR.
Ipv4Address mainAddr;
/// Time at which this tuple expires and must be removed.
Time expirationTime; // previously called 'time_'
};
static inline bool
operator == (const MprSelectorTuple &a, const MprSelectorTuple &b)
{
return (a.mainAddr == b.mainAddr);
}
/// The type "list of interface addresses"
//typedef std::vector<nsaddr_t> addr_list_t;
/// A Duplicate Tuple
struct DuplicateTuple
{
/// Originator address of the message.
Ipv4Address address;
/// Message sequence number.
uint16_t sequenceNumber;
/// Indicates whether the message has been retransmitted or not.
bool retransmitted;
/// List of interfaces which the message has been received on.
std::vector<Ipv4Address> ifaceList;
/// Time at which this tuple expires and must be removed.
Time expirationTime;
};
static inline bool
operator == (const DuplicateTuple &a, const DuplicateTuple &b)
{
return (a.address == b.address
&& a.sequenceNumber == b.sequenceNumber);
}
/// A Topology Tuple
struct TopologyTuple
{
/// Main address of the destination.
Ipv4Address destAddr;
/// Main address of a node which is a neighbor of the destination.
Ipv4Address lastAddr;
/// Sequence number.
uint16_t sequenceNumber;
/// Time at which this tuple expires and must be removed.
Time expirationTime;
};
static inline bool
operator == (const TopologyTuple &a, const TopologyTuple &b)
{
return (a.destAddr == b.destAddr
&& a.lastAddr == b.lastAddr
&& a.sequenceNumber == b.sequenceNumber);
}
typedef std::set<Ipv4Address> MprSet; ///< MPR Set type.
typedef std::vector<MprSelectorTuple> MprSelectorSet; ///< MPR Selector Set type.
typedef std::vector<LinkTuple> LinkSet; ///< Link Set type.
typedef std::vector<NeighborTuple> NeighborSet; ///< Neighbor Set type.
typedef std::vector<TwoHopNeighborTuple> TwoHopNeighborSet; ///< 2-hop Neighbor Set type.
typedef std::vector<TopologyTuple> TopologySet; ///< Topology Set type.
typedef std::vector<DuplicateTuple> DuplicateSet; ///< Duplicate Set type.
typedef std::vector<IfaceAssocTuple> IfaceAssocSet; ///< Interface Association Set type.
}}; // namespace ns3, olsr
#endif /* __OLSR_REPOSITORIES_H__ */

View File

@@ -0,0 +1,290 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2004 Francisco J. Ros
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Authors: Francisco J. Ros <fjrm@dif.um.es>
* Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
///
/// \file OLSR_rtable.cc
/// \brief Implementation of our routing table.
///
#include "routing-table.h"
#include "ns3/packet.h"
#include "ns3/ipv4-header.h"
#include "ns3/debug.h"
namespace ns3 { namespace olsr {
NS_DEBUG_COMPONENT_DEFINE ("OlsrRoutingTable");
///
/// \brief Clears the routing table and frees the memory assigned to each one of its entries.
///
void
RoutingTable::Clear ()
{
m_table.clear ();
}
///
/// \brief Deletes the entry whose destination address is given.
/// \param dest address of the destination node.
///
void
RoutingTable::RemoveEntry (Ipv4Address const &dest)
{
m_table.erase (dest);
}
///
/// \brief Looks up an entry for the specified destination address.
/// \param dest destination address.
/// \param outEntry output parameter to hold the routing entry result, if fuond
/// \return true if found, false if not found
///
bool
RoutingTable::Lookup (Ipv4Address const &dest,
RoutingTableEntry &outEntry) const
{
// Get the iterator at "dest" position
std::map<Ipv4Address, RoutingTableEntry>::const_iterator it =
m_table.find (dest);
// If there is no route to "dest", return NULL
if (it == m_table.end ())
return false;
outEntry = it->second;
return true;
}
///
/// \brief Finds the appropiate entry which must be used in order to forward
/// a data packet to a next hop (given a destination).
///
/// Imagine a routing table like this: [A,B] [B,C] [C,C]; being each pair of the
/// form [dest addr,next-hop addr]. In this case, if this function is invoked with
/// [A,B] then pair [C,C] is returned because C is the next hop that must be used
/// to forward a data packet destined to A. That is, C is a neighbor of this node,
/// but B isn't. This function finds the appropiate neighbor for forwarding a packet.
///
/// \param entry the routing table entry which indicates the destination node
/// we are interested in.
/// \return the appropiate routing table entry which indicates the next
/// hop which must be used for forwarding a data packet, or NULL
/// if there is no such entry.
///
bool
RoutingTable::FindSendEntry (RoutingTableEntry const &entry,
RoutingTableEntry &outEntry) const
{
outEntry = entry;
while (outEntry.destAddr != outEntry.nextAddr)
{
if (not Lookup(outEntry.nextAddr, outEntry))
return false;
}
return true;
}
bool
RoutingTable::RequestRoute (uint32_t ifIndex,
const Ipv4Header &ipHeader,
Packet packet,
RouteReplyCallback routeReply)
{
RoutingTableEntry entry1, entry2;
if (Lookup (ipHeader.GetDestination (), entry1))
{
bool foundSendEntry = FindSendEntry (entry1, entry2);
if (!foundSendEntry)
NS_FATAL_ERROR ("FindSendEntry failure");
Ipv4Route route = Ipv4Route::CreateHostRouteTo
(ipHeader.GetDestination (), entry2.nextAddr, entry2.interface);
NS_DEBUG ("Olsr node" << m_mainAddress
<< ": RouteRequest for dest=" << ipHeader.GetDestination ()
<< " --> destHop=" << entry2.nextAddr
<< " interface=" << entry2.interface);
routeReply (true, route, packet, ipHeader);
return true;
}
else
{
NS_DEBUG ("Olsr node" << m_mainAddress
<< ": RouteRequest for dest=" << ipHeader.GetDestination ()
<< " --> NOT FOUND");
return false;
}
}
bool
RoutingTable::RequestIfIndex (Ipv4Address destination,
uint32_t& ifIndex)
{
RoutingTableEntry entry1, entry2;
if (Lookup (destination, entry1))
{
bool foundSendEntry = FindSendEntry (entry1, entry2);
if (!foundSendEntry)
NS_FATAL_ERROR ("FindSendEntry failure");
ifIndex = entry2.interface;
return true;
}
else
{
return false;
}
}
///
/// \brief Adds a new entry into the routing table.
///
/// If an entry for the given destination existed, it is deleted and freed.
///
/// \param dest address of the destination node.
/// \param next address of the next hop node.
/// \param iface address of the local interface.
/// \param dist distance to the destination node.
///
void
RoutingTable::AddEntry (Ipv4Address const &dest,
Ipv4Address const &next,
uint32_t interface,
uint32_t distance)
{
// Creates a new rt entry with specified values
RoutingTableEntry &entry = m_table[dest];
entry.destAddr = dest;
entry.nextAddr = next;
entry.interface = interface;
entry.distance = distance;
}
void
RoutingTable::AddEntry (Ipv4Address const &dest,
Ipv4Address const &next,
Ipv4Address const &interfaceAddress,
uint32_t distance)
{
RoutingTableEntry entry;
NS_ASSERT (m_ipv4);
for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
{
if (m_ipv4->GetAddress (i) == interfaceAddress)
{
AddEntry (dest, next, i, distance);
return;
}
}
NS_ASSERT (false); // should not be reached
AddEntry (dest, next, 0, distance);
}
///
/// \brief Returns the number of entries in the routing table.
/// \return the number of entries in the routing table.
///
// u_int32_t
// RoutingTable::size() {
// return rt_.size();
// }
}}; // namespace ns3, olsr
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
namespace ns3 { namespace olsr {
class OlsrRoutingTableTest : public ns3::Test {
private:
public:
OlsrRoutingTableTest ();
virtual bool RunTests (void);
};
OlsrRoutingTableTest::OlsrRoutingTableTest ()
: ns3::Test ("OlsrRoutingTable")
{}
bool
OlsrRoutingTableTest::RunTests (void)
{
bool result = true;
RoutingTable table;
table.AddEntry (Ipv4Address ("1.2.3.5"),
Ipv4Address ("1.2.3.4"),
0,
1);
table.AddEntry (Ipv4Address ("1.2.3.4"),
Ipv4Address ("1.2.3.4"),
0,
1);
RoutingTableEntry entry1;
NS_TEST_ASSERT (table.Lookup (Ipv4Address ("1.2.3.5"), entry1));
NS_TEST_ASSERT_EQUAL (entry1.destAddr, Ipv4Address ("1.2.3.5"));
NS_TEST_ASSERT_EQUAL (entry1.nextAddr, Ipv4Address ("1.2.3.4"));
NS_TEST_ASSERT_EQUAL (entry1.interface, 0);
NS_TEST_ASSERT_EQUAL (entry1.distance, 1);
RoutingTableEntry entry2;
NS_TEST_ASSERT (table.Lookup (Ipv4Address ("1.2.3.4"), entry2));
NS_TEST_ASSERT_EQUAL (entry2.destAddr, Ipv4Address ("1.2.3.4"));
NS_TEST_ASSERT_EQUAL (entry2.nextAddr, Ipv4Address ("1.2.3.4"));
NS_TEST_ASSERT_EQUAL (entry2.interface, 0);
NS_TEST_ASSERT_EQUAL (entry2.distance, 1);
RoutingTableEntry sendEntry;
NS_TEST_ASSERT (table.FindSendEntry (entry1, sendEntry));
NS_TEST_ASSERT_EQUAL (sendEntry.destAddr, Ipv4Address ("1.2.3.4"));
NS_TEST_ASSERT_EQUAL (sendEntry.nextAddr, Ipv4Address ("1.2.3.4"));
NS_TEST_ASSERT_EQUAL (sendEntry.interface, 0);
NS_TEST_ASSERT_EQUAL (sendEntry.distance, 1);
table.RemoveEntry (Ipv4Address ("1.2.3.5"));
RoutingTableEntry removedEntry;
NS_TEST_ASSERT (not table.Lookup (Ipv4Address ("1.2.3.5"), removedEntry));
return result;
}
static OlsrRoutingTableTest gOlsrRoutingTableTest;
}}; // namespace
#endif /* RUN_SELF_TESTS */

View File

@@ -0,0 +1,112 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2004 Francisco J. Ros
* Copyright (c) 2007 INESC Porto
*
* 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
*
* Authors: Francisco J. Ros <fjrm@dif.um.es>
* Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
///
/// \file OLSR_rtable.h
/// \brief Header file for routing table's related stuff.
///
#ifndef __OLSR_RTABLE_H__
#define __OLSR_RTABLE_H__
#include "ns3/ipv4.h"
#include <map>
namespace ns3 { namespace olsr {
/// An %OLSR's routing table entry.
struct RoutingTableEntry
{
Ipv4Address destAddr; ///< Address of the destination node.
Ipv4Address nextAddr; ///< Address of the next hop.
uint32_t interface; ///< Interface index
uint32_t distance; ///< Distance in hops to the destination.
RoutingTableEntry () : // default values
destAddr (), nextAddr (),
interface (0), distance (0) {};
};
///
/// \brief Defines rtable_t as a map of OLSR_rt_entry, whose key is the destination address.
///
/// The routing table is thus defined as pairs: [dest address, entry]. Each element
/// of the pair can be accesed via "first" and "second" members.
///
//typedef std::map<Ipv4Address, RoutingTableEntry> RoutingTable;
///
/// \brief This class is a representation of the OLSR's Routing Table.
///
class RoutingTable : public Ipv4RoutingProtocol
{
std::map<Ipv4Address, RoutingTableEntry> m_table; ///< Data structure for the routing table.
Ptr<Ipv4> m_ipv4;
Ipv4Address m_mainAddress; // used only for printing debug messages
void DoDispose ()
{
m_ipv4 = 0;
Ipv4RoutingProtocol::DoDispose ();
}
public:
RoutingTable () {}
RoutingTable (Ptr<Ipv4> ipv4, const Ipv4Address &mainAddress)
:
m_ipv4 (ipv4),
m_mainAddress (mainAddress)
{}
~RoutingTable () {}
void Clear ();
void RemoveEntry (const Ipv4Address &dest);
void AddEntry (const Ipv4Address &dest,
const Ipv4Address &next,
uint32_t interface,
uint32_t distance);
void AddEntry (const Ipv4Address &dest,
const Ipv4Address &next,
const Ipv4Address &interfaceAddress,
uint32_t distance);
bool Lookup (const Ipv4Address &dest,
RoutingTableEntry &outEntry) const;
bool FindSendEntry (const RoutingTableEntry &entry,
RoutingTableEntry &outEntry) const;
// From Ipv4RoutingProtocol
virtual bool RequestRoute (uint32_t ifIndex,
const Ipv4Header &ipHeader,
Packet packet,
RouteReplyCallback routeReply);
virtual bool RequestIfIndex (Ipv4Address destination,
uint32_t& ifIndex);
};
}}; // namespace ns3, olsr
#endif

21
src/routing/olsr/wscript Normal file
View File

@@ -0,0 +1,21 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
module = bld.create_ns3_module('olsr', ['internet-node'])
module.includes = '.'
module.source = [
'olsr-header.cc',
'olsr-state.cc',
'routing-table.cc',
'olsr-agent.cc',
'olsr-agent-impl.cc',
'olsr.cc',
'event-garbage-collector.cc',
]
headers = bld.create_obj('ns3header')
headers.source = [
'olsr-agent.h',
'olsr.h',
]

View File

@@ -20,7 +20,6 @@
#include "timer.h"
#include "simulator.h"
#include "simulation-singleton.h"
#include "event-garbage-collector.h"
namespace ns3 {
@@ -31,16 +30,8 @@ Timer::Timer ()
m_impl (0)
{}
Timer::Timer (enum SchedulePolicy schedulePolicy,
enum DestroyPolicy destroyPolicy)
: m_flags (schedulePolicy | destroyPolicy),
m_delay (FemtoSeconds (0)),
m_event (),
m_impl (0)
{}
Timer::Timer (enum GarbageCollectPolicy policy)
: m_flags (GARBAGE_COLLECT),
Timer::Timer (enum DestroyPolicy destroyPolicy)
: m_flags (destroyPolicy),
m_delay (FemtoSeconds (0)),
m_event (),
m_impl (0)
@@ -149,26 +140,11 @@ void
Timer::Schedule (Time delay)
{
NS_ASSERT (m_impl != 0);
if (m_flags & CHECK_ON_SCHEDULE)
if (m_event.IsRunning ())
{
if (m_event.IsRunning ())
{
NS_FATAL_ERROR ("Event is still running while re-scheduling.");
}
}
else if (m_flags & CANCEL_ON_SCHEDULE)
{
m_event.Cancel ();
}
else if (m_flags & REMOVE_ON_SCHEDULE)
{
Simulator::Remove (m_event);
NS_FATAL_ERROR ("Event is still running while re-scheduling.");
}
m_event = m_impl->Schedule (delay);
if (m_flags & GARBAGE_COLLECT)
{
SimulationSingleton<EventGarbageCollector>::Get ()->Track (m_event);
}
}
void

View File

@@ -43,23 +43,6 @@ class TimerImpl;
class Timer
{
public:
enum SchedulePolicy {
/**
* This policy cancels the event before scheduling a new event
* for each call to Timer::Schedule.
*/
CANCEL_ON_SCHEDULE = (1<<0),
/**
* This policy removes the event from the simulation event list
* before scheduling a new event for each call to Timer::Schedule.
*/
REMOVE_ON_SCHEDULE = (1<<1),
/**
* This policy enforces a check before each call to Timer::Schedule
* to verify that the timer has already expired.
*/
CHECK_ON_SCHEDULE = (1<<2),
};
enum DestroyPolicy {
/**
* This policy cancels the event from the destructor of the Timer
@@ -77,15 +60,6 @@ public:
*/
CHECK_ON_DESTROY = (1<<5)
};
enum GarbageCollectPolicy {
/**
* Every event scheduled with this policy is kept track of by an
* event garbage collector which makes sure that all events
* of timers with a GARBAGE_COLLECT policy are cancelled at the
* end of the simulation.
*/
GARBAGE_COLLECT = (1<<6)
};
enum State {
RUNNING,
EXPIRED,
@@ -93,21 +67,13 @@ public:
};
/**
* create a timer with a default event lifetime management policy:
* - CHECK_ON_SCHEDULE
* - CHECK_ON_DESTROY
*/
Timer ();
/**
* \param scheduleFlags the event lifetime management policies to use for schedule events
* \param destroyFlags the event lifetime management policies to use for destroy events
*/
Timer (enum SchedulePolicy schedulePolicy,
enum DestroyPolicy destroyPolicy);
/**
* \param policy the garbage collect policy. Only one
* value is possible.
*/
Timer (enum GarbageCollectPolicy policy);
Timer (enum DestroyPolicy destroyPolicy);
~Timer ();
/**

View File

@@ -61,7 +61,6 @@ def build(bld):
'simulator.cc',
'time-default-value.cc',
'timer.cc',
'event-garbage-collector.cc',
'watchdog.cc',
]

View File

@@ -21,6 +21,7 @@ all_modules = (
'applications/onoff',
'applications/packet-sink',
'applications/udp-echo',
'routing/olsr',
'routing/global-routing',
'mobility',
'devices/wifi',

View File

@@ -15,6 +15,7 @@
*/
#include "ns3/log.h"
#include "ns3/debug.h"
NS_LOG_COMPONENT_DEFINE ("HelloSimulator");
@@ -23,7 +24,10 @@ using namespace ns3;
int
main (int argc, char *argv[])
{
LogComponentEnable ("HelloSimulator", LOG_LEVEL_INFO);
DebugComponentEnable ("Log");
// LogComponentEnable ("HelloSimulator",
// LogLevel (LOG_LEVEL_INFO | LOG_PREFIX_ALL));
NS_LOG_INFO ("Hello Simulator");
}

View File

@@ -0,0 +1,35 @@
#include <iostream>
#include <vector>
#include <stdlib.h>
#include "ns3/event-collector.h"
#include "ns3/simulator.h"
using namespace ns3;
void Foo ()
{
}
int main (int argc, char *argv[])
{
EventCollector events;
if (argc < 3)
{
std::cerr << "usage: bench-event-collector NUM_EVENTS NUM_REPETITIONS" << std::endl;
return 1;
}
int numEvents = atoi (argv[1]);
int numRepetitions = atoi (argv[2]);
for (int repetition = 0; repetition < numRepetitions; ++repetition)
{
for (int n = 0; n < numEvents; ++n)
{
events.Track (Simulator::Schedule (Simulator::Now (), Foo));
}
Simulator::Run ();
}
}

View File

@@ -174,6 +174,10 @@ def build(bld):
check_shell()
if Params.g_options.doxygen:
doxygen()
raise SystemExit(0)
# process subfolders from here
bld.add_subdirs('src')
bld.add_subdirs('samples utils examples tutorial')