Bug 1824 - L4 protocol sockets should support BindToNetDevice over IPv6
authorTommaso Pecorella <tommaso.pecorella@unifi.it>
Fri, 12 Sep 2014 20:47:17 +0200
changeset 10933 7442f5603ef4
parent 10932 d5783e5a8b7e
child 10934 4bbf92963b74
Bug 1824 - L4 protocol sockets should support BindToNetDevice over IPv6
CHANGES.html
RELEASE_NOTES
src/dsdv/model/dsdv-routing-protocol.cc
src/internet/doc/internet-stack.rst
src/internet/model/tcp-socket-base.cc
src/internet/model/udp-socket-impl.cc
src/network/model/socket.h
--- a/CHANGES.html	Fri Sep 12 10:18:55 2014 -0700
+++ b/CHANGES.html	Fri Sep 12 20:47:17 2014 +0200
@@ -114,6 +114,9 @@
        Data or Control channel and RbId can be configured by new attributes in RadioEnvironmentMapHelper </li>
   <li> lte-sinr-chunk-processor refactored to lte-chunk-processor. Removed all lte-xxx-chunk-processor 
        implementations</li>
+  <li> BindToNetDevice affects also sockets using IPv6.</li>
+  <li> BindToNetDevice now calls implicitly Bind (). To bind a socket to a NetDevice and to a specific address,
+       the correct sequence is Bind (address) - BindToNetDevice (device). The opposite will raise an error.</li>
 </ul>
 
 <h2>Changes to build system:</h2>
--- a/RELEASE_NOTES	Fri Sep 12 10:18:55 2014 -0700
+++ b/RELEASE_NOTES	Fri Sep 12 20:47:17 2014 +0200
@@ -52,6 +52,7 @@
 
 - Bug 1762 - UE stuck in IDLE_CONNECTING because RRC CONN REQ is not transmitted
 - Bug 1811 - basic traffic generator for network module 
+- Bug 1824 - L4 protocol sockets should support BindToNetDevice over IPv6
 - Bug 1831 - TcpSocket SlowStartThreshold is not a TraceSource
 - Bug 1851 - WifiRadioEnergyModel energy consumption values are taken from a 802.15.4 chip
 - Bug 1854 - std::out_of_range Problem
--- a/src/dsdv/model/dsdv-routing-protocol.cc	Fri Sep 12 10:18:55 2014 -0700
+++ b/src/dsdv/model/dsdv-routing-protocol.cc	Fri Sep 12 20:47:17 2014 +0200
@@ -956,8 +956,8 @@
   Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),UdpSocketFactory::GetTypeId ());
   NS_ASSERT (socket != 0);
   socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvDsdv,this));
+  socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), DSDV_PORT));
   socket->BindToNetDevice (l3->GetNetDevice (i));
-  socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), DSDV_PORT));
   socket->SetAllowBroadcast (true);
   socket->SetAttribute ("IpTtl",UintegerValue (1));
   m_socketAddresses.insert (std::make_pair (socket,iface));
@@ -1013,9 +1013,9 @@
       Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),UdpSocketFactory::GetTypeId ());
       NS_ASSERT (socket != 0);
       socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvDsdv,this));
-      socket->BindToNetDevice (l3->GetNetDevice (i));
       // Bind to any IP address so that broadcasts can be received
       socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), DSDV_PORT));
+      socket->BindToNetDevice (l3->GetNetDevice (i));
       socket->SetAllowBroadcast (true);
       m_socketAddresses.insert (std::make_pair (socket,iface));
       Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()));
--- a/src/internet/doc/internet-stack.rst	Fri Sep 12 10:18:55 2014 -0700
+++ b/src/internet/doc/internet-stack.rst	Fri Sep 12 20:47:17 2014 +0200
@@ -204,6 +204,35 @@
 a :cpp:class:`Ipv4Address` or :cpp:class:`Ipv6Address`, these functions will
 return an error.  The ``Bind (void)`` and ``Bind6 (void)`` functions bind to
 "0.0.0.0" and "::" respectively.
