merge with trunk

This commit is contained in:
Mathieu Lacage
2007-08-04 17:17:23 +02:00
25 changed files with 6032 additions and 13 deletions

521
SConstruct Normal file
View File

@@ -0,0 +1,521 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
import os.path
import build
version_file = open ('VERSION', 'r')
version = version_file.readline ()
version_file.close ()
version = version.strip ()
ns3 = build.Ns3()
ns3.build_dir = 'build-dir'
ns3.version = version
ns3.name = 'ns3'
ns3.distname = 'ns'
ns3.doxygen_config = os.path.join('doc', 'doxygen.conf')
ns3.add_extra_dist(os.path.join('doc', 'main.txt'))
ns3.add_extra_dist ('doc/architecture.pdf')
ns3.add_extra_dist ('doc/contributing.txt')
ns3.add_extra_dist ('doc/build.txt')
ns3.add_extra_dist ('doc/codingstd.txt')
ns3.add_extra_dist ('doc/mercurial.txt')
ns3.add_extra_dist ('README')
ns3.add_extra_dist ('RELEASE_NOTES')
ns3.add_extra_dist ('AUTHORS')
ns3.add_extra_dist ('VERSION')
ns3.add_extra_dist('doc/build-waf.txt')
ns3.add_extra_dist('ns3/_placeholder_')
for wscript in [
"src/core/wscript",
"src/node/wscript",
"src/devices/p2p/wscript",
"src/common/wscript",
"src/applications/wscript",
"src/simulator/wscript",
"src/internet-node/wscript",
"src/wscript",
"utils/wscript",
"samples/wscript",
"examples/wscript",
"wscript",
]:
ns3.add_extra_dist(wscript)
ns3.add_extra_dist('waf')
ns3.add_extra_dist('waf.bat')
#
# The Core module
#
core = build.Ns3Module('core', 'src/core')
ns3.add(core)
core.add_sources([
'callback-test.cc',
'debug.cc',
'assert.cc',
'ptr.cc',
'object.cc',
'test.cc',
'random-variable.cc',
'rng-stream.cc',
'uid-manager.cc',
'default-value.cc',
'command-line.cc',
'type-name.cc',
'component-manager.cc',
])
env = Environment()
if env['PLATFORM'] == 'posix' or env['PLATFORM'] == 'darwin' or env['PLATFORM'] == 'cygwin':
core.add_external_dep('pthread')
core.add_sources([
'unix-system-wall-clock-ms.cc',
])
elif env['PLATFORM'] == 'win32':
core.add_sources([
'win32-system-wall-clock-ms.cc',
])
core.add_headers ([
'uid-manager.h',
'singleton.h',
])
core.add_inst_headers([
'system-wall-clock-ms.h',
'empty.h',
'callback.h',
'ptr.h',
'object.h',
'debug.h',
'assert.h',
'fatal-error.h',
'test.h',
'random-variable.h',
'rng-stream.h',
'default-value.h',
'command-line.h',
'type-name.h',
'component-manager.h',
])
def config_core (env, config):
retval = []
# XXX This check is primitive but it should be
# good enough for now.
if config.CheckCHeader ('stdlib.h') == 1:
retval.append ('#define HAVE_STDLIB_H 1')
retval.append ('#define HAVE_GETENV 1')
else:
retval.append ('#undef HAVE_STDLIB_H')
retval.append ('#undef HAVE_GETENV')
return retval
core.add_config (config_core)
#
# The Simulator module
#
simu = build.Ns3Module('simulator', 'src/simulator')
ns3.add(simu)
simu.add_dep('core')
simu.add_external_dep('m')
simu.add_sources([
'high-precision.cc',
'time.cc',
'event-id.cc',
'scheduler.cc',
'scheduler-factory.cc',
'scheduler-list.cc',
'scheduler-heap.cc',
'scheduler-map.cc',
'event-impl.cc',
'simulator.cc',
])
simu.add_headers([
'scheduler-heap.h',
'scheduler-map.h',
'scheduler-list.h'
])
simu.add_inst_headers([
'high-precision.h',
'nstime.h',
'event-id.h',
'event-impl.h',
'simulator.h',
'scheduler.h',
'scheduler-factory.h',
'simulation-singleton.h',
])
high_precision_as_double = ARGUMENTS.get('high-precision-as-double', 'n')
if high_precision_as_double == 'y':
simu.add_inst_header ('high-precision-double.h')
simu.add_source ('high-precision-double.cc')
else:
simu.add_inst_headers ([
'high-precision-128.h',
'cairo-wideint-private.h'
])
simu.add_sources ([
'high-precision-128.cc',
'cairo-wideint.c',
])
def config_simulator (env, config):
retval = []
high_precision_as_double = ARGUMENTS.get('high-precision-as-double', 'n')
if high_precision_as_double == 'y':
retval.append ('#define USE_HIGH_PRECISION_DOUBLE 1')
else:
retval.append ('#undef USE_HIGH_PRECISION_DOUBLE')
if config.CheckCHeader ('stdint.h') == 1:
retval.append ('#define HAVE_STDINT_H 1')
elif config.CheckCHeader ('inttypes.h') == 1:
retval.append ('#define HAVE_INTTYPES_H 1')
elif config.CheckCHeader ('sys/inttypes.h') == 1:
retval.append ('#define HAVE_SYS_INT_TYPES_H 1')
return retval
simu.add_config (config_simulator)
#
# The Common module
#
common = build.Ns3Module('common', 'src/common')
common.add_deps(['core', 'simulator'])
ns3.add(common)
common.add_sources([
'buffer.cc',
'chunk.cc',
'header.cc',
'trailer.cc',
'packet-printer.cc',
'packet-metadata.cc',
'packet.cc',
'tags.cc',
'pcap-writer.cc',
'variable-tracer-test.cc',
'trace-context.cc',
'trace-resolver.cc',
'callback-trace-source.cc',
'empty-trace-resolver.cc',
'composite-trace-resolver.cc',
'trace-root.cc',
'data-rate.cc',
])
common.add_headers ([
])
common.add_inst_headers([
'buffer.h',
'chunk.h',
'header.h',
'trailer.h',
'tags.h',
'packet.h',
'packet-printer.h',
'packet-metadata.h',
'uv-trace-source.h',
'sv-trace-source.h',
'fv-trace-source.h',
'pcap-writer.h',
'callback-trace-source.h',
'trace-context.h',
'trace-resolver.h',
'empty-trace-resolver.h',
'composite-trace-resolver.h',
'array-trace-resolver.h',
'trace-root.h',
'terminal-trace-resolver.h',
'data-rate.h',
])
#
# The Node module
#
node = build.Ns3Module ('node', 'src/node')
ns3.add (node)
node.add_deps (['core', 'common', 'simulator'])
node.add_sources ([
'node.cc',
'ipv4-address.cc',
'net-device.cc',
'mac-address.cc',
'llc-snap-header.cc',
'ipv4-route.cc',
'queue.cc',
'drop-tail-queue.cc',
'channel.cc',
'node-list.cc',
'socket.cc',
'socket-factory.cc',
'udp.cc',
'ipv4.cc',
'application.cc',
])
node.add_inst_headers ([
'node.h',
'ipv4-address.h',
'net-device.h',
'mac-address.h',
'ipv4-route.h',
'queue.h',
'drop-tail-queue.h',
'llc-snap-header.h',
'channel.h',
'node-list.h',
'socket.h',
'socket-factory.h',
'udp.h',
'ipv4.h',
'application.h',
])
#
# The Applications module
#
applications = build.Ns3Module ('applications', 'src/applications')
ns3.add (applications)
applications.add_deps (['node'])
applications.add_sources ([
'onoff-application.cc',
])
applications.add_inst_headers ([
'onoff-application.h',
])
#
# The Internet Node module
#
inode = build.Ns3Module ('internet-node', 'src/internet-node')
ns3.add (inode)
inode.add_deps (['node', 'routing'])
inode.add_sources ([
'internet-node.cc',
'l3-demux.cc',
'l3-protocol.cc',
'ipv4-l4-demux.cc',
'ipv4-l4-protocol.cc',
'ipv4-header.cc',
'udp-header.cc',
'ipv4-checksum.cc',
'ipv4-interface.cc',
'ipv4-l3-protocol.cc',
'ipv4-end-point.cc',
'udp-l4-protocol.cc',
'arp-header.cc',
'arp-cache.cc',
'arp-ipv4-interface.cc',
'arp-l3-protocol.cc',
'ipv4-loopback-interface.cc',
'header-utils.cc',
'udp-socket.cc',
'ipv4-end-point-demux.cc',
'arp-private.cc',
'ipv4-impl.cc',
'ipv4-private.cc',
'ascii-trace.cc',
'pcap-trace.cc',
'udp-impl.cc',
])
inode.add_headers ([
'ipv4-checksum.h',
'arp-header.h',
'arp-cache.h',
'arp-l3-protocol.h',
'ipv4-loopback-interface.h',
'l3-demux.h',
'header-utils.h',
'arp-ipv4-interface.h',
'udp-socket.h',
'udp-l4-protocol.h',
'arp-private.h',
'ipv4-impl.h',
'ipv4-private.h',
'ipv4-l3-protocol.h',
'l3-protocol.h',
'ipv4-l4-protocol.h',
'ipv4-l4-demux.h',
'ipv4-end-point-demux.h',
'ipv4-end-point.h',
'ipv4-header.h',
'ipv4-interface.h',
'udp-header.h',
'sgi-hashmap.h',
'udp-impl.h',
])
inode.add_inst_headers ([
'internet-node.h',
'ascii-trace.h',
'pcap-trace.h',
'ipv4-header.h',
'udp-header.h',
])
#
# The Point-to-point module
#
p2p = build.Ns3Module ('p2p', 'src/devices/p2p')
ns3.add (p2p)
p2p.add_deps (['node'])
p2p.add_sources ([
'p2p-net-device.cc',
'p2p-channel.cc',
'p2p-topology.cc',
])
p2p.add_inst_headers ([
'p2p-net-device.h',
'p2p-channel.h',
'p2p-topology.h',
])
#
# The Routing module
#
routing = build.Ns3Module('routing', 'src/routing')
routing.add_deps(['core', 'node'])
ns3.add(routing)
routing.add_sources([
'routing-environment.cc',
'static-router.cc',
'static-route-manager.cc',
'static-route-manager-impl.cc',
'candidate-queue.cc',
])
routing.add_headers ([
'candidate-queue.h',
'static-route-manager-impl.h',
])
routing.add_inst_headers([
'routing-environment.h',
'static-router.h',
'static-route-manager.h',
])
# utils
run_tests = build.Ns3Module('run-tests', 'utils')
ns3.add(run_tests)
run_tests.set_executable()
run_tests.add_deps(['core', 'simulator', 'common', 'routing'])
run_tests.add_source('run-tests.cc')
bench_object = build.Ns3Module('bench-object', 'utils')
ns3.add(bench_object)
bench_object.set_executable()
bench_object.add_deps(['core'])
bench_object.add_source('bench-object.cc')
bench_packets = build.Ns3Module('bench-packets', 'utils')
ns3.add(bench_packets)
bench_packets.set_executable()
bench_packets.add_deps (['core', 'common'])
bench_packets.add_source('bench-packets.cc')
bench_simu = build.Ns3Module('bench-simulator', 'utils')
ns3.add(bench_simu)
bench_simu.set_executable()
bench_simu.add_dep('simulator')
bench_simu.add_source('bench-simulator.cc')
replay_simu = build.Ns3Module('replay-simulation', 'utils')
ns3.add(replay_simu)
replay_simu.set_executable()
replay_simu.add_dep('simulator')
replay_simu.add_source('replay-simulation.cc')
# samples
sample_debug = build.Ns3Module('sample-debug', 'samples')
sample_debug.set_executable()
ns3.add(sample_debug)
sample_debug.add_dep('core')
sample_debug.add_source('main-debug.cc')
sample_debug.add_source('main-debug-other.cc')
sample_packet_printer = build.Ns3Module('sample-packet-printer', 'samples')
sample_packet_printer.set_executable()
ns3.add(sample_packet_printer)
sample_packet_printer.add_deps (['common', 'internet-node'])
sample_packet_printer.add_source('main-packet-printer.cc')
sample_callback = build.Ns3Module('sample-callback', 'samples')
sample_callback.set_executable()
ns3.add(sample_callback)
sample_callback.add_dep('core')
sample_callback.add_source('main-callback.cc')
sample_ptr = build.Ns3Module('sample-ptr', 'samples')
sample_ptr.set_executable()
ns3.add(sample_ptr)
sample_ptr.add_dep('core')
sample_ptr.add_source('main-ptr.cc')
sample_trace = build.Ns3Module('sample-trace', 'samples')
#ns3.add(sample_trace)
sample_trace.add_dep('common')
sample_trace.set_executable()
sample_trace.add_source('main-trace.cc')
sample_query_interface = build.Ns3Module('sample-query-interface', 'samples')
ns3.add(sample_query_interface)
sample_query_interface.add_dep('common')
sample_query_interface.set_executable()
sample_query_interface.add_source('main-query-interface.cc')
sample_simu = build.Ns3Module('sample-simulator', 'samples')
ns3.add(sample_simu)
sample_simu.set_executable()
sample_simu.add_dep('simulator')
sample_simu.add_source('main-simulator.cc')
sample_packet = build.Ns3Module('sample-packet', 'samples')
ns3.add(sample_packet)
sample_packet.set_executable()
sample_packet.add_dep('common')
sample_packet.add_source('main-packet.cc')
sample_test = build.Ns3Module('sample-test', 'samples')
sample_test.set_executable()
ns3.add(sample_test)
sample_test.add_dep('core')
sample_test.add_source('main-test.cc')
sample_simple = build.Ns3Module('sample-simple', 'samples')
sample_simple.set_executable()
ns3.add(sample_simple)
sample_simple.add_deps(['core', 'simulator', 'node', 'internet-node', 'routing'])
sample_simple.add_source('main-simple.cc')
sample_sp2p = build.Ns3Module('sample-simple-p2p', 'samples')
sample_sp2p.set_executable()
#n3.add(sample_sp2p)
sample_sp2p.add_deps(['core', 'simulator', 'node', 'internet-node', 'p2p'])
sample_sp2p.add_source('main-simple-p2p.cc')
sample_default_value = build.Ns3Module('sample-default-value', 'samples')
sample_default_value.set_executable()
ns3.add(sample_default_value)
sample_default_value.add_deps(['core', 'simulator', 'node', 'p2p'])
sample_default_value.add_source('main-default-value.cc')
sample_object = build.Ns3Module('sample-object', 'samples')
sample_object.set_executable()
ns3.add(sample_object)
sample_object.add_deps(['core'])
sample_object.add_source('main-object.cc')
sample_component_manager = build.Ns3Module('sample-component-manager', 'samples')
sample_component_manager.set_executable()
ns3.add(sample_component_manager)
sample_component_manager.add_deps(['core'])
sample_component_manager.add_source('main-component-manager.cc')
# examples
example_simple_p2p = build.Ns3Module('simple-p2p', 'examples')
example_simple_p2p.set_executable()
ns3.add(example_simple_p2p)
example_simple_p2p.add_deps(['core', 'simulator', 'node', 'p2p', 'internet-node', 'applications', 'routing'])
example_simple_p2p.add_source('simple-p2p.cc')
example_static_routing = build.Ns3Module('simple-static-routing', 'examples')
example_static_routing.set_executable()
ns3.add(example_static_routing)
example_static_routing.add_deps(['core', 'simulator', 'node', 'p2p', 'internet-node', 'applications', 'routing'])
example_static_routing.add_source('simple-static-routing.cc')
ns3.generate_dependencies()

View File

