diff --git a/CHANGES.html b/CHANGES.html index 82e79eb9b..00d1fcb26 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -106,6 +106,14 @@ assignment of /32 addresses. +
  • 17-11-2008; changeset +756887a9bbea
  • + +

    changes from ns-3.1 to ns-3.2

    diff --git a/examples/csma-bridge-one-hop.cc b/examples/csma-bridge-one-hop.cc new file mode 100644 index 000000000..e9876cffe --- /dev/null +++ b/examples/csma-bridge-one-hop.cc @@ -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 +#include + +#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 n0 = CreateObject (); + Ptr n1 = CreateObject (); + Ptr n2 = CreateObject (); + Ptr n3 = CreateObject (); + Ptr n4 = CreateObject (); + + Ptr bridge1 = CreateObject (); + Ptr bridge2 = CreateObject (); + + 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-- + // 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."); +} diff --git a/examples/wifi-wired-bridging.cc b/examples/wifi-wired-bridging.cc index 2852ae9b6..3d0ffb69e 100644 --- a/examples/wifi-wired-bridging.cc +++ b/examples/wifi-wired-bridging.cc @@ -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 @@ int main (int argc, char *argv[]) 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 @@ int main (int argc, char *argv[]) wifiPhy.SetChannel (wifiChannel.Create ()); sta.Create (nStas); - ip.NewNetwork (); mobility.SetPositionAllocator ("ns3::GridPositionAllocator", "MinX", DoubleValue (wifiX), "MinY", DoubleValue (0.0), @@ -87,8 +127,12 @@ int main (int argc, char *argv[]) "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); diff --git a/examples/wscript b/examples/wscript index 189c8d740..7f1318574 100644 --- a/examples/wscript +++ b/examples/wscript @@ -28,6 +28,10 @@ def build(bld): ['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' diff --git a/src/applications/v4ping/v4ping.cc b/src/applications/v4ping/v4ping.cc index e70917e60..2e53e5e64 100644 --- a/src/applications/v4ping/v4ping.cc +++ b/src/applications/v4ping/v4ping.cc @@ -149,6 +149,7 @@ void V4Ping::StopApplication (void) { NS_LOG_FUNCTION (this); + m_socket->Close (); } diff --git a/src/core/abort.h b/src/core/abort.h index 306058df3..6f52e684c 100644 --- a/src/core/abort.h +++ b/src/core/abort.h @@ -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) \ diff --git a/src/devices/bridge/bridge-net-device.cc b/src/devices/bridge/bridge-net-device.cc index e85ab5f78..413540157 100644 --- a/src/devices/bridge/bridge-net-device.cc +++ b/src/devices/bridge/bridge-net-device.cc @@ -57,6 +57,7 @@ BridgeNetDevice::BridgeNetDevice () m_ifIndex (0), m_mtu (0xffff) { + NS_LOG_FUNCTION_NOARGS (); m_channel = CreateObject (); } @@ -100,6 +101,7 @@ void BridgeNetDevice::ForwardUnicast (Ptr incomingPort, Ptr packet, uint16_t protocol, Mac48Address src, Mac48Address dst) { + NS_LOG_FUNCTION_NOARGS (); NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName () << ", packet=" << packet << ", protocol="< incomingPort, Ptr packet, uint16_t protocol, Mac48Address src, Mac48Address dst) { + NS_LOG_FUNCTION_NOARGS (); NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName () << ", packet=" << packet << ", protocol="< incomingPort, Ptr port) { + NS_LOG_FUNCTION_NOARGS (); if (m_enableLearning) { LearnedState &state = m_learnState[source]; @@ -164,6 +168,7 @@ void BridgeNetDevice::Learn (Mac48Address source, Ptr port) Ptr BridgeNetDevice::GetLearnedState (Mac48Address source) { + NS_LOG_FUNCTION_NOARGS (); if (m_enableLearning) { Time now = Simulator::Now (); @@ -185,9 +190,25 @@ Ptr BridgeNetDevice::GetLearnedState (Mac48Address source) return NULL; } +uint32_t +BridgeNetDevice::GetNBridgePorts (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_ports.size (); +} + + +Ptr +BridgeNetDevice::GetBridgePort (uint32_t n) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_ports[n]; +} + void BridgeNetDevice::AddBridgePort (Ptr bridgePort) { + NS_LOG_FUNCTION_NOARGS (); NS_ASSERT (bridgePort != this); if (!Mac48Address::IsMatchingType (bridgePort->GetAddress ())) { @@ -212,42 +233,49 @@ BridgeNetDevice::AddBridgePort (Ptr bridgePort) 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 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 @@ BridgeNetDevice::SetMtu (const uint16_t mtu) uint16_t BridgeNetDevice::GetMtu (void) const { + NS_LOG_FUNCTION_NOARGS (); return m_mtu; } @@ -262,6 +291,7 @@ BridgeNetDevice::GetMtu (void) const bool BridgeNetDevice::IsLinkUp (void) const { + NS_LOG_FUNCTION_NOARGS (); return true; } @@ -274,6 +304,7 @@ BridgeNetDevice::SetLinkChangeCallback (Callback callback) bool BridgeNetDevice::IsBroadcast (void) const { + NS_LOG_FUNCTION_NOARGS (); return true; } @@ -281,12 +312,14 @@ BridgeNetDevice::IsBroadcast (void) const 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 @@ BridgeNetDevice::GetMulticast (Ipv4Address multicastGroup) const 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, const Address& dest, uint16_t protocolNumber) { + NS_LOG_FUNCTION_NOARGS (); for (std::vector< Ptr >::iterator iter = m_ports.begin (); iter != m_ports.end (); iter++) { @@ -322,6 +364,7 @@ BridgeNetDevice::Send (Ptr packet, const Address& dest, uint16_t protoco bool BridgeNetDevice::SendFrom (Ptr packet, const Address& src, const Address& dest, uint16_t protocolNumber) { + NS_LOG_FUNCTION_NOARGS (); for (std::vector< Ptr >::iterator iter = m_ports.begin (); iter != m_ports.end (); iter++) { @@ -336,6 +379,7 @@ BridgeNetDevice::SendFrom (Ptr packet, const Address& src, const Address Ptr BridgeNetDevice::GetNode (void) const { + NS_LOG_FUNCTION_NOARGS (); return m_node; } @@ -343,6 +387,7 @@ BridgeNetDevice::GetNode (void) const void BridgeNetDevice::SetNode (Ptr node) { + NS_LOG_FUNCTION_NOARGS (); m_node = node; } @@ -350,6 +395,7 @@ BridgeNetDevice::SetNode (Ptr node) bool BridgeNetDevice::NeedsArp (void) const { + NS_LOG_FUNCTION_NOARGS (); return true; } @@ -357,25 +403,28 @@ BridgeNetDevice::NeedsArp (void) const 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 (); } diff --git a/src/devices/bridge/bridge-net-device.h b/src/devices/bridge/bridge-net-device.h index d8532c4b9..4353a5f58 100644 --- a/src/devices/bridge/bridge-net-device.h +++ b/src/devices/bridge/bridge-net-device.h @@ -82,6 +82,10 @@ public: */ void AddBridgePort (Ptr bridgePort); + uint32_t GetNBridgePorts (void) const; + + Ptr 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 @@ public: 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, const Address& dest, uint16_t protocolNumber); virtual bool SendFrom (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); virtual Ptr GetNode (void) const; diff --git a/src/devices/csma/csma-net-device.cc b/src/devices/csma/csma-net-device.cc index 5e6766518..11e9ee49d 100644 --- a/src/devices/csma/csma-net-device.cc +++ b/src/devices/csma/csma-net-device.cc @@ -832,6 +832,13 @@ CsmaNetDevice::GetMulticast (Ipv4Address multicastGroup) const bool CsmaNetDevice::IsPointToPoint (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return false; +} + + bool +CsmaNetDevice::IsBridge (void) const { NS_LOG_FUNCTION_NOARGS (); return false; diff --git a/src/devices/csma/csma-net-device.h b/src/devices/csma/csma-net-device.h index 59b7d59a7..e77b5e02e 100644 --- a/src/devices/csma/csma-net-device.h +++ b/src/devices/csma/csma-net-device.h @@ -350,6 +350,12 @@ public: */ virtual bool IsPointToPoint (void) const; + /** + * Is this a bridge? + * \returns false. + */ + virtual bool IsBridge (void) const; + /** * Start sending a packet down the channel. */ diff --git a/src/devices/emu/emu-net-device.cc b/src/devices/emu/emu-net-device.cc index 6e81f4bc1..95c620c48 100644 --- a/src/devices/emu/emu-net-device.cc +++ b/src/devices/emu/emu-net-device.cc @@ -882,6 +882,12 @@ EmuNetDevice::IsPointToPoint (void) const return false; } +bool +EmuNetDevice::IsBridge (void) const +{ + return false; +} + void EmuNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb) { diff --git a/src/devices/emu/emu-net-device.h b/src/devices/emu/emu-net-device.h index a2a04277f..b2147f3b8 100644 --- a/src/devices/emu/emu-net-device.h +++ b/src/devices/emu/emu-net-device.h @@ -165,6 +165,12 @@ public: */ virtual bool IsPointToPoint (void) const; + /** + * Is this a bridge? + * \returns false. + */ + virtual bool IsBridge (void) const; + virtual bool Send(Ptr packet, const Address &dest, uint16_t protocolNumber); virtual bool SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); diff --git a/src/devices/point-to-point/point-to-point-net-device.cc b/src/devices/point-to-point/point-to-point-net-device.cc index 9d3628663..60972851a 100644 --- a/src/devices/point-to-point/point-to-point-net-device.cc +++ b/src/devices/point-to-point/point-to-point-net-device.cc @@ -391,6 +391,12 @@ PointToPointNetDevice::IsPointToPoint (void) const return true; } + bool +PointToPointNetDevice::IsBridge (void) const +{ + return false; +} + bool PointToPointNetDevice::Send( Ptr packet, diff --git a/src/devices/point-to-point/point-to-point-net-device.h b/src/devices/point-to-point/point-to-point-net-device.h index c57241573..f8ce2e3ae 100644 --- a/src/devices/point-to-point/point-to-point-net-device.h +++ b/src/devices/point-to-point/point-to-point-net-device.h @@ -252,6 +252,7 @@ public: virtual Address GetMulticast (Ipv4Address multicastGroup) const; virtual bool IsPointToPoint (void) const; + virtual bool IsBridge (void) const; virtual bool Send(Ptr packet, const Address &dest, uint16_t protocolNumber); virtual bool SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); diff --git a/src/devices/wifi/wifi-net-device.cc b/src/devices/wifi/wifi-net-device.cc index 0b7c2afd8..bb29e07b9 100644 --- a/src/devices/wifi/wifi-net-device.cc +++ b/src/devices/wifi/wifi-net-device.cc @@ -238,6 +238,11 @@ WifiNetDevice::IsPointToPoint (void) const return false; } bool +WifiNetDevice::IsBridge (void) const +{ + return false; +} +bool WifiNetDevice::Send(Ptr packet, const Address& dest, uint16_t protocolNumber) { NS_ASSERT (Mac48Address::IsMatchingType (dest)); diff --git a/src/devices/wifi/wifi-net-device.h b/src/devices/wifi/wifi-net-device.h index 29afc476f..30a3427d9 100644 --- a/src/devices/wifi/wifi-net-device.h +++ b/src/devices/wifi/wifi-net-device.h @@ -90,6 +90,7 @@ public: 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, const Address& dest, uint16_t protocolNumber); virtual Ptr GetNode (void) const; virtual void SetNode (Ptr node); diff --git a/src/helper/bridge-helper.cc b/src/helper/bridge-helper.cc index 720dfb86d..4c7f8e553 100644 --- a/src/helper/bridge-helper.cc +++ b/src/helper/bridge-helper.cc @@ -1,24 +1,49 @@ -#include "bridge-helper.h" +/* -*- 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, NetDeviceContainer c) { + NS_LOG_FUNCTION_NOARGS (); + NS_LOG_LOGIC ("**** Install bridge device on node " << node->GetId ()); + NetDeviceContainer devs; Ptr dev = m_deviceFactory.Create (); devs.Add (dev); @@ -26,6 +51,7 @@ BridgeHelper::Install (Ptr node, NetDeviceContainer c) for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); ++i) { + NS_LOG_LOGIC ("**** Add BridgePort "<< *i); dev->AddBridgePort (*i); } return devs; diff --git a/src/helper/node-container.cc b/src/helper/node-container.cc index 333737e9c..5e3018046 100644 --- a/src/helper/node-container.cc +++ b/src/helper/node-container.cc @@ -50,6 +50,17 @@ NodeContainer::NodeContainer (const NodeContainer &a, const NodeContainer &b, 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 { diff --git a/src/helper/node-container.h b/src/helper/node-container.h index a4d9bbf9a..efeaaa96b 100644 --- a/src/helper/node-container.h +++ b/src/helper/node-container.h @@ -64,6 +64,8 @@ public: 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. diff --git a/src/node/net-device.h b/src/node/net-device.h index 490f3225e..ced6c9dff 100644 --- a/src/node/net-device.h +++ b/src/node/net-device.h @@ -184,6 +184,15 @@ public: 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; diff --git a/src/node/simple-net-device.cc b/src/node/simple-net-device.cc index 970ca74db..d13bd53fe 100644 --- a/src/node/simple-net-device.cc +++ b/src/node/simple-net-device.cc @@ -163,6 +163,13 @@ SimpleNetDevice::IsPointToPoint (void) const { return false; } + +bool +SimpleNetDevice::IsBridge (void) const +{ + return false; +} + bool SimpleNetDevice::Send(Ptr packet, const Address& dest, uint16_t protocolNumber) { diff --git a/src/node/simple-net-device.h b/src/node/simple-net-device.h index 2dac82c96..1e1f15323 100644 --- a/src/node/simple-net-device.h +++ b/src/node/simple-net-device.h @@ -61,6 +61,7 @@ public: 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, const Address& dest, uint16_t protocolNumber); virtual bool SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); virtual Ptr GetNode (void) const; diff --git a/src/routing/global-routing/global-route-manager-impl.cc b/src/routing/global-routing/global-route-manager-impl.cc index 8230c2a7f..eb9ff94c9 100644 --- a/src/routing/global-routing/global-route-manager-impl.cc +++ b/src/routing/global-routing/global-route-manager-impl.cc @@ -97,7 +97,7 @@ SPFVertex::~SPFVertex () void SPFVertex::SetVertexType (SPFVertex::VertexType type) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (type); m_vertexType = type; } @@ -111,7 +111,7 @@ SPFVertex::GetVertexType (void) const void SPFVertex::SetVertexId (Ipv4Address id) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (id); m_vertexId = id; } @@ -125,7 +125,7 @@ SPFVertex::GetVertexId (void) const void SPFVertex::SetLSA (GlobalRoutingLSA* lsa) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (lsa); m_lsa = lsa; } @@ -139,7 +139,7 @@ SPFVertex::GetLSA (void) const void SPFVertex::SetDistanceFromRoot (uint32_t distance) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (distance); m_distanceFromRoot = distance; } @@ -153,7 +153,7 @@ SPFVertex::GetDistanceFromRoot (void) const void SPFVertex::SetOutgoingTypeId (uint32_t id) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (id); m_rootOif = id; } @@ -167,7 +167,7 @@ SPFVertex::GetOutgoingTypeId (void) const void SPFVertex::SetNextHop (Ipv4Address nextHop) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (nextHop); m_nextHop = nextHop; } @@ -181,7 +181,7 @@ SPFVertex::GetNextHop (void) const void SPFVertex::SetParent (SPFVertex* parent) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (parent); m_parent = parent; } @@ -202,7 +202,7 @@ SPFVertex::GetNChildren (void) const 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 @@ SPFVertex::GetChild (uint32_t n) const return *i; } } - NS_ASSERT_MSG(false, "Index out of range."); + NS_ASSERT_MSG (false, "Index 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 @@ GlobalRouteManagerLSDB::Initialize () 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 @@ GlobalRouteManagerLSDB::GetLSA (Ipv4Address addr) const 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 @@ GlobalRouteManagerImpl::~GlobalRouteManagerImpl () void GlobalRouteManagerImpl::DebugUseLsdb (GlobalRouteManagerLSDB* lsdb) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (lsdb); if (m_lsdb) { delete m_lsdb; @@ -351,8 +351,7 @@ GlobalRouteManagerImpl::DebugUseLsdb (GlobalRouteManagerLSDB* lsdb) // // 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 @@ GlobalRouteManagerImpl::SelectRouterNodes () } } + void +GlobalRouteManagerImpl::SelectRouterNodes (NodeContainer c) +{ + NS_LOG_FUNCTION (&c); + for (NodeContainer::Iterator i = c.Begin (); i != c.End (); i++) + { + Ptr node = *i; + NS_LOG_LOGIC ("Adding GlobalRouter interface to node " << + node->GetId ()); + + Ptr globalRouter = CreateObject (); + 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 @@ GlobalRouteManagerImpl::BuildGlobalRoutingDatabase () { 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 = *i; - Ptr rtr = - node->GetObject (); + Ptr rtr = node->GetObject (); // // Ignore nodes that aren't participating in routing. // @@ -504,7 +518,7 @@ GlobalRouteManagerImpl::InitializeRoutes () 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 @@ GlobalRouteManagerImpl::SPFNexthopCalculation ( 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 @@ GlobalRouteManagerImpl::SPFNexthopCalculation ( // return the link record describing the link from to . Think of it as // SPFGetLink. // - NS_ASSERT(l); + NS_ASSERT (l); GlobalRoutingLinkRecord *linkRemote = 0; linkRemote = SPFGetNextLink (w, v, linkRemote); // @@ -778,7 +792,7 @@ GlobalRouteManagerImpl::SPFNexthopCalculation ( // from the root node to the host represented by vertex , 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 -- remember that is the link "from" @@ -832,7 +846,7 @@ GlobalRouteManagerImpl::SPFNexthopCalculation ( * 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 @@ GlobalRouteManagerImpl::SPFGetNextLink ( 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 @@ GlobalRouteManagerImpl::SPFGetNextLink ( void GlobalRouteManagerImpl::DebugSPFCalculate (Ipv4Address root) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (root); SPFCalculate (root); } @@ -987,7 +1001,7 @@ GlobalRouteManagerImpl::SPFCalculate (Ipv4Address root) // 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 @@ GlobalRouteManagerImpl::SPFCalculate (Ipv4Address root) } else { - NS_ASSERT_MSG(0, "illegal SPFVertex type"); + NS_ASSERT_MSG (0, "illegal SPFVertex type"); } // // RFC2328 16.1. (5). @@ -1123,7 +1137,7 @@ GlobalRouteManagerImpl::SPFCalculate (Ipv4Address root) uint32_t GlobalRouteManagerImpl::FindOutgoingTypeId (Ipv4Address a, Ipv4Mask amask) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (a << amask); // // We have an IP address 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 @@ GlobalRouteManagerImpl::FindOutgoingTypeId (Ipv4Address a, Ipv4Mask amask) 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 @@ GlobalRouteManagerImpl::SPFIntraAddRouter (SPFVertex* v) 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 @@ GlobalRouteManagerImpl::SPFIntraAddTransit (SPFVertex* v) void GlobalRouteManagerImpl::SPFVertexAddParent (SPFVertex* v) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (v); v->GetParent ()->AddChild (v); } diff --git a/src/routing/global-routing/global-route-manager-impl.h b/src/routing/global-routing/global-route-manager-impl.h index 139b25178..46c3247a8 100644 --- a/src/routing/global-routing/global-route-manager-impl.h +++ b/src/routing/global-routing/global-route-manager-impl.h @@ -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 { @@ -707,6 +708,14 @@ public: */ 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. diff --git a/src/routing/global-routing/global-route-manager.cc b/src/routing/global-routing/global-route-manager.cc index 4349f0df8..5fc23f2f3 100644 --- a/src/routing/global-routing/global-route-manager.cc +++ b/src/routing/global-routing/global-route-manager.cc @@ -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 @@ namespace ns3 { // --------------------------------------------------------------------------- void -GlobalRouteManager::PopulateRoutingTables () +GlobalRouteManager::PopulateRoutingTables (void) { SelectRouterNodes (); BuildGlobalRoutingDatabase (); @@ -41,28 +42,43 @@ GlobalRouteManager::PopulateRoutingTables () } void -GlobalRouteManager::SelectRouterNodes () +GlobalRouteManager::PopulateRoutingTables (NodeContainer c) +{ + SelectRouterNodes (c); + BuildGlobalRoutingDatabase (); + InitializeRoutes (); +} + + void +GlobalRouteManager::SelectRouterNodes (void) { SimulationSingleton::Get ()-> SelectRouterNodes (); } void -GlobalRouteManager::BuildGlobalRoutingDatabase () +GlobalRouteManager::SelectRouterNodes (NodeContainer c) +{ + SimulationSingleton::Get ()-> + SelectRouterNodes (c); +} + + void +GlobalRouteManager::BuildGlobalRoutingDatabase (void) { SimulationSingleton::Get ()-> BuildGlobalRoutingDatabase (); } void -GlobalRouteManager::InitializeRoutes () +GlobalRouteManager::InitializeRoutes (void) { SimulationSingleton::Get ()-> InitializeRoutes (); } uint32_t -GlobalRouteManager::AllocateRouterId () +GlobalRouteManager::AllocateRouterId (void) { static uint32_t routerId = 0; return routerId++; diff --git a/src/routing/global-routing/global-route-manager.h b/src/routing/global-routing/global-route-manager.h index 333aff78c..8fe4c0471 100644 --- a/src/routing/global-routing/global-route-manager.h +++ b/src/routing/global-routing/global-route-manager.h @@ -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 @@ class GlobalRouteManager 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 (). @@ -50,6 +53,19 @@ public: */ 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. */ @@ -64,6 +80,14 @@ private: */ 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. diff --git a/src/routing/global-routing/global-router-interface.cc b/src/routing/global-routing/global-router-interface.cc index 441863726..19558c05b 100644 --- a/src/routing/global-routing/global-router-interface.cc +++ b/src/routing/global-routing/global-router-interface.cc @@ -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 NS_LOG_COMPONENT_DEFINE ("GlobalRouter"); @@ -365,8 +369,7 @@ GlobalRoutingLSA::GetAttachedRouter (uint32_t n) const 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 @@ GlobalRoutingLSA::SetStatus (GlobalRoutingLSA::SPFStatus status) 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 @@ GlobalRoutingLSA::Print (std::ostream &os) const 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 @@ GlobalRouter::GetRouterId (void) const } // -// 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 = GetObject (); - NS_LOG_LOGIC("For node " << node->GetId () ); - NS_ASSERT_MSG(node, - "GlobalRouter::DiscoverLSAs (): interface not set"); + NS_ABORT_MSG_UNLESS (node, "GlobalRouter::DiscoverLSAs (): GetObject for 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 > 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 ipv4Local = node->GetObject (); - NS_ASSERT_MSG(ipv4Local, - "GlobalRouter::DiscoverLSAs (): QI for interface failed"); -// -// Each node originates a Router-LSA -// + NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::DiscoverLSAs (): GetObject for 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 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 @@ GlobalRouter::DiscoverLSAs (void) 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 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 ch = ndLocal->GetChannel(); - if (ch == NULL) - { - continue; - } - Ptr 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 nodeRemote = ndRemote->GetNode(); - Ptr ipv4Remote = nodeRemote->GetObject (); - NS_ASSERT_MSG(ipv4Remote, - "GlobalRouter::DiscoverLSAs (): QI for remote failed"); -// -// Per the OSPF spec, we're going to need the remote router ID, so we might as -// well get it now. -// - Ptr srRemote = - nodeRemote->GetObject (); - NS_ASSERT_MSG(srRemote, - "GlobalRouter::DiscoverLSAs():QI for remote 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) { - for (std::list >::iterator i = listOfDRInterfaces.begin (); - i != listOfDRInterfaces.end (); i++) - { -// Build one NetworkLSA for each interface that is a DR - Ptr ndLocal = *i; - uint32_t ifIndexLocal = FindIfIndexForDevice(node, ndLocal); - Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); - Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); - - 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 ch = ndLocal->GetChannel(); - uint32_t nDevices = ch->GetNDevices(); - NS_ASSERT (nDevices); - for (uint32_t i = 0; i < nDevices; i++) - { - Ptr tempNd = ch->GetDevice (i); - NS_ASSERT (tempNd); - Ptr tempNode = tempNd->GetNode (); - uint32_t tempIfIndex = FindIfIndexForDevice (tempNode, tempNd); - Ptr tempIpv4 = tempNode->GetObject (); - NS_ASSERT (tempIpv4); - Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex); - pLSA->AddAttachedRouter (tempAddr); - } - m_LSAs.push_back (pLSA); - NS_LOG_LOGIC (*pLSA); - } + NS_LOG_LOGIC ("Build Network LSAs"); + BuildNetworkLSAs (c); } return m_LSAs.size (); } - Ipv4Address -GlobalRouter::FindDesignatedRouterForLink (Ptr node, - Ptr ndLocal) const + void +GlobalRouter::ProcessBroadcastLink (Ptr nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c) { - uint32_t ifIndexLocal = FindIfIndexForDevice(node, ndLocal); - Ptr ipv4Local = GetObject (); - NS_ASSERT (ipv4Local); + NS_LOG_FUNCTION (nd << pLSA << &c); + + if (nd->IsBridge ()) + { + ProcessBridgedBroadcastLink (nd, pLSA, c); + } + else + { + ProcessSingleBroadcastLink (nd, pLSA, c); + } +} + + void +GlobalRouter::ProcessSingleBroadcastLink (Ptr 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 = 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 ipv4Local = node->GetObject (); + NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessSingleBroadcastLink (): GetObject for 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 + { + // + // 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 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 bnd = nd->GetObject (); + NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for 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 = 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 ipv4Local = node->GetObject (); + NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessBridgedBroadcastLink (): GetObject for 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 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)) + { + 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 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 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 ipv4Local = nodeLocal->GetObject (); + NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for 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 ch = ndLocal->GetChannel(); + + // + // Get the net device on the other side of the point-to-point channel. + // + Ptr 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. 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 nodeRemote = ndRemote->GetNode(); + Ptr ipv4Remote = nodeRemote->GetObject (); + NS_ABORT_MSG_UNLESS (ipv4Remote, + "GlobalRouter::ProcessPointToPointLink(): GetObject for remote 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 rtrRemote = nodeRemote->GetObject (); + NS_ABORT_MSG_UNLESS(rtrRemote, + "GlobalRouter::ProcessPointToPointLinks(): GetObject for remote 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 ndLocal = c.Get (i); + Ptr 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 ipv4Local = node->GetObject (); + NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for 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 ch = ndLocal->GetChannel(); + uint32_t nDevices = ch->GetNDevices(); + NS_ASSERT (nDevices); + + for (uint32_t i = 0; i < nDevices; i++) + { + Ptr tempNd = ch->GetDevice (i); + NS_ASSERT (tempNd); + Ptr tempNode = tempNd->GetNode (); + + // + // Does the node in question have a GlobalRouter interface? If not it can + // hardly be considered an attached router. + // + Ptr rtr = tempNode->GetObject (); + 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 tempIpv4 = tempNode->GetObject (); + NS_ASSERT (tempIpv4); + Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex); + pLSA->AddAttachedRouter (tempAddr); + } + } + m_LSAs.push_back (pLSA); + pLSA = 0; + } +} + +// +// 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 ndLocal, bool allowRecursion) const +{ + NS_LOG_FUNCTION (ndLocal << allowRecursion); Ptr 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 tempNd = ch->GetDevice (i); - NS_ASSERT (tempNd); - Ptr tempNode = tempNd->GetNode (); - uint32_t tempIfIndex = FindIfIndexForDevice (tempNode, tempNd); - Ptr tempIpv4 = tempNode->GetObject (); - NS_ASSERT (tempIpv4); - Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex); - if (tempAddr < addrLocal) + Ptr ndOther = ch->GetDevice (i); + NS_ASSERT (ndOther); + + Ptr 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 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 rtr = nodeOther->GetObject (); + Ptr ipv4 = nodeOther->GetObject (); + 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 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 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 rtr = nodeOther->GetObject (); + Ptr ipv4 = nodeOther->GetObject (); + 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 nd, bool allowRecursion) const +{ + NS_LOG_FUNCTION (nd << allowRecursion); + + Ptr 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 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 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 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 nodeTemp = ndOther->GetNode (); + NS_ASSERT (nodeTemp); + + Ptr rtr = nodeTemp->GetObject (); + 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 @@ GlobalRouter::GetLSA (uint32_t n, GlobalRoutingLSA &lsa) const // other end. This only makes sense with a point-to-point channel. // Ptr -GlobalRouter::GetAdjacent(Ptr nd, Ptr ch) const +GlobalRouter::GetAdjacent (Ptr nd, Ptr 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 @@ GlobalRouter::GetAdjacent(Ptr nd, Ptr ch) const } // -// 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, Ptr nd) const + bool +GlobalRouter::FindIfIndexForDevice (Ptr node, Ptr nd, uint32_t &index) const { NS_LOG_FUNCTION_NOARGS (); + NS_LOG_LOGIC("For node " << node->GetId () << " for net device " << nd ); + Ptr ipv4 = node->GetObject (); - NS_ASSERT_MSG(ipv4, "QI for 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 +GlobalRouter::NetDeviceIsBridged (Ptr nd) const +{ + NS_LOG_FUNCTION (nd); + + Ptr 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 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 bnd = ndTest->GetObject (); + NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for 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; } diff --git a/src/routing/global-routing/global-router-interface.h b/src/routing/global-routing/global-router-interface.h index bd5dddfda..80116172a 100644 --- a/src/routing/global-routing/global-router-interface.h +++ b/src/routing/global-routing/global-router-interface.h @@ -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 @@ namespace ns3 { class GlobalRoutingLinkRecord { public: + friend class GlobalRoutingLSA; /** * @enum LinkType * @brief Enumeration of the possible types of Global Routing Link Records. @@ -639,9 +644,17 @@ private: void ClearLSAs (void); Ptr GetAdjacent(Ptr nd, Ptr ch) const; - uint32_t FindIfIndexForDevice(Ptr node, Ptr nd) const; - Ipv4Address FindDesignatedRouterForLink (Ptr node, - Ptr ndLocal) const; + bool FindIfIndexForDevice(Ptr node, Ptr nd, uint32_t &index) const; + Ipv4Address FindDesignatedRouterForLink (Ptr ndLocal, bool allowRecursion) const; + bool AnotherRouterOnLink (Ptr nd, bool allowRecursion) const; + void ProcessBroadcastLink (Ptr nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c); + void ProcessSingleBroadcastLink (Ptr nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c); + void ProcessBridgedBroadcastLink (Ptr nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c); + + void ProcessPointToPointLink (Ptr ndLocal, GlobalRoutingLSA *pLSA); + void BuildNetworkLSAs (NetDeviceContainer c); + Ptr NetDeviceIsBridged (Ptr nd) const; + typedef std::list ListOfLSAs_t; ListOfLSAs_t m_LSAs; diff --git a/wscript b/wscript index 85097f941..894310e68 100644 --- a/wscript +++ b/wscript @@ -447,16 +447,13 @@ def build(bld): 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 diff --git a/wutils.py b/wutils.py index 2baf21ae2..fe89dd579 100644 --- a/wutils.py +++ b/wutils.py @@ -94,13 +94,12 @@ def run_argv(argv, os_env=None): 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 @@ def run_program(program_string, command_template=None): 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)