mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 13:18:50 +08:00
net/arp: Improve arp_find() commit 9774d35010
to reduce the amount and frequency of data copies.
This commit is contained in:
parent
aa409f46ab
commit
3bf96c8e7e
11 changed files with 94 additions and 55 deletions
|
@ -2,7 +2,8 @@
|
|||
* include/nuttx/net/arp.h
|
||||
* Macros and definitions for the ARP module.
|
||||
*
|
||||
* Copyright (C) 2007, 2009-2012, 2015-2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009-2012, 2015-2016, 2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Derived from uIP with has a similar BSD-style license:
|
||||
|
@ -78,7 +79,7 @@
|
|||
|
||||
/* One entry in the ARP table (volatile!) */
|
||||
|
||||
struct arp_entry
|
||||
struct arp_entry_s
|
||||
{
|
||||
in_addr_t at_ipaddr; /* IP address */
|
||||
struct ether_addr at_ethaddr; /* Hardware address */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* net/arp/arp.h
|
||||
*
|
||||
* Copyright (C) 2014-2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2014-2016, 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -384,7 +384,7 @@ void arp_notify(in_addr_t ipaddr);
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct arp_entry *arp_lookup(in_addr_t ipaddr);
|
||||
FAR struct arp_entry_s *arp_lookup(in_addr_t ipaddr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arp_find
|
||||
|
@ -394,15 +394,19 @@ FAR struct arp_entry *arp_lookup(in_addr_t ipaddr);
|
|||
* not be in the ARP table (it may, instead, be a local network device).
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipaddr - Refers to an IP address in network order
|
||||
* entry - location to return a copy of the ARP table entry.
|
||||
* ipaddr - Refers to an IP address in network order
|
||||
* ethaddr - Location to return the corresponding Ethernet MAN address.
|
||||
* This address may be NULL. In that case, this function may be
|
||||
* used simply to determine if the Ethernet MAC address is
|
||||
* available.
|
||||
*
|
||||
* Assumptions
|
||||
* The network is locked to assure exclusive access to the ARP table.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arp_find(in_addr_t ipaddr, FAR struct arp_entry *entry);
|
||||
struct ether_addr; /* Forward reference */
|
||||
int arp_find(in_addr_t ipaddr, FAR struct ether_addr *ethaddr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arp_delete
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/****************************************************************************
|
||||
* net/arp/arp_out.c
|
||||
*
|
||||
* Copyright (C) 2007-2011, 2014-2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2011, 2014-2015, 2017-2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Based on uIP which also has a BSD style license:
|
||||
|
@ -136,7 +137,7 @@ static const uint8_t g_multicast_ethaddr[3] =
|
|||
|
||||
void arp_out(FAR struct net_driver_s *dev)
|
||||
{
|
||||
struct arp_entry entry;
|
||||
struct ether_addr ethaddr;
|
||||
FAR struct eth_hdr_s *peth = ETHBUF;
|
||||
FAR struct arp_iphdr_s *pip = IPBUF;
|
||||
in_addr_t ipaddr;
|
||||
|
@ -250,7 +251,7 @@ void arp_out(FAR struct net_driver_s *dev)
|
|||
|
||||
/* Check if we already have this destination address in the ARP table */
|
||||
|
||||
ret = arp_find(ipaddr, &entry);
|
||||
ret = arp_find(ipaddr, ðaddr);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ninfo("ARP request for IP %08lx\n", (unsigned long)ipaddr);
|
||||
|
@ -266,7 +267,7 @@ void arp_out(FAR struct net_driver_s *dev)
|
|||
|
||||
/* Build an Ethernet header. */
|
||||
|
||||
memcpy(peth->dest, entry.at_ethaddr.ether_addr_octet, ETHER_ADDR_LEN);
|
||||
memcpy(peth->dest, ethaddr.ether_addr_octet, ETHER_ADDR_LEN);
|
||||
|
||||
/* Finish populating the Ethernet header */
|
||||
|
||||
|
|
|
@ -315,8 +315,6 @@ int arp_send(in_addr_t ipaddr)
|
|||
|
||||
while (state.snd_retries < CONFIG_ARP_SEND_MAXTRIES)
|
||||
{
|
||||
struct arp_entry entry;
|
||||
|
||||
/* Check if the address mapping is present in the ARP table. This
|
||||
* is only really meaningful on the first time through the loop.
|
||||
*
|
||||
|
@ -324,7 +322,7 @@ int arp_send(in_addr_t ipaddr)
|
|||
* issue.
|
||||
*/
|
||||
|
||||
if (arp_find(ipaddr, &entry) >= 0)
|
||||
if (arp_find(ipaddr, NULL) >= 0)
|
||||
{
|
||||
/* We have it! Break out with success */
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
@ -66,13 +65,23 @@
|
|||
|
||||
#ifdef CONFIG_NET_ARP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct arp_table_info_s
|
||||
{
|
||||
in_addr_t ai_ipaddr; /* IP address for lookup */
|
||||
FAR struct ether_addr *ai_ethaddr; /* Location to return the MAC address */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* The table of known address mappings */
|
||||
|
||||
static struct arp_entry g_arptable[CONFIG_NET_ARPTAB_SIZE];
|
||||
static struct arp_entry_s g_arptable[CONFIG_NET_ARPTAB_SIZE];
|
||||
static uint8_t g_arptime;
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -90,19 +99,38 @@ static uint8_t g_arptime;
|
|||
|
||||
static int arp_match(FAR struct net_driver_s *dev, FAR void *arg)
|
||||
{
|
||||
FAR struct arp_entry *entry = arg;
|
||||
FAR struct arp_table_info_s *info = arg;
|
||||
|
||||
if (dev->d_lltype != NET_LL_ETHERNET)
|
||||
/* Make sure that this is an Ethernet device (or an IEEE 802.11 device
|
||||
* which is also Ethernet)
|
||||
*/
|
||||
|
||||
if (dev->d_lltype != NET_LL_ETHERNET &&
|
||||
dev->d_lltype != NET_LL_IEEE80211)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!net_ipv4addr_cmp(dev->d_ipaddr, entry->at_ipaddr))
|
||||
/* Check if the network device has been assigned the IP address of the
|
||||
* lookup.
|
||||
*/
|
||||
|
||||
if (!net_ipv4addr_cmp(dev->d_ipaddr, info->ai_ipaddr))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&entry->at_ethaddr, &dev->d_mac.ether, ETHER_ADDR_LEN);
|
||||
/* Yes.. Return the matching Ethernet MAC address if the caller of
|
||||
* arp_find() provided a non-NULL location.
|
||||
*/
|
||||
|
||||
if (info->ai_ethaddr != NULL)
|
||||
{
|
||||
memcpy(info->ai_ethaddr, &dev->d_mac.ether, ETHER_ADDR_LEN);
|
||||
}
|
||||
|
||||
/* Return success in any event */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -141,7 +169,7 @@ void arp_reset(void)
|
|||
|
||||
void arp_timer(void)
|
||||
{
|
||||
FAR struct arp_entry *tabptr;
|
||||
FAR struct arp_entry_s *tabptr;
|
||||
int i;
|
||||
|
||||
++g_arptime;
|
||||
|
@ -179,7 +207,7 @@ void arp_timer(void)
|
|||
|
||||
int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr)
|
||||
{
|
||||
struct arp_entry *tabptr = NULL;
|
||||
struct arp_entry_s *tabptr = NULL;
|
||||
int i;
|
||||
|
||||
/* Walk through the ARP mapping table and try to find an entry to
|
||||
|
@ -299,9 +327,9 @@ void arp_hdr_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct arp_entry *arp_lookup(in_addr_t ipaddr)
|
||||
FAR struct arp_entry_s *arp_lookup(in_addr_t ipaddr)
|
||||
{
|
||||
FAR struct arp_entry *tabptr;
|
||||
FAR struct arp_entry_s *tabptr;
|
||||
int i;
|
||||
|
||||
/* Check if the IPv4 address is already in the ARP table. */
|
||||
|
@ -328,25 +356,40 @@ FAR struct arp_entry *arp_lookup(in_addr_t ipaddr)
|
|||
* not be in the ARP table (it may, instead, be a local network device).
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipaddr - Refers to an IP address in network order
|
||||
* ipaddr - Refers to an IP address in network order
|
||||
* ethaddr - Location to return the corresponding Ethernet MAN address.
|
||||
* This address may be NULL. In that case, this function may be
|
||||
* used simply to determine if the Ethernet MAC address is
|
||||
* available.
|
||||
*
|
||||
* Assumptions:
|
||||
* Assumptions
|
||||
* The network is locked to assure exclusive access to the ARP table.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arp_find(in_addr_t ipaddr, FAR struct arp_entry *entry)
|
||||
int arp_find(in_addr_t ipaddr, FAR struct ether_addr *ethaddr)
|
||||
{
|
||||
FAR struct arp_entry *tabptr;
|
||||
|
||||
DEBUGASSERT(entry);
|
||||
FAR struct arp_entry_s *tabptr;
|
||||
struct arp_table_info_s info;
|
||||
|
||||
/* Check if the IPv4 address is already in the ARP table. */
|
||||
|
||||
tabptr = arp_lookup(ipaddr);
|
||||
if (tabptr != NULL)
|
||||
{
|
||||
memcpy(entry, tabptr, sizeof(struct arp_entry));
|
||||
/* Yes.. return the Ethernet MAC address if the caller has provided a
|
||||
* non-NULL address in 'ethaddr'.
|
||||
*/
|
||||
|
||||
if (ethaddr != NULL)
|
||||
{
|
||||
memcpy(ethaddr, &tabptr->at_ethaddr, ETHER_ADDR_LEN);
|
||||
}
|
||||
|
||||
/* Return success in any case meaning that a valid Ethernet MAC
|
||||
* address mapping is available for the IP address.
|
||||
*/
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -355,8 +398,10 @@ int arp_find(in_addr_t ipaddr, FAR struct arp_entry *entry)
|
|||
* to the Ethernet MAC address assigned to the network device.
|
||||
*/
|
||||
|
||||
entry->at_ipaddr = ipaddr;
|
||||
if (netdev_foreach(arp_match, entry) != 0)
|
||||
info.ai_ipaddr = ipaddr;
|
||||
info.ai_ethaddr = ethaddr;
|
||||
|
||||
if (netdev_foreach(arp_match, &info) != 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
@ -382,7 +427,7 @@ int arp_find(in_addr_t ipaddr, FAR struct arp_entry *entry)
|
|||
|
||||
void arp_delete(in_addr_t ipaddr)
|
||||
{
|
||||
FAR struct arp_entry *tabptr;
|
||||
FAR struct arp_entry_s *tabptr;
|
||||
|
||||
/* Check if the IPv4 address is in the ARP table. */
|
||||
|
||||
|
|
|
@ -159,10 +159,9 @@ static inline bool ipfwd_addrchk(FAR struct forward_s *fwd)
|
|||
{
|
||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||
FAR struct ipv4_hdr_s *ipv4 = (FAR struct ipv4_hdr_s *)fwd->f_iob->io_data;
|
||||
struct arp_entry entry;
|
||||
int ret;
|
||||
|
||||
ret = arp_find(*(in_addr_t *)ipv4->destipaddr, &entry);
|
||||
ret = arp_find(*(in_addr_t *)ipv4->destipaddr, NULL);
|
||||
return (ret >= 0);
|
||||
#else
|
||||
return true;
|
||||
|
|
|
@ -1259,7 +1259,7 @@ static int netdev_arp_ioctl(FAR struct socket *psock, int cmd,
|
|||
|
||||
/* Find the existing ARP table entry for this protocol address. */
|
||||
|
||||
FAR struct arp_entry *entry = arp_lookup(addr->sin_addr.s_addr);
|
||||
FAR struct arp_entry_s *entry = arp_lookup(addr->sin_addr.s_addr);
|
||||
if (entry != NULL)
|
||||
{
|
||||
/* The ARP table is fixed size; an entry is deleted
|
||||
|
@ -1287,19 +1287,18 @@ static int netdev_arp_ioctl(FAR struct socket *psock, int cmd,
|
|||
{
|
||||
FAR struct sockaddr_in *addr =
|
||||
(FAR struct sockaddr_in *)&req->arp_pa;
|
||||
struct arp_entry entry;
|
||||
|
||||
/* Find the existing ARP table entry for this protocol address. */
|
||||
/* Get the hardware address from an existing ARP table entry
|
||||
* matching this protocol address.
|
||||
*/
|
||||
|
||||
ret = arp_find(addr->sin_addr.s_addr, &entry);
|
||||
ret = arp_find(addr->sin_addr.s_addr,
|
||||
(FAR struct ether_addr *)req->arp_ha.sa_data);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Return the mapped hardware address. */
|
||||
|
||||
req->arp_ha.sa_family = ARPHRD_ETHER;
|
||||
memcpy(req->arp_ha.sa_data,
|
||||
entry.at_ethaddr.ether_addr_octet,
|
||||
ETHER_ADDR_LEN);
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -309,9 +309,7 @@ static inline bool psock_send_addrchck(FAR struct tcp_conn_s *conn)
|
|||
#endif
|
||||
|
||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||
struct arp_entry entry;
|
||||
|
||||
if (arp_find(conn->u.ipv4.raddr, &entry) >= 0)
|
||||
if (arp_find(conn->u.ipv4.raddr, NULL) >= 0)
|
||||
{
|
||||
/* Return true if the address was found in the ARP table */
|
||||
|
||||
|
|
|
@ -258,9 +258,7 @@ static inline bool psock_send_addrchck(FAR struct tcp_conn_s *conn)
|
|||
in_addr_t router;
|
||||
#endif
|
||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||
struct arp_entry entry;
|
||||
|
||||
if (arp_find(conn->u.ipv4.raddr, &entry) >= 0)
|
||||
if (arp_find(conn->u.ipv4.raddr, NULL) >= 0)
|
||||
{
|
||||
/* Return true if the address was found in the ARP table */
|
||||
|
||||
|
|
|
@ -296,9 +296,7 @@ static inline bool sendfile_addrcheck(FAR struct tcp_conn_s *conn)
|
|||
#endif
|
||||
{
|
||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||
struct arp_entry entry;
|
||||
|
||||
return (arp_find(conn->u.ipv4.raddr, &entry) >= 0);
|
||||
return (arp_find(conn->u.ipv4.raddr, NULL) >= 0);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
|
|
@ -281,9 +281,7 @@ static inline bool sendto_addrcheck(FAR struct udp_conn_s *conn,
|
|||
#endif
|
||||
{
|
||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||
struct arp_entry entry;
|
||||
|
||||
return (arp_find(conn->u.ipv4.raddr, entry) >= 0);
|
||||
return (arp_find(conn->u.ipv4.raddr, NULL) >= 0);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue