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 #include "nx_tcp.h"
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _nx_tcp_socket_create                               PORTABLE C      */
36 /*                                                           6.4.0        */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Yuxin Zhou, Microsoft Corporation                                   */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function creates a TCP socket for the specified IP instance.   */
44 /*    Both client and server sockets are created by this service.         */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    ip_ptr                                IP instance pointer           */
49 /*    socket_ptr                            Pointer to new TCP socket     */
50 /*    name                                  Name of new TCP socket        */
51 /*    type_of_service                       Type of service for this TCP  */
52 /*                                            socket                      */
53 /*    fragment                              Flag to enable IP fragmenting */
54 /*    time_to_live                          Time to live value for socket */
55 /*    window_size                           Size of socket's receive      */
56 /*                                            window                      */
57 /*    tcp_urgent_data_callback              Routine to call when urgent   */
58 /*                                            data is received            */
59 /*    tcp_disconnect_callback               Routine to call when a        */
60 /*                                            disconnect occurs           */
61 /*                                                                        */
62 /*  OUTPUT                                                                */
63 /*                                                                        */
64 /*    status                                Completion status             */
65 /*                                                                        */
66 /*  CALLS                                                                 */
67 /*                                                                        */
68 /*    tx_mutex_get                          Obtain protection             */
69 /*    tx_mutex_put                          Release protection            */
70 /*                                                                        */
71 /*  CALLED BY                                                             */
72 /*                                                                        */
73 /*    Application Code                                                    */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
80 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
81 /*                                            resulting in version 6.1    */
82 /*  12-31-2023     Yajun Xia                Modified comment(s),          */
83 /*                                            supported VLAN,             */
84 /*                                            resulting in version 6.4.0  */
85 /*                                                                        */
86 /**************************************************************************/
_nx_tcp_socket_create(NX_IP * ip_ptr,NX_TCP_SOCKET * socket_ptr,CHAR * name,ULONG type_of_service,ULONG fragment,UINT time_to_live,ULONG window_size,VOID (* tcp_urgent_data_callback)(NX_TCP_SOCKET * socket_ptr),VOID (* tcp_disconnect_callback)(NX_TCP_SOCKET * socket_ptr))87 UINT  _nx_tcp_socket_create(NX_IP *ip_ptr, NX_TCP_SOCKET *socket_ptr, CHAR *name,
88                             ULONG type_of_service, ULONG fragment, UINT time_to_live, ULONG window_size,
89                             VOID (*tcp_urgent_data_callback)(NX_TCP_SOCKET *socket_ptr),
90                             VOID (*tcp_disconnect_callback)(NX_TCP_SOCKET *socket_ptr))
91 {
92 TX_INTERRUPT_SAVE_AREA
93 
94 NX_TCP_SOCKET *tail_ptr;
95 
96 
97     /* Initialize the TCP control block to zero.  */
98     memset((void *)socket_ptr, 0, sizeof(NX_TCP_SOCKET));
99 
100     /* Fill in the basic information in the new TCP socket structure.  */
101 
102     /* Remember the associated IP structure.  */
103     socket_ptr -> nx_tcp_socket_ip_ptr =  ip_ptr;
104 
105     /* By default, indicate the socket is a client socket.  */
106     socket_ptr -> nx_tcp_socket_client_type =  NX_TRUE;
107 
108     /* Save the TCP socket's name.  */
109     socket_ptr -> nx_tcp_socket_name =  name;
110 
111     /* Setup the counter for duplicated ACK packet.  */
112     socket_ptr -> nx_tcp_socket_duplicated_ack_received = 0;
113 
114     /* Setup this socket's maximum segment size (mss).  */
115     socket_ptr -> nx_tcp_socket_mss = 0;
116 
117     /* Setup the default receiver's maximum segment size.  */
118     socket_ptr -> nx_tcp_socket_connect_mss =  NX_TCP_MSS_SIZE;
119 
120     /* Save the type of service input parameter.  */
121     socket_ptr -> nx_tcp_socket_type_of_service =  type_of_service;
122 
123     /* Save the fragment input parameter.  */
124     socket_ptr -> nx_tcp_socket_fragment_enable =  fragment & NX_DONT_FRAGMENT;
125 
126     /* Save the time-to-live input parameter.  */
127     socket_ptr -> nx_tcp_socket_time_to_live =  time_to_live;
128 
129     /* Clear the socket bind in progress flag.  */
130     socket_ptr -> nx_tcp_socket_bind_in_progress =  NX_FALSE;
131 
132     /* Setup the delayed ACK timeout periodic rate.  */
133     socket_ptr -> nx_tcp_socket_delayed_ack_timeout =  _nx_tcp_ack_timer_rate;
134 
135     /* Setup the default transmit timeout.  */
136     socket_ptr -> nx_tcp_socket_timeout_rate =         _nx_tcp_transmit_timer_rate;
137     socket_ptr -> nx_tcp_socket_timeout_max_retries =  NX_TCP_MAXIMUM_RETRIES;
138     socket_ptr -> nx_tcp_socket_timeout_shift =        NX_TCP_RETRY_SHIFT;
139 
140     /* Setup the default maximum transmit queue depth.  */
141     socket_ptr -> nx_tcp_socket_transmit_queue_maximum_default =  NX_TCP_MAXIMUM_TX_QUEUE;
142     socket_ptr -> nx_tcp_socket_transmit_queue_maximum =          NX_TCP_MAXIMUM_TX_QUEUE;
143 
144 #ifdef NX_ENABLE_LOW_WATERMARK
145     /* Setup the default maximum receive queue depth.  */
146     socket_ptr -> nx_tcp_socket_receive_queue_maximum = NX_TCP_MAXIMUM_RX_QUEUE;
147 #endif /* NX_ENABLE_LOW_WATERMARK */
148 
149 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
150 
151     /* Window scaling feature is enabled.  Record this user-specified window size. */
152     socket_ptr -> nx_tcp_socket_rx_window_maximum = window_size;
153 #endif /* NX_ENABLE_TCP_WINDOW_SCALING */
154 
155     /* Setup the sliding window information.  */
156     socket_ptr -> nx_tcp_socket_rx_window_default =   window_size;
157     socket_ptr -> nx_tcp_socket_rx_window_current =   window_size;
158     socket_ptr -> nx_tcp_socket_tx_outstanding_bytes = 0;
159     socket_ptr -> nx_tcp_socket_tx_window_advertised = 0;
160     socket_ptr -> nx_tcp_socket_tx_window_congestion = 0;
161 
162 
163     /* Initialize the ack_n_packet counter. */
164     socket_ptr -> nx_tcp_socket_ack_n_packet_counter = 1;
165 
166     /* Save the application callback routines.  */
167     socket_ptr -> nx_tcp_urgent_data_callback = tcp_urgent_data_callback;
168     socket_ptr -> nx_tcp_disconnect_callback =  tcp_disconnect_callback;
169 
170     /* Clear the receive notify function pointer.  */
171     socket_ptr -> nx_tcp_receive_callback =  NX_NULL;
172 
173 #ifdef NX_ENABLE_TCP_KEEPALIVE
174     /* If the Keep alive feature is enabled in NetX, enable it
175        on all TCP sockets. */
176     socket_ptr -> nx_tcp_socket_keepalive_enabled = NX_TRUE;
177 
178 #endif
179 
180     /* If trace is enabled, insert this event into the trace buffer.  */
181     NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_TCP_STATE_CHANGE, ip_ptr, socket_ptr, socket_ptr -> nx_tcp_socket_state, NX_TCP_CLOSED, NX_TRACE_INTERNAL_EVENTS, 0, 0);
182 
183     /* Setup the initial TCP socket state.  */
184     socket_ptr -> nx_tcp_socket_state =  NX_TCP_CLOSED;
185 
186 #ifdef NX_ENABLE_VLAN
187     /* Initialize the tcp socket vlan priority.  */
188     socket_ptr -> nx_tcp_socket_vlan_priority = NX_VLAN_PRIORITY_INVALID;
189 #endif /* NX_ENABLE_VLAN */
190 
191     /* If trace is enabled, register this object.  */
192     NX_TRACE_OBJECT_REGISTER(NX_TRACE_OBJECT_TYPE_TCP_SOCKET, socket_ptr, name, type_of_service, window_size);
193 
194     /* If trace is enabled, insert this event into the trace buffer.  */
195     NX_TRACE_IN_LINE_INSERT(NX_TRACE_TCP_SOCKET_CREATE, ip_ptr, socket_ptr, type_of_service, window_size, NX_TRACE_TCP_EVENTS, 0, 0);
196 
197     /* Get protection while we insert the TCP socket into the created list.  */
198     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
199 
200     /* Disable interrupts while we link the new TCP socket to the IP structure.  */
201     TX_DISABLE
202 
203     /* Load the TCP ID field in the TCP control block.  */
204     socket_ptr -> nx_tcp_socket_id =  NX_TCP_ID;
205 
206     /* Place the new TCP control block on the list of created TCP sockets for this IP.  First,
207        check for an empty list.  */
208     if (ip_ptr -> nx_ip_tcp_created_sockets_ptr)
209     {
210 
211         /* Pickup tail pointer.  */
212         tail_ptr =  (ip_ptr -> nx_ip_tcp_created_sockets_ptr) -> nx_tcp_socket_created_previous;
213 
214         /* Place the new TCP socket control block in the list.  */
215         (ip_ptr -> nx_ip_tcp_created_sockets_ptr) -> nx_tcp_socket_created_previous =  socket_ptr;
216         tail_ptr ->  nx_tcp_socket_created_next =  socket_ptr;
217 
218         /* Setup this TCP socket's created links.  */
219         socket_ptr -> nx_tcp_socket_created_previous =  tail_ptr;
220         socket_ptr -> nx_tcp_socket_created_next =      ip_ptr -> nx_ip_tcp_created_sockets_ptr;
221     }
222     else
223     {
224 
225         /* The created TCP socket list is empty.  Add TCP socket control block to empty list.  */
226         ip_ptr -> nx_ip_tcp_created_sockets_ptr =       socket_ptr;
227         socket_ptr -> nx_tcp_socket_created_previous =  socket_ptr;
228         socket_ptr -> nx_tcp_socket_created_next =      socket_ptr;
229     }
230 
231     /* Increment the created TCP socket counter.  */
232     ip_ptr -> nx_ip_tcp_created_sockets_count++;
233 
234 #ifdef FEATURE_NX_IPV6
235     socket_ptr -> nx_tcp_socket_ipv6_addr   =             NX_NULL;
236 #endif /* FEATURE_NX_IPV6 */
237 
238 
239 #ifdef NX_IPSEC_ENABLE
240     socket_ptr -> nx_tcp_socket_egress_sa = NX_NULL;
241     socket_ptr -> nx_tcp_socket_egress_sa_data_offset = 0;
242 #endif /* NX_IPSEC_ENABLE */
243     /* Restore previous interrupt posture.  */
244     TX_RESTORE
245 
246     /* Release protection.  */
247     tx_mutex_put(&(ip_ptr -> nx_ip_protection));
248 
249     /* Return successful completion.  */
250     return(NX_SUCCESS);
251 }
252 
253