mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 11:26:12 +08:00
net/arp: Improve arp_find() commit 9774d35010 to reduce the amount and frequency of data copies.
This commit is contained in:
@@ -2,7 +2,8 @@
|
|||||||
* include/nuttx/net/arp.h
|
* include/nuttx/net/arp.h
|
||||||
* Macros and definitions for the ARP module.
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Derived from uIP with has a similar BSD-style license:
|
* Derived from uIP with has a similar BSD-style license:
|
||||||
@@ -78,7 +79,7 @@
|
|||||||
|
|
||||||
/* One entry in the ARP table (volatile!) */
|
/* One entry in the ARP table (volatile!) */
|
||||||
|
|
||||||
struct arp_entry
|
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 */
|
||||||
|
|||||||
+9
-5
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/arp/arp.h
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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
|
* 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).
|
* not be in the ARP table (it may, instead, be a local network device).
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* ipaddr - Refers to an IP address in network order
|
* ipaddr - Refers to an IP address in network order
|
||||||
* entry - location to return a copy of the ARP table entry.
|
* 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.
|
* 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
|
* Name: arp_delete
|
||||||
|
|||||||
+5
-4
@@ -1,7 +1,8 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/arp/arp_out.c
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Based on uIP which also has a BSD style license:
|
* 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)
|
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 eth_hdr_s *peth = ETHBUF;
|
||||||
FAR struct arp_iphdr_s *pip = IPBUF;
|
FAR struct arp_iphdr_s *pip = IPBUF;
|
||||||
in_addr_t ipaddr;
|
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 */
|
/* 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)
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
ninfo("ARP request for IP %08lx\n", (unsigned long)ipaddr);
|
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. */
|
/* 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 */
|
/* Finish populating the Ethernet header */
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -315,8 +315,6 @@ int arp_send(in_addr_t ipaddr)
|
|||||||
|
|
||||||
while (state.snd_retries < CONFIG_ARP_SEND_MAXTRIES)
|
while (state.snd_retries < CONFIG_ARP_SEND_MAXTRIES)
|
||||||
{
|
{
|
||||||
struct arp_entry entry;
|
|
||||||
|
|
||||||
/* Check if the address mapping is present in the ARP table. This
|
/* Check if the address mapping is present in the ARP table. This
|
||||||
* is only really meaningful on the first time through the loop.
|
* is only really meaningful on the first time through the loop.
|
||||||
*
|
*
|
||||||
@@ -324,7 +322,7 @@ int arp_send(in_addr_t ipaddr)
|
|||||||
* issue.
|
* issue.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (arp_find(ipaddr, &entry) >= 0)
|
if (arp_find(ipaddr, NULL) >= 0)
|
||||||
{
|
{
|
||||||
/* We have it! Break out with success */
|
/* We have it! Break out with success */
|
||||||
|
|
||||||
|
|||||||
+65
-20
@@ -49,7 +49,6 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@@ -66,13 +65,23 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_NET_ARP
|
#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
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* The table of known address mappings */
|
/* 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;
|
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)
|
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;
|
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;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +169,7 @@ void arp_reset(void)
|
|||||||
|
|
||||||
void arp_timer(void)
|
void arp_timer(void)
|
||||||
{
|
{
|
||||||
FAR struct arp_entry *tabptr;
|
FAR struct arp_entry_s *tabptr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
++g_arptime;
|
++g_arptime;
|
||||||
@@ -179,7 +207,7 @@ 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 *tabptr = NULL;
|
struct arp_entry_s *tabptr = NULL;
|
||||||
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
|
||||||
@@ -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;
|
int i;
|
||||||
|
|
||||||
/* Check if the IPv4 address is already in the ARP table. */
|
/* 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).
|
* not be in the ARP table (it may, instead, be a local network device).
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* 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.
|
* 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;
|
FAR struct arp_entry_s *tabptr;
|
||||||
|
struct arp_table_info_s info;
|
||||||
DEBUGASSERT(entry);
|
|
||||||
|
|
||||||
/* Check if the IPv4 address is already in the ARP table. */
|
/* Check if the IPv4 address is already in the ARP table. */
|
||||||
|
|
||||||
tabptr = arp_lookup(ipaddr);
|
tabptr = arp_lookup(ipaddr);
|
||||||
if (tabptr != NULL)
|
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;
|
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.
|
* to the Ethernet MAC address assigned to the network device.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
entry->at_ipaddr = ipaddr;
|
info.ai_ipaddr = ipaddr;
|
||||||
if (netdev_foreach(arp_match, entry) != 0)
|
info.ai_ethaddr = ethaddr;
|
||||||
|
|
||||||
|
if (netdev_foreach(arp_match, &info) != 0)
|
||||||
{
|
{
|
||||||
return OK;
|
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)
|
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. */
|
/* 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)
|
#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;
|
FAR struct ipv4_hdr_s *ipv4 = (FAR struct ipv4_hdr_s *)fwd->f_iob->io_data;
|
||||||
struct arp_entry entry;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = arp_find(*(in_addr_t *)ipv4->destipaddr, &entry);
|
ret = arp_find(*(in_addr_t *)ipv4->destipaddr, NULL);
|
||||||
return (ret >= 0);
|
return (ret >= 0);
|
||||||
#else
|
#else
|
||||||
return true;
|
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. */
|
/* 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)
|
if (entry != NULL)
|
||||||
{
|
{
|
||||||
/* The ARP table is fixed size; an entry is deleted
|
/* 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 *addr =
|
||||||
(FAR struct sockaddr_in *)&req->arp_pa;
|
(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)
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
/* Return the mapped hardware address. */
|
/* Return the mapped hardware address. */
|
||||||
|
|
||||||
req->arp_ha.sa_family = ARPHRD_ETHER;
|
req->arp_ha.sa_family = ARPHRD_ETHER;
|
||||||
memcpy(req->arp_ha.sa_data,
|
|
||||||
entry.at_ethaddr.ether_addr_octet,
|
|
||||||
ETHER_ADDR_LEN);
|
|
||||||
ret = OK;
|
ret = OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -309,9 +309,7 @@ static inline bool psock_send_addrchck(FAR struct tcp_conn_s *conn)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||||
struct arp_entry entry;
|
if (arp_find(conn->u.ipv4.raddr, NULL) >= 0)
|
||||||
|
|
||||||
if (arp_find(conn->u.ipv4.raddr, &entry) >= 0)
|
|
||||||
{
|
{
|
||||||
/* Return true if the address was found in the ARP table */
|
/* 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;
|
in_addr_t router;
|
||||||
#endif
|
#endif
|
||||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||||
struct arp_entry entry;
|
if (arp_find(conn->u.ipv4.raddr, NULL) >= 0)
|
||||||
|
|
||||||
if (arp_find(conn->u.ipv4.raddr, &entry) >= 0)
|
|
||||||
{
|
{
|
||||||
/* Return true if the address was found in the ARP table */
|
/* 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
|
#endif
|
||||||
{
|
{
|
||||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||||
struct arp_entry entry;
|
return (arp_find(conn->u.ipv4.raddr, NULL) >= 0);
|
||||||
|
|
||||||
return (arp_find(conn->u.ipv4.raddr, &entry) >= 0);
|
|
||||||
#else
|
#else
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -281,9 +281,7 @@ static inline bool sendto_addrcheck(FAR struct udp_conn_s *conn,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||||
struct arp_entry entry;
|
return (arp_find(conn->u.ipv4.raddr, NULL) >= 0);
|
||||||
|
|
||||||
return (arp_find(conn->u.ipv4.raddr, entry) >= 0);
|
|
||||||
#else
|
#else
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user