📄 tcp_output.c
字号:
pcb->unsent != NULL); }#endif /* LWIP_DEBUG */ DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen)); return ERR_MEM;}/*-----------------------------------------------------------------------------------*//* find out what we can send and send it */err_ttcp_output(struct tcp_pcb *pcb){ struct pbuf *p; struct tcp_hdr *tcphdr; struct tcp_seg *seg, *useg; u32_t wnd;#if TCP_CWND_DEBUG int i = 0;#endif /* TCP_CWND_DEBUG */ wnd = MIN(pcb->snd_wnd, pcb->cwnd); seg = pcb->unsent; if(pcb->flags & TF_ACK_NOW) { /* If no segments are enqueued but we should send an ACK, we construct the ACK and send it. */ pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM); if(p == NULL) { DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: (ACK) could not allocate pbuf\n")); return ERR_BUF; } DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: sending ACK for %lu\n", pcb->rcv_nxt)); if(pbuf_header(p, TCP_HLEN)) { DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: (ACK) no room for TCP header in pbuf.\n")); #ifdef TCP_STATS ++stats.tcp.err;#endif /* TCP_STATS */ pbuf_free(p); return ERR_BUF; } tcphdr = p->payload; tcphdr->src = htons(pcb->local_port); tcphdr->dest = htons(pcb->remote_port); tcphdr->seqno = htonl(pcb->snd_nxt); tcphdr->ackno = htonl(pcb->rcv_nxt); TCPH_FLAGS_SET(tcphdr, TCP_ACK); tcphdr->wnd = htons(pcb->rcv_wnd); tcphdr->urgp = 0; TCPH_OFFSET_SET(tcphdr, 5 << 4); tcphdr->chksum = 0; tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip), IP_PROTO_TCP, p->tot_len); ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL, IP_PROTO_TCP); pbuf_free(p); return ERR_OK; } #if TCP_OUTPUT_DEBUG if(seg == NULL) { DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send\n")); }#endif /* TCP_OUTPUT_DEBUG */#if TCP_CWND_DEBUG if(seg == NULL) { DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n", pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); } else { DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n", pcb->snd_wnd, pcb->cwnd, wnd, ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, ntohl(seg->tcphdr->seqno), pcb->lastack)); }#endif /* TCP_CWND_DEBUG */ 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, ntohl(seg->tcphdr->seqno) + seg->len - pcb->lastack, ntohl(seg->tcphdr->seqno), pcb->lastack, i)); ++i;#endif /* TCP_CWND_DEBUG */ pcb->unsent = seg->next; if(pcb->state != SYN_SENT) { TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_ACK); pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); } tcp_output_segment(seg, pcb); pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); if(TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) { pcb->snd_max = pcb->snd_nxt; } /* put segment on unacknowledged list if length > 0 */ if(TCP_TCPLEN(seg) > 0) { seg->next = NULL; if(pcb->unacked == NULL) { pcb->unacked = seg; } else { for(useg = pcb->unacked; useg->next != NULL; useg = useg->next); useg->next = seg; } /* seg->rtime = 0;*/ } else { tcp_seg_free(seg); } seg = pcb->unsent; } return ERR_OK;}/*-----------------------------------------------------------------------------------*/static voidtcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb){ u16_t len, tot_len; struct netif *netif; /* The TCP header has already been constructed, but the ackno and wnd fields remain. */ seg->tcphdr->ackno = htonl(pcb->rcv_nxt); /* silly window avoidance */ if(pcb->rcv_wnd < pcb->mss) { seg->tcphdr->wnd = 0; } else { seg->tcphdr->wnd = htons(pcb->rcv_wnd); } /* If we don't have a local IP address, we get one by calling ip_route(). */ if(ip_addr_isany(&(pcb->local_ip))) { netif = ip_route(&(pcb->remote_ip)); if(netif == NULL) { return; } ip_addr_set(&(pcb->local_ip), &(netif->ip_addr)); } pcb->rtime = 0; if(pcb->rttest == 0) { pcb->rttest = tcp_ticks; pcb->rtseq = ntohl(seg->tcphdr->seqno); DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq)); } DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n", htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + seg->len)); seg->tcphdr->chksum = 0; seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip), &(pcb->remote_ip), IP_PROTO_TCP, seg->p->tot_len);#ifdef TCP_STATS ++stats.tcp.xmit;#endif /* TCP_STATS */ len = seg->p->len; tot_len = seg->p->tot_len; ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL, IP_PROTO_TCP); seg->p->len = len; seg->p->tot_len = tot_len; seg->p->payload = seg->tcphdr;}/*-----------------------------------------------------------------------------------*/voidtcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg){ u32_t wnd; u16_t len, tot_len; struct netif *netif; DEBUGF(TCP_REXMIT_DEBUG, ("tcp_rexmit_seg: skickar %ld:%ld\n", ntohl(seg->tcphdr->seqno), ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); wnd = MIN(pcb->snd_wnd, pcb->cwnd); if(ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { /* Count the number of retranmissions. */ ++pcb->nrtx; if((netif = ip_route((struct ip_addr *)&(pcb->remote_ip))) == NULL) { DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_rexmit_segment: No route to 0x%lx\n", pcb->remote_ip.addr));#ifdef TCP_STATS ++stats.tcp.rterr;#endif /* TCP_STATS */ return; } seg->tcphdr->ackno = htonl(pcb->rcv_nxt); seg->tcphdr->wnd = htons(pcb->rcv_wnd); /* Recalculate checksum. */ seg->tcphdr->chksum = 0; seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip), &(pcb->remote_ip), IP_PROTO_TCP, seg->p->tot_len); len = seg->p->len; tot_len = seg->p->tot_len; pbuf_header(seg->p, IP_HLEN); ip_output_if(seg->p, NULL, IP_HDRINCL, TCP_TTL, IP_PROTO_TCP, netif); seg->p->len = len; seg->p->tot_len = tot_len; seg->p->payload = seg->tcphdr;#ifdef TCP_STATS ++stats.tcp.xmit; ++stats.tcp.rexmit;#endif /* TCP_STATS */ pcb->rtime = 0; /* Don't take any rtt measurements after retransmitting. */ pcb->rttest = 0; } else { DEBUGF(TCP_REXMIT_DEBUG, ("tcp_rexmit_seg: no room in window %lu to send %lu (ack %lu)\n", wnd, ntohl(seg->tcphdr->seqno), pcb->lastack)); }}/*-----------------------------------------------------------------------------------*/voidtcp_rst(u32_t seqno, u32_t ackno, struct ip_addr *local_ip, struct ip_addr *remote_ip, u16_t local_port, u16_t remote_port){ struct pbuf *p; struct tcp_hdr *tcphdr; p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM); if(p == NULL) {#if MEM_RECLAIM mem_reclaim(sizeof(struct pbuf)); p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM);#endif /* MEM_RECLAIM */ if(p == NULL) { DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); return; } } if(pbuf_header(p, TCP_HLEN)) { DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_send_data: no room for TCP header in pbuf.\n"));#ifdef TCP_STATS ++stats.tcp.err;#endif /* TCP_STATS */ return; } tcphdr = p->payload; tcphdr->src = htons(local_port); tcphdr->dest = htons(remote_port); tcphdr->seqno = htonl(seqno); tcphdr->ackno = htonl(ackno); TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK); tcphdr->wnd = 0; tcphdr->urgp = 0; TCPH_OFFSET_SET(tcphdr, 5 << 4); tcphdr->chksum = 0; tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip, IP_PROTO_TCP, p->tot_len);#ifdef TCP_STATS ++stats.tcp.xmit;#endif /* TCP_STATS */ ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP); pbuf_free(p); DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));}/*-----------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -