net/arp: Redesign ARP table aging to simplify the net initialization

This commit is contained in:
Xiang Xiao 2018-11-09 13:54:55 -06:00 committed by Gregory Nutt
parent 9d09b5aad7
commit 43706cd797
8 changed files with 62 additions and 351 deletions

View File

@ -83,7 +83,7 @@ struct arp_entry_s
{ {
in_addr_t at_ipaddr; /* IP address */ in_addr_t at_ipaddr; /* IP address */
struct ether_addr at_ethaddr; /* Hardware address */ struct ether_addr at_ethaddr; /* Hardware address */
uint8_t at_time; /* Time of last usage */ clock_t at_time; /* Time of last usage */
}; };
/* Used with the SIOCSARP, SIOCDARP, and SIOCGARP IOCTL commands to set, /* Used with the SIOCSARP, SIOCDARP, and SIOCGARP IOCTL commands to set,

View File

@ -256,7 +256,7 @@ extern "C"
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: net_setup * Name: net_initialize
* *
* Description: * Description:
* This is called from the OS initialization logic at power-up reset in * This is called from the OS initialization logic at power-up reset in
@ -278,25 +278,6 @@ extern "C"
* *
****************************************************************************/ ****************************************************************************/
void net_setup(void);
/****************************************************************************
* Name: net_initialize
*
* Description:
* This function is called from the OS initialization logic at power-up
* reset AFTER initialization of hardware facilities such as timers and
* interrupts. This logic completes the initialization started by
* net_setup().
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void net_initialize(void); void net_initialize(void);
/**************************************************************************** /****************************************************************************

View File

@ -36,7 +36,7 @@
# ARP support is available for Ethernet only # ARP support is available for Ethernet only
ifeq ($(CONFIG_NET_ARP),y) ifeq ($(CONFIG_NET_ARP),y)
NET_CSRCS += arp_arpin.c arp_out.c arp_format.c arp_table.c arp_timer.c NET_CSRCS += arp_arpin.c arp_out.c arp_format.c arp_table.c
ifeq ($(CONFIG_NET_ARP_IPIN),y) ifeq ($(CONFIG_NET_ARP_IPIN),y)
NET_CSRCS += arp_ipin.c NET_CSRCS += arp_ipin.c

View File

@ -176,49 +176,6 @@ struct arp_notify_s
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_NET_ARP #ifdef CONFIG_NET_ARP
/****************************************************************************
* Name: arp_reset
*
* Description:
* Re-initialize the ARP table.
*
****************************************************************************/
void arp_reset(void);
/****************************************************************************
* Name: arp_timer_initialize
*
* Description:
* Initialized the 10 second timer that is need by the ARP logic in order
* to age ARP address associations
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions:
* Called once at system initialization time
*
****************************************************************************/
void arp_timer_initialize(void);
/****************************************************************************
* Name: arp_timer
*
* Description:
* This function performs periodic timer processing in the ARP module
* and should be called at regular intervals. The recommended interval
* is 10 seconds between the calls. It is responsible for flushing old
* entries in the ARP table.
*
****************************************************************************/
void arp_timer(void);
/**************************************************************************** /****************************************************************************
* Name: arp_format * Name: arp_format
* *
@ -492,9 +449,6 @@ void arp_dump(FAR struct arp_hdr_s *arp);
/* If ARP is disabled, stub out all ARP interfaces */ /* If ARP is disabled, stub out all ARP interfaces */
# define arp_reset()
# define arp_timer_initialize()
# define arp_timer()
# define arp_format(d,i); # define arp_format(d,i);
# define arp_send(i) (0) # define arp_send(i) (0)
# define arp_poll(d,c) (0) # define arp_poll(d,c) (0)

View File

