Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ARP: add more memory efficient way of handling arp requests #40

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 75 additions & 1 deletion src/core/ipv4/etharp.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,8 @@ etharp_get_entry(size_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth
}
}

#define Swap(X,Y) do{ __typeof__ (X) _T = X; X = Y; Y = _T; }while(0)

/**
* Responds to ARP requests to us. Upon ARP replies to us, add entry to cache
* send out queued IP packets. Updates cache with snooped address pairs.
Expand All @@ -635,11 +637,17 @@ etharp_get_entry(size_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth
*
* @param p The ARP packet that arrived on netif. Is freed by this function.
* @param netif The lwIP network interface on which the ARP packet pbuf arrived.
* @param header_size_document pass ethernet header size to handle both arp and ethernet headers
* here for more effective memory usage (see LWIP_ARP_REUSE_MEMORY description in opts.h)
*
* @see pbuf_free()
*/
void
etharp_input(struct pbuf *p, struct netif *netif)
etharp_input(struct pbuf *p, struct netif *netif
#if LWIP_ARP_REUSE_MEMORY
, size_t header_size_decrement
#endif /* LWIP_ARP_REUSE_MEMORY */
)
{
struct etharp_hdr *hdr;
/* these are aligned properly, whereas the ARP header fields might not be */
Expand All @@ -650,7 +658,11 @@ etharp_input(struct pbuf *p, struct netif *netif)

LWIP_ERROR("netif != NULL", (netif != NULL), return;);

#if LWIP_ARP_REUSE_MEMORY
hdr = (struct etharp_hdr *)((u8_t *)p->payload + header_size_decrement);
#else
hdr = (struct etharp_hdr *)p->payload;
#endif /* LWIP_ARP_REUSE_MEMORY */

/* RFC 826 "Packet Reception": */
if ((hdr->hwtype != PP_HTONS(LWIP_IANA_HWTYPE_ETHERNET)) ||
Expand Down Expand Up @@ -714,11 +726,73 @@ etharp_input(struct pbuf *p, struct netif *netif)
/* ARP request for our address? */
if (for_us && !from_us) {
/* send ARP response */
#if !LWIP_ARP_REUSE_MEMORY
etharp_raw(netif,
(struct eth_addr *)netif->hwaddr, &hdr->shwaddr,
(struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif),
&hdr->shwaddr, &sipaddr,
ARP_REPLY);
#else
/* swapping addresses here so we don't need need to call any other functions or waste memory
* to create header for response packet */
struct eth_hdr *ethhdr;
u16_t eth_type_be;
hdr->opcode = lwip_htons(ARP_REPLY);
Swap(hdr->shwaddr, hdr->dhwaddr);
Swap(hdr->sipaddr, hdr->dipaddr);
SMEMCPY(&hdr->shwaddr, (struct eth_addr *)netif->hwaddr, ETH_HWADDR_LEN);
ethhdr = (struct eth_hdr *)p->payload;
eth_type_be = lwip_htons(ETHTYPE_ARP);

#if ETHARP_SUPPORT_VLAN && (defined(LWIP_HOOK_VLAN_SET) || LWIP_VLAN_PCP)
s32_t vlan_prio_vid;
#ifdef LWIP_HOOK_VLAN_SET
vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, ethhdr->src, ethhdr->dest, ETHTYPE_ARP);
#elif LWIP_VLAN_PCP
vlan_prio_vid = -1;
if (netif->hints && (netif->hints->tci >= 0)) {
vlan_prio_vid = (u16_t)netif->hints->tci;
}
#endif
if (vlan_prio_vid >= 0) {
struct eth_vlan_hdr *vlanhdr;

LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF);

vlanhdr = (struct eth_vlan_hdr *)(((u8_t *)p->payload) + SIZEOF_ETH_HDR);
vlanhdr->tpid = eth_type_be;
vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid);

eth_type_be = PP_HTONS(ETHTYPE_VLAN);
}
#endif /* ETHARP_SUPPORT_VLAN && (defined(LWIP_HOOK_VLAN_SET) || LWIP_VLAN_PCP) */

LWIP_ASSERT_CORE_LOCKED();

ethhdr = (struct eth_hdr *)p->payload;
ethhdr->type = eth_type_be;
Swap(ethhdr->dest, ethhdr->src);
#if LWIP_AUTOIP
/* If we are using Link-Local, all ARP packets that contain a Link-Local
* 'sender IP address' MUST be sent using link-layer broadcast instead of
* link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
if (ip4_addr_islinklocal(netif_ip4_addr(netif))) {
SMEMCPY(&ethhdr->src, &ethbroadcast, ETH_HWADDR_LEN);
} else
#endif /* LWIP_AUTOIP */
{
SMEMCPY(&ethhdr->src, &hdr->shwaddr, ETH_HWADDR_LEN);
}

LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!",
(netif->hwaddr_len == ETH_HWADDR_LEN));
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
("ethernet_output: sending packet %p\n", (void *)p));

netif->linkoutput(netif, p);

ETHARP_STATS_INC(etharp.xmit);
#endif /* !LWIP_ARP_REUSE_MEMORY */
/* we are not configured? */
} else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
/* { for_us == 0 and netif->ip_addr.addr == 0 } */
Expand Down
6 changes: 5 additions & 1 deletion src/include/lwip/etharp.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ err_t etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr
err_t etharp_remove_static_entry(const ip4_addr_t *ipaddr);
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */

void etharp_input(struct pbuf *p, struct netif *netif);
void etharp_input(struct pbuf *p, struct netif *netif
#if LWIP_ARP_REUSE_MEMORY
, size_t header_size_decrement
#endif
);

#ifdef __cplusplus
}
Expand Down
10 changes: 10 additions & 0 deletions src/include/lwip/opt.h
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,16 @@
#if !defined ETHARP_TABLE_MATCH_NETIF || defined __DOXYGEN__
#define ETHARP_TABLE_MATCH_NETIF !LWIP_SINGLE_NETIF
#endif

/** LWIP_ARP_REUSE_MEMORY==1: Reuse pbuf used for arp request to send an
* arp reply as described in RFC 826.
* If disabled, new pbuf will be allocated and all required data from request
* packet will be copied with SMEMCPY (better if you want to separate layers
* but worse in terms of memory usage)
*/
#if !defined LWIP_ARP_REUSE_MEMORY || defined __DOXYGEN__
#define LWIP_ARP_REUSE_MEMORY 1
#endif
/**
* @}
*/
Expand Down
4 changes: 4 additions & 0 deletions src/netif/ethernet.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ ethernet_input(struct pbuf *p, struct netif *netif)
goto free_and_return;
}
/* skip Ethernet header (min. size checked above) */
#if !LWIP_ARP_REUSE_MEMORY
if (pbuf_remove_header(p, next_hdr_offset)) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
("ethernet_input: ARP response packet dropped, too short (%"U16_F"/%"U16_F")\n",
Expand All @@ -204,6 +205,9 @@ ethernet_input(struct pbuf *p, struct netif *netif)
/* pass p to ARP module */
etharp_input(p, netif);
}
#else
etharp_input(p, netif, next_hdr_offset);
#endif /* !LWIP_ARP_REUSE_MEMORY */
break;
#endif /* LWIP_IPV4 && LWIP_ARP */
#if PPPOE_SUPPORT
Expand Down