@@ -0,0 +1,183 @@
/* -*- 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-global-routing.tr"
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include "ns3/debug.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/mac-address.h"
#include "ns3/ipv4-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/global-route-manager.h"
using namespace ns3;
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
DebugComponentEnable ("Object");
DebugComponentEnable ("Queue");
DebugComponentEnable ("DropTailQueue");
DebugComponentEnable ("Channel");
DebugComponentEnable ("PointToPointChannel");
DebugComponentEnable ("PointToPointNetDevice");
DebugComponentEnable ("GlobalRouter");
DebugComponentEnable ("GlobalRouteManager");
#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
Bind ("Queue", "DropTailQueue");
Bind ("OnOffApplicationPacketSize", "210");
Bind ("OnOffApplicationDataRate", "448kb/s");
//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.
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
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.
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"));
// 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 of size
// 210 bytes at a rate of 448 Kb/s
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
n0,
Ipv4Address ("10.1.3.2"),
80,
"Udp",
ConstantVariable (1),
ConstantVariable (0));
// Start the application
ooff->Start (Seconds (1.0));
ooff->Stop (Seconds (10.0));
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
ooff = Create<OnOffApplication> (
n3,
Ipv4Address ("10.1.2.1"),
80,
"Udp",
ConstantVariable (1),
ConstantVariable (0));
// Start the application
ooff->Start (Seconds (1.1));
ooff->Stop (Seconds (10.0));
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
// Trace output will be sent to the simple-global-routing.tr file
AsciiTrace asciitrace ("simple-global-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-global-routing.pcap");
pcaptrace.TraceAllIp ();
Simulator::Run ();
Simulator::Destroy ();
}

191
examples/simple-p2p.cc Normal file
View File

@@ -0,0 +1,191 @@
/* -*- 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 p2p 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-p2p.tr"
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#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/p2p-channel.h"
#include "ns3/p2p-net-device.h"
#include "ns3/mac-address.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv4.h"
#include "ns3/socket.h"
#include "ns3/ipv4-route.h"
#include "ns3/p2p-topology.h"
#include "ns3/onoff-application.h"
using namespace ns3;
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
DebugComponentEnable("Object");
DebugComponentEnable("Queue");
DebugComponentEnable("DropTailQueue");
DebugComponentEnable("Channel");
DebugComponentEnable("PointToPointChannel");
DebugComponentEnable("PointToPointNetDevice");
#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
Bind ("Queue", "DropTailQueue");
Bind ("OnOffApplicationPacketSize", "210");
Bind ("OnOffApplicationDataRate", "448kb/s");
//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.
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
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.
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
PointToPointTopology::AddIpv4Routes(n0, n2, channel0);
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
PointToPointTopology::AddIpv4Routes(n2, n3, channel2);
// Create the OnOff application to send UDP datagrams of size
// 210 bytes at a rate of 448 Kb/s
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
n0,
Ipv4Address("10.1.3.2"),
80,
"Udp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
ooff->Start(Seconds(1.0));
ooff->Stop (Seconds(10.0));
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
ooff = Create<OnOffApplication> (
n3,
Ipv4Address("10.1.2.1"),
80,
"Udp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
ooff->Start(Seconds(1.1));
ooff->Stop (Seconds(10.0));
// Here, finish off packet routing configuration
// This will likely set by some global StaticRouting object in the future
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-p2p.tr file
AsciiTrace asciitrace ("simple-p2p.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-p2p.pcap");
pcaptrace.TraceAllIp ();
Simulator::Run ();
Simulator::Destroy ();
}

View File

@@ -9,6 +9,10 @@ def build(bld):
obj.source = source
return obj
obj = create_ns_prog('simple-point-to-point', 'simple-point-to-point.cc', deps=['point-to-point', 'internet-node'])
obj = create_ns_prog('csma-cd-one-subnet', 'csma-cd-one-subnet.cc', deps=['csma-cd', 'internet-node'])
obj = create_ns_prog('simple-global-routing', 'simple-global-routing.cc',
deps=['point-to-point', 'internet-node', 'global-routing'])
obj = create_ns_prog('simple-point-to-point', 'simple-point-to-point.cc',
deps=['point-to-point', 'internet-node'])
obj = create_ns_prog('csma-cd-one-subnet', 'csma-cd-one-subnet.cc',
deps=['csma-cd', 'internet-node'])

View File

@@ -0,0 +1,186 @@
/* -*- 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
*/
#include "p2p-channel.h"
#include "p2p-net-device.h"
#include "ns3/packet.h"
#include "ns3/simulator.h"
#include "ns3/debug.h"
NS_DEBUG_COMPONENT_DEFINE ("PointToPointChannel");
namespace ns3 {
//
// By default, you get a channel with the name "PointToPoint Channel" that
// has an "infitely" fast transmission speed and zero delay.
//
PointToPointChannel::PointToPointChannel()
:
Channel ("PointToPoint Channel"),
m_bps (DataRate(0xffffffff)),
m_delay (Seconds(0)),
m_nDevices(0)
{
NS_DEBUG("PointToPointChannel::PointToPointChannel ()");
}
PointToPointChannel::PointToPointChannel(
const DataRate& bps,
const Time& delay)
:
Channel ("PointToPoint Channel"),
m_bps (bps),
m_delay (delay),
m_nDevices(0)
{
NS_DEBUG("PointToPointChannel::PointToPointChannel (" << Channel::GetName()
<< ", " << bps.GetBitRate() << ", " << delay << ")");
}
PointToPointChannel::PointToPointChannel(
const std::string& name,
const DataRate& bps,
const Time& delay)
:
Channel (name),
m_bps (bps),
m_delay (delay),
m_nDevices(0)
{
NS_DEBUG("PointToPointChannel::PointToPointChannel (" << name << ", " <<
bps.GetBitRate() << ", " << delay << ")");
}
void
PointToPointChannel::Attach(Ptr<PointToPointNetDevice> device)
{
NS_DEBUG("PointToPointChannel::Attach (" << device << ")");
NS_ASSERT(m_nDevices < N_DEVICES && "Only two devices permitted");
NS_ASSERT(device != 0);
m_link[m_nDevices].m_src = device;
++m_nDevices;
//
// If we have both devices connected to the channel, then finish introducing
// the two halves and set the links to IDLE.
//
if (m_nDevices == N_DEVICES)
{
m_link[0].m_dst = m_link[1].m_src;
m_link[1].m_dst = m_link[0].m_src;
m_link[0].m_state = IDLE;
m_link[1].m_state = IDLE;
}
}
bool
PointToPointChannel::TransmitStart(Packet& p, Ptr<PointToPointNetDevice> src)
{
NS_DEBUG ("PointToPointChannel::TransmitStart (" << &p << ", " << src <<
")");
NS_DEBUG ("PointToPointChannel::TransmitStart (): UID is " <<
p.GetUid () << ")");
NS_ASSERT(m_link[0].m_state != INITIALIZING);
NS_ASSERT(m_link[1].m_state != INITIALIZING);
uint32_t wire = src == m_link[0].m_src ? 0 : 1;
if (m_link[wire].m_state == TRANSMITTING)
{
NS_DEBUG("PointToPointChannel::TransmitStart (): **** ERROR ****");
NS_DEBUG("PointToPointChannel::TransmitStart (): state TRANSMITTING");
return false;
}
NS_DEBUG("PointToPointChannel::TransmitStart (): switch to TRANSMITTING");
m_link[wire].m_state = TRANSMITTING;
return true;
}
bool
PointToPointChannel::TransmitEnd(Packet& p, Ptr<PointToPointNetDevice> src)
{
NS_DEBUG("PointToPointChannel::TransmitEnd (" << &p << ", " << src << ")");
NS_DEBUG ("PointToPointChannel::TransmitEnd (): UID is " <<
p.GetUid () << ")");
NS_ASSERT(m_link[0].m_state != INITIALIZING);
NS_ASSERT(m_link[1].m_state != INITIALIZING);
uint32_t wire = src == m_link[0].m_src ? 0 : 1;
NS_ASSERT(m_link[wire].m_state == TRANSMITTING);
m_link[wire].m_state = PROPAGATING;
//
// The sender is going to free the packet as soon as it has been transmitted.
// We need to copy it to get a reference so it won't e deleted.
//
Packet packet = p;
NS_DEBUG ("PointToPointChannel::TransmitEnd (): Schedule event in " <<
m_delay.GetSeconds () << "sec");
Simulator::Schedule (m_delay,
&PointToPointChannel::PropagationCompleteEvent,
this, packet, src);
return true;
}
void
PointToPointChannel::PropagationCompleteEvent(
Packet p,
Ptr<PointToPointNetDevice> src)
{
NS_DEBUG("PointToPointChannel::PropagationCompleteEvent (" << &p << ", " <<
src << ")");
NS_DEBUG ("PointToPointChannel::PropagationCompleteEvent (): UID is " <<
p.GetUid () << ")");
uint32_t wire = src == m_link[0].m_src ? 0 : 1;
NS_ASSERT(m_link[wire].m_state == PROPAGATING);
m_link[wire].m_state = IDLE;
NS_DEBUG ("PointToPointChannel::PropagationCompleteEvent (): Receive");
m_link[wire].m_dst->Receive (p);
}
uint32_t
PointToPointChannel::GetNDevices (void) const
{
return m_nDevices;
}
Ptr<NetDevice>
PointToPointChannel::GetDevice (uint32_t i) const
{
NS_ASSERT(i < 2);
return m_link[i].m_src;
}
DataRate
PointToPointChannel::GetDataRate (void)
{
return m_bps;
}
Time
PointToPointChannel::GetDelay (void)
{
return m_delay;
}
} // namespace ns3

View File

@@ -0,0 +1,128 @@
/* -*- 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
*/
#ifndef POINT_TO_POINT_CHANNEL_H
#define POINT_TO_POINT_CHANNEL_H
#include <list>
#include "ns3/channel.h"
#include "ns3/ptr.h"
#include "ns3/packet.h"
#include "ns3/nstime.h"
#include "ns3/data-rate.h"
namespace ns3 {
class PointToPointNetDevice;
/**
* \brief Simple Point To Point Channel.
*
* This class represents a very simple point to point channel. Think full
* duplex RS-232 or RS-422 with null modem and no handshaking. There is no
* multi-drop capability on this channel -- there can be a maximum of two
* point-to-point net devices connected. Once we start talking about multi-
* drop, or CSMA, or some other sharing mechanism, things begin getting
* complicated quickly. Rather than invent some ad-hoc mechanism, we just
* Keep It Simple everywhere.
*
* When the channel is instaniated, the constructor takes parameters for
* a single speed, in bits per second, and a speed-of-light delay time as a
* Time object. Both directions use the same speed and delay time.
*
* There are two "wires" in the channel. The first device connected gets the
* [0] wire to transmit on. The second device gets the [1] wire. There is a
* state (IDLE, TRANSMITTING) associated with each wire.
*/
class PointToPointChannel : public Channel {
public:
//
// This is really kidding myself, since just setting N_DEVICES to 3 isn't
// going to come close to magically creating a multi-drop link, but I can't
// bring myself to just type 2 in the code (even though I type 0 and 1 :-).
//
static const int N_DEVICES = 2;
/**
* \brief Create a PointToPointChannel
*
* By default, you get a channel with the name "PointToPoint Channel" that
* has an "infitely" fast transmission speed and zero delay.
*/
PointToPointChannel ();
/**
* \brief Create a PointToPointChannel
*
* \param bps The bitrate of the channel
* \param delay Transmission delay through the channel
*/
PointToPointChannel (const DataRate& bps, const Time& delay);
/**
* \brief Create a PointToPointChannel
*
* \param name the name of the channel for identification purposes
* \param bps The bitrate of the channel
* \param delay Transmission delay through the channel
*/
PointToPointChannel (const std::string& name,
const DataRate& bps, const Time& delay);
/**
* \brief Attach a given netdevice to this channel
* \param device pointer to the netdevice to attach to the channel
*/
void Attach (Ptr<PointToPointNetDevice> device);
bool TransmitStart (Packet& p, Ptr<PointToPointNetDevice> src);
bool TransmitEnd (Packet &p, Ptr<PointToPointNetDevice> src);
void PropagationCompleteEvent(Packet p, Ptr<PointToPointNetDevice> src);
virtual uint32_t GetNDevices (void) const;
virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
virtual DataRate GetDataRate (void);
virtual Time GetDelay (void);
private:
DataRate m_bps;
Time m_delay;
int32_t m_nDevices;
enum WireState
{
INITIALIZING,
IDLE,
TRANSMITTING,
PROPAGATING
};
class Link
{
public:
Link() : m_state (INITIALIZING), m_src (0), m_dst (0) {}
WireState m_state;
Ptr<PointToPointNetDevice> m_src;
Ptr<PointToPointNetDevice> m_dst;
};
Link m_link[N_DEVICES];
};
} // namespace ns3
#endif /* POINT_TO_POINT_CHANNEL_H */

View File

