Only free the queued packets if there are any.

This commit is contained in:
likewise 2003-06-09 20:28:10 +00:00
parent b306cab8be
commit 734400cafa

View File

@ -10,9 +10,9 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* All rights reserved.
*
* 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,
@ -21,51 +21,51 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* This file is part of the lwIP TCP/IP stack.
*
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*
* TODO:
*
RFC 3220 4.6 IP Mobility Support for IPv4 January 2002
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).
- 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].
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.
@ -84,9 +84,9 @@ RFC 3220 4.6 IP Mobility Support for IPv4 January 2002
#endif
/** the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. */
#define ARP_MAXAGE 120
#define ARP_MAXAGE 120
/** the time an ARP entry stays pending after first request, (2 * 10) seconds = 20 seconds. */
#define ARP_MAXPENDING 2
#define ARP_MAXPENDING 2
#define HWTYPE_ETHERNET 1
@ -148,33 +148,37 @@ void
etharp_tmr(void)
{
u8_t i;
DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
/* remove expired entries from the ARP table */
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
arp_table[i].ctime++;
if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
(arp_table[i].ctime >= ARP_MAXAGE)) {
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
arp_table[i].state = ETHARP_STATE_EMPTY;
#if ARP_QUEUEING
/* remove any queued packet */
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
if (arp_table[i].p != NULL) {
/* remove any queued packet */
DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing packet queue %p.\n", i, (void *)(arp_table[i].p)));
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
}
#endif
} else if ((arp_table[i].state == ETHARP_STATE_PENDING) &&
(arp_table[i].ctime >= ARP_MAXPENDING)) {
arp_table[i].state = ETHARP_STATE_EMPTY;
#if ARP_QUEUEING
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u - dequeueing %p.\n", i, (void *)(arp_table[i].p)));
/* remove any queued packet */
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
#else
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));
#if ARP_QUEUEING
if (arp_table[i].p != NULL) {
/* remove any queued packet */
DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing packet queue %p.\n", i, (void *)(arp_table[i].p)));
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
}
#endif
}
}
}
}
/**
@ -188,7 +192,7 @@ static u8_t
find_arp_entry(void)
{
u8_t i, j, maxtime;
/* Try to find an unused entry in the ARP table. */
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
if (arp_table[i].state == ETHARP_STATE_EMPTY) {
@ -196,7 +200,7 @@ find_arp_entry(void)
break;
}
}
/* If no unused entry is found, we try to find the oldest entry and
throw it away. If all entries are new and have 0 ctime drop one */
if (i == ARP_TABLE_SIZE) {
@ -289,7 +293,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
for (k = 0; k < netif->hwaddr_len; ++k) {
ethhdr->dest.addr[k] = ethaddr->addr[k];
}
ethhdr->type = htons(ETHTYPE_IP);
ethhdr->type = htons(ETHTYPE_IP);
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet.\n"));
/* send the queued IP packet */
netif->linkoutput(netif, p);
@ -327,17 +331,17 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("update_arp_entry: filling empty entry %u with state %u\n", i, arp_table[i].state));
LWIP_ASSERT("update_arp_entry: arp_table[i].state == ETHARP_STATE_EMPTY", arp_table[i].state == ETHARP_STATE_EMPTY);
}
/* set IP address */
/* set IP address */
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
/* set Ethernet hardware address */
/* set Ethernet hardware address */
for (k = 0; k < netif->hwaddr_len; ++k) {
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
}
/* reset time-stamp */
/* reset time-stamp */
arp_table[i].ctime = 0;
/* mark as stable */
/* mark as stable */
arp_table[i].state = ETHARP_STATE_STABLE;
/* no queued packet */
/* no queued packet */
#if ARP_QUEUEING
arp_table[i].p = NULL;
#endif
@ -359,7 +363,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
*
* @param netif The lwIP network interface on which the IP packet pbuf arrived.
* @param pbuf The IP packet that arrived on netif.
*
*
* @return NULL
*
* @see pbuf_free()
@ -368,7 +372,7 @@ struct pbuf *
etharp_ip_input(struct netif *netif, struct pbuf *p)
{
struct ethip_hdr *hdr;
/* Only insert an entry if the source IP address of the
incoming IP packet comes from a host on the local network. */
hdr = p->payload;
@ -377,7 +381,7 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
/* do nothing */
return NULL;
}
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
/* update ARP table, ask to insert entry */
update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);
@ -387,7 +391,7 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
/**
* Responds to ARP requests, updates ARP entries and sends queued IP packets.
*
*
* Should be called for incoming ARP packets. The pbuf in the argument
* is freed by this function.
*
@ -451,16 +455,16 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
hdr->proto = htons(ETHTYPE_IP);
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
hdr->ethhdr.type = htons(ETHTYPE_ARP);
hdr->ethhdr.type = htons(ETHTYPE_ARP);
/* return ARP reply */
netif->linkoutput(netif, p);
} else {
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n"));
}
break;
case ARP_REPLY:
case ARP_REPLY:
/* ARP reply. We insert or update the ARP table. */
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
@ -492,7 +496,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
return NULL;
}
/**
/**
* Resolve and fill-in Ethernet address header for outgoing packet.
*
* If ARP has the Ethernet address in cache, the given packet is
@ -510,8 +514,8 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
* @param netif The lwIP network interface which the IP packet will be sent on.
* @param ipaddr The IP address of the packet destination.
* @param pbuf The pbuf(s) containing the IP packet to be sent.
*
* @return If non-NULL, a packet ready to be sent.
*
* @return If non-NULL, a packet ready to be sent.
*/
struct pbuf *
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
@ -521,7 +525,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
u8_t i;
/* Make room for Ethernet header. */
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
/* The pbuf_header() call shouldn't fail, and we'll just bail
out if it does.. */
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
@ -580,7 +584,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
/* Ethernet address for IP destination address is in ARP cache? */
for(i = 0; i < ARP_TABLE_SIZE; ++i) {
/* match found? */
/* match found? */
if (arp_table[i].state == ETHARP_STATE_STABLE &&
ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
dest = &arp_table[i].ethaddr;
@ -616,7 +620,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
/* return the outgoing packet */
return q;
}
/* never reached; here for safety */
/* never reached; here for safety */
return NULL;
}
@ -750,7 +754,7 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
hdr->ethhdr.dest.addr[j] = 0xff;
hdr->ethhdr.src.addr[j] = srcaddr->addr[j];
}
hdr->ethhdr.type = htons(ETHTYPE_ARP);
hdr->ethhdr.type = htons(ETHTYPE_ARP);
/* send ARP query */
result = netif->linkoutput(netif, p);
/* free ARP query packet */