branch merge

This commit is contained in:
Tom Henderson
2007-09-11 22:47:13 -07:00
33 changed files with 2943 additions and 251 deletions

235
README.multicast-routing Normal file
View File

@@ -0,0 +1,235 @@
Static multicast routing overview
--------------------------------
This is brief documentation of a proposal to add static multicast
routing to ns-3.
This extension allows the simulation user to:
- manually add Ipv4 multicast routes to a router
- specify a default outgoing interface for multicast sources (hosts) in
various ways
- allow a multicast receiver (hosts) to join a multicast group, to enable
reception of that group's datagrams
1. Code location:
- http://code.nsnam.org/craigdo/ns-3-mc
- the main source code is found in src/internet-node/ipv4-static-routing.{cc,h}
also touched are:
- src/internet-node/ipv4-l3-protocol.cc (forwarding methods for the
static routing API)
- src/node/net-device.cc (provides virtual NetDevice::MakeMulticastAddress)
- src/arp-ipv4-interface.cc (calls NetDevice::MakeMulticastAddress)
- src/devices/csma/csma-net-device.cc (handles multicast addressing and
reception).
- src/devices/point-to-point/point-to-point-net-device.cc (implements required
virtual methods.
- src/internet-node/ (several files have added tracing)
- a heavily commented example script is in examples/csma-multicast.cc
2. API:
The API for adding a multicast route is:
/**
* @brief Add a multicast route to the static routing table.
*
* A multicast route must specify an origin IP address, a multicast group and
* an input network interface index as conditions and provide a vector of
* output network interface indices over which packets matching the conditions
* are sent.
*
* Typically there are two main types of multicast routes: routes of the
* first kind are used during forwarding. All of the conditions must be
* exlicitly provided. The second kind of routes are used to get packets off
* of a local node. The difference is in the input interface. Routes for
* forwarding will always have an explicit input interface specified. Routes
* off of a node will always set the input interface to a wildcard specified
* by the index Ipv4RoutingProtocol::IF_INDEX_ANY.
*
* For routes off of a local node wildcards may be used in the origin and
* multicast group addresses. The wildcard used for Ipv4Adresses is that
* address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage
* of a wildcard allows one to specify default behavior to varying degrees.
*
* For example, making the origin address a wildcard, but leaving the
* multicast group specific allows one (in the case of a node with multiple
* interfaces) to create different routes using different output interfaces
* for each multicast group.
*
* If the origin and multicast addresses are made wildcards, you have created
* essentially a default multicast address that can forward to multiple
* interfaces. Compare this to the actual default multicast address that is
* limited to specifying a single output interface for compatibility with
* existing functionality in other systems.
*
* @param origin The Ipv4Address of the origin of packets for this route. May
* be Ipv4Address:GetAny for open groups.
* @param group The Ipv4Address of the multicast group or this route.
* @param inputInterface The input network interface index over which to
* expect packets destined for this route. May be
* Ipv4RoutingProtocol::IF_INDEX_ANY for packets of local origin.
* @param outputInterface A vector of network interface indices used to specify
* how to send packets to the destination(s).
*
* @see Ipv4Address
*/
Ipv4::AddMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces)
To remove a route, one uses:
/**
* @brief Remove a route from the static multicast routing table.
*
* Externally, the multicast static routing table appears simply as a table
* with n entries. The one sublety of note is that if a default multicast
* route has been set it will appear as the zeroth entry in the table. This
* means that the default route may be removed by calling this method with
* appropriate wildcard parameters.
*
* This method causes the multicast routing table to be searched for the first
* route that matches the parameters and removes it.
*
* Wildcards may be provided to this function, but the wildcards are used to
* exacly match wildcards in the routes (see AddMulticastRoute). That is,
* calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not
* remove routes with any address in the origin, but will only remove routes
* with "0.0.0.0" set as the the origin.
*
* @param origin The IP address specified as the origin of packets for the
* route.
* @param origin The IP address specified as the multicast group addres of
* the route.
* @param inputInterfade The network interface index specified as the expected
* input interface for the route.
* @returns True if a route was found and removed, false otherwise.
*
* @see Ipv4MulticastRoute
* @see Ipv4StaticRouting::AddMulticastRoute
*/
Ipv4::RemoveMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface)
For symmetry with the unicast routing interface, a method is provided to
remove routes by index:
/**
* @brief Remove a route from the static multicast routing table.
*
* Externally, the multicast static routing table appears simply as a table
* with n entries. The one sublety of note is that if a default multicast
* route has been set it will appear as the zeroth entry in the table. This
* means that if the default route has been set, calling
* RemoveMulticastRoute (0) will remove the default route.
*
* @param index The index (into the multicast routing table) of the route to
* remove. If the default route has been set, it will occupy index zero.
*
* @see Ipv4Route
* @see Ipv4StaticRouting::GetRoute
* @see Ipv4StaticRouting::AddRoute
*/
void RemoveMulticastRoute (uint32_t index);
For compatibility, and to provide simplicity, one can set a default multicast
route for a host originating data:
/**
* @brief Add a default multicast route to the static routing table.
*
* This is the multicast equivalent of the unicast version SetDefaultRoute.
* We tell the routing system what to do in the case where a specific route
* to a destination multicast group is not found. The system forwards
* packets out the specified interface in the hope that "something out there"
* knows better how to route the packet. This method is only used in
* initially sending packets off of a host. The default multicast route is
* not consulted during forwarding -- exact routes must be specified using
* AddMulticastRoute for that case.
*
* Since we're basically sending packets to some entity we think may know
* better what to do, we don't pay attention to "subtleties" like origin
* address, nor do we worry about forwarding out multiple interfaces. If the
* default multicast route is set, it is returned as the selected route from
* LookupStatic irrespective of origin or multicast group if another specific
* route is not found.
*
* @param outputInterface The network interface index used to specify where
* to send packets in the case of unknown routes.
*
* @see Ipv4Address
*/
Ipv4::SetDefaultMulticastRoute (uint32_t outputInterface)
For a host wanting to receive multicast data, the following function is used
to join each multicast group.
/**
* \brief Join a multicast group for a given multicast source and
* group.
*
* \param origin The Ipv4 address of the multicast source.
* \param group The multicast group address.
*/
Ipv4::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
To stop receiving multicast data, the following function is used:
/**
* \brief Leave a multicast group for a given multicast source and
* group.
*
* \param origin The Ipv4 address of the multicast source.
* \param group The multicast group address.
*/
LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
There are new lookup functions implemented in Ipv4:
/**
* \brief Find and return the interface ID of the interface that has been
* assigned the specified IP address.
* \param addr The IP address assigned to the interface of interest.
* \returns The index of the ipv4 interface with the given address.
*
* Each IP interface has an IP address associated with it. It is often
* useful to search the list of interfaces for one that corresponds to
* a known IP Address. This call takes an IP address as a parameter and
* returns the interface index of the first interface that has been assigned
* that address. If the address is not found, this function asserts.
*/
Ipv4::FindInterfaceForAddr (Ipv4Address addr) const;
/**
* \brief Find and return the interface ID of the interface that has been
* assigned the specified (masked) IP address.
* \param addr The IP address assigned to the interface of interest.
* \param mask The address mask to be used in address matching.
* \returns The index of the ipv4 interface with the given address.
*
* Each IP interface has an IP address associated with it. It is often
* useful to search the list of interfaces for one that corresponds to
* a known IP Address. This call takes an IP address and an IP address
* mask as parameters and returns the interface index of the first interface
* that matches the masked IP address.
*/
Ipv4::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const;
Also, there are various methods to lookup and iterate the static multicast
routes of a node, in the Ipv4StaticRouting class.
3. Dependencies:
- fix for bug 69 (source Ipv4 address is set correctly for UDP)
- fix for OnOffApplication that receives data
4. Open issues or features not included
- choose source interface on a per-group basis when a host is multihomed

View File

@@ -66,13 +66,24 @@ 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("CsmaNetDevice");
DebugComponentEnable("Ipv4L3Protocol");
DebugComponentEnable("NetDevice");
#if 0
DebugComponentEnable("Object");
DebugComponentEnable("Queue");
DebugComponentEnable("DropTailQueue");
DebugComponentEnable("Channel");
DebugComponentEnable("CsmaChannel");
DebugComponentEnable("NetDevice");
DebugComponentEnable("CsmaNetDevice");
DebugComponentEnable("Ipv4L3Protocol");
DebugComponentEnable("OnOffApplication");
DebugComponentEnable("PacketSocket");
DebugComponentEnable("UdpSocket");
DebugComponentEnable("UdpL4Protocol");
DebugComponentEnable("Ipv4L3Protocol");
DebugComponentEnable("Ipv4StaticRouting");
DebugComponentEnable("Ipv4Interface");
DebugComponentEnable("ArpIpv4Interface");
DebugComponentEnable("Ipv4LoopbackInterface");
#endif
// Set up some default values for the simulation. Use the Bind()
@@ -103,13 +114,13 @@ int main (int argc, char *argv[])
CsmaTopology::CreateCsmaChannel(
DataRate(5000000), MilliSeconds(2));
uint32_t n0ifIndex0 = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0,
uint32_t n0ifIndex0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, channel0,
Eui48Address("10:54:23:54:0:50"));
uint32_t n0ifIndex1 = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel1,
uint32_t n0ifIndex1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, channel1,
Eui48Address("10:54:23:54:0:51"));
uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0,
uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, channel0,
Eui48Address("10:54:23:54:23:51"));
uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channel1,
uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, channel1,
Eui48Address("10:54:23:54:23:52"));
// Later, we add IP addresses.
@@ -125,6 +136,18 @@ int main (int argc, char *argv[])
CsmaIpv4Topology::AddIpv4Address (
n2, n2ifIndex, Ipv4Address("192.168.1.2"), Ipv4Mask("255.255.255.0"));
// XXX Is this the right thing to do?
//
// The OnOff application uses a connected socket. This socket needs to be
// able to figure out which interface to use as the source address for
// packets. When there's one interface, this isn't too hard, but node zero
// has two interfaces, and limited broadcasts will be sent out both of those
// interfaces. We need to provide some way to disambiguate the choice.
// If we supply a default route, the specified interface will be chosen.
Ptr<Ipv4> ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
ipv4->SetDefaultRoute ("192.168.1.3", n0ifIndex0);
// Create the OnOff application to send UDP datagrams of size
// 210 bytes at a rate of 448 Kb/s
// from n0 to n1

312
examples/csma-multicast.cc Normal file
View File

@@ -0,0 +1,312 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Network topology
//
// Lan1
// ===========
// | | |
// n0 n1 n2 n3 n4
// | | |
// ===========
// Lan0
//
// - Multicast source is at node n0;
// - Multicast forwarded by node n2 onto LAN1;
// - Nodes n0, n1, n2, n3, and n4 receive the multicast frame.
// - Node n4 listens for the data (actual listener not yet implementted)
#include "ns3/command-line.h"
#include "ns3/default-value.h"
#include "ns3/ptr.h"
#include "ns3/random-variable.h"
#include "ns3/debug.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/csma-channel.h"
#include "ns3/csma-net-device.h"
#include "ns3/csma-topology.h"
#include "ns3/csma-ipv4-topology.h"
#include "ns3/eui48-address.h"
#include "ns3/ipv4-address.h"
#include "ns3/inet-socket-address.h"
#include "ns3/ipv4.h"
#include "ns3/socket.h"
#include "ns3/ipv4-route.h"
#include "ns3/onoff-application.h"
using namespace ns3;
NS_DEBUG_COMPONENT_DEFINE ("CsmaMulticast");
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("CsmaMulticast");
DebugComponentEnable("Object");
DebugComponentEnable("Queue");
DebugComponentEnable("DropTailQueue");
DebugComponentEnable("Channel");
DebugComponentEnable("CsmaChannel");
DebugComponentEnable("NetDevice");
DebugComponentEnable("CsmaNetDevice");
DebugComponentEnable("Ipv4L3Protocol");
DebugComponentEnable("OnOffApplication");
DebugComponentEnable("PacketSocket");
DebugComponentEnable("UdpSocket");
DebugComponentEnable("UdpL4Protocol");
DebugComponentEnable("Ipv4L3Protocol");
DebugComponentEnable("Ipv4StaticRouting");
DebugComponentEnable("Ipv4Interface");
DebugComponentEnable("ArpIpv4Interface");
DebugComponentEnable("Ipv4LoopbackInterface");
#endif
//
// Set up default values for the simulation. Use the DefaultValue::Bind()
// technique to tell the system what subclass of Queue to use. The Bind
// command command tells the queue factory which class to instantiate when the
// queue factory is invoked in the topology code
//
DefaultValue::Bind ("Queue", "DropTailQueue");
//
// Allow the user to override any of the defaults and the above Bind() at
// run-time, via command-line arguments
//
CommandLine::Parse (argc, argv);
//
// Explicitly create the nodes required by the topology (shown above).
//
NS_DEBUG("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
Ptr<Node> n4 = Create<InternetNode> ();
NS_DEBUG("Create channels.");
//
// Explicitly create the channels required by the topology (shown above).
//
Ptr<CsmaChannel> lan0 =
CsmaTopology::CreateCsmaChannel(DataRate(5000000), MilliSeconds(2));
Ptr<CsmaChannel> lan1 =
CsmaTopology::CreateCsmaChannel(DataRate(5000000), MilliSeconds(2));
NS_DEBUG("Build Topology.");
//
// Now fill out the topology by creating the net devices required to connect
// the nodes to the channels and hooking them up. AddIpv4CsmaNetDevice will
// create a net device, add a MAC address (in memory of the pink flamingo) and
// connect the net device to a nodes and also to a channel. the
// AddIpv4CsmaNetDevice method returns a net device index for the net device
// created on the node. Interpret nd0 as the net device we created for node
// zero. Interpret nd2Lan0 as the net device we created for node two to
// connect to Lan0.
//
uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan0,
Eui48Address("08:00:2e:00:00:00"));
uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan0,
Eui48Address("08:00:2e:00:00:01"));
uint32_t nd2Lan0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan0,
Eui48Address("08:00:2e:00:00:02"));
uint32_t nd2Lan1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan1,
Eui48Address("08:00:2e:00:00:03"));
uint32_t nd3 __attribute__ ((unused)) =
CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan1,
Eui48Address("08:00:2e:00:00:04"));
uint32_t nd4 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n4, lan1,
Eui48Address("08:00:2e:00:00:05"));
NS_DEBUG ("nd0 = " << nd0);
NS_DEBUG ("nd1 = " << nd1);
NS_DEBUG ("nd2Lan0 = " << nd2Lan0);
NS_DEBUG ("nd2Lan1 = " << nd2Lan1);
NS_DEBUG ("nd3 = " << nd3);
NS_DEBUG ("nd4 = " << nd3);
//
// We've got the "hardware" in place. Now we need to add IP addresses.
//
NS_DEBUG("Assign IP Addresses.");
CsmaIpv4Topology::AddIpv4Address (n0, nd0, Ipv4Address ("10.1.1.1"),
Ipv4Mask ("255.255.255.0"));
CsmaIpv4Topology::AddIpv4Address (n1, nd1, Ipv4Address ("10.1.1.2"),
Ipv4Mask ("255.255.255.0"));
//
// We'll need these addresses later
//
Ipv4Address n2Lan0Addr ("10.1.1.3");
Ipv4Address n2Lan1Addr ("10.1.2.1");
CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan0, n2Lan0Addr,
Ipv4Mask ("255.255.255.0"));
//
// Assign IP addresses to the net devices and associated interfaces on Lan1
//
CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan1, n2Lan1Addr,
Ipv4Mask ("255.255.255.0"));
CsmaIpv4Topology::AddIpv4Address (n3, nd1, Ipv4Address ("10.1.2.2"),
Ipv4Mask ("255.255.255.0"));
CsmaIpv4Topology::AddIpv4Address (n4, nd4, Ipv4Address ("10.1.2.3"),
Ipv4Mask ("255.255.255.0"));
NS_DEBUG("Configure multicasting.");
//
// Now we can configure multicasting. As described above, the multicast
// source is at node zero, which we assigned the IP address of 10.1.1.1
// earlier. We need to define a multicast group to send packets to. This
// can be any multicast address from 224.0.0.0 through 239.255.255.255
// (avoiding the reserved routing protocol addresses). We just pick a
// convenient number (225.0.0.0) and or in some bits to let us verify that
// correct Ethernet multicast addresses are constructed down in the system.
//
Ipv4Address multicastSource ("10.1.1.1");
Ipv4Address multicastGroup ("225.1.2.4");
//
// We are going to manually configure multicast routing. This means telling
// node two that it should expect multicast data coming from IP address
// 10.1.1.1 originally. It should expect these data coming in over its IP
// interface connected to Lan0. When node two receives these packets, they
// should be forwarded out the interface that connects it to Lan1.
//
// We're going to need the interface indices on node two corresponding to
// these interfaces, which we call ifIndexLan0 and ifIndexLan1. The most
// general way to get these interfaces is to look them up by IP address.
// Looking back to the topology creation calls above, we saved the addresses
// assigned to the interface connecting node two to Lan0 and Lan1. Now is
// a fine time to find the interface indices on node two.
//
Ptr<Ipv4> ipv4;
ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
uint32_t ifIndexLan0 = ipv4->FindInterfaceForAddr (n2Lan0Addr);
uint32_t ifIndexLan1 = ipv4->FindInterfaceForAddr (n2Lan1Addr);
//
// Now, we need to do is to call the AddMulticastRoute () method on node
// two's Ipv4 interface and tell it that whenever it receives a packet on
// the interface from Lan0, with the packet from the multicast source,
// destined for the multicast group, it should forward these packets down
// the interface connecting it to Lan1. (Note: the vector of output
// interfaces is in case there are multiple net devices on a node -- not
// true in this case).
//
std::vector<uint32_t> outputInterfaces (1);
outputInterfaces[0] = ifIndexLan1;
ipv4->AddMulticastRoute (multicastSource, multicastGroup, ifIndexLan0,
outputInterfaces);
//
// We need to specify how the source node handles multicasting. There are a
// number of ways we can deal with this, we just need to pick one. The first
// method is to add an explicit route out of the source node, just as we did
// for the forwarding node. Use this method when you want to send packets out
// multiple interfaces or send packets out different interfaces based on the
// differing multicast groups. Since the source is local, there will be no
// input interface over which packets are received, so use
// Ipv4RoutingProtocol::IF_INDEX_ANY as a wildcard.
//
// A second way is to specify a multicast route using wildcards. If you
// want to send multicasts out differing sets of interfaces based on the
// multicast group, you can use AddMulticastRoute () but specify the origin
// as a wildcard. If you want all multicasts to go out a single set of
// interfaces, you can make both the origin and group a wildcard.
//
// If you have a simple system, where the source has a single interface, this
// can be done via the SetDefaultMulticastRoute () method on the Ipv4
// interface. This tells the system to send all multicasts out a single
// specified network interface index.
//
// A last way is to specify a (or use an existing) default unicast route. The
// multicast routing code uses the unicast default route as a multicast "route
// of last resort." this method for is also on Ipv4 and is called
// SetDefaultRoute ().
//
// Since this is a simple multicast example, we use the
// SetDefaultMulticastRoute () approach. We are going to first need the
// Ipv4 interface for node 0 which is the multicast source. We use this
// interface to find the output interface index, and tell node zero to send
// its multicast traffic out that interface.
//
ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
uint32_t ifIndexSrc = ipv4->FindInterfaceForAddr (multicastSource);
ipv4->SetDefaultMulticastRoute (ifIndexSrc);
//
// As described above, node four will be the only node listening for the
// multicast data. To enable forwarding bits up the protocol stack, we need
// to tell the stack to join the multicast group.
//
ipv4 = n4->QueryInterface<Ipv4> (Ipv4::iid);
ipv4->JoinMulticastGroup (multicastSource, multicastGroup);
//
// Create an OnOff application to send UDP datagrams from node zero to the
// multicast group (node four will be listening).
//
NS_DEBUG("Create Applications.");
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
n0,
InetSocketAddress (multicastGroup, 80),
"Udp",
ConstantVariable(1),
ConstantVariable(0),
DataRate ("255b/s"),
128);
//
// Tell the application when to start and stop.
//
ooff->Start(Seconds(1.));
ooff->Stop (Seconds(10.));
//
// Configure tracing of all enqueue, dequeue, and NetDevice receive events.
// Trace output will be sent to the file "csma-multicast.tr"
//
NS_DEBUG("Configure Tracing.");
AsciiTrace asciitrace ("csma-multicast.tr");
asciitrace.TraceAllNetDeviceRx ();
asciitrace.TraceAllQueues ();
//
// Also configure some tcpdump traces; each interface will be traced.
// The output files will be named:
// csma-multicast.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
//
PcapTrace pcaptrace ("csma-multicast.pcap");
pcaptrace.TraceAllIp ();
//
// Now, do the actual simulation.
//
NS_DEBUG("Run Simulation.");
Simulator::Run ();
Simulator::Destroy ();
NS_DEBUG("Done.");
}

