From 548fda783489bb3a580d922d7edc525273795e21 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 18 Aug 2014 15:24:51 -0600 Subject: [PATCH] arp_poll(): inished the implementation of logic to send ARP requests. Complete, fully hooked into the networking logic, and ready for test (but still untested) --- net/arp/Make.defs | 2 +- net/arp/arp.h | 98 +++++++++++++++++++++++++ net/arp/arp_poll.c | 99 +++++++++++++++++++++++++ net/arp/arp_send.c | 40 +--------- net/devif/devif_poll.c | 161 +++++++++++++++++++++++++---------------- 5 files changed, 301 insertions(+), 99 deletions(-) create mode 100644 net/arp/arp_poll.c diff --git a/net/arp/Make.defs b/net/arp/Make.defs index dc06872133..7814906b4c 100644 --- a/net/arp/Make.defs +++ b/net/arp/Make.defs @@ -43,7 +43,7 @@ NET_CSRCS += arp_ipin.c endif ifeq ($(CONFIG_NET_ARP_SEND),y) -NET_CSRCS += arp_send.c +NET_CSRCS += arp_send.c arp_poll.c endif ifeq ($(CONFIG_NET_ARP_DUMP),y) diff --git a/net/arp/arp.h b/net/arp/arp.h index 857c5bf7fe..75119fc51a 100644 --- a/net/arp/arp.h +++ b/net/arp/arp.h @@ -53,8 +53,12 @@ #include #include +#include + #include +#include + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -81,6 +85,11 @@ #define RASIZE 4 /* Size of ROUTER ALERT */ +/* Allocate a new ARP data callback */ + +#define arp_callback_alloc(conn) devif_callback_alloc(&(conn)->list) +#define arp_callback_free(conn,cb) devif_callback_free(cb, &(conn)->list) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -117,6 +126,45 @@ struct arp_iphdr_s uint16_t eh_ipoption[2]; /* (optional) */ }; +#ifdef CONFIG_NET_ARP_SEND +/* This structure holds the state of the send operation until it can be + * operated upon from the interrupt level. + */ + +struct arp_send_s +{ + FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */ + sem_t snd_sem; /* Used to wake up the waiting thread */ + uint8_t snd_retries; /* Retry count */ + volatile bool snd_sent; /* True: if request sent */ +#ifdef CONFIG_NETDEV_MULTINIC + uint8_t snd_ifname[IFNAMSIZ]; /* Interface name */ +#endif + in_addr_t snd_ipaddr; /* The IP address to be queried */ +}; +#endif + +#ifdef CONFIG_NET_ARP_SEND +/* For symmetry with other protocols, a "connection" structure is + * provided. But it is a singleton for the case of ARP packet transfers. + */ + +struct arp_conn_s +{ + FAR struct devif_callback_s *list; /* ARP callbacks */ +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef CONFIG_NET_ARP_SEND +/* This is the singleton "connection" structure */ + +extern struct arp_conn_s g_arp_conn; +#endif + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -183,6 +231,56 @@ void arp_timer(void); struct net_driver_s; /* Forward reference */ void arp_format(FAR struct net_driver_s *dev, in_addr_t ipaddr); +/**************************************************************************** + * Function: arp_send + * + * Description: + * The arp_send() call may be to send an ARP request to resolve an IP + * address. This function first checks if the IP address is already in + * ARP table. If so, then it returns success immediately. + * + * If the requested IP address in not in the ARP table, then this function + * will send an ARP request, delay, then check if the IP address is now in + * the ARP table. It will repeat this sequence until either (1) the IP + * address mapping is now in the ARP table, or (2) a configurable number + * of timeouts occur without receiving the ARP replay. + * + * Parameters: + * ipaddr The IP address to be queried. + * + * Returned Value: + * Zero (OK) is returned on success and the IP address mapping can now be + * found in the ARP table. On error a negated errno value is returned: + * + * -ETIMEDOUT: The number or retry counts has been exceed. + * -EHOSTUNREACH: Could not find a route to the host + * + * Assumptions: + * This function is called from the normal tasking context. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ARP_SEND +int arp_send(in_addr_t ipaddr); +#endif + +/**************************************************************************** + * Function: arp_poll + * + * Description: + * Poll all pending transfer for ARP requests to send. + * + * Assumptions: + * This function is called from the MAC device driver indirectly through + * devif_poll() and devif_timer() and may be called from the timer + * interrupt/watchdog handler level. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ARP_SEND +int arp_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback); +#endif + /**************************************************************************** * Name: arp_dump * diff --git a/net/arp/arp_poll.c b/net/arp/arp_poll.c new file mode 100644 index 0000000000..111547b319 --- /dev/null +++ b/net/arp/arp_poll.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * net/arp/arp_poll.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "devif/devif.h" +#include "arp/arp.h" + +#ifdef CONFIG_NET_ARP_SEND + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* This is the singleton "connection" structure */ + +struct arp_conn_s g_arp_conn; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: arp_poll + * + * Description: + * Poll all pending transfer for ARP requests to send. + * + * Assumptions: + * This function is called from the MAC device driver indirectly through + * devif_poll() and devif_timer() and may be called from the timer + * interrupt/watchdog handler level. + * + ****************************************************************************/ + +int arp_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback) +{ + /* Setup for the ARP callback (most of these do not apply) */ + + dev->d_appdata = NULL; + dev->d_snddata = NULL; + + dev->d_len = 0; + dev->d_sndlen = 0; + + /* Perform the ARP callbacks */ + + (void)devif_callback_execute(dev, &g_arp_conn, PKT_POLL, g_arp_conn.list); + + /* Call back into the driver */ + + return callback(dev); +} + +#endif /* CONFIG_NET_ARP_SEND */ diff --git a/net/arp/arp_send.c b/net/arp/arp_send.c index 750e5097f0..38d1228b40 100644 --- a/net/arp/arp_send.c +++ b/net/arp/arp_send.c @@ -61,48 +61,14 @@ * Pre-processor Definitions ****************************************************************************/ -/* Allocate a new packet socket data callback */ - -#define arp_callback_alloc(conn) devif_callback_alloc(&(conn)->list) -#define arp_callback_free(conn,cb) devif_callback_free(cb, &(conn)->list) - /**************************************************************************** * Private Types ****************************************************************************/ -/* This structure holds the state of the send operation until it can be - * operated upon from the interrupt level. - */ - -struct arp_send_s -{ - FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */ - sem_t snd_sem; /* Used to wake up the waiting thread */ - uint8_t snd_retries; /* Retry count */ - volatile bool snd_sent; /* True: if request sent */ -#ifdef CONFIG_NETDEV_MULTINIC - uint8_t snd_ifname[IFNAMSIZ]; /* Interface name */ -#endif - in_addr_t snd_ipaddr; /* The IP address to be queried */ -}; - -/* For compatibility with other protocols, a "connection" structure is - * provided. But it is a singleton for the case of ARP pack transfers. - */ - -struct arp_conn_s -{ - FAR struct devif_callback_s *list; /* ARP callbacks */ -}; - /**************************************************************************** * Private Data ****************************************************************************/ -/* This is the singleton "connection" structure */ - -static struct arp_conn_s g_arp_conn; - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -161,7 +127,7 @@ static uint16_t arp_send_interrupt(FAR struct net_driver_s *dev, */ dev->d_flags |= IFF_NOARP; - + /* Don't allow any further call backs. */ state->snd_sent = true; @@ -242,7 +208,7 @@ int arp_send(in_addr_t ipaddr) } /* Initialize the state structure. This is done with interrupts - * disabled + * disabled */ (void)sem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */ @@ -259,7 +225,7 @@ int arp_send(in_addr_t ipaddr) */ ret = -ETIMEDOUT; /* Assume a timeout failure */ - + while (state.snd_retries < CONFIG_ARP_SEND_MAXTRIES) { /* Check if the address mapping is present in the ARP table */ diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c index 1764f0f6ab..26fc80f652 100644 --- a/net/devif/devif_poll.c +++ b/net/devif/devif_poll.c @@ -46,6 +46,7 @@ #include #include "devif/devif.h" +#include "arp/arp.h" #include "tcp/tcp.h" #include "udp/udp.h" #include "pkt/pkt.h" @@ -72,7 +73,7 @@ * ****************************************************************************/ -#if defined(CONFIG_NET_PKT) +#ifdef CONFIG_NET_PKT static int devif_poll_pkt_connections(FAR struct net_driver_s *dev, devif_poll_callback_t callback) { @@ -298,44 +299,63 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback) * action. */ +#ifdef CONFIG_NET_ARP_SEND + /* Check for pending ARP requests */ + + bstop = arp_poll(dev, callback); + if (!bstop) +#endif #ifdef CONFIG_NET_PKT - bstop = devif_poll_pkt_connections(dev, callback); + { + /* Check for pending packet socket transfer */ + + bstop = devif_poll_pkt_connections(dev, callback); + } + + if (!bstop) +#endif +#ifdef CONFIG_NET_IGMP + { + /* Check for pending IGMP messages */ + + bstop = devif_poll_igmp(dev, callback); + } + + if (!bstop) +#endif +#ifdef CONFIG_NET_TCP + { + /* Traverse all of the active TCP connections and perform the poll + * action. + */ + + bstop = devif_poll_tcp_connections(dev, callback); + } + + if (!bstop) +#endif +#ifdef CONFIG_NET_UDP + { + /* Traverse all of the allocated UDP connections and perform + * the poll action + */ + + bstop = devif_poll_udp_connections(dev, callback); + } + + if (!bstop) +#endif +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) + { + /* Traverse all of the tasks waiting to send an ICMP ECHO request. */ + + bstop = devif_poll_icmp(dev, callback); + } + if (!bstop) #endif { - /* Check for pendig IGMP messages */ - -#ifdef CONFIG_NET_IGMP - bstop = devif_poll_igmp(dev, callback); - if (!bstop) -#endif - { - /* Traverse all of the active TCP connections and perform the poll - * action. - */ - - bstop = devif_poll_tcp_connections(dev, callback); - if (!bstop) - { -#ifdef CONFIG_NET_UDP - /* Traverse all of the allocated UDP connections and perform - * the poll action - */ - - bstop = devif_poll_udp_connections(dev, callback); - if (!bstop) -#endif - { -#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) - /* Traverse all of the tasks waiting to send an ICMP ECHO - * request. - */ - - bstop = devif_poll_icmp(dev, callback); -#endif - } - } - } + /* Nothing more to do */ } return bstop; @@ -384,44 +404,63 @@ int devif_timer(FAR struct net_driver_s *dev, devif_poll_callback_t callback, * action. */ -#ifdef CONFIG_NET_PKT - bstop = devif_poll_pkt_connections(dev, callback); +#ifdef CONFIG_NET_ARP_SEND + /* Check for pending ARP requests */ + + bstop = arp_poll(dev, callback); if (!bstop) #endif +#ifdef CONFIG_NET_PKT + { + /* Check for pending packet socket transfer */ + + bstop = devif_poll_pkt_connections(dev, callback); + } + + if (!bstop) +#endif +#ifdef CONFIG_NET_IGMP { /* Check for pending IGMP messages */ -#ifdef CONFIG_NET_IGMP bstop = devif_poll_igmp(dev, callback); - if (!bstop) + } + + if (!bstop) #endif - { - /* Traverse all of the active TCP connections and perform the - * timer action. - */ +#ifdef CONFIG_NET_TCP + { + /* Traverse all of the active TCP connections and perform the + * timer action. + */ - bstop = devif_poll_tcp_timer(dev, callback, hsec); - if (!bstop) - { - /* Traverse all of the allocated UDP connections and perform - * the poll action. - */ + bstop = devif_poll_tcp_timer(dev, callback, hsec); + } + if (!bstop) +#endif #ifdef CONFIG_NET_UDP - bstop = devif_poll_udp_connections(dev, callback); - if (!bstop) -#endif - { -#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) - /* Traverse all of the tasks waiting to send an ICMP ECHO - * request. - */ + { + /* Traverse all of the allocated UDP connections and perform + * the timer action. + */ - bstop = devif_poll_icmp(dev, callback); + bstop = devif_poll_udp_connections(dev, callback); + } + + if (!bstop) #endif - } - } - } +#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) + { + /* Traverse all of the tasks waiting to send an ICMP ECHO request. */ + + bstop = devif_poll_icmp(dev, callback); + } + + if (!bstop) +#endif + { + /* Nothing to do */ } return bstop;