1 /* This tests that in NX_PPP_IPCP_CONFIGURE_REQUEST_ACKED_STATE state, we can send the correct NAK. */
2
3 #include "tx_api.h"
4 #include "nx_api.h"
5 #include "nx_ppp.h"
6
7 extern void test_control_return(UINT status);
8
9 #if !defined(NX_DISABLE_IPV4)
10
11 /* Define demo stack size. */
12
13 #define DEMO_STACK_SIZE 2048
14 #define DEMO_DATA "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
15
16
17 /* Define the ThreadX and NetX object control blocks... */
18
19 static TX_THREAD thread_0;
20 static TX_THREAD thread_1;
21
22 static NX_PACKET_POOL pool_0;
23
24 static NX_IP ip_0;
25 static NX_IP ip_1;
26
27 static NX_PPP ppp_0;
28 static NX_PPP ppp_1;
29
30 static NX_UDP_SOCKET socket_0;
31 static NX_UDP_SOCKET socket_1;
32
33
34 /* Define the counters used in the demo application... */
35
36 static ULONG ppp_0_link_up_counter;
37 static ULONG ppp_0_link_down_counter;
38 static ULONG ppp_1_link_up_counter;
39 static ULONG ppp_1_link_down_counter;
40 static UINT error_counter = 0;
41 static UINT thread_1_alive = NX_TRUE;
42
43
44 /* Define thread prototypes. */
45 static void thread_0_entry(ULONG thread_input);
46 static void thread_1_entry(ULONG thread_input);
47
48 static void link_up_callback(NX_PPP *ppp_ptr);
49 static void link_down_callback(NX_PPP *ppp_ptr);
50 static void ppp_0_serial_byte_output(UCHAR byte);
51 static void ppp_1_serial_byte_output(UCHAR byte);
52 static void invalid_packet_handler(NX_PACKET *packet_ptr);
53
54 /* Define what the initial system looks like. */
55
56 #ifdef CTEST
test_application_define(void * first_unused_memory)57 VOID test_application_define(void *first_unused_memory)
58 #else
59 void netx_ppp_IPCP_retransmit_test_application_define(void *first_unused_memory)
60 #endif
61 {
62
63 CHAR *pointer;
64 UINT status;
65
66
67 /* Setup the working pointer. */
68 pointer = (CHAR *) first_unused_memory;
69
70 /* Create the thread 0. */
71 tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
72 pointer, DEMO_STACK_SIZE,
73 5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
74 pointer = pointer + DEMO_STACK_SIZE;
75
76 /* Create the thread 1. */
77 tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,
78 pointer, DEMO_STACK_SIZE,
79 5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
80 pointer = pointer + DEMO_STACK_SIZE;
81
82 /* Initialize the NetX system. */
83 nx_system_initialize();
84
85 /* Create a packet pool. */
86 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, 2048);
87 pointer = pointer + 2048;
88
89 /* Check for pool creation error. */
90 if (status)
91 error_counter++;
92
93 /* Create the first PPP instance. */
94 status = nx_ppp_create(&ppp_0, "PPP 0", &ip_0, pointer, 2048, 1, &pool_0, invalid_packet_handler, ppp_0_serial_byte_output);
95 pointer = pointer + 2048;
96
97 /* Check for PPP create error. */
98 if (status)
99 error_counter++;
100
101 /* Define IP address. This PPP instance is effectively the server since it has both IP addresses. */
102 status = nx_ppp_ip_address_assign(&ppp_0, IP_ADDRESS(1, 2, 3, 4), IP_ADDRESS(1, 2, 3, 5));
103
104 /* Check for PPP IP address assign error. */
105 if (status)
106 error_counter++;
107
108 /* Register the link up/down callbacks. */
109 status = nx_ppp_link_up_notify(&ppp_0, link_up_callback);
110 status += nx_ppp_link_down_notify(&ppp_0, link_down_callback);
111
112 /* Check for PPP link up/down callback registration error(s). */
113 if (status)
114 error_counter++;
115
116 /* Create an IP instance. */
117 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(0, 0, 0, 0), 0xFFFFF000UL, &pool_0, nx_ppp_driver,
118 pointer, 2048, 1);
119 pointer = pointer + 2048;
120
121 if (status)
122 error_counter++;
123
124 /* Create the next PPP instance. */
125 status = nx_ppp_create(&ppp_1, "PPP 1", &ip_1, pointer, 2048, 1, &pool_0, invalid_packet_handler, ppp_1_serial_byte_output);
126 pointer = pointer + 2048;
127
128 /* Check for PPP create error. */
129 if (status)
130 error_counter++;
131
132 /* Define IP address. This PPP instance is effectively the client since it doesn't have any IP addresses. */
133 status = nx_ppp_ip_address_assign(&ppp_1, IP_ADDRESS(0, 0, 0, 0), IP_ADDRESS(0, 0, 0, 0));
134
135 /* Check for PPP IP address assign error. */
136 if (status)
137 error_counter++;
138
139 /* Register the link up/down callbacks. */
140 status = nx_ppp_link_up_notify(&ppp_1, link_up_callback);
141 status += nx_ppp_link_down_notify(&ppp_1, link_down_callback);
142
143 /* Check for PPP link up/down callback registration error(s). */
144 if (status)
145 error_counter++;
146
147 /* Create another IP instance. */
148 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(0, 0, 0, 0), 0xFFFFF000UL, &pool_0, nx_ppp_driver, pointer, 2048, 1);
149 pointer = pointer + 2048;
150
151 if (status)
152 error_counter++;
153
154 /* Enable UDP traffic. */
155 nx_udp_enable(&ip_0);
156 nx_udp_enable(&ip_1);
157 }
158
159
160 /* Define the test threads. */
161
thread_0_entry(ULONG thread_input)162 static void thread_0_entry(ULONG thread_input)
163 {
164
165 UINT status;
166 ULONG ip_status;
167 NX_PACKET *my_packet;
168
169 /* Print out test information banner. */
170 printf("NetX Test: PPP IPCP Retransmit Test..................................");
171
172 if (error_counter)
173 {
174
175 printf("ERROR!\n");
176 test_control_return(1);
177 }
178
179 /* Wait for the link to come up. */
180 status = nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &ip_status, 30 * NX_IP_PERIODIC_RATE);
181
182 if (status != NX_SUCCESS)
183 {
184
185 printf("ERROR!\n");
186 test_control_return(1);
187 }
188
189
190 /* Create a UDP socket. */
191 status = nx_udp_socket_create(&ip_0, &socket_0, "Socket 0", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
192
193 /* Check status. */
194 if (status)
195 {
196 error_counter++;
197 }
198
199 /* Bind the UDP socket to the IP port. */
200 status = nx_udp_socket_bind(&socket_0, 0x88, TX_WAIT_FOREVER);
201
202 /* Check status. */
203 if (status)
204 {
205 error_counter++;
206 }
207
208 /* Disable checksum logic for this socket. */
209 nx_udp_socket_checksum_disable(&socket_0);
210
211 /* Let receiver thread run. */
212 tx_thread_relinquish();
213
214 /* Allocate a packet. */
215 status = nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
216
217 /* Check status. */
218 if (status != NX_SUCCESS)
219 error_counter++;
220
221 /* Write ABCs into the packet payload! */
222 nx_packet_data_append(my_packet, DEMO_DATA, sizeof(DEMO_DATA), &pool_0, TX_WAIT_FOREVER);
223
224 /* Send the UDP packet. */
225 status = nx_udp_socket_send(&socket_0, my_packet, IP_ADDRESS(1, 2, 3, 5), 0x89);
226
227 /* Check status. */
228 if (status != NX_SUCCESS)
229 {
230 error_counter++;
231 }
232
233 while(thread_1_alive)
234 tx_thread_sleep(50);
235
236 if (error_counter)
237 {
238 printf("ERROR!\n");
239 test_control_return(1);
240 }
241 else
242 {
243 printf("SUCCESS!\n");
244 test_control_return(0);
245 }
246 }
247
248
thread_1_entry(ULONG thread_input)249 static void thread_1_entry(ULONG thread_input)
250 {
251
252 UINT status;
253 ULONG ip_status;
254 NX_PACKET *my_packet;
255
256 /* Wait for the link to come up. */
257 status = nx_ip_status_check(&ip_1, NX_IP_ADDRESS_RESOLVED, &ip_status, 30 * NX_IP_PERIODIC_RATE);
258
259 if (status != NX_SUCCESS)
260 {
261
262 printf("ERROR!\n");
263 test_control_return(1);
264 }
265
266 /* Create a UDP socket. */
267 status = nx_udp_socket_create(&ip_1, &socket_1, "Socket 1", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
268
269 /* Check status. */
270 if (status)
271 {
272 error_counter++;
273 return;
274 }
275
276 /* Bind the UDP socket to the IP port. */
277 status = nx_udp_socket_bind(&socket_1, 0x89, TX_WAIT_FOREVER);
278
279 /* Check status. */
280 if (status)
281 {
282 error_counter++;
283 return;
284 }
285
286 /* Receive a UDP packet. */
287 status = nx_udp_socket_receive(&socket_1, &my_packet, TX_WAIT_FOREVER);
288
289 /* Check status. */
290 if (status != NX_SUCCESS)
291 error_counter++;
292
293 /* Release the packet. */
294 status = nx_packet_release(my_packet);
295
296 /* Check status. */
297 if (status != NX_SUCCESS)
298 error_counter++;
299
300 thread_1_alive = NX_FALSE;
301
302 return;
303 }
304
305 /* Define serial output routines. Normally these routines would
306 map to physical UART routines and the nx_ppp_byte_receive call
307 would be made from a UART receive interrupt. */
308 static UCHAR temp_data[8] = {0};
309 static UCHAR temp_index = 0;
310 static UINT i = 0;
311 static UINT packet_drop = NX_FALSE;
312 static UINT packet_end = NX_FALSE;
313
314 static UCHAR configure_request_ack[] = {0x7E, 0xFF, 0x7D, 0x23, 0xc0, 0x21, 0x7D, 0x22};
315
ppp_0_serial_byte_output(UCHAR byte)316 static void ppp_0_serial_byte_output(UCHAR byte)
317 {
318
319 /* Discard LCP Configure Request ACK before NX_PPP_IPCP_CONFIGURE_REQUEST_SENT_STATE. */
320 if (ppp_0.nx_ppp_ipcp_state < NX_PPP_IPCP_CONFIGURE_REQUEST_SENT_STATE)
321 {
322
323 if (byte == 0x7e)
324 {
325
326 if (temp_index == 0)
327 {
328 packet_drop = NX_TRUE;
329 packet_end = NX_FALSE;
330 i = 0;
331 }
332 else
333 {
334 packet_end = NX_TRUE;
335 }
336 }
337
338 if (temp_index < 8)
339 {
340 temp_data[temp_index++] = byte;
341 }
342 else if (memcmp(temp_data, configure_request_ack, 8) != 0)
343 {
344 packet_drop = NX_FALSE;
345 }
346
347 if (packet_drop)
348 {
349 if (packet_end)
350 temp_index = 0;
351 return;
352 }
353 else
354 {
355 for (;i < temp_index; i++)
356 {
357 nx_ppp_byte_receive(&ppp_1, temp_data[i]);
358 }
359
360 if (packet_end)
361 temp_index = 0;
362 }
363 }
364
365 /* Just feed the PPP 1 input routine. */
366 nx_ppp_byte_receive(&ppp_1, byte);
367 }
368
ppp_1_serial_byte_output(UCHAR byte)369 static void ppp_1_serial_byte_output(UCHAR byte)
370 {
371
372 /* Just feed the PPP 0 input routine. */
373 nx_ppp_byte_receive(&ppp_0, byte);
374 }
375
376
invalid_packet_handler(NX_PACKET * packet_ptr)377 static void invalid_packet_handler(NX_PACKET *packet_ptr)
378 {
379 /* Print out the non-PPP byte. In Windows, the string "CLIENT" will
380 be sent before Windows PPP starts. Once CLIENT is received, we need
381 to send "CLIENTSERVER" to establish communication. It's also possible
382 to receive modem commands here that might need some response to
383 continue. */
384 nx_packet_release(packet_ptr);
385 }
386
387
link_up_callback(NX_PPP * ppp_ptr)388 static void link_up_callback(NX_PPP *ppp_ptr)
389 {
390
391 /* Just increment the link up counter. */
392 if (ppp_ptr == &ppp_0)
393 ppp_0_link_up_counter++;
394 else
395 ppp_1_link_up_counter++;
396 }
397
398
link_down_callback(NX_PPP * ppp_ptr)399 static void link_down_callback(NX_PPP *ppp_ptr)
400 {
401
402 /* Just increment the link down counter. */
403 if (ppp_ptr == &ppp_0)
404 ppp_0_link_down_counter++;
405 else
406 ppp_1_link_down_counter++;
407
408 /* Restart the PPP instance. */
409 nx_ppp_restart(ppp_ptr);
410 }
411 #else
412
413 #ifdef CTEST
test_application_define(void * first_unused_memory)414 VOID test_application_define(void *first_unused_memory)
415 #else
416 void netx_ppp_IPCP_retransmit_test_application_define(void *first_unused_memory)
417 #endif
418 {
419
420 /* Print out test information banner. */
421 printf("NetX Test: PPP IPCP retransmit Test..................................N/A\n");
422
423 test_control_return(3);
424 }
425 #endif
426