View File

@@ -14,35 +14,25 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Port of ns-2/tcl/ex/simple.tcl to ns-3
//
// Network topology
//
// n0 n1 n2 n3
// | | | |
// =====================
// =================
// LAN
//
// - CBR/UDP flows from n0 to n1, and from n3 to n0
// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
// (i.e., DataRate of 448,000 bps)
// - CBR/UDP flows from n0 to n1 and from n3 to n0
// - DropTail queues
// - Tracing of queues and packet receptions to file "csma-one-subnet.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/debug.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"
@@ -58,109 +48,168 @@
#include "ns3/ipv4-route.h"
#include "ns3/onoff-application.h"
using namespace ns3;
NS_DEBUG_COMPONENT_DEFINE ("CsmaOneSubnet");
int main (int argc, char *argv[])
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
//
// Users may find it convenient to turn on explicit debugging
// for selected modules; the below lines suggest how to do this
//
#if 0
DebugComponentEnable("CsmaOneSubnet");
DebugComponentEnable("Object");
DebugComponentEnable("Queue");
DebugComponentEnable("DropTailQueue");
DebugComponentEnable("Channel");
DebugComponentEnable("CsmaChannel");
DebugComponentEnable("CsmaNetDevice");
DebugComponentEnable("Ipv4L3Protocol");
DebugComponentEnable("NetDevice");
DebugComponentEnable("Channel");
DebugComponentEnable("CsmaChannel");
DebugComponentEnable("PacketSocket");
DebugComponentEnable("OnOffApplication");
DebugComponentEnable("UdpSocket");
DebugComponentEnable("UdpL4Protocol");
DebugComponentEnable("Ipv4L3Protocol");
DebugComponentEnable("Ipv4StaticRouting");
DebugComponentEnable("Ipv4Interface");
DebugComponentEnable("ArpIpv4Interface");
DebugComponentEnable("Ipv4LoopbackInterface");
#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
//
// Set up default values for the simulation. Use the DefaultValue::Bind()
// technique to tell the system what subclass of Queue to use. The Bind
// command command tells the queue factory which class to instantiate when the
// queue factory is invoked in the topology code
//
DefaultValue::Bind ("Queue", "DropTailQueue");
// Allow the user to override any of the defaults and the above
// Bind()s at run-time, via command-line arguments
//
// Allow the user to override any of the defaults and the above Bind() 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.
//
// Explicitly create the nodes required by the topology (shown above).
//
NS_DEBUG("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
// We create the channels first without any IP addressing information
Ptr<CsmaChannel> channel0 =
CsmaTopology::CreateCsmaChannel(
DataRate(5000000), MilliSeconds(2));
NS_DEBUG("Create channels.");
//
// Explicitly create the channels required by the topology (shown above).
//
Ptr<CsmaChannel> lan = CsmaTopology::CreateCsmaChannel(
DataRate(5000000), MilliSeconds(2));
uint32_t n0ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0,
Eui48Address("10:54:23:54:23:50"));
uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0,
Eui48Address("10:54:23:54:23:51"));
uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channel0,
Eui48Address("10:54:23:54:23:52"));
uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channel0,
Eui48Address("10:54:23:54:23:53"));
NS_DEBUG("Build Topology.");
//
// Now fill out the topology by creating the net devices required to connect
// the nodes to the channels and hooking them up. AddIpv4CsmaNetDevice will
// create a net device, add a MAC address (in memory of the pink flamingo) and
// connect the net device to a nodes and also to a channel. the
// AddIpv4CsmaNetDevice method returns a net device index for the net device
// created on the node. Interpret nd0 as the net device we created for node
// zero.
//
uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan,
Eui48Address("08:00:2e:00:00:00"));
// Later, we add IP addresses.
CsmaIpv4Topology::AddIpv4Address (
n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0"));
uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan,
Eui48Address("08:00:2e:00:00:01"));
CsmaIpv4Topology::AddIpv4Address (
n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0"));
uint32_t nd2 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan,
Eui48Address("08:00:2e:00:00:02"));
CsmaIpv4Topology::AddIpv4Address (
n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0"));
uint32_t nd3 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan,
Eui48Address("08:00:2e:00:00:03"));
NS_DEBUG ("nd0 = " << nd0);
NS_DEBUG ("nd1 = " << nd1);
NS_DEBUG ("nd2 = " << nd2);
NS_DEBUG ("nd3 = " << nd3);
//
// We've got the "hardware" in place. Now we need to add IP addresses.
//
NS_DEBUG("Assign IP Addresses.");
//
// XXX BUGBUG
// Need a better way to get the interface index. The point-to-point topology
// as implemented can't return the index since it creates interfaces on both
// sides (i.e., it does AddIpv4Addresses, not AddIpv4Address). We need a
// method on Ipv4 to find the interface index corresponding to a given ipv4
// address.
//
// Assign IP addresses to the net devices and associated interfaces
// on the lan. The AddIpv4Address method returns an Ipv4 interface index
// which we do not need here.
//
CsmaIpv4Topology::AddIpv4Address (n0, nd0, Ipv4Address("10.1.1.1"),
Ipv4Mask("255.255.255.0"));
CsmaIpv4Topology::AddIpv4Address (n1, nd1, Ipv4Address("10.1.1.2"),
Ipv4Mask("255.255.255.0"));
CsmaIpv4Topology::AddIpv4Address (n2, nd2, Ipv4Address("10.1.1.3"),
Ipv4Mask("255.255.255.0"));
CsmaIpv4Topology::AddIpv4Address (
n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0"));
// Create the OnOff application to send UDP datagrams of size
// 210 bytes at a rate of 448 Kb/s
// from n0 to n1
CsmaIpv4Topology::AddIpv4Address (n3, nd3, Ipv4Address("10.1.1.4"),
Ipv4Mask("255.255.255.0"));
//
// Create an OnOff application to send UDP datagrams from node zero to node 1.
//
NS_DEBUG("Create Applications.");
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
n0,
InetSocketAddress ("10.1.1.2", 80),
"Udp",
ConstantVariable(1),
ConstantVariable(0));
// Start the application
//
// Tell the application when to start and stop.
//
ooff->Start(Seconds(1.0));
ooff->Stop (Seconds(10.0));
// Create a similar flow from n3 to n0, starting at time 1.1 seconds
//
// Create a similar flow from n3 to n0, starting at time 1.1 seconds
//
ooff = Create<OnOffApplication> (
n3,
InetSocketAddress ("10.1.1.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 csma-one-subnet.tr file
//
// Configure tracing of all enqueue, dequeue, and NetDevice receive events.
// Trace output will be sent to the file "csma-one-subnet.tr"
//
NS_DEBUG("Configure Tracing.");
AsciiTrace asciitrace ("csma-one-subnet.tr");
asciitrace.TraceAllNetDeviceRx ();
asciitrace.TraceAllQueues ();
// Also configure some tcpdump traces; each interface will be traced
// The output files will be named
// simple-point-to-point.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
//
// Also configure some tcpdump traces; each interface will be traced.
// The output files will be named:
// csma-one-subnet.pcap-<nodeId>-<interfaceId>
// and can be read by the "tcpdump -r" command (use "-tt" option to
// display timestamps correctly)
//
PcapTrace pcaptrace ("csma-one-subnet.pcap");
pcaptrace.TraceAllIp ();
//
// Now, do the actual simulation.
//
NS_DEBUG("Run Simulation.");
Simulator::Run ();
Simulator::Destroy ();
NS_DEBUG("Done.");
}

View File

@@ -128,13 +128,13 @@ int main (int argc, char *argv[])
CsmaTopology::CreateCsmaChannel(
DataRate(5000000), MilliSeconds(2));
uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channelc0,
uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, channelc0,
Eui48Address("10:54:23:54:23:50"));
uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channelc0,
uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, channelc0,
Eui48Address("10:54:23:54:23:51"));
uint32_t n4ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n4, channelc0,
uint32_t n4ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n4, channelc0,
Eui48Address("10:54:23:54:23:52"));
uint32_t n5ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n5, channelc0,
uint32_t n5ifIndex = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n5, channelc0,
Eui48Address("10:54:23:54:23:53"));
// Later, we add IP addresses.

View File

@@ -38,11 +38,7 @@
// - Tracing of queues and packet receptions to file
// "simple-point-to-point.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"
@@ -68,21 +64,48 @@
using namespace ns3;
int main (int argc, char *argv[])
NS_DEBUG_COMPONENT_DEFINE ("Me");
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
// remember to add #include "ns3/debug.h" before enabling these
#if 0
DebugComponentEnable("Me");
DebugComponentEnable("Object");
DebugComponentEnable("Queue");
DebugComponentEnable("DropTailQueue");
DebugComponentEnable("Channel");
DebugComponentEnable("PointToPointChannel");
DebugComponentEnable("PointToPointNetDevice");
DebugComponentEnable("Ipv4L3Protocol");
DebugComponentEnable("NetDevice");
DebugComponentEnable("PacketSocket");
DebugComponentEnable("OnOffApplication");
DebugComponentEnable("UdpSocket");
DebugComponentEnable("UdpL4Protocol");
DebugComponentEnable("Ipv4L3Protocol");
DebugComponentEnable("Ipv4StaticRouting");
DebugComponentEnable("Ipv4Interface");
DebugComponentEnable("ArpIpv4Interface");
DebugComponentEnable("Ipv4LoopbackInterface");
#endif
DebugComponentEnable("Me");
DebugComponentEnable("OnOffApplication");
DebugComponentEnable("UdpSocket");
DebugComponentEnable("UdpL4Protocol");
DebugComponentEnable("Ipv4L3Protocol");
DebugComponentEnable("Ipv4StaticRouting");
DebugComponentEnable("PointToPointChannel");
DebugComponentEnable("PointToPointNetDevice");
DebugComponentEnable("Ipv4Interface");
DebugComponentEnable("ArpIpv4Interface");
DebugComponentEnable("Ipv4LoopbackInterface");
// 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
@@ -102,12 +125,14 @@ int main (int argc, char *argv[])
// Here, we will explicitly create four nodes. In more sophisticated
// topologies, we could configure a node factory.
NS_DEBUG("Create nodes.");
Ptr<Node> n0 = Create<InternetNode> ();
Ptr<Node> n1 = Create<InternetNode> ();
Ptr<Node> n2 = Create<InternetNode> ();
Ptr<Node> n3 = Create<InternetNode> ();
// We create the channels first without any IP addressing information
NS_DEBUG("Create channels.");
Ptr<PointToPointChannel> channel0 =
PointToPointTopology::AddPointToPointLink (
n0, n2, DataRate(5000000), MilliSeconds(2));
@@ -121,6 +146,7 @@ int main (int argc, char *argv[])
n2, n3, DataRate(1500000), MilliSeconds(10));
// Later, we add IP addresses.
NS_DEBUG("Assign IP Addresses.");
PointToPointTopology::AddIpv4Addresses (
channel0, n0, Ipv4Address("10.1.1.1"),
n2, Ipv4Address("10.1.1.2"));
@@ -137,13 +163,14 @@ int main (int argc, char *argv[])
// NetDevice creation, IP Address assignment, and routing) are
// separated because there may be a need to postpone IP Address
// assignment (emulation) or modify to use dynamic routing
NS_DEBUG("Add Static Routes.");
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
NS_DEBUG("Create Applications.");
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
n0,
InetSocketAddress ("10.1.3.2", 80),
@@ -185,6 +212,7 @@ int main (int argc, char *argv[])
// Here, finish off packet routing configuration
// This will likely set by some global StaticRouting object in the future
NS_DEBUG("Set Default Routes.");
Ptr<Ipv4> ipv4;
ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
@@ -193,6 +221,7 @@ int main (int argc, char *argv[])
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
// Trace output will be sent to the simple-point-to-point.tr file
NS_DEBUG("Configure Tracing.");
AsciiTrace asciitrace ("simple-point-to-point.tr");
asciitrace.TraceAllQueues ();
asciitrace.TraceAllNetDeviceRx ();
@@ -205,7 +234,8 @@ int main (int argc, char *argv[])
PcapTrace pcaptrace ("simple-point-to-point.pcap");
pcaptrace.TraceAllIp ();
Simulator::Run ();
NS_DEBUG("Run Simulation.");
Simulator::Run ();
Simulator::Destroy ();
NS_DEBUG("Done.");
}

View File

@@ -22,6 +22,10 @@ def build(bld):
['csma', 'internet-node'])
obj.source = 'csma-packet-socket.cc'
obj = bld.create_ns3_program('csma-multicast',
['csma', 'internet-node'])
obj.source = 'csma-multicast.cc'
obj = bld.create_ns3_program( 'mixed-global-routing',
['point-to-point', 'internet-node', 'global-routing' , 'csma-cd'])
obj.source = 'mixed-global-routing.cc'

View File

