mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2025-08-03 21:14:40 +08:00
Implemented conditional insertion of ARP entries to update_arp_entry using ARP_INSERT_FLAG.
This commit is contained in:
parent
1f1e6eb5a1
commit
f9129c4dcd
@ -3,6 +3,9 @@
|
|||||||
* Address Resolution Protocol module for IP over Ethernet
|
* Address Resolution Protocol module for IP over Ethernet
|
||||||
*
|
*
|
||||||
* $Log: etharp.c,v $
|
* $Log: etharp.c,v $
|
||||||
|
* Revision 1.7 2002/11/13 08:56:11 likewise
|
||||||
|
* Implemented conditional insertion of ARP entries to update_arp_entry using ARP_INSERT_FLAG.
|
||||||
|
*
|
||||||
* Revision 1.6 2002/11/11 14:34:29 likewise
|
* Revision 1.6 2002/11/11 14:34:29 likewise
|
||||||
* Changed static etharp_query() to support queueing packets. This fix missed in last commit.
|
* Changed static etharp_query() to support queueing packets. This fix missed in last commit.
|
||||||
*
|
*
|
||||||
@ -53,6 +56,38 @@
|
|||||||
* Author: Adam Dunkels <adam@sics.se>
|
* Author: Adam Dunkels <adam@sics.se>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO:
|
||||||
|
*
|
||||||
|
RFC 3220 4.6 IP Mobility Support for IPv4 January 2002
|
||||||
|
|
||||||
|
- A Gratuitous ARP [45] is an ARP packet sent by a node in order
|
||||||
|
to spontaneously cause other nodes to update an entry in their
|
||||||
|
ARP cache. A gratuitous ARP MAY use either an ARP Request or
|
||||||
|
an ARP Reply packet. In either case, the ARP Sender Protocol
|
||||||
|
Address and ARP Target Protocol Address are both set to the IP
|
||||||
|
address of the cache entry to be updated, and the ARP Sender
|
||||||
|
Hardware Address is set to the link-layer address to which this
|
||||||
|
cache entry should be updated. When using an ARP Reply packet,
|
||||||
|
the Target Hardware Address is also set to the link-layer
|
||||||
|
address to which this cache entry should be updated (this field
|
||||||
|
is not used in an ARP Request packet).
|
||||||
|
|
||||||
|
In either case, for a gratuitous ARP, the ARP packet MUST be
|
||||||
|
transmitted as a local broadcast packet on the local link. As
|
||||||
|
specified in [36], any node receiving any ARP packet (Request
|
||||||
|
or Reply) MUST update its local ARP cache with the Sender
|
||||||
|
Protocol and Hardware Addresses in the ARP packet, if the
|
||||||
|
receiving node has an entry for that IP address already in its
|
||||||
|
ARP cache. This requirement in the ARP protocol applies even
|
||||||
|
for ARP Request packets, and for ARP Reply packets that do not
|
||||||
|
match any ARP Request transmitted by the receiving node [36].
|
||||||
|
*
|
||||||
|
My suggestion would be to send a ARP request for our newly obtained
|
||||||
|
address upon configuration of an Ethernet interface.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/debug.h"
|
#include "lwip/debug.h"
|
||||||
@ -67,10 +102,10 @@
|
|||||||
# include "lwip/dhcp.h"
|
# include "lwip/dhcp.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** the time an ARP entry stays valid after its last update */
|
/** the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. */
|
||||||
#define ARP_MAXAGE 120 /* 120 * 10 seconds = 20 minutes. */
|
#define ARP_MAXAGE 120
|
||||||
/** the maximum time waiting for ARP reply to a ARP request */
|
/** the time an ARP entry stays pending after first request, (2 * 10) seconds = 20 seconds. */
|
||||||
#define ARP_MAXPENDING 2 /* 2 * 10 seconds = 20 seconds. */
|
#define ARP_MAXPENDING 2
|
||||||
|
|
||||||
#define HWTYPE_ETHERNET 1
|
#define HWTYPE_ETHERNET 1
|
||||||
|
|
||||||
@ -138,7 +173,8 @@ static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
|
|||||||
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
|
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
|
||||||
static u8_t ctime;
|
static u8_t ctime;
|
||||||
|
|
||||||
static struct pbuf *insert_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr);
|
static struct pbuf *update_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
|
||||||
|
#define ARP_INSERT_FLAG 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes ARP module.
|
* Initializes ARP module.
|
||||||
@ -151,6 +187,7 @@ etharp_init(void)
|
|||||||
for(i = 0; i < ARP_TABLE_SIZE; ++i) {
|
for(i = 0; i < ARP_TABLE_SIZE; ++i) {
|
||||||
arp_table[i].state = ETHARP_STATE_EMPTY;
|
arp_table[i].state = ETHARP_STATE_EMPTY;
|
||||||
}
|
}
|
||||||
|
/* reset ARP current time */
|
||||||
ctime = 0;
|
ctime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,18 +260,20 @@ find_arp_entry(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert an entry into the ARP cache, or update an existing one.
|
* Update (or insert) an entry in the ARP cache.
|
||||||
*
|
*
|
||||||
* @param ipaddr IP address of the inserted ARP entry.
|
* @param ipaddr IP address of the inserted ARP entry.
|
||||||
* @param ethaddr Ethernet address of the inserted ARP entry.
|
* @param ethaddr Ethernet address of the inserted ARP entry.
|
||||||
*
|
* @param flags Defines behaviour:
|
||||||
|
* - ARP_INSERT_FLAG Allows ARP to insert this as a new item. If not specified,
|
||||||
|
* only existing ARP entries will be updated.
|
||||||
* @return pbuf If non-NULL, a packet that was queued on a pending entry.
|
* @return pbuf If non-NULL, a packet that was queued on a pending entry.
|
||||||
* You should sent it and must call pbuf_free().
|
* You should sent it and must call pbuf_free().
|
||||||
*
|
*
|
||||||
* @see pbuf_free()
|
* @see pbuf_free()
|
||||||
*/
|
*/
|
||||||
static struct pbuf *
|
static struct pbuf *
|
||||||
insert_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)
|
update_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
|
||||||
{
|
{
|
||||||
u8_t i, k;
|
u8_t i, k;
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
@ -250,7 +289,7 @@ insert_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)
|
|||||||
|
|
||||||
/* check those entries that are already in use. */
|
/* check those entries that are already in use. */
|
||||||
if(arp_table[i].state == ETHARP_STATE_STABLE) {
|
if(arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||||
DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: updating stable entry %u\n", i));
|
DEBUGF(ETHARP_DEBUG, ("update_arp_entry: updating stable entry %u\n", i));
|
||||||
/* An old entry found, update this and return. */
|
/* An old entry found, update this and return. */
|
||||||
for(k = 0; k < 6; ++k) {
|
for(k = 0; k < 6; ++k) {
|
||||||
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
||||||
@ -260,8 +299,8 @@ insert_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)
|
|||||||
}
|
}
|
||||||
else if(arp_table[i].state == ETHARP_STATE_PENDING) {
|
else if(arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||||
/* A pending entry was found, so we fill this in and return
|
/* A pending entry was found, so we fill this in and return
|
||||||
the queued packet (if any). */
|
the queued packet (if any). */
|
||||||
DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: pending entry %u made stable\n", i));
|
DEBUGF(ETHARP_DEBUG, ("update_arp_entry: pending entry %u made stable\n", i));
|
||||||
for(k = 0; k < 6; ++k) {
|
for(k = 0; k < 6; ++k) {
|
||||||
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
||||||
}
|
}
|
||||||
@ -281,34 +320,38 @@ insert_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ethhdr->type = htons(ETHTYPE_IP);
|
ethhdr->type = htons(ETHTYPE_IP);
|
||||||
DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: returning queued packet %p\n", p));
|
DEBUGF(ETHARP_DEBUG, ("update_arp_entry: returning queued packet %p\n", p));
|
||||||
}
|
}
|
||||||
/* return queued packet, if any */
|
/* return queued packet, if any */
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* no matching ARP entry was found. find an empty or old entry. */
|
/* no matching ARP entry was found */
|
||||||
i = find_arp_entry();
|
/* allowed to insert an entry? */
|
||||||
if(i == ARP_TABLE_SIZE) {
|
if (flags & ARP_INSERT_FLAG)
|
||||||
DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: no available entry found\n"));
|
{
|
||||||
return NULL;
|
/* find an empty or old entry. */
|
||||||
}
|
i = find_arp_entry();
|
||||||
|
if(i == ARP_TABLE_SIZE) {
|
||||||
|
DEBUGF(ETHARP_DEBUG, ("update_arp_entry: no available entry found\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||||
DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: overwriting old stable entry %u\n", i));
|
DEBUGF(ETHARP_DEBUG, ("update_arp_entry: overwriting old stable entry %u\n", i));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DEBUGF(ETHARP_DEBUG, ("update_arp_entry: using empty entry %u\n", i));
|
||||||
|
}
|
||||||
|
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
|
||||||
|
for(k = 0; k < 6; ++k) {
|
||||||
|
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
||||||
|
}
|
||||||
|
arp_table[i].ctime = ctime;
|
||||||
|
arp_table[i].state = ETHARP_STATE_STABLE;
|
||||||
|
arp_table[i].p = NULL;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: using empty entry %u\n", i));
|
|
||||||
}
|
|
||||||
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
|
|
||||||
for(k = 0; k < 6; ++k) {
|
|
||||||
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
|
||||||
}
|
|
||||||
arp_table[i].ctime = ctime;
|
|
||||||
arp_table[i].state = ETHARP_STATE_STABLE;
|
|
||||||
arp_table[i].p = NULL;
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,8 +389,8 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));
|
DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));
|
||||||
/* update ARP table */
|
/* update ARP table, may insert */
|
||||||
return insert_arp_entry(&(hdr->ip.src), &(hdr->eth.src));
|
return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -432,9 +475,9 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||||||
if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
|
if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply for us\n"));
|
DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply for us\n"));
|
||||||
/* insert_arp_entry() can return a pbuf that has previously been
|
/* update_arp_entry() can return a pbuf that has previously been
|
||||||
queued waiting for this IP address to become ARP stable. */
|
queued waiting for this IP address to become ARP stable. */
|
||||||
q = insert_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr));
|
q = update_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);
|
||||||
/* free incoming ARP reply pbuf */
|
/* free incoming ARP reply pbuf */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
p = NULL;
|
p = NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user