merge with trunk
This commit is contained in:
521
SConstruct
Normal file
521
SConstruct
Normal 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()
|
||||
183
examples/simple-global-routing.cc
Normal file
183
examples/simple-global-routing.cc
Normal 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
191
examples/simple-p2p.cc
Normal 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 ();
|
||||
}
|
||||
@@ -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'])
|
||||
|
||||
|
||||
186
src/devices/p2p/p2p-channel.cc
Normal file
186
src/devices/p2p/p2p-channel.cc
Normal 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
|
||||
128
src/devices/p2p/p2p-channel.h
Normal file
128
src/devices/p2p/p2p-channel.h
Normal 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 */
|
||||
354
src/devices/p2p/p2p-net-device.cc
Normal file
354
src/devices/p2p/p2p-net-device.cc
Normal 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
|
||||
313
src/devices/p2p/p2p-net-device.h
Normal file
313
src/devices/p2p/p2p-net-device.h
Normal 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
|
||||
|
||||
172
src/devices/p2p/p2p-topology.cc
Normal file
172
src/devices/p2p/p2p-topology.cc
Normal 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
|
||||
|
||||
87
src/devices/p2p/p2p-topology.h
Normal file
87
src/devices/p2p/p2p-topology.h
Normal 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
24
src/devices/p2p/wscript
Normal 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',
|
||||
]
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
};
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
150
src/routing/global-routing/candidate-queue.cc
Normal file
150
src/routing/global-routing/candidate-queue.cc
Normal 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
|
||||
181
src/routing/global-routing/candidate-queue.h
Normal file
181
src/routing/global-routing/candidate-queue.h
Normal 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 */
|
||||
1408
src/routing/global-routing/global-route-manager-impl.cc
Normal file
1408
src/routing/global-routing/global-route-manager-impl.cc
Normal file
File diff suppressed because it is too large
Load Diff
747
src/routing/global-routing/global-route-manager-impl.h
Normal file
747
src/routing/global-routing/global-route-manager-impl.h
Normal 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 */
|
||||
68
src/routing/global-routing/global-route-manager.cc
Normal file
68
src/routing/global-routing/global-route-manager.cc
Normal 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
|
||||
93
src/routing/global-routing/global-route-manager.h
Normal file
93
src/routing/global-routing/global-route-manager.h
Normal 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 */
|
||||
588
src/routing/global-routing/global-router-interface.cc
Normal file
588
src/routing/global-routing/global-router-interface.cc
Normal 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
|
||||
580
src/routing/global-routing/global-router-interface.h
Normal file
580
src/routing/global-routing/global-router-interface.h
Normal 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 */
|
||||
20
src/routing/global-routing/wscript
Normal file
20
src/routing/global-routing/wscript
Normal 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',
|
||||
]
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user