@@ -22,6 +22,7 @@
// George F. Riley, Georgia Tech, Spring 2007
// Adapted from ApplicationOnOff in GTNetS.
#include "ns3/debug.h"
#include "ns3/address.h"
#include "ns3/node.h"
#include "ns3/nstime.h"
@@ -34,6 +35,8 @@
#include "ns3/packet.h"
#include "onoff-application.h"
NS_DEBUG_COMPONENT_DEFINE ("OnOffApplication");
using namespace std;
namespace ns3 {
@@ -95,30 +98,37 @@ OnOffApplication::Construct (Ptr<Node> n,
m_iid = iid;
}
OnOffApplication::~OnOffApplication()
{}
{
NS_DEBUG("OnOffApplication::~OnOffApplication()");
}
void
OnOffApplication::SetMaxBytes(uint32_t maxBytes)
{
NS_DEBUG("OnOffApplication::SetMaxBytes(" << maxBytes << ")");
m_maxBytes = maxBytes;
}
void
OnOffApplication::SetDefaultRate (const DataRate &rate)
{
NS_DEBUG("OnOffApplication::SetDefaultRate(" << &rate << ")");
g_defaultRate.SetValue (rate);
}
void
OnOffApplication::SetDefaultSize (uint32_t size)
{
NS_DEBUG("OnOffApplication::SetDefaultSize(" << size << ")");
g_defaultSize.SetValue (size);
}
void
OnOffApplication::DoDispose (void)
{
NS_DEBUG("OnOffApplication::DoDispose()");
m_socket = 0;
delete m_onTime;
delete m_offTime;
@@ -130,10 +140,11 @@ OnOffApplication::DoDispose (void)
Application::DoDispose ();
}
// Application Methods
void OnOffApplication::StartApplication() // Called at time specified by Start
void OnOffApplication::StartApplication() // Called at time specified by Start
{
NS_DEBUG("OnOffApplication::StartApplication()");
// Create the socket if not already
if (!m_socket)
{
@@ -151,8 +162,10 @@ void OnOffApplication::StartApplication() // Called at time specified by Star
ScheduleStartEvent();
}
void OnOffApplication::StopApplication() // Called at time specified by Stop
void OnOffApplication::StopApplication() // Called at time specified by Stop
{
NS_DEBUG("OnOffApplication::StopApplication()");
if (m_sendEvent.IsRunning ())
{ // Cancel the pending send packet event
// Calculate residual bits since last packet sent
@@ -166,23 +179,32 @@ void OnOffApplication::StopApplication() // Called at time specified by Stop
// Event handlers
void OnOffApplication::StartSending()
{
NS_DEBUG("OnOffApplication::StartSending ()");
ScheduleNextTx(); // Schedule the send packet event
}
void OnOffApplication::StopSending()
{
NS_DEBUG("OnOffApplication::StopSending ()");
Simulator::Cancel(m_sendEvent);
}
// Private helpers
void OnOffApplication::ScheduleNextTx()
{
NS_DEBUG("OnOffApplication::ScheduleNextTx ()");
if (m_totBytes < m_maxBytes)
{
uint32_t bits = m_pktSize * 8 - m_residualBits;
NS_DEBUG("OnOffApplication::ScheduleNextTx (): bits = " << bits);
Time nextTime(Seconds (bits /
static_cast<double>(m_cbrRate.GetBitRate()))); // Time till next packet
m_sendEvent = Simulator::Schedule(nextTime, &OnOffApplication::SendPacket, this);
NS_DEBUG("OnOffApplication::ScheduleNextTx (): nextTime = " << nextTime);
m_sendEvent = Simulator::Schedule(nextTime,
&OnOffApplication::SendPacket, this);
}
else
{ // All done, cancel any pending events
@@ -192,12 +214,18 @@ void OnOffApplication::ScheduleNextTx()
void OnOffApplication::ScheduleStartEvent()
{ // Schedules the event to start sending data (switch to the "On" state)
NS_DEBUG("OnOffApplication::ScheduleStartEvent ()");
Time offInterval = Seconds(m_offTime->GetValue());
NS_DEBUG("OnOffApplication::ScheduleStartEvent (): "
"start at " << offInterval);
m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this);
}
void OnOffApplication::ScheduleStopEvent()
{ // Schedules the event to stop sending data (switch to "Off" state)
NS_DEBUG("OnOffApplication::ScheduleStopEvent ()");
Time onInterval = Seconds(m_onTime->GetValue());
Simulator::Schedule(onInterval, &OnOffApplication::StopSending, this);
}
@@ -205,6 +233,8 @@ void OnOffApplication::ScheduleStopEvent()
void OnOffApplication::SendPacket()
{
NS_DEBUG("OnOffApplication::SendPacket ()");
NS_ASSERT (m_sendEvent.IsExpired ());
m_socket->Send(Packet (m_pktSize));
m_totBytes += m_pktSize;
@@ -215,6 +245,8 @@ void OnOffApplication::SendPacket()
void OnOffApplication::ConnectionSucceeded(Ptr<Socket>)
{
NS_DEBUG("OnOffApplication::ConnectionSucceeded ()");
m_connected = true;
ScheduleStartEvent();
}

View File

@@ -250,7 +250,7 @@ CsmaChannel::TransmitEnd()
}
NS_DEBUG ("CsmaChannel::TransmitEnd (): Schedule event in " <<
m_delay.GetSeconds () << "sec");
m_delay.GetSeconds () << " sec");
Simulator::Schedule (m_delay,
&CsmaChannel::PropagationCompleteEvent,

View File

@@ -35,82 +35,79 @@
namespace ns3 {
uint32_t
CsmaIpv4Topology::AddIpv4CsmaNode(Ptr<Node> n1,
Ptr<CsmaChannel> ch,
Eui48Address addr)
CsmaIpv4Topology::AddIpv4CsmaNetDevice(
Ptr<Node> node,
Ptr<CsmaChannel> channel,
Eui48Address addr)
{
Ptr<Queue> q = Queue::CreateDefault ();
// assume full-duplex
Ptr<CsmaNetDevice> nd0 = Create<CsmaNetDevice> (n1, addr,
ns3::CsmaNetDevice::IP_ARP,
true, true);
nd0->AddQueue(q);
nd0->Attach (ch);
return nd0->GetIfIndex ();
Ptr<CsmaNetDevice> nd = Create<CsmaNetDevice> (node, addr,
ns3::CsmaNetDevice::IP_ARP, true, true);
nd->AddQueue(q);
nd->Attach (channel);
return nd->GetIfIndex ();
}
void
CsmaIpv4Topology::AddIpv4LlcCsmaNode(Ptr<Node> n1,
Ptr<CsmaChannel> ch,
Eui48Address addr)
Ptr<CsmaChannel> ch,
Eui48Address addr)
{
Ptr<Queue> q = Queue::CreateDefault ();
Ptr<CsmaNetDevice> nd0 = Create<CsmaNetDevice> (n1, addr,
ns3::CsmaNetDevice::LLC,
true, false);
ns3::CsmaNetDevice::LLC,
true, false);
nd0->AddQueue(q);
nd0->Attach (ch);
Ptr<CsmaNetDevice> nd1 = Create<CsmaNetDevice> (n1, addr,
ns3::CsmaNetDevice::LLC,
false, true);
ns3::CsmaNetDevice::LLC,
false, true);
nd1->AddQueue(q);
nd1->Attach (ch);
}
void
CsmaIpv4Topology::AddIpv4RawCsmaNode(Ptr<Node> n1,
Ptr<CsmaChannel> ch,
Eui48Address addr)
Ptr<CsmaChannel> ch,
Eui48Address addr)
{
Ptr<Queue> q = Queue::CreateDefault ();
Ptr<CsmaNetDevice> nd0 = Create<CsmaNetDevice> (n1, addr,
ns3::CsmaNetDevice::RAW,
true, false);
ns3::CsmaNetDevice::RAW,
true, false);
nd0->AddQueue(q);
nd0->Attach (ch);
Ptr<CsmaNetDevice> nd1 = Create<CsmaNetDevice> (n1, addr,
ns3::CsmaNetDevice::RAW,
false, true);
ns3::CsmaNetDevice::RAW,
false, true);
nd1->AddQueue(q);
nd1->Attach (ch);
}
void
CsmaIpv4Topology::AddIpv4Address(Ptr<Node> n1,
int ndNum,
const Ipv4Address& addr1,
const Ipv4Mask& netmask1)
uint32_t
CsmaIpv4Topology::AddIpv4Address(
Ptr<Node> node,
uint32_t netDeviceNumber,
const Ipv4Address address,
const Ipv4Mask mask)
{
Ptr<NetDevice> nd = node->GetDevice(netDeviceNumber);
// Duplex link is assumed to be subnetted as a /30
// May run this unnumbered in the future?
Ipv4Mask netmask(netmask1);
Ptr<NetDevice> nd1 = n1->GetDevice(ndNum);
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> ipv4 = node->QueryInterface<Ipv4> (Ipv4::iid);
uint32_t ifIndex = ipv4->AddInterface (nd);
ipv4->SetAddress (ifIndex, address);
ipv4->SetNetworkMask (ifIndex, mask);
ipv4->SetUp (ifIndex);
return ifIndex;
}
void
@@ -133,7 +130,7 @@ CsmaIpv4Topology::AddIpv4Routes (
found = true;
}
}
NS_ASSERT(found);
NS_ASSERT (found);
uint32_t index2 = 0;
found = false;
@@ -145,7 +142,7 @@ CsmaIpv4Topology::AddIpv4Routes (
found = true;
}
}
NS_ASSERT(found);
NS_ASSERT (found);
ip1->AddHostRouteTo (ip2-> GetAddress (index2), index1);
ip2->AddHostRouteTo (ip1-> GetAddress (index1), index2);

View File

