Improve icmp handling if MULTINIC enabled. From Max Neklyudov

This commit is contained in:
Gregory Nutt 2015-05-27 09:26:00 -06:00
parent adb617cdcd
commit 8ecb84ed89
9 changed files with 98 additions and 17 deletions

View File

@ -70,6 +70,8 @@
* Public Types
****************************************************************************/
struct devif_callback_s; /* Forward reference */
/* This structure collects information that is specific to a specific network
* interface driver. If the hardware platform supports only a single instance
* of this structure.
@ -190,6 +192,17 @@ struct net_driver_s
sq_queue_t grplist;
#endif
/* Application callbacks:
*
* Network device event handlers are retained in a 'list' and are called
* for events specified in the flags set within struct devif_callback_s.
* The following network event flags may be specified:
*
* NETDEV_DOWN - The network is down
*/
FAR struct devif_callback_s *d_callbacks;
/* Driver callbacks */
int (*d_ifup)(FAR struct net_driver_s *dev);

View File

@ -115,6 +115,7 @@
* OUT: Cleared (only) by the socket layer logic to indicate
* that the reply was processed, suppressing further
* attempts to process the reply.
* NETDEV_DOWN: IN: The network device has been taken down.
*/
#define TCP_ACKDATA (1 << 0)
@ -138,8 +139,10 @@
#define TCP_TIMEDOUT (1 << 9)
#define ICMP_ECHOREPLY (1 << 10)
#define ICMPv6_ECHOREPLY ICMP_ECHOREPLY
#define NETDEV_DOWN (1 << 11)
#define TCP_CONN_EVENTS (TCP_CLOSE | TCP_ABORT | TCP_CONNECTED | TCP_TIMEDOUT)
#define TCP_CONN_EVENTS (TCP_CLOSE | TCP_ABORT | TCP_CONNECTED | \
TCP_TIMEDOUT | NETDEV_DOWN)
/* IPv4/IPv6 Helpers */

View File

@ -69,17 +69,13 @@
#define ICMPBUF ((struct icmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
/****************************************************************************
* Public Variables
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
* Private Data
****************************************************************************/
#ifdef CONFIG_NET_ICMP_PING
FAR struct devif_callback_s *g_icmp_echocallback = NULL;
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
@ -182,9 +178,9 @@ void icmp_input(FAR struct net_driver_s *dev)
*/
#ifdef CONFIG_NET_ICMP_PING
else if (picmp->type == ICMP_ECHO_REPLY && g_icmp_echocallback)
else if (picmp->type == ICMP_ECHO_REPLY && dev->d_callbacks)
{
(void)devif_callback_execute(dev, picmp, ICMP_ECHOREPLY, g_icmp_echocallback);
(void)devif_callback_execute(dev, picmp, ICMP_ECHOREPLY, dev->d_callbacks);
}
#endif

View File

@ -70,8 +70,8 @@
/* Allocate a new ICMP data callback */
#define icmp_callback_alloc() devif_callback_alloc(&g_icmp_echocallback)
#define icmp_callback_free(cb) devif_callback_free(cb, &g_icmp_echocallback)
#define icmp_callback_alloc() devif_callback_alloc(&dev->d_callbacks)
#define icmp_callback_free(cb) devif_callback_free(cb, &dev->d_callbacks)
/****************************************************************************
* Private Types
@ -87,7 +87,7 @@ struct icmp_ping_s
int png_result; /* 0: success; <0:negated errno on fail */
in_addr_t png_addr; /* The peer to be ping'ed */
uint16_t png_id; /* Used to match requests with replies */
uint16_t png_seqno; /* IN: seqno to send; OUT: seqno recieved */
uint16_t png_seqno; /* IN: seqno to send; OUT: seqno received */
uint16_t png_datlen; /* The length of data to send in the ECHO request */
bool png_sent; /* true... the PING request has been sent */
};
@ -164,13 +164,25 @@ static uint16_t ping_interrupt(FAR struct net_driver_s *dev, FAR void *conn,
nllvdbg("flags: %04x\n", flags);
if (pstate)
{
/* Check if the network is still up
*
* REVISIT: Now does the ICMP logic know that this was the correct device?
*/
if ((flags & NETDEV_DOWN) != 0)
{
nlldbg("ERROR: Interface is down\n");
pstate->png_result = -ENETUNREACH;
goto end_wait;
}
/* Check if this is a ICMP ECHO reply. If so, return the sequence
* number to the caller. NOTE: We may not even have sent the
* requested ECHO request; this could have been the delayed ECHO
* response from a previous ping.
*/
if ((flags & ICMP_ECHOREPLY) != 0 && conn != NULL)
else if ((flags & ICMP_ECHOREPLY) != 0 && conn != NULL)
{
FAR struct icmp_iphdr_s *icmp = (FAR struct icmp_iphdr_s *)conn;
@ -332,7 +344,22 @@ int icmp_ping(in_addr_t addr, uint16_t id, uint16_t seqno, uint16_t datalen,
net_lock_t save;
#ifdef CONFIG_NET_ARP_SEND
int ret;
#endif
#ifdef CONFIG_NETDEV_MULTINIC
FAR struct net_driver_s *dev;
/* Get the device that will be used to route this ICMP ECHO request */
dev = netdev_findby_ipv4addr(g_ipv4_allzeroaddr, addr);
if (dev == 0)
{
ndbg("ERROR: Not reachable\n");
return -ENETUNREACH;
}
#endif
#ifdef CONFIG_NET_ARP_SEND
/* Make sure that the IP address mapping is in the ARP table */
ret = arp_send(addr);
@ -362,7 +389,7 @@ int icmp_ping(in_addr_t addr, uint16_t id, uint16_t seqno, uint16_t datalen,
state.png_cb = icmp_callback_alloc();
if (state.png_cb)
{
state.png_cb->flags = (ICMP_POLL | ICMP_ECHOREPLY);
state.png_cb->flags = (ICMP_POLL | ICMP_ECHOREPLY | NETDEV_DOWN);
state.png_cb->priv = (void*)&state;
state.png_cb->event = ping_interrupt;
state.png_result = -EINTR; /* Assume sem-wait interrupted by signal */
@ -370,7 +397,7 @@ int icmp_ping(in_addr_t addr, uint16_t id, uint16_t seqno, uint16_t datalen,
/* Notify the device driver of the availability of TX data */
#ifdef CONFIG_NETDEV_MULTINIC
netdev_ipv4_txnotify(g_ipv4_allzeroaddr, state.png_addr);
netdev_ipv4_txnotify_dev(dev);
#else
netdev_ipv4_txnotify(state.png_addr);
#endif

View File

@ -96,7 +96,7 @@ void icmp_poll(FAR struct net_driver_s *dev)
/* Perform the application callback */
(void)devif_callback_execute(dev, NULL, ICMP_POLL, g_icmp_echocallback);
(void)devif_callback_execute(dev, NULL, ICMP_POLL, dev->d_callbacks);
}
#endif /* CONFIG_NET && CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING */

View File

@ -130,6 +130,7 @@ FAR struct net_driver_s *netdev_default(void);
#ifdef CONFIG_NET_IPv4
# ifdef CONFIG_NETDEV_MULTINIC
void netdev_ipv4_txnotify(in_addr_t lipaddr, in_addr_t ripaddr);
void netdev_ipv4_txnotify_dev(FAR struct net_driver_s *dev);
# else
void netdev_ipv4_txnotify(in_addr_t ripaddr);
# endif

View File

@ -65,6 +65,7 @@
#include "socket/socket.h"
#include "netdev/netdev.h"
#include "devif/devif.h"
#include "igmp/igmp.h"
#include "icmpv6/icmpv6.h"
#include "route/route.h"
@ -1024,7 +1025,7 @@ void netdev_ifup(FAR struct net_driver_s *dev)
void netdev_ifdown(FAR struct net_driver_s *dev)
{
/* Make sure that the device supports the d_ifdown() method */
/* Check sure that the device supports the d_ifdown() method */
if (dev->d_ifdown)
{
@ -1041,6 +1042,11 @@ void netdev_ifdown(FAR struct net_driver_s *dev)
dev->d_flags &= ~IFF_UP;
}
}
/* Notify clients that the network has been taken down */
(void)devif_callback_execute(dev, NULL, NETDEV_DOWN,
dev->d_callbacks);
}
}

View File

@ -247,6 +247,10 @@ int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype)
devfmt = NETDEV_DEFAULT_FORMAT;
#endif
/* There are no clients of the device yet */
dev->d_callbacks = NULL;
/* Get the next available device number and sssign a device name to
* the interface
*/

View File

@ -166,4 +166,35 @@ void netdev_ipv6_txnotify(FAR const net_ipv6addr_t ripaddr)
}
#endif /* CONFIG_NET_IPv6 */
/****************************************************************************
* Function: netdev_ipv4_txnotify_dev
*
* Description:
* Notify the device driver that new TX data is available. This variant
* would be called when the upper level logic already understands how the
* packet will be routed.
*
* Parameters:
* dev - The network device driver state structure.
*
* Returned Value:
* None
*
* Assumptions:
* Called from normal user mode
*
****************************************************************************/
#ifdef CONFIG_NETDEV_MULTINIC
void netdev_ipv4_txnotify_dev(FAR struct net_driver_s *dev)
{
if (dev && dev->d_txavail)
{
/* Notify the device driver that new TX data is available. */
(void)dev->d_txavail(dev);
}
}
#endif /* CONFIG_NET_IPv6 */
#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */