diff -r 084b07dceafb src/internet-node/ipv4-end-point-demux.cc --- a/src/internet-node/ipv4-end-point-demux.cc Mon Feb 11 14:46:44 2008 +0000 +++ b/src/internet-node/ipv4-end-point-demux.cc Tue Feb 12 15:20:45 2008 +0000 @@ -83,14 +83,14 @@ Ipv4EndPointDemux::Allocate (void) NS_LOG_WARN ("Ephemeral port allocation failed."); return 0; } - Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port); + Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port, Ipv4Address::GetAny ()); m_endPoints.push_back (endPoint); NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); return endPoint; } Ipv4EndPoint * -Ipv4EndPointDemux::Allocate (Ipv4Address address) +Ipv4EndPointDemux::Allocate (Ipv4Address address, Ipv4Address localInterface) { NS_LOG_FUNCTION; NS_LOG_PARAMS (this << address); @@ -100,7 +100,7 @@ Ipv4EndPointDemux::Allocate (Ipv4Address NS_LOG_WARN ("Ephemeral port allocation failed."); return 0; } - Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port); + Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port, localInterface); m_endPoints.push_back (endPoint); NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); return endPoint; @@ -110,20 +110,22 @@ Ipv4EndPointDemux::Allocate (uint16_t po Ipv4EndPointDemux::Allocate (uint16_t port) { NS_LOG_FUNCTION; - return Allocate (Ipv4Address::GetAny (), port); + NS_LOG_PARAMS (this << port); + + return Allocate (Ipv4Address::GetAny (), port, Ipv4Address::GetAny ()); } Ipv4EndPoint * -Ipv4EndPointDemux::Allocate (Ipv4Address address, uint16_t port) +Ipv4EndPointDemux::Allocate (Ipv4Address address, uint16_t port, Ipv4Address localInterface) { NS_LOG_FUNCTION; - NS_LOG_PARAMS (this << address << port); + NS_LOG_PARAMS (this << address << port << localInterface); if (LookupLocal (address, port)) { NS_LOG_WARN ("Duplicate address/port; failing."); return 0; } - Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port); + Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port, localInterface); m_endPoints.push_back (endPoint); NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); return endPoint; @@ -131,7 +133,8 @@ Ipv4EndPointDemux::Allocate (Ipv4Address Ipv4EndPoint * Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort) + Ipv4Address peerAddress, uint16_t peerPort, + Ipv4Address localInterface) { NS_LOG_FUNCTION; NS_LOG_PARAMS (this << localAddress << localPort << peerAddress << peerPort); @@ -147,7 +150,7 @@ Ipv4EndPointDemux::Allocate (Ipv4Address return 0; } } - Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort); + Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort, localInterface); endPoint->SetPeer (peerAddress, peerPort); m_endPoints.push_back (endPoint); @@ -213,17 +216,34 @@ Ipv4EndPointDemux::Lookup (Ipv4Address d bool isBroadcast = (daddr.IsBroadcast () || daddr.IsSubnetDirectedBroadcast (incomingInterface->GetNetworkMask ())); - NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast); + Ipv4Address incomingInterfaceAddr = incomingInterface->GetAddress (); - NS_LOG_LOGIC ("Local address matches: " << - bool ((*i)->GetLocalAddress () == daddr || isBroadcast)); + NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast + << " localInterface="<< (*i)->GetLocalInterface ()); + bool localAddressMatches; + if (isBroadcast) + { + if ((*i)->GetLocalInterface () == Ipv4Address::GetAny ()) + { + localAddressMatches = true; + } + else + { + localAddressMatches = ((*i)->GetLocalInterface () == incomingInterfaceAddr); + } + } + else + { + localAddressMatches = ((*i)->GetLocalAddress () == daddr); + } + NS_LOG_LOGIC ("Local address matches: " << localAddressMatches); NS_LOG_LOGIC ("Peer port matches: " << bool ((*i)->GetPeerPort () == sport || (*i)->GetPeerPort () == 0)); NS_LOG_LOGIC ("Peer address matches: " << bool ((*i)->GetPeerAddress () == saddr || (*i)->GetPeerAddress () == Ipv4Address::GetAny ())); - if ( ((*i)->GetLocalAddress () == daddr || isBroadcast) + if ( localAddressMatches && ((*i)->GetPeerPort () == sport || (*i)->GetPeerPort () == 0) && ((*i)->GetPeerAddress () == saddr || (*i)->GetPeerAddress () == Ipv4Address::GetAny ())) { diff -r 084b07dceafb src/internet-node/ipv4-end-point-demux.h --- a/src/internet-node/ipv4-end-point-demux.h Mon Feb 11 14:46:44 2008 +0000 +++ b/src/internet-node/ipv4-end-point-demux.h Tue Feb 12 15:20:45 2008 +0000 @@ -48,13 +48,13 @@ public: Ptr incomingInterface); Ipv4EndPoint *Allocate (void); - Ipv4EndPoint *Allocate (Ipv4Address address); + Ipv4EndPoint *Allocate (Ipv4Address address, Ipv4Address localInterface); Ipv4EndPoint *Allocate (uint16_t port); - Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port); + Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port, Ipv4Address localInterface); Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort, Ipv4Address peerAddress, - uint16_t peerPort); + uint16_t peerPort, Ipv4Address localInterface); void DeAllocate (Ipv4EndPoint *endPoint); diff -r 084b07dceafb src/internet-node/ipv4-end-point.cc --- a/src/internet-node/ipv4-end-point.cc Mon Feb 11 14:46:44 2008 +0000 +++ b/src/internet-node/ipv4-end-point.cc Tue Feb 12 15:20:45 2008 +0000 @@ -24,11 +24,12 @@ namespace ns3 { -Ipv4EndPoint::Ipv4EndPoint (Ipv4Address address, uint16_t port) +Ipv4EndPoint::Ipv4EndPoint (Ipv4Address address, uint16_t port, Ipv4Address localInterface) : m_localAddr (address), m_localPort (port), m_peerAddr (Ipv4Address::GetAny ()), - m_peerPort (0) + m_peerPort (0), + m_localInterface (localInterface) {} Ipv4EndPoint::~Ipv4EndPoint () { @@ -48,6 +49,17 @@ Ipv4EndPoint::SetLocalAddress (Ipv4Addre Ipv4EndPoint::SetLocalAddress (Ipv4Address address) { m_localAddr = address; +} + +Ipv4Address Ipv4EndPoint::GetLocalInterface (void) const +{ + return m_localInterface; +} + +void +Ipv4EndPoint::SetLocalInterface (Ipv4Address localInterface) +{ + m_localInterface = localInterface; } uint16_t diff -r 084b07dceafb src/internet-node/ipv4-end-point.h --- a/src/internet-node/ipv4-end-point.h Mon Feb 11 14:46:44 2008 +0000 +++ b/src/internet-node/ipv4-end-point.h Tue Feb 12 15:20:45 2008 +0000 @@ -33,7 +33,7 @@ class Packet; class Ipv4EndPoint { public: - Ipv4EndPoint (Ipv4Address address, uint16_t port); + Ipv4EndPoint (Ipv4Address address, uint16_t port, Ipv4Address localInterface); ~Ipv4EndPoint (); Ipv4Address GetLocalAddress (void); @@ -41,6 +41,8 @@ public: uint16_t GetLocalPort (void); Ipv4Address GetPeerAddress (void); uint16_t GetPeerPort (void); + Ipv4Address GetLocalInterface (void) const; + void SetLocalInterface (Ipv4Address localInterface); void SetPeer (Ipv4Address address, uint16_t port); @@ -56,6 +58,7 @@ private: uint16_t m_peerPort; Callback, Ipv4Address, uint16_t> m_rxCallback; Callback m_destroyCallback; + Ipv4Address m_localInterface; // local interface (optional) }; }; // namespace ns3 diff -r 084b07dceafb src/internet-node/ipv4-l3-protocol.cc --- a/src/internet-node/ipv4-l3-protocol.cc Mon Feb 11 14:46:44 2008 +0000 +++ b/src/internet-node/ipv4-l3-protocol.cc Tue Feb 12 15:20:45 2008 +0000 @@ -497,8 +497,8 @@ Ipv4L3Protocol::FindInterfaceForAddr (Ip } } - NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): " - "Interface not found for IP address"); + NS_FATAL_ERROR ("Ipv4L3Protocol::FindInterfaceForAddr (): " + "Interface not found for IP address " << addr); return 0; } diff -r 084b07dceafb src/internet-node/tcp-l4-protocol.cc --- a/src/internet-node/tcp-l4-protocol.cc Mon Feb 11 14:46:44 2008 +0000 +++ b/src/internet-node/tcp-l4-protocol.cc Tue Feb 12 15:20:46 2008 +0000 @@ -353,11 +353,11 @@ TcpL4Protocol::Allocate (void) } Ipv4EndPoint * -TcpL4Protocol::Allocate (Ipv4Address address) +TcpL4Protocol::Allocate (Ipv4Address address, Ipv4Address localInterface) { NS_LOG_FUNCTION; NS_LOG_PARAMS (this << address); - return m_endPoints->Allocate (address); + return m_endPoints->Allocate (address, localInterface); } Ipv4EndPoint * @@ -369,21 +369,23 @@ TcpL4Protocol::Allocate (uint16_t port) } Ipv4EndPoint * -TcpL4Protocol::Allocate (Ipv4Address address, uint16_t port) +TcpL4Protocol::Allocate (Ipv4Address address, uint16_t port, Ipv4Address localInterface) { NS_LOG_FUNCTION; NS_LOG_PARAMS (this << address << port); - return m_endPoints->Allocate (address, port); + return m_endPoints->Allocate (address, port, localInterface); } Ipv4EndPoint * TcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort) + Ipv4Address peerAddress, uint16_t peerPort, + Ipv4Address localInterface) { NS_LOG_FUNCTION; NS_LOG_PARAMS (this << localAddress << localPort << peerAddress << peerPort); return m_endPoints->Allocate (localAddress, localPort, - peerAddress, peerPort); + peerAddress, peerPort, + localInterface); } void diff -r 084b07dceafb src/internet-node/tcp-l4-protocol.h --- a/src/internet-node/tcp-l4-protocol.h Mon Feb 11 14:46:44 2008 +0000 +++ b/src/internet-node/tcp-l4-protocol.h Tue Feb 12 15:20:46 2008 +0000 @@ -60,11 +60,12 @@ public: Ptr CreateSocket (void); Ipv4EndPoint *Allocate (void); - Ipv4EndPoint *Allocate (Ipv4Address address); + Ipv4EndPoint *Allocate (Ipv4Address address, Ipv4Address localInterface); Ipv4EndPoint *Allocate (uint16_t port); - Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port); + Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port, Ipv4Address localInterface); Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort); + Ipv4Address peerAddress, uint16_t peerPort, + Ipv4Address localInterface); void DeAllocate (Ipv4EndPoint *endPoint); diff -r 084b07dceafb src/internet-node/tcp-socket.cc --- a/src/internet-node/tcp-socket.cc Mon Feb 11 14:46:44 2008 +0000 +++ b/src/internet-node/tcp-socket.cc Tue Feb 12 15:20:46 2008 +0000 @@ -155,6 +155,13 @@ TcpSocket::Bind (const Address &address) InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); Ipv4Address ipv4 = transport.GetIpv4 (); uint16_t port = transport.GetPort (); + Ipv4Address localInterface = Ipv4Address::GetAny (); + if (ipv4 != Ipv4Address::GetAny ()) + { + Ptr ipv4_api = m_node->GetObject (); + ipv4_api->FindInterfaceForAddr (ipv4); // check if address matches a local interface + localInterface = ipv4; + } if (ipv4 == Ipv4Address::GetAny () && port == 0) { m_endPoint = m_tcp->Allocate (); @@ -167,12 +174,12 @@ TcpSocket::Bind (const Address &address) } else if (ipv4 != Ipv4Address::GetAny () && port == 0) { - m_endPoint = m_tcp->Allocate (ipv4); + m_endPoint = m_tcp->Allocate (ipv4, localInterface); NS_LOG_LOGIC ("TcpSocket "<Allocate (ipv4, port); + m_endPoint = m_tcp->Allocate (ipv4, port, localInterface); NS_LOG_LOGIC ("TcpSocket "<Allocate (address); + return m_endPoints->Allocate (address, localInterface); } Ipv4EndPoint * @@ -96,20 +96,21 @@ UdpL4Protocol::Allocate (uint16_t port) } Ipv4EndPoint * -UdpL4Protocol::Allocate (Ipv4Address address, uint16_t port) +UdpL4Protocol::Allocate (Ipv4Address address, uint16_t port, Ipv4Address localInterface) { NS_LOG_FUNCTION; NS_LOG_PARAMS (this << address << port); - return m_endPoints->Allocate (address, port); + return m_endPoints->Allocate (address, port, localInterface); } Ipv4EndPoint * UdpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort) + Ipv4Address peerAddress, uint16_t peerPort, + Ipv4Address localInterface) { NS_LOG_FUNCTION; NS_LOG_PARAMS (this << localAddress << localPort << peerAddress << peerPort); return m_endPoints->Allocate (localAddress, localPort, - peerAddress, peerPort); + peerAddress, peerPort, localInterface); } void diff -r 084b07dceafb src/internet-node/udp-l4-protocol.h --- a/src/internet-node/udp-l4-protocol.h Mon Feb 11 14:46:44 2008 +0000 +++ b/src/internet-node/udp-l4-protocol.h Tue Feb 12 15:20:46 2008 +0000 @@ -56,11 +56,13 @@ public: Ptr CreateSocket (void); Ipv4EndPoint *Allocate (void); - Ipv4EndPoint *Allocate (Ipv4Address address); + Ipv4EndPoint *Allocate (Ipv4Address address, Ipv4Address localInterface); Ipv4EndPoint *Allocate (uint16_t port); - Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port); + Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port, + Ipv4Address localInterface); Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort); + Ipv4Address peerAddress, uint16_t peerPort, + Ipv4Address localInterface); void DeAllocate (Ipv4EndPoint *endPoint); diff -r 084b07dceafb src/internet-node/udp-socket.cc --- a/src/internet-node/udp-socket.cc Mon Feb 11 14:46:44 2008 +0000 +++ b/src/internet-node/udp-socket.cc Tue Feb 12 15:20:46 2008 +0000 @@ -127,6 +127,15 @@ UdpSocket::Bind (const Address &address) InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); Ipv4Address ipv4 = transport.GetIpv4 (); uint16_t port = transport.GetPort (); + + Ipv4Address localInterface = Ipv4Address::GetAny (); + if (ipv4 != Ipv4Address::GetAny ()) + { + Ptr ipv4_api = m_node->GetObject (); + ipv4_api->FindInterfaceForAddr (ipv4); // check if address matches a local interface + localInterface = ipv4; + } + if (ipv4 == Ipv4Address::GetAny () && port == 0) { m_endPoint = m_udp->Allocate (); @@ -137,11 +146,11 @@ UdpSocket::Bind (const Address &address) } else if (ipv4 != Ipv4Address::GetAny () && port == 0) { - m_endPoint = m_udp->Allocate (ipv4); + m_endPoint = m_udp->Allocate (ipv4, localInterface); } else if (ipv4 != Ipv4Address::GetAny () && port != 0) { - m_endPoint = m_udp->Allocate (ipv4, port); + m_endPoint = m_udp->Allocate (ipv4, port, localInterface); } return FinishBind (); @@ -388,35 +397,55 @@ UdpSocketTest::RunTests (void) // Receiver Node Ptr rxNode = CreateObject (); - Ptr rxDev = CreateObject (rxNode); - rxDev->AddQueue(CreateObject ()); - Ptr ipv4 = rxNode->GetObject (); - uint32_t netdev_idx = ipv4->AddInterface (rxDev); - ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1")); - ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); - ipv4->SetUp (netdev_idx); + Ptr rxDev1, rxDev2; + { // first interface + rxDev1 = CreateObject (rxNode); + rxDev1->AddQueue(CreateObject ()); + Ptr ipv4 = rxNode->GetObject (); + uint32_t netdev_idx = ipv4->AddInterface (rxDev1); + ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1")); + ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + ipv4->SetUp (netdev_idx); + } + { // second interface + rxDev2 = CreateObject (rxNode); + rxDev2->AddQueue(CreateObject ()); + Ptr ipv4 = rxNode->GetObject (); + uint32_t netdev_idx = ipv4->AddInterface (rxDev2); + ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.1")); + ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + ipv4->SetUp (netdev_idx); + } + // Sender Node Ptr txNode = CreateObject (); - Ptr txDev = CreateObject (txNode); - txDev->AddQueue(CreateObject ()); - ipv4 = txNode->GetObject (); - netdev_idx = ipv4->AddInterface (txDev); - ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2")); - ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); - ipv4->SetUp (netdev_idx); + Ptr txDev; + { + txDev = CreateObject (txNode); + txDev->AddQueue(CreateObject ()); + Ptr ipv4 = txNode->GetObject (); + uint32_t netdev_idx = ipv4->AddInterface (txDev); + ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2")); + ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + ipv4->SetUp (netdev_idx); + } // link the two nodes Ptr channel = CreateObject (); - rxDev->Attach (channel); + rxDev1->Attach (channel); txDev->Attach (channel); // Create the UDP sockets Ptr rxSocketFactory = rxNode->GetObject (); Ptr rxSocket = rxSocketFactory->CreateSocket (); - NS_TEST_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.2"), 1234)), 0); + NS_TEST_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0); rxSocket->SetRecvCallback (MakeCallback (&UdpSocketTest::ReceivePacket, this)); + + Ptr rxSocket2 = rxSocketFactory->CreateSocket (); + rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketTest::ReceivePacket2, this)); + NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0); Ptr txSocketFactory = txNode->GetObject (); Ptr txSocket = txSocketFactory->CreateSocket (); @@ -425,26 +454,33 @@ UdpSocketTest::RunTests (void) // Unicast test m_receivedPacket = Create (); + m_receivedPacket2 = Create (); NS_TEST_ASSERT_EQUAL (txSocket->SendTo (InetSocketAddress (Ipv4Address("10.0.0.1"), 1234), Create (123)), 0); Simulator::Run (); NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); + NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it // Simple broadcast test m_receivedPacket = Create (); + m_receivedPacket2 = Create (); NS_TEST_ASSERT_EQUAL (txSocket->SendTo (InetSocketAddress (Ipv4Address("255.255.255.255"), 1234), Create (123)), 0); Simulator::Run (); NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); + // second socket should not receive it (it is bound specifically to the second interface's address + NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // Broadcast test with multiple receiving sockets // When receiving broadcast packets, all sockets sockets bound to - // the address/port should receive a copy of the same packet. - Ptr rxSocket2 = rxSocketFactory->CreateSocket (); + // the address/port should receive a copy of the same packet -- if + // the socket address matches. + rxSocket2->Dispose (); + rxSocket2 = rxSocketFactory->CreateSocket (); rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketTest::ReceivePacket2, this)); NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0);