@@ -61,9 +61,9 @@ public:
*
* \return ifIndex of the device
*/
static uint32_t AddIpv4CsmaNode( Ptr<Node> n1,
Ptr<CsmaChannel> ch,
Eui48Address addr);
static uint32_t AddIpv4CsmaNetDevice(Ptr<Node> node,
Ptr<CsmaChannel> channel,
Eui48Address addr);
/**
* \param n1 Node to be attached to the Csma channel
@@ -94,18 +94,23 @@ public:
/**
* \param n1 Node
* \param ndNum NetDevice number with which to associate address
* \param addr1 Ipv4 Address for ndNum of n1
* \param netmask1 network mask for ndNum of node n1
* \brief Create an Ipv4 interface for a net device and assign an
* Ipv4Address to that interface.
*
* \param node The node to which to add the new address and corresponding
* interface.
* \param netDeviceNumber The NetDevice index number with which to associate
* the address.
* \param address The Ipv4 Address for the interface.
* \param network The network mask for the interface
*
* Add an Ipv4Address to the Ipv4 interface associated with the
* ndNum CsmaIpv4NetDevices on the provided
* CsmaIpv4Channel
* ndNum CsmaIpv4NetDevices on the provided CsmaIpv4Channel
*/
static void AddIpv4Address(Ptr<Node> n1, int ndNum,
const Ipv4Address& addr1,
const Ipv4Mask& netmask1);
static uint32_t AddIpv4Address(Ptr<Node> node,
uint32_t netDeviceNumber,
const Ipv4Address address,
const Ipv4Mask mask);
/**
* \param nd1 Node

View File

@@ -19,8 +19,6 @@
* Author: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
*/
#include <iostream>
#include <cassert>
#include "ns3/debug.h"
#include "ns3/queue.h"
#include "ns3/simulator.h"
@@ -70,7 +68,6 @@ CsmaTraceType::Get (void) const
return m_type;
}
CsmaNetDevice::CsmaNetDevice (Ptr<Node> node)
: NetDevice (node, Eui48Address::Allocate ()),
m_bps (DataRate (0xffffffff))
@@ -81,7 +78,7 @@ CsmaNetDevice::CsmaNetDevice (Ptr<Node> node)
}
CsmaNetDevice::CsmaNetDevice (Ptr<Node> node, Eui48Address addr,
CsmaEncapsulationMode encapMode)
CsmaEncapsulationMode encapMode)
: NetDevice(node, addr),
m_bps (DataRate (0xffffffff))
{
@@ -92,8 +89,8 @@ CsmaNetDevice::CsmaNetDevice (Ptr<Node> node, Eui48Address addr,
}
CsmaNetDevice::CsmaNetDevice (Ptr<Node> node, Eui48Address addr,
CsmaEncapsulationMode encapMode,
bool sendEnable, bool receiveEnable)
CsmaEncapsulationMode encapMode,
bool sendEnable, bool receiveEnable)
: NetDevice(node, addr),
m_bps (DataRate (0xffffffff))
{
@@ -142,7 +139,7 @@ CsmaNetDevice::Init(bool sendEnable, bool receiveEnable)
m_queue = 0;
EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff"));
EnableMulticast();
EnableMulticast (Eui48Address ("01:00:5e:00:00:00"));
SetSendEnable (sendEnable);
SetReceiveEnable (receiveEnable);
@@ -513,10 +510,11 @@ CsmaNetDevice::Receive (const Packet& packet)
EthernetHeader header (false);
EthernetTrailer trailer;
Eui48Address broadcast;
Eui48Address multicast;
Eui48Address destination;
Packet p = packet;
NS_DEBUG ("CsmaNetDevice::Receive UID is (" << p.GetUid() << ")");
NS_DEBUG ("CsmaNetDevice::Receive (): UID is " << p.GetUid());
// Only receive if send side of net device is enabled
if (!IsReceiveEnabled())
@@ -535,12 +533,34 @@ CsmaNetDevice::Receive (const Packet& packet)
trailer.CheckFcs(p);
p.RemoveHeader(header);
NS_DEBUG ("CsmaNetDevice::Receive (): Pkt destination is " <<
header.GetDestination ());
//
// An IP host group address is mapped to an Ethernet multicast address
// by placing the low-order 23-bits of the IP address into the low-order
// 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 (hex).
//
// We are going to receive all packets destined to any multicast address,
// which means clearing the low-order 23 bits the header destination
//
Eui48Address mcDest;
uint8_t mcBuf[6];
header.GetDestination ().CopyTo (mcBuf);
mcBuf[3] &= 0x80;
mcBuf[4] = 0;
mcBuf[5] = 0;
mcDest.CopyFrom (mcBuf);
multicast = Eui48Address::ConvertFrom (GetMulticast ());
broadcast = Eui48Address::ConvertFrom (GetBroadcast ());
destination = Eui48Address::ConvertFrom (GetAddress ());
if ((header.GetDestination() != broadcast) &&
(header.GetDestination() != destination))
if ((header.GetDestination () != broadcast) &&
(mcDest != multicast) &&
(header.GetDestination () != destination))
{
// not for us.
NS_DEBUG ("CsmaNetDevice::Receive (): Dropping pkt ");
m_dropTrace (p);
return;
}
@@ -572,6 +592,61 @@ CsmaNetDevice::Receive (const Packet& packet)
return;
}
Address
CsmaNetDevice::MakeMulticastAddress(Ipv4Address multicastGroup) const
{
NS_DEBUG ("CsmaNetDevice::MakeMulticastAddress (" << multicastGroup <<
")");
//
// First, get the generic multicast address.
//
Address hardwareDestination = GetMulticast ();
NS_DEBUG ("CsmaNetDevice::MakeMulticastAddress (): "
"Device multicast address: " << hardwareDestination);
//
// It's our address, and we know we're playing with an EUI-48 address here
// primarily since we know that by construction, but also since the parameter
// is an Ipv4Address.
//
Eui48Address etherAddr = Eui48Address::ConvertFrom (hardwareDestination);
//
// We now have the multicast address in an abstract 48-bit container. We
// need to pull it out so we can play with it. When we're done, we have the
// high order bits in etherBuffer[0], etc.
//
uint8_t etherBuffer[6];
etherAddr.CopyTo (etherBuffer);
//
// Now we need to pull the raw bits out of the Ipv4 destination address.
//
uint8_t ipBuffer[4];
multicastGroup.Serialize (ipBuffer);
//
// RFC 1112 says that an Ipv4 host group address is mapped to an EUI-48
// multicast address by placing the low-order 23-bits of the IP address into
// the low-order 23 bits of the Ethernet multicast address
// 01-00-5E-00-00-00 (hex).
//
etherBuffer[3] |= ipBuffer[1] & 0x7f;
etherBuffer[4] = ipBuffer[2];
etherBuffer[5] = ipBuffer[3];
//
// Now, etherBuffer has the desired ethernet multicast address. We have to
// suck these bits back into the Eui48Address,
//
etherAddr.CopyFrom (etherBuffer);
//
// Implicit conversion (operator Address ()) is defined for Eui48Address, so
// use it by just returning the EUI-48 address which is automagically converted
// to an Address.
//
NS_DEBUG ("CsmaNetDevice::MakeMulticastAddress (): "
"multicast address is " << etherAddr);
return etherAddr;
}
Ptr<Queue>
CsmaNetDevice::GetQueue(void) const
{

View File

@@ -205,6 +205,37 @@ enum CsmaEncapsulationMode {
*/
void Receive (const Packet& p);
/**
* @brief Make and return a MAC multicast address using the provided
* multicast group
*
* RFC 1112 says that an Ipv4 host group address is mapped to an Ethernet
* multicast address by placing the low-order 23-bits of the IP address into
* the low-order 23 bits of the Ethernet multicast address
* 01-00-5E-00-00-00 (hex).
*
* This method performs the multicast address creation function appropriate
* to an EUI-48-based CSMA device. This MAC address is encapsulated in an
* abstract Address to avoid dependencies on the exact address format.
*
* A default imlementation of MakeMulticastAddress is provided, but this
* method simply NS_ASSERTS. In the case of net devices that do not support
* multicast, clients are expected to test NetDevice::IsMulticast and avoid
* attempting to map multicast packets. Subclasses of NetDevice that do
* support multicasting are expected to override this method and provide an
* implementation appropriate to the particular device.
*
* @param multicastGroup The IP address for the multicast group destination
* of the packet.
* @return The MAC multicast Address used to send packets to the provided
* multicast group.
*
* @see Ipv4Address
* @see Eui48Address
* @see Address
*/
Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
bool IsSendEnabled (void);
bool IsReceiveEnabled (void);

View File

@@ -20,8 +20,6 @@
* Revised: George Riley <riley@ece.gatech.edu>
*/
#include <iostream>
#include <cassert>
#include "ns3/debug.h"
#include "ns3/queue.h"
#include "ns3/simulator.h"
@@ -73,11 +71,14 @@ PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
{
NS_DEBUG ("PointToPointNetDevice::PointToPointNetDevice (" << node << ")");
// BUGBUG FIXME
//
// You _must_ support broadcast to get any sort of packet from the ARP layer.
// BUGBUG FIXME
//
// You _must_ support broadcast to get any sort of packet from the ARP layer.
EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff"));
EnableMulticast();
//
// We want to allow multicast packets to flow across this link
//
EnableMulticast (Eui48Address ("01:00:5e:00:00:00"));
EnablePointToPoint();
}
@@ -218,6 +219,8 @@ bool PointToPointNetDevice::Attach (Ptr<PointToPointChannel> ch)
m_bps = m_channel->GetDataRate ();
// GFR Comment. Below is definitely wrong. Interframe gap
// is unrelated to channel delay.
// -- unlesss you want to introduce a default gap which is there to avoid
// parts of multiple packets flowing on the "wire" at the same time.
//m_tInterframeGap = m_channel->GetDelay ();
/*

View File

@@ -31,18 +31,26 @@
#include "ipv4-l3-protocol.h"
#include "arp-l3-protocol.h"
NS_DEBUG_COMPONENT_DEFINE ("ArpIpv4Interface");
namespace ns3 {
ArpIpv4Interface::ArpIpv4Interface (Ptr<Node> node, Ptr<NetDevice> device)
: Ipv4Interface (device),
m_node (node)
{}
{
NS_DEBUG ("ArpIpv4Interface::ArpIpv4Interface ()");
}
ArpIpv4Interface::~ArpIpv4Interface ()
{}
{
NS_DEBUG ("ArpIpv4Interface::~ArpIpv4Interface ()");
}
Ptr<TraceResolver>
ArpIpv4Interface::GetTraceResolver (void) const
{
NS_DEBUG ("ArpIpv4Interface::DoCreateTraceResolver ()");
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
if (GetDevice () != 0)
{
@@ -55,32 +63,52 @@ ArpIpv4Interface::GetTraceResolver (void) const
void
ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest)
{
NS_DEBUG ("ArpIpv4Interface::SendTo (" << &p << ", " << dest << ")");
NS_ASSERT (GetDevice () != 0);
if (GetDevice ()->NeedsArp ())
{
Ptr<ArpL3Protocol> arp = m_node->QueryInterface<ArpL3Protocol> (ArpL3Protocol::iid);
NS_DEBUG ("ArpIpv4Interface::SendTo (): Needs ARP");
Ptr<ArpL3Protocol> arp =
m_node->QueryInterface<ArpL3Protocol> (ArpL3Protocol::iid);
Address hardwareDestination;
bool found;
if (dest.IsBroadcast () ||
dest.IsSubnetDirectedBroadcast (GetNetworkMask ()) )
{
NS_DEBUG ("ArpIpv4Interface::SendTo (): IsBroadcast");
hardwareDestination = GetDevice ()->GetBroadcast ();
found = true;
}
else if (dest.IsMulticast ())
{
NS_DEBUG ("ArpIpv4Interface::SendTo (): IsMulticast");
NS_ASSERT_MSG(GetDevice ()->IsMulticast (),
"ArpIpv4Interface::SendTo (): Sending multicast packet over "
"non-multicast device");
hardwareDestination = GetDevice ()->MakeMulticastAddress(dest);
found = true;
}
else
{
NS_DEBUG ("ArpIpv4Interface::SendTo (): ARP Lookup");
found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination);
}
if (found)
{
GetDevice ()->Send (p, hardwareDestination, Ipv4L3Protocol::PROT_NUMBER);
NS_DEBUG ("ArpIpv4Interface::SendTo (): Address Resolved. Send.");
GetDevice ()->Send (p, hardwareDestination,
Ipv4L3Protocol::PROT_NUMBER);
}
}
else
{
GetDevice ()->Send (p, GetDevice ()->GetBroadcast (), Ipv4L3Protocol::PROT_NUMBER);
NS_DEBUG ("ArpIpv4Interface::SendTo (): Doesn't need ARP");
GetDevice ()->Send (p, GetDevice ()->GetBroadcast (),
Ipv4L3Protocol::PROT_NUMBER);
}
}

View File

@@ -24,6 +24,7 @@
#include "ipv4-interface.h"
#include "ns3/ptr.h"
#include "ns3/eui48-address.h"
namespace ns3 {

View File

@@ -95,22 +95,90 @@ Ipv4Impl::RemoveRoute (uint32_t i)
{
return m_ipv4->RemoveRoute (i);
}
void
Ipv4Impl::AddMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces)
{
m_ipv4->AddMulticastRoute (origin, group, inputInterface, outputInterfaces);
}
void
Ipv4Impl::SetDefaultMulticastRoute (uint32_t outputInterface)
{
m_ipv4->SetDefaultMulticastRoute (outputInterface);
}
uint32_t
Ipv4Impl::GetNMulticastRoutes (void) const
{
return m_ipv4->GetNMulticastRoutes ();
}
Ipv4MulticastRoute
Ipv4Impl::GetMulticastRoute (uint32_t i) const
{
return *m_ipv4->GetMulticastRoute (i);
}
void
Ipv4Impl::RemoveMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface)
{
m_ipv4->RemoveMulticastRoute (origin, group, inputInterface);
}
void
Ipv4Impl::RemoveMulticastRoute (uint32_t i)
{
return m_ipv4->RemoveMulticastRoute (i);
}
uint32_t
Ipv4Impl::AddInterface (Ptr<NetDevice> device)
{
return m_ipv4->AddInterface (device);
}
uint32_t
Ipv4Impl::GetNInterfaces (void)
{
return m_ipv4->GetNInterfaces ();
}
uint32_t
Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr) const
{
return m_ipv4->FindInterfaceForAddr (addr);
}
uint32_t
Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
{
return m_ipv4->FindInterfaceForAddr (addr, mask);
}
Ptr<NetDevice>
Ipv4Impl::GetNetDevice (uint32_t i)
{
return m_ipv4->GetInterface (i)-> GetDevice ();
}
void
Ipv4Impl::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
{
m_ipv4->JoinMulticastGroup(origin, group);
}
void
Ipv4Impl::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
{
m_ipv4->LeaveMulticastGroup(origin, group);
}
void
Ipv4Impl::SetAddress (uint32_t i, Ipv4Address address)
{
@@ -126,11 +194,39 @@ Ipv4Impl::GetNetworkMask (uint32_t i) const
{
return m_ipv4->GetNetworkMask (i);
}
Ipv4Address
Ipv4Impl::GetAddress (uint32_t i) const
{
return m_ipv4->GetAddress (i);
}
bool
Ipv4Impl::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const
{
return m_ipv4->GetIfIndexForDestination (dest, ifIndex);
}
Ipv4Address
Ipv4Impl::GetSourceAddress (Ipv4Address destination) const
{
uint32_t ifIndex = 0xffffffff;
bool result = m_ipv4->GetIfIndexForDestination (destination, ifIndex);
if (result)
{
return m_ipv4->GetAddress (ifIndex);
}
else
{
//
// If we can't find any address, just leave it 0.0.0.0
//
return Ipv4Address::GetAny ();
}
}
uint16_t
Ipv4Impl::GetMtu (uint32_t i) const
{

View File

@@ -55,14 +55,43 @@ public:
virtual uint32_t GetNRoutes (void);
virtual Ipv4Route GetRoute (uint32_t i);
virtual void RemoveRoute (uint32_t i);
virtual void AddMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces);
virtual void SetDefaultMulticastRoute (uint32_t outputInterface);
virtual uint32_t GetNMulticastRoutes (void) const;
virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const;
virtual void RemoveMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface);
virtual void RemoveMulticastRoute (uint32_t i);
virtual uint32_t AddInterface (Ptr<NetDevice> device);
virtual uint32_t GetNInterfaces (void);
virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const;
virtual uint32_t FindInterfaceForAddr (Ipv4Address addr,
Ipv4Mask mask) const;
virtual Ptr<NetDevice> GetNetDevice(uint32_t i);
virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
virtual void SetAddress (uint32_t i, Ipv4Address address);
virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask);
virtual Ipv4Mask GetNetworkMask (uint32_t t) const;
virtual Ipv4Address GetAddress (uint32_t i) const;
virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const;
virtual bool GetIfIndexForDestination (Ipv4Address dest,
uint32_t &ifIndex) const;
virtual uint16_t GetMtu (uint32_t i) const;
virtual bool IsUp (uint32_t i) const;
virtual void SetUp (uint32_t i);

View File

@@ -23,6 +23,9 @@
#include "ns3/ipv4-address.h"
#include "ns3/net-device.h"
#include "ns3/trace-resolver.h"
#include "ns3/debug.h"
NS_DEBUG_COMPONENT_DEFINE ("Ipv4Interface");
namespace ns3 {
@@ -35,10 +38,14 @@ namespace ns3 {
Ipv4Interface::Ipv4Interface (Ptr<NetDevice> nd)
: m_netdevice (nd),
m_ifup(false)
{}
{
NS_DEBUG ("Ipv4Interface::Ipv4Interface (" << &nd << ")");
}
Ipv4Interface::~Ipv4Interface ()
{}
{
NS_DEBUG ("Ipv4Interface::~Ipv4Interface ()");
}
void
Ipv4Interface::DoDispose (void)
@@ -50,42 +57,53 @@ Ipv4Interface::DoDispose (void)
Ptr<NetDevice>
Ipv4Interface::GetDevice (void) const
{
NS_DEBUG ("Ipv4Interface::GetDevice ()");
return m_netdevice;
}
void
Ipv4Interface::SetAddress (Ipv4Address a)
{
NS_DEBUG ("Ipv4Interface::SetAddress (" << a << ")");
m_address = a;
}
void
Ipv4Interface::SetNetworkMask (Ipv4Mask mask)
{
NS_DEBUG ("Ipv4Interface::SetMask (" << mask << ")");
m_netmask = mask;
}
Ipv4Address
Ipv4Interface::GetBroadcast (void) const
{
NS_DEBUG ("Ipv4Interface::GetBroadcast ()");
uint32_t mask = m_netmask.GetHostOrder ();
uint32_t address = m_address.GetHostOrder ();
Ipv4Address broadcast = Ipv4Address (address | (~mask));
return broadcast;
}
Ipv4Mask
Ipv4Interface::GetNetworkMask (void) const
{
NS_DEBUG ("Ipv4Interface::GetNetworkMask ()");
return m_netmask;
}
Ipv4Address
Ipv4Interface::GetAddress (void) const
{
NS_DEBUG ("Ipv4Interface::Address ()");
return m_address;
}
uint16_t
Ipv4Interface::GetMtu (void) const
{
NS_DEBUG ("Ipv4Interface::GetMtu ()");
if (m_netdevice == 0)
{
uint32_t mtu = (1<<16) - 1;
@@ -94,32 +112,36 @@ Ipv4Interface::GetMtu (void) const
return m_netdevice->GetMtu ();
}
/**
* These are IP interface states and may be distinct from
* NetDevice states, such as found in real implementations
* (where the device may be down but IP interface state is still up).
*/
/**
* These are IP interface states and may be distinct from
* NetDevice states, such as found in real implementations
* (where the device may be down but IP interface state is still up).
*/
bool
Ipv4Interface::IsUp (void) const
{
NS_DEBUG ("Ipv4Interface::IsUp ()");
return m_ifup;
}
bool
Ipv4Interface::IsDown (void) const
{
NS_DEBUG ("Ipv4Interface::IsDown ()");
return !m_ifup;
}
void
Ipv4Interface::SetUp (void)
{
NS_DEBUG ("Ipv4Interface::SetUp ()");
m_ifup = true;
}
void
Ipv4Interface::SetDown (void)
{
NS_DEBUG ("Ipv4Interface::SetDown ()");
m_ifup = false;
}
@@ -127,7 +149,10 @@ Ipv4Interface::SetDown (void)
void
Ipv4Interface::Send(Packet p, Ipv4Address dest)
{
NS_DEBUG ("Ipv4Interface::Send ()");
if (IsUp()) {
NS_DEBUG ("Ipv4Interface::Send (): SendTo ()");
SendTo(p, dest);
}
}

View File

@@ -129,17 +129,24 @@ Ipv4L3Protocol::Ipv4L3Protocol(Ptr<Node> node)
m_identification (0),
m_node (node)
{
NS_DEBUG("Ipv4L3Protocol::Ipv4L3Protocol ()");
SetInterfaceId (Ipv4L3Protocol::iid);
m_staticRouting = Create<Ipv4StaticRouting> ();
AddRoutingProtocol (m_staticRouting, 0);
SetupLoopback ();
}
Ipv4L3Protocol::~Ipv4L3Protocol ()
{}
{
NS_DEBUG("Ipv4L3Protocol::~Ipv4L3Protocol ()");
}
void
Ipv4L3Protocol::DoDispose (void)
{
NS_DEBUG("Ipv4L3Protocol::DoDispose ()");
m_interfaces.clear ();
m_node = 0;
m_staticRouting->Dispose ();
@@ -150,6 +157,8 @@ Ipv4L3Protocol::DoDispose (void)
void
Ipv4L3Protocol::SetupLoopback (void)
{
NS_DEBUG("Ipv4L3Protocol::SetupLoopback ()");
Ptr<Ipv4LoopbackInterface> interface = Create<Ipv4LoopbackInterface> (m_node);
interface->SetAddress (Ipv4Address::GetLoopback ());
interface->SetNetworkMask (Ipv4Mask::GetLoopback ());
@@ -161,6 +170,8 @@ Ipv4L3Protocol::SetupLoopback (void)
Ptr<TraceResolver>
Ipv4L3Protocol::GetTraceResolver (void) const
{
NS_DEBUG("Ipv4L3Protocol::GetTraceResolver ()");
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
resolver->AddSource ("tx",
TraceDoc ("send ipv4 packet to outgoing interface",
@@ -185,6 +196,7 @@ Ipv4L3Protocol::GetTraceResolver (void) const
void
Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl)
{
NS_DEBUG("Ipv4L3Protocol::SetDefaultTtl ()");
m_defaultTtl = ttl;
}
@@ -194,20 +206,28 @@ Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest,
Ipv4Address nextHop,
uint32_t interface)
{
NS_DEBUG("Ipv4L3Protocol::AddHostRouteTo (" << dest << ", " << nextHop <<
", " << interface << ")");
m_staticRouting->AddHostRouteTo (dest, nextHop, interface);
}
void
Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest,
uint32_t interface)
{
NS_DEBUG("Ipv4L3Protocol::AddHostRouteTo (" << dest << ", " <<
interface << ")");
m_staticRouting->AddHostRouteTo (dest, interface);
}
void
Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network,
Ipv4Mask networkMask,
Ipv4Address nextHop,
uint32_t interface)
{
NS_DEBUG("Ipv4L3Protocol::AddNetworkRouteTo (" << network << ", " <<
networkMask << ", " << nextHop << ", " << interface << ")");
m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface);
}
void
@@ -215,28 +235,81 @@ Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network,
Ipv4Mask networkMask,
uint32_t interface)
{
NS_DEBUG("Ipv4L3Protocol::AddNetworkRouteTo (" << network << ", " <<
networkMask << ", " << interface << ")");
m_staticRouting->AddNetworkRouteTo (network, networkMask, interface);
}
void
Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop,
uint32_t interface)
{
NS_DEBUG("Ipv4L3Protocol::SetDefaultRoute (" << nextHop << ", " <<
interface << ")");
m_staticRouting->SetDefaultRoute (nextHop, interface);
}
void
Ipv4L3Protocol::Lookup (
Ipv4Header const &ipHeader,
Packet packet,
Ipv4RoutingProtocol::RouteReplyCallback routeReply)
{
NS_DEBUG("Ipv4L3Protocol::Lookup (" << &ipHeader <<
", " << &packet << &routeReply << ")");
Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply);
}
void
Ipv4L3Protocol::Lookup (Ipv4Header const &ipHeader,
Packet packet,
Ipv4RoutingProtocol::RouteReplyCallback routeReply)
Ipv4L3Protocol::Lookup (
uint32_t ifIndex,
Ipv4Header const &ipHeader,
Packet packet,
Ipv4RoutingProtocol::RouteReplyCallback routeReply)
{
for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
rprotoIter != m_routingProtocols.end (); rprotoIter++)
NS_DEBUG("Ipv4L3Protocol::Lookup (" << ifIndex << ", " << &ipHeader <<
", " << &packet << &routeReply << ")");
for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
m_routingProtocols.begin ();
rprotoIter != m_routingProtocols.end ();
rprotoIter++)
{
if ((*rprotoIter).second->RequestRoute (ipHeader, packet, routeReply))
NS_DEBUG("Ipv4L3Protocol::Lookup (): Requesting route");
if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet,
routeReply))
return;
}
// No route found
if (ipHeader.GetDestination ().IsMulticast () &&
ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY)
{
NS_DEBUG ("Ipv4L3Protocol::Lookup (): "
"Multicast destination with local source");
//
// We have a multicast packet originating from the current node and were not
// able to send it using the usual RequestRoute process. Since the usual
// process includes trying to use a default multicast route, this means that
// there was no specific route out of the node found, and there was no default
// multicast route set.
//
// The fallback position is to look for a default unicast route and use that
// to get the packet off the node if we have one.
//
Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
if (route)
{
NS_DEBUG ("Ipv4StaticRouting::Lookup (): "
"Local source. Using unicast default route for multicast packet");
routeReply (true, *route, packet, ipHeader);
return;
}
}
//
// No route found
//
routeReply (false, Ipv4Route (), packet, ipHeader);
}
@@ -244,6 +317,8 @@ void
Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
int priority)
{
NS_DEBUG("Ipv4L3Protocol::AddRoutingProtocol (" << &routingProtocol <<
", " << priority << ")");
m_routingProtocols.push_back
(std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
m_routingProtocols.sort ();
@@ -252,39 +327,99 @@ Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
uint32_t
Ipv4L3Protocol::GetNRoutes (void)
{
NS_DEBUG("Ipv4L3Protocol::GetNRoutes ()");
return m_staticRouting->GetNRoutes ();
}
Ipv4Route *
Ipv4L3Protocol::GetRoute (uint32_t index)
{
NS_DEBUG("Ipv4L3Protocol::GetRoute ()");
return m_staticRouting->GetRoute (index);
}
void
Ipv4L3Protocol::RemoveRoute (uint32_t index)
{
NS_DEBUG("Ipv4L3Protocol::RemoveRoute (" << index << ")");
m_staticRouting->RemoveRoute (index);
}
void
Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces)
{
NS_DEBUG("Ipv4L3Protocol::AddMulticastRoute (" << origin << ", " <<
group << ", " << inputInterface << ", " << &outputInterfaces << ")");
m_staticRouting->AddMulticastRoute (origin, group, inputInterface,
outputInterfaces);
}
void
Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface)
{
NS_DEBUG("Ipv4L3Protocol::SetDefaultMulticastRoute (" << outputInterface <<
")");
m_staticRouting->SetDefaultMulticastRoute (outputInterface);
}
uint32_t
Ipv4L3Protocol::GetNMulticastRoutes (void) const
{
NS_DEBUG("Ipv4L3Protocol::GetNMulticastRoutes ()");
return m_staticRouting->GetNMulticastRoutes ();
}
Ipv4MulticastRoute *
Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const
{
NS_DEBUG("Ipv4L3Protocol::GetMulticastRoute (" << index << ")");
return m_staticRouting->GetMulticastRoute (index);
}
void
Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface)
{
NS_DEBUG("Ipv4L3Protocol::RemoveMulticastRoute (" << origin << ", " <<
group << ", " << inputInterface << ")");
m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface);
}
void
Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index)
{
NS_DEBUG("Ipv4L3Protocol::RemoveMulticastRoute (" << index << ")");
m_staticRouting->RemoveMulticastRoute (index);
}
uint32_t
Ipv4L3Protocol::AddInterface (Ptr<NetDevice> device)
{
NS_DEBUG("Ipv4L3Protocol::AddInterface (" << &device << ")");
Ptr<Ipv4Interface> interface = Create<ArpIpv4Interface> (m_node, device);
return AddIpv4Interface (interface);
}
uint32_t
Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
{
NS_DEBUG("Ipv4L3Protocol::AddIpv4Interface (" << interface << ")");
uint32_t index = m_nInterfaces;
m_interfaces.push_back (interface);
m_nInterfaces++;
return index;
}
Ptr<Ipv4Interface>
Ipv4L3Protocol::GetInterface (uint32_t index) const
{
NS_DEBUG("Ipv4L3Protocol::GetInterface (" << index << ")");
uint32_t tmp = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
{
@@ -296,15 +431,61 @@ Ipv4L3Protocol::GetInterface (uint32_t index) const
}
return 0;
}
uint32_t
Ipv4L3Protocol::GetNInterfaces (void) const
{
NS_DEBUG("Ipv4L3Protocol::GetNInterface ()");
return m_nInterfaces;
}
uint32_t
Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const
{
NS_DEBUG("Ipv4L3Protocol::FindInterfaceForAddr (" << addr << ")");
uint32_t ifIndex = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, ifIndex++)
{
if ((*i)->GetAddress () == addr)
{
return ifIndex;
}
}
NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
"Interface not found for IP address");
return 0;
}
uint32_t
Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
{
NS_DEBUG("Ipv4L3Protocol::FindInterfaceForAddr (" << addr << ", " <<
mask << ")");
uint32_t ifIndex = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, ifIndex++)
{
if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask))
{
return ifIndex;
}
}
NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
"Interface not found for masked IP address");
return 0;
}
Ptr<Ipv4Interface>
Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
{
NS_DEBUG("Ipv4L3Protocol::FindInterfaceForDevice (" << &device << ")");
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
{
if ((*i)->GetDevice () == device)
@@ -318,8 +499,15 @@ Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
void
Ipv4L3Protocol::Receive( Ptr<NetDevice> device, const Packet& p, uint16_t protocol, const Address &from)
{
NS_DEBUG("Ipv4L3Protocol::Receive (" << &device << ", " << &p << ", " <<
protocol << ", " << from << ")");
NS_DEBUG("Ipv4L3Protocol::Receive (): Packet from " << from);
uint32_t index = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++)
{
if ((*i)->GetDevice () == device)
{
@@ -337,7 +525,7 @@ Ipv4L3Protocol::Receive( Ptr<NetDevice> device, const Packet& p, uint16_t protoc
return;
}
if (Forwarding (packet, ipHeader, device))
if (Forwarding (index, packet, ipHeader, device))
{
return;
}
@@ -352,6 +540,9 @@ Ipv4L3Protocol::Send (Packet const &packet,
Ipv4Address destination,
uint8_t protocol)
{
NS_DEBUG("Ipv4L3Protocol::Send (" << &packet << ", " << source << ", " <<
", " << destination << ", " << protocol << ")");
Ipv4Header ipHeader;
ipHeader.SetSource (source);
@@ -400,36 +591,54 @@ Ipv4L3Protocol::SendRealOut (bool found,
Packet packet,
Ipv4Header const &ipHeader)
{
NS_DEBUG("Ipv4L3Protocol::SendRealOut (" << found << ", " << &route <<
", " << &packet << &ipHeader << ")");
if (!found)
{
NS_DEBUG ("no route to host. drop.");
NS_DEBUG ("Ipv4L3Protocol::SendRealOut (): No route to host. Drop.");
m_dropTrace (packet);
return;
}
NS_DEBUG ("Ipv4L3Protocol::SendRealOut (): Send via interface " <<
route.GetInterface ());
packet.AddHeader (ipHeader);
Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
NS_ASSERT (packet.GetSize () <= outInterface->GetMtu ());
m_txTrace (packet, route.GetInterface ());
if (route.IsGateway ())
{
NS_DEBUG ("Ipv4L3Protocol::SendRealOut (): Send to gateway " <<
route.GetGateway ());
outInterface->Send (packet, route.GetGateway ());
}
else
{
NS_DEBUG ("Ipv4L3Protocol::SendRealOut (): Send to destination " <<
ipHeader.GetDestination ());
outInterface->Send (packet, ipHeader.GetDestination ());
}
}
bool
Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr<NetDevice> device)
Ipv4L3Protocol::Forwarding (
uint32_t ifIndex,
Packet const &packet,
Ipv4Header &ipHeader,
Ptr<NetDevice> device)
{
NS_DEBUG("Ipv4L3Protocol::Forwarding (" << ifIndex << ", " << &packet <<
", " << &ipHeader << ", " << device << ")");
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end (); i++)
{
if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ()))
{
NS_DEBUG ("for me 1");
NS_DEBUG("Ipv4L3Protocol::Forwarding (): "
"For me (destination match)");
return false;
}
}
@@ -442,7 +651,8 @@ Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr<NetD
{
if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ()))
{
NS_DEBUG ("for me 2");
NS_DEBUG("Ipv4L3Protocol::Forwarding (): "
"For me (interface broadcast address)");
return false;
}
break;
@@ -451,78 +661,213 @@ Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr<NetD
if (ipHeader.GetDestination ().IsBroadcast ())
{
NS_DEBUG ("for me 3");
NS_DEBUG("Ipv4L3Protocol::Forwarding (): "
"For me (Ipv4Addr broadcast address)");
return false;
}
if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ()))
{
NS_DEBUG ("for me 4");
NS_DEBUG("Ipv4L3Protocol::Forwarding (): "
"For me (Ipv4Addr any address)");
return false;
}
if (ipHeader.GetTtl () == 1)
{
// Should send ttl expired here
// XXX
NS_DEBUG ("not for me -- ttl expired. drop.");
NS_DEBUG("Ipv4L3Protocol::Forwarding (): "
"Not for me (TTL expired). Drop");
m_dropTrace (packet);
return true;
}
ipHeader.SetTtl (ipHeader.GetTtl () - 1);
NS_DEBUG ("not for me -- forwarding.");
Lookup (ipHeader, packet,
NS_DEBUG("Ipv4L3Protocol::Forwarding (): Forwarding packet.");
Lookup (ifIndex, ipHeader, packet,
MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
//
// If this is a to a multicast address and this node is a member of the
// indicated group we need to return false so the multicast is forwarded up.
// Note that we may have just forwarded this packet too.
//
for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin ();
i != m_multicastGroups.end (); i++)
{
if ((*i).first.IsEqual (ipHeader.GetSource ()) &&
(*i).second.IsEqual (ipHeader.GetDestination ()))
{
NS_DEBUG("Ipv4L3Protocol::Forwarding (): "
"For me (Joined multicast group)");
return false;
}
}
NS_DEBUG("Ipv4L3Protocol::Forwarding (): Not for me.");
return true;
}
void
Ipv4L3Protocol::ForwardUp (Packet p, Ipv4Header const&ip)
{
NS_DEBUG("Ipv4L3Protocol::ForwardUp (" << &p << ", " << &ip << ")");
Ptr<Ipv4L4Demux> demux = m_node->QueryInterface<Ipv4L4Demux> (Ipv4L4Demux::iid);
Ptr<Ipv4L4Protocol> protocol = demux->GetProtocol (ip.GetProtocol ());
protocol->Receive (p, ip.GetSource (), ip.GetDestination ());
}
void
Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
{
NS_DEBUG("Ipv4L3Protocol::JoinMulticastGroup (" << origin << ", " <<
group << ")");
m_multicastGroups.push_back(
std::pair<Ipv4Address, Ipv4Address> (origin, group));
}
void
Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
{
NS_DEBUG("Ipv4L3Protocol::LeaveMulticastGroup (" << origin << ", " <<
group << ")");
for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin ();
i != m_multicastGroups.end ();
i++)
{
if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group))
{
m_multicastGroups.erase (i);
return;
}
}
}
void
Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address)
{
NS_DEBUG("Ipv4L3Protocol::SetAddress (" << i << ", " << address << ")");
Ptr<Ipv4Interface> interface = GetInterface (i);
interface->SetAddress (address);
}
void
Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask)
{
NS_DEBUG("Ipv4L3Protocol::SetNetworkMask (" << i << ", " << mask << ")");
Ptr<Ipv4Interface> interface = GetInterface (i);
interface->SetNetworkMask (mask);
}
Ipv4Mask
Ipv4L3Protocol::GetNetworkMask (uint32_t i) const
{
NS_DEBUG("Ipv4L3Protocol::GetNetworkMask (" << i << ")");
Ptr<Ipv4Interface> interface = GetInterface (i);
return interface->GetNetworkMask ();
}
Ipv4Address
Ipv4L3Protocol::GetAddress (uint32_t i) const
{
NS_DEBUG("Ipv4L3Protocol::GetAddress (" << i << ")");
Ptr<Ipv4Interface> interface = GetInterface (i);
return interface->GetAddress ();
}
bool
Ipv4L3Protocol::GetIfIndexForDestination (
Ipv4Address destination, uint32_t& ifIndex) const
{
NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (" << destination <<
", " << &ifIndex << ")");
//
// The first thing we do in trying to determine a source address is to
// consult the routing protocols. These will also check for a default route
// if one has been set.
//
for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
i != m_routingProtocols.end ();
i++)
{
NS_DEBUG("Ipv4L3Protocol::Lookup (): Requesting Source Address");
uint32_t ifIndexTmp;
if ((*i).second->RequestIfIndex (destination, ifIndexTmp))
{
NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): "
"Found ifIndex " << ifIndexTmp);
ifIndex = ifIndexTmp;
return true;
}
}
//
// If there's no routing table entry telling us what *single* interface will
// be used to send a packet to this destination, we'll have to just pick one.
// If there's only one interface on this node, a good answer isn't very hard
// to come up with. Before jumping to any conclusions, remember that the
// zeroth interface is the loopback interface, so what we actually want is
// a situation where there are exactly two interfaces on the node, in which
// case interface one is the "single" interface connected to the outside world.
//
if (GetNInterfaces () == 2)
{
NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): "
"One Interface. Using interface 1.");
ifIndex = 1;
return true;
}
//
// If we fall through to here, we have a node with multiple interfaces and
// no routes to guide us in determining what interface to choose. Either
// no default route was found (for unicast or multicast), or in the case of a
// multicast, the default route contained multiple outbound interfaces.
//
// The fallback position is to just get the unicast default route and use
// the outgoing interface specified there. We don't want to leave the source
// address unset, so we just assert here.
//
// N.B. that in the case of a multicast with a route containing multiple
// outgoing interfaces, the source address of packets from that node will be
// set to the IP address of the interface set in the default unicast route.
// Also, in the case of a broadcast, the same will be true.
//
NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): "
"Using default unicast route");
Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
NS_ASSERT_MSG(route,
"Ipv4L3Protocol::GetIfIndexForDestination (): "
"Unable to determine outbound interface. No default route set");
ifIndex = route->GetInterface ();
NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): "
"Default route specifies interface " << ifIndex);
return true;
}
uint16_t
Ipv4L3Protocol::GetMtu (uint32_t i) const
{
NS_DEBUG("Ipv4L3Protocol::GetMtu (" << i << ")");
Ptr<Ipv4Interface> interface = GetInterface (i);
return interface->GetMtu ();
}
bool
Ipv4L3Protocol::IsUp (uint32_t i) const
{
NS_DEBUG("Ipv4L3Protocol::IsUp (" << i << ")");
Ptr<Ipv4Interface> interface = GetInterface (i);
return interface->IsUp ();
}
void
Ipv4L3Protocol::SetUp (uint32_t i)
{
NS_DEBUG("Ipv4L3Protocol::SetUp (" << i << ")");
Ptr<Ipv4Interface> interface = GetInterface (i);
interface->SetUp ();
@@ -536,9 +881,11 @@ Ipv4L3Protocol::SetUp (uint32_t i)
interface->GetNetworkMask (), i);
}
}
void
Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
{
NS_DEBUG("Ipv4L3Protocol::SetDown (" << ifaceIndex << ")");
Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
interface->SetDown ();

View File

@@ -169,15 +169,37 @@ public:
Ipv4Route *GetRoute (uint32_t i);
void RemoveRoute (uint32_t i);
void AddMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces);
void SetDefaultMulticastRoute (uint32_t onputInterface);
uint32_t GetNMulticastRoutes (void) const;
Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
void RemoveMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface);
void RemoveMulticastRoute (uint32_t i);
uint32_t AddInterface (Ptr<NetDevice> device);
Ptr<Ipv4Interface> GetInterface (uint32_t i) const;
uint32_t GetNInterfaces (void) const;
uint32_t FindInterfaceForAddr (Ipv4Address addr) const;
uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const;
void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
void SetAddress (uint32_t i, Ipv4Address address);
void SetNetworkMask (uint32_t i, Ipv4Mask mask);
Ipv4Mask GetNetworkMask (uint32_t t) const;
Ipv4Address GetAddress (uint32_t i) const;
bool GetIfIndexForDestination (Ipv4Address destination,
uint32_t& ifIndex) const;
uint16_t GetMtu (uint32_t i) const;
bool IsUp (uint32_t i) const;
void SetUp (uint32_t i);
@@ -192,17 +214,26 @@ protected:
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
private:
void Lookup (uint32_t ifIndex,
Ipv4Header const &ipHeader,
Packet packet,
Ipv4RoutingProtocol::RouteReplyCallback routeReply);
void SendRealOut (bool found,
Ipv4Route const &route,
Packet packet,
Ipv4Header const &ipHeader);
bool Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr<NetDevice> device);
bool Forwarding (uint32_t ifIndex,
Packet const &packet,
Ipv4Header &ipHeader,
Ptr<NetDevice> device);
void ForwardUp (Packet p, Ipv4Header const&ip);
uint32_t AddIpv4Interface (Ptr<Ipv4Interface> interface);
void SetupLoopback (void);
typedef std::list<Ptr<Ipv4Interface> > Ipv4InterfaceList;
typedef std::list<std::pair<Ipv4Address, Ipv4Address> >
Ipv4MulticastGroupList;
typedef std::list< std::pair< int, Ptr<Ipv4RoutingProtocol> > > Ipv4RoutingProtocolList;
Ipv4InterfaceList m_interfaces;
@@ -217,6 +248,7 @@ private:
Ipv4RoutingProtocolList m_routingProtocols;
Ptr<Ipv4StaticRouting> m_staticRouting;
Ipv4MulticastGroupList m_multicastGroups;
};
} // Namespace ns3

