1 /* 15.24 TCP MUST include 'exponential backoff' (check that it increases) for successive RTO values for sending data segments. */
2
3 /* Procedure
4 1. Client sends data to server.
5 2. When server receives packet for the first three times, check RTO and drop the packet.
6 3. Check if server receives data successfully. */
7
8 #include "tx_api.h"
9 #include "nx_api.h"
10 #include "nx_tcp.h"
11 #include "nx_ram_network_driver_test_1500.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 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
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 drop_counter;
35 static ULONG data_packet_counter;
36
37 /* Define thread prototypes. */
38
39 static void ntest_0_entry(ULONG thread_input);
40 static void ntest_1_entry(ULONG thread_input);
41 static void ntest_0_connect_received(NX_TCP_SOCKET *server_socket, UINT port);
42 static void ntest_0_disconnect_received(NX_TCP_SOCKET *server_socket);
43 extern void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
44 extern void _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
45 extern UINT (*advanced_packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
46 static UINT my_packet_process_15_24(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
47
48 /* Define what the initial system looks like. */
49
50 #ifdef CTEST
test_application_define(void * first_unused_memory)51 VOID test_application_define(void *first_unused_memory)
52 #else
53 void netx_15_24_application_define(void *first_unused_memory)
54 #endif
55 {
56 CHAR *pointer;
57 UINT status;
58
59 /* Setup the working pointer. */
60 pointer = (CHAR *) first_unused_memory;
61
62 error_counter = 0;
63 drop_counter = 0;
64 data_packet_counter = 0;
65
66 /* Create the main thread. */
67 tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
68 pointer, DEMO_STACK_SIZE,
69 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
70
71 pointer = pointer + DEMO_STACK_SIZE;
72
73 /* Create the main thread. */
74 tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
75 pointer, DEMO_STACK_SIZE,
76 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
77
78 pointer = pointer + DEMO_STACK_SIZE;
79
80 /* Initialize the NetX system. */
81 nx_system_initialize();
82
83 /* Create a packet pool. */
84 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 512, pointer, 8192);
85 pointer = pointer + 8192;
86
87 if(status)
88 error_counter++;
89
90 /* Create an IP instance. */
91 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500,
92 pointer, 2048, 1);
93 pointer = pointer + 2048;
94
95 /* Create another IP instance. */
96 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
97 pointer, 2048, 1);
98 pointer = pointer + 2048;
99
100 if(status)
101 error_counter++;
102
103 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
104 status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
105 pointer = pointer + 1024;
106
107 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
108 status += nx_arp_enable(&ip_1, (void *) pointer, 1024);
109 pointer = pointer + 1024;
110
111 /* Check ARP enable status. */
112 if(status)
113 error_counter++;
114
115 /* Enable TCP processing for both IP instances. */
116 status = nx_tcp_enable(&ip_0);
117 status += nx_tcp_enable(&ip_1);
118
119 /* Check TCP enable status. */
120 if(status)
121 error_counter++;
122 }
123
124 /* Define the test threads. */
125
ntest_0_entry(ULONG thread_input)126 static void ntest_0_entry(ULONG thread_input)
127 {
128 UINT status;
129 ULONG actual_status;
130 NX_PACKET *my_packet;
131
132 /* Print out test information banner. */
133 printf("NetX Test: TCP Spec 15.24 Test.......................................");
134
135 /* Check for earlier error. */
136 if(error_counter)
137 {
138 printf("ERROR!\n");
139 test_control_return(1);
140 }
141
142 /* Ensure the IP instance has been initialized. */
143 status = nx_ip_status_check(&ip_0, NX_IP_INITIALIZE_DONE, &actual_status, NX_IP_PERIODIC_RATE);
144
145 /* Check for error. */
146 if(status)
147 error_counter++;
148
149 /* Create a socket. */
150 status = nx_tcp_socket_create(&ip_0, &server_socket, "Server Socket",
151 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 200,
152 NX_NULL, ntest_0_disconnect_received);
153
154 /* Check for error. */
155 if(status)
156 error_counter++;
157
158 /* Setup this thread to listen. */
159 status = nx_tcp_server_socket_listen(&ip_0, 12, &server_socket, 5, ntest_0_connect_received);
160
161 /* Check for error. */
162 if(status)
163 error_counter++;
164
165 /* If accept return successfully, the connection has established. */
166 status = nx_tcp_server_socket_accept(&server_socket, NX_IP_PERIODIC_RATE);
167
168 /* Check for error. */
169 if(status)
170 error_counter++;
171
172 /* Init transmit configure. */
173 status = nx_tcp_socket_transmit_configure(&server_socket, server_socket.nx_tcp_socket_transmit_queue_maximum,
174 server_socket.nx_tcp_socket_timeout_rate, server_socket.nx_tcp_socket_timeout_max_retries, 1);
175
176 /* Check for error. */
177 if(status)
178 error_counter++;
179
180 /* Create a packet to send. */
181 status = nx_packet_allocate(&pool_0, &my_packet, NX_TCP_PACKET, NX_IP_PERIODIC_RATE);
182
183 /* Check for error. */
184 if(status)
185 error_counter++;
186
187 status = nx_packet_data_append(my_packet, MSG, 20, &pool_0, NX_IP_PERIODIC_RATE);
188
189 /* Check for error. */
190 if(status)
191 error_counter++;
192
193 advanced_packet_process_callback = my_packet_process_15_24;
194
195 /* Send packet to server. */
196 status = nx_tcp_socket_send(&server_socket , my_packet, NX_IP_PERIODIC_RATE);
197
198 /* Check for error. */
199 if(status)
200 error_counter++;
201
202 /* Wait for the retransmit. */
203 tx_thread_suspend(&ntest_0);
204
205 /* Disconnect the server socket. */
206 status = nx_tcp_socket_disconnect(&server_socket, NX_IP_PERIODIC_RATE);
207
208 /* Check for error. */
209 if(status)
210 error_counter++;
211
212 status = nx_tcp_server_socket_unaccept(&server_socket);
213
214 /* Check for error. */
215 if(status)
216 error_counter++;
217
218 /* Unlisten on the server port. */
219 status = nx_tcp_server_socket_unlisten(&ip_0, 12);
220
221 /* Check for error. */
222 if (status)
223 error_counter++;
224
225 /* Delete the socket. */
226 status = nx_tcp_socket_delete(&server_socket);
227
228 /* Check for error. */
229 if(status)
230 error_counter++;
231 }
232
ntest_1_entry(ULONG thread_input)233 static void ntest_1_entry(ULONG thread_input)
234 {
235 UINT status;
236 NX_PACKET *rcv_packet_ptr;
237
238 /* Create a socket. */
239 status = nx_tcp_socket_create(&ip_1, &client_socket, "Client Socket",
240 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 300,
241 NX_NULL, NX_NULL);
242
243 /* Check for error. */
244 if(status)
245 error_counter++;
246
247 /* Bind the socket. */
248 status = nx_tcp_client_socket_bind(&client_socket, 12, NX_IP_PERIODIC_RATE);
249
250 /* Check for error. */
251 if(status)
252 error_counter++;
253
254 /* Attempt to connect the socket. */
255 status = nx_tcp_client_socket_connect(&client_socket, IP_ADDRESS(1, 2, 3, 4), 12, 2 * NX_IP_PERIODIC_RATE);
256
257 /* Check for error. */
258 if(status)
259 error_counter++;
260
261 /* Wait until retransmit. */
262 tx_thread_suspend(&ntest_1);
263
264 status = nx_tcp_socket_receive(&client_socket, &rcv_packet_ptr, 2 * NX_IP_PERIODIC_RATE);
265
266 /* Check for error. */
267 if(status)
268 error_counter++;
269 else
270 {
271 /* Check data length and payload */
272 if((rcv_packet_ptr -> nx_packet_length == 20) &&
273 (!memcmp(rcv_packet_ptr -> nx_packet_prepend_ptr, MSG, 20)))
274 data_packet_counter++;
275
276 /* Release the packet. */
277 nx_packet_release(rcv_packet_ptr);
278 }
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 || (drop_counter != 2) || (data_packet_counter != 1))
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
my_packet_process_15_24(NX_IP * ip_ptr,NX_PACKET * packet_ptr,UINT * operation_ptr,UINT * delay_ptr)330 static UINT my_packet_process_15_24(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr)
331 {
332 /* Drop packet three times. */
333 if ((packet_ptr -> nx_packet_length - 40 == 20) && (!memcmp(packet_ptr -> nx_packet_prepend_ptr + 40, MSG, 20)))
334 {
335
336 if(drop_counter < 2)
337 {
338
339 /* Check if successive RTO increases as 'exponential backoff'. */
340 if(server_socket.nx_tcp_socket_timeout != (server_socket.nx_tcp_socket_timeout_rate << (drop_counter * server_socket.nx_tcp_socket_timeout_shift)))
341 {
342 error_counter++;
343 }
344
345 *operation_ptr = NX_RAMDRIVER_OP_DROP;
346
347 drop_counter++;
348 }
349 else
350 {
351 advanced_packet_process_callback = NX_NULL;
352
353 /* Wake up server and client thread. */
354 tx_thread_resume(&ntest_0);
355 tx_thread_resume(&ntest_1);
356 }
357 }
358
359 return NX_TRUE;
360 }
361 #else
362
363 #ifdef CTEST
test_application_define(void * first_unused_memory)364 VOID test_application_define(void *first_unused_memory)
365 #else
366 void netx_15_24_application_define(void *first_unused_memory)
367 #endif
368 {
369
370 /* Print out test information banner. */
371 printf("NetX Test: TCP Spec 15.24 Test.......................................N/A\n");
372
373 test_control_return(3);
374 }
375 #endif
376