@@ -0,0 +1,354 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* 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
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include <iostream>
#include <cassert>
#include "ns3/debug.h"
#include "ns3/queue.h"
#include "ns3/simulator.h"
#include "ns3/composite-trace-resolver.h"
#include "p2p-net-device.h"
#include "p2p-channel.h"
NS_DEBUG_COMPONENT_DEFINE ("PointToPointNetDevice");
namespace ns3 {
PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node)
:
NetDevice(node, MacAddress ("00:00:00:00:00:00")),
m_txMachineState (READY),
m_bps (DataRate (0xffffffff)),
m_tInterframeGap (Seconds(0)),
m_channel (0),
m_queue (0),
m_rxTrace ()
{
NS_DEBUG ("PointToPointNetDevice::PointToPointNetDevice (" << node << ")");
// BUGBUG FIXME
//
// You _must_ support broadcast to get any sort of packet from the ARP layer.
EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff"));
EnableMulticast();
EnablePointToPoint();
}
PointToPointNetDevice::~PointToPointNetDevice()
{
NS_DEBUG ("PointToPointNetDevice::~PointToPointNetDevice ()");
m_queue = 0;
}
//
// Copy constructor for PointToPointNetDevice.
//
// We use the underlying NetDevice copy constructor to get the base class
// copied. These just remain as is (e.g. you get the same name, the same
// MAC address). If you need to fix them up, YOU, the copier need to do
// that.
//
// The things we need to be careful of are the channel, the queue and the
// trace callback. If the channel pointer is non-zero, we copy the pointer
// and add a reference. If the queue is non-zero, we copy it using the queue
// assignment operator. We don't mess with the trace -- we just reset it.
// We're assuming that the tracing will be set up after the topology creation
// phase and this won't actually matter.
//
PointToPointNetDevice::PointToPointNetDevice (const PointToPointNetDevice& nd)
:
NetDevice(nd),
m_txMachineState(READY),
m_bps (nd.m_bps),
m_tInterframeGap (nd.m_tInterframeGap),
m_channel(nd.m_channel),
m_queue(0),
m_rxTrace ()
{
NS_DEBUG ("PointToPointNetDevice::PointToPointNetDevice (" << &nd << ")");
if (nd.m_queue)
{
m_queue = nd.m_queue;
}
}
void PointToPointNetDevice::DoDispose()
{
m_channel = 0;
NetDevice::DoDispose ();
}
//
// Assignment operator for PointToPointNetDevice.
//
// This uses the non-obvious trick of taking the source net device passed by
// value instead of by reference. This causes the copy constructor to be
// invoked (where the real work is done -- see above). All we have to do
// here is to return the newly constructed net device.
//
PointToPointNetDevice&
PointToPointNetDevice::operator= (const PointToPointNetDevice nd)
{
NS_DEBUG ("PointToPointNetDevice::operator= (" << &nd << ")");
return *this;
}
void
PointToPointNetDevice::SetDataRate(DataRate bps)
{
m_bps = bps;
}
void
PointToPointNetDevice::SetInterframeGap(Time t)
{
m_tInterframeGap = t;
}
bool
PointToPointNetDevice::SendTo (Packet& p, const MacAddress& dest)
{
NS_DEBUG ("PointToPointNetDevice::SendTo (" << &p << ", " << &dest << ")");
NS_DEBUG ("PointToPointNetDevice::SendTo (): UID is " << p.GetUid () << ")");
NS_ASSERT (IsLinkUp ());
#ifdef NOTYET
struct NetDevicePacketDestAddress tag;
tag.address = address;
p.AddTag (tag);
#endif
//
// This class simulates a point to point device. In the case of a serial
// link, this means that we're simulating something like a UART. This is
// not a requirement for a point-to-point link, but it's a typical model for
// the device.
//
// Generally, a real device will have a list of pending packets to transmit.
// An on-device CPU frees the main CPU(s) of the details of what is happening
// in the device and feeds the USART. The main CPU basically just sees the
// list of packets -- it puts packets into the list, and the device frees the
// packets when they are transmitted.
//
// In the case of our virtual device here, the queue pointed to by m_queue
// corresponds to this list. The main CPU adds packets to the list by
// calling this method and when the device completes a send, the packets are
// freed in an "interrupt" service routine.
//
// We're going to do the same thing here. So first of all, the incoming packet
// goes onto our queue if possible. If the queue can't handle it, there's
// nothing to be done.
//
if (m_queue->Enqueue(p) == false )
{
return false;
}
//
// If there's a transmission in progress, the "interrupt" will keep the
// transmission process going. If the device is idle, we need to start a
// transmission.
//
// In the real world, the USART runs until it finishes sending bits, and then
// pulls on the device's transmit complete interrupt wire. At the same time,
// the electrons from the last wiggle of the wire are busy propagating down
// the wire. In the case of a long speed-of-light delay in the wire, we could
// conceivably start transmitting the next packet before the end of the
// previously sent data has even reached the end of the wire. This situation
// is usually avoided (like the plague) and an "interframe gap" is introduced.
// This is usually the round-trip delay on the channel plus some hard-to-
// quantify receiver turn-around time (the time required for the receiver
// to process the last frame and prepare for reception of the next).
//
// So, if the transmit machine is ready, we need to schedule a transmit
// complete event (at which time we tell the channel we're no longer sending
// bits). A separate transmit ready event (at which time the transmitter
// becomes ready to start sending bits again is scheduled there). Finally,
// we tell the channel (via TransmitStart ()) that we've started wiggling the
// wire and bits are coming out.
//
// If the transmit machine is not ready, we just leave and the transmit ready
// event we know is coming will kick-start the transmit process.
//
if (m_txMachineState == READY)
{
return TransmitStart (p);
}
return true;
}
bool
PointToPointNetDevice::TransmitStart (Packet &p)
{
NS_DEBUG ("PointToPointNetDevice::TransmitStart (" << &p << ")");
NS_DEBUG (
"PointToPointNetDevice::TransmitStart (): UID is " << p.GetUid () << ")");
//
// This function is called to start the process of transmitting a packet.
// We need to tell the channel that we've started wiggling the wire and
// schedule an event that will be executed when it's time to tell the
// channel that we're done wiggling the wire.
//
NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit");
m_txMachineState = BUSY;
Time tEvent = Seconds (m_bps.CalculateTxTime(p.GetSize()));
NS_DEBUG ("PointToPointNetDevice::TransmitStart (): " <<
"Schedule TransmitCompleteEvent in " <<
tEvent.GetSeconds () << "sec");
Simulator::Schedule (tEvent,
&PointToPointNetDevice::TransmitCompleteEvent,
this);
return m_channel->TransmitStart (p, this);
}
void
PointToPointNetDevice::TransmitCompleteEvent (void)
{
NS_DEBUG ("PointToPointNetDevice::TransmitCompleteEvent ()");
//
// This function is called to finish the process of transmitting a packet.
// We need to tell the channel that we've stopped wiggling the wire and
// schedule an event that will be executed when it's time to re-enable
// the transmitter after the interframe gap.
//
NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
m_txMachineState = GAP;
Packet p;
bool found;
found = m_queue->Dequeue (p);
NS_ASSERT_MSG(found, "Packet must be on queue if transmitted");
NS_DEBUG ("PointToPointNetDevice::TransmitCompleteEvent (): Pkt UID is " <<
p.GetUid () << ")");
m_channel->TransmitEnd (p, this);
NS_DEBUG (
"PointToPointNetDevice::TransmitCompleteEvent (): " <<
"Schedule TransmitReadyEvent in "
<< m_tInterframeGap.GetSeconds () << "sec");
Simulator::Schedule (m_tInterframeGap,
&PointToPointNetDevice::TransmitReadyEvent,
this);
}
void
PointToPointNetDevice::TransmitReadyEvent (void)
{
NS_DEBUG ("PointToPointNetDevice::TransmitReadyEvent ()");
//
// This function is called to enable the transmitter after the interframe
// gap has passed. If there are pending transmissions, we use this opportunity
// to start the next transmit.
//
NS_ASSERT_MSG(m_txMachineState == GAP, "Must be in interframe gap");
m_txMachineState = READY;
if (m_queue->IsEmpty())
{
return;
}
else
{
Packet p;
bool found;
found = m_queue->Peek (p);
NS_ASSERT_MSG(found, "IsEmpty false but no Packet on queue?");
TransmitStart (p);
}
}
TraceResolver *
PointToPointNetDevice::DoCreateTraceResolver (TraceContext const &context)
{
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
resolver->Add ("queue",
MakeCallback (&Queue::CreateTraceResolver, PeekPointer (m_queue)),
PointToPointNetDevice::QUEUE);
resolver->Add ("rx",
m_rxTrace,
PointToPointNetDevice::RX);
return resolver;
}
bool
PointToPointNetDevice::Attach (Ptr<PointToPointChannel> ch)
{
NS_DEBUG ("PointToPointNetDevice::Attach (" << &ch << ")");
m_channel = ch;
m_channel->Attach(this);
m_bps = m_channel->GetDataRate ();
m_tInterframeGap = m_channel->GetDelay ();
/*
* For now, this device is up whenever a channel is attached to it.
* In fact, it should become up only when the second device
* is attached to the channel. So, there should be a way for
* a PointToPointChannel to notify both of its attached devices
* that the channel is 'complete', hence that the devices are
* up, hence that they can call NotifyLinkUp.
*/
NotifyLinkUp ();
return true;
}
void
PointToPointNetDevice::AddQueue (Ptr<Queue> q)
{
NS_DEBUG ("PointToPointNetDevice::AddQueue (" << q << ")");
m_queue = q;
}
void
PointToPointNetDevice::Receive (Packet& p)
{
// ignore return value for now.
NS_DEBUG ("PointToPointNetDevice::Receive (" << &p << ")");
m_rxTrace (p);
ForwardUp (p);
}
Ptr<Queue>
PointToPointNetDevice::GetQueue(void) const
{
return m_queue;
}
Ptr<Channel>
PointToPointNetDevice::DoGetChannel(void) const
{
return m_channel;
}
bool
PointToPointNetDevice::DoNeedsArp (void) const
{
return false;
}
} // namespace ns3

View File

@@ -0,0 +1,313 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 University of Washington
*
* 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: Craig Dowell <craigdo@ee.washington.edu>
*/
#ifndef POINT_TO_POINT_NET_DEVICE_H
#define POINT_TO_POINT_NET_DEVICE_H
#include <string.h>
#include "ns3/mac-address.h"
#include "ns3/node.h"
#include "ns3/net-device.h"
#include "ns3/callback.h"
#include "ns3/packet.h"
#include "ns3/callback-trace-source.h"
#include "ns3/nstime.h"
#include "ns3/data-rate.h"
#include "ns3/ptr.h"
namespace ns3 {
class Queue;
class PointToPointChannel;
/**
* \class PointToPointNetDevice
* \brief A Device for a Point to Point Network Link.
*
* Ns-3 takes a four-layer view of a protocol stack. This is the same model
* that TCP uses. In this view, layers 5-7 of the OSI reference model are
* grouped together into an application layer; layer four (transport / TCP) is
* broken out; layer three (network / IP) is broken out; and layers 1-2 are
* grouped together. We call this grouping of layers one and two a NetDevice
* and represent it as a class in the system.
*
* The NetDevice class is specialized according to the needs of the specific
* kind of network link. In this case, the link is a PointToPoint link. The
* PointToPoint link is a family of classes that includes this class, the
* PointToPointNetDevice, a PointToPointChannel class that represents the
* actual medium across which bits are sent, a PointToPointIpv4Interface class
* that provides the hook to tie a general purpose node to this specific
* link, and finally, a PointToPointTopology object that is responsible for
* putting all of the pieces together.
*
* This is the PointToPointNetDevice class that represents, essentially, the
* PC card that is used to connect to the PointToPoint network.
*/
class PointToPointNetDevice : public NetDevice {
public:
/**
* Enumeration of the types of traces supported in the class.
*
*/
enum TraceType {
QUEUE, /**< Trace queue events on the attached queue */
RX, /**< Trace packet reception events (from the channel) */
};
/**
* Construct a PointToPointNetDevice
*
* This is the constructor for the PointToPointNetDevice. It takes as a
* parameter the Node to which this device is connected. Ownership of the
* Node pointer is not implied and the node must not be deleded.
*
* @see PointToPointTopology::AddPointToPointLink ()
* @param node the Node to which this device is connected.
*/
PointToPointNetDevice (Ptr<Node> node);
/**
* Copy Construct a PointToPointNetDevice
*
* This is the copy constructor for the PointToPointNetDevice. This is
* primarily used in topology creation.
*
* @see PointToPointTopology::AddPointToPointLink ()
* @param nd the object to be copied
*/
PointToPointNetDevice (const PointToPointNetDevice& nd);
/**
* Destroy a PointToPointNetDevice
*
* This is the destructor for the PointToPointNetDevice.
*/
virtual ~PointToPointNetDevice();
/**
* Assignment Operator for a PointToPointNetDevice
*
* This is the assignment operator for the PointToPointNetDevice. This is
* to allow
*
* @param nd the object to be copied
*/
PointToPointNetDevice& operator= (PointToPointNetDevice nd);
/**
* Set the Data Rate used for transmission of packets. The data rate is
* set in the Attach () method from the corresponding field in the channel
* to which the device is attached. It can be overridden using this method.
*
* @see Attach ()
* @param bps the data rate at which this object operates
*/
void SetDataRate(DataRate bps);
/**
* Set the inteframe gap used to separate packets. The interframe gap
* defines the minimum space required between packets sent by this device.
* It is usually set in the Attach () method based on the speed of light
* delay of the channel to which the device is attached. It can be
* overridden using this method if desired.
*
* @see Attach ()
* @param t the interframe gap time
*/
void SetInterframeGap(Time t);
/**
* Attach the device to a channel.
*
* The PointToPointTopology object creates a PointToPointChannel and two
* PointtoPointNetDevices. In order to introduce these components to each
* other, the topology object calls Attach () on each PointToPointNetDevice.
* Inside this method, the Net Device calls out to the PointToPointChannel
* to introduce itself.
*
* @see PointToPointTopology::AddPointToPointLink ()
* @see SetDataRate ()
* @see SetInterframeGap ()
* @param ch a pointer to the channel to which this object is being attached.
*/
bool Attach(Ptr<PointToPointChannel> ch);
/**
* Attach a queue to the PointToPointNetDevice.
*
* The PointToPointNetDevice "owns" a queue. This queue is created by the
* PointToPointTopology object and implements a queueing method such as
* DropTail or RED. The PointToPointNetDevice assumes ownership of this
* queue and must delete it when the device is destroyed.
*
* @see PointToPointTopology::AddPointToPointLink ()
* @see Queue
* @see DropTailQueue
* @param queue a pointer to the queue for which object is assuming
* ownership.
*/
void AddQueue(Ptr<Queue> queue);
/**
* Receive a packet from a connected PointToPointChannel.
*
* The PointToPointNetDevice receives packets from its connected channel
* and forwards them up the protocol stack. This is the public method
* used by the channel to indicate that the last bit of a packet has
* arrived at the device.
*
* @see PointToPointChannel
* @param p a reference to the received packet
*/
void Receive (Packet& p);
protected:
virtual void DoDispose (void);
/**
* Get a copy of the attached Queue.
*
* This method is provided for any derived class that may need to get
* direct access to the underlying queue.
*
* @see PointToPointTopology
* @returns a pointer to the queue.
*/
Ptr<Queue> GetQueue(void) const;
/**
* Get a copy of the attached Channel
*
* This method is provided for any derived class that may need to get
* direct access to the connected channel
*
* @see PointToPointChannel
* @returns a pointer to the channel
*/
virtual Ptr<Channel> DoGetChannel(void) const;
private:
/**
* Send a Packet Down the Wire.
*
* The SendTo method is defined as the standard way that the level three
* protocol uses to tell a NetDevice to send a packet. SendTo is declared
* as abstract in the NetDevice class and we declare it here.
*
* @see NetDevice
* @param p a reference to the packet to send
* @param dest a reference to the MacAddress of the destination device
* @returns true if success, false on failure
*/
virtual bool SendTo (Packet& p, const MacAddress& dest);
/**
* Start Sending a Packet Down the Wire.
*
* The TransmitStart method is the method that is used internally in the
* PointToPointNetDevice to begin the process of sending a packet out on
* the channel. The corresponding method is called on the channel to let
* it know that the physical device this class represents has virually
* started sending signals. An event is scheduled for the time at which
* the bits have been completely transmitted.
*
* @see PointToPointChannel::TransmitStart ()
* @see TransmitCompleteEvent ()
* @param p a reference to the packet to send
* @returns true if success, false on failure
*/
bool TransmitStart (Packet &p);
/**
* Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
*
* The TransmitCompleteEvent method is used internally to finish the process
* of sending a packet out on the channel. During execution of this method
* the TransmitEnd method is called on the channel to let it know that the
* physical device this class represents has virually finished sending
* signals. The channel uses this event to begin its speed of light delay
* timer after which it notifies the Net Device at the other end of the
* link that the bits have arrived. During this method, the net device
* also schedules the TransmitReadyEvent at which time the transmitter
* becomes ready to send the next packet.
*
* @see PointToPointChannel::TransmitEnd ()
* @see TransmitReadyEvent ()
* @returns true if success, false on failure
*/
void TransmitCompleteEvent (void);
/**
* Cause the Transmitter to Become Ready to Send Another Packet.
*
* The TransmitReadyEvent method is used internally to re-enable the
* transmit machine of the net device. It is scheduled after a suitable
* interframe gap after the completion of the previous transmission.
* The queue is checked at this time, and if there is a packet waiting on
* the queue, the transmission process is begun.
*
* @see TransmitStart ()
*/
void TransmitReadyEvent (void);
/**
* Create a Trace Resolver for events in the net device.
*
* @see class TraceResolver
*/
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
virtual bool DoNeedsArp (void) const;
/**
* Enumeration of the states of the transmit machine of the net device.
*/
enum TxMachineState
{
READY, /**< The transmitter is ready to begin transmission of a packet */
BUSY, /**< The transmitter is busy transmitting a packet */
GAP /**< The transmitter is in the interframe gap time */
};
/**
* The state of the Net Device transmit state machine.
* @see TxMachineState
*/
TxMachineState m_txMachineState;
/**
* The data rate that the Net Device uses to simulate packet transmission
* timing.
* @see class DataRate
*/
DataRate m_bps;
/**
* The interframe gap that the Net Device uses to throttle packet
* transmission
* @see class Time
*/
Time m_tInterframeGap;
/**
* The PointToPointChannel to which this PointToPointNetDevice has been
* attached.
* @see class PointToPointChannel
*/
Ptr<PointToPointChannel> m_channel;
/**
* The Queue which this PointToPointNetDevice uses as a packet source.
* Management of this Queue has been delegated to the PointToPointNetDevice
* and it has the responsibility for deletion.
* @see class Queue
* @see class DropTailQueue
*/
Ptr<Queue> m_queue;
/**
* The trace source for the packet reception events that the device can
* fire.
*
* @see class CallBackTraceSource
* @see class TraceResolver
*/
CallbackTraceSource<Packet &> m_rxTrace;
};
}; // namespace ns3
#endif // POINT_TO_POINT_NET_DEVICE_H