View File

@@ -19,25 +19,41 @@
* Authors:
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
*/
#include "ns3/debug.h"
#include "ns3/net-device.h"
#include "ns3/node.h"
#include "ns3/eui48-address.h"
#include "ipv4-loopback-interface.h"
#include "ipv4-l3-protocol.h"
NS_DEBUG_COMPONENT_DEFINE ("Ipv4LoopbackInterface");
namespace ns3 {
Ipv4LoopbackInterface::Ipv4LoopbackInterface (Ptr<Node> node)
: Ipv4Interface (0),
m_node (node)
{}
{
NS_DEBUG("Ipv4LoopbackInterface::Ipv4LoopbackInterface ()");
}
Ipv4LoopbackInterface::~Ipv4LoopbackInterface ()
{}
{
NS_DEBUG("Ipv4LoopbackInterface::~Ipv4LoopbackInterface ()");
}
void
Ipv4LoopbackInterface::SendTo (Packet packet, Ipv4Address dest)
{
Ptr<Ipv4L3Protocol> ipv4 = m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
ipv4->Receive (GetDevice (), packet, Ipv4L3Protocol::PROT_NUMBER, Eui48Address ("ff:ff:ff:ff:ff:ff"));
NS_DEBUG("Ipv4LoopbackInterface::SendTo (" << &packet << ", " <<
dest << ")");
Ptr<Ipv4L3Protocol> ipv4 =
m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
ipv4->Receive (GetDevice (), packet, Ipv4L3Protocol::PROT_NUMBER,
Eui48Address ("ff:ff:ff:ff:ff:ff"));
}
}//namespace ns3

View File

