diff --git a/.hgtags b/.hgtags index 4d7dfea78..164114709 100644 --- a/.hgtags +++ b/.hgtags @@ -35,3 +35,4 @@ dfd0bc16dc991313896f351530a3dc5a25f62e15 ns-3.3-RC4 13a5b15fbe3429a6c3d00c1bccffa2c156a0603b ns-3.5-rc1 8562a42accf6f715d312c037326ec7da48095e13 ns-3.5-rc2 a600c11ff8d40a40e88c2d692acad6512dde70c8 ns-3.5-rc3 +c975274c9707b1f07d94cc51f205c351122131a5 ns-3.5 diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 4264e8903..79f4dbce8 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -4,9 +4,7 @@ This file contains ns-3 release notes (most recent releases first). All of the ns-3 documentation is accessible from the ns-3 website: -http://www.nsnam.org -including tutorials: -http://www.nsnam.org/tutorials.html +http://www.nsnam.org including tutorials: http://www.nsnam.org/tutorials.html Release 3.5 =========== @@ -64,8 +62,8 @@ Future releases --------------- Our next release, which is expected to happen in 2 to 4 months from now, will feature the merging of some of our projects currently in development including -fuller IPv6 support, and some smaller features such as a new Global ARP package -and possibly a new Testing and Validation suite. +fuller IPv6 support, some smaller features such as a new Global ARP +package, and possibly a new Testing and Validation suite. Release 3.4 =========== diff --git a/doc/manual/attributes.texi b/doc/manual/attributes.texi index db7dcb61b..91a7340bd 100644 --- a/doc/manual/attributes.texi +++ b/doc/manual/attributes.texi @@ -114,6 +114,7 @@ example: @code{class ns3::Node}. The public header file node.h has a declaration that includes a static GetTypeId function call: + @verbatim class Node : public Object { @@ -123,21 +124,72 @@ public: @end verbatim This is defined in the node.cc file as follows: + @verbatim TypeId Node::GetTypeId (void) { static TypeId tid = TypeId ("ns3::Node") .SetParent () + .AddConstructor () + .AddAttribute ("DeviceList", "The list of devices associated to this Node.", + ObjectVectorValue (), + MakeObjectVectorAccessor (&Node::m_devices), + MakeObjectVectorChecker ()) + .AddAttribute ("ApplicationList", "The list of applications associated to this Node.", + ObjectVectorValue (), + MakeObjectVectorAccessor (&Node::m_applications), + MakeObjectVectorChecker ()) + .AddAttribute ("Id", "The id (unique integer) of this Node.", + TypeId::ATTR_GET, // allow only getting it. + UintegerValue (0), + MakeUintegerAccessor (&Node::m_id), + MakeUintegerChecker ()) ; return tid; } @end verbatim -Finally, when users want to create Nodes, they call: + +Look at the TypeId of an ns-3 @code{Object} class as an extended form of run +time type information (RTTI). The C++ language includes simple kind of RTTI +in order to support @code{dynamic_cast} and @code{typeid} operators. + +The ``@code{.SetParent ()}'' call in the declaration above is used in +conjunction with our object aggregation mechanisms to allow safe up- and +down-casing in inheritance trees during @code{GetObject}. + +The ``@code{.AddConstructor ()}'' call is used in conjunction with our +abstract object factory mechanisms to allow us to construct C++ objects without +forcing a user to know the concrete class of the object she is building. + +The three calls to ``@code{.AddAttribute}'' associate a given string with a +strongly typed value in the class. Notice that you must provide a help string +which may be displayed, for example, via command line processors. Each +@code{Attribute} is associated with mechanisms for accessing the underlying +member variable in the object (for example, @code{MakeUintegerAccessor} tells +the generic @code{Attribute} code how to get to the node ID above). There are +also ``Checker'' methods which are used to validate values. + +When users want to create Nodes, they will usually call some form of +@code{CreateObject}, + @verbatim Ptr n = CreateObject (); @end verbatim +or more abstractly, using an object factory, you can create a @code{Node} object +without even knowing the concrete C++ type + +@verbatim + ObjectFactory factory; + const std::string typeId = "ns3::Node''; + factory.SetTypeId(typeId); + Ptr node = factory.Create (); +@end verbatim + +Both of these methods result in fully initialized attributes being available +in the resulting @code{Object} instances. + We next discuss how attributes (values associated with member variables or functions of the class) are plumbed into the above TypeId. @@ -206,6 +258,7 @@ and some type of global default value. In the ns-3 attribute system, these value definitions and accessor functions are moved into the TypeId class; e.g.: + @verbatim NS_OBJECT_ENSURE_REGISTERED (DropTailQueue); @@ -358,11 +411,11 @@ Now, let's set it to another value (60 packets) @subsubsection Namespace-based access -An alternative way to get at the attribute is to use the configuration -namespace. Here, this attribute resides on a known path in this -namespace; this approach is useful if one doesn't have access to -the underlying pointers and would like to configure a specific -attribute with a single statement. +An alternative way to get at the attribute is to use the configuration namespace. +Here, this attribute resides on a known path in this namespace; this approach +is useful if one doesn't have access to the underlying pointers and would like +to configure a specific attribute with a single statement. + @verbatim Config::Set ("/NodeList/0/DeviceList/0/TxQueue/MaxPackets", UintegerValue (25)); txQueue->GetAttribute ("MaxPackets", limit); @@ -370,9 +423,8 @@ attribute with a single statement. limit.Get () << " packets"); @end verbatim -We could have also used wildcards to set this value for all nodes -and all net devices (which in this simple example has the same -effect as the previous Set()) +We could have also used wildcards to set this value for all nodes and all net +devices (which in this simple example has the same effect as the previous Set()) @verbatim Config::Set ("/NodeList/*/DeviceList/*/TxQueue/MaxPackets", UintegerValue (15)); txQueue->GetAttribute ("MaxPackets", limit); @@ -380,6 +432,22 @@ effect as the previous Set()) limit.Get () << " packets"); @end verbatim +@subsubsection Object Name Service-based access + +Another way to get at the attribute is to use the object name service facility. +Here, this attribute is found using a name string. This approach is useful if +one doesn't have access to the underlying pointers and it is difficult to +determine the required concrete configuration namespaced path. + +@verbatim + Names::Add ("server", serverNode); + Names::Add ("server/eth0", serverDevice); + + ... + + Config::Set ("/Names/server/eth0/TxQueue/MaxPackets", UintegerValue (25)); +@end verbatim + @subsection Setting through constructors helper classes Arbitrary combinations of attributes can be set and fetched from @@ -438,13 +506,13 @@ Consider this variable in class TcpSocket: Suppose that someone working with Tcp wanted to get or set the value of that variable using the metadata system. If it were not already provided by ns-3, the user could declare the following addition -in the metadata system (to the TypeId declaration for TcpSocket): +in the runtime metadata system (to the TypeId declaration for TcpSocket): @verbatim - .AddParameter ("Congestion window", + .AddAttribute ("Congestion window", "Tcp congestion window (bytes)", - Uinteger (1), + UintegerValue (1), MakeUintegerAccessor (&TcpSocket::m_cWnd), - MakeUintegerChecker ()); + MakeUintegerChecker ()) @end verbatim @@ -511,21 +579,26 @@ wants to hook it in to the attribute system, there is mainly the matter of writing the conversions to/from strings and attribute values. Most of this can be copy/pasted with macro-ized code. For instance, consider class -Rectangle in the @code{src/mobility/} directory: +delcaration for Rectangle in the @code{src/mobility/} directory: -One line is added to the class declaration: @verbatim /** * \brief a 2d rectangle */ class Rectangle { -... + ... + double xMin; + double xMax; + double yMin; + double yMax; }; @end verbatim -One macro call and two operators, are added below the class declaration: +One macro call and two operators, must be added below the class declaration +in order to turn a Rectangle into a value usable by the @code{Attribute} +system: @verbatim std::ostream &operator << (std::ostream &os, const Rectangle &rectangle); @@ -534,7 +607,7 @@ std::istream &operator >> (std::istream &is, Rectangle &rectangle); ATTRIBUTE_HELPER_HEADER (Rectangle); @end verbatim -In the class definition, the code looks like this: +In the class definition (@code{.cc} file), the code looks like this: @verbatim ATTRIBUTE_HELPER_CPP (Rectangle); @@ -568,9 +641,9 @@ of an instance of the new class. @node ConfigStore @section ConfigStore -@strong{Feedback requested:} This is an experimental feature of ns-3. -It is not in the main tree. If you like this feature and would like -to provide feedback on it, please email us. +@strong{Feedback requested:} This is an experimental feature of ns-3. It is +found in @code{src/contrib} and not in the main tree. If you like this feature +and would like to provide feedback on it, please email us. Values for ns-3 attributes can be stored in an ascii text file and loaded into a future simulation. This feature is known as the diff --git a/examples/virtual-net-device.cc b/examples/virtual-net-device.cc index aa65a13bf..96a60bc20 100644 --- a/examples/virtual-net-device.cc +++ b/examples/virtual-net-device.cc @@ -78,23 +78,33 @@ class Tunnel bool - N0N1VirtualSend (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) + N0VirtualSend (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) { - m_n3Socket->SendTo (packet, 0, InetSocketAddress (m_n3Address, 667)); + NS_LOG_DEBUG ("Send to " << m_n3Address << ": " << *packet); + m_n0Socket->SendTo (packet, 0, InetSocketAddress (m_n3Address, 667)); + return true; + } + + bool + N1VirtualSend (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) + { + NS_LOG_DEBUG ("Send to " << m_n3Address << ": " << *packet); + m_n1Socket->SendTo (packet, 0, InetSocketAddress (m_n3Address, 667)); return true; } bool N3VirtualSend (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) { - if (m_rng.GetValue () < 0.25) { - m_n0Socket->SendTo (packet, 0, InetSocketAddress (m_n0Address, 667)); + NS_LOG_DEBUG ("Send to " << m_n0Address << ": " << *packet); + m_n3Socket->SendTo (packet, 0, InetSocketAddress (m_n0Address, 667)); } else { - m_n1Socket->SendTo (packet, 0, InetSocketAddress (m_n1Address, 667)); + NS_LOG_DEBUG ("Send to " << m_n1Address << ": " << *packet); + m_n3Socket->SendTo (packet, 0, InetSocketAddress (m_n1Address, 667)); } return true; } @@ -102,6 +112,7 @@ class Tunnel void N3SocketRecv (Ptr socket) { Ptr packet = socket->Recv (65535, 0); + NS_LOG_DEBUG ("N3SocketRecv: " << *packet); SocketAddressTag socketAddressTag; packet->RemovePacketTag (socketAddressTag); m_n3Tap->Receive (packet, 0x0800, m_n3Tap->GetAddress (), m_n3Tap->GetAddress (), NetDevice::PACKET_HOST); @@ -110,6 +121,7 @@ class Tunnel void N0SocketRecv (Ptr socket) { Ptr packet = socket->Recv (65535, 0); + NS_LOG_DEBUG ("N0SocketRecv: " << *packet); SocketAddressTag socketAddressTag; packet->RemovePacketTag (socketAddressTag); m_n0Tap->Receive (packet, 0x0800, m_n0Tap->GetAddress (), m_n0Tap->GetAddress (), NetDevice::PACKET_HOST); @@ -118,6 +130,7 @@ class Tunnel void N1SocketRecv (Ptr socket) { Ptr packet = socket->Recv (65535, 0); + NS_LOG_DEBUG ("N1SocketRecv: " << *packet); SocketAddressTag socketAddressTag; packet->RemovePacketTag (socketAddressTag); m_n1Tap->Receive (packet, 0x0800, m_n1Tap->GetAddress (), m_n1Tap->GetAddress (), NetDevice::PACKET_HOST); @@ -144,7 +157,7 @@ public: // n0 tap device m_n0Tap = CreateObject (); m_n0Tap->SetAddress (Mac48Address ("11:00:01:02:03:01")); - m_n0Tap->SetSendCallback (MakeCallback (&Tunnel::N0N1VirtualSend, this)); + m_n0Tap->SetSendCallback (MakeCallback (&Tunnel::N0VirtualSend, this)); n0->AddDevice (m_n0Tap); Ptr ipv4 = n0->GetObject (); uint32_t i = ipv4->AddInterface (m_n0Tap); @@ -154,7 +167,7 @@ public: // n1 tap device m_n1Tap = CreateObject (); m_n1Tap->SetAddress (Mac48Address ("11:00:01:02:03:02")); - m_n1Tap->SetSendCallback (MakeCallback (&Tunnel::N0N1VirtualSend, this)); + m_n1Tap->SetSendCallback (MakeCallback (&Tunnel::N1VirtualSend, this)); n1->AddDevice (m_n1Tap); ipv4 = n1->GetObject (); i = ipv4->AddInterface (m_n1Tap); @@ -186,6 +199,8 @@ main (int argc, char *argv[]) #if 0 LogComponentEnable ("VirtualNetDeviceExample", LOG_LEVEL_INFO); #endif + Packet::EnablePrinting (); + // Set up some default values for the simulation. Use the Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (210)); @@ -260,11 +275,11 @@ main (int argc, char *argv[]) Address (InetSocketAddress (Ipv4Address::GetAny (), port))); apps = sink.Install (c.Get (3)); apps.Start (Seconds (1.0)); - apps.Stop (Seconds (10.0)); + //apps.Stop (Seconds (10.0)); // Create a similar flow from n3 to n1, starting at time 1.1 seconds onoff.SetAttribute ("Remote", - AddressValue (InetSocketAddress (Ipv4Address ("11.0.0.2"), port))); + AddressValue (InetSocketAddress (Ipv4Address ("11.0.0.1"), port))); apps = onoff.Install (c.Get (3)); apps.Start (Seconds (1.1)); apps.Stop (Seconds (10.0)); @@ -272,7 +287,7 @@ main (int argc, char *argv[]) // Create a packet sink to receive these packets apps = sink.Install (c.Get (1)); apps.Start (Seconds (1.1)); - apps.Stop (Seconds (10.0)); + //apps.Stop (Seconds (10.0)); std::ofstream ascii; ascii.open ("virtual-net-device.tr"); diff --git a/src/core/global-value.cc b/src/core/global-value.cc index 70a226e55..506fb11b8 100644 --- a/src/core/global-value.cc +++ b/src/core/global-value.cc @@ -174,6 +174,30 @@ GlobalValue::End (void) { return GetVector ()->end (); } + +bool +GlobalValue::GetValueByNameFailSafe (std::string name, AttributeValue &value) +{ + for (GlobalValue::Iterator gvit = GlobalValue::Begin (); gvit != GlobalValue::End (); ++gvit) + { + if ((*gvit)->GetName () == name) + { + (*gvit)->GetValue (value); + return true; + } + } + return false; // not found +} + +void +GlobalValue::GetValueByName (std::string name, AttributeValue &value) +{ + if (! GetValueByNameFailSafe (name, value)) + { + NS_FATAL_ERROR ("Could not find GlobalValue named \"" << name << "\""); + } +} + GlobalValue::Vector * GlobalValue::GetVector (void) { diff --git a/src/core/global-value.h b/src/core/global-value.h index a40d2244f..c744247dd 100644 --- a/src/core/global-value.h +++ b/src/core/global-value.h @@ -114,6 +114,30 @@ public: * \returns an iterator which represents a pointer to the last GlobalValue registered. */ static Iterator End (void); + + + /** + * finds the GlobalValue with the given name and returns its value + * + * @param name the name of the GlobalValue to be found + * @param value where to store the value of the found GlobalValue + * + * @return true if the GlobalValue was found, false otherwise + */ + static bool GetValueByNameFailSafe (std::string name, AttributeValue &value); + + /** + * finds the GlobalValue with the given name and returns its + * value. This method cannot fail, i.e., it will trigger a + * NS_FATAL_ERROR if the requested GlobalValue is not found. + * + * @param name the name of the GlobalValue to be found + * @param value where to store the value of the found GlobalValue + * + */ + static void GetValueByName (std::string name, AttributeValue &value); + + private: friend class GlobalValueTests; static Vector *GetVector (void); diff --git a/src/helper/bridge-helper.h b/src/helper/bridge-helper.h index 8a4bbb859..8ebc8f65a 100644 --- a/src/helper/bridge-helper.h +++ b/src/helper/bridge-helper.h @@ -1,3 +1,23 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2008 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + * Author: Gustavo Carneiro + */ #ifndef BRIDGE_HELPER_H #define BRIDGE_HELPER_H @@ -10,12 +30,42 @@ namespace ns3 { class Node; class AttributeValue; +/** + * \brief Add capability to bridge multiple LAN segments (IEEE 802.1D bridging) + */ class BridgeHelper { public: BridgeHelper (); + /** + * \param n1 the name of the attribute to set + * \param v1 the value of the attribute to set + * + * Set an attribute on each ns3::BridgeNetDevice created by + * BridgeHelper::Install + */ void SetDeviceAttribute (std::string n1, const AttributeValue &v1); + /** + * This method creates an ns3::BridgeNetDevice with the attributes + * configured by BridgeHelper::SetDeviceAttribute, adds the device + * to the node, and attaches the given NetDevices as ports of the + * bridge. + * + * \param node The node to install the device in + * \param c Container of NetDevices to add as bridge ports + * \returns A containter holding the added net device. + */ NetDeviceContainer Install (Ptr node, NetDeviceContainer c); + /** + * This method creates an ns3::BridgeNetDevice with the attributes + * configured by BridgeHelper::SetDeviceAttribute, adds the device + * to the node, and attaches the given NetDevices as ports of the + * bridge. + * + * \param nodeName The name of the node to install the device in + * \param c Container of NetDevices to add as bridge ports + * \returns A containter holding the added net device. + */ NetDeviceContainer Install (std::string nodeName, NetDeviceContainer c); private: ObjectFactory m_deviceFactory; diff --git a/src/helper/ipv4-list-routing-helper.h b/src/helper/ipv4-list-routing-helper.h index 5849c6840..ef34068c7 100644 --- a/src/helper/ipv4-list-routing-helper.h +++ b/src/helper/ipv4-list-routing-helper.h @@ -28,6 +28,9 @@ namespace ns3 { /** * \brief Helper class that adds ns3::Ipv4ListRouting objects + * + * This class is expected to be used in conjunction with + * ns3::InternetStackHelper::SetRoutingHelper */ class Ipv4ListRoutingHelper : public Ipv4RoutingHelper { diff --git a/src/helper/ipv4-routing-helper.h b/src/helper/ipv4-routing-helper.h index 170052a6e..9c8a28233 100644 --- a/src/helper/ipv4-routing-helper.h +++ b/src/helper/ipv4-routing-helper.h @@ -33,7 +33,7 @@ class Node; * For each new routing protocol created as a subclass of * ns3::Ipv4RoutingProtocol, you need to create a subclass of * ns3::Ipv4RoutingHelper which can be used by - * ns3::InternetStackHelper::SetRoutingProtocol and + * ns3::InternetStackHelper::SetRoutingHelper and * ns3::InternetStackHelper::Install. */ class Ipv4RoutingHelper diff --git a/src/helper/ipv4-static-routing-helper.h b/src/helper/ipv4-static-routing-helper.h index 24a885e31..2092900e4 100644 --- a/src/helper/ipv4-static-routing-helper.h +++ b/src/helper/ipv4-static-routing-helper.h @@ -33,6 +33,9 @@ namespace ns3 { /** * \brief Helper class that adds ns3::Ipv4StaticRouting objects + * + * This class is expected to be used in conjunction with + * ns3::InternetStackHelper::SetRoutingHelper */ class Ipv4StaticRoutingHelper : public Ipv4RoutingHelper { diff --git a/src/helper/nqos-wifi-mac-helper.h b/src/helper/nqos-wifi-mac-helper.h index 9800b6082..ae67b1922 100644 --- a/src/helper/nqos-wifi-mac-helper.h +++ b/src/helper/nqos-wifi-mac-helper.h @@ -24,6 +24,10 @@ namespace ns3 { +/** + * \brief create non-qos MAC layers for a ns3::WifiNetDevice. + * This class can create MACs of type ns3::NqapWifiMac, ns3::NqstaWifiMac, and, ns3::AdhocWifiMac + */ class NqosWifiMacHelper : public WifiMacHelper { public: diff --git a/src/helper/olsr-helper.h b/src/helper/olsr-helper.h index 0856abf97..7a40044d7 100644 --- a/src/helper/olsr-helper.h +++ b/src/helper/olsr-helper.h @@ -29,6 +29,9 @@ namespace ns3 { /** * \brief Helper class that adds OLSR routing to nodes. + * + * This class is expected to be used in conjunction with + * ns3::InternetStackHelper::SetRoutingHelper */ class OlsrHelper : public Ipv4RoutingHelper { diff --git a/src/helper/qos-wifi-mac-helper.h b/src/helper/qos-wifi-mac-helper.h index ea2c6fdcc..32537283a 100644 --- a/src/helper/qos-wifi-mac-helper.h +++ b/src/helper/qos-wifi-mac-helper.h @@ -27,6 +27,10 @@ namespace ns3 { +/** + * \brief create qos MAC layers for a ns3::WifiNetDevice. + * This class can create MACs of type ns3::QapWifiMac, ns3::QstaWifiMac, and, ns3::QadhocWifiMac + */ class QosWifiMacHelper : public WifiMacHelper { public: diff --git a/src/internet-stack/ipv4-interface.cc b/src/internet-stack/ipv4-interface.cc index 3d1779fce..67754a114 100644 --- a/src/internet-stack/ipv4-interface.cc +++ b/src/internet-stack/ipv4-interface.cc @@ -178,7 +178,7 @@ Ipv4Interface::SetForwarding (bool val) void Ipv4Interface::Send (Ptr p, Ipv4Address dest) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (dest << *p); if (!IsUp()) { return;