mirror of
https://github.com/azure-rtos/netx.git
synced 2023-08-10 07:57:54 +08:00
332 lines
9.9 KiB
C
332 lines
9.9 KiB
C
|
/* This is a small demo of DHCP Client for the high-performance NetX IP stack. */
|
||
|
|
||
|
#include "tx_api.h"
|
||
|
#include "nx_api.h"
|
||
|
#include "nx_dhcp.h"
|
||
|
#include "nx_dhcp_server.h"
|
||
|
|
||
|
#define DEMO_STACK_SIZE 4096
|
||
|
#define NX_PACKET_SIZE 1536
|
||
|
#define NX_PACKET_POOL_SIZE NX_PACKET_SIZE * 8
|
||
|
|
||
|
#define NX_DHCP_SERVER_IP_ADDRESS_0 IP_ADDRESS(10,0,0,1)
|
||
|
#define START_IP_ADDRESS_LIST_0 IP_ADDRESS(10,0,0,10)
|
||
|
#define END_IP_ADDRESS_LIST_0 IP_ADDRESS(10,0,0,19)
|
||
|
|
||
|
#define NX_DHCP_SUBNET_MASK_0 IP_ADDRESS(255,255,255,0)
|
||
|
#define NX_DHCP_DEFAULT_GATEWAY_0 IP_ADDRESS(10,0,0,1)
|
||
|
#define NX_DHCP_DNS_SERVER_0 IP_ADDRESS(10,0,0,1)
|
||
|
|
||
|
/* Define the interface index. */
|
||
|
#define NX_DHCP_INTERFACE_INDEX 0
|
||
|
|
||
|
/* If defined, the host requests a (previous) client IP address. */
|
||
|
/*
|
||
|
#define REQUEST_CLIENT_IP
|
||
|
*/
|
||
|
|
||
|
#ifdef REQUEST_CLIENT_IP
|
||
|
/* Request a specific IP address using the DHCP client address option. */
|
||
|
#define NX_DHCP_CLIENT_IP_ADDRESS IP_ADDRESS(10,0,0,18)
|
||
|
|
||
|
/* If defined NX_TRUE, the client requests to jump to the boot state and skip the DISCOVER message. */
|
||
|
#define SKIP_DISCOVER_MESSAGE NX_TRUE
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
/* Define the ThreadX and NetX object control blocks... */
|
||
|
TX_THREAD client_thread;
|
||
|
NX_PACKET_POOL client_pool;
|
||
|
NX_IP client_ip;
|
||
|
NX_DHCP dhcp_client;
|
||
|
|
||
|
TX_THREAD server_thread;
|
||
|
NX_PACKET_POOL server_pool;
|
||
|
NX_IP server_ip;
|
||
|
NX_DHCP_SERVER dhcp_server;
|
||
|
|
||
|
/* Define the counters used in the demo application... */
|
||
|
|
||
|
ULONG client_thread_counter;
|
||
|
ULONG state_changes;
|
||
|
ULONG error_counter;
|
||
|
CHAR *pointer;
|
||
|
|
||
|
UCHAR message[50] = "My Ping Request!" ;
|
||
|
|
||
|
|
||
|
/* Define thread prototypes. */
|
||
|
|
||
|
void server_thread_entry(ULONG thread_input);
|
||
|
void client_thread_entry(ULONG thread_input);
|
||
|
void dhcp_state_change(NX_DHCP *dhcp_ptr, UCHAR new_state);
|
||
|
|
||
|
/******** Optionally substitute your Ethernet driver here. ***********/
|
||
|
void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
|
||
|
|
||
|
/* Define main entry point. */
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
|
||
|
/* Enter the ThreadX kernel. */
|
||
|
tx_kernel_enter();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Define what the initial system looks like. */
|
||
|
|
||
|
void tx_application_define(void *first_unused_memory)
|
||
|
{
|
||
|
|
||
|
UINT status;
|
||
|
|
||
|
|
||
|
/* Setup the working pointer. */
|
||
|
pointer = (CHAR *) first_unused_memory;
|
||
|
|
||
|
/* Create the client thread. */
|
||
|
tx_thread_create(&client_thread, "thread client", client_thread_entry, 0,
|
||
|
pointer, DEMO_STACK_SIZE,
|
||
|
4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||
|
pointer = pointer + DEMO_STACK_SIZE;
|
||
|
|
||
|
/* Create the server thread. */
|
||
|
tx_thread_create(&server_thread, "thread server", server_thread_entry, 0,
|
||
|
pointer, DEMO_STACK_SIZE,
|
||
|
3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||
|
pointer = pointer + DEMO_STACK_SIZE;
|
||
|
|
||
|
/* Initialize the NetX system. */
|
||
|
nx_system_initialize();
|
||
|
|
||
|
/* Create the client packet pool. */
|
||
|
status = nx_packet_pool_create(&client_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
|
||
|
pointer = pointer + NX_PACKET_POOL_SIZE;
|
||
|
|
||
|
/* Check for pool creation error. */
|
||
|
if (status)
|
||
|
return;
|
||
|
|
||
|
/* Create the server packet pool. */
|
||
|
status = nx_packet_pool_create(&server_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
|
||
|
pointer = pointer + NX_PACKET_POOL_SIZE;
|
||
|
|
||
|
/* Check for pool creation error. */
|
||
|
if (status)
|
||
|
return;
|
||
|
|
||
|
/* Create an IP instance for the DHCP Client. */
|
||
|
status = nx_ip_create(&client_ip, "DHCP Client", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &client_pool, _nx_ram_network_driver, pointer, 2048, 1);
|
||
|
pointer = pointer + 2048;
|
||
|
|
||
|
/* Check for IP create errors. */
|
||
|
if (status)
|
||
|
return;
|
||
|
|
||
|
/* Create an IP instance for the DHCP Server. */
|
||
|
status = nx_ip_create(&server_ip, "DHCP Server", NX_DHCP_SERVER_IP_ADDRESS_0, 0xFFFFFF00UL, &server_pool, _nx_ram_network_driver, pointer, 2048, 1);
|
||
|
pointer = pointer + 2048;
|
||
|
|
||
|
/* Check for IP create errors. */
|
||
|
if (status)
|
||
|
return;
|
||
|
|
||
|
/* Enable ARP and supply ARP cache memory for DHCP Client IP. */
|
||
|
status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
|
||
|
pointer = pointer + 1024;
|
||
|
|
||
|
/* Enable ARP and supply ARP cache memory for DHCP Server IP. */
|
||
|
status += nx_arp_enable(&server_ip, (void *) pointer, 1024);
|
||
|
pointer = pointer + 1024;
|
||
|
|
||
|
/* Check for ARP enable errors. */
|
||
|
if (status)
|
||
|
return;
|
||
|
|
||
|
/* Enable UDP traffic. */
|
||
|
status = nx_udp_enable(&client_ip);
|
||
|
status += nx_udp_enable(&server_ip);
|
||
|
|
||
|
/* Check for UDP enable errors. */
|
||
|
if (status)
|
||
|
return;
|
||
|
|
||
|
/* Enable ICMP. */
|
||
|
status = nx_icmp_enable(&client_ip);
|
||
|
status += nx_icmp_enable(&server_ip);
|
||
|
|
||
|
/* Check for errors. */
|
||
|
if (status)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Define the server thread. */
|
||
|
|
||
|
void server_thread_entry(ULONG thread_input)
|
||
|
{
|
||
|
|
||
|
UINT status;
|
||
|
UINT addresses_added;
|
||
|
|
||
|
NX_PARAMETER_NOT_USED(thread_input);
|
||
|
|
||
|
/* Modified the mtu size to avoid fragmenting the DHCP packet since the default mtu size is 128 in _nx_ram_network_driver. */
|
||
|
server_ip.nx_ip_interface[NX_DHCP_INTERFACE_INDEX].nx_interface_ip_mtu_size = 1500;
|
||
|
|
||
|
/* Create the DHCP Server. */
|
||
|
status = nx_dhcp_server_create(&dhcp_server, &server_ip, pointer, DEMO_STACK_SIZE,
|
||
|
"DHCP Server", &server_pool);
|
||
|
pointer = pointer + DEMO_STACK_SIZE;
|
||
|
|
||
|
/* Check for errors creating the DHCP Server. */
|
||
|
if (status)
|
||
|
return;
|
||
|
|
||
|
/* Load the assignable DHCP IP addresses for the first interface. */
|
||
|
status = nx_dhcp_create_server_ip_address_list(&dhcp_server, NX_DHCP_INTERFACE_INDEX, START_IP_ADDRESS_LIST_0,
|
||
|
END_IP_ADDRESS_LIST_0, &addresses_added);
|
||
|
|
||
|
/* Check for errors creating the list. */
|
||
|
if (status)
|
||
|
return;
|
||
|
|
||
|
/* Verify all the addresses were added to the list. */
|
||
|
if (addresses_added != 10)
|
||
|
return;
|
||
|
|
||
|
/* Set the interface network parameters. */
|
||
|
status = nx_dhcp_set_interface_network_parameters(&dhcp_server, NX_DHCP_INTERFACE_INDEX, NX_DHCP_SUBNET_MASK_0,
|
||
|
NX_DHCP_DEFAULT_GATEWAY_0, NX_DHCP_DNS_SERVER_0);
|
||
|
|
||
|
/* Check for errors setting network parameters. */
|
||
|
if (status)
|
||
|
return;
|
||
|
|
||
|
/* Start DHCP Server task. */
|
||
|
status = nx_dhcp_server_start(&dhcp_server);
|
||
|
|
||
|
/* Check for errors starting up the DHCP server. */
|
||
|
if (status)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Define the client thread. */
|
||
|
|
||
|
void client_thread_entry(ULONG thread_input)
|
||
|
{
|
||
|
|
||
|
UINT status;
|
||
|
UINT actual_status;
|
||
|
UINT length;
|
||
|
UINT ping = NX_TRUE;
|
||
|
UINT run_dhcp_client = NX_TRUE;
|
||
|
NX_PACKET *my_packet;
|
||
|
|
||
|
NX_PARAMETER_NOT_USED(thread_input);
|
||
|
|
||
|
/* Modified the mtu size to avoid fragmenting the DHCP packet since the default mtu size is 128 in _nx_ram_network_driver. */
|
||
|
client_ip.nx_ip_interface[NX_DHCP_INTERFACE_INDEX].nx_interface_ip_mtu_size = 1500;
|
||
|
|
||
|
/* Create the DHCP instance. */
|
||
|
status = nx_dhcp_create(&dhcp_client, &client_ip, "DHCP-CLIENT");
|
||
|
if (status)
|
||
|
return;
|
||
|
|
||
|
#ifdef REQUEST_CLIENT_IP
|
||
|
/* Request a specific IP address using the DHCP client address option. */
|
||
|
status = nx_dhcp_request_client_ip(&dhcp_client, NX_DHCP_CLIENT_IP_ADDRESS, SKIP_DISCOVER_MESSAGE);
|
||
|
if (status)
|
||
|
error_counter++;
|
||
|
#endif
|
||
|
|
||
|
/* Register state change variable. */
|
||
|
status = nx_dhcp_state_change_notify(&dhcp_client, dhcp_state_change);
|
||
|
if (status)
|
||
|
error_counter++;
|
||
|
|
||
|
/* Start the DHCP Client. */
|
||
|
nx_dhcp_start(&dhcp_client);
|
||
|
while(run_dhcp_client)
|
||
|
{
|
||
|
|
||
|
/* Wait for DHCP to assign the IP address. */
|
||
|
do
|
||
|
{
|
||
|
|
||
|
/* Check for address resolution. */
|
||
|
status = nx_ip_status_check(&client_ip, NX_IP_ADDRESS_RESOLVED, (ULONG *) &actual_status, NX_IP_PERIODIC_RATE);
|
||
|
|
||
|
/* Check status. */
|
||
|
if (status)
|
||
|
{
|
||
|
/* wait a bit. */
|
||
|
tx_thread_sleep(NX_IP_PERIODIC_RATE);
|
||
|
}
|
||
|
|
||
|
} while (status != NX_SUCCESS);
|
||
|
|
||
|
length = sizeof(message);
|
||
|
|
||
|
while(ping)
|
||
|
{
|
||
|
|
||
|
/* Send pings to another host on the network... */
|
||
|
status = nx_icmp_ping(&client_ip, NX_DHCP_SERVER_IP_ADDRESS_0, (CHAR *)message, length, &my_packet, NX_IP_PERIODIC_RATE);
|
||
|
if (status)
|
||
|
error_counter++;
|
||
|
else
|
||
|
nx_packet_release(my_packet);
|
||
|
|
||
|
/* Increment counter. */
|
||
|
client_thread_counter++;
|
||
|
|
||
|
/* Sleep for a few ticks... */
|
||
|
tx_thread_sleep(NX_IP_PERIODIC_RATE);
|
||
|
}
|
||
|
|
||
|
/* Use this API to send a message to the server, e.g. a DECLINE if the IP address is owned by another host.
|
||
|
nx_dhcp_send_request(&dhcp_client, NX_DHCP_TYPE_DHCPDECLINE);
|
||
|
*/
|
||
|
|
||
|
/* Use this API to release an IP address if the host is switching networks or running the host through DHCP cycles.
|
||
|
nx_dhcp_release(&dhcp_client);
|
||
|
*/
|
||
|
|
||
|
/* Stopping the DHCP client. */
|
||
|
nx_dhcp_stop(&dhcp_client);
|
||
|
|
||
|
tx_thread_sleep(NX_IP_PERIODIC_RATE);
|
||
|
|
||
|
/* Use this API to clear the network parameters and restart the client in the INIT state. */
|
||
|
nx_dhcp_reinitialize(&dhcp_client);
|
||
|
|
||
|
/* Resume the DHCP client thread. */
|
||
|
nx_dhcp_start(&dhcp_client);
|
||
|
|
||
|
/* Ok to resume ping attempts. */
|
||
|
ping = NX_TRUE;
|
||
|
}
|
||
|
|
||
|
/* All done. Return resources to NetX and ThreadX. */
|
||
|
nx_dhcp_delete(&dhcp_client);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void dhcp_state_change(NX_DHCP *dhcp_ptr, UCHAR new_state)
|
||
|
{
|
||
|
|
||
|
NX_PARAMETER_NOT_USED(dhcp_ptr);
|
||
|
NX_PARAMETER_NOT_USED(new_state);
|
||
|
|
||
|
/* Increment state changes counter. */
|
||
|
state_changes++;
|
||
|
|
||
|
return;
|
||
|
}
|