@@ -19,22 +19,30 @@
// Author: George F. Riley<riley@ece.gatech.edu>
// Gustavo Carneiro <gjc@inescporto.pt>
#include "ns3/debug.h"
#include "ipv4-static-routing.h"
#include "ns3/packet.h"
NS_DEBUG_COMPONENT_DEFINE ("Ipv4StaticRouting");
namespace ns3 {
Ipv4StaticRouting::Ipv4StaticRouting ()
: m_defaultRoute (0), m_defaultMulticastRoute (0)
{
}
void
Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest,
Ipv4Address nextHop,
uint32_t interface)
{
Ipv4Route *route = new Ipv4Route ();
*route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface);
m_hostRoutes.push_back (route);
}
void
Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest,
uint32_t interface)
@@ -43,6 +51,7 @@ Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest,
*route = Ipv4Route::CreateHostRouteTo (dest, interface);
m_hostRoutes.push_back (route);
}
void
Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network,
Ipv4Mask networkMask,
@@ -56,6 +65,7 @@ Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network,
interface);
m_networkRoutes.push_back (route);
}
void
Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network,
Ipv4Mask networkMask,
@@ -67,6 +77,7 @@ Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network,
interface);
m_networkRoutes.push_back (route);
}
void
Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop,
uint32_t interface)
@@ -77,6 +88,168 @@ Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop,
m_defaultRoute = route;
}
void
Ipv4StaticRouting::AddMulticastRoute(Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces)
{
Ipv4MulticastRoute *route = new Ipv4MulticastRoute ();
*route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group,
inputInterface, outputInterfaces);
m_multicastRoutes.push_back (route);
}
void
Ipv4StaticRouting::SetDefaultMulticastRoute(uint32_t outputInterface)
{
Ipv4Address origin = Ipv4Address::GetAny ();
Ipv4Address group = Ipv4Address::GetAny ();
uint32_t inputInterface = Ipv4RoutingProtocol::IF_INDEX_ANY;
std::vector<uint32_t> outputInterfaces (1);
outputInterfaces[0] = outputInterface;
Ipv4MulticastRoute *route = new Ipv4MulticastRoute ();
*route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group,
inputInterface, outputInterfaces);
delete m_defaultMulticastRoute;
m_defaultMulticastRoute = route;
}
uint32_t
Ipv4StaticRouting::GetNMulticastRoutes (void) const
{
return m_multicastRoutes.size () + m_defaultMulticastRoute ? 1 : 0;
}
Ipv4MulticastRoute *
Ipv4StaticRouting::GetMulticastRoute (uint32_t index) const
{
NS_ASSERT_MSG(index < m_multicastRoutes.size (),
"Ipv4StaticRouting::GetMulticastRoute (): Index out of range");
//
// From an external point of view the default route appears to be in slot 0
// of the routing table. The implementation, however, puts it in a separate
// place. So, if a client asks for index 0 and we have a default multicast
// route, we have to return it from that different place
// (m_defaultMulticastRoute).
//
if (index == 0 && m_defaultMulticastRoute != 0)
{
return m_defaultMulticastRoute;
}
//
// If there is a default multicast route present, a client will just assume
// that it is in slot zero and there is one "extra" zeroth route in the table.
// To return the correct indexed entry in our list, we have to decrement the
// index to take into account the default route not being in the actual list.
// Since we fell through to here, we've taken care of the case where the
// index was zero.
//
if (m_defaultMulticastRoute != 0)
{
NS_ASSERT(index > 0);
index--;
}
if (index < m_multicastRoutes.size ())
{
uint32_t tmp = 0;
for (MulticastRoutesCI i = m_multicastRoutes.begin ();
i != m_multicastRoutes.end ();
i++)
{
if (tmp == index)
{
return *i;
}
tmp++;
}
}
return 0;
}
Ipv4MulticastRoute *
Ipv4StaticRouting::GetDefaultMulticastRoute () const
{
if (m_defaultMulticastRoute != 0)
{
return m_defaultMulticastRoute;
}
return 0;
}
bool
Ipv4StaticRouting::RemoveMulticastRoute(Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface)
{
//
// This method does not attempt to delete the multicast route.
//
for (MulticastRoutesI i = m_multicastRoutes.begin ();
i != m_multicastRoutes.end ();
i++)
{
Ipv4MulticastRoute *route = *i;
if (origin == route->GetOrigin () &&
group == route->GetGroup () &&
inputInterface == route->GetInputInterface ())
{
delete *i;
m_multicastRoutes.erase (i);
return true;
}
}
return false;
}
void
Ipv4StaticRouting::RemoveMulticastRoute(uint32_t index)
{
//
// From an external point of view the default route appears to be in slot 0
// of the routing table. The implementation, however, puts it in a separate
// place. So, if a client asks to delete index 0 and we have a default
// multicast route set, we have to delete it from that different place
// (m_defaultMulticastRoute).
//
if (index == 0 && m_defaultMulticastRoute != 0)
{
delete m_defaultMulticastRoute;
m_defaultMulticastRoute = 0;
}
//
// If there is a default multicast route present, a client will just assume
// that it is in slot zero and there is one "extra" zeroth route in the table.
// To return the correct indexed entry in our list, we have to decrement the
// index to take into account the default route not being in the actual list.
// Since we fell through to here, we've taken care of the case where the
// index was zero.
//
if (m_defaultMulticastRoute != 0)
{
NS_ASSERT(index > 0);
index--;
}
uint32_t tmp = 0;
for (MulticastRoutesI i = m_multicastRoutes.begin ();
i != m_multicastRoutes.end ();
i++)
{
if (tmp == index)
{
delete *i;
m_multicastRoutes.erase (i);
return;
}
tmp++;
}
}
Ipv4Route *
Ipv4StaticRouting::LookupStatic (Ipv4Address dest)
{
@@ -110,6 +283,110 @@ Ipv4StaticRouting::LookupStatic (Ipv4Address dest)
return 0;
}
Ipv4MulticastRoute *
Ipv4StaticRouting::LookupStatic (
Ipv4Address origin,
Ipv4Address group,
uint32_t ifIndex)
{
//
// We treat the "any" address (typically 0.0.0.0) as a wildcard in our matching
// scheme.
//
Ipv4Address wildcard = Ipv4Address::GetAny ();
for (MulticastRoutesI i = m_multicastRoutes.begin ();
i != m_multicastRoutes.end ();
i++)
{
Ipv4MulticastRoute *route = *i;
//
// We've been passed an origin address, a multicast group address and an
// interface index. We have to decide if the current route in the list is
// a match.
//
// The first case is the restrictive case where the origin, group and index
// matches. This picks up exact routes during forwarded and exact routes from
// the local node (in which case the ifIndex is a wildcard).
//
if (origin == route->GetOrigin () && group == route->GetGroup ())
{
if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY ||
ifIndex == route->GetInputInterface ())
{
return *i;
}
}
}
//
// If the input interface index is not a wildcard (that means that the packet
// did not originally come from this node), we're done. We don't
// just happily forward packets we don't really know what to do with.
// Multicast storms are not generally considered a good thing.
//
if (ifIndex != Ipv4RoutingProtocol::IF_INDEX_ANY)
{
return 0;
}
//
// Now, we're going to get a litle less restricive. This only applies in the
// case where the packet in question is coming from the local node. In order
// to avoid dependencies on the order in which routes were added, we will
// actually walk the list two more times, the first time looking for routes
// with a single wildcard, and the last time looking for the first route
// with two wildcards.
//
for (MulticastRoutesI i = m_multicastRoutes.begin ();
i != m_multicastRoutes.end ();
i++)
{
Ipv4MulticastRoute *route = *i;
//
// Here we will ignore the origin. We know that a single source address must
// be picked for a packet, but we may want to send multicast packets out
// multiple interfaces. To support this case, a user would need to add
// a Multicast route with the route's origin set to wildcard. N.B As a
// result, packets sourced from a node with multiple interface may have a
// source IP address different from that of the interface actually used to
// send the packet.
//
if (route->GetOrigin () == wildcard && group == route->GetGroup ())
{
return *i;
}
}
//
// Finally we want to allow users to specify a default route that specifies
// sending all multicast packets out multiple interfaces. The standard
// default multicast route is patterned after other systems and limits the
// number of outputs to one. If, however a client manually adds a multicast
// route with the origin, the multicast group and the input interface index
// all set to wildcard, she has created a default route with multiple output
// interfaces.
//
for (MulticastRoutesI i = m_multicastRoutes.begin ();
i != m_multicastRoutes.end ();
i++)
{
Ipv4MulticastRoute *route = *i;
if (route->GetOrigin () == wildcard && route->GetGroup () == wildcard)
{
return *i;
}
}
//
// We also allow users to specify a typical default multicast route. This
// default route is limited to specifying a single output interface.
//
if (m_defaultMulticastRoute != 0)
{
return m_defaultMulticastRoute;
}
return 0;
}
uint32_t
Ipv4StaticRouting::GetNRoutes (void)
{
@@ -122,6 +399,20 @@ Ipv4StaticRouting::GetNRoutes (void)
n += m_networkRoutes.size ();
return n;
}
Ipv4Route *
Ipv4StaticRouting::GetDefaultRoute ()
{
if (m_defaultRoute != 0)
{
return m_defaultRoute;
}
else
{
return 0;
}
}
Ipv4Route *
Ipv4StaticRouting::GetRoute (uint32_t index)
{
@@ -209,10 +500,52 @@ Ipv4StaticRouting::RemoveRoute (uint32_t index)
}
bool
Ipv4StaticRouting::RequestRoute (Ipv4Header const &ipHeader,
Packet packet,
RouteReplyCallback routeReply)
Ipv4StaticRouting::RequestRoute (
uint32_t ifIndex,
Ipv4Header const &ipHeader,
Packet packet,
RouteReplyCallback routeReply)
{
NS_DEBUG ("Ipv4StaticRouting::RequestRoute (" << &ipHeader << ", " <<
&packet << ", " << &routeReply << ")");
NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): source = " <<
ipHeader.GetSource ());
NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): destination = " <<
ipHeader.GetDestination ());
if (ipHeader.GetDestination ().IsMulticast ())
{
NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast destination");
Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (),
ipHeader.GetDestination (), ifIndex);
if (mRoute)
{
NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): "
"Multicast route found");
for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i)
{
Packet p = packet;
Ipv4Header h = ipHeader;
Ipv4Route route =
Ipv4Route::CreateHostRouteTo(h.GetDestination (),
mRoute->GetOutputInterface(i));
NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): "
"Send via interface " << mRoute->GetOutputInterface(i));
routeReply (true, route, p, h);
}
return true;
}
return false; // Let other routing protocols try to handle this
}
//
// This is a unicast packet. Check to see if we have a route for it.
//
NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Unicast destination");
Ipv4Route *route = LookupStatic (ipHeader.GetDestination ());
if (route != 0)
{
@@ -226,6 +559,57 @@ Ipv4StaticRouting::RequestRoute (Ipv4Header const &ipHeader,
}
}
bool
Ipv4StaticRouting::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex)
{
NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (" << destination << ", " <<
&ifIndex << ")");
//
// First, see if this is a multicast packet we have a route for. If we
// have a route, then send the packet down each of the specified interfaces.
//
if (destination.IsMulticast ())
{
NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): Multicast destination");
Ipv4MulticastRoute *mRoute = LookupStatic(Ipv4Address::GetAny (),
destination, Ipv4RoutingProtocol::IF_INDEX_ANY);
if (mRoute)
{
NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): "
"Multicast route found");
if (mRoute->GetNOutputInterfaces () != 1)
{
NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): "
"Route is to multiple interfaces. Ignoring.");
return false;
}
ifIndex = mRoute->GetOutputInterface(0);
NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): "
"Found ifIndex " << ifIndex);
return true;
}
return false; // Let other routing protocols try to handle this
}
//
// See if this is a unicast packet we have a route for.
//
NS_DEBUG ("Ipv4StaticRouting::RequestIfIndex (): Unicast destination");
Ipv4Route *route = LookupStatic (destination);
if (route)
{
ifIndex = route->GetInterface ();
return true;
}
else
{
return false;
}
}
void
Ipv4StaticRouting::DoDispose (void)
{
@@ -246,8 +630,18 @@ Ipv4StaticRouting::DoDispose (void)
delete m_defaultRoute;
m_defaultRoute = 0;
}
for (MulticastRoutesI i = m_multicastRoutes.begin ();
i != m_multicastRoutes.end ();
i = m_multicastRoutes.erase (i))
{
delete (*i);
}
if (m_defaultMulticastRoute != 0)
{
delete m_defaultMulticastRoute;
m_defaultMulticastRoute = 0;
}
Ipv4RoutingProtocol::DoDispose ();
}
}//namespace ns3

View File

@@ -45,36 +45,441 @@ class TraceResolver;
class TraceContext;
/**
* @brief Static routing protocol for IP version 4 stacks.
*
* In ns-3 we have the concept of a pluggable routing protocol. Routing
* protocols are added to a list maintained by the Ipv4L3Protocol. Every
* stack gets one routing protocol for free -- the Ipv4StaticRouting routing
* protocol is added in the constructor of the Ipv4L3Protocol (this is the
* piece of code that implements the functionality of the IP layer).
*
* The Ipv4StaticRouting class inherits from the abstract base class
* Ipv4RoutingProtocol that defines the interface methods that a routing
* protocol must support.
*
* When a packet arrives in the Ipv4L3Protocol for transmission, it comes
* either from a local source via Ipv4L3Protocol::Send or from a remote
* source via Ipv4L3Protocol::Forwarding. In both cases, a function is called
* (Ipv4L3Protocol::Lookup) to look up the routing information for the packet.
*
* The lookup function iterates through the list of routing protocols asking
* each to see if it can find a route and send the packet. A callback is
* provided during each of these calls that should be considered a pre-
* packaged send call. This is done to allow asynchronous calls into
* routing subsystems in order to support on-demand routing, for example. The
* method for requesting this operation is Ipv4StaticRouting::RequestRoute for
* the static routing protocol.
*
* Each routing protocol is also free to implement its own methods for managing
* routes which you will find below. This class manages a set of "static" or
* manually configured routes for host, network and multicast routes.
*
* @see Ipv4RoutingProtocol
* @see Ipv4L3Protocol::AddRoutingProtocol
* @see Ipv4L3Protocol::Ipv4L3Protocol
*/
class Ipv4StaticRouting : public Ipv4RoutingProtocol
{
public:
Ipv4StaticRouting () : m_defaultRoute (0) {}
/**
* @brief Construct an empty Ipv4StaticRouting routing protocol,
* @internal
*
* The Ipv4StaticRouting class supports host, network and multicast routes.
* This method initializes the lists containing these routes to empty.
*
* @see Ipv4StaticRouting
*/
Ipv4StaticRouting ();
virtual bool RequestRoute (Ipv4Header const &ipHeader,
/**
* @brief Request that a check for a route bw performed and if a route is found
* that the packet be sent on its way using the pre-packaged send callback.
*
* The source and destination IP addresses for the packet in question are found
* in the provided Ipv4Header. There are two major processing forks depending
* on the type of destination address.
*
* If the destination address is unicast then the routing table is consulted
* for a route to the destination and if it is found, the routeReply callback
* is executed to send the packet (with the found route).
*
* If the destination address is a multicast, then the exact processing steps
* depend on whether or not the packet has been sourced locally. This is
* determined by the parameter ifIndex. This is the interface index over which
* this packet was received. If the packet has not been received over a
* network interface, this index will be set to
* Ipv4RoutingProtocol::IF_INDEX_ANY (a very large number). In that case,
* we want to avoid the requirement that an explicit route out of each node
* must be set, so we don't do anything here.
*
* If the packet is a multicast destination and has been received over a
* network interface, a call to this method implies that the packet is being
* forwarded. In that case, there must be an explicit route out of the node.
* A multicast route references the source address, the destination address
* (the multicast group) and the input interface in order to find a route.
* We consult the multicast routing table and, if a route is found, send the
* packet out of as many interfaces as required using the provided callback
* (think of it as a pre-packaged send call).
*
* @param ifIndex The network interface index over which the packed was
* received. If the packet is from a local source, ifIndex will be set to
* Ipv4RoutingProtocol::IF_INDEX_ANY.
* @param ipHeader the Ipv4Header containing the source and destination IP
* addresses for the packet.
* @param packet The packet to be sent if a route is found.
* @param routeReply A callback that packaged up the call to actually send the
* packet.
* @return Returns true if a route is found and the packet has been sent,
* otherwise returns false indicating that the next routing protocol should
* be consulted. In practice, the static routing protocol is the last chance
* protocol.
*
* @see Ipv4StaticRouting
* @see Ipv4RoutingProtocol
*/
virtual bool RequestRoute (uint32_t ifIndex,
Ipv4Header const &ipHeader,
Packet packet,
RouteReplyCallback routeReply);
/**
* @brief Check to see if we can determine the interface index that will be
* used if a packet is sent to this destination.
*
* This method addresses a problem in the IP stack where a destination address
* must be present and checksummed into the IP header before the actual
* interface over which the packet is sent can be determined. The answer is
* to implement a known and intentional cross-layer violation. This is the
* endpoint of a call chain that started up quite high in the stack (sockets)
* and has found its way down to the Ipv4L3Protocol which is consulting the
* routing protocols for what they would do if presented with a packet of the
* given destination.
*
* Note that the a single interface index is returned. This means that if
* the destination address is a multicast, and an explicit route is present
* that includeds multiple output interfaces, that route cannot be used.
*
* If there are multiple paths out of the node, the resolution is performed
* by Ipv4L3Protocol::GetIfIndexforDestination which has access to more
* contextual information that is useful for making a determination.
*
* @param destination The Ipv4Address if the destination of a hypothetical
* packet. This may be a multicast group address.
* @param ifIndex A reference to the interface index over which a packet
* sent to this destination would be sent.
* @return Returns true if a route is found to the destination that involves
* a single output interface index, otherwise returns false indicating that
* the next routing protocol should be consulted. In practice, the static
* routing protocol is the last chance protocol.
*
* @see Ipv4StaticRouting
* @see Ipv4RoutingProtocol
* @see Ipv4L3Protocol
*/
virtual bool RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex);
/**
* @brief Add a host route to the static routing table.
*
* @param dest The Ipv4Address destination for this route.
* @param nextHop The Ipv4Address of the next hop in the route.
* @param interface The network interface index used to send packets to the
* destination.
*
* @see Ipv4Address
*/
void AddHostRouteTo (Ipv4Address dest,
Ipv4Address nextHop,
uint32_t interface);
/**
* @brief Add a host route to the static routing table.
*
* @param dest The Ipv4Address destination for this route.
* @param interface The network interface index used to send packets to the
* destination.
*
* @see Ipv4Address
*/
void AddHostRouteTo (Ipv4Address dest,
uint32_t interface);
/**
* @brief Add a network route to the static routing table.
*
* @param network The Ipv4Address network for this route.
* @param networkmask The Ipv4Mask to extract the network.
* @param nextHop The next hop in the route to the destination network.
* @param interface The network interface index used to send packets to the
* destination.
*
* @see Ipv4Address
*/
void AddNetworkRouteTo (Ipv4Address network,
Ipv4Mask networkMask,
Ipv4Address nextHop,
uint32_t interface);
/**
* @brief Add a network route to the static routing table.
*
* @param network The Ipv4Address network for this route.
* @param networkmask The Ipv4Mask to extract the network.
* @param interface The network interface index used to send packets to the
* destination.
*
* @see Ipv4Address
*/
void AddNetworkRouteTo (Ipv4Address network,
Ipv4Mask networkMask,
uint32_t interface);
/**
* @brief Add a default route to the static routing table.
*
* This method tells the routing system what to do in the case where a specific
* route to a destination is not found. The system forwards packets to the
* specified node in the hope that it knows better how to route the packet.
*
* If the default route is set, it is returned as the selected route from
* LookupStatic irrespective of destination address if no specific route is
* found.
*
* @param nextHop The Ipv4Address to send packets to in the hope that they
* will be forwarded correctly.
* @param interface The network interface index used to send packets.
*
* @see Ipv4Address
* @see Ipv4StaticRouting::Lookup
*/
void SetDefaultRoute (Ipv4Address nextHop,
uint32_t interface);
/**
* @brief Get the number of individual unicast routes that have been added
* to the routing table.
*
* @warning The default route counts as one of the routes.
*/
uint32_t GetNRoutes (void);
/**
* @brief Get the default route from the static routing table.
*
* @return If the default route is set, a pointer to that Ipv4Route is
* returned, otherwise a zero pointer is returned.
*
* @see Ipv4Route
*/
Ipv4Route *GetDefaultRoute (void);
/**
* @brief Get a route from the static unicast routing table.
*
* Externally, the unicast static routing table appears simply as a table with
* n entries. The one sublety of note is that if a default route has been set
* it will appear as the zeroth entry in the table. This means that if you
* add only a default route, the table will have one entry that can be accessed
* either by explicity calling GetDefaultRoute () or by calling GetRoute (0).
*
* Similarly, if the default route has been set, calling RemoveRoute (0) will
* remove the default route.
*
* @param i The index (into the routing table) of the route to retrieve. If
* the default route has been set, it will occupy index zero.
* @return If route is set, a pointer to that Ipv4Route is returned, otherwise
* a zero pointer is returned.
*
* @see Ipv4Route
* @see Ipv4StaticRouting::RemoveRoute
*/
Ipv4Route *GetRoute (uint32_t i);
/**
* @brief Remove a route from the static unicast routing table.
*
* Externally, the unicast static routing table appears simply as a table with
* n entries. The one sublety of note is that if a default route has been set
* it will appear as the zeroth entry in the table. This means that if the
* default route has been set, calling RemoveRoute (0) will remove the
* default route.
*
* @param i The index (into the routing table) of the route to remove. If
* the default route has been set, it will occupy index zero.
*
* @see Ipv4Route
* @see Ipv4StaticRouting::GetRoute
* @see Ipv4StaticRouting::AddRoute
*/
void RemoveRoute (uint32_t i);
/**
* @brief Add a multicast route to the static routing table.
*
* A multicast route must specify an origin IP address, a multicast group and
* an input network interface index as conditions and provide a vector of
* output network interface indices over which packets matching the conditions
* are sent.
*
* Typically there are two main types of multicast routes: routes of the
* first kind are used during forwarding. All of the conditions must be
* exlicitly provided. The second kind of routes are used to get packets off
* of a local node. The difference is in the input interface. Routes for
* forwarding will always have an explicit input interface specified. Routes
* off of a node will always set the input interface to a wildcard specified
* by the index Ipv4RoutingProtocol::IF_INDEX_ANY.
*
* For routes off of a local node wildcards may be used in the origin and
* multicast group addresses. The wildcard used for Ipv4Adresses is that
* address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage
* of a wildcard allows one to specify default behavior to varying degrees.
*
* For example, making the origin address a wildcard, but leaving the
* multicast group specific allows one (in the case of a node with multiple
* interfaces) to create different routes using different output interfaces
* for each multicast group.
*
* If the origin and multicast addresses are made wildcards, you have created
* essentially a default multicast address that can forward to multiple
* interfaces. Compare this to the actual default multicast address that is
* limited to specifying a single output interface for compatibility with
* existing functionality in other systems.
*
* @param origin The Ipv4Address of the origin of packets for this route. May
* be Ipv4Address:GetAny for open groups.
* @param group The Ipv4Address of the multicast group or this route.
* @param inputInterface The input network interface index over which to
* expect packets destined for this route. May be
* Ipv4RoutingProtocol::IF_INDEX_ANY for packets of local origin.
* @param outputInterface A vector of network interface indices used to specify
* how to send packets to the destination(s).
*
* @see Ipv4Address
*/
void AddMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces);
/**
* @brief Add a default multicast route to the static routing table.
*
* This is the multicast equivalent of the unicast version SetDefaultRoute.
* We tell the routing system what to do in the case where a specific route
* to a destination multicast group is not found. The system forwards
* packets out the specified interface in the hope that "something out there"
* knows better how to route the packet. This method is only used in
* initially sending packets off of a host. The default multicast route is
* not consulted during forwarding -- exact routes must be specified using
* AddMulticastRoute for that case.
*
* Since we're basically sending packets to some entity we think may know
* better what to do, we don't pay attention to "subtleties" like origin
* address, nor do we worry about forwarding out multiple interfaces. If the
* default multicast route is set, it is returned as the selected route from
* LookupStatic irrespective of origin or multicast group if another specific
* route is not found.
*
* @param outputInterface The network interface index used to specify where
* to send packets in the case of unknown routes.
*
* @see Ipv4Address
*/
void SetDefaultMulticastRoute (uint32_t outputInterface);
/**
* @brief Get the number of individual multicast routes that have been added
* to the routing table.
*
* @warning The default multicast route counts as one of the routes.
*/
uint32_t GetNMulticastRoutes (void) const;
/**
* @brief Get a route from the static multicast routing table.
*
* Externally, the multicast static routing table appears simply as a table
* with n entries. The one sublety of note is that if a default route has
* been set it will appear as the zeroth entry in the table. This means that
* if you add only a default route, the table will have one entry that can be
* accessed either by explicity calling GetDefaultMulticastRoute () or by
* calling GetMulticastRoute (0).
*
* Similarly, if the default route has been set, calling
* RemoveMulticastRoute (0) will remove the default route.
*
* @param i The index (into the routing table) of the multicast route to
* retrieve. If the default route has been set, it will occupy index zero.
* @return If route <i> is set, a pointer to that Ipv4MulticastRoute is
* returned, otherwise a zero pointer is returned.
*
* @see Ipv4MulticastRoute
* @see Ipv4StaticRouting::RemoveRoute
*/
Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
/**
* @brief Get the default multicast route from the static routing table.
*
* @return If the default route is set, a pointer to that Ipv4MulticastRoute is
* returned, otherwise a zero pointer is returned.
*
* @see Ipv4Route
*/
Ipv4MulticastRoute *GetDefaultMulticastRoute (void) const;
/**
* @brief Remove a route from the static multicast routing table.
*
* Externally, the multicast static routing table appears simply as a table
* with n entries. The one sublety of note is that if a default multicast
* route has been set it will appear as the zeroth entry in the table. This
* means that the default route may be removed by calling this method with
* appropriate wildcard parameters.
*
* This method causes the multicast routing table to be searched for the first
* route that matches the parameters and removes it.
*
* Wildcards may be provided to this function, but the wildcards are used to
* exacly match wildcards in the routes (see AddMulticastRoute). That is,
* calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not
* remove routes with any address in the origin, but will only remove routes
* with "0.0.0.0" set as the the origin.
*
* @param origin The IP address specified as the origin of packets for the
* route.
* @param origin The IP address specified as the multicast group addres of
* the route.
* @param inputInterfade The network interface index specified as the expected
* input interface for the route.
* @returns True if a route was found and removed, false otherwise.
*
* @see Ipv4MulticastRoute
* @see Ipv4StaticRouting::AddMulticastRoute
*/
bool RemoveMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface);
/**
* @brief Remove a route from the static multicast routing table.
*
* Externally, the multicast static routing table appears simply as a table
* with n entries. The one sublety of note is that if a default multicast
* route has been set it will appear as the zeroth entry in the table. This
* means that if the default route has been set, calling
* RemoveMulticastRoute (0) will remove the default route.
*
* @param index The index (into the multicast routing table) of the route to
* remove. If the default route has been set, it will occupy index zero.
*
* @see Ipv4Route
* @see Ipv4StaticRouting::GetRoute
* @see Ipv4StaticRouting::AddRoute
*/
void RemoveMulticastRoute (uint32_t index);
protected:
void DoDispose (void);
@@ -86,15 +491,21 @@ private:
typedef std::list<Ipv4Route *>::const_iterator NetworkRoutesCI;
typedef std::list<Ipv4Route *>::iterator NetworkRoutesI;
typedef std::list<Ipv4MulticastRoute *> MulticastRoutes;
typedef std::list<Ipv4MulticastRoute *>::const_iterator MulticastRoutesCI;
typedef std::list<Ipv4MulticastRoute *>::iterator MulticastRoutesI;
Ipv4Route *LookupStatic (Ipv4Address dest);
Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group,
uint32_t ifIndex);
HostRoutes m_hostRoutes;
NetworkRoutes m_networkRoutes;
Ipv4Route *m_defaultRoute;
Ipv4MulticastRoute *m_defaultMulticastRoute;
MulticastRoutes m_multicastRoutes;
};
} // Namespace ns3
#endif /* IPV4_STATIC_ROUTING_H */

