1 /*************************************************************************** 2 * Copyright (c) 2024 Microsoft Corporation 3 * 4 * This program and the accompanying materials are made available under the 5 * terms of the MIT License which is available at 6 * https://opensource.org/licenses/MIT. 7 * 8 * SPDX-License-Identifier: MIT 9 **************************************************************************/ 10 11 12 /**************************************************************************/ 13 /**************************************************************************/ 14 /** */ 15 /** NetX Component */ 16 /** */ 17 /** Transmission Control Protocol (TCP) */ 18 /** */ 19 /**************************************************************************/ 20 /**************************************************************************/ 21 22 #define NX_SOURCE_CODE 23 24 25 /* Include necessary system files. */ 26 27 #include "nx_api.h" 28 #include "nx_ip.h" 29 #ifdef FEATURE_NX_IPV6 30 #include "nx_ipv6.h" 31 #endif /* FEATURE_NX_IPV6 */ 32 #include "nx_packet.h" 33 #include "nx_tcp.h" 34 35 36 /**************************************************************************/ 37 /* */ 38 /* FUNCTION RELEASE */ 39 /* */ 40 /* _nx_tcp_socket_state_transmit_check PORTABLE C */ 41 /* 6.1 */ 42 /* AUTHOR */ 43 /* */ 44 /* Yuxin Zhou, Microsoft Corporation */ 45 /* */ 46 /* DESCRIPTION */ 47 /* */ 48 /* This function determines if the new receive window value is large */ 49 /* enough to satisfy a thread suspended trying to send data on the TCP */ 50 /* connection. This is typically called from the ESTABLISHED state. */ 51 /* */ 52 /* INPUT */ 53 /* */ 54 /* socket_ptr Pointer to TCP socket */ 55 /* */ 56 /* OUTPUT */ 57 /* */ 58 /* None */ 59 /* */ 60 /* CALLS */ 61 /* */ 62 /* _nx_tcp_socket_thread_resume Resume suspended thread */ 63 /* */ 64 /* CALLED BY */ 65 /* */ 66 /* _nx_tcp_socket_packet_process Process TCP packet for socket */ 67 /* */ 68 /* RELEASE HISTORY */ 69 /* */ 70 /* DATE NAME DESCRIPTION */ 71 /* */ 72 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ 73 /* 09-30-2020 Yuxin Zhou Modified comment(s), */ 74 /* resulting in version 6.1 */ 75 /* */ 76 /**************************************************************************/ _nx_tcp_socket_state_transmit_check(NX_TCP_SOCKET * socket_ptr)77VOID _nx_tcp_socket_state_transmit_check(NX_TCP_SOCKET *socket_ptr) 78 { 79 80 ULONG tx_window_current; 81 82 /* Now check to see if there is a thread suspended attempting to transmit. */ 83 if (socket_ptr -> nx_tcp_socket_transmit_suspension_list) 84 { 85 86 /* Yes, a thread is suspended attempting to transmit when the transmit window 87 is lower than its request size. Determine if the current transmit window 88 size can now accommodate the request. */ 89 90 /* Pick up the min(cwnd, swnd) */ 91 if (socket_ptr -> nx_tcp_socket_tx_window_advertised > socket_ptr -> nx_tcp_socket_tx_window_congestion) 92 { 93 tx_window_current = socket_ptr -> nx_tcp_socket_tx_window_congestion; 94 95 /* On the first and second duplicate ACKs received, the total FlightSize would 96 remain less than or equal to cwnd plus 2*SMSS. 97 Section 3.2, Page 9, RFC5681. */ 98 if ((socket_ptr -> nx_tcp_socket_duplicated_ack_received == 1) || 99 (socket_ptr -> nx_tcp_socket_duplicated_ack_received == 2)) 100 { 101 tx_window_current += (socket_ptr -> nx_tcp_socket_connect_mss << 1); 102 } 103 104 /* Make sure the tx_window_current is less or equal to swnd. */ 105 if (tx_window_current > socket_ptr -> nx_tcp_socket_tx_window_advertised) 106 { 107 tx_window_current = socket_ptr -> nx_tcp_socket_tx_window_advertised; 108 } 109 } 110 else 111 { 112 tx_window_current = socket_ptr -> nx_tcp_socket_tx_window_advertised; 113 } 114 115 /* Substract any data transmitted but unacked (outstanding bytes) */ 116 if (tx_window_current > socket_ptr -> nx_tcp_socket_tx_outstanding_bytes) 117 { 118 tx_window_current -= socket_ptr -> nx_tcp_socket_tx_outstanding_bytes; 119 } 120 else /* Set tx_window_current to zero. */ 121 { 122 tx_window_current = 0; 123 } 124 125 126 /* Determine if the current transmit window (received from the connected socket) 127 is large enough to handle the transmit. */ 128 if ((tx_window_current) && 129 (socket_ptr -> nx_tcp_socket_transmit_sent_count < socket_ptr -> nx_tcp_socket_transmit_queue_maximum)) 130 { 131 132 /* Is NetX set up with a windows update callback? */ 133 if (socket_ptr -> nx_tcp_socket_window_update_notify) 134 { 135 136 /* Yes; Call this function when there is a change in transmit windows size. */ 137 (socket_ptr -> nx_tcp_socket_window_update_notify)(socket_ptr); 138 } 139 140 141 /* Decrement the suspension count. */ 142 socket_ptr -> nx_tcp_socket_transmit_suspended_count--; 143 144 /* Remove the suspended thread from the list. */ 145 _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_transmit_suspension_list), NX_SUCCESS); 146 } 147 } 148 } 149 150