diff --git a/SConstruct b/SConstruct index 988125fc2..8934d5b29 100644 --- a/SConstruct +++ b/SConstruct @@ -358,13 +358,4 @@ ns3.add(sample_ns2_simple) sample_ns2_simple.add_deps(['core', 'simulator', 'node', 'serial']) sample_ns2_simple.add_source('ns-2/simple.cc') -sample_channel = build.Ns3Module('sample-channel', 'samples') -sample_channel.set_executable() -ns3.add(sample_channel) -sample_channel.add_dep ('common') -sample_channel.add_dep ('node') -sample_channel.add_dep ('core') -sample_channel.add_dep ('serial') -sample_channel.add_source('main-channel.cc') - ns3.generate_dependencies() diff --git a/samples/ns-2/simple.cc b/samples/ns-2/simple.cc index 003dc698f..624e1ca4e 100644 --- a/samples/ns-2/simple.cc +++ b/samples/ns-2/simple.cc @@ -199,6 +199,9 @@ PrintRoutingTable (InternetNode *a, std::string name) static SerialChannel * AddDuplexLink( + std::string &name, + uint64_t bps, + uint32_t delay, InternetNode* a, const Ipv4Address& addra, const MacAddress& macaddra, @@ -207,11 +210,10 @@ AddDuplexLink( const MacAddress& macaddrb, // const Rate& rate, // const Time& delay, - TraceContainer &traceContainer, - std::string &name) + TraceContainer &traceContainer) { std::string qName; - SerialChannel* channel = new SerialChannel(); + SerialChannel* channel = new SerialChannel(name, bps, MilliSeconds(delay)); // Duplex link is assumed to be subnetted as a /30 // May run this unnumbered in the future? @@ -276,6 +278,16 @@ SetupTrace (TraceContainer &container, Tracer &tracer) int main (int argc, char *argv[]) { + +#if 0 + DebugComponentEnable("Queue"); + DebugComponentEnable("DropTailQueue"); + DebugComponentEnable("Channel"); + DebugComponentEnable("SerialChannel"); + DebugComponentEnable("SerialNetDevice"); + DebugComponentEnable("SerialPhy"); +#endif + // ** Here, some kind of factory or topology object will instantiates // ** four identical nodes; for now, we just explicitly create them InternetNode *n0 = new InternetNode(); @@ -295,24 +307,24 @@ int main (int argc, char *argv[]) std::string channelName; channelName = "Channel 1"; - SerialChannel* ch1 = AddDuplexLink ( + SerialChannel* ch1 = AddDuplexLink (channelName, 5000000, 2, n0, Ipv4Address("10.1.1.1"), MacAddress("00:00:00:00:00:01"), n2, Ipv4Address("10.1.1.2"), MacAddress("00:00:00:00:00:02"), - traceContainer, channelName); + traceContainer); SetupTrace (traceContainer, tracer); channelName = "Channel 2"; - SerialChannel* ch2 = AddDuplexLink ( + SerialChannel* ch2 = AddDuplexLink (channelName, 5000000, 2, n1, Ipv4Address("10.1.2.1"), MacAddress("00:00:00:00:00:03"), n2, Ipv4Address("10.1.2.2"), MacAddress("00:00:00:00:00:04"), - traceContainer, channelName); + traceContainer); SetupTrace (traceContainer, tracer); channelName = "Channel 3"; - SerialChannel* ch3 = AddDuplexLink ( + SerialChannel* ch3 = AddDuplexLink (channelName, 1500000, 10, n2, Ipv4Address("10.1.3.1"), MacAddress("00:00:00:00:00:05"), n3, Ipv4Address("10.1.3.2"), MacAddress("00:00:00:00:00:06"), - traceContainer, channelName); + traceContainer); SetupTrace (traceContainer, tracer); UdpSocket *source0 = new UdpSocket (n0); diff --git a/src/devices/serial/channel.cc b/src/devices/serial/channel.cc index efc350e27..5b1f9a212 100644 --- a/src/devices/serial/channel.cc +++ b/src/devices/serial/channel.cc @@ -1,7 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 University of Washington - * 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 @@ -29,53 +28,32 @@ NS_DEBUG_COMPONENT_DEFINE ("Channel"); namespace ns3 { Channel::Channel () + : m_name("Channel") { NS_DEBUG("Channel::Channel ()"); } + Channel::Channel (std::string name) + : m_name(name) +{ + NS_DEBUG("Channel::Channel (" << name << ")"); +} + Channel::~Channel () { NS_DEBUG("Channel::~Channel ()"); } - bool -Channel::DoConnectToUpper (LayerConnectorUpper &upper) + void +Channel::SetName(std::string name) { - NS_DEBUG("Channel::DoConnectToUpper (" << &upper << ")"); - m_connectorList.push_back(&upper); - - return true; + m_name = name; } - bool -Channel::LowerDoNotify (LayerConnectorUpper *upper) + std::string +Channel::GetName(void) { - NS_DEBUG("Channel::LowerDoNotify ()"); - - Packet p; - - NS_DEBUG("Channel::LowerDoNotify (): Starting pull"); - - upper->UpperPull(p); - - NS_DEBUG("Channel::LowerDoNotify (): Got bits, Propagate()"); - - return Propagate(p); -} - - bool -Channel::Propagate (Packet &p) -{ - NS_DEBUG("Channel::Propagate (" << &p << ")"); - - for (ConnectorList::const_iterator i = m_connectorList.begin (); - i != m_connectorList.end (); - i++) - { - (*i)->UpperSendUp (p); - } - - return true; + return m_name; } } // namespace ns3 diff --git a/src/devices/serial/channel.h b/src/devices/serial/channel.h index 67b74178e..43d952373 100644 --- a/src/devices/serial/channel.h +++ b/src/devices/serial/channel.h @@ -1,7 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 University of Washington - * 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 @@ -30,21 +29,24 @@ namespace ns3 { -class Channel : public LayerConnectorLower +/** + * \brief Abstract Channel Base Class. + * + * A channel is a logical path over which information flows. The path can + * be as simple as a short piece of wire, or as complicated as space-time. + */ +class Channel { public: Channel (); + Channel (std::string name); virtual ~Channel (); - // Called by the physical layer to cause bits to propagate along the channel - // The channel will call Receive on each of the phys. - bool Propagate (Packet &p); - bool DoConnectToUpper (LayerConnectorUpper &upper); - bool LowerDoNotify (LayerConnectorUpper *upper); + virtual void SetName(std::string); + virtual std::string GetName(void); protected: - typedef std::list ConnectorList; - ConnectorList m_connectorList; + std::string m_name; private: }; diff --git a/src/devices/serial/serial-channel.cc b/src/devices/serial/serial-channel.cc index 6da4dcb92..07ba1a7b8 100644 --- a/src/devices/serial/serial-channel.cc +++ b/src/devices/serial/serial-channel.cc @@ -15,31 +15,123 @@ * 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: Craig Dowell */ #include "serial-channel.h" #include "serial-net-device.h" #include "ns3/packet.h" +#include "ns3/simulator.h" +#include "ns3/debug.h" + +NS_DEBUG_COMPONENT_DEFINE ("SerialChannel"); namespace ns3 { -void -SerialChannel::Attach(SerialNetDevice* nd) +// +// By default, you get a channel with the name "Serial Channel" that has an +// "infitely" fast transmission speed and zero delay. +// +SerialChannel::SerialChannel() +: + Channel ("Serial Channel"), + m_bps (UINT64_MAX), + m_delay (Seconds(0)), + m_nDevices(0) { - nd->Attach(this); - m_devices.push_back (nd); + NS_DEBUG("SerialChannel::SerialChannel ()"); } -bool -SerialChannel::Send(Packet& p, SerialNetDevice* caller) +SerialChannel::SerialChannel( + std::string name, + DataRate bps, + Time delay) +: + Channel (name), + m_bps (bps), + m_delay (delay), + m_nDevices(0) { - for (NetDevicesCI i = m_devices.begin (); i != m_devices.end (); i++) { - if (caller != (*i)) { - (*i)->Receive (p); - return true; - } + NS_DEBUG("SerialChannel::SerialChannel (" << name << ", " << bps << ", " << + delay << ")"); +} + + void +SerialChannel::Attach(SerialNetDevice *device) +{ + NS_DEBUG("SerialChannel::Attach (" << device << ")"); + NS_ASSERT(m_nDevices < N_DEVICES && "Only two devices permitted"); + NS_ASSERT(device); + + m_link[m_nDevices].m_src = device; + ++m_nDevices; +// +// If we have both devices connected to the channel, then finish introducing +// the two halves and set the links to IDLE. +// + if (m_nDevices == N_DEVICES) + { + m_link[0].m_dst = m_link[1].m_src; + m_link[1].m_dst = m_link[0].m_src; + m_link[0].m_state = IDLE; + m_link[1].m_state = IDLE; } - return false; +} + + void +SerialChannel::TransmitCompleteEvent(Packet &p, SerialNetDevice *src) +{ + NS_DEBUG("SerialChannel::TransmitCompleteEvent (" << &p << ", " << + src << ")"); + + NS_ASSERT(m_link[0].m_state != INITIALIZING); + NS_ASSERT(m_link[1].m_state != INITIALIZING); + uint32_t wire = src == m_link[0].m_src ? 0 : 1; + NS_ASSERT(m_link[wire].m_state == TRANSMITTING); + + m_link[wire].m_state = IDLE; + + NS_DEBUG("SerialChannel::TransmitCompleteEvent (): Receive()"); + + m_link[wire].m_dst->Receive (p); +} + + bool +SerialChannel::Propagate(Packet& p, SerialNetDevice* src) +{ + NS_DEBUG("SerialChannel::DoPropagate (" << &p << ", " << src << ")"); + + NS_ASSERT(m_link[0].m_state != INITIALIZING); + NS_ASSERT(m_link[1].m_state != INITIALIZING); + + uint32_t wire = src == m_link[0].m_src ? 0 : 1; + + if (m_link[wire].m_state == TRANSMITTING) + { + NS_DEBUG("SerialChannel::DoPropagate (): TRANSMITTING, return"); + return false; + } + + m_link[wire].m_state = TRANSMITTING; + +// +// I believe Raj has a method in the DataRate class to do this. Should use +// it when it is available. +// + Time tEvent = Simulator::Now () + + Seconds (static_cast (p.GetSize() * 8) / + static_cast (m_bps)) + m_delay; + + NS_DEBUG("SerialChannel::DoSend (): Schedule Receive at " << tEvent); + +#if 0 + Simulator::Schedule (tEvent, &SerialChannel::TransmitCompleteEvent, this, + p, src); +#else + TransmitCompleteEvent (p, src); +#endif + return true; } } // namespace ns3 diff --git a/src/devices/serial/serial-channel.h b/src/devices/serial/serial-channel.h index b5a7c4378..41e5b49e3 100644 --- a/src/devices/serial/serial-channel.h +++ b/src/devices/serial/serial-channel.h @@ -1,7 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 University of Washington - * 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 @@ -17,31 +16,81 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// The queue base class does not have any limit based on the number -// of packets or number of bytes. It is, conceptually, infinite -// by default. Only subclasses define limitations. -// The base class implements tracing and basic statistics calculations. - -#ifndef CHANNEL_SERIAL_H -#define CHANNEL_SERIAL_H +#ifndef SERIAL_CHANNEL_H +#define SERIAL_CHANNEL_H #include -#include "serial-net-device.h" +#include "channel.h" +#include "serial-phy.h" #include "ns3/packet.h" +#include "ns3/nstime.h" namespace ns3 { -// Simple SerialChannel class -class SerialChannel { +// temporary until Raj's code makes it into the dev tree +typedef uint64_t DataRate; + +/** + * \brief Simple Serial Channel. + * + * This class represents a very simple serial channel. Think full duplex + * RS-232 or RS-422 with null modem and no handshaking. There is no multi- + * drop capability on this channel -- there can be a maximum of two serial + * net devices connected. Once we start talking about multi-drop, or CSMA, + * or some other sharing mechanism, things begin getting complicated quickly. + * Rather than invent some ad-hoc mechanism, we just Keep It Simple everywhere. + * + * When the channel is instaniated, the constructor takes parameters for + * a single channel speed, in bits per second, and a delay time as a Time + * object. Both directions use the same speed and delay time. + * + * There are two "wires" in the channel. The first device connected gets the + * [0] wire to transmit on. The second device gets the [1] wire. There is a + * state (IDLE, TRANSMITTING) associated with each wire. + */ +class SerialChannel : public Channel { public: - bool Send(Packet& p, SerialNetDevice *caller); +// +// This is really kidding myself, since just setting N_DEVICES to 3 isn't +// going to come close to magically creating a multi-drop link, but I can't +// bring myself to just type 2 in the code (even though I type 0 and 1 :-). +// + static const int N_DEVICES = 2; + + SerialChannel (); + SerialChannel (std::string name, DataRate bps, Time delay); + void Attach (SerialNetDevice* nd); -private: - typedef std::list NetDevices; - typedef std::list::const_iterator NetDevicesCI; - NetDevices m_devices; + bool Propagate (Packet& p, SerialNetDevice *src); + +protected: + void TransmitCompleteEvent (Packet &p, SerialNetDevice *src); + + std::string m_name; + DataRate m_bps; + Time m_delay; + + int32_t m_nDevices; + + enum WireState + { + INITIALIZING, + IDLE, + TRANSMITTING + }; + + class Link + { + public: + Link() : m_state (INITIALIZING), m_src (0), m_dst (0) {} + WireState m_state; + SerialNetDevice *m_src; + SerialNetDevice *m_dst; + }; + + Link m_link[N_DEVICES]; }; } // namespace ns3 -#endif /* CHANNEL_SERIAL__H */ +#endif /* SERIAL_CHANNEL_H */ diff --git a/src/devices/serial/serial-net-device.cc b/src/devices/serial/serial-net-device.cc index 13d158b30..ee071e854 100644 --- a/src/devices/serial/serial-net-device.cc +++ b/src/devices/serial/serial-net-device.cc @@ -125,7 +125,7 @@ SerialNetDevice::NotifyDataAvailable(void) // send packet to address tag.address #endif NS_DEBUG ("SerialNetDevice::NotifyDataAvailable (): Dequeued"); - m_channel->Send(p, this); + m_channel->Propagate(p, this); } } diff --git a/src/devices/serial/serial-net-device.h b/src/devices/serial/serial-net-device.h index 9d8ebd47e..6d77e9c76 100644 --- a/src/devices/serial/serial-net-device.h +++ b/src/devices/serial/serial-net-device.h @@ -1,7 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 University of Washington - * 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 diff --git a/src/devices/serial/serial-phy.cc b/src/devices/serial/serial-phy.cc index 33cb16ab0..f1e6f1277 100644 --- a/src/devices/serial/serial-phy.cc +++ b/src/devices/serial/serial-phy.cc @@ -55,7 +55,7 @@ SerialPhy::NotifyDataAvailable(void) // send packet to address tag.address #endif NS_DEBUG ("SerialPhy::NotifyDataAvailable (): Dequeued"); - m_netdevice->GetChannel()->Send(p, m_netdevice); + m_netdevice->GetChannel()->Propagate(p, m_netdevice); } } @@ -63,7 +63,6 @@ void SerialPhy::Receive (Packet& p) { NS_DEBUG ("SerialPhy::Receive (" << &p << ")"); - m_netdevice->ForwardUp (p); } diff --git a/src/devices/serial/serial-phy.h b/src/devices/serial/serial-phy.h index 1f804230a..00d59f9f0 100644 --- a/src/devices/serial/serial-phy.h +++ b/src/devices/serial/serial-phy.h @@ -1,7 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 University of Washington - * 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