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) ======================== diff --git a/examples/csma-cd-one-subnet.cc b/examples/csma-cd-one-subnet.cc new file mode 100644 index 000000000..f93337823 --- /dev/null +++ b/examples/csma-cd-one-subnet.cc @@ -0,0 +1,171 @@ +/* -*- 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 + */ + +// Port of ns-2/tcl/ex/simple.tcl to ns-3 +// +// Network topology +// +// 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 "csma-cd-one-subnet.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/eui48-address.h" +#include "ns3/ipv4-address.h" +#include "ns3/inet-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("CsmaCdNetDevice"); + DebugComponentEnable("Ipv4L3Protocol"); + DebugComponentEnable("NetDevice"); + DebugComponentEnable("Channel"); + DebugComponentEnable("CsmaCdChannel"); + DebugComponentEnable("PacketSocket"); +#endif + + // 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)); + + uint32_t n0ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n0, channel0, + Eui48Address("10:54:23:54:23:50")); + uint32_t n1ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n1, channel0, + Eui48Address("10:54:23:54:23:51")); + uint32_t n2ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n2, channel0, + Eui48Address("10:54:23:54:23:52")); + uint32_t n3ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n3, channel0, + Eui48Address("10:54:23:54:23:53")); + + // Later, we add IP addresses. + CsmaCdIpv4Topology::AddIpv4Address ( + n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); + + CsmaCdIpv4Topology::AddIpv4Address ( + n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); + + CsmaCdIpv4Topology::AddIpv4Address ( + n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0")); + + 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 + Ptr ooff = Create ( + n0, + InetAddress (Ipv4Address("10.1.1.2"), 80).ConvertTo (), + "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 n0, starting at time 1.1 seconds + ooff = Create ( + n3, + InetAddress (Ipv4Address("10.1.1.1"), 80).ConvertTo (), + "Udp", + ConstantVariable(1), + ConstantVariable(0)); + // Start the application + ooff->Start(Seconds(1.1)); + ooff->Stop (Seconds(10.0)); + + // 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 (); + + // 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 (); + + Simulator::Destroy (); +} diff --git a/examples/simple-point-to-point.cc b/examples/simple-point-to-point.cc new file mode 100644 index 000000000..2398cc22b --- /dev/null +++ b/examples/simple-point-to-point.cc @@ -0,0 +1,191 @@ +/* -*- 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 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-point-to-point.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/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/point-to-point-channel.h" +#include "ns3/point-to-point-net-device.h" +#include "ns3/ipv4-address.h" +#include "ns3/inet-address.h" +#include "ns3/ipv4.h" +#include "ns3/socket.h" +#include "ns3/ipv4-route.h" +#include "ns3/point-to-point-topology.h" +#include "ns3/onoff-application.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("Object"); + DebugComponentEnable("Queue"); + DebugComponentEnable("DropTailQueue"); + DebugComponentEnable("Channel"); + DebugComponentEnable("PointToPointChannel"); + DebugComponentEnable("PointToPointNetDevice"); +#endif + + // 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"); + + Bind ("OnOffApplicationPacketSize", "210"); + Bind ("OnOffApplicationDataRate", "448kb/s"); + + //Bind ("DropTailQueue::m_maxPackets", 30); + + // 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 = + PointToPointTopology::AddPointToPointLink ( + n0, n2, DataRate(5000000), MilliSeconds(2)); + + Ptr channel1 = + PointToPointTopology::AddPointToPointLink ( + n1, n2, DataRate(5000000), MilliSeconds(2)); + + Ptr channel2 = + PointToPointTopology::AddPointToPointLink ( + n2, n3, DataRate(1500000), MilliSeconds(10)); + + // Later, we add IP addresses. + PointToPointTopology::AddIpv4Addresses ( + channel0, n0, Ipv4Address("10.1.1.1"), + n2, Ipv4Address("10.1.1.2")); + + PointToPointTopology::AddIpv4Addresses ( + channel1, n1, Ipv4Address("10.1.2.1"), + n2, Ipv4Address("10.1.2.2")); + + PointToPointTopology::AddIpv4Addresses ( + channel2, n2, Ipv4Address("10.1.3.1"), + n3, Ipv4Address("10.1.3.2")); + + // 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 + PointToPointTopology::AddIpv4Routes(n0, n2, channel0); + PointToPointTopology::AddIpv4Routes(n1, n2, channel1); + PointToPointTopology::AddIpv4Routes(n2, n3, channel2); + + + // Create the OnOff application to send UDP datagrams of size + // 210 bytes at a rate of 448 Kb/s + Ptr ooff = Create ( + n0, + InetAddress (Ipv4Address("10.1.3.2"), 80).ConvertTo (), + "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, + InetAddress (Ipv4Address("10.1.2.1"), 80).ConvertTo (), + "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-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-point-to-point.pcap-- + // and can be read by the "tcpdump -r" command (use "-tt" option to + // display timestamps correctly) + PcapTrace pcaptrace ("simple-point-to-point.pcap"); + pcaptrace.TraceAllIp (); + + Simulator::Run (); + + Simulator::Destroy (); +} diff --git a/examples/wscript b/examples/wscript index f535ea93f..e1b960ddc 100644 --- a/examples/wscript +++ b/examples/wscript @@ -9,5 +9,6 @@ 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-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']) 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/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/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..7b6d211f7 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-channel.cc @@ -0,0 +1,371 @@ +/* -*- 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..923f89dc4 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-ipv4-topology.cc @@ -0,0 +1,156 @@ +/* -*- 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 { + + +uint32_t +CsmaCdIpv4Topology::AddIpv4CsmaCdNode(Ptr n1, + Ptr ch, + Eui48Address addr) +{ + Ptr q = Queue::CreateDefault (); + + // assume full-duplex + Ptr nd0 = Create (n1, addr, + ns3::CsmaCdNetDevice::IP_ARP, + true, true); + nd0->AddQueue(q); + nd0->Attach (ch); + return nd0->GetIfIndex (); +} + + +void +CsmaCdIpv4Topology::AddIpv4LlcCsmaCdNode(Ptr n1, + Ptr ch, + Eui48Address 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, + Eui48Address 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..84a769880 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-ipv4-topology.h @@ -0,0 +1,122 @@ +/* -*- 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. + * + * \return ifIndex of the device + */ + static uint32_t AddIpv4CsmaCdNode( Ptr n1, + Ptr ch, + Eui48Address 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, + Eui48Address 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, + Eui48Address 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..ea4855f05 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-net-device.cc @@ -0,0 +1,494 @@ +/* -*- 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, Eui48Address addr, + CsmaCdEncapsulationMode encapMode) + : NetDevice(node, addr.ConvertTo ()), + m_bps (DataRate (0xffffffff)) +{ + NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")"); + m_encapMode = encapMode; + + Init(true, true); +} + +CsmaCdNetDevice::CsmaCdNetDevice (Ptr node, Eui48Address addr, + CsmaCdEncapsulationMode encapMode, + bool sendEnable, bool receiveEnable) + : NetDevice(node, addr.ConvertTo ()), + m_bps (DataRate (0xffffffff)) +{ + NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")"); + m_encapMode = encapMode; + + Init(sendEnable, receiveEnable); +} + +CsmaCdNetDevice::~CsmaCdNetDevice() +{ + NS_DEBUG ("CsmaCdNetDevice::~CsmaCdNetDevice ()"); + m_queue = 0; +} + +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 (Eui48Address ("ff:ff:ff:ff:ff:ff").ConvertTo ()); + 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, Eui48Address dest, + uint16_t protocolNumber) +{ + if (m_encapMode == RAW) + { + return; + } + EthernetHeader header (false); + EthernetTrailer trailer; + Eui48Address source = Eui48Address::ConvertFrom (GetAddress ()); + header.SetSource(source); + header.SetDestination(dest); + + uint16_t lengthType = 0; + 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, uint16_t & param) +{ + if (m_encapMode == RAW) + { + return true; + } + EthernetHeader header (false); + EthernetTrailer trailer; + + p.RemoveTrailer(trailer); + trailer.CheckFcs(p); + p.RemoveHeader(header); + + Eui48Address broadcast = Eui48Address::ConvertFrom (GetBroadcast ()); + Eui48Address destination = Eui48Address::ConvertFrom (GetAddress ()); + if ((header.GetDestination() != broadcast) && + (header.GetDestination() != destination)) + { + 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 true; +} + +bool +CsmaCdNetDevice::DoNeedsArp (void) const +{ + if ((m_encapMode == IP_ARP) || (m_encapMode == LLC)) + { + return true; + } + else + { + return false; + } +} + +bool +CsmaCdNetDevice::SendTo (Packet& p, const Address& 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; + + Eui48Address address = Eui48Address::ConvertFrom (dest); + AddHeader(p, address, 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; + + uint16_t 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..eb116f3e3 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-net-device.h @@ -0,0 +1,410 @@ +/* -*- 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/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" +#include "ns3/eui48-address.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, Eui48Address addr, CsmaCdEncapsulationMode pktType); + CsmaCdNetDevice (Ptr node, Eui48Address addr, + CsmaCdEncapsulationMode pktType, + bool sendEnable, bool receiveEnable); + /** + * Destroy a CsmaCdNetDevice + * + * This is the destructor for the CsmaCdNetDevice. + */ + virtual ~CsmaCdNetDevice(); + /** + * 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, Eui48Address 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, uint16_t & param); + +private: + // disable copy constructor and operator = + CsmaCdNetDevice &operator = (const CsmaCdNetDevice &o); + CsmaCdNetDevice (const CsmaCdNetDevice &o); + /** + * 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 Address& 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_encapMode; + /** + * 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..46c54a022 --- /dev/null +++ b/src/devices/csma-cd/csma-cd-topology.h @@ -0,0 +1,123 @@ +/* -*- 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" +#include "ns3/node.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/devices/p2p/wscript b/src/devices/p2p/wscript deleted file mode 100644 index 639420dc7..000000000 --- a/src/devices/p2p/wscript +++ /dev/null @@ -1,22 +0,0 @@ -## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- - - -def build(bld): - p2p = bld.create_obj('cpp', 'shlib') - p2p.name = 'ns3-p2p' - p2p.target = p2p.name - p2p.uselib_local = ['ns3-node'] - p2p.source = [ - 'p2p-net-device.cc', - 'p2p-channel.cc', - 'p2p-topology.cc', - ] - p2p.includes = '.' - - headers = bld.create_obj('ns3header') - headers.source = [ - 'p2p-net-device.h', - 'p2p-channel.h', - 'p2p-topology.h', - ] - diff --git a/src/devices/p2p/p2p-channel.cc b/src/devices/point-to-point/point-to-point-channel.cc similarity index 98% rename from src/devices/p2p/p2p-channel.cc rename to src/devices/point-to-point/point-to-point-channel.cc index adceda3f4..ae78010cf 100644 --- a/src/devices/p2p/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/p2p/p2p-channel.h b/src/devices/point-to-point/point-to-point-channel.h similarity index 100% rename from src/devices/p2p/p2p-channel.h rename to src/devices/point-to-point/point-to-point-channel.h 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 new file mode 100644 index 000000000..4b4157b26 --- /dev/null +++ b/src/devices/point-to-point/point-to-point-net-device.cc @@ -0,0 +1,246 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006 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: Craig Dowell + * Revised: George Riley + */ + +#include +#include +#include "ns3/debug.h" +#include "ns3/queue.h" +#include "ns3/simulator.h" +#include "ns3/composite-trace-resolver.h" +#include "ns3/eui48-address.h" +#include "ns3/llc-snap-header.h" +#include "point-to-point-net-device.h" +#include "point-to-point-channel.h" + +NS_DEBUG_COMPONENT_DEFINE ("PointToPointNetDevice"); + +namespace ns3 { + +DataRateDefaultValue PointToPointNetDevice::g_defaultRate( + "PointToPointLinkDataRate", + "The default data rate for point to point links", + DataRate ("10Mb/s")); + +PointToPointNetDevice::PointToPointNetDevice (Ptr node, + const DataRate& rate) +: + NetDevice(node, Eui48Address::Allocate ().ConvertTo ()), + m_txMachineState (READY), + m_bps (rate), + m_tInterframeGap (Seconds(0)), + m_channel (0), + m_queue (0), + m_rxTrace () +{ + NS_DEBUG ("PointToPointNetDevice::PointToPointNetDevice (" << node << ")"); + + // BUGBUG FIXME + // + // You _must_ support broadcast to get any sort of packet from the ARP layer. + EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff").ConvertTo ()); + EnableMulticast(); + EnablePointToPoint(); +} + +PointToPointNetDevice::~PointToPointNetDevice() +{ + NS_DEBUG ("PointToPointNetDevice::~PointToPointNetDevice ()"); + m_queue = 0; +} + +void +PointToPointNetDevice::AddHeader(Packet& p, uint16_t protocolNumber) +{ + LlcSnapHeader llc; + llc.SetType (protocolNumber); + p.AddHeader (llc); +} + +bool +PointToPointNetDevice::ProcessHeader(Packet& p, uint16_t& 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; +} + +void PointToPointNetDevice::SetInterframeGap(const Time& t) +{ + m_tInterframeGap = t; +} + +bool PointToPointNetDevice::SendTo (Packet& p, const Address& dest, + uint16_t protocolNumber) +{ + NS_DEBUG ("PointToPointNetDevice::SendTo (" << &p << ", " << &dest << ")"); + NS_DEBUG ("PointToPointNetDevice::SendTo (): UID is " << p.GetUid () << ")"); + + // GFR Comment. Why is this an assertion? Can't a link legitimately + // "go down" during the simulation? Shouldn't we just wait for it + // to come back up? + NS_ASSERT (IsLinkUp ()); + AddHeader(p, protocolNumber); + +// +// This class simulates a point to point device. In the case of a serial +// link, this means that we're simulating something like a UART. +// +// +// If there's a transmission in progress, we enque the packet for later +// trnsmission; otherwise we send it now. + if (m_txMachineState == READY) + { + return TransmitStart (p); + } + else + { + return m_queue->Enqueue(p); + } +} + + bool +PointToPointNetDevice::TransmitStart (Packet &p) +{ + NS_DEBUG ("PointToPointNetDevice::TransmitStart (" << &p << ")"); + NS_DEBUG ( + "PointToPointNetDevice::TransmitStart (): UID is " << p.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 the transmission is complete. +// + NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit"); + m_txMachineState = BUSY; + Time txTime = Seconds (m_bps.CalculateTxTime(p.GetSize())); + Time txCompleteTime = txTime + m_tInterframeGap; + + NS_DEBUG ("PointToPointNetDevice::TransmitStart (): " << + "Schedule TransmitCompleteEvent in " << + txCompleteTime.GetSeconds () << "sec"); + // Schedule the tx complete event + Simulator::Schedule (txCompleteTime, + &PointToPointNetDevice::TransmitComplete, + this); + return m_channel->TransmitStart(p, this, txTime); +} + +void PointToPointNetDevice::TransmitComplete (void) +{ + NS_DEBUG ("PointToPointNetDevice::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 +// get the next packet from the queue. If the queue is empty, we are +// done, otherwise transmit the next packet. +// + NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting"); + m_txMachineState = READY; + Packet p; + if (!m_queue->Dequeue(p)) return; // Nothing to do at this point + TransmitStart(p); +} + +TraceResolver* PointToPointNetDevice::DoCreateTraceResolver ( + TraceContext const &context) +{ + CompositeTraceResolver *resolver = new CompositeTraceResolver (context); + resolver->Add ("queue", + MakeCallback (&Queue::CreateTraceResolver, PeekPointer (m_queue)), + PointToPointNetDevice::QUEUE); + resolver->Add ("rx", + m_rxTrace, + PointToPointNetDevice::RX); + return resolver; +} + +bool PointToPointNetDevice::Attach (Ptr ch) +{ + NS_DEBUG ("PointToPointNetDevice::Attach (" << &ch << ")"); + + m_channel = ch; + + m_channel->Attach(this); + m_bps = m_channel->GetDataRate (); + // GFR Comment. Below is definitely wrong. Interframe gap + // is unrelated to channel delay. + //m_tInterframeGap = m_channel->GetDelay (); + + /* + * For now, this device is up whenever a channel is attached to it. + * In fact, it should become up only when the second device + * is attached to the channel. So, there should be a way for + * a PointToPointChannel to notify both of its attached devices + * that the channel is 'complete', hence that the devices are + * up, hence that they can call NotifyLinkUp. + */ + NotifyLinkUp (); + return true; +} + +void PointToPointNetDevice::AddQueue (Ptr q) +{ + NS_DEBUG ("PointToPointNetDevice::AddQueue (" << q << ")"); + + m_queue = q; +} + +void PointToPointNetDevice::Receive (Packet& p) +{ + NS_DEBUG ("PointToPointNetDevice::Receive (" << &p << ")"); + uint16_t param = 0; + Packet packet = p; + + ProcessHeader(packet, param); + m_rxTrace (packet); + ForwardUp (packet, param); +} + +Ptr PointToPointNetDevice::GetQueue(void) const +{ + return m_queue; +} + +Ptr PointToPointNetDevice::DoGetChannel(void) const +{ + return m_channel; +} + +bool PointToPointNetDevice::DoNeedsArp (void) const +{ + return false; +} + +} // namespace ns3 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 new file mode 100644 index 000000000..77a55a8dc --- /dev/null +++ b/src/devices/point-to-point/point-to-point-net-device.h @@ -0,0 +1,305 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 University of Washington + * + * 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: Craig Dowell + */ + +#ifndef POINT_TO_POINT_NET_DEVICE_H +#define POINT_TO_POINT_NET_DEVICE_H + +#include +#include "ns3/address.h" +#include "ns3/node.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/default-value.h" +#include "ns3/ptr.h" + +namespace ns3 { + +class Queue; +class PointToPointChannel; + +/** + * \class PointToPointNetDevice + * \brief A Device for a Point to Point Network Link. + * + * Ns-3 takes a four-layer view of a protocol stack. This is the same model + * that TCP uses. In this view, layers 5-7 of the OSI reference model are + * grouped together into an application layer; layer four (transport / TCP) is + * broken out; layer three (network / IP) is broken out; and layers 1-2 are + * grouped together. We call this grouping of layers one and two a NetDevice + * and represent it as a class in the system. + * + * The NetDevice class is specialized according to the needs of the specific + * kind of network link. In this case, the link is a PointToPoint link. The + * PointToPoint link is a family of classes that includes this class, the + * PointToPointNetDevice, a PointToPointChannel class that represents the + * actual medium across which bits are sent, a PointToPointIpv4Interface class + * that provides the hook to tie a general purpose node to this specific + * link, and finally, a PointToPointTopology object that is responsible for + * putting all of the pieces together. + * + * This is the PointToPointNetDevice class that represents, essentially, the + * PC card that is used to connect to the PointToPoint network. + */ +class PointToPointNetDevice : 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) */ + }; + /** + * Construct a PointToPointNetDevice + * + * This is the constructor for the PointToPointNetDevice. 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 deleded. + * + * @see PointToPointTopology::AddPointToPointLink () + * @param node the Node to which this device is connected. + */ + PointToPointNetDevice (Ptr node, + const DataRate& = g_defaultRate.GetValue()); + /** + * Destroy a PointToPointNetDevice + * + * This is the destructor for the PointToPointNetDevice. + */ + virtual ~PointToPointNetDevice(); + /** + * 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(const 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(const Time& t); + /** + * Attach the device to a channel. + * + * The PointToPointTopology object creates a PointToPointChannel and two + * PointtoPointNetDevices. In order to introduce these components to each + * other, the topology object calls Attach () on each PointToPointNetDevice. + * Inside this method, the Net Device calls out to the PointToPointChannel + * to introduce itself. + * + * @see PointToPointTopology::AddPointToPointLink () + * @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 PointToPointNetDevice. + * + * The PointToPointNetDevice "owns" a queue. This queue is created by the + * PointToPointTopology object and implements a queueing method such as + * DropTail or RED. The PointToPointNetDevice assumes ownership of this + * queue and must delete it when the device is destroyed. + * + * @see PointToPointTopology::AddPointToPointLink () + * @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 PointToPointChannel. + * + * The PointToPointNetDevice 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 PointToPointChannel + * @param p a reference to the received packet + */ + void Receive (Packet& p); +protected: + 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. + * + * @see PointToPointTopology + * @returns 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 + * + * @see PointToPointChannel + * @returns a pointer to the channel + */ + virtual Ptr DoGetChannel(void) const; + /** + * Set a new default data rate + * @param Data rate to set for new default + */ + static void SetDefaultRate(const DataRate&); + + /** + * Get the current default rate. + * @returns a const reference to current default + */ + + static const DataRate& GetDefaultRate(); + +private: + /** + * 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, 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, uint16_t& param); + /** + * Send a Packet Down the Wire. + * + * The SendTo method is defined as the standard way that the level three + * protocol uses to tell a NetDevice to send a packet. SendTo is declared + * as abstract in the NetDevice class and we declare it here. + * + * @see NetDevice + * @param p a reference to the packet to send + * @param dest a reference to the Address 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 Address& dest, + uint16_t protocolNumber); + /** + * Start Sending a Packet Down the Wire. + * + * The TransmitStart method is the method that is used internally in the + * PointToPointNetDevice 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. An event is scheduled for the time at which + * the bits have been completely transmitted. + * + * @see PointToPointChannel::TransmitStart () + * @see TransmitCompleteEvent () + * @param p a reference to the packet to send + * @returns true if success, false on failure + */ + bool TransmitStart (Packet &p); + /** + * Stop Sending a Packet Down the Wire and Begin the Interframe Gap. + * + * The TransmitComplete method is used internally to finish the process + * of sending a packet out on the channel. + * + */ + void TransmitComplete(void); + /** + * Create a Trace Resolver for events in the net device. + * + * @see class TraceResolver + */ + virtual TraceResolver* DoCreateTraceResolver (TraceContext const &context); + virtual bool DoNeedsArp (void) const; + /** + * 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 */ + }; + /** + * The state of the Net Device transmit state machine. + * @see TxMachineState + */ + TxMachineState m_txMachineState; + /** + * 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; + /** + * The PointToPointChannel to which this PointToPointNetDevice has been + * attached. + * @see class PointToPointChannel + */ + Ptr m_channel; + /** + * The Queue which this PointToPointNetDevice uses as a packet source. + * Management of this Queue has been delegated to the PointToPointNetDevice + * and it has the responsibility for deletion. + * @see class Queue + * @see class DropTailQueue + */ + Ptr m_queue; + /** + * The trace source for the packet reception events that the device can + * fire. + * + * @see class CallBackTraceSource + * @see class TraceResolver + */ + CallbackTraceSource m_rxTrace; + /** + * Default data rate. Used for all newly created p2p net devices + */ + static DataRateDefaultValue g_defaultRate; + +}; + +}; // namespace ns3 + +#endif // POINT_TO_POINT_NET_DEVICE_H + diff --git a/src/devices/p2p/p2p-topology.cc b/src/devices/point-to-point/point-to-point-topology.cc similarity index 97% rename from src/devices/p2p/p2p-topology.cc rename to src/devices/point-to-point/point-to-point-topology.cc index 0b0ee003b..5a9558419 100644 --- a/src/devices/p2p/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/p2p/p2p-topology.h b/src/devices/point-to-point/point-to-point-topology.h similarity index 100% rename from src/devices/p2p/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 new file mode 100644 index 000000000..77c26fd80 --- /dev/null +++ b/src/devices/point-to-point/wscript @@ -0,0 +1,20 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + 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', + ] + headers = bld.create_obj('ns3header') + headers.source = [ + 'point-to-point-net-device.h', + 'point-to-point-channel.h', + 'point-to-point-topology.h', + ] + diff --git a/src/internet-node/arp-cache.cc b/src/internet-node/arp-cache.cc index 4b166c99b..b4987daef 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-header.cc b/src/internet-node/arp-header.cc index dc8cd3f7a..7ca91e8bf 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/arp-ipv4-interface.cc b/src/internet-node/arp-ipv4-interface.cc index 9319929c2..d5a9105fe 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" @@ -61,7 +62,19 @@ ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest) { Ptr arp = m_node->QueryInterface (ArpPrivate::iid); Address 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 583b4e574..947d5fc42 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, Address 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); 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/ipv4-impl.cc b/src/internet-node/ipv4-impl.cc index 9c7754be9..307425114 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, + int16_t 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..445c10454 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, + int16_t 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 4a46290e6..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, PtrSetUp (); + + // 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/internet-node/ipv4-l3-protocol.h b/src/internet-node/ipv4-l3-protocol.h index 7c9894d27..b41b6aefa 100644 --- a/src/internet-node/ipv4-l3-protocol.h +++ b/src/internet-node/ipv4-l3-protocol.h @@ -27,8 +27,11 @@ #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" +#include "ipv4-static-routing.h" namespace ns3 { @@ -124,7 +127,10 @@ public: void SetDefaultRoute (Ipv4Address nextHop, uint32_t interface); - Ipv4Route *Lookup (Ipv4Address dest); + void Lookup (Ipv4Header const &ipHeader, + Packet packet, + Ipv4RoutingProtocol::RouteReplyCallback routeReply); + uint32_t GetNRoutes (void); Ipv4Route *GetRoute (uint32_t i); void RemoveRoute (uint32_t i); @@ -143,11 +149,19 @@ public: void SetUp (uint32_t i); void SetDown (uint32_t i); + void AddRoutingProtocol (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/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 diff --git a/src/internet-node/wscript b/src/internet-node/wscript index cf412d6c8..7a1b1c10e 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', @@ -24,7 +25,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', @@ -34,11 +34,11 @@ def build(bld): 'pcap-trace.cc', 'udp-impl.cc', ] - obj.includes = '.' headers = bld.create_obj('ns3header') headers.source = [ 'internet-node.h', 'ascii-trace.h', 'pcap-trace.h', + 'ipv4-header.h', ] 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/internet-node/header-utils.cc b/src/node/address-utils.cc similarity index 79% rename from src/internet-node/header-utils.cc rename to src/node/address-utils.cc index 64bb29285..08c5b1736 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 { @@ -26,12 +26,18 @@ void WriteTo (Buffer::Iterator &i, Ipv4Address ad) { i.WriteHtonU32 (ad.GetHostOrder ()); } -void WriteTo (Buffer::Iterator &i, Address ad) +void WriteTo (Buffer::Iterator &i, const Address &ad) { uint8_t mac[Address::MAX_SIZE]; ad.CopyTo (mac); i.Write (mac, ad.GetLength ()); } +void WriteTo (Buffer::Iterator &i, Eui48Address ad) +{ + uint8_t mac[6]; + ad.CopyTo (mac); + i.Write (mac, 6); +} void ReadFrom (Buffer::Iterator &i, Ipv4Address &ad) { @@ -43,7 +49,11 @@ void ReadFrom (Buffer::Iterator &i, Address &ad, uint32_t len) i.Read (mac, len); ad.CopyFrom (mac, len); } +void ReadFrom (Buffer::Iterator &i, Eui48Address &ad) +{ + uint8_t mac[6]; + i.Read (mac, 6); + ad.CopyFrom (mac); +} - - -}; // namespace ns3 +} // namespace ns3 diff --git a/src/internet-node/header-utils.h b/src/node/address-utils.h similarity index 77% rename from src/internet-node/header-utils.h rename to src/node/address-utils.h index 88d3dfe10..1403c544a 100644 --- a/src/internet-node/header-utils.h +++ b/src/node/address-utils.h @@ -18,21 +18,24 @@ * * 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" -#include "ns3/address.h" +#include "ipv4-address.h" +#include "address.h" +#include "eui48-address.h" namespace ns3 { void WriteTo (Buffer::Iterator &i, Ipv4Address ad); -void WriteTo (Buffer::Iterator &i, Address ad); +void WriteTo (Buffer::Iterator &i, const Address &ad); +void WriteTo (Buffer::Iterator &i, Eui48Address ad); void ReadFrom (Buffer::Iterator &i, Ipv4Address &ad); void ReadFrom (Buffer::Iterator &i, Address &ad, uint32_t len); +void ReadFrom (Buffer::Iterator &i, Eui48Address &ad); }; -#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..76c3ed609 --- /dev/null +++ b/src/node/ethernet-header.cc @@ -0,0 +1,163 @@ +/* -*- 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 { + +EthernetHeader::EthernetHeader (bool hasPreamble) + : m_enPreambleSfd (hasPreamble), + m_lengthType (0) +{} + +EthernetHeader::EthernetHeader () + : m_enPreambleSfd (false), + m_lengthType (0) +{} + +EthernetHeader::~EthernetHeader () +{} + +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 (Eui48Address source) +{ + m_source = source; +} +Eui48Address +EthernetHeader::GetSource (void) const +{ + return m_source; +} + +void +EthernetHeader::SetDestination (Eui48Address dst) +{ + m_destination = dst; +} +Eui48Address +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); + } + 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); + ReadFrom (i, m_source); + 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..8195dfd10 --- /dev/null +++ b/src/node/ethernet-header.h @@ -0,0 +1,127 @@ +/* -*- 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/eui48-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 + * \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 (); + /** + * \param size The size of the payload in bytes + */ + void SetLengthType (uint16_t size); + /** + * \param source The source address of this packet + */ + void SetSource (Eui48Address source); + /** + * \param destination The destination address of this packet. + */ + void SetDestination (Eui48Address 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 + */ + Eui48Address GetSource (void) const; + /** + * \return The destination address of this packet + */ + Eui48Address 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); + + /** + * If false, the preamble/sfd are not serialised/deserialised. + */ + bool m_enPreambleSfd; + uint64_t m_preambleSfd; /// Value of the Preamble/SFD fields + uint16_t m_lengthType; /// Length or type of the packet + Eui48Address m_source; /// Source address + Eui48Address 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/eui48-address.cc b/src/node/eui48-address.cc index a3ed8fd4e..a5944d146 100644 --- a/src/node/eui48-address.cc +++ b/src/node/eui48-address.cc @@ -1,6 +1,7 @@ #include "eui48-address.h" #include "address.h" #include "ns3/assert.h" +#include namespace ns3 { @@ -58,6 +59,17 @@ Eui48Address::Eui48Address (const char *str) } NS_ASSERT (i == 6); } +void +Eui48Address::CopyFrom (const uint8_t buffer[6]) +{ + memcpy (m_address, buffer, 6); +} +void +Eui48Address::CopyTo (uint8_t buffer[6]) const +{ + memcpy (buffer, m_address, 6); +} + Address Eui48Address::ConvertTo (void) const { @@ -92,5 +104,36 @@ Eui48Address::GetType (void) return type; } +bool operator == (const Eui48Address &a, const Eui48Address &b) +{ + uint8_t ada[6]; + uint8_t adb[6]; + a.CopyTo (ada); + b.CopyTo (adb); + return memcmp (ada, adb, 6) == 0; +} +bool operator != (const Eui48Address &a, const Eui48Address &b) +{ + return ! (a == b); +} + +std::ostream& operator<< (std::ostream& os, const Eui48Address & address) +{ + uint8_t ad[6]; + address.CopyTo (ad); + + os.setf (std::ios::hex, std::ios::basefield); + std::cout.fill('0'); + for (uint8_t i=0; i < 5; i++) + { + os << std::setw(2) << (uint32_t)ad[i] << ":"; + } + // Final byte not suffixed by ":" + os << std::setw(2) << (uint32_t)ad[5]; + os.setf (std::ios::dec, std::ios::basefield); + std::cout.fill(' '); + return os; +} + } // namespace ns3 diff --git a/src/node/eui48-address.h b/src/node/eui48-address.h index d113503db..ad045f078 100644 --- a/src/node/eui48-address.h +++ b/src/node/eui48-address.h @@ -2,6 +2,7 @@ #define EUI48_ADDRESS_H #include +#include namespace ns3 { @@ -22,6 +23,19 @@ public: * The format of the string is "xx:xx:xx:xx:xx:xx" */ Eui48Address (const char *str); + + /** + * \param buffer address in network order + * + * Copy the input address to our internal buffer. + */ + void CopyFrom (const uint8_t buffer[6]); + /** + * \param buffer address in network order + * + * Copy the internal address to the input buffer. + */ + void CopyTo (uint8_t buffer[6]) const; /** * \returns a new Address instance * @@ -42,9 +56,12 @@ public: private: static uint8_t GetType (void); uint8_t m_address[6]; - }; +bool operator == (const Eui48Address &a, const Eui48Address &b); +bool operator != (const Eui48Address &a, const Eui48Address &b); +std::ostream& operator<< (std::ostream& os, const Eui48Address & address); + } // namespace ns3 #endif /* EUI48_ADDRESS_H */ diff --git a/src/node/ipv4-address.cc b/src/node/ipv4-address.cc index 5c923f06f..67028125d 100644 --- a/src/node/ipv4-address.cc +++ b/src/node/ipv4-address.cc @@ -145,8 +145,20 @@ Ipv4Address::IsEqual (Ipv4Address other) const } } +Ipv4Address +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 2012d2f78..9911d24c4 100644 --- a/src/node/ipv4-address.h +++ b/src/node/ipv4-address.h @@ -28,6 +28,8 @@ namespace ns3 { +class Ipv4Mask; + /** Ipv4 addresses are stored in host order in * this class. */ @@ -89,8 +91,18 @@ 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 + * + * 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; Address ConvertTo (void) const; static Ipv4Address ConvertFrom (const Address &address); diff --git a/src/node/ipv4.h b/src/node/ipv4.h index 1424884af..76d88faea 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,78 @@ namespace ns3 { class NetDevice; class Packet; 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); + + + /** + * \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 + * \param routeReply callback that will receive the route reply + * + * \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 (const Ipv4Header &ipHeader, + Packet packet, + RouteReplyCallback routeReply) = 0; +}; + /** * \brief Access to the Ipv4 forwarding table and to the ipv4 interfaces * @@ -47,7 +120,20 @@ public: static const InterfaceId iid; 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, + int16_t priority) = 0; + /** * \param dest destination address * \param nextHop address of next hop. diff --git a/src/node/net-device.cc b/src/node/net-device.cc index 1a9163aad..a7ef06c7a 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 Address& 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 9dace11e5..88109a894 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 Address& dest) = 0; + virtual bool SendTo (Packet& p, const Address &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; Address 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 diff --git a/src/node/wscript b/src/node/wscript index d02aea513..47f5b09a2 100644 --- a/src/node/wscript +++ b/src/node/wscript @@ -12,7 +12,10 @@ def build(bld): 'node.cc', 'ipv4-address.cc', 'net-device.cc', + 'address-utils.cc', 'llc-snap-header.cc', + 'ethernet-header.cc', + 'ethernet-trailer.cc', 'ipv4-route.cc', 'queue.cc', 'drop-tail-queue.cc', @@ -24,7 +27,6 @@ def build(bld): 'ipv4.cc', 'application.cc', ] - node.includes = '.' headers = bld.create_obj('ns3header') headers.source = [ @@ -34,10 +36,13 @@ def build(bld): 'node.h', 'ipv4-address.h', 'net-device.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', 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 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 = [ diff --git a/src/wscript b/src/wscript index 4b34a9156..32c7bdde0 100644 --- a/src/wscript +++ b/src/wscript @@ -15,7 +15,8 @@ all_modules = ( 'simulator', 'node', 'internet-node', - 'devices/p2p', + 'devices/point-to-point', + 'devices/csma-cd', 'applications', 'mobility', )