Compare commits

...

21 Commits

Author SHA1 Message Date
jani
07af438a38 fix printing of recved packet.Discovered by Ed Sutter 2003-01-16 13:09:19 +00:00
likewise
fa8f6cb204 Free incoming pbuf's in the TCP event macro if the recv callback is NULL. Fixes bug #2156. 2003-01-14 12:54:02 +00:00
jani
049853362a ack duplicate segments too to prevent connection hanging when a single transmitted ACK gets lost 2003-01-14 09:38:10 +00:00
jani
3e6202f614 do not set rtime too many times to 0.it's enough to do it in tcp_output_segment 2003-01-14 08:37:01 +00:00
jani
a993e962f5 fix compiler warnings in DEBUGF 2003-01-14 08:22:05 +00:00
likewise
1ad5537c9b Fixed some typo's in the comments. 2003-01-13 13:22:09 +00:00
likewise
ea0dc429a7 Added #include <string.h> for memset()/memcpy(). 2003-01-13 13:14:45 +00:00
jani
8d7f09fa92 remove global ctime.Each entry's ctime is now absolute.This avoids wrapping and also solves naming clash reported on the list 2003-01-13 09:38:21 +00:00
jani
02a6a8a809 etharp_output_sent no longer exists 2003-01-11 15:10:12 +00:00
jani
2bba9bcd9f make rtime field u16_t like rto otherwise it won't catch rto if that goes beyond 255.When that happens there's trouble already since 255 ticks is over 2 minutes but still... 2003-01-10 15:46:58 +00:00
jani
4eebbdea0d print correct pcb->rtime value in debug statament.it does not directly depend on tcp_ticks 2003-01-10 15:41:02 +00:00
jani
4a2d03a517 seqno is u32_t so use %lu instead of %ld when printing it 2003-01-10 15:36:47 +00:00
jani
5212afdd8f remove already commented out function : memp_realloc 2003-01-10 09:42:27 +00:00
jani
e196108931 fix debug messages in tcp_slowtmr to reflect the correct name of this function 2003-01-10 09:41:24 +00:00
likewise
a5e9b73703 Made hardware address length definable (was 6 bytes for Ethernet). 2003-01-08 16:06:02 +00:00
likewise
5e13d495f0 Merged patch #927 which fixes "needs modifiable lvalue" compile error in TCP_REG. 2003-01-08 15:37:20 +00:00
likewise
a528a2323e More debugging in checksum routines. 2003-01-08 15:36:25 +00:00
likewise
c786f238ef Output snd_buf size in debug message in tcp_enqueue(). 2003-01-08 14:35:02 +00:00
adamdunkels
d04f7aa4bc Added comments to the tcp_enqueue() function. 2003-01-08 14:11:24 +00:00
likewise
ced453a72b Moved ETHARP_ALWAYS_INSERT switch to lwipopts.h 2003-01-08 11:03:54 +00:00
likewise
0f3e8c19e8 Added check if ARP_QUEUEING is 1 for a queueing related debug statement. 2003-01-08 10:49:16 +00:00
20 changed files with 199 additions and 158 deletions

View File

@@ -121,6 +121,15 @@ a lot of data that needs to be copied, this should be set high. */
/* ---------- ARP options ---------- */
#define ARP_TABLE_SIZE 10
#define ARP_QUEUEING 0
/**
* - If enabled, cache entries are generated for every kind of ARP traffic or
* broadcast IP traffic. This enhances behaviour for sending to a dynamic set
* of hosts, for example if acting as a gateway.
* - If disabled, cache entries are generated only for IP destination addresses
* in use by lwIP or applications. This enhances performance if sending to a small,
* reasonably static number of hosts. Typically for embedded devices.
*/
#define ETHARP_ALWAYS_INSERT 0
/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward

View File

