Fix for bug69: set local address correctly upon UDP connect; apply correct UDP connect() semantics (that sendto cannot override addresses on a connected socket); if destination is IPv4 limited broadcast address, convert to subnet-directed broadcast and send out on each interface; provide example csma-broadcast.cc script
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/csma-broadcast.cc Tue Sep 04 21:26:54 2007 -0700
@@ -0,0 +1,159 @@
+/* -*- 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
+ */
+
+//
+// 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, which is replicated
+// and received on both n1 and n2
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#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-channel.h"
+#include "ns3/csma-net-device.h"
+#include "ns3/csma-topology.h"
+#include "ns3/csma-ipv4-topology.h"
+#include "ns3/eui48-address.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.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("CsmaNetDevice");
+ DebugComponentEnable("Ipv4L3Protocol");
+ DebugComponentEnable("NetDevice");
+ DebugComponentEnable("Channel");
+ DebugComponentEnable("CsmaChannel");
+ 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
+ DefaultValue::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<Node> n0 = Create<InternetNode> ();
+ Ptr<Node> n1 = Create<InternetNode> ();
+ Ptr<Node> n2 = Create<InternetNode> ();
+
+ // We create the channels first without any IP addressing information
+ Ptr<CsmaChannel> channel0 =
+ CsmaTopology::CreateCsmaChannel(
+ DataRate(5000000), MilliSeconds(2));
+
+ // We create the channels first without any IP addressing information
+ Ptr<CsmaChannel> channel1 =
+ CsmaTopology::CreateCsmaChannel(
+ DataRate(5000000), MilliSeconds(2));
+
+ uint32_t n0ifIndex0 = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0,
+ Eui48Address("10:54:23:54:0:50"));
+ uint32_t n0ifIndex1 = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel1,
+ Eui48Address("10:54:23:54:0:51"));
+ uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0,
+ Eui48Address("10:54:23:54:23:51"));
+ uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channel1,
+ Eui48Address("10:54:23:54:23:52"));
+
+ // Later, we add IP addresses.
+ CsmaIpv4Topology::AddIpv4Address (
+ n0, n0ifIndex0, Ipv4Address("10.1.0.1"), Ipv4Mask("255.255.0.0"));
+
+ CsmaIpv4Topology::AddIpv4Address (
+ n1, n1ifIndex, Ipv4Address("10.1.0.2"), Ipv4Mask("255.255.0.0"));
+
+ CsmaIpv4Topology::AddIpv4Address (
+ n0, n0ifIndex1, Ipv4Address("192.168.1.1"), Ipv4Mask("255.255.255.0"));
+
+ CsmaIpv4Topology::AddIpv4Address (
+ n2, n2ifIndex, Ipv4Address("192.168.1.2"), 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<OnOffApplication> ooff = Create<OnOffApplication> (
+ n0,
+ InetSocketAddress ("255.255.255.255", 80),
+ "Udp",
+ ConstantVariable(1),
+ ConstantVariable(0));
+ // Start the application
+ ooff->Start(Seconds(1.0));
+ ooff->Stop (Seconds(10.0));
+
+
+ // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+ // Trace output will be sent to the csma-broadcast.tr file
+ AsciiTrace asciitrace ("csma-broadcast.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-<nodeId>-<interfaceId>
+ // and can be read by the "tcpdump -r" command (use "-tt" option to
+ // display timestamps correctly)
+ PcapTrace pcaptrace ("csma-broadcast.pcap");
+ pcaptrace.TraceAllIp ();
+
+ Simulator::Run ();
+
+ Simulator::Destroy ();
+}
--- a/examples/wscript Mon Sep 03 23:32:23 2007 -0700
+++ b/examples/wscript Tue Sep 04 21:26:54 2007 -0700
@@ -14,6 +14,10 @@
['csma', 'internet-node'])
obj.source = 'csma-one-subnet.cc'
+ obj = bld.create_ns3_program('csma-broadcast',
+ ['csma', 'internet-node'])
+ obj.source = 'csma-broadcast.cc'
+
obj = bld.create_ns3_program('csma-packet-socket',
['csma', 'internet-node'])
obj.source = 'csma-packet-socket.cc'
--- a/src/internet-node/arp-ipv4-interface.cc Mon Sep 03 23:32:23 2007 -0700
+++ b/src/internet-node/arp-ipv4-interface.cc Tue Sep 04 21:26:54 2007 -0700
@@ -62,8 +62,9 @@
Ptr<ArpL3Protocol> arp = m_node->QueryInterface<ArpL3Protocol> (ArpL3Protocol::iid);
Address hardwareDestination;
bool found;
-
- if (dest.IsBroadcast ())
+
+ if (dest.IsBroadcast () ||
+ dest.IsSubnetDirectedBroadcast (GetNetworkMask ()) )
{
hardwareDestination = GetDevice ()->GetBroadcast ();
found = true;
--- a/src/internet-node/udp-socket.cc Mon Sep 03 23:32:23 2007 -0700
+++ b/src/internet-node/udp-socket.cc Tue Sep 04 21:26:54 2007 -0700
@@ -153,10 +153,6 @@
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
m_defaultAddress = transport.GetIpv4 ();
m_defaultPort = transport.GetPort ();
- if (m_defaultAddress.IsBroadcast () )
- {
- NS_ASSERT_MSG(false, "UdpSocket::Connect, can't connect to broadcast");
- }
NotifyConnectionSucceeded ();
m_connected = true;
if (GetIpv4RouteToDestination (m_node, routeToDest, m_defaultAddress) )
@@ -196,24 +192,31 @@
m_errno = ERROR_SHUTDOWN;
return -1;
}
- m_udp->Send (p, m_endPoint->GetLocalAddress (), m_defaultAddress,
- m_endPoint->GetLocalPort (), m_defaultPort);
- NotifyDataSent (p.GetSize ());
- return 0;
+
+ return DoSendTo (p, m_defaultAddress, m_defaultPort);
}
int
UdpSocket::DoSendTo (const Packet &p, const Address &address)
{
- InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
- Ipv4Address ipv4 = transport.GetIpv4 ();
- uint16_t port = transport.GetPort ();
- return DoSendTo (p, ipv4, port);
+ if (!m_connected)
+ {
+ InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+ Ipv4Address ipv4 = transport.GetIpv4 ();
+ uint16_t port = transport.GetPort ();
+ return DoSendTo (p, ipv4, port);
+ }
+ else
+ {
+ // connected UDP socket must use default addresses
+ return DoSendTo (p, m_defaultAddress, m_defaultPort);
+ }
}
int
UdpSocket::DoSendTo (const Packet &p, Ipv4Address dest, uint16_t port)
{
+ Ipv4Route routeToDest;
if (m_endPoint == 0)
{
if (Bind () == -1)
@@ -228,8 +231,23 @@
m_errno = ERROR_SHUTDOWN;
return -1;
}
- Ipv4Route routeToDest;
- if (GetIpv4RouteToDestination (m_node, routeToDest, dest) )
+ //
+ // If dest is sent to the limited broadcast address (all ones),
+ // convert it to send a copy of the packet out of every interface
+ //
+ if (dest.IsBroadcast ())
+ {
+ Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
+ for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
+ {
+ Ipv4Address addri = ipv4->GetAddress (i);
+ Ipv4Mask maski = ipv4->GetNetworkMask (i);
+ m_udp->Send (p, addri, addri.GetSubnetDirectedBroadcast (maski),
+ m_endPoint->GetLocalPort (), port);
+ NotifyDataSent (p.GetSize ());
+ }
+ }
+ else if (GetIpv4RouteToDestination (m_node, routeToDest, dest) )
{
uint32_t localIfIndex = routeToDest.GetInterface ();
Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
--- a/src/node/ipv4-address.cc Mon Sep 03 23:32:23 2007 -0700
+++ b/src/node/ipv4-address.cc Tue Sep 04 21:26:54 2007 -0700
@@ -99,6 +99,11 @@
{
m_mask = value;
}
+uint32_t
+Ipv4Mask::GetInverse (void) const
+{
+ return ~m_mask;
+}
void
Ipv4Mask::Print (std::ostream &os) const
@@ -162,6 +167,18 @@
return Ipv4Address (GetHostOrder () & mask.GetHostOrder ());
}
+Ipv4Address
+Ipv4Address::GetSubnetDirectedBroadcast (Ipv4Mask const &mask) const
+{
+ return Ipv4Address (GetHostOrder () | mask.GetInverse ());
+}
+
+bool
+Ipv4Address::IsSubnetDirectedBroadcast (Ipv4Mask const &mask) const
+{
+ return ( (GetHostOrder () | mask.GetInverse ()) == GetHostOrder () );
+}
+
bool
Ipv4Address::IsBroadcast (void) const
{
--- a/src/node/ipv4-address.h Mon Sep 03 23:32:23 2007 -0700
+++ b/src/node/ipv4-address.h Tue Sep 04 21:26:54 2007 -0700
@@ -119,6 +119,16 @@
* \param mask a network mask
*/
Ipv4Address CombineMask (Ipv4Mask const &mask) const;
+ /**
+ * \brief Generate subnet-directed broadcast address corresponding to mask
+ *
+ * The subnet-directed broadcast address has the host bits set to all
+ * ones.
+ *
+ * \param mask a network mask
+ */
+ Ipv4Address GetSubnetDirectedBroadcast (Ipv4Mask const &mask) const;
+ bool IsSubnetDirectedBroadcast (Ipv4Mask const &mask) const;
static bool IsMatchingType (const Address &address);
operator Address ();
@@ -151,6 +161,10 @@
*/
uint32_t GetHostOrder (void) const;
void SetHostOrder (uint32_t value);
+ /**
+ * \brief Return the inverse mask in host order.
+ */
+ uint32_t GetInverse (void) const;
void Print (std::ostream &os) const;