TcpSocketBase::BindToNetDevice isssue

117 views
Skip to first unread message

Miralem Mehic

unread,
Nov 10, 2016, 6:05:45 AM11/10/16
to ns-3-users
Hi Guys,

I want to bound my sockets to NetDevices since I need such scenario in simulations with multiple netdevices.
I created a UDP socket using code:
 

  /**---------------------------------------------------------------------
  *   UDP socket settings
  *----------------------------------------------------------------------*/
  /**
  *   UDP SINK socket settings
  */

  // Create the socket if not already
  if (!m_sinkSocket_udp  )
    m_sinkSocket_udp = Socket::CreateSocket (GetNode (), m_tid);

  m_sinkSocket_udp->SetIpTos(16);
  m_sinkSocket_udp->SetIpRecvTos(true);
  m_sinkSocket_udp->Bind (m_local);
  m_sinkSocket_udp->BindToNetDevice(m_sinkDevice);
  m_sinkSocket_udp->ShutdownSend ();      

  m_sinkSocket_udp->SetRecvCallback (MakeCallback (&MyAPP::HandleRead, this));
  m_sinkSocket_udp->SetAcceptCallback (
    MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
    MakeCallback (&MyAPP::HandleAccept, this));

  m_sinkSocket_udp->SetCloseCallbacks (
    MakeCallback (&MyAPP::HandlePeerClose, this),
    MakeCallback (&MyAPP::HandlePeerError, this));

  /**
  *   UDP SEND socket settings
  */
  // Create the socket if not already
  if (!m_sendSocket_udp)
    m_sendSocket_udp = Socket::CreateSocket (GetNode (), m_tid);

  //setIPtos to top priority
  m_sendSocket_udp->SetIpTos(16);
  m_sendSocket_udp->SetIpRecvTos(true);
  //m_sendSocket_udp->Bind (m_local);
  m_sendSocket_udp->BindToNetDevice(m_sendDevice);
  m_sendSocket_udp->Connect (m_peer);


which works just fine.
However, I created a TCP socket using following code:

 /**
  *   SINK socket settings
  */
  // Create the socket if not already
  if (!m_sinkSocket)
    m_sinkSocket = Socket::CreateSocket (GetNode (), m_tid);

  m_sinkSocket->SetIpTos(16);
  m_sinkSocket->SetIpRecvTos(true);
  m_sinkSocket->Bind (m_local);
  m_sinkSocket->BindToNetDevice(m_sinkDevice);

  m_sinkSocket->Listen ();
  m_sinkSocket->ShutdownSend ();      

  m_sinkSocket->SetRecvCallback (MakeCallback (&MyAPP::HandleRead, this));
  m_sinkSocket->SetAcceptCallback (
      MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
      MakeCallback (&MyAPP::HandleAccept, this));

  m_sinkSocket->SetCloseCallbacks (
      MakeCallback (&MyAPP::HandlePeerClose, this),
      MakeCallback (&MyAPP::HandlePeerError, this));

  /**
  * SEND socket settings
  */
  // Create the socket if not already
  if (!m_sendSocket)
      m_sendSocket = Socket::CreateSocket (GetNode (), m_tid);
 
  //setIPtos to top priority
  m_sendSocket->SetIpTos(16);
  m_sendSocket->SetIpRecvTos(true);
  m_sendSocket->Bind (m_local);
  m_sendSocket->BindToNetDevice(m_sendDevice);
  //initate TCP-threehand shaking

  if (InetSocketAddress::IsMatchingType (m_peer))
    NS_LOG_FUNCTION (this << m_peer << "IT IS IPV4!!!!!");

  m_sendSocket->Connect (m_peer);
  //disable receiving any data on this socket
  m_sendSocket->ShutdownRecv ();
   
  m_sendSocket->SetConnectCallback (
      MakeCallback (&MyAPP::ConnectionSucceeded, this),
      MakeCallback (&MyAPP::ConnectionFailed, this));

  m_sendSocket->SetDataSentCallback (
      MakeCallback (&MyAPP::DataSend, this));

  m_sendSocket->TraceConnectWithoutContext ("RTT", MakeCallback (&MyAPP::RegisterAckTime, this));


but TCP never execute Connect phase (SYN packets). I dig into the code and I found out that in TcpSocketBase::BindToNetDevice both endpoints (m_endPoint and m_endPoint6) are set.


