From 2d950869f8b517d58040836c9314283e22c5ed1b Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 27 Jul 2007 10:48:10 -0700 Subject: [PATCH 01/29] Add patch 49 (add/remove network route when bringing interface up/down) --- src/internet-node/ipv4-l3-protocol.cc | 31 +++++++++++++++++++++++++-- src/node/ipv4-address.cc | 6 ++++++ src/node/ipv4-address.h | 12 +++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/internet-node/ipv4-l3-protocol.cc b/src/internet-node/ipv4-l3-protocol.cc index 4a46290e6..8328a9be6 100644 --- a/src/internet-node/ipv4-l3-protocol.cc +++ b/src/internet-node/ipv4-l3-protocol.cc @@ -551,12 +551,39 @@ Ipv4L3Protocol::SetUp (uint32_t i) { Ipv4Interface *interface = GetInterface (i); interface->SetUp (); + + // If interface address and network mask have been set, add a route + // to the network of the interface (like e.g. ifconfig does on a + // Linux box) + if ((interface->GetAddress ()) != (Ipv4Address ()) + && (interface->GetNetworkMask ()) != (Ipv4Mask ())) + { + AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()), + interface->GetNetworkMask (), i); + } } void -Ipv4L3Protocol::SetDown (uint32_t i) +Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) { - Ipv4Interface *interface = GetInterface (i); + Ipv4Interface *interface = GetInterface (ifaceIndex); interface->SetDown (); + + // Remove all routes that are going through this interface + bool modified = true; + while (modified) + { + modified = false; + for (uint32_t i = 0; i < GetNRoutes (); i++) + { + Ipv4Route *route = GetRoute (i); + if (route->GetInterface () == ifaceIndex) + { + RemoveRoute (i); + modified = true; + break; + } + } + } } diff --git a/src/node/ipv4-address.cc b/src/node/ipv4-address.cc index f8ff9f7a6..8960293ee 100644 --- a/src/node/ipv4-address.cc +++ b/src/node/ipv4-address.cc @@ -145,6 +145,12 @@ Ipv4Address::IsEqual (Ipv4Address other) const } } +Ipv4Address +Ipv4Address::CombineMask (Ipv4Mask const &mask) const +{ + return Ipv4Address (GetHostOrder () & mask.GetHostOrder ()); +} + bool Ipv4Address::IsMulticast (void) { diff --git a/src/node/ipv4-address.h b/src/node/ipv4-address.h index dc834052a..37b1e23cd 100644 --- a/src/node/ipv4-address.h +++ b/src/node/ipv4-address.h @@ -27,6 +27,8 @@ namespace ns3 { +class Ipv4Mask; + /** Ipv4 addresses are stored in host order in * this class. */ @@ -82,6 +84,16 @@ public: bool IsBroadcast (void); bool IsMulticast (void); + /** + * \brief Combine this address with a network mask + * + * This method returns an IPv4 address that is this address combined + * (bitwise and) with a network mask, yielding an IPv4 network + * address. + * + * \param a network mask + */ + Ipv4Address CombineMask (Ipv4Mask const &mask) const; static Ipv4Address GetZero (void); static Ipv4Address GetAny (void); From 54af49fe405fd98b48a8fdd7f667cce6ea8d696a Mon Sep 17 00:00:00 2001 From: Emmanuelle Laprise Date: Fri, 27 Jul 2007 20:17:23 +0200 Subject: [PATCH 02/29] src/devices/p2p -> src/devices/point-to-point --- src/devices/{p2p => point-to-point}/p2p-channel.cc | 0 src/devices/{p2p => point-to-point}/p2p-channel.h | 0 src/devices/{p2p => point-to-point}/p2p-net-device.cc | 0 src/devices/{p2p => point-to-point}/p2p-net-device.h | 0 src/devices/{p2p => point-to-point}/p2p-topology.cc | 0 src/devices/{p2p => point-to-point}/p2p-topology.h | 0 src/devices/{p2p => point-to-point}/wscript | 0 src/wscript | 2 +- 8 files changed, 1 insertion(+), 1 deletion(-) rename src/devices/{p2p => point-to-point}/p2p-channel.cc (100%) rename src/devices/{p2p => point-to-point}/p2p-channel.h (100%) rename src/devices/{p2p => point-to-point}/p2p-net-device.cc (100%) rename src/devices/{p2p => point-to-point}/p2p-net-device.h (100%) rename src/devices/{p2p => point-to-point}/p2p-topology.cc (100%) rename src/devices/{p2p => point-to-point}/p2p-topology.h (100%) rename src/devices/{p2p => point-to-point}/wscript (100%) diff --git a/src/devices/p2p/p2p-channel.cc b/src/devices/point-to-point/p2p-channel.cc similarity index 100% rename from src/devices/p2p/p2p-channel.cc rename to src/devices/point-to-point/p2p-channel.cc diff --git a/src/devices/p2p/p2p-channel.h b/src/devices/point-to-point/p2p-channel.h similarity index 100% rename from src/devices/p2p/p2p-channel.h rename to src/devices/point-to-point/p2p-channel.h diff --git a/src/devices/p2p/p2p-net-device.cc b/src/devices/point-to-point/p2p-net-device.cc similarity index 100% rename from src/devices/p2p/p2p-net-device.cc rename to src/devices/point-to-point/p2p-net-device.cc diff --git a/src/devices/p2p/p2p-net-device.h b/src/devices/point-to-point/p2p-net-device.h similarity index 100% rename from src/devices/p2p/p2p-net-device.h rename to src/devices/point-to-point/p2p-net-device.h diff --git a/src/devices/p2p/p2p-topology.cc b/src/devices/point-to-point/p2p-topology.cc similarity index 100% rename from src/devices/p2p/p2p-topology.cc rename to src/devices/point-to-point/p2p-topology.cc diff --git a/src/devices/p2p/p2p-topology.h b/src/devices/point-to-point/p2p-topology.h similarity index 100% rename from src/devices/p2p/p2p-topology.h rename to src/devices/point-to-point/p2p-topology.h diff --git a/src/devices/p2p/wscript b/src/devices/point-to-point/wscript similarity index 100% rename from src/devices/p2p/wscript rename to src/devices/point-to-point/wscript diff --git a/src/wscript b/src/wscript index 4b34a9156..1d20c24e4 100644 --- a/src/wscript +++ b/src/wscript @@ -15,7 +15,7 @@ all_modules = ( 'simulator', 'node', 'internet-node', - 'devices/p2p', + 'devices/point-to-point', 'applications', 'mobility', ) From 0e21d85be1091655f2555e577d85e5108fb2f275 Mon Sep 17 00:00:00 2001 From: Emmanuelle Laprise Date: Fri, 27 Jul 2007 20:26:36 +0200 Subject: [PATCH 03/29] src/devices/point-to-point/p2p-* -> src/devices/point-to-point/point-to-point-* --- examples/simple-p2p.cc | 6 +++--- .../{p2p-channel.cc => point-to-point-channel.cc} | 4 ++-- .../{p2p-channel.h => point-to-point-channel.h} | 0 ...2p-net-device.cc => point-to-point-net-device.cc} | 4 ++-- ...{p2p-net-device.h => point-to-point-net-device.h} | 0 .../{p2p-topology.cc => point-to-point-topology.cc} | 6 +++--- .../{p2p-topology.h => point-to-point-topology.h} | 0 src/devices/point-to-point/wscript | 12 ++++++------ 8 files changed, 16 insertions(+), 16 deletions(-) rename src/devices/point-to-point/{p2p-channel.cc => point-to-point-channel.cc} (98%) rename src/devices/point-to-point/{p2p-channel.h => point-to-point-channel.h} (100%) rename src/devices/point-to-point/{p2p-net-device.cc => point-to-point-net-device.cc} (98%) rename src/devices/point-to-point/{p2p-net-device.h => point-to-point-net-device.h} (100%) rename src/devices/point-to-point/{p2p-topology.cc => point-to-point-topology.cc} (97%) rename src/devices/point-to-point/{p2p-topology.h => point-to-point-topology.h} (100%) diff --git a/examples/simple-p2p.cc b/examples/simple-p2p.cc index 9ad235b5e..412edcaa1 100644 --- a/examples/simple-p2p.cc +++ b/examples/simple-p2p.cc @@ -54,14 +54,14 @@ #include "ns3/ascii-trace.h" #include "ns3/pcap-trace.h" #include "ns3/internet-node.h" -#include "ns3/p2p-channel.h" -#include "ns3/p2p-net-device.h" +#include "ns3/point-to-point-channel.h" +#include "ns3/point-to-point-net-device.h" #include "ns3/mac-address.h" #include "ns3/ipv4-address.h" #include "ns3/ipv4.h" #include "ns3/socket.h" #include "ns3/ipv4-route.h" -#include "ns3/p2p-topology.h" +#include "ns3/point-to-point-topology.h" #include "ns3/onoff-application.h" using namespace ns3; diff --git a/src/devices/point-to-point/p2p-channel.cc b/src/devices/point-to-point/point-to-point-channel.cc similarity index 98% rename from src/devices/point-to-point/p2p-channel.cc rename to src/devices/point-to-point/point-to-point-channel.cc index adceda3f4..ae78010cf 100644 --- a/src/devices/point-to-point/p2p-channel.cc +++ b/src/devices/point-to-point/point-to-point-channel.cc @@ -19,8 +19,8 @@ * Author: Craig Dowell */ -#include "p2p-channel.h" -#include "p2p-net-device.h" +#include "point-to-point-channel.h" +#include "point-to-point-net-device.h" #include "ns3/packet.h" #include "ns3/simulator.h" #include "ns3/debug.h" diff --git a/src/devices/point-to-point/p2p-channel.h b/src/devices/point-to-point/point-to-point-channel.h similarity index 100% rename from src/devices/point-to-point/p2p-channel.h rename to src/devices/point-to-point/point-to-point-channel.h diff --git a/src/devices/point-to-point/p2p-net-device.cc b/src/devices/point-to-point/point-to-point-net-device.cc similarity index 98% rename from src/devices/point-to-point/p2p-net-device.cc rename to src/devices/point-to-point/point-to-point-net-device.cc index 13d352889..8f474edde 100644 --- a/src/devices/point-to-point/p2p-net-device.cc +++ b/src/devices/point-to-point/point-to-point-net-device.cc @@ -26,8 +26,8 @@ #include "ns3/queue.h" #include "ns3/simulator.h" #include "ns3/composite-trace-resolver.h" -#include "p2p-net-device.h" -#include "p2p-channel.h" +#include "point-to-point-net-device.h" +#include "point-to-point-channel.h" NS_DEBUG_COMPONENT_DEFINE ("PointToPointNetDevice"); diff --git a/src/devices/point-to-point/p2p-net-device.h b/src/devices/point-to-point/point-to-point-net-device.h similarity index 100% rename from src/devices/point-to-point/p2p-net-device.h rename to src/devices/point-to-point/point-to-point-net-device.h diff --git a/src/devices/point-to-point/p2p-topology.cc b/src/devices/point-to-point/point-to-point-topology.cc similarity index 97% rename from src/devices/point-to-point/p2p-topology.cc rename to src/devices/point-to-point/point-to-point-topology.cc index 0b0ee003b..5a9558419 100644 --- a/src/devices/point-to-point/p2p-topology.cc +++ b/src/devices/point-to-point/point-to-point-topology.cc @@ -32,9 +32,9 @@ #include "ns3/ipv4.h" #include "ns3/queue.h" -#include "p2p-channel.h" -#include "p2p-net-device.h" -#include "p2p-topology.h" +#include "point-to-point-channel.h" +#include "point-to-point-net-device.h" +#include "point-to-point-topology.h" namespace ns3 { diff --git a/src/devices/point-to-point/p2p-topology.h b/src/devices/point-to-point/point-to-point-topology.h similarity index 100% rename from src/devices/point-to-point/p2p-topology.h rename to src/devices/point-to-point/point-to-point-topology.h diff --git a/src/devices/point-to-point/wscript b/src/devices/point-to-point/wscript index 639420dc7..e09cb71b4 100644 --- a/src/devices/point-to-point/wscript +++ b/src/devices/point-to-point/wscript @@ -7,16 +7,16 @@ def build(bld): p2p.target = p2p.name p2p.uselib_local = ['ns3-node'] p2p.source = [ - 'p2p-net-device.cc', - 'p2p-channel.cc', - 'p2p-topology.cc', + 'point-to-point-net-device.cc', + 'point-to-point-channel.cc', + 'point-to-point-topology.cc', ] p2p.includes = '.' headers = bld.create_obj('ns3header') headers.source = [ - 'p2p-net-device.h', - 'p2p-channel.h', - 'p2p-topology.h', + 'point-to-point-net-device.h', + 'point-to-point-channel.h', + 'point-to-point-topology.h', ] From b078d918945993974043cc5999504d6722d30473 Mon Sep 17 00:00:00 2001 From: Emmanuelle Laprise Date: Fri, 27 Jul 2007 20:45:07 +0200 Subject: [PATCH 04/29] cleanup the wscripts --- examples/wscript | 2 +- samples/wscript | 4 ++-- src/devices/point-to-point/wscript | 13 ++++++------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/examples/wscript b/examples/wscript index f535ea93f..c5b5ed69f 100644 --- a/examples/wscript +++ b/examples/wscript @@ -9,5 +9,5 @@ def build(bld): obj.source = source return obj - obj = create_ns_prog('simple-p2p', 'simple-p2p.cc', deps=['p2p', 'internet-node']) + obj = create_ns_prog('simple-p2p', 'simple-p2p.cc', deps=['point-to-point', 'internet-node']) diff --git a/samples/wscript b/samples/wscript index 9883cd24d..30c825555 100644 --- a/samples/wscript +++ b/samples/wscript @@ -18,9 +18,9 @@ def build(bld): obj = create_ns_prog('main-test', 'main-test.cc') obj = create_ns_prog('main-simple', 'main-simple.cc', deps=['node', 'internet-node', 'applications']) - #obj = create_ns_prog('main-simple-p2p', 'main-simple-p2p.cc', deps=['node', 'p2p']) + #obj = create_ns_prog('main-simple-p2p', 'main-simple-p2p.cc', deps=['node', 'point-to-point']) obj = create_ns_prog('main-default-value', 'main-default-value.cc', - deps=['core', 'simulator', 'node', 'p2p']) + deps=['core', 'simulator', 'node', 'point-to-point']) obj = create_ns_prog('main-grid-topology', 'main-grid-topology.cc', deps=['core', 'simulator', 'mobility', 'internet-node']) obj = create_ns_prog('main-random-topology', 'main-random-topology.cc', diff --git a/src/devices/point-to-point/wscript b/src/devices/point-to-point/wscript index e09cb71b4..59d6ba3f8 100644 --- a/src/devices/point-to-point/wscript +++ b/src/devices/point-to-point/wscript @@ -2,21 +2,20 @@ def build(bld): - p2p = bld.create_obj('cpp', 'shlib') - p2p.name = 'ns3-p2p' - p2p.target = p2p.name - p2p.uselib_local = ['ns3-node'] - p2p.source = [ + module = bld.create_obj('cpp', 'shlib') + module.name = 'ns3-point-to-point' + module.target = module.name + module.uselib_local = ['ns3-node'] + module.source = [ 'point-to-point-net-device.cc', 'point-to-point-channel.cc', 'point-to-point-topology.cc', ] - p2p.includes = '.' - headers = bld.create_obj('ns3header') headers.source = [ 'point-to-point-net-device.h', 'point-to-point-channel.h', 'point-to-point-topology.h', ] + module.includes = '.' From 718ec6459308a607dfbc155743a09681306c9aa8 Mon Sep 17 00:00:00 2001 From: Emmanuelle Laprise Date: Fri, 27 Jul 2007 20:45:18 +0200 Subject: [PATCH 05/29] Move LLC encapsulation from NetDevice to subclasses. --- .../point-to-point-net-device.cc | 31 ++++++++++++++++--- .../point-to-point-net-device.h | 21 +++++++++---- src/node/net-device.cc | 28 ++++++++++------- src/node/net-device.h | 14 ++++++--- 4 files changed, 69 insertions(+), 25 deletions(-) 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 8f474edde..565557df6 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 @@ -28,6 +28,7 @@ #include "ns3/composite-trace-resolver.h" #include "point-to-point-net-device.h" #include "point-to-point-channel.h" +#include "ns3/llc-snap-header.h" NS_DEBUG_COMPONENT_DEFINE ("PointToPointNetDevice"); @@ -65,13 +66,30 @@ PointToPointNetDevice::~PointToPointNetDevice() m_queue = 0; } +void PointToPointNetDevice::AddHeader(Packet& p, const MacAddress& dest, + uint16_t protocolNumber) +{ + LlcSnapHeader llc; + llc.SetType (protocolNumber); + p.AddHeader (llc); +} + +bool PointToPointNetDevice::ProcessHeader(Packet& p, int& param) +{ + LlcSnapHeader llc; + p.RemoveHeader (llc); + + param = llc.GetType (); + + return true; +} + void PointToPointNetDevice::DoDispose() { m_channel = 0; NetDevice::DoDispose (); } - void PointToPointNetDevice::SetDataRate(const DataRate& bps) { m_bps = bps; @@ -82,7 +100,8 @@ void PointToPointNetDevice::SetInterframeGap(const Time& t) m_tInterframeGap = t; } -bool PointToPointNetDevice::SendTo (Packet& p, const MacAddress& dest) +bool PointToPointNetDevice::SendTo (Packet& p, const MacAddress& dest, + uint16_t protocolNumber) { NS_DEBUG ("PointToPointNetDevice::SendTo (" << &p << ", " << &dest << ")"); NS_DEBUG ("PointToPointNetDevice::SendTo (): UID is " << p.GetUid () << ")"); @@ -91,6 +110,7 @@ bool PointToPointNetDevice::SendTo (Packet& p, const MacAddress& dest) // "go down" during the simulation? Shouldn't we just wait for it // to come back up? NS_ASSERT (IsLinkUp ()); + AddHeader(p, dest, protocolNumber); // // This class simulates a point to point device. In the case of a serial @@ -198,9 +218,12 @@ void PointToPointNetDevice::AddQueue (Ptr q) void PointToPointNetDevice::Receive (Packet& p) { NS_DEBUG ("PointToPointNetDevice::Receive (" << &p << ")"); + int param = 0; + Packet packet = p; - m_rxTrace (p); - ForwardUp (p); + ProcessHeader(packet, param); + m_rxTrace (packet); + ForwardUp (packet, param); } Ptr PointToPointNetDevice::GetQueue(void) const 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 a4bc3be00..6e8f3f0ae 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 @@ -187,11 +187,18 @@ protected: static const DataRate& GetDefaultRate(); private: - // unimplemented methods to make it impossible - // to copy these objects. - PointToPointNetDevice (const PointToPointNetDevice& nd); - PointToPointNetDevice& operator = (const PointToPointNetDevice&o); - + /** + * Adds the necessary headers and trailers to a packet of data in order to + * respect the protocol implemented by the agent. + */ + void AddHeader(Packet& p, const MacAddress& dest, uint16_t protocolNumber); + /** + * Removes, from a packet of data, all headers and trailers that + * relate to the protocol implemented by the agent + * \return Returns true if the packet should be forwarded up the + * protocol stack. + */ + bool ProcessHeader(Packet& p, int& param); /** * Send a Packet Down the Wire. * @@ -202,9 +209,11 @@ private: * @see NetDevice * @param p a reference to the packet to send * @param dest a reference to the MacAddress of the destination device + * @param protocolNumber Protocol Number used to find protocol touse * @returns true if success, false on failure */ - virtual bool SendTo (Packet& p, const MacAddress& dest); + virtual bool SendTo (Packet& p, const MacAddress& dest, + uint16_t protocolNumber); /** * Start Sending a Packet Down the Wire. * diff --git a/src/node/net-device.cc b/src/node/net-device.cc index 5774abeac..7bc61dc9b 100644 --- a/src/node/net-device.cc +++ b/src/node/net-device.cc @@ -22,12 +22,15 @@ #include #include "ns3/assert.h" #include "ns3/object.h" +#include "ns3/debug.h" + #include "channel.h" #include "net-device.h" -#include "llc-snap-header.h" #include "node.h" +NS_DEBUG_COMPONENT_DEFINE ("NetDevice"); + namespace ns3 { const InterfaceId NetDevice::iid = MakeInterfaceId ("NetDevice", Object::iid); @@ -172,10 +175,7 @@ NetDevice::Send(Packet& p, const MacAddress& dest, uint16_t protocolNumber) { if (m_isUp) { - LlcSnapHeader llc; - llc.SetType (protocolNumber); - p.AddHeader (llc); - return SendTo(p, dest); + return SendTo(p, dest, protocolNumber); } else { @@ -195,18 +195,24 @@ NetDevice::GetChannel (void) const return DoGetChannel (); } -// Receive packet from below +// Receive packets from below bool -NetDevice::ForwardUp (Packet& packet) +NetDevice::ForwardUp(Packet& p, uint32_t param) { bool retval = false; - LlcSnapHeader llc; - packet.RemoveHeader (llc); + Packet packet = p; + + NS_DEBUG ("NetDevice::ForwardUp: UID is " << packet.GetUid() + << " device is: " << GetName()); + if (!m_receiveCallback.IsNull ()) { - retval = m_receiveCallback (this, packet, llc.GetType ()); + retval = m_receiveCallback (this, packet, param); + } else { + NS_DEBUG ("NetDevice::Receive call back is NULL"); } - return retval; + + return retval; } void diff --git a/src/node/net-device.h b/src/node/net-device.h index 522b1ed41..b5de34fc8 100644 --- a/src/node/net-device.h +++ b/src/node/net-device.h @@ -17,6 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Mathieu Lacage + * Modified by Emmanuelle Laprise to remove dependance on LLC headers */ #ifndef NET_DEVICE_H #define NET_DEVICE_H @@ -227,6 +228,8 @@ public: /** * \param p packet sent from below up to Network Device + * \param param Extra parameter extracted from header and needed by + * some protocols * \returns true if the packet was forwarded successfully, * false otherwise. * @@ -234,7 +237,8 @@ public: * forwards it to the higher layers by calling this method * which is responsible for passing it up to the Rx callback. */ - bool ForwardUp (Packet& p); + bool ForwardUp (Packet& p, uint32_t param); + /** * The dispose method for this NetDevice class. @@ -244,10 +248,13 @@ public: */ virtual void DoDispose (void); + Callback,const Packet &,uint16_t> m_receiveCallback; + private: /** * \param p packet to send * \param dest address of destination to which packet must be sent + * \param protocolNumber Number of the protocol (used with some protocols) * \returns true if the packet could be sent successfully, false * otherwise. * @@ -255,7 +262,7 @@ public: * method. When the link is Up, this method is invoked to ask * subclasses to forward packets. Subclasses MUST override this method. */ - virtual bool SendTo (Packet& p, const MacAddress& dest) = 0; + virtual bool SendTo (Packet& p, const MacAddress &dest, uint16_t protocolNumber) = 0; /** * \returns true if this NetDevice needs the higher-layers * to perform ARP over it, false otherwise. @@ -279,7 +286,7 @@ public: */ virtual Ptr DoGetChannel (void) const = 0; - Ptr m_node; + Ptr m_node; std::string m_name; uint16_t m_ifIndex; MacAddress m_address; @@ -290,7 +297,6 @@ public: bool m_isMulticast; bool m_isPointToPoint; Callback m_linkChangeCallback; - Callback,const Packet &,uint16_t> m_receiveCallback; }; }; // namespace ns3 From ad5f36f2acacebe15ade4d060bdcdfc628decc89 Mon Sep 17 00:00:00 2001 From: Emmanuelle Laprise Date: Fri, 27 Jul 2007 21:16:40 +0200 Subject: [PATCH 06/29] ethernet Header and Trailer classes --- src/internet-node/arp-header.cc | 2 +- src/internet-node/wscript | 1 - .../header-utils.cc => node/address-utils.cc} | 2 +- .../header-utils.h => node/address-utils.h} | 6 +- src/node/ethernet-header.cc | 173 ++++++++++++++++++ src/node/ethernet-header.h | 128 +++++++++++++ src/node/ethernet-trailer.cc | 124 +++++++++++++ src/node/ethernet-trailer.h | 104 +++++++++++ src/node/wscript | 6 + 9 files changed, 540 insertions(+), 6 deletions(-) rename src/{internet-node/header-utils.cc => node/address-utils.cc} (98%) rename src/{internet-node/header-utils.h => node/address-utils.h} (93%) create mode 100644 src/node/ethernet-header.cc create mode 100644 src/node/ethernet-header.h create mode 100644 src/node/ethernet-trailer.cc create mode 100644 src/node/ethernet-trailer.h diff --git a/src/internet-node/arp-header.cc b/src/internet-node/arp-header.cc index e340404f4..7191b0299 100644 --- a/src/internet-node/arp-header.cc +++ b/src/internet-node/arp-header.cc @@ -20,8 +20,8 @@ */ #include "ns3/assert.h" +#include "ns3/address-utils.h" #include "arp-header.h" -#include "header-utils.h" namespace ns3 { diff --git a/src/internet-node/wscript b/src/internet-node/wscript index cf412d6c8..47b81358b 100644 --- a/src/internet-node/wscript +++ b/src/internet-node/wscript @@ -24,7 +24,6 @@ def build(bld): 'arp-ipv4-interface.cc', 'arp-l3-protocol.cc', 'ipv4-loopback-interface.cc', - 'header-utils.cc', 'udp-socket.cc', 'ipv4-end-point-demux.cc', 'arp-private.cc', diff --git a/src/internet-node/header-utils.cc b/src/node/address-utils.cc similarity index 98% rename from src/internet-node/header-utils.cc rename to src/node/address-utils.cc index b3da88cfa..702db4dd5 100644 --- a/src/internet-node/header-utils.cc +++ b/src/node/address-utils.cc @@ -18,7 +18,7 @@ * * Author: Mathieu Lacage */ -#include "header-utils.h" +#include "address-utils.h" namespace ns3 { diff --git a/src/internet-node/header-utils.h b/src/node/address-utils.h similarity index 93% rename from src/internet-node/header-utils.h rename to src/node/address-utils.h index e65e7533c..9dbe8fc55 100644 --- a/src/internet-node/header-utils.h +++ b/src/node/address-utils.h @@ -18,8 +18,8 @@ * * Author: Mathieu Lacage */ -#ifndef HEADER_UTILS_H -#define HEADER_UTILS_H +#ifndef ADDRESS_UTILS_H +#define ADDRESS_UTILS_H #include "ns3/buffer.h" #include "ns3/ipv4-address.h" @@ -35,4 +35,4 @@ void ReadFrom (Buffer::Iterator &i, MacAddress &ad, uint32_t len); }; -#endif /* HEADER_UTILS_H */ +#endif /* ADDRESS_UTILS_H */ diff --git a/src/node/ethernet-header.cc b/src/node/ethernet-header.cc new file mode 100644 index 000000000..621bf0ecb --- /dev/null +++ b/src/node/ethernet-header.cc @@ -0,0 +1,173 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise + */ + +#include "ns3/assert.h" +#include "ns3/debug.h" +#include "ns3/header.h" +#include "ethernet-header.h" +#include "address-utils.h" + +NS_DEBUG_COMPONENT_DEFINE ("EthernetHeader"); + +namespace ns3 { + +bool EthernetHeader::m_enPreambleSfd = false; + +EthernetHeader::EthernetHeader () +{ + Init(); +} + +EthernetHeader::~EthernetHeader () +{} + +void +EthernetHeader::Init() +{ + m_preambleSfd = 0; + m_lengthType = 0x0; +} + +void +EthernetHeader::EnablePreambleSfd (bool enable) +{ + m_enPreambleSfd = enable; +} + +void +EthernetHeader::SetLengthType (uint16_t lengthType) +{ + m_lengthType = lengthType; +} +uint16_t +EthernetHeader::GetLengthType (void) const +{ + return m_lengthType; +} + +void +EthernetHeader::SetPreambleSfd (uint64_t preambleSfd) +{ + m_preambleSfd = preambleSfd; +} +uint64_t +EthernetHeader::GetPreambleSfd (void) const +{ + return m_preambleSfd; +} + +void +EthernetHeader::SetSource (MacAddress source) +{ + m_source = source; +} +MacAddress +EthernetHeader::GetSource (void) const +{ + return m_source; +} + +void +EthernetHeader::SetDestination (MacAddress dst) +{ + m_destination = dst; +} +MacAddress +EthernetHeader::GetDestination (void) const +{ + return m_destination; +} + +ethernet_header_t +EthernetHeader::GetPacketType (void) const +{ + return LENGTH; +} + +uint32_t +EthernetHeader::GetHeaderSize (void) const +{ + return GetSerializedSize(); +} + +std::string +EthernetHeader::DoGetName (void) const +{ + return "ETHERNET"; +} + +void +EthernetHeader::PrintTo (std::ostream &os) const +{ + // ethernet, right ? + os << "(ethernet)"; + if (m_enPreambleSfd) + { + os << " preamble/sfd=" << m_preambleSfd << ","; + } + os << " length/type=" << m_lengthType + << ", source=" << m_source + << ", destination=" << m_destination; +} +uint32_t +EthernetHeader::GetSerializedSize (void) const +{ + if (m_enPreambleSfd) + { + return PREAMBLE_SIZE + LENGTH_SIZE + 2*MAC_ADDR_SIZE; + } else { + return LENGTH_SIZE + 2*MAC_ADDR_SIZE; + } +} + +void +EthernetHeader::SerializeTo (Buffer::Iterator start) const +{ + Buffer::Iterator i = start; + + if (m_enPreambleSfd) + { + i.WriteU64(m_preambleSfd); + } + NS_ASSERT (m_destination.GetLength () == MAC_ADDR_SIZE); + NS_ASSERT (m_source.GetLength () == MAC_ADDR_SIZE); + WriteTo (i, m_destination); + WriteTo (i, m_source); + i.WriteU16 (m_lengthType); +} +uint32_t +EthernetHeader::DeserializeFrom (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + + if (m_enPreambleSfd) + { + m_enPreambleSfd = i.ReadU64 (); + } + + ReadFrom (i, m_destination, MAC_ADDR_SIZE); + ReadFrom (i, m_source, MAC_ADDR_SIZE); + m_lengthType = i.ReadU16 (); + + return GetSerializedSize (); +} + +}; // namespace ns3 diff --git a/src/node/ethernet-header.h b/src/node/ethernet-header.h new file mode 100644 index 000000000..e9fde048a --- /dev/null +++ b/src/node/ethernet-header.h @@ -0,0 +1,128 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise + */ + +#ifndef ETHERNET_HEADER_H +#define ETHERNET_HEADER_H + +#include "ns3/header.h" +#include "ns3/mac-address.h" + +namespace ns3 { + + /** + * Types of ethernet packets. Indicates the type of the current + * header. + */ + enum ethernet_header_t { + LENGTH, /**< Basic ethernet packet, no tags, type/length field + indicates packet length or IP/ARP packet */ + VLAN, /**< Single tagged packet. Header includes VLAN tag */ + QINQ /**< Double tagged packet. Header includes two VLAN tags */ + }; +/** + * \brief Packet header for Ethernet + * + * This class can be used to add a header to an ethernet packet that + * will specify the source and destination addresses and the length of + * the packet. Eventually the class will be improved to also support + * VLAN tags in packet headers. + */ +class EthernetHeader : public Header { +public: + static const int PREAMBLE_SIZE = 8; /// size of the preamble_sfd header field + static const int LENGTH_SIZE = 2; /// size of the length_type header field + static const int MAC_ADDR_SIZE = 6; /// size of src/dest addr header fields + + /** + * \brief Construct a null ethernet header + */ + EthernetHeader (); + virtual ~EthernetHeader (); + /** + * \brief Enable or disabled the serialisation of the preamble and + * Sfd header fields + */ + static void EnablePreambleSfd (bool enable); + /** + * \param size The size of the payload in bytes + */ + void SetLengthType (uint16_t size); + /** + * \param source The source address of this packet + */ + void SetSource (MacAddress source); + /** + * \param destination The destination address of this packet. + */ + void SetDestination (MacAddress destination); + /** + * \param preambleSfd The value that the preambleSfd field should take + */ + void SetPreambleSfd (uint64_t preambleSfd); + /** + * \return The size of the payload in bytes + */ + uint16_t GetLengthType (void) const; + /** + * \return The type of packet (only basic Ethernet is currently supported) + */ + ethernet_header_t GetPacketType (void) const; + /** + * \return The source address of this packet + */ + MacAddress GetSource (void) const; + /** + * \return The destination address of this packet + */ + MacAddress GetDestination (void) const; + /** + * \return The value of the PreambleSfd field + */ + uint64_t GetPreambleSfd () const; + /** + * \return The size of the header + */ + uint32_t GetHeaderSize() const; + +private: + virtual std::string DoGetName (void) const; + virtual void PrintTo (std::ostream &os) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void SerializeTo (Buffer::Iterator start) const; + virtual uint32_t DeserializeFrom (Buffer::Iterator start); + + void Init (void); + + /** + * If false, the preamble/sfd are not serialised/deserialised. + */ + static bool m_enPreambleSfd; + + uint64_t m_preambleSfd; /// Value of the Preamble/SFD fields + uint16_t m_lengthType : 16; /// Length or type of the packet + MacAddress m_source; /// Source address + MacAddress m_destination; /// Destination address +}; + +}; // namespace ns3 + + +#endif /* ETHERNET_HEADER_H */ diff --git a/src/node/ethernet-trailer.cc b/src/node/ethernet-trailer.cc new file mode 100644 index 000000000..6aa622b66 --- /dev/null +++ b/src/node/ethernet-trailer.cc @@ -0,0 +1,124 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise + */ + +#include "ns3/assert.h" +#include "ns3/debug.h" +#include "ns3/trailer.h" +#include "ethernet-trailer.h" + +NS_DEBUG_COMPONENT_DEFINE ("EthernetTrailer"); + +namespace ns3 { + +bool EthernetTrailer::m_calcFcs = false; + +EthernetTrailer::EthernetTrailer () +{ + Init(); +} + +EthernetTrailer::~EthernetTrailer () +{} + +void EthernetTrailer::Init() +{ + m_fcs = 0; +} + +void +EthernetTrailer::EnableFcs (bool enable) +{ + m_calcFcs = enable; +} + +bool +EthernetTrailer::CheckFcs (const Packet& p) const +{ + if (!m_calcFcs) + { + return true; + } else { + NS_DEBUG("FCS calculation is not yet enabled" << std::endl); + return false; + } +} + +void +EthernetTrailer::CalcFcs (const Packet& p) +{ + NS_DEBUG("FCS calculation is not yet enabled" << std::endl); +} + +void +EthernetTrailer::SetFcs (uint32_t fcs) +{ + m_fcs = fcs; +} + +uint32_t +EthernetTrailer::GetFcs (void) +{ + return m_fcs; +} + +uint32_t +EthernetTrailer::GetTrailerSize (void) const +{ + return GetSerializedSize(); +} +std::string +EthernetTrailer::DoGetName (void) const +{ + return "ETHERNET"; +} + +void +EthernetTrailer::PrintTo (std::ostream &os) const +{ + os << " fcs=" << m_fcs; +} +uint32_t +EthernetTrailer::GetSerializedSize (void) const +{ + return 4; +} + +void +EthernetTrailer::SerializeTo (Buffer::Iterator end) const +{ + Buffer::Iterator i = end; + i.Prev(GetSerializedSize()); + + i.WriteU32 (m_fcs); +} +uint32_t +EthernetTrailer::DeserializeFrom (Buffer::Iterator end) +{ + Buffer::Iterator i = end; + uint32_t size = GetSerializedSize(); + i.Prev(size); + + m_fcs = i.ReadU32 (); + + return size; +} + +}; // namespace ns3 diff --git a/src/node/ethernet-trailer.h b/src/node/ethernet-trailer.h new file mode 100644 index 000000000..7ec3e162d --- /dev/null +++ b/src/node/ethernet-trailer.h @@ -0,0 +1,104 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise + */ + +#ifndef ETHERNET_TRAILER_H +#define ETHERNET_TRAILER_H + +#include "ns3/trailer.h" +#include "ns3/packet.h" + +namespace ns3 { +/** + * \brief Packet trailer for Ethernet + * + * This class can be used to add and verify the FCS at the end of an + * ethernet packet. The actual FCS functionality is not yet coded and + * so this acts more as a placeholder. + */ +class EthernetTrailer : public Trailer { +public: + /** + * \brief Construct a null ethernet trailer + */ + EthernetTrailer (); + virtual ~EthernetTrailer (); + /** + * \brief Enable or disabled FCS checking and calculations + * \param enable If true, enables FCS calculations. + */ + static void EnableFcs (bool enable); + /** + * \brief Updates the Fcs Field to the correct FCS + * \param p Reference to a packet on which the FCS should be + * calculated. The packet should not currently contain an FCS + * trailer. + */ + void CalcFcs (const Packet& p); + /** + * \brief Sets the FCS to a new value + * \param fcs New FCS value + */ + void SetFcs (uint32_t fcs); + /** + * \return the FCS contained in this trailer + */ + uint32_t GetFcs (); + + /** + * \param p Reference to the packet on which the FCS should be + * calculated. The packet should not contain an FCS trailer. + * \return Returns true if the packet fcs is correct, false otherwise. + * + * If FCS checking is disabled, this method will always + * return true. + */ + bool CheckFcs (const Packet& p) const; + + /** + *\return Returns the size of the trailer + */ + uint32_t GetTrailerSize() const; + +private: + virtual std::string DoGetName (void) const; + virtual void PrintTo (std::ostream &os) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void SerializeTo (Buffer::Iterator end) const; + virtual uint32_t DeserializeFrom (Buffer::Iterator end); + + /** + * Initializes the trailer parameters during construction. + */ + void Init (void); + + /** + * Enabled FCS calculations. If false, fcs is set to 0 and checkFCS + * returns true. + */ + static bool m_calcFcs; + uint32_t m_fcs; /// Value of the fcs contained in the trailer + +}; + +}; // namespace ns3 + + +#endif /* ETHERNET_TRAILER_H */ diff --git a/src/node/wscript b/src/node/wscript index 0a5c64aa9..62974351a 100644 --- a/src/node/wscript +++ b/src/node/wscript @@ -10,7 +10,10 @@ def build(bld): 'ipv4-address.cc', 'net-device.cc', 'mac-address.cc', + 'address-utils.cc', 'llc-snap-header.cc', + 'ethernet-header.cc', + 'ethernet-trailer.cc', 'ipv4-route.cc', 'queue.cc', 'drop-tail-queue.cc', @@ -30,10 +33,13 @@ def build(bld): 'ipv4-address.h', 'net-device.h', 'mac-address.h', + 'address-utils.h', 'ipv4-route.h', 'queue.h', 'drop-tail-queue.h', 'llc-snap-header.h', + 'ethernet-header.h', + 'ethernet-trailer.h', 'channel.h', 'node-list.h', 'socket.h', From 31530c731173b63e06c891c9ada1431552b69419 Mon Sep 17 00:00:00 2001 From: Emmanuelle Laprise Date: Fri, 27 Jul 2007 21:17:14 +0200 Subject: [PATCH 07/29] a csma/cd NetDevice subclass and a test script --- examples/simple-csma-cd.cc | 209 ++++++++ examples/wscript | 1 + src/devices/csma-cd/backoff.cc | 83 +++ src/devices/csma-cd/backoff.h | 87 ++++ src/devices/csma-cd/csma-cd-channel.cc | 359 +++++++++++++ src/devices/csma-cd/csma-cd-channel.h | 307 +++++++++++ src/devices/csma-cd/csma-cd-ipv4-topology.cc | 162 ++++++ src/devices/csma-cd/csma-cd-ipv4-topology.h | 120 +++++ src/devices/csma-cd/csma-cd-net-device.cc | 504 +++++++++++++++++++ src/devices/csma-cd/csma-cd-net-device.h | 424 ++++++++++++++++ src/devices/csma-cd/csma-cd-topology.cc | 103 ++++ src/devices/csma-cd/csma-cd-topology.h | 128 +++++ src/devices/csma-cd/wscript | 24 + src/wscript | 1 + 14 files changed, 2512 insertions(+) create mode 100644 examples/simple-csma-cd.cc create mode 100644 src/devices/csma-cd/backoff.cc create mode 100644 src/devices/csma-cd/backoff.h create mode 100644 src/devices/csma-cd/csma-cd-channel.cc create mode 100644 src/devices/csma-cd/csma-cd-channel.h create mode 100644 src/devices/csma-cd/csma-cd-ipv4-topology.cc create mode 100644 src/devices/csma-cd/csma-cd-ipv4-topology.h create mode 100644 src/devices/csma-cd/csma-cd-net-device.cc create mode 100644 src/devices/csma-cd/csma-cd-net-device.h create mode 100644 src/devices/csma-cd/csma-cd-topology.cc create mode 100644 src/devices/csma-cd/csma-cd-topology.h create mode 100644 src/devices/csma-cd/wscript diff --git a/examples/simple-csma-cd.cc b/examples/simple-csma-cd.cc new file mode 100644 index 000000000..d5549af5b --- /dev/null +++ b/examples/simple-csma-cd.cc @@ -0,0 +1,209 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ns-2 simple.tcl script (ported from ns-2) + * Originally authored by Steve McCanne, 12/19/1996 + */ + +// Port of ns-2/tcl/ex/simple.tcl to ns-3 +// +// Network topology +// +// n0 +// \ 5 Mb/s, 2ms +// \ 1.5Mb/s, 10ms +// n2 -------------------------n3 +// / +// / 5 Mb/s, 2ms +// n1 +// +// - all links are p2p links with indicated one-way BW/delay +// - CBR/UDP flows from n0 to n3, and from n3 to n1 +// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec. +// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec. +// (i.e., DataRate of 448,000 bps) +// - DropTail queues +// - Tracing of queues and packet receptions to file "simple-p2p.tr" + +#include +#include +#include +#include + +#include "ns3/command-line.h" +#include "ns3/default-value.h" +#include "ns3/ptr.h" +#include "ns3/random-variable.h" +#include "ns3/debug.h" + +#include "ns3/simulator.h" +#include "ns3/nstime.h" +#include "ns3/data-rate.h" + +#include "ns3/ascii-trace.h" +#include "ns3/pcap-trace.h" +#include "ns3/internet-node.h" +#include "ns3/csma-cd-channel.h" +#include "ns3/csma-cd-net-device.h" +#include "ns3/csma-cd-topology.h" +#include "ns3/csma-cd-ipv4-topology.h" +#include "ns3/mac-address.h" +#include "ns3/ipv4-address.h" +#include "ns3/ipv4.h" +#include "ns3/socket.h" +#include "ns3/ipv4-route.h" +#include "ns3/onoff-application.h" + +#include "ns3/ascii-trace.h" + +#include "ns3/trace-context.h" +#include "ns3/trace-root.h" + + +using namespace ns3; + + +int main (int argc, char *argv[]) +{ + + // Users may find it convenient to turn on explicit debugging + // for selected modules; the below lines suggest how to do this +#if 0 + DebugComponentEnable("Channel"); + DebugComponentEnable("CsmaCdChannel"); + DebugComponentEnable("CsmaCdNetDevice"); + DebugComponentEnable("NetDevice"); + DebugComponentEnable("PacketSocket"); +#endif + + Packet::EnableMetadata(); + + // Set up some default values for the simulation. Use the Bind() + // technique to tell the system what subclass of Queue to use, + // and what the queue limit is + + // The below Bind command tells the queue factory which class to + // instantiate, when the queue factory is invoked in the topology code + Bind ("Queue", "DropTailQueue"); + + // Allow the user to override any of the defaults and the above + // Bind()s at run-time, via command-line arguments + CommandLine::Parse (argc, argv); + + // Here, we will explicitly create four nodes. In more sophisticated + // topologies, we could configure a node factory. + Ptr n0 = Create (); + Ptr n1 = Create (); + Ptr n2 = Create (); + Ptr n3 = Create (); + + // We create the channels first without any IP addressing information + Ptr channel0 = + CsmaCdTopology::CreateCsmaCdChannel( + DataRate(5000000), MilliSeconds(2)); + + CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n0, channel0, + MacAddress("10:54:23:54:23:50")); + CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n1, channel0, + MacAddress("10:54:23:54:23:51")); + CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n2, channel0, + MacAddress("10:54:23:54:23:52")); + CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n3, channel0, + MacAddress("10:54:23:54:23:53")); + + // Later, we add IP addresses. + CsmaCdIpv4Topology::AddIpv4Address ( + n0, 0, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); + + CsmaCdIpv4Topology::AddIpv4Address ( + n0, 1, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); + + CsmaCdIpv4Topology::AddIpv4Address ( + n1, 0, Ipv4Address("10.1.2.1"), Ipv4Mask("255.255.255.0")); + + CsmaCdIpv4Topology::AddIpv4Address ( + n1, 1, Ipv4Address("10.1.2.2"), Ipv4Mask("255.255.255.0")); + + CsmaCdIpv4Topology::AddIpv4Address ( + n2, 0, Ipv4Address("10.1.3.1"), Ipv4Mask("255.255.255.0")); + + CsmaCdIpv4Topology::AddIpv4Address ( + n2, 1, Ipv4Address("10.1.3.2"), Ipv4Mask("255.255.255.0")); + + CsmaCdIpv4Topology::AddIpv4Address ( + n3, 0, Ipv4Address("10.1.4.1"), Ipv4Mask("255.255.255.0")); + + CsmaCdIpv4Topology::AddIpv4Address ( + n3, 1, Ipv4Address("10.1.4.2"), Ipv4Mask("255.255.255.0")); + + // Finally, we add static routes. These three steps (Channel and + // NetDevice creation, IP Address assignment, and routing) are + // separated because there may be a need to postpone IP Address + // assignment (emulation) or modify to use dynamic routing + CsmaCdIpv4Topology::AddIpv4Routes(n0->GetDevice(0), n2->GetDevice(1)); + CsmaCdIpv4Topology::AddIpv4Routes(n1->GetDevice(0), n2->GetDevice(1)); + CsmaCdIpv4Topology::AddIpv4Routes(n2->GetDevice(0), n3->GetDevice(1)); + + + // Create the OnOff application to send UDP datagrams of size + // 210 bytes at a rate of 448 Kb/s + Ptr ooff = Create ( + n0, + Ipv4Address("10.1.3.2"), + 80, + "Udp", + ConstantVariable(1), + ConstantVariable(0)); + // Start the application + ooff->Start(Seconds(1.0)); + ooff->Stop (Seconds(10.0)); + + // Create a similar flow from n3 to n1, starting at time 1.1 seconds + ooff = Create ( + n3, + Ipv4Address("10.1.2.1"), + 80, + "Udp", + ConstantVariable(1), + ConstantVariable(0)); + // Start the application + ooff->Start(Seconds(1.1)); + ooff->Stop (Seconds(10.0)); + + // Here, finish off packet routing configuration + // This will likely set by some global StaticRouting object in the future + Ptr ipv4; + ipv4 = n0->QueryInterface (Ipv4::iid); + ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1); + ipv4 = n3->QueryInterface (Ipv4::iid); + ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1); + + // Configure tracing of all enqueue, dequeue, and NetDevice receive events + // Trace output will be sent to the simple-p2p.tr file + AsciiTrace asciitrace ("simple-csma-cd.tr"); + asciitrace.TraceAllNetDeviceRx (); + // asciitrace.TraceAllQueues (); + + // Also configure some tcpdump traces; each interface will be traced + // The output files will be named simple-p2p.pcap-- + // and can be read by the "tcpdump -r" command (use "-tt" option to + // display timestamps correctly) + // PcapTrace pcaptrace ("simple-p2p.pcap"); + // pcaptrace.TraceAllIp (); + + Simulator::Run (); + + Simulator::Destroy (); +} diff --git a/examples/wscript b/examples/wscript index c5b5ed69f..dcdf4ef67 100644 --- a/examples/wscript +++ b/examples/wscript @@ -10,4 +10,5 @@ def build(bld): return obj obj = create_ns_prog('simple-p2p', 'simple-p2p.cc', deps=['point-to-point', 'internet-node']) + obj = create_ns_prog('simple-csma-cd', 'simple-csma-cd.cc', deps=['csma-cd', 'internet-node']) diff --git a/src/devices/csma-cd/backoff.cc b/src/devices/csma-cd/backoff.cc new file mode 100644 index 000000000..8f6dd1ee0 --- /dev/null +++ b/src/devices/csma-cd/backoff.cc @@ -0,0 +1,83 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007, Emmanuelle Laprise + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise + */ + +#include "backoff.h" + +namespace ns3 { + +Backoff::Backoff() +{ + m_slotTime = MicroSeconds(1); + m_minSlots = 1; + m_maxSlots = 1000; + m_ceiling = 10; + m_maxRetries = 1000; + + ResetBackoffTime(); +} + +Backoff::Backoff(Time slotTime, uint32_t minSlots, uint32_t maxSlots, + uint32_t ceiling, uint32_t maxRetries) +{ + m_slotTime = slotTime; + m_minSlots = minSlots; + m_maxSlots = maxSlots; + m_ceiling = ceiling; + m_maxRetries = maxRetries; +} + +Time +Backoff::GetBackoffTime (void) +{ + Time backoff; + uint32_t ceiling; + + if ((m_ceiling > 0) &&(m_numBackoffRetries > m_ceiling)) + ceiling = m_ceiling; + else + ceiling = m_numBackoffRetries; + + uint32_t minSlot = m_minSlots; + uint32_t maxSlot = (uint32_t)pow(2, ceiling) - 1; + if (maxSlot > m_maxSlots) + maxSlot = m_maxSlots; + + uint32_t backoffSlots = + (uint32_t)UniformVariable::GetSingleValue(minSlot, maxSlot); + + backoff = Scalar(backoffSlots) * m_slotTime; + return (backoff); +} + +void Backoff::ResetBackoffTime (void) +{ + m_numBackoffRetries = 0; +} + +bool Backoff::MaxRetriesReached(void) { + return (m_numBackoffRetries >= m_maxRetries); +} + +void Backoff::IncrNumRetries(void) { + m_numBackoffRetries++; +} + +} // namespace ns3 diff --git a/src/devices/csma-cd/backoff.h b/src/devices/csma-cd/backoff.h new file mode 100644 index 000000000..adf270076 --- /dev/null +++ b/src/devices/csma-cd/backoff.h @@ -0,0 +1,87 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise + * + * 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: Emmanuelle Laprise +#include "ns3/nstime.h" +#include "ns3/random-variable.h" + +namespace ns3 { + + /** + * \brief The backoff class is used for calculating backoff times + * when many net devices can write to the same channel + * + */ + +class Backoff { +public: + uint32_t m_minSlots; // Minimum number of backoff slots (when + // multiplied by m_slotTime, determines minimum + // backoff time) + uint32_t m_maxSlots; // Maximim number of backoff slots (when + // multiplied by m_slotTime, determines + // maximum backoff time) + uint32_t m_ceiling; // Caps the exponential function when the + // number of retries reaches m_ceiling + uint32_t m_maxRetries; // Maximum number of transmission retries + // before the packet is dropped. + Time m_slotTime; // Length of one slot. A slot time, it usually + // the packet transmission time, if the packet + // size is fixed. + + Backoff(); + Backoff(Time slotTime, uint32_t minSlots, uint32_t maxSlots, + uint32_t ceiling, uint32_t maxRetries); + + /** + * \return The amount of time that the net device should wait before + * trying to retransmit the packet + */ + Time GetBackoffTime(); + /** + * Indicates to the backoff object that the last packet was + * successfully transmitted and that the number of retries should be + * reset to 0. + */ + void ResetBackoffTime(); + /** + * \return True if the maximum number of retries has been reached + */ + bool MaxRetriesReached(); + /** + * Increments the number of retries by 1. + */ + void IncrNumRetries(); + +private: + uint32_t m_numBackoffRetries; // Number of times that the + // transmitter has tried to + // unsuccessfully transmit the current + // packet +}; + +}; // namespace ns3 + +#endif // BACKOFF_H + diff --git a/src/devices/csma-cd/csma-cd-channel.cc b/src/devices/csma-cd/csma-cd-channel.cc new file mode 100644 index 000000000..004ddbd33 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-channel.cc @@ -0,0 +1,359 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise + */ + +#include "csma-cd-channel.h" +#include "csma-cd-net-device.h" +#include "ns3/packet.h" +#include "ns3/simulator.h" +#include "ns3/debug.h" + +NS_DEBUG_COMPONENT_DEFINE ("CsmaCdChannel"); + +namespace ns3 { + +CsmaCdDeviceRec::CsmaCdDeviceRec() +{ + active = false; +} + +CsmaCdDeviceRec::CsmaCdDeviceRec(Ptr device) +{ + devicePtr = device; + active = true; +} + +bool +CsmaCdDeviceRec::IsActive() { + return active; +} + + +// +// By default, you get a channel with the name "CsmaCd Channel" that +// has an "infitely" fast transmission speed and zero delay. +CsmaCdChannel::CsmaCdChannel() +: + Channel ("CsmaCd Channel"), + m_bps (DataRate(0xffffffff)), + m_delay (Seconds(0)) +{ + NS_DEBUG("CsmaCdChannel::CsmaCdChannel ()"); + Init(); +} + +CsmaCdChannel::CsmaCdChannel( + const DataRate& bps, + const Time& delay) +: + Channel ("CsmaCd Channel"), + m_bps (bps), + m_delay (delay) +{ + NS_DEBUG("CsmaCdChannel::CsmaCdChannel (" << Channel::GetName() + << ", " << bps.GetBitRate() << ", " << delay << ")"); + Init(); +} + +CsmaCdChannel::CsmaCdChannel( + const std::string& name, + const DataRate& bps, + const Time& delay) +: + Channel (name), + m_bps (bps), + m_delay (delay) +{ + NS_DEBUG("CsmaCdChannel::CsmaCdChannel (" << name << ", " << + bps.GetBitRate() << ", " << delay << ")"); + Init(); +} + +void CsmaCdChannel::Init() { + m_state = IDLE; + m_deviceList.clear(); +} + +int32_t +CsmaCdChannel::Attach(Ptr device) +{ + NS_DEBUG("CsmaCdChannel::Attach (" << device << ")"); + NS_ASSERT(device != 0); + + CsmaCdDeviceRec rec(device); + + m_deviceList.push_back(rec); + return (m_deviceList.size() - 1); +} + +bool +CsmaCdChannel::Reattach(Ptr device) +{ + NS_DEBUG("CsmaCdChannel::Reattach (" << device << ")"); + NS_ASSERT(device != 0); + + std::vector::iterator it; + for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) + { + if (it->devicePtr == device) + { + if (!it->active) { + it->active = true; + return true; + } else { + return false; + } + } + } + return false; +} + +bool +CsmaCdChannel::Reattach(uint32_t deviceId) +{ + NS_DEBUG("CsmaCdChannel::Reattach (" << deviceId << ")"); + if (deviceId < m_deviceList.size()) + { + return false; + } + + if (m_deviceList[deviceId].active) + { + return false; + } else { + m_deviceList[deviceId].active = true; + return true; + } +} + +bool +CsmaCdChannel::Detach(uint32_t deviceId) +{ + NS_DEBUG("CsmaCdChannel::Detach (" << deviceId << ")"); + + if (deviceId < m_deviceList.size()) + { + if (!m_deviceList[deviceId].active) + { + NS_DEBUG("CsmaCdChannel::Detach Device is already detached (" + << deviceId << ")"); + return false; + } + + m_deviceList[deviceId].active = false; + if ((m_state == TRANSMITTING) && (m_currentSrc == deviceId)) + { + NS_DEBUG("CsmaCdChannel::Detach Device is currently" + << "transmitting (" << deviceId << ")"); + // Here we will need to place a warning in the packet + } + + return true; + } else { + return false; + } +} + +bool +CsmaCdChannel::Detach(Ptr device) +{ + NS_DEBUG("CsmaCdChannel::Detach (" << device << ")"); + NS_ASSERT(device != 0); + + std::vector::iterator it; + for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) + { + if ((it->devicePtr == device) && (it->active)) + { + it->active = false; + return true; + } + } + return false; +} + +bool +CsmaCdChannel::TransmitStart(Packet& p, uint32_t srcId) +{ + NS_DEBUG ("CsmaCdChannel::TransmitStart (" << &p << ", " << srcId + << ")"); + NS_DEBUG ("CsmaCdChannel::TransmitStart (): UID is " << + p.GetUid () << ")"); + + if (m_state != IDLE) + { + NS_DEBUG("CsmaCdChannel::TransmitStart (): state is not IDLE"); + return false; + } + + if (!IsActive(srcId)) + { + NS_DEBUG("CsmaCdChannel::TransmitStart (): ERROR: Seclected " + << "source is not currently attached to network"); + return false; + } + + NS_DEBUG("CsmaCdChannel::TransmitStart (): switch to TRANSMITTING"); + m_currentPkt = p; + m_currentSrc = srcId; + m_state = TRANSMITTING; + return true; +} + +bool +CsmaCdChannel::IsActive(uint32_t deviceId) { + return (m_deviceList[deviceId].active); +} + +bool +CsmaCdChannel::TransmitEnd() +{ + NS_DEBUG("CsmaCdChannel::TransmitEnd (" << &m_currentPkt << ", " + << m_currentSrc << ")"); + NS_DEBUG("CsmaCdChannel::TransmitEnd (): UID is " << + m_currentPkt.GetUid () << ")"); + + NS_ASSERT(m_state == TRANSMITTING); + m_state = PROPAGATING; + + bool retVal = true; + + if (!IsActive(m_currentSrc)) { + NS_DEBUG("CsmaCdChannel::TransmitEnd (): ERROR: Seclected source " + << "was detached before the end of the transmission"); + retVal = false; + } + + NS_DEBUG ("CsmaCdChannel::TransmitEnd (): Schedule event in " << + m_delay.GetSeconds () << "sec"); + + Simulator::Schedule (m_delay, + &CsmaCdChannel::PropagationCompleteEvent, + this); + return retVal; +} + +void +CsmaCdChannel::PropagationCompleteEvent() +{ + NS_DEBUG("CsmaCdChannel::PropagationCompleteEvent (" + << &m_currentPkt << ")"); + NS_DEBUG ("CsmaCdChannel::PropagationCompleteEvent (): UID is " << + m_currentPkt.GetUid () << ")"); + + NS_ASSERT(m_state == PROPAGATING); + m_state = IDLE; + + NS_DEBUG ("CsmaCdChannel::PropagationCompleteEvent (): Receive"); + + std::vector::iterator it; + for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) + { + if (it->IsActive()) + { + it->devicePtr->Receive (m_currentPkt); + } + } +} + + +uint32_t +CsmaCdChannel::GetNumActDevices (void) +{ + int numActDevices = 0; + std::vector::iterator it; + for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) + { + if (it->active) + { + numActDevices++; + } + } + return numActDevices; +} + +// This is not the number of active devices. This is the total number +// of devices even if some were detached after. +uint32_t +CsmaCdChannel::GetNDevices (void) const +{ + return (m_deviceList.size()); +} + +Ptr +CsmaCdChannel::GetDevice (uint32_t i) const +{ + Ptr< CsmaCdNetDevice > netDevice; + + netDevice = m_deviceList[i].devicePtr; + return netDevice; +} + +int32_t +CsmaCdChannel::GetDeviceNum (Ptr device) +{ + std::vector::iterator it; + int i = 0; + for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) + { + if (it->devicePtr == device) + { + if (it->active) + { + return i; + } else { + return -2; + } + } + i++; + } + return -1; +} + +bool +CsmaCdChannel::IsBusy (void) +{ + if (m_state == IDLE) + { + return false; + } else { + return true; + } +} + +DataRate +CsmaCdChannel::GetDataRate (void) +{ + return m_bps; +} + +Time +CsmaCdChannel::GetDelay (void) +{ + return m_delay; +} + +WireState +CsmaCdChannel::GetState(void) +{ + return m_state; +} + +} // namespace ns3 diff --git a/src/devices/csma-cd/csma-cd-channel.h b/src/devices/csma-cd/csma-cd-channel.h new file mode 100644 index 000000000..fafb5b6ad --- /dev/null +++ b/src/devices/csma-cd/csma-cd-channel.h @@ -0,0 +1,307 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise + * + * 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: Emmanuelle Laprise + */ + +#ifndef CSMA_CD_CHANNEL_H +#define CSMA_CD_CHANNEL_H + +#include "ns3/channel.h" +#include "ns3/ptr.h" +#include "ns3/packet.h" +#include "ns3/nstime.h" +#include "ns3/data-rate.h" + +namespace ns3 { + +class CsmaCdNetDevice; + + /** + * \brief CsmaCdNetDevice Record + * + * Stores the information related to each net device that is + * connected to the channel. + */ + class CsmaCdDeviceRec { + public: + Ptr< CsmaCdNetDevice > devicePtr; /// Pointer to the net device + bool active; /// Is net device enabled to TX/RX + + CsmaCdDeviceRec(); + CsmaCdDeviceRec(Ptr< CsmaCdNetDevice > device); + /* + * \return If the net device pointed to by the devicePtr is active + * and ready to RX/TX. + */ + bool IsActive(); + }; + + /** + * Current state of the channel + */ + enum WireState + { + IDLE, /**< Channel is IDLE, no packet is being + transmitted */ + TRANSMITTING, /**< Channel is BUSY, a packet is being written + by a net device */ + PROPAGATING /**< Channel is BUSY, packet is propagating to + all attached net devices */ + }; + +/** + * \brief CsmaCd Channel. + * + * This class represents a simple Csma/Cd channel that can be used + * when many nodes are connected to one wire. It uses a single busy + * flag to indicate if the channel is currently in use. It does not + * take into account the distances between stations or the speed of + * light to determine collisions. + * + * Each net device must query the state of the channel and make sure + * that it is IDLE before writing a packet to the channel. + * + * When the channel is instaniated, the constructor takes parameters + * for a single speed, in bits per second, and a speed-of-light delay + * time as a Time object. When a net device is attached to a channel, + * it is assigned a device ID, this is in order to facilitate the + * check that makes sure that a net device that is trying to send a + * packet to the channel is really connected to this channel + * + */ +class CsmaCdChannel : public Channel { +public: + /** + * \brief Create a CsmaCdChannel + * + * By default, you get a channel with the name "CsmaCd Channel" that + * has an "infitely" fast transmission speed and zero delay. + */ + CsmaCdChannel (); + + /** + * \brief Create a CsmaCdChannel + * + * \param bps The bitrate of the channel + * \param delay Transmission delay through the channel + */ + CsmaCdChannel (const DataRate& bps, const Time& delay); + + /** + * \brief Create a CsmaCdChannel + * + * \param name the name of the channel for identification purposes + * \param bps The bitrate of the channel + * \param delay Transmission delay through the channel + */ + CsmaCdChannel (const std::string& name, + const DataRate& bps, const Time& delay); + + /** + * \brief Attach a given netdevice to this channel + * + * \param device Device pointer to the netdevice to attach to the channel + * \return The assigned device number + */ + int32_t Attach (Ptr device); + /** + * \brief Detach a given netdevice from this channel + * + * The net device is marked as inactive and it is not allowed to + * receive or transmit packets + * + * \param device Device pointer to the netdevice to detach from the channel + * \return True if the device is found and attached to the channel, + * false if the device is not currently connected to the channel or + * can't be found. + */ + bool Detach (Ptr device); + /** + * \brief Detach a given netdevice from this channel + * + * The net device is marked as inactive and it is not allowed to + * receive or transmit packets + * + * \param deviceId The deviceID assigned to the net device when it + * was connected to the channel + * \return True if the device is found and attached to the channel, + * false if the device is not currently connected to the channel or + * can't be found. + */ + bool Detach (uint32_t deviceId); + /** + * \brief Reattach a previously detached net device to the channel + * + * The net device is marked as active. It is now allowed to receive + * or transmit packets. The net device must have been previously + * attached to the channel using the attach function. + * + * \param deviceId The device ID assigned to the net device when it + * was connected to the channel + * \return True if the device is found and is not attached to the + * channel, false if the device is currently connected to the + * channel or can't be found. + */ + bool Reattach(uint32_t deviceId); + /** + * \brief Reattach a previously detached net device to the channel + * + * The net device is marked as active. It is now allowed to receive + * or transmit packets. The net device must have been previously + * attached to the channel using the attach function. + * + * \param device Device pointer to the netdevice to detach from the channel + * \return True if the device is found and is not attached to the + * channel, false if the device is currently connected to the + * channel or can't be found. + */ + bool Reattach(Ptr device); + /** + * \brief Start transmitting a packet over the channel + * + * If the srcId belongs to a net device that is connected to the + * channel, packet transmission begins, and the channel becomes busy + * until the packet has completely reached all destinations. + * + * \param p A reference to the packet that will be transmitted over + * the channel + * \param srcId The device Id of the net device that wants to + * transmit on the channel. + * \return True if the channel is not busy and the transmitting net + * device is currently active. + */ + bool TransmitStart (Packet& p, uint32_t srcId); + /** + * \brief Indicates that the net device has finished transmitting + * the packet over the channel + * + * The channel will stay busy until the packet has completely + * propagated to all net devices attached to the channel. The + * TransmitEnd function schedules the PropagationCompleteEvent which + * will free the channel for further transmissions. Stores the + * packet p as the m_currentPkt, the packet being currently + * transmitting. + * + * \return Returns true unless the source was detached before it + * completed its transmission. + */ + bool TransmitEnd (); + /** + * \brief Indicates that the channel has finished propagating the + * current packet. The channel is released and becomes free. + * + * Calls the receive function of every active net device that is + * attached to the channel. + */ + void PropagationCompleteEvent(); + /** + * \return Returns the device number assigned to a net device by the + * channel + * + * \param device Device pointer to the netdevice for which the device + * number is needed + */ + int32_t GetDeviceNum (Ptr device); + /** + * \return Returns the state of the channel (IDLE -- free, + * TRANSMITTING -- busy, PROPAGATING - busy ) + */ + WireState GetState(); + + /** + * \brief Indicates if the channel is busy. The channel will only + * accept new packets for transmission if it is not busy. + * + * \return Returns true if the channel is busy and false if it is + * free. + */ + bool IsBusy(); + + /** + * \brief Indicates if a net device is currently attached or + * detached from the channel. + * + * \param deviceId The ID that was assigned to the net device when + * it was attached to the channel. + * \return Returns true if the net device is attached to the + * channel, false otherwise. + */ + bool IsActive(uint32_t deviceId); + /** + * \return Returns the number of net devices that are currently + * attached to the channel. + */ + uint32_t GetNumActDevices (void); + /** + * \return Returns the total number of devices including devices + * that have been detached from the channel. + */ + virtual uint32_t GetNDevices (void) const; + /** + * \param i The deviceId of the net device for which we want the + * pointer. + * \return Returns the pointer to the net device that is associated + * with deviceId i. + */ + virtual Ptr GetDevice (uint32_t i) const; + + virtual DataRate GetDataRate (void); + virtual Time GetDelay (void); + +private: + DataRate m_bps; /// Data rate of the channel + Time m_delay; /// Delay of the channel. + + /** + * List of the net devices that have been or are currently connected + * to the channel. + * + * Devices are nor removed from this list, they are marked as + * inactive. Otherwise the assigned device IDs will not refer to the + * correct NetDevice. The DeviceIds are used so that it is possible + * to have a number to refer to an entry in the list so that the + * whole list does not have to be searched when making sure that a + * source is attached to a channel when it is transmitting data. + */ + std::vector< CsmaCdDeviceRec > m_deviceList; + /** + * Packet that is currently being transmitted on the channel (or last + * packet to have been transmitted on the channel if the channel is + * free.) + */ + Packet m_currentPkt; + /** + * Device Id of the source that is currently transmitting on the + * channel. Or last source to have transmitted a packet on the + * channel, if the channel is currently not busy. + */ + uint32_t m_currentSrc; + /** + * Current state of the channel + */ + WireState m_state; + /** + * Initializes the channel when it is constructed. Resets the + * deviceList and sets the channel state to IDLE. + */ + void Init (void); +}; + +} // namespace ns3 + +#endif /* CSMA_CD_CHANNEL_H */ diff --git a/src/devices/csma-cd/csma-cd-ipv4-topology.cc b/src/devices/csma-cd/csma-cd-ipv4-topology.cc new file mode 100644 index 000000000..64ddc036c --- /dev/null +++ b/src/devices/csma-cd/csma-cd-ipv4-topology.cc @@ -0,0 +1,162 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2007 Emmanuelle Laprise +// +// 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: Emmanuelle Laprise +// + +#include +#include "ns3/assert.h" +#include "ns3/debug.h" +#include "ns3/fatal-error.h" +#include "ns3/nstime.h" +#include "ns3/internet-node.h" +#include "ns3/ipv4-address.h" +#include "ns3/ipv4.h" +#include "ns3/queue.h" + +#include "csma-cd-channel.h" +#include "csma-cd-net-device.h" +#include "csma-cd-ipv4-topology.h" + +namespace ns3 { + + +void +CsmaCdIpv4Topology::AddIpv4CsmaCdNode(Ptr n1, + Ptr ch, + MacAddress addr) +{ + Ptr q = Queue::CreateDefault (); + + // Use the first net device in the node to transmit + Ptr nd0 = Create (n1, addr, + ns3::CsmaCdNetDevice::IP_ARP, + true, false); + nd0->AddQueue(q); + nd0->Attach (ch); + + // Use the second net device in the node to transmit + Ptr nd1 = Create (n1, addr, + ns3::CsmaCdNetDevice::IP_ARP, + false, true); + nd1->AddQueue(q); + nd1->Attach (ch); +} + + +void +CsmaCdIpv4Topology::AddIpv4LlcCsmaCdNode(Ptr n1, + Ptr ch, + MacAddress addr) +{ + Ptr q = Queue::CreateDefault (); + + Ptr nd0 = Create (n1, addr, + ns3::CsmaCdNetDevice::LLC, + true, false); + nd0->AddQueue(q); + nd0->Attach (ch); + + Ptr nd1 = Create (n1, addr, + ns3::CsmaCdNetDevice::LLC, + false, true); + nd1->AddQueue(q); + nd1->Attach (ch); +} + +void +CsmaCdIpv4Topology::AddIpv4RawCsmaCdNode(Ptr n1, + Ptr ch, + MacAddress addr) +{ + Ptr q = Queue::CreateDefault (); + + Ptr nd0 = Create (n1, addr, + ns3::CsmaCdNetDevice::RAW, + true, false); + nd0->AddQueue(q); + nd0->Attach (ch); + + Ptr nd1 = Create (n1, addr, + ns3::CsmaCdNetDevice::RAW, + false, true); + nd1->AddQueue(q); + nd1->Attach (ch); +} + +void +CsmaCdIpv4Topology::AddIpv4Address(Ptr n1, + int ndNum, + const Ipv4Address& addr1, + const Ipv4Mask& netmask1) +{ + + // Duplex link is assumed to be subnetted as a /30 + // May run this unnumbered in the future? + Ipv4Mask netmask(netmask1); + + Ptr nd1 = n1->GetDevice(ndNum); + + Ptr ip1 = n1->QueryInterface (Ipv4::iid); + uint32_t index1 = ip1->AddInterface (nd1); + + ip1->SetAddress (index1, addr1); + ip1->SetNetworkMask (index1, netmask); + ip1->SetUp (index1); + +} + +void +CsmaCdIpv4Topology::AddIpv4Routes ( + Ptr nd1, Ptr nd2) +{ + // Assert that both are Ipv4 nodes + Ptr ip1 = nd1->GetNode ()->QueryInterface (Ipv4::iid); + Ptr ip2 = nd2->GetNode ()->QueryInterface (Ipv4::iid); + NS_ASSERT(ip1 != 0 && ip2 != 0); + + // Get interface indexes for both nodes corresponding to the right channel + uint32_t index1 = 0; + bool found = false; + for (uint32_t i = 0; i < ip1->GetNInterfaces (); i++) + { + if (ip1 ->GetNetDevice (i) == nd1) + { + index1 = i; + found = true; + } + } + NS_ASSERT(found); + + uint32_t index2 = 0; + found = false; + for (uint32_t i = 0; i < ip2->GetNInterfaces (); i++) + { + if (ip2 ->GetNetDevice (i) == nd2) + { + index2 = i; + found = true; + } + } + NS_ASSERT(found); + + ip1->AddHostRouteTo (ip2-> GetAddress (index2), index1); + ip2->AddHostRouteTo (ip1-> GetAddress (index1), index2); +} + +} // namespace ns3 + diff --git a/src/devices/csma-cd/csma-cd-ipv4-topology.h b/src/devices/csma-cd/csma-cd-ipv4-topology.h new file mode 100644 index 000000000..fe821cee6 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-ipv4-topology.h @@ -0,0 +1,120 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2007 Emmanuelle Laprise +// +// 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: Emmanuelle Laprise +// + +#ifndef __CSMA_CD_IPV4_TOPOLOGY_H__ +#define __CSMA_CD_IPV4_TOPOLOGY_H__ + +#include "ns3/ptr.h" +#include "ns3/ipv4-address.h" +#include "ns3/ipv4.h" +#include "ns3/ipv4-route.h" +#include "ns3/internet-node.h" +#include "ns3/csma-cd-net-device.h" + +// The topology class consists of only static methods thar are used to +// create the topology and data flows for an ns3 simulation + +namespace ns3 { + +class CsmaCdIpv4Channel; +class Node; +class IPAddr; +class DataRate; +class Queue; + +/** + * \brief A helper class to create Topologies based on the + * InternetNodes and CsmaCdChannels. Either the + * SimpleCsmaCdNetDevice or the LLCCsmaCdNetDevice can be used + * when constructing these topologies. + */ +class CsmaCdIpv4Topology { +public: + + /** + * \param n1 Node to be attached to the Csma/Cd channel + * \param ch CsmaCdChannel to which node n1 should be attached + * \param addr Mac address of the node + * + * Add a Csma/Cd node to a Csma/Cd channel. This function adds + * a EthernetCsmaCdNetDevice to the nodes so that they can + * connect to a CsmaCdChannel. This means that Ethernet headers + * and trailers will be added to the packet before sending out on + * the net device. + */ + static void AddIpv4CsmaCdNode( Ptr n1, + Ptr ch, + MacAddress addr); + + /** + * \param n1 Node to be attached to the Csma/Cd channel + * \param ch CsmaCdChannel to which node n1 should be attached + * \param addr Mac address of the node + * + * Add a Csma/Cd node to a Csma/Cd channel. This function adds + * a RawCsmaCdNetDevice to the nodes so that they can connect + * to a CsmaCdChannel. + */ + static void AddIpv4RawCsmaCdNode( Ptr n1, + Ptr ch, + MacAddress addr); + + /** + * \param n1 Node to be attached to the Csma/Cd channel + * \param ch CsmaCdChannel to which node n1 should be attached + * \param addr Mac address of the node + * + * Add a Csma/Cd node to a Csma/Cd channel. This function adds + * a LlcCsmaCdNetDevice to the nodes so that they can connect + * to a CsmaCdChannel. + */ + static void AddIpv4LlcCsmaCdNode( Ptr n1, + Ptr ch, + MacAddress addr); + + + + /** + * \param n1 Node + * \param ndNum NetDevice number with which to associate address + * \param addr1 Ipv4 Address for ndNum of n1 + * \param network network mask for ndNum of node n1 + * + * Add an Ipv4Address to the Ipv4 interface associated with the + * ndNum CsmaCdIpv4NetDevices on the provided + * CsmaCdIpv4Channel + */ + static void AddIpv4Address(Ptr n1, int ndNum, + const Ipv4Address& addr1, + const Ipv4Mask& netmask1); + + /** + * \param nd1 Node + * \param nd2 Node + * + * Add an IPV4 host route between the two specified net devices + */ + static void AddIpv4Routes (Ptr nd1, Ptr nd2); +}; + +} // namespace ns3 + +#endif + diff --git a/src/devices/csma-cd/csma-cd-net-device.cc b/src/devices/csma-cd/csma-cd-net-device.cc new file mode 100644 index 000000000..61b162420 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-net-device.cc @@ -0,0 +1,504 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise + */ + +#include +#include +#include "ns3/debug.h" +#include "ns3/queue.h" +#include "ns3/simulator.h" +#include "ns3/composite-trace-resolver.h" +#include "csma-cd-net-device.h" +#include "csma-cd-channel.h" +#include "ns3/ethernet-header.h" +#include "ns3/ethernet-trailer.h" +#include "ns3/llc-snap-header.h" + +NS_DEBUG_COMPONENT_DEFINE ("CsmaCdNetDevice"); + +namespace ns3 { + +CsmaCdNetDevice::CsmaCdNetDevice (Ptr node, MacAddress addr, + CsmaCdEncapsulationMode pktType) + : NetDevice(node, addr), m_bps (DataRate (0xffffffff)) +{ + NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")"); + m_pktType = pktType; + + Init(true, true); +} + +CsmaCdNetDevice::CsmaCdNetDevice (Ptr node, MacAddress addr, + CsmaCdEncapsulationMode pktType, + bool sendEnable, bool receiveEnable) + : NetDevice(node, addr), m_bps (DataRate (0xffffffff)) +{ + NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")"); + m_pktType = pktType; + + Init(sendEnable, receiveEnable); +} + +CsmaCdNetDevice::~CsmaCdNetDevice() +{ + NS_DEBUG ("CsmaCdNetDevice::~CsmaCdNetDevice ()"); + m_queue = 0; +} + +// +// Copy constructor for CsmaCdNetDevice. +// +// We use the underlying NetDevice copy constructor to get the base class +// copied. These just remain as is (e.g. you get the same name, the same +// MAC address). If you need to fix them up, YOU, the copier need to do +// that. +// +// The things we need to be careful of are the channel, the queue and the +// trace callback. If the channel pointer is non-zero, we copy the pointer +// and add a reference. If the queue is non-zero, we copy it using the queue +// assignment operator. We don't mess with the trace -- we just reset it. +// We're assuming that the tracing will be set up after the topology creation +// phase and this won't actually matter. +// + +CsmaCdNetDevice::CsmaCdNetDevice (const CsmaCdNetDevice& nd) + : NetDevice(nd), m_bps (nd.m_bps) +{ + NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << &nd << ")"); + + m_txMachineState = READY; + m_tInterframeGap = nd.m_tInterframeGap; + m_backoff = nd.m_backoff; + m_channel = nd.m_channel; + m_queue = 0; + m_pktType = nd.m_pktType; + m_sendEnable = nd.m_sendEnable; + m_receiveEnable = nd.m_receiveEnable; + + if (nd.m_queue) + { + m_queue = nd.m_queue; + } + +} + +void +CsmaCdNetDevice::DoDispose () +{ + m_channel = 0; + NetDevice::DoDispose (); +} + +// +// Assignment operator for CsmaCdNetDevice. +// +// This uses the non-obvious trick of taking the source net device passed by +// value instead of by reference. This causes the copy constructor to be +// invoked (where the real work is done -- see above). All we have to do +// here is to return the newly constructed net device. +// +/* +CsmaCdNetDevice& +CsmaCdNetDevice::operator= (const CsmaCdNetDevice nd) +{ + NS_DEBUG ("CsmaCdNetDevice::operator= (" << &nd << ")"); + return *this; +} +*/ + +void +CsmaCdNetDevice::Init(bool sendEnable, bool receiveEnable) +{ + m_txMachineState = READY; + m_tInterframeGap = Seconds(0); + m_channel = 0; + m_queue = 0; + + EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff")); + EnableMulticast(); + EnablePointToPoint(); + + SetSendEnable (sendEnable); + SetReceiveEnable (receiveEnable); +} + +void +CsmaCdNetDevice::SetSendEnable (bool sendEnable) +{ + m_sendEnable = sendEnable; +} + +void +CsmaCdNetDevice::SetReceiveEnable (bool receiveEnable) +{ + m_receiveEnable = receiveEnable; +} +bool +CsmaCdNetDevice::IsSendEnabled (void) +{ + return (m_sendEnable); +} + +bool +CsmaCdNetDevice::IsReceiveEnabled (void) +{ + return (m_receiveEnable); +} + +void +CsmaCdNetDevice::SetDataRate (DataRate bps) +{ + m_bps = bps; +} + +void +CsmaCdNetDevice::SetInterframeGap (Time t) +{ + m_tInterframeGap = t; +} + +void +CsmaCdNetDevice::SetBackoffParams (Time slotTime, uint32_t minSlots, + uint32_t maxSlots, uint32_t ceiling, + uint32_t maxRetries) +{ + m_backoff.m_slotTime = slotTime; + m_backoff.m_minSlots = minSlots; + m_backoff.m_maxSlots = maxSlots; + m_backoff.m_ceiling = ceiling; + m_backoff.m_maxRetries = maxRetries; +} +void +CsmaCdNetDevice::AddHeader (Packet& p, const MacAddress& dest, + uint16_t protocolNumber) +{ + if ((m_pktType == ETHERNET_V1) || (m_pktType == IP_ARP)) + { + EthernetHeader header; + EthernetTrailer trailer; + + header.SetSource(this->GetAddress()); + header.SetDestination(dest); + switch (m_pktType) + { + case IP_ARP: + header.SetLengthType(protocolNumber); + break; + default: + header.SetLengthType(p.GetSize() + header.GetSize() + trailer.GetSize()); + break; + } + p.AddHeader(header); + trailer.CalcFcs(p); + p.AddTrailer(trailer); + } + else if (m_pktType == LLC) + { + LlcSnapHeader llc; + llc.SetType (protocolNumber); + p.AddHeader (llc); + } +} +bool +CsmaCdNetDevice::ProcessHeader(Packet& p, int& param) +{ + bool retVal = true; + + if ((m_pktType == ETHERNET_V1) || (m_pktType == IP_ARP)) + { + EthernetHeader header; + EthernetTrailer trailer; + + p.RemoveTrailer(trailer); + trailer.CheckFcs(p); + p.RemoveHeader(header); + + param = header.GetLengthType(); + if ((header.GetDestination() != this->GetBroadcast()) && + (header.GetDestination() != this->GetAddress())) + { + retVal = false; + } + } + else if (m_pktType == LLC) + { + LlcSnapHeader llc; + p.RemoveHeader (llc); + + param = llc.GetType (); + } + + return retVal; +} + +bool +CsmaCdNetDevice::DoNeedsArp (void) const +{ + if ((m_pktType == IP_ARP) || (m_pktType == LLC)) + { + return true; + } else { + return false; + } +} + +bool +CsmaCdNetDevice::SendTo (Packet& p, const MacAddress& dest, uint16_t protocolNumber) +{ + NS_DEBUG ("CsmaCdNetDevice::SendTo (" << &p << ")"); + NS_DEBUG ("CsmaCdNetDevice::SendTo (): UID is " << p.GetUid () << ")"); + + NS_ASSERT (IsLinkUp ()); + + // Only transmit if send side of net device is enabled + if (!IsSendEnabled()) + return false; + + AddHeader(p, dest, protocolNumber); + + // Place the packet to be sent on the send queue + if (m_queue->Enqueue(p) == false ) + { + return false; + } + // If the device is idle, we need to start a transmission. Otherwise, + // the transmission will be started when the current packet finished + // transmission (see TransmitCompleteEvent) + if (m_txMachineState == READY) + { + // Store the next packet to be transmitted + if (m_queue->Dequeue (m_currentPkt)) + { + TransmitStart(); + } + } + return true; +} + +void +CsmaCdNetDevice::TransmitStart () +{ + NS_DEBUG ("CsmaCdNetDevice::TransmitStart (" << &m_currentPkt << ")"); + NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): UID is " + << m_currentPkt.GetUid () << ")"); +// +// This function is called to start the process of transmitting a packet. +// We need to tell the channel that we've started wiggling the wire and +// schedule an event that will be executed when it's time to tell the +// channel that we're done wiggling the wire. +// + NS_ASSERT_MSG((m_txMachineState == READY) || (m_txMachineState == BACKOFF), + "Must be READY to transmit. Tx state is: " + << m_txMachineState); + + // Only transmit if send side of net device is enabled + if (!IsSendEnabled()) + return; + + if (m_channel->GetState() != IDLE) + { // Channel busy, backoff and rechedule TransmitStart() + m_txMachineState = BACKOFF; + if (m_backoff.MaxRetriesReached()) + { // Too many retries reached, abort transmission of packet + TransmitAbort(); + } else { + m_backoff.IncrNumRetries(); + Time backoffTime = m_backoff.GetBackoffTime(); + + NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): " + << "Channel busy, backing off for " + << backoffTime.GetSeconds () << "sec"); + + Simulator::Schedule (backoffTime, + &CsmaCdNetDevice::TransmitStart, + this); + } + } else { + // Channel is free, transmit packet + m_txMachineState = BUSY; + Time tEvent = Seconds (m_bps.CalculateTxTime(m_currentPkt.GetSize())); + + NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): " << + "Schedule TransmitCompleteEvent in " << + tEvent.GetSeconds () << "sec"); + + Simulator::Schedule (tEvent, + &CsmaCdNetDevice::TransmitCompleteEvent, + this); + if (!m_channel->TransmitStart (m_currentPkt, m_deviceId)) + { + NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): " << + "Channel transmit start did not work at " << + tEvent.GetSeconds () << "sec"); + m_txMachineState = READY; + } else { + // Transmission success, reset backoff time parameters. + m_backoff.ResetBackoffTime(); + } + } +} + + +void +CsmaCdNetDevice::TransmitAbort (void) +{ + NS_DEBUG ("CsmaCdNetDevice::TransmitAbort ()"); + + NS_DEBUG ("CsmaCdNetDevice::TransmitAbort (): Pkt UID is " << + m_currentPkt.GetUid () << ")"); + + // Try to transmit a new packet + bool found; + found = m_queue->Dequeue (m_currentPkt); + NS_ASSERT_MSG(found, "IsEmpty false but no Packet on queue?"); + m_backoff.ResetBackoffTime(); + m_txMachineState = READY; + TransmitStart (); +} + +void +CsmaCdNetDevice::TransmitCompleteEvent (void) +{ + NS_DEBUG ("CsmaCdNetDevice::TransmitCompleteEvent ()"); +// +// This function is called to finish the process of transmitting a packet. +// We need to tell the channel that we've stopped wiggling the wire and +// schedule an event that will be executed when it's time to re-enable +// the transmitter after the interframe gap. +// + NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting"); + // Channel should be transmitting + NS_ASSERT(m_channel->GetState() == TRANSMITTING); + m_txMachineState = GAP; + + NS_DEBUG ("CsmaCdNetDevice::TransmitCompleteEvent (): Pkt UID is " << + m_currentPkt.GetUid () << ")"); + m_channel->TransmitEnd (); + + NS_DEBUG ( + "CsmaCdNetDevice::TransmitCompleteEvent (): " << + "Schedule TransmitReadyEvent in " + << m_tInterframeGap.GetSeconds () << "sec"); + + Simulator::Schedule (m_tInterframeGap, + &CsmaCdNetDevice::TransmitReadyEvent, + this); +} + +void +CsmaCdNetDevice::TransmitReadyEvent (void) +{ + NS_DEBUG ("CsmaCdNetDevice::TransmitReadyEvent ()"); +// +// This function is called to enable the transmitter after the interframe +// gap has passed. If there are pending transmissions, we use this opportunity +// to start the next transmit. +// + NS_ASSERT_MSG(m_txMachineState == GAP, "Must be in interframe gap"); + m_txMachineState = READY; + + // Get the next packet from the queue for transmitting + if (m_queue->IsEmpty()) + { + return; + } + else + { + bool found; + found = m_queue->Dequeue (m_currentPkt); + NS_ASSERT_MSG(found, "IsEmpty false but no Packet on queue?"); + TransmitStart (); + } +} + +TraceResolver * +CsmaCdNetDevice::DoCreateTraceResolver (TraceContext const &context) +{ + CompositeTraceResolver *resolver = new CompositeTraceResolver (context); + resolver->Add ("queue", + MakeCallback (&Queue::CreateTraceResolver, + PeekPointer (m_queue)), + CsmaCdNetDevice::QUEUE); + resolver->Add ("rx", + m_rxTrace, + CsmaCdNetDevice::RX); + return resolver; +} + +bool +CsmaCdNetDevice::Attach (Ptr ch) +{ + NS_DEBUG ("CsmaCdNetDevice::Attach (" << &ch << ")"); + + m_channel = ch; + + m_deviceId = m_channel->Attach(this); + m_bps = m_channel->GetDataRate (); + m_tInterframeGap = m_channel->GetDelay (); + + /* + * For now, this device is up whenever a channel is attached to it. + */ + NotifyLinkUp (); + return true; +} + +void +CsmaCdNetDevice::AddQueue (Ptr q) +{ + NS_DEBUG ("CsmaCdNetDevice::AddQueue (" << q << ")"); + + m_queue = q; +} + +void +CsmaCdNetDevice::Receive (Packet& p) +{ + NS_DEBUG ("CsmaCdNetDevice::Receive UID is (" << p.GetUid() << ")"); + + // Only receive if send side of net device is enabled + if (!IsReceiveEnabled()) + return; + + int param = 0; + Packet packet = p; + + if (ProcessHeader(packet, param)) + { + m_rxTrace (packet); + ForwardUp (packet, param); + } else { + m_dropTrace (packet); + } +} + +Ptr +CsmaCdNetDevice::GetQueue(void) const +{ + return m_queue; +} + +Ptr +CsmaCdNetDevice::DoGetChannel(void) const +{ + return m_channel; +} + +} // namespace ns3 diff --git a/src/devices/csma-cd/csma-cd-net-device.h b/src/devices/csma-cd/csma-cd-net-device.h new file mode 100644 index 000000000..d2972feb2 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-net-device.h @@ -0,0 +1,424 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Emmanuelle Laprise + * + * 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: Emmanuelle Laprise +#include "ns3/node.h" +#include "ns3/backoff.h" +#include "ns3/mac-address.h" +#include "ns3/net-device.h" +#include "ns3/callback.h" +#include "ns3/packet.h" +#include "ns3/callback-trace-source.h" +#include "ns3/nstime.h" +#include "ns3/data-rate.h" +#include "ns3/ptr.h" +#include "ns3/random-variable.h" + +namespace ns3 { + +class Queue; +class CsmaCdChannel; + +/** + * \class CsmaCdNetDevice + * \brief A Device for a CsmaCd Network Link. + * + * The Csma/Cd net device class is analogous to layer 1 and 2 of the + * TCP stack. The NetDevice takes a raw packet of bytes and creates a + * protocol specific packet from them. The Csma/Cd net device class + * takes this packet and adds and processes the headers/trailers that + * are associated with EthernetV1, EthernetV2, RAW or LLC + * protocols. The EthernetV1 packet type adds and removes Ethernet + * destination and source addresses. The LLC packet type adds and + * removes LLC snap headers. The raw packet type does not add or + * remove any headers. Each Csma/Cd net device will receive all + * packets written to the Csma/Cd link. The ProcessHeader function can + * be used to filter out the packets such that higher level layers + * only receive packets that are addressed to their associated net + * devices + * + */ +class CsmaCdNetDevice : public NetDevice { +public: + /** + * Enumeration of the types of traces supported in the class. + * + */ + enum TraceType { + QUEUE, /**< Trace queue events on the attached queue */ + RX, /**< Trace packet reception events (from the channel) */ + DROP /**< Trace packet drop events (from the channel) */ + }; + + /** + * Enumeration of the types of packets supported in the class. + * + */ +enum CsmaCdEncapsulationMode { + ETHERNET_V1, /**< Version one ethernet packet, length field */ + IP_ARP, /**< Ethernet packet encapsulates IP/ARP packet */ + RAW, /**< Packet that contains no headers */ + LLC, /**< LLC packet encapsulation */ +}; + + /** + * Construct a CsmaCdNetDevice + * + * This is the constructor for the CsmaCdNetDevice. It takes as a + * parameter the Node to which this device is connected. Ownership of the + * Node pointer is not implied and the node must not be deleted. + * + * \param node the Node to which this device is connected. + * \param addr The source MAC address of the net device. + */ + CsmaCdNetDevice (Ptr node, MacAddress addr, CsmaCdEncapsulationMode pktType); + CsmaCdNetDevice (Ptr node, MacAddress addr, + CsmaCdEncapsulationMode pktType, + bool sendEnable, bool receiveEnable); + /** + * Copy Construct a CsmaCdNetDevice + * + * This is the copy constructor for the CsmaCdNetDevice. This is + * primarily used in topology creation. + * + * \param nd the object to be copied + */ + CsmaCdNetDevice (const CsmaCdNetDevice& nd); + /** + * Destroy a CsmaCdNetDevice + * + * This is the destructor for the CsmaCdNetDevice. + */ + virtual ~CsmaCdNetDevice(); + /** + * Assignment Operator for a CsmaCdNetDevice + * + * This is the assignment operator for the CsmaCdNetDevice. This is + * to allow + * + * \param nd the object to be copied + */ + // CsmaCdNetDevice& operator= (CsmaCdNetDevice nd); + /** + * Set the Data Rate used for transmission of packets. The data rate is + * set in the Attach () method from the corresponding field in the channel + * to which the device is attached. It can be overridden using this method. + * + * @see Attach () + * \param bps the data rate at which this object operates + */ + void SetDataRate (DataRate bps); + /** + * Set the inteframe gap used to separate packets. The interframe gap + * defines the minimum space required between packets sent by this device. + * It is usually set in the Attach () method based on the speed of light + * delay of the channel to which the device is attached. It can be + * overridden using this method if desired. + * + * @see Attach () + * \param t the interframe gap time + */ + void SetInterframeGap (Time t); + /** + * Set the backoff parameters used to determine the wait to retry + * transmitting a packet when the channel is busy. + * + * @see Attach () + * \param slotTime Length of a packet slot (or average packet time) + * \param minSlots Minimum number of slots to wait + * \param maxSlots Maximum number of slots to wait + * \param maxRetries Maximum number of retries before packet is discard + * \param ceiling Cap on the exponential function when calculating max slots + */ + void SetBackoffParams (Time slotTime, uint32_t minSlots, uint32_t maxSlots, + uint32_t maxRetries, uint32_t ceiling); + /** + * Attach the device to a channel. + * + * The function Attach is used to add a CsmaCdNetDevice to a + * CsmaCdChannel. + * + * @see SetDataRate () + * @see SetInterframeGap () + * \param ch a pointer to the channel to which this object is being attached. + */ + bool Attach (Ptr ch); + /** + * Attach a queue to the CsmaCdNetDevice. + * + * The CsmaCdNetDevice "owns" a queue. This queue is created by the + * CsmaCdTopology object and implements a queueing method such as + * DropTail or RED. The CsmaCdNetDevice assumes ownership of this + * queue and must delete it when the device is destroyed. + * + * @see CsmaCdTopology::AddCsmaCdLink () + * @see Queue + * @see DropTailQueue + * \param queue a pointer to the queue for which object is assuming + * ownership. + */ + void AddQueue (Ptr queue); + /** + * Receive a packet from a connected CsmaCdChannel. + * + * The CsmaCdNetDevice receives packets from its connected channel + * and forwards them up the protocol stack. This is the public method + * used by the channel to indicate that the last bit of a packet has + * arrived at the device. + * + * @see CsmaCdChannel + * \param p a reference to the received packet + */ + void Receive (Packet& p); + + bool IsSendEnabled (void); + bool IsReceiveEnabled (void); + + void SetSendEnable (bool); + void SetReceiveEnable (bool); + +protected: + virtual bool DoNeedsArp (void) const; + virtual void DoDispose (void); + /** + * Get a copy of the attached Queue. + * + * This method is provided for any derived class that may need to get + * direct access to the underlying queue. + * + * \return a pointer to the queue. + */ + Ptr GetQueue (void) const; + /** + * Get a copy of the attached Channel + * + * This method is provided for any derived class that may need to get + * direct access to the connected channel + * + * \return a pointer to the channel + */ + virtual Ptr DoGetChannel (void) const; + /** + * Adds the necessary headers and trailers to a packet of data in order to + * respect the packet type + * + * \param p Packet to which header should be added + * \param dest MAC destination address to which packet should be sent + * \param protocolNumber In some protocols, identifies the type of + * payload contained in this packet. + */ + void AddHeader (Packet& p, const MacAddress& dest, + uint16_t protocolNumber); + /** + * Removes, from a packet of data, all headers and trailers that + * relate to the packet type + * + * \param p Packet whose headers need to be processed + * \param param An integer parameter that can be set by the function + * to return information gathered in the header + * \return Returns true if the packet should be forwarded up the + * protocol stack. + */ + bool ProcessHeader (Packet& p, int& param); + +private: + /** + * Initializes variablea when construction object. + */ + void Init (bool sendEnable, bool receiveEnable); + /** + * Send a Packet on the Csma/Cd network + * + * This method does not use a destination address since all packets + * are broadcast to all NetDevices attached to the channel. Packet + * should contain all needed headers at this time. + * + * If the device is ready to transmit, the next packet is read off + * of the queue and stored locally until it has been transmitted. + * + * \param p a reference to the packet to send + * \param dest destination address + * \param protocolNumber -- this parameter is not used here + * \return true if success, false on failure + */ + virtual bool SendTo (Packet& p, const MacAddress& dest, uint16_t protocolNumber); + + /** + * Start Sending a Packet Down the Wire. + * + * The TransmitStart method is the method that is used internally in + * the CsmaCdNetDevice to begin the process of sending a packet + * out on the channel. The corresponding method is called on the + * channel to let it know that the physical device this class + * represents has virually started sending signals, this causes the + * channel to become busy. An event is scheduled for the time at + * which the bits have been completely transmitted. If the channel + * is busy, the method reschedules itself for a later time (within + * the backoff period) + * + * @see CsmaCdChannel::TransmitStart () + * @see TransmitCompleteEvent () + */ + void TransmitStart (); + /** + * Stop Sending a Packet Down the Wire and Begin the Interframe Gap. + * + * The TransmitCompleteEvent method is used internally to finish the process + * of sending a packet out on the channel. During execution of this method + * the TransmitEnd method is called on the channel to let it know that the + * physical device this class represents has virually finished sending + * signals. The channel uses this event to begin its speed of light delay + * timer after which it notifies the Net Device at the other end of the + * link that the bits have arrived. During this method, the net device + * also schedules the TransmitReadyEvent at which time the transmitter + * becomes ready to send the next packet. + * + * @see CsmaCdChannel::TransmitEnd () + * @see TransmitReadyEvent () + */ + void TransmitCompleteEvent (void); + /** + * Cause the Transmitter to Become Ready to Send Another Packet. + * + * The TransmitReadyEvent method is used internally to re-enable the + * transmit machine of the net device. It is scheduled after a suitable + * interframe gap after the completion of the previous transmission. + * The queue is checked at this time, and if there is a packet waiting on + * the queue, the transmission process is begun. + * + * If a packet is in the queue, it is extracted for the queue as the + * next packet to be transmitted by the net device. + * + * @see TransmitStart () + */ + void TransmitReadyEvent (void); + /** + * Create a Trace Resolver for events in the net device. + * (NOT TESTED) + * @see class TraceResolver + */ + virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); + + /** + * Aborts the transmission of the current packet + * + * If the net device has tried to transmit a packet for more times + * than the maximum allowed number of retries (channel always busy) + * then the packet is dropped. + * + */ + void TransmitAbort (void); + + /** + * Device ID returned by the attached functions. It is used by the + * mp-channel to identify each net device to make sure that only + * active net devices are writing to the channel + */ + uint32_t m_deviceId; + + /** + * Enable net device to send packets. True by default + */ + bool m_sendEnable; + /** + * Enable net device to receive packets. True by default + */ + bool m_receiveEnable; + /** + * Enumeration of the states of the transmit machine of the net device. + */ + enum TxMachineState + { + READY, /**< The transmitter is ready to begin transmission of a packet */ + BUSY, /**< The transmitter is busy transmitting a packet */ + GAP, /**< The transmitter is in the interframe gap time */ + BACKOFF /**< The transmitter is waiting for the channel to be free */ + }; + /** + * The state of the Net Device transmit state machine. + * @see TxMachineState + */ + TxMachineState m_txMachineState; + + /** + * The type of packet that should be created by the AddHeader + * function and that should be processed by the ProcessHeader + * function. + */ + CsmaCdEncapsulationMode m_pktType; + /** + * The data rate that the Net Device uses to simulate packet transmission + * timing. + * @see class DataRate + */ + DataRate m_bps; + /** + * The interframe gap that the Net Device uses to throttle packet + * transmission + * @see class Time + */ + Time m_tInterframeGap; + /** + * Holds the backoff parameters and is used to calculate the next + * backoff time to use when the channel is busy and the net device + * is ready to transmit + */ + Backoff m_backoff; + /** + * Next packet that will be transmitted (if transmitter is not + * currently transmitting) or packet that is currently being + * transmitted. + */ + Packet m_currentPkt; + /** + * The CsmaCdChannel to which this CsmaCdNetDevice has been + * attached. + * @see class CsmaCdChannel + */ + Ptr m_channel; + /** + * The Queue which this CsmaCdNetDevice uses as a packet source. + * Management of this Queue has been delegated to the CsmaCdNetDevice + * and it has the responsibility for deletion. + * @see class Queue + * @see class DropTailQueue + */ + Ptr m_queue; + /** + * NOT TESTED + * The trace source for the packet reception events that the device can + * fire. + * + * @see class CallBackTraceSource + * @see class TraceResolver + */ + CallbackTraceSource m_rxTrace; + CallbackTraceSource m_dropTrace; + +}; + +}; // namespace ns3 + +#endif // CSMA_CD_NET_DEVICE_H + diff --git a/src/devices/csma-cd/csma-cd-topology.cc b/src/devices/csma-cd/csma-cd-topology.cc new file mode 100644 index 000000000..e4af1a309 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-topology.cc @@ -0,0 +1,103 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2007 Emmanuelle Laprise +// +// 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: Emmanuelle Laprise +// + +// +// Topology helper for CsmaCd channels in ns3. + +#include "ns3/assert.h" +#include "ns3/debug.h" +#include "ns3/queue.h" + +#include "csma-cd-channel.h" +#include "csma-cd-net-device.h" +#include "csma-cd-topology.h" +#include "ns3/socket-factory.h" + +namespace ns3 { + +Ptr +CsmaCdTopology::CreateCsmaCdChannel( + const DataRate& bps, + const Time& delay) +{ + Ptr channel = Create (bps, delay); + + return channel; +} + +#if 0 +Ptr +CsmaCdTopology::AddCsmaCdEthernetNode( + Ptr n1, + Ptr ch, + MacAddress addr) +{ + Ptr nd1 = Create (n1, addr, + ns3::CsmaCdNetDevice::ETHERNET_V1); + + Ptr q = Queue::CreateDefault (); + nd1->AddQueue(q); + nd1->Attach (ch); + + return nd1; +} + +Ptr +CsmaCdTopology::ConnectPacketSocket(Ptr app, + Ptr ndSrc, + Ptr ndDest) +{ + Ptr socket = Create (); + socket->Bind(ndSrc); + socket->Connect(ndDest->GetAddress()); + app->Connect(socket); + + return socket; +} + +Ptr +CsmaCdTopology::ConnectPacketSocket(Ptr app, + Ptr ndSrc, + MacAddress macAddr) +{ + Ptr socket = Create (); + socket->Bind(ndSrc); + socket->Connect(macAddr); + app->Connect(socket); + + return socket; +} + +Ptr +CsmaCdTopology::CreatePacketSocket(Ptr n1, std::string iid_name) +{ + InterfaceId iid = InterfaceId::LookupByName (iid_name); + + Ptr socketFactory = + n1->QueryInterface (iid); + + Ptr socket = socketFactory->CreateSocket (); + + return socket; +} +#endif + +} // namespace ns3 + diff --git a/src/devices/csma-cd/csma-cd-topology.h b/src/devices/csma-cd/csma-cd-topology.h new file mode 100644 index 000000000..b89e0b522 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-topology.h @@ -0,0 +1,128 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2007 Emmanuelle Laprise +// +// 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: Emmanuelle Laprise +// +// Topology helper for multipoint channels in ns3. +// +#ifndef CSMA_CD_TOPOLOGY_H +#define CSMA_CD_TOPOLOGY_H + +#include "ns3/ptr.h" +#include "ns3/csma-cd-net-device.h" +#if 0 +#include "ns3/packet-socket.h" +#include "ns3/packet-socket-app.h" +#endif +#include "ns3/node.h" +#include "ns3/mac-address.h" + +// The topology class consists of only static methods thar are used to +// create the topology and data flows for an ns3 simulation + +namespace ns3 { + +class CsmaCdChannel; +class Node; +class DataRate; +class Queue; + +/** + * \brief A helper class to create CsmaCd Topologies + * + * CsmaCd topologies are created based on the + * ns3::CsmaCdNetDevice subclasses and ns3::CsmaCdChannel + * objects. This class uses the EthernetNetDevice and + * PacketSocket classes in order to create logical connections between + * net devices. The PacketSocket class generates the data and the + * EthernetNetDevice class creates ethernet packets from the + * data, filling in source and destination addresses. The + * EthernetNetDevice class filters received data packets + * according to its destination Mac addresses. + */ +class CsmaCdTopology { +public: + /** + * \param dataRate Maximum transmission link rate + * \param delay propagation delay between any two nodes + * \return Pointer to the created CsmaCdChannel + * + * Create a CsmaCdChannel. All nodes connected to a multipoint + * channels will receive all packets written to that channel + */ + static Ptr CreateCsmaCdChannel( + const DataRate& dataRate, const Time& delay); + +#if 0 + /** + * \param n1 Node to be attached to the multipoint channel + * \param ch CsmaCdChannel to which node n1 should be attached + * \param addr MacAddress that should be assigned to the + * EthernetNetDevice that will be added to the node. + * + * Add a multipoint node to a multipoint channel + */ + static Ptr AddCsmaCdEthernetNode(Ptr n1, + Ptr ch, + MacAddress addr); + + /** + * \param app Application that will be sending data to the agent + * \param ndSrc Net Device that will be sending the packets onto the + * network + * \param ndDest Net Device to which ndSrc will be sending the packets + * \return A pointer to the PacketSocket + * + * Creates an PacketSocket and configure it to send packets between + * two net devices + */ +static Ptr ConnectPacketSocket(Ptr app, + Ptr ndSrc, + Ptr ndDest); + + /** + * \param app Application that will be sending data to the agent + * \param ndSrc Net Device that will be sending the packets onto the + * network + * \param macAddr Mac destination address for the packets send by + * the ndSrc net device \return a Pointer to the created + * PacketSocket + * + * Creates an PacketSocket and configure it to send packets from a + * net device to a destination MacAddress + */ +static Ptr ConnectPacketSocket(Ptr app, + Ptr ndSrc, + MacAddress macAddr); + + /** + * \param n1 Node from which socketfactory should be tested. + * \param iid_name Interface identifier ("Packet", in this case) + * + * This is a test function to make sure that a socket can be created + * by using the socketfactory interface provided in the + * netdevicenode. + */ +static Ptr CreatePacketSocket(Ptr n1, + std::string iid_name); +#endif + +}; +} // namespace ns3 + +#endif + diff --git a/src/devices/csma-cd/wscript b/src/devices/csma-cd/wscript new file mode 100644 index 000000000..31497fd51 --- /dev/null +++ b/src/devices/csma-cd/wscript @@ -0,0 +1,24 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + obj = bld.create_obj('cpp', 'shlib') + obj.name = 'ns3-csma-cd' + obj.target = obj.name + obj.uselib_local = ['ns3-node'] + obj.source = [ + 'backoff.cc', + 'csma-cd-net-device.cc', + 'csma-cd-channel.cc', + 'csma-cd-topology.cc', + 'csma-cd-ipv4-topology.cc', + ] + headers = bld.create_obj('ns3header') + headers.source = [ + 'backoff.h', + 'csma-cd-net-device.h', + 'csma-cd-channel.h', + 'csma-cd-topology.h', + 'csma-cd-ipv4-topology.h', + ] + diff --git a/src/wscript b/src/wscript index 1d20c24e4..32c7bdde0 100644 --- a/src/wscript +++ b/src/wscript @@ -16,6 +16,7 @@ all_modules = ( 'node', 'internet-node', 'devices/point-to-point', + 'devices/csma-cd', 'applications', 'mobility', ) From 230b3840ad8c352ca46abeecd002b1f23a5d4a76 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Fri, 27 Jul 2007 21:39:58 +0200 Subject: [PATCH 08/29] cleanup simple example --- examples/simple-csma-cd.cc | 85 ++++++++++---------------------------- 1 file changed, 22 insertions(+), 63 deletions(-) diff --git a/examples/simple-csma-cd.cc b/examples/simple-csma-cd.cc index d5549af5b..d24f7c54b 100644 --- a/examples/simple-csma-cd.cc +++ b/examples/simple-csma-cd.cc @@ -12,30 +12,25 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ns-2 simple.tcl script (ported from ns-2) - * Originally authored by Steve McCanne, 12/19/1996 */ // Port of ns-2/tcl/ex/simple.tcl to ns-3 // // Network topology // -// n0 -// \ 5 Mb/s, 2ms -// \ 1.5Mb/s, 10ms -// n2 -------------------------n3 -// / -// / 5 Mb/s, 2ms -// n1 +// n0 +// | +// | +// n2---+----n3 +// | +// | +// n1 // -// - all links are p2p links with indicated one-way BW/delay -// - CBR/UDP flows from n0 to n3, and from n3 to n1 -// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec. +// - CBR/UDP flows from n0 to n1, and from n3 to n0 // - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec. // (i.e., DataRate of 448,000 bps) // - DropTail queues -// - Tracing of queues and packet receptions to file "simple-p2p.tr" +// - Tracing of queues and packet receptions to file "simple-csma-cd.tr" #include #include @@ -88,8 +83,6 @@ int main (int argc, char *argv[]) DebugComponentEnable("PacketSocket"); #endif - Packet::EnableMetadata(); - // Set up some default values for the simulation. Use the Bind() // technique to tell the system what subclass of Queue to use, // and what the queue limit is @@ -115,53 +108,34 @@ int main (int argc, char *argv[]) DataRate(5000000), MilliSeconds(2)); CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n0, channel0, - MacAddress("10:54:23:54:23:50")); + MacAddress("10:54:23:54:23:50")); CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n1, channel0, - MacAddress("10:54:23:54:23:51")); + MacAddress("10:54:23:54:23:51")); CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n2, channel0, - MacAddress("10:54:23:54:23:52")); + MacAddress("10:54:23:54:23:52")); CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n3, channel0, - MacAddress("10:54:23:54:23:53")); + MacAddress("10:54:23:54:23:53")); // Later, we add IP addresses. CsmaCdIpv4Topology::AddIpv4Address ( - n0, 0, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); + n0, 1, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); CsmaCdIpv4Topology::AddIpv4Address ( - n0, 1, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); + n1, 1, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); CsmaCdIpv4Topology::AddIpv4Address ( - n1, 0, Ipv4Address("10.1.2.1"), Ipv4Mask("255.255.255.0")); - - CsmaCdIpv4Topology::AddIpv4Address ( - n1, 1, Ipv4Address("10.1.2.2"), Ipv4Mask("255.255.255.0")); - - CsmaCdIpv4Topology::AddIpv4Address ( - n2, 0, Ipv4Address("10.1.3.1"), Ipv4Mask("255.255.255.0")); + n2, 1, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0")); CsmaCdIpv4Topology::AddIpv4Address ( - n2, 1, Ipv4Address("10.1.3.2"), Ipv4Mask("255.255.255.0")); - - CsmaCdIpv4Topology::AddIpv4Address ( - n3, 0, Ipv4Address("10.1.4.1"), Ipv4Mask("255.255.255.0")); - - CsmaCdIpv4Topology::AddIpv4Address ( - n3, 1, Ipv4Address("10.1.4.2"), Ipv4Mask("255.255.255.0")); - - // Finally, we add static routes. These three steps (Channel and - // NetDevice creation, IP Address assignment, and routing) are - // separated because there may be a need to postpone IP Address - // assignment (emulation) or modify to use dynamic routing - CsmaCdIpv4Topology::AddIpv4Routes(n0->GetDevice(0), n2->GetDevice(1)); - CsmaCdIpv4Topology::AddIpv4Routes(n1->GetDevice(0), n2->GetDevice(1)); - CsmaCdIpv4Topology::AddIpv4Routes(n2->GetDevice(0), n3->GetDevice(1)); + n3, 1, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0")); // Create the OnOff application to send UDP datagrams of size // 210 bytes at a rate of 448 Kb/s + // from n0 to n1 Ptr ooff = Create ( n0, - Ipv4Address("10.1.3.2"), + Ipv4Address("10.1.1.2"), 80, "Udp", ConstantVariable(1), @@ -170,10 +144,10 @@ int main (int argc, char *argv[]) ooff->Start(Seconds(1.0)); ooff->Stop (Seconds(10.0)); - // Create a similar flow from n3 to n1, starting at time 1.1 seconds + // Create a similar flow from n3 to n0, starting at time 1.1 seconds ooff = Create ( n3, - Ipv4Address("10.1.2.1"), + Ipv4Address("10.1.1.1"), 80, "Udp", ConstantVariable(1), @@ -181,28 +155,13 @@ int main (int argc, char *argv[]) // Start the application ooff->Start(Seconds(1.1)); ooff->Stop (Seconds(10.0)); - - // Here, finish off packet routing configuration - // This will likely set by some global StaticRouting object in the future - Ptr ipv4; - ipv4 = n0->QueryInterface (Ipv4::iid); - ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1); - ipv4 = n3->QueryInterface (Ipv4::iid); - ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1); - + // Configure tracing of all enqueue, dequeue, and NetDevice receive events // Trace output will be sent to the simple-p2p.tr file AsciiTrace asciitrace ("simple-csma-cd.tr"); asciitrace.TraceAllNetDeviceRx (); // asciitrace.TraceAllQueues (); - // Also configure some tcpdump traces; each interface will be traced - // The output files will be named simple-p2p.pcap-- - // and can be read by the "tcpdump -r" command (use "-tt" option to - // display timestamps correctly) - // PcapTrace pcaptrace ("simple-p2p.pcap"); - // pcaptrace.TraceAllIp (); - Simulator::Run (); Simulator::Destroy (); From 41c4b6453a8caadf25b12692fe44c62c394756f7 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 26 Jul 2007 12:05:31 +0100 Subject: [PATCH 09/29] EvenId const fixes. --- src/simulator/event-id.cc | 4 ++-- src/simulator/event-id.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/simulator/event-id.cc b/src/simulator/event-id.cc index 18f875935..1c2915037 100644 --- a/src/simulator/event-id.cc +++ b/src/simulator/event-id.cc @@ -45,12 +45,12 @@ EventId::Cancel (void) } } bool -EventId::IsExpired (void) +EventId::IsExpired (void) const { return Simulator::IsExpired (*this); } bool -EventId::IsRunning (void) +EventId::IsRunning (void) const { return !IsExpired (); } diff --git a/src/simulator/event-id.h b/src/simulator/event-id.h index 4350c9bbe..52371faa1 100644 --- a/src/simulator/event-id.h +++ b/src/simulator/event-id.h @@ -44,8 +44,8 @@ public: * method. * \returns true if the event has expired, false otherwise. */ - bool IsExpired (void); - bool IsRunning (void); + bool IsExpired (void) const; + bool IsRunning (void) const; public: /* The following methods are semi-private * they are supposed to be invoked only by From 1da64ebbd63d6280192671693be433f2d66087ab Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 26 Jul 2007 12:12:51 +0100 Subject: [PATCH 10/29] Allow ARP resolution to work with broadcast IPv4 (dest=255.255.255.255) packets; Partially fixes bug #36. --- src/internet-node/arp-cache.cc | 2 ++ src/internet-node/arp-ipv4-interface.cc | 15 ++++++++++++++- src/internet-node/arp-l3-protocol.cc | 22 ++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/internet-node/arp-cache.cc b/src/internet-node/arp-cache.cc index e9f48561d..92cb13af4 100644 --- a/src/internet-node/arp-cache.cc +++ b/src/internet-node/arp-cache.cc @@ -109,6 +109,8 @@ ArpCache::Lookup (Ipv4Address to) ArpCache::Entry * ArpCache::Add (Ipv4Address to) { + NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ()); + ArpCache::Entry *entry = new ArpCache::Entry (this); m_arpCache[to] = entry; return entry; diff --git a/src/internet-node/arp-ipv4-interface.cc b/src/internet-node/arp-ipv4-interface.cc index 42d6af238..4ca7ebbb3 100644 --- a/src/internet-node/arp-ipv4-interface.cc +++ b/src/internet-node/arp-ipv4-interface.cc @@ -21,6 +21,7 @@ */ #include "ns3/packet.h" +#include "ns3/debug.h" #include "ns3/composite-trace-resolver.h" #include "ns3/node.h" #include "ns3/net-device.h" @@ -60,7 +61,19 @@ ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest) { Ptr arp = m_node->QueryInterface (ArpPrivate::iid); MacAddress hardwareDestination; - bool found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination); + bool found; + + if (dest.IsBroadcast ()) + { + hardwareDestination = GetDevice ()->GetBroadcast (); + found = true; + } + else + { + Ptr arp = m_node->QueryInterface (ArpPrivate::iid); + found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination); + } + if (found) { GetDevice ()->Send (p, hardwareDestination, Ipv4L3Protocol::PROT_NUMBER); diff --git a/src/internet-node/arp-l3-protocol.cc b/src/internet-node/arp-l3-protocol.cc index f04a6aa25..b68995be3 100644 --- a/src/internet-node/arp-l3-protocol.cc +++ b/src/internet-node/arp-l3-protocol.cc @@ -87,6 +87,13 @@ ArpL3Protocol::Receive(Packet& packet, Ptr device) ArpCache *cache = FindCache (device); ArpHeader arp; packet.RemoveHeader (arp); + + NS_DEBUG ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") << + " node="<GetId ()<<", got request from " << + arp.GetSourceIpv4Address () << " for address " << + arp.GetDestinationIpv4Address () << "; we have address " << + cache->GetInterface ()->GetAddress ()); + if (arp.IsRequest () && arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress ()) { @@ -128,6 +135,12 @@ ArpL3Protocol::Receive(Packet& packet, Ptr device) // XXX report packet as dropped. } } + else + { + NS_DEBUG ("node="<GetId ()<<", got request from " << + arp.GetSourceIpv4Address () << " for unknown address " << + arp.GetDestinationIpv4Address () << " -- drop"); + } } bool ArpL3Protocol::Lookup (Packet &packet, Ipv4Address destination, @@ -203,6 +216,11 @@ void ArpL3Protocol::SendArpRequest (ArpCache const *cache, Ipv4Address to) { ArpHeader arp; + NS_DEBUG ("ARP: sending request from node "<GetId ()<< + " || src: " << cache->GetDevice ()->GetAddress () << + " / " << cache->GetInterface ()->GetAddress () << + " || dst: " << cache->GetDevice ()->GetBroadcast () << + " / " << to); arp.SetRequest (cache->GetDevice ()->GetAddress (), cache->GetInterface ()->GetAddress (), cache->GetDevice ()->GetBroadcast (), @@ -216,6 +234,10 @@ void ArpL3Protocol::SendArpReply (ArpCache const *cache, Ipv4Address toIp, MacAddress toMac) { ArpHeader arp; + NS_DEBUG ("ARP: sending reply from node "<GetId ()<< + "|| src: " << cache->GetDevice ()->GetAddress () << + " / " << cache->GetInterface ()->GetAddress () << + " || dst: " << toMac << " / " << toIp); arp.SetReply (cache->GetDevice ()->GetAddress (), cache->GetInterface ()->GetAddress (), toMac, toIp); From ddd0dc6dff1da2fc1b8066c0aabecf05c7abe523 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 26 Jul 2007 12:26:21 +0100 Subject: [PATCH 11/29] Support dynamic routing and multiple routing protocols; static routing table is refactored as a "routing protocol". Support sending IP broadcast (255.255.255.255) packets (bug #36). --- src/internet-node/ipv4-impl.cc | 7 + src/internet-node/ipv4-impl.h | 3 + src/internet-node/ipv4-l3-protocol.cc | 257 +++++++---------------- src/internet-node/ipv4-l3-protocol.h | 34 +-- src/internet-node/ipv4-static-routing.cc | 253 ++++++++++++++++++++++ src/internet-node/ipv4-static-routing.h | 101 +++++++++ src/internet-node/wscript | 2 + src/node/ipv4.h | 30 ++- 8 files changed, 494 insertions(+), 193 deletions(-) create mode 100644 src/internet-node/ipv4-static-routing.cc create mode 100644 src/internet-node/ipv4-static-routing.h diff --git a/src/internet-node/ipv4-impl.cc b/src/internet-node/ipv4-impl.cc index 9c7754be9..020413896 100644 --- a/src/internet-node/ipv4-impl.cc +++ b/src/internet-node/ipv4-impl.cc @@ -39,6 +39,13 @@ Ipv4Impl::DoDispose (void) m_ipv4 = 0; } +void +Ipv4Impl::AddRoutingProtocol (Ptr routingProtocol, + int priority) +{ + m_ipv4->AddRoutingProtocol (routingProtocol, priority); +} + void Ipv4Impl::AddHostRouteTo (Ipv4Address dest, Ipv4Address nextHop, diff --git a/src/internet-node/ipv4-impl.h b/src/internet-node/ipv4-impl.h index 979eb02f9..32d9e5c68 100644 --- a/src/internet-node/ipv4-impl.h +++ b/src/internet-node/ipv4-impl.h @@ -35,6 +35,9 @@ public: virtual ~Ipv4Impl (); + virtual void AddRoutingProtocol (Ptr routingProtocol, + int priority); + virtual void AddHostRouteTo (Ipv4Address dest, Ipv4Address nextHop, uint32_t interface); diff --git a/src/internet-node/ipv4-l3-protocol.cc b/src/internet-node/ipv4-l3-protocol.cc index 8328a9be6..077acb3f7 100644 --- a/src/internet-node/ipv4-l3-protocol.cc +++ b/src/internet-node/ipv4-l3-protocol.cc @@ -48,9 +48,10 @@ Ipv4L3Protocol::Ipv4L3Protocol(Ptr node) m_nInterfaces (0), m_defaultTtl (64), m_identification (0), - m_defaultRoute (0), m_node (node) { + m_staticRouting = Create (); + AddRoutingProtocol (m_staticRouting, 0); SetupLoopback (); } Ipv4L3Protocol::~Ipv4L3Protocol () @@ -64,25 +65,10 @@ Ipv4L3Protocol::DoDispose (void) delete (*i); } m_interfaces.clear (); - for (HostRoutesI i = m_hostRoutes.begin (); - i != m_hostRoutes.end (); - i = m_hostRoutes.erase (i)) - { - delete (*i); - } - for (NetworkRoutesI j = m_networkRoutes.begin (); - j != m_networkRoutes.end (); - j = m_networkRoutes.erase (j)) - { - delete (*j); - } - if (m_defaultRoute != 0) - { - delete m_defaultRoute; - m_defaultRoute = 0; - } m_node = 0; L3Protocol::DoDispose (); + m_staticRouting->Dispose (); + m_staticRouting = 0; } void @@ -132,17 +118,13 @@ Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, Ipv4Address nextHop, uint32_t interface) { - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface); - m_hostRoutes.push_back (route); + m_staticRouting->AddHostRouteTo (dest, nextHop, interface); } void Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, uint32_t interface) { - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateHostRouteTo (dest, interface); - m_hostRoutes.push_back (route); + m_staticRouting->AddHostRouteTo (dest, interface); } void Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, @@ -150,163 +132,63 @@ Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, Ipv4Address nextHop, uint32_t interface) { - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateNetworkRouteTo (network, - networkMask, - nextHop, - interface); - m_networkRoutes.push_back (route); + m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface); } void Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkMask, uint32_t interface) { - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateNetworkRouteTo (network, - networkMask, - interface); - m_networkRoutes.push_back (route); + m_staticRouting->AddNetworkRouteTo (network, networkMask, interface); } void Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, uint32_t interface) { - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateDefaultRoute (nextHop, interface); - delete m_defaultRoute; - m_defaultRoute = route; + m_staticRouting->SetDefaultRoute (nextHop, interface); } -Ipv4Route * -Ipv4L3Protocol::Lookup (Ipv4Address dest) + +void +Ipv4L3Protocol::Lookup (Ipv4Header const &ipHeader, + Packet packet, + Ipv4RoutingProtocol::RouteReplyCallback routeReply) { - for (HostRoutesCI i = m_hostRoutes.begin (); - i != m_hostRoutes.end (); - i++) + for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin (); + rprotoIter != m_routingProtocols.end (); rprotoIter++) { - NS_ASSERT ((*i)->IsHost ()); - if ((*i)->GetDest ().IsEqual (dest)) - { - return (*i); - } + if ((*rprotoIter).second->RequestRoute (ipHeader, packet, routeReply)) + return; } - for (NetworkRoutesI j = m_networkRoutes.begin (); - j != m_networkRoutes.end (); - j++) - { - NS_ASSERT ((*j)->IsNetwork ()); - Ipv4Mask mask = (*j)->GetDestNetworkMask (); - Ipv4Address entry = (*j)->GetDestNetwork (); - if (mask.IsMatch (dest, entry)) - { - return (*j); - } - } - if (m_defaultRoute != 0) - { - NS_ASSERT (m_defaultRoute->IsDefault ()); - return m_defaultRoute; - } - return 0; + // No route found + routeReply (false, Ipv4Route (), packet, ipHeader); +} + +void +Ipv4L3Protocol::AddRoutingProtocol (Ptr routingProtocol, + int priority) +{ + m_routingProtocols.push_back + (std::pair > (-priority, routingProtocol)); + m_routingProtocols.sort (); } uint32_t Ipv4L3Protocol::GetNRoutes (void) { - uint32_t n = 0; - if (m_defaultRoute != 0) - { - n++; - } - n += m_hostRoutes.size (); - n += m_networkRoutes.size (); - return n; + return m_staticRouting->GetNRoutes (); } + Ipv4Route * Ipv4L3Protocol::GetRoute (uint32_t index) { - if (index == 0 && m_defaultRoute != 0) - { - return m_defaultRoute; - } - if (index > 0 && m_defaultRoute != 0) - { - index--; - } - if (index < m_hostRoutes.size ()) - { - uint32_t tmp = 0; - for (HostRoutesCI i = m_hostRoutes.begin (); - i != m_hostRoutes.end (); - i++) - { - if (tmp == index) - { - return *i; - } - tmp++; - } - } - index -= m_hostRoutes.size (); - uint32_t tmp = 0; - for (NetworkRoutesI j = m_networkRoutes.begin (); - j != m_networkRoutes.end (); - j++) - { - if (tmp == index) - { - return *j; - } - tmp++; - } - NS_ASSERT (false); - // quiet compiler. - return 0; + return m_staticRouting->GetRoute (index); } + void Ipv4L3Protocol::RemoveRoute (uint32_t index) { - if (index == 0 && m_defaultRoute != 0) - { - delete m_defaultRoute; - m_defaultRoute = 0; - } - if (index > 0 && m_defaultRoute != 0) - { - index--; - } - if (index < m_hostRoutes.size ()) - { - uint32_t tmp = 0; - for (HostRoutesI i = m_hostRoutes.begin (); - i != m_hostRoutes.end (); - i++) - { - if (tmp == index) - { - delete *i; - m_hostRoutes.erase (i); - return; - } - tmp++; - } - } - index -= m_hostRoutes.size (); - uint32_t tmp = 0; - for (NetworkRoutesI j = m_networkRoutes.begin (); - j != m_networkRoutes.end (); - j++) - { - if (tmp == index) - { - delete *j; - m_networkRoutes.erase (j); - return; - } - tmp++; - } - NS_ASSERT (false); + m_staticRouting->RemoveRoute (index); } @@ -386,6 +268,7 @@ Ipv4L3Protocol::Receive(Packet& packet, Ptr device) ForwardUp (packet, ipHeader); } + void Ipv4L3Protocol::Send (Packet const &packet, Ipv4Address source, @@ -404,30 +287,49 @@ Ipv4L3Protocol::Send (Packet const &packet, m_identification ++; - // XXX Note here that in most ipv4 stacks in the world, - // the route calculation for an outgoing packet is not - // done in the ip layer. It is done within the application - // socket when the first packet is sent to avoid this - // costly lookup on a per-packet basis. - // That would require us to get the route from the packet, - // most likely with a packet tag. The higher layers do not - // do this yet for us. - Ipv4Route *route = Lookup (ipHeader.GetDestination ()); - if (route == 0) + if (destination.IsBroadcast ()) { - NS_DEBUG ("not for me -- forwarding but no route to host. drop."); - m_dropTrace (packet); - return; - } + uint32_t ifaceIndex = 0; + for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); + ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) + { + Ipv4Interface *outInterface = *ifaceIter; + Packet packetCopy = packet; - SendRealOut (packet, ipHeader, *route); + NS_ASSERT (packetCopy.GetSize () <= outInterface->GetMtu ()); + packetCopy.AddHeader (ipHeader); + m_txTrace (packetCopy, ifaceIndex); + outInterface->Send (packetCopy, destination); + } + } + else + { + // XXX Note here that in most ipv4 stacks in the world, + // the route calculation for an outgoing packet is not + // done in the ip layer. It is done within the application + // socket when the first packet is sent to avoid this + // costly lookup on a per-packet basis. + // That would require us to get the route from the packet, + // most likely with a packet tag. The higher layers do not + // do this yet for us. + Lookup (ipHeader, packet, + MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); + } } void -Ipv4L3Protocol::SendRealOut (Packet const &p, Ipv4Header const &ip, Ipv4Route const &route) +Ipv4L3Protocol::SendRealOut (bool found, + Ipv4Route const &route, + Packet packet, + Ipv4Header const &ipHeader) { - Packet packet = p; - packet.AddHeader (ip); + if (!found) + { + NS_DEBUG ("no route to host. drop."); + m_dropTrace (packet); + return; + } + packet.AddHeader (ipHeader); Ipv4Interface *outInterface = GetInterface (route.GetInterface ()); NS_ASSERT (packet.GetSize () <= outInterface->GetMtu ()); m_txTrace (packet, route.GetInterface ()); @@ -437,7 +339,7 @@ Ipv4L3Protocol::SendRealOut (Packet const &p, Ipv4Header const &ip, Ipv4Route co } else { - outInterface->Send (packet, ip.GetDestination ()); + outInterface->Send (packet, ipHeader.GetDestination ()); } } @@ -470,7 +372,7 @@ Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr routingProtocol, + int priority); protected: + virtual void DoDispose (void); + private: - void SendRealOut (Packet const &packet, Ipv4Header const &ip, Ipv4Route const &route); + + void SendRealOut (bool found, + Ipv4Route const &route, + Packet packet, + Ipv4Header const &ipHeader); bool Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr device); void ForwardUp (Packet p, Ipv4Header const&ip); uint32_t AddIpv4Interface (Ipv4Interface *interface); @@ -155,26 +169,22 @@ private: TraceResolver *InterfacesCreateTraceResolver (TraceContext const &context) const; typedef std::list Ipv4InterfaceList; - typedef std::list HostRoutes; - typedef std::list::const_iterator HostRoutesCI; - typedef std::list::iterator HostRoutesI; - typedef std::list NetworkRoutes; - typedef std::list::const_iterator NetworkRoutesCI; - typedef std::list::iterator NetworkRoutesI; + typedef std::list< std::pair< int, Ptr > > Ipv4RoutingProtocolList; Ipv4InterfaceList m_interfaces; uint32_t m_nInterfaces; uint8_t m_defaultTtl; uint16_t m_identification; - HostRoutes m_hostRoutes; - NetworkRoutes m_networkRoutes; - Ipv4Route *m_defaultRoute; Ptr m_node; CallbackTraceSource m_txTrace; CallbackTraceSource m_rxTrace; CallbackTraceSource m_dropTrace; + + Ipv4RoutingProtocolList m_routingProtocols; + + Ptr m_staticRouting; }; } // Namespace ns3 -#endif /* IPV$_L3_PROTOCOL_H */ +#endif /* IPV4_L3_PROTOCOL_H */ diff --git a/src/internet-node/ipv4-static-routing.cc b/src/internet-node/ipv4-static-routing.cc new file mode 100644 index 000000000..b70c1c1af --- /dev/null +++ b/src/internet-node/ipv4-static-routing.cc @@ -0,0 +1,253 @@ +// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- +// +// Copyright (c) 2006 Georgia Tech Research Corporation +// All rights reserved. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Author: George F. Riley +// Gustavo Carneiro + +#include "ipv4-static-routing.h" +#include "ns3/packet.h" + + +namespace ns3 { + + +void +Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, + Ipv4Address nextHop, + uint32_t interface) +{ + Ipv4Route *route = new Ipv4Route (); + *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface); + m_hostRoutes.push_back (route); +} +void +Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, + uint32_t interface) +{ + Ipv4Route *route = new Ipv4Route (); + *route = Ipv4Route::CreateHostRouteTo (dest, interface); + m_hostRoutes.push_back (route); +} +void +Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address nextHop, + uint32_t interface) +{ + Ipv4Route *route = new Ipv4Route (); + *route = Ipv4Route::CreateNetworkRouteTo (network, + networkMask, + nextHop, + interface); + m_networkRoutes.push_back (route); +} +void +Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface) +{ + Ipv4Route *route = new Ipv4Route (); + *route = Ipv4Route::CreateNetworkRouteTo (network, + networkMask, + interface); + m_networkRoutes.push_back (route); +} +void +Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop, + uint32_t interface) +{ + Ipv4Route *route = new Ipv4Route (); + *route = Ipv4Route::CreateDefaultRoute (nextHop, interface); + delete m_defaultRoute; + m_defaultRoute = route; +} + +Ipv4Route * +Ipv4StaticRouting::LookupStatic (Ipv4Address dest) +{ + for (HostRoutesCI i = m_hostRoutes.begin (); + i != m_hostRoutes.end (); + i++) + { + NS_ASSERT ((*i)->IsHost ()); + if ((*i)->GetDest ().IsEqual (dest)) + { + return (*i); + } + } + for (NetworkRoutesI j = m_networkRoutes.begin (); + j != m_networkRoutes.end (); + j++) + { + NS_ASSERT ((*j)->IsNetwork ()); + Ipv4Mask mask = (*j)->GetDestNetworkMask (); + Ipv4Address entry = (*j)->GetDestNetwork (); + if (mask.IsMatch (dest, entry)) + { + return (*j); + } + } + if (m_defaultRoute != 0) + { + NS_ASSERT (m_defaultRoute->IsDefault ()); + return m_defaultRoute; + } + return 0; +} + +uint32_t +Ipv4StaticRouting::GetNRoutes (void) +{ + uint32_t n = 0; + if (m_defaultRoute != 0) + { + n++; + } + n += m_hostRoutes.size (); + n += m_networkRoutes.size (); + return n; +} +Ipv4Route * +Ipv4StaticRouting::GetRoute (uint32_t index) +{ + if (index == 0 && m_defaultRoute != 0) + { + return m_defaultRoute; + } + if (index > 0 && m_defaultRoute != 0) + { + index--; + } + if (index < m_hostRoutes.size ()) + { + uint32_t tmp = 0; + for (HostRoutesCI i = m_hostRoutes.begin (); + i != m_hostRoutes.end (); + i++) + { + if (tmp == index) + { + return *i; + } + tmp++; + } + } + index -= m_hostRoutes.size (); + uint32_t tmp = 0; + for (NetworkRoutesI j = m_networkRoutes.begin (); + j != m_networkRoutes.end (); + j++) + { + if (tmp == index) + { + return *j; + } + tmp++; + } + NS_ASSERT (false); + // quiet compiler. + return 0; +} +void +Ipv4StaticRouting::RemoveRoute (uint32_t index) +{ + if (index == 0 && m_defaultRoute != 0) + { + delete m_defaultRoute; + m_defaultRoute = 0; + } + if (index > 0 && m_defaultRoute != 0) + { + index--; + } + if (index < m_hostRoutes.size ()) + { + uint32_t tmp = 0; + for (HostRoutesI i = m_hostRoutes.begin (); + i != m_hostRoutes.end (); + i++) + { + if (tmp == index) + { + delete *i; + m_hostRoutes.erase (i); + return; + } + tmp++; + } + } + index -= m_hostRoutes.size (); + uint32_t tmp = 0; + for (NetworkRoutesI j = m_networkRoutes.begin (); + j != m_networkRoutes.end (); + j++) + { + if (tmp == index) + { + delete *j; + m_networkRoutes.erase (j); + return; + } + tmp++; + } + NS_ASSERT (false); +} + +bool +Ipv4StaticRouting::RequestRoute (Ipv4Header const &ipHeader, + Packet packet, + RouteReplyCallback routeReply) +{ + Ipv4Route *route = LookupStatic (ipHeader.GetDestination ()); + if (route != 0) + { + routeReply (true, *route, packet, ipHeader); + return true; + } + else + { + return false; // Let other routing protocols try to handle this + // route request. + } +} + +void +Ipv4StaticRouting::DoDispose (void) +{ + for (HostRoutesI i = m_hostRoutes.begin (); + i != m_hostRoutes.end (); + i = m_hostRoutes.erase (i)) + { + delete (*i); + } + for (NetworkRoutesI j = m_networkRoutes.begin (); + j != m_networkRoutes.end (); + j = m_networkRoutes.erase (j)) + { + delete (*j); + } + if (m_defaultRoute != 0) + { + delete m_defaultRoute; + m_defaultRoute = 0; + } + Ipv4RoutingProtocol::DoDispose (); +} + + +}//namespace ns3 diff --git a/src/internet-node/ipv4-static-routing.h b/src/internet-node/ipv4-static-routing.h new file mode 100644 index 000000000..f7e6d52ab --- /dev/null +++ b/src/internet-node/ipv4-static-routing.h @@ -0,0 +1,101 @@ +// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- +// +// Copyright (c) 2006 Georgia Tech Research Corporation +// All rights reserved. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Author: George F. Riley +// Gustavo Carneiro +// + +#ifndef IPV4_STATIC_ROUTING_H +#define IPV4_STATIC_ROUTING_H + +#include +#include +#include "ns3/callback-trace-source.h" +#include "ns3/array-trace-resolver.h" +#include "ns3/ipv4-address.h" +#include "ipv4-header.h" +#include "ns3/ptr.h" +#include "ns3/ipv4.h" +#include "l3-protocol.h" + +namespace ns3 { + +class Packet; +class NetDevice; +class Ipv4Interface; +class Ipv4Address; +class Ipv4Header; +class Ipv4Route; +class Node; +class TraceResolver; +class TraceContext; + + +class Ipv4StaticRouting : public Ipv4RoutingProtocol +{ + +public: + Ipv4StaticRouting () : m_defaultRoute (0) {} + + virtual bool RequestRoute (Ipv4Header const &ipHeader, + Packet packet, + RouteReplyCallback routeReply); + + + void AddHostRouteTo (Ipv4Address dest, + Ipv4Address nextHop, + uint32_t interface); + void AddHostRouteTo (Ipv4Address dest, + uint32_t interface); + + void AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address nextHop, + uint32_t interface); + void AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface); + void SetDefaultRoute (Ipv4Address nextHop, + uint32_t interface); + uint32_t GetNRoutes (void); + Ipv4Route *GetRoute (uint32_t i); + void RemoveRoute (uint32_t i); + +protected: + void DoDispose (void); + +private: + typedef std::list HostRoutes; + typedef std::list::const_iterator HostRoutesCI; + typedef std::list::iterator HostRoutesI; + typedef std::list NetworkRoutes; + typedef std::list::const_iterator NetworkRoutesCI; + typedef std::list::iterator NetworkRoutesI; + + Ipv4Route *LookupStatic (Ipv4Address dest); + + HostRoutes m_hostRoutes; + NetworkRoutes m_networkRoutes; + Ipv4Route *m_defaultRoute; +}; + + + +} // Namespace ns3 + +#endif /* IPV4_STATIC_ROUTING_H */ diff --git a/src/internet-node/wscript b/src/internet-node/wscript index 47b81358b..e1c452157 100644 --- a/src/internet-node/wscript +++ b/src/internet-node/wscript @@ -17,6 +17,7 @@ def build(bld): 'ipv4-checksum.cc', 'ipv4-interface.cc', 'ipv4-l3-protocol.cc', + 'ipv4-static-routing.cc', 'ipv4-end-point.cc', 'udp-l4-protocol.cc', 'arp-header.cc', @@ -40,4 +41,5 @@ def build(bld): 'internet-node.h', 'ascii-trace.h', 'pcap-trace.h', + 'ipv4-header.h', ] diff --git a/src/node/ipv4.h b/src/node/ipv4.h index 1424884af..1a957a4ee 100644 --- a/src/node/ipv4.h +++ b/src/node/ipv4.h @@ -24,6 +24,7 @@ #include #include "ns3/ipv4-address.h" #include "ns3/object.h" +#include "ns3/callback.h" #include "ipv4-route.h" namespace ns3 { @@ -31,6 +32,30 @@ namespace ns3 { class NetDevice; class Packet; class Ipv4Route; +class Ipv4Header; // FIXME: ipv4-header.h needs to move from module + // "internet-node" to module "node" + +class Ipv4RoutingProtocol : public Object +{ +public: + // void (*RouteReply) (bool found, Ipv4Route route, Packet packet, Ipv4Header const &ipHeader); + typedef Callback RouteReplyCallback; + + /** + * \brief Asynchronously requests a route for a given packet and IP header + * + * \param ipHeader IP header of the packet + * \param packet packet that is being sent or forwarded + * \param routeReply callback that will receive the route reply + * + * \returns true if the routing protocol should be able to get the + * route, false otherwise. + */ + virtual bool RequestRoute (Ipv4Header const &ipHeader, + Packet packet, + RouteReplyCallback routeReply) = 0; +}; + /** * \brief Access to the Ipv4 forwarding table and to the ipv4 interfaces * @@ -47,7 +72,10 @@ public: static const InterfaceId iid; Ipv4 (); virtual ~Ipv4 (); - + + virtual void AddRoutingProtocol (Ptr routingProtocol, + int priority) = 0; + /** * \param dest destination address * \param nextHop address of next hop. From 317f336c76d8d45f84145ad89a08aee113535437 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 26 Jul 2007 12:27:49 +0100 Subject: [PATCH 12/29] Allow UDP sockets to receive broadcast (bug #51) --- src/internet-node/ipv4-end-point-demux.cc | 66 ++++++++++++++++------- src/internet-node/ipv4-end-point-demux.h | 13 ++--- src/internet-node/udp-l4-protocol.cc | 11 ++-- 3 files changed, 61 insertions(+), 29 deletions(-) diff --git a/src/internet-node/ipv4-end-point-demux.cc b/src/internet-node/ipv4-end-point-demux.cc index 47240c7eb..6d310e133 100644 --- a/src/internet-node/ipv4-end-point-demux.cc +++ b/src/internet-node/ipv4-end-point-demux.cc @@ -21,9 +21,12 @@ #include "ipv4-end-point-demux.h" #include "ipv4-end-point.h" +#include "ns3/debug.h" namespace ns3{ +NS_DEBUG_COMPONENT_DEFINE ("Ipv4EndPointDemux"); + Ipv4EndPointDemux::Ipv4EndPointDemux () : m_ephemeral (1025) {} @@ -68,9 +71,11 @@ Ipv4EndPointDemux::LookupLocal (Ipv4Address addr, uint16_t port) Ipv4EndPoint * Ipv4EndPointDemux::Allocate (void) { + NS_DEBUG ("Ipv4EndPointDemux::Allocate ()"); uint16_t port = AllocateEphemeralPort (); if (port == 0) { + NS_DEBUG ("Ipv4EndPointDemux::Allocate ephemeral port allocation failed."); return 0; } Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port); @@ -80,9 +85,11 @@ Ipv4EndPointDemux::Allocate (void) Ipv4EndPoint * Ipv4EndPointDemux::Allocate (Ipv4Address address) { + NS_DEBUG ("Ipv4EndPointDemux::Allocate (address=" << address << ")"); uint16_t port = AllocateEphemeralPort (); if (port == 0) { + NS_DEBUG ("Ipv4EndPointDemux::Allocate ephemeral port allocation failed."); return 0; } Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port); @@ -97,8 +104,11 @@ Ipv4EndPointDemux::Allocate (uint16_t port) Ipv4EndPoint * Ipv4EndPointDemux::Allocate (Ipv4Address address, uint16_t port) { + NS_DEBUG ("Ipv4EndPointDemux::Allocate (address=" << address + << ", port=" << port << ")"); if (LookupLocal (address, port)) { + NS_DEBUG ("Ipv4EndPointDemux::Allocate duplicate address/port; failing."); return 0; } Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port); @@ -110,6 +120,10 @@ Ipv4EndPoint * Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort, Ipv4Address peerAddress, uint16_t peerPort) { + NS_DEBUG ("Ipv4EndPointDemux::Allocate (localAddress=" << localAddress + << ", localPort=" << localPort + << ", peerAddress=" << peerAddress + << ", peerPort=" << peerPort << ")"); for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) { if ((*i)->GetLocalPort () == localPort && @@ -117,6 +131,7 @@ Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort, (*i)->GetPeerPort () == peerPort && (*i)->GetPeerAddress () == peerAddress) { + NS_DEBUG ("Ipv4EndPointDemux::Allocate: no way we can allocate this end-point."); /* no way we can allocate this end-point. */ return 0; } @@ -147,35 +162,46 @@ Ipv4EndPointDemux::DeAllocate (Ipv4EndPoint *endPoint) * Otherwise, if we find a generic match, we return it. * Otherwise, we return 0. */ -Ipv4EndPoint * +Ipv4EndPointDemux::EndPoints Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport, - Ipv4Address saddr, uint16_t sport) + Ipv4Address saddr, uint16_t sport) { uint32_t genericity = 3; Ipv4EndPoint *generic = 0; - //TRACE ("lookup " << daddr << ":" << dport << " " << saddr << ":" << sport); + EndPoints retval; + + NS_DEBUG ("Ipv4EndPointDemux::Lookup (daddr=" << daddr << ", dport=" << dport + << ", saddr=" << saddr << ", sport=" << sport + << ")"); for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) { -#if 0 - TRACE ("against " << - (*i)->GetLocalAddress () - << ":" << - (*i)->GetLocalPort () - << " " << - (*i)->GetPeerAddress () - << ":" - << (*i)->GetPeerPort ()); -#endif + NS_DEBUG ("Ipv4EndPointDemux::Lookup against " << + (*i)->GetLocalAddress () + << ":" << + (*i)->GetLocalPort () + << " " << + (*i)->GetPeerAddress () + << ":" + << (*i)->GetPeerPort ()); if ((*i)->GetLocalPort () != dport) { continue; } - if ((*i)->GetLocalAddress () == daddr && - (*i)->GetPeerPort () == sport && - (*i)->GetPeerAddress () == saddr) + NS_DEBUG ("Ipv4EndPointDemux::Lookup local address matches: " + << bool ((*i)->GetLocalAddress () == daddr || daddr.IsBroadcast ())); + NS_DEBUG ("Ipv4EndPointDemux::Lookup peer port matches: " + << bool ((*i)->GetPeerPort () == sport || sport == 0)); + NS_DEBUG ("Ipv4EndPointDemux::Lookup peer address matches: " + << bool ((*i)->GetPeerAddress () == saddr || + (*i)->GetPeerAddress () == Ipv4Address::GetAny ())); + + if ( ((*i)->GetLocalAddress () == daddr || daddr.IsBroadcast ()) + && ((*i)->GetPeerPort () == sport || (*i)->GetPeerPort () == 0) + && ((*i)->GetPeerAddress () == saddr || (*i)->GetPeerAddress () == Ipv4Address::GetAny ())) { + NS_DEBUG ("Ipv4EndPointDemux::Lookup MATCH"); /* this is an exact match. */ - return *i; + retval.push_back (*i); } uint32_t tmp = 0; if ((*i)->GetLocalAddress () == Ipv4Address::GetAny ()) @@ -192,7 +218,11 @@ Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport, genericity = tmp; } } - return generic; + if (retval.size () == 0 && generic != 0) + { + retval.push_back (generic); + } + return retval; } uint16_t diff --git a/src/internet-node/ipv4-end-point-demux.h b/src/internet-node/ipv4-end-point-demux.h index 7de2c17d1..e45a6267b 100644 --- a/src/internet-node/ipv4-end-point-demux.h +++ b/src/internet-node/ipv4-end-point-demux.h @@ -32,15 +32,18 @@ class Ipv4EndPoint; class Ipv4EndPointDemux { public: + typedef std::list EndPoints; + typedef std::list::iterator EndPointsI; + Ipv4EndPointDemux (); ~Ipv4EndPointDemux (); bool LookupPortLocal (uint16_t port); bool LookupLocal (Ipv4Address addr, uint16_t port); - Ipv4EndPoint *Lookup (Ipv4Address daddr, - uint16_t dport, - Ipv4Address saddr, - uint16_t sport); + EndPoints Lookup (Ipv4Address daddr, + uint16_t dport, + Ipv4Address saddr, + uint16_t sport); Ipv4EndPoint *Allocate (void); Ipv4EndPoint *Allocate (Ipv4Address address); @@ -55,8 +58,6 @@ public: private: uint16_t AllocateEphemeralPort (void); - typedef std::list EndPoints; - typedef std::list::iterator EndPointsI; uint16_t m_ephemeral; EndPoints m_endPoints; diff --git a/src/internet-node/udp-l4-protocol.cc b/src/internet-node/udp-l4-protocol.cc index d873ef582..90fb782b9 100644 --- a/src/internet-node/udp-l4-protocol.cc +++ b/src/internet-node/udp-l4-protocol.cc @@ -113,13 +113,14 @@ UdpL4Protocol::Receive(Packet& packet, { UdpHeader udpHeader; packet.RemoveHeader (udpHeader); - Ipv4EndPoint *endPoint = m_endPoints->Lookup (destination, udpHeader.GetDestination (), - source, udpHeader.GetSource ()); - if (endPoint == 0) + Ipv4EndPointDemux::EndPoints endPoints = + m_endPoints->Lookup (destination, udpHeader.GetDestination (), + source, udpHeader.GetSource ()); + for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin (); + endPoint != endPoints.end (); endPoint++) { - return; + (*endPoint)->ForwardUp (packet, source, udpHeader.GetSource ()); } - endPoint->ForwardUp (packet, source, udpHeader.GetSource ()); } void From 6b29b3c817eb3632c97d9bbd6329cde9eca580a6 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Fri, 27 Jul 2007 15:38:04 +0100 Subject: [PATCH 13/29] Add documentation for the dynamic routing interfaces. Change Ipv4::AddRoutingProtocol priority parameter type from int to int16_t to make way for in the future providing stable sorting of routing protocols of the same priority. --- src/internet-node/ipv4-impl.cc | 2 +- src/internet-node/ipv4-impl.h | 2 +- src/node/ipv4.h | 66 +++++++++++++++++++++++++++++++--- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/internet-node/ipv4-impl.cc b/src/internet-node/ipv4-impl.cc index 020413896..307425114 100644 --- a/src/internet-node/ipv4-impl.cc +++ b/src/internet-node/ipv4-impl.cc @@ -41,7 +41,7 @@ Ipv4Impl::DoDispose (void) void Ipv4Impl::AddRoutingProtocol (Ptr routingProtocol, - int priority) + int16_t priority) { m_ipv4->AddRoutingProtocol (routingProtocol, priority); } diff --git a/src/internet-node/ipv4-impl.h b/src/internet-node/ipv4-impl.h index 32d9e5c68..445c10454 100644 --- a/src/internet-node/ipv4-impl.h +++ b/src/internet-node/ipv4-impl.h @@ -36,7 +36,7 @@ public: virtual ~Ipv4Impl (); virtual void AddRoutingProtocol (Ptr routingProtocol, - int priority); + int16_t priority); virtual void AddHostRouteTo (Ipv4Address dest, Ipv4Address nextHop, diff --git a/src/node/ipv4.h b/src/node/ipv4.h index 1a957a4ee..76d88faea 100644 --- a/src/node/ipv4.h +++ b/src/node/ipv4.h @@ -35,14 +35,40 @@ class Ipv4Route; class Ipv4Header; // FIXME: ipv4-header.h needs to move from module // "internet-node" to module "node" +/** + * \brief Base class for IPv4 routing protocols. + * + * This class represents the interface between the IPv4 routing core + * and a specific IPv4 routing protocol. The interface is + * asynchronous (callback based) in order to support reactive routing + * protocols (e.g. AODV). + */ class Ipv4RoutingProtocol : public Object { public: // void (*RouteReply) (bool found, Ipv4Route route, Packet packet, Ipv4Header const &ipHeader); - typedef Callback RouteReplyCallback; + /** - * \brief Asynchronously requests a route for a given packet and IP header + * \brief Callback to be invoked when route discovery is completed + * + * \param bool flag indicating whether a route was actually found; + * when this is false, the Ipv4Route parameter is ignored + * + * \param Ipv4Route the route found + * + * \param Packet the packet for which a route was requested; can be + * modified by the routing protocol + * + * \param Ipv4Header the IP header supplied to the route request + * method (possibly modified in case a new routing header is + * inserted and consequently the protocol type has to change). + * + */ + typedef Callback RouteReplyCallback; + + /** + * \brief Asynchronously requests a route for a given packet and IP header * * \param ipHeader IP header of the packet * \param packet packet that is being sent or forwarded @@ -50,8 +76,30 @@ public: * * \returns true if the routing protocol should be able to get the * route, false otherwise. + * + * This method is called whenever a node's IPv4 forwarding engine + * needs to lookup a route for a given packet and IP header. + * + * The routing protocol implementation may determine immediately it + * should not be handling this particular the route request. For + * instance, a routing protocol may decline to search for routes for + * certain classes of addresses, like link-local. In this case, + * RequestRoute() should return false and the routeReply callback + * must not be invoked. + * + * If the routing protocol implementations assumes it can provide + * the requested route, then it should return true, and the + * routeReply callback must be invoked, either immediately before + * returning true (synchronously), or in the future (asynchronous). + * The routing protocol may use any information available in the IP + * header and packet as routing key, although most routing protocols + * use only the destination address (as given by + * ipHeader.GetDestination ()). The routing protocol is also + * allowed to add a new header to the packet, which will appear + * immediately after the IP header, although most routing do not + * insert any extra header. */ - virtual bool RequestRoute (Ipv4Header const &ipHeader, + virtual bool RequestRoute (const Ipv4Header &ipHeader, Packet packet, RouteReplyCallback routeReply) = 0; }; @@ -73,8 +121,18 @@ public: Ipv4 (); virtual ~Ipv4 (); + /** + * \brief Register a new routing protocol to be used in this IPv4 stack + * + * \param routingProtocol new routing protocol implementation object + * \param priority priority to give to this routing protocol. + * Values may range between -32768 and +32767. The priority 0 + * corresponds to static routing table lookups, higher values have + * more priority. The order by which routing protocols with the + * same priority value are consulted is undefined. + */ virtual void AddRoutingProtocol (Ptr routingProtocol, - int priority) = 0; + int16_t priority) = 0; /** * \param dest destination address From f35ff8f583c0e118f74a308e7695bb9c63235497 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 26 Jul 2007 12:11:37 +0100 Subject: [PATCH 14/29] Add Ipv4Address::CombineMask, and implement Ipv4Address::IsBroadcast. --- src/node/ipv4-address.cc | 8 +++++++- src/node/ipv4-address.h | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/node/ipv4-address.cc b/src/node/ipv4-address.cc index 8960293ee..c716930fd 100644 --- a/src/node/ipv4-address.cc +++ b/src/node/ipv4-address.cc @@ -151,8 +151,14 @@ Ipv4Address::CombineMask (Ipv4Mask const &mask) const return Ipv4Address (GetHostOrder () & mask.GetHostOrder ()); } +bool +Ipv4Address::IsBroadcast (void) const +{ + return (m_address == 0xffffffffU); +} + bool -Ipv4Address::IsMulticast (void) +Ipv4Address::IsMulticast (void) const { // XXX return false; diff --git a/src/node/ipv4-address.h b/src/node/ipv4-address.h index 37b1e23cd..cddfc176c 100644 --- a/src/node/ipv4-address.h +++ b/src/node/ipv4-address.h @@ -82,8 +82,8 @@ public: */ void Print (std::ostream &os) const; - bool IsBroadcast (void); - bool IsMulticast (void); + bool IsBroadcast (void) const; + bool IsMulticast (void) const; /** * \brief Combine this address with a network mask * From 5e4dbc66dcdf311b944b2c0f1d4301a7aaf1dd95 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 27 Jul 2007 12:50:31 -0700 Subject: [PATCH 15/29] new script for csma-cd --- .../{simple-csma-cd.cc => csma-cd-one-subnet.cc} | 16 ++++++---------- examples/wscript | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) rename examples/{simple-csma-cd.cc => csma-cd-one-subnet.cc} (94%) diff --git a/examples/simple-csma-cd.cc b/examples/csma-cd-one-subnet.cc similarity index 94% rename from examples/simple-csma-cd.cc rename to examples/csma-cd-one-subnet.cc index d24f7c54b..306e98677 100644 --- a/examples/simple-csma-cd.cc +++ b/examples/csma-cd-one-subnet.cc @@ -18,19 +18,15 @@ // // Network topology // -// n0 -// | -// | -// n2---+----n3 -// | -// | -// n1 +// n0 n1 n2 n3 +// | | | | +// ===================== // // - CBR/UDP flows from n0 to n1, and from n3 to n0 // - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec. // (i.e., DataRate of 448,000 bps) // - DropTail queues -// - Tracing of queues and packet receptions to file "simple-csma-cd.tr" +// - Tracing of queues and packet receptions to file "csma-cd-one-subnet.tr" #include #include @@ -157,8 +153,8 @@ int main (int argc, char *argv[]) ooff->Stop (Seconds(10.0)); // Configure tracing of all enqueue, dequeue, and NetDevice receive events - // Trace output will be sent to the simple-p2p.tr file - AsciiTrace asciitrace ("simple-csma-cd.tr"); + // Trace output will be sent to the csma-cd-one-subnet.tr file + AsciiTrace asciitrace ("csma-cd-one-subnet.tr"); asciitrace.TraceAllNetDeviceRx (); // asciitrace.TraceAllQueues (); diff --git a/examples/wscript b/examples/wscript index dcdf4ef67..55ece2369 100644 --- a/examples/wscript +++ b/examples/wscript @@ -10,5 +10,5 @@ def build(bld): return obj obj = create_ns_prog('simple-p2p', 'simple-p2p.cc', deps=['point-to-point', 'internet-node']) - obj = create_ns_prog('simple-csma-cd', 'simple-csma-cd.cc', deps=['csma-cd', 'internet-node']) + obj = create_ns_prog('csma-cd-one-subnet', 'csma-cd-one-subnet.cc', deps=['csma-cd', 'internet-node']) From a9fe0f2d23e137fa1c4b9d703dea47ffcbea0251 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 27 Jul 2007 13:07:36 -0700 Subject: [PATCH 16/29] rename example from p2p to point-to-point --- .../{simple-p2p.cc => simple-point-to-point.cc} | 14 ++++++++------ examples/wscript | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) rename examples/{simple-p2p.cc => simple-point-to-point.cc} (93%) diff --git a/examples/simple-p2p.cc b/examples/simple-point-to-point.cc similarity index 93% rename from examples/simple-p2p.cc rename to examples/simple-point-to-point.cc index 412edcaa1..cf3091a7b 100644 --- a/examples/simple-p2p.cc +++ b/examples/simple-point-to-point.cc @@ -29,13 +29,14 @@ // / 5 Mb/s, 2ms // n1 // -// - all links are p2p links with indicated one-way BW/delay +// - all links are point-to-point links with indicated one-way BW/delay // - CBR/UDP flows from n0 to n3, and from n3 to n1 // - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec. // - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec. // (i.e., DataRate of 448,000 bps) // - DropTail queues -// - Tracing of queues and packet receptions to file "simple-p2p.tr" +// - Tracing of queues and packet receptions to file +// "simple-point-to-point.tr" #include #include @@ -173,16 +174,17 @@ int main (int argc, char *argv[]) ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1); // Configure tracing of all enqueue, dequeue, and NetDevice receive events - // Trace output will be sent to the simple-p2p.tr file - AsciiTrace asciitrace ("simple-p2p.tr"); + // Trace output will be sent to the simple-point-to-point.tr file + AsciiTrace asciitrace ("simple-point-to-point.tr"); asciitrace.TraceAllQueues (); asciitrace.TraceAllNetDeviceRx (); // Also configure some tcpdump traces; each interface will be traced - // The output files will be named simple-p2p.pcap-- + // The output files will be named + // simple-point-to-point.pcap-- // and can be read by the "tcpdump -r" command (use "-tt" option to // display timestamps correctly) - PcapTrace pcaptrace ("simple-p2p.pcap"); + PcapTrace pcaptrace ("simple-point-to-point.pcap"); pcaptrace.TraceAllIp (); Simulator::Run (); diff --git a/examples/wscript b/examples/wscript index 55ece2369..e1b960ddc 100644 --- a/examples/wscript +++ b/examples/wscript @@ -9,6 +9,6 @@ def build(bld): obj.source = source return obj - obj = create_ns_prog('simple-p2p', 'simple-p2p.cc', deps=['point-to-point', 'internet-node']) + obj = create_ns_prog('simple-point-to-point', 'simple-point-to-point.cc', deps=['point-to-point', 'internet-node']) obj = create_ns_prog('csma-cd-one-subnet', 'csma-cd-one-subnet.cc', deps=['csma-cd', 'internet-node']) From 9f8910c2584f84593377e4cdb70c733a1aeb1c54 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 27 Jul 2007 14:40:50 -0700 Subject: [PATCH 17/29] return ifIndex when adding netdevice to node (topology) --- src/devices/csma-cd/csma-cd-ipv4-topology.cc | 14 ++++---------- src/devices/csma-cd/csma-cd-ipv4-topology.h | 4 +++- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/devices/csma-cd/csma-cd-ipv4-topology.cc b/src/devices/csma-cd/csma-cd-ipv4-topology.cc index 64ddc036c..be04cc8d4 100644 --- a/src/devices/csma-cd/csma-cd-ipv4-topology.cc +++ b/src/devices/csma-cd/csma-cd-ipv4-topology.cc @@ -35,26 +35,20 @@ namespace ns3 { -void +uint32_t CsmaCdIpv4Topology::AddIpv4CsmaCdNode(Ptr n1, Ptr ch, MacAddress addr) { Ptr q = Queue::CreateDefault (); - // Use the first net device in the node to transmit + // assume full-duplex Ptr nd0 = Create (n1, addr, ns3::CsmaCdNetDevice::IP_ARP, - true, false); + true, true); nd0->AddQueue(q); nd0->Attach (ch); - - // Use the second net device in the node to transmit - Ptr nd1 = Create (n1, addr, - ns3::CsmaCdNetDevice::IP_ARP, - false, true); - nd1->AddQueue(q); - nd1->Attach (ch); + return nd0->GetIfIndex (); } diff --git a/src/devices/csma-cd/csma-cd-ipv4-topology.h b/src/devices/csma-cd/csma-cd-ipv4-topology.h index fe821cee6..d31ee4184 100644 --- a/src/devices/csma-cd/csma-cd-ipv4-topology.h +++ b/src/devices/csma-cd/csma-cd-ipv4-topology.h @@ -58,8 +58,10 @@ public: * connect to a CsmaCdChannel. This means that Ethernet headers * and trailers will be added to the packet before sending out on * the net device. + * + * \return ifIndex of the device */ - static void AddIpv4CsmaCdNode( Ptr n1, + static uint32_t AddIpv4CsmaCdNode( Ptr n1, Ptr ch, MacAddress addr); From 45773a987db111f680602bb27522a0d062be8922 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 27 Jul 2007 14:43:56 -0700 Subject: [PATCH 18/29] disable tracing; fix ifIndex assignment --- examples/csma-cd-one-subnet.cc | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/csma-cd-one-subnet.cc b/examples/csma-cd-one-subnet.cc index 306e98677..aaa83cde4 100644 --- a/examples/csma-cd-one-subnet.cc +++ b/examples/csma-cd-one-subnet.cc @@ -71,11 +71,12 @@ 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 + DebugComponentEnable("CsmaCdNetDevice"); + DebugComponentEnable("Ipv4L3Protocol"); + DebugComponentEnable("NetDevice"); #if 0 DebugComponentEnable("Channel"); DebugComponentEnable("CsmaCdChannel"); - DebugComponentEnable("CsmaCdNetDevice"); - DebugComponentEnable("NetDevice"); DebugComponentEnable("PacketSocket"); #endif @@ -103,27 +104,27 @@ int main (int argc, char *argv[]) CsmaCdTopology::CreateCsmaCdChannel( DataRate(5000000), MilliSeconds(2)); - CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n0, channel0, + uint32_t n0ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n0, channel0, MacAddress("10:54:23:54:23:50")); - CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n1, channel0, + uint32_t n1ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n1, channel0, MacAddress("10:54:23:54:23:51")); - CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n2, channel0, + uint32_t n2ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n2, channel0, MacAddress("10:54:23:54:23:52")); - CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n3, channel0, + uint32_t n3ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n3, channel0, MacAddress("10:54:23:54:23:53")); // Later, we add IP addresses. CsmaCdIpv4Topology::AddIpv4Address ( - n0, 1, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); + n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); CsmaCdIpv4Topology::AddIpv4Address ( - n1, 1, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); + n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); CsmaCdIpv4Topology::AddIpv4Address ( - n2, 1, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0")); + n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0")); CsmaCdIpv4Topology::AddIpv4Address ( - n3, 1, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0")); + n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0")); // Create the OnOff application to send UDP datagrams of size @@ -154,8 +155,8 @@ int main (int argc, char *argv[]) // Configure tracing of all enqueue, dequeue, and NetDevice receive events // Trace output will be sent to the csma-cd-one-subnet.tr file - AsciiTrace asciitrace ("csma-cd-one-subnet.tr"); - asciitrace.TraceAllNetDeviceRx (); + // AsciiTrace asciitrace ("csma-cd-one-subnet.tr"); +// asciitrace.TraceAllNetDeviceRx (); // asciitrace.TraceAllQueues (); Simulator::Run (); From e7f300bc7cfe7c33858c32a5475067df415cefe8 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 27 Jul 2007 14:54:41 -0700 Subject: [PATCH 19/29] fix tracing --- examples/csma-cd-one-subnet.cc | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/examples/csma-cd-one-subnet.cc b/examples/csma-cd-one-subnet.cc index aaa83cde4..caff83dcf 100644 --- a/examples/csma-cd-one-subnet.cc +++ b/examples/csma-cd-one-subnet.cc @@ -71,10 +71,10 @@ int main (int argc, char *argv[]) // Users may find it convenient to turn on explicit debugging // for selected modules; the below lines suggest how to do this +#if 0 DebugComponentEnable("CsmaCdNetDevice"); DebugComponentEnable("Ipv4L3Protocol"); DebugComponentEnable("NetDevice"); -#if 0 DebugComponentEnable("Channel"); DebugComponentEnable("CsmaCdChannel"); DebugComponentEnable("PacketSocket"); @@ -126,7 +126,6 @@ int main (int argc, char *argv[]) CsmaCdIpv4Topology::AddIpv4Address ( n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0")); - // Create the OnOff application to send UDP datagrams of size // 210 bytes at a rate of 448 Kb/s // from n0 to n1 @@ -155,9 +154,17 @@ int main (int argc, char *argv[]) // Configure tracing of all enqueue, dequeue, and NetDevice receive events // Trace output will be sent to the csma-cd-one-subnet.tr file - // AsciiTrace asciitrace ("csma-cd-one-subnet.tr"); -// asciitrace.TraceAllNetDeviceRx (); - // asciitrace.TraceAllQueues (); + AsciiTrace asciitrace ("csma-cd-one-subnet.tr"); + asciitrace.TraceAllNetDeviceRx (); + asciitrace.TraceAllQueues (); + + // Also configure some tcpdump traces; each interface will be traced + // The output files will be named + // simple-point-to-point.pcap-- + // and can be read by the "tcpdump -r" command (use "-tt" option to + // display timestamps correctly) + PcapTrace pcaptrace ("csma-cd-one-subnet.pcap"); + pcaptrace.TraceAllIp (); Simulator::Run (); From b4ebd87229de54c4cbf14f0eb0b25f3c10f36f12 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sat, 28 Jul 2007 12:30:31 +0200 Subject: [PATCH 20/29] disable copy constructor and operator = for CsmaCdNetDevice --- src/devices/csma-cd/csma-cd-net-device.cc | 37 ----------------------- src/devices/csma-cd/csma-cd-net-device.h | 21 ++----------- 2 files changed, 3 insertions(+), 55 deletions(-) diff --git a/src/devices/csma-cd/csma-cd-net-device.cc b/src/devices/csma-cd/csma-cd-net-device.cc index 61b162420..b3fae0e2b 100644 --- a/src/devices/csma-cd/csma-cd-net-device.cc +++ b/src/devices/csma-cd/csma-cd-net-device.cc @@ -62,43 +62,6 @@ CsmaCdNetDevice::~CsmaCdNetDevice() m_queue = 0; } -// -// Copy constructor for CsmaCdNetDevice. -// -// We use the underlying NetDevice copy constructor to get the base class -// copied. These just remain as is (e.g. you get the same name, the same -// MAC address). If you need to fix them up, YOU, the copier need to do -// that. -// -// The things we need to be careful of are the channel, the queue and the -// trace callback. If the channel pointer is non-zero, we copy the pointer -// and add a reference. If the queue is non-zero, we copy it using the queue -// assignment operator. We don't mess with the trace -- we just reset it. -// We're assuming that the tracing will be set up after the topology creation -// phase and this won't actually matter. -// - -CsmaCdNetDevice::CsmaCdNetDevice (const CsmaCdNetDevice& nd) - : NetDevice(nd), m_bps (nd.m_bps) -{ - NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << &nd << ")"); - - m_txMachineState = READY; - m_tInterframeGap = nd.m_tInterframeGap; - m_backoff = nd.m_backoff; - m_channel = nd.m_channel; - m_queue = 0; - m_pktType = nd.m_pktType; - m_sendEnable = nd.m_sendEnable; - m_receiveEnable = nd.m_receiveEnable; - - if (nd.m_queue) - { - m_queue = nd.m_queue; - } - -} - void CsmaCdNetDevice::DoDispose () { diff --git a/src/devices/csma-cd/csma-cd-net-device.h b/src/devices/csma-cd/csma-cd-net-device.h index d2972feb2..0b2af252e 100644 --- a/src/devices/csma-cd/csma-cd-net-device.h +++ b/src/devices/csma-cd/csma-cd-net-device.h @@ -96,30 +96,12 @@ enum CsmaCdEncapsulationMode { CsmaCdNetDevice (Ptr node, MacAddress addr, CsmaCdEncapsulationMode pktType, bool sendEnable, bool receiveEnable); - /** - * Copy Construct a CsmaCdNetDevice - * - * This is the copy constructor for the CsmaCdNetDevice. This is - * primarily used in topology creation. - * - * \param nd the object to be copied - */ - CsmaCdNetDevice (const CsmaCdNetDevice& nd); /** * Destroy a CsmaCdNetDevice * * This is the destructor for the CsmaCdNetDevice. */ virtual ~CsmaCdNetDevice(); - /** - * Assignment Operator for a CsmaCdNetDevice - * - * This is the assignment operator for the CsmaCdNetDevice. This is - * to allow - * - * \param nd the object to be copied - */ - // CsmaCdNetDevice& operator= (CsmaCdNetDevice nd); /** * Set the Data Rate used for transmission of packets. The data rate is * set in the Attach () method from the corresponding field in the channel @@ -243,6 +225,9 @@ protected: bool ProcessHeader (Packet& p, int& param); private: + // disable copy constructor and operator = + CsmaCdNetDevice &operator = (const CsmaCdNetDevice &o); + CsmaCdNetDevice (const CsmaCdNetDevice &o); /** * Initializes variablea when construction object. */ From 4c5fe41f2b6a75f9b892ed7036f7a8648b523a07 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sat, 28 Jul 2007 12:41:53 +0200 Subject: [PATCH 21/29] pktType -> encapMode --- src/devices/csma-cd/csma-cd-net-device.cc | 20 ++++++++++---------- src/devices/csma-cd/csma-cd-net-device.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/devices/csma-cd/csma-cd-net-device.cc b/src/devices/csma-cd/csma-cd-net-device.cc index b3fae0e2b..90bd5397d 100644 --- a/src/devices/csma-cd/csma-cd-net-device.cc +++ b/src/devices/csma-cd/csma-cd-net-device.cc @@ -36,22 +36,22 @@ NS_DEBUG_COMPONENT_DEFINE ("CsmaCdNetDevice"); namespace ns3 { CsmaCdNetDevice::CsmaCdNetDevice (Ptr node, MacAddress addr, - CsmaCdEncapsulationMode pktType) + CsmaCdEncapsulationMode encapMode) : NetDevice(node, addr), m_bps (DataRate (0xffffffff)) { NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")"); - m_pktType = pktType; + m_encapMode = encapMode; Init(true, true); } CsmaCdNetDevice::CsmaCdNetDevice (Ptr node, MacAddress addr, - CsmaCdEncapsulationMode pktType, + CsmaCdEncapsulationMode encapMode, bool sendEnable, bool receiveEnable) : NetDevice(node, addr), m_bps (DataRate (0xffffffff)) { NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")"); - m_pktType = pktType; + m_encapMode = encapMode; Init(sendEnable, receiveEnable); } @@ -152,14 +152,14 @@ void CsmaCdNetDevice::AddHeader (Packet& p, const MacAddress& dest, uint16_t protocolNumber) { - if ((m_pktType == ETHERNET_V1) || (m_pktType == IP_ARP)) + if ((m_encapMode == ETHERNET_V1) || (m_encapMode == IP_ARP)) { EthernetHeader header; EthernetTrailer trailer; header.SetSource(this->GetAddress()); header.SetDestination(dest); - switch (m_pktType) + switch (m_encapMode) { case IP_ARP: header.SetLengthType(protocolNumber); @@ -172,7 +172,7 @@ CsmaCdNetDevice::AddHeader (Packet& p, const MacAddress& dest, trailer.CalcFcs(p); p.AddTrailer(trailer); } - else if (m_pktType == LLC) + else if (m_encapMode == LLC) { LlcSnapHeader llc; llc.SetType (protocolNumber); @@ -184,7 +184,7 @@ CsmaCdNetDevice::ProcessHeader(Packet& p, int& param) { bool retVal = true; - if ((m_pktType == ETHERNET_V1) || (m_pktType == IP_ARP)) + if ((m_encapMode == ETHERNET_V1) || (m_encapMode == IP_ARP)) { EthernetHeader header; EthernetTrailer trailer; @@ -200,7 +200,7 @@ CsmaCdNetDevice::ProcessHeader(Packet& p, int& param) retVal = false; } } - else if (m_pktType == LLC) + else if (m_encapMode == LLC) { LlcSnapHeader llc; p.RemoveHeader (llc); @@ -214,7 +214,7 @@ CsmaCdNetDevice::ProcessHeader(Packet& p, int& param) bool CsmaCdNetDevice::DoNeedsArp (void) const { - if ((m_pktType == IP_ARP) || (m_pktType == LLC)) + if ((m_encapMode == IP_ARP) || (m_encapMode == LLC)) { return true; } else { diff --git a/src/devices/csma-cd/csma-cd-net-device.h b/src/devices/csma-cd/csma-cd-net-device.h index 0b2af252e..88ebf72ba 100644 --- a/src/devices/csma-cd/csma-cd-net-device.h +++ b/src/devices/csma-cd/csma-cd-net-device.h @@ -351,7 +351,7 @@ private: * function and that should be processed by the ProcessHeader * function. */ - CsmaCdEncapsulationMode m_pktType; + CsmaCdEncapsulationMode m_encapMode; /** * The data rate that the Net Device uses to simulate packet transmission * timing. From 3b522470587f437f92e38a3528a0901414a47e1c Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sat, 28 Jul 2007 13:14:24 +0200 Subject: [PATCH 22/29] small cleanups --- src/node/ethernet-header.cc | 24 +++++++----------------- src/node/ethernet-header.h | 19 +++++++++---------- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/src/node/ethernet-header.cc b/src/node/ethernet-header.cc index 621bf0ecb..73172d3e5 100644 --- a/src/node/ethernet-header.cc +++ b/src/node/ethernet-header.cc @@ -29,29 +29,19 @@ NS_DEBUG_COMPONENT_DEFINE ("EthernetHeader"); namespace ns3 { -bool EthernetHeader::m_enPreambleSfd = false; +EthernetHeader::EthernetHeader (bool hasPreamble) + : m_enPreambleSfd (hasPreamble), + m_lengthType (0) +{} EthernetHeader::EthernetHeader () -{ - Init(); -} + : m_enPreambleSfd (false), + m_lengthType (0) +{} EthernetHeader::~EthernetHeader () {} -void -EthernetHeader::Init() -{ - m_preambleSfd = 0; - m_lengthType = 0x0; -} - -void -EthernetHeader::EnablePreambleSfd (bool enable) -{ - m_enPreambleSfd = enable; -} - void EthernetHeader::SetLengthType (uint16_t lengthType) { diff --git a/src/node/ethernet-header.h b/src/node/ethernet-header.h index e9fde048a..f16db2976 100644 --- a/src/node/ethernet-header.h +++ b/src/node/ethernet-header.h @@ -53,14 +53,16 @@ public: /** * \brief Construct a null ethernet header + * \param hasPreamble if true, insert and remove an ethernet preamble from the + * packet, if false, does not insert and remove it. + */ + EthernetHeader (bool hasPreamble); + /** + * \brief Construct a null ethernet header + * By default, does not add or remove an ethernet preamble */ EthernetHeader (); virtual ~EthernetHeader (); - /** - * \brief Enable or disabled the serialisation of the preamble and - * Sfd header fields - */ - static void EnablePreambleSfd (bool enable); /** * \param size The size of the payload in bytes */ @@ -109,15 +111,12 @@ private: virtual void SerializeTo (Buffer::Iterator start) const; virtual uint32_t DeserializeFrom (Buffer::Iterator start); - void Init (void); - /** * If false, the preamble/sfd are not serialised/deserialised. */ - static bool m_enPreambleSfd; - + bool m_enPreambleSfd; uint64_t m_preambleSfd; /// Value of the Preamble/SFD fields - uint16_t m_lengthType : 16; /// Length or type of the packet + uint16_t m_lengthType; /// Length or type of the packet MacAddress m_source; /// Source address MacAddress m_destination; /// Destination address }; From 7b0e63b12312f545b18942d362aaccae1c8f4344 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sat, 28 Jul 2007 13:15:04 +0200 Subject: [PATCH 23/29] param is a 16 bit integer. implement proper llc encapsulation/decapsulation --- src/devices/csma-cd/csma-cd-net-device.cc | 101 ++++++++++++---------- src/devices/csma-cd/csma-cd-net-device.h | 2 +- 2 files changed, 58 insertions(+), 45 deletions(-) diff --git a/src/devices/csma-cd/csma-cd-net-device.cc b/src/devices/csma-cd/csma-cd-net-device.cc index 90bd5397d..fc84a9061 100644 --- a/src/devices/csma-cd/csma-cd-net-device.cc +++ b/src/devices/csma-cd/csma-cd-net-device.cc @@ -150,65 +150,76 @@ CsmaCdNetDevice::SetBackoffParams (Time slotTime, uint32_t minSlots, } void CsmaCdNetDevice::AddHeader (Packet& p, const MacAddress& dest, - uint16_t protocolNumber) + uint16_t protocolNumber) { - if ((m_encapMode == ETHERNET_V1) || (m_encapMode == IP_ARP)) + if (m_encapMode == RAW) { - EthernetHeader header; - EthernetTrailer trailer; - - header.SetSource(this->GetAddress()); - header.SetDestination(dest); - switch (m_encapMode) - { - case IP_ARP: - header.SetLengthType(protocolNumber); - break; - default: - header.SetLengthType(p.GetSize() + header.GetSize() + trailer.GetSize()); - break; - } - p.AddHeader(header); - trailer.CalcFcs(p); - p.AddTrailer(trailer); - } - else if (m_encapMode == LLC) + return; + } + EthernetHeader header (false); + EthernetTrailer trailer; + header.SetSource(this->GetAddress()); + header.SetDestination(dest); + + uint16_t lengthType; + switch (m_encapMode) { + case ETHERNET_V1: + lengthType = p.GetSize() + header.GetSize() + trailer.GetSize(); + break; + case IP_ARP: + lengthType = protocolNumber; + break; + case LLC: { LlcSnapHeader llc; llc.SetType (protocolNumber); p.AddHeader (llc); + } break; + case RAW: + NS_ASSERT (false); + break; } + header.SetLengthType (lengthType); + p.AddHeader(header); + trailer.CalcFcs(p); + p.AddTrailer(trailer); } bool -CsmaCdNetDevice::ProcessHeader(Packet& p, int& param) +CsmaCdNetDevice::ProcessHeader (Packet& p, uint16_t & param) { - bool retVal = true; - - if ((m_encapMode == ETHERNET_V1) || (m_encapMode == IP_ARP)) + if (m_encapMode == RAW) { - EthernetHeader header; - EthernetTrailer trailer; - - p.RemoveTrailer(trailer); - trailer.CheckFcs(p); - p.RemoveHeader(header); - - param = header.GetLengthType(); - if ((header.GetDestination() != this->GetBroadcast()) && - (header.GetDestination() != this->GetAddress())) - { - retVal = false; - } + return true; } - else if (m_encapMode == LLC) + EthernetHeader header (false); + EthernetTrailer trailer; + + p.RemoveTrailer(trailer); + trailer.CheckFcs(p); + p.RemoveHeader(header); + + if ((header.GetDestination() != this->GetBroadcast()) && + (header.GetDestination() != this->GetAddress())) { + return false; + } + + switch (m_encapMode) + { + case ETHERNET_V1: + case IP_ARP: + param = header.GetLengthType(); + break; + case LLC: { LlcSnapHeader llc; p.RemoveHeader (llc); - param = llc.GetType (); + } break; + case RAW: + NS_ASSERT (false); + break; } - - return retVal; + return true; } bool @@ -440,14 +451,16 @@ CsmaCdNetDevice::Receive (Packet& p) if (!IsReceiveEnabled()) return; - int param = 0; + uint16_t param = 0; Packet packet = p; if (ProcessHeader(packet, param)) { m_rxTrace (packet); ForwardUp (packet, param); - } else { + } + else + { m_dropTrace (packet); } } diff --git a/src/devices/csma-cd/csma-cd-net-device.h b/src/devices/csma-cd/csma-cd-net-device.h index 88ebf72ba..c3ef7586e 100644 --- a/src/devices/csma-cd/csma-cd-net-device.h +++ b/src/devices/csma-cd/csma-cd-net-device.h @@ -222,7 +222,7 @@ protected: * \return Returns true if the packet should be forwarded up the * protocol stack. */ - bool ProcessHeader (Packet& p, int& param); + bool ProcessHeader (Packet& p, uint16_t & param); private: // disable copy constructor and operator = From 14404dff66125e156acca8c454cb73da9a85f748 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sat, 28 Jul 2007 13:20:47 +0200 Subject: [PATCH 24/29] protocol number is a 16 bit unsigned integer --- src/devices/point-to-point/point-to-point-net-device.cc | 4 ++-- src/devices/point-to-point/point-to-point-net-device.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 565557df6..fff158521 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 @@ -74,7 +74,7 @@ void PointToPointNetDevice::AddHeader(Packet& p, const MacAddress& dest, p.AddHeader (llc); } -bool PointToPointNetDevice::ProcessHeader(Packet& p, int& param) +bool PointToPointNetDevice::ProcessHeader(Packet& p, uint16_t& param) { LlcSnapHeader llc; p.RemoveHeader (llc); @@ -218,7 +218,7 @@ void PointToPointNetDevice::AddQueue (Ptr q) void PointToPointNetDevice::Receive (Packet& p) { NS_DEBUG ("PointToPointNetDevice::Receive (" << &p << ")"); - int param = 0; + uint16_t param = 0; Packet packet = p; ProcessHeader(packet, param); 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 6e8f3f0ae..2cdafab28 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 @@ -198,7 +198,7 @@ private: * \return Returns true if the packet should be forwarded up the * protocol stack. */ - bool ProcessHeader(Packet& p, int& param); + bool ProcessHeader(Packet& p, uint16_t& param); /** * Send a Packet Down the Wire. * From 08758e9129e9c28abffa3eccdd68f44c7a034b80 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sat, 28 Jul 2007 13:22:47 +0200 Subject: [PATCH 25/29] fix indent, basic coding style issues --- src/devices/csma-cd/csma-cd-net-device.cc | 48 +++++++++++++---------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/devices/csma-cd/csma-cd-net-device.cc b/src/devices/csma-cd/csma-cd-net-device.cc index fc84a9061..6263a070c 100644 --- a/src/devices/csma-cd/csma-cd-net-device.cc +++ b/src/devices/csma-cd/csma-cd-net-device.cc @@ -228,7 +228,9 @@ CsmaCdNetDevice::DoNeedsArp (void) const if ((m_encapMode == IP_ARP) || (m_encapMode == LLC)) { return true; - } else { + } + else + { return false; } } @@ -248,22 +250,22 @@ CsmaCdNetDevice::SendTo (Packet& p, const MacAddress& dest, uint16_t protocolNum AddHeader(p, dest, protocolNumber); // Place the packet to be sent on the send queue - if (m_queue->Enqueue(p) == false ) - { - return false; - } - // If the device is idle, we need to start a transmission. Otherwise, - // the transmission will be started when the current packet finished - // transmission (see TransmitCompleteEvent) - if (m_txMachineState == READY) - { - // Store the next packet to be transmitted - if (m_queue->Dequeue (m_currentPkt)) - { - TransmitStart(); - } - } - return true; + if (m_queue->Enqueue(p) == false ) + { + return false; + } + // If the device is idle, we need to start a transmission. Otherwise, + // the transmission will be started when the current packet finished + // transmission (see TransmitCompleteEvent) + if (m_txMachineState == READY) + { + // Store the next packet to be transmitted + if (m_queue->Dequeue (m_currentPkt)) + { + TransmitStart(); + } + } + return true; } void @@ -292,7 +294,9 @@ CsmaCdNetDevice::TransmitStart () if (m_backoff.MaxRetriesReached()) { // Too many retries reached, abort transmission of packet TransmitAbort(); - } else { + } + else + { m_backoff.IncrNumRetries(); Time backoffTime = m_backoff.GetBackoffTime(); @@ -304,7 +308,9 @@ CsmaCdNetDevice::TransmitStart () &CsmaCdNetDevice::TransmitStart, this); } - } else { + } + else + { // Channel is free, transmit packet m_txMachineState = BUSY; Time tEvent = Seconds (m_bps.CalculateTxTime(m_currentPkt.GetSize())); @@ -322,7 +328,9 @@ CsmaCdNetDevice::TransmitStart () "Channel transmit start did not work at " << tEvent.GetSeconds () << "sec"); m_txMachineState = READY; - } else { + } + else + { // Transmission success, reset backoff time parameters. m_backoff.ResetBackoffTime(); } From 9e23045867fd95e2a9b4e5e76633bf005a190548 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sat, 28 Jul 2007 13:25:10 +0200 Subject: [PATCH 26/29] fix basic coding style issues --- src/devices/csma-cd/csma-cd-channel.cc | 34 +++++++++++++++++--------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/devices/csma-cd/csma-cd-channel.cc b/src/devices/csma-cd/csma-cd-channel.cc index 004ddbd33..7b6d211f7 100644 --- a/src/devices/csma-cd/csma-cd-channel.cc +++ b/src/devices/csma-cd/csma-cd-channel.cc @@ -114,12 +114,15 @@ CsmaCdChannel::Reattach(Ptr device) { if (it->devicePtr == device) { - if (!it->active) { - it->active = true; - return true; - } else { - return false; - } + if (!it->active) + { + it->active = true; + return true; + } + else + { + return false; + } } } return false; @@ -137,7 +140,9 @@ CsmaCdChannel::Reattach(uint32_t deviceId) if (m_deviceList[deviceId].active) { return false; - } else { + } + else + { m_deviceList[deviceId].active = true; return true; } @@ -166,7 +171,9 @@ CsmaCdChannel::Detach(uint32_t deviceId) } return true; - } else { + } + else + { return false; } } @@ -218,7 +225,8 @@ CsmaCdChannel::TransmitStart(Packet& p, uint32_t srcId) } bool -CsmaCdChannel::IsActive(uint32_t deviceId) { +CsmaCdChannel::IsActive(uint32_t deviceId) +{ return (m_deviceList[deviceId].active); } @@ -318,7 +326,9 @@ CsmaCdChannel::GetDeviceNum (Ptr device) if (it->active) { return i; - } else { + } + else + { return -2; } } @@ -333,7 +343,9 @@ CsmaCdChannel::IsBusy (void) if (m_state == IDLE) { return false; - } else { + } + else + { return true; } } From 28ddc5db69c45af1f6f4a28b35d35b021d065826 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sat, 28 Jul 2007 14:50:56 +0200 Subject: [PATCH 27/29] start filling release notes with merged items --- RELEASE_NOTES | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 9de1ba7c1..9b3b40b1b 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -3,6 +3,13 @@ This file contains ns-3 release notes (most recent releases first). +Release 3.0.5 (2007/08/XX) +======================== + + - Add CSMA/CD model (Emmanuelle Laprise) + - Modularize ipv4 routing support (Gustavo Carneiro) + - Add mobility framework and basic mobility models + Release 3.0.4 (2007/07/15) ======================== From 8682d0293ad0d987e1e7ddc38d6701e5c7f56994 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Sat, 28 Jul 2007 14:14:16 +0100 Subject: [PATCH 28/29] WAF: remove the obj.includes = '.' part from modules, since it causes build failure in OS X, and waf was just fixed to enable header files dependency tracking by default without needing to change obj.includes --- src/applications/wscript | 1 - src/common/wscript | 1 - src/core/wscript | 1 - src/devices/point-to-point/wscript | 1 - src/internet-node/wscript | 1 - src/mobility/wscript | 1 - src/node/wscript | 1 - src/simulator/wscript | 1 - 8 files changed, 8 deletions(-) diff --git a/src/applications/wscript b/src/applications/wscript index 5a9c76f50..0874d58ab 100644 --- a/src/applications/wscript +++ b/src/applications/wscript @@ -8,7 +8,6 @@ def build(bld): obj.source = [ 'onoff-application.cc', ] - obj.includes = '.' headers = bld.create_obj('ns3header') headers.source = [ diff --git a/src/common/wscript b/src/common/wscript index 8f2518d4c..5d58f37b2 100644 --- a/src/common/wscript +++ b/src/common/wscript @@ -24,7 +24,6 @@ def build(bld): 'trace-root.cc', 'data-rate.cc', ] - common.includes = '.' headers = bld.create_obj('ns3header') headers.source = [ diff --git a/src/core/wscript b/src/core/wscript index 011023938..219f5541f 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -39,7 +39,6 @@ def build(bld): 'component-manager.cc', 'random-variable-default-value.cc', ] - core.includes = '.' if sys.platform == 'win32': core.source.extend([ diff --git a/src/devices/point-to-point/wscript b/src/devices/point-to-point/wscript index 59d6ba3f8..77c26fd80 100644 --- a/src/devices/point-to-point/wscript +++ b/src/devices/point-to-point/wscript @@ -17,5 +17,4 @@ def build(bld): 'point-to-point-channel.h', 'point-to-point-topology.h', ] - module.includes = '.' diff --git a/src/internet-node/wscript b/src/internet-node/wscript index e1c452157..7a1b1c10e 100644 --- a/src/internet-node/wscript +++ b/src/internet-node/wscript @@ -34,7 +34,6 @@ def build(bld): 'pcap-trace.cc', 'udp-impl.cc', ] - obj.includes = '.' headers = bld.create_obj('ns3header') headers.source = [ diff --git a/src/mobility/wscript b/src/mobility/wscript index 99f732fc2..b20c5af67 100644 --- a/src/mobility/wscript +++ b/src/mobility/wscript @@ -20,7 +20,6 @@ def build(bld): 'static-speed-helper.cc', 'static-speed-mobility-model.cc', ] - mobility.includes = '.' headers = bld.create_obj('ns3header') headers.source = [ diff --git a/src/node/wscript b/src/node/wscript index 62974351a..4b1ea1f01 100644 --- a/src/node/wscript +++ b/src/node/wscript @@ -25,7 +25,6 @@ def build(bld): 'ipv4.cc', 'application.cc', ] - node.includes = '.' headers = bld.create_obj('ns3header') headers.source = [ diff --git a/src/simulator/wscript b/src/simulator/wscript index c9f14bd67..9c7925f22 100644 --- a/src/simulator/wscript +++ b/src/simulator/wscript @@ -65,7 +65,6 @@ def build(bld): 'simulator.cc', 'time-default-value.cc', ] - sim.includes = '.' headers = bld.create_obj('ns3header') headers.source = [ From ecd4f30e4133a694b459571acb487a96675ee3af Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Sat, 28 Jul 2007 23:20:58 -0700 Subject: [PATCH 29/29] Fix lengthType initialization for optimized build --- src/devices/csma-cd/csma-cd-net-device.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices/csma-cd/csma-cd-net-device.cc b/src/devices/csma-cd/csma-cd-net-device.cc index 6263a070c..b3527d354 100644 --- a/src/devices/csma-cd/csma-cd-net-device.cc +++ b/src/devices/csma-cd/csma-cd-net-device.cc @@ -161,7 +161,7 @@ CsmaCdNetDevice::AddHeader (Packet& p, const MacAddress& dest, header.SetSource(this->GetAddress()); header.SetDestination(dest); - uint16_t lengthType; + uint16_t lengthType = 0; switch (m_encapMode) { case ETHERNET_V1: