1 /* 14.19 TCP MUST include an SWS avoidance algorithm in the receiver when effective send MSS < (1/ 2)*RCV_BUFF.  */
2 
3 /*  Procedure
4     1.Connection successfully
5     2.First Client sends 40 data to Server, then check if the last_sent changed
6     3.Then Client sends more 20 data to Server, also check if the last_sent changed
7     4.If the last_sent changed, the SWS avoidance algorithm has not been used.  */
8 
9 #include   "tx_api.h"
10 #include   "nx_api.h"
11 #include   "nx_tcp.h"
12 extern void    test_control_return(UINT status);
13 
14 #if !defined(NX_DISABLE_IPV4)
15 
16 #define     DEMO_STACK_SIZE    2048
17 
18 #define MSG "----------abcdefgh20----------ABCDEFGH40----------klmnopqr60----------KLMNOPQR80--------------------"
19 
20 /* Define the ThreadX and NetX object control blocks...  */
21 
22 static TX_THREAD               ntest_0;
23 static TX_THREAD               ntest_1;
24 
25 static NX_PACKET_POOL          pool_0;
26 static NX_IP                   ip_0;
27 static NX_IP                   ip_1;
28 static NX_TCP_SOCKET           client_socket;
29 static NX_TCP_SOCKET           server_socket;
30 
31 /* Define the counters used in the demo application...  */
32 
33 static ULONG                   error_counter;
34 static ULONG                   data_packet_counter;
35 static UINT                    is_included;
36 static ULONG                   mss_option;
37 
38 /* Define thread prototypes.  */
39 
40 static void    ntest_0_entry(ULONG thread_input);
41 static void    ntest_1_entry(ULONG thread_input);
42 static void    ntest_0_connect_received(NX_TCP_SOCKET *server_socket, UINT port);
43 static void    ntest_0_disconnect_received(NX_TCP_SOCKET *server_socket);
44 extern void    _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
45 
46 /* Define what the initial system looks like.  */
47 
48 #ifdef CTEST
test_application_define(void * first_unused_memory)49 VOID test_application_define(void *first_unused_memory)
50 #else
51 void           netx_14_20_application_define(void *first_unused_memory)
52 #endif
53 {
54 CHAR       *pointer;
55 UINT       status;
56 
57     /* Setup the working pointer.  */
58     pointer = (CHAR *) first_unused_memory;
59 
60     error_counter = 0;
61     data_packet_counter = 0;
62     is_included = NX_FALSE;
63     mss_option = 0;
64 
65     /* Create the main thread.  */
66     tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
67                      pointer, DEMO_STACK_SIZE,
68                      3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
69 
70     pointer = pointer + DEMO_STACK_SIZE;
71 
72     /* Create the main thread.  */
73     tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
74                      pointer, DEMO_STACK_SIZE,
75                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
76 
77     pointer = pointer + DEMO_STACK_SIZE;
78 
79     /* Initialize the NetX system.  */
80     nx_system_initialize();
81 
82     /* Create a packet pool.  */
83     status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 512, pointer, 8192);
84     pointer = pointer + 8192;
85 
86     if(status)
87         error_counter++;
88 
89     /* Create an IP instance.  */
90     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
91                           pointer, 2048, 1);
92     pointer = pointer + 2048;
93 
94     /* Create another IP instance.  */
95     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
96                            pointer, 2048, 1);
97     pointer = pointer + 2048;
98 
99     if(status)
100         error_counter++;
101 
102     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
103     status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
104     pointer = pointer + 1024;
105 
106     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
107     status += nx_arp_enable(&ip_1, (void *) pointer, 1024);
108     pointer = pointer + 1024;
109 
110     /* Check ARP enable status.  */
111     if(status)
112         error_counter++;
113 
114     /* Enable TCP processing for both IP instances.  */
115     status = nx_tcp_enable(&ip_0);
116     status += nx_tcp_enable(&ip_1);
117 
118     /* Check TCP enable status.  */
119     if(status)
120         error_counter++;
121 }
122 
123 /* Define the test threads.  */
124 
ntest_0_entry(ULONG thread_input)125 static void    ntest_0_entry(ULONG thread_input)
126 {
127 UINT         status;
128 ULONG        actual_status;
129 NX_PACKET    *rcv_packet_ptr;
130 ULONG        window_last_sent;
131 ULONG        rcv_length;
132 
133     /* Print out test information banner.  */
134     printf("NetX Test:   TCP Spec 14.20 Test.......................................");
135 
136     /* Check for earlier error.  */
137     if(error_counter)
138     {
139         printf("ERROR!\n");
140         test_control_return(1);
141     }
142 
143     /* Ensure the IP instance has been initialized.  */
144     status = nx_ip_status_check(&ip_0, NX_IP_INITIALIZE_DONE, &actual_status, NX_IP_PERIODIC_RATE);
145 
146     /* Check for error.  */
147     if(status)
148         error_counter++;
149 
150     /* Create a socket.  */
151     status = nx_tcp_socket_create(&ip_0, &server_socket, "Server Socket",
152                                   NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 100,
153                                   NX_NULL, ntest_0_disconnect_received);
154 
155     /* Check for error.  */
156     if(status)
157         error_counter++;
158 
159     /* Setup this thread to listen.  */
160     status = nx_tcp_server_socket_listen(&ip_0, 12, &server_socket, 5, ntest_0_connect_received);
161 
162     /* Check for error.  */
163     if(status)
164         error_counter++;
165 
166     /* Accept a client socket connection.  */
167     status = nx_tcp_server_socket_accept(&server_socket, NX_IP_PERIODIC_RATE);
168 
169     /* Check for error.  */
170     if(status)
171         error_counter++;
172 
173     tx_thread_suspend(&ntest_0);
174 
175     window_last_sent = server_socket.nx_tcp_socket_rx_window_last_sent;
176 
177     status = nx_tcp_socket_receive(&server_socket, &rcv_packet_ptr, 2 * NX_IP_PERIODIC_RATE);
178 
179     /* Check for error.  */
180     if(status)
181         error_counter++;
182     else
183     {
184         /* Check data length and payload */
185         if((rcv_packet_ptr -> nx_packet_length == mss_option) && (!memcmp(rcv_packet_ptr -> nx_packet_prepend_ptr, MSG, mss_option)))
186            data_packet_counter++;
187 
188         rcv_length = rcv_packet_ptr -> nx_packet_length;
189 
190         /* Release the packet.  */
191         nx_packet_release(rcv_packet_ptr);
192     }
193 
194     if((data_packet_counter == 1) && (rcv_length <= server_socket.nx_tcp_socket_connect_mss) && (server_socket.nx_tcp_socket_connect_mss >= (0.5 * server_socket.nx_tcp_socket_rx_window_default)))
195         if(window_last_sent != server_socket.nx_tcp_socket_rx_window_last_sent)
196         is_included = NX_TRUE;
197 
198 
199 
200     /* Disconnect the server socket.  */
201     status = nx_tcp_socket_disconnect(&server_socket, NX_IP_PERIODIC_RATE);
202 
203     /* Check for error.  */
204     if(status)
205         error_counter++;
206 
207     /* Unaccepted the server socket.  */
208     status = nx_tcp_server_socket_unaccept(&server_socket);
209 
210     /* Check for error.  */
211     if(status)
212         error_counter++;
213 
214     /* Unlisten on the server port.  */
215     status = nx_tcp_server_socket_unlisten(&ip_0, 12);
216 
217     /* Check for error.  */
218     if (status)
219         error_counter++;
220 
221     /* Delete the socket.  */
222     status = nx_tcp_socket_delete(&server_socket);
223 
224     /* Check for error.  */
225     if(status)
226         error_counter++;
227 }
228 
ntest_1_entry(ULONG thread_input)229 static void    ntest_1_entry(ULONG thread_input)
230 {
231 UINT         status;
232 NX_PACKET    *my_packet;
233 char         *msg = MSG;
234 
235     /* Create a socket.  */
236     status = nx_tcp_socket_create(&ip_1, &client_socket, "Client Socket",
237                                   NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 200,
238                                   NX_NULL, NX_NULL);
239 
240     /* Check for error.  */
241     if(status)
242         error_counter++;
243 
244     /* Bind the socket.  */
245     status = nx_tcp_client_socket_bind(&client_socket, 12, NX_IP_PERIODIC_RATE);
246 
247     /* Check for error.  */
248     if(status)
249         error_counter++;
250 
251     status = nx_tcp_client_socket_connect(&client_socket, IP_ADDRESS(1, 2, 3, 4), 12, 5 * NX_IP_PERIODIC_RATE);
252 
253     if(status)
254         error_counter++;
255 
256     mss_option = client_socket.nx_tcp_socket_connect_mss;
257 
258 
259     status = nx_packet_allocate(&pool_0, &my_packet, NX_TCP_PACKET, NX_IP_PERIODIC_RATE);
260 
261     /* Check for error.  */
262     if(status)
263         error_counter++;
264 
265     status = nx_packet_data_append(my_packet, msg, mss_option, &pool_0, NX_IP_PERIODIC_RATE);
266 
267     /* Check for error.  */
268     if(status)
269         error_counter++;
270 
271     /* Send the my_packet0  */
272     status = nx_tcp_socket_send(&client_socket, my_packet, 2 * NX_IP_PERIODIC_RATE);
273 
274     /* Check for error.  */
275     if(status)
276         error_counter++;
277 
278     tx_thread_resume(&ntest_0);
279 
280     /* Disconnect this socket.  */
281     status = nx_tcp_socket_disconnect(&client_socket, NX_IP_PERIODIC_RATE);
282 
283     /* Check for error.  */
284     if(status)
285         error_counter++;
286 
287     /* Unbind the socket.  */
288     status = nx_tcp_client_socket_unbind(&client_socket);
289 
290     /* Check for error.  */
291     if(status)
292         error_counter++;
293 
294     /* Delete the socket.  */
295     status = nx_tcp_socket_delete(&client_socket);
296 
297     /* Check for error.  */
298     if(status)
299         error_counter++;
300 
301     /* Determine if the test was successful.  */
302     if(error_counter || (data_packet_counter != 1) || (is_included != NX_TRUE))
303     {
304         printf("ERROR!\n");
305         test_control_return(1);
306     }
307     else
308     {
309         printf("SUCCESS!\n");
310         test_control_return(0);
311     }
312 }
313 
ntest_0_connect_received(NX_TCP_SOCKET * socket_ptr,UINT port)314 static void    ntest_0_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port)
315 {
316 
317     /* Check for the proper socket and port.  */
318     if((socket_ptr != &server_socket) || (port != 12))
319         error_counter++;
320 }
321 
ntest_0_disconnect_received(NX_TCP_SOCKET * socket)322 static void    ntest_0_disconnect_received(NX_TCP_SOCKET *socket)
323 {
324 
325     /* Check for proper disconnected socket.  */
326     if(socket != &server_socket)
327         error_counter++;
328 }
329 #else
330 
331 #ifdef CTEST
test_application_define(void * first_unused_memory)332 VOID test_application_define(void *first_unused_memory)
333 #else
334 void    netx_14_20_application_define(void *first_unused_memory)
335 #endif
336 {
337 
338     /* Print out test information banner.  */
339     printf("NetX Test:   TCP Spec 14.20 Test.......................................N/A\n");
340 
341     test_control_return(3);
342 }
343 #endif
344