If CONFIG_NET_ARP_SEND is enabled, then all ICMP, TCP, and UDP send operations will call arp_send() before attempting the real send operation. arp_send() will check if the the IP address mapping is in the ARP table and, if not send ARP requests periodically until it is. This eliminates losing the first outgoing message because there is not mapping in the ARP table.

This commit is contained in:
Gregory Nutt 2014-08-18 16:22:14 -06:00
parent 7f862bd381
commit 6e04518e4a
5 changed files with 98 additions and 12 deletions

View File

@ -58,6 +58,7 @@
#include "netdev/netdev.h"
#include "devif/devif.h"
#include "arp/arp.h"
#include "icmp/icmp.h"
/****************************************************************************
@ -331,6 +332,18 @@ int icmp_ping(net_ipaddr_t addr, uint16_t id, uint16_t seqno,
{
struct icmp_ping_s state;
net_lock_t save;
#ifdef CONFIG_NET_ARP_SEND
int ret;
/* Make sure that the IP address mapping is in the ARP table */
ret = arp_send(addr);
if (ret < 0)
{
ndbg("ERROR: Not reachable\n");
return -ENETUNREACH;
}
#endif
/* Initialize the state structure */

View File

@ -2,7 +2,7 @@
* net/socket/net_sendfile.c
*
* Copyright (C) 2013 UVC Ingenieure. All rights reserved.
* Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2014 Gregory Nutt. All rights reserved.
* Authors: Gregory Nutt <gnutt@nuttx.org>
* Max Holtzberg <mh@uvc.de>
*
@ -65,10 +65,10 @@
#include "netdev/netdev.h"
#include "devif/devif.h"
#include "arp/arp.h"
#include "tcp/tcp.h"
#include "socket/socket.h"
/****************************************************************************
* Definitions
****************************************************************************/
@ -322,10 +322,14 @@ static uint16_t sendfile_interrupt(FAR struct net_driver_s *dev, FAR void *pvcon
*
* NOTE 2: If we are actually harvesting IP addresses on incoming IP
* packets, then this check should not be necessary; the MAC mapping
* should already be in the ARP table.
* should already be in the ARP table in many cases.
*
* NOTE 3: If CONFIG_NET_ARP_SEND then we can be assured that the IP
* address mapping is already in the ARP table.
*/
#if defined(CONFIG_NET_ETHERNET) && !defined (CONFIG_NET_ARP_IPIN)
#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN) && \
!defined(CONFIG_NET_ARP_SEND)
if (pstate->snd_sent != 0 || arp_find(conn->ripaddr) != NULL)
#endif
{
@ -463,6 +467,7 @@ ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset,
if (!psock || psock->s_crefs <= 0)
{
ndbg("ERROR: Invalid socket\n");
err = EBADF;
goto errout;
}
@ -471,10 +476,23 @@ ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset,
if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags))
{
ndbg("ERROR: Not connected\n");
err = ENOTCONN;
goto errout;
}
/* Make sure that the IP address mapping is in the ARP table */
#ifdef CONFIG_NET_ARP_SEND
ret = arp_send(conn->ripaddr);
if (ret < 0)
{
ndbg("ERROR: Not reachable\n");
err = ENETUNREACH;
goto errout;
}
#endif
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);

View File

@ -55,6 +55,7 @@
#include "netdev/netdev.h"
#include "devif/devif.h"
#include "arp/arp.h"
#include "udp/udp.h"
#include "socket/socket.h"
@ -322,6 +323,7 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
#ifdef CONFIG_NET_TCP
return psock_send(psock, buf, len, flags);
#else
ndbg("ERROR: No to address\n");
err = EINVAL;
goto errout;
#endif
@ -335,6 +337,7 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
if (to->sa_family != AF_INET || tolen < sizeof(struct sockaddr_in))
#endif
{
ndbg("ERROR: Invalid address\n");
err = EBADF;
goto errout;
}
@ -343,6 +346,7 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
if (!psock || psock->s_crefs <= 0)
{
ndbg("ERROR: Invalid socket\n");
err = EBADF;
goto errout;
}
@ -351,10 +355,23 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
if (psock->s_type != SOCK_DGRAM)
{
ndbg("ERROR: Connected socket\n");
err = EISCONN;
goto errout;
}
/* Make sure that the IP address mapping is in the ARP table */
#ifdef CONFIG_NET_ARP_SEND
ret = arp_send(into->sin_addr.s_addr);
if (ret < 0)
{
ndbg("ERROR: Not reachable\n");
err = ENETUNREACH;
goto errout;
}
#endif
/* Perform the UDP sendto operation */
#ifdef CONFIG_NET_UDP

View File

@ -71,6 +71,7 @@
#include "socket/socket.h"
#include "netdev/netdev.h"
#include "arp/arp.h"
#include "tcp/tcp.h"
#include "devif/devif.h"
@ -539,10 +540,14 @@ static uint16_t psock_send_interrupt(FAR struct net_driver_s *dev,
*
* NOTE 2: If we are actually harvesting IP addresses on incoming IP
* packets, then this check should not be necessary; the MAC mapping
* should already be in the ARP table.
* should already be in the ARP table in many cases.
*
* NOTE 3: If CONFIG_NET_ARP_SEND then we can be assured that the IP
* address mapping is already in the ARP table.
*/
#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN)
#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN) && \
!defined(CONFIG_NET_ARP_SEND)
if (arp_find(conn->ripaddr) != NULL)
#endif
{
@ -721,6 +726,7 @@ static uint16_t psock_send_interrupt(FAR struct net_driver_s *dev,
ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
size_t len)
{
FAR struct tcp_conn_s *conn;
net_lock_t save;
ssize_t result = 0;
int err;
@ -728,16 +734,31 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
if (!psock || psock->s_crefs <= 0)
{
ndbg("ERROR: Invalid socket\n");
err = EBADF;
goto errout;
}
if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags))
{
ndbg("ERROR: Not connected\n");
err = ENOTCONN;
goto errout;
}
/* Make sure that the IP address mapping is in the ARP table */
conn = (FAR struct tcp_conn_s *)psock->s_conn;
#ifdef CONFIG_NET_ARP_SEND
ret = arp_send(conn->ripaddr);
if (ret < 0)
{
ndbg("ERROR: Not reachable\n");
err = ENETUNREACH;
goto errout;
}
#endif
/* Dump the incoming buffer */
BUF_DUMP("psock_tcp_send", buf, len);
@ -750,8 +771,6 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
if (len > 0)
{
FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)psock->s_conn;
/* Allocate resources to receive a callback */
if (!psock->s_sndcb)

View File

@ -59,6 +59,7 @@
#include "netdev/netdev.h"
#include "devif/devif.h"
#include "arp/arp.h"
#include "tcp/tcp.h"
#include "socket/socket.h"
@ -388,10 +389,14 @@ static uint16_t tcpsend_interrupt(FAR struct net_driver_s *dev,
*
* NOTE 2: If we are actually harvesting IP addresses on incoming IP
* packets, then this check should not be necessary; the MAC mapping
* should already be in the ARP table.
* should already be in the ARP table in many cases.
*
* NOTE 3: If CONFIG_NET_ARP_SEND then we can be assured that the IP
* address mapping is already in the ARP table.
*/
#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN)
#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN) && \
!defined(CONFIG_NET_ARP_SEND)
if (pstate->snd_sent != 0 || arp_find(conn->ripaddr) != NULL)
#endif
{
@ -505,6 +510,7 @@ end_wait:
ssize_t psock_tcp_send(FAR struct socket *psock,
FAR const void *buf, size_t len)
{
FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)psock->s_conn;
struct send_s state;
net_lock_t save;
int err;
@ -514,6 +520,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
if (!psock || psock->s_crefs <= 0)
{
ndbg("ERROR: Invalid socket\n");
err = EBADF;
goto errout;
}
@ -522,10 +529,24 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags))
{
ndbg("ERROR: Not connected\n");
err = ENOTCONN;
goto errout;
}
/* Make sure that the IP address mapping is in the ARP table */
conn = (FAR struct tcp_conn_s *)psock->s_conn;
#ifdef CONFIG_NET_ARP_SEND
ret = arp_send(conn->ripaddr);
if (ret < 0)
{
ndbg("ERROR: Not reachable\n");
err = ENETUNREACH;
goto errout;
}
#endif
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
@ -546,8 +567,6 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
if (len > 0)
{
FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)psock->s_conn;
/* Allocate resources to receive a callback */
state.snd_cb = tcp_callback_alloc(conn);