1 /** @file 2 TCP output process routines. 3 4 Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php<BR> 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "Tcp4Main.h" 16 17 UINT8 mTcpOutFlag[] = { 18 0, // TCP_CLOSED 19 0, // TCP_LISTEN 20 TCP_FLG_SYN, // TCP_SYN_SENT 21 TCP_FLG_SYN | TCP_FLG_ACK, // TCP_SYN_RCVD 22 TCP_FLG_ACK, // TCP_ESTABLISHED 23 TCP_FLG_FIN | TCP_FLG_ACK, // TCP_FIN_WAIT_1 24 TCP_FLG_ACK, // TCP_FIN_WAIT_2 25 TCP_FLG_ACK | TCP_FLG_FIN, // TCP_CLOSING 26 TCP_FLG_ACK, // TCP_TIME_WAIT 27 TCP_FLG_ACK, // TCP_CLOSE_WAIT 28 TCP_FLG_FIN | TCP_FLG_ACK // TCP_LAST_ACK 29 }; 30 31 32 /** 33 Compute the sequence space left in the old receive window. 34 35 @param Tcb Pointer to the TCP_CB of this TCP instance. 36 37 @return The sequence space left in the old receive window. 38 39 **/ 40 UINT32 41 TcpRcvWinOld ( 42 IN TCP_CB *Tcb 43 ) 44 { 45 UINT32 OldWin; 46 47 OldWin = 0; 48 49 if (TCP_SEQ_GT (Tcb->RcvWl2 + Tcb->RcvWnd, Tcb->RcvNxt)) { 50 51 OldWin = TCP_SUB_SEQ ( 52 Tcb->RcvWl2 + Tcb->RcvWnd, 53 Tcb->RcvNxt 54 ); 55 } 56 57 return OldWin; 58 } 59 60 61 /** 62 Compute the current receive window. 63 64 @param Tcb Pointer to the TCP_CB of this TCP instance. 65 66 @return The size of the current receive window, in bytes. 67 68 **/ 69 UINT32 70 TcpRcvWinNow ( 71 IN TCP_CB *Tcb 72 ) 73 { 74 SOCKET *Sk; 75 UINT32 Win; 76 UINT32 Increase; 77 UINT32 OldWin; 78 79 Sk = Tcb->Sk; 80 ASSERT (Sk != NULL); 81 82 OldWin = TcpRcvWinOld (Tcb); 83 84 Win = SockGetFreeSpace (Sk, SOCK_RCV_BUF); 85 86 Increase = 0; 87 if (Win > OldWin) { 88 Increase = Win - OldWin; 89 } 90 91 // 92 // Receiver's SWS: don't advertise a bigger window 93 // unless it can be increased by at least one Mss or 94 // half of the receive buffer. 95 // 96 if ((Increase > Tcb->SndMss) || 97 (2 * Increase >= GET_RCV_BUFFSIZE (Sk))) { 98 99 return Win; 100 } 101 102 return OldWin; 103 } 104 105 106 /** 107 Compute the value to fill in the window size field of the outgoing segment. 108 109 @param Tcb Pointer to the TCP_CB of this TCP instance. 110 @param Syn The flag to indicate whether the outgoing segment is a SYN 111 segment. 112 113 @return The value of the local receive window size used to fill the outing segment. 114 115 **/ 116 UINT16 117 TcpComputeWnd ( 118 IN OUT TCP_CB *Tcb, 119 IN BOOLEAN Syn 120 ) 121 { 122 UINT32 Wnd; 123 124 // 125 // RFC requires that initial window not be scaled 126 // 127 if (Syn) { 128 129 Wnd = GET_RCV_BUFFSIZE (Tcb->Sk); 130 } else { 131 132 Wnd = TcpRcvWinNow (Tcb); 133 134 Tcb->RcvWnd = Wnd; 135 } 136 137 Wnd = MIN (Wnd >> Tcb->RcvWndScale, 0xffff); 138 return NTOHS ((UINT16) Wnd); 139 } 140 141 142 /** 143 Get the maximum SndNxt. 144 145 @param Tcb Pointer to the TCP_CB of this TCP instance. 146 147 @return The sequence number of the maximum SndNxt. 148 149 **/ 150 TCP_SEQNO 151 TcpGetMaxSndNxt ( 152 IN TCP_CB *Tcb 153 ) 154 { 155 LIST_ENTRY *Entry; 156 NET_BUF *Nbuf; 157 158 if (IsListEmpty (&Tcb->SndQue)) { 159 return Tcb->SndNxt; 160 } 161 162 Entry = Tcb->SndQue.BackLink; 163 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List); 164 165 ASSERT (TCP_SEQ_GEQ (TCPSEG_NETBUF (Nbuf)->End, Tcb->SndNxt)); 166 return TCPSEG_NETBUF (Nbuf)->End; 167 } 168 169 170 /** 171 Compute how much data to send. 172 173 @param Tcb Pointer to the TCP_CB of this TCP instance. 174 @param Force Whether to ignore the sender's SWS avoidance algorithm and send 175 out data by force. 176 177 @return The length of the data can be sent, if 0, no data can be sent. 178 179 **/ 180 UINT32 181 TcpDataToSend ( 182 IN TCP_CB *Tcb, 183 IN INTN Force 184 ) 185 { 186 SOCKET *Sk; 187 UINT32 Win; 188 UINT32 Len; 189 UINT32 Left; 190 UINT32 Limit; 191 192 Sk = Tcb->Sk; 193 ASSERT (Sk != NULL); 194 195 // 196 // TCP should NOT send data beyond the send window 197 // and congestion window. The right edge of send 198 // window is defined as SND.WL2 + SND.WND. The right 199 // edge of congestion window is defined as SND.UNA + 200 // CWND. 201 // 202 Win = 0; 203 Limit = Tcb->SndWl2 + Tcb->SndWnd; 204 205 if (TCP_SEQ_GT (Limit, Tcb->SndUna + Tcb->CWnd)) { 206 207 Limit = Tcb->SndUna + Tcb->CWnd; 208 } 209 210 if (TCP_SEQ_GT (Limit, Tcb->SndNxt)) { 211 Win = TCP_SUB_SEQ (Limit, Tcb->SndNxt); 212 } 213 214 // 215 // The data to send contains two parts: the data on the 216 // socket send queue, and the data on the TCB's send 217 // buffer. The later can be non-zero if the peer shrinks 218 // its advertised window. 219 // 220 Left = GET_SND_DATASIZE (Sk) + 221 TCP_SUB_SEQ (TcpGetMaxSndNxt (Tcb), Tcb->SndNxt); 222 223 Len = MIN (Win, Left); 224 225 if (Len > Tcb->SndMss) { 226 Len = Tcb->SndMss; 227 } 228 229 if ((Force != 0)|| (Len == 0 && Left == 0)) { 230 return Len; 231 } 232 233 if (Len == 0 && Left != 0) { 234 goto SetPersistTimer; 235 } 236 237 // 238 // Sender's SWS avoidance: Don't send a small segment unless 239 // a)A full-sized segment can be sent, 240 // b)at least one-half of the maximum sized windows that 241 // the other end has ever advertised. 242 // c)It can send everything it has and either it isn't 243 // expecting an ACK or the Nagle algorithm is disabled. 244 // 245 if ((Len == Tcb->SndMss) || (2 * Len >= Tcb->SndWndMax)) { 246 247 return Len; 248 } 249 250 if ((Len == Left) && 251 ((Tcb->SndNxt == Tcb->SndUna) || 252 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE))) { 253 254 return Len; 255 } 256 257 // 258 // RFC1122 suggests to set a timer when SWSA forbids TCP 259 // sending more data, and combine it with probe timer. 260 // 261 SetPersistTimer: 262 if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT)) { 263 264 DEBUG ( 265 (EFI_D_WARN, 266 "TcpDataToSend: enter persistent state for TCB %p\n", 267 Tcb) 268 ); 269 270 if (!Tcb->ProbeTimerOn) { 271 TcpSetProbeTimer (Tcb); 272 } 273 } 274 275 return 0; 276 } 277 278 279 /** 280 Build the TCP header of the TCP segment and transmit the segment by IP. 281 282 @param Tcb Pointer to the TCP_CB of this TCP instance. 283 @param Nbuf Pointer to the buffer containing the segment to be sent out. 284 285 @retval 0 The segment is sent out successfully. 286 @retval other Error condition occurred. 287 288 **/ 289 INTN 290 TcpTransmitSegment ( 291 IN OUT TCP_CB *Tcb, 292 IN NET_BUF *Nbuf 293 ) 294 { 295 UINT16 Len; 296 TCP_HEAD *Head; 297 TCP_SEG *Seg; 298 BOOLEAN Syn; 299 UINT32 DataLen; 300 301 ASSERT ((Nbuf != NULL) && (Nbuf->Tcp == NULL) && (TcpVerifySegment (Nbuf) != 0)); 302 303 DataLen = Nbuf->TotalSize; 304 305 Seg = TCPSEG_NETBUF (Nbuf); 306 Syn = TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN); 307 308 if (Syn) { 309 310 Len = TcpSynBuildOption (Tcb, Nbuf); 311 } else { 312 313 Len = TcpBuildOption (Tcb, Nbuf); 314 } 315 316 ASSERT ((Len % 4 == 0) && (Len <= 40)); 317 318 Len += sizeof (TCP_HEAD); 319 320 Head = (TCP_HEAD *) NetbufAllocSpace ( 321 Nbuf, 322 sizeof (TCP_HEAD), 323 NET_BUF_HEAD 324 ); 325 326 ASSERT (Head != NULL); 327 328 Nbuf->Tcp = Head; 329 330 Head->SrcPort = Tcb->LocalEnd.Port; 331 Head->DstPort = Tcb->RemoteEnd.Port; 332 Head->Seq = NTOHL (Seg->Seq); 333 Head->Ack = NTOHL (Tcb->RcvNxt); 334 Head->HeadLen = (UINT8) (Len >> 2); 335 Head->Res = 0; 336 Head->Wnd = TcpComputeWnd (Tcb, Syn); 337 Head->Checksum = 0; 338 339 // 340 // Check whether to set the PSH flag. 341 // 342 TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_PSH); 343 344 if (DataLen != 0) { 345 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_PSH) && 346 TCP_SEQ_BETWEEN (Seg->Seq, Tcb->SndPsh, Seg->End)) { 347 348 TCP_SET_FLG (Seg->Flag, TCP_FLG_PSH); 349 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH); 350 351 } else if ((Seg->End == Tcb->SndNxt) && 352 (GET_SND_DATASIZE (Tcb->Sk) == 0)) { 353 354 TCP_SET_FLG (Seg->Flag, TCP_FLG_PSH); 355 } 356 } 357 358 // 359 // Check whether to set the URG flag and the urgent pointer. 360 // 361 TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_URG); 362 363 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) && 364 TCP_SEQ_LEQ (Seg->Seq, Tcb->SndUp)) { 365 366 TCP_SET_FLG (Seg->Flag, TCP_FLG_URG); 367 368 if (TCP_SEQ_LT (Tcb->SndUp, Seg->End)) { 369 370 Seg->Urg = (UINT16) TCP_SUB_SEQ (Tcb->SndUp, Seg->Seq); 371 } else { 372 373 Seg->Urg = (UINT16) MIN ( 374 TCP_SUB_SEQ (Tcb->SndUp, 375 Seg->Seq), 376 0xffff 377 ); 378 } 379 } 380 381 Head->Flag = Seg->Flag; 382 Head->Urg = NTOHS (Seg->Urg); 383 Head->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum); 384 385 // 386 // update the TCP session's control information 387 // 388 Tcb->RcvWl2 = Tcb->RcvNxt; 389 if (Syn) { 390 Tcb->RcvWnd = NTOHS (Head->Wnd); 391 } 392 393 // 394 // clear delayedack flag 395 // 396 Tcb->DelayedAck = 0; 397 398 return TcpSendIpPacket (Tcb, Nbuf, Tcb->LocalEnd.Ip, Tcb->RemoteEnd.Ip); 399 } 400 401 402 /** 403 Get a segment from the Tcb's SndQue. 404 405 @param Tcb Pointer to the TCP_CB of this TCP instance. 406 @param Seq The sequence number of the segment. 407 @param Len The maximum length of the segment. 408 409 @return Pointer to the segment, if NULL some error occurred. 410 411 **/ 412 NET_BUF * 413 TcpGetSegmentSndQue ( 414 IN TCP_CB *Tcb, 415 IN TCP_SEQNO Seq, 416 IN UINT32 Len 417 ) 418 { 419 LIST_ENTRY *Head; 420 LIST_ENTRY *Cur; 421 NET_BUF *Node; 422 TCP_SEG *Seg; 423 NET_BUF *Nbuf; 424 TCP_SEQNO End; 425 UINT8 *Data; 426 UINT8 Flag; 427 INT32 Offset; 428 INT32 CopyLen; 429 430 ASSERT ((Tcb != NULL) && TCP_SEQ_LEQ (Seq, Tcb->SndNxt) && (Len > 0)); 431 432 // 433 // Find the segment that contains the Seq. 434 // 435 Head = &Tcb->SndQue; 436 437 Node = NULL; 438 Seg = NULL; 439 440 NET_LIST_FOR_EACH (Cur, Head) { 441 Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List); 442 Seg = TCPSEG_NETBUF (Node); 443 444 if (TCP_SEQ_LT (Seq, Seg->End) && TCP_SEQ_LEQ (Seg->Seq, Seq)) { 445 446 break; 447 } 448 } 449 450 ASSERT (Cur != Head); 451 ASSERT (Node != NULL); 452 ASSERT (Seg != NULL); 453 454 // 455 // Return the buffer if it can be returned without 456 // adjustment: 457 // 458 if ((Seg->Seq == Seq) && 459 TCP_SEQ_LEQ (Seg->End, Seg->Seq + Len) && 460 !NET_BUF_SHARED (Node)) { 461 462 NET_GET_REF (Node); 463 return Node; 464 } 465 466 // 467 // Create a new buffer and copy data there. 468 // 469 Nbuf = NetbufAlloc (Len + TCP_MAX_HEAD); 470 471 if (Nbuf == NULL) { 472 return NULL; 473 } 474 475 NetbufReserve (Nbuf, TCP_MAX_HEAD); 476 477 Flag = Seg->Flag; 478 End = Seg->End; 479 480 if (TCP_SEQ_LT (Seq + Len, Seg->End)) { 481 End = Seq + Len; 482 } 483 484 CopyLen = TCP_SUB_SEQ (End, Seq); 485 Offset = TCP_SUB_SEQ (Seq, Seg->Seq); 486 487 // 488 // If SYN is set and out of the range, clear the flag. 489 // Becuase the sequence of the first byte is SEG.SEQ+1, 490 // adjust Offset by -1. If SYN is in the range, copy 491 // one byte less. 492 // 493 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) { 494 495 if (TCP_SEQ_LT (Seg->Seq, Seq)) { 496 497 TCP_CLEAR_FLG (Flag, TCP_FLG_SYN); 498 Offset--; 499 } else { 500 501 CopyLen--; 502 } 503 } 504 505 // 506 // If FIN is set and in the range, copy one byte less, 507 // and if it is out of the range, clear the flag. 508 // 509 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) { 510 511 if (Seg->End == End) { 512 513 CopyLen--; 514 } else { 515 516 TCP_CLEAR_FLG (Flag, TCP_FLG_FIN); 517 } 518 } 519 520 ASSERT (CopyLen >= 0); 521 522 // 523 // copy data to the segment 524 // 525 if (CopyLen != 0) { 526 Data = NetbufAllocSpace (Nbuf, CopyLen, NET_BUF_TAIL); 527 ASSERT (Data != NULL); 528 529 if ((INT32) NetbufCopy (Node, Offset, CopyLen, Data) != CopyLen) { 530 goto OnError; 531 } 532 } 533 534 CopyMem (TCPSEG_NETBUF (Nbuf), Seg, sizeof (TCP_SEG)); 535 536 TCPSEG_NETBUF (Nbuf)->Seq = Seq; 537 TCPSEG_NETBUF (Nbuf)->End = End; 538 TCPSEG_NETBUF (Nbuf)->Flag = Flag; 539 540 return Nbuf; 541 542 OnError: 543 NetbufFree (Nbuf); 544 return NULL; 545 } 546 547 548 /** 549 Get a segment from the Tcb's socket buffer. 550 551 @param Tcb Pointer to the TCP_CB of this TCP instance. 552 @param Seq The sequence number of the segment. 553 @param Len The maximum length of the segment. 554 555 @return Pointer to the segment, if NULL some error occurred. 556 557 **/ 558 NET_BUF * 559 TcpGetSegmentSock ( 560 IN TCP_CB *Tcb, 561 IN TCP_SEQNO Seq, 562 IN UINT32 Len 563 ) 564 { 565 NET_BUF *Nbuf; 566 UINT8 *Data; 567 UINT32 DataGet; 568 569 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL)); 570 571 Nbuf = NetbufAlloc (Len + TCP_MAX_HEAD); 572 573 if (Nbuf == NULL) { 574 DEBUG ((EFI_D_ERROR, "TcpGetSegmentSock: failed to allocate " 575 "a netbuf for TCB %p\n",Tcb)); 576 577 return NULL; 578 } 579 580 NetbufReserve (Nbuf, TCP_MAX_HEAD); 581 582 DataGet = 0; 583 584 if (Len != 0) { 585 // 586 // copy data to the segment. 587 // 588 Data = NetbufAllocSpace (Nbuf, Len, NET_BUF_TAIL); 589 ASSERT (Data != NULL); 590 591 DataGet = SockGetDataToSend (Tcb->Sk, 0, Len, Data); 592 } 593 594 NET_GET_REF (Nbuf); 595 596 TCPSEG_NETBUF (Nbuf)->Seq = Seq; 597 TCPSEG_NETBUF (Nbuf)->End = Seq + Len; 598 599 InsertTailList (&(Tcb->SndQue), &(Nbuf->List)); 600 601 if (DataGet != 0) { 602 603 SockDataSent (Tcb->Sk, DataGet); 604 } 605 606 return Nbuf; 607 } 608 609 610 /** 611 Get a segment starting from sequence Seq of a maximum 612 length of Len. 613 614 @param Tcb Pointer to the TCP_CB of this TCP instance. 615 @param Seq The sequence number of the segment. 616 @param Len The maximum length of the segment. 617 618 @return Pointer to the segment, if NULL some error occurred. 619 620 **/ 621 NET_BUF * 622 TcpGetSegment ( 623 IN TCP_CB *Tcb, 624 IN TCP_SEQNO Seq, 625 IN UINT32 Len 626 ) 627 { 628 NET_BUF *Nbuf; 629 630 ASSERT (Tcb != NULL); 631 632 // 633 // Compare the SndNxt with the max sequence number sent. 634 // 635 if ((Len != 0) && TCP_SEQ_LT (Seq, TcpGetMaxSndNxt (Tcb))) { 636 637 Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len); 638 } else { 639 640 Nbuf = TcpGetSegmentSock (Tcb, Seq, Len); 641 } 642 643 ASSERT (TcpVerifySegment (Nbuf) != 0); 644 return Nbuf; 645 } 646 647 648 /** 649 Retransmit the segment from sequence Seq. 650 651 @param Tcb Pointer to the TCP_CB of this TCP instance. 652 @param Seq The sequence number of the segment to be retransmitted. 653 654 @retval 0 Retransmission succeeded. 655 @retval -1 Error condition occurred. 656 657 **/ 658 INTN 659 TcpRetransmit ( 660 IN TCP_CB *Tcb, 661 IN TCP_SEQNO Seq 662 ) 663 { 664 NET_BUF *Nbuf; 665 UINT32 Len; 666 667 // 668 // Compute the maxium length of retransmission. It is 669 // limited by three factors: 670 // 1. Less than SndMss 671 // 2. must in the current send window 672 // 3. will not change the boundaries of queued segments. 673 // 674 if (TCP_SEQ_LT (Tcb->SndWl2 + Tcb->SndWnd, Seq)) { 675 DEBUG ((EFI_D_WARN, "TcpRetransmit: retransmission cancelled " 676 "because send window too small for TCB %p\n", Tcb)); 677 678 return 0; 679 } 680 681 Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq); 682 Len = MIN (Len, Tcb->SndMss); 683 684 Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len); 685 if (Nbuf == NULL) { 686 return -1; 687 } 688 689 ASSERT (TcpVerifySegment (Nbuf) != 0); 690 691 if (TcpTransmitSegment (Tcb, Nbuf) != 0) { 692 goto OnError; 693 } 694 695 // 696 // The retransmitted buffer may be on the SndQue, 697 // trim TCP head because all the buffer on SndQue 698 // are headless. 699 // 700 ASSERT (Nbuf->Tcp != NULL); 701 NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD); 702 Nbuf->Tcp = NULL; 703 704 NetbufFree (Nbuf); 705 return 0; 706 707 OnError: 708 if (Nbuf != NULL) { 709 NetbufFree (Nbuf); 710 } 711 712 return -1; 713 } 714 715 716 /** 717 Check whether to send data/SYN/FIN and piggy back an ACK. 718 719 @param Tcb Pointer to the TCP_CB of this TCP instance. 720 @param Force Whether to ignore the sender's SWS avoidance algorithm and send 721 out data by force. 722 723 @return The number of bytes sent. 724 725 **/ 726 INTN 727 TcpToSendData ( 728 IN OUT TCP_CB *Tcb, 729 IN INTN Force 730 ) 731 { 732 UINT32 Len; 733 INTN Sent; 734 UINT8 Flag; 735 NET_BUF *Nbuf; 736 TCP_SEG *Seg; 737 TCP_SEQNO Seq; 738 TCP_SEQNO End; 739 740 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL) && (Tcb->State != TCP_LISTEN)); 741 742 Sent = 0; 743 744 if ((Tcb->State == TCP_CLOSED) || 745 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT)) { 746 747 return 0; 748 } 749 750 SEND_AGAIN: 751 // 752 // compute how much data can be sent 753 // 754 Len = TcpDataToSend (Tcb, Force); 755 Seq = Tcb->SndNxt; 756 757 ASSERT ((Tcb->State) < (sizeof (mTcpOutFlag) / sizeof (mTcpOutFlag[0]))); 758 Flag = mTcpOutFlag[Tcb->State]; 759 760 if ((Flag & TCP_FLG_SYN) != 0) { 761 762 Seq = Tcb->Iss; 763 Len = 0; 764 } 765 766 // 767 // only send a segment without data if SYN or 768 // FIN is set. 769 // 770 if ((Len == 0) && 771 ((Flag & (TCP_FLG_SYN | TCP_FLG_FIN)) == 0)) { 772 return Sent; 773 } 774 775 Nbuf = TcpGetSegment (Tcb, Seq, Len); 776 777 if (Nbuf == NULL) { 778 DEBUG ( 779 (EFI_D_ERROR, 780 "TcpToSendData: failed to get a segment for TCB %p\n", 781 Tcb) 782 ); 783 784 goto OnError; 785 } 786 787 Seg = TCPSEG_NETBUF (Nbuf); 788 789 // 790 // Set the TcpSeg in Nbuf. 791 // 792 Len = Nbuf->TotalSize; 793 End = Seq + Len; 794 if (TCP_FLG_ON (Flag, TCP_FLG_SYN)) { 795 End++; 796 } 797 798 if ((Flag & TCP_FLG_FIN) != 0) { 799 // 800 // Send FIN if all data is sent, and FIN is 801 // in the window 802 // 803 if ((TcpGetMaxSndNxt (Tcb) == Tcb->SndNxt) && 804 (GET_SND_DATASIZE (Tcb->Sk) == 0) && 805 TCP_SEQ_LT (End + 1, Tcb->SndWnd + Tcb->SndWl2)) { 806 807 DEBUG ( 808 (EFI_D_INFO, 809 "TcpToSendData: send FIN " 810 "to peer for TCB %p in state %s\n", 811 Tcb, 812 mTcpStateName[Tcb->State]) 813 ); 814 815 End++; 816 } else { 817 TCP_CLEAR_FLG (Flag, TCP_FLG_FIN); 818 } 819 } 820 821 Seg->Seq = Seq; 822 Seg->End = End; 823 Seg->Flag = Flag; 824 825 ASSERT (TcpVerifySegment (Nbuf) != 0); 826 ASSERT (TcpCheckSndQue (&Tcb->SndQue) != 0); 827 828 // 829 // don't send an empty segment here. 830 // 831 if (Seg->End == Seg->Seq) { 832 DEBUG ((EFI_D_WARN, "TcpToSendData: created a empty" 833 " segment for TCB %p, free it now\n", Tcb)); 834 835 NetbufFree (Nbuf); 836 return Sent; 837 } 838 839 if (TcpTransmitSegment (Tcb, Nbuf) != 0) { 840 NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD); 841 Nbuf->Tcp = NULL; 842 843 if ((Flag & TCP_FLG_FIN) != 0) { 844 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT); 845 } 846 847 goto OnError; 848 } 849 850 Sent += TCP_SUB_SEQ (End, Seq); 851 852 // 853 // All the buffer in the SndQue is headless 854 // 855 ASSERT (Nbuf->Tcp != NULL); 856 857 NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD); 858 Nbuf->Tcp = NULL; 859 860 NetbufFree (Nbuf); 861 862 // 863 // update status in TCB 864 // 865 Tcb->DelayedAck = 0; 866 867 if ((Flag & TCP_FLG_FIN) != 0) { 868 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT); 869 } 870 871 if (TCP_SEQ_GT (End, Tcb->SndNxt)) { 872 Tcb->SndNxt = End; 873 } 874 875 if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT)) { 876 TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto); 877 } 878 879 // 880 // Enable RTT measurement only if not in retransmit. 881 // Karn's algorithm reqires not to update RTT when in loss. 882 // 883 if ((Tcb->CongestState == TCP_CONGEST_OPEN) && 884 !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) { 885 886 DEBUG ((EFI_D_INFO, "TcpToSendData: set RTT measure " 887 "sequence %d for TCB %p\n", Seq, Tcb)); 888 889 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON); 890 Tcb->RttSeq = Seq; 891 Tcb->RttMeasure = 0; 892 } 893 894 if (Len == Tcb->SndMss) { 895 goto SEND_AGAIN; 896 } 897 898 return Sent; 899 900 OnError: 901 if (Nbuf != NULL) { 902 NetbufFree (Nbuf); 903 } 904 905 return Sent; 906 } 907 908 909 /** 910 Send an ACK immediately. 911 912 @param Tcb Pointer to the TCP_CB of this TCP instance. 913 914 **/ 915 VOID 916 TcpSendAck ( 917 IN OUT TCP_CB *Tcb 918 ) 919 { 920 NET_BUF *Nbuf; 921 TCP_SEG *Seg; 922 923 Nbuf = NetbufAlloc (TCP_MAX_HEAD); 924 925 if (Nbuf == NULL) { 926 return; 927 } 928 929 NetbufReserve (Nbuf, TCP_MAX_HEAD); 930 931 Seg = TCPSEG_NETBUF (Nbuf); 932 Seg->Seq = Tcb->SndNxt; 933 Seg->End = Tcb->SndNxt; 934 Seg->Flag = TCP_FLG_ACK; 935 936 if (TcpTransmitSegment (Tcb, Nbuf) == 0) { 937 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW); 938 Tcb->DelayedAck = 0; 939 } 940 941 NetbufFree (Nbuf); 942 } 943 944 945 /** 946 Send a zero probe segment. It can be used by keepalive and zero window probe. 947 948 @param Tcb Pointer to the TCP_CB of this TCP instance. 949 950 @retval 0 The zero probe segment was sent out successfully. 951 @retval other Error condition occurred. 952 953 **/ 954 INTN 955 TcpSendZeroProbe ( 956 IN OUT TCP_CB *Tcb 957 ) 958 { 959 NET_BUF *Nbuf; 960 TCP_SEG *Seg; 961 INTN Result; 962 963 Nbuf = NetbufAlloc (TCP_MAX_HEAD); 964 965 if (Nbuf == NULL) { 966 return -1; 967 } 968 969 NetbufReserve (Nbuf, TCP_MAX_HEAD); 970 971 // 972 // SndNxt-1 is out of window. The peer should respond 973 // with an ACK. 974 // 975 Seg = TCPSEG_NETBUF (Nbuf); 976 Seg->Seq = Tcb->SndNxt - 1; 977 Seg->End = Tcb->SndNxt - 1; 978 Seg->Flag = TCP_FLG_ACK; 979 980 Result = TcpTransmitSegment (Tcb, Nbuf); 981 NetbufFree (Nbuf); 982 983 return Result; 984 } 985 986 987 /** 988 Check whether to send an ACK or delayed ACK. 989 990 @param Tcb Pointer to the TCP_CB of this TCP instance. 991 992 **/ 993 VOID 994 TcpToSendAck ( 995 IN OUT TCP_CB *Tcb 996 ) 997 { 998 UINT32 TcpNow; 999 1000 TcpNow = TcpRcvWinNow (Tcb); 1001 // 1002 // Generally, TCP should send a delayed ACK unless: 1003 // 1. ACK at least every other FULL sized segment received, 1004 // 2. Packets received out of order 1005 // 3. Receiving window is open 1006 // 1007 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) || 1008 (Tcb->DelayedAck >= 1) || 1009 (TcpNow > TcpRcvWinOld (Tcb))) { 1010 TcpSendAck (Tcb); 1011 return; 1012 } 1013 1014 DEBUG ((EFI_D_INFO, "TcpToSendAck: scheduled a delayed" 1015 " ACK for TCB %p\n", Tcb)); 1016 1017 // 1018 // schedule a delayed ACK 1019 // 1020 Tcb->DelayedAck++; 1021 } 1022 1023 1024 /** 1025 Send a RESET segment in response to the segment received. 1026 1027 @param Tcb Pointer to the TCP_CB of this TCP instance, may be NULL. 1028 @param Head TCP header of the segment that triggers the reset. 1029 @param Len Length of the segment that triggers the reset. 1030 @param Local Local IP address. 1031 @param Remote Remote peer's IP address. 1032 1033 @retval 0 A reset is sent or no need to send it. 1034 @retval -1 No reset is sent. 1035 1036 **/ 1037 INTN 1038 TcpSendReset ( 1039 IN TCP_CB *Tcb, 1040 IN TCP_HEAD *Head, 1041 IN INT32 Len, 1042 IN UINT32 Local, 1043 IN UINT32 Remote 1044 ) 1045 { 1046 NET_BUF *Nbuf; 1047 TCP_HEAD *Nhead; 1048 UINT16 HeadSum; 1049 1050 // 1051 // Don't respond to a Reset with reset 1052 // 1053 if ((Head->Flag & TCP_FLG_RST) != 0) { 1054 return 0; 1055 } 1056 1057 Nbuf = NetbufAlloc (TCP_MAX_HEAD); 1058 1059 if (Nbuf == NULL) { 1060 return -1; 1061 } 1062 1063 Nhead = (TCP_HEAD *) NetbufAllocSpace ( 1064 Nbuf, 1065 sizeof (TCP_HEAD), 1066 NET_BUF_TAIL 1067 ); 1068 1069 ASSERT (Nhead != NULL); 1070 1071 Nbuf->Tcp = Nhead; 1072 Nhead->Flag = TCP_FLG_RST; 1073 1074 // 1075 // Derive Seq/ACK from the segment if no TCB 1076 // associated with it, otherwise from the Tcb 1077 // 1078 if (Tcb == NULL) { 1079 1080 if (TCP_FLG_ON (Head->Flag, TCP_FLG_ACK)) { 1081 Nhead->Seq = Head->Ack; 1082 Nhead->Ack = 0; 1083 } else { 1084 Nhead->Seq = 0; 1085 TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK); 1086 Nhead->Ack = HTONL (NTOHL (Head->Seq) + Len); 1087 } 1088 } else { 1089 1090 Nhead->Seq = HTONL (Tcb->SndNxt); 1091 Nhead->Ack = HTONL (Tcb->RcvNxt); 1092 TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK); 1093 } 1094 1095 Nhead->SrcPort = Head->DstPort; 1096 Nhead->DstPort = Head->SrcPort; 1097 Nhead->HeadLen = (UINT8) (sizeof (TCP_HEAD) >> 2); 1098 Nhead->Res = 0; 1099 Nhead->Wnd = HTONS (0xFFFF); 1100 Nhead->Checksum = 0; 1101 Nhead->Urg = 0; 1102 1103 HeadSum = NetPseudoHeadChecksum (Local, Remote, 6, 0); 1104 Nhead->Checksum = TcpChecksum (Nbuf, HeadSum); 1105 1106 TcpSendIpPacket (Tcb, Nbuf, Local, Remote); 1107 1108 NetbufFree (Nbuf); 1109 return 0; 1110 } 1111 1112 1113 /** 1114 Verify that the segment is in good shape. 1115 1116 @param Nbuf Buffer that contains the segment to be checked. 1117 1118 @retval 0 The segment is broken. 1119 @retval 1 The segment is in good shape. 1120 1121 **/ 1122 INTN 1123 TcpVerifySegment ( 1124 IN NET_BUF *Nbuf 1125 ) 1126 { 1127 TCP_HEAD *Head; 1128 TCP_SEG *Seg; 1129 UINT32 Len; 1130 1131 if (Nbuf == NULL) { 1132 return 1; 1133 } 1134 1135 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE); 1136 1137 Seg = TCPSEG_NETBUF (Nbuf); 1138 Len = Nbuf->TotalSize; 1139 Head = Nbuf->Tcp; 1140 1141 if (Head != NULL) { 1142 if (Head->Flag != Seg->Flag) { 1143 return 0; 1144 } 1145 1146 Len -= (Head->HeadLen << 2); 1147 } 1148 1149 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) { 1150 Len++; 1151 } 1152 1153 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) { 1154 Len++; 1155 } 1156 1157 if (Seg->Seq + Len != Seg->End) { 1158 return 0; 1159 } 1160 1161 return 1; 1162 } 1163 1164 1165 /** 1166 Verify that all the segments in SndQue are in good shape. 1167 1168 @param Head Pointer to the head node of the SndQue. 1169 1170 @retval 0 At least one segment is broken. 1171 @retval 1 All segments in the specific queue are in good shape. 1172 1173 **/ 1174 INTN 1175 TcpCheckSndQue ( 1176 IN LIST_ENTRY *Head 1177 ) 1178 { 1179 LIST_ENTRY *Entry; 1180 NET_BUF *Nbuf; 1181 TCP_SEQNO Seq; 1182 1183 if (IsListEmpty (Head)) { 1184 return 1; 1185 } 1186 // 1187 // Initialize the Seq 1188 // 1189 Entry = Head->ForwardLink; 1190 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List); 1191 Seq = TCPSEG_NETBUF (Nbuf)->Seq; 1192 1193 NET_LIST_FOR_EACH (Entry, Head) { 1194 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List); 1195 1196 if (TcpVerifySegment (Nbuf) == 0) { 1197 return 0; 1198 } 1199 1200 // 1201 // All the node in the SndQue should has: 1202 // SEG.SEQ = LAST_SEG.END 1203 // 1204 if (Seq != TCPSEG_NETBUF (Nbuf)->Seq) { 1205 return 0; 1206 } 1207 1208 Seq = TCPSEG_NETBUF (Nbuf)->End; 1209 } 1210 1211 return 1; 1212 } 1213