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