Compare commits
78 Commits
PRE_PACK_R
...
STABLE-1_1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb99d21022 | ||
|
|
793cbcdff8 | ||
|
|
751557bcbf | ||
|
|
252dcd8626 | ||
|
|
0ad7ea16d2 | ||
|
|
79842d4fdd | ||
|
|
1e1f5d5462 | ||
|
|
19d8ffe177 | ||
|
|
4cb8192c1d | ||
|
|
2ed5bc5195 | ||
|
|
fae1397468 | ||
|
|
e871548772 | ||
|
|
a3d27e30e0 | ||
|
|
89abd1f58e | ||
|
|
fae709d9ea | ||
|
|
36df79b207 | ||
|
|
b9ebcd7738 | ||
|
|
515fb5a3fd | ||
|
|
785f90d9fa | ||
|
|
22ac311496 | ||
|
|
0e31ca73c0 | ||
|
|
98ba558fa5 | ||
|
|
c4ef1e5c19 | ||
|
|
1fa0d66f15 | ||
|
|
4680307a34 | ||
|
|
42a6fa972d | ||
|
|
1da6c35a6d | ||
|
|
7c427a4dce | ||
|
|
c2abae538b | ||
|
|
eb69032773 | ||
|
|
fb5452910f | ||
|
|
a6d37fcb25 | ||
|
|
fb18e1f036 | ||
|
|
786cbee510 | ||
|
|
a4f5673ff3 | ||
|
|
1121f2b7f7 | ||
|
|
4d30218eb2 | ||
|
|
d7699ca81d | ||
|
|
afc3bc6b65 | ||
|
|
6f066fca82 | ||
|
|
5e24ae49a6 | ||
|
|
bf74ffe974 | ||
|
|
2074861b57 | ||
|
|
58b64d42f1 | ||
|
|
a6ab0405ea | ||
|
|
8273b54108 | ||
|
|
c356f560e8 | ||
|
|
8d052ecf24 | ||
|
|
45e36d9f56 | ||
|
|
c222d8b672 | ||
|
|
efed3f1f0d | ||
|
|
7524893802 | ||
|
|
25a0273b05 | ||
|
|
ce0410b205 | ||
|
|
efe5ce5c78 | ||
|
|
07f52b4b96 | ||
|
|
0be3598990 | ||
|
|
c3284c30cd | ||
|
|
2d94bf4998 | ||
|
|
31c1e72b8c | ||
|
|
d11fcafad8 | ||
|
|
27c6d299cf | ||
|
|
450dd65165 | ||
|
|
26819e6c39 | ||
|
|
6587efb3e8 | ||
|
|
8d2200f29b | ||
|
|
e4295396ac | ||
|
|
5c7a70df28 | ||
|
|
16a7a8258f | ||
|
|
fb1f61b212 | ||
|
|
c3137df39c | ||
|
|
2df9cd7262 | ||
|
|
a23f6afbee | ||
|
|
e37f7fafc1 | ||
|
|
7b803465ad | ||
|
|
273612b251 | ||
|
|
e2bc8e86e2 | ||
|
|
79110ba469 |
63
CHANGELOG
63
CHANGELOG
@@ -9,13 +9,72 @@ HISTORY
|
||||
|
||||
(HEAD)
|
||||
|
||||
(STABLE-1_1_0-RC1)
|
||||
|
||||
2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
|
||||
* tcp.c Add code to tcp_recved() to send an ACK (window update) immediately,
|
||||
even if one is already pending, if the rcv_wnd is above a threshold
|
||||
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a
|
||||
delayed ACK in order to open the window if the stack is only receiving data.
|
||||
|
||||
2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
|
||||
* tcp*.* Retransmit time-out handling improvement by Sam Jansen.
|
||||
|
||||
2004-08-20 Tony Mountifield <tony@softins.co.uk>
|
||||
* etharp.c Make sure the first pbuf queued on an ARP entry
|
||||
is properly ref counted.
|
||||
|
||||
2004-07-27 Tony Mountifield <tony@softins.co.uk>
|
||||
* debug.h Added (int) cast in LWIP_DEBUGF() to avoid compiler
|
||||
warnings about comparison.
|
||||
* pbuf.c Stopped compiler complaining of empty if statement
|
||||
when LWIP_DEBUGF() empty. Closed an unclosed comment.
|
||||
* tcp.c Stopped compiler complaining of empty if statement
|
||||
when LWIP_DEBUGF() empty.
|
||||
* ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons().
|
||||
* inet.c Added a couple of casts to quiet the compiler.
|
||||
No need to test isascii(c) before isdigit(c) or isxdigit(c).
|
||||
|
||||
2004-07-22 Tony Mountifield <tony@softins.co.uk>
|
||||
* inet.c Made data types consistent in inet_ntoa().
|
||||
Added casts for return values of checksum routines, to pacify compiler.
|
||||
* ip_frag.c, tcp_out.c, sockets.c, pbuf.c
|
||||
Small corrections to some debugging statements, to pacify compiler.
|
||||
|
||||
2004-07-21 Tony Mountifield <tony@softins.co.uk>
|
||||
* etharp.c Removed spurious semicolon and added missing end-of-comment.
|
||||
* ethernetif.c Updated low_level_output() to match prototype for
|
||||
netif->linkoutput and changed low_level_input() similarly for consistency.
|
||||
* api_msg.c Changed recv_raw() from int to u8_t, to match prototype
|
||||
of raw_recv() in raw.h and so avoid compiler error.
|
||||
* sockets.c Added trivial (int) cast to keep compiler happier.
|
||||
* ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros.
|
||||
|
||||
|
||||
(STABLE-1_0_0)
|
||||
|
||||
++ Changes:
|
||||
|
||||
2004-07-05 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* sockets.* Restructured LWIP_PRIVATE_TIMEVAL. Make sure
|
||||
your cc.h file defines this either 1 or 0. If non-defined,
|
||||
defaults to 1.
|
||||
* .c: Added <string.h> and <errno.h> includes where used.
|
||||
* etharp.c: Made some array indices unsigned.
|
||||
|
||||
2004-06-27 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* netif.*: Added netif_set_up()/down().
|
||||
* dhcp.c: Changes to restart program flow.
|
||||
|
||||
2004-05-07 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* etharp.c: In find_entry(), instead of a list traversal per candidate, do a
|
||||
single-pass lookup for different candidates. Should exploit locality.
|
||||
|
||||
2004-04-29 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* tcp*.c: Cleaned up source comment documentation for Doxygen processing.
|
||||
* opt.h: ETHHARP_ALWAYS_INSERT option removed to comply with ARP RFC.
|
||||
* opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC.
|
||||
* etharp.c: update_arp_entry() only adds new ARP entries when adviced to by
|
||||
the caller. This deprecates the ETHHARP_ALWAYS_INSERT overrule option.
|
||||
the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option.
|
||||
|
||||
++ Bug fixes:
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ in lwIP development.
|
||||
2 How to contribute to lwIP
|
||||
|
||||
Here is a short list of suggestions to anybody working with lwIP and
|
||||
trying to contribute bugreports, fixes, enhancements, platform ports etc.
|
||||
trying to contribute bug reports, fixes, enhancements, platform ports etc.
|
||||
First of all as you may already know lwIP is a volunteer project so feedback
|
||||
to fixes or questions might often come late. Hopefully the bug and patch tracking
|
||||
features of Savannah help us not lose users' input.
|
||||
@@ -14,13 +14,14 @@ features of Savannah help us not lose users' input.
|
||||
2.1 Source code style:
|
||||
|
||||
1. do not use tabs.
|
||||
2. identation is two spaces per level.
|
||||
2. indentation is two spaces per level (i.e. per tab).
|
||||
3. end debug messages with a trailing newline (\n).
|
||||
4. one space between keyword and opening bracket.
|
||||
5. no space between function and opening bracket.
|
||||
6. one space and no newline before opening curly braces of a block.
|
||||
7. spaces surrounding assignment and comparisons.
|
||||
8. use current source code style as further reference.
|
||||
7. closing curly brace on a single line.
|
||||
8. spaces surrounding assignment and comparisons.
|
||||
9. use current source code style as further reference.
|
||||
|
||||
2.2 Source code documentation style:
|
||||
|
||||
@@ -55,9 +56,7 @@ features of Savannah help us not lose users' input.
|
||||
|
||||
2.4 Platform porters:
|
||||
|
||||
1. If you've ported lwIP to a platform (an OS, a uC/processor or a combination of these) and you think it
|
||||
could benefit others[1] you might want to post an url to a tarball or zip from which it can be imported
|
||||
to the contrib CVS module. Then you get CVS access and have to maintain your port :)
|
||||
|
||||
[1] - lwIP CVS should not be just a place to keep your port so you don't have to set up your own CVS :)
|
||||
Especially welcome are ports to common enough OS/hardware that others can have access too.
|
||||
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
|
||||
you think it could benefit others[1] you might want discuss this on the mailing list. You
|
||||
can also ask for CVS access to submit and maintain your port in the contrib CVS module.
|
||||
|
||||
@@ -115,40 +115,16 @@ tar czvf lwip-0.6.3.tar.gz lwip-0.6.3
|
||||
tar cjvf lwip-0.6.3.tar.bz2 lwip-0.6.3
|
||||
zip -r lwip-0.6.3.zip lwip-0.6.3
|
||||
|
||||
First, make a local release directory to work in, I use "lwip-releases":
|
||||
Now, sign the archives with a detached GPG binary signature as follows:
|
||||
|
||||
mkdir lwip-releases
|
||||
cd lwip-releases
|
||||
gpg -b lwip-0.6.3.tar.gz
|
||||
gpg -b lwip-0.6.3.tar.bz2
|
||||
gpg -b lwip-0.6.3.zip
|
||||
|
||||
Now, make a new release by creating a new directory for it (these are
|
||||
Savannah conventions so that it shows up in the Files list real nice):
|
||||
Upload these files using anonymous FTP:
|
||||
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
|
||||
|
||||
mkdir stable.pkg
|
||||
mkdir stable.pkg 0.6.3
|
||||
|
||||
We can now copy the tar archive we made earlier into the release directory:
|
||||
|
||||
cp ../../../lwip-0.6.3.tar.gz .
|
||||
|
||||
Finally, synchronize this directory upwards to Savannah:
|
||||
|
||||
rsync -n -e "ssh -1" -t -u -v -r *.pkg likewise@savannah.nongnu.org:/upload/lwip
|
||||
|
||||
This does a "dry run": no files are modified! After you have confirmed that
|
||||
this is what you intended to do, remove "-n" and actually synchronize for
|
||||
real. The release should now be available here:
|
||||
|
||||
http://savannah.nongnu.org/files/?group=lwip
|
||||
|
||||
---
|
||||
Explanation of rsync options used:
|
||||
|
||||
-t: preserve file timestamps
|
||||
-u: do not overwrite existing files, unless they are older
|
||||
-v: be verbose (long format file attributes)
|
||||
-r: recurse into directories
|
||||
-n: dry-run, do not modify anything.
|
||||
---
|
||||
ncftp>mput *0.6.3.*
|
||||
|
||||
Additionally, you may post a news item on Savannah, like this:
|
||||
|
||||
|
||||
@@ -280,9 +280,10 @@ netconn_delete(struct netconn *conn)
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
pbuf_free((struct pbuf *)mem);
|
||||
if(mem != NULL)
|
||||
pbuf_free((struct pbuf *)mem);
|
||||
} else {
|
||||
netbuf_delete((struct netbuf *)mem);
|
||||
netbuf_delete((struct netbuf *)mem);
|
||||
}
|
||||
}
|
||||
sys_mbox_free(conn->recvmbox);
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#if LWIP_RAW
|
||||
static int
|
||||
static u8_t
|
||||
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr)
|
||||
{
|
||||
|
||||
@@ -32,12 +32,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#define LWIP_TIMEVAL_PRIVATE
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#define NUM_SOCKETS MEMP_NUM_NETCONN
|
||||
@@ -416,7 +418,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
|
||||
} else {
|
||||
#if SOCKETS_DEBUG > 0
|
||||
#if SOCKETS_DEBUG != 0
|
||||
addr = netbuf_fromaddr(buf);
|
||||
port = netbuf_fromport(buf);
|
||||
|
||||
@@ -1139,7 +1141,7 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );
|
||||
break;
|
||||
case TCP_KEEPALIVE:
|
||||
*(int*)optval = sock->conn->pcb.tcp->keepalive;
|
||||
*(int*)optval = (int)sock->conn->pcb.tcp->keepalive;
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
|
||||
break;
|
||||
} /* switch */
|
||||
@@ -1307,7 +1309,7 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
||||
break;
|
||||
case TCP_KEEPALIVE:
|
||||
sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s, sock->conn->pcb.tcp->keepalive));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n", s, sock->conn->pcb.tcp->keepalive));
|
||||
break;
|
||||
} /* switch */
|
||||
break;
|
||||
|
||||
@@ -56,19 +56,25 @@ tcpip_tcp_timer(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
/* call TCP timer handler */
|
||||
tcp_tmr();
|
||||
/* timer still needed? */
|
||||
if (tcp_active_pcbs || tcp_tw_pcbs) {
|
||||
/* restart timer */
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
} else {
|
||||
tcpip_tcp_timer_active = 0;
|
||||
/* disable timer */
|
||||
tcpip_tcp_timer_active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tcp_timer_needed(void)
|
||||
{
|
||||
/* timer is off but needed again? */
|
||||
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
|
||||
tcpip_tcp_timer_active = 1;
|
||||
/* enable and start timer */
|
||||
tcpip_tcp_timer_active = 1;
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,9 @@
|
||||
* to remove the DHCP client.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/udp.h"
|
||||
@@ -82,7 +85,8 @@
|
||||
#if LWIP_DHCP /* don't build if not configured for use in lwipopt.h */
|
||||
|
||||
/** global transaction identifier, must be
|
||||
* unique for each DHCP request. */
|
||||
* unique for each DHCP request. We simply increment, starting
|
||||
* with this value (easy to match with a packet analyzer) */
|
||||
static u32_t xid = 0xABCD0000;
|
||||
|
||||
/** DHCP client state machine functions */
|
||||
@@ -231,10 +235,11 @@ static err_t dhcp_select(struct netif *netif)
|
||||
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
|
||||
dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
|
||||
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
|
||||
|
||||
dhcp_option_trailer(dhcp);
|
||||
/* shrink the pbuf to the actual content length */
|
||||
@@ -293,18 +298,20 @@ void dhcp_coarse_tmr()
|
||||
/**
|
||||
* DHCP transaction timeout handling
|
||||
*
|
||||
* A DHCP server is expected to respond within a
|
||||
* short period of time.
|
||||
* A DHCP server is expected to respond within a short period of time.
|
||||
* This timer checks whether an outstanding DHCP request is timed out.
|
||||
*
|
||||
*/
|
||||
void dhcp_fine_tmr()
|
||||
{
|
||||
struct netif *netif = netif_list;
|
||||
/* loop through clients */
|
||||
/* loop through netif's */
|
||||
while (netif != NULL) {
|
||||
/* only act on DHCP configured interfaces */
|
||||
if (netif->dhcp != NULL) {
|
||||
/* timer is active (non zero), and triggers (zeroes) now */
|
||||
/* timer is active (non zero), and is about to trigger now */
|
||||
if (netif->dhcp->request_timeout-- == 1) {
|
||||
/* { netif->dhcp->request_timeout == 0 } */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
|
||||
/* this clients' request timeout triggered */
|
||||
dhcp_timeout(netif);
|
||||
@@ -383,8 +390,8 @@ static void dhcp_t1_timeout(struct netif *netif)
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_t1_timeout()\n"));
|
||||
if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
|
||||
/* just retry to renew */
|
||||
/* note that the rebind timer will eventually time-out if renew does not work */
|
||||
/* just retry to renew - note that the rebind timer (t2) will
|
||||
* eventually time-out if renew tries fail. */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
|
||||
dhcp_renew(netif);
|
||||
}
|
||||
@@ -479,6 +486,19 @@ static void dhcp_handle_ack(struct netif *netif)
|
||||
if (option_ptr != NULL) {
|
||||
dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
|
||||
}
|
||||
|
||||
/* DNS servers */
|
||||
option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_DNS_SERVER);
|
||||
if (option_ptr != NULL) {
|
||||
u8_t n;
|
||||
dhcp->dns_count = dhcp_get_option_byte(&option_ptr[1]);
|
||||
/* limit to at most DHCP_MAX_DNS DNS servers */
|
||||
if (dhcp->dns_count > DHCP_MAX_DNS) dhcp->dns_count = DHCP_MAX_DNS;
|
||||
for (n = 0; n < dhcp->dns_count; n++)
|
||||
{
|
||||
dhcp->offered_dns_addr[n].addr = htonl(dhcp_get_option_long(&option_ptr[2+(n<<2)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -501,39 +521,43 @@ err_t dhcp_start(struct netif *netif)
|
||||
|
||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
|
||||
netif->flags &= ~NETIF_FLAG_DHCP;
|
||||
|
||||
/* no DHCP client attached yet? */
|
||||
if (dhcp == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
|
||||
dhcp = mem_malloc(sizeof(struct dhcp));
|
||||
if (dhcp == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
|
||||
netif->flags &= ~NETIF_FLAG_DHCP;
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* clear data structure */
|
||||
memset(dhcp, 0, sizeof(struct dhcp));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp"));
|
||||
dhcp->pcb = udp_new();
|
||||
if (dhcp->pcb == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
|
||||
mem_free((void *)dhcp);
|
||||
dhcp = NULL;
|
||||
netif->flags &= ~NETIF_FLAG_DHCP;
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* store this dhcp client in the netif */
|
||||
netif->dhcp = dhcp;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): created new udp pcb\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp"));
|
||||
/* already has DHCP client attached */
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
|
||||
}
|
||||
|
||||
/* clear data structure */
|
||||
memset(dhcp, 0, sizeof(struct dhcp));
|
||||
/* allocate UDP PCB */
|
||||
dhcp->pcb = udp_new();
|
||||
if (dhcp->pcb == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
|
||||
mem_free((void *)dhcp);
|
||||
netif->dhcp = dhcp = NULL;
|
||||
return ERR_MEM;
|
||||
}
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
|
||||
/* (re)start the DHCP negotiation */
|
||||
result = dhcp_discover(netif);
|
||||
if (result != ERR_OK) {
|
||||
/* free resources allocated above */
|
||||
dhcp_stop(netif);
|
||||
return ERR_MEM;
|
||||
}
|
||||
netif->flags |= NETIF_FLAG_DHCP;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -694,10 +718,11 @@ static err_t dhcp_discover(struct netif *netif)
|
||||
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
|
||||
dhcp_option_short(dhcp, 576);
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
|
||||
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
|
||||
|
||||
dhcp_option_trailer(dhcp);
|
||||
|
||||
@@ -781,6 +806,8 @@ static void dhcp_bind(struct netif *netif)
|
||||
netif_set_netmask(netif, &sn_mask);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08lx\n", gw_addr.addr));
|
||||
netif_set_gw(netif, &gw_addr);
|
||||
/* bring the interface up */
|
||||
netif_set_up(netif);
|
||||
/* netif is now bound to DHCP leased address */
|
||||
dhcp_set_state(dhcp, DHCP_BOUND);
|
||||
}
|
||||
@@ -907,8 +934,13 @@ static err_t dhcp_release(struct netif *netif)
|
||||
|
||||
/* idle DHCP client */
|
||||
dhcp_set_state(dhcp, DHCP_OFF);
|
||||
|
||||
|
||||
/* clean old DHCP offer */
|
||||
dhcp->server_ip_addr.addr = 0;
|
||||
dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0;
|
||||
dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0;
|
||||
dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
|
||||
dhcp->dns_count = 0;
|
||||
|
||||
/* create and initialize the DHCP message header */
|
||||
result = dhcp_create_request(netif);
|
||||
if (result == ERR_OK) {
|
||||
@@ -930,11 +962,14 @@ static err_t dhcp_release(struct netif *netif)
|
||||
dhcp->tries++;
|
||||
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs));
|
||||
/* bring the interface down */
|
||||
netif_set_down(netif);
|
||||
/* remove IP address from interface */
|
||||
netif_set_ipaddr(netif, IP_ADDR_ANY);
|
||||
netif_set_gw(netif, IP_ADDR_ANY);
|
||||
netif_set_netmask(netif, IP_ADDR_ANY);
|
||||
|
||||
/* TODO: netif_down(netif); */
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -46,10 +46,21 @@
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/inet.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
|
||||
/* This is a reference implementation of the checksum algorithm
|
||||
|
||||
- it may not work on all architectures, and all processors, particularly
|
||||
if they have issues with alignment and 16 bit access.
|
||||
|
||||
- in this case you will need to port it to your architecture and
|
||||
#define LWIP_CHKSUM <your_checksum_routine>
|
||||
in your sys_arch.h
|
||||
*/
|
||||
#ifndef LWIP_CHKSUM
|
||||
#define LWIP_CHKSUM lwip_standard_chksum
|
||||
static u16_t
|
||||
lwip_chksum(void *dataptr, int len)
|
||||
lwip_standard_chksum(void *dataptr, int len)
|
||||
{
|
||||
u32_t acc;
|
||||
|
||||
@@ -75,6 +86,7 @@ lwip_chksum(void *dataptr, int len)
|
||||
|
||||
return (u16_t)acc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* inet_chksum_pseudo:
|
||||
*
|
||||
@@ -96,7 +108,7 @@ inet_chksum_pseudo(struct pbuf *p,
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||
(void *)q, (void *)q->next));
|
||||
acc += lwip_chksum(q->payload, q->len);
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%lx \n", acc));*/
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
@@ -122,7 +134,7 @@ inet_chksum_pseudo(struct pbuf *p,
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
|
||||
return ~(acc & 0xffffUL);
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/* inet_chksum:
|
||||
@@ -136,11 +148,11 @@ inet_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc;
|
||||
|
||||
acc = lwip_chksum(dataptr, len);
|
||||
acc = LWIP_CHKSUM(dataptr, len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
return ~(acc & 0xffff);
|
||||
return (u16_t)~(acc & 0xffff);
|
||||
}
|
||||
|
||||
u16_t
|
||||
@@ -153,7 +165,7 @@ inet_chksum_pbuf(struct pbuf *p)
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += lwip_chksum(q->payload, q->len);
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
@@ -166,7 +178,7 @@ inet_chksum_pbuf(struct pbuf *p)
|
||||
if (swapped) {
|
||||
acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
}
|
||||
return ~(acc & 0xffffUL);
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/* Here for now until needed in other places in lwIP */
|
||||
@@ -232,12 +244,12 @@ inet_chksum_pbuf(struct pbuf *p)
|
||||
base = 8;
|
||||
}
|
||||
for (;;) {
|
||||
if (isascii(c) && isdigit(c)) {
|
||||
val = (val * base) + (c - '0');
|
||||
if (isdigit(c)) {
|
||||
val = (val * base) + (int)(c - '0');
|
||||
c = *++cp;
|
||||
} else if (base == 16 && isascii(c) && isxdigit(c)) {
|
||||
} else if (base == 16 && isxdigit(c)) {
|
||||
val = (val << 4) |
|
||||
(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
(int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
@@ -302,17 +314,17 @@ inet_chksum_pbuf(struct pbuf *p)
|
||||
*/
|
||||
char *inet_ntoa(struct in_addr addr)
|
||||
{
|
||||
static u8_t str[16];
|
||||
static char str[16];
|
||||
u32_t s_addr = addr.s_addr;
|
||||
u8_t inv[3];
|
||||
u8_t *rp;
|
||||
char inv[3];
|
||||
char *rp;
|
||||
u8_t *ap;
|
||||
u8_t rem;
|
||||
u8_t n;
|
||||
u8_t i;
|
||||
|
||||
rp = str;
|
||||
ap = (char *)&s_addr;
|
||||
ap = (u8_t *)&s_addr;
|
||||
for(n = 0; n < 4; n++) {
|
||||
i = 0;
|
||||
do {
|
||||
|
||||
@@ -101,7 +101,7 @@ ip_route(struct ip_addr *dest)
|
||||
* checksum and outputs the packet on the appropriate interface.
|
||||
*/
|
||||
|
||||
static void
|
||||
static struct netif *
|
||||
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
{
|
||||
struct netif *netif;
|
||||
@@ -113,14 +113,14 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n",
|
||||
iphdr->dest.addr));
|
||||
snmp_inc_ipnoroutes();
|
||||
return;
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
/* Do not forward packets onto the same network interface on which
|
||||
* they arrived. */
|
||||
if (netif == inp) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
|
||||
snmp_inc_ipnoroutes();
|
||||
return;
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
|
||||
/* decrement TTL */
|
||||
@@ -132,7 +132,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
icmp_time_exceeded(p, ICMP_TE_TTL);
|
||||
snmp_inc_icmpouttimeexcds();
|
||||
}
|
||||
return;
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
|
||||
/* Incrementally update the IP checksum. */
|
||||
@@ -152,6 +152,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
PERF_STOP("ip_forward");
|
||||
/* transmit pbuf on chosen interface */
|
||||
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
|
||||
return netif;
|
||||
}
|
||||
#endif /* IP_FORWARD */
|
||||
|
||||
@@ -163,13 +164,16 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
* forwarded (using ip_forward). The IP checksum is always checked.
|
||||
*
|
||||
* Finally, the packet is sent to the upper layer protocol input function.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
err_t
|
||||
ip_input(struct pbuf *p, struct netif *inp) {
|
||||
static struct ip_hdr *iphdr;
|
||||
static struct netif *netif;
|
||||
static u16_t iphdrlen;
|
||||
struct ip_hdr *iphdr;
|
||||
struct netif *netif;
|
||||
u16_t iphdrlen;
|
||||
|
||||
IP_STATS_INC(ip.recv);
|
||||
snmp_inc_ipinreceives();
|
||||
@@ -220,17 +224,17 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
* but we'll do it anyway just to be sure that its done. */
|
||||
pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
|
||||
|
||||
/* is this packet for us? */
|
||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
/* match packet against an interface, i.e. is this packet for us? */
|
||||
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n",
|
||||
iphdr->dest.addr, netif->ip_addr.addr,
|
||||
iphdr->dest.addr & netif->netmask.addr,
|
||||
netif->ip_addr.addr & netif->netmask.addr,
|
||||
iphdr->dest.addr & ~(netif->netmask.addr)));
|
||||
iphdr->dest.addr, netif->ip_addr.addr,
|
||||
iphdr->dest.addr & netif->netmask.addr,
|
||||
netif->ip_addr.addr & netif->netmask.addr,
|
||||
iphdr->dest.addr & ~(netif->netmask.addr)));
|
||||
|
||||
/* interface configured? */
|
||||
if (!ip_addr_isany(&(netif->ip_addr)))
|
||||
/* interface is up and configured? */
|
||||
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
|
||||
{
|
||||
/* unicast to this interface address? */
|
||||
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
|
||||
@@ -239,17 +243,18 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) ||
|
||||
/* or restricted broadcast? */
|
||||
ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
break;
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LWIP_DHCP
|
||||
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
|
||||
* using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
|
||||
* According to RFC 1542 section 3.1.1, referred by RFC 2131). */
|
||||
* According to RFC 1542 section 3.1.1, referred by RFC 2131).
|
||||
*/
|
||||
if (netif == NULL) {
|
||||
/* remote port is DHCP server? */
|
||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
|
||||
@@ -262,7 +267,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_DHCP */
|
||||
/* packet not for us? */
|
||||
/* packet not for us? */
|
||||
if (netif == NULL) {
|
||||
/* packet not for us, route or discard */
|
||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
|
||||
@@ -295,7 +300,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
|
||||
ntohs(IPH_OFFSET(iphdr))));
|
||||
ntohs(IPH_OFFSET(iphdr))));
|
||||
IP_STATS_INC(ip.opterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipunknownprotos();
|
||||
@@ -375,8 +380,8 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos,
|
||||
u8_t proto, struct netif *netif)
|
||||
{
|
||||
static struct ip_hdr *iphdr;
|
||||
static u16_t ip_id = 0;
|
||||
struct ip_hdr *iphdr;
|
||||
u16_t ip_id = 0;
|
||||
|
||||
snmp_inc_ipoutrequests();
|
||||
|
||||
@@ -484,17 +489,17 @@ ip_debug_print(struct pbuf *p)
|
||||
IPH_PROTO(iphdr),
|
||||
ntohs(IPH_CHKSUM(iphdr))));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (src)\n",
|
||||
ntohl(iphdr->src.addr) >> 24 & 0xff,
|
||||
ntohl(iphdr->src.addr) >> 16 & 0xff,
|
||||
ntohl(iphdr->src.addr) >> 8 & 0xff,
|
||||
ntohl(iphdr->src.addr) & 0xff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | %3u | %3u | (src)\n",
|
||||
ip4_addr1(&iphdr->src),
|
||||
ip4_addr2(&iphdr->src),
|
||||
ip4_addr3(&iphdr->src),
|
||||
ip4_addr4(&iphdr->src)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (dest)\n",
|
||||
ntohl(iphdr->dest.addr) >> 24 & 0xff,
|
||||
ntohl(iphdr->dest.addr) >> 16 & 0xff,
|
||||
ntohl(iphdr->dest.addr) >> 8 & 0xff,
|
||||
ntohl(iphdr->dest.addr) & 0xff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | %3u | %3u | (dest)\n",
|
||||
ip4_addr1(&iphdr->dest),
|
||||
ip4_addr2(&iphdr->dest),
|
||||
ip4_addr3(&iphdr->dest),
|
||||
ip4_addr4(&iphdr->dest)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
}
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
@@ -243,7 +243,7 @@ ip_reass(struct pbuf *p)
|
||||
variable. */
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: memcpy from %p (%d) to %p, %d bytes\n",
|
||||
&ip_reassbuf[i], i, q->payload,
|
||||
(void *)&ip_reassbuf[i], i, q->payload,
|
||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
|
||||
memcpy(q->payload, &ip_reassbuf[i],
|
||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/opt.h"
|
||||
|
||||
@@ -68,7 +68,6 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||
{
|
||||
static int netifnum = 0;
|
||||
|
||||
|
||||
#if LWIP_DHCP
|
||||
/* netif not under DHCP control by default */
|
||||
@@ -208,10 +207,10 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
#endif
|
||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %u.%u.%u.%u\n",
|
||||
netif->name[0], netif->name[1],
|
||||
(unsigned int)(ntohl(netif->ip_addr.addr) >> 24 & 0xff),
|
||||
(unsigned int)(ntohl(netif->ip_addr.addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(netif->ip_addr.addr) >> 8 & 0xff),
|
||||
(unsigned int)(ntohl(netif->ip_addr.addr) & 0xff)));
|
||||
ip4_addr1(&netif->ip_addr),
|
||||
ip4_addr2(&netif->ip_addr),
|
||||
ip4_addr3(&netif->ip_addr),
|
||||
ip4_addr4(&netif->ip_addr)));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -219,11 +218,11 @@ netif_set_gw(struct netif *netif, struct ip_addr *gw)
|
||||
{
|
||||
ip_addr_set(&(netif->gw), gw);
|
||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %u.%u.%u.%u\n",
|
||||
netif->name[0], netif->name[1],
|
||||
(unsigned int)(ntohl(netif->gw.addr) >> 24 & 0xff),
|
||||
(unsigned int)(ntohl(netif->gw.addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(netif->gw.addr) >> 8 & 0xff),
|
||||
(unsigned int)(ntohl(netif->gw.addr) & 0xff)));
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->gw),
|
||||
ip4_addr2(&netif->gw),
|
||||
ip4_addr3(&netif->gw),
|
||||
ip4_addr4(&netif->gw)));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -231,11 +230,11 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
||||
{
|
||||
ip_addr_set(&(netif->netmask), netmask);
|
||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %u.%u.%u.%u\n",
|
||||
netif->name[0], netif->name[1],
|
||||
(unsigned int)(ntohl(netif->netmask.addr) >> 24 & 0xff),
|
||||
(unsigned int)(ntohl(netif->netmask.addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(netif->netmask.addr) >> 8 & 0xff),
|
||||
(unsigned int)(ntohl(netif->netmask.addr) & 0xff)));
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->netmask),
|
||||
ip4_addr2(&netif->netmask),
|
||||
ip4_addr3(&netif->netmask),
|
||||
ip4_addr4(&netif->netmask)));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -246,6 +245,41 @@ netif_set_default(struct netif *netif)
|
||||
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring an interface up, available for processing
|
||||
* traffic.
|
||||
*
|
||||
* @note: Enabling DHCP on a down interface will make it come
|
||||
* up once configured.
|
||||
*
|
||||
* @see dhcp_start()
|
||||
*/
|
||||
void netif_set_up(struct netif *netif)
|
||||
{
|
||||
netif->flags |= NETIF_FLAG_UP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask if an interface is up
|
||||
*/
|
||||
u8_t netif_is_up(struct netif *netif)
|
||||
{
|
||||
return (netif->flags & NETIF_FLAG_UP)?1:0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring an interface down, disabling any traffic processing.
|
||||
*
|
||||
* @note: Enabling DHCP on a down interface will make it come
|
||||
* up once configured.
|
||||
*
|
||||
* @see dhcp_start()
|
||||
*/
|
||||
void netif_set_down(struct netif *netif)
|
||||
{
|
||||
netif->flags &= ~NETIF_FLAG_UP;
|
||||
}
|
||||
|
||||
void
|
||||
netif_init(void)
|
||||
{
|
||||
|
||||
@@ -306,7 +306,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
||||
break;
|
||||
case PBUF_RAM:
|
||||
/* If pbuf is to be allocated in RAM, allocate memory for it. */
|
||||
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + length + offset));
|
||||
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + offset) + MEM_ALIGN_SIZE(length));
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -482,8 +482,8 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
||||
/* boundary check fails? */
|
||||
if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
|
||||
(u8_t *)p->payload,
|
||||
(u8_t *)p + sizeof(struct pbuf)) );\
|
||||
(void *)p->payload,
|
||||
(void *)(p + 1)));\
|
||||
/* restore old payload pointer */
|
||||
p->payload = payload;
|
||||
/* bail out unsuccesfully */
|
||||
@@ -520,7 +520,8 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
||||
*
|
||||
* For a pbuf chain, this is repeated for each pbuf in the chain,
|
||||
* up to the first pbuf which has a non-zero reference count after
|
||||
* decrementing. (This might de-allocate the whole chain.)
|
||||
* decrementing. So, when all reference counts are one, the whole
|
||||
* chain is free'd.
|
||||
*
|
||||
* @param pbuf The pbuf (chain) to be dereferenced.
|
||||
*
|
||||
@@ -586,7 +587,7 @@ pbuf_free(struct pbuf *p)
|
||||
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
|
||||
p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
|
||||
PBUF_POOL_FREE(p);
|
||||
/* a ROM or RAM referencing pbuf */
|
||||
/* is this a ROM or RAM referencing pbuf? */
|
||||
} else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
|
||||
memp_free(MEMP_PBUF, p);
|
||||
/* p->flags == PBUF_FLAG_RAM */
|
||||
@@ -600,7 +601,7 @@ pbuf_free(struct pbuf *p)
|
||||
/* (and so the remaining pbufs in chain as well) */
|
||||
} else {
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref));
|
||||
/* stop walking through chain */
|
||||
/* stop walking through the chain */
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
@@ -739,9 +740,10 @@ pbuf_queue(struct pbuf *p, struct pbuf *n)
|
||||
p = p->next;
|
||||
/* { p->tot_len == p->len => p is last pbuf of a packet } */
|
||||
}
|
||||
#endif
|
||||
/* { p->tot_len == p->len and p is last pbuf of a packet } */
|
||||
/* { p is last pbuf of a packet } */
|
||||
/* proceed to next packet on queue */
|
||||
#endif
|
||||
/* proceed to next pbuf */
|
||||
if (p->next != NULL) p = p->next;
|
||||
}
|
||||
/* { p->tot_len == p->len and p->next == NULL } ==>
|
||||
@@ -750,15 +752,19 @@ pbuf_queue(struct pbuf *p, struct pbuf *n)
|
||||
p->next = n;
|
||||
/* n is now referenced to by the (packet p in the) queue */
|
||||
pbuf_ref(n);
|
||||
#if PBUF_DEBUG
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2,
|
||||
("pbuf_queue: newly queued packet %p sits after packet %p in queue %p\n",
|
||||
(void *)n, (void *)p, (void *)q));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a packet from the head of a queue.
|
||||
*
|
||||
* The caller MUST reference the remainder of the queue (as returned).
|
||||
* The caller MUST reference the remainder of the queue (as returned). The
|
||||
* caller MUST NOT call pbuf_ref() as it implicitly takes over the reference
|
||||
* from p.
|
||||
*
|
||||
* @param p pointer to first packet on the queue which will be dequeued.
|
||||
* @return first packet on the remaining queue (NULL if no further packets).
|
||||
@@ -770,7 +776,7 @@ pbuf_dequeue(struct pbuf *p)
|
||||
struct pbuf *q;
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
|
||||
/* iterate through all pbufs in packet */
|
||||
/* iterate through all pbufs in packet p */
|
||||
while (p->tot_len != p->len) {
|
||||
/* make sure invariant condition holds */
|
||||
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
|
||||
@@ -779,15 +785,16 @@ pbuf_dequeue(struct pbuf *p)
|
||||
p = p->next;
|
||||
}
|
||||
/* { p->tot_len == p->len } => p is the last pbuf of the first packet */
|
||||
/* remember next packet on queue */
|
||||
/* remember next packet on queue in q */
|
||||
q = p->next;
|
||||
/* dequeue p from queue */
|
||||
p->next = NULL;
|
||||
/* any next packet on queue? */
|
||||
if (q != NULL) {
|
||||
/* although q is no longer referenced by p, it MUST be referenced by
|
||||
* the caller, who is maintaining this packet queue */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: at least one packet on queue, first %p\n", (void *)q));
|
||||
* the caller, who is maintaining this packet queue. So, we do not call
|
||||
* pbuf_free(q) here, resulting in an implicit pbuf_ref(q) for the caller. */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: first remaining packet on queue is %p\n", (void *)q));
|
||||
} else {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: no further packets on queue\n"));
|
||||
}
|
||||
@@ -808,7 +815,7 @@ pbuf_dequeue(struct pbuf *p)
|
||||
*
|
||||
* @note You MUST explicitly use p = pbuf_take(p);
|
||||
* The pbuf you give as argument, may have been replaced
|
||||
* by pbuf_take()!
|
||||
* by a (differently located) copy through pbuf_take()!
|
||||
*
|
||||
* @note Any replaced pbufs will be freed through pbuf_free().
|
||||
* This may deallocate them if they become no longer referenced.
|
||||
@@ -836,7 +843,9 @@ pbuf_take(struct pbuf *p)
|
||||
/* PBUF_POOL buffers are faster if we can use them */
|
||||
if (p->len <= PBUF_POOL_BUFSIZE) {
|
||||
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
|
||||
if (q == NULL) LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
|
||||
}
|
||||
} else {
|
||||
/* no replacement pbuf yet */
|
||||
q = NULL;
|
||||
@@ -845,7 +854,9 @@ pbuf_take(struct pbuf *p)
|
||||
/* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
|
||||
if (q == NULL) {
|
||||
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
|
||||
if (q == NULL) LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
|
||||
}
|
||||
}
|
||||
/* replacement pbuf could be allocated? */
|
||||
if (q != NULL)
|
||||
@@ -928,8 +939,10 @@ pbuf_dechain(struct pbuf *p)
|
||||
/* q is no longer referenced by p, free it */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
|
||||
tail_gone = pbuf_free(q);
|
||||
if (tail_gone > 0) LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
|
||||
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
|
||||
if (tail_gone > 0) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
|
||||
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
|
||||
}
|
||||
/* return remaining tail or NULL if deallocated */
|
||||
}
|
||||
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
@@ -120,6 +122,18 @@ tcp_close(struct tcp_pcb *pcb)
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||
#endif /* TCP_DEBUG */
|
||||
switch (pcb->state) {
|
||||
case CLOSED:
|
||||
/* Closing a pcb in the CLOSED state might seem erroneous,
|
||||
* however, it is in this state once allocated and as yet unused
|
||||
* and the user needs some way to free it should the need arise.
|
||||
* Calling tcp_close() with a pcb that has already been closed, (i.e. twice)
|
||||
* or for a pcb that has been used and then entered the CLOSED state
|
||||
* is erroneous, but this should never happen as the pcb has in those cases
|
||||
* been freed, and so any remaining handles are bogus. */
|
||||
err = ERR_OK;
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
pcb = NULL;
|
||||
break;
|
||||
case LISTEN:
|
||||
err = ERR_OK;
|
||||
tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb);
|
||||
@@ -430,6 +444,16 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
||||
* continue to transmit.
|
||||
*/
|
||||
tcp_ack(pcb);
|
||||
}
|
||||
else if (pcb->flags & TF_ACK_DELAY && pcb->rcv_wnd >= TCP_WND/2) {
|
||||
/* If we can send a window update such that there is a full
|
||||
* segment available in the window, do so now. This is sort of
|
||||
* nagle-like in its goals, and tries to hit a compromise between
|
||||
* sending acks each time the window is updated, and only sending
|
||||
* window updates when a timer expires. The "threshold" used
|
||||
* above (currently TCP_WND/2) can be tuned to be more or less
|
||||
* aggressive */
|
||||
tcp_ack_now(pcb);
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n",
|
||||
@@ -545,7 +569,9 @@ tcp_slowtmr(void)
|
||||
/* Steps through all of the active PCBs. */
|
||||
prev = NULL;
|
||||
pcb = tcp_active_pcbs;
|
||||
if (pcb == NULL) LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
|
||||
if (pcb == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
|
||||
}
|
||||
while (pcb != NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
|
||||
LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);
|
||||
@@ -574,7 +600,6 @@ tcp_slowtmr(void)
|
||||
if (pcb->state != SYN_SENT) {
|
||||
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
|
||||
}
|
||||
tcp_rexmit(pcb);
|
||||
/* Reduce congestion window and ssthresh. */
|
||||
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
|
||||
pcb->ssthresh = eff_wnd >> 1;
|
||||
@@ -584,7 +609,10 @@ tcp_slowtmr(void)
|
||||
pcb->cwnd = pcb->mss;
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n",
|
||||
pcb->cwnd, pcb->ssthresh));
|
||||
}
|
||||
|
||||
/* The following needs to be called AFTER cwnd is set to one mss - STJ */
|
||||
tcp_rexmit_rto(pcb);
|
||||
}
|
||||
}
|
||||
/* Check if this PCB has stayed too long in FIN-WAIT-2 */
|
||||
if (pcb->state == FIN_WAIT_2) {
|
||||
|
||||
@@ -351,7 +351,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
increase the reference counter in the pbuf. If so, the buffer
|
||||
isn't actually deallocated by the call to pbuf_free(), only the
|
||||
reference count is decreased. */
|
||||
pbuf_free(inseg.p);
|
||||
if (inseg.p != NULL) pbuf_free(inseg.p);
|
||||
#if TCP_INPUT_DEBUG
|
||||
#if TCP_DEBUG
|
||||
tcp_debug_print_state(pcb->state);
|
||||
@@ -506,9 +506,11 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
acceptable = 1;
|
||||
}
|
||||
} else {
|
||||
if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
|
||||
TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
|
||||
acceptable = 1;
|
||||
/*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
|
||||
TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
|
||||
*/
|
||||
if(TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)){
|
||||
acceptable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,8 +564,9 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
case SYN_RCVD:
|
||||
if (flags & TCP_ACK &&
|
||||
!(flags & TCP_RST)) {
|
||||
if (TCP_SEQ_LT(pcb->lastack, ackno) &&
|
||||
TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) {
|
||||
/*if (TCP_SEQ_LT(pcb->lastack, ackno) &&
|
||||
TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) { */
|
||||
if(TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
|
||||
pcb->state = ESTABLISHED;
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
#if LWIP_CALLBACK_API
|
||||
@@ -672,6 +675,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
s32_t off;
|
||||
int m;
|
||||
u32_t right_wnd_edge;
|
||||
u16_t new_tot_len;
|
||||
|
||||
|
||||
if (flags & TCP_ACK) {
|
||||
@@ -699,43 +703,50 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
pcb->acked = 0;
|
||||
|
||||
if (pcb->snd_wl1 + pcb->snd_wnd == right_wnd_edge){
|
||||
++pcb->dupacks;
|
||||
if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
|
||||
if (!(pcb->flags & TF_INFR)) {
|
||||
/* This is fast retransmit. Retransmit the first unacked segment. */
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %u (%lu), fast retransmit %lu\n",
|
||||
(unsigned int)pcb->dupacks, pcb->lastack,
|
||||
ntohl(pcb->unacked->tcphdr->seqno)));
|
||||
tcp_rexmit(pcb);
|
||||
/* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
|
||||
pcb->ssthresh = LWIP_MAX((pcb->snd_max -
|
||||
pcb->lastack) / 2,
|
||||
2 * pcb->mss);
|
||||
++pcb->dupacks;
|
||||
if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
|
||||
if (!(pcb->flags & TF_INFR)) {
|
||||
/* This is fast retransmit. Retransmit the first unacked segment. */
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %u (%lu), fast retransmit %lu\n",
|
||||
(unsigned int)pcb->dupacks, pcb->lastack,
|
||||
ntohl(pcb->unacked->tcphdr->seqno)));
|
||||
tcp_rexmit(pcb);
|
||||
/* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
|
||||
/*pcb->ssthresh = LWIP_MAX((pcb->snd_max -
|
||||
pcb->lastack) / 2,
|
||||
2 * pcb->mss);*/
|
||||
/* Set ssthresh to half of the minimum of the currenct cwnd and the advertised window */
|
||||
if(pcb->cwnd > pcb->snd_wnd)
|
||||
pcb->ssthresh = pcb->snd_wnd / 2;
|
||||
else
|
||||
pcb->ssthresh = pcb->cwnd / 2;
|
||||
|
||||
pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
|
||||
pcb->flags |= TF_INFR;
|
||||
} else {
|
||||
/* Inflate the congestion window, but not if it means that
|
||||
the value overflows. */
|
||||
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
|
||||
pcb->cwnd += pcb->mss;
|
||||
}
|
||||
}
|
||||
}
|
||||
pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
|
||||
pcb->flags |= TF_INFR;
|
||||
} else {
|
||||
/* Inflate the congestion window, but not if it means that
|
||||
the value overflows. */
|
||||
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
|
||||
pcb->cwnd += pcb->mss;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n",
|
||||
pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n",
|
||||
pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
|
||||
}
|
||||
} else if (TCP_SEQ_LT(pcb->lastack, ackno) &&
|
||||
TCP_SEQ_LEQ(ackno, pcb->snd_max)) {
|
||||
} else
|
||||
/*if (TCP_SEQ_LT(pcb->lastack, ackno) &&
|
||||
TCP_SEQ_LEQ(ackno, pcb->snd_max)) { */
|
||||
if(TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){
|
||||
/* We come here when the ACK acknowledges new data. */
|
||||
|
||||
|
||||
/* Reset the "IN Fast Retransmit" flag, since we are no longer
|
||||
in fast retransmit. Also reset the congestion window to the
|
||||
slow start threshold. */
|
||||
if (pcb->flags & TF_INFR) {
|
||||
pcb->flags &= ~TF_INFR;
|
||||
pcb->cwnd = pcb->ssthresh;
|
||||
pcb->flags &= ~TF_INFR;
|
||||
pcb->cwnd = pcb->ssthresh;
|
||||
}
|
||||
|
||||
/* Reset the number of retransmissions. */
|
||||
@@ -756,86 +767,85 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
ssthresh). */
|
||||
if (pcb->state >= ESTABLISHED) {
|
||||
if (pcb->cwnd < pcb->ssthresh) {
|
||||
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
|
||||
pcb->cwnd += pcb->mss;
|
||||
}
|
||||
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
|
||||
pcb->cwnd += pcb->mss;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %u\n", pcb->cwnd));
|
||||
} else {
|
||||
u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
|
||||
if (new_cwnd > pcb->cwnd) {
|
||||
pcb->cwnd = new_cwnd;
|
||||
}
|
||||
u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
|
||||
if (new_cwnd > pcb->cwnd) {
|
||||
pcb->cwnd = new_cwnd;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %u\n", pcb->cwnd));
|
||||
}
|
||||
}
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %lu, unacked->seqno %lu:%lu\n",
|
||||
ackno,
|
||||
pcb->unacked != NULL?
|
||||
ntohl(pcb->unacked->tcphdr->seqno): 0,
|
||||
pcb->unacked != NULL?
|
||||
ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
|
||||
ackno,
|
||||
pcb->unacked != NULL?
|
||||
ntohl(pcb->unacked->tcphdr->seqno): 0,
|
||||
pcb->unacked != NULL?
|
||||
ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
|
||||
|
||||
/* Remove segment from the unacknowledged list if the incoming
|
||||
ACK acknowlegdes them. */
|
||||
ACK acknowlegdes them. */
|
||||
while (pcb->unacked != NULL &&
|
||||
TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unacked), ackno)) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",
|
||||
ntohl(pcb->unacked->tcphdr->seqno),
|
||||
ntohl(pcb->unacked->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unacked)));
|
||||
TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unacked), ackno)) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",
|
||||
ntohl(pcb->unacked->tcphdr->seqno),
|
||||
ntohl(pcb->unacked->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unacked)));
|
||||
|
||||
next = pcb->unacked;
|
||||
pcb->unacked = pcb->unacked->next;
|
||||
next = pcb->unacked;
|
||||
pcb->unacked = pcb->unacked->next;
|
||||
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
|
||||
pcb->snd_queuelen -= pbuf_clen(next->p);
|
||||
tcp_seg_free(next);
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
|
||||
pcb->snd_queuelen -= pbuf_clen(next->p);
|
||||
tcp_seg_free(next);
|
||||
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unacked)\n", (unsigned int)pcb->snd_queuelen));
|
||||
if (pcb->snd_queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
|
||||
pcb->unsent != NULL);
|
||||
}
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unacked)\n", (unsigned int)pcb->snd_queuelen));
|
||||
if (pcb->snd_queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
|
||||
pcb->unsent != NULL);
|
||||
}
|
||||
}
|
||||
pcb->polltmr = 0;
|
||||
}
|
||||
|
||||
/* We go through the ->unsent list to see if any of the segments
|
||||
on the list are acknowledged by the ACK. This may seem
|
||||
strange since an "unsent" segment shouldn't be acked. The
|
||||
rationale is that lwIP puts all outstanding segments on the
|
||||
->unsent list after a retransmission, so these segments may
|
||||
in fact have been sent once. */
|
||||
while (pcb->unsent != NULL &&
|
||||
TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent),
|
||||
ackno) &&
|
||||
TCP_SEQ_LEQ(ackno, pcb->snd_max)) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unsent\n",
|
||||
ntohl(pcb->unsent->tcphdr->seqno),
|
||||
ntohl(pcb->unsent->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unsent)));
|
||||
/* We go through the ->unsent list to see if any of the segments
|
||||
on the list are acknowledged by the ACK. This may seem
|
||||
strange since an "unsent" segment shouldn't be acked. The
|
||||
rationale is that lwIP puts all outstanding segments on the
|
||||
->unsent list after a retransmission, so these segments may
|
||||
in fact have been sent once. */
|
||||
while (pcb->unsent != NULL &&
|
||||
/*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) &&
|
||||
TCP_SEQ_LEQ(ackno, pcb->snd_max)*/
|
||||
TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max)
|
||||
) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unsent\n",
|
||||
ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unsent)));
|
||||
|
||||
next = pcb->unsent;
|
||||
pcb->unsent = pcb->unsent->next;
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
|
||||
pcb->snd_queuelen -= pbuf_clen(next->p);
|
||||
tcp_seg_free(next);
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unsent)\n", (unsigned int)pcb->snd_queuelen));
|
||||
if (pcb->snd_queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
|
||||
pcb->unsent != NULL);
|
||||
}
|
||||
|
||||
if (pcb->unsent != NULL) {
|
||||
pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
|
||||
}
|
||||
next = pcb->unsent;
|
||||
pcb->unsent = pcb->unsent->next;
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
|
||||
pcb->snd_queuelen -= pbuf_clen(next->p);
|
||||
tcp_seg_free(next);
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unsent)\n", (unsigned int)pcb->snd_queuelen));
|
||||
if (pcb->snd_queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_receive: valid queue length",
|
||||
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||
}
|
||||
|
||||
if (pcb->unsent != NULL) {
|
||||
pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
|
||||
}
|
||||
}
|
||||
/* End of ACK for new data processing. */
|
||||
|
||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %u rtseq %lu ackno %lu\n",
|
||||
pcb->rttest, pcb->rtseq, ackno));
|
||||
pcb->rttest, pcb->rtseq, ackno));
|
||||
|
||||
/* RTT estimation calculations. This is done by checking if the
|
||||
incoming segment acknowledges the segment we use to take a
|
||||
@@ -844,20 +854,20 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
m = tcp_ticks - pcb->rttest;
|
||||
|
||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %u ticks (%u msec).\n",
|
||||
m, m * TCP_SLOW_INTERVAL));
|
||||
m, m * TCP_SLOW_INTERVAL));
|
||||
|
||||
/* This is taken directly from VJs original code in his paper */
|
||||
m = m - (pcb->sa >> 3);
|
||||
pcb->sa += m;
|
||||
if (m < 0) {
|
||||
m = -m;
|
||||
m = -m;
|
||||
}
|
||||
m = m - (pcb->sv >> 2);
|
||||
pcb->sv += m;
|
||||
pcb->rto = (pcb->sa >> 3) + pcb->sv;
|
||||
|
||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %u (%u miliseconds)\n",
|
||||
pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
|
||||
pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
|
||||
|
||||
pcb->rttest = 0;
|
||||
}
|
||||
@@ -868,290 +878,309 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
if (tcplen > 0) {
|
||||
/* This code basically does three things:
|
||||
|
||||
+) If the incoming segment contains data that is the next
|
||||
in-sequence data, this data is passed to the application. This
|
||||
might involve trimming the first edge of the data. The rcv_nxt
|
||||
variable and the advertised window are adjusted.
|
||||
+) If the incoming segment contains data that is the next
|
||||
in-sequence data, this data is passed to the application. This
|
||||
might involve trimming the first edge of the data. The rcv_nxt
|
||||
variable and the advertised window are adjusted.
|
||||
|
||||
+) If the incoming segment has data that is above the next
|
||||
sequence number expected (->rcv_nxt), the segment is placed on
|
||||
the ->ooseq queue. This is done by finding the appropriate
|
||||
place in the ->ooseq queue (which is ordered by sequence
|
||||
number) and trim the segment in both ends if needed. An
|
||||
immediate ACK is sent to indicate that we received an
|
||||
out-of-sequence segment.
|
||||
+) If the incoming segment has data that is above the next
|
||||
sequence number expected (->rcv_nxt), the segment is placed on
|
||||
the ->ooseq queue. This is done by finding the appropriate
|
||||
place in the ->ooseq queue (which is ordered by sequence
|
||||
number) and trim the segment in both ends if needed. An
|
||||
immediate ACK is sent to indicate that we received an
|
||||
out-of-sequence segment.
|
||||
|
||||
+) Finally, we check if the first segment on the ->ooseq queue
|
||||
now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
|
||||
rcv_nxt > ooseq->seqno, we must trim the first edge of the
|
||||
segment on ->ooseq before we adjust rcv_nxt. The data in the
|
||||
segments that are now on sequence are chained onto the
|
||||
incoming segment so that we only need to call the application
|
||||
once.
|
||||
+) Finally, we check if the first segment on the ->ooseq queue
|
||||
now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
|
||||
rcv_nxt > ooseq->seqno, we must trim the first edge of the
|
||||
segment on ->ooseq before we adjust rcv_nxt. The data in the
|
||||
segments that are now on sequence are chained onto the
|
||||
incoming segment so that we only need to call the application
|
||||
once.
|
||||
*/
|
||||
|
||||
/* First, we check if we must trim the first edge. We have to do
|
||||
this if the sequence number of the incoming segment is less
|
||||
than rcv_nxt, and the sequence number plus the length of the
|
||||
segment is larger than rcv_nxt. */
|
||||
if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
|
||||
if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {
|
||||
/* Trimming the first edge is done by pushing the payload
|
||||
pointer in the pbuf downwards. This is somewhat tricky since
|
||||
we do not want to discard the full contents of the pbuf up to
|
||||
the new starting point of the data since we have to keep the
|
||||
TCP header which is present in the first pbuf in the chain.
|
||||
|
||||
What is done is really quite a nasty hack: the first pbuf in
|
||||
the pbuf chain is pointed to by inseg.p. Since we need to be
|
||||
able to deallocate the whole pbuf, we cannot change this
|
||||
inseg.p pointer to point to any of the later pbufs in the
|
||||
chain. Instead, we point the ->payload pointer in the first
|
||||
pbuf to data in one of the later pbufs. We also set the
|
||||
inseg.data pointer to point to the right place. This way, the
|
||||
->p pointer will still point to the first pbuf, but the
|
||||
->p->payload pointer will point to data in another pbuf.
|
||||
|
||||
After we are done with adjusting the pbuf pointers we must
|
||||
adjust the ->data pointer in the seg and the segment
|
||||
length.*/
|
||||
off = pcb->rcv_nxt - seqno;
|
||||
if (inseg.p->len < off) {
|
||||
p = inseg.p;
|
||||
while (p->len < off) {
|
||||
off -= p->len;
|
||||
inseg.p->tot_len -= p->len;
|
||||
p->len = 0;
|
||||
p = p->next;
|
||||
}
|
||||
pbuf_header(p, -off);
|
||||
} else {
|
||||
pbuf_header(inseg.p, -off);
|
||||
}
|
||||
inseg.dataptr = inseg.p->payload;
|
||||
inseg.len -= pcb->rcv_nxt - seqno;
|
||||
inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
|
||||
/* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
|
||||
if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
|
||||
if(TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno+1, seqno+tcplen-1)){
|
||||
/* Trimming the first edge is done by pushing the payload
|
||||
pointer in the pbuf downwards. This is somewhat tricky since
|
||||
we do not want to discard the full contents of the pbuf up to
|
||||
the new starting point of the data since we have to keep the
|
||||
TCP header which is present in the first pbuf in the chain.
|
||||
|
||||
What is done is really quite a nasty hack: the first pbuf in
|
||||
the pbuf chain is pointed to by inseg.p. Since we need to be
|
||||
able to deallocate the whole pbuf, we cannot change this
|
||||
inseg.p pointer to point to any of the later pbufs in the
|
||||
chain. Instead, we point the ->payload pointer in the first
|
||||
pbuf to data in one of the later pbufs. We also set the
|
||||
inseg.data pointer to point to the right place. This way, the
|
||||
->p pointer will still point to the first pbuf, but the
|
||||
->p->payload pointer will point to data in another pbuf.
|
||||
|
||||
After we are done with adjusting the pbuf pointers we must
|
||||
adjust the ->data pointer in the seg and the segment
|
||||
length.*/
|
||||
|
||||
off = pcb->rcv_nxt - seqno;
|
||||
p = inseg.p;
|
||||
if (inseg.p->len < off) {
|
||||
new_tot_len = inseg.p->tot_len - off;
|
||||
while (p->len < off) {
|
||||
off -= p->len;
|
||||
/* KJM following line changed (with addition of new_tot_len var)
|
||||
to fix bug #9076
|
||||
inseg.p->tot_len -= p->len; */
|
||||
p->tot_len = new_tot_len;
|
||||
p->len = 0;
|
||||
p = p->next;
|
||||
}
|
||||
pbuf_header(p, -off);
|
||||
} else {
|
||||
pbuf_header(inseg.p, -off);
|
||||
}
|
||||
else{
|
||||
/* the whole segment is < rcv_nxt */
|
||||
/* must be a duplicate of a packet that has already been correctly handled */
|
||||
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));
|
||||
tcp_ack_now(pcb);
|
||||
/* KJM following line changed to use p->payload rather than inseg->p->payload
|
||||
to fix bug #9076 */
|
||||
inseg.dataptr = p->payload;
|
||||
inseg.len -= pcb->rcv_nxt - seqno;
|
||||
inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
|
||||
}
|
||||
else{
|
||||
if(TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
|
||||
/* the whole segment is < rcv_nxt */
|
||||
/* must be a duplicate of a packet that has already been correctly handled */
|
||||
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));
|
||||
tcp_ack_now(pcb);
|
||||
}
|
||||
}
|
||||
|
||||
/* The sequence number must be within the window (above rcv_nxt
|
||||
and below rcv_nxt + rcv_wnd) in order to be further
|
||||
processed. */
|
||||
if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
|
||||
TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
|
||||
/*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
|
||||
TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
|
||||
if(TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)){
|
||||
if (pcb->rcv_nxt == seqno) {
|
||||
/* The incoming segment is the next in sequence. We check if
|
||||
/* The incoming segment is the next in sequence. We check if
|
||||
we have to trim the end of the segment and update rcv_nxt
|
||||
and pass the data to the application. */
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
if (pcb->ooseq != NULL &&
|
||||
TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) {
|
||||
/* We have to trim the second edge of the incoming
|
||||
if (pcb->ooseq != NULL &&
|
||||
TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) {
|
||||
/* We have to trim the second edge of the incoming
|
||||
segment. */
|
||||
inseg.len = pcb->ooseq->tcphdr->seqno - seqno;
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
}
|
||||
inseg.len = pcb->ooseq->tcphdr->seqno - seqno;
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
}
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
|
||||
pcb->rcv_nxt += tcplen;
|
||||
pcb->rcv_nxt += tcplen;
|
||||
|
||||
/* Update the receiver's (our) window. */
|
||||
if (pcb->rcv_wnd < tcplen) {
|
||||
pcb->rcv_wnd = 0;
|
||||
} else {
|
||||
pcb->rcv_wnd -= tcplen;
|
||||
}
|
||||
/* Update the receiver's (our) window. */
|
||||
if (pcb->rcv_wnd < tcplen) {
|
||||
pcb->rcv_wnd = 0;
|
||||
} else {
|
||||
pcb->rcv_wnd -= tcplen;
|
||||
}
|
||||
|
||||
/* If there is data in the segment, we make preparations to
|
||||
pass this up to the application. The ->recv_data variable
|
||||
is used for holding the pbuf that goes to the
|
||||
application. The code for reassembling out-of-sequence data
|
||||
chains its data on this pbuf as well.
|
||||
/* If there is data in the segment, we make preparations to
|
||||
pass this up to the application. The ->recv_data variable
|
||||
is used for holding the pbuf that goes to the
|
||||
application. The code for reassembling out-of-sequence data
|
||||
chains its data on this pbuf as well.
|
||||
|
||||
If the segment was a FIN, we set the TF_GOT_FIN flag that will
|
||||
be used to indicate to the application that the remote side has
|
||||
closed its end of the connection. */
|
||||
if (inseg.p->tot_len > 0) {
|
||||
recv_data = inseg.p;
|
||||
/* Since this pbuf now is the responsibility of the
|
||||
application, we delete our reference to it so that we won't
|
||||
(mistakingly) deallocate it. */
|
||||
inseg.p = NULL;
|
||||
}
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
|
||||
recv_flags = TF_GOT_FIN;
|
||||
}
|
||||
If the segment was a FIN, we set the TF_GOT_FIN flag that will
|
||||
be used to indicate to the application that the remote side has
|
||||
closed its end of the connection. */
|
||||
if (inseg.p->tot_len > 0) {
|
||||
recv_data = inseg.p;
|
||||
/* Since this pbuf now is the responsibility of the
|
||||
application, we delete our reference to it so that we won't
|
||||
(mistakingly) deallocate it. */
|
||||
inseg.p = NULL;
|
||||
}
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
|
||||
recv_flags = TF_GOT_FIN;
|
||||
}
|
||||
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
/* We now check if we have segments on the ->ooseq queue that
|
||||
/* We now check if we have segments on the ->ooseq queue that
|
||||
is now in sequence. */
|
||||
while (pcb->ooseq != NULL &&
|
||||
pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
|
||||
while (pcb->ooseq != NULL &&
|
||||
pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
|
||||
|
||||
cseg = pcb->ooseq;
|
||||
seqno = pcb->ooseq->tcphdr->seqno;
|
||||
cseg = pcb->ooseq;
|
||||
seqno = pcb->ooseq->tcphdr->seqno;
|
||||
|
||||
pcb->rcv_nxt += TCP_TCPLEN(cseg);
|
||||
if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
|
||||
pcb->rcv_wnd = 0;
|
||||
} else {
|
||||
pcb->rcv_wnd -= TCP_TCPLEN(cseg);
|
||||
}
|
||||
if (cseg->p->tot_len > 0) {
|
||||
/* Chain this pbuf onto the pbuf that we will pass to
|
||||
the application. */
|
||||
if (recv_data) {
|
||||
pcb->rcv_nxt += TCP_TCPLEN(cseg);
|
||||
if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
|
||||
pcb->rcv_wnd = 0;
|
||||
} else {
|
||||
pcb->rcv_wnd -= TCP_TCPLEN(cseg);
|
||||
}
|
||||
if (cseg->p->tot_len > 0) {
|
||||
/* Chain this pbuf onto the pbuf that we will pass to
|
||||
the application. */
|
||||
if (recv_data) {
|
||||
pbuf_cat(recv_data, cseg->p);
|
||||
} else {
|
||||
recv_data = cseg->p;
|
||||
}
|
||||
cseg->p = NULL;
|
||||
}
|
||||
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
|
||||
recv_flags = TF_GOT_FIN;
|
||||
}
|
||||
recv_data = cseg->p;
|
||||
}
|
||||
cseg->p = NULL;
|
||||
}
|
||||
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
|
||||
recv_flags = TF_GOT_FIN;
|
||||
}
|
||||
|
||||
|
||||
pcb->ooseq = cseg->next;
|
||||
tcp_seg_free(cseg);
|
||||
}
|
||||
pcb->ooseq = cseg->next;
|
||||
tcp_seg_free(cseg);
|
||||
}
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
|
||||
/* Acknowledge the segment(s). */
|
||||
tcp_ack(pcb);
|
||||
/* Acknowledge the segment(s). */
|
||||
tcp_ack(pcb);
|
||||
|
||||
} else {
|
||||
/* We get here if the incoming segment is out-of-sequence. */
|
||||
tcp_ack_now(pcb);
|
||||
/* We get here if the incoming segment is out-of-sequence. */
|
||||
tcp_ack_now(pcb);
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
/* We queue the segment on the ->ooseq queue. */
|
||||
if (pcb->ooseq == NULL) {
|
||||
pcb->ooseq = tcp_seg_copy(&inseg);
|
||||
} else {
|
||||
/* If the queue is not empty, we walk through the queue and
|
||||
try to find a place where the sequence number of the
|
||||
incoming segment is between the sequence numbers of the
|
||||
previous and the next segment on the ->ooseq queue. That is
|
||||
the place where we put the incoming segment. If needed, we
|
||||
trim the second edges of the previous and the incoming
|
||||
segment so that it will fit into the sequence.
|
||||
/* We queue the segment on the ->ooseq queue. */
|
||||
if (pcb->ooseq == NULL) {
|
||||
pcb->ooseq = tcp_seg_copy(&inseg);
|
||||
} else {
|
||||
/* If the queue is not empty, we walk through the queue and
|
||||
try to find a place where the sequence number of the
|
||||
incoming segment is between the sequence numbers of the
|
||||
previous and the next segment on the ->ooseq queue. That is
|
||||
the place where we put the incoming segment. If needed, we
|
||||
trim the second edges of the previous and the incoming
|
||||
segment so that it will fit into the sequence.
|
||||
|
||||
If the incoming segment has the same sequence number as a
|
||||
segment on the ->ooseq queue, we discard the segment that
|
||||
contains less data. */
|
||||
If the incoming segment has the same sequence number as a
|
||||
segment on the ->ooseq queue, we discard the segment that
|
||||
contains less data. */
|
||||
|
||||
prev = NULL;
|
||||
for(next = pcb->ooseq; next != NULL; next = next->next) {
|
||||
if (seqno == next->tcphdr->seqno) {
|
||||
/* The sequence number of the incoming segment is the
|
||||
prev = NULL;
|
||||
for(next = pcb->ooseq; next != NULL; next = next->next) {
|
||||
if (seqno == next->tcphdr->seqno) {
|
||||
/* The sequence number of the incoming segment is the
|
||||
same as the sequence number of the segment on
|
||||
->ooseq. We check the lengths to see which one to
|
||||
discard. */
|
||||
if (inseg.len > next->len) {
|
||||
/* The incoming segment is larger than the old
|
||||
if (inseg.len > next->len) {
|
||||
/* The incoming segment is larger than the old
|
||||
segment. We replace the old segment with the new
|
||||
one. */
|
||||
cseg = tcp_seg_copy(&inseg);
|
||||
if (cseg != NULL) {
|
||||
cseg->next = next->next;
|
||||
if (prev != NULL) {
|
||||
prev->next = cseg;
|
||||
} else {
|
||||
pcb->ooseq = cseg;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
/* Either the lenghts are the same or the incoming
|
||||
cseg = tcp_seg_copy(&inseg);
|
||||
if (cseg != NULL) {
|
||||
cseg->next = next->next;
|
||||
if (prev != NULL) {
|
||||
prev->next = cseg;
|
||||
} else {
|
||||
pcb->ooseq = cseg;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
/* Either the lenghts are the same or the incoming
|
||||
segment was smaller than the old one; in either
|
||||
case, we ditch the incoming segment. */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (prev == NULL) {
|
||||
if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
|
||||
/* The sequence number of the incoming segment is lower
|
||||
than the sequence number of the first segment on the
|
||||
queue. We put the incoming segment first on the
|
||||
queue. */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (prev == NULL) {
|
||||
if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
|
||||
/* The sequence number of the incoming segment is lower
|
||||
than the sequence number of the first segment on the
|
||||
queue. We put the incoming segment first on the
|
||||
queue. */
|
||||
|
||||
if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
|
||||
/* We need to trim the incoming segment. */
|
||||
inseg.len = next->tcphdr->seqno - seqno;
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
}
|
||||
cseg = tcp_seg_copy(&inseg);
|
||||
if (cseg != NULL) {
|
||||
cseg->next = next;
|
||||
pcb->ooseq = cseg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
|
||||
TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
|
||||
/* The sequence number of the incoming segment is in
|
||||
if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
|
||||
/* We need to trim the incoming segment. */
|
||||
inseg.len = next->tcphdr->seqno - seqno;
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
}
|
||||
cseg = tcp_seg_copy(&inseg);
|
||||
if (cseg != NULL) {
|
||||
cseg->next = next;
|
||||
pcb->ooseq = cseg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else
|
||||
/*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
|
||||
TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
|
||||
if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){
|
||||
/* The sequence number of the incoming segment is in
|
||||
between the sequence numbers of the previous and
|
||||
the next segment on ->ooseq. We trim and insert the
|
||||
incoming segment and trim the previous segment, if
|
||||
needed. */
|
||||
if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
|
||||
/* We need to trim the incoming segment. */
|
||||
inseg.len = next->tcphdr->seqno - seqno;
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
}
|
||||
if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
|
||||
/* We need to trim the incoming segment. */
|
||||
inseg.len = next->tcphdr->seqno - seqno;
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
}
|
||||
|
||||
cseg = tcp_seg_copy(&inseg);
|
||||
if (cseg != NULL) {
|
||||
cseg->next = next;
|
||||
prev->next = cseg;
|
||||
if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
|
||||
/* We need to trim the prev segment. */
|
||||
prev->len = seqno - prev->tcphdr->seqno;
|
||||
pbuf_realloc(prev->p, prev->len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* If the "next" segment is the last segment on the
|
||||
cseg = tcp_seg_copy(&inseg);
|
||||
if (cseg != NULL) {
|
||||
cseg->next = next;
|
||||
prev->next = cseg;
|
||||
if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
|
||||
/* We need to trim the prev segment. */
|
||||
prev->len = seqno - prev->tcphdr->seqno;
|
||||
pbuf_realloc(prev->p, prev->len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* If the "next" segment is the last segment on the
|
||||
ooseq queue, we add the incoming segment to the end
|
||||
of the list. */
|
||||
if (next->next == NULL &&
|
||||
TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
|
||||
next->next = tcp_seg_copy(&inseg);
|
||||
if (next->next != NULL) {
|
||||
if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
|
||||
/* We need to trim the last segment. */
|
||||
next->len = seqno - next->tcphdr->seqno;
|
||||
pbuf_realloc(next->p, next->len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (next->next == NULL &&
|
||||
TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
|
||||
next->next = tcp_seg_copy(&inseg);
|
||||
if (next->next != NULL) {
|
||||
if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
|
||||
/* We need to trim the last segment. */
|
||||
next->len = seqno - next->tcphdr->seqno;
|
||||
pbuf_realloc(next->p, next->len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
}
|
||||
} else {
|
||||
/*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
|
||||
TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
|
||||
if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
|
||||
tcp_ack_now(pcb);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Segments with length 0 is taken care of here. Segments that
|
||||
fall out of the window are ACKed. */
|
||||
if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
|
||||
TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
|
||||
/*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
|
||||
TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
|
||||
if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
|
||||
tcp_ack_now(pcb);
|
||||
}
|
||||
}
|
||||
@@ -1185,7 +1214,7 @@ tcp_parseopt(struct tcp_pcb *pcb)
|
||||
++c;
|
||||
/* NOP option. */
|
||||
} else if (opt == 0x02 &&
|
||||
opts[c + 1] == 0x04) {
|
||||
opts[c + 1] == 0x04) {
|
||||
/* An MSS option with the right option length. */
|
||||
mss = (opts[c + 2] << 8) | opts[c + 3];
|
||||
pcb->mss = mss > TCP_MSS? TCP_MSS: mss;
|
||||
|
||||
@@ -462,8 +462,16 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
pcb->unacked = seg;
|
||||
useg = seg;
|
||||
} else {
|
||||
useg->next = seg;
|
||||
useg = useg->next;
|
||||
/* In the case of fast retransmit, the packet should not go to the end
|
||||
* of the unacked queue, but rather at the start. We need to check for
|
||||
* this case. -STJ Jul 27, 2004 */
|
||||
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
|
||||
seg->next = pcb->unacked;
|
||||
pcb->unacked = seg;
|
||||
} else {
|
||||
useg->next = seg;
|
||||
useg = useg->next;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tcp_seg_free(seg);
|
||||
@@ -569,7 +577,7 @@ tcp_rst(u32_t seqno, u32_t ackno,
|
||||
}
|
||||
|
||||
void
|
||||
tcp_rexmit(struct tcp_pcb *pcb)
|
||||
tcp_rexmit_rto(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct tcp_seg *seg;
|
||||
|
||||
@@ -579,13 +587,10 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
||||
|
||||
/* Move all unacked segments to the unsent queue. */
|
||||
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
|
||||
|
||||
seg->next = pcb->unsent;
|
||||
pcb->unsent = pcb->unacked;
|
||||
|
||||
pcb->unacked = NULL;
|
||||
|
||||
|
||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||
|
||||
++pcb->nrtx;
|
||||
@@ -598,6 +603,34 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
tcp_rexmit(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct tcp_seg *seg;
|
||||
|
||||
if (pcb->unacked == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move the first unacked segment to the unsent queue */
|
||||
seg = pcb->unacked->next;
|
||||
pcb->unacked->next = pcb->unsent;
|
||||
pcb->unsent = pcb->unacked;
|
||||
pcb->unacked = seg;
|
||||
|
||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||
|
||||
++pcb->nrtx;
|
||||
|
||||
/* Don't take any rtt measurements after retransmitting. */
|
||||
pcb->rttest = 0;
|
||||
|
||||
/* Do the actual retransmission. */
|
||||
tcp_output(pcb);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tcp_keepalive(struct tcp_pcb *pcb)
|
||||
{
|
||||
@@ -608,7 +641,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %ld pcb->tmr %ld pcb->keep_cnt %ld\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %lu pcb->tmr %lu pcb->keep_cnt %u\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
|
||||
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
@@ -134,10 +136,10 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
again_1:
|
||||
|
||||
/* Iterate through the UDP pcb list for a fully matching pcb */
|
||||
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
||||
for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
||||
#else /* SO_REUSE */
|
||||
/* Iterate through the UDP pcb list for a fully matching pcb */
|
||||
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
#endif /* SO_REUSE */
|
||||
/* print the PCB local and remote address */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
|
||||
@@ -159,7 +161,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
/* PCB local IP address matches UDP destination IP address? */
|
||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
||||
#if SO_REUSE
|
||||
if(pcb->so_options & SOF_REUSEPORT) {
|
||||
if (pcb->so_options & SOF_REUSEPORT) {
|
||||
if(reuse) {
|
||||
/* We processed one PCB already */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
|
||||
@@ -173,7 +175,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
p->ref++;
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
|
||||
} else {
|
||||
if(reuse) {
|
||||
if (reuse) {
|
||||
/* We processed one PCB already */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
|
||||
}
|
||||
@@ -192,9 +194,9 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
again_2:
|
||||
|
||||
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
||||
for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
||||
#else /* SO_REUSE */
|
||||
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
#endif /* SO_REUSE */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
|
||||
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
||||
@@ -210,8 +212,8 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
/* ...matching interface address? */
|
||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
||||
#if SO_REUSE
|
||||
if(pcb->so_options & SOF_REUSEPORT) {
|
||||
if(reuse) {
|
||||
if (pcb->so_options & SOF_REUSEPORT) {
|
||||
if (reuse) {
|
||||
/* We processed one PCB already */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
|
||||
} else {
|
||||
@@ -224,7 +226,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
p->ref++;
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
|
||||
} else {
|
||||
if(reuse) {
|
||||
if (reuse) {
|
||||
/* We processed one PCB already */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ PACK_STRUCT_END
|
||||
|
||||
#define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12)
|
||||
#define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f)
|
||||
#define IPH_TOS(hdr) (htons((ntohs((hdr)->_v_hl_tos) & 0xff)))
|
||||
#define IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff)
|
||||
#define IPH_LEN(hdr) ((hdr)->_len)
|
||||
#define IPH_ID(hdr) ((hdr)->_id)
|
||||
#define IPH_OFFSET(hdr) ((hdr)->_offset)
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
/** print debug message only if debug message type is enabled...
|
||||
* AND is of correct type AND is at least DBG_LEVEL
|
||||
*/
|
||||
# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && (((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0)
|
||||
# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && ((int)((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0)
|
||||
# define LWIP_ERROR(x) do { LWIP_PLATFORM_DIAG(x); } while(0)
|
||||
#else /* LWIP_DEBUG */
|
||||
# define LWIP_DEBUGF(debug,x)
|
||||
|
||||
@@ -43,6 +43,10 @@ struct dhcp
|
||||
struct ip_addr offered_sn_mask;
|
||||
struct ip_addr offered_gw_addr;
|
||||
struct ip_addr offered_bc_addr;
|
||||
#define DHCP_MAX_DNS 2
|
||||
u32_t dns_count; /* actual number of DNS servers obtained */
|
||||
struct ip_addr offered_dns_addr[DHCP_MAX_DNS]; /* DNS server addresses */
|
||||
|
||||
u32_t offered_t0_lease; /* lease period (in seconds) */
|
||||
u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
|
||||
u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */
|
||||
@@ -174,7 +178,8 @@ void dhcp_fine_tmr(void);
|
||||
/** BootP options */
|
||||
#define DHCP_OPTION_PAD 0
|
||||
#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */
|
||||
#define DHCP_OPTION_ROUTER 3
|
||||
#define DHCP_OPTION_ROUTER 3
|
||||
#define DHCP_OPTION_DNS_SERVER 6
|
||||
#define DHCP_OPTION_HOSTNAME 12
|
||||
#define DHCP_OPTION_IP_TTL 23
|
||||
#define DHCP_OPTION_MTU 26
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
/** whether the network interface is 'up'. this is
|
||||
* a software flag used to control whether this network
|
||||
* interface is enabled and processes traffic.
|
||||
* TODO: who should act on this flag, lwIP stack or driver?? */
|
||||
*/
|
||||
#define NETIF_FLAG_UP 0x1U
|
||||
/** if set, the netif has broadcast capability */
|
||||
#define NETIF_FLAG_BROADCAST 0x2U
|
||||
@@ -105,6 +105,8 @@ struct netif {
|
||||
u16_t mtu;
|
||||
/** flags (see NETIF_FLAG_ above) */
|
||||
u8_t flags;
|
||||
/** link type */
|
||||
u8_t link_type;
|
||||
/** descriptive abbreviation */
|
||||
char name[2];
|
||||
/** number of this interface */
|
||||
@@ -141,5 +143,8 @@ void netif_set_default(struct netif *netif);
|
||||
void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr);
|
||||
void netif_set_netmask(struct netif *netif, struct ip_addr *netmast);
|
||||
void netif_set_gw(struct netif *netif, struct ip_addr *gw);
|
||||
void netif_set_up(struct netif *netif);
|
||||
void netif_set_down(struct netif *netif);
|
||||
u8_t netif_is_up(struct netif *netif);
|
||||
|
||||
#endif /* __LWIP_NETIF_H__ */
|
||||
|
||||
@@ -146,10 +146,10 @@ a lot of data that needs to be copied, this should be set high. */
|
||||
#endif
|
||||
|
||||
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
|
||||
link level header. */
|
||||
link level header. Defaults to 14 for Ethernet. */
|
||||
|
||||
#ifndef PBUF_LINK_HLEN
|
||||
#define PBUF_LINK_HLEN 0
|
||||
#define PBUF_LINK_HLEN 14
|
||||
#endif
|
||||
|
||||
|
||||
@@ -168,12 +168,10 @@ a lot of data that needs to be copied, this should be set high. */
|
||||
#ifndef ARP_QUEUEING
|
||||
#define ARP_QUEUEING 1
|
||||
#endif
|
||||
/** If enabled, the first packet queued will not be overwritten by
|
||||
* later packets. If disabled, later packets overwrite early packets
|
||||
* in the queue. Default is disabled, which is recommended.
|
||||
*/
|
||||
#ifndef ARP_QUEUE_FIRST
|
||||
#define ARP_QUEUE_FIRST 0
|
||||
|
||||
/* This option is deprecated */
|
||||
#ifdef ETHARP_QUEUE_FIRST
|
||||
#error ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h.
|
||||
#endif
|
||||
|
||||
/* This option is removed to comply with the ARP standard */
|
||||
|
||||
@@ -209,7 +209,11 @@ struct linger {
|
||||
* only define this in sockets.c so it does not interfere
|
||||
* with other projects namespaces where timeval is present
|
||||
*/
|
||||
#ifdef LWIP_TIMEVAL_PRIVATE
|
||||
#ifndef LWIP_TIMEVAL_PRIVATE
|
||||
#define LWIP_TIMEVAL_PRIVATE 1
|
||||
#endif
|
||||
|
||||
#if LWIP_TIMEVAL_PRIVATE
|
||||
struct timeval {
|
||||
long tv_sec; /* seconds */
|
||||
long tv_usec; /* and microseconds */
|
||||
|
||||
@@ -105,6 +105,7 @@ void tcp_input (struct pbuf *p, struct netif *inp);
|
||||
/* Used within the TCP code only: */
|
||||
err_t tcp_output (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
||||
|
||||
|
||||
|
||||
@@ -112,7 +113,11 @@ void tcp_rexmit (struct tcp_pcb *pcb);
|
||||
#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
|
||||
#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
|
||||
#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
|
||||
|
||||
/* is b<=a<=c? */
|
||||
#if 0 /* see bug #10548 */
|
||||
#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
|
||||
#endif
|
||||
#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
|
||||
#define TCP_FIN 0x01U
|
||||
#define TCP_SYN 0x02U
|
||||
#define TCP_RST 0x04U
|
||||
@@ -375,7 +380,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
||||
if((pcb)->recv != NULL) \
|
||||
{ ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
|
||||
pbuf_free(p); }
|
||||
if (p) pbuf_free(p); }
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
||||
if((pcb)->connected != NULL) \
|
||||
(ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
|
||||
|
||||
@@ -52,7 +52,13 @@ struct eth_addr {
|
||||
PACK_STRUCT_FIELD(u8_t addr[6]);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct eth_hdr {
|
||||
#if ETH_PAD_SIZE
|
||||
@@ -63,7 +69,13 @@ struct eth_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t type);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** the ARP message */
|
||||
struct etharp_hdr {
|
||||
@@ -78,12 +90,19 @@ struct etharp_hdr {
|
||||
PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ethip_hdr {
|
||||
PACK_STRUCT_FIELD(struct eth_hdr eth);
|
||||
PACK_STRUCT_FIELD(struct ip_hdr ip);
|
||||
};
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
@@ -101,7 +120,6 @@ void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
|
||||
err_t etharp_output(struct netif *netif, struct ip_addr *ipaddr,
|
||||
struct pbuf *q);
|
||||
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q);
|
||||
|
||||
|
||||
err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr);
|
||||
|
||||
#endif /* __NETIF_ARP_H__ */
|
||||
|
||||
@@ -55,9 +55,6 @@
|
||||
# include "lwip/dhcp.h"
|
||||
#endif
|
||||
|
||||
/* allows new queueing code to be disabled (0) for regression testing */
|
||||
#define ARP_NEW_QUEUE 1
|
||||
|
||||
/** the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. */
|
||||
#define ARP_MAXAGE 120
|
||||
/** the time an ARP entry stays pending after first request, (1 * 10) seconds = 10 seconds. */
|
||||
@@ -79,37 +76,38 @@ enum etharp_state {
|
||||
ETHARP_STATE_EMPTY,
|
||||
ETHARP_STATE_PENDING,
|
||||
ETHARP_STATE_STABLE,
|
||||
/** @internal convenience transitional state used in etharp_tmr() */
|
||||
/** @internal transitional state used in etharp_tmr() for convenience*/
|
||||
ETHARP_STATE_EXPIRED
|
||||
};
|
||||
|
||||
struct etharp_entry {
|
||||
struct ip_addr ipaddr;
|
||||
struct eth_addr ethaddr;
|
||||
enum etharp_state state;
|
||||
#if ARP_QUEUEING
|
||||
/**
|
||||
* Pointer to queue of pending outgoing packets on this ARP entry.
|
||||
* Must be at most a single packet for now. */
|
||||
struct pbuf *p;
|
||||
*/
|
||||
struct pbuf *p;
|
||||
#endif
|
||||
struct ip_addr ipaddr;
|
||||
struct eth_addr ethaddr;
|
||||
enum etharp_state state;
|
||||
u8_t ctime;
|
||||
};
|
||||
|
||||
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
|
||||
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
|
||||
|
||||
static s8_t find_arp_entry(void);
|
||||
/** ask update_arp_entry() to add instead of merely update an ARP entry */
|
||||
#define ARP_INSERT_FLAG 1
|
||||
static struct pbuf *update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
|
||||
/** ask update_arp_entry() to create new entry instead of merely update existing */
|
||||
/** ask find_entry() to create new entry instead of merely finding existing */
|
||||
#define ETHARP_CREATE 1
|
||||
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags);
|
||||
static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
|
||||
/**
|
||||
* Initializes ARP module.
|
||||
*/
|
||||
void
|
||||
etharp_init(void)
|
||||
{
|
||||
s8_t i;
|
||||
u8_t i;
|
||||
/* clear ARP entries */
|
||||
for(i = 0; i < ARP_TABLE_SIZE; ++i) {
|
||||
arp_table[i].state = ETHARP_STATE_EMPTY;
|
||||
@@ -129,24 +127,29 @@ etharp_init(void)
|
||||
void
|
||||
etharp_tmr(void)
|
||||
{
|
||||
s8_t i;
|
||||
u8_t i;
|
||||
|
||||
LWIP_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++;
|
||||
/* a resolved/stable entry? */
|
||||
/* stable entry? */
|
||||
if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
|
||||
/* entry has become old? */
|
||||
(arp_table[i].ctime >= ARP_MAXAGE)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
|
||||
arp_table[i].state = ETHARP_STATE_EXPIRED;
|
||||
/* an unresolved/pending entry? */
|
||||
} else if ((arp_table[i].state == ETHARP_STATE_PENDING) &&
|
||||
/* entry unresolved/pending for too long? */
|
||||
(arp_table[i].ctime >= ARP_MAXPENDING)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));
|
||||
arp_table[i].state = ETHARP_STATE_EXPIRED;
|
||||
/* pending entry? */
|
||||
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
/* entry unresolved/pending for too long? */
|
||||
if (arp_table[i].ctime >= ARP_MAXPENDING) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));
|
||||
arp_table[i].state = ETHARP_STATE_EXPIRED;
|
||||
#if ARP_QUEUEING
|
||||
} else if (arp_table[i].p != NULL) {
|
||||
/* resend an ARP query here */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* clean up entries that have just been expired */
|
||||
if (arp_table[i].state == ETHARP_STATE_EXPIRED) {
|
||||
@@ -166,59 +169,166 @@ etharp_tmr(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an empty ARP entry (possibly recycling the oldest stable entry).
|
||||
* Search the ARP table for a specific entry.
|
||||
*
|
||||
* If an IP address is given, return a pending or stable ARP entry that matches
|
||||
* the address. If no match is found, create a new entry with this address set,
|
||||
* but in state ETHARP_EMPTY. The caller must check and possibly change the
|
||||
* state of the returned entry.
|
||||
*
|
||||
* If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
|
||||
*
|
||||
* In all cases, attempt to create new entries from an empty entry. If no
|
||||
* empty entries are available and ETHARP_CREATE flag is set, recycle
|
||||
* old entries. Heuristic choose the least important entry for recycling.
|
||||
*
|
||||
* @return The ARP entry index that is available, ERR_MEM if no usable
|
||||
* entry is found.
|
||||
* @param ipaddr IP address to find in ARP cache, or to add if not found.
|
||||
* @param flags
|
||||
* - ETHARP_CREATE: Try hard to create a entry by allowing recycling.
|
||||
*
|
||||
* @return The ARP entry index that matched or is created, ERR_MEM if no
|
||||
* entry is found or could be recycled.
|
||||
*/
|
||||
static s8_t
|
||||
find_arp_entry(void)
|
||||
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
|
||||
{
|
||||
s8_t i, j;
|
||||
u8_t maxtime = 0;
|
||||
s8_t old_pending, old_stable, empty, i;
|
||||
u8_t age_pending, age_stable;
|
||||
#if ARP_QUEUEING
|
||||
s8_t old_queue = ARP_TABLE_SIZE;
|
||||
u8_t age_queue = 0;
|
||||
#endif
|
||||
|
||||
old_pending = old_stable = empty = ARP_TABLE_SIZE;
|
||||
age_pending = age_stable = 0;
|
||||
|
||||
/**
|
||||
* a) do a search through the cache, remember candidates
|
||||
* b) select candidate entry
|
||||
* c) create new entry
|
||||
*/
|
||||
|
||||
/* a) in a single search sweep, do all of this
|
||||
* 1) remember the first empty entry (if any)
|
||||
* 2) remember the oldest stable entry (if any)
|
||||
* 3) remember the oldest pending entry without queued packets (if any)
|
||||
* 4) remember the oldest pending entry with queued packets (if any)
|
||||
* 5) search for a matching IP entry, either pending or stable
|
||||
* until 5 matches, or all entries are searched for.
|
||||
*/
|
||||
|
||||
j = ARP_TABLE_SIZE;
|
||||
/* search ARP table for an unused or old entry */
|
||||
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
|
||||
/* empty entry? */
|
||||
if (arp_table[i].state == ETHARP_STATE_EMPTY) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning empty entry %u\n", i));
|
||||
return i;
|
||||
/* stable entry? */
|
||||
} else if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||
/* remember entry with oldest stable entry in j */
|
||||
if (arp_table[i].ctime >= maxtime) maxtime = arp_table[j = i].ctime;
|
||||
/* no empty entry found yet and now we do find one? */
|
||||
if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %d\n", i));
|
||||
/* remember first empty entry */
|
||||
empty = i;
|
||||
}
|
||||
/* pending entry? */
|
||||
else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
/* if given, does IP address match IP address in ARP entry? */
|
||||
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: found matching pending entry %d\n", i));
|
||||
/* found match, simply bail out */
|
||||
return i;
|
||||
#if ARP_QUEUEING
|
||||
/* pending with queued packets? */
|
||||
} else if (arp_table[i].p != NULL) {
|
||||
if (arp_table[i].ctime >= age_queue) {
|
||||
old_queue = i;
|
||||
age_queue = arp_table[i].ctime;
|
||||
}
|
||||
#endif
|
||||
/* pending without queued packets? */
|
||||
} else {
|
||||
if (arp_table[i].ctime >= age_pending) {
|
||||
old_pending = i;
|
||||
age_pending = arp_table[i].ctime;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* stable entry? */
|
||||
else if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||
/* if given, does IP address match IP address in ARP entry? */
|
||||
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: found matching stable entry %d\n", i));
|
||||
/* found match, simply bail out */
|
||||
return i;
|
||||
/* remember entry with oldest stable entry in oldest, its age in maxtime */
|
||||
} else if (arp_table[i].ctime >= age_stable) {
|
||||
old_stable = i;
|
||||
age_stable = arp_table[i].ctime;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* no empty entry found? */
|
||||
if (i == ARP_TABLE_SIZE) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j));
|
||||
/* fall-back to oldest stable */
|
||||
i = j;
|
||||
|
||||
/* b) choose the least destructive entry to recycle:
|
||||
* 1) empty entry
|
||||
* 2) oldest stable entry
|
||||
* 3) oldest pending entry without queued packets
|
||||
* 4) oldest pending entry without queued packets
|
||||
*/
|
||||
|
||||
/* 1) empty entry available? */
|
||||
if (empty < ARP_TABLE_SIZE) {
|
||||
i = empty;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting empty entry %d\n", i));
|
||||
}
|
||||
/* no available entry found? */
|
||||
if (i == ARP_TABLE_SIZE) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: no replacable entry could be found\n"));
|
||||
/* return failure */
|
||||
/* 2) found recyclable stable entry? */
|
||||
else if (old_stable < ARP_TABLE_SIZE) {
|
||||
/* recycle oldest stable*/
|
||||
i = old_stable;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest stable entry %d\n", i));
|
||||
#if ARP_QUEUEING
|
||||
/* no queued packets should exist on stable entries */
|
||||
LWIP_ASSERT("arp_table[i].p == NULL", arp_table[i].p == NULL);
|
||||
#endif
|
||||
/* 3) found recyclable pending entry without queued packets? */
|
||||
} else if (old_pending < ARP_TABLE_SIZE) {
|
||||
/* recycle oldest pending */
|
||||
i = old_pending;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %d (without queue)\n", i));
|
||||
#if ARP_QUEUEING
|
||||
/* 4) found recyclable pending entry with queued packets? */
|
||||
} else if (old_queue < ARP_TABLE_SIZE) {
|
||||
/* recycle oldest pending */
|
||||
i = old_queue;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %d, freeing packet queue %p\n", i, (void *)(arp_table[i].p)));
|
||||
/* no empty or recyclable entries found */
|
||||
#endif
|
||||
} else {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/* clean up the oldest stable entry (to be recycled) */
|
||||
if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||
#if ARP_QUEUEING
|
||||
/* and empty the packet queue */
|
||||
if (arp_table[i].p != NULL) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: freeing entry %u, packet queue %p.\n", i, (void *)(arp_table[i].p)));
|
||||
/* remove all queued packets */
|
||||
pbuf_free(arp_table[i].p);
|
||||
arp_table[i].p = NULL;
|
||||
}
|
||||
#endif
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_arp_entry: recycling oldest stable entry %u\n", i));
|
||||
/* { empty or recyclable entry found } */
|
||||
LWIP_ASSERT("i >= 0", i >= 0);
|
||||
LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
|
||||
|
||||
/* allowed to recycle a entry? */
|
||||
if (flags & ETHARP_CREATE) {
|
||||
/* recycle (no-op for an already empty entry) */
|
||||
arp_table[i].state = ETHARP_STATE_EMPTY;
|
||||
}
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning %u\n", i));
|
||||
return i;
|
||||
|
||||
/* empty entry found or created? */
|
||||
if (arp_table[i].state == ETHARP_STATE_EMPTY) {
|
||||
/* IP address given? */
|
||||
if (ipaddr != NULL) {
|
||||
/* set IP address */
|
||||
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
|
||||
}
|
||||
arp_table[i].ctime = 0;
|
||||
#if ARP_QUEUEING
|
||||
/* remove any queued packets */
|
||||
if (arp_table[i].p != NULL) pbuf_free(arp_table[i].p);
|
||||
arp_table[i].p = NULL;
|
||||
#endif
|
||||
/* no entry available */
|
||||
} else {
|
||||
/* return failure */
|
||||
i = (s8_t)ERR_MEM;
|
||||
}
|
||||
|
||||
return (err_t)i;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,15 +340,17 @@ find_arp_entry(void)
|
||||
* @param ipaddr IP 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,
|
||||
* - ETHARP_CREATE 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.
|
||||
* You should sent it and must call pbuf_free() afterwards.
|
||||
* @return
|
||||
* - ERR_OK Succesfully updated ARP cache.
|
||||
* - ERR_MEM If we could not add a new ARP entry when ETHARP_CREATE was set.
|
||||
* - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
|
||||
*
|
||||
* @see pbuf_free()
|
||||
*/
|
||||
static struct pbuf *
|
||||
err_t
|
||||
update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
|
||||
{
|
||||
s8_t i, k;
|
||||
@@ -248,97 +360,52 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
|
||||
ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),
|
||||
ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
|
||||
ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
|
||||
/* do not update for 0.0.0.0 addresses */
|
||||
if (ipaddr->addr == 0) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: will not add 0.0.0.0 to ARP cache\n"));
|
||||
return NULL;
|
||||
/* non-unicast address? */
|
||||
if (ip_addr_isany(ipaddr) ||
|
||||
ip_addr_isbroadcast(ipaddr, netif) ||
|
||||
ip_addr_ismulticast(ipaddr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
|
||||
return ERR_ARG;
|
||||
}
|
||||
/* Walk through the ARP mapping table and try to find an entry to update.
|
||||
* If none is found, a new IP -> MAC address mapping is inserted. */
|
||||
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
|
||||
/* Check if the source IP address of the incoming packet matches
|
||||
* the IP address in this ARP table entry. */
|
||||
if (arp_table[i].state != ETHARP_STATE_EMPTY &&
|
||||
ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
|
||||
/* pending entry? */
|
||||
if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: pending entry %u goes stable\n", i));
|
||||
/* A pending entry was found, mark it stable */
|
||||
arp_table[i].state = ETHARP_STATE_STABLE;
|
||||
/* fall-through to next if */
|
||||
}
|
||||
/* stable entry? (possibly just marked stable) */
|
||||
if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %u\n", i));
|
||||
/* An old entry found, update this and return. */
|
||||
for (k = 0; k < netif->hwaddr_len; ++k) {
|
||||
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
||||
}
|
||||
/* reset time stamp */
|
||||
arp_table[i].ctime = 0;
|
||||
/* find or create ARP entry */
|
||||
i = find_entry(ipaddr, flags);
|
||||
/* bail out if no entry could be found */
|
||||
if (i < 0) return (err_t)i;
|
||||
|
||||
/* mark it stable */
|
||||
arp_table[i].state = ETHARP_STATE_STABLE;
|
||||
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %u\n", i));
|
||||
/* update address */
|
||||
for (k = 0; k < netif->hwaddr_len; ++k) {
|
||||
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
||||
}
|
||||
/* reset time stamp */
|
||||
arp_table[i].ctime = 0;
|
||||
/* this is where we will send out queued packets! */
|
||||
#if ARP_QUEUEING
|
||||
while (arp_table[i].p != NULL) {
|
||||
/* get the first packet on the queue (if any) */
|
||||
struct pbuf *p = arp_table[i].p;
|
||||
/* Ethernet header */
|
||||
struct eth_hdr *ethhdr = p->payload;;
|
||||
/* remember (and reference) remainder of queue */
|
||||
/* note: this will also terminate the p pbuf chain */
|
||||
arp_table[i].p = pbuf_dequeue(p);
|
||||
/* fill-in Ethernet header */
|
||||
for (k = 0; k < netif->hwaddr_len; ++k) {
|
||||
ethhdr->dest.addr[k] = ethaddr->addr[k];
|
||||
ethhdr->src.addr[k] = netif->hwaddr[k];
|
||||
}
|
||||
ethhdr->type = htons(ETHTYPE_IP);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet %p.\n", (void *)p));
|
||||
/* send the queued IP packet */
|
||||
netif->linkoutput(netif, p);
|
||||
/* free the queued IP packet */
|
||||
pbuf_free(p);
|
||||
}
|
||||
#endif
|
||||
/* IP addresses should only occur once in the ARP entry, we are done */
|
||||
return NULL;
|
||||
}
|
||||
} /* if STABLE */
|
||||
} /* for all ARP entries */
|
||||
|
||||
/* no matching ARP entry was found */
|
||||
LWIP_ASSERT("update_arp_entry: i == ARP_TABLE_SIZE", i == ARP_TABLE_SIZE);
|
||||
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: IP address not yet in table\n"));
|
||||
/* allowed to insert a new entry? */
|
||||
if (flags & ARP_INSERT_FLAG)
|
||||
{
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: adding entry to table\n"));
|
||||
/* find an empty or old entry. */
|
||||
i = find_arp_entry();
|
||||
if (i == ERR_MEM) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no available entry found\n"));
|
||||
return NULL;
|
||||
}
|
||||
/* set IP address */
|
||||
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
|
||||
/* set Ethernet hardware address */
|
||||
while (arp_table[i].p != NULL) {
|
||||
/* get the first packet on the queue (if any) */
|
||||
struct pbuf *p = arp_table[i].p;
|
||||
/* Ethernet header */
|
||||
struct eth_hdr *ethhdr = p->payload;;
|
||||
/* remember (and reference) remainder of queue */
|
||||
/* note: this will also terminate the p pbuf chain */
|
||||
arp_table[i].p = pbuf_dequeue(p);
|
||||
/* fill-in Ethernet header */
|
||||
for (k = 0; k < netif->hwaddr_len; ++k) {
|
||||
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
||||
ethhdr->dest.addr[k] = ethaddr->addr[k];
|
||||
ethhdr->src.addr[k] = netif->hwaddr[k];
|
||||
}
|
||||
/* reset time-stamp */
|
||||
arp_table[i].ctime = 0;
|
||||
/* mark as stable */
|
||||
arp_table[i].state = ETHARP_STATE_STABLE;
|
||||
/* no queued packet */
|
||||
#if ARP_QUEUEING
|
||||
arp_table[i].p = NULL;
|
||||
ethhdr->type = htons(ETHTYPE_IP);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet %p.\n", (void *)p));
|
||||
/* send the queued IP packet */
|
||||
netif->linkoutput(netif, p);
|
||||
/* free the queued IP packet */
|
||||
pbuf_free(p);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no matching stable entry to update\n"));
|
||||
}
|
||||
return NULL;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -372,7 +439,7 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
|
||||
|
||||
LWIP_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);
|
||||
update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ETHARP_CREATE);
|
||||
}
|
||||
|
||||
|
||||
@@ -425,7 +492,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
||||
if (for_us) {
|
||||
/* add IP address in ARP cache; assume requester wants to talk to us.
|
||||
* can result in directly sending the queued packets for this host. */
|
||||
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ARP_INSERT_FLAG);
|
||||
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_CREATE);
|
||||
/* ARP message not directed to us? */
|
||||
} else {
|
||||
/* update the source IP address in the cache, if present */
|
||||
@@ -525,15 +592,13 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||
{
|
||||
struct eth_addr *dest, *srcaddr, mcastaddr;
|
||||
struct eth_hdr *ethhdr;
|
||||
s8_t i;
|
||||
err_t result = ERR_OK;
|
||||
|
||||
/* make room for Ethernet header - should not fail*/
|
||||
/* make room for Ethernet header - should not fail */
|
||||
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
|
||||
/* bail out */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
|
||||
LINK_STATS_INC(link.lenerr);
|
||||
pbuf_free(q);
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
@@ -546,9 +611,8 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||
if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, netif)) {
|
||||
/* broadcast on Ethernet also */
|
||||
dest = (struct eth_addr *)ðbroadcast;
|
||||
}
|
||||
/* destination IP address is an IP multicast address? */
|
||||
else if (ip_addr_ismulticast(ipaddr)) {
|
||||
} else if (ip_addr_ismulticast(ipaddr)) {
|
||||
/* Hash IP multicast address to MAC address. */
|
||||
mcastaddr.addr[0] = 0x01;
|
||||
mcastaddr.addr[1] = 0x00;
|
||||
@@ -558,33 +622,33 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||
mcastaddr.addr[5] = ip4_addr4(ipaddr);
|
||||
/* destination Ethernet address is multicast */
|
||||
dest = &mcastaddr;
|
||||
}
|
||||
/* destination IP address is an IP unicast address */
|
||||
else {
|
||||
} else {
|
||||
/* outside local network? */
|
||||
if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
|
||||
/* interface has default gateway? */
|
||||
if (netif->gw.addr != 0) {
|
||||
/* send to hardware address of default gateway IP address */
|
||||
ipaddr = &(netif->gw);
|
||||
/* no default gateway available? */
|
||||
/* no default gateway available */
|
||||
} else {
|
||||
/* destination unreachable, discard packet */
|
||||
pbuf_free(q);
|
||||
/* no route to destination error */
|
||||
return ERR_RTE;
|
||||
}
|
||||
}
|
||||
result = etharp_query(netif, ipaddr, q);
|
||||
} /* else unicast */
|
||||
/* queue on destination Ethernet address belonging to ipaddr */
|
||||
return etharp_query(netif, ipaddr, q);
|
||||
}
|
||||
|
||||
/* destination Ethernet address known */
|
||||
if (dest != NULL) {
|
||||
u8_t i;
|
||||
/* obtain source Ethernet address of the given interface */
|
||||
srcaddr = (struct eth_addr *)netif->hwaddr;
|
||||
/* A valid IP->MAC address mapping was found, fill in the
|
||||
* Ethernet header for the outgoing packet */
|
||||
ethhdr = q->payload;
|
||||
for(i = 0; i < netif->hwaddr_len; i++) {
|
||||
for (i = 0; i < netif->hwaddr_len; i++) {
|
||||
ethhdr->dest.addr[i] = dest->addr[i];
|
||||
ethhdr->src.addr[i] = srcaddr->addr[i];
|
||||
}
|
||||
@@ -592,13 +656,11 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||
/* send packet */
|
||||
result = netif->linkoutput(netif, q);
|
||||
}
|
||||
/* never reached; here for safety */
|
||||
pbuf_free(q);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an ARP request for the given IP address.
|
||||
* Send an ARP request for the given IP address and/or queue a packet.
|
||||
*
|
||||
* If the IP address was not yet in the cache, a pending ARP cache entry
|
||||
* is added and an ARP request is sent for the given address. The packet
|
||||
@@ -607,13 +669,17 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||
* If the IP address was already pending in the cache, a new ARP request
|
||||
* is sent for the given address. The packet is queued on this entry.
|
||||
*
|
||||
* If the IP address was already stable in the cache, the packet is
|
||||
* directly sent. An ARP request is sent out.
|
||||
* If the IP address was already stable in the cache, and a packet is
|
||||
* given, it is directly sent and no ARP request is sent out.
|
||||
*
|
||||
* @param netif The lwIP network interface where ipaddr
|
||||
* If the IP address was already stable in the cache, and no packet is
|
||||
* given, an ARP request is sent out.
|
||||
*
|
||||
* @param netif The lwIP network interface on which ipaddr
|
||||
* must be queried for.
|
||||
* @param ipaddr The IP address to be resolved.
|
||||
* @param q If non-NULL, a pbuf that must be delivered to the IP address.
|
||||
* q is not freed by this function.
|
||||
*
|
||||
* @return
|
||||
* - ERR_BUF Could not make room for Ethernet header.
|
||||
@@ -621,34 +687,109 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||
* to query for address or queue the packet.
|
||||
* - ERR_MEM Could not queue packet due to memory shortage.
|
||||
* - ERR_RTE No route to destination (no gateway to external networks).
|
||||
*
|
||||
* @note Might be used in the future by manual IP configuration
|
||||
* as well.
|
||||
* - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
|
||||
*
|
||||
* TODO: use the ctime field to see how long ago an ARP request was sent,
|
||||
* possibly retry.
|
||||
*/
|
||||
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
|
||||
err_t result = ERR_OK;
|
||||
err_t result = ERR_MEM;
|
||||
s8_t i; /* ARP entry index */
|
||||
u8_t k; /* Ethernet address octet index */
|
||||
|
||||
/* Do three things in this order (by design):
|
||||
*
|
||||
* 1) send out ARP request
|
||||
* 2) find entry in ARP cache
|
||||
* 3) handle the packet
|
||||
*/
|
||||
/* non-unicast address? */
|
||||
if (ip_addr_isany(ipaddr) ||
|
||||
ip_addr_isbroadcast(ipaddr, netif) ||
|
||||
ip_addr_ismulticast(ipaddr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/* find entry in ARP cache, ask to create entry if queueing packet */
|
||||
i = find_entry(ipaddr, (q != NULL) ? ETHARP_CREATE : 0);
|
||||
|
||||
/* could not find or create entry? */
|
||||
if (i < 0) return (err_t)i;
|
||||
|
||||
/* mark a fresh entry as pending (we just sent a request) */
|
||||
if (arp_table[i].state == ETHARP_STATE_EMPTY) {
|
||||
arp_table[i].state = ETHARP_STATE_PENDING;
|
||||
}
|
||||
|
||||
/* { i is either a STABLE or (new or existing) PENDING entry } */
|
||||
LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
|
||||
((arp_table[i].state == ETHARP_STATE_PENDING) ||
|
||||
(arp_table[i].state == ETHARP_STATE_STABLE)));
|
||||
|
||||
/* do we have a pending entry? */
|
||||
if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
|
||||
/* try to resolve it; send out ARP request */
|
||||
result = etharp_request(netif, ipaddr);
|
||||
}
|
||||
|
||||
/* packet given? */
|
||||
if (q != NULL) {
|
||||
/* stable entry? */
|
||||
if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||
/* we have a valid IP->Ethernet address mapping,
|
||||
* fill in the Ethernet header for the outgoing packet */
|
||||
struct eth_hdr *ethhdr = q->payload;
|
||||
for(k = 0; k < netif->hwaddr_len; k++) {
|
||||
ethhdr->dest.addr[k] = arp_table[i].ethaddr.addr[k];
|
||||
ethhdr->src.addr[k] = srcaddr->addr[k];
|
||||
}
|
||||
ethhdr->type = htons(ETHTYPE_IP);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending packet %p\n", (void *)q));
|
||||
/* send the packet */
|
||||
result = netif->linkoutput(netif, q);
|
||||
/* pending entry? (either just created or already pending */
|
||||
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
#if ARP_QUEUEING /* queue the given q packet */
|
||||
/* copy any PBUF_REF referenced payloads into PBUF_RAM */
|
||||
/* (the caller of lwIP assumes the referenced payload can be
|
||||
* freed after it returns from the lwIP call that brought us here) */
|
||||
p = pbuf_take(q);
|
||||
/* packet could be taken over? */
|
||||
if (p != NULL) {
|
||||
/* queue packet ... */
|
||||
if (arp_table[i].p == NULL) {
|
||||
/* ... in the empty queue */
|
||||
pbuf_ref(p);
|
||||
arp_table[i].p = p;
|
||||
} else {
|
||||
/* ... at tail of non-empty queue */
|
||||
pbuf_queue(arp_table[i].p, p);
|
||||
}
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %d\n", (void *)q, i));
|
||||
result = ERR_OK;
|
||||
} else {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
||||
/* { result == ERR_MEM } through initialization */
|
||||
}
|
||||
#else /* ARP_QUEUEING == 0 */
|
||||
/* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
|
||||
/* { result == ERR_MEM } through initialization */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
|
||||
err_t result = ERR_OK;
|
||||
u8_t k; /* ARP entry index */
|
||||
|
||||
/* allocate a pbuf for the outgoing ARP request packet */
|
||||
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
|
||||
/* could allocate a pbuf for an ARP request? */
|
||||
if (p != NULL) {
|
||||
struct etharp_hdr *hdr = p->payload;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n"));
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_request: sending ARP request.\n"));
|
||||
hdr->opcode = htons(ARP_REQUEST);
|
||||
for (k = 0; k < netif->hwaddr_len; k++)
|
||||
{
|
||||
@@ -680,77 +821,7 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||
/* could not allocate pbuf for ARP request */
|
||||
} else {
|
||||
result = ERR_MEM;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_query: could not allocate pbuf for ARP request.\n"));
|
||||
}
|
||||
|
||||
/* search entry of queried IP address in the ARP cache */
|
||||
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
|
||||
/* valid ARP cache entry with matching IP address? */
|
||||
if (arp_table[i].state != ETHARP_STATE_EMPTY &&
|
||||
ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
|
||||
/* pending entry? */
|
||||
if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already pending in entry %u\n", i));
|
||||
/* { i != ARP_TABLE_SIZE } */
|
||||
break;
|
||||
}
|
||||
else if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already stable in entry %u\n", i));
|
||||
/* { i != ARP_TABLE_SIZE } */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* queried address not yet in ARP table? */
|
||||
if (i == ARP_TABLE_SIZE) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: IP address not found in ARP table\n"));
|
||||
/* find an available (unused or old) entry */
|
||||
i = find_arp_entry();
|
||||
/* bail out if no ARP entries are available */
|
||||
if (i == ERR_MEM) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available. Should seldom occur.\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* i is available, create ARP entry */
|
||||
arp_table[i].state = ETHARP_STATE_PENDING;
|
||||
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
|
||||
arp_table[i].p = NULL;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: added pending entry %u for IP address\n", i));
|
||||
}
|
||||
|
||||
/* { i is either a (new or existing) PENDING or STABLE entry } */
|
||||
|
||||
/* packet given? */
|
||||
if (q != NULL) {
|
||||
/* stable entry? */
|
||||
if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||
/* we have a valid IP->Ethernet address mapping,
|
||||
* fill in the Ethernet header for the outgoing packet */
|
||||
struct eth_hdr *ethhdr = q->payload;
|
||||
for(k = 0; k < netif->hwaddr_len; k++) {
|
||||
ethhdr->dest.addr[k] = arp_table[i].ethaddr.addr[k];
|
||||
ethhdr->src.addr[k] = srcaddr->addr[k];
|
||||
}
|
||||
ethhdr->type = htons(ETHTYPE_IP);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending packet %p\n", (void *)q));
|
||||
/* send the packet */
|
||||
result = netif->linkoutput(netif, q);
|
||||
#if ARP_QUEUEING /* queue the given q packet */
|
||||
/* pending entry? (either just created or already pending */
|
||||
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
/* copy any PBUF_REF referenced payloads into PBUF_RAM */
|
||||
/* (the caller assumes the referenced payload can be freed) */
|
||||
p = pbuf_take(q);
|
||||
/* queue packet */
|
||||
if (p != NULL) {
|
||||
pbuf_queue(arp_table[i].p, p);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %d\n", (void *)q, i));
|
||||
} else {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
||||
result = ERR_MEM;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_request: could not allocate pbuf for ARP request.\n"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -64,9 +64,7 @@ static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
|
||||
static void
|
||||
low_level_init(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif;
|
||||
|
||||
ethernetif = netif->state;
|
||||
struct ethernetif *ethernetif = netif->state;
|
||||
|
||||
/* set MAC hardware address length */
|
||||
netif->hwaddr_len = 6;
|
||||
@@ -95,8 +93,9 @@ low_level_init(struct netif *netif)
|
||||
*/
|
||||
|
||||
static err_t
|
||||
low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
|
||||
low_level_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
struct ethernetif *ethernetif = netif->state;
|
||||
struct pbuf *q;
|
||||
|
||||
initiate transfer();
|
||||
@@ -134,8 +133,9 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
|
||||
*/
|
||||
|
||||
static struct pbuf *
|
||||
low_level_input(struct ethernetif *ethernetif)
|
||||
low_level_input(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif = netif->state;
|
||||
struct pbuf *p, *q;
|
||||
u16_t len;
|
||||
|
||||
@@ -223,7 +223,7 @@ ethernetif_input(struct netif *netif)
|
||||
ethernetif = netif->state;
|
||||
|
||||
/* move received packet into a new pbuf */
|
||||
p = low_level_input(ethernetif);
|
||||
p = low_level_input(netif);
|
||||
/* no packet could be read, silently ignore this */
|
||||
if (p == NULL) return;
|
||||
/* points to packet payload, which starts with an Ethernet header */
|
||||
@@ -273,7 +273,7 @@ arp_timer(void *arg)
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
err_t
|
||||
ethernetif_init(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif;
|
||||
@@ -299,5 +299,7 @@ ethernetif_init(struct netif *netif)
|
||||
etharp_init();
|
||||
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ppp.h"
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "auth.h"
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ppp.h"
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "fsm.h"
|
||||
|
||||
@@ -78,6 +78,9 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ppp.h"
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "randm.h"
|
||||
|
||||
@@ -28,11 +28,12 @@
|
||||
* for a 16 bit processor.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ppp.h"
|
||||
#include "vj.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
|
||||
#if VJ_SUPPORT > 0
|
||||
|
||||
#if LINK_STATS
|
||||
|
||||
Reference in New Issue
Block a user