--- a/CHANGES.html Fri Nov 28 08:55:24 2008 +0100
+++ b/CHANGES.html Fri Nov 28 08:56:47 2008 +0100
@@ -106,6 +106,14 @@
</li>
</ul>
+<li>17-11-2008; changeset
+<a href="http://code.nsnam.org/ns-3-dev/rev/756887a9bbea">756887a9bbea</a></li>
+<ul>
+<li>
+Global routing supports bridge devices.
+</li>
+</ul>
+
<hr>
<h1>changes from ns-3.1 to ns-3.2</h1>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/csma-bridge-one-hop.cc Fri Nov 28 08:56:47 2008 +0100
@@ -0,0 +1,246 @@
+/* -*- 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
+//
+// bridge1 The node named bridge1 (node 5 in the nodelist)
+// ------------------ has three CMSA net devices that are bridged
+// CSMA CSMA CSMA together using a BridgeNetDevice.
+// | | |
+// | | | The bridge node talks over three CSMA channels
+// | | |
+// CSMA CSMA CSMA to three other CSMA net devices
+// ---- ---- ----
+// n0 n1 n2 Node two acts as a router and talks to another
+// ---- bridge that connects the remaining nodes.
+// CSMA
+// |
+// n3 n4 |
+// ---- ---- |
+// CSMA CSMA |
+// | | |
+// | | |
+// | | |
+// CSMA CSMA CSMA The node named bridge2 (node 6 in the nodelist)
+// ------------------ has three CMSA net devices that are bridged
+// bridge2 together using a BridgeNetDevice.
+//
+// Or, more abstractly, recognizing that bridge 1 and bridge 2 are nodes
+// with three net devices:
+//
+// n0 n1 (n0 = 10.1.1.2)
+// | | (n1 = 10.1.1.3) Note odd addressing
+// ----------- (n2 = 10.1.1.1)
+// | bridge1 | <- n5
+// -----------
+// |
+// router <- n2
+// |
+// -----------
+// | bridge2 | <- n6
+// ----------- (n2 = 10.1.2.1)
+// | | (n3 = 10.1.2.2)
+// n3 n4 (n4 = 10.1.2.3)
+//
+// So, this example shows two broadcast domains, each interconnected by a bridge
+// with a router node (n2) interconnecting the layer-2 broadcast domains
+//
+// It is meant to mirror somewhat the csma-bridge example but adds another
+// bridged link separated by a router.
+//
+// - CBR/UDP flows from n0 (10.1.1.2) to n1 (10.1.1.3) and from n3 (10.1.2.2) to n0 (10.1.1.3)
+// - DropTail queues
+// - Global static routing
+// - Tracing of queues and packet receptions to file "csma-bridge-one-hop.tr"
+
+#include <iostream>
+#include <fstream>
+
+#include "ns3/simulator-module.h"
+#include "ns3/node-module.h"
+#include "ns3/core-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/bridge-module.h"
+#include "ns3/global-route-manager.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("CsmaBridgeOneHopExample");
+
+int
+main (int argc, char *argv[])
+{
+ //
+ // Users may find it convenient to turn on explicit debugging
+ // for selected modules; the below lines suggest how to do this
+ //
+#if 0
+ LogComponentEnable ("CsmaBridgeOneHopExample", LOG_LEVEL_INFO);
+#endif
+
+ //
+ // Make the random number generators generate reproducible results.
+ //
+ RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
+
+ //
+ // Allow the user to override any of the defaults and the above Bind() at
+ // run-time, via command-line arguments
+ //
+ CommandLine cmd;
+ cmd.Parse (argc, argv);
+
+ //
+ // Explicitly create the nodes required by the topology (shown above).
+ //
+ NS_LOG_INFO ("Create nodes.");
+
+ Ptr<Node> n0 = CreateObject<Node> ();
+ Ptr<Node> n1 = CreateObject<Node> ();
+ Ptr<Node> n2 = CreateObject<Node> ();
+ Ptr<Node> n3 = CreateObject<Node> ();
+ Ptr<Node> n4 = CreateObject<Node> ();
+
+ Ptr<Node> bridge1 = CreateObject<Node> ();
+ Ptr<Node> bridge2 = CreateObject<Node> ();
+
+ NS_LOG_INFO ("Build Topology");
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+ csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+
+ // Create the csma links, from each terminal to the bridge
+ // This will create six network devices; we'll keep track separately
+ // of the devices on and off the bridge respectively, for later configuration
+ NetDeviceContainer topLanDevices;
+ NetDeviceContainer topBridgeDevices;
+
+ // It is easier to iterate the nodes in C++ if we put them into a container
+ NodeContainer topLan (n2, n0, n1);
+
+ for (int i = 0; i < 3; i++)
+ {
+ // install a csma channel between the ith toplan node and the bridge node
+ NetDeviceContainer link = csma.Install (NodeContainer (topLan.Get (i), bridge1));
+ topLanDevices.Add (link.Get (0));
+ topBridgeDevices.Add (link.Get (1));
+ }
+
+ //
+ // Now, Create the bridge netdevice, which will do the packet switching. The
+ // bridge lives on the node bridge1 and bridges together the topBridgeDevices
+ // which are the three CSMA net devices on the node in the diagram above.
+ //
+ BridgeHelper bridge;
+ bridge.Install (bridge1, topBridgeDevices);
+
+ // Add internet stack to the topLan nodes
+ InternetStackHelper internet;
+ internet.Install (topLan);
+
+ // Repeat for bottom bridged LAN
+ NetDeviceContainer bottomLanDevices;
+ NetDeviceContainer bottomBridgeDevices;
+ NodeContainer bottomLan (n2, n3, n4);
+ for (int i = 0; i < 3; i++)
+ {
+ NetDeviceContainer link = csma.Install (NodeContainer (bottomLan.Get (i), bridge2));
+ bottomLanDevices.Add (link.Get (0));
+ bottomBridgeDevices.Add (link.Get (1));
+ }
+ bridge.Install (bridge2, bottomBridgeDevices);
+
+ // Add internet stack to the bottomLan nodes
+ internet.Install (NodeContainer (n3, n4));
+
+ // We've got the "hardware" in place. Now we need to add IP addresses.
+ NS_LOG_INFO ("Assign IP Addresses.");
+ Ipv4AddressHelper ipv4;
+ ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+ ipv4.Assign (topLanDevices);
+ ipv4.SetBase ("10.1.2.0", "255.255.255.0");
+ ipv4.Assign (bottomLanDevices);
+
+ //
+ // Create router nodes, initialize routing database and set up the routing
+ // tables in the nodes. We excuse the bridge nodes from having to serve as
+ // routers, since they don't even have internet stacks on them.
+ //
+ NodeContainer routerNodes (n0, n1, n2, n3, n4);
+ GlobalRouteManager::PopulateRoutingTables (routerNodes);
+
+ //
+ // Create an OnOff application to send UDP datagrams from node zero to node 1.
+ //
+ NS_LOG_INFO ("Create Applications.");
+ uint16_t port = 9; // Discard port (RFC 863)
+
+ OnOffHelper onoff ("ns3::UdpSocketFactory",
+ Address (InetSocketAddress (Ipv4Address ("10.1.1.3"), port)));
+ onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+ onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+
+ ApplicationContainer app = onoff.Install (n0);
+ // Start the application
+ app.Start (Seconds (1.0));
+ app.Stop (Seconds (10.0));
+
+ // Create an optional packet sink to receive these packets
+ PacketSinkHelper sink ("ns3::UdpSocketFactory",
+ Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+ ApplicationContainer sink1 = sink.Install (n1);
+ sink1.Start (Seconds (1.0));
+ sink1.Stop (Seconds (10.0));
+
+ //
+ // Create a similar flow from n3 to n0, starting at time 1.1 seconds
+ //
+ onoff.SetAttribute ("Remote",
+ AddressValue (InetSocketAddress (Ipv4Address ("10.1.1.2"), port)));
+ ApplicationContainer app2 = onoff.Install (n3);
+ app2.Start (Seconds (1.1));
+ app2.Stop (Seconds (10.0));
+
+ ApplicationContainer sink2 = sink.Install (n0);
+ sink2.Start (Seconds (1.1));
+ sink2.Stop (Seconds (10.0));
+
+ //
+ // Configure tracing of all enqueue, dequeue, and NetDevice receive events.
+ // Trace output will be sent to the file "csma-bridge-one-hop.tr"
+ //
+ NS_LOG_INFO ("Configure Tracing.");
+ std::ofstream ascii;
+ ascii.open ("csma-bridge-one-hop.tr");
+ CsmaHelper::EnableAsciiAll (ascii);
+
+ //
+ // Also configure some tcpdump traces; each interface will be traced.
+ // The output files will be named:
+ // csma-bridge.pcap-<nodeId>-<interfaceId>
+ // and can be read by the "tcpdump -r" command (use "-tt" option to
+ // display timestamps correctly)
+ //
+ CsmaHelper::EnablePcapAll ("csma-bridge-one-hop");
+
+ //
+ // Now, do the actual simulation.
+ //
+ NS_LOG_INFO ("Run Simulation.");
+ Simulator::Run ();
+ Simulator::Destroy ();
+ NS_LOG_INFO ("Done.");
+}
--- a/examples/wifi-wired-bridging.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/examples/wifi-wired-bridging.cc Fri Nov 28 08:56:47 2008 +0100
@@ -1,4 +1,46 @@
/* -*- 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
+ */
+
+// Default network topology includes some number of AP nodes specified by
+// the variable nWifis (defaults to two). Off of each AP node, there are some
+// number of STA nodes specified by the variable nStas (defaults to two).
+// Each AP talks to its associated STA nodes. There are bridge net devices
+// on each AP node that bridge the whole thing into one network.
+//
+// +-----+ +-----+ +-----+ +-----+
+// | STA | | STA | | STA | | STA |
+// +-----+ +-----+ +-----+ +-----+
+// 192.168.0.3 192.168.0.4 192.168.0.5 192.168.0.6
+// -------- -------- -------- --------
+// WIFI STA WIFI STA WIFI STA WIFI STA
+// -------- -------- -------- --------
+// ((*)) ((*)) | ((*)) ((*))
+// |
+// ((*)) | ((*))
+// ------- -------
+// WIFI AP CSMA ========= CSMA WIFI AP
+// ------- ---- ---- -------
+// ############## ##############
+// BRIDGE BRIDGE
+// ############## ##############
+// 192.168.0.1 192.168.0.2
+// +---------+ +---------+
+// | AP Node | | AP Node |
+// +---------+ +---------+
+//
#include "ns3/core-module.h"
#include "ns3/simulator-module.h"
@@ -46,7 +88,6 @@
stack.Install (backboneNodes);
backboneDevices = csma.Install (backboneNodes);
- backboneInterfaces = ip.Assign (backboneDevices);
double wifiX = 0.0;
for (uint32_t i = 0; i < nWifis; ++i)
@@ -69,7 +110,6 @@
wifiPhy.SetChannel (wifiChannel.Create ());
sta.Create (nStas);
- ip.NewNetwork ();
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (wifiX),
"MinY", DoubleValue (0.0),
@@ -87,8 +127,12 @@
"BeaconGeneration", BooleanValue (true),
"BeaconInterval", TimeValue (Seconds (2.5)));
apDev = wifi.Install (wifiPhy, backboneNodes.Get (i));
- apInterface = ip.Assign (apDev);
- bridge.Install (backboneNodes.Get (i), NetDeviceContainer (apDev, backboneDevices.Get (i)));
+
+ NetDeviceContainer bridgeDev;
+ bridgeDev = bridge.Install (backboneNodes.Get (i), NetDeviceContainer (apDev, backboneDevices.Get (i)));
+
+ // assign AP IP address to bridge, not wifi
+ apInterface = ip.Assign (bridgeDev);
// setup the STAs
stack.Install (sta);
--- a/examples/wscript Fri Nov 28 08:55:24 2008 +0100
+++ b/examples/wscript Fri Nov 28 08:56:47 2008 +0100
@@ -28,6 +28,10 @@
['bridge', 'csma', 'internet-stack'])
obj.source = 'csma-bridge.cc'
+ obj = bld.create_ns3_program('csma-bridge-one-hop',
+ ['bridge', 'csma', 'internet-stack'])
+ obj.source = 'csma-bridge-one-hop.cc'
+
obj = bld.create_ns3_program('udp-echo',
['csma', 'internet-stack'])
obj.source = 'udp-echo.cc'
--- a/src/applications/v4ping/v4ping.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/applications/v4ping/v4ping.cc Fri Nov 28 08:56:47 2008 +0100
@@ -149,6 +149,7 @@
V4Ping::StopApplication (void)
{
NS_LOG_FUNCTION (this);
+ m_socket->Close ();
}
--- a/src/core/abort.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/core/abort.h Fri Nov 28 08:56:47 2008 +0100
@@ -21,6 +21,16 @@
#include "fatal-error.h"
+#define NS_ABORT_MSG(msg) \
+ do { \
+ std::cerr << "file=" << __FILE__ << \
+ ", line=" << __LINE__ << ", abort, msg=\"" << \
+ msg << "\"" << std::endl; \
+ int *a = 0; \
+ *a = 0; \
+ } while (false)
+
+
#define NS_ABORT_IF(cond) \
do { \
if (cond) \
--- a/src/devices/bridge/bridge-net-device.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/devices/bridge/bridge-net-device.cc Fri Nov 28 08:56:47 2008 +0100
@@ -57,6 +57,7 @@
m_ifIndex (0),
m_mtu (0xffff)
{
+ NS_LOG_FUNCTION_NOARGS ();
m_channel = CreateObject<BridgeChannel> ();
}
@@ -100,6 +101,7 @@
BridgeNetDevice::ForwardUnicast (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet,
uint16_t protocol, Mac48Address src, Mac48Address dst)
{
+ NS_LOG_FUNCTION_NOARGS ();
NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName ()
<< ", packet=" << packet << ", protocol="<<protocol
<< ", src=" << src << ", dst=" << dst << ")");
@@ -133,6 +135,7 @@
BridgeNetDevice::ForwardBroadcast (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet,
uint16_t protocol, Mac48Address src, Mac48Address dst)
{
+ NS_LOG_FUNCTION_NOARGS ();
NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName ()
<< ", packet=" << packet << ", protocol="<<protocol
<< ", src=" << src << ", dst=" << dst << ")");
@@ -154,6 +157,7 @@
void BridgeNetDevice::Learn (Mac48Address source, Ptr<NetDevice> port)
{
+ NS_LOG_FUNCTION_NOARGS ();
if (m_enableLearning)
{
LearnedState &state = m_learnState[source];
@@ -164,6 +168,7 @@
Ptr<NetDevice> BridgeNetDevice::GetLearnedState (Mac48Address source)
{
+ NS_LOG_FUNCTION_NOARGS ();
if (m_enableLearning)
{
Time now = Simulator::Now ();
@@ -185,9 +190,25 @@
return NULL;
}
+uint32_t
+BridgeNetDevice::GetNBridgePorts (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_ports.size ();
+}
+
+
+Ptr<NetDevice>
+BridgeNetDevice::GetBridgePort (uint32_t n) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_ports[n];
+}
+
void
BridgeNetDevice::AddBridgePort (Ptr<NetDevice> bridgePort)
{
+ NS_LOG_FUNCTION_NOARGS ();
NS_ASSERT (bridgePort != this);
if (!Mac48Address::IsMatchingType (bridgePort->GetAddress ()))
{
@@ -212,42 +233,49 @@
void
BridgeNetDevice::SetName(const std::string name)
{
+ NS_LOG_FUNCTION_NOARGS ();
m_name = name;
}
std::string
BridgeNetDevice::GetName(void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return m_name;
}
void
BridgeNetDevice::SetIfIndex(const uint32_t index)
{
+ NS_LOG_FUNCTION_NOARGS ();
m_ifIndex = index;
}
uint32_t
BridgeNetDevice::GetIfIndex(void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return m_ifIndex;
}
Ptr<Channel>
BridgeNetDevice::GetChannel (void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return m_channel;
}
Address
BridgeNetDevice::GetAddress (void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return m_address;
}
bool
BridgeNetDevice::SetMtu (const uint16_t mtu)
{
+ NS_LOG_FUNCTION_NOARGS ();
m_mtu = mtu;
return true;
}
@@ -255,6 +283,7 @@
uint16_t
BridgeNetDevice::GetMtu (void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return m_mtu;
}
@@ -262,6 +291,7 @@
bool
BridgeNetDevice::IsLinkUp (void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return true;
}
@@ -274,6 +304,7 @@
bool
BridgeNetDevice::IsBroadcast (void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return true;
}
@@ -281,12 +312,14 @@
Address
BridgeNetDevice::GetBroadcast (void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return Mac48Address ("ff:ff:ff:ff:ff:ff");
}
bool
BridgeNetDevice::IsMulticast (void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return true;
}
@@ -302,13 +335,22 @@
bool
BridgeNetDevice::IsPointToPoint (void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return false;
}
+bool
+BridgeNetDevice::IsBridge (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
bool
BridgeNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
{
+ NS_LOG_FUNCTION_NOARGS ();
for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
iter != m_ports.end (); iter++)
{
@@ -322,6 +364,7 @@
bool
BridgeNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
{
+ NS_LOG_FUNCTION_NOARGS ();
for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
iter != m_ports.end (); iter++)
{
@@ -336,6 +379,7 @@
Ptr<Node>
BridgeNetDevice::GetNode (void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return m_node;
}
@@ -343,6 +387,7 @@
void
BridgeNetDevice::SetNode (Ptr<Node> node)
{
+ NS_LOG_FUNCTION_NOARGS ();
m_node = node;
}
@@ -350,6 +395,7 @@
bool
BridgeNetDevice::NeedsArp (void) const
{
+ NS_LOG_FUNCTION_NOARGS ();
return true;
}
@@ -357,25 +403,28 @@
void
BridgeNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
{
+ NS_LOG_FUNCTION_NOARGS ();
m_rxCallback = cb;
}
void
BridgeNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
{
+ NS_LOG_FUNCTION_NOARGS ();
m_promiscRxCallback = cb;
}
bool
BridgeNetDevice::SupportsSendFrom () const
{
+ NS_LOG_FUNCTION_NOARGS ();
return true;
}
-
void
BridgeNetDevice::DoDispose (void)
{
+ NS_LOG_FUNCTION_NOARGS ();
m_node = 0;
NetDevice::DoDispose ();
}
--- a/src/devices/bridge/bridge-net-device.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/devices/bridge/bridge-net-device.h Fri Nov 28 08:56:47 2008 +0100
@@ -82,6 +82,10 @@
*/
void AddBridgePort (Ptr<NetDevice> bridgePort);
+ uint32_t GetNBridgePorts (void) const;
+
+ Ptr<NetDevice> GetBridgePort (uint32_t n) const;
+
// inherited from NetDevice base class.
virtual void SetName(const std::string name);
virtual std::string GetName(void) const;
@@ -98,6 +102,7 @@
virtual bool IsMulticast (void) const;
virtual Address GetMulticast (Ipv4Address multicastGroup) const;
virtual bool IsPointToPoint (void) const;
+ virtual bool IsBridge (void) const;
virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
virtual Ptr<Node> GetNode (void) const;
--- a/src/devices/csma/csma-net-device.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/devices/csma/csma-net-device.cc Fri Nov 28 08:56:47 2008 +0100
@@ -837,6 +837,13 @@
return false;
}
+ bool
+CsmaNetDevice::IsBridge (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return false;
+}
+
bool
CsmaNetDevice::Send (Ptr<Packet> packet,const Address& dest, uint16_t protocolNumber)
{
--- a/src/devices/csma/csma-net-device.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/devices/csma/csma-net-device.h Fri Nov 28 08:56:47 2008 +0100
@@ -351,6 +351,12 @@
virtual bool IsPointToPoint (void) const;
/**
+ * Is this a bridge?
+ * \returns false.
+ */
+ virtual bool IsBridge (void) const;
+
+ /**
* Start sending a packet down the channel.
*/
virtual bool Send (Ptr<Packet> packet, const Address& dest,
--- a/src/devices/emu/emu-net-device.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/devices/emu/emu-net-device.cc Fri Nov 28 08:56:47 2008 +0100
@@ -882,6 +882,12 @@
return false;
}
+bool
+EmuNetDevice::IsBridge (void) const
+{
+ return false;
+}
+
void
EmuNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
{
--- a/src/devices/emu/emu-net-device.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/devices/emu/emu-net-device.h Fri Nov 28 08:56:47 2008 +0100
@@ -165,6 +165,12 @@
*/
virtual bool IsPointToPoint (void) const;
+ /**
+ * Is this a bridge?
+ * \returns false.
+ */
+ virtual bool IsBridge (void) const;
+
virtual bool Send(Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber);
virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
--- a/src/devices/point-to-point/point-to-point-net-device.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/devices/point-to-point/point-to-point-net-device.cc Fri Nov 28 08:56:47 2008 +0100
@@ -392,6 +392,12 @@
}
bool
+PointToPointNetDevice::IsBridge (void) const
+{
+ return false;
+}
+
+ bool
PointToPointNetDevice::Send(
Ptr<Packet> packet,
const Address &dest,
--- a/src/devices/point-to-point/point-to-point-net-device.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/devices/point-to-point/point-to-point-net-device.h Fri Nov 28 08:56:47 2008 +0100
@@ -252,6 +252,7 @@
virtual Address GetMulticast (Ipv4Address multicastGroup) const;
virtual bool IsPointToPoint (void) const;
+ virtual bool IsBridge (void) const;
virtual bool Send(Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber);
virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
--- a/src/devices/wifi/wifi-net-device.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/devices/wifi/wifi-net-device.cc Fri Nov 28 08:56:47 2008 +0100
@@ -238,6 +238,11 @@
return false;
}
bool
+WifiNetDevice::IsBridge (void) const
+{
+ return false;
+}
+bool
WifiNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
{
NS_ASSERT (Mac48Address::IsMatchingType (dest));
--- a/src/devices/wifi/wifi-net-device.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/devices/wifi/wifi-net-device.h Fri Nov 28 08:56:47 2008 +0100
@@ -90,6 +90,7 @@
virtual bool IsMulticast (void) const;
virtual Address GetMulticast (Ipv4Address multicastGroup) const;
virtual bool IsPointToPoint (void) const;
+ virtual bool IsBridge (void) const;
virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
virtual Ptr<Node> GetNode (void) const;
virtual void SetNode (Ptr<Node> node);
--- a/src/helper/bridge-helper.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/helper/bridge-helper.cc Fri Nov 28 08:56:47 2008 +0100
@@ -1,24 +1,49 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
#include "bridge-helper.h"
-
+#include "ns3/log.h"
#include "ns3/bridge-net-device.h"
#include "ns3/node.h"
+NS_LOG_COMPONENT_DEFINE ("BridgeHelper");
+
namespace ns3 {
BridgeHelper::BridgeHelper ()
{
+ NS_LOG_FUNCTION_NOARGS ();
m_deviceFactory.SetTypeId ("ns3::BridgeNetDevice");
}
void
BridgeHelper::SetDeviceAttribute (std::string n1, const AttributeValue &v1)
{
+ NS_LOG_FUNCTION_NOARGS ();
m_deviceFactory.Set (n1, v1);
}
NetDeviceContainer
BridgeHelper::Install (Ptr<Node> node, NetDeviceContainer c)
{
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_LOGIC ("**** Install bridge device on node " << node->GetId ());
+
NetDeviceContainer devs;
Ptr<BridgeNetDevice> dev = m_deviceFactory.Create<BridgeNetDevice> ();
devs.Add (dev);
@@ -26,6 +51,7 @@
for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
{
+ NS_LOG_LOGIC ("**** Add BridgePort "<< *i);
dev->AddBridgePort (*i);
}
return devs;
--- a/src/helper/node-container.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/helper/node-container.cc Fri Nov 28 08:56:47 2008 +0100
@@ -50,6 +50,17 @@
Add (d);
}
+NodeContainer::NodeContainer (const NodeContainer &a, const NodeContainer &b,
+ const NodeContainer &c, const NodeContainer &d,
+ const NodeContainer &e)
+{
+ Add (a);
+ Add (b);
+ Add (c);
+ Add (d);
+ Add (e);
+}
+
NodeContainer::Iterator
NodeContainer::Begin (void) const
{
--- a/src/helper/node-container.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/helper/node-container.h Fri Nov 28 08:56:47 2008 +0100
@@ -64,6 +64,8 @@
NodeContainer (const NodeContainer &a, const NodeContainer &b, const NodeContainer &c);
NodeContainer (const NodeContainer &a, const NodeContainer &b, const NodeContainer &c, const NodeContainer &d);
+ NodeContainer (const NodeContainer &a, const NodeContainer &b, const NodeContainer &c, const NodeContainer &d,
+ const NodeContainer &e);
/**
* \returns an iterator to the start of the vector of node pointers.
--- a/src/node/net-device.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/node/net-device.h Fri Nov 28 08:56:47 2008 +0100
@@ -184,6 +184,15 @@
virtual Address GetMulticast (Ipv6Address addr) const = 0;
/**
+ * \brief Return true if the net device is acting as a bridge.
+ *
+ * \return value of m_isBridge flag
+ */
+ virtual bool IsBridge (void) const = 0;
+
+ /**
+ * \brief Return true if the net device is on a point-to-point link.
+ *
* \return value of m_isPointToPoint flag
*/
virtual bool IsPointToPoint (void) const = 0;
--- a/src/node/simple-net-device.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/node/simple-net-device.cc Fri Nov 28 08:56:47 2008 +0100
@@ -163,6 +163,13 @@
{
return false;
}
+
+bool
+SimpleNetDevice::IsBridge (void) const
+{
+ return false;
+}
+
bool
SimpleNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
{
--- a/src/node/simple-net-device.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/node/simple-net-device.h Fri Nov 28 08:56:47 2008 +0100
@@ -61,6 +61,7 @@
virtual bool IsMulticast (void) const;
virtual Address GetMulticast (Ipv4Address multicastGroup) const;
virtual bool IsPointToPoint (void) const;
+ virtual bool IsBridge (void) const;
virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
virtual Ptr<Node> GetNode (void) const;
--- a/src/routing/global-routing/global-route-manager-impl.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/routing/global-routing/global-route-manager-impl.cc Fri Nov 28 08:56:47 2008 +0100
@@ -97,7 +97,7 @@
void
SPFVertex::SetVertexType (SPFVertex::VertexType type)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (type);
m_vertexType = type;
}
@@ -111,7 +111,7 @@
void
SPFVertex::SetVertexId (Ipv4Address id)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (id);
m_vertexId = id;
}
@@ -125,7 +125,7 @@
void
SPFVertex::SetLSA (GlobalRoutingLSA* lsa)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (lsa);
m_lsa = lsa;
}
@@ -139,7 +139,7 @@
void
SPFVertex::SetDistanceFromRoot (uint32_t distance)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (distance);
m_distanceFromRoot = distance;
}
@@ -153,7 +153,7 @@
void
SPFVertex::SetOutgoingTypeId (uint32_t id)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (id);
m_rootOif = id;
}
@@ -167,7 +167,7 @@
void
SPFVertex::SetNextHop (Ipv4Address nextHop)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (nextHop);
m_nextHop = nextHop;
}
@@ -181,7 +181,7 @@
void
SPFVertex::SetParent (SPFVertex* parent)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (parent);
m_parent = parent;
}
@@ -202,7 +202,7 @@
SPFVertex*
SPFVertex::GetChild (uint32_t n) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (n);
uint32_t j = 0;
for ( ListOfSPFVertex_t::const_iterator i = m_children.begin ();
@@ -214,14 +214,14 @@
return *i;
}
}
- NS_ASSERT_MSG(false, "Index <n> out of range.");
+ NS_ASSERT_MSG (false, "Index <n> out of range.");
return 0;
}
uint32_t
SPFVertex::AddChild (SPFVertex* child)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (child);
m_children.push_back (child);
return m_children.size ();
}
@@ -268,14 +268,14 @@
void
GlobalRouteManagerLSDB::Insert (Ipv4Address addr, GlobalRoutingLSA* lsa)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (addr << lsa);
m_database.insert (LSDBPair_t (addr, lsa));
}
GlobalRoutingLSA*
GlobalRouteManagerLSDB::GetLSA (Ipv4Address addr) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (addr);
//
// Look up an LSA by its address.
//
@@ -293,7 +293,7 @@
GlobalRoutingLSA*
GlobalRouteManagerLSDB::GetLSAByLinkData (Ipv4Address addr) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (addr);
//
// Look up an LSA by its address.
//
@@ -341,7 +341,7 @@
void
GlobalRouteManagerImpl::DebugUseLsdb (GlobalRouteManagerLSDB* lsdb)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (lsdb);
if (m_lsdb)
{
delete m_lsdb;
@@ -351,8 +351,7 @@
//
// In order to build the routing database, we need at least one of the nodes
-// to participate as a router. Eventually we expect to provide a mechanism
-// for selecting a subset of the nodes to participate; for now, we just make
+// to participate as a router. This is a convenience function that makes
// all nodes routers. We do this by walking the list of nodes in the system
// and aggregating a Global Router Interface to each of the nodes.
//
@@ -371,6 +370,21 @@
}
}
+ void
+GlobalRouteManagerImpl::SelectRouterNodes (NodeContainer c)
+{
+ NS_LOG_FUNCTION (&c);
+ for (NodeContainer::Iterator i = c.Begin (); i != c.End (); i++)
+ {
+ Ptr<Node> node = *i;
+ NS_LOG_LOGIC ("Adding GlobalRouter interface to node " <<
+ node->GetId ());
+
+ Ptr<GlobalRouter> globalRouter = CreateObject<GlobalRouter> ();
+ node->AggregateObject (globalRouter);
+ }
+}
+
//
// In order to build the routing database, we need to walk the list of nodes
// in the system and look for those that support the GlobalRouter interface.
@@ -385,14 +399,14 @@
{
NS_LOG_FUNCTION_NOARGS ();
//
-// Walk the list of nodes looking for the GlobalRouter Interface.
+// Walk the list of nodes looking for the GlobalRouter Interface. Nodes with
+// global router interfaces are, not too surprisingly, our routers.
//
for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); i++)
{
Ptr<Node> node = *i;
- Ptr<GlobalRouter> rtr =
- node->GetObject<GlobalRouter> ();
+ Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter> ();
//
// Ignore nodes that aren't participating in routing.
//
@@ -504,7 +518,7 @@
void
GlobalRouteManagerImpl::SPFNext (SPFVertex* v, CandidateQueue& candidate)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (v << &candidate);
SPFVertex* w = 0;
GlobalRoutingLSA* w_lsa = 0;
@@ -706,13 +720,13 @@
GlobalRoutingLinkRecord* l,
uint32_t distance)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (v << w << l << distance);
//
// If w is a NetworkVertex, l should be null
/*
if (w->GetVertexType () == SPFVertex::VertexNetwork && l)
{
- NS_ASSERT_MSG(0, "Error: SPFNexthopCalculation parameter problem");
+ NS_ASSERT_MSG (0, "Error: SPFNexthopCalculation parameter problem");
}
*/
@@ -764,7 +778,7 @@
// return the link record describing the link from <w> to <v>. Think of it as
// SPFGetLink.
//
- NS_ASSERT(l);
+ NS_ASSERT (l);
GlobalRoutingLinkRecord *linkRemote = 0;
linkRemote = SPFGetNextLink (w, v, linkRemote);
//
@@ -778,7 +792,7 @@
// from the root node to the host represented by vertex <w>, you have to send
// the packet to the next hop address specified in w->m_nextHop.
//
- w->SetNextHop(linkRemote->GetLinkData ());
+ w->SetNextHop (linkRemote->GetLinkData ());
//
// Now find the outgoing interface corresponding to the point to point link
// from the perspective of <v> -- remember that <l> is the link "from"
@@ -832,7 +846,7 @@
* use can then be derived from the next hop IP address (or
* it can be inherited from the parent network).
*/
- w->SetNextHop(linkRemote->GetLinkData ());
+ w->SetNextHop (linkRemote->GetLinkData ());
w->SetOutgoingTypeId (v->GetOutgoingTypeId ());
NS_LOG_LOGIC ("Next hop from " <<
v->GetVertexId () << " to " << w->GetVertexId () <<
@@ -891,7 +905,7 @@
SPFVertex* w,
GlobalRoutingLinkRecord* prev_link)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (v << w << prev_link);
bool skip = true;
bool found_prev_link = false;
@@ -966,7 +980,7 @@
void
GlobalRouteManagerImpl::DebugSPFCalculate (Ipv4Address root)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (root);
SPFCalculate (root);
}
@@ -987,7 +1001,7 @@
// of the tree. Initially, this queue is empty.
//
CandidateQueue candidate;
- NS_ASSERT(candidate.Size () == 0);
+ NS_ASSERT (candidate.Size () == 0);
//
// Initialize the shortest-path tree to only contain the router doing the
// calculation. Each router (and corresponding network) is a vertex in the
@@ -1094,7 +1108,7 @@
}
else
{
- NS_ASSERT_MSG(0, "illegal SPFVertex type");
+ NS_ASSERT_MSG (0, "illegal SPFVertex type");
}
//
// RFC2328 16.1. (5).
@@ -1123,7 +1137,7 @@
uint32_t
GlobalRouteManagerImpl::FindOutgoingTypeId (Ipv4Address a, Ipv4Mask amask)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (a << amask);
//
// We have an IP address <a> and a vertex ID of the root of the SPF tree.
// The question is what interface index does this address correspond to.
@@ -1199,7 +1213,7 @@
void
GlobalRouteManagerImpl::SPFIntraAddRouter (SPFVertex* v)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (v);
NS_ASSERT_MSG (m_spfroot,
"GlobalRouteManagerImpl::SPFIntraAddRouter (): Root pointer not set");
@@ -1316,7 +1330,7 @@
void
GlobalRouteManagerImpl::SPFIntraAddTransit (SPFVertex* v)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (v);
NS_ASSERT_MSG (m_spfroot,
"GlobalRouteManagerImpl::SPFIntraAddTransit (): Root pointer not set");
@@ -1409,7 +1423,7 @@
void
GlobalRouteManagerImpl::SPFVertexAddParent (SPFVertex* v)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (v);
v->GetParent ()->AddChild (v);
}
--- a/src/routing/global-routing/global-route-manager-impl.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/routing/global-routing/global-route-manager-impl.h Fri Nov 28 08:56:47 2008 +0100
@@ -29,6 +29,7 @@
#include "ns3/object.h"
#include "ns3/ptr.h"
#include "ns3/ipv4-address.h"
+#include "ns3/node-container.h"
#include "global-router-interface.h"
namespace ns3 {
@@ -708,6 +709,14 @@
virtual void SelectRouterNodes ();
/**
+ * @brief Select which nodes in the system are to be router nodes and
+ * aggregate the appropriate interfaces onto those nodes.
+ * @internal
+ *
+ */
+ virtual void SelectRouterNodes (NodeContainer c);
+
+/**
* @brief Build the routing database by gathering Link State Advertisements
* from each node exporting a GlobalRouter interface.
* @internal
--- a/src/routing/global-routing/global-route-manager.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/routing/global-routing/global-route-manager.cc Fri Nov 28 08:56:47 2008 +0100
@@ -21,6 +21,7 @@
#include "ns3/assert.h"
#include "ns3/log.h"
#include "ns3/simulation-singleton.h"
+#include "ns3/node-container.h"
#include "global-route-manager.h"
#include "global-route-manager-impl.h"
@@ -33,7 +34,7 @@
// ---------------------------------------------------------------------------
void
-GlobalRouteManager::PopulateRoutingTables ()
+GlobalRouteManager::PopulateRoutingTables (void)
{
SelectRouterNodes ();
BuildGlobalRoutingDatabase ();
@@ -41,28 +42,43 @@
}
void
-GlobalRouteManager::SelectRouterNodes ()
+GlobalRouteManager::PopulateRoutingTables (NodeContainer c)
+{
+ SelectRouterNodes (c);
+ BuildGlobalRoutingDatabase ();
+ InitializeRoutes ();
+}
+
+ void
+GlobalRouteManager::SelectRouterNodes (void)
{
SimulationSingleton<GlobalRouteManagerImpl>::Get ()->
SelectRouterNodes ();
}
void
-GlobalRouteManager::BuildGlobalRoutingDatabase ()
+GlobalRouteManager::SelectRouterNodes (NodeContainer c)
+{
+ SimulationSingleton<GlobalRouteManagerImpl>::Get ()->
+ SelectRouterNodes (c);
+}
+
+ void
+GlobalRouteManager::BuildGlobalRoutingDatabase (void)
{
SimulationSingleton<GlobalRouteManagerImpl>::Get ()->
BuildGlobalRoutingDatabase ();
}
void
-GlobalRouteManager::InitializeRoutes ()
+GlobalRouteManager::InitializeRoutes (void)
{
SimulationSingleton<GlobalRouteManagerImpl>::Get ()->
InitializeRoutes ();
}
uint32_t
-GlobalRouteManager::AllocateRouterId ()
+GlobalRouteManager::AllocateRouterId (void)
{
static uint32_t routerId = 0;
return routerId++;
--- a/src/routing/global-routing/global-route-manager.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/routing/global-routing/global-route-manager.h Fri Nov 28 08:56:47 2008 +0100
@@ -22,6 +22,8 @@
#ifndef GLOBAL_ROUTE_MANAGER_H
#define GLOBAL_ROUTE_MANAGER_H
+#include "ns3/node-container.h"
+
namespace ns3 {
/**
@@ -40,7 +42,8 @@
public:
/**
* @brief Build a routing database and initialize the routing tables of
- * the nodes in the simulation.
+ * the nodes in the simulation. Makes all nodes in the simulation into
+ * routers.
*
* All this function does is call BuildGlobalRoutingDatabase () and
* InitializeRoutes ().
@@ -51,6 +54,19 @@
static void PopulateRoutingTables ();
/**
+ * @brief Build a routing database and initialize the routing tables of
+ * the nodes in the simulation. Makes the nodes in the provided container
+ * into routers.
+ *
+ * All this function does is call BuildGlobalRoutingDatabase () and
+ * InitializeRoutes ().
+ *
+ * @see BuildGlobalRoutingDatabase ();
+ * @see InitializeRoutes ();
+ */
+ static void PopulateRoutingTables (NodeContainer c);
+
+/**
* @brief Allocate a 32-bit router ID from monotonically increasing counter.
*/
static uint32_t AllocateRouterId ();
@@ -65,6 +81,14 @@
static void SelectRouterNodes ();
/**
+ * @brief Select which nodes in the system are to be router nodes and
+ * aggregate the appropriate interfaces onto those nodes.
+ * @internal
+ *
+ */
+ static void SelectRouterNodes (NodeContainer c);
+
+/**
* @brief Build the routing database by gathering Link State Advertisements
* from each node exporting a GlobalRouter interface.
* @internal
--- a/src/routing/global-routing/global-router-interface.cc Fri Nov 28 08:55:24 2008 +0100
+++ b/src/routing/global-routing/global-router-interface.cc Fri Nov 28 08:56:47 2008 +0100
@@ -20,11 +20,15 @@
#include "ns3/log.h"
#include "ns3/assert.h"
+#include "ns3/abort.h"
#include "ns3/channel.h"
#include "ns3/net-device.h"
#include "ns3/node.h"
#include "ns3/ipv4.h"
+#include "ns3/bridge-net-device.h"
+#include "ns3/net-device-container.h"
#include "global-router-interface.h"
+#include <vector>
NS_LOG_COMPONENT_DEFINE ("GlobalRouter");
@@ -365,8 +369,7 @@
return *i;
}
}
- NS_ASSERT_MSG(false,
- "GlobalRoutingLSA::GetAttachedRouter (): invalid index");
+ NS_ASSERT_MSG(false, "GlobalRoutingLSA::GetAttachedRouter (): invalid index");
return Ipv4Address("0.0.0.0");
}
@@ -380,9 +383,25 @@
void
GlobalRoutingLSA::Print (std::ostream &os) const
{
- os << "m_lsType = " << m_lsType << std::endl <<
- "m_linkStateId = " << m_linkStateId << std::endl <<
- "m_advertisingRtr = " << m_advertisingRtr << std::endl;
+ os << std::endl;
+ os << "========== Global Routing LSA ==========" << std::endl;
+ os << "m_lsType = " << m_lsType;
+ if (m_lsType == GlobalRoutingLSA::RouterLSA)
+ {
+ os << " (GlobalRoutingLSA::RouterLSA)";
+ }
+ else if (m_lsType == GlobalRoutingLSA::NetworkLSA)
+ {
+ os << " (GlobalRoutingLSA::NetworkLSA)";
+ }
+ else
+ {
+ os << "(Unknown LSType)";
+ }
+ os << std::endl;
+
+ os << "m_linkStateId = " << m_linkStateId << " (Router ID)" << std::endl;
+ os << "m_advertisingRtr = " << m_advertisingRtr << " (Router ID)" << std::endl;
if (m_lsType == GlobalRoutingLSA::RouterLSA)
{
@@ -391,30 +410,49 @@
i++)
{
GlobalRoutingLinkRecord *p = *i;
- os << "----------" << std::endl;
- os << "m_linkId = " << p->GetLinkId () << std::endl;
- os << "m_linkData = " << p->GetLinkData () << std::endl;
- os << "m_metric = " << p->GetMetric () << std::endl;
+
+ os << "---------- RouterLSA Link Record ----------" << std::endl;
+ os << "m_linkType = " << p->m_linkType;
+ if (p->m_linkType == GlobalRoutingLinkRecord::TransitNetwork)
+ {
+ os << " (GlobalRoutingLinkRecord::TransitNetwork)" << std::endl;
+ os << "m_linkId = " << p->m_linkId << " (Designated router for network)" << std::endl;
+ os << "m_linkData = " << p->m_linkData << " (This router's IP address)" << std::endl;
+ os << "m_metric = " << p->m_metric << std::endl;
+ }
+ else if (p->GetLinkType () == GlobalRoutingLinkRecord::StubNetwork)
+ {
+ os << "(GlobalRoutingLinkRecord::StubNetwork)" << std::endl;
+ os << "m_linkId = " << p->m_linkId << " (Network number of attached network)" << std::endl;
+ os << "m_linkData = " << p->m_linkData << " (Network mask of attached network)" << std::endl;
+ os << "m_metric = " << p->m_metric << std::endl;
+ }
+ else
+ {
+ os << "(Unknown LinkType)" << std::endl;
+ os << "m_linkId = " << p->m_linkId << std::endl;
+ os << "m_linkData = " << p->m_linkData << std::endl;
+ os << "m_metric = " << p->m_metric << std::endl;
+ }
+ os << "---------- End RouterLSA Link Record ----------" << std::endl;
}
}
else if (m_lsType == GlobalRoutingLSA::NetworkLSA)
{
- os << "----------" << std::endl;
- os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask
- << std::endl;
- for ( ListOfAttachedRouters_t::const_iterator i =
- m_attachedRouters.begin ();
- i != m_attachedRouters.end ();
- i++)
+ os << "---------- NetworkLSA Link Record ----------" << std::endl;
+ os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
+ for ( ListOfAttachedRouters_t::const_iterator i = m_attachedRouters.begin (); i != m_attachedRouters.end (); i++)
{
Ipv4Address p = *i;
os << "attachedRouter = " << p << std::endl;
}
+ os << "---------- End NetworkLSA Link Record ----------" << std::endl;
}
else
{
NS_ASSERT_MSG(0, "Illegal LSA LSType: " << m_lsType);
}
+ os << "========== End Global Routing LSA ==========" << std::endl;
}
std::ostream& operator<< (std::ostream& os, GlobalRoutingLSA& lsa)
@@ -487,53 +525,79 @@
}
//
-// Go out and discover any adjacent routers and build the Link State
-// Advertisements that reflect them and their associated networks.
+// DiscoverLSAs is called on all nodes in the system that have a GlobalRouter
+// interface aggregated. We need to go out and discover any adjacent routers
+// and build the Link State Advertisements that reflect them and their associated
+// networks.
//
uint32_t
GlobalRouter::DiscoverLSAs (void)
{
NS_LOG_FUNCTION_NOARGS ();
Ptr<Node> node = GetObject<Node> ();
- NS_LOG_LOGIC("For node " << node->GetId () );
- NS_ASSERT_MSG(node,
- "GlobalRouter::DiscoverLSAs (): <Node> interface not set");
+ NS_ABORT_MSG_UNLESS (node, "GlobalRouter::DiscoverLSAs (): GetObject for <Node> interface failed");
+ NS_LOG_LOGIC ("For node " << node->GetId () );
ClearLSAs ();
-// While building the router-LSA, keep a list of those NetDevices for
-// which I am the designated router and need to later build a NetworkLSA
- std::list<Ptr<NetDevice> > listOfDRInterfaces;
+ //
+ // While building the Router-LSA, keep a list of those NetDevices for
+ // which the current node is the designated router and we will later build
+ // a NetworkLSA for.
+ //
+ NetDeviceContainer c;
-//
-// We're aggregated to a node. We need to ask the node for a pointer to its
-// Ipv4 interface. This is where the information regarding the attached
-// interfaces lives.
-//
+ //
+ // We're aggregated to a node. We need to ask the node for a pointer to its
+ // Ipv4 interface. This is where the information regarding the attached
+ // interfaces lives. If we're a router, we had better have an Ipv4 interface.
+ //
Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
- NS_ASSERT_MSG(ipv4Local,
- "GlobalRouter::DiscoverLSAs (): QI for <Ipv4> interface failed");
-//
-// Each node originates a Router-LSA
-//
+ NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::DiscoverLSAs (): GetObject for <Ipv4> interface failed");
+
+ //
+ // Every router node originates a Router-LSA
+ //
GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
pLSA->SetLSType (GlobalRoutingLSA::RouterLSA);
pLSA->SetLinkStateId (m_routerId);
pLSA->SetAdvertisingRouter (m_routerId);
pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
-//
-// We need to ask the node for the number of net devices attached. This isn't
-// necessarily equal to the number of links to adjacent nodes (other routers)
-// as the number of devices may include those for stub networks (e.g.,
-// ethernets, etc.).
-//
+
+ //
+ // Ask the node for the number of net devices attached. This isn't necessarily
+ // equal to the number of links to adjacent nodes (other routers) as the number
+ // of devices may include those for stub networks (e.g., ethernets, etc.) and
+ // bridge devices also take up an "extra" net device.
+ //
uint32_t numDevices = node->GetNDevices();
- NS_LOG_LOGIC ("numDevices = " << numDevices);
+
+ //
+ // Iterate through the devices on the node and walk the channel to see what's
+ // on the other side of the standalone devices..
+ //
for (uint32_t i = 0; i < numDevices; ++i)
{
Ptr<NetDevice> ndLocal = node->GetDevice(i);
- // Check if it is an IP interface (could be a pure L2 NetDevice)
+ //
+ // There is an assumption that bridge ports must never have an IP address
+ // associated with them. This turns out to be a very convenient place to
+ // check and make sure that this is the case.
+ //
+ if (NetDeviceIsBridged (ndLocal))
+ {
+ uint32_t ifIndexBridge;
+ bool rc = FindIfIndexForDevice(node, ndLocal, ifIndexBridge);
+ NS_ABORT_MSG_IF (rc, "GlobalRouter::DiscoverLSAs(): Bridge ports must not have an IPv4 interface index");
+ }
+
+ //
+ // Check to see if the net device we just got has a corresponding IP
+ // interface (could be a pure L2 NetDevice) -- for example a net device
+ // associated with a bridge. We are only going to involve devices with
+ // IP addresses in routing.
+ //
bool isIp = false;
for (uint32_t i = 0; i < ipv4Local->GetNInterfaces (); ++i )
{
@@ -543,240 +607,723 @@
break;
}
}
+
if (!isIp)
{
+ NS_LOG_LOGIC ("Net device " << ndLocal << "has no IP interface, skipping");
continue;
}
+ //
+ // We have a net device that we need to check out. If it suports
+ // broadcast and is not a point-point link, then it will be either a stub
+ // network or a transit network depending on the number of routers on
+ // the segment. We add the appropriate link record to the LSA.
+ //
+ // If the device is a point to point link, we treat it separately. In
+ // that case, there always two link records added.
+ //
if (ndLocal->IsBroadcast () && !ndLocal->IsPointToPoint () )
{
NS_LOG_LOGIC ("Broadcast link");
- GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
-//
-// We need to determine whether we are on a transit or stub network
-// If we find at least one more router on this channel, we are a transit
-//
-//
-// Now, we have to find the Ipv4 interface whose netdevice is the one we
-// just found. This is still the IP on the local side of the channel. There
-// is a function to do this used down in the guts of the stack, but it's not
-// exported so we had to whip up an equivalent.
-//
- uint32_t ifIndexLocal = FindIfIndexForDevice(node, ndLocal);
- Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
- Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
- NS_LOG_LOGIC ("Working with local address " << addrLocal);
- uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal);
-//
-// Now, we're going to walk over to the remote net device on the other end of
-// the point-to-point channel we now know we have. This is where our adjacent
-// router (to use OSPF lingo) is running.
-//
- Ptr<Channel> ch = ndLocal->GetChannel();
- uint32_t nDevices = ch->GetNDevices();
- if (nDevices == 1)
- {
- // This is a stub broadcast interface
- NS_LOG_LOGIC("Router-LSA stub broadcast link");
- // XXX in future, need to consider if >1 includes other routers
- plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
- // Link ID is IP network number of attached network
- plr->SetLinkId (addrLocal.CombineMask(maskLocal));
- // Link Data is network mask; convert to Ipv4Address
- Ipv4Address maskLocalAddr;
- maskLocalAddr.Set(maskLocal.Get ());
- plr->SetLinkData (maskLocalAddr);
- plr->SetMetric (metricLocal);
- pLSA->AddLinkRecord(plr);
- plr = 0;
- continue;
- }
- else
- {
- NS_LOG_LOGIC ("Router-LSA Broadcast link");
- // multiple routers on a broadcast interface
- // lowest IP address is designated router
- plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork);
- // Link ID is IP interface address of designated router
- Ipv4Address desigRtr =
- FindDesignatedRouterForLink (node, ndLocal);
- if (desigRtr == addrLocal)
- {
- listOfDRInterfaces.push_back (ndLocal);
- NS_LOG_LOGIC (node->GetId () << " is a DR");
- }
- plr->SetLinkId (desigRtr);
- // Link Data is router's own IP address
- plr->SetLinkData (addrLocal);
- plr->SetMetric (metricLocal);
- pLSA->AddLinkRecord (plr);
- plr = 0;
- continue;
- }
+ ProcessBroadcastLink (ndLocal, pLSA, c);
}
else if (ndLocal->IsPointToPoint () )
{
- NS_LOG_LOGIC ("Router-LSA Point-to-point device");
-//
-// Now, we have to find the Ipv4 interface whose netdevice is the one we
-// just found. This is still the IP on the local side of the channel. There
-// is a function to do this used down in the guts of the stack, but it's not
-// exported so we had to whip up an equivalent.
-//
- uint32_t ifIndexLocal = FindIfIndexForDevice(node, ndLocal);
-//
-// Now that we have the Ipv4 interface index, we can get the address and mask
-// we need.
-//
- Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
- Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
- NS_LOG_LOGIC ("Working with local address " << addrLocal);
- uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal);
-//
-// Now, we're going to walk over to the remote net device on the other end of
-// the point-to-point channel we now know we have. This is where our adjacent
-// router (to use OSPF lingo) is running.
-//
- Ptr<Channel> ch = ndLocal->GetChannel();
- if (ch == NULL)
- {
- continue;
- }
- Ptr<NetDevice> ndRemote = GetAdjacent(ndLocal, ch);
-//
-// The adjacent net device is aggregated to a node. We need to ask that net
-// device for its node, then ask that node for its Ipv4 interface.
-//
- Ptr<Node> nodeRemote = ndRemote->GetNode();
- Ptr<Ipv4> ipv4Remote = nodeRemote->GetObject<Ipv4> ();
- NS_ASSERT_MSG(ipv4Remote,
- "GlobalRouter::DiscoverLSAs (): QI for remote <Ipv4> failed");
-//
-// Per the OSPF spec, we're going to need the remote router ID, so we might as
-// well get it now.
-//
- Ptr<GlobalRouter> srRemote =
- nodeRemote->GetObject<GlobalRouter> ();
- NS_ASSERT_MSG(srRemote,
- "GlobalRouter::DiscoverLSAs():QI for remote <GlobalRouter> failed");
- Ipv4Address rtrIdRemote = srRemote->GetRouterId();
- NS_LOG_LOGIC ("Working with remote router " << rtrIdRemote);
-//
-// Now, just like we did above, we need to get the IP interface index for the
-// net device on the other end of the point-to-point channel.
-//
- uint32_t ifIndexRemote = FindIfIndexForDevice(nodeRemote, ndRemote);
-//
-// Now that we have the Ipv4 interface, we can get the (remote) address and
-// mask we need.
-//
- Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote);
- Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote);
- NS_LOG_LOGIC ("Working with remote address " << addrRemote);
-//
-// Now we can fill out the link records for this link. There are always two
-// link records; the first is a point-to-point record describing the link and
-// the second is a stub network record with the network number.
-//
- GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
- plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint);
- plr->SetLinkId (rtrIdRemote);
- plr->SetLinkData (addrLocal);
- plr->SetMetric (metricLocal);
- pLSA->AddLinkRecord (plr);
- plr = 0;
-
- plr = new GlobalRoutingLinkRecord;
- plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
- plr->SetLinkId (addrRemote);
- plr->SetLinkData (Ipv4Address(maskRemote.Get())); // Frown
- plr->SetMetric (metricLocal);
- pLSA->AddLinkRecord (plr);
- plr = 0;
+ NS_LOG_LOGIC ("Point=to-point link");
+ ProcessPointToPointLink (ndLocal, pLSA);
}
else
{
NS_ASSERT_MSG(0, "GlobalRouter::DiscoverLSAs (): unknown link type");
}
+ }
- }
-//
-// The LSA goes on a list of LSAs in case we want to begin exporting other
-// kinds of advertisements (than Router LSAs).
- m_LSAs.push_back (pLSA);
+ NS_LOG_LOGIC ("========== LSA for node " << node->GetId () << " ==========");
NS_LOG_LOGIC (*pLSA);
+ m_LSAs.push_back (pLSA);
+ pLSA = 0;
-// Now, determine whether we need to build a NetworkLSA
- if (listOfDRInterfaces.size () > 0)
+ //
+ // Now, determine whether we need to build a NetworkLSA. This is the case if
+ // we found at least one designated router.
+ //
+ uint32_t nDesignatedRouters = c.GetN ();
+ if (nDesignatedRouters > 0)
+ {
+ NS_LOG_LOGIC ("Build Network LSAs");
+ BuildNetworkLSAs (c);
+ }
+
+ return m_LSAs.size ();
+}
+
+ void
+GlobalRouter::ProcessBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
+{
+ NS_LOG_FUNCTION (nd << pLSA << &c);
+
+ if (nd->IsBridge ())
+ {
+ ProcessBridgedBroadcastLink (nd, pLSA, c);
+ }
+ else
+ {
+ ProcessSingleBroadcastLink (nd, pLSA, c);
+ }
+}
+
+ void
+GlobalRouter::ProcessSingleBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
+{
+ NS_LOG_FUNCTION (nd << pLSA << &c);
+
+ GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
+ NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessSingleBroadcastLink(): Can't alloc link record");
+
+ //
+ // We have some preliminaries to do to get enough information to proceed.
+ // This information we need comes from the internet stack, so notice that
+ // there is an implied assumption that global routing is only going to
+ // work with devices attached to the internet stack (have an ipv4 interface
+ // associated to them.
+ //
+ Ptr<Node> node = nd->GetNode ();
+
+ uint32_t ifIndexLocal;
+ bool rc = FindIfIndexForDevice(node, nd, ifIndexLocal);
+ NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessSingleBroadcastLink(): No interface index associated with device");
+
+ Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
+ NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessSingleBroadcastLink (): GetObject for <Ipv4> interface failed");
+
+ Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
+ Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
+ NS_LOG_LOGIC ("Working with local address " << addrLocal);
+ uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal);
+
+ //
+ // Check to see if the net device is connected to a channel/network that has
+ // another router on it. If there is no other router on the link (but us) then
+ // this is a stub network. If we find another router, then what we have here
+ // is a transit network.
+ //
+ if (AnotherRouterOnLink (nd, true) == false)
+ {
+ //
+ // This is a net device connected to a stub network
+ //
+ NS_LOG_LOGIC("Router-LSA Stub Network");
+ plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
+
+ //
+ // According to OSPF, the Link ID is the IP network number of
+ // the attached network.
+ //
+ plr->SetLinkId (addrLocal.CombineMask(maskLocal));
+
+ //
+ // and the Link Data is the network mask; converted to Ipv4Address
+ //
+ Ipv4Address maskLocalAddr;
+ maskLocalAddr.Set(maskLocal.Get ());
+ plr->SetLinkData (maskLocalAddr);
+ plr->SetMetric (metricLocal);
+ pLSA->AddLinkRecord(plr);
+ plr = 0;
+ }
+ else
{
- for (std::list<Ptr<NetDevice> >::iterator i = listOfDRInterfaces.begin ();
- i != listOfDRInterfaces.end (); i++)
+ //
+ // We have multiple routers on a broadcast interface, so this is
+ // a transit network.
+ //
+ NS_LOG_LOGIC ("Router-LSA Transit Network");
+ plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork);
+
+ //
+ // By definition, the router with the lowest IP address is the
+ // designated router for the network. OSPF says that the Link ID
+ // gets the IP interface address of the designated router in this
+ // case.
+ //
+ Ipv4Address desigRtr = FindDesignatedRouterForLink (nd, true);
+
+ //
+ // Let's double-check that any designated router we find out on our
+ // network is really on our network.
+ //
+ if (desigRtr != "255.255.255.255")
+ {
+ Ipv4Address networkHere = addrLocal.CombineMask (maskLocal);
+ Ipv4Address networkThere = desigRtr.CombineMask (maskLocal);
+ NS_ABORT_MSG_UNLESS (networkHere == networkThere,
+ "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion");
+ }
+ if (desigRtr == addrLocal)
+ {
+ c.Add (nd);
+ NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router");
+ }
+ plr->SetLinkId (desigRtr);
+
+ //
+ // OSPF says that the Link Data is this router's own IP address.
+ //
+ plr->SetLinkData (addrLocal);
+ plr->SetMetric (metricLocal);
+ pLSA->AddLinkRecord (plr);
+ plr = 0;
+ }
+}
+
+ void
+GlobalRouter::ProcessBridgedBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
+{
+ NS_LOG_FUNCTION (nd << pLSA << &c);
+ NS_ASSERT_MSG (nd->IsBridge (), "GlobalRouter::ProcessBridgedBroadcastLink(): Called with non-bridge net device");
+
+#if 0
+ //
+ // It is possible to admit the possibility that a bridge device on a node
+ // can also participate in routing. This would surprise people who don't
+ // come from Microsoft-land where they do use such a construct. Based on
+ // the principle of least-surprise, we will leave the relatively simple
+ // code in place to do this, but not enable it until someone really wants
+ // the capability. Even then, we will not enable this code as a default
+ // but rather something you will have to go and turn on.
+ //
+
+ Ptr<BridgeNetDevice> bnd = nd->GetObject<BridgeNetDevice> ();
+ NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
+
+ //
+ // We have some preliminaries to do to get enough information to proceed.
+ // This information we need comes from the internet stack, so notice that
+ // there is an implied assumption that global routing is only going to
+ // work with devices attached to the internet stack (have an ipv4 interface
+ // associated to them.
+ //
+ Ptr<Node> node = nd->GetNode ();
+
+ uint32_t ifIndexLocal;
+ bool rc = FindIfIndexForDevice(node, nd, ifIndexLocal);
+ NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessBridgedBroadcastLink(): No interface index associated with device");
+
+ Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
+ NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessBridgedBroadcastLink (): GetObject for <Ipv4> interface failed");
+
+ Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
+ Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
+ NS_LOG_LOGIC ("Working with local address " << addrLocal);
+ uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal);
+
+ //
+ // We need to handle a bridge on the router. This means that we have been
+ // given a net device that is a BridgeNetDevice. It has an associated Ipv4
+ // interface index and address. Some number of other net devices live "under"
+ // the bridge device as so-called bridge ports. In a nutshell, what we have
+ // to do is to repeat what is done for a single broadcast link on all of
+ // those net devices living under the bridge (trolls?)
+ //
+
+ bool areTransitNetwork = false;
+ Ipv4Address desigRtr ("255.255.255.255");
+
+ for (uint32_t i = 0; i < bnd->GetNBridgePorts (); ++i)
+ {
+ Ptr<NetDevice> ndTemp = bnd->GetBridgePort (i);
+
+ //
+ // We have to decide if we are a transit network. This is characterized
+ // by the presence of another router on the network segment. If we find
+ // another router on any of our bridged links, we are a transit network.
+ //
+ if (AnotherRouterOnLink (ndTemp, true))
{
-// Build one NetworkLSA for each interface that is a DR
- Ptr<NetDevice> ndLocal = *i;
- uint32_t ifIndexLocal = FindIfIndexForDevice(node, ndLocal);
- Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
- Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
+ areTransitNetwork = true;
+
+ //
+ // If we're going to be a transit network, then we have got to elect
+ // a designated router for the whole bridge. This means finding the
+ // router with the lowest IP address on the whole bridge. We ask
+ // for the lowest address on each segment and pick the lowest of them
+ // all.
+ //
+ Ipv4Address desigRtrTemp = FindDesignatedRouterForLink (ndTemp, true);
+
+ //
+ // Let's double-check that any designated router we find out on our
+ // network is really on our network.
+ //
+ if (desigRtrTemp != "255.255.255.255")
+ {
+ Ipv4Address networkHere = addrLocal.CombineMask (maskLocal);
+ Ipv4Address networkThere = desigRtrTemp.CombineMask (maskLocal);
+ NS_ABORT_MSG_UNLESS (networkHere == networkThere,
+ "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion");
+ }
+ if (desigRtrTemp < desigRtr)
+ {
+ desigRtr = desigRtrTemp;
+ }
+ }
+ }
+ //
+ // That's all the information we need to put it all together, just like we did
+ // in the case of a single broadcast link.
+ //
+
+ GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
+ NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessBridgedBroadcastLink(): Can't alloc link record");
+
+ if (areTransitNetwork == false)
+ {
+ //
+ // This is a net device connected to a bridge of stub networks
+ //
+ NS_LOG_LOGIC("Router-LSA Stub Network");
+ plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
+
+ //
+ // According to OSPF, the Link ID is the IP network number of
+ // the attached network.
+ //
+ plr->SetLinkId (addrLocal.CombineMask(maskLocal));
+
+ //
+ // and the Link Data is the network mask; converted to Ipv4Address
+ //
+ Ipv4Address maskLocalAddr;
+ maskLocalAddr.Set(maskLocal.Get ());
+ plr->SetLinkData (maskLocalAddr);
+ plr->SetMetric (metricLocal);
+ pLSA->AddLinkRecord(plr);
+ plr = 0;
+ }
+ else
+ {
+ //
+ // We have multiple routers on a bridged broadcast interface, so this is
+ // a transit network.
+ //
+ NS_LOG_LOGIC ("Router-LSA Transit Network");
+ plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork);
+
+ //
+ // By definition, the router with the lowest IP address is the
+ // designated router for the network. OSPF says that the Link ID
+ // gets the IP interface address of the designated router in this
+ // case.
+ //
+ if (desigRtr == addrLocal)
+ {
+ c.Add (nd);
+ NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router");
+ }
+ plr->SetLinkId (desigRtr);
+
+ //
+ // OSPF says that the Link Data is this router's own IP address.
+ //
+ plr->SetLinkData (addrLocal);
+ plr->SetMetric (metricLocal);
+ pLSA->AddLinkRecord (plr);
+ plr = 0;
+ }
+#endif
+}
+
+ void
+GlobalRouter::ProcessPointToPointLink (Ptr<NetDevice> ndLocal, GlobalRoutingLSA *pLSA)
+{
+ NS_LOG_FUNCTION (ndLocal << pLSA);
+
+ //
+ // We have some preliminaries to do to get enough information to proceed.
+ // This information we need comes from the internet stack, so notice that
+ // there is an implied assumption that global routing is only going to
+ // work with devices attached to the internet stack (have an ipv4 interface
+ // associated to them.
+ //
+ Ptr<Node> nodeLocal = ndLocal->GetNode ();
+
+ uint32_t ifIndexLocal;
+ bool rc = FindIfIndexForDevice(nodeLocal, ndLocal, ifIndexLocal);
+ NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLink (): No interface index associated with device");
+
+ Ptr<Ipv4> ipv4Local = nodeLocal->GetObject<Ipv4> ();
+ NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
+
+ Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
+ Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
+ NS_LOG_LOGIC ("Working with local address " << addrLocal);
+ uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal);
+
+ //
+ // Now, we're going to walk over to the remote net device on the other end of
+ // the point-to-point channel we know we have. This is where our adjacent
+ // router (to use OSPF lingo) is running.
+ //
+ Ptr<Channel> ch = ndLocal->GetChannel();
+
+ //
+ // Get the net device on the other side of the point-to-point channel.
+ //
+ Ptr<NetDevice> ndRemote = GetAdjacent(ndLocal, ch);
- GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
- pLSA->SetLSType (GlobalRoutingLSA::NetworkLSA);
- pLSA->SetLinkStateId (addrLocal);
- pLSA->SetAdvertisingRouter (m_routerId);
- pLSA->SetNetworkLSANetworkMask (maskLocal);
- pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
-// Build list of AttachedRouters
- Ptr<Channel> ch = ndLocal->GetChannel();
- uint32_t nDevices = ch->GetNDevices();
- NS_ASSERT (nDevices);
- for (uint32_t i = 0; i < nDevices; i++)
+ //
+ // The adjacent net device is aggregated to a node. We need to ask that net
+ // device for its node, then ask that node for its Ipv4 interface. Note a
+ // requirement that nodes on either side of a point-to-point link must have
+ // internet stacks; and an assumption that point-to-point links are incompatible
+ // with bridging.
+ //
+ Ptr<Node> nodeRemote = ndRemote->GetNode();
+ Ptr<Ipv4> ipv4Remote = nodeRemote->GetObject<Ipv4> ();
+ NS_ABORT_MSG_UNLESS (ipv4Remote,
+ "GlobalRouter::ProcessPointToPointLink(): GetObject for remote <Ipv4> failed");
+
+ //
+ // Further note the requirement that nodes on either side of a point-to-point
+ // link must participate in global routing and therefore have a GlobalRouter
+ // interface aggregated.
+ //
+ Ptr<GlobalRouter> rtrRemote = nodeRemote->GetObject<GlobalRouter> ();
+ NS_ABORT_MSG_UNLESS(rtrRemote,
+ "GlobalRouter::ProcessPointToPointLinks(): GetObject for remote <GlobalRouter> failed");
+
+ //
+ // We're going to need the remote router ID, so we might as well get it now.
+ //
+ Ipv4Address rtrIdRemote = rtrRemote->GetRouterId();
+ NS_LOG_LOGIC ("Working with remote router " << rtrIdRemote);
+
+ //
+ // Now, just like we did above, we need to get the IP interface index for the
+ // net device on the other end of the point-to-point channel.
+ //
+ uint32_t ifIndexRemote;
+ rc = FindIfIndexForDevice(nodeRemote, ndRemote, ifIndexRemote);
+ NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLinks(): No interface index associated with remote device");
+
+ //
+ // Now that we have the Ipv4 interface, we can get the (remote) address and
+ // mask we need.
+ //
+ Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote);
+ Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote);
+ NS_LOG_LOGIC ("Working with remote address " << addrRemote);
+
+ //
+ // Now we can fill out the link records for this link. There are always two
+ // link records; the first is a point-to-point record describing the link and
+ // the second is a stub network record with the network number.
+ //
+ GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
+ NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
+ plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint);
+ plr->SetLinkId (rtrIdRemote);
+ plr->SetLinkData (addrLocal);
+ plr->SetMetric (metricLocal);
+ pLSA->AddLinkRecord (plr);
+ plr = 0;
+
+ plr = new GlobalRoutingLinkRecord;
+ NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
+ plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
+ plr->SetLinkId (addrRemote);
+ plr->SetLinkData (Ipv4Address(maskRemote.Get())); // Frown
+ plr->SetMetric (metricLocal);
+ pLSA->AddLinkRecord (plr);
+ plr = 0;
+}
+
+ void
+GlobalRouter::BuildNetworkLSAs (NetDeviceContainer c)
+{
+ NS_LOG_FUNCTION (&c);
+
+ uint32_t nDesignatedRouters = c.GetN ();
+
+ for (uint32_t i = 0; i < nDesignatedRouters; ++i)
+ {
+ //
+ // Build one NetworkLSA for each net device talking to a network that we are the
+ // designated router for. These devices are in the provided container.
+ //
+ Ptr<NetDevice> ndLocal = c.Get (i);
+ Ptr<Node> node = ndLocal->GetNode ();
+
+ uint32_t ifIndexLocal;
+ bool rc = FindIfIndexForDevice(node, ndLocal, ifIndexLocal);
+ NS_ABORT_MSG_IF (rc == false, "GlobalRouter::BuildNetworkLSAs (): No interface index associated with device");
+
+ Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
+ NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
+
+ Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
+ Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
+
+ GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
+ NS_ABORT_MSG_IF (pLSA == 0, "GlobalRouter::BuildNetworkLSAs(): Can't alloc link record");
+
+ pLSA->SetLSType (GlobalRoutingLSA::NetworkLSA);
+ pLSA->SetLinkStateId (addrLocal);
+ pLSA->SetAdvertisingRouter (m_routerId);
+ pLSA->SetNetworkLSANetworkMask (maskLocal);
+ pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
+
+ //
+ // Build a list of AttachedRouters by walking the devices in the channel
+ // and, if we find a node with a GlobalRouter interface and an IPv4
+ // interface associated with that device, we call it an attached router.
+ //
+ Ptr<Channel> ch = ndLocal->GetChannel();
+ uint32_t nDevices = ch->GetNDevices();
+ NS_ASSERT (nDevices);
+
+ for (uint32_t i = 0; i < nDevices; i++)
+ {
+ Ptr<NetDevice> tempNd = ch->GetDevice (i);
+ NS_ASSERT (tempNd);
+ Ptr<Node> tempNode = tempNd->GetNode ();
+
+ //
+ // Does the node in question have a GlobalRouter interface? If not it can
+ // hardly be considered an attached router.
+ //
+ Ptr<GlobalRouter> rtr = tempNode->GetObject<GlobalRouter> ();
+ if (rtr == 0)
+ {
+ continue;
+ }
+
+ //
+ // Does the attached node have an ipv4 interface for the device we're probing?
+ // If not, it can't play router.
+ //
+ uint32_t tempIfIndex;
+ if (FindIfIndexForDevice (tempNode, tempNd, tempIfIndex))
{
- Ptr<NetDevice> tempNd = ch->GetDevice (i);
- NS_ASSERT (tempNd);
- Ptr<Node> tempNode = tempNd->GetNode ();
- uint32_t tempIfIndex = FindIfIndexForDevice (tempNode, tempNd);
Ptr<Ipv4> tempIpv4 = tempNode->GetObject<Ipv4> ();
NS_ASSERT (tempIpv4);
Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex);
pLSA->AddAttachedRouter (tempAddr);
}
- m_LSAs.push_back (pLSA);
- NS_LOG_LOGIC (*pLSA);
}
+ m_LSAs.push_back (pLSA);
+ pLSA = 0;
}
-
- return m_LSAs.size ();
}
+//
+// Given a local net device, we need to walk the channel to which the net device is
+// attached and look for nodes with GlobalRouter interfaces on them (one of them
+// will be us). Of these, the router with the lowest IP address on the net device
+// connecting to the channel becomes the designated router for the link.
+//
Ipv4Address
-GlobalRouter::FindDesignatedRouterForLink (Ptr<Node> node,
- Ptr<NetDevice> ndLocal) const
+GlobalRouter::FindDesignatedRouterForLink (Ptr<NetDevice> ndLocal, bool allowRecursion) const
{
- uint32_t ifIndexLocal = FindIfIndexForDevice(node, ndLocal);
- Ptr<Ipv4> ipv4Local = GetObject<Ipv4> ();
- NS_ASSERT (ipv4Local);
- Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
- Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
+ NS_LOG_FUNCTION (ndLocal << allowRecursion);
Ptr<Channel> ch = ndLocal->GetChannel();
uint32_t nDevices = ch->GetNDevices();
NS_ASSERT (nDevices);
- Ipv4Address lowest = addrLocal;
- // iterate all NetDevices and return the lowest numbered IP address
+
+ NS_LOG_LOGIC ("Looking for designated router off of net device " << ndLocal << " on node " <<
+ ndLocal->GetNode ()->GetId ());
+
+ Ipv4Address desigRtr ("255.255.255.255");
+
+ //
+ // Look through all of the devices on the channel to which the net device
+ // in question is attached.
+ //
for (uint32_t i = 0; i < nDevices; i++)
{
- Ptr<NetDevice> tempNd = ch->GetDevice (i);
- NS_ASSERT (tempNd);
- Ptr<Node> tempNode = tempNd->GetNode ();
- uint32_t tempIfIndex = FindIfIndexForDevice (tempNode, tempNd);
- Ptr<Ipv4> tempIpv4 = tempNode->GetObject<Ipv4> ();
- NS_ASSERT (tempIpv4);
- Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex);
- if (tempAddr < addrLocal)
+ Ptr<NetDevice> ndOther = ch->GetDevice (i);
+ NS_ASSERT (ndOther);
+
+ Ptr<Node> nodeOther = ndOther->GetNode ();
+
+ NS_LOG_LOGIC ("Examine channel device " << i << " on node " << nodeOther->GetId ());
+
+ //
+ // For all other net devices, we need to check and see if a router
+ // is present. If the net device on the other side is a bridged
+ // device, we need to consider all of the other devices on the
+ // bridge as well (all of the bridge ports.
+ //
+ NS_LOG_LOGIC ("checking to see if the device is bridged");
+ Ptr<BridgeNetDevice> bnd = NetDeviceIsBridged (ndOther);
+ if (bnd)
{
- addrLocal = tempAddr;
+ NS_LOG_LOGIC ("Device is bridged by BridgeNetDevice " << bnd);
+
+ //
+ // It is possible that the bridge net device is sitting under a
+ // router, so we have to check for the presence of that router
+ // before we run off and follow all the links
+ //
+ // We require a designated router to have a GlobalRouter interface and
+ // an internet stack that includes the Ipv4 interface. If it doesn't
+ // it can't play router.
+ //
+ NS_LOG_LOGIC ("Checking for router on bridge net device " << bnd);
+ Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter> ();
+ Ptr<Ipv4> ipv4 = nodeOther->GetObject<Ipv4> ();
+ if (rtr && ipv4)
+ {
+ uint32_t ifIndexOther;
+ if (FindIfIndexForDevice(nodeOther, bnd, ifIndexOther))
+ {
+ NS_LOG_LOGIC ("Found router on bridge net device " << bnd);
+ Ipv4Address addrOther = ipv4->GetAddress (ifIndexOther);
+ desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
+ NS_LOG_LOGIC ("designated router now " << desigRtr);
+ }
+ }
+
+ NS_LOG_LOGIC ("Looking through bridge ports of bridge net device " << bnd);
+ for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
+ {
+ Ptr<NetDevice> ndBridged = bnd->GetBridgePort (j);
+ NS_LOG_LOGIC ("Examining bridge port " << j << " device " << ndBridged);
+ if (ndBridged == ndOther)
+ {
+ NS_LOG_LOGIC ("That bridge port is me, don't walk backward");
+ continue;
+ }
+
+ if (allowRecursion)
+ {
+ NS_LOG_LOGIC ("Recursively looking for routers down bridge port " << ndBridged);
+ Ipv4Address addrOther = FindDesignatedRouterForLink (ndBridged, false);
+ desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
+ NS_LOG_LOGIC ("designated router now " << desigRtr);
+ }
+ }
+ }
+ else
+ {
+ NS_LOG_LOGIC ("This device is not bridged");
+ Ptr<Node> nodeOther = ndOther->GetNode ();
+ NS_ASSERT (nodeOther);
+
+ //
+ // We require a designated router to have a GlobalRouter interface and
+ // an internet stack that includes the Ipv4 interface. If it doesn't
+ //
+ Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter> ();
+ Ptr<Ipv4> ipv4 = nodeOther->GetObject<Ipv4> ();
+ if (rtr && ipv4)
+ {
+ uint32_t ifIndexOther;
+ if (FindIfIndexForDevice(nodeOther, ndOther, ifIndexOther))
+ {
+ NS_LOG_LOGIC ("Found router on net device " << ndOther);
+ Ipv4Address addrOther = ipv4->GetAddress (ifIndexOther);
+ desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
+ NS_LOG_LOGIC ("designated router now " << desigRtr);
+ }
+ }
}
}
- return addrLocal;
+ return desigRtr;
+}
+
+//
+// Given a node and an attached net device, take a look off in the channel to
+// which the net device is attached and look for a node on the other side
+// that has a GlobalRouter interface aggregated. Life gets more complicated
+// when there is a bridged net device on the other side.
+//
+ bool
+GlobalRouter::AnotherRouterOnLink (Ptr<NetDevice> nd, bool allowRecursion) const
+{
+ NS_LOG_FUNCTION (nd << allowRecursion);
+
+ Ptr<Channel> ch = nd->GetChannel();
+ uint32_t nDevices = ch->GetNDevices();
+ NS_ASSERT (nDevices);
+
+ NS_LOG_LOGIC ("Looking for routers off of net device " << nd << " on node " << nd->GetNode ()->GetId ());
+
+ //
+ // Look through all of the devices on the channel to which the net device
+ // in question is attached.
+ //
+ for (uint32_t i = 0; i < nDevices; i++)
+ {
+ Ptr<NetDevice> ndOther = ch->GetDevice (i);
+ NS_ASSERT (ndOther);
+
+ NS_LOG_LOGIC ("Examine channel device " << i << " on node " << ndOther->GetNode ()->GetId ());
+
+ //
+ // Ignore the net device itself.
+ //
+ if (ndOther == nd)
+ {
+ NS_LOG_LOGIC ("Myself, skip");
+ continue;
+ }
+
+ //
+ // For all other net devices, we need to check and see if a router
+ // is present. If the net device on the other side is a bridged
+ // device, we need to consider all of the other devices on the
+ // bridge.
+ //
+ NS_LOG_LOGIC ("checking to see if device is bridged");
+ Ptr<BridgeNetDevice> bnd = NetDeviceIsBridged (ndOther);
+ if (bnd)
+ {
+ NS_LOG_LOGIC ("Device is bridged by net device " << bnd);
+ NS_LOG_LOGIC ("Looking through bridge ports of bridge net device " << bnd);
+ for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
+ {
+ Ptr<NetDevice> ndBridged = bnd->GetBridgePort (j);
+ NS_LOG_LOGIC ("Examining bridge port " << j << " device " << ndBridged);
+ if (ndBridged == ndOther)
+ {
+ NS_LOG_LOGIC ("That bridge port is me, skip");
+ continue;
+ }
+
+ if (allowRecursion)
+ {
+ NS_LOG_LOGIC ("Recursively looking for routers on bridge port " << ndBridged);
+ if (AnotherRouterOnLink (ndBridged, false))
+ {
+ NS_LOG_LOGIC ("Found routers on bridge port, return true");
+ return true;
+ }
+ }
+ }
+ NS_LOG_LOGIC ("No routers on bridged net device, return false");
+ return false;
+ }
+
+ NS_LOG_LOGIC ("This device is not bridged");
+ Ptr<Node> nodeTemp = ndOther->GetNode ();
+ NS_ASSERT (nodeTemp);
+
+ Ptr<GlobalRouter> rtr = nodeTemp->GetObject<GlobalRouter> ();
+ if (rtr)
+ {
+ NS_LOG_LOGIC ("Found GlobalRouter interface, return true");
+ return true;
+ }
+ else
+ {
+ NS_LOG_LOGIC ("No GlobalRouter interface on device, continue search");
+ }
+ }
+ NS_LOG_LOGIC ("No routers found, return false");
+ return false;
}
uint32_t
@@ -820,11 +1367,10 @@
// other end. This only makes sense with a point-to-point channel.
//
Ptr<NetDevice>
-GlobalRouter::GetAdjacent(Ptr<NetDevice> nd, Ptr<Channel> ch) const
+GlobalRouter::GetAdjacent (Ptr<NetDevice> nd, Ptr<Channel> ch) const
{
NS_LOG_FUNCTION_NOARGS ();
- NS_ASSERT_MSG(ch->GetNDevices() == 2,
- "GlobalRouter::GetAdjacent (): Channel with other than two devices");
+ NS_ASSERT_MSG(ch->GetNDevices() == 2, "GlobalRouter::GetAdjacent (): Channel with other than two devices");
//
// This is a point to point channel with two endpoints. Get both of them.
//
@@ -852,24 +1398,79 @@
}
//
-// Given a node and a net device, find the IPV4 interface index that
-// corresponds to that net device.
+// Given a node and a net device, find an IPV4 interface index that corresponds
+// to that net device. This function may fail for various reasons. If a node
+// does not have an internet stack (for example if it is a bridge) we won't have
+// an IPv4 at all. If the node does have a stack, but the net device in question
+// is bridged, there will not be an interface associated directly with the device.
//
- uint32_t
-GlobalRouter::FindIfIndexForDevice(Ptr<Node> node, Ptr<NetDevice> nd) const
+ bool
+GlobalRouter::FindIfIndexForDevice (Ptr<Node> node, Ptr<NetDevice> nd, uint32_t &index) const
{
NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_LOGIC("For node " << node->GetId () << " for net device " << nd );
+
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
- NS_ASSERT_MSG(ipv4, "QI for <Ipv4> interface failed");
+ if (ipv4 == 0)
+ {
+ NS_LOG_LOGIC ("No Ipv4 interface on node " << node->GetId ());
+ return false;
+ }
+
for (uint32_t i = 0; i < ipv4->GetNInterfaces(); ++i )
{
if (ipv4->GetNetDevice(i) == nd)
{
- return i;
+ NS_LOG_LOGIC ("Device " << nd << " has associated ipv4 index " << i);
+ index = i;
+ return true;
}
}
- NS_ASSERT_MSG(0, "Cannot find interface for device");
+ NS_LOG_LOGIC ("Device " << nd << " has no associated ipv4 index");
+ return false;
+}
+
+//
+// Decide whether or not a given net device is being bridged by a BridgeNetDevice.
+//
+ Ptr<BridgeNetDevice>
+GlobalRouter::NetDeviceIsBridged (Ptr<NetDevice> nd) const
+{
+ NS_LOG_FUNCTION (nd);
+
+ Ptr<Node> node = nd->GetNode ();
+ uint32_t nDevices = node->GetNDevices();
+
+ //
+ // There is no bit on a net device that says it is being bridged, so we have
+ // to look for bridges on the node to which the device is attached. If we
+ // find a bridge, we need to look through its bridge ports (the devices it
+ // bridges) to see if we find the device in question.
+ //
+ for (uint32_t i = 0; i < nDevices; ++i)
+ {
+ Ptr<NetDevice> ndTest = node->GetDevice(i);
+ NS_LOG_LOGIC ("Examine device " << i << " " << ndTest);
+
+ if (ndTest->IsBridge ())
+ {
+ NS_LOG_LOGIC ("device " << i << " is a bridge net device");
+ Ptr<BridgeNetDevice> bnd = ndTest->GetObject<BridgeNetDevice> ();
+ NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
+
+ for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
+ {
+ NS_LOG_LOGIC ("Examine bridge port " << j << " " << bnd->GetBridgePort (j));
+ if (bnd->GetBridgePort (j) == nd)
+ {
+ NS_LOG_LOGIC ("Net device " << nd << " is bridged by " << bnd);
+ return bnd;
+ }
+ }
+ }
+ }
+ NS_LOG_LOGIC ("Net device " << nd << " is not bridged");
return 0;
}
--- a/src/routing/global-routing/global-router-interface.h Fri Nov 28 08:55:24 2008 +0100
+++ b/src/routing/global-routing/global-router-interface.h Fri Nov 28 08:56:47 2008 +0100
@@ -29,10 +29,14 @@
#include "ns3/node.h"
#include "ns3/channel.h"
#include "ns3/ipv4-address.h"
+#include "ns3/net-device-container.h"
+#include "ns3/bridge-net-device.h"
#include "ns3/global-route-manager.h"
namespace ns3 {
+class GlobalRouter;
+
/**
* @brief A single link record for a link state advertisement.
*
@@ -43,6 +47,7 @@
class GlobalRoutingLinkRecord
{
public:
+ friend class GlobalRoutingLSA;
/**
* @enum LinkType
* @brief Enumeration of the possible types of Global Routing Link Records.
@@ -639,9 +644,17 @@
void ClearLSAs (void);
Ptr<NetDevice> GetAdjacent(Ptr<NetDevice> nd, Ptr<Channel> ch) const;
- uint32_t FindIfIndexForDevice(Ptr<Node> node, Ptr<NetDevice> nd) const;
- Ipv4Address FindDesignatedRouterForLink (Ptr<Node> node,
- Ptr<NetDevice> ndLocal) const;
+ bool FindIfIndexForDevice(Ptr<Node> node, Ptr<NetDevice> nd, uint32_t &index) const;
+ Ipv4Address FindDesignatedRouterForLink (Ptr<NetDevice> ndLocal, bool allowRecursion) const;
+ bool AnotherRouterOnLink (Ptr<NetDevice> nd, bool allowRecursion) const;
+ void ProcessBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c);
+ void ProcessSingleBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c);
+ void ProcessBridgedBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c);
+
+ void ProcessPointToPointLink (Ptr<NetDevice> ndLocal, GlobalRoutingLSA *pLSA);
+ void BuildNetworkLSAs (NetDeviceContainer c);
+ Ptr<BridgeNetDevice> NetDeviceIsBridged (Ptr<NetDevice> nd) const;
+
typedef std::list<GlobalRoutingLSA*> ListOfLSAs_t;
ListOfLSAs_t m_LSAs;
--- a/wscript Fri Nov 28 08:55:24 2008 +0100
+++ b/wscript Fri Nov 28 08:56:47 2008 +0100
@@ -447,16 +447,13 @@
if Params.g_options.run:
# Check that the requested program name is valid
- try:
- wutils.find_program(Params.g_options.run, env)
- except ValueError, ex:
- Params.fatal(str(ex))
-
+ program_name, dummy_program_argv = wutils.get_run_program(Params.g_options.run, get_command_template())
+
# When --run'ing a program, tell WAF to only build that program,
# nothing more; this greatly speeds up compilation when all you
# want to do is run a test program.
if not Params.g_options.compile_targets:
- Params.g_options.compile_targets = Params.g_options.run
+ Params.g_options.compile_targets = program_name
--- a/wutils.py Fri Nov 28 08:55:24 2008 +0100
+++ b/wutils.py Fri Nov 28 08:56:47 2008 +0100
@@ -94,13 +94,12 @@
Params.fatal("Command %s exited with code %i" % (argv, retval))
return retval
-def run_program(program_string, command_template=None):
+def get_run_program(program_string, command_template=None):
"""
- if command_template is not None, then program_string == program
- name and argv is given by command_template with %s replaced by the
- full path to the program. Else, program_string is interpreted as
- a shell command with first name being the program name.
+ Return the program name and argv of the process that would be executed by
+ run_program(program_string, command_template).
"""
+ #print "get_run_program_argv(program_string=%r, command_template=%r)" % (program_string, command_template)
env = Params.g_build.env_of_name('default')
if command_template in (None, '%s'):
@@ -132,7 +131,16 @@
Params.fatal("%s does not appear to be a program" % (program_name,))
execvec = shlex.split(command_template % (program_node.abspath(env),))
+ return program_name, execvec
+def run_program(program_string, command_template=None):
+ """
+ if command_template is not None, then program_string == program
+ name and argv is given by command_template with %s replaced by the
+ full path to the program. Else, program_string is interpreted as
+ a shell command with first name being the program name.
+ """
+ dummy_program_name, execvec = get_run_program(program_string, command_template)
former_cwd = os.getcwd()
if (Params.g_options.cwd_launch):
os.chdir(Params.g_options.cwd_launch)