+
+The socket can also be bound to a specific NetDevice though the 
+``BindToNetDevice (Ptr<NetDevice> netdevice)`` function.
+``BindToNetDevice (Ptr<NetDevice> netdevice)`` will bind the socket
+to "0.0.0.0" and "::" (equivalent to calling ``Bind ()`` and ``Bind6 ()``,
+unless the socket has been already bound to a specific address.
+Summarizing, the correct sequence is::
+
+      Ptr<Udp> udpSocketFactory = GetNode ()->GetObject<Udp> ();
+      Ptr<Socket> m_socket = socketFactory->CreateSocket ();
+      m_socket->BindToNetDevice (n_netDevice);
+     ...
+
+or::
+
+      Ptr<Udp> udpSocketFactory = GetNode ()->GetObject<Udp> ();
+      Ptr<Socket> m_socket = socketFactory->CreateSocket ();
+      m_socket->Bind (m_local_address);
+      m_socket->BindToNetDevice (n_netDevice);
+      ...
+
+The following raises an error::
+
+      Ptr<Udp> udpSocketFactory = GetNode ()->GetObject<Udp> ();
+      Ptr<Socket> m_socket = socketFactory->CreateSocket ();
+      m_socket->BindToNetDevice (n_netDevice);
+      m_socket->Bind (m_local_address);
+      ...
+
 See the chapter on |ns3| sockets for more information.  
 
 We have described so far a socket factory (e.g. ``class Udp``) and a socket,
--- a/src/internet/model/tcp-socket-base.cc	Fri Sep 12 10:18:55 2014 -0700
+++ b/src/internet/model/tcp-socket-base.cc	Fri Sep 12 20:47:17 2014 +0200
@@ -686,21 +686,28 @@
 {
   NS_LOG_FUNCTION (netdevice);
   Socket::BindToNetDevice (netdevice); // Includes sanity check
-  if (m_endPoint == 0 && m_endPoint6 == 0)
+  if (m_endPoint == 0)
     {
       if (Bind () == -1)
         {
-          NS_ASSERT ((m_endPoint == 0 && m_endPoint6 == 0));
+          NS_ASSERT (m_endPoint == 0);
           return;
         }
-      NS_ASSERT ((m_endPoint != 0 && m_endPoint6 != 0));
+      NS_ASSERT (m_endPoint != 0);
     }
+  m_endPoint->BindToNetDevice (netdevice);
 
-  if (m_endPoint != 0)
+  if (m_endPoint6 == 0)
     {
-      m_endPoint->BindToNetDevice (netdevice);
+      if (Bind6 () == -1)
+        {
+          NS_ASSERT (m_endPoint6 == 0);
+          return;
+        }
+      NS_ASSERT (m_endPoint6 != 0);
     }
-  // No BindToNetDevice() for Ipv6EndPoint
+  m_endPoint6->BindToNetDevice (netdevice);
+
   return;
 }
 
--- a/src/internet/model/udp-socket-impl.cc	Fri Sep 12 10:18:55 2014 -0700
+++ b/src/internet/model/udp-socket-impl.cc	Fri Sep 12 20:47:17 2014 +0200
@@ -247,6 +247,8 @@
 
   if (InetSocketAddress::IsMatchingType (address))
     {
+      NS_ASSERT_MSG (m_endPoint == 0, "Endpoint already allocated (maybe you used BindToNetDevice before Bind).");
+
       InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
       Ipv4Address ipv4 = transport.GetIpv4 ();
       uint16_t port = transport.GetPort ();
@@ -274,6 +276,8 @@
     }
   else if (Inet6SocketAddress::IsMatchingType (address))
     {
+      NS_ASSERT_MSG (m_endPoint == 0, "Endpoint already allocated (maybe you used BindToNetDevice before Bind).");
+
       Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
       Ipv6Address ipv6 = transport.GetIpv6 ();
       uint16_t port = transport.GetPort ();
@@ -917,6 +921,7 @@
 UdpSocketImpl::BindToNetDevice (Ptr<NetDevice> netdevice)
 {
   NS_LOG_FUNCTION (netdevice);
+
   Socket::BindToNetDevice (netdevice); // Includes sanity check
   if (m_endPoint == 0)
     {
@@ -928,6 +933,17 @@
       NS_ASSERT (m_endPoint != 0);
     }
   m_endPoint->BindToNetDevice (netdevice);
+
+  if (m_endPoint6 == 0)
+    {
+      if (Bind6 () == -1)
+        {
+          NS_ASSERT (m_endPoint6 == 0);
+          return;
+        }
+      NS_ASSERT (m_endPoint6 != 0);
+    }
+  m_endPoint6->BindToNetDevice (netdevice);
   return;
 }
 
--- a/src/network/model/socket.h	Fri Sep 12 10:18:55 2014 -0700
+++ b/src/network/model/socket.h	Fri Sep 12 20:47:17 2014 +0200
@@ -576,6 +576,9 @@
    * is also possible to bind to mismatching device and address, even if
    * the socket can not receive any packets as a result.
    *
+   * \warning BindToNetDevice should be used \a after Bind. Otherwise
+   * it will perform a Bind itself.
+   *
    * \param netdevice Pointer to Netdevice of desired interface
    * \returns nothing
    */