Bugzilla – Bug 51
Allow UDP sockets to receive broadcast
Last modified: 2007-09-24 06:02:19 EDT
Some context: For my OLSR code, I need to use two UDP sockets, bound to the same OLSR port. One is bound to address 0.0.0.0 in order to receive OLSR packets on all interfaces. Another one is bound the "main address", which is the address of one of the node netdevices. This second socket is used for sending OLSR packets, and binding it to the main address is needed to ensure that OLSR packets are always sent with that address as source, regardless of the interface that actually transmits it. This is required by the OLSR protocol. Now the problem; it is two fold: 1. Currently, UDP sockets are not receiving broadcast packets; 2. NS-3 is allowing multiple sockets bound to the same port, but only allows one of them to actually receive the packets, which is clearly wrong.
Created attachment 29 [details] a sample python program The point of this (python, but python sockets API is exactly the same as in C/unix) program is to demonstrate that in a real system sockets can send broadcast packets, although it does require the line: s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) In addition, multiple sockets can be bound to the same port, although it requires a socket option: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) Afterwards, we can have multiple sockets listening on the same port and they will all receive a copy of the same packets.
Created attachment 30 [details] proposed patch
This is already merged.
This bug re-surfaced lately. Again UDP sockets are not receiving broadcast packets... :-( I'll try to add a unit test for this specific problem so that hopefully it gets fixed sooner next time :)
Unit test pushed to ns-3-dev. Now I'll try to fix it...
My code is: NS_TEST_ASSERT_EQUAL (txSocket->SendTo (InetSocketAddress (Ipv4Address("255.255.255.255"), 1234), Packet (123)), 0); But: std::list<ns3::Ipv4EndPoint*, std::allocator<ns3::Ipv4EndPoint*> > ns3::Ipv4EndPointDemux::Lookup(ns3::Ipv4Address, uint16_t, ns3::Ipv4Address, uint16_t) ==> (daddr=10.0.255.255, dport=1234, saddr=10.0.0.2, sport=49153) So, something is transforming the destination address 255.255.255.255 into 10.0.255.255. Is this correct?
(In reply to comment #6) > My code is: > > NS_TEST_ASSERT_EQUAL (txSocket->SendTo (InetSocketAddress > (Ipv4Address("255.255.255.255"), 1234), Packet (123)), 0); > > But: > > std::list<ns3::Ipv4EndPoint*, std::allocator<ns3::Ipv4EndPoint*> > > ns3::Ipv4EndPointDemux::Lookup(ns3::Ipv4Address, uint16_t, ns3::Ipv4Address, > uint16_t) ==> (daddr=10.0.255.255, dport=1234, saddr=10.0.0.2, sport=49153) > > So, something is transforming the destination address 255.255.255.255 into > 10.0.255.255. Is this correct? > OK, I made a small real world experiment and when I ping -b 255.255.255.255, a receiving node in the same LAN receives a packet to 255.255.255.255. So NS-3 is wrong.
The source of the problem is udp-socket.cc, UdpSocket::DoSendTo: if (dest.IsBroadcast ()) { NS_LOG_LOGIC ("Limited broadcast"); 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 ()); } } This "addri.GetSubnetDirectedBroadcast (maski)" is changing the 255.255.255.255 address to 10.0.255.255. This behavior does not match my real world experience. Replacing "addri.GetSubnetDirectedBroadcast (maski)" with "dest" fixes the problem. Any comments?
Response to your question in comment #6: There appear to be different possible correct behaviors, one of which is what is implemented in ns-3. Note that it differs from Linux. From Stevens, UNP, vol 1, ed. 3, p. 532. "What does a host do when sending UDP to 255.255.255.255? Most hosts allow this and convert the destination address to the subnet-directed broadcast address of the outgoing interface. It is often necessary to access the datalink directly to send a packet to 255.255.255.255. Another question is: What does a multihomed host do when the application sends UDP to 255.255.255.255? Some systems send a single broadcast on the primary interface with destination set to subnet-directed broadcast. Other systems send one copy out from each broadcast-capabile interface. Section 3.3.6 of RFC 1122 "takes no stand" on this issue. For portability, however, applications that want to broadcast to all interfaces should obtain the interface configuration and do one sendto() for each interface with destination set to that interface's broadcast address."
Created attachment 66 [details] patch to fix (allows limited broadcast to be received on multiple sockets)
(In reply to comment #9) > Response to your question in comment #6: > > There appear to be different possible correct behaviors, one of which is what > is implemented in ns-3. Note that it differs from Linux. > > From Stevens, UNP, vol 1, ed. 3, p. 532. The project as a whole has to decide whether to be thoroughly pedantic, or to be as easy to program as possible. After deciding that, document the decision and with time enforce it everywhere. What NS-3 should NOT do is change behavior over time, since it breaks code maintained outside of ns-3-dev, like the olsr code. In this case I also don't think the behavior or 255.255.255.255 is not fully specified in RFCs because "sockets" are mostly a Operating System concept, not a protocol issue. Finally, keep in mind that if we don't allow the flexibility of multiple sockets being able to receive broadcast packets then I would have to stop using sockets for OLSR (explanation of why is in my first comment), which would be a pity...
Gustavo, can you please split out your patch into two (LOG_M modifications, and the logic fix to Ipv4EndPointDemux::Lookup (and related unit tests), and apply the latter to fix the current ns-3-dev build, and close out this bug? Perhaps take the LOG_M proposal to another tracker item or the list.
(In reply to comment #12) > Gustavo, can you please split out your patch into two (LOG_M modifications, and > the logic fix to Ipv4EndPointDemux::Lookup (and related unit tests), and apply > the latter to fix the current ns-3-dev build, and close out this bug? Perhaps > take the LOG_M proposal to another tracker item or the list. Committed without the G_LOG_M stuff.