--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/csma-system-test-suite.cc Fri Oct 15 16:31:32 2010 -0700
@@ -0,0 +1,1126 @@
+/* -*- 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
+ */
+
+// This is not a test of CsmaNetDevice model behavior per-se, but
+// instead is a roll up of several end-to-end examples in examples/csma
+// directory, converted into system tests. Writing a test suite
+// to test Csma itself is for further study.
+
+#include <string>
+
+#include "ns3/address.h"
+#include "ns3/application-container.h"
+#include "ns3/bridge-helper.h"
+#include "ns3/callback.h"
+#include "ns3/config.h"
+#include "ns3/csma-helper.h"
+#include "ns3/csma-star-helper.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/ipv4-global-routing-helper.h"
+#include "ns3/ipv4-static-routing-helper.h"
+#include "ns3/node.h"
+#include "ns3/node-container.h"
+#include "ns3/on-off-helper.h"
+#include "ns3/packet.h"
+#include "ns3/packet-sink-helper.h"
+#include "ns3/packet-socket-helper.h"
+#include "ns3/packet-socket-address.h"
+#include "ns3/pointer.h"
+#include "ns3/random-variable.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simulator.h"
+#include "ns3/string.h"
+#include "ns3/test.h"
+#include "ns3/uinteger.h"
+#include "ns3/v4ping-helper.h"
+
+using namespace ns3;
+
+class CsmaBridgeTestCase : public TestCase
+{
+public:
+ CsmaBridgeTestCase ();
+ virtual ~CsmaBridgeTestCase ();
+
+private:
+ virtual bool DoRun (void);
+ void SinkRx (Ptr<const Packet> p, const Address &ad);
+ uint32_t m_count;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaBridgeTestCase::CsmaBridgeTestCase ()
+ : TestCase ("Bridge example for Carrier Sense Multiple Access (CSMA) networks"), m_count (0)
+{
+}
+
+CsmaBridgeTestCase::~CsmaBridgeTestCase ()
+{
+}
+
+void
+CsmaBridgeTestCase::SinkRx (Ptr<const Packet> p, const Address &ad)
+{
+ m_count++;
+}
+
+// Network topology
+//
+// n0 n1
+// | |
+// ----------
+// | Switch |
+// ----------
+// | |
+// n2 n3
+//
+// - CBR/UDP test flow from n0 to n1; test that packets received on n1
+//
+bool
+CsmaBridgeTestCase::DoRun (void)
+{
+ NodeContainer terminals;
+ terminals.Create (4);
+
+ NodeContainer csmaSwitch;
+ csmaSwitch.Create (1);
+
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+ csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+
+ NetDeviceContainer terminalDevices;
+ NetDeviceContainer switchDevices;
+
+ for (int i = 0; i < 4; i++)
+ {
+ NetDeviceContainer link = csma.Install (NodeContainer (terminals.Get (i), csmaSwitch));
+ terminalDevices.Add (link.Get (0));
+ switchDevices.Add (link.Get (1));
+ }
+
+ // Create the bridge netdevice, which will do the packet switching
+ Ptr<Node> switchNode = csmaSwitch.Get (0);
+ BridgeHelper bridge;
+ bridge.Install (switchNode, switchDevices);
+
+ InternetStackHelper internet;
+ internet.Install (terminals);
+
+ Ipv4AddressHelper ipv4;
+ ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+ ipv4.Assign (terminalDevices);
+
+ uint16_t port = 9; // Discard port (RFC 863)
+
+ // Create the OnOff application to send UDP datagrams from n0 to n1.
+ //
+ // Make packets be sent about every DefaultPacketSize / DataRate =
+ // 4096 bits / (5000 bits/second) = 0.82 second.
+ OnOffHelper onoff ("ns3::UdpSocketFactory",
+ Address (InetSocketAddress (Ipv4Address ("10.1.1.2"), port)));
+ onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+ onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+ onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+ ApplicationContainer app = onoff.Install (terminals.Get (0));
+ app.Start (Seconds (1.0));
+ app.Stop (Seconds (10.0));
+
+ PacketSinkHelper sink ("ns3::UdpSocketFactory",
+ Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+ app = sink.Install (terminals.Get (1));
+ app.Start (Seconds (0.0));
+
+ // Trace receptions
+ Config::ConnectWithoutContext ("/NodeList/1/ApplicationList/0/$ns3::PacketSink/Rx", MakeCallback (&CsmaBridgeTestCase::SinkRx, this));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ // We should have sent and received 10 packets
+ NS_TEST_ASSERT_MSG_EQ (m_count, 10, "Bridge should have passed 10 packets");
+
+ return GetErrorStatus ();
+}
+
+class CsmaBroadcastTestCase : public TestCase
+{
+public:
+ CsmaBroadcastTestCase ();
+ virtual ~CsmaBroadcastTestCase ();
+
+private:
+ virtual bool DoRun (void);
+ void SinkRxNode1 (Ptr<const Packet> p, const Address &ad);
+ void SinkRxNode2 (Ptr<const Packet> p, const Address &ad);
+ void DropEvent (Ptr<const Packet> p);
+ uint32_t m_countNode1;
+ uint32_t m_countNode2;
+ uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaBroadcastTestCase::CsmaBroadcastTestCase ()
+ : TestCase ("Broadcast example for Carrier Sense Multiple Access (CSMA) networks"), m_countNode1 (0), m_countNode2 (0), m_drops (0)
+{
+}
+
+CsmaBroadcastTestCase::~CsmaBroadcastTestCase ()
+{
+}
+
+void
+CsmaBroadcastTestCase::SinkRxNode1 (Ptr<const Packet> p, const Address &ad)
+{
+ m_countNode1++;
+}
+
+void
+CsmaBroadcastTestCase::SinkRxNode2 (Ptr<const Packet> p, const Address &ad)
+{
+ m_countNode2++;
+}
+
+void
+CsmaBroadcastTestCase::DropEvent (Ptr<const Packet> p)
+{
+ m_drops++;
+}
+
+//
+// Example of the sending of a datagram to a broadcast address
+//
+// Network topology
+// ==============
+// | |
+// n0 n1 n2
+// | |
+// ==========
+//
+// n0 originates UDP broadcast to 255.255.255.255/discard port, which
+// is replicated and received on both n1 and n2
+//
+bool
+CsmaBroadcastTestCase::DoRun (void)
+{
+ NodeContainer c;
+ c.Create (3);
+ NodeContainer c0 = NodeContainer (c.Get (0), c.Get (1));
+ NodeContainer c1 = NodeContainer (c.Get (0), c.Get (2));
+
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate(5000000)));
+ csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds(2)));
+
+ NetDeviceContainer n0 = csma.Install (c0);
+ NetDeviceContainer n1 = csma.Install (c1);
+
+ InternetStackHelper internet;
+ internet.Install (c);
+
+ Ipv4AddressHelper ipv4;
+ ipv4.SetBase ("10.1.0.0", "255.255.255.0");
+ ipv4.Assign (n0);
+ ipv4.SetBase ("192.168.1.0", "255.255.255.0");
+ ipv4.Assign (n1);
+
+
+ // RFC 863 discard port ("9") indicates packet should be thrown away
+ // by the system. We allow this silent discard to be overridden
+ // by the PacketSink application.
+ uint16_t port = 9;
+
+ // Create the OnOff application to send UDP datagrams from n0.
+ //
+ // Make packets be sent about every DefaultPacketSize / DataRate =
+ // 4096 bits / (5000 bits/second) = 0.82 second.
+ OnOffHelper onoff ("ns3::UdpSocketFactory",
+ Address (InetSocketAddress (Ipv4Address ("255.255.255.255"), port)));
+ onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+ onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+ onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+ ApplicationContainer app = onoff.Install (c0.Get (0));
+ // Start the application
+ app.Start (Seconds (1.0));
+ app.Stop (Seconds (10.0));
+
+ // Create an optional packet sink to receive these packets
+ PacketSinkHelper sink ("ns3::UdpSocketFactory",
+ Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+ app = sink.Install (c0.Get (1));
+ app.Add (sink.Install (c1.Get (1)));
+ app.Start (Seconds (1.0));
+ app.Stop (Seconds (10.0));
+
+ // Trace receptions
+ Config::ConnectWithoutContext ("/NodeList/1/ApplicationList/0/$ns3::PacketSink/Rx", MakeCallback (&CsmaBroadcastTestCase::SinkRxNode1, this));
+ Config::ConnectWithoutContext ("/NodeList/2/ApplicationList/0/$ns3::PacketSink/Rx", MakeCallback (&CsmaBroadcastTestCase::SinkRxNode2, this));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ // We should have sent and received 10 packets
+ NS_TEST_ASSERT_MSG_EQ (m_countNode1, 10, "Node 1 should have received 10 packets");
+ NS_TEST_ASSERT_MSG_EQ (m_countNode2, 10, "Node 2 should have received 10 packets");
+
+ return GetErrorStatus ();
+}
+
+class CsmaMulticastTestCase : public TestCase
+{
+public:
+ CsmaMulticastTestCase ();
+ virtual ~CsmaMulticastTestCase ();
+
+private:
+ virtual bool DoRun (void);
+ void SinkRx (Ptr<const Packet> p, const Address &ad);
+ void DropEvent (Ptr<const Packet> p);
+ uint32_t m_count;
+ uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaMulticastTestCase::CsmaMulticastTestCase ()
+ : TestCase ("Multicast example for Carrier Sense Multiple Access (CSMA) networks"), m_count (0), m_drops (0)
+{
+}
+
+CsmaMulticastTestCase::~CsmaMulticastTestCase ()
+{
+}
+
+void
+CsmaMulticastTestCase::SinkRx (Ptr<const Packet> p, const Address& ad)
+{
+ m_count++;
+}
+
+void
+CsmaMulticastTestCase::DropEvent (Ptr<const Packet> p)
+{
+ m_drops++;
+}
+
+// Network topology
+//
+// Lan1
+// ===========
+// | | |
+// n0 n1 n2 n3 n4
+// | | |
+// ===========
+// Lan0
+//
+// - Multicast source is at node n0;
+// - Multicast forwarded by node n2 onto LAN1;
+// - Nodes n0, n1, n2, n3, and n4 receive the multicast frame.
+// - Node n4 listens for the data
+//
+bool
+CsmaMulticastTestCase::DoRun (void)
+{
+ //
+ // Set up default values for the simulation.
+ //
+ // Select DIX/Ethernet II-style encapsulation (no LLC/Snap header)
+ Config::SetDefault ("ns3::CsmaNetDevice::EncapsulationMode", StringValue ("Dix"));
+
+ NodeContainer c;
+ c.Create (5);
+ // We will later want two subcontainers of these nodes, for the two LANs
+ NodeContainer c0 = NodeContainer (c.Get (0), c.Get (1), c.Get (2));
+ NodeContainer c1 = NodeContainer (c.Get (2), c.Get (3), c.Get (4));
+
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000)));
+ csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+
+ // We will use these NetDevice containers later, for IP addressing
+ NetDeviceContainer nd0 = csma.Install (c0); // First LAN
+ NetDeviceContainer nd1 = csma.Install (c1); // Second LAN
+
+ InternetStackHelper internet;
+ internet.Install (c);
+
+ Ipv4AddressHelper ipv4Addr;
+ ipv4Addr.SetBase ("10.1.1.0", "255.255.255.0");
+ ipv4Addr.Assign (nd0);
+ ipv4Addr.SetBase ("10.1.2.0", "255.255.255.0");
+ ipv4Addr.Assign (nd1);
+
+ //
+ // Now we can configure multicasting. As described above, the multicast
+ // source is at node zero, which we assigned the IP address of 10.1.1.1
+ // earlier. We need to define a multicast group to send packets to. This
+ // can be any multicast address from 224.0.0.0 through 239.255.255.255
+ // (avoiding the reserved routing protocol addresses).
+ //
+
+ Ipv4Address multicastSource ("10.1.1.1");
+ Ipv4Address multicastGroup ("225.1.2.4");
+
+ // Now, we will set up multicast routing. We need to do three things:
+ // 1) Configure a (static) multicast route on node n2
+ // 2) Set up a default multicast route on the sender n0
+ // 3) Have node n4 join the multicast group
+ // We have a helper that can help us with static multicast
+ Ipv4StaticRoutingHelper multicast;
+
+ // 1) Configure a (static) multicast route on node n2 (multicastRouter)
+ Ptr<Node> multicastRouter = c.Get (2); // The node in question
+ Ptr<NetDevice> inputIf = nd0.Get (2); // The input NetDevice
+ NetDeviceContainer outputDevices; // A container of output NetDevices
+ outputDevices.Add (nd1.Get (0)); // (we only need one NetDevice here)
+
+ multicast.AddMulticastRoute (multicastRouter, multicastSource,
+ multicastGroup, inputIf, outputDevices);
+
+ // 2) Set up a default multicast route on the sender n0
+ Ptr<Node> sender = c.Get (0);
+ Ptr<NetDevice> senderIf = nd0.Get(0);
+ multicast.SetDefaultMulticastRoute (sender, senderIf);
+
+ //
+ // Create an OnOff application to send UDP datagrams from node zero to the
+ // multicast group (node four will be listening).
+ //
+
+ uint16_t multicastPort = 9; // Discard port (RFC 863)
+
+ // Configure a multicast packet generator.
+ //
+ // Make packets be sent about every defaultPacketSize / dataRate =
+ // 4096 bits / (5000 bits/second) = 0.82 second.
+ OnOffHelper onoff ("ns3::UdpSocketFactory",
+ Address (InetSocketAddress (multicastGroup, multicastPort)));
+ onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+ onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+ onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+ ApplicationContainer srcC = onoff.Install (c0.Get (0));
+
+ //
+ // Tell the application when to start and stop.
+ //
+ srcC.Start(Seconds(1.));
+ srcC.Stop (Seconds(10.));
+
+ // Create an optional packet sink to receive these packets
+ PacketSinkHelper sink ("ns3::UdpSocketFactory",
+ InetSocketAddress (Ipv4Address::GetAny(), multicastPort));
+
+ ApplicationContainer sinkC = sink.Install (c1.Get (2)); // Node n4
+ // Start the sink
+ sinkC.Start (Seconds (1.0));
+ sinkC.Stop (Seconds (10.0));
+
+ // Trace receptions
+ Config::ConnectWithoutContext ("/NodeList/4/ApplicationList/0/$ns3::PacketSink/Rx", MakeCallback (&CsmaMulticastTestCase::SinkRx, this));
+
+ //
+ // Now, do the actual simulation.
+ //
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ // We should have sent and received 10 packets
+ NS_TEST_ASSERT_MSG_EQ (m_count, 10, "Node 4 should have received 10 packets");
+
+ return GetErrorStatus ();
+}
+
+class CsmaOneSubnetTestCase : public TestCase
+{
+public:
+ CsmaOneSubnetTestCase ();
+ virtual ~CsmaOneSubnetTestCase ();
+
+private:
+ virtual bool DoRun (void);
+ void SinkRxNode0 (Ptr<const Packet> p, const Address &ad);
+ void SinkRxNode1 (Ptr<const Packet> p, const Address &ad);
+ void DropEvent (Ptr<const Packet> p);
+ uint32_t m_countNode0;
+ uint32_t m_countNode1;
+ uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaOneSubnetTestCase::CsmaOneSubnetTestCase ()
+ : TestCase ("One subnet example for Carrier Sense Multiple Access (CSMA) networks"), m_countNode0 (0), m_countNode1 (0), m_drops (0)
+{
+}
+
+CsmaOneSubnetTestCase::~CsmaOneSubnetTestCase ()
+{
+}
+
+void
+CsmaOneSubnetTestCase::SinkRxNode0 (Ptr<const Packet> p, const Address &ad)
+{
+ m_countNode0++;
+}
+
+void
+CsmaOneSubnetTestCase::SinkRxNode1 (Ptr<const Packet> p, const Address &ad)
+{
+ m_countNode1++;
+}
+
+void
+CsmaOneSubnetTestCase::DropEvent (Ptr<const Packet> p)
+{
+ m_drops++;
+}
+
+// Network topology
+//
+// n0 n1 n2 n3
+// | | | |
+// =================
+// LAN
+//
+// - CBR/UDP flows from n0 to n1 and from n3 to n0
+// - DropTail queues
+//
+bool
+CsmaOneSubnetTestCase::DoRun (void)
+{
+ NodeContainer nodes;
+ nodes.Create (4);
+
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+ csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+ //
+ // Now fill out the topology by creating the net devices required to connect
+ // the nodes to the channels and hooking them up.
+ //
+ NetDeviceContainer devices = csma.Install (nodes);
+
+ InternetStackHelper internet;
+ internet.Install (nodes);
+
+ // We've got the "hardware" in place. Now we need to add IP addresses.
+ //
+ Ipv4AddressHelper ipv4;
+ ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
+
+ uint16_t port = 9; // Discard port (RFC 863)
+
+ //
+ // Create an OnOff application to send UDP datagrams from node zero
+ // to node 1.
+ //
+ // Make packets be sent about every defaultPacketSize / dataRate =
+ // 4096 bits / (5000 bits/second) = 0.82 second.
+ OnOffHelper onoff ("ns3::UdpSocketFactory",
+ Address (InetSocketAddress (interfaces.GetAddress (1), port)));
+ onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+ onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+ onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+ ApplicationContainer app = onoff.Install (nodes.Get (0));
+ // Start the application
+ app.Start (Seconds (1.0));
+ app.Stop (Seconds (10.0));
+
+ // Create an optional packet sink to receive these packets
+ PacketSinkHelper sink ("ns3::UdpSocketFactory",
+ Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+ app = sink.Install (nodes.Get (1));
+ app.Start (Seconds (0.0));
+
+ //
+ // Create a similar flow from n3 to n0, starting at time 1.1 seconds
+ //
+ onoff.SetAttribute ("Remote",
+ AddressValue (InetSocketAddress (interfaces.GetAddress (0), port)));
+ app = onoff.Install (nodes.Get (3));
+ app.Start(Seconds (1.1));
+ app.Stop (Seconds (10.0));
+
+ app = sink.Install (nodes.Get (0));
+ app.Start (Seconds (0.0));
+
+ // Trace receptions
+ Config::ConnectWithoutContext ("/NodeList/0/ApplicationList/1/$ns3::PacketSink/Rx", MakeCallback (&CsmaOneSubnetTestCase::SinkRxNode0, this));
+ Config::ConnectWithoutContext ("/NodeList/1/ApplicationList/0/$ns3::PacketSink/Rx", MakeCallback (&CsmaOneSubnetTestCase::SinkRxNode1, this));
+
+ //
+ // Now, do the actual simulation.
+ //
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ // We should have sent and received 10 packets
+ NS_TEST_ASSERT_MSG_EQ (m_countNode0, 10, "Node 0 should have received 10 packets");
+ NS_TEST_ASSERT_MSG_EQ (m_countNode1, 10, "Node 1 should have received 10 packets");
+
+ return GetErrorStatus ();
+}
+
+class CsmaPacketSocketTestCase : public TestCase
+{
+public:
+ CsmaPacketSocketTestCase ();
+ virtual ~CsmaPacketSocketTestCase ();
+
+private:
+ virtual bool DoRun (void);
+ void SinkRx (std::string path, Ptr<const Packet> p, const Address &address);
+ void DropEvent (Ptr<const Packet> p);
+ uint32_t m_count;
+ uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaPacketSocketTestCase::CsmaPacketSocketTestCase ()
+ : TestCase ("Packet socket example for Carrier Sense Multiple Access (CSMA) networks"), m_count (0), m_drops (0)
+{
+}
+
+CsmaPacketSocketTestCase::~CsmaPacketSocketTestCase ()
+{
+}
+
+void
+CsmaPacketSocketTestCase::SinkRx (std::string path, Ptr<const Packet> p, const Address& address)
+{
+ m_count++;
+}
+
+void
+CsmaPacketSocketTestCase::DropEvent (Ptr<const Packet> p)
+{
+ m_drops++;
+}
+
+//
+// Network topology
+//
+// n0 n1 n2 n3
+// | | | |
+// =====================
+//
+// - Packet socket flow from n0 to n1 and from node n3 to n0
+// -- We will test reception at node n0
+// - Default 512 byte packets generated by traffic generator
+//
+bool
+CsmaPacketSocketTestCase::DoRun (void)
+{
+ // Here, we will explicitly create four nodes.
+ NodeContainer nodes;
+ nodes.Create (4);
+
+ PacketSocketHelper packetSocket;
+ packetSocket.Install (nodes);
+
+ // create the shared medium used by all csma devices.
+ Ptr<CsmaChannel> channel = CreateObjectWithAttributes<CsmaChannel> (
+ "DataRate", DataRateValue (DataRate(5000000)),
+ "Delay", TimeValue (MilliSeconds(2)));
+
+ // use a helper function to connect our nodes to the shared channel.
+ CsmaHelper csma;
+ csma.SetDeviceAttribute ("EncapsulationMode", StringValue ("Llc"));
+ NetDeviceContainer devs = csma.Install (nodes, channel);
+
+ // Create the OnOff application to send raw datagrams
+ //
+ // Make packets be sent about every DefaultPacketSize / DataRate =
+ // 4096 bits / (5000 bits/second) = 0.82 second.
+ PacketSocketAddress socket;
+ socket.SetSingleDevice(devs.Get (0)->GetIfIndex ());
+ socket.SetPhysicalAddress (devs.Get (1)->GetAddress ());
+ socket.SetProtocol (2);
+ OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
+ onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1.0)));
+ onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0.0)));
+ onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+ ApplicationContainer apps = onoff.Install (nodes.Get (0));
+ apps.Start (Seconds (1.0));
+ apps.Stop (Seconds (10.0));
+
+ socket.SetSingleDevice (devs.Get (3)->GetIfIndex ());
+ socket.SetPhysicalAddress (devs.Get (0)->GetAddress ());
+ socket.SetProtocol (3);
+ onoff.SetAttribute ("Remote", AddressValue (socket));
+ onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0.0)));
+ apps = onoff.Install (nodes.Get (3));
+ apps.Start (Seconds (1.0));
+ apps.Stop (Seconds (10.0));
+
+ PacketSinkHelper sink = PacketSinkHelper ("ns3::PacketSocketFactory",
+ socket);
+ apps = sink.Install (nodes.Get (0));
+ apps.Start (Seconds (0.0));
+ apps.Stop (Seconds (20.0));
+
+ // Trace receptions
+ Config::Connect ("/NodeList/0/ApplicationList/*/$ns3::PacketSink/Rx",
+ MakeCallback (&CsmaPacketSocketTestCase::SinkRx, this));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ // We should have received 10 packets on node 0
+ NS_TEST_ASSERT_MSG_EQ (m_count, 10, "Node 0 should have received 10 packets");
+
+ return GetErrorStatus ();
+}
+
+class CsmaPingTestCase : public TestCase
+{
+public:
+ CsmaPingTestCase ();
+ virtual ~CsmaPingTestCase ();
+
+private:
+ virtual bool DoRun (void);
+ void SinkRx (Ptr<const Packet> p, const Address &ad);
+ void PingRtt (std::string context, Time rtt);
+ void DropEvent (Ptr<const Packet> p);
+ uint32_t m_countSinkRx;
+ uint32_t m_countPingRtt;
+ uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaPingTestCase::CsmaPingTestCase ()
+ : TestCase ("Ping example for Carrier Sense Multiple Access (CSMA) networks"), m_countSinkRx (0), m_countPingRtt (0), m_drops (0)
+{
+}
+
+CsmaPingTestCase::~CsmaPingTestCase ()
+{
+}
+
+void
+CsmaPingTestCase::SinkRx (Ptr<const Packet> p, const Address &ad)
+{
+ m_countSinkRx++;
+}
+
+void
+CsmaPingTestCase::PingRtt (std::string context, Time rtt)
+{
+ m_countPingRtt++;
+}
+
+void
+CsmaPingTestCase::DropEvent (Ptr<const Packet> p)
+{
+ m_drops++;
+}
+
+// Network topology
+//
+// n0 n1 n2 n3
+// | | | |
+// =====================
+//
+// node n0,n1,n3 pings to node n2
+// node n0 generates protocol 2 (IGMP) to node n3
+//
+bool
+CsmaPingTestCase::DoRun (void)
+{
+ // Here, we will explicitly create four nodes.
+ NodeContainer c;
+ c.Create (4);
+
+ // connect all our nodes to a shared channel.
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000)));
+ csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+ csma.SetDeviceAttribute ("EncapsulationMode", StringValue ("Llc"));
+ NetDeviceContainer devs = csma.Install (c);
+
+ // add an ip stack to all nodes.
+ InternetStackHelper ipStack;
+ ipStack.Install (c);
+
+ // assign ip addresses
+ Ipv4AddressHelper ip;
+ ip.SetBase ("192.168.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer addresses = ip.Assign (devs);
+
+ // Create the OnOff application to send UDP datagrams from n0 to n1.
+ //
+ // Make packets be sent about every DefaultPacketSize / DataRate =
+ // 4096 bits / (5000 bits/second) = 0.82 second.
+ Config::SetDefault ("ns3::Ipv4RawSocketImpl::Protocol", StringValue ("2"));
+ InetSocketAddress dst = InetSocketAddress (addresses.GetAddress (3));
+ OnOffHelper onoff = OnOffHelper ("ns3::Ipv4RawSocketFactory", dst);
+ onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1.0)));
+ onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0.0)));
+ onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+ ApplicationContainer apps = onoff.Install (c.Get (0));
+ apps.Start (Seconds (1.0));
+ apps.Stop (Seconds (10.0));
+
+ PacketSinkHelper sink = PacketSinkHelper ("ns3::Ipv4RawSocketFactory", dst);
+ apps = sink.Install (c.Get (3));
+ apps.Start (Seconds (0.0));
+ apps.Stop (Seconds (11.0));
+
+ V4PingHelper ping = V4PingHelper (addresses.GetAddress (2));
+ NodeContainer pingers;
+ pingers.Add (c.Get (0));
+ pingers.Add (c.Get (1));
+ pingers.Add (c.Get (3));
+ apps = ping.Install (pingers);
+ apps.Start (Seconds (2.0));
+ apps.Stop (Seconds (5.0));
+
+ // Trace receptions
+ Config::ConnectWithoutContext ("/NodeList/3/ApplicationList/0/$ns3::PacketSink/Rx",
+ MakeCallback (&CsmaPingTestCase::SinkRx, this));
+
+ // Trace pings
+ Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt",
+ MakeCallback (&CsmaPingTestCase::PingRtt, this));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ // We should have sent and received 10 packets
+ NS_TEST_ASSERT_MSG_EQ (m_countSinkRx, 10, "Node 3 should have received 10 packets");
+
+ // We should have 3 pingers that ping every second for 3 seconds.
+ NS_TEST_ASSERT_MSG_EQ (m_countPingRtt, 9, "Node 2 should have been pinged 9 times");
+
+ return GetErrorStatus ();
+}
+
+class CsmaRawIpSocketTestCase : public TestCase
+{
+public:
+ CsmaRawIpSocketTestCase ();
+ virtual ~CsmaRawIpSocketTestCase ();
+
+private:
+ virtual bool DoRun (void);
+ void SinkRx (Ptr<const Packet> p, const Address &ad);
+ void DropEvent (Ptr<const Packet> p);
+ uint32_t m_count;
+ uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaRawIpSocketTestCase::CsmaRawIpSocketTestCase ()
+ : TestCase ("Raw internet protocol socket example for Carrier Sense Multiple Access (CSMA) networks"), m_count (0), m_drops (0)
+{
+}
+
+CsmaRawIpSocketTestCase::~CsmaRawIpSocketTestCase ()
+{
+}
+
+void
+CsmaRawIpSocketTestCase::SinkRx (Ptr<const Packet> p, const Address &ad)
+{
+ m_count++;
+}
+
+void
+CsmaRawIpSocketTestCase::DropEvent (Ptr<const Packet> p)
+{
+ m_drops++;
+}
+
+//
+// Network topology
+// (sender) (receiver)
+// n0 n1 n2 n3
+// | | | |
+// =====================
+//
+// Node n0 sends data to node n3 over a raw IP socket. The protocol
+// number used is 2.
+//
+bool
+CsmaRawIpSocketTestCase::DoRun (void)
+{
+ // Here, we will explicitly create four nodes.
+ NodeContainer c;
+ c.Create (4);
+
+ // connect all our nodes to a shared channel.
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000)));
+ csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+ csma.SetDeviceAttribute ("EncapsulationMode", StringValue ("Llc"));
+ NetDeviceContainer devs = csma.Install (c);
+
+ // add an ip stack to all nodes.
+ InternetStackHelper ipStack;
+ ipStack.Install (c);
+
+ // assign ip addresses
+ Ipv4AddressHelper ip;
+ ip.SetBase ("192.168.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer addresses = ip.Assign (devs);
+
+ // IP protocol configuration
+ //
+ // Make packets be sent about every DefaultPacketSize / DataRate =
+ // 4096 bits / (5000 bits/second) = 0.82 second.
+ Config::SetDefault ("ns3::Ipv4RawSocketImpl::Protocol", StringValue ("2"));
+ InetSocketAddress dst = InetSocketAddress (addresses.GetAddress (3));
+ OnOffHelper onoff = OnOffHelper ("ns3::Ipv4RawSocketFactory", dst);
+ onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1.0)));
+ onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0.0)));
+ onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+ ApplicationContainer apps = onoff.Install (c.Get (0));
+ apps.Start (Seconds (1.0));
+ apps.Stop (Seconds (10.0));
+
+ PacketSinkHelper sink = PacketSinkHelper ("ns3::Ipv4RawSocketFactory", dst);
+ apps = sink.Install (c.Get (3));
+ apps.Start (Seconds (0.0));
+ apps.Stop (Seconds (12.0));
+
+ // Trace receptions
+ Config::ConnectWithoutContext ("/NodeList/3/ApplicationList/0/$ns3::PacketSink/Rx",
+ MakeCallback (&CsmaRawIpSocketTestCase::SinkRx, this));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ // We should have sent and received 10 packets
+ NS_TEST_ASSERT_MSG_EQ (m_count, 10, "Node 3 should have received 10 packets");
+
+ return GetErrorStatus ();
+}
+
+class CsmaStarTestCase : public TestCase
+{
+public:
+ CsmaStarTestCase ();
+ virtual ~CsmaStarTestCase ();
+
+private:
+ virtual bool DoRun (void);
+ void SinkRx (Ptr<const Packet> p, const Address &ad);
+ void DropEvent (Ptr<const Packet> p);
+ uint32_t m_count;
+ uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaStarTestCase::CsmaStarTestCase ()
+ : TestCase ("Star example for Carrier Sense Multiple Access (CSMA) networks"), m_count (0), m_drops (0)
+{
+}
+
+CsmaStarTestCase::~CsmaStarTestCase ()
+{
+}
+
+void
+CsmaStarTestCase::SinkRx (Ptr<const Packet> p, const Address& ad)
+{
+ m_count++;
+}
+
+void
+CsmaStarTestCase::DropEvent (Ptr<const Packet> p)
+{
+ m_drops++;
+}
+
+// Network topology (default)
+//
+// n2 + + n3 .
+// | ... |\ /| ... | .
+// ======= \ / ======= .
+// CSMA \ / CSMA .
+// \ / .
+// n1 +--- n0 ---+ n4 .
+// | ... | / \ | ... | .
+// ======= / \ ======= .
+// CSMA / \ CSMA .
+// / \ .
+// n6 + + n5 .
+// | ... | | ... | .
+// ======= ======= .
+// CSMA CSMA .
+//
+bool
+CsmaStarTestCase::DoRun (void)
+{
+ //
+ // Default number of nodes in the star.
+ //
+ uint32_t nSpokes = 7;
+
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
+ csma.SetChannelAttribute ("Delay", StringValue ("1ms"));
+ CsmaStarHelper star (nSpokes, csma);
+
+ NodeContainer fillNodes;
+
+ //
+ // Just to be nasy, hang some more nodes off of the CSMA channel for each
+ // spoke, so that there are a total of 16 nodes on each channel. Stash
+ // all of these new devices into a container.
+ //
+ NetDeviceContainer fillDevices;
+
+ uint32_t nFill = 14;
+ for (uint32_t i = 0; i < star.GetSpokeDevices ().GetN (); ++i)
+ {
+ Ptr<Channel> channel = star.GetSpokeDevices ().Get (i)->GetChannel ();
+ Ptr<CsmaChannel> csmaChannel = channel->GetObject<CsmaChannel> ();
+ NodeContainer newNodes;
+ newNodes.Create (nFill);
+ fillNodes.Add (newNodes);
+ fillDevices.Add (csma.Install (newNodes, csmaChannel));
+ }
+
+ InternetStackHelper internet;
+ star.InstallStack (internet);
+ internet.Install (fillNodes);
+
+ star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.0.0", "255.255.255.0"));
+
+ //
+ // We assigned addresses to the logical hub and the first "drop" of the
+ // CSMA network that acts as the spoke, but we also have a number of fill
+ // devices (nFill) also hanging off the CSMA network. We have got to
+ // assign addresses to them as well. We put all of the fill devices into
+ // a single device container, so the first nFill devices are associated
+ // with the channel connected to spokeDevices.Get (0), the second nFill
+ // devices afe associated with the channel connected to spokeDevices.Get (1)
+ // etc.
+ //
+ Ipv4AddressHelper address;
+ for(uint32_t i = 0; i < star.SpokeCount (); ++i)
+ {
+ std::ostringstream subnet;
+ subnet << "10.1." << i << ".0";
+ address.SetBase (subnet.str ().c_str (), "255.255.255.0", "0.0.0.3");
+
+ for (uint32_t j = 0; j < nFill; ++j)
+ {
+ address.Assign (fillDevices.Get (i * nFill + j));
+ }
+ }
+
+ //
+ // Create a packet sink on the star "hub" to receive packets.
+ //
+ uint16_t port = 50000;
+ Address hubLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
+ PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", hubLocalAddress);
+ ApplicationContainer hubApp = packetSinkHelper.Install (star.GetHub ());
+ hubApp.Start (Seconds (1.0));
+ hubApp.Stop (Seconds (10.0));
+
+ //
+ // Create OnOff applications to send TCP to the hub, one on each spoke node.
+ //
+ // Make packets be sent about every DefaultPacketSize / DataRate =
+ // 4096 bits / (5000 bits/second) = 0.82 second.
+ OnOffHelper onOffHelper ("ns3::TcpSocketFactory", Address ());
+ onOffHelper.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+ onOffHelper.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+ onOffHelper.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+ ApplicationContainer spokeApps;
+
+ for (uint32_t i = 0; i < star.SpokeCount (); ++i)
+ {
+ AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i), port));
+ onOffHelper.SetAttribute ("Remote", remoteAddress);
+ spokeApps.Add (onOffHelper.Install (star.GetSpokeNode (i)));
+ }
+
+ spokeApps.Start (Seconds (1.0));
+ spokeApps.Stop (Seconds (10.0));
+
+ //
+ // Because we are evil, we also add OnOff applications to send TCP to the hub
+ // from the fill devices on each CSMA link. The first nFill nodes in the
+ // fillNodes container are on the CSMA network talking to the zeroth device
+ // on the hub node. The next nFill nodes are on the CSMA network talking to
+ // the first device on the hub node, etc. So the ith fillNode is associated
+ // with the hub address found on the (i / nFill)th device on the hub node.
+ //
+ ApplicationContainer fillApps;
+
+ for (uint32_t i = 0; i < fillNodes.GetN (); ++i)
+ {
+ AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i / nFill), port));
+ onOffHelper.SetAttribute ("Remote", remoteAddress);
+ fillApps.Add (onOffHelper.Install (fillNodes.Get (i)));
+ }
+
+ fillApps.Start (Seconds (1.0));
+ fillApps.Stop (Seconds (10.0));
+
+ //
+ // Turn on global static routing so we can actually be routed across the star.
+ //
+ Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+ // Trace receptions
+ Config::ConnectWithoutContext ("/NodeList/0/ApplicationList/*/$ns3::PacketSink/Rx",
+ MakeCallback (&CsmaStarTestCase::SinkRx, this));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ // The hub node should have received 10 packets from the nFill + 1
+ // nodes on each spoke.
+ NS_TEST_ASSERT_MSG_EQ (m_count, 10 * ( nSpokes * (nFill + 1)), "Hub node did not receive the proper number of packets");
+
+ return GetErrorStatus ();
+}
+
+class CsmaSystemTestSuite : public TestSuite
+{
+public:
+ CsmaSystemTestSuite ();
+};
+
+CsmaSystemTestSuite::CsmaSystemTestSuite ()
+ : TestSuite ("csma-system", BVT)
+{
+ AddTestCase (new CsmaBridgeTestCase);
+ AddTestCase (new CsmaBroadcastTestCase);
+ AddTestCase (new CsmaMulticastTestCase);
+ AddTestCase (new CsmaOneSubnetTestCase);
+ AddTestCase (new CsmaPacketSocketTestCase);
+ AddTestCase (new CsmaPingTestCase);
+ AddTestCase (new CsmaRawIpSocketTestCase);
+ AddTestCase (new CsmaStarTestCase);
+}
+
+// Do not forget to allocate an instance of this TestSuite
+static CsmaSystemTestSuite csmaSystemTestSuite;