mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-01-30 12:32:37 +00:00
fixed bug #37614 "Errors from ipX_output are not processed". Now tcp_output(_segment) checks for the return value of ipX_output and does not try to send more on error. A netif driver can call tcp_txnow() (from tcpip_thread!) to try to send again if TX buffers are available again.
This commit is contained in:
parent
90db821036
commit
5d13b5a2fb
@ -186,6 +186,13 @@ HISTORY
|
|||||||
|
|
||||||
++ Bugfixes:
|
++ Bugfixes:
|
||||||
|
|
||||||
|
2015-02-17: Simon Goldschmidt
|
||||||
|
* tcp_impl.h, tcp_out.c, tcp.c, api_msg.c: fixed bug #37614 "Errors from
|
||||||
|
ipX_output are not processed". Now tcp_output(_segment) checks for the return
|
||||||
|
value of ipX_output and does not try to send more on error. A netif driver
|
||||||
|
can call tcp_txnow() (from tcpip_thread!) to try to send again if TX buffers
|
||||||
|
are available again.
|
||||||
|
|
||||||
2015-02-14: patches by Freddie Chopin
|
2015-02-14: patches by Freddie Chopin
|
||||||
* snmp*: made community writable, fixed some const pointers
|
* snmp*: made community writable, fixed some const pointers
|
||||||
|
|
||||||
|
@ -1482,6 +1482,7 @@ err_mem:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (err == ERR_OK) {
|
if (err == ERR_OK) {
|
||||||
|
err_t out_err;
|
||||||
conn->write_offset += len;
|
conn->write_offset += len;
|
||||||
if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) {
|
if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) {
|
||||||
/* return sent length */
|
/* return sent length */
|
||||||
@ -1490,18 +1491,34 @@ err_mem:
|
|||||||
write_finished = 1;
|
write_finished = 1;
|
||||||
conn->write_offset = 0;
|
conn->write_offset = 0;
|
||||||
}
|
}
|
||||||
tcp_output(conn->pcb.tcp);
|
out_err = tcp_output(conn->pcb.tcp);
|
||||||
|
if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) {
|
||||||
|
/* If tcp_output fails with fatal error or no route is found,
|
||||||
|
don't try writing any more but return the error
|
||||||
|
to the application thread. */
|
||||||
|
err = out_err;
|
||||||
|
write_finished = 1;
|
||||||
|
conn->current_msg->msg.w.len = 0;
|
||||||
|
}
|
||||||
} else if ((err == ERR_MEM) && !dontblock) {
|
} else if ((err == ERR_MEM) && !dontblock) {
|
||||||
/* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
|
/* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
|
||||||
we do NOT return to the application thread, since ERR_MEM is
|
we do NOT return to the application thread, since ERR_MEM is
|
||||||
only a temporary error! */
|
only a temporary error! */
|
||||||
|
|
||||||
/* tcp_write returned ERR_MEM, try tcp_output anyway */
|
/* tcp_write returned ERR_MEM, try tcp_output anyway */
|
||||||
tcp_output(conn->pcb.tcp);
|
err_t out_err = tcp_output(conn->pcb.tcp);
|
||||||
|
if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) {
|
||||||
|
/* If tcp_output fails with fatal error or no route is found,
|
||||||
|
don't try writing any more but return the error
|
||||||
|
to the application thread. */
|
||||||
|
err = out_err;
|
||||||
|
write_finished = 1;
|
||||||
|
conn->current_msg->msg.w.len = 0;
|
||||||
|
} else {
|
||||||
#if LWIP_TCPIP_CORE_LOCKING
|
#if LWIP_TCPIP_CORE_LOCKING
|
||||||
conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
|
conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* On errors != ERR_MEM, we don't try writing any more but return
|
/* On errors != ERR_MEM, we don't try writing any more but return
|
||||||
the error to the application thread. */
|
the error to the application thread. */
|
||||||
|
@ -879,13 +879,17 @@ tcp_slowtmr_start:
|
|||||||
if (pcb->persist_backoff > 0) {
|
if (pcb->persist_backoff > 0) {
|
||||||
/* If snd_wnd is zero, use persist timer to send 1 byte probes
|
/* If snd_wnd is zero, use persist timer to send 1 byte probes
|
||||||
* instead of using the standard retransmission mechanism. */
|
* instead of using the standard retransmission mechanism. */
|
||||||
pcb->persist_cnt++;
|
u8_t backoff_cnt = tcp_persist_backoff[pcb->persist_backoff-1];
|
||||||
if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) {
|
if (pcb->persist_cnt < backoff_cnt) {
|
||||||
pcb->persist_cnt = 0;
|
pcb->persist_cnt++;
|
||||||
if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) {
|
}
|
||||||
pcb->persist_backoff++;
|
if (pcb->persist_cnt >= backoff_cnt) {
|
||||||
|
if (tcp_zero_window_probe(pcb) == ERR_OK) {
|
||||||
|
pcb->persist_cnt = 0;
|
||||||
|
if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) {
|
||||||
|
pcb->persist_backoff++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tcp_zero_window_probe(pcb);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Increase the retransmission timer if it is running */
|
/* Increase the retransmission timer if it is running */
|
||||||
@ -957,8 +961,10 @@ tcp_slowtmr_start:
|
|||||||
(pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb))
|
(pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb))
|
||||||
/ TCP_SLOW_INTERVAL)
|
/ TCP_SLOW_INTERVAL)
|
||||||
{
|
{
|
||||||
tcp_keepalive(pcb);
|
err = tcp_keepalive(pcb);
|
||||||
pcb->keep_cnt_sent++;
|
if (err == ERR_OK) {
|
||||||
|
pcb->keep_cnt_sent++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,6 +1136,19 @@ tcp_fasttmr_start:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Call tcp_output for all active pcbs that have TF_NAGLEMEMERR set */
|
||||||
|
void
|
||||||
|
tcp_txnow(void)
|
||||||
|
{
|
||||||
|
struct tcp_pcb *pcb;
|
||||||
|
|
||||||
|
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
|
if (pcb->flags & TF_NAGLEMEMERR) {
|
||||||
|
tcp_output(pcb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Pass pcb->refused_data to the recv callback */
|
/** Pass pcb->refused_data to the recv callback */
|
||||||
err_t
|
err_t
|
||||||
tcp_process_refused_data(struct tcp_pcb *pcb)
|
tcp_process_refused_data(struct tcp_pcb *pcb)
|
||||||
|
@ -94,7 +94,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Forward declarations.*/
|
/* Forward declarations.*/
|
||||||
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
|
static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
|
||||||
|
|
||||||
/** Allocate a pbuf and create a tcphdr at p->payload, used for output
|
/** Allocate a pbuf and create a tcphdr at p->payload, used for output
|
||||||
* functions other than the default tcp_output -> tcp_output_segment
|
* functions other than the default tcp_output -> tcp_output_segment
|
||||||
@ -895,6 +895,7 @@ tcp_build_wnd_scale_option(u32_t *opts)
|
|||||||
err_t
|
err_t
|
||||||
tcp_send_empty_ack(struct tcp_pcb *pcb)
|
tcp_send_empty_ack(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
|
err_t err;
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
u8_t optlen = 0;
|
u8_t optlen = 0;
|
||||||
#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
|
#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
|
||||||
@ -909,6 +910,8 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt));
|
p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt));
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
|
/* let tcp_fasttmr retry sending this ACK */
|
||||||
|
pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
||||||
return ERR_BUF;
|
return ERR_BUF;
|
||||||
}
|
}
|
||||||
@ -917,8 +920,6 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
|
|||||||
#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */
|
#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
|
||||||
("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
|
("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
|
||||||
/* remove ACK flags from the PCB, as we send an empty ACK now */
|
|
||||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
|
||||||
|
|
||||||
/* NB. MSS and window scale options are only sent on SYNs, so ignore them here */
|
/* NB. MSS and window scale options are only sent on SYNs, so ignore them here */
|
||||||
#if LWIP_TCP_TIMESTAMPS
|
#if LWIP_TCP_TIMESTAMPS
|
||||||
@ -934,15 +935,23 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
|
|||||||
&pcb->local_ip, &pcb->remote_ip);
|
&pcb->local_ip, &pcb->remote_ip);
|
||||||
#endif
|
#endif
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos,
|
err = ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos,
|
||||||
IP_PROTO_TCP, &pcb->addr_hint);
|
IP_PROTO_TCP, &pcb->addr_hint);
|
||||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||||
ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos,
|
err = ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos,
|
||||||
IP_PROTO_TCP);
|
IP_PROTO_TCP);
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
|
|
||||||
return ERR_OK;
|
if (err != ERR_OK) {
|
||||||
|
/* let tcp_fasttmr retry sending this ACK */
|
||||||
|
pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
|
||||||
|
} else {
|
||||||
|
/* remove ACK flags from the PCB, as we sent an empty ACK now */
|
||||||
|
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -957,6 +966,7 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
{
|
{
|
||||||
struct tcp_seg *seg, *useg;
|
struct tcp_seg *seg, *useg;
|
||||||
u32_t wnd, snd_nxt;
|
u32_t wnd, snd_nxt;
|
||||||
|
err_t err;
|
||||||
#if TCP_CWND_DEBUG
|
#if TCP_CWND_DEBUG
|
||||||
s16_t i = 0;
|
s16_t i = 0;
|
||||||
#endif /* TCP_CWND_DEBUG */
|
#endif /* TCP_CWND_DEBUG */
|
||||||
@ -1041,17 +1051,23 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
++i;
|
++i;
|
||||||
#endif /* TCP_CWND_DEBUG */
|
#endif /* TCP_CWND_DEBUG */
|
||||||
|
|
||||||
pcb->unsent = seg->next;
|
|
||||||
|
|
||||||
if (pcb->state != SYN_SENT) {
|
if (pcb->state != SYN_SENT) {
|
||||||
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
|
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
|
||||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TCP_OVERSIZE_DBGCHECK
|
#if TCP_OVERSIZE_DBGCHECK
|
||||||
seg->oversize_left = 0;
|
seg->oversize_left = 0;
|
||||||
#endif /* TCP_OVERSIZE_DBGCHECK */
|
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||||
tcp_output_segment(seg, pcb);
|
err = tcp_output_segment(seg, pcb);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
/* segment could not be sent, for whatever reason */
|
||||||
|
pcb->flags |= TF_NAGLEMEMERR;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
pcb->unsent = seg->next;
|
||||||
|
if (pcb->state != SYN_SENT) {
|
||||||
|
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||||
|
}
|
||||||
snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
|
snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
|
||||||
if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
|
if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
|
||||||
pcb->snd_nxt = snd_nxt;
|
pcb->snd_nxt = snd_nxt;
|
||||||
@ -1106,9 +1122,10 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
* @param seg the tcp_seg to send
|
* @param seg the tcp_seg to send
|
||||||
* @param pcb the tcp_pcb for the TCP connection used to send the segment
|
* @param pcb the tcp_pcb for the TCP connection used to send the segment
|
||||||
*/
|
*/
|
||||||
static void
|
static err_t
|
||||||
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
|
err_t err;
|
||||||
u16_t len;
|
u16_t len;
|
||||||
u32_t *opts;
|
u32_t *opts;
|
||||||
|
|
||||||
@ -1174,7 +1191,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
ipX_addr_t *local_ip;
|
ipX_addr_t *local_ip;
|
||||||
ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip);
|
ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip);
|
||||||
if ((netif == NULL) || (local_ip == NULL)) {
|
if ((netif == NULL) || (local_ip == NULL)) {
|
||||||
return;
|
return ERR_RTE;
|
||||||
}
|
}
|
||||||
ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip);
|
ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip);
|
||||||
}
|
}
|
||||||
@ -1237,12 +1254,13 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
TCP_STATS_INC(tcp.xmit);
|
TCP_STATS_INC(tcp.xmit);
|
||||||
|
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
ipX_output_hinted(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip,
|
err = ipX_output_hinted(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip,
|
||||||
pcb->ttl, pcb->tos, IP_PROTO_TCP, &pcb->addr_hint);
|
pcb->ttl, pcb->tos, IP_PROTO_TCP, &pcb->addr_hint);
|
||||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||||
ipX_output(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
err = ipX_output(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
||||||
pcb->tos, IP_PROTO_TCP);
|
pcb->tos, IP_PROTO_TCP);
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1448,9 +1466,10 @@ tcp_rexmit_fast(struct tcp_pcb *pcb)
|
|||||||
*
|
*
|
||||||
* @param pcb the tcp_pcb for which to send a keepalive packet
|
* @param pcb the tcp_pcb for which to send a keepalive packet
|
||||||
*/
|
*/
|
||||||
void
|
err_t
|
||||||
tcp_keepalive(struct tcp_pcb *pcb)
|
tcp_keepalive(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
|
err_t err;
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
#if CHECKSUM_GEN_TCP
|
#if CHECKSUM_GEN_TCP
|
||||||
struct tcp_hdr *tcphdr;
|
struct tcp_hdr *tcphdr;
|
||||||
@ -1465,9 +1484,9 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1));
|
p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1));
|
||||||
if(p == NULL) {
|
if(p == NULL) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG,
|
LWIP_DEBUGF(TCP_DEBUG,
|
||||||
("tcp_keepalive: could not allocate memory for pbuf\n"));
|
("tcp_keepalive: could not allocate memory for pbuf\n"));
|
||||||
return;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
#if CHECKSUM_GEN_TCP
|
#if CHECKSUM_GEN_TCP
|
||||||
tcphdr = (struct tcp_hdr *)p->payload;
|
tcphdr = (struct tcp_hdr *)p->payload;
|
||||||
@ -1479,17 +1498,18 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
/* Send output to IP */
|
/* Send output to IP */
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip,
|
err = ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip,
|
||||||
pcb->ttl, 0, IP_PROTO_TCP, &pcb->addr_hint);
|
pcb->ttl, 0, IP_PROTO_TCP, &pcb->addr_hint);
|
||||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||||
ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
err = ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
||||||
0, IP_PROTO_TCP);
|
0, IP_PROTO_TCP);
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||||
|
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n",
|
||||||
pcb->snd_nxt - 1, pcb->rcv_nxt));
|
pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err));
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1501,9 +1521,10 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
*
|
*
|
||||||
* @param pcb the tcp_pcb for which to send a zero-window probe packet
|
* @param pcb the tcp_pcb for which to send a zero-window probe packet
|
||||||
*/
|
*/
|
||||||
void
|
err_t
|
||||||
tcp_zero_window_probe(struct tcp_pcb *pcb)
|
tcp_zero_window_probe(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
|
err_t err;
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
struct tcp_hdr *tcphdr;
|
struct tcp_hdr *tcphdr;
|
||||||
struct tcp_seg *seg;
|
struct tcp_seg *seg;
|
||||||
@ -1525,7 +1546,8 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
|||||||
seg = pcb->unsent;
|
seg = pcb->unsent;
|
||||||
}
|
}
|
||||||
if(seg == NULL) {
|
if(seg == NULL) {
|
||||||
return;
|
/* nothing to send, zero window probe not needed */
|
||||||
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
|
is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
|
||||||
@ -1535,7 +1557,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
|||||||
p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
|
p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
|
||||||
if(p == NULL) {
|
if(p == NULL) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
|
||||||
return;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
tcphdr = (struct tcp_hdr *)p->payload;
|
tcphdr = (struct tcp_hdr *)p->payload;
|
||||||
|
|
||||||
@ -1559,16 +1581,17 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
/* Send output to IP */
|
/* Send output to IP */
|
||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
err = ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
|
||||||
0, IP_PROTO_TCP, &pcb->addr_hint);
|
0, IP_PROTO_TCP, &pcb->addr_hint);
|
||||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||||
ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
err = ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||||
|
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
|
||||||
" ackno %"U32_F".\n",
|
" ackno %"U32_F" err %d.\n",
|
||||||
pcb->snd_nxt - 1, pcb->rcv_nxt));
|
pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err));
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
|
@ -61,6 +61,11 @@ void tcp_tmr (void); /* Must be called every
|
|||||||
void tcp_slowtmr (void);
|
void tcp_slowtmr (void);
|
||||||
void tcp_fasttmr (void);
|
void tcp_fasttmr (void);
|
||||||
|
|
||||||
|
/* Call this from a netif driver (watch out for threading issues!) that has
|
||||||
|
returned a memory error on transmit and now has free buffers to send more.
|
||||||
|
This iterates all active pcbs that had an error and tries to call
|
||||||
|
tcp_output, so use this with care as it might slow down the system. */
|
||||||
|
void tcp_txnow (void);
|
||||||
|
|
||||||
/* Only used by IP to pass a TCP segment to TCP: */
|
/* Only used by IP to pass a TCP segment to TCP: */
|
||||||
void tcp_input (struct pbuf *p, struct netif *inp);
|
void tcp_input (struct pbuf *p, struct netif *inp);
|
||||||
@ -490,8 +495,8 @@ void tcp_rst_impl(u32_t seqno, u32_t ackno,
|
|||||||
|
|
||||||
u32_t tcp_next_iss(void);
|
u32_t tcp_next_iss(void);
|
||||||
|
|
||||||
void tcp_keepalive(struct tcp_pcb *pcb);
|
err_t tcp_keepalive(struct tcp_pcb *pcb);
|
||||||
void tcp_zero_window_probe(struct tcp_pcb *pcb);
|
err_t tcp_zero_window_probe(struct tcp_pcb *pcb);
|
||||||
|
|
||||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||||
u16_t tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest
|
u16_t tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest
|
||||||
|
Loading…
x
Reference in New Issue
Block a user