@ -54,6 +54,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <net/ethernet.h> #include <net/ethernet.h>
#include <nuttx/clock.h>
#include <nuttx/net/netconfig.h> #include <nuttx/net/netconfig.h>
#include <nuttx/net/net.h> #include <nuttx/net/net.h>
#include <nuttx/net/netdev.h> #include <nuttx/net/netdev.h>
@ -65,6 +66,12 @@
#ifdef CONFIG_NET_ARP #ifdef CONFIG_NET_ARP
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ARP_MAXAGE_TICK SEC2TICK(10 * CONFIG_NET_ARP_MAXAGE)
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
@ -82,7 +89,6 @@ struct arp_table_info_s
/* The table of known address mappings */ /* The table of known address mappings */
static struct arp_entry_s g_arptable[CONFIG_NET_ARPTAB_SIZE]; static struct arp_entry_s g_arptable[CONFIG_NET_ARPTAB_SIZE];
static uint8_t g_arptime;
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
@ -134,57 +140,40 @@ static int arp_match(FAR struct net_driver_s *dev, FAR void *arg)
return 1; return 1;
} }
/****************************************************************************
* Name: arp_return_old_entry
*
* Description:
* Compare and return the old ARP table entry.
*
****************************************************************************/
static FAR struct arp_entry_s *
arp_return_old_entry(FAR struct arp_entry_s *e1, FAR struct arp_entry_s *e2)
{
if (e1->at_ipaddr == 0)
{
return e1;
}
else if (e2->at_ipaddr == 0)
{
return e2;
}
else if ((int)(e1->at_time - e2->at_time) <= 0)
{
return e1;
}
else
{
return e2;
}
}
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Name: arp_reset
*
* Description:
* Re-initialize the ARP table.
*
****************************************************************************/
void arp_reset(void)
{
int i;
for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{
memset(&g_arptable[i].at_ipaddr, 0, sizeof(in_addr_t));
}
}
/****************************************************************************
* Name: arp_timer
*
* Description:
* This function performs periodic timer processing in the ARP module
* and should be called at regular intervals. The recommended interval
* is 10 seconds between the calls. It is responsible for flushing old
* entries in the ARP table.
*
****************************************************************************/
void arp_timer(void)
{
FAR struct arp_entry_s *tabptr;
int i;
++g_arptime;
for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{
tabptr = &g_arptable[i];
if (tabptr->at_ipaddr != 0 &&
g_arptime - tabptr->at_time >= CONFIG_NET_ARP_MAXAGE)
{
tabptr->at_ipaddr = 0;
}
}
}
/**************************************************************************** /****************************************************************************
* Name: arp_update * Name: arp_update
* *
@ -207,8 +196,8 @@ void arp_timer(void)
int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr) int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr)
{ {
struct arp_entry_s *tabptr = NULL; FAR struct arp_entry_s *tabptr = &g_arptable[0];
int i; int i;
/* Walk through the ARP mapping table and try to find an entry to /* Walk through the ARP mapping table and try to find an entry to
* update. If none is found, the IP -> MAC address mapping is * update. If none is found, the IP -> MAC address mapping is
@ -217,69 +206,33 @@ int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr)
for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{ {
tabptr = &g_arptable[i]; /* Check if the source IP address of the incoming packet matches
* the IP address in this ARP table entry.
*/
/* Only check those entries that are actually in use. */ if (g_arptable[i].at_ipaddr != 0 &&
net_ipv4addr_cmp(ipaddr, g_arptable[i].at_ipaddr))
if (tabptr->at_ipaddr != 0)
{ {
/* Check if the source IP address of the incoming packet matches /* An old entry found, break. */
* the IP address in this ARP table entry.
*/
if (net_ipv4addr_cmp(ipaddr, tabptr->at_ipaddr)) tabptr = &g_arptable[i];
{
/* An old entry found, update this and return. */
memcpy(tabptr->at_ethaddr.ether_addr_octet, ethaddr, ETHER_ADDR_LEN);
tabptr->at_time = g_arptime;
return OK;
}
}
}
/* If we get here, no existing ARP table entry was found, so we create one. */
/* First, we try to find an unused entry in the ARP table. */
for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{
tabptr = &g_arptable[i];
if (tabptr->at_ipaddr == 0)
{
break; break;
} }
} else
/* If no unused entry is found, we try to find the oldest entry and
* throw it away.
*/
if (i == CONFIG_NET_ARPTAB_SIZE)
{
uint8_t tmpage = 0;
int j = 0;
for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{ {
tabptr = &g_arptable[i]; /* Record the oldest entry. */
if (g_arptime - tabptr->at_time > tmpage)
{
tmpage = g_arptime - tabptr->at_time;
j = i;
}
}
i = j; tabptr = arp_return_old_entry(tabptr, &g_arptable[i]);
tabptr = &g_arptable[i]; }
} }
/* Now, i is the ARP table entry which we will fill with the new /* Now, tabptr is the ARP table entry which we will fill with the new
* information. * information.
*/ */
tabptr->at_ipaddr = ipaddr; tabptr->at_ipaddr = ipaddr;
memcpy(tabptr->at_ethaddr.ether_addr_octet, ethaddr, ETHER_ADDR_LEN); memcpy(tabptr->at_ethaddr.ether_addr_octet, ethaddr, ETHER_ADDR_LEN);
tabptr->at_time = g_arptime; tabptr->at_time = clock_systimer();
return OK; return OK;
} }
@ -337,7 +290,8 @@ FAR struct arp_entry_s *arp_lookup(in_addr_t ipaddr)
for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i)
{ {
tabptr = &g_arptable[i]; tabptr = &g_arptable[i];
if (net_ipv4addr_cmp(ipaddr, tabptr->at_ipaddr)) if (net_ipv4addr_cmp(ipaddr, tabptr->at_ipaddr) &&
clock_systimer() - tabptr->at_time <= ARP_MAXAGE_TICK)
{ {
return tabptr; return tabptr;
} }
@ -442,3 +396,4 @@ void arp_delete(in_addr_t ipaddr)
#endif /* CONFIG_NET_ARP */ #endif /* CONFIG_NET_ARP */
#endif /* CONFIG_NET */ #endif /* CONFIG_NET */

View File

@ -1,133 +0,0 @@
/****************************************************************************
* net/arp/arp_timer.c
*
* Copyright (C) 2007-2009, 2011, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#ifdef CONFIG_NET
#include <stdint.h>
#include <time.h>
#include <debug.h>
#include <nuttx/wdog.h>
#include <nuttx/net/netconfig.h>
#include <arp/arp.h>
#ifdef CONFIG_NET_ARP
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* ARP timer interval = 10 seconds. CLK_TCK is the number of clock ticks
* per second
*/
#define ARPTIMER_WDINTERVAL (10*CLK_TCK)
/****************************************************************************
* Private Data
****************************************************************************/
static WDOG_ID g_arptimer; /* ARP timer */
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: arptimer_poll
*
* Description:
* Periodic timer handler. Called from the timer interrupt handler.
*
* Input Parameters:
* argc - The number of available arguments
* arg - The first argument
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static void arptimer_poll(int argc, wdparm_t arg, ...)
{
/* Call the ARP timer function every 10 seconds. */
arp_timer();
/* Setup the watchdog timer again */
(void)wd_start(g_arptimer, ARPTIMER_WDINTERVAL, arptimer_poll, 0);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: arp_timer_initialize
*
* Description:
* Initialized the 10 second timer that is need by the ARP logic in order
* to age ARP address associations
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions:
* Called once at system initialization time
*
****************************************************************************/
void arp_timer_initialize(void)
{
/* Create and start the ARP timer */
g_arptimer = wd_create();
(void)wd_start(g_arptimer, ARPTIMER_WDINTERVAL, arptimer_poll, 0);
}
#endif /* CONFIG_NET_ARP */
#endif /* CONFIG_NET */

View File

@ -49,7 +49,6 @@
#include "devif/devif.h" #include "devif/devif.h"
#include "netdev/netdev.h" #include "netdev/netdev.h"
#include "ipforward/ipforward.h" #include "ipforward/ipforward.h"
#include "arp/arp.h"
#include "sixlowpan/sixlowpan.h" #include "sixlowpan/sixlowpan.h"
#include "neighbor/neighbor.h" #include "neighbor/neighbor.h"
#include "icmp/icmp.h" #include "icmp/icmp.h"
@ -72,7 +71,7 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: net_setup * Name: net_initialize
* *
* Description: * Description:
* This is called from the OS initialization logic at power-up reset in * This is called from the OS initialization logic at power-up reset in
@ -94,16 +93,12 @@
* *
****************************************************************************/ ****************************************************************************/
void net_setup(void) void net_initialize(void)
{ {
/* Initialize the locking facility */ /* Initialize the locking facility */
net_lockinitialize(); net_lockinitialize();
/* Clear the ARP table */
arp_reset();
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
/* Initialize the Neighbor Table data structures */ /* Initialize the Neighbor Table data structures */
@ -219,28 +214,4 @@ void net_setup(void)
#endif #endif
} }
/****************************************************************************
* Name: net_initialize
*
* Description:
* This function is called from the OS initialization logic at power-up
* reset AFTER initialization of hardware facilities such as timers and
* interrupts. This logic completes the initialization started by
* net_setup().
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void net_initialize(void)
{
/* Initialize the periodic ARP timer */
arp_timer_initialize();
}
#endif /* CONFIG_NET */ #endif /* CONFIG_NET */

View File

@ -68,9 +68,6 @@
#ifndef CONFIG_DISABLE_PTHREAD #ifndef CONFIG_DISABLE_PTHREAD
# include "pthread/pthread.h" # include "pthread/pthread.h"
#endif #endif
#ifdef CONFIG_SCHED_WORKQUEUE
# include "wqueue/wqueue.h"
#endif
#include "clock/clock.h" #include "clock/clock.h"
#include "timer/timer.h" #include "timer/timer.h"
#include "irq/irq.h" #include "irq/irq.h"
@ -694,15 +691,9 @@ void os_start(void)
#endif #endif
#ifdef CONFIG_NET #ifdef CONFIG_NET
/* Initialize the networking system. Network initialization is /* Initialize the networking system */
* performed in two steps: (1) net_setup() initializes static
* configuration of the network support. This must be done prior
* to registering network drivers by up_initialize(). This step
* cannot require upon any hardware-depending features such as
* timers or interrupts.
*/
net_setup(); net_initialize();
#endif #endif
/* The processor specific details of running the operating system /* The processor specific details of running the operating system
@ -717,14 +708,6 @@ void os_start(void)
g_os_initstate = OSINIT_HARDWARE; g_os_initstate = OSINIT_HARDWARE;
#ifdef CONFIG_NET
/* Complete initialization the networking system now that interrupts
* and timers have been configured by up_initialize().
*/
net_initialize();
#endif
#ifdef CONFIG_MM_SHM #ifdef CONFIG_MM_SHM
/* Initialize shared memory support */ /* Initialize shared memory support */