# HG changeset patch # Parent 223148e5de54850403b63f833c51666b536d1641 diff -r 223148e5de54 AUTHORS --- a/AUTHORS Thu Apr 08 11:14:56 2010 +0900 +++ b/AUTHORS Thu Apr 08 11:21:19 2010 +0900 @@ -53,3 +53,4 @@ Florian Westphal (fw@strlen.de) Josh Pelkey (jpelkey@gatech.edu) Dan Broyles (muxman@sbcglobal.net) +Hajime Tazaki (tazaki@sfc.wide.ad.jp) diff -r 223148e5de54 RELEASE_NOTES --- a/RELEASE_NOTES Thu Apr 08 11:14:56 2010 +0900 +++ b/RELEASE_NOTES Thu Apr 08 11:21:19 2010 +0900 @@ -108,6 +108,7 @@ - bug 850 - Ipv4GlobalRouting::LookupGlobal bug - bug 864 - Invalid return value in UdpSocketImpl::Send and Ipv4RawSocketImpl::Send - bug 865 - Ipv4RawSocketImpl::RecvFrom does not return from address all the time. + - Bug 859 - Output interface estimation for the source address bound socket in IPv4 Raw socket Known issues ------------ diff -r 223148e5de54 src/internet-stack/ipv4-raw-socket-impl.cc --- a/src/internet-stack/ipv4-raw-socket-impl.cc Thu Apr 08 11:14:56 2010 +0900 +++ b/src/internet-stack/ipv4-raw-socket-impl.cc Thu Apr 08 11:21:19 2010 +0900 @@ -179,6 +179,14 @@ SocketErrno errno_ = ERROR_NOTERROR;//do not use errno as it is the standard C last error number Ptr route; Ptr oif = m_boundnetdevice; //specify non-zero if bound to a source address + if (!oif && m_src != Ipv4Address::GetAny ()) + { + int32_t index = ipv4->GetInterfaceForAddress (m_src); + NS_ASSERT (index >= 0); + oif = ipv4->GetNetDevice (index); + NS_LOG_LOGIC ("Set index " << oif << "from source " << m_src); + } + // TBD-- we could cache the route and just check its validity route = ipv4->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_); if (route != 0) diff -r 223148e5de54 src/internet-stack/ipv4-raw-test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-raw-test.cc Thu Apr 08 11:21:19 2010 +0900 @@ -0,0 +1,281 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Keio University + * + * 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 + * + * Author: Hajime Tazaki + */ +/** + * This is the test code for ipv4-raw-socket-impl.cc. + */ + +#include "ns3/test.h" +#include "ns3/socket-factory.h" +#include "ns3/ipv4-raw-socket-factory.h" +#include "ns3/simulator.h" +#include "ns3/simple-channel.h" +#include "ns3/simple-net-device.h" +#include "ns3/drop-tail-queue.h" +#include "ns3/socket.h" + +#include "ns3/log.h" +#include "ns3/node.h" +#include "ns3/inet-socket-address.h" + +#include "arp-l3-protocol.h" +#include "ipv4-l3-protocol.h" +#include "icmpv4-l4-protocol.h" +#include "ns3/ipv4-list-routing.h" +#include "ns3/ipv4-static-routing.h" + +#include +#include +namespace ns3 { + +static void +AddInternetStack (Ptr node) +{ + //ARP + Ptr arp = CreateObject (); + node->AggregateObject(arp); + //IPV4 + Ptr ipv4 = CreateObject (); + //Routing for Ipv4 + Ptr ipv4Routing = CreateObject (); + ipv4->SetRoutingProtocol (ipv4Routing); + Ptr ipv4staticRouting = CreateObject (); + ipv4Routing->AddRoutingProtocol (ipv4staticRouting, 0); + node->AggregateObject(ipv4); + //ICMP + Ptr icmp = CreateObject (); + node->AggregateObject(icmp); + // //Ipv4Raw + // Ptr udp = CreateObject (); + // node->AggregateObject(udp); +} + + +class Ipv4RawSocketImplTest: public TestCase +{ + Ptr m_receivedPacket; + Ptr m_receivedPacket2; + void DoSendData (Ptr socket, std::string to); + void SendData (Ptr socket, std::string to); + +public: + virtual bool DoRun (void); + Ipv4RawSocketImplTest (); + + void ReceivePacket (Ptr socket, Ptr packet, const Address &from); + void ReceivePacket2 (Ptr socket, Ptr packet, const Address &from); + void ReceivePkt (Ptr socket); + void ReceivePkt2 (Ptr socket); +}; + + +Ipv4RawSocketImplTest::Ipv4RawSocketImplTest () + : TestCase ("IPv4 Raw socket implementation") +{ +} + +void Ipv4RawSocketImplTest::ReceivePacket (Ptr socket, Ptr packet, const Address &from) +{ + m_receivedPacket = packet; +} + +void Ipv4RawSocketImplTest::ReceivePacket2 (Ptr socket, Ptr packet, const Address &from) +{ + m_receivedPacket2 = packet; +} + +void Ipv4RawSocketImplTest::ReceivePkt (Ptr socket) +{ + uint32_t availableData; + availableData = socket->GetRxAvailable (); + m_receivedPacket = socket->Recv (std::numeric_limits::max(), 0); + NS_ASSERT (availableData == m_receivedPacket->GetSize ()); +} + +void Ipv4RawSocketImplTest::ReceivePkt2 (Ptr socket) +{ + uint32_t availableData; + availableData = socket->GetRxAvailable (); + m_receivedPacket2 = socket->Recv (std::numeric_limits::max(), 0); + NS_ASSERT (availableData == m_receivedPacket2->GetSize ()); +} + +void +Ipv4RawSocketImplTest::DoSendData (Ptr socket, std::string to) +{ + Address realTo = InetSocketAddress (Ipv4Address(to.c_str()), 0); + NS_TEST_EXPECT_MSG_NE (socket->SendTo (Create (123), 0, realTo), + -1, to); +} + +void +Ipv4RawSocketImplTest::SendData (Ptr socket, std::string to) +{ + m_receivedPacket = Create (); + m_receivedPacket2 = Create (); + Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0), + &Ipv4RawSocketImplTest::DoSendData, this, socket, to); + Simulator::Run (); +} + +bool +Ipv4RawSocketImplTest::DoRun (void) +{ + // Create topology + + // Receiver Node + Ptr rxNode = CreateObject (); + AddInternetStack (rxNode); + Ptr rxDev1, rxDev2; + { // first interface + rxDev1 = CreateObject (); + rxDev1->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ())); + rxNode->AddDevice (rxDev1); + Ptr ipv4 = rxNode->GetObject (); + uint32_t netdev_idx = ipv4->AddInterface (rxDev1); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.1"), Ipv4Mask (0xffff0000U)); + ipv4->AddAddress (netdev_idx, ipv4Addr); + ipv4->SetUp (netdev_idx); + } + + { // second interface + rxDev2 = CreateObject (); + rxDev2->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ())); + rxNode->AddDevice (rxDev2); + Ptr ipv4 = rxNode->GetObject (); + uint32_t netdev_idx = ipv4->AddInterface (rxDev2); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.1"), Ipv4Mask (0xffff0000U)); + ipv4->AddAddress (netdev_idx, ipv4Addr); + ipv4->SetUp (netdev_idx); + } + + // Sender Node + Ptr txNode = CreateObject (); + AddInternetStack (txNode); + Ptr txDev1; + { + txDev1 = CreateObject (); + txDev1->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ())); + txNode->AddDevice (txDev1); + Ptr ipv4 = txNode->GetObject (); + uint32_t netdev_idx = ipv4->AddInterface (txDev1); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.2"), Ipv4Mask (0xffff0000U)); + ipv4->AddAddress (netdev_idx, ipv4Addr); + ipv4->SetUp (netdev_idx); + } + Ptr txDev2; + { + txDev2 = CreateObject (); + txDev2->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ())); + txNode->AddDevice (txDev2); + Ptr ipv4 = txNode->GetObject (); + uint32_t netdev_idx = ipv4->AddInterface (txDev2); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.2"), Ipv4Mask (0xffff0000U)); + ipv4->AddAddress (netdev_idx, ipv4Addr); + ipv4->SetUp (netdev_idx); + } + + // link the two nodes + Ptr channel1 = CreateObject (); + rxDev1->SetChannel (channel1); + txDev1->SetChannel (channel1); + + Ptr channel2 = CreateObject (); + rxDev2->SetChannel (channel2); + txDev2->SetChannel (channel2); + + + // Create the IPv4 Raw sockets + Ptr rxSocketFactory = rxNode->GetObject (); + Ptr rxSocket = rxSocketFactory->CreateSocket (); + NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0.0"), 0)), 0, "trivial"); + rxSocket->SetRecvCallback (MakeCallback (&Ipv4RawSocketImplTest::ReceivePkt, this)); + + Ptr rxSocket2 = rxSocketFactory->CreateSocket (); + rxSocket2->SetRecvCallback (MakeCallback (&Ipv4RawSocketImplTest::ReceivePkt2, this)); + NS_TEST_EXPECT_MSG_EQ (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 0)), 0, "trivial"); + + Ptr txSocketFactory = txNode->GetObject (); + Ptr txSocket = txSocketFactory->CreateSocket (); + + // ------ Now the tests ------------ + + // Unicast test + SendData (txSocket, "10.0.0.1"); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 143, "recv: 10.0.0.1"); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket2->GetSize (), 0, "second interface should not receive it"); + + m_receivedPacket->RemoveAllByteTags (); + m_receivedPacket2->RemoveAllByteTags (); + +#if 0 + // Simple broadcast test + + SendData (txSocket, "255.255.255.255"); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 143, "recv: 255.255.255.255"); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket2->GetSize (), 143, "second socket should not receive it (it is bound specifically to the second interface's address"); + + m_receivedPacket->RemoveAllByteTags (); + m_receivedPacket2->RemoveAllByteTags (); +#endif + + // Simple Link-local multicast test + + txSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.1.2"), 0)); + SendData (txSocket, "224.0.0.9"); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 143, "recv: 224.0.0.9"); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket2->GetSize (), 0, "second socket should not receive it (it is bound specifically to the second interface's address"); + + m_receivedPacket->RemoveAllByteTags (); + m_receivedPacket2->RemoveAllByteTags (); + +#if 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 -- if + // the socket address matches. + rxSocket2->Dispose (); + rxSocket2 = rxSocketFactory->CreateSocket (); + rxSocket2->SetRecvCallback (MakeCallback (&Ipv4RawSocketImplTest::ReceivePkt2, this)); + NS_TEST_EXPECT_MSG_EQ (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 0)), 0, "trivial"); + + SendData (txSocket, "255.255.255.255"); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 143, "recv: 255.255.255.255"); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket2->GetSize (), 143, "recv: 255.255.255.255"); +#endif + + m_receivedPacket = 0; + m_receivedPacket2 = 0; + + Simulator::Destroy (); + + return GetErrorStatus (); +} +//----------------------------------------------------------------------------- +class Ipv4RawTestSuite : public TestSuite +{ +public: + Ipv4RawTestSuite () : TestSuite ("ipv4-raw", UNIT) + { + AddTestCase (new Ipv4RawSocketImplTest); + } +} g_ipv4rawTestSuite; + +}; // namespace ns3 diff -r 223148e5de54 src/internet-stack/wscript --- a/src/internet-stack/wscript Thu Apr 08 11:14:56 2010 +0900 +++ b/src/internet-stack/wscript Thu Apr 08 11:21:19 2010 +0900 @@ -75,6 +75,7 @@ 'tcp-test.cc', 'udp-test.cc', 'ipv4-test.cc', + 'ipv4-raw-test.cc', 'ipv4-l4-protocol.cc', 'udp-header.cc', 'tcp-header.cc',