View File

@@ -0,0 +1,172 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
//
// Copyright (c) 2006 Georgia Tech Research Corporation
//
// 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: George F. Riley<riley@ece.gatech.edu>
//
//
// Topology helper for ns3.
// George F. Riley, Georgia Tech, Spring 2007
#include <algorithm>
#include "ns3/assert.h"
#include "ns3/debug.h"
#include "ns3/fatal-error.h"
#include "ns3/nstime.h"
#include "ns3/internet-node.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv4.h"
#include "ns3/queue.h"
#include "p2p-channel.h"
#include "p2p-net-device.h"
#include "p2p-topology.h"
namespace ns3 {
Ptr<PointToPointChannel>
PointToPointTopology::AddPointToPointLink(
Ptr<Node> n1,
Ptr<Node> n2,
const DataRate& bps,
const Time& delay)
{
Ptr<PointToPointChannel> channel = Create<PointToPointChannel> (bps, delay);
Ptr<PointToPointNetDevice> net1 = Create<PointToPointNetDevice> (n1);
Ptr<Queue> q = Queue::CreateDefault ();
net1->AddQueue(q);
net1->Attach (channel);
Ptr<PointToPointNetDevice> net2 = Create<PointToPointNetDevice> (n2);
q = Queue::CreateDefault ();
net2->AddQueue(q);
net2->Attach (channel);
return channel;
}
void
PointToPointTopology::AddIpv4Addresses(
Ptr<const PointToPointChannel> chan,
Ptr<Node> n1, const Ipv4Address& addr1,
Ptr<Node> n2, const Ipv4Address& addr2)
{
// Duplex link is assumed to be subnetted as a /30
// May run this unnumbered in the future?
Ipv4Mask netmask("255.255.255.252");
NS_ASSERT (netmask.IsMatch(addr1,addr2));
// 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 ());
Ptr<Ipv4> ip1 = n1->QueryInterface<Ipv4> (Ipv4::iid);
uint32_t index1 = ip1->AddInterface (nd1);
ip1->SetAddress (index1, addr1);
ip1->SetNetworkMask (index1, netmask);
ip1->SetUp (index1);
Ptr<Ipv4> ip2 = n2->QueryInterface<Ipv4> (Ipv4::iid);
uint32_t index2 = ip2->AddInterface (nd2);
ip2->SetAddress (index2, addr2);
ip2->SetNetworkMask (index2, netmask);
ip2->SetUp (index2);
}
void
PointToPointTopology::AddIpv4Routes (
Ptr<Node> n1, Ptr<Node> n2, Ptr<const PointToPointChannel> chan)
{
// 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);
// Assert that n1 is the Node owning one of the two NetDevices
// and make sure that nd1 corresponds to it
if (nd1->GetNode ()->GetId () == n1->GetId ())
{
; // Do nothing
}
else if (nd2->GetNode ()->GetId () == n1->GetId ())
{
std::swap(nd1, nd2);
}
else
{
NS_FATAL_ERROR("P2PTopo: Node does not contain an interface on Channel");
}
// Assert that n2 is the Node owning one of the two NetDevices
// and make sure that nd2 corresponds to it
if (nd2->GetNode ()->GetId () != n2->GetId ())
{
NS_FATAL_ERROR("P2PTopo: Node does not contain an interface on Channel");
}
// Assert that both are Ipv4 nodes
Ptr<Ipv4> ip1 = nd1->GetNode ()->QueryInterface<Ipv4> (Ipv4::iid);
Ptr<Ipv4> ip2 = nd2->GetNode ()->QueryInterface<Ipv4> (Ipv4::iid);
NS_ASSERT(ip1 != 0 && ip2 != 0);
// Get interface indexes for both nodes corresponding to the right channel
uint32_t index1 = 0;
bool found = false;
for (uint32_t i = 0; i < ip1->GetNInterfaces (); i++)
{
if (ip1 ->GetNetDevice (i) == nd1)
{
index1 = i;
found = true;
}
}
NS_ASSERT(found);
uint32_t index2 = 0;
found = false;
for (uint32_t i = 0; i < ip2->GetNInterfaces (); i++)
{
if (ip2 ->GetNetDevice (i) == nd2)
{
index2 = i;
found = true;
}
}
NS_ASSERT(found);
ip1->AddHostRouteTo (ip2-> GetAddress (index2), index1);
ip2->AddHostRouteTo (ip1-> GetAddress (index1), index2);
}
} // namespace ns3

View File

@@ -0,0 +1,87 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
//
// Copyright (c) 2006 Georgia Tech Research Corporation
//
// 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: George F. Riley<riley@ece.gatech.edu>
//
// Topology helper for ns3.
// George F. Riley, Georgia Tech, Spring 2007
#ifndef __POINT_TO_POINT_TOPOLOGY_H__
#define __POINT_TO_POINT_TOPOLOGY_H__
#include "ns3/ptr.h"
// The topology class consists of only static methods thar are used to
// create the topology and data flows for an ns3 simulation
namespace ns3 {
class PointToPointChannel;
class Node;
class IPAddr;
class DataRate;
class Queue;
/**
* \brief A helper class to create Topologies based on the
* ns3::PointToPointNetDevice and ns3::PointToPointChannel objects.
*/
class PointToPointTopology {
public:
/**
* \param n1 Node
* \param n2 Node
* \param dataRate Maximum transmission link rate
* \param delay one-way propagation delay
* \return Pointer to the underlying PointToPointChannel
*
* Add a full-duplex point-to-point link between two nodes
* and attach PointToPointNetDevices to the resulting
* PointToPointChannel.
*/
static Ptr<PointToPointChannel> AddPointToPointLink(
Ptr<Node> n1, Ptr<Node> n2, const DataRate& dataRate, const Time& delay);
/**
* \param chan PointToPointChannel to use
* \param n1 Node
* \param addr1 Ipv4 Address for n1
* \param n2 Node
* \param addr2 Ipv4 Address for n2
*
* Add Ipv4Addresses to the Ipv4 interfaces associated with the
* two PointToPointNetDevices on the provided PointToPointChannel
*/
static void AddIpv4Addresses(
Ptr<const PointToPointChannel> chan,
Ptr<Node> n1, const Ipv4Address& addr1,
Ptr<Node> n2, const Ipv4Address& addr2);
/**
* \param channel PointToPointChannel to use
* \param n1 Node
* \param n2 Node
*
* For the given PointToPointChannel, for each Node, add an
* IPv4 host route to the IPv4 address of the peer node.
*/
static void AddIpv4Routes (Ptr<Node> n1, Ptr<Node> n2, Ptr<const PointToPointChannel> channel);
};
} // namespace ns3
#endif

24
src/devices/p2p/wscript Normal file
View File

@@ -0,0 +1,24 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def configure(conf):
conf.env.append_value('NS3_MODULES', 'ns3-p2p')
def build(bld):
p2p = bld.create_obj('cpp', 'shlib')
p2p.name = 'ns3-p2p'
p2p.target = p2p.name
p2p.uselib_local = ['ns3-node']
p2p.source = [
'p2p-net-device.cc',
'p2p-channel.cc',
'p2p-topology.cc',
]
headers = bld.create_obj('ns3header')
headers.source = [
'p2p-net-device.h',
'p2p-channel.h',
'p2p-topology.h',
]

View File