View File

@@ -19,6 +19,7 @@
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "ns3/debug.h"
#include "ns3/assert.h"
#include "ns3/packet.h"
#include "ns3/node.h"
@@ -30,6 +31,8 @@
#include "ipv4-l3-protocol.h"
#include "udp-socket.h"
NS_DEBUG_COMPONENT_DEFINE ("UdpL4Protocol");
namespace ns3 {
/* see http://www.iana.org/assignments/protocol-numbers */
@@ -39,14 +42,19 @@ UdpL4Protocol::UdpL4Protocol (Ptr<Node> node)
: Ipv4L4Protocol (PROT_NUMBER, 2),
m_node (node),
m_endPoints (new Ipv4EndPointDemux ())
{}
{
NS_DEBUG("UdpL4Protocol::UdpL4Protocol ()");
}
UdpL4Protocol::~UdpL4Protocol ()
{}
{
NS_DEBUG("UdpL4Protocol::~UdpL4Protocol ()");
}
void
UdpL4Protocol::DoDispose (void)
{
NS_DEBUG("UdpL4Protocol::DoDispose ()");
if (m_endPoints != 0)
{
delete m_endPoints;
@@ -59,6 +67,7 @@ UdpL4Protocol::DoDispose (void)
Ptr<Socket>
UdpL4Protocol::CreateSocket (void)
{
NS_DEBUG("UdpL4Protocol::CreateSocket ()");
Ptr<Socket> socket = Create<UdpSocket> (m_node, this);
return socket;
}
@@ -66,27 +75,36 @@ UdpL4Protocol::CreateSocket (void)
Ipv4EndPoint *
UdpL4Protocol::Allocate (void)
{
NS_DEBUG("UdpL4Protocol::Allocate ()");
return m_endPoints->Allocate ();
}
Ipv4EndPoint *
UdpL4Protocol::Allocate (Ipv4Address address)
{
NS_DEBUG("UdpL4Protocol::Allocate (" << address << ")");
return m_endPoints->Allocate (address);
}
Ipv4EndPoint *
UdpL4Protocol::Allocate (uint16_t port)
{
NS_DEBUG("UdpL4Protocol::Allocate (" << port << ")");
return m_endPoints->Allocate (port);
}
Ipv4EndPoint *
UdpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
{
NS_DEBUG("UdpL4Protocol::Allocate (" << address << ", " << port << ")");
return m_endPoints->Allocate (address, port);
}
Ipv4EndPoint *
UdpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
Ipv4Address peerAddress, uint16_t peerPort)
{
NS_DEBUG("UdpL4Protocol::Allocate (" << localAddress << ", " << localPort <<
", " << peerAddress << ", " << peerPort << ")");
return m_endPoints->Allocate (localAddress, localPort,
peerAddress, peerPort);
}
@@ -94,6 +112,7 @@ UdpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
void
UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
{
NS_DEBUG("UdpL4Protocol::Deallocate (" << endPoint << ")");
m_endPoints->DeAllocate (endPoint);
}
@@ -102,6 +121,9 @@ UdpL4Protocol::Receive(Packet& packet,
Ipv4Address const &source,
Ipv4Address const &destination)
{
NS_DEBUG("UdpL4Protocol::Receive (" << &packet << ", " << source <<
", " << destination << ")");
UdpHeader udpHeader;
packet.RemoveHeader (udpHeader);
Ipv4EndPointDemux::EndPoints endPoints =
@@ -119,6 +141,9 @@ UdpL4Protocol::Send (Packet packet,
Ipv4Address saddr, Ipv4Address daddr,
uint16_t sport, uint16_t dport)
{
NS_DEBUG("UdpL4Protocol::Send (" << &packet << ", " << saddr <<
", " << daddr << ", " << sport << ", " << dport << ")");
UdpHeader udpHeader;
udpHeader.SetDestination (dport);
udpHeader.SetSource (sport);
@@ -132,6 +157,7 @@ UdpL4Protocol::Send (Packet packet,
Ptr<Ipv4L3Protocol> ipv4 = m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
if (ipv4 != 0)
{
NS_DEBUG("UdpL4Protocol::Send (): Sending to IP");
ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
}
}

View File

@@ -18,6 +18,8 @@
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "ns3/debug.h"
#include "ns3/node.h"
#include "ns3/inet-socket-address.h"
#include "ns3/ipv4-route.h"
@@ -26,6 +28,9 @@
#include "udp-l4-protocol.h"
#include "ipv4-end-point.h"
#include "ipv4-l4-demux.h"
#include "ns3/ipv4.h"
NS_DEBUG_COMPONENT_DEFINE ("UdpSocket");
namespace ns3 {
@@ -37,9 +42,14 @@ UdpSocket::UdpSocket (Ptr<Node> node, Ptr<UdpL4Protocol> udp)
m_shutdownSend (false),
m_shutdownRecv (false),
m_connected (false)
{}
{
NS_DEBUG("UdpSocket::UdpSocket ()");
}
UdpSocket::~UdpSocket ()
{
NS_DEBUG("UdpSocket::~UdpSocket ()");
m_node = 0;
if (m_endPoint != 0)
{
@@ -62,25 +72,32 @@ UdpSocket::~UdpSocket ()
enum Socket::SocketErrno
UdpSocket::GetErrno (void) const
{
NS_DEBUG("UdpSocket::GetErrno ()");
return m_errno;
}
Ptr<Node>
UdpSocket::GetNode (void) const
{
NS_DEBUG("UdpSocket::GetNode ()");
return m_node;
}
void
UdpSocket::Destroy (void)
{
NS_DEBUG("UdpSocket::Destroy ()");
m_node = 0;
m_endPoint = 0;
m_udp = 0;
}
int
UdpSocket::FinishBind (void)
{
NS_DEBUG("UdpSocket::FinishBind ()");
if (m_endPoint == 0)
{
return -1;
@@ -93,14 +110,20 @@ UdpSocket::FinishBind (void)
int
UdpSocket::Bind (void)
{
NS_DEBUG("UdpSocket::Bind ()");
m_endPoint = m_udp->Allocate ();
return FinishBind ();
}
int
UdpSocket::Bind (const Address &address)
{
NS_DEBUG("UdpSocket::Bind (" << address << ")");
if (!InetSocketAddress::IsMatchingType (address))
{
NS_DEBUG("UdpSocket::Bind (): Not IsMatchingType");
return ERROR_INVAL;
}
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
@@ -129,12 +152,15 @@ UdpSocket::Bind (const Address &address)
int
UdpSocket::ShutdownSend (void)
{
NS_DEBUG("UdpSocket::ShutDownSend ()");
m_shutdownSend = true;
return 0;
}
int
UdpSocket::ShutdownRecv (void)
{
NS_DEBUG("UdpSocket::ShutDownRecv ()");
m_shutdownRecv = false;
return 0;
}
@@ -142,6 +168,7 @@ UdpSocket::ShutdownRecv (void)
int
UdpSocket::Close(void)
{
NS_DEBUG("UdpSocket::Close ()");
NotifyCloseCompleted ();
return 0;
}
@@ -149,24 +176,36 @@ UdpSocket::Close(void)
int
UdpSocket::Connect(const Address & address)
{
NS_DEBUG ("UdpSocket::Connect (" << address << ")");
Ipv4Route routeToDest;
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
m_defaultAddress = transport.GetIpv4 ();
m_defaultPort = transport.GetPort ();
NotifyConnectionSucceeded ();
m_connected = true;
if (GetIpv4RouteToDestination (m_node, routeToDest, m_defaultAddress) )
NS_DEBUG ("UdpSocket::Connect (): Updating local address");
uint32_t localIfIndex;
Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
if (ipv4->GetIfIndexForDestination (m_defaultAddress, localIfIndex))
{
uint32_t localIfIndex = routeToDest.GetInterface ();
Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
m_endPoint->SetLocalAddress (ipv4->GetAddress(localIfIndex) );
m_endPoint->SetLocalAddress (ipv4->GetAddress(localIfIndex));
}
NS_DEBUG ("UdpSocket::Connect (): Local address is " <<
m_endPoint->GetLocalAddress());
return 0;
}
int
UdpSocket::Send (const Packet &p)
{
NS_DEBUG("UdpSocket::Send (" << &p << ")");
if (!m_connected)
{
m_errno = ERROR_NOTCONN;
@@ -196,12 +235,14 @@ UdpSocket::DoSend (const Packet &p)
return DoSendTo (p, m_defaultAddress, m_defaultPort);
}
int
UdpSocket::DoSendTo (const Packet &p, const Address &address)
{
NS_DEBUG("UdpSocket::DoSendTo (" << &p << ", " << address << ")");
if (!m_connected)
{
NS_DEBUG("UdpSocket::DoSendTo (): Not connected");
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
@@ -210,13 +251,19 @@ UdpSocket::DoSendTo (const Packet &p, const Address &address)
else
{
// connected UDP socket must use default addresses
NS_DEBUG("UdpSocket::DoSendTo (): Connected");
return DoSendTo (p, m_defaultAddress, m_defaultPort);
}
}
int
UdpSocket::DoSendTo (const Packet &p, Ipv4Address dest, uint16_t port)
{
NS_DEBUG("UdpSocket::DoSendTo (" << &p << ", " << dest << ", " <<
port << ")");
Ipv4Route routeToDest;
if (m_endPoint == 0)
{
if (Bind () == -1)
@@ -231,13 +278,17 @@ UdpSocket::DoSendTo (const Packet &p, Ipv4Address dest, uint16_t port)
m_errno = ERROR_SHUTDOWN;
return -1;
}
uint32_t localIfIndex;
Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
//
// If dest is sent to the limited broadcast address (all ones),
// convert it to send a copy of the packet out of every interface
//
if (dest.IsBroadcast ())
{
Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
NS_DEBUG("UdpSocket::DoSendTo (): Limited broadcast");
for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
{
Ipv4Address addri = ipv4->GetAddress (i);
@@ -247,10 +298,9 @@ UdpSocket::DoSendTo (const Packet &p, Ipv4Address dest, uint16_t port)
NotifyDataSent (p.GetSize ());
}
}
else if (GetIpv4RouteToDestination (m_node, routeToDest, dest) )
else if (ipv4->GetIfIndexForDestination(dest, localIfIndex))
{
uint32_t localIfIndex = routeToDest.GetInterface ();
Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
NS_DEBUG("UdpSocket::DoSendTo (): Route exists");
m_udp->Send (p, ipv4->GetAddress (localIfIndex), dest,
m_endPoint->GetLocalPort (), port);
NotifyDataSent (p.GetSize ());
@@ -258,15 +308,18 @@ UdpSocket::DoSendTo (const Packet &p, Ipv4Address dest, uint16_t port)
}
else
{
NS_DEBUG("UdpSocket::DoSendTo (): ERROR_NOROUTETOHOST");
m_errno = ERROR_NOROUTETOHOST;
return -1;
}
return 0;
}
int
UdpSocket::SendTo(const Address &address, const Packet &p)
{
NS_DEBUG("UdpSocket::SendTo (" << address << ", " << &p << ")");
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
@@ -276,6 +329,9 @@ UdpSocket::SendTo(const Address &address, const Packet &p)
void
UdpSocket::ForwardUp (const Packet &packet, Ipv4Address ipv4, uint16_t port)
{
NS_DEBUG("UdpSocket::ForwardUp (" << &packet << ", " << ipv4 << ", " <<
port << ")");
if (m_shutdownRecv)
{
return;
@@ -286,4 +342,4 @@ UdpSocket::ForwardUp (const Packet &packet, Ipv4Address ipv4, uint16_t port)
NotifyDataReceived (p, address);
}
}//namespace ns3
} //namespace ns3

View File

@@ -30,6 +30,7 @@ namespace ns3 {
Ipv4Route::Ipv4Route ()
{}
Ipv4Route::Ipv4Route (Ipv4Route const &route)
: m_dest (route.m_dest),
m_destNetworkMask (route.m_destNetworkMask),
@@ -37,6 +38,13 @@ Ipv4Route::Ipv4Route (Ipv4Route const &route)
m_interface (route.m_interface)
{}
Ipv4Route::Ipv4Route (Ipv4Route const *route)
: m_dest (route->m_dest),
m_destNetworkMask (route->m_destNetworkMask),
m_gateway (route->m_gateway),
m_interface (route->m_interface)
{}
Ipv4Route::Ipv4Route (Ipv4Address dest,
Ipv4Address gateway,
uint32_t interface)
@@ -137,7 +145,6 @@ Ipv4Route::GetInterface (void) const
return m_interface;
}
Ipv4Route
Ipv4Route::CreateHostRouteTo (Ipv4Address dest,
Ipv4Address nextHop,
@@ -220,4 +227,108 @@ std::ostream& operator<< (std::ostream& os, Ipv4Route const& route)
return os;
}
/*****************************************************
* Ipv4MulticastRoute
*****************************************************/
Ipv4MulticastRoute::Ipv4MulticastRoute ()
{
}
Ipv4MulticastRoute::Ipv4MulticastRoute (Ipv4MulticastRoute const &route)
:
m_origin (route.m_origin),
m_group (route.m_group),
m_inputInterface (route.m_inputInterface),
m_outputInterfaces (route.m_outputInterfaces)
{
}
Ipv4MulticastRoute::Ipv4MulticastRoute (Ipv4MulticastRoute const *route)
:
m_origin (route->m_origin),
m_group (route->m_group),
m_inputInterface (route->m_inputInterface),
m_outputInterfaces (route->m_outputInterfaces)
{
}
Ipv4MulticastRoute::Ipv4MulticastRoute (
Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces)
{
m_origin = origin;
m_group = group;
m_inputInterface = inputInterface;
m_outputInterfaces = outputInterfaces;
}
Ipv4Address
Ipv4MulticastRoute::GetOrigin (void) const
{
return m_origin;
}
Ipv4Address
Ipv4MulticastRoute::GetGroup (void) const
{
return m_group;
}
uint32_t
Ipv4MulticastRoute::GetInputInterface (void) const
{
return m_inputInterface;
}
uint32_t
Ipv4MulticastRoute::GetNOutputInterfaces (void) const
{
return m_outputInterfaces.size ();
}
uint32_t
Ipv4MulticastRoute::GetOutputInterface (uint32_t n) const
{
NS_ASSERT_MSG(n < m_outputInterfaces.size (),
"Ipv4MulticastRoute::GetOutputInterface (): index out of bounds");
return m_outputInterfaces[n];
}
std::vector<uint32_t>
Ipv4MulticastRoute::GetOutputInterfaces (void) const
{
return m_outputInterfaces;
}
Ipv4MulticastRoute
Ipv4MulticastRoute::CreateMulticastRoute (
Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces)
{
return Ipv4MulticastRoute (origin, group, inputInterface, outputInterfaces);
}
std::ostream&
operator<< (std::ostream& os, Ipv4MulticastRoute const& route)
{
os << "origin=" << route.GetOrigin () <<
", group=" << route.GetGroup () <<
", input interface=" << route.GetInputInterface () <<
", output interfaces=";
for (uint32_t i = 0; i < route.GetNOutputInterfaces (); ++i)
{
os << route.GetOutputInterface (i) << " ";
}
return os;
}
}//namespace ns3

View File

@@ -22,6 +22,7 @@
#define IPV4_ROUTE_H
#include <list>
#include <vector>
#include <ostream>
#include "ipv4-address.h"
@@ -36,12 +37,19 @@ public:
* \brief This constructor does nothing
*/
Ipv4Route ();
/**
* \brief Copy Constructor
* \param route The route to copy
*/
Ipv4Route (Ipv4Route const &route);
/**
* \brief Copy Constructor
* \param route The route to copy
*/
Ipv4Route (Ipv4Route const *route);
bool IsHost (void) const;
/**
* \return The IPv4 address of the destination of this route
@@ -98,6 +106,74 @@ private:
std::ostream& operator<< (std::ostream& os, Ipv4Route const& route);
/**
* \brief A record of an IPv4 multicast route
*/
class Ipv4MulticastRoute {
public:
/**
* \brief This constructor does nothing
*/
Ipv4MulticastRoute ();
/**
* \brief Copy Constructor
* \param route The route to copy
*/
Ipv4MulticastRoute (Ipv4MulticastRoute const &route);
/**
* \brief Copy Constructor
* \param route The route to copy
*/
Ipv4MulticastRoute (Ipv4MulticastRoute const *route);
/**
* \return The IPv4 address of the source of this route
*/
Ipv4Address GetOrigin (void) const;
/**
* \return The IPv4 address of the multicast group of this route
*/
Ipv4Address GetGroup (void) const;
/**
* \return The IPv4 address of the input interface of this route
*/
uint32_t GetInputInterface (void) const;
/**
* \return The number of output interfaces of this route
*/
uint32_t GetNOutputInterfaces (void) const;
/**
* \return A specified output interface.
*/
uint32_t GetOutputInterface (uint32_t n) const;
/**
* \return A vector of all of the output interfaces of this route.
*/
std::vector<uint32_t> GetOutputInterfaces (void) const;
static Ipv4MulticastRoute CreateMulticastRoute (Ipv4Address origin,
Ipv4Address group, uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces);
private:
Ipv4MulticastRoute (Ipv4Address origin, Ipv4Address group,
uint32_t inputInterface, std::vector<uint32_t> outputInterfaces);
Ipv4Address m_origin;
Ipv4Address m_group;
uint32_t m_inputInterface;
std::vector<uint32_t> m_outputInterfaces;
};
std::ostream& operator<< (std::ostream& os, Ipv4MulticastRoute const& route);
}//namespace ns3
#endif /* IPV4_ROUTE_H */

View File

@@ -36,10 +36,10 @@ Ipv4::~Ipv4 ()
{}
uint32_t
GetIfIndexByIpv4Address (Ptr<Node> node, Ipv4Address a, Ipv4Mask amask)
Ipv4::GetIfIndexByAddress (Ptr<Node> node, Ipv4Address a, Ipv4Mask amask)
{
Ptr<Ipv4> ipv4 = node->QueryInterface<Ipv4> (Ipv4::iid);
NS_ASSERT_MSG (ipv4, "GetIfIndexByIpv4Address: No Ipv4 interface");
NS_ASSERT_MSG (ipv4, "Ipv4::GetIfIndexByAddress: No Ipv4 interface");
for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++)
{
if (ipv4->GetAddress (i).CombineMask(amask) == a.CombineMask(amask) )
@@ -48,17 +48,26 @@ GetIfIndexByIpv4Address (Ptr<Node> node, Ipv4Address a, Ipv4Mask amask)
}
}
// Mapping not found
NS_ASSERT_MSG (false, "GetIfIndexByIpv4Address failed");
NS_ASSERT_MSG (false, "Ipv4::GetIfIndexByAddress failed");
return 0;
}
//
// XXX BUGBUG I don't think this is really the right approach here. The call
// to GetRoute () filters down into Ipv4L3Protocol where it translates into
// a call into the Ipv4 static routing package. This bypasses any other
// routing packages. At a minimum, the name is misleading.
//
bool
GetIpv4RouteToDestination (Ptr<Node> node, Ipv4Route& route,
Ipv4Address a, Ipv4Mask amask)
Ipv4::GetRouteToDestination (
Ptr<Node> node,
Ipv4Route& route,
Ipv4Address a,
Ipv4Mask amask)
{
Ipv4Route tempRoute;
Ptr<Ipv4> ipv4 = node->QueryInterface<Ipv4> (Ipv4::iid);
NS_ASSERT_MSG (ipv4, "GetIpv4RouteToDestination: No Ipv4 interface");
NS_ASSERT_MSG (ipv4, "Ipv4::GetRouteToDestination: No Ipv4 interface");
for (uint32_t i = 0; i < ipv4->GetNRoutes (); i++)
{
tempRoute = ipv4->GetRoute (i);
@@ -83,5 +92,4 @@ GetIpv4RouteToDestination (Ptr<Node> node, Ipv4Route& route,
return false;
}
} // namespace ns3

View File

@@ -71,6 +71,7 @@ public:
/**
* \brief Asynchronously requests a route for a given packet and IP header
*
* \param ifIndex The interface index on which the packet was received.
* \param ipHeader IP header of the packet
* \param packet packet that is being sent or forwarded
* \param routeReply callback that will receive the route reply
@@ -100,9 +101,47 @@ public:
* immediately after the IP header, although most routing do not
* insert any extra header.
*/
virtual bool RequestRoute (const Ipv4Header &ipHeader,
virtual bool RequestRoute (uint32_t ifIndex,
const Ipv4Header &ipHeader,
Packet packet,
RouteReplyCallback routeReply) = 0;
/**
* \brief Synchronously check to see if we can determine the interface index
* that will be used if a packet is sent to this destination.
*
* This method addresses a problem in the IP stack where a destination address
* must be present and checksummed into the IP header before the actual
* interface over which the packet is sent can be determined. The answer is
* to implement a known and intentional cross-layer violation. This is the
* endpoint of a call chain that started up quite high in the stack (sockets)
* and has found its way down to the Ipv4L3Protocol which is consulting the
* routing protocols for what they would do if presented with a packet of the
* given destination.
*
* Note that the a single interface index is returned. This means that if
* the destination address is a multicast, and an explicit route is present
* that includeds multiple output interfaces, that route cannot be used.
*
* If there are multiple paths out of the node, the resolution is performed
* by Ipv4L3Protocol::GetIfIndexforDestination which has access to more
* contextual information that is useful for making a determination.
*
* \param destination The Ipv4Address if the destination of a hypothetical
* packet. This may be a multicast group address.
* \param ifIndex A reference to the interface index over which a packet
* sent to this destination would be sent.
* \return Returns true if a route is found to the destination that involves
* a single output interface index, otherwise false.
*
* \see Ipv4StaticRouting
* \see Ipv4RoutingProtocol
* \see Ipv4L3Protocol
*/
virtual bool RequestIfIndex (Ipv4Address destination,
uint32_t& ifIndex) = 0;
static const uint32_t IF_INDEX_ANY = 0xffffffff;
};
/**
@@ -194,16 +233,68 @@ public:
* \returns the number of entries in the routing table.
*/
virtual uint32_t GetNRoutes (void) = 0;
/**
* \param i index of route to return
* \returns the route whose index is i
*/
virtual Ipv4Route GetRoute (uint32_t i) = 0;
/**
* \param i index of route to remove from routing table.
*/
virtual void RemoveRoute (uint32_t i) = 0;
/**
* \brief Add a static multicast route for a given multicast source and
* group.
*
* \param origin The Ipv4 address of the multicast source.
* \param group The multicast group address.
* \param inputInterface The interface index over which the packet arrived.
* \param outputInterfaces The list of output interface indices over which
* the packet should be sent (excluding the inputInterface).
*/
virtual void AddMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface,
std::vector<uint32_t> outputInterfaces) = 0;
/**
* \brief Remove a static multicast route for a given multicast source and
* group.
*
* \param origin The Ipv4 address of the multicast source.
* \param group The multicast group address.
* \param inputInterface The interface index over which the packet arrived.
*/
virtual void RemoveMulticastRoute (Ipv4Address origin,
Ipv4Address group,
uint32_t inputInterface) = 0;
/**
* \brief Set the default static multicast route.
*
* \param outputInterface The network output interface index over which
* packets without specific routes should be sent.
*/
virtual void SetDefaultMulticastRoute (uint32_t outputInterface) = 0;
/**
* \returns the number of entries in the multicast routing table.
*/
virtual uint32_t GetNMulticastRoutes (void) const = 0;
/**
* \param i index of route to return
* \returns the route whose index is i
*/
virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const = 0;
/**
* \param i index of route to remove from routing table.
*/
virtual void RemoveMulticastRoute (uint32_t i) = 0;
/**
* \param device device to add to the list of ipv4 interfaces
* which can be used as output interfaces during packet forwarding.
@@ -214,49 +305,120 @@ public:
* make sure that it is never used during packet forwarding.
*/
virtual uint32_t AddInterface (Ptr<NetDevice> device) = 0;
/**
* \returns the number of interfaces added by the user.
*/
virtual uint32_t GetNInterfaces (void) = 0;
/**
* \brief Find and return the interface ID of the interface that has been
* assigned the specified IP address.
* \param addr The IP address assigned to the interface of interest.
* \returns The index of the ipv4 interface with the given address.
*
* Each IP interface has an IP address associated with it. It is often
* useful to search the list of interfaces for one that corresponds to
* a known IP Address. This call takes an IP address as a parameter and
* returns the interface index of the first interface that has been assigned
* that address. If the address is not found, this function asserts.
*/
virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const = 0;
/**
* \brief Find and return the interface ID of the interface that has been
* assigned the specified (masked) IP address.
* \param addr The IP address assigned to the interface of interest.
* \param mask The address mask to be used in address matching.
* \returns The index of the ipv4 interface with the given address.
*
* Each IP interface has an IP address associated with it. It is often
* useful to search the list of interfaces for one that corresponds to
* a known IP Address. This call takes an IP address and an IP address
* mask as parameters and returns the interface index of the first interface
* that matches the masked IP address.
*/
virtual uint32_t FindInterfaceForAddr (Ipv4Address addr,
Ipv4Mask mask) const = 0;
/**
* \param i index of ipv4 interface
* \returns the NetDevice associated with the ipv4 interface index
*/
virtual Ptr<NetDevice> GetNetDevice (uint32_t i) = 0;
/**
* \brief Join a multicast group for a given multicast source and
* group.
*
* \param origin The Ipv4 address of the multicast source.
* \param group The multicast group address.
*/
virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0;
/**
* \brief Leave a multicast group for a given multicast source and
* group.
*
* \param origin The Ipv4 address of the multicast source.
* \param group The multicast group address.
*/
virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0;
/**
* \param i index of ipv4 interface
* \param address address to associate to the underlying ipv4 interface
*/
virtual void SetAddress (uint32_t i, Ipv4Address address) = 0;
/**
* \param i index of ipv4 interface
* \param mask mask to associate to the underlying ipv4 interface
*/
virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask) = 0;
/**
* \param i index of ipv4 interface
* \returns the mask associated to the underlying ipv4 interface
*/
virtual Ipv4Mask GetNetworkMask (uint32_t i) const = 0;
/**
* \param i index of ipv4 interface
* \returns the address associated to the underlying ipv4 interface
*/
virtual Ipv4Address GetAddress (uint32_t i) const = 0;
/**
* \param destination The IP address of a hypothetical destination.
* \returns The IP address assigned to the interface that will be used
* if we were to send a packet to destination.
*/
virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const = 0;
/**
* \param destination The IP address of a hypothetical destination.
* \param ifIndex filled in with the interface index that will be used to
* send a packet to the hypothetical destination.
* \returns True if a single interface can be identified, false otherwise.
*/
virtual bool GetIfIndexForDestination (Ipv4Address dest,
uint32_t &ifIndex) const = 0;
/**
* \param i index of ipv4 interface
* \returns the Maximum Transmission Unit (in bytes) associated
* to the underlying ipv4 interface
*/
virtual uint16_t GetMtu (uint32_t i) const = 0;
/**
* \param i index of ipv4 interface
* \returns true if the underlying interface is in the "up" state,
* false otherwise.
*/
virtual bool IsUp (uint32_t i) const = 0;
/**
* \param i index of ipv4 interface
*
@@ -264,6 +426,7 @@ public:
* considered valid during ipv4 forwarding.
*/
virtual void SetUp (uint32_t i) = 0;
/**
* \param i index of ipv4 interface
*
@@ -271,21 +434,18 @@ public:
* ignored during ipv4 forwarding.
*/
virtual void SetDown (uint32_t i) = 0;
};
/**
* Convenience functions (Doxygen still needed)
*
* Return the ifIndex corresponding to the Ipv4Address provided.
*/
uint32_t GetIfIndexByIpv4Address (Ptr<Node> node,
Ipv4Address a,
Ipv4Mask amask = Ipv4Mask("255.255.255.255"));
static uint32_t GetIfIndexByAddress (Ptr<Node> node, Ipv4Address a,
Ipv4Mask amask = Ipv4Mask("255.255.255.255"));
bool GetIpv4RouteToDestination (Ptr<Node> node, Ipv4Route& route,
Ipv4Address a,
Ipv4Mask amask = Ipv4Mask("255.255.255.255"));
static bool GetRouteToDestination (Ptr<Node> node, Ipv4Route& route,
Ipv4Address a, Ipv4Mask amask = Ipv4Mask("255.255.255.255"));
};
} // namespace ns3

View File

@@ -114,6 +114,7 @@ NetDevice::IsBroadcast (void) const
{
return m_isBroadcast;
}
Address const &
NetDevice::GetBroadcast (void) const
{
@@ -140,10 +141,27 @@ NetDevice::IsMulticast (void) const
return m_isMulticast;
}
Address
NetDevice::GetMulticast (void) const
{
NS_ASSERT_MSG (m_isMulticast, "NetDevice::GetMulticast (): "
"Invalid operation when not IsMulticast ()");
return m_multicast;
}
Address
NetDevice::MakeMulticastAddress(Ipv4Address multicastGroup) const
{
NS_ASSERT_MSG (m_isMulticast, "NetDevice::GetMulticast (): "
"Invalid operation when not IsMulticast ()");
return m_multicast;
}
void
NetDevice::EnableMulticast (void)
NetDevice::EnableMulticast (Address multicast)
{
m_isMulticast = true;
m_multicast = multicast;
}
void

View File

@@ -29,6 +29,7 @@
#include "ns3/object.h"
#include "ns3/ptr.h"
#include "address.h"
#include "ipv4-address.h"
namespace ns3 {
@@ -130,10 +131,69 @@ public:
* not true.
*/
Address const &GetBroadcast (void) const;
/**
* \return value of m_isMulticast flag
*/
bool IsMulticast (void) const;
/**
* \brief Return the MAC multicast base address used when mapping multicast
* groups to MAC multicast addresses.
*
* Typically when one constructs a multicast MAC addresses, some bits from
* the IP multicast group are copied into a corresponding MAC multicast
* group. In EUI-48, for example, the low order 23 bits of the multicast
* group are copied to the MAC multicast group base address.
*
* This method allows access to the underlying MAC multicast group base
* address. It is expected that in most cases, a net device client will
* allow the net device to perform the actual construction of the multicast
* address. Use of this method is discouraged unless you have a good reason
* to perform a custom mapping. You should prefer
* NetDevice::MakeMulticastAddress which will do the RFC-specified mapping
* for the net device in question.
*
* \return The multicast address supported by this net device.
*
* \warning Calling this method is invalid if IsMulticast returns not true.
* The method NS_ASSERTs if the device is not a multicast device.
* \see NetDevice::MakeMulticastAddress
*/
Address GetMulticast (void) const;
/**
* \brief Make and return a MAC multicast address using the provided
* multicast group
*
* RFC 1112 says that an Ipv4 host group address is mapped to an Ethernet
* multicast address by placing the low-order 23-bits of the IP address into
* the low-order 23 bits of the Ethernet multicast address
* 01-00-5E-00-00-00 (hex). Similar RFCs exist for Ipv6 and Eui64 mappings.
* This method performs the multicast address creation function appropriate
* to the underlying MAC address of the device. This MAC address is
* encapsulated in an abstract Address to avoid dependencies on the exact
* MAC address format.
*
* A default imlementation of MakeMulticastAddress is provided, but this
* method simply NS_ASSERTS. In the case of net devices that do not support
* multicast, clients are expected to test NetDevice::IsMulticast and avoid
* attempting to map multicast packets. Subclasses of NetDevice that do
* support multicasting are expected to override this method and provide an
* implementation appropriate to the particular device.
*
* \param multicastGroup The IP address for the multicast group destination
* of the packet.
* \return The MAC multicast Address used to send packets to the provided
* multicast group.
*
* \warning Calling this method is invalid if IsMulticast returns not true.
* \see Ipv4Address
* \see Address
* \see NetDevice::IsMulticast
*/
virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
/**
* \return value of m_isPointToPoint flag
*/
@@ -204,9 +264,10 @@ public:
*/
void DisableBroadcast (void);
/**
* Set m_isMulticast flag to true
* Enable multicast support. This method should be
* called by subclasses from their constructor
*/
void EnableMulticast (void);
void EnableMulticast (Address multicast);
/**
* Set m_isMulticast flag to false
*/
@@ -286,6 +347,7 @@ public:
uint16_t m_ifIndex;
Address m_address;
Address m_broadcast;
Address m_multicast;
uint16_t m_mtu;
bool m_isUp;
bool m_isBroadcast;

View File

@@ -1152,7 +1152,7 @@ GlobalRouteManagerImpl::FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask)
// we're looking for. If we find one, return the corresponding interface
// index.
//
return (GetIfIndexByIpv4Address (node, a, amask) );
return (Ipv4::GetIfIndexByAddress (node, a, amask) );
}
}
//