diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 5eae49506..74b8741e6 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -107,6 +107,7 @@ Bugs fixed - Bug 2744 - 802.11n/ac with RTS/CTS is crashing for a large number of nodes - Bug 2758 - IPv4 sockets bound to unicast receive also subnet-directed broadcasts - Bug 2759 - Packets sent to broadcast address are converted to subnet-directed broadcast +- Bug 2760 - OLSR uses unicast-bound sockets to receive broadcasts Known issues ------------ diff --git a/src/olsr/model/olsr-routing-protocol.cc b/src/olsr/model/olsr-routing-protocol.cc index 817c417d9..768df682c 100644 --- a/src/olsr/model/olsr-routing-protocol.cc +++ b/src/olsr/model/olsr-routing-protocol.cc @@ -47,6 +47,7 @@ #include "ns3/enum.h" #include "ns3/trace-source-accessor.h" #include "ns3/ipv4-header.h" +#include "ns3/ipv4-packet-info-tag.h" /********** Useful macros **********/ @@ -240,12 +241,17 @@ void RoutingProtocol::DoDispose () m_hnaRoutingTable = 0; m_routingTableAssociation = 0; - for (std::map< Ptr, Ipv4InterfaceAddress >::iterator iter = m_socketAddresses.begin (); - iter != m_socketAddresses.end (); iter++) + if (m_recvSocket) + { + m_recvSocket->Close (); + } + + for (std::map< Ptr, Ipv4InterfaceAddress >::iterator iter = m_sendSockets.begin (); + iter != m_sendSockets.end (); iter++) { iter->first->Close (); } - m_socketAddresses.clear (); + m_sendSockets.clear (); Ipv4RoutingProtocol::DoDispose (); } @@ -340,7 +346,23 @@ void RoutingProtocol::DoInitialize () continue; } - // Create a socket to listen only on this interface + // Create a socket to listen on all the interfaces + if (m_recvSocket == 0) + { + m_recvSocket = Socket::CreateSocket (GetObject (), + UdpSocketFactory::GetTypeId ()); + m_recvSocket->SetAllowBroadcast (true); + InetSocketAddress inetAddr (Ipv4Address::GetAny (), OLSR_PORT_NUMBER); + m_recvSocket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvOlsr, this)); + if (m_recvSocket->Bind (inetAddr)) + { + NS_FATAL_ERROR ("Failed to bind() OLSR socket"); + } + m_recvSocket->SetRecvPktInfo (true); + m_recvSocket->ShutdownSend (); + } + + // Create a socket to send packets from this specific interfaces Ptr socket = Socket::CreateSocket (GetObject (), UdpSocketFactory::GetTypeId ()); socket->SetAllowBroadcast (true); @@ -351,7 +373,8 @@ void RoutingProtocol::DoInitialize () NS_FATAL_ERROR ("Failed to bind() OLSR socket"); } socket->BindToNetDevice (m_ipv4->GetNetDevice (i)); - m_socketAddresses[socket] = m_ipv4->GetAddress (i, 0); + socket->SetRecvPktInfo (true); + m_sendSockets[socket] = m_ipv4->GetAddress (i, 0); canRunOlsr = true; } @@ -386,9 +409,33 @@ RoutingProtocol::RecvOlsr (Ptr socket) Address sourceAddress; receivedPacket = socket->RecvFrom (sourceAddress); + Ipv4PacketInfoTag interfaceInfo; + if (!receivedPacket->RemovePacketTag (interfaceInfo)) + { + NS_ABORT_MSG ("No incoming interface on OLSR message, aborting."); + } + uint32_t incomingIf = interfaceInfo.GetRecvIf (); + Ptr node = this->GetObject (); + Ptr dev = node->GetDevice (incomingIf); + uint32_t recvInterfaceIndex = m_ipv4->GetInterfaceForDevice (dev); + + if (m_interfaceExclusions.find (recvInterfaceIndex) != m_interfaceExclusions.end ()) + { + return; + } + + InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress); Ipv4Address senderIfaceAddr = inetSourceAddr.GetIpv4 (); - Ipv4Address receiverIfaceAddr = m_socketAddresses[socket].GetLocal (); + + int32_t interfaceForAddress = m_ipv4->GetInterfaceForAddress (senderIfaceAddr); + if (interfaceForAddress != -1) + { + NS_LOG_LOGIC ("Ignoring a packet sent by myself."); + return; + } + + Ipv4Address receiverIfaceAddr = m_ipv4->GetAddress (recvInterfaceIndex, 0).GetLocal (); NS_ASSERT (receiverIfaceAddr != Ipv4Address ()); NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " received a OLSR packet from " << senderIfaceAddr << " to " << receiverIfaceAddr); @@ -1588,10 +1635,11 @@ RoutingProtocol::SendPacket (Ptr packet, // Send it for (std::map, Ipv4InterfaceAddress>::const_iterator i = - m_socketAddresses.begin (); i != m_socketAddresses.end (); i++) + m_sendSockets.begin (); i != m_sendSockets.end (); i++) { + Ptr pkt = packet->Copy (); Ipv4Address bcast = i->second.GetLocal ().GetSubnetDirectedBroadcast (i->second.GetMask ()); - i->first->SendTo (packet, 0, InetSocketAddress (bcast, OLSR_PORT_NUMBER)); + i->first->SendTo (pkt, 0, InetSocketAddress (bcast, OLSR_PORT_NUMBER)); } } @@ -3082,8 +3130,8 @@ RoutingProtocol::AssignStreams (int64_t stream) bool RoutingProtocol::IsMyOwnAddress (const Ipv4Address & a) const { - for (std::map, Ipv4InterfaceAddress>::const_iterator j = - m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) + std::map, Ipv4InterfaceAddress>::const_iterator j; + for (j = m_sendSockets.begin (); j != m_sendSockets.end (); ++j) { Ipv4InterfaceAddress iface = j->second; if (a == iface.GetLocal ()) diff --git a/src/olsr/model/olsr-routing-protocol.h b/src/olsr/model/olsr-routing-protocol.h index 92b726447..efb64f9b0 100644 --- a/src/olsr/model/olsr-routing-protocol.h +++ b/src/olsr/model/olsr-routing-protocol.h @@ -764,7 +764,9 @@ private: // One socket per interface, each bound to that interface's address // (reason: for OLSR Link Sensing we need to know on which interface // HELLO messages arrive) - std::map< Ptr, Ipv4InterfaceAddress > m_socketAddresses; //!< Container of sockets and the interfaces they are opened onto. + std::map< Ptr, Ipv4InterfaceAddress > m_sendSockets; //!< Container of sockets and the interfaces they are opened onto. + Ptr m_recvSocket; //!< Receiving socket. + /// Rx packet trace. TracedCallback m_rxPacketTrace;