@@ -124,6 +124,15 @@ a lot of data that needs to be copied, this should be set high. */
/* ---------- ARP options ---------- */
#define ARP_TABLE_SIZE 10
#define ARP_QUEUEING 1
/**
* - If enabled, cache entries are generated for every kind of ARP traffic or
* broadcast IP traffic. This enhances behaviour for sending to a dynamic set
* of hosts, for example if acting as a gateway.
* - If disabled, cache entries are generated only for IP destination addresses
* in use by lwIP or applications. This enhances performance if sending to a small,
* reasonably static number of hosts. Typically for embedded devices.
*/
#define ETHARP_ALWAYS_INSERT 1
/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward

View File

@@ -51,8 +51,9 @@ udpecho_thread(void *arg)
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
netconn_connect(conn, addr, port);
netbuf_copy(buf, buffer, buf->p->tot_len);
buffer[buf->p->tot_len] = '\0';
netconn_send(conn, buf);
netbuf_copy(buf, buffer, sizeof(buffer));
printf("got %s\n", buffer);
netbuf_delete(buf);
}

View File

@@ -122,6 +122,15 @@ a lot of data that needs to be copied, this should be set high. */
/* ---------- ARP options ---------- */
#define ARP_TABLE_SIZE 10
#define ARP_QUEUEING 1
/**
* - If enabled, cache entries are generated for every kind of ARP traffic or
* broadcast IP traffic. This enhances behaviour for sending to a dynamic set
* of hosts, for example if acting as a gateway.
* - If disabled, cache entries are generated only for IP destination addresses
* in use by lwIP or applications. This enhances performance if sending to a small,
* reasonably static number of hosts. Typically for embedded devices.
*/
#define ETHARP_ALWAYS_INSERT 1
/* ---------- IP options ---------- */

View File

@@ -1,6 +1,9 @@
#ifndef __CC_H__
#define __CC_H__
/* memset(), memcpy() */
#include <string.h>
typedef unsigned char u8_t;
typedef signed char s8_t;
typedef unsigned short u16_t;
@@ -16,5 +19,4 @@ typedef u32_t mem_ptr_t;
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
#endif /* __CC_H__ */

View File

@@ -110,7 +110,7 @@ timeout(void *arg)
bufptr = (u_char *)pcapif->pkt;
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
avaliable data in the pbuf is given by the q->len
available data in the pbuf is given by the q->len
variable. */
/* read data into(q->payload, q->len); */
bcopy(bufptr, q->payload, q->len);

View File

