00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "lwip/opt.h"
00042
00043 #if LWIP_TCP
00044
00045 #include "lwip/tcp.h"
00046 #include "lwip/def.h"
00047 #include "lwip/mem.h"
00048 #include "lwip/memp.h"
00049 #include "lwip/sys.h"
00050 #include "lwip/ip_addr.h"
00051 #include "lwip/netif.h"
00052 #include "lwip/inet.h"
00053 #include "lwip/inet_chksum.h"
00054 #include "lwip/stats.h"
00055 #include "lwip/snmp.h"
00056
00057 #include <string.h>
00058
00059
00060 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
00061
00062 static struct tcp_hdr *
00063 tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen,
00064 u32_t seqno_be )
00065 {
00066 struct tcp_hdr *tcphdr = p->payload;
00067 tcphdr->src = htons(pcb->local_port);
00068 tcphdr->dest = htons(pcb->remote_port);
00069 tcphdr->seqno = seqno_be;
00070 tcphdr->ackno = htonl(pcb->rcv_nxt);
00071 TCPH_FLAGS_SET(tcphdr, TCP_ACK);
00072 tcphdr->wnd = htons(pcb->rcv_ann_wnd);
00073 tcphdr->urgp = 0;
00074 TCPH_HDRLEN_SET(tcphdr, (5 + optlen / 4));
00075 tcphdr->chksum = 0;
00076
00077
00078 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
00079
00080 return tcphdr;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090 err_t
00091 tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
00092 {
00093
00094 return tcp_enqueue(pcb, NULL, 0, flags, TCP_WRITE_FLAG_COPY, 0);
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 err_t
00116 tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
00117 {
00118 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", (void *)pcb,
00119 data, len, (u16_t)apiflags));
00120
00121 if (pcb->state == ESTABLISHED ||
00122 pcb->state == CLOSE_WAIT ||
00123 pcb->state == SYN_SENT ||
00124 pcb->state == SYN_RCVD) {
00125 if (len > 0) {
00126 #if LWIP_TCP_TIMESTAMPS
00127 return tcp_enqueue(pcb, (void *)data, len, 0, apiflags,
00128 pcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0);
00129 #else
00130 return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 0);
00131 #endif
00132 }
00133 return ERR_OK;
00134 } else {
00135 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
00136 return ERR_CONN;
00137 }
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 err_t
00155 tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
00156 u8_t flags, u8_t apiflags, u8_t optflags)
00157 {
00158 struct pbuf *p;
00159 struct tcp_seg *seg, *useg, *queue;
00160 u32_t seqno;
00161 u16_t left, seglen;
00162 void *ptr;
00163 u16_t queuelen;
00164 u8_t optlen;
00165
00166 LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
00167 ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", apiflags=%"U16_F")\n",
00168 (void *)pcb, arg, len, (u16_t)flags, (u16_t)apiflags));
00169 LWIP_ERROR("tcp_enqueue: packet needs payload, options, or SYN/FIN (programmer violates API)",
00170 ((len != 0) || (optflags != 0) || ((flags & (TCP_SYN | TCP_FIN)) != 0)),
00171 return ERR_ARG;);
00172 LWIP_ERROR("tcp_enqueue: len != 0 || arg == NULL (programmer violates API)",
00173 ((len != 0) || (arg == NULL)), return ERR_ARG;);
00174
00175
00176 if (len > pcb->snd_buf) {
00177 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
00178 ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
00179 pcb->flags |= TF_NAGLEMEMERR;
00180 return ERR_MEM;
00181 }
00182 left = len;
00183 ptr = arg;
00184
00185 optlen = LWIP_TCP_OPT_LENGTH(optflags);
00186
00187
00188
00189 seqno = pcb->snd_lbb;
00190
00191 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
00192
00193
00194
00195 queuelen = pcb->snd_queuelen;
00196
00197 if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00198 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
00199 ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
00200 TCP_STATS_INC(tcp.memerr);
00201 pcb->flags |= TF_NAGLEMEMERR;
00202 return ERR_MEM;
00203 }
00204 if (queuelen != 0) {
00205 LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
00206 pcb->unacked != NULL || pcb->unsent != NULL);
00207 } else {
00208 LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
00209 pcb->unacked == NULL && pcb->unsent == NULL);
00210 }
00211
00212
00213
00214 useg = queue = seg = NULL;
00215 seglen = 0;
00216 while (queue == NULL || left > 0) {
00217
00218 seglen = left > (pcb->mss - optlen) ? (pcb->mss - optlen) : left;
00219
00220
00221 seg = memp_malloc(MEMP_TCP_SEG);
00222 if (seg == NULL) {
00223 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00224 ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
00225 goto memerr;
00226 }
00227 seg->next = NULL;
00228 seg->p = NULL;
00229
00230
00231 if (queue == NULL) {
00232 queue = seg;
00233 }
00234
00235 else {
00236
00237 LWIP_ASSERT("useg != NULL", useg != NULL);
00238 useg->next = seg;
00239 }
00240
00241 useg = seg;
00242
00243
00244
00245
00246 if (apiflags & TCP_WRITE_FLAG_COPY) {
00247 if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) {
00248 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00249 ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
00250 goto memerr;
00251 }
00252 LWIP_ASSERT("check that first pbuf can hold the complete seglen",
00253 (seg->p->len >= seglen + optlen));
00254 queuelen += pbuf_clen(seg->p);
00255 if (arg != NULL) {
00256 MEMCPY((char *)seg->p->payload + optlen, ptr, seglen);
00257 }
00258 seg->dataptr = seg->p->payload;
00259 }
00260
00261 else {
00262
00263 if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
00264 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00265 ("tcp_enqueue: could not allocate memory for header pbuf\n"));
00266 goto memerr;
00267 }
00268 queuelen += pbuf_clen(seg->p);
00269
00270
00271
00272
00273
00274
00275 if (left > 0) {
00276 if ((p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
00277
00278 pbuf_free(seg->p);
00279 seg->p = NULL;
00280 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00281 ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
00282 goto memerr;
00283 }
00284 ++queuelen;
00285
00286 p->payload = ptr;
00287 seg->dataptr = ptr;
00288
00289
00290 pbuf_cat(seg->p, p);
00291 p = NULL;
00292 }
00293 }
00294
00295
00296
00297 if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00298 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00299 ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
00300 goto memerr;
00301 }
00302
00303 seg->len = seglen;
00304
00305
00306 if (pbuf_header(seg->p, TCP_HLEN)) {
00307 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
00308 TCP_STATS_INC(tcp.err);
00309 goto memerr;
00310 }
00311 seg->tcphdr = seg->p->payload;
00312 seg->tcphdr->src = htons(pcb->local_port);
00313 seg->tcphdr->dest = htons(pcb->remote_port);
00314 seg->tcphdr->seqno = htonl(seqno);
00315 seg->tcphdr->urgp = 0;
00316 TCPH_FLAGS_SET(seg->tcphdr, flags);
00317
00318
00319 seg->flags = optflags;
00320
00321
00322 TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
00323 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
00324 ntohl(seg->tcphdr->seqno),
00325 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
00326 (u16_t)flags));
00327
00328 left -= seglen;
00329 seqno += seglen;
00330 ptr = (void *)((u8_t *)ptr + seglen);
00331 }
00332
00333
00334
00335
00336 if (pcb->unsent == NULL) {
00337 useg = NULL;
00338 }
00339 else {
00340 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
00341 }
00342
00343
00344
00345
00346 if (useg != NULL &&
00347 TCP_TCPLEN(useg) != 0 &&
00348 !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
00349 (!(flags & (TCP_SYN | TCP_FIN)) || (flags == TCP_FIN)) &&
00350
00351 (useg->len + queue->len <= pcb->mss) &&
00352
00353 (useg->flags == queue->flags) &&
00354
00355 (ntohl(useg->tcphdr->seqno) + useg->len == ntohl(queue->tcphdr->seqno)) ) {
00356
00357 if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
00358
00359 LWIP_ASSERT("pbuf_header failed\n", 0);
00360 TCP_STATS_INC(tcp.err);
00361 goto memerr;
00362 }
00363 if (queue->p->len == 0) {
00364
00365 struct pbuf *old_q = queue->p;
00366 queue->p = queue->p->next;
00367 old_q->next = NULL;
00368 queuelen--;
00369 pbuf_free(old_q);
00370 }
00371 if (flags & TCP_FIN) {
00372
00373 LWIP_ASSERT("FIN enqueued together with data", queue->p == NULL && queue->len == 0);
00374 TCPH_SET_FLAG(useg->tcphdr, TCP_FIN);
00375 } else {
00376 LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
00377 pbuf_cat(useg->p, queue->p);
00378 useg->len += queue->len;
00379 useg->next = queue->next;
00380 }
00381
00382 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
00383 if (seg == queue) {
00384 seg = useg;
00385 seglen = useg->len;
00386 }
00387 memp_free(MEMP_TCP_SEG, queue);
00388 }
00389 else {
00390
00391 if (useg == NULL) {
00392
00393 pcb->unsent = queue;
00394 }
00395
00396 else {
00397 useg->next = queue;
00398 }
00399 }
00400 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
00401 ++len;
00402 }
00403 if (flags & TCP_FIN) {
00404 pcb->flags |= TF_FIN;
00405 }
00406 pcb->snd_lbb += len;
00407
00408 pcb->snd_buf -= len;
00409
00410
00411 pcb->snd_queuelen = queuelen;
00412 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
00413 if (pcb->snd_queuelen != 0) {
00414 LWIP_ASSERT("tcp_enqueue: valid queue length",
00415 pcb->unacked != NULL || pcb->unsent != NULL);
00416 }
00417
00418
00419
00420 if (seg != NULL && seglen > 0 && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
00421 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
00422 }
00423
00424 return ERR_OK;
00425 memerr:
00426 pcb->flags |= TF_NAGLEMEMERR;
00427 TCP_STATS_INC(tcp.memerr);
00428
00429 if (queue != NULL) {
00430 tcp_segs_free(queue);
00431 }
00432 if (pcb->snd_queuelen != 0) {
00433 LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
00434 pcb->unsent != NULL);
00435 }
00436 LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
00437 return ERR_MEM;
00438 }
00439
00440
00441 #if LWIP_TCP_TIMESTAMPS
00442
00443
00444
00445
00446
00447 static void
00448 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
00449 {
00450
00451 opts[0] = htonl(0x0101080A);
00452 opts[1] = htonl(sys_now());
00453 opts[2] = htonl(pcb->ts_recent);
00454 }
00455 #endif
00456
00457
00458
00459
00460
00461 err_t
00462 tcp_send_empty_ack(struct tcp_pcb *pcb)
00463 {
00464 struct pbuf *p;
00465 struct tcp_hdr *tcphdr;
00466 u8_t optlen = 0;
00467
00468 #if LWIP_TCP_TIMESTAMPS
00469 if (pcb->flags & TF_TIMESTAMP) {
00470 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
00471 }
00472 #endif
00473 p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
00474 if (p == NULL) {
00475 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
00476 return ERR_BUF;
00477 }
00478 LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
00479 ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
00480
00481 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00482
00483 tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
00484
00485
00486 #if LWIP_TCP_TIMESTAMPS
00487 pcb->ts_lastacksent = pcb->rcv_nxt;
00488
00489 if (pcb->flags & TF_TIMESTAMP) {
00490 tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
00491 }
00492 #endif
00493
00494 #if CHECKSUM_GEN_TCP
00495 tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
00496 IP_PROTO_TCP, p->tot_len);
00497 #endif
00498 #if LWIP_NETIF_HWADDRHINT
00499 ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00500 IP_PROTO_TCP, &(pcb->addr_hint));
00501 #else
00502 ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00503 IP_PROTO_TCP);
00504 #endif
00505 pbuf_free(p);
00506
00507 return ERR_OK;
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517 err_t
00518 tcp_output(struct tcp_pcb *pcb)
00519 {
00520 struct tcp_seg *seg, *useg;
00521 u32_t wnd, snd_nxt;
00522 #if TCP_CWND_DEBUG
00523 s16_t i = 0;
00524 #endif
00525
00526
00527
00528
00529
00530 if (tcp_input_pcb == pcb) {
00531 return ERR_OK;
00532 }
00533
00534 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
00535
00536 seg = pcb->unsent;
00537
00538
00539
00540
00541
00542
00543
00544 if (pcb->flags & TF_ACK_NOW &&
00545 (seg == NULL ||
00546 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
00547 return tcp_send_empty_ack(pcb);
00548 }
00549
00550
00551 useg = pcb->unacked;
00552 if (useg != NULL) {
00553 for (; useg->next != NULL; useg = useg->next);
00554 }
00555
00556 #if TCP_OUTPUT_DEBUG
00557 if (seg == NULL) {
00558 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n",
00559 (void*)pcb->unsent));
00560 }
00561 #endif
00562 #if TCP_CWND_DEBUG
00563 if (seg == NULL) {
00564 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F
00565 ", cwnd %"U16_F", wnd %"U32_F
00566 ", seg == NULL, ack %"U32_F"\n",
00567 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
00568 } else {
00569 LWIP_DEBUGF(TCP_CWND_DEBUG,
00570 ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F
00571 ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
00572 pcb->snd_wnd, pcb->cwnd, wnd,
00573 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
00574 ntohl(seg->tcphdr->seqno), pcb->lastack));
00575 }
00576 #endif
00577
00578 while (seg != NULL &&
00579 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
00580 LWIP_ASSERT("RST not expected here!",
00581 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
00582
00583
00584
00585
00586
00587
00588
00589 if((tcp_do_output_nagle(pcb) == 0) &&
00590 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
00591 break;
00592 }
00593 #if TCP_CWND_DEBUG
00594 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
00595 pcb->snd_wnd, pcb->cwnd, wnd,
00596 ntohl(seg->tcphdr->seqno) + seg->len -
00597 pcb->lastack,
00598 ntohl(seg->tcphdr->seqno), pcb->lastack, i));
00599 ++i;
00600 #endif
00601
00602 pcb->unsent = seg->next;
00603
00604 if (pcb->state != SYN_SENT) {
00605 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
00606 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00607 }
00608
00609 tcp_output_segment(seg, pcb);
00610 snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
00611 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
00612 pcb->snd_nxt = snd_nxt;
00613 }
00614
00615 if (TCP_TCPLEN(seg) > 0) {
00616 seg->next = NULL;
00617
00618 if (pcb->unacked == NULL) {
00619 pcb->unacked = seg;
00620 useg = seg;
00621
00622 } else {
00623
00624
00625
00626 if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
00627
00628 struct tcp_seg **cur_seg = &(pcb->unacked);
00629 while (*cur_seg &&
00630 TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
00631 cur_seg = &((*cur_seg)->next );
00632 }
00633 seg->next = (*cur_seg);
00634 (*cur_seg) = seg;
00635 } else {
00636
00637 useg->next = seg;
00638 useg = useg->next;
00639 }
00640 }
00641
00642 } else {
00643 tcp_seg_free(seg);
00644 }
00645 seg = pcb->unsent;
00646 }
00647
00648 if (seg != NULL && pcb->persist_backoff == 0 &&
00649 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
00650
00651 pcb->persist_cnt = 0;
00652 pcb->persist_backoff = 1;
00653 }
00654
00655 pcb->flags &= ~TF_NAGLEMEMERR;
00656 return ERR_OK;
00657 }
00658
00659
00660
00661
00662
00663
00664
00665 static void
00666 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
00667 {
00668 u16_t len;
00669 struct netif *netif;
00670 u32_t *opts;
00671
00672
00673 snmp_inc_tcpoutsegs();
00674
00675
00676
00677 seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
00678
00679
00680 seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
00681
00682 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
00683
00684
00685
00686 opts = (u32_t *)(seg->tcphdr + 1);
00687 if (seg->flags & TF_SEG_OPTS_MSS) {
00688 TCP_BUILD_MSS_OPTION(*opts);
00689 opts += 1;
00690 }
00691 #if LWIP_TCP_TIMESTAMPS
00692 pcb->ts_lastacksent = pcb->rcv_nxt;
00693
00694 if (seg->flags & TF_SEG_OPTS_TS) {
00695 tcp_build_timestamp_option(pcb, opts);
00696 opts += 3;
00697 }
00698 #endif
00699
00700
00701
00702 if (ip_addr_isany(&(pcb->local_ip))) {
00703 netif = ip_route(&(pcb->remote_ip));
00704 if (netif == NULL) {
00705 return;
00706 }
00707 ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
00708 }
00709
00710
00711 if(pcb->rtime == -1)
00712 pcb->rtime = 0;
00713
00714 if (pcb->rttest == 0) {
00715 pcb->rttest = tcp_ticks;
00716 pcb->rtseq = ntohl(seg->tcphdr->seqno);
00717
00718 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
00719 }
00720 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
00721 htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
00722 seg->len));
00723
00724 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
00725
00726 seg->p->len -= len;
00727 seg->p->tot_len -= len;
00728
00729 seg->p->payload = seg->tcphdr;
00730
00731 seg->tcphdr->chksum = 0;
00732 #if CHECKSUM_GEN_TCP
00733 seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
00734 &(pcb->local_ip),
00735 &(pcb->remote_ip),
00736 IP_PROTO_TCP, seg->p->tot_len);
00737 #endif
00738 TCP_STATS_INC(tcp.xmit);
00739
00740 #if LWIP_NETIF_HWADDRHINT
00741 ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00742 IP_PROTO_TCP, &(pcb->addr_hint));
00743 #else
00744 ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00745 IP_PROTO_TCP);
00746 #endif
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 void
00770 tcp_rst(u32_t seqno, u32_t ackno,
00771 struct ip_addr *local_ip, struct ip_addr *remote_ip,
00772 u16_t local_port, u16_t remote_port)
00773 {
00774 struct pbuf *p;
00775 struct tcp_hdr *tcphdr;
00776 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
00777 if (p == NULL) {
00778 LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
00779 return;
00780 }
00781 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
00782 (p->len >= sizeof(struct tcp_hdr)));
00783
00784 tcphdr = p->payload;
00785 tcphdr->src = htons(local_port);
00786 tcphdr->dest = htons(remote_port);
00787 tcphdr->seqno = htonl(seqno);
00788 tcphdr->ackno = htonl(ackno);
00789 TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
00790 tcphdr->wnd = htons(TCP_WND);
00791 tcphdr->urgp = 0;
00792 TCPH_HDRLEN_SET(tcphdr, 5);
00793
00794 tcphdr->chksum = 0;
00795 #if CHECKSUM_GEN_TCP
00796 tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
00797 IP_PROTO_TCP, p->tot_len);
00798 #endif
00799 TCP_STATS_INC(tcp.xmit);
00800 snmp_inc_tcpoutrsts();
00801
00802 ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
00803 pbuf_free(p);
00804 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814 void
00815 tcp_rexmit_rto(struct tcp_pcb *pcb)
00816 {
00817 struct tcp_seg *seg;
00818
00819 if (pcb->unacked == NULL) {
00820 return;
00821 }
00822
00823
00824 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
00825
00826 seg->next = pcb->unsent;
00827
00828 pcb->unsent = pcb->unacked;
00829
00830 pcb->unacked = NULL;
00831
00832
00833 ++pcb->nrtx;
00834
00835
00836 pcb->rttest = 0;
00837
00838
00839 tcp_output(pcb);
00840 }
00841
00842
00843
00844
00845
00846
00847
00848
00849 void
00850 tcp_rexmit(struct tcp_pcb *pcb)
00851 {
00852 struct tcp_seg *seg;
00853 struct tcp_seg **cur_seg;
00854
00855 if (pcb->unacked == NULL) {
00856 return;
00857 }
00858
00859
00860
00861 seg = pcb->unacked;
00862 pcb->unacked = seg->next;
00863
00864 cur_seg = &(pcb->unsent);
00865 while (*cur_seg &&
00866 TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
00867 cur_seg = &((*cur_seg)->next );
00868 }
00869 seg->next = *cur_seg;
00870 *cur_seg = seg;
00871
00872 ++pcb->nrtx;
00873
00874
00875 pcb->rttest = 0;
00876
00877
00878 snmp_inc_tcpretranssegs();
00879
00880
00881 }
00882
00883
00884
00885
00886
00887
00888
00889 void
00890 tcp_rexmit_fast(struct tcp_pcb *pcb)
00891 {
00892 if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
00893
00894 LWIP_DEBUGF(TCP_FR_DEBUG,
00895 ("tcp_receive: dupacks %"U16_F" (%"U32_F
00896 "), fast retransmit %"U32_F"\n",
00897 (u16_t)pcb->dupacks, pcb->lastack,
00898 ntohl(pcb->unacked->tcphdr->seqno)));
00899 tcp_rexmit(pcb);
00900
00901
00902
00903 if (pcb->cwnd > pcb->snd_wnd)
00904 pcb->ssthresh = pcb->snd_wnd / 2;
00905 else
00906 pcb->ssthresh = pcb->cwnd / 2;
00907
00908
00909 if (pcb->ssthresh < 2*pcb->mss) {
00910 LWIP_DEBUGF(TCP_FR_DEBUG,
00911 ("tcp_receive: The minimum value for ssthresh %"U16_F
00912 " should be min 2 mss %"U16_F"...\n",
00913 pcb->ssthresh, 2*pcb->mss));
00914 pcb->ssthresh = 2*pcb->mss;
00915 }
00916
00917 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
00918 pcb->flags |= TF_INFR;
00919 }
00920 }
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931 void
00932 tcp_keepalive(struct tcp_pcb *pcb)
00933 {
00934 struct pbuf *p;
00935 struct tcp_hdr *tcphdr;
00936
00937 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00938 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
00939 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
00940
00941 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
00942 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
00943
00944 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
00945
00946 if(p == NULL) {
00947 LWIP_DEBUGF(TCP_DEBUG,
00948 ("tcp_keepalive: could not allocate memory for pbuf\n"));
00949 return;
00950 }
00951 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
00952 (p->len >= sizeof(struct tcp_hdr)));
00953
00954 tcphdr = tcp_output_set_header(pcb, p, 0, htonl(pcb->snd_nxt - 1));
00955
00956 #if CHECKSUM_GEN_TCP
00957 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
00958 IP_PROTO_TCP, p->tot_len);
00959 #endif
00960 TCP_STATS_INC(tcp.xmit);
00961
00962
00963 #if LWIP_NETIF_HWADDRHINT
00964 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
00965 &(pcb->addr_hint));
00966 #else
00967 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
00968 #endif
00969
00970 pbuf_free(p);
00971
00972 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n",
00973 pcb->snd_nxt - 1, pcb->rcv_nxt));
00974 }
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985 void
00986 tcp_zero_window_probe(struct tcp_pcb *pcb)
00987 {
00988 struct pbuf *p;
00989 struct tcp_hdr *tcphdr;
00990 struct tcp_seg *seg;
00991 u16_t len;
00992 u8_t is_fin;
00993
00994 LWIP_DEBUGF(TCP_DEBUG,
00995 ("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
00996 U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00997 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
00998 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
00999
01000 LWIP_DEBUGF(TCP_DEBUG,
01001 ("tcp_zero_window_probe: tcp_ticks %"U32_F
01002 " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
01003 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
01004
01005 seg = pcb->unacked;
01006
01007 if(seg == NULL)
01008 seg = pcb->unsent;
01009
01010 if(seg == NULL)
01011 return;
01012
01013 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
01014 len = is_fin ? TCP_HLEN : TCP_HLEN + 1;
01015
01016 p = pbuf_alloc(PBUF_IP, len, PBUF_RAM);
01017 if(p == NULL) {
01018 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
01019 return;
01020 }
01021 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
01022 (p->len >= sizeof(struct tcp_hdr)));
01023
01024 tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
01025
01026 if (is_fin) {
01027
01028 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
01029 } else {
01030
01031 *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
01032 }
01033
01034 #if CHECKSUM_GEN_TCP
01035 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
01036 IP_PROTO_TCP, p->tot_len);
01037 #endif
01038 TCP_STATS_INC(tcp.xmit);
01039
01040
01041 #if LWIP_NETIF_HWADDRHINT
01042 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
01043 &(pcb->addr_hint));
01044 #else
01045 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
01046 #endif
01047
01048 pbuf_free(p);
01049
01050 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
01051 " ackno %"U32_F".\n",
01052 pcb->snd_nxt - 1, pcb->rcv_nxt));
01053 }
01054 #endif