1 //==========================================================================
5 // Test of repeatedly releasing and reacquiring DHCP leases
7 //==========================================================================
8 //####BSDCOPYRIGHTBEGIN####
10 // -------------------------------------------
12 // Portions of this software may have been derived from OpenBSD or other sources,
13 // and are covered by the appropriate copyright disclaimers included herein.
15 // -------------------------------------------
17 //####BSDCOPYRIGHTEND####
18 //==========================================================================
19 //#####DESCRIPTIONBEGIN####
21 // Author(s): hmt, tomislav.sostaric@ascom.ch
24 // Purpose: Test repeated up-down cycles of interfaces with DHCP.
28 //####DESCRIPTIONEND####
30 //==========================================================================
33 * A test program for bringing out the DHCP memory leak bug
34 * This file is in the public domain and may be used for any purpose
41 #include <pkgconf/system.h>
42 #include <pkgconf/net.h>
44 #include <cyg/infra/testcase.h>
46 #ifdef CYGPKG_NET_DHCP
48 #ifdef CYGBLD_DEVS_ETH_DEVICE_H // Get the device config if it exists
49 #include CYGBLD_DEVS_ETH_DEVICE_H // May provide CYGTST_DEVS_ETH_TEST_NET_REALTIME
53 #include <stdio.h> /* printf */
54 #include <string.h> /* strlen */
55 #include <cyg/kernel/kapi.h> /* All the kernel specific stuff */
56 #include <cyg/io/io.h> /* I/O functions */
57 #include <cyg/hal/hal_arch.h> /* CYGNUM_HAL_STACK_SIZE_TYPICAL */
61 // ------------------------------------------------------------------------
65 #define TICKS_PER_SEC 100
67 #define nLOOPS 1000000
70 // ------------------------------------------------------------------------
72 #define NINTERFACES (2)
74 struct bootp bootp_data[ NINTERFACES ];
75 cyg_uint8 state[ NINTERFACES ];
76 struct dhcp_lease lease[ NINTERFACES ];
77 int up[ NINTERFACES ], oldup[ NINTERFACES ];
79 char *eth[ NINTERFACES ] = { "eth0", "eth1" };
84 tdhcp_init( int which )
86 printf("%s: Initializing device to use DHCP.\n", eth[which] );
87 bzero( &bootp_data[which], sizeof( *bootp_data ) );
89 bzero( &lease[which], sizeof( *lease ) );
90 up[which] = oldup[which] = FALSE;
95 tdhcp_do_one( int which )
97 oldup[which] = up[which];
98 up[which] = do_dhcp( eth[which], &bootp_data[which], &state[which], &lease[which] );
102 tdhcp_updown_one( int which )
104 /* DHCP wants interface to go up or down, do it. */
105 if (up[which] != oldup[which]) {
110 result = init_net( eth[which], &bootp_data[which]);
112 printf("%s: Initialization (DHCP) failed.\n", eth[which] );
116 if (lease[which].expiry == (cyg_tick_count_t)-1) {
117 strcpy(tbuf, "infinite");
119 cyg_tick_count_t now;
122 now = cyg_current_time();
123 exp = ((lease[which].expiry > now) ? lease[which].expiry - now : 0) / TICKS_PER_SEC;
124 sprintf(tbuf, "%ud %uh %um %us", exp / 86400,
125 (exp / 3600) % 24, (exp / 60) % 60, exp % 60);
127 printf("%s: Configured by DHCP, IP address %s, "
128 "lease expiry: %s.\n", eth[which],
129 inet_ntoa(bootp_data[which].bp_yiaddr), tbuf);
130 printf("%s: Interface ready\n", eth[which] );
132 printf("%s: Deconfigured by DHCP.\n", eth[which] );
133 cyg_thread_delay(10);
134 do_dhcp_down_net( eth[which], &bootp_data[which], &state[which], &lease[which]);
135 state[which] = DHCPSTATE_INIT;
141 tdhcp_release_one( int which )
143 /* If DHCP failed (most probably because there was no DHCP server around),
144 * sleep a bit, then try again. Otherwise, just wait until DHCP needs our
147 if (state[which] == DHCPSTATE_FAILED) {
148 printf("%s: DHCP failed, will retry later.\n", eth[which] );
149 cyg_thread_delay(10);
150 printf("%s: Retrying DHCP.\n", eth[which] );
152 cyg_thread_delay(10);
153 printf("%s: Releasing DHCP lease.\n", eth[which] );
154 do_dhcp_release( eth[which], &bootp_data[which], &state[which], &lease[which]);
155 cyg_thread_delay(10);
157 state[which] = DHCPSTATE_INIT;
162 dhcp_if_fn(cyg_addrword_t data)
166 #ifdef CYGHWR_NET_DRIVER_ETH0
168 #endif // CYGHWR_NET_DRIVER_ETH0
169 #ifdef CYGHWR_NET_DRIVER_ETH1
171 #endif // CYGHWR_NET_DRIVER_ETH1
173 while ( ++counter < LOOPS ) {
174 diag_printf( "--------- counter %d ---------\n", counter );
175 #ifdef CYGHWR_NET_DRIVER_ETH0
177 #endif // CYGHWR_NET_DRIVER_ETH0
178 #ifdef CYGHWR_NET_DRIVER_ETH1
180 #endif // CYGHWR_NET_DRIVER_ETH1
182 #ifdef CYGHWR_NET_DRIVER_ETH0
183 tdhcp_updown_one( 0 );
184 #endif // CYGHWR_NET_DRIVER_ETH0
185 #ifdef CYGHWR_NET_DRIVER_ETH1
186 tdhcp_updown_one( 1 );
187 #endif // CYGHWR_NET_DRIVER_ETH1
189 #ifdef CYGHWR_NET_DRIVER_ETH0
190 tdhcp_release_one( 0 );
191 #endif // CYGHWR_NET_DRIVER_ETH0
192 #ifdef CYGHWR_NET_DRIVER_ETH1
193 tdhcp_release_one( 1 );
194 #endif // CYGHWR_NET_DRIVER_ETH1
196 CYG_TEST_PASS_EXIT( "All done" );
200 // ------------------------------------------------------------------------
203 #define STACKSIZE ( CYGNUM_HAL_STACK_SIZE_TYPICAL + 4096 )
205 static cyg_handle_t thread[NTHREADS];
206 static cyg_thread thread_obj[NTHREADS];
207 static char stack[NTHREADS][STACKSIZE];
209 void cyg_user_start(void)
211 // Use the DHCP thread prio as provided even though we're not using the thread itself;
212 // This priroty should be right (lower than net thread prio) by default.
213 cyg_thread_create(CYGPKG_NET_DHCP_THREAD_PRIORITY, dhcp_if_fn, (cyg_addrword_t) 0, "dhcp",
214 (void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]);
215 cyg_thread_resume(thread[0]);
218 // ------------------------------------------------------------------------
220 #else // CYGPKG_NET_DHCP
222 void cyg_user_start(void)
225 CYG_TEST_NA( "DHCP is not enabled" );
226 CYG_TEST_EXIT( "DHCP is not enabled" );
229 #endif // CYGPKG_NET_DHCP
231 // ------------------------------------------------------------------------