net/socket and net/tcp: Fix a problem in whent there are multiple network devices. Polls were being sent to all TCP sockets before. This is not good because it means that packets may sometimes be sent out on the wrong device. That is inefficient because it will cause retransmissions and bad performance. But, worse, when one of the devices is not Ethernet, it will have a different MSS and, as a result, incorrect data transfers can cause crashes. The fix is to lock into a single device once the MSS is locked locked down.

This commit is contained in:
Gregory Nutt 2015-08-27 09:06:46 -06:00
parent 3bcdb218ff
commit b1e09d4847
6 changed files with 77 additions and 8 deletions

View File

@ -10883,4 +10883,13 @@
SaeHie Park (2015-08-25). SaeHie Park (2015-08-25).
* drivers/rwbuffer.c: Fix some logic errors. From Dmitry Nikolaev * drivers/rwbuffer.c: Fix some logic errors. From Dmitry Nikolaev
via Juha Niskanen (2015-08-26). via Juha Niskanen (2015-08-26).
* net/socket and net/tcp: Fix a problem in whent there are multiple
network devices. Polls were being sent to all TCP sockets before.
This is not good because it means that packets may sometimes be
sent out on the wrong device. That is inefficient because it
will cause retransmissions and bad performance. But, worse, when
one of the devices is not Ethernet, it will have a different MSS
and, as a result, incorrect data transfers can cause crashes.
The fix is to lock into a single device once the MSS is locked
locked down (2015-08-27).

View File

@ -278,22 +278,32 @@ static uint16_t psock_connect_interrupt(FAR struct net_driver_s *dev,
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
if (pstate->tc_conn->domain == PF_INET) if (pstate->tc_conn->domain == PF_INET)
#endif #endif
{ {
pstate->tc_conn->mss = TCP_IPv4_INITIAL_MSS(dev); pstate->tc_conn->mss = TCP_IPv4_INITIAL_MSS(dev);
} }
#endif /* CONFIG_NET_IPv4 */ #endif /* CONFIG_NET_IPv4 */
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
else else
#endif #endif
{ {
pstate->tc_conn->mss = TCP_IPv4_INITIAL_MSS(dev); pstate->tc_conn->mss = TCP_IPv4_INITIAL_MSS(dev);
} }
#endif /* CONFIG_NET_IPv6 */ #endif /* CONFIG_NET_IPv6 */
#ifdef CONFIG_NETDEV_MULTINIC
/* We now have to filter all outgoing transfers so that they use only
* the MSS of this device.
*/
DEBUGASSERT(pstate->tc_conn->dev == NULL ||
pstate->tc_conn->dev == dev);
pstate->tc_conn->dev = dev;
#endif /* CONFIG_NETDEV_MULTINIC */
#endif /* CONFIG_NET_MULTILINK */ #endif /* CONFIG_NET_MULTILINK */
/* Wake up the waiting thread */ /* Wake up the waiting thread */

View File

@ -324,6 +324,18 @@ static uint16_t sendfile_interrupt(FAR struct net_driver_s *dev, FAR void *pvcon
FAR struct sendfile_s *pstate = (FAR struct sendfile_s *)pvpriv; FAR struct sendfile_s *pstate = (FAR struct sendfile_s *)pvpriv;
int ret; int ret;
#ifdef CONFIG_NETDEV_MULTINIC
/* The TCP socket is connected and, hence, should be bound to a device.
* Make sure that the polling device is the own that we are bound to.
*/
DEBUGASSERT(conn->dev != NULL);
if (dev != conn->dev)
{
return flags;
}
#endif
nllvdbg("flags: %04x acked: %d sent: %d\n", nllvdbg("flags: %04x acked: %d sent: %d\n",
flags, pstate->snd_acked, pstate->snd_sent); flags, pstate->snd_acked, pstate->snd_sent);

View File

@ -1003,6 +1003,13 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
net_ipv6addr_copy(conn->u.ipv6.raddr, ip->srcipaddr); net_ipv6addr_copy(conn->u.ipv6.raddr, ip->srcipaddr);
#ifdef CONFIG_NETDEV_MULTINIC #ifdef CONFIG_NETDEV_MULTINIC
net_ipv6addr_copy(conn->u.ipv6.laddr, ip->destipaddr); net_ipv6addr_copy(conn->u.ipv6.laddr, ip->destipaddr);
/* We now have to filter all outgoing transfers so that they use
* only the MSS of this device.
*/
DEBUGASSERT(conn->dev == NULL || conn->dev == dev);
conn->dev = dev;
#endif #endif
/* Find the device that can receive packets on the network /* Find the device that can receive packets on the network
@ -1028,6 +1035,13 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
#ifdef CONFIG_NETDEV_MULTINIC #ifdef CONFIG_NETDEV_MULTINIC
net_ipv4addr_copy(conn->u.ipv4.laddr, net_ipv4addr_copy(conn->u.ipv4.laddr,
net_ip4addr_conv32(ip->destipaddr)); net_ip4addr_conv32(ip->destipaddr));
/* We now have to filter all outgoing transfers so that they use
* only the MSS of this device.
*/
DEBUGASSERT(conn->dev == NULL || conn->dev == dev);
conn->dev = dev;
#endif #endif
/* Find the device that can receive packets on the network /* Find the device that can receive packets on the network

View File

@ -338,6 +338,18 @@ static uint16_t psock_send_interrupt(FAR struct net_driver_s *dev,
FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn;
FAR struct socket *psock = (FAR struct socket *)pvpriv; FAR struct socket *psock = (FAR struct socket *)pvpriv;
#ifdef CONFIG_NETDEV_MULTINIC
/* The TCP socket is connected and, hence, should be bound to a device.
* Make sure that the polling device is the own that we are bound to.
*/
DEBUGASSERT(conn->dev != NULL);
if (dev != conn->dev)
{
return flags;
}
#endif
nllvdbg("flags: %04x\n", flags); nllvdbg("flags: %04x\n", flags);
/* If this packet contains an acknowledgement, then update the count of /* If this packet contains an acknowledgement, then update the count of

View File

@ -290,6 +290,18 @@ static uint16_t tcpsend_interrupt(FAR struct net_driver_s *dev,
FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn;
FAR struct send_s *pstate = (FAR struct send_s *)pvpriv; FAR struct send_s *pstate = (FAR struct send_s *)pvpriv;
#ifdef CONFIG_NETDEV_MULTINIC
/* The TCP socket is connected and, hence, should be bound to a device.
* Make sure that the polling device is the own that we are bound to.
*/
DEBUGASSERT(conn->dev != NULL);
if (dev != conn->dev)
{
return flags;
}
#endif
nllvdbg("flags: %04x acked: %d sent: %d\n", nllvdbg("flags: %04x acked: %d sent: %d\n",
flags, pstate->snd_acked, pstate->snd_sent); flags, pstate->snd_acked, pstate->snd_sent);