1 /* This demo tests the nx_ppp_restart() function. To simulate a link down in the middle of the IPCP
2 negotiation, the thread_0/PPP_0 promotes the PPP 1 instance to LCP complete, and its IPCP state to STARTED.
3 Then the PPP0 instance is suspended as part of simulating link down.
4
5 PPP_1 should go into a FAILED state after the max number of retries, and call the link down callback.
6 NetX PPP has a restart function which reinitializes the PPP instance so it can restart the PPP
7 protocol using nx_ppp_restart().
8
9 The process is started again, PPP 0 is resumed, and thread 0 promotes the PPP 1 instance ahead
10 to the LCP complete state, and ICP start state. After the second link down event, the test is complete.
11
12 This test verifies that the NetX PPP properly clears and restarts a PPP instance, including resetting
13 the PPP state to restart the IPCP negotiation.
14 */
15
16 #include "tx_api.h"
17 #include "nx_api.h"
18 #include "nx_ppp.h"
19
20 extern void test_control_return(UINT status);
21
22 #if !defined(NX_DISABLE_IPV4)
23
24 /* Define demo stack size. */
25
26 #define DEMO_STACK_SIZE 2048
27
28
29 /* Define the ThreadX and NetX object control blocks... */
30
31 static TX_THREAD thread_0;
32 static TX_THREAD thread_1;
33
34 static NX_PACKET_POOL pool_0;
35 static NX_PACKET_POOL pool_1;
36
37 static NX_IP ip_0;
38 static NX_IP ip_1;
39
40 static NX_PPP ppp_0;
41 static NX_PPP ppp_1;
42
43
44 /* Define the counters used in the demo application... */
45
46 static ULONG ppp_0_link_up_counter;
47 static ULONG ppp_0_link_down_counter;
48 static ULONG ppp_1_link_up_counter;
49 static ULONG ppp_1_link_down_counter;
50 static ULONG error_counter = 0;
51 static UINT suspend_thread = NX_TRUE;
52
53 /* Define thread prototypes. */
54 static void thread_0_entry(ULONG thread_input);
55 static void thread_1_entry(ULONG thread_input);
56 static void link_up_callback(NX_PPP *ppp_ptr);
57 static void link_down_callback(NX_PPP *ppp_ptr);
58 static void ppp_0_serial_byte_output(UCHAR byte);
59 static void ppp_1_serial_byte_output(UCHAR byte);
60 static void invalid_packet_handler(NX_PACKET *packet_ptr);
61
62
63
64 /* Define what the initial system looks like. */
65
66 #ifdef CTEST
test_application_define(void * first_unused_memory)67 VOID test_application_define(void *first_unused_memory)
68 #else
69 void netx_ppp_IPCP_timeout_test_application_define(void *first_unused_memory)
70 #endif
71 {
72
73 CHAR *pointer;
74 UINT status;
75
76 /* Setup the working pointer. */
77 pointer = (CHAR *) first_unused_memory;
78
79 /* Create the thread 0. */
80 tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
81 pointer, DEMO_STACK_SIZE,
82 5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
83 pointer = pointer + DEMO_STACK_SIZE;
84
85 /* Create the thread 1. */
86 tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,
87 pointer, DEMO_STACK_SIZE,
88 5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
89 pointer = pointer + DEMO_STACK_SIZE;
90
91 /* Initialize the NetX system. */
92 nx_system_initialize();
93
94 /* Create a packet pool. */
95 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1024, pointer, 8192);
96 pointer = pointer + 8192;
97 status += nx_packet_pool_create(&pool_1, "NetX Main Packet Pool", NX_PPP_MIN_PACKET_PAYLOAD, pointer, 4096);
98 pointer = pointer + 4096;
99
100 /* Check for pool creation error. */
101 if (status)
102 error_counter++;
103
104
105 /* Create the first PPP instance. */
106 status = nx_ppp_create(&ppp_0, "PPP0", &ip_0, pointer, 2048, 1, &pool_0, invalid_packet_handler, ppp_0_serial_byte_output);
107 pointer = pointer + 2048;
108
109 /* Check for PPP create error. */
110 if (status)
111 error_counter++;
112
113 /* Define the IP addresses. This PPP instance is effectively the server since it has both IP addresses. */
114 status = nx_ppp_ip_address_assign(&ppp_0, IP_ADDRESS(1, 2, 3, 4), IP_ADDRESS(1, 2, 3, 5));
115
116 /* Check for PPP IP address assign error. */
117 if (status)
118 error_counter++;
119
120 /* Create an IP instance. */
121 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(0, 0, 0, 0), 0xFFFFF000UL, &pool_0, nx_ppp_driver,
122 pointer, 2048, 1);
123 pointer = pointer + 2048;
124
125 /* Check for IP create error. */
126 if (status)
127 error_counter++;
128
129 /* Register the link up/down callbacks. */
130 status = nx_ppp_link_up_notify(&ppp_0, link_up_callback);
131 status += nx_ppp_link_down_notify(&ppp_0, link_down_callback);
132
133 /* Check for PPP link up/down callback registration error(s). */
134 if (status)
135 error_counter++;
136
137 /* Create the next PPP instance. */
138 status = nx_ppp_create(&ppp_1, "PPP1", &ip_1, pointer, 2048, 1, &pool_1, invalid_packet_handler, ppp_1_serial_byte_output);
139 pointer = pointer + 2048;
140
141 /* Check for PPP create error. */
142 if (status)
143 error_counter++;
144
145 /* Define IP address. This PPP instance is effectively the client since it doesn't have any IP addresses. */
146 status = nx_ppp_ip_address_assign(&ppp_1, IP_ADDRESS(0, 0, 0, 0), IP_ADDRESS(0, 0, 0, 0));
147
148 /* Check for PPP IP address assign error. */
149 if (status)
150 error_counter++;
151
152 /* Create another IP instance. */
153 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(0, 0, 0, 0), 0xFFFFF000UL, &pool_1, nx_ppp_driver,
154 pointer, 2048, 1);
155 pointer = pointer + 2048;
156
157 /* Check for IP create error. */
158 if (status)
159 error_counter++;
160
161 /* Register the link up/down callbacks. */
162 status = nx_ppp_link_up_notify(&ppp_1, link_up_callback);
163 status += nx_ppp_link_down_notify(&ppp_1, link_down_callback);
164
165 /* Check for PPP link up/down callback registration error(s). */
166 if (status)
167 error_counter++;
168
169 /* Enable UDP traffic. */
170 nx_udp_enable(&ip_0);
171 nx_udp_enable(&ip_1);
172
173 /* Enable ICMP traffic. */
174 nx_icmp_enable(&ip_0);
175 nx_icmp_enable(&ip_1);
176
177 }
178
179
180 /* Define the test threads. */
181
thread_0_entry(ULONG thread_input)182 static void thread_0_entry(ULONG thread_input)
183 {
184
185 UINT status;
186 ULONG ip_status;
187
188 /* Print out test information banner. */
189 printf("NetX Test: PPP IPCP Timeout/Restart Test.............................");
190
191 if (error_counter)
192 {
193
194 printf("ERROR!\n");
195 test_control_return(1);
196 }
197
198 do
199 {
200
201 if (suspend_thread)
202 {
203
204 if (ppp_1.nx_ppp_lcp_state >= 2)
205 {
206
207 suspend_thread = NX_FALSE;
208
209 /* PPP_1 is in the LCP completed state. Suspend PPP_0 thread so PPP_1 will not be able
210 to complete the IPCP protocol. */
211 tx_thread_suspend(&(ppp_0.nx_ppp_thread));
212
213 ppp_1.nx_ppp_timeout = NX_PPP_PROTOCOL_TIMEOUT;
214 ppp_1.nx_ppp_lcp_state = NX_PPP_LCP_COMPLETED_STATE;
215 ppp_1.nx_ppp_ipcp_state = NX_PPP_IPCP_START_STATE;
216
217 }
218
219 }
220
221 /* Determine if the two or more restarts have occurred */
222 if (ppp_1_link_down_counter >= 2)
223 {
224 break;
225 }
226
227 /* Wait for the link to come up (this should not happen if we are
228 testing the link down callback. */
229 status = nx_ip_status_check(&ip_0, NX_IP_LINK_ENABLED, &ip_status, NX_IP_PERIODIC_RATE/2);
230
231 } while (status != NX_SUCCESS) ;
232
233 /* Determine if the test completed successfully. */
234 if ((error_counter == 0) && (ppp_0_link_down_counter == 0) && (ppp_1_link_down_counter >= 2))
235 {
236 printf("SUCCESS!\n");
237 test_control_return(0);
238 }
239 else
240 {
241 printf("ERROR!\n");
242 test_control_return(1);
243 }
244
245 }
246
247
thread_1_entry(ULONG thread_input)248 static void thread_1_entry(ULONG thread_input)
249 {
250
251
252 UINT status;
253 ULONG ip_status;
254
255 tx_thread_sleep(20);
256 do
257 {
258
259 /* If this is the second restart, the test is complete. */
260 if (ppp_1_link_down_counter > 1)
261 {
262
263 return;
264 }
265
266 /* Wait for the link to come up. */
267 status = nx_ip_status_check(&ip_1, NX_IP_LINK_ENABLED, &ip_status, NX_IP_PERIODIC_RATE/2);
268
269 } while (status != NX_SUCCESS);
270
271 }
272
273 /* Define serial output routines. Normally these routines would
274 map to physical UART routines and the nx_ppp_byte_receive call
275 would be made from a UART receive interrupt. */
276
ppp_0_serial_byte_output(UCHAR byte)277 static void ppp_0_serial_byte_output(UCHAR byte)
278 {
279
280 /* Just feed the PPP 1 input routine. */
281 nx_ppp_byte_receive(&ppp_1, byte);
282 }
283
ppp_1_serial_byte_output(UCHAR byte)284 static void ppp_1_serial_byte_output(UCHAR byte)
285 {
286
287 /* Just feed the PPP 0 input routine. */
288 nx_ppp_byte_receive(&ppp_0, byte);
289 }
290
291
invalid_packet_handler(NX_PACKET * packet_ptr)292 static void invalid_packet_handler(NX_PACKET *packet_ptr)
293 {
294
295 error_counter++;
296 nx_packet_release(packet_ptr);
297 }
298
299
link_up_callback(NX_PPP * ppp_ptr)300 static void link_up_callback(NX_PPP *ppp_ptr)
301 {
302
303 /* Just increment the link up counter. */
304 if (ppp_ptr == &ppp_0)
305 ppp_0_link_up_counter++;
306 else
307 ppp_1_link_up_counter++;
308 }
309
310
link_down_callback(NX_PPP * ppp_ptr)311 static void link_down_callback(NX_PPP *ppp_ptr)
312 {
313
314 /* Just increment the link down counter. */
315 if (ppp_ptr == &ppp_0)
316 ppp_0_link_down_counter++;
317 else
318 ppp_1_link_down_counter++;
319
320 if (ppp_ptr -> nx_ppp_ipcp_state != NX_PPP_IPCP_FAILED_STATE)
321 {
322 /* Error test should only restart from the IPCP FAILED state */
323 error_counter++;
324 return;
325 }
326
327 /* If this is the second restart, the test is complete. */
328 if (ppp_1_link_down_counter > 1)
329 {
330 /* Success. Restart test is complete */
331 return;
332 }
333
334 /* Restart PPP 1. */
335 nx_ppp_restart(ppp_ptr);
336
337 if (ppp_1_link_down_counter == 1)
338 {
339 /* First restart. Wait for second restart to verify first restart succeeds */
340 suspend_thread = NX_TRUE;
341 }
342
343 return;
344
345 }
346 #else
347
348 #ifdef CTEST
test_application_define(void * first_unused_memory)349 VOID test_application_define(void *first_unused_memory)
350 #else
351 void netx_ppp_IPCP_timeout_test_application_define(void *first_unused_memory)
352 #endif
353 {
354
355 /* Print out test information banner. */
356 printf("NetX Test: PPP IPCP Timeout/Restart Test.............................N/A\n");
357
358 test_control_return(3);
359 }
360 #endif
361
362
363