@@ -37,7 +37,6 @@
namespace ns3 {
InternetNode::InternetNode()
{
Construct ();
@@ -78,7 +77,6 @@ InternetNode::Construct (void)
Object::AddInterface (ipv4L4Demux);
}
TraceResolver *
InternetNode::DoCreateTraceResolver (TraceContext const &context)
{

View File

@@ -1,7 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 University of Washington
*
* 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;
@@ -14,11 +12,8 @@
* 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: Craig Dowell <craigdo@ee.washingon.edu>
*
* Wed Feb 14 16:05:46 PST 2007 craigdo: Created
*/
#ifndef CHANNEL_H
#define CHANNEL_H
@@ -41,6 +36,7 @@ class Channel : public Object
{
public:
static const InterfaceId iid;
Channel ();
Channel (std::string name);
@@ -62,8 +58,8 @@ public:
virtual Ptr<NetDevice> GetDevice (uint32_t i) const = 0;
protected:
virtual ~Channel ();
std::string m_name;
virtual ~Channel ();
std::string m_name;
private:
};

View File

@@ -135,6 +135,17 @@ Ipv4Address::Ipv4Address (char const *address)
m_address = AsciiToIpv4Host (address);
}
void
Ipv4Address::Set (uint32_t address)
{
m_address = address;
}
void
Ipv4Address::Set (char const *address)
{
m_address = AsciiToIpv4Host (address);
}
bool
Ipv4Address::IsEqual (Ipv4Address other) const
{

View File

@@ -51,6 +51,22 @@ public:
*/
Ipv4Address (char const *address);
/**
* input address is in host order.
* \param address The host order 32-bit address
*/
void Set (uint32_t address);
/**
* \brief Sets an Ipv4Address by parsing a the input C-string
*
* Input address is in format:
* hhh.xxx.xxx.lll
* where h is the high byte and l the
* low byte
* \param address C-string containing the address as described above
*/
void Set (char const *address);
/**
* \brief Comparison operation between two Ipv4Addresses
* \param other address to which to compare this address

View File

@@ -0,0 +1,150 @@
/* -*- 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
*/
#include "ns3/debug.h"
#include "ns3/assert.h"
#include "candidate-queue.h"
NS_DEBUG_COMPONENT_DEFINE ("CandidateQueue");
namespace ns3 {
CandidateQueue::CandidateQueue()
: m_candidates ()
{
NS_DEBUG("CandidateQueue::CandidateQueue ()");
}
CandidateQueue::~CandidateQueue()
{
NS_DEBUG("CandidateQueue::~CandidateQueue ()");
Clear ();
}
void
CandidateQueue::Clear (void)
{
NS_DEBUG("CandidateQueue::Clear ()");
while (!m_candidates.empty ())
{
SPFVertex *p = Pop ();
delete p;
p = 0;
}
}
void
CandidateQueue::Push (SPFVertex *vNew)
{
NS_DEBUG("CandidateQueue::Push (" << vNew << ")");
CandidateList_t::iterator i = m_candidates.begin ();
for (; i != m_candidates.end (); i++)
{
SPFVertex *v = *i;
if (vNew->GetDistanceFromRoot () < v->GetDistanceFromRoot ())
{
break;
}
}
m_candidates.insert(i, vNew);
}
SPFVertex *
CandidateQueue::Pop (void)
{
NS_DEBUG("CandidateQueue::Pop ()");
if (m_candidates.empty ())
{
return 0;
}
SPFVertex *v = m_candidates.front ();
m_candidates.pop_front ();
return v;
}
SPFVertex *
CandidateQueue::Top (void) const
{
NS_DEBUG("CandidateQueue::Top ()");
if (m_candidates.empty ())
{
return 0;
}
return m_candidates.front ();
}
bool
CandidateQueue::Empty (void) const
{
NS_DEBUG("CandidateQueue::Empty ()");
return m_candidates.empty ();
}
uint32_t
CandidateQueue::Size (void) const
{
NS_DEBUG("CandidateQueue::Size ()");
return m_candidates.size ();
}
SPFVertex *
CandidateQueue::Find (const Ipv4Address addr) const
{
NS_DEBUG("CandidateQueue::Find ()");
CandidateList_t::const_iterator i = m_candidates.begin ();
for (; i != m_candidates.end (); i++)
{
SPFVertex *v = *i;
if (v->GetVertexId() == addr)
{
return v;
}
}
return 0;
}
void
CandidateQueue::Reorder (void)
{
NS_DEBUG("CandidateQueue::Reorder ()");
std::list<SPFVertex*> temp;
while (!m_candidates.empty ()) {
SPFVertex *v = m_candidates.front ();
m_candidates.pop_front ();
temp.push_back(v);
}
while (!temp.empty ()) {
Push (temp.front ());
temp.pop_front ();
}
}
} // namespace ns3

View File

@@ -0,0 +1,181 @@
/* -*- 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
*/
#ifndef CANDIDATE_QUEUE_H
#define CANDIDATE_QUEUE_H
#include <stdint.h>
#include <list>
#include "global-route-manager-impl.h"
namespace ns3 {
/**
* \brief A Candidate Queue used in static routing.
*
* The CandidateQueue is used in the OSPF shortest path computations. It
* is a priority queue used to store candidates for the shortest path to a
* given network.
*
* The queue holds Shortest Path First Vertex pointers and orders them
* according to the lowest value of the field m_distanceFromRoot. Remaining
* vertices are ordered according to increasing distance. This implements a
* priority queue.
*
* Although a STL priority_queue almost does what we want, the requirement
* for a Find () operation, the dynamic nature of the data and the derived
* requirement for a Reorder () operation led us to implement this simple
* enhanced priority queue.
*/
class CandidateQueue
{
public:
/**
* @brief Create an empty SPF Candidate Queue.
* @internal
*
* @see SPFVertex
*/
CandidateQueue ();
/**
* @internal Destroy an SPF Candidate Queue and release any resources held
* by the contents.
* @internal
*
* @see SPFVertex
*/
virtual ~CandidateQueue ();
/**
* @brief Empty the Candidate Queue and release all of the resources
* associated with the Shortest Path First Vertex pointers in the queue.
* @internal
*
* @see SPFVertex
*/
void Clear (void);
/**
* @brief Push a Shortest Path First Vertex pointer onto the queue according
* to the priority scheme.
* @internal
*
* On completion, the top of the queue will hold the Shortest Path First
* Vertex pointer that points to a vertex having lowest value of the field
* m_distanceFromRoot. Remaining vertices are ordered according to
* increasing distance.
*
* @see SPFVertex
* @param vNew The Shortest Path First Vertex to add to the queue.
*/
void Push (SPFVertex *vNew);
/**
* @brief Pop the Shortest Path First Vertex pointer at the top of the queue.
* @internal
*
* The caller is given the responsiblity for releasing the resources
* associated with the vertex.
*
* @see SPFVertex
* @see Top ()
* @returns The Shortest Path First Vertex pointer at the top of the queue.
*/
SPFVertex* Pop (void);
/**
* @brief Return the Shortest Path First Vertex pointer at the top of the
* queue.
* @internal
*
* This method does not pop the SPFVertex* off of the queue, it simply
* returns the pointer.
*
* @see SPFVertex
* @see Pop ()
* @returns The Shortest Path First Vertex pointer at the top of the queue.
*/
SPFVertex* Top (void) const;
/**
* @brief Test the Candidate Queue to determine if it is empty.
* @internal
*
* @returns True if the queue is empty, false otherwise.
*/
bool Empty (void) const;
/**
* @brief Return the number of Shortest Path First Vertex pointers presently
* stored in the Candidate Queue.
* @internal
*
* @see SPFVertex
* @returns The number of SPFVertex* pointers in the Candidate Queue.
*/
uint32_t Size (void) const;
/**
* @brief Searches the Candidate Queue for a Shortest Path First Vertex
* pointer that points to a vertex having the given IP address.
* @internal
*
* @see SPFVertex
* @param addr The IP address to search for.
* @returns The SPFVertex* pointer corresponding to the given IP address.
*/
SPFVertex* Find (const Ipv4Address addr) const;
/**
* @brief Reorders the Candidate Queue according to the priority scheme.
* @internal
*
* On completion, the top of the queue will hold the Shortest Path First
* Vertex pointer that points to a vertex having lowest value of the field
* m_distanceFromRoot. Remaining vertices are ordered according to
* increasing distance.
*
* This method is provided in case the values of m_distanceFromRoot change
* during the routing calculations.
*
* @see SPFVertex
*/
void Reorder (void);
protected:
typedef std::list<SPFVertex*> CandidateList_t;
CandidateList_t m_candidates;
private:
/**
* Candidate Queue copy construction is disallowed (not implemented) to
* prevent the compiler from slipping in incorrect versions that don't
* properly deal with deep copies.
*/
CandidateQueue (CandidateQueue& sr);
/**
* Candidate Queue assignment operator is disallowed (not implemented) to
* prevent the compiler from slipping in incorrect versions that don't
* properly deal with deep copies.
*/
CandidateQueue& operator= (CandidateQueue& sr);
};
} // namespace ns3
#endif /* CANDIDATE_QUEUE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,747 @@
/* -*- 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
*/
#ifndef GLOBAL_ROUTE_MANAGER_IMPL_H
#define GLOBAL_ROUTE_MANAGER_IMPL_H
#include <stdint.h>
#include <list>
#include <queue>
#include <map>
#include "ns3/object.h"
#include "ns3/ptr.h"
#include "ns3/ipv4-address.h"
#include "global-router-interface.h"
namespace ns3 {
const uint32_t SPF_INFINITY = 0xffffffff;
class CandidateQueue;
/**
* @brief Vertex used in shortest path first (SPF) computations. See RFC 2328,
* Section 16.
*
* Each router in the simulation is associated with an SPFVertex object. When
* calculating routes, each of these routers is, in turn, chosen as the "root"
* of the calculation and routes to all of the other routers are eventually
* saved in the routing tables of each of the chosen nodes. Each of these
* routers in the calculation has an associated SPFVertex.
*
* The "Root" vertex is the SPFVertex representing the router that is having
* its routing tables set. The SPFVertex objects representing other routers
* or networks in the simulation are arranged in the SPF tree. It is this
* tree that represents the Shortest Paths to the other networks.
*
* Each SPFVertex has a pointer to the Global Router Link State Advertisement
* (LSA) that its underlying router has exported. Within these LSAs are
* Global Router Link Records that describe the point to point links from the
* underlying router to other nodes (represented by other SPFVertex objects)
* in the simulation topology. The combination of the arrangement of the
* SPFVertex objects in the SPF tree, along with the details of the link
* records that connect them provide the information required to construct the
* required routes.
*/
class SPFVertex
{
public:
/**
* @brief Enumeration of the possible types of SPFVertex objects.
* @internal
*
* Currently we use VertexRouter to identify objects that represent a router
* in the simulation topology, and VertexNetwork to identify objects that
* represent a network.
*/
enum VertexType {
VertexUnknown = 0, /**< Uninitialized Link Record */
VertexRouter, /**< Vertex representing a router in the topology */
VertexNetwork /**< Vertex representing a network in the topology */
};
/**
* @brief Construct an empty ("uninitialized") SPFVertex (Shortest Path First
* Vertex).
* @internal
*
* The Vertex Type is set to VertexUnknown, the Vertex ID is set to
* 255.255.255.255, and the distance from root is set to infinity
* (UINT32_MAX). The referenced Link State Advertisement (LSA) is set to
* null as is the parent SPFVertex. The outgoing interface index is set to
* infinity, the next hop address is set to 0.0.0.0 and the list of children
* of the SPFVertex is initialized to empty.
*
* @see VertexType
*/
SPFVertex();
/**
* @brief Construct an initialized SPFVertex (Shortest Path First Vertex).
* @internal
*
* The Vertex Type is initialized to VertexRouter and the Vertex ID is found
* from the Link State ID of the Link State Advertisement (LSA) passed as a
* parameter. The Link State ID is set to the Router ID of the advertising
* router. The referenced LSA (m_lsa) is set to the given LSA. Other than
* these members, initialization is as in the default constructor.
* of the SPFVertex is initialized to empty.
*
* @see SPFVertex::SPFVertex ()
* @see VertexType
* @see GlobalRouterLSA
* @param lsa The Link State Advertisement used for finding initial values.
*/
SPFVertex(GlobalRouterLSA* lsa);
/**
* @brief Destroy an SPFVertex (Shortest Path First Vertex).
* @internal
*
* The children vertices of the SPFVertex are recursively deleted.
*
* @see SPFVertex::SPFVertex ()
*/
~SPFVertex();
/**
* @brief Get the Vertex Type field of a SPFVertex object.
* @internal
*
* The Vertex Type describes the kind of simulation object a given SPFVertex
* represents.
*
* @see VertexType
* @returns The VertexType of the current SPFVertex object.
*/
VertexType GetVertexType (void) const;
/**
* @brief Set the Vertex Type field of a SPFVertex object.
* @internal
*
* The Vertex Type describes the kind of simulation object a given SPFVertex
* represents.
*
* @see VertexType
* @param type The new VertexType for the current SPFVertex object.
*/
void SetVertexType (VertexType type);
/**
* @brief Get the Vertex ID field of a SPFVertex object.
* @internal
*
* The Vertex ID uniquely identifies the simulation object a given SPFVertex
* represents. Typically, this is the Router ID for SPFVertex objects
* representing routers, and comes from the Link State Advertisement of a
* router aggregated to a node in the simulation. These IDs are allocated
* automatically by the routing environment and look like IP addresses
* beginning at 0.0.0.0 and monotonically increasing as new routers are
* instantiated.
*
* @returns The Ipv4Address Vertex ID of the current SPFVertex object.
*/
Ipv4Address GetVertexId (void) const;
/**
* @brief Set the Vertex ID field of a SPFVertex object.
* @internal
*
* The Vertex ID uniquely identifies the simulation object a given SPFVertex
* represents. Typically, this is the Router ID for SPFVertex objects
* representing routers, and comes from the Link State Advertisement of a
* router aggregated to a node in the simulation. These IDs are allocated
* automatically by the routing environment and look like IP addresses
* beginning at 0.0.0.0 and monotonically increase as new routers are
* instantiated. This method is an explicit override of the automatically
* generated value.
*
* @param id The new Ipv4Address Vertex ID for the current SPFVertex object.
*/
void SetVertexId (Ipv4Address id);
/**
* @brief Get the Global Router Link State Advertisement returned by the
* Global Router represented by this SPFVertex during the route discovery
* process.
* @internal
*
* @see GlobalRouter
* @see GlobalRouterLSA
* @see GlobalRouter::DiscoverLSAs ()
* @returns A pointer to the GlobalRouterLSA found by the router represented
* by this SPFVertex object.
*/
GlobalRouterLSA* GetLSA (void) const;
/**
* @brief Set the Global Router Link State Advertisement returned by the
* Global Router represented by this SPFVertex during the route discovery
* process.
* @internal
*
* @see SPFVertex::GetLSA ()
* @see GlobalRouter
* @see GlobalRouterLSA
* @see GlobalRouter::DiscoverLSAs ()
* @warning Ownership of the LSA is transferred to the "this" SPFVertex. You
* must not delete the LSA after calling this method.
* @param lsa A pointer to the GlobalRouterLSA.
*/
void SetLSA (GlobalRouterLSA* lsa);
/**
* @brief Get the distance from the root vertex to "this" SPFVertex object.
* @internal
*
* Each router in the simulation is associated with an SPFVertex object. When
* calculating routes, each of these routers is, in turn, chosen as the "root"
* of the calculation and routes to all of the other routers are eventually
* saved in the routing tables of each of the chosen nodes. Each of these
* routers in the calculation has an associated SPFVertex.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set. The "this" SPFVertex is the vertex to which
* a route is being calculated from the root. The distance from the root that
* we're asking for is the number of hops from the root vertex to the vertex
* in question.
*
* The distance is calculated during route discovery and is stored in a
* member variable. This method simply fetches that value.
*
* @returns The distance, in hops, from the root SPFVertex to "this" SPFVertex.
*/
uint32_t GetDistanceFromRoot (void) const;
/**
* @brief Set the distance from the root vertex to "this" SPFVertex object.
* @internal
*
* Each router in the simulation is associated with an SPFVertex object. When
* calculating routes, each of these routers is, in turn, chosen as the "root"
* of the calculation and routes to all of the other routers are eventually
* saved in the routing tables of each of the chosen nodes. Each of these
* routers in the calculation has an associated SPFVertex.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set. The "this" SPFVertex is the vertex to which
* a route is being calculated from the root. The distance from the root that
* we're asking for is the number of hops from the root vertex to the vertex
* in question.
*
* @param distance The distance, in hops, from the root SPFVertex to "this"
* SPFVertex.
*/
void SetDistanceFromRoot (uint32_t distance);
/**
* @brief Get the interface ID that should be used to begin forwarding packets
* from the root SPFVertex to "this" SPFVertex.
* @internal
*
* Each router node in the simulation is associated with an SPFVertex object.
* When calculating routes, each of these routers is, in turn, chosen as the
* "root" of the calculation and routes to all of the other routers are
* eventually saved in the routing tables of each of the chosen nodes.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set. The "this" SPFVertex is the vertex that
* represents the host or network to which a route is being calculated from
* the root. The outgoing interface that we're asking for is the interface
* index on the root node that should be used to start packets along the
* path to "this" vertex.
*
* When initializing the root SPFVertex, the interface ID is determined by
* examining the Global Router Link Records of the Link State Advertisement
* generated by the root node's GlobalRouter. These interfaces are used to
* forward packets off of the root's network down those links. As other
* vertices are discovered which are further away from the root, they will
* be accessible down one of the paths begun by a Global Router Link Record.
*
* To forward packets to these hosts or networks, the root node must begin
* the forwarding process by sending the packets to the interface of that
* first hop. This means that the first hop address and interface ID must
* be the same for all downstream SPFVertices. We call this "inheriting"
* the interface and next hop.
*
* In this method, the root node is asking, "which of my local interfaces
* should I use to get a packet to the network or host represented by 'this'
* SPFVertex."
*
* @see GlobalRouter
* @see GlobalRouterLSA
* @see GlobalRouterLinkRecord
* @returns The interface index to use when forwarding packets to the host
* or network represented by "this" SPFVertex.
*/
uint32_t GetOutgoingInterfaceId (void) const;
/**
* @brief Set the interface ID that should be used to begin forwarding packets
* from the root SPFVertex to "this" SPFVertex.
* @internal
*
* Each router node in the simulation is associated with an SPFVertex object.
* When calculating routes, each of these routers is, in turn, chosen as the
* "root" of the calculation and routes to all of the other routers are
* eventually saved in the routing tables of each of the chosen nodes.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set. The "this" SPFVertex is the vertex that
* represents the host or network to which a route is being calculated from
* the root. The outgoing interface that we're asking for is the interface
* index on the root node that should be used to start packets along the
* path to "this" vertex.
*
* When initializing the root SPFVertex, the interface ID is determined by
* examining the Global Router Link Records of the Link State Advertisement
* generated by the root node's GlobalRouter. These interfaces are used to
* forward packets off of the root's network down those links. As other
* vertices are discovered which are further away from the root, they will
* be accessible down one of the paths begun by a Global Router Link Record.
*
* To forward packets to these hosts or networks, the root node must begin
* the forwarding process by sending the packets to the interface of that
* first hop. This means that the first hop address and interface ID must
* be the same for all downstream SPFVertices. We call this "inheriting"
* the interface and next hop.
*
* In this method, we are letting the root node know which of its local
* interfaces it should use to get a packet to the network or host represented
* by "this" SPFVertex.
*
* @see GlobalRouter
* @see GlobalRouterLSA
* @see GlobalRouterLinkRecord
* @param id The interface index to use when forwarding packets to the host or
* network represented by "this" SPFVertex.
*/
void SetOutgoingInterfaceId (uint32_t id);
/**
* @brief Get the IP address that should be used to begin forwarding packets
* from the root SPFVertex to "this" SPFVertex.
* @internal
*
* Each router node in the simulation is associated with an SPFVertex object.
* When calculating routes, each of these routers is, in turn, chosen as the
* "root" of the calculation and routes to all of the other routers are
* eventually saved in the routing tables of each of the chosen nodes.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set. The "this" SPFVertex is the vertex that
* represents the host or network to which a route is being calculated from
* the root. The IP address that we're asking for is the address on the
* remote side of a link off of the root node that should be used as the
* destination for packets along the path to "this" vertex.
*
* When initializing the root SPFVertex, the IP address used when forwarding
* packets is determined by examining the Global Router Link Records of the
* Link State Advertisement generated by the root node's GlobalRouter. This
* address is used to forward packets off of the root's network down those
* links. As other vertices / nodes are discovered which are further away
* from the root, they will be accessible down one of the paths via a link
* described by one of these Global Router Link Records.
*
* To forward packets to these hosts or networks, the root node must begin
* the forwarding process by sending the packets to a first hop router down
* an interface. This means that the first hop address and interface ID must
* be the same for all downstream SPFVertices. We call this "inheriting"
* the interface and next hop.
*
* In this method, the root node is asking, "which router should I send a
* packet to in order to get that packet to the network or host represented
* by 'this' SPFVertex."
*
* @see GlobalRouter
* @see GlobalRouterLSA
* @see GlobalRouterLinkRecord
* @returns The IP address to use when forwarding packets to the host
* or network represented by "this" SPFVertex.
*/
Ipv4Address GetNextHop (void) const;
/**
* @brief Set the IP address that should be used to begin forwarding packets
* from the root SPFVertex to "this" SPFVertex.
* @internal
*
* Each router node in the simulation is associated with an SPFVertex object.
* When calculating routes, each of these routers is, in turn, chosen as the
* "root" of the calculation and routes to all of the other routers are
* eventually saved in the routing tables of each of the chosen nodes.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set. The "this" SPFVertex is the vertex that
* represents the host or network to which a route is being calculated from
* the root. The IP address that we're asking for is the address on the
* remote side of a link off of the root node that should be used as the
* destination for packets along the path to "this" vertex.
*
* When initializing the root SPFVertex, the IP address used when forwarding
* packets is determined by examining the Global Router Link Records of the
* Link State Advertisement generated by the root node's GlobalRouter. This
* address is used to forward packets off of the root's network down those
* links. As other vertices / nodes are discovered which are further away
* from the root, they will be accessible down one of the paths via a link
* described by one of these Global Router Link Records.
*
* To forward packets to these hosts or networks, the root node must begin
* the forwarding process by sending the packets to a first hop router down
* an interface. This means that the first hop address and interface ID must
* be the same for all downstream SPFVertices. We call this "inheriting"
* the interface and next hop.
*
* In this method we are telling the root node which router it should send
* should I send a packet to in order to get that packet to the network or
* host represented by 'this' SPFVertex."
*
* @see GlobalRouter
* @see GlobalRouterLSA
* @see GlobalRouterLinkRecord
* @param nextHop The IP address to use when forwarding packets to the host
* or network represented by "this" SPFVertex.
*/
void SetNextHop (Ipv4Address nextHop);
/**
* @brief Get a pointer to the SPFVector that is the parent of "this"
* SPFVertex.
* @internal
*
* Each router node in the simulation is associated with an SPFVertex object.
* When calculating routes, each of these routers is, in turn, chosen as the
* "root" of the calculation and routes to all of the other routers are
* eventually saved in the routing tables of each of the chosen nodes.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set and is the root of the SPF tree.
*
* This method returns a pointer to the parent node of "this" SPFVertex
* (both of which reside in that SPF tree).
*
* @returns A pointer to the SPFVertex that is the parent of "this" SPFVertex
* in the SPF tree.
*/
SPFVertex* GetParent (void) const;
/**
* @brief Set the pointer to the SPFVector that is the parent of "this"
* SPFVertex.
* @internal
*
* Each router node in the simulation is associated with an SPFVertex object.
* When calculating routes, each of these routers is, in turn, chosen as the
* "root" of the calculation and routes to all of the other routers are
* eventually saved in the routing tables of each of the chosen nodes.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set and is the root of the SPF tree.
*
* This method sets the parent pointer of "this" SPFVertex (both of which
* reside in that SPF tree).
*
* @param parent A pointer to the SPFVertex that is the parent of "this"
* SPFVertex* in the SPF tree.
*/
void SetParent (SPFVertex* parent);
/**
* @brief Get the number of children of "this" SPFVertex.
* @internal
*
* Each router node in the simulation is associated with an SPFVertex object.
* When calculating routes, each of these routers is, in turn, chosen as the
* "root" of the calculation and routes to all of the other routers are
* eventually saved in the routing tables of each of the chosen nodes.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set and is the root of the SPF tree. Each vertex
* in the SPF tree can have a number of children that represent host or
* network routes available via that vertex.
*
* This method returns the number of children of "this" SPFVertex (which
* reside in the SPF tree).
*
* @returns The number of children of "this" SPFVertex (which reside in the
* SPF tree).
*/
uint32_t GetNChildren (void) const;
/**
* @brief Get a borrowed SPFVertex pointer to the specified child of "this"
* SPFVertex.
* @internal
*
* Each router node in the simulation is associated with an SPFVertex object.
* When calculating routes, each of these routers is, in turn, chosen as the
* "root" of the calculation and routes to all of the other routers are
* eventually saved in the routing tables of each of the chosen nodes.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set and is the root of the SPF tree. Each vertex
* in the SPF tree can have a number of children that represent host or
* network routes available via that vertex.
*
* This method the number of children of "this" SPFVertex (which reside in
* the SPF tree.
*
* @see SPFVertex::GetNChildren
* @param n The index (from 0 to the number of children minus 1) of the
* child SPFVertex to return.
* @warning The pointer returned by GetChild () is a borrowed pointer. You
* do not have any ownership of the underlying object and must not delete
* that object.
* @returns A pointer to the specified child SPFVertex (which resides in the
* SPF tree).
*/
SPFVertex* GetChild (uint32_t n) const;
/**
* @brief Get a borrowed SPFVertex pointer to the specified child of "this"
* SPFVertex.
* @internal
*
* Each router node in the simulation is associated with an SPFVertex object.
* When calculating routes, each of these routers is, in turn, chosen as the
* "root" of the calculation and routes to all of the other routers are
* eventually saved in the routing tables of each of the chosen nodes.
*
* The "Root" vertex is then the SPFVertex representing the router that is
* having its routing tables set and is the root of the SPF tree. Each vertex
* in the SPF tree can have a number of children that represent host or
* network routes available via that vertex.
*
* This method the number of children of "this" SPFVertex (which reside in
* the SPF tree.
*
* @see SPFVertex::GetNChildren
* @warning Ownership of the pointer added to the children of "this"
* SPFVertex is transferred to the "this" SPFVertex. You must not delete the
* (now) child SPFVertex after calling this method.
* @param child A pointer to the SPFVertex (which resides in the SPF tree) to
* be added to the list of children of "this" SPFVertex.
* @returns The number of children of "this" SPFVertex after the addition of
* the new child.
*/
uint32_t AddChild (SPFVertex* child);
private:
VertexType m_vertexType;
Ipv4Address m_vertexId;
GlobalRouterLSA* m_lsa;
uint32_t m_distanceFromRoot;
uint32_t m_rootOif;
Ipv4Address m_nextHop;
SPFVertex* m_parent;
typedef std::list<SPFVertex*> ListOfSPFVertex_t;
ListOfSPFVertex_t m_children;
/**
* @brief The SPFVertex copy construction is disallowed. There's no need for
* it and a compiler provided shallow copy would be wrong.
*/
SPFVertex (SPFVertex& v);
/**
* @brief The SPFVertex copy assignment operator is disallowed. There's no
* need for it and a compiler provided shallow copy would be wrong.
*/
SPFVertex& operator= (SPFVertex& v);
};
/**
* @brief The Link State DataBase (LSDB) of the Global Route Manager.
*
* Each node in the simulation participating in global routing has a
* GlobalRouter interface. The primary job of this interface is to export
* Global Router Link State Advertisements (LSAs). These advertisements in
* turn contain a number of Global Router Link Records that describe the
* point to point links from the underlying node to other nodes (that will
* also export their own LSAs.
*
* This class implements a searchable database of LSAs gathered from every
* router in the simulation.
*/
class GlobalRouteManagerLSDB
{
public:
/**
* @brief Construct an empty Global Router Manager Link State Database.
* @internal
*
* The database map composing the Link State Database is initialized in
* this constructor.
*/
GlobalRouteManagerLSDB ();
/**
* @brief Destroy an empty Global Router Manager Link State Database.
* @internal
*
* The database map is walked and all of the Link State Advertisements stored
* in the database are freed; then the database map itself is clear ()ed to
* release any remaining resources.
*/
~GlobalRouteManagerLSDB ();
/**
* @brief Insert an IP address / Link State Advertisement pair into the Link
* State Database.
* @internal
*
* The IPV4 address and the GlobalRouterLSA given as parameters are converted
* to an STL pair and are inserted into the database map.
*
* @see GlobalRouterLSA
* @see Ipv4Address
* @param addr The IP address associated with the LSA. Typically the Router
* ID.
* @param lsa A pointer to the Link State Advertisement for the router.
*/
void Insert(Ipv4Address addr, GlobalRouterLSA* lsa);
/**
* @brief Look up the Link State Advertisement associated with the given
* IP Address.
* @internal
*
* The database map is searched for the given IPV4 address and corresponding
* GlobalRouterLSA is returned.
*
* @see GlobalRouterLSA
* @see Ipv4Address
* @param addr The IP address associated with the LSA. Typically the Router
* ID.
* @returns A pointer to the Link State Advertisement for the router specified
* by the IP address addr.
*/
GlobalRouterLSA* GetLSA (Ipv4Address addr) const;
/**
* @brief Set all LSA flags to an initialized state, for SPF computation
* @internal
*
* This function walks the database and resets the status flags of all of the
* contained Link State Advertisements to LSA_SPF_NOT_EXPLORED. This is done
* prior to each SPF calculation to reset the state of the SPFVertex structures
* that will reference the LSAs during the calculation.
*
* @see GlobalRouterLSA
* @see SPFVertex
*/
void Initialize ();
private:
typedef std::map<Ipv4Address, GlobalRouterLSA*> LSDBMap_t;
typedef std::pair<Ipv4Address, GlobalRouterLSA*> LSDBPair_t;
LSDBMap_t m_database;
/**
* @brief GlobalRouteManagerLSDB copy construction is disallowed. There's no
* need for it and a compiler provided shallow copy would be wrong.
*/
GlobalRouteManagerLSDB (GlobalRouteManagerLSDB& lsdb);
/**
* @brief The SPFVertex copy assignment operator is disallowed. There's no
* need for it and a compiler provided shallow copy would be wrong.
*/
GlobalRouteManagerLSDB& operator= (GlobalRouteManagerLSDB& lsdb);
};
/**
* @brief A global router implementation.
*
* This singleton object can query interface each node in the system
* for a GlobalRouter interface. For those nodes, it fetches one or
* more Link State Advertisements and stores them in a local database.
* Then, it can compute shortest paths on a per-node basis to all routers,
* and finally configure each of the node's forwarding tables.
*
* The design is guided by OSPFv2 RFC 2328 section 16.1.1 and quagga ospfd.
*/
class GlobalRouteManagerImpl
{
public:
GlobalRouteManagerImpl ();
virtual ~GlobalRouteManagerImpl ();
/**
* @brief Select which nodes in the system are to be router nodes and
* aggregate the appropriate interfaces onto those nodes.
* @internal
*
*/
virtual void SelectRouterNodes ();
/**
* @brief Build the routing database by gathering Link State Advertisements
* from each node exporting a GlobalRouter interface.
* @internal
*/
virtual void BuildGlobalRoutingDatabase ();
/**
* @brief Compute routes using a Dijkstra SPF computation and populate
* per-node forwarding tables
* @internal
*/
virtual void InitializeRoutes ();
/**
* @brief Debugging routine; allow client code to supply a pre-built LSDB
* @internal
*/
void DebugUseLsdb (GlobalRouteManagerLSDB*);
/**
* @brief Debugging routine; call the core SPF from the unit tests
* @internal
*/
void DebugSPFCalculate (Ipv4Address root);
private:
/**
* @brief GlobalRouteManagerImpl copy construction is disallowed.
* There's no need for it and a compiler provided shallow copy would be
* wrong.
*/
GlobalRouteManagerImpl (GlobalRouteManagerImpl& srmi);
/**
* @brief Global Route Manager Implementation assignment operator is
* disallowed. There's no need for it and a compiler provided shallow copy
* would be hopelessly wrong.
*/
GlobalRouteManagerImpl& operator= (GlobalRouteManagerImpl& srmi);
SPFVertex* m_spfroot;
GlobalRouteManagerLSDB* m_lsdb;
void SPFCalculate (Ipv4Address root);
void SPFNext (SPFVertex*, CandidateQueue&);
int SPFNexthopCalculation (SPFVertex* v, SPFVertex* w,
GlobalRouterLinkRecord* l, uint32_t distance);
void SPFVertexAddParent (SPFVertex* v);
GlobalRouterLinkRecord* SPFGetNextLink (SPFVertex* v, SPFVertex* w,
GlobalRouterLinkRecord* prev_link);
void SPFIntraAddRouter (SPFVertex* v);
uint32_t FindOutgoingInterfaceId (Ipv4Address a);
};
} // namespace ns3
#endif /* GLOBAL_ROUTE_MANAGER_IMPL_H */

View File

@@ -0,0 +1,68 @@
/* -*- 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
*/
#include "ns3/assert.h"
#include "ns3/debug.h"
#include "ns3/simulation-singleton.h"
#include "global-route-manager.h"
#include "global-route-manager-impl.h"
namespace ns3 {
// ---------------------------------------------------------------------------
//
// GlobalRouteManager Implementation
//
// ---------------------------------------------------------------------------
void
GlobalRouteManager::PopulateRoutingTables ()
{
SelectRouterNodes ();
BuildGlobalRoutingDatabase ();
InitializeRoutes ();
}
void
GlobalRouteManager::SelectRouterNodes ()
{
SimulationSingleton<GlobalRouteManagerImpl>::Get ()->
SelectRouterNodes ();
}
void
GlobalRouteManager::BuildGlobalRoutingDatabase ()
{
SimulationSingleton<GlobalRouteManagerImpl>::Get ()->
BuildGlobalRoutingDatabase ();
}
void
GlobalRouteManager::InitializeRoutes ()
{
SimulationSingleton<GlobalRouteManagerImpl>::Get ()->
InitializeRoutes ();
}
uint32_t
GlobalRouteManager::AllocateRouterId ()
{
static uint32_t routerId = 0;
return routerId++;
}
} // namespace ns3

View File

@@ -0,0 +1,93 @@
/* -*- 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
*/
#ifndef GLOBAL_ROUTE_MANAGER_H
#define GLOBAL_ROUTE_MANAGER_H
namespace ns3 {
/**
* @brief A global global router
*
* This singleton object can query interface each node in the system
* for a GlobalRouter interface. For those nodes, it fetches one or
* more Link State Advertisements and stores them in a local database.
* Then, it can compute shortest paths on a per-node basis to all routers,
* and finally configure each of the node's forwarding tables.
*
* The design is guided by OSPFv2 RFC 2328 section 16.1.1 and quagga ospfd.
*/
class GlobalRouteManager
{
public:
/**
* @brief Build a routing database and initialize the routing tables of
* the nodes in the simulation.
*
* All this function does is call BuildGlobalRoutingDatabase () and
* InitializeRoutes ().
*
* @see BuildGlobalRoutingDatabase ();
* @see InitializeRoutes ();
*/
static void PopulateRoutingTables ();
/**
* @brief Allocate a 32-bit router ID from monotonically increasing counter.
*/
static uint32_t AllocateRouterId ();
private:
/**
* @brief Select which nodes in the system are to be router nodes and
* aggregate the appropriate interfaces onto those nodes.
* @internal
*
*/
static void SelectRouterNodes ();
/**
* @brief Build the routing database by gathering Link State Advertisements
* from each node exporting a GlobalRouter interface.
* @internal
*
*/
static void BuildGlobalRoutingDatabase ();
/**
* @brief Compute routes using a Dijkstra SPF computation and populate
* per-node forwarding tables
* @internal
*/
static void InitializeRoutes ();
/**
* @brief Global Route Manager copy construction is disallowed. There's no
* need for it and a compiler provided shallow copy would be wrong.
*
*/
GlobalRouteManager (GlobalRouteManager& srm);
/**
* @brief Global Router copy assignment operator is disallowed. There's no
* need for it and a compiler provided shallow copy would be wrong.
*/
GlobalRouteManager& operator= (GlobalRouteManager& srm);
};
} // namespace ns3
#endif /* GLOBAL_ROUTE_MANAGER_H */

View File

@@ -0,0 +1,588 @@
/* -*- 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
*/
#include "ns3/debug.h"
#include "ns3/assert.h"
#include "ns3/channel.h"
#include "ns3/net-device.h"
#include "ns3/internet-node.h"
#include "ns3/ipv4.h"
#include "global-router-interface.h"
NS_DEBUG_COMPONENT_DEFINE ("GlobalRouter");
namespace ns3 {
// ---------------------------------------------------------------------------
//
// GlobalRouterLinkRecord Implementation
//
// ---------------------------------------------------------------------------
GlobalRouterLinkRecord::GlobalRouterLinkRecord ()
:
m_linkId ("0.0.0.0"),
m_linkData ("0.0.0.0"),
m_linkType (Unknown),
m_metric (0)
{
NS_DEBUG("GlobalRouterLinkRecord::GlobalRouterLinkRecord ()");
}
GlobalRouterLinkRecord::GlobalRouterLinkRecord (
LinkType linkType,
Ipv4Address linkId,
Ipv4Address linkData,
uint32_t metric)
:
m_linkId (linkId),
m_linkData (linkData),
m_linkType (linkType),
m_metric (metric)
{
NS_DEBUG("GlobalRouterLinkRecord::GlobalRouterLinkRecord (" <<
linkType << ", " << linkId << ", " << linkData << ", " << metric << ")");
}
GlobalRouterLinkRecord::~GlobalRouterLinkRecord ()
{
NS_DEBUG("GlobalRouterLinkRecord::~GlobalRouterLinkRecord ()");
}
Ipv4Address
GlobalRouterLinkRecord::GetLinkId (void) const
{
NS_DEBUG("GlobalRouterLinkRecord::GetLinkId ()");
return m_linkId;
}
void
GlobalRouterLinkRecord::SetLinkId (Ipv4Address addr)
{
NS_DEBUG("GlobalRouterLinkRecord::SetLinkId ()");
m_linkId = addr;
}
Ipv4Address
GlobalRouterLinkRecord::GetLinkData (void) const
{
NS_DEBUG("GlobalRouterLinkRecord::GetLinkData ()");
return m_linkData;
}
void
GlobalRouterLinkRecord::SetLinkData (Ipv4Address addr)
{
NS_DEBUG("GlobalRouterLinkRecord::SetLinkData ()");
m_linkData = addr;
}
GlobalRouterLinkRecord::LinkType
GlobalRouterLinkRecord::GetLinkType (void) const
{
NS_DEBUG("GlobalRouterLinkRecord::GetLinkType ()");
return m_linkType;
}
void
GlobalRouterLinkRecord::SetLinkType (
GlobalRouterLinkRecord::LinkType linkType)
{
NS_DEBUG("GlobalRouterLinkRecord::SetLinkType ()");
m_linkType = linkType;
}
uint32_t
GlobalRouterLinkRecord::GetMetric (void) const
{
NS_DEBUG("GlobalRouterLinkRecord::GetMetric ()");
return m_metric;
}
void
GlobalRouterLinkRecord::SetMetric (uint32_t metric)
{
NS_DEBUG("GlobalRouterLinkRecord::SetMetric ()");
m_metric = metric;
}
// ---------------------------------------------------------------------------
//
// GlobalRouterLSA Implementation
//
// ---------------------------------------------------------------------------
GlobalRouterLSA::GlobalRouterLSA()
:
m_linkStateId("0.0.0.0"),
m_advertisingRtr("0.0.0.0"),
m_linkRecords(),
m_status(GlobalRouterLSA::LSA_SPF_NOT_EXPLORED)
{
NS_DEBUG("GlobalRouterLSA::GlobalRouterLSA ()");
}
GlobalRouterLSA::GlobalRouterLSA (
GlobalRouterLSA::SPFStatus status,
Ipv4Address linkStateId,
Ipv4Address advertisingRtr)
:
m_linkStateId(linkStateId),
m_advertisingRtr(advertisingRtr),
m_linkRecords(),
m_status(status)
{
NS_DEBUG("GlobalRouterLSA::GlobalRouterLSA (" << status << ", " <<
linkStateId << ", " << advertisingRtr << ")");
}
GlobalRouterLSA::GlobalRouterLSA (GlobalRouterLSA& lsa)
: m_linkStateId(lsa.m_linkStateId), m_advertisingRtr(lsa.m_advertisingRtr),
m_status(lsa.m_status)
{
NS_ASSERT_MSG(IsEmpty(),
"GlobalRouterLSA::GlobalRouterLSA (): Non-empty LSA in constructor");
CopyLinkRecords (lsa);
}
GlobalRouterLSA&
GlobalRouterLSA::operator= (const GlobalRouterLSA& lsa)
{
m_linkStateId = lsa.m_linkStateId;
m_advertisingRtr = lsa.m_advertisingRtr;
m_status = lsa.m_status;
ClearLinkRecords ();
CopyLinkRecords (lsa);
return *this;
}
void
GlobalRouterLSA::CopyLinkRecords (const GlobalRouterLSA& lsa)
{
for (ListOfLinkRecords_t::const_iterator i = lsa.m_linkRecords.begin ();
i != lsa.m_linkRecords.end ();
i++)
{
GlobalRouterLinkRecord *pSrc = *i;
GlobalRouterLinkRecord *pDst = new GlobalRouterLinkRecord;
pDst->SetLinkType (pSrc->GetLinkType ());
pDst->SetLinkId (pSrc->GetLinkId ());
pDst->SetLinkData (pSrc->GetLinkData ());
m_linkRecords.push_back(pDst);
pDst = 0;
}
}
GlobalRouterLSA::~GlobalRouterLSA()
{
NS_DEBUG("GlobalRouterLSA::~GlobalRouterLSA ()");
ClearLinkRecords ();
}
void
GlobalRouterLSA::ClearLinkRecords(void)
{
for ( ListOfLinkRecords_t::iterator i = m_linkRecords.begin ();
i != m_linkRecords.end ();
i++)
{
NS_DEBUG("GlobalRouterLSA::ClearLinkRecords (): free link record");
GlobalRouterLinkRecord *p = *i;
delete p;
p = 0;
*i = 0;
}
NS_DEBUG("GlobalRouterLSA::ClearLinkRecords(): clear list");
m_linkRecords.clear();
}
uint32_t
GlobalRouterLSA::AddLinkRecord (GlobalRouterLinkRecord* lr)
{
m_linkRecords.push_back (lr);
return m_linkRecords.size ();
}
uint32_t
GlobalRouterLSA::GetNLinkRecords (void) const
{
return m_linkRecords.size ();
}
GlobalRouterLinkRecord *
GlobalRouterLSA::GetLinkRecord (uint32_t n) const
{
uint32_t j = 0;
for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin ();
i != m_linkRecords.end ();
i++, j++)
{
if (j == n)
{
return *i;
}
}
NS_ASSERT_MSG(false, "GlobalRouterLSA::GetLinkRecord (): invalid index");
return 0;
}
bool
GlobalRouterLSA::IsEmpty (void) const
{
return m_linkRecords.size () == 0;
}
Ipv4Address
GlobalRouterLSA::GetLinkStateId (void) const
{
return m_linkStateId;
}
void
GlobalRouterLSA::SetLinkStateId (Ipv4Address addr)
{
m_linkStateId = addr;
}
Ipv4Address
GlobalRouterLSA::GetAdvertisingRouter (void) const
{
return m_advertisingRtr;
}
void
GlobalRouterLSA::SetAdvertisingRouter (Ipv4Address addr)
{
m_advertisingRtr = addr;
}
GlobalRouterLSA::SPFStatus
GlobalRouterLSA::GetStatus (void) const
{
return m_status;
}
void
GlobalRouterLSA::SetStatus (GlobalRouterLSA::SPFStatus status)
{
m_status = status;
}
void
GlobalRouterLSA::Print (std::ostream &os) const
{
os << "m_linkStateId = " << m_linkStateId << std::endl <<
"m_advertisingRtr = " << m_advertisingRtr << std::endl;
for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin ();
i != m_linkRecords.end ();
i++)
{
GlobalRouterLinkRecord *p = *i;
os << "----------" << std::endl;
os << "m_linkId = " << p->GetLinkId () << std::endl;
os << "m_linkData = " << p->GetLinkData () << std::endl;
}
}
std::ostream& operator<< (std::ostream& os, GlobalRouterLSA& lsa)
{
lsa.Print (os);
return os;
}
// ---------------------------------------------------------------------------
//
// GlobalRouter Implementation
//
// ---------------------------------------------------------------------------
const InterfaceId GlobalRouter::iid =
MakeInterfaceId ("GlobalRouter", Object::iid);
GlobalRouter::GlobalRouter (Ptr<Node> node)
: m_node(node), m_LSAs()
{
NS_DEBUG("GlobalRouter::GlobalRouter ()");
SetInterfaceId (GlobalRouter::iid);
m_routerId.Set(GlobalRouteManager::AllocateRouterId ());
}
GlobalRouter::~GlobalRouter ()
{
NS_DEBUG("GlobalRouter::~GlobalRouter ()");
ClearLSAs();
}
void
GlobalRouter::ClearLSAs ()
{
NS_DEBUG("GlobalRouter::ClearLSAs ()");
for ( ListOfLSAs_t::iterator i = m_LSAs.begin ();
i != m_LSAs.end ();
i++)
{
NS_DEBUG("GlobalRouter::ClearLSAs (): free LSA");
GlobalRouterLSA *p = *i;
delete p;
p = 0;
*i = 0;
}
NS_DEBUG("GlobalRouter::ClearLSAs (): clear list");
m_LSAs.clear();
}
Ipv4Address
GlobalRouter::GetRouterId (void) const
{
return m_routerId;
}
//
// Go out and discover any adjacent routers and build the Link State
// Advertisements that reflect them and their associated networks.
//
uint32_t
GlobalRouter::DiscoverLSAs (void)
{
NS_DEBUG("GlobalRouter::DiscoverLSAs ()");
NS_ASSERT_MSG(m_node,
"GlobalRouter::DiscoverLSAs (): <Node> interface not set");
ClearLSAs ();
//
// We're aggregated to a node. We need to ask the node for a pointer to its
// Ipv4 interface. This is where the information regarding the attached
// interfaces lives.
//
Ptr<Ipv4> ipv4Local = m_node->QueryInterface<Ipv4> (Ipv4::iid);
NS_ASSERT_MSG(ipv4Local,
"GlobalRouter::DiscoverLSAs (): QI for <Ipv4> interface failed");
//
// We are, for now at least, only going to report RouterLSAs in this method.
// What this means is that there is going to be one advertisement with some
// number of link records. This means that GetNumLSAs will actually always
// return exactly one.
//
GlobalRouterLSA *pLSA = new GlobalRouterLSA;
pLSA->SetLinkStateId (m_routerId);
pLSA->SetAdvertisingRouter (m_routerId);
pLSA->SetStatus (GlobalRouterLSA::LSA_SPF_NOT_EXPLORED);
//
// We need to ask the node for the number of net devices attached. This isn't
// necessarily equal to the number of links to adjacent nodes (other routers)
// as the number of devices may include those for stub networks (e.g.,
// ethernets, etc.). So we have to walk through the list of net devices and
// pay attention to those that are directly connected to another router through
// a point-to-point channel.
//
uint32_t numDevices = m_node->GetNDevices();
NS_DEBUG("GlobalRouter::DiscoverLSAs (): numDevices = " << numDevices);
//
// Loop through the devices looking for those connected to a point-to-point
// channel.
//
for (uint32_t i = 0; i < numDevices; ++i)
{
Ptr<NetDevice> ndLocal = m_node->GetDevice(i);
if (!ndLocal->IsPointToPoint ())
{
NS_DEBUG("GlobalRouter::DiscoverLSAs (): non-point-to-point device");
continue;
}
NS_DEBUG("GlobalRouter::DiscoverLSAs (): Point-to-point device");
//
// Now, we have to find the Ipv4 interface whose netdevice is the one we
// just found. This is still the IP on the local side of the channel. There
// is a function to do this used down in the guts of the stack, but it's not
// exported so we had to whip up an equivalent.
//
uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, ndLocal);
//
// Now that we have the Ipv4 interface index, we can get the address and mask
// we need.
//
Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
NS_DEBUG("Working with local address " << addrLocal);
//
// 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
// router (to use OSPF lingo) is running.
//
Ptr<Channel> ch = ndLocal->GetChannel();
Ptr<NetDevice> ndRemote = GetAdjacent(ndLocal, ch);
//
// The adjacent net device is aggregated to a node. We need to ask that net
// device for its node, then ask that node for its Ipv4 interface.
//
Ptr<Node> nodeRemote = ndRemote->GetNode();
Ptr<Ipv4> ipv4Remote = nodeRemote->QueryInterface<Ipv4> (Ipv4::iid);
NS_ASSERT_MSG(ipv4Remote,
"GlobalRouter::DiscoverLSAs (): QI for remote <Ipv4> failed");
//
// Per the OSPF spec, we're going to need the remote router ID, so we might as
// well get it now.
//
Ptr<GlobalRouter> srRemote =
nodeRemote->QueryInterface<GlobalRouter> (GlobalRouter::iid);
NS_ASSERT_MSG(srRemote,
"GlobalRouter::DiscoverLSAs (): QI for remote <GlobalRouter> failed");
Ipv4Address rtrIdRemote = srRemote->GetRouterId();
NS_DEBUG("Working with remote router " << rtrIdRemote);
//
// Now, just like we did above, we need to get the IP interface index for the
// net device on the other end of the point-to-point channel.
//
uint32_t ifIndexRemote = FindIfIndexForDevice(nodeRemote, ndRemote);
//
// Now that we have the Ipv4 interface, we can get the (remote) address and
// mask we need.
//
Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote);
Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote);
NS_DEBUG("Working with remote address " << addrRemote);
//
// Now we can fill out the link records for this link. There are always two
// link records; the first is a point-to-point record describing the link and
// the second is a stub network record with the network number.
//
GlobalRouterLinkRecord *plr = new GlobalRouterLinkRecord;
plr->SetLinkType (GlobalRouterLinkRecord::PointToPoint);
plr->SetLinkId (rtrIdRemote);
plr->SetLinkData (addrLocal);
pLSA->AddLinkRecord(plr);
plr = 0;
plr = new GlobalRouterLinkRecord;
plr->SetLinkType (GlobalRouterLinkRecord::StubNetwork);
plr->SetLinkId (addrRemote);
plr->SetLinkData (Ipv4Address(maskRemote.GetHostOrder())); // Frown
pLSA->AddLinkRecord(plr);
plr = 0;
}
//
// The LSA goes on a list of LSAs in case we want to begin exporting other
// kinds of advertisements (than Router LSAs).
m_LSAs.push_back (pLSA);
NS_DEBUG(*pLSA);
return m_LSAs.size ();
}
uint32_t
GlobalRouter::GetNumLSAs (void) const
{
NS_DEBUG("GlobalRouter::GetNumLSAs ()");
return m_LSAs.size ();
}
//
// Get the nth link state advertisement from this router.
//
bool
GlobalRouter::GetLSA (uint32_t n, GlobalRouterLSA &lsa) const
{
NS_ASSERT_MSG(lsa.IsEmpty(), "GlobalRouter::GetLSA (): Must pass empty LSA");
//
// All of the work was done in GetNumLSAs. All we have to do here is to
// walk the list of link state advertisements created there and return the
// one the client is interested in.
//
ListOfLSAs_t::const_iterator i = m_LSAs.begin ();
uint32_t j = 0;
for (; i != m_LSAs.end (); i++, j++)
{
if (j == n)
{
GlobalRouterLSA *p = *i;
lsa = *p;
return true;
}
}
return false;
}
//
// Link through the given channel and find the net device that's on the
// other end. This only makes sense with a point-to-point channel.
//
Ptr<NetDevice>
GlobalRouter::GetAdjacent(Ptr<NetDevice> nd, Ptr<Channel> ch) const
{
uint32_t nDevices = ch->GetNDevices();
NS_ASSERT_MSG(nDevices == 2,
"GlobalRouter::GetAdjacent (): Channel with other than two devices");
//
// This is a point to point channel with two endpoints. Get both of them.
//
Ptr<NetDevice> nd1 = ch->GetDevice(0);
Ptr<NetDevice> nd2 = ch->GetDevice(1);
//
// One of the endpoints is going to be "us" -- that is the net device attached
// to the node on which we're running -- i.e., "nd". The other endpoint (the
// one to which we are connected via the channel) is the adjacent router.
//
if (nd1 == nd)
{
return nd2;
}
else if (nd2 == nd)
{
return nd1;
}
else
{
NS_ASSERT_MSG(false,
"GlobalRouter::GetAdjacent (): Wrong or confused channel?");
return 0;
}
}
//
// Given a node and a net device, find the IPV4 interface index that
// corresponds to that net device.
//
uint32_t
GlobalRouter::FindIfIndexForDevice(Ptr<Node> node, Ptr<NetDevice> nd) const
{
Ptr<Ipv4> ipv4 = node->QueryInterface<Ipv4> (Ipv4::iid);
NS_ASSERT_MSG(ipv4, "QI for <Ipv4> interface failed");
for (uint32_t i = 0; i < ipv4->GetNInterfaces(); ++i )
{
if (ipv4->GetNetDevice(i) == nd)
{
return i;
}
}
NS_ASSERT_MSG(0, "Cannot find interface for device");
return 0;
}
} // namespace ns3