@@ -205,7 +205,7 @@ low_level_input(struct tapif *tapif)
bufptr = &buf[0];
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
avaliable data in the pbuf is given by the q->len
available data in the pbuf is given by the q->len
variable. */
/* read data into(q->payload, q->len); */
memcpy(q->payload, bufptr, q->len);
@@ -262,7 +262,6 @@ tapif_output(struct netif *netif, struct pbuf *p,
p = etharp_output(netif, ipaddr, p);
if(p != NULL) {
low_level_output(netif, p);
etharp_output_sent(p);
p = NULL;
}
return ERR_OK;

View File

@@ -179,7 +179,7 @@ low_level_input(struct tunif *tunif)
bufptr = &buf[0];
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
avaliable data in the pbuf is given by the q->len
available data in the pbuf is given by the q->len
variable. */
/* read data into(q->payload, q->len); */
bcopy(bufptr, q->payload, q->len);

View File

@@ -357,7 +357,7 @@ static struct pbuf * low_level_input(struct xemacif *xemacif_ptr)
* read the entire packet into the pbuf. */
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf
* in the chain. The avaliable data in
* in the chain. The available data in
* the pbuf is given by the q->len variable. */
for (i = 0 ; i < q->len ; i++) {
((u8_t *)q->payload)[i] = *(frame_bytes++);

View File

@@ -53,14 +53,19 @@ lwip_chksum(void *dataptr, int len)
{
u32_t acc;
DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %d)\n", dataptr, len));
for(acc = 0; len > 1; len -= 2) {
acc = acc + *((u16_t *)dataptr)++;
// acc = acc + *((u16_t *)dataptr)++;
acc += *(u16_t *)dataptr;
dataptr = (void *)((u16_t *)dataptr + 1);
}
/* add up any odd byte */
if(len == 1) {
acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8);
DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", *(u8_t *)dataptr));
} else {
DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n"));
}
acc = (acc >> 16) + (acc & 0xffffUL);
@@ -87,8 +92,11 @@ inet_chksum_pseudo(struct pbuf *p,
acc = 0;
swapped = 0;
/* iterate through all pbuf in chain */
for(q = p; q != NULL; q = q->next) {
DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", q, q->next));
acc += lwip_chksum(q->payload, q->len);
//DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%lx \n", acc));
while(acc >> 16) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
@@ -96,6 +104,7 @@ inet_chksum_pseudo(struct pbuf *p,
swapped = 1 - swapped;
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
}
//DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%lx \n", acc));
}
if(swapped) {
@@ -111,6 +120,7 @@ inet_chksum_pseudo(struct pbuf *p,
while(acc >> 16) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
return ~(acc & 0xffffUL);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -232,7 +232,7 @@ ip_reass(struct pbuf *p)
i = 0;
for (q = p; q != NULL; q = q->next) {
/* Copy enough bytes to fill this pbuf in the chain. The
avaliable data in the pbuf is given by the q->len
available data in the pbuf is given by the q->len
variable. */
DEBUGF(IP_REASS_DEBUG,
("ip_reass: memcpy from %p (%d) to %p, %d bytes\n",

View File

@@ -218,30 +218,6 @@ memp_mallocp(memp_t type)
return mem;
}
/*-----------------------------------------------------------------------------------*/
#if 0
void *
memp_realloc(memp_t fromtype, memp_t totype, void *mem)
{
void *rmem;
u16_t size;
if(mem == NULL) {
return NULL;
}
rmem = memp_malloc(totype);
if(rmem != NULL) {
size = memp_sizes[totype];
if(memp_sizes[fromtype] < size) {
size = memp_sizes[fromtype];
}
bcopy(mem, rmem, size);
memp_free(fromtype, mem);
}
return rmem;
}
#endif /* 0 */
/*-----------------------------------------------------------------------------------*/
void
memp_free(memp_t type, void *mem)
{

View File

@@ -312,14 +312,7 @@ tcp_listen(struct tcp_pcb *pcb)
#if LWIP_CALLBACK_API
lpcb->accept = tcp_accept_null;
#endif /* LWIP_CALLBACK_API */
/* workaround for compile error: assignment requires modifiable lvalue in TCP_REG */
#if LWIP_TCP_REG_COMPILE_ERROR
/* place this pcb at the start the "listening pcbs" list */
lpcb->next = tcp_listen_pcbs;
tcp_listen_pcbs = lpcb;
#else
TCP_REG((struct tcp_pcb **)&tcp_listen_pcbs, (struct tcp_pcb *)lpcb);
#endif
TCP_REG(&tcp_listen_pcbs, lpcb);
return (struct tcp_pcb *)lpcb;
}
/*-----------------------------------------------------------------------------------*/
@@ -464,9 +457,9 @@ tcp_slowtmr(void)
if (pcb == NULL) DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs"));
while(pcb != NULL) {
DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb"));
ASSERT("tcp_timer_coarse: active pcb->state != CLOSED", pcb->state != CLOSED);
ASSERT("tcp_timer_coarse: active pcb->state != LISTEN", pcb->state != LISTEN);
ASSERT("tcp_timer_coarse: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
ASSERT("tcp_slowtmr: active pcb->state != CLOSED", pcb->state != CLOSED);
ASSERT("tcp_slowtmr: active pcb->state != LISTEN", pcb->state != LISTEN);
ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
pcb_remove = 0;
@@ -482,8 +475,8 @@ tcp_slowtmr(void)
if(pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
/* Time for a retransmission. */
DEBUGF(TCP_RTO_DEBUG, ("tcp_timer_coarse: rtime %ld pcb->rto %d\n",
tcp_ticks - pcb->rtime, pcb->rto));
DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %ld pcb->rto %d\n",
pcb->rtime, pcb->rto));
/* Double retransmission time-out unless we are trying to
connect to somebody (i.e., we are in SYN_SENT). */
@@ -501,7 +494,7 @@ tcp_slowtmr(void)
}
pcb->cwnd = pcb->mss;
DEBUGF(TCP_CWND_DEBUG, ("tcp_rexmit_seg: cwnd %u ssthresh %u\n",
DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n",
pcb->cwnd, pcb->ssthresh));
}
}
@@ -524,7 +517,7 @@ tcp_slowtmr(void)
pcb->rto * TCP_OOSEQ_TIMEOUT) {
tcp_segs_free(pcb->ooseq);
pcb->ooseq = NULL;
DEBUGF(TCP_CWND_DEBUG, ("tcp: dropping OOSEQ queued data\n"));
DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n"));
}
#endif /* TCP_QUEUE_OOSEQ */
@@ -533,7 +526,7 @@ tcp_slowtmr(void)
if((u32_t)(tcp_ticks - pcb->tmr) >
TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
++pcb_remove;
DEBUGF(TCP_DEBUG, ("tcp_slottmr: removing pcb stuck in SYN-RCVD\n"));
DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
}
}
@@ -543,11 +536,11 @@ tcp_slowtmr(void)
tcp_pcb_purge(pcb);
/* Remove PCB from tcp_active_pcbs list. */
if(prev != NULL) {
ASSERT("tcp_timer_coarse: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
prev->next = pcb->next;
} else {
/* This PCB was the first. */
ASSERT("tcp_timer_coarse: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
tcp_active_pcbs = pcb->next;
}
@@ -562,7 +555,7 @@ tcp_slowtmr(void)
++pcb->polltmr;
if(pcb->polltmr >= pcb->pollinterval) {
pcb->polltmr = 0;
DEBUGF(TCP_DEBUG, ("tcp_slottmr: polling application\n"));
DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n"));
TCP_EVENT_POLL(pcb, err);
if(err == ERR_OK) {
tcp_output(pcb);
@@ -579,7 +572,7 @@ tcp_slowtmr(void)
prev = NULL;
pcb = tcp_tw_pcbs;
while(pcb != NULL) {
ASSERT("tcp_timer_coarse: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
pcb_remove = 0;
/* Check if this PCB has stayed long enough in TIME-WAIT */
@@ -594,11 +587,11 @@ tcp_slowtmr(void)
tcp_pcb_purge(pcb);
/* Remove PCB from tcp_tw_pcbs list. */
if(prev != NULL) {
ASSERT("tcp_timer_coarse: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
prev->next = pcb->next;
} else {
/* This PCB was the first. */
ASSERT("tcp_timer_coarse: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
tcp_tw_pcbs = pcb->next;
}
pcb2 = pcb->next;

View File

@@ -274,7 +274,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
} else {
err = ERR_OK;
/* If the application has registered a "sent" function to be
called when new send buffer space is avaliable, we call it
called when new send buffer space is available, we call it
now. */
if(pcb->acked > 0) {
TCP_EVENT_SENT(pcb, pcb->acked, err);
@@ -356,7 +356,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
npcb = tcp_alloc(pcb->prio);
/* If a new PCB could not be created (probably due to lack of memory),
we don't do anything, but rely on the sender will retransmit the
SYN at a time when we have more memory avaliable. */
SYN at a time when we have more memory available. */
if(npcb == NULL) {
DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
#ifdef TCP_STATS
@@ -872,7 +872,8 @@ tcp_receive(struct tcp_pcb *pcb)
/* the whole segment is < rcv_nxt */
/* must be a duplicate of a packet that has already been correctly handled */
DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %ld\n", seqno));
DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));
tcp_ack_now(pcb);
}
}

View File

@@ -76,6 +76,7 @@ tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb, arg, len, copy));
if(pcb->state == SYN_SENT ||
pcb->state == SYN_RCVD ||
pcb->state == ESTABLISHED ||
@@ -85,6 +86,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
}
return ERR_OK;
} else {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write() called in invalid state\n"));
return ERR_CONN;
}
}
@@ -101,39 +103,49 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
void *ptr;
u8_t queuelen;
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%d)\n", (void *)pcb, arg, len, flags, copy));
left = len;
ptr = arg;
/* fail on too much data */
if(len > pcb->snd_buf) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too much data %d\n", len));
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too much data (len=%d > snd_buf=%d)\n", len, pcb->snd_buf));
return ERR_MEM;
}
/* seqno will be the sequence number of the first segment enqueued
by the call to this function. */
seqno = pcb->snd_lbb;
queue = NULL;
DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d\n", pcb->snd_queuelen));
queue = NULL;
DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %d\n", pcb->snd_queuelen));
/* Check if the queue length exceeds the configured maximum queue
length. If so, we return an error. */
queuelen = pcb->snd_queuelen;
if(queuelen >= TCP_SND_QUEUELEN) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too long queue %d (max %d)\n", queuelen, TCP_SND_QUEUELEN));
goto memerr;
}
#ifdef LWIP_DEBUG
if(pcb->snd_queuelen != 0) {
ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
pcb->unsent != NULL);
}
#endif /* LWIP_DEBUG */
seg = NULL;
seglen = 0;
/* First, break up the data into segments and tuck them together in
the local "queue" variable. */
while(queue == NULL || left > 0) {
/* The segment length should be the MSS if the data to be enqueued
is larger than the MSS. */
seglen = left > pcb->mss? pcb->mss: left;
/* allocate memory for tcp_seg, and fill in fields */
/* Allocate memory for tcp_seg, and fill in fields. */
seg = memp_malloc(MEMP_TCP_SEG);
if(seg == NULL) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
@@ -141,67 +153,81 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
seg->next = NULL;
seg->p = NULL;
if(queue == NULL) {
queue = seg;
} else {
}
else {
/* Attach the segment to the end of the queued segments. */
for(useg = queue; useg->next != NULL; useg = useg->next);
useg->next = seg;
}
/* If copy is set, memory should be allocated
and data copied into pbuf, otherwise data comes from
ROM or other static memory, and need not be copied. If
optdata is != NULL, we have options instead of data. */
and data copied into pbuf, otherwise data comes from
ROM or other static memory, and need not be copied. If
optdata is != NULL, we have options instead of data. */
if(optdata != NULL) {
if((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
goto memerr;
goto memerr;
}
++queuelen;
seg->dataptr = seg->p->payload;
} else if(copy) {
}
else if(copy) {
if((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for pbuf copy\n"));
goto memerr;
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for pbuf copy size %u\n", seglen));
goto memerr;
}
++queuelen;
if(arg != NULL) {
memcpy(seg->p->payload, ptr, seglen);
memcpy(seg->p->payload, ptr, seglen);
}
seg->dataptr = seg->p->payload;
} else {
}
else {
/* Do not copy the data. */
/* First, allocate a pbuf for holding the data. */
if((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for pbuf non-copy\n"));
goto memerr;
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for pbuf non-copy\n"));
goto memerr;
}
++queuelen;
p->payload = ptr;
seg->dataptr = ptr;
/* Second, allocate a pbuf for the headers. */
if((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
pbuf_free(p);
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
goto memerr;
/* If allocation fails, we have to deallocate the data pbuf as
well. */
pbuf_free(p);
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
goto memerr;
}
++queuelen;
/* Chain the headers and data pbufs together. */
pbuf_chain(seg->p, p);
}
/* Now that there are more segments queued, we check again if the
length of the queue exceeds the configured maximum. */
if(queuelen > TCP_SND_QUEUELEN) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: queue too long %d (%d)\n", queuelen, TCP_SND_QUEUELEN));
goto memerr;
}
seg->len = seglen;
/* if((flags & TCP_SYN) || (flags & TCP_FIN)) {
++seg->len;
}*/
/* build TCP header */
++seg->len;
}*/
/* Build TCP header. */
if(pbuf_header(seg->p, TCP_HLEN)) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
#ifdef TCP_STATS
++lwip_stats.tcp.err;
#endif /* TCP_STATS */
@@ -214,57 +240,64 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
seg->tcphdr->urgp = 0;
TCPH_FLAGS_SET(seg->tcphdr, flags);
/* don't fill in tcphdr->ackno and tcphdr->wnd until later */
/* Copy the options into the header, if they are present. */
if(optdata == NULL) {
TCPH_OFFSET_SET(seg->tcphdr, 5 << 4);
} else {
}
else {
TCPH_OFFSET_SET(seg->tcphdr, (5 + optlen / 4) << 4);
/* Copy options into data portion of segment.
Options can thus only be sent in non data carrying
segments such as SYN|ACK. */
Options can thus only be sent in non data carrying
segments such as SYN|ACK. */
memcpy(seg->dataptr, optdata, optlen);
}
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n",
ntohl(seg->tcphdr->seqno),
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
flags));
ntohl(seg->tcphdr->seqno),
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
flags));
left -= seglen;
seqno += seglen;
ptr = (void *)((char *)ptr + seglen);
}
/* Go to the last segment on the ->unsent queue. */
/* Now that the data to be enqueued has been broken up into TCP
segments in the queue variable, we add them to the end of the
pcb->unsent queue. */
if(pcb->unsent == NULL) {
useg = NULL;
} else {
}
else {
for(useg = pcb->unsent; useg->next != NULL; useg = useg->next);
}
/* If there is room in the last pbuf on the unsent queue,
chain the first pbuf on the queue together with that. */
chain the first pbuf on the queue together with that. */
if(useg != NULL &&
TCP_TCPLEN(useg) != 0 &&
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
!(flags & (TCP_SYN | TCP_FIN)) &&
useg->len + queue->len <= pcb->mss) {
TCP_TCPLEN(useg) != 0 &&
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
!(flags & (TCP_SYN | TCP_FIN)) &&
useg->len + queue->len <= pcb->mss) {
/* Remove TCP header from first segment. */
pbuf_header(queue->p, -TCP_HLEN);
pbuf_chain(useg->p, queue->p);
useg->len += queue->len;
useg->next = queue->next;
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: chaining, new len %u\n", useg->len));
if(seg == queue) {
seg = NULL;
}
memp_free(MEMP_TCP_SEG, queue);
} else {
}
else {
if(useg == NULL) {
pcb->unsent = queue;
} else {
}
else {
useg->next = queue;
}
}
@@ -278,19 +311,19 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
#ifdef LWIP_DEBUG
if(pcb->snd_queuelen != 0) {
ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
pcb->unsent != NULL);
}
#endif /* LWIP_DEBUG */
/* Set the PSH flag in the last segment that we enqueued, but only
if the segment has data (indicated by seglen > 0). */
if the segment has data (indicated by seglen > 0). */
if(seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_PSH);
}
return ERR_OK;
memerr:
memerr:
#ifdef TCP_STATS
++lwip_stats.tcp.memerr;
#endif /* TCP_STATS */
@@ -301,8 +334,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
#ifdef LWIP_DEBUG
if(pcb->snd_queuelen != 0) {
ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
pcb->unsent != NULL);
}
#endif /* LWIP_DEBUG */
DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
@@ -392,7 +425,6 @@ tcp_output(struct tcp_pcb *pcb)
while(seg != NULL &&
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
pcb->rtime = 0;
#if TCP_CWND_DEBUG
DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n",
pcb->snd_wnd, pcb->cwnd, wnd,
@@ -425,7 +457,6 @@ tcp_output(struct tcp_pcb *pcb)
for(useg = pcb->unacked; useg->next != NULL; useg = useg->next);
useg->next = seg;
}
/* seg->rtime = 0;*/
} else {
tcp_seg_free(seg);
}
@@ -448,6 +479,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
if(pcb->rcv_wnd < pcb->mss) {
seg->tcphdr->wnd = 0;
} else {
/* advertise our receive window size in this TCP segment */
seg->tcphdr->wnd = htons(pcb->rcv_wnd);
}
@@ -549,7 +581,6 @@ tcp_rexmit(struct tcp_pcb *pcb)
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
++pcb->nrtx;
pcb->rtime = 0;
/* Don't take any rtt measurements after retransmitting. */
pcb->rttest = 0;

