1 /* 15.25 TCP MUST include exponential backoff(check that it increases) for successive RTO values for sending SYN segments. */
2
3 /* Procedure
4 1. Client sends SYN to server.
5 2. When server receives SYN packet for the first three times, check RTO and drop the packet.
6 3. Check if client connects to server 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 syn_counter;
36
37 /* Define thread prototypes. */
38
39 static void ntest_1_entry(ULONG thread_input);
40 static void ntest_0_entry(ULONG thread_input);
41 static void ntest_1_connect_received(NX_TCP_SOCKET *server_socket, UINT port);
42 static void ntest_1_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_25(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_25_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 syn_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 4, 4, 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 3, 3, 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
130 /* Create a socket. */
131 status = nx_tcp_socket_create(&ip_0, &client_socket, "Client Socket",
132 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 300,
133 NX_NULL, NX_NULL);
134
135 /* Check for error. */
136 if(status)
137 error_counter++;
138
139 /* Bind the socket. */
140 status = nx_tcp_client_socket_bind(&client_socket, 12, NX_IP_PERIODIC_RATE);
141
142 /* Check for error. */
143 if(status)
144 error_counter++;
145
146 /* Init transmit configure. */
147 status = nx_tcp_socket_transmit_configure(&client_socket, client_socket.nx_tcp_socket_transmit_queue_maximum,
148 client_socket.nx_tcp_socket_timeout_rate, client_socket.nx_tcp_socket_timeout_max_retries, 1);
149
150 /* Check for error. */
151 if(status)
152 error_counter++;
153
154 advanced_packet_process_callback = my_packet_process_15_25;
155
156 /* Attempt to connect the socket. */
157 status = nx_tcp_client_socket_connect(&client_socket, IP_ADDRESS(1, 2, 3, 5), 12, 100 * NX_IP_PERIODIC_RATE);
158
159 /* Check for error. */
160 if(status)
161 error_counter++;
162
163 /* Disconnect this socket. */
164 status = nx_tcp_socket_disconnect(&client_socket, NX_IP_PERIODIC_RATE);
165
166 /* Check for error. */
167 if(status)
168 error_counter++;
169
170 /* Unbind the socket. */
171 status = nx_tcp_client_socket_unbind(&client_socket);
172
173 /* Check for error. */
174 if(status)
175 error_counter++;
176
177 /* Delete the socket. */
178 status = nx_tcp_socket_delete(&client_socket);
179
180 /* Check for error. */
181 if(status)
182 error_counter++;
183
184 /* Determine if the test was successful. */
185 if(error_counter || (drop_counter != 1) || (syn_counter != 2))
186 {
187 printf("ERROR!\n");
188 test_control_return(1);
189 }
190 else
191 {
192 printf("SUCCESS!\n");
193 test_control_return(0);
194 }
195 }
196
ntest_1_entry(ULONG thread_input)197 static void ntest_1_entry(ULONG thread_input)
198 {
199 UINT status;
200 ULONG actual_status;
201
202 /* Print out test information banner. */
203 printf("NetX Test: TCP Spec 15.25 Test.......................................");
204
205 /* Check for earlier error. */
206 if(error_counter)
207 {
208 printf("ERROR!\n");
209 test_control_return(1);
210 }
211
212 /* Ensure the IP instance has been initialized. */
213 status = nx_ip_status_check(&ip_1, NX_IP_INITIALIZE_DONE, &actual_status, NX_IP_PERIODIC_RATE);
214
215 /* Check for error. */
216 if(status)
217 error_counter++;
218
219 /* Create a socket. */
220 status = nx_tcp_socket_create(&ip_1, &server_socket, "Server Socket",
221 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 200,
222 NX_NULL, ntest_1_disconnect_received);
223
224 /* Check for error. */
225 if(status)
226 error_counter++;
227
228 /* Setup this thread to listen. */
229 status = nx_tcp_server_socket_listen(&ip_1, 12, &server_socket, 5, ntest_1_connect_received);
230
231 /* Check for error. */
232 if(status)
233 error_counter++;
234
235 /* If accept return successfully, the connection has established. */
236 status = nx_tcp_server_socket_accept(&server_socket, 100 * NX_IP_PERIODIC_RATE);
237
238 /* Check for error. */
239 if(status)
240 error_counter++;
241
242 /* Disconnect the server socket. */
243 status = nx_tcp_socket_disconnect(&server_socket, NX_IP_PERIODIC_RATE);
244
245 /* Check for error. */
246 if(status)
247 error_counter++;
248
249 status = nx_tcp_server_socket_unaccept(&server_socket);
250
251 /* Check for error. */
252 if(status)
253 error_counter++;
254
255 /* Unlisten on the server port. */
256 status = nx_tcp_server_socket_unlisten(&ip_1, 12);
257
258 /* Check for error. */
259 if (status)
260 error_counter++;
261
262 /* Delete the socket. */
263 status = nx_tcp_socket_delete(&server_socket);
264
265 /* Check for error. */
266 if(status)
267 error_counter++;
268 }
269
ntest_1_connect_received(NX_TCP_SOCKET * socket_ptr,UINT port)270 static void ntest_1_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port)
271 {
272
273 /* Check for the proper socket and port. */
274 if((socket_ptr != &server_socket) || (port != 12))
275 error_counter++;
276 }
277
ntest_1_disconnect_received(NX_TCP_SOCKET * socket)278 static void ntest_1_disconnect_received(NX_TCP_SOCKET *socket)
279 {
280
281 /* Check for proper disconnected socket. */
282 if(socket != &server_socket)
283 error_counter++;
284 }
285
my_packet_process_15_25(NX_IP * ip_ptr,NX_PACKET * packet_ptr,UINT * operation_ptr,UINT * delay_ptr)286 static UINT my_packet_process_15_25(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr)
287 {
288 NX_TCP_HEADER *header_ptr;
289
290 header_ptr = (NX_TCP_HEADER *)(packet_ptr -> nx_packet_prepend_ptr + 20);
291
292 NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_3);
293
294 /* If this is a tcp packet but not an ARP packet or other kind packet. */
295 if(packet_ptr -> nx_packet_length >= 40)
296 {
297 /* Drop packet three times. */
298 if((header_ptr -> nx_tcp_header_word_3 & NX_TCP_SYN_BIT) && !(header_ptr -> nx_tcp_header_word_3 & NX_TCP_ACK_BIT) && !(header_ptr -> nx_tcp_header_word_3 & NX_TCP_RST_BIT))
299 {
300
301 syn_counter++;
302
303 if(drop_counter == 0)
304 {
305
306 *operation_ptr = NX_RAMDRIVER_OP_DROP;
307
308 drop_counter++;
309 }
310 else
311 {
312 /* Check if successive RTO increases as 'exponential backoff'. */
313 if(client_socket.nx_tcp_socket_timeout != (client_socket.nx_tcp_socket_timeout_rate << (drop_counter * client_socket.nx_tcp_socket_timeout_shift)))
314 {
315 error_counter++;
316 }
317
318 advanced_packet_process_callback = NX_NULL;
319
320 /* Wake up server and client thread. */
321 tx_thread_resume(&ntest_0);
322 tx_thread_resume(&ntest_1);
323 }
324
325 NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_3);
326 }
327 }
328 return NX_TRUE;
329 }
330 #else
331
332 #ifdef CTEST
test_application_define(void * first_unused_memory)333 VOID test_application_define(void *first_unused_memory)
334 #else
335 void netx_15_25_application_define(void *first_unused_memory)
336 #endif
337 {
338
339 /* Print out test information banner. */
340 printf("NetX Test: TCP Spec 15.25 Test.......................................N/A\n");
341
342 test_control_return(3);
343 }
344 #endif