/* Inherit from Socket class: Bind this socket to the specified NetDevice */
void
TcpSocketBase::BindToNetDevice (Ptr<NetDevice> netdevice)
{
  NS_LOG_FUNCTION (netdevice);
  Socket::BindToNetDevice (netdevice); // Includes sanity check
  if (m_endPoint == 0)
    {
      if (Bind () == -1)
        {
          NS_ASSERT (m_endPoint == 0);
          return;
        }
      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;
}


So when TcpSocketBase::Connect is called, it simply fail since both endpoints !=0 :

int
TcpSocketBase::Connect (const Address & address)
{
  NS_LOG_FUNCTION (this << address);

  // If haven't do so, Bind() this socket first
  if (InetSocketAddress::IsMatchingType (address) && m_endPoint6 == 0)
    {
      if (m_endPoint == 0)
        {
          if (Bind () == -1)
            {
              NS_ASSERT (m_endPoint == 0);
              return -1; // Bind() failed
            }
          NS_ASSERT (m_endPoint != 0);
        }
      InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
      m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
      SetIpTos (transport.GetTos ());
      m_endPoint6 = 0;

      // Get the appropriate local address and port number from the routing protocol and set up endpoint
      if (SetupEndpoint () != 0)
        {
          NS_LOG_ERROR ("Route to destination does not exist ?!");
          return -1;
        }
    }
  else if (Inet6SocketAddress::IsMatchingType (address)  && m_endPoint == 0)
    {
      // If we are operating on a v4-mapped address, translate the address to
      // a v4 address and re-call this function
      Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
      Ipv6Address v6Addr = transport.GetIpv6 ();
      if (v6Addr.IsIpv4MappedAddress () == true)
        {
          Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
          return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
        }

      if (m_endPoint6 == 0)
        {
          if (Bind6 () == -1)
            {
              NS_ASSERT (m_endPoint6 == 0);
              return -1; // Bind() failed
            }
          NS_ASSERT (m_endPoint6 != 0);
        }
      m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
      m_endPoint = 0;

      // Get the appropriate local address and port number from the routing protocol and set up endpoint
      if (SetupEndpoint6 () != 0)
        { // Route to destination does not exist
          return -1;
        }
    }
  else
    {
      m_errno = ERROR_INVAL;
      return -1;
    }

  // Re-initialize parameters in case this socket is being reused after CLOSE
  m_rtt->Reset ();
  m_synCount = m_synRetries;
  m_dataRetrCount = m_dataRetries;

  // DoConnect() will do state-checking and send a SYN packet
  return DoConnect ();
}


Note that this is not the case in UDPSocketImpl which does not check whether m_endpoint are 0:

int
UdpSocketImpl::Connect (const Address & address)
{
  NS_LOG_FUNCTION (this << address);
  if (InetSocketAddress::IsMatchingType(address) == true)
    {
      InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
      m_defaultAddress = Address(transport.GetIpv4 ());
      m_defaultPort = transport.GetPort ();
      SetIpTos (transport.GetTos ());
      m_connected = true;
      NotifyConnectionSucceeded ();
    }
  else if (Inet6SocketAddress::IsMatchingType(address) == true)
    {
      Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
      m_defaultAddress = Address(transport.GetIpv6 ());
      m_defaultPort = transport.GetPort ();
      m_connected = true;
      NotifyConnectionSucceeded ();
    }
  else
    {
      NotifyConnectionFailed ();
      return -1;
    }

  return 0;
}


I belive that this might be the reason why TPC cannot be used with BindToNetDevice command.

Best,
M

Tommaso Pecorella

unread,
Nov 10, 2016, 6:36:39 AM11/10/16
to ns-3-users
Hi,

can you attach a short script example ? I'll take a look at it tonight.

Cheers,

T.

Miralem Mehic

unread,
Nov 10, 2016, 12:11:16 PM11/10/16
to ns-3-users
Hi Tommaso,

thank you for reply!
Please find attached a simple code with BindToNetDevice scenario.

M
tcp_fifth_test.cc

Tommaso Pecorella

unread,
Nov 22, 2016, 7:43:15 PM11/22/16
to ns-3-users
Hi all,

for the records, this is a bug. See here bug 2561 to track its resolution.

Cheers,

T.
Reply all
Reply to author
Forward
0 new messages