src/internet-node/udp-socket-impl.cc
changeset 3894 6b3415c550e1
parent 3893 94f771c1373a
parent 3261 b0987a6a74c8
child 3895 b584563a7781
equal deleted inserted replaced
3893:94f771c1373a 3894:6b3415c550e1
     1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
       
     2 /*
       
     3  * Copyright (c) 2007 INRIA
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License version 2 as
       
     7  * published by the Free Software Foundation;
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    17  *
       
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
       
    19  */
       
    20 
       
    21 #include "ns3/log.h"
       
    22 #include "ns3/node.h"
       
    23 #include "ns3/inet-socket-address.h"
       
    24 #include "ns3/ipv4-route.h"
       
    25 #include "ns3/ipv4.h"
       
    26 #include "ns3/udp-socket-factory.h"
       
    27 #include "ns3/trace-source-accessor.h"
       
    28 #include "ns3/uinteger.h"
       
    29 #include "ns3/boolean.h"
       
    30 #include "udp-socket-impl.h"
       
    31 #include "udp-l4-protocol.h"
       
    32 #include "ipv4-end-point.h"
       
    33 #include "ipv4-l4-demux.h"
       
    34 
       
    35 NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl");
       
    36 
       
    37 namespace ns3 {
       
    38 
       
    39 static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507;
       
    40 
       
    41 // Add attributes generic to all UdpSockets to base class UdpSocket
       
    42 TypeId
       
    43 UdpSocketImpl::GetTypeId (void)
       
    44 {
       
    45   static TypeId tid = TypeId ("ns3::UdpSocketImpl")
       
    46     .SetParent<UdpSocket> ()
       
    47     .AddConstructor<UdpSocketImpl> ()
       
    48     .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow",
       
    49                      MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace))
       
    50     ;
       
    51   return tid;
       
    52 }
       
    53 
       
    54 UdpSocketImpl::UdpSocketImpl ()
       
    55   : m_endPoint (0),
       
    56     m_node (0),
       
    57     m_udp (0),
       
    58     m_errno (ERROR_NOTERROR),
       
    59     m_shutdownSend (false),
       
    60     m_shutdownRecv (false),
       
    61     m_connected (false),
       
    62     m_rxAvailable (0)
       
    63 {
       
    64   NS_LOG_FUNCTION_NOARGS ();
       
    65 }
       
    66 
       
    67 UdpSocketImpl::~UdpSocketImpl ()
       
    68 {
       
    69   NS_LOG_FUNCTION_NOARGS ();
       
    70 
       
    71   m_node = 0;
       
    72   if (m_endPoint != 0)
       
    73     {
       
    74       NS_ASSERT (m_udp != 0);
       
    75       /**
       
    76        * Note that this piece of code is a bit tricky:
       
    77        * when DeAllocate is called, it will call into
       
    78        * Ipv4EndPointDemux::Deallocate which triggers
       
    79        * a delete of the associated endPoint which triggers
       
    80        * in turn a call to the method ::Destroy below
       
    81        * will will zero the m_endPoint field.
       
    82        */
       
    83       NS_ASSERT (m_endPoint != 0);
       
    84       m_udp->DeAllocate (m_endPoint);
       
    85       NS_ASSERT (m_endPoint == 0);
       
    86     }
       
    87   m_udp = 0;
       
    88 }
       
    89 
       
    90 void 
       
    91 UdpSocketImpl::SetNode (Ptr<Node> node)
       
    92 {
       
    93   NS_LOG_FUNCTION_NOARGS ();
       
    94   m_node = node;
       
    95 
       
    96 }
       
    97 void 
       
    98 UdpSocketImpl::SetUdp (Ptr<UdpL4Protocol> udp)
       
    99 {
       
   100   NS_LOG_FUNCTION_NOARGS ();
       
   101   m_udp = udp;
       
   102 }
       
   103 
       
   104 
       
   105 enum Socket::SocketErrno
       
   106 UdpSocketImpl::GetErrno (void) const
       
   107 {
       
   108   NS_LOG_FUNCTION_NOARGS ();
       
   109   return m_errno;
       
   110 }
       
   111 
       
   112 Ptr<Node>
       
   113 UdpSocketImpl::GetNode (void) const
       
   114 {
       
   115   NS_LOG_FUNCTION_NOARGS ();
       
   116   return m_node;
       
   117 }
       
   118 
       
   119 void 
       
   120 UdpSocketImpl::Destroy (void)
       
   121 {
       
   122   NS_LOG_FUNCTION_NOARGS ();
       
   123   m_node = 0;
       
   124   m_endPoint = 0;
       
   125   m_udp = 0;
       
   126 }
       
   127 
       
   128 int
       
   129 UdpSocketImpl::FinishBind (void)
       
   130 {
       
   131   NS_LOG_FUNCTION_NOARGS ();
       
   132   if (m_endPoint == 0)
       
   133     {
       
   134       return -1;
       
   135     }
       
   136   m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
       
   137   m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
       
   138   return 0;
       
   139 }
       
   140 
       
   141 int
       
   142 UdpSocketImpl::Bind (void)
       
   143 {
       
   144   NS_LOG_FUNCTION_NOARGS ();
       
   145   m_endPoint = m_udp->Allocate ();
       
   146   return FinishBind ();
       
   147 }
       
   148 
       
   149 int 
       
   150 UdpSocketImpl::Bind (const Address &address)
       
   151 {
       
   152   NS_LOG_FUNCTION (this << address);
       
   153 
       
   154   if (!InetSocketAddress::IsMatchingType (address))
       
   155     {
       
   156       NS_LOG_ERROR ("Not IsMatchingType");
       
   157       return ERROR_INVAL;
       
   158     }
       
   159   InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
       
   160   Ipv4Address ipv4 = transport.GetIpv4 ();
       
   161   uint16_t port = transport.GetPort ();
       
   162   if (ipv4 == Ipv4Address::GetAny () && port == 0)
       
   163     {
       
   164       m_endPoint = m_udp->Allocate ();
       
   165     }
       
   166   else if (ipv4 == Ipv4Address::GetAny () && port != 0)
       
   167     {
       
   168       m_endPoint = m_udp->Allocate (port);
       
   169     }
       
   170   else if (ipv4 != Ipv4Address::GetAny () && port == 0)
       
   171     {
       
   172       m_endPoint = m_udp->Allocate (ipv4);
       
   173     }
       
   174   else if (ipv4 != Ipv4Address::GetAny () && port != 0)
       
   175     {
       
   176       m_endPoint = m_udp->Allocate (ipv4, port);
       
   177     }
       
   178 
       
   179   return FinishBind ();
       
   180 }
       
   181 
       
   182 int 
       
   183 UdpSocketImpl::ShutdownSend (void)
       
   184 {
       
   185   NS_LOG_FUNCTION_NOARGS ();
       
   186   m_shutdownSend = true;
       
   187   return 0;
       
   188 }
       
   189 
       
   190 int 
       
   191 UdpSocketImpl::ShutdownRecv (void)
       
   192 {
       
   193   NS_LOG_FUNCTION_NOARGS ();
       
   194   m_shutdownRecv = false;
       
   195   return 0;
       
   196 }
       
   197 
       
   198 int
       
   199 UdpSocketImpl::Close(void)
       
   200 {
       
   201   NS_LOG_FUNCTION_NOARGS ();
       
   202   NotifyCloseCompleted ();
       
   203   return 0;
       
   204 }
       
   205 
       
   206 int
       
   207 UdpSocketImpl::Connect(const Address & address)
       
   208 {
       
   209   NS_LOG_FUNCTION (this << address);
       
   210   InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
       
   211   m_defaultAddress = transport.GetIpv4 ();
       
   212   m_defaultPort = transport.GetPort ();
       
   213   NotifyConnectionSucceeded ();
       
   214   m_connected = true;
       
   215 
       
   216   return 0;
       
   217 }
       
   218 
       
   219 int 
       
   220 UdpSocketImpl::Listen (uint32_t queueLimit)
       
   221 {
       
   222   m_errno = Socket::ERROR_OPNOTSUPP;
       
   223   return -1;
       
   224 }
       
   225 
       
   226 int 
       
   227 UdpSocketImpl::Send (Ptr<Packet> p)
       
   228 {
       
   229   NS_LOG_FUNCTION (this << p);
       
   230 
       
   231   if (!m_connected)
       
   232     {
       
   233       m_errno = ERROR_NOTCONN;
       
   234       return -1;
       
   235     }
       
   236   return DoSend (p);
       
   237 }
       
   238 
       
   239 int 
       
   240 UdpSocketImpl::DoSend (Ptr<Packet> p)
       
   241 {
       
   242   NS_LOG_FUNCTION_NOARGS ();
       
   243   if (m_endPoint == 0)
       
   244     {
       
   245       if (Bind () == -1)
       
   246        {
       
   247           NS_ASSERT (m_endPoint == 0);
       
   248          return -1;
       
   249        }
       
   250       NS_ASSERT (m_endPoint != 0);
       
   251     }
       
   252   if (m_shutdownSend)
       
   253     {
       
   254       m_errno = ERROR_SHUTDOWN;
       
   255       return -1;
       
   256     } 
       
   257   
       
   258   return DoSendTo (p, m_defaultAddress, m_defaultPort);
       
   259 }
       
   260 
       
   261 int
       
   262 UdpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
       
   263 {
       
   264   NS_LOG_FUNCTION (this << p << address);
       
   265 
       
   266   if (!m_connected)
       
   267     {
       
   268       NS_LOG_LOGIC ("Not connected");
       
   269       InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
       
   270       Ipv4Address ipv4 = transport.GetIpv4 ();
       
   271       uint16_t port = transport.GetPort ();
       
   272       return DoSendTo (p, ipv4, port);
       
   273     }
       
   274   else
       
   275     {
       
   276       // connected UDP socket must use default addresses
       
   277       NS_LOG_LOGIC ("Connected");
       
   278       return DoSendTo (p, m_defaultAddress, m_defaultPort);
       
   279     }
       
   280 }
       
   281 
       
   282 int
       
   283 UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
       
   284 {
       
   285   NS_LOG_FUNCTION (this << p << dest << port);
       
   286 
       
   287   if (m_endPoint == 0)
       
   288     {
       
   289       if (Bind () == -1)
       
   290 	{
       
   291           NS_ASSERT (m_endPoint == 0);
       
   292 	  return -1;
       
   293 	}
       
   294       NS_ASSERT (m_endPoint != 0);
       
   295     }
       
   296   if (m_shutdownSend)
       
   297     {
       
   298       m_errno = ERROR_SHUTDOWN;
       
   299       return -1;
       
   300     }
       
   301 
       
   302   if (p->GetSize () > GetTxAvailable () )
       
   303     {
       
   304       m_errno = ERROR_MSGSIZE;
       
   305       return -1;
       
   306     }
       
   307 
       
   308   uint32_t localIfIndex;
       
   309   Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
       
   310 
       
   311   // Locally override the IP TTL for this socket
       
   312   // We cannot directly modify the TTL at this stage, so we set a Packet tag
       
   313   // The destination can be either multicast, unicast/anycast, or
       
   314   // either all-hosts broadcast or limited (subnet-directed) broadcast.
       
   315   // For the latter two broadcast types, the TTL will later be set to one
       
   316   // irrespective of what is set in these socket options.  So, this tagging  
       
   317   // may end up setting the TTL of a limited broadcast packet to be
       
   318   // the same as a unicast, but it will be fixed further down the stack
       
   319   //NS_LOG_UNCOND ("IPttl: " << m_ipTtl);
       
   320   if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
       
   321     {
       
   322       SocketIpTtlTag tag;
       
   323       tag.SetTtl (m_ipMulticastTtl);
       
   324       p->AddTag (tag);
       
   325     }
       
   326   else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ())
       
   327     {
       
   328       SocketIpTtlTag tag;
       
   329       tag.SetTtl (m_ipTtl);
       
   330       p->AddTag (tag);
       
   331     }
       
   332   //
       
   333   // If dest is sent to the limited broadcast address (all ones),
       
   334   // convert it to send a copy of the packet out of every interface
       
   335   //
       
   336   if (dest.IsBroadcast ())
       
   337     {
       
   338       NS_LOG_LOGIC ("Limited broadcast start.");
       
   339       for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
       
   340         {
       
   341           Ipv4Address addri = ipv4->GetAddress (i);
       
   342           Ipv4Mask maski = ipv4->GetNetworkMask (i);
       
   343           Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
       
   344           NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast
       
   345                         << " (mask is " << maski << ")");
       
   346           m_udp->Send (p->Copy (), addri, bcast,
       
   347                        m_endPoint->GetLocalPort (), port);
       
   348           NotifyDataSent (p->GetSize ());
       
   349         }
       
   350       NS_LOG_LOGIC ("Limited broadcast end.");
       
   351       return p->GetSize();
       
   352     }
       
   353   else if (ipv4->GetIfIndexForDestination(dest, localIfIndex))
       
   354     {
       
   355       NS_LOG_LOGIC ("Route exists");
       
   356       m_udp->Send (p->Copy (), ipv4->GetAddress (localIfIndex), dest,
       
   357 		   m_endPoint->GetLocalPort (), port);
       
   358       NotifyDataSent (p->GetSize ());
       
   359       return p->GetSize();;
       
   360     }
       
   361   else
       
   362    {
       
   363       NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
       
   364       m_errno = ERROR_NOROUTETOHOST;
       
   365       return -1;
       
   366    }
       
   367 
       
   368   return 0;
       
   369 }
       
   370 
       
   371 // XXX maximum message size for UDP broadcast is limited by MTU
       
   372 // size of underlying link; we are not checking that now.
       
   373 uint32_t
       
   374 UdpSocketImpl::GetTxAvailable (void) const
       
   375 {
       
   376   NS_LOG_FUNCTION_NOARGS ();
       
   377   // No finite send buffer is modelled, but we must respect
       
   378   // the maximum size of an IP datagram (65535 bytes - headers).
       
   379   return MAX_IPV4_UDP_DATAGRAM_SIZE;
       
   380 }
       
   381 
       
   382 int 
       
   383 UdpSocketImpl::SendTo (Ptr<Packet> p, const Address &address)
       
   384 {
       
   385   NS_LOG_FUNCTION (this << address << p);
       
   386   InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
       
   387   Ipv4Address ipv4 = transport.GetIpv4 ();
       
   388   uint16_t port = transport.GetPort ();
       
   389   return DoSendTo (p, ipv4, port);
       
   390 }
       
   391 
       
   392 Ptr<Packet>
       
   393 UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
       
   394 {
       
   395   NS_LOG_FUNCTION_NOARGS ();
       
   396   if (m_deliveryQueue.empty() )
       
   397     {
       
   398       return 0;
       
   399     }
       
   400   Ptr<Packet> p = m_deliveryQueue.front ();
       
   401   if (p->GetSize () <= maxSize) 
       
   402     {
       
   403       m_deliveryQueue.pop ();
       
   404       m_rxAvailable -= p->GetSize ();
       
   405     }
       
   406   else
       
   407     {
       
   408       p = 0; 
       
   409     }
       
   410   return p;
       
   411 }
       
   412 
       
   413 uint32_t
       
   414 UdpSocketImpl::GetRxAvailable (void) const
       
   415 {
       
   416   NS_LOG_FUNCTION_NOARGS ();
       
   417   // We separately maintain this state to avoid walking the queue 
       
   418   // every time this might be called
       
   419   return m_rxAvailable;
       
   420 }
       
   421 
       
   422 void 
       
   423 UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
       
   424 {
       
   425   NS_LOG_FUNCTION (this << packet << ipv4 << port);
       
   426 
       
   427   if (m_shutdownRecv)
       
   428     {
       
   429       return;
       
   430     }
       
   431   if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
       
   432     {
       
   433       Address address = InetSocketAddress (ipv4, port);
       
   434       SocketRxAddressTag tag;
       
   435       tag.SetAddress (address);
       
   436       packet->AddTag (tag);
       
   437       m_deliveryQueue.push (packet);
       
   438       m_rxAvailable += packet->GetSize ();
       
   439       NotifyDataRecv ();
       
   440     }
       
   441   else
       
   442     {
       
   443       // In general, this case should not occur unless the
       
   444       // receiving application reads data from this socket slowly
       
   445       // in comparison to the arrival rate
       
   446       //
       
   447       // drop and trace packet
       
   448       NS_LOG_WARN ("No receive buffer space available.  Drop.");
       
   449       m_dropTrace (packet);
       
   450     }
       
   451 }
       
   452 
       
   453 
       
   454 void 
       
   455 UdpSocketImpl::SetRcvBufSize (uint32_t size)
       
   456 {
       
   457   m_rcvBufSize = size;
       
   458 }
       
   459 
       
   460 uint32_t 
       
   461 UdpSocketImpl::GetRcvBufSize (void) const
       
   462 {
       
   463   return m_rcvBufSize;
       
   464 }
       
   465 
       
   466 void 
       
   467 UdpSocketImpl::SetIpTtl (uint32_t ipTtl)
       
   468 {
       
   469   m_ipTtl = ipTtl;
       
   470 }
       
   471 
       
   472 uint32_t 
       
   473 UdpSocketImpl::GetIpTtl (void) const
       
   474 {
       
   475   return m_ipTtl;
       
   476 }
       
   477 
       
   478 void 
       
   479 UdpSocketImpl::SetIpMulticastTtl (uint32_t ipTtl)
       
   480 {
       
   481   m_ipMulticastTtl = ipTtl;
       
   482 }
       
   483 
       
   484 uint32_t 
       
   485 UdpSocketImpl::GetIpMulticastTtl (void) const
       
   486 {
       
   487   return m_ipMulticastTtl;
       
   488 }
       
   489 
       
   490 } //namespace ns3
       
   491 
       
   492 
       
   493 #ifdef RUN_SELF_TESTS
       
   494 
       
   495 #include "ns3/test.h"
       
   496 #include "ns3/socket-factory.h"
       
   497 #include "ns3/udp-socket-factory.h"
       
   498 #include "ns3/simulator.h"
       
   499 #include "ns3/simple-channel.h"
       
   500 #include "ns3/simple-net-device.h"
       
   501 #include "ns3/drop-tail-queue.h"
       
   502 #include "internet-stack.h"
       
   503 #include <string>
       
   504 
       
   505 namespace ns3 {
       
   506 
       
   507 class UdpSocketImplTest: public Test
       
   508 {
       
   509   Ptr<Packet> m_receivedPacket;
       
   510   Ptr<Packet> m_receivedPacket2;
       
   511 
       
   512 public:
       
   513   virtual bool RunTests (void);
       
   514   UdpSocketImplTest ();
       
   515 
       
   516   void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
       
   517   void ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
       
   518   void ReceivePkt (Ptr<Socket> socket);
       
   519   void ReceivePkt2 (Ptr<Socket> socket);
       
   520 };
       
   521 
       
   522 
       
   523 UdpSocketImplTest::UdpSocketImplTest ()
       
   524   : Test ("UdpSocketImpl") 
       
   525 {
       
   526 }
       
   527 
       
   528 void UdpSocketImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
       
   529 {
       
   530   m_receivedPacket = packet;
       
   531 }
       
   532 
       
   533 void UdpSocketImplTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
       
   534 {
       
   535   m_receivedPacket2 = packet;
       
   536 }
       
   537 
       
   538 void UdpSocketImplTest::ReceivePkt (Ptr<Socket> socket)
       
   539 {
       
   540   uint32_t availableData;
       
   541   availableData = socket->GetRxAvailable ();
       
   542   m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
       
   543   NS_ASSERT (availableData == m_receivedPacket->GetSize ());
       
   544 }
       
   545 
       
   546 void UdpSocketImplTest::ReceivePkt2 (Ptr<Socket> socket)
       
   547 {
       
   548   uint32_t availableData;
       
   549   availableData = socket->GetRxAvailable ();
       
   550   m_receivedPacket2 = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
       
   551   NS_ASSERT (availableData == m_receivedPacket2->GetSize ());
       
   552 }
       
   553 
       
   554 bool
       
   555 UdpSocketImplTest::RunTests (void)
       
   556 {
       
   557   bool result = true;
       
   558 
       
   559   // Create topology
       
   560   
       
   561   // Receiver Node
       
   562   Ptr<Node> rxNode = CreateObject<Node> ();
       
   563   AddInternetStack (rxNode);
       
   564   Ptr<SimpleNetDevice> rxDev1, rxDev2;
       
   565   { // first interface
       
   566     rxDev1 = CreateObject<SimpleNetDevice> ();
       
   567     rxDev1->SetAddress (Mac48Address::Allocate ());
       
   568     rxNode->AddDevice (rxDev1);
       
   569     Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
       
   570     uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
       
   571     ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1"));
       
   572     ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
       
   573     ipv4->SetUp (netdev_idx);
       
   574   }
       
   575 
       
   576   { // second interface
       
   577     rxDev2 = CreateObject<SimpleNetDevice> ();
       
   578     rxDev2->SetAddress (Mac48Address::Allocate ());
       
   579     rxNode->AddDevice (rxDev2);
       
   580     Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
       
   581     uint32_t netdev_idx = ipv4->AddInterface (rxDev2);
       
   582     ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.1"));
       
   583     ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
       
   584     ipv4->SetUp (netdev_idx);
       
   585   }
       
   586   
       
   587   // Sender Node
       
   588   Ptr<Node> txNode = CreateObject<Node> ();
       
   589   AddInternetStack (txNode);
       
   590   Ptr<SimpleNetDevice> txDev1;
       
   591   {
       
   592     txDev1 = CreateObject<SimpleNetDevice> ();
       
   593     txDev1->SetAddress (Mac48Address::Allocate ());
       
   594     txNode->AddDevice (txDev1);
       
   595     Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
       
   596     uint32_t netdev_idx = ipv4->AddInterface (txDev1);
       
   597     ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2"));
       
   598     ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
       
   599     ipv4->SetUp (netdev_idx);
       
   600   }
       
   601   Ptr<SimpleNetDevice> txDev2;
       
   602   {
       
   603     txDev2 = CreateObject<SimpleNetDevice> ();
       
   604     txDev2->SetAddress (Mac48Address::Allocate ());
       
   605     txNode->AddDevice (txDev2);
       
   606     Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
       
   607     uint32_t netdev_idx = ipv4->AddInterface (txDev2);
       
   608     ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.2"));
       
   609     ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
       
   610     ipv4->SetUp (netdev_idx);
       
   611   }
       
   612 
       
   613   // link the two nodes
       
   614   Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
       
   615   rxDev1->SetChannel (channel1);
       
   616   txDev1->SetChannel (channel1);
       
   617 
       
   618   Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
       
   619   rxDev2->SetChannel (channel2);
       
   620   txDev2->SetChannel (channel2);
       
   621 
       
   622 
       
   623   // Create the UDP sockets
       
   624   Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
       
   625   Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
       
   626   NS_TEST_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0);
       
   627   rxSocket->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt, this));
       
   628 
       
   629   Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket ();
       
   630   rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
       
   631   NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0);
       
   632 
       
   633   Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
       
   634   Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
       
   635 
       
   636   // ------ Now the tests ------------
       
   637 
       
   638   // Unicast test
       
   639   m_receivedPacket = Create<Packet> ();
       
   640   m_receivedPacket2 = Create<Packet> ();
       
   641   NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), 
       
   642     InetSocketAddress (Ipv4Address("10.0.0.1"), 1234)), 123);
       
   643   Simulator::Run ();
       
   644   NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
       
   645   NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it
       
   646 
       
   647   m_receivedPacket->RemoveAllTags ();
       
   648   m_receivedPacket2->RemoveAllTags ();
       
   649 
       
   650   // Simple broadcast test
       
   651 
       
   652   m_receivedPacket = Create<Packet> ();
       
   653   m_receivedPacket2 = Create<Packet> ();
       
   654   NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), 
       
   655     InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
       
   656   Simulator::Run ();
       
   657   NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
       
   658   // second socket should not receive it (it is bound specifically to the second interface's address
       
   659   NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0);
       
   660 
       
   661   m_receivedPacket->RemoveAllTags ();
       
   662   m_receivedPacket2->RemoveAllTags ();
       
   663 
       
   664   // Broadcast test with multiple receiving sockets
       
   665 
       
   666   // When receiving broadcast packets, all sockets sockets bound to
       
   667   // the address/port should receive a copy of the same packet -- if
       
   668   // the socket address matches.
       
   669   rxSocket2->Dispose ();
       
   670   rxSocket2 = rxSocketFactory->CreateSocket ();
       
   671   rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
       
   672   NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0);
       
   673 
       
   674   m_receivedPacket = Create<Packet> ();
       
   675   m_receivedPacket2 = Create<Packet> ();
       
   676   NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create<Packet> (123),
       
   677 InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
       
   678   Simulator::Run ();
       
   679   NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
       
   680   NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123);
       
   681 
       
   682   m_receivedPacket->RemoveAllTags ();
       
   683   m_receivedPacket2->RemoveAllTags ();
       
   684 
       
   685   Simulator::Destroy ();
       
   686 
       
   687   return result;
       
   688 }
       
   689 
       
   690 static UdpSocketImplTest gUdpSocketImplTest;
       
   691 
       
   692 }; // namespace ns3
       
   693 
       
   694 #endif /* RUN_SELF_TESTS */