View File

@@ -0,0 +1,580 @@
/* -*- 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
*/
#ifndef GLOBAL_ROUTER_INTERFACE_H
#define GLOBAL_ROUTER_INTERFACE_H
#include <stdint.h>
#include <list>
#include "ns3/object.h"
#include "ns3/ptr.h"
#include "ns3/node.h"
#include "ns3/channel.h"
#include "ns3/ipv4-address.h"
#include "ns3/global-route-manager.h"
namespace ns3 {
/**
* @brief A single link record for a link state advertisement.
*
* The GlobalRouterLinkRecord is modeled after the OSPF link record field of
* a Link State Advertisement. Right now we will only see two types of link
* records corresponding to a stub network and a point-to-point link (channel).
*/
class GlobalRouterLinkRecord
{
public:
/**
* @enum LinkType
* @brief Enumeration of the possible types of Global Router Link Records.
*
* These values are defined in the OSPF spec. We currently only use
* PointToPoint and StubNetwork types.
*/
enum LinkType {
Unknown = 0, /**< Uninitialized Link Record */
PointToPoint, /**< Record representing a point to point channel */
TransitNetwork, /**< Unused -- for future OSPF compatibility */
StubNetwork, /**< Record represents a leaf node network */
VirtualLink /**< Unused -- for future OSPF compatibility */
};
/**
* @brief Construct an empty ("uninitialized") Global Router Link Record.
*
* The Link ID and Link Data Ipv4 addresses are set to "0.0.0.0";
* The Link Type is set to Unknown;
* The metric is set to 0.
*/
GlobalRouterLinkRecord ();
/**
* Construct an initialized Global Router Link Record.
*
* @param linkType The type of link record to construct.
* @param linkId The link ID for the record.
* @param linkData The link data field for the record.
* @param metric The metric field for the record.
* @see LinkType
* @see SetLinkId
* @see SetLinkData
*/
GlobalRouterLinkRecord (
LinkType linkType,
Ipv4Address linkId,
Ipv4Address linkData,
uint32_t metric);
/**
* @brief Destroy a Global Router Link Record.
*
* Currently does nothing. Here as a placeholder only.
*/
~GlobalRouterLinkRecord ();
/**
* Get the Link ID field of the Global Router Link Record.
*
* For an OSPF type 1 link (PointToPoint) the Link ID will be the Router ID
* of the neighboring router.
*
* For an OSPF type 3 link (StubNetwork), the Link ID will be the adjacent
* neighbor's IP address
*
* @returns The Ipv4Address corresponding to the Link ID field of the record.
*/
Ipv4Address GetLinkId(void) const;
/**
* @brief Set the Link ID field of the Global Router Link Record.
*
* For an OSPF type 1 link (PointToPoint) the Link ID must be the Router ID
* of the neighboring router.
*
* For an OSPF type 3 link (StubNetwork), the Link ID must be the adjacent
* neighbor's IP address
*
* @param addr An Ipv4Address to store in the Link ID field of the record.
*/
void SetLinkId(Ipv4Address addr);
/**
* @brief Get the Link Data field of the Global Router Link Record.
*
* For an OSPF type 1 link (PointToPoint) the Link Data will be the IP
* address of the node of the local side of the link.
*
* For an OSPF type 3 link (StubNetwork), the Link Data will be the
* network mask
*
* @returns The Ipv4Address corresponding to the Link Data field of the record.
*/
Ipv4Address GetLinkData(void) const;
/**
* @brief Set the Link Data field of the Global Router Link Record.
*
* For an OSPF type 1 link (PointToPoint) the Link Data must be the IP
* address of the node of the local side of the link.
*
* For an OSPF type 3 link (StubNetwork), the Link Data must be set to the
* network mask
*
* @param addr An Ipv4Address to store in the Link Data field of the record.
*/
void SetLinkData(Ipv4Address addr);
/**
* @brief Get the Link Type field of the Global Router Link Record.
*
* The Link Type describes the kind of link a given record represents. The
* values are defined by OSPF.
*
* @see LinkType
* @returns The LinkType of the current Global Router Link Record.
*/
LinkType GetLinkType(void) const;
/**
* @brief Set the Link Type field of the Global Router Link Record.
*
* The Link Type describes the kind of link a given record represents. The
* values are defined by OSPF.
*
* @see LinkType
* @param linkType The new LinkType for the current Global Router Link Record.
*/
void SetLinkType(LinkType linkType);
/**
* @brief Get the Metric Data field of the Global Router Link Record.
*
* The metric is an abstract cost associated with forwarding a packet across
* a link. A sum of metrics must have a well-defined meaning. That is, you
* shouldn't use bandwidth as a metric (how does the sum of the bandwidth of
* two hops relate to the cost of sending a packet); rather you should use
* something like delay.
*
* @returns The metric field of the Global Router Link Record.
*/
uint32_t GetMetric(void) const;
/**
* @brief Set the Metric Data field of the Global Router Link Record.
*
* The metric is an abstract cost associated with forwarding a packet across
* a link. A sum of metrics must have a well-defined meaning. That is, you
* shouldn't use bandwidth as a metric (how does the sum of the bandwidth of
* two hops relate to the cost of sending a packet); rather you should use
* something like delay.
*
* @param metric The new metric for the current Global Router Link Record.
*/
void SetMetric(uint32_t metric);
private:
/**
* m_linkId and m_linkData are defined by OSPF to have different meanings
* depending on the type of link a given link records represents. They work
* together.
*
* For Type 1 link (PointToPoint), set m_linkId to Router ID of
* neighboring router.
*
* For Type 3 link (Stub), set m_linkId to neighbor's IP address
*/
Ipv4Address m_linkId;
/**
* m_linkId and m_linkData are defined by OSPF to have different meanings
* depending on the type of link a given link records represents. They work
* together.
*
* For Type 1 link (PointToPoint), set m_linkData to local IP address
*
* For Type 3 link (Stub), set m_linkData to mask
*/
Ipv4Address m_linkData; // for links to RouterLSA,
/**
* The type of the Global Router Link Record. Defined in the OSPF spec.
* We currently only use PointToPoint and StubNetwork types.
*/
LinkType m_linkType;
/**
* The metric for a given link.
*
* A metric is abstract cost associated with forwarding a packet across a
* link. A sum of metrics must have a well-defined meaning. That is, you
* shouldn't use bandwidth as a metric (how does the sum of the bandwidth
* of two hops relate to the cost of sending a packet); rather you should
* use something like delay.
*/
uint32_t m_metric;
};
/**
* @brief a Link State Advertisement (LSA) for a router, used in global
* routing.
*
* Roughly equivalent to a global incarnation of the OSPF link state header
* combined with a list of Link Records. Since it's global, there's
* no need for age or sequence number. See RFC 2328, Appendix A.
*/
class GlobalRouterLSA
{
public:
/**
* @enum SPFStatus
* @brief Enumeration of the possible values of the status flag in the Router
* Link State Advertisements.
*/
enum SPFStatus {
LSA_SPF_NOT_EXPLORED = 0, /**< New vertex not yet considered */
LSA_SPF_CANDIDATE, /**< Vertex is in the SPF candidate queue */
LSA_SPF_IN_SPFTREE /**< Vertex is in the SPF tree */
};
/**
* @brief Create a blank Global Router Link State Advertisement.
*
* On completion Ipv4Address variables initialized to 0.0.0.0 and the
* list of Link State Records is empty.
*/
GlobalRouterLSA();
/**
* @brief Create an initialized Global Router Link State Advertisement.
*
* On completion the list of Link State Records is empty.
*
* @param status The status to of the new LSA.
* @param linkStateId The Ipv4Address for the link state ID field.
* @param advertisingRtr The Ipv4Address for the advertising router field.
*/
GlobalRouterLSA(SPFStatus status, Ipv4Address linkStateId,
Ipv4Address advertisingRtr);
/**
* @brief Copy constructor for a Global Router Link State Advertisement.
*
* Takes a piece of memory and constructs a semantically identical copy of
* the given LSA.
*
* @param lsa The existing LSA to be used as the source.
*/
GlobalRouterLSA (GlobalRouterLSA& lsa);
/**
* @brief Destroy an existing Global Router Link State Advertisement.
*
* Any Global Router Link Records present in the list are freed.
*/
~GlobalRouterLSA();
/**
* @brief Assignment operator for a Global Router Link State Advertisement.
*
* Takes an existing Global Router Link State Advertisement and overwrites
* it to make a semantically identical copy of a given prototype LSA.
*
* If there are any Global Router Link Records present in the existing
* LSA, they are freed before the assignment happens.
*
* @param lsa The existing LSA to be used as the source.
* @returns Reference to the overwritten LSA.
*/
GlobalRouterLSA& operator= (const GlobalRouterLSA& lsa);
/**
* @brief Copy any Global Router Link Records in a given Global Router Link
* State Advertisement to the current LSA.
*
* Existing Link Records are not deleted -- this is a concatenation of Link
* Records.
*
* @see ClearLinkRecords ()
* @param lsa The LSA to copy the Link Records from.
*/
void CopyLinkRecords (const GlobalRouterLSA& lsa);
/**
* @brief Add a given Global Router Link Record to the LSA.
*
* @param lr The Global Router Link Record to be added.
* @returns The number of link records in the list.
*/
uint32_t AddLinkRecord (GlobalRouterLinkRecord* lr);
/**
* @brief Return the number of Global Router Link Records in the LSA.
*
* @returns The number of link records in the list.
*/
uint32_t GetNLinkRecords (void) const;
/**
* @brief Return a pointer to the specified Global Router Link Record.
*
* @param n The LSA number desired.
* @returns The number of link records in the list.
*/
GlobalRouterLinkRecord* GetLinkRecord (uint32_t n) const;
/**
* @brief Release all of the Global Router Link Records present in the Global
* Router Link State Advertisement and make the list of link records empty.
*/
void ClearLinkRecords(void);
/**
* @brief Check to see if the list of Global Router Link Records present in the
* Global Router Link State Advertisement is empty.
*
* @returns True if the list is empty, false otherwise.
*/
bool IsEmpty(void) const;
/**
* @brief Print the contents of the Global Router Link State Advertisement and
* any Global Router Link Records present in the list. Quite verbose.
*/
void Print (std::ostream &os) const;
/**
* @brief Get the Link State ID as defined by the OSPF spec. We always set it
* to the router ID of the router making the advertisement.
*
* @see RoutingEnvironment::AllocateRouterId ()
* @see GlobalRouter::GetRouterId ()
* @returns The Ipv4Address stored as the link state ID.
*/
Ipv4Address GetLinkStateId (void) const;
/**
* @brief Set the Link State ID is defined by the OSPF spec. We always set it
* to the router ID of the router making the advertisement.
*
* @see RoutingEnvironment::AllocateRouterId ()
* @see GlobalRouter::GetRouterId ()
*/
void SetLinkStateId (Ipv4Address addr);
/**
* @brief Get the Advertising Router as defined by the OSPF spec. We always
* set it to the router ID of the router making the advertisement.
*
* @see RoutingEnvironment::AllocateRouterId ()
* @see GlobalRouter::GetRouterId ()
* @returns The Ipv4Address stored as the advetising router.
*/
Ipv4Address GetAdvertisingRouter (void) const;
/**
* @brief Set the Advertising Router as defined by the OSPF spec. We always
* set it to the router ID of the router making the advertisement.
*
* @see RoutingEnvironment::AllocateRouterId ()
* @see GlobalRouter::GetRouterId ()
*/
void SetAdvertisingRouter (Ipv4Address rtr);
/**
* @brief Get the SPF status of the advertisement.
*
* @see SPFStatus
* @returns The SPFStatus of the LSA.
*/
SPFStatus GetStatus (void) const;
/**
* @brief Set the SPF status of the advertisement
*
* @see SPFStatus
*/
void SetStatus (SPFStatus status);
private:
/**
* The Link State ID is defined by the OSPF spec. We always set it to the
* router ID of the router making the advertisement.
*
* @see RoutingEnvironment::AllocateRouterId ()
* @see GlobalRouter::GetRouterId ()
*/
Ipv4Address m_linkStateId;
/**
* The Advertising Router is defined by the OSPF spec. We always set it to
* the router ID of the router making the advertisement.
*
* @see RoutingEnvironment::AllocateRouterId ()
* @see GlobalRouter::GetRouterId ()
*/
Ipv4Address m_advertisingRtr;
/**
* A convenience typedef to avoid too much writers cramp.
*/
typedef std::list<GlobalRouterLinkRecord*> ListOfLinkRecords_t;
/**
* Each Link State Advertisement contains a number of Link Records that
* describe the kinds of links that are attached to a given node. We
* consider PointToPoint and StubNetwork links.
*
* m_linkRecords is an STL list container to hold the Link Records that have
* been discovered and prepared for the advertisement.
*
* @see GlobalRouter::DiscoverLSAs ()
*/
ListOfLinkRecords_t m_linkRecords;
/**
* This is a tristate flag used internally in the SPF computation to mark
* if an SPFVertex (a data structure representing a vertex in the SPF tree
* -- a router) is new, is a candidate for a shortest path, or is in its
* proper position in the tree.
*/
SPFStatus m_status;
};
std::ostream& operator<< (std::ostream& os, GlobalRouterLSA& lsa);
/**
* @brief An interface aggregated to a node to provide global routing info
*
* An interface aggregated to a node that provides global routing information
* to a global route manager. The presence of the interface indicates that
* the node is a router. The interface is the mechanism by which the router
* advertises its connections to neighboring routers. We're basically
* allowing the route manager to query for link state advertisements.
*/
class GlobalRouter : public Object
{
public:
/**
* @brief The Interface ID of the Global Router interface.
*
* @see Object::QueryInterface ()
*/
static const InterfaceId iid;
/**
* @brief Create a Global Router class and aggregate its interface onto the
* Node provided.
*
* @param node The existing Node onto which this router will be aggregated.
*/
GlobalRouter (Ptr<Node> node);
/**
* @brief Get the Router ID associated with this Global Router.
*
* The Router IDs are allocated in the RoutingEnvironment -- one per Router,
* starting at 0.0.0.1 and incrementing with each instantiation of a router.
*
* @see RoutingEnvironment::AllocateRouterId ()
* @returns The Router ID associated with the Global Router.
*/
Ipv4Address GetRouterId (void) const;
/**
* @brief Walk the connected channels, discover the adjacent routers and build
* the associated number of Global Router Link State Advertisements that
* this router can export.
*
* This is a fairly expensive operation in that every time it is called
* the current list of LSAs is built by walking connected point-to-point
* channels and peeking into adjacent IPV4 stacks to get address information.
* This is done to allow for limited dymanics of the Global Routing
* environment. By that we mean that you can discover new link state
* advertisements after a network topology change by calling DiscoverLSAs
* and then by reading those advertisements.
*
* @see GlobalRouterLSA
* @see GlobalRouter::GetLSA ()
* @returns The number of Global Router Link State Advertisements.
*/
uint32_t DiscoverLSAs (void);
/**
* @brief Get the Number of Global Router Link State Advertisements that this
* router can export.
*
* To get meaningful information you must have previously called DiscoverLSAs.
* After you know how many LSAs are present in the router, you may call
* GetLSA () to retrieve the actual advertisement.
*
* @see GlobalRouterLSA
* @see GlobalRouter::DiscoverLSAs ()
* @see GlobalRouter::GetLSA ()
* @returns The number of Global Router Link State Advertisements.
*/
uint32_t GetNumLSAs (void) const;
/**
* @brief Get a Global Router Link State Advertisements that this router has
* said that it can export.
*
* This is a fairly inexpensive expensive operation in that the hard work
* was done in GetNumLSAs. We just copy the indicated Global Router Link
* State Advertisement into the requested GlobalRouterLSA object.
*
* You must call GlobalRouter::GetNumLSAs before calling this method in
* order to discover the adjacent routers and build the advertisements.
* GetNumLSAs will return the number of LSAs this router advertises.
* The parameter n (requested LSA number) must be in the range 0 to
* GetNumLSAs() - 1.
*
* @see GlobalRouterLSA
* @see GlobalRouter::GetNumLSAs ()
* @param n The index number of the LSA you want to read.
* @param lsa The GlobalRouterLSA class to receive the LSA information.
* @returns The number of Global Router Link State Advertisements.
*/
bool GetLSA (uint32_t n, GlobalRouterLSA &lsa) const;
protected:
virtual ~GlobalRouter ();
void ClearLSAs (void);
Ptr<NetDevice> GetAdjacent(Ptr<NetDevice> nd, Ptr<Channel> ch) const;
uint32_t FindIfIndexForDevice(Ptr<Node> node, Ptr<NetDevice> nd) const;
Ptr<Node> m_node;
typedef std::list<GlobalRouterLSA*> ListOfLSAs_t;
ListOfLSAs_t m_LSAs;
Ipv4Address m_routerId;
private:
/**
* @brief Global Router copy construction is disallowed.
*/
GlobalRouter (GlobalRouter& sr);
/**
* @brief Global Router assignment operator is disallowed.
*/
GlobalRouter& operator= (GlobalRouter& sr);
};
} // namespace ns3
#endif /* GLOBAL_ROUTER_INTERFACE_H */

View File

@@ -0,0 +1,20 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
module = bld.create_obj('cpp', 'shlib')
module.name = 'ns3-global-routing'
module.target = module.name
module.uselib_local = ['ns3-node']
module.source = [
'global-router-interface.cc',
'global-route-manager.cc',
'global-route-manager-impl.cc',
'candidate-queue.cc',
]
headers = bld.create_obj('ns3header')
headers.source = [
'global-router-interface.h',
'global-route-manager.h',
'candidate-queue.h',
]

View File

@@ -18,10 +18,10 @@ all_modules = (
'devices/point-to-point',
'devices/csma-cd',
'applications',
'routing/global-routing',
'mobility',
)
def set_options(opt):
opt.sub_options('simulator')