View File

@@ -28,7 +28,7 @@
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: udp.c,v 1.7 2003/01/08 10:09:42 likewise Exp $
* $Id: udp.c,v 1.8 2003/01/13 13:24:11 likewise Exp $
*/
/*-----------------------------------------------------------------------------------*/
@@ -58,7 +58,7 @@
/* The list of UDP PCBs. */
#if LWIP_UDP
static struct udp_pcb *udp_pcbs = NULL;
/*static*/ struct udp_pcb *udp_pcbs = NULL;
static struct udp_pcb *pcb_cache = NULL;
#endif /* LWIP_UDP */
@@ -336,6 +336,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
if(pcb->flags & UDP_FLAGS_UDPLITE) {
DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u", p->tot_len));
/* set UDP message length in UDP header */
udphdr->len = htons(pcb->chksum_len);
/* calculate checksum */
udphdr->chksum = inet_chksum_pseudo(p, src_ip, &(pcb->remote_ip),

View File

@@ -41,6 +41,8 @@
#include "lwip/inet.h"
#include "lwip/pbuf.h"
/** must be the maximum of all used hardware address lengths */
#define NETIF_HWADDR_LEN 6
struct netif {
struct netif *next;
@@ -49,7 +51,7 @@ struct netif {
struct ip_addr ip_addr;
struct ip_addr netmask; /* netmask in network byte order */
struct ip_addr gw;
unsigned char hwaddr[6];
unsigned char hwaddr[NETIF_HWADDR_LEN];
/* This function is called by the network device driver
when it wants to pass a packet to the TCP/IP stack. */
@@ -69,16 +71,16 @@ struct netif {
the pbuf on the link medium. */
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
/* This field can be set bu the device driver and could point
/* This field can be set by the device driver and could point
to state information for the device. */
void *state;
};
/* The list of network interfaces. */
/** The list of network interfaces. */
extern struct netif *netif_list;
/** The default network interface. */
extern struct netif *netif_default;
/* netif_init() must be called first. */
void netif_init(void);

View File

@@ -217,7 +217,7 @@ struct tcp_pcb {
u8_t polltmr, pollinterval;
/* Retransmission timer. */
u8_t rtime;
u16_t rtime;
u16_t mss; /* maximum segment size */
@@ -323,7 +323,8 @@ struct tcp_pcb_listen {
(ret = (pcb)->sent((pcb)->callback_arg,(pcb),(space)))
#define TCP_EVENT_RECV(pcb,p,err,ret) \
if((pcb)->recv != NULL) \
(ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)))
{ ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
pbuf_free(p); }
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
if((pcb)->connected != NULL) \
(ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
@@ -417,6 +418,7 @@ extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
} \
/* TODO: state field doesn't exist in listen pcbs */ \
ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
npcb->next = *pcbs; \
ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \

View File

@@ -3,6 +3,12 @@
* Address Resolution Protocol module for IP over Ethernet
*
* $Log: etharp.c,v $
* Revision 1.22 2003/01/13 09:38:21 jani
* remove global ctime.Each entry's ctime is now absolute.This avoids wrapping and also solves naming clash reported on the list
*
* Revision 1.21 2003/01/08 11:04:36 likewise
* Moved ETHARP_ALWAYS_INSERT switch to lwipopts.h
*
* Revision 1.19 2003/01/08 10:09:43 likewise
* Updated lwIP module copyright years to include 2003. Committers must check theirs.
*
@@ -100,15 +106,6 @@ RFC 3220 4.6 IP Mobility Support for IPv4 January 2002
/** the time an ARP entry stays pending after first request, (2 * 10) seconds = 20 seconds. */
#define ARP_MAXPENDING 2
/**
*
* - If enabled, cache entries are generated for every kind of ARP/IP traffic.
* This enhances behaviour for sending to a dynamic set of hosts, for example
* if acting as a gateway.
* - If disabled, cache entries are generated only for IP destination addresses
* in use by lwIP or applications. This enhances performance if sending to a small,
* reasonably static number of hosts. Typically for embedded devices.
*/
#ifndef ETHARP_ALWAYS_INSERT
# define ETHARP_ALWAYS_INSERT 1
#endif
@@ -143,7 +140,6 @@ struct etharp_entry {
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
static u8_t ctime;
static struct pbuf *update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
#define ARP_INSERT_FLAG 1
@@ -162,8 +158,6 @@ etharp_init(void)
arp_table[i].p = NULL;
#endif
}
/* reset ARP current time */
ctime = 0;
}
/**
@@ -177,12 +171,12 @@ etharp_tmr(void)
{
u8_t i;
++ctime;
DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
/* remove expired entries from the ARP table */
for(i = 0; i < ARP_TABLE_SIZE; ++i) {
arp_table[i].ctime++;
if((arp_table[i].state == ETHARP_STATE_STABLE) &&
(ctime - arp_table[i].ctime >= ARP_MAXAGE)) {
(arp_table[i].ctime >= ARP_MAXAGE)) {
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
arp_table[i].state = ETHARP_STATE_EMPTY;
#if ARP_QUEUEING
@@ -191,7 +185,7 @@ etharp_tmr(void)
arp_table[i].p = NULL;
#endif
} else if((arp_table[i].state == ETHARP_STATE_PENDING) &&
(ctime - arp_table[i].ctime >= ARP_MAXPENDING)) {
(arp_table[i].ctime >= ARP_MAXPENDING)) {
arp_table[i].state = ETHARP_STATE_EMPTY;
#if ARP_QUEUEING
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u - dequeueing %p.\n", i, (void *)(arp_table[i].p)));
@@ -233,8 +227,8 @@ find_arp_entry(void)
for(i = 0; i < ARP_TABLE_SIZE; ++i) {
/* remember entry with oldest stable entry in j*/
if((arp_table[i].state == ETHARP_STATE_STABLE) &&
(ctime - arp_table[i].ctime > maxtime)) {
maxtime = ctime - arp_table[i].ctime;
(arp_table[i].ctime > maxtime)) {
maxtime = arp_table[i].ctime;
j = i;
}
}
@@ -295,8 +289,8 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
for(k = 0; k < 6; ++k) {
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
}
/* time stamp */
arp_table[i].ctime = ctime;
/* reset time stamp */
arp_table[i].ctime = 0;
#if ARP_QUEUEING
/* queued packet present? */
if(arp_table[i].p != NULL) {
@@ -339,7 +333,9 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
if (arp_table[i].state == ETHARP_STATE_STABLE) {
DEBUGF(ETHARP_DEBUG, ("update_arp_entry: overwriting old stable entry %u\n", i));
/* stable entries should have no queued packets (TODO: allow later) */
#if ARP_QUEUEING
ASSERT("update_arp_entry: arp_table[i].p == NULL", arp_table[i].p == NULL);
#endif
} else {
DEBUGF(ETHARP_DEBUG, ("update_arp_entry: filling empty entry %u with state %u\n", i, arp_table[i].state));
ASSERT("update_arp_entry: arp_table[i].state == ETHARP_STATE_EMPTY", arp_table[i].state == ETHARP_STATE_EMPTY);
@@ -350,8 +346,8 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
for(k = 0; k < 6; ++k) {
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
}
/* time-stamp */
arp_table[i].ctime = ctime;
/* reset time-stamp */
arp_table[i].ctime = 0;
/* mark as stable */
arp_table[i].state = ETHARP_STATE_STABLE;
/* no queued packet */
@@ -702,7 +698,7 @@ struct pbuf *etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pb
DEBUGF(ETHARP_DEBUG, ("etharp_query: created ARP table entry.\n"));
/* i is available, create ARP entry */
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
arp_table[i].ctime = ctime;
arp_table[i].ctime = 0;
arp_table[i].state = ETHARP_STATE_PENDING;
#if ARP_QUEUEING
arp_table[i].p = NULL;

View File

@@ -140,7 +140,7 @@ low_level_input(struct ethernetif *ethernetif)
packet into the pbuf. */
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
avaliable data in the pbuf is given by the q->len
available data in the pbuf is given by the q->len
variable. */
read data into(q->payload, q->len);
}