Warning, cross-references for /kernel/lwip/core/tcp_out.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 #include "lwip/opt.h"
0042
0043 #if LWIP_TCP
0044
0045 #include "lwip/tcp.h"
0046 #include "lwip/def.h"
0047 #include "lwip/mem.h"
0048 #include "lwip/memp.h"
0049 #include "lwip/sys.h"
0050 #include "lwip/ip_addr.h"
0051 #include "lwip/netif.h"
0052 #include "lwip/inet.h"
0053 #include "lwip/inet_chksum.h"
0054 #include "lwip/stats.h"
0055 #include "lwip/snmp.h"
0056
0057 #include <string.h>
0058
0059
0060 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
0061
0062 static struct tcp_hdr *
0063 tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen,
0064 u32_t seqno_be )
0065 {
0066 struct tcp_hdr *tcphdr = p->payload;
0067 tcphdr->src = htons(pcb->local_port);
0068 tcphdr->dest = htons(pcb->remote_port);
0069 tcphdr->seqno = seqno_be;
0070 tcphdr->ackno = htonl(pcb->rcv_nxt);
0071 TCPH_FLAGS_SET(tcphdr, TCP_ACK);
0072 tcphdr->wnd = htons(pcb->rcv_ann_wnd);
0073 tcphdr->urgp = 0;
0074 TCPH_HDRLEN_SET(tcphdr, (5 + optlen / 4));
0075 tcphdr->chksum = 0;
0076
0077
0078 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
0079
0080 return tcphdr;
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090 err_t
0091 tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
0092 {
0093
0094 return tcp_enqueue(pcb, NULL, 0, flags, TCP_WRITE_FLAG_COPY, 0);
0095 }
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 err_t
0116 tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
0117 {
0118 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", (void *)pcb,
0119 data, len, (u16_t)apiflags));
0120
0121 if (pcb->state == ESTABLISHED ||
0122 pcb->state == CLOSE_WAIT ||
0123 pcb->state == SYN_SENT ||
0124 pcb->state == SYN_RCVD) {
0125 if (len > 0) {
0126 #if LWIP_TCP_TIMESTAMPS
0127 return tcp_enqueue(pcb, (void *)data, len, 0, apiflags,
0128 pcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0);
0129 #else
0130 return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 0);
0131 #endif
0132 }
0133 return ERR_OK;
0134 } else {
0135 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
0136 return ERR_CONN;
0137 }
0138 }
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 err_t
0155 tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
0156 u8_t flags, u8_t apiflags, u8_t optflags)
0157 {
0158 struct pbuf *p;
0159 struct tcp_seg *seg, *useg, *queue;
0160 u32_t seqno;
0161 u16_t left, seglen;
0162 void *ptr;
0163 u16_t queuelen;
0164 u8_t optlen;
0165
0166 LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
0167 ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", apiflags=%"U16_F")\n",
0168 (void *)pcb, arg, len, (u16_t)flags, (u16_t)apiflags));
0169 LWIP_ERROR("tcp_enqueue: packet needs payload, options, or SYN/FIN (programmer violates API)",
0170 ((len != 0) || (optflags != 0) || ((flags & (TCP_SYN | TCP_FIN)) != 0)),
0171 return ERR_ARG;);
0172 LWIP_ERROR("tcp_enqueue: len != 0 || arg == NULL (programmer violates API)",
0173 ((len != 0) || (arg == NULL)), return ERR_ARG;);
0174
0175
0176 if (len > pcb->snd_buf) {
0177 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
0178 ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
0179 pcb->flags |= TF_NAGLEMEMERR;
0180 return ERR_MEM;
0181 }
0182 left = len;
0183 ptr = arg;
0184
0185 optlen = LWIP_TCP_OPT_LENGTH(optflags);
0186
0187
0188
0189 seqno = pcb->snd_lbb;
0190
0191 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
0192
0193
0194
0195 queuelen = pcb->snd_queuelen;
0196
0197 if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
0198 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
0199 ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
0200 TCP_STATS_INC(tcp.memerr);
0201 pcb->flags |= TF_NAGLEMEMERR;
0202 return ERR_MEM;
0203 }
0204 if (queuelen != 0) {
0205 LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
0206 pcb->unacked != NULL || pcb->unsent != NULL);
0207 } else {
0208 LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
0209 pcb->unacked == NULL && pcb->unsent == NULL);
0210 }
0211
0212
0213
0214 useg = queue = seg = NULL;
0215 seglen = 0;
0216 while (queue == NULL || left > 0) {
0217
0218 seglen = left > (pcb->mss - optlen) ? (pcb->mss - optlen) : left;
0219
0220
0221 seg = memp_malloc(MEMP_TCP_SEG);
0222 if (seg == NULL) {
0223 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
0224 ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
0225 goto memerr;
0226 }
0227 seg->next = NULL;
0228 seg->p = NULL;
0229
0230
0231 if (queue == NULL) {
0232 queue = seg;
0233 }
0234
0235 else {
0236
0237 LWIP_ASSERT("useg != NULL", useg != NULL);
0238 useg->next = seg;
0239 }
0240
0241 useg = seg;
0242
0243
0244
0245
0246 if (apiflags & TCP_WRITE_FLAG_COPY) {
0247 if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) {
0248 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
0249 ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
0250 goto memerr;
0251 }
0252 LWIP_ASSERT("check that first pbuf can hold the complete seglen",
0253 (seg->p->len >= seglen + optlen));
0254 queuelen += pbuf_clen(seg->p);
0255 if (arg != NULL) {
0256 MEMCPY((char *)seg->p->payload + optlen, ptr, seglen);
0257 }
0258 seg->dataptr = seg->p->payload;
0259 }
0260
0261 else {
0262
0263 if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
0264 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
0265 ("tcp_enqueue: could not allocate memory for header pbuf\n"));
0266 goto memerr;
0267 }
0268 queuelen += pbuf_clen(seg->p);
0269
0270
0271
0272
0273
0274
0275 if (left > 0) {
0276 if ((p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
0277
0278 pbuf_free(seg->p);
0279 seg->p = NULL;
0280 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
0281 ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
0282 goto memerr;
0283 }
0284 ++queuelen;
0285
0286 p->payload = ptr;
0287 seg->dataptr = ptr;
0288
0289
0290 pbuf_cat(seg->p, p);
0291 p = NULL;
0292 }
0293 }
0294
0295
0296
0297 if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
0298 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
0299 ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
0300 goto memerr;
0301 }
0302
0303 seg->len = seglen;
0304
0305
0306 if (pbuf_header(seg->p, TCP_HLEN)) {
0307 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
0308 TCP_STATS_INC(tcp.err);
0309 goto memerr;
0310 }
0311 seg->tcphdr = seg->p->payload;
0312 seg->tcphdr->src = htons(pcb->local_port);
0313 seg->tcphdr->dest = htons(pcb->remote_port);
0314 seg->tcphdr->seqno = htonl(seqno);
0315 seg->tcphdr->urgp = 0;
0316 TCPH_FLAGS_SET(seg->tcphdr, flags);
0317
0318
0319 seg->flags = optflags;
0320
0321
0322 TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
0323 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
0324 ntohl(seg->tcphdr->seqno),
0325 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
0326 (u16_t)flags));
0327
0328 left -= seglen;
0329 seqno += seglen;
0330 ptr = (void *)((u8_t *)ptr + seglen);
0331 }
0332
0333
0334
0335
0336 if (pcb->unsent == NULL) {
0337 useg = NULL;
0338 }
0339 else {
0340 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
0341 }
0342
0343
0344
0345
0346 if (useg != NULL &&
0347 TCP_TCPLEN(useg) != 0 &&
0348 !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
0349 (!(flags & (TCP_SYN | TCP_FIN)) || (flags == TCP_FIN)) &&
0350
0351 (useg->len + queue->len <= pcb->mss) &&
0352
0353 (useg->flags == queue->flags) &&
0354
0355 (ntohl(useg->tcphdr->seqno) + useg->len == ntohl(queue->tcphdr->seqno)) ) {
0356
0357 if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
0358
0359 LWIP_ASSERT("pbuf_header failed\n", 0);
0360 TCP_STATS_INC(tcp.err);
0361 goto memerr;
0362 }
0363 if (queue->p->len == 0) {
0364
0365 struct pbuf *old_q = queue->p;
0366 queue->p = queue->p->next;
0367 old_q->next = NULL;
0368 queuelen--;
0369 pbuf_free(old_q);
0370 }
0371 if (flags & TCP_FIN) {
0372
0373 LWIP_ASSERT("FIN enqueued together with data", queue->p == NULL && queue->len == 0);
0374 TCPH_SET_FLAG(useg->tcphdr, TCP_FIN);
0375 } else {
0376 LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
0377 pbuf_cat(useg->p, queue->p);
0378 useg->len += queue->len;
0379 useg->next = queue->next;
0380 }
0381
0382 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
0383 if (seg == queue) {
0384 seg = useg;
0385 seglen = useg->len;
0386 }
0387 memp_free(MEMP_TCP_SEG, queue);
0388 }
0389 else {
0390
0391 if (useg == NULL) {
0392
0393 pcb->unsent = queue;
0394 }
0395
0396 else {
0397 useg->next = queue;
0398 }
0399 }
0400 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
0401 ++len;
0402 }
0403 if (flags & TCP_FIN) {
0404 pcb->flags |= TF_FIN;
0405 }
0406 pcb->snd_lbb += len;
0407
0408 pcb->snd_buf -= len;
0409
0410
0411 pcb->snd_queuelen = queuelen;
0412 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
0413 if (pcb->snd_queuelen != 0) {
0414 LWIP_ASSERT("tcp_enqueue: valid queue length",
0415 pcb->unacked != NULL || pcb->unsent != NULL);
0416 }
0417
0418
0419
0420 if (seg != NULL && seglen > 0 && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
0421 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
0422 }
0423
0424 return ERR_OK;
0425 memerr:
0426 pcb->flags |= TF_NAGLEMEMERR;
0427 TCP_STATS_INC(tcp.memerr);
0428
0429 if (queue != NULL) {
0430 tcp_segs_free(queue);
0431 }
0432 if (pcb->snd_queuelen != 0) {
0433 LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
0434 pcb->unsent != NULL);
0435 }
0436 LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
0437 return ERR_MEM;
0438 }
0439
0440
0441 #if LWIP_TCP_TIMESTAMPS
0442
0443
0444
0445
0446
0447 static void
0448 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
0449 {
0450
0451 opts[0] = htonl(0x0101080A);
0452 opts[1] = htonl(sys_now());
0453 opts[2] = htonl(pcb->ts_recent);
0454 }
0455 #endif
0456
0457
0458
0459
0460
0461 err_t
0462 tcp_send_empty_ack(struct tcp_pcb *pcb)
0463 {
0464 struct pbuf *p;
0465 struct tcp_hdr *tcphdr;
0466 u8_t optlen = 0;
0467
0468 #if LWIP_TCP_TIMESTAMPS
0469 if (pcb->flags & TF_TIMESTAMP) {
0470 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
0471 }
0472 #endif
0473 p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
0474 if (p == NULL) {
0475 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
0476 return ERR_BUF;
0477 }
0478 LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
0479 ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
0480
0481 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
0482
0483 tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
0484
0485
0486 #if LWIP_TCP_TIMESTAMPS
0487 pcb->ts_lastacksent = pcb->rcv_nxt;
0488
0489 if (pcb->flags & TF_TIMESTAMP) {
0490 tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
0491 }
0492 #endif
0493
0494 #if CHECKSUM_GEN_TCP
0495 tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
0496 IP_PROTO_TCP, p->tot_len);
0497 #endif
0498 #if LWIP_NETIF_HWADDRHINT
0499 ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
0500 IP_PROTO_TCP, &(pcb->addr_hint));
0501 #else
0502 ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
0503 IP_PROTO_TCP);
0504 #endif
0505 pbuf_free(p);
0506
0507 return ERR_OK;
0508 }
0509
0510
0511
0512
0513
0514
0515
0516
0517 err_t
0518 tcp_output(struct tcp_pcb *pcb)
0519 {
0520 struct tcp_seg *seg, *useg;
0521 u32_t wnd, snd_nxt;
0522 #if TCP_CWND_DEBUG
0523 s16_t i = 0;
0524 #endif
0525
0526
0527
0528
0529
0530 if (tcp_input_pcb == pcb) {
0531 return ERR_OK;
0532 }
0533
0534 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
0535
0536 seg = pcb->unsent;
0537
0538
0539
0540
0541
0542
0543
0544 if (pcb->flags & TF_ACK_NOW &&
0545 (seg == NULL ||
0546 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
0547 return tcp_send_empty_ack(pcb);
0548 }
0549
0550
0551 useg = pcb->unacked;
0552 if (useg != NULL) {
0553 for (; useg->next != NULL; useg = useg->next);
0554 }
0555
0556 #if TCP_OUTPUT_DEBUG
0557 if (seg == NULL) {
0558 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n",
0559 (void*)pcb->unsent));
0560 }
0561 #endif
0562 #if TCP_CWND_DEBUG
0563 if (seg == NULL) {
0564 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F
0565 ", cwnd %"U16_F", wnd %"U32_F
0566 ", seg == NULL, ack %"U32_F"\n",
0567 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
0568 } else {
0569 LWIP_DEBUGF(TCP_CWND_DEBUG,
0570 ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F
0571 ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
0572 pcb->snd_wnd, pcb->cwnd, wnd,
0573 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
0574 ntohl(seg->tcphdr->seqno), pcb->lastack));
0575 }
0576 #endif
0577
0578 while (seg != NULL &&
0579 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
0580 LWIP_ASSERT("RST not expected here!",
0581 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
0582
0583
0584
0585
0586
0587
0588
0589 if((tcp_do_output_nagle(pcb) == 0) &&
0590 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
0591 break;
0592 }
0593 #if TCP_CWND_DEBUG
0594 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",
0595 pcb->snd_wnd, pcb->cwnd, wnd,
0596 ntohl(seg->tcphdr->seqno) + seg->len -
0597 pcb->lastack,
0598 ntohl(seg->tcphdr->seqno), pcb->lastack, i));
0599 ++i;
0600 #endif
0601
0602 pcb->unsent = seg->next;
0603
0604 if (pcb->state != SYN_SENT) {
0605 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
0606 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
0607 }
0608
0609 tcp_output_segment(seg, pcb);
0610 snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
0611 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
0612 pcb->snd_nxt = snd_nxt;
0613 }
0614
0615 if (TCP_TCPLEN(seg) > 0) {
0616 seg->next = NULL;
0617
0618 if (pcb->unacked == NULL) {
0619 pcb->unacked = seg;
0620 useg = seg;
0621
0622 } else {
0623
0624
0625
0626 if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
0627
0628 struct tcp_seg **cur_seg = &(pcb->unacked);
0629 while (*cur_seg &&
0630 TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
0631 cur_seg = &((*cur_seg)->next );
0632 }
0633 seg->next = (*cur_seg);
0634 (*cur_seg) = seg;
0635 } else {
0636
0637 useg->next = seg;
0638 useg = useg->next;
0639 }
0640 }
0641
0642 } else {
0643 tcp_seg_free(seg);
0644 }
0645 seg = pcb->unsent;
0646 }
0647
0648 if (seg != NULL && pcb->persist_backoff == 0 &&
0649 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
0650
0651 pcb->persist_cnt = 0;
0652 pcb->persist_backoff = 1;
0653 }
0654
0655 pcb->flags &= ~TF_NAGLEMEMERR;
0656 return ERR_OK;
0657 }
0658
0659
0660
0661
0662
0663
0664
0665 static void
0666 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
0667 {
0668 u16_t len;
0669 struct netif *netif;
0670 u32_t *opts;
0671
0672
0673 snmp_inc_tcpoutsegs();
0674
0675
0676
0677 seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
0678
0679
0680 seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
0681
0682 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
0683
0684
0685
0686 opts = (u32_t *)(seg->tcphdr + 1);
0687 if (seg->flags & TF_SEG_OPTS_MSS) {
0688 TCP_BUILD_MSS_OPTION(*opts);
0689 opts += 1;
0690 }
0691 #if LWIP_TCP_TIMESTAMPS
0692 pcb->ts_lastacksent = pcb->rcv_nxt;
0693
0694 if (seg->flags & TF_SEG_OPTS_TS) {
0695 tcp_build_timestamp_option(pcb, opts);
0696 opts += 3;
0697 }
0698 #endif
0699
0700
0701
0702 if (ip_addr_isany(&(pcb->local_ip))) {
0703 netif = ip_route(&(pcb->remote_ip));
0704 if (netif == NULL) {
0705 return;
0706 }
0707 ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
0708 }
0709
0710
0711 if(pcb->rtime == -1)
0712 pcb->rtime = 0;
0713
0714 if (pcb->rttest == 0) {
0715 pcb->rttest = tcp_ticks;
0716 pcb->rtseq = ntohl(seg->tcphdr->seqno);
0717
0718 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
0719 }
0720 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
0721 htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
0722 seg->len));
0723
0724 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
0725
0726 seg->p->len -= len;
0727 seg->p->tot_len -= len;
0728
0729 seg->p->payload = seg->tcphdr;
0730
0731 seg->tcphdr->chksum = 0;
0732 #if CHECKSUM_GEN_TCP
0733 seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
0734 &(pcb->local_ip),
0735 &(pcb->remote_ip),
0736 IP_PROTO_TCP, seg->p->tot_len);
0737 #endif
0738 TCP_STATS_INC(tcp.xmit);
0739
0740 #if LWIP_NETIF_HWADDRHINT
0741 ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
0742 IP_PROTO_TCP, &(pcb->addr_hint));
0743 #else
0744 ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
0745 IP_PROTO_TCP);
0746 #endif
0747 }
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769 void
0770 tcp_rst(u32_t seqno, u32_t ackno,
0771 struct ip_addr *local_ip, struct ip_addr *remote_ip,
0772 u16_t local_port, u16_t remote_port)
0773 {
0774 struct pbuf *p;
0775 struct tcp_hdr *tcphdr;
0776 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
0777 if (p == NULL) {
0778 LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
0779 return;
0780 }
0781 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
0782 (p->len >= sizeof(struct tcp_hdr)));
0783
0784 tcphdr = p->payload;
0785 tcphdr->src = htons(local_port);
0786 tcphdr->dest = htons(remote_port);
0787 tcphdr->seqno = htonl(seqno);
0788 tcphdr->ackno = htonl(ackno);
0789 TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
0790 tcphdr->wnd = htons(TCP_WND);
0791 tcphdr->urgp = 0;
0792 TCPH_HDRLEN_SET(tcphdr, 5);
0793
0794 tcphdr->chksum = 0;
0795 #if CHECKSUM_GEN_TCP
0796 tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
0797 IP_PROTO_TCP, p->tot_len);
0798 #endif
0799 TCP_STATS_INC(tcp.xmit);
0800 snmp_inc_tcpoutrsts();
0801
0802 ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
0803 pbuf_free(p);
0804 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
0805 }
0806
0807
0808
0809
0810
0811
0812
0813
0814 void
0815 tcp_rexmit_rto(struct tcp_pcb *pcb)
0816 {
0817 struct tcp_seg *seg;
0818
0819 if (pcb->unacked == NULL) {
0820 return;
0821 }
0822
0823
0824 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
0825
0826 seg->next = pcb->unsent;
0827
0828 pcb->unsent = pcb->unacked;
0829
0830 pcb->unacked = NULL;
0831
0832
0833 ++pcb->nrtx;
0834
0835
0836 pcb->rttest = 0;
0837
0838
0839 tcp_output(pcb);
0840 }
0841
0842
0843
0844
0845
0846
0847
0848
0849 void
0850 tcp_rexmit(struct tcp_pcb *pcb)
0851 {
0852 struct tcp_seg *seg;
0853 struct tcp_seg **cur_seg;
0854
0855 if (pcb->unacked == NULL) {
0856 return;
0857 }
0858
0859
0860
0861 seg = pcb->unacked;
0862 pcb->unacked = seg->next;
0863
0864 cur_seg = &(pcb->unsent);
0865 while (*cur_seg &&
0866 TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
0867 cur_seg = &((*cur_seg)->next );
0868 }
0869 seg->next = *cur_seg;
0870 *cur_seg = seg;
0871
0872 ++pcb->nrtx;
0873
0874
0875 pcb->rttest = 0;
0876
0877
0878 snmp_inc_tcpretranssegs();
0879
0880
0881 }
0882
0883
0884
0885
0886
0887
0888
0889 void
0890 tcp_rexmit_fast(struct tcp_pcb *pcb)
0891 {
0892 if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
0893
0894 LWIP_DEBUGF(TCP_FR_DEBUG,
0895 ("tcp_receive: dupacks %"U16_F" (%"U32_F
0896 "), fast retransmit %"U32_F"\n",
0897 (u16_t)pcb->dupacks, pcb->lastack,
0898 ntohl(pcb->unacked->tcphdr->seqno)));
0899 tcp_rexmit(pcb);
0900
0901
0902
0903 if (pcb->cwnd > pcb->snd_wnd)
0904 pcb->ssthresh = pcb->snd_wnd / 2;
0905 else
0906 pcb->ssthresh = pcb->cwnd / 2;
0907
0908
0909 if (pcb->ssthresh < 2*pcb->mss) {
0910 LWIP_DEBUGF(TCP_FR_DEBUG,
0911 ("tcp_receive: The minimum value for ssthresh %"U16_F
0912 " should be min 2 mss %"U16_F"...\n",
0913 pcb->ssthresh, 2*pcb->mss));
0914 pcb->ssthresh = 2*pcb->mss;
0915 }
0916
0917 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
0918 pcb->flags |= TF_INFR;
0919 }
0920 }
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931 void
0932 tcp_keepalive(struct tcp_pcb *pcb)
0933 {
0934 struct pbuf *p;
0935 struct tcp_hdr *tcphdr;
0936
0937 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
0938 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
0939 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
0940
0941 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
0942 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
0943
0944 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
0945
0946 if(p == NULL) {
0947 LWIP_DEBUGF(TCP_DEBUG,
0948 ("tcp_keepalive: could not allocate memory for pbuf\n"));
0949 return;
0950 }
0951 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
0952 (p->len >= sizeof(struct tcp_hdr)));
0953
0954 tcphdr = tcp_output_set_header(pcb, p, 0, htonl(pcb->snd_nxt - 1));
0955
0956 #if CHECKSUM_GEN_TCP
0957 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
0958 IP_PROTO_TCP, p->tot_len);
0959 #endif
0960 TCP_STATS_INC(tcp.xmit);
0961
0962
0963 #if LWIP_NETIF_HWADDRHINT
0964 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
0965 &(pcb->addr_hint));
0966 #else
0967 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
0968 #endif
0969
0970 pbuf_free(p);
0971
0972 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n",
0973 pcb->snd_nxt - 1, pcb->rcv_nxt));
0974 }
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985 void
0986 tcp_zero_window_probe(struct tcp_pcb *pcb)
0987 {
0988 struct pbuf *p;
0989 struct tcp_hdr *tcphdr;
0990 struct tcp_seg *seg;
0991 u16_t len;
0992 u8_t is_fin;
0993
0994 LWIP_DEBUGF(TCP_DEBUG,
0995 ("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
0996 U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
0997 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
0998 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
0999
1000 LWIP_DEBUGF(TCP_DEBUG,
1001 ("tcp_zero_window_probe: tcp_ticks %"U32_F
1002 " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
1003 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
1004
1005 seg = pcb->unacked;
1006
1007 if(seg == NULL)
1008 seg = pcb->unsent;
1009
1010 if(seg == NULL)
1011 return;
1012
1013 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
1014 len = is_fin ? TCP_HLEN : TCP_HLEN + 1;
1015
1016 p = pbuf_alloc(PBUF_IP, len, PBUF_RAM);
1017 if(p == NULL) {
1018 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
1019 return;
1020 }
1021 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
1022 (p->len >= sizeof(struct tcp_hdr)));
1023
1024 tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
1025
1026 if (is_fin) {
1027
1028 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
1029 } else {
1030
1031 *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
1032 }
1033
1034 #if CHECKSUM_GEN_TCP
1035 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
1036 IP_PROTO_TCP, p->tot_len);
1037 #endif
1038 TCP_STATS_INC(tcp.xmit);
1039
1040
1041 #if LWIP_NETIF_HWADDRHINT
1042 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
1043 &(pcb->addr_hint));
1044 #else
1045 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
1046 #endif
1047
1048 pbuf_free(p);
1049
1050 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
1051 " ackno %"U32_F".\n",
1052 pcb->snd_nxt - 1, pcb->rcv_nxt));
1053 }
1054 #endif