diff options
Diffstat (limited to 'netdemo')
-rw-r--r-- | netdemo/Makefile | 59 | ||||
-rw-r--r-- | netdemo/README | 27 | ||||
-rw-r--r-- | netdemo/init.c | 185 | ||||
-rw-r--r-- | netdemo/test.c | 313 |
4 files changed, 584 insertions, 0 deletions
diff --git a/netdemo/Makefile b/netdemo/Makefile new file mode 100644 index 0000000..4894a7c --- /dev/null +++ b/netdemo/Makefile @@ -0,0 +1,59 @@ +SAMPLE=netdemo +PGM=${ARCH}/$(SAMPLE).exe + +MANAGERS=io message event semaphore timer rate_monotonic region + +# C source names, if any, go here -- minus the .c +C_PIECES= init test +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +H_FILES= + +DOCTYPES= +DOCS=$(DOCTYPES:%=$(SAMPLE).%) + +SRCS=$(DOCS) $(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES) +OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) + +PRINT_SRCS=$(DOCS) + +PGM=${ARCH}/$(SAMPLE).exe + +include $(RTEMS_MAKEFILE_PATH)/Makefile.inc +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += +CFLAGS_LD += -Wl,--defsym -Wl,HeapSize=0xC0000 # KA9Q needs more space +CFLAGS_OPTIMIZE_V += +CFLAGS_DEBUG_V += -v -qrtems_debug + +LD_PATHS += +LD_LIBS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +all: ${ARCH} $(SRCS) $(PGM) + +${PGM}: $(OBJS) $(LINK_FILES) + $(make-exe) + +# Install the program(s), appending _g or _p as appropriate. +# for include files, just use $(INSTALL) +install: all + $(INSTALL_VARIANT) -m 555 ${PGM} ${PROJECT_RELEASE}/tests diff --git a/netdemo/README b/netdemo/README new file mode 100644 index 0000000..5f9a303 --- /dev/null +++ b/netdemo/README @@ -0,0 +1,27 @@ +A simple application to test some of the KA9Q networking code. + + ************************** + * NOTES * + ************************** + +1. Make sure you change the definition of MY_ETHERNET_ADDRESS in init.c + before you try to use this program. + +2. If you do not use BOOTP (i.e. the `#define USE_BOOTP 1' in init.c is + removed), make sure you change the definition of MY_INTERNET_ADDRESS + before you try to use the program. + +FAILURE TO FOLLOW THE ABOVE INSTRUCTIONS MAY PROVOKE YOUR NETWORK +ADMINISTRATOR TO THE POINT WHERE VICIOUS ATTACKS WILL BE MADE UPON YOU. + +3. Once this program is running on the target machine, you can test + the network code by: + a) Typing commands at the target console: + s - show network statistics + t - transmit TCP packets + u - transmit UDP packets + b) Run `telnet target_machine 24742' on another machines. + Everything you type should be echoed back and noted on + the target console. + You can run more than one telnet session at once. + You can use port number 24743 as well. diff --git a/netdemo/init.c b/netdemo/init.c new file mode 100644 index 0000000..27b5889 --- /dev/null +++ b/netdemo/init.c @@ -0,0 +1,185 @@ +/* + * RTEMS configuration/initialization + * + * This program may be distributed and used for any purpose. + * I ask only that you: + * 1. Leave this author information intact. + * 2. Document any changes you make. + * + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + */ + +/*#define TRACE_NETWORK_DRIVER 1 */ +#include <bsp.h> + +#define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_EXECUTIVE_RAM_SIZE (512*1024) +#define CONFIGURE_MAXIMUM_SEMAPHORES 20 +#define CONFIGURE_MAXIMUM_TASKS 20 +#define CONFIGURE_MAXIMUM_TIMERS 10 +#define CONFIGURE_MAXIMUM_PERIODS 1 + +#define CONFIGURE_MICROSECONDS_PER_TICK 10486 + +#define CONFIGURE_INIT_TASK_STACK_SIZE (10*1024) +#define CONFIGURE_INIT_TASK_PRIORITY 100 +#define CONFIGURE_INIT_TASK_INITIAL_MODES (RTEMS_PREEMPT | \ + RTEMS_NO_TIMESLICE | \ + RTEMS_NO_ASR | \ + RTEMS_INTERRUPT_LEVEL(0)) + +#define CONFIGURE_INIT +rtems_task Init (rtems_task_argument argument); + +#include <confdefs.h> + +#include <stdio.h> +#include <rtems_ka9q.h> + +/* + * Board ethernet address + * REPLACE THIS WITH YOUR OWN VALUE BEFORE TRYING TO USE THIS PROGRAM! + */ +#define MY_ETHERNET_ADDRESS "37:1D:3E:21:2B:A5" + +/* + * Some board support packages let the network driver + * get the Ethernet address from the bootstrap PROM. + */ +#define MY_ETHERNET_ADDRESS "prom" + +/* + * Use BOOTP to get information about me? + */ +#define USE_BOOTP 1 + +#if (defined (USE_BOOTP)) +#include <bootp.h> +#else +/* + * Information about me if BOOTP isn't used + * CHOOSE A VALUE APPROPRIATE TO YOUR NETWORK! + */ +#define MY_IP_ADDRESS "128.233.14.68" +#endif + +/* + * Suspend execution for the specified number of seconds + */ +static void +delay_task (int seconds) +{ + rtems_interval ticksPerSecond; + + rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond); + rtems_task_wake_after (seconds * ticksPerSecond); +} + +/* + * RTEMS Startup Task + */ +rtems_task +Init (rtems_task_argument ignored) +{ + printf( "\n\n*** HELLO WORLD TEST ***\n" ); + printf( "Hello World\n" ); + printf( "*** END OF HELLO WORLD TEST ***\n" ); + + /* + * Start KA9Q + */ + rtems_ka9q_start (50); + + /* + * Hook up drivers + */ +#if (defined (USE_BOOTP)) + if (rtems_ka9q_execute_command ("attach rtems broadcast y" + " ether " MY_ETHERNET_ADDRESS)) +#else + if (rtems_ka9q_execute_command ("attach rtems broadcast y" + " ip " MY_IP_ADDRESS + " ether " MY_ETHERNET_ADDRESS)) +#endif + rtems_panic ("Can't attach Ethernet driver.\n"); + +#if (defined (TRACE_NETWORK_DRIVER)) + /* + * Turn on debugging + */ + if (rtems_ka9q_execute_command ("trace rtems input <stdout>") + || rtems_ka9q_execute_command ("trace rtems output <stdout>") + || rtems_ka9q_execute_command ("trace rtems ascii <stdout>")) + rtems_panic ("Can't set tracing for Ethernet driver.\n"); +#endif + + /* + * Configure the driver + */ + if (rtems_ka9q_execute_command ("ifconfig rtems broadcast 255.255.255.255")) + rtems_panic ("Can't configure Ethernet driver.\n"); + + /* + * Add the ethernet broadcast address to the ARP table. + */ + if (rtems_ka9q_execute_command ("arp add 255.255.255.255 ether FF:FF:FF:FF:FF:FF")) + rtems_panic ("Can't add broadcast entry to ARP table.\n"); + +#if (defined (USE_BOOTP)) + { + int i; + /* + * Get BOOTP information + */ + for (i = 0 ; ; ) { + if (rtems_ka9q_execute_command ("bootp") == 0) + break; + if (++i == 10) + rtems_panic ("Can't get information from BOOTP server.\n"); + delay_task (i); + } + if (BootpFileName) + printf ("BOOTP filename: `%s'\n", BootpFileName); + else + printf ("BOOTP -- No filename!\n"); + } +#else + if (rtems_ka9q_execute_command ("ifconfig rtems netmask 255.255.255.0")) + rtems_panic ("Can't set netmask.\n"); + if (rtems_ka9q_execute_command ("route add default rtems")) + rtems_panic ("Can't add default route.\n"); + printf ("Routing table after adding default route\n"); + rtems_ka9q_execute_command ("route"); +#endif + + /* + * Issue a gratuitous ARP request to update tables in + * other hosts on this network. + */ + if (rtems_ka9q_execute_command ("arp gratuitous rtems")) + rtems_panic ("Can't send gratuitous ARP.\n"); + + /* + * Everything is now running + */ + printf ("NETWORK INITIALIZED!\n"); + + /* + * See if sockets work properly + */ + doSocket (); + + /* + * Wind things up + */ + delay_task (2); + rtems_ka9q_execute_command ("detach rtems"); + exit (0); +} diff --git a/netdemo/test.c b/netdemo/test.c new file mode 100644 index 0000000..de0ee80 --- /dev/null +++ b/netdemo/test.c @@ -0,0 +1,313 @@ +/* + * Test KA9Q networking + * + * This program may be distributed and used for any purpose. + * I ask only that you: + * 1. Leave this author information intact. + * 2. Document any changes you make. + * + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + */ +#include <stdio.h> +#include <unistd.h> +#include <rtems.h> +#include <rtems/error.h> +#include <socket.h> +#include <sockaddr.h> +#include <netuser.h> +#include <rtems_ka9q.h> + +#define NSERVER 2 +#define BASE_PORT 24742 + +#define DATA_SINK_HOST "128.233.14.1" + +/* + * Display the contents of several KA9Q tables + */ +static void +show_ka9q_tables (void) +{ + printf ("\n****************** MALLOC Statistics ***************\n"); + malloc_dump (); + printf ("\n****************** MBUF Statistics ***************\n"); + mbufstat (); + mbufsizes (); + printf ("\n****************** Routing Table ***************\n"); + rtems_ka9q_execute_command ("route"); + printf ("\n****************** ARP Table ***************\n"); + rtems_ka9q_execute_command ("arp"); + printf ("\n****************** Driver Statistics ***************\n"); + rtems_ka9q_execute_command ("ifconfig rtems"); + printf ("\n****************** Ip Statistics ***************\n"); + rtems_ka9q_execute_command ("ip status"); + printf ("\n****************** ICMP Statistics ***************\n"); + rtems_ka9q_execute_command ("icmp status"); + printf ("\n****************** UDP Statistics ***************\n"); + rtems_ka9q_execute_command ("udp status"); + printf ("\n****************** TCP Statistics ***************\n"); + rtems_ka9q_execute_command ("tcp status"); +} + +/* + * Stress the transmit queue -- send a large number of UDP packets + */ +static void +transmitUdp (void) +{ + int s; + int i; + static struct sockaddr_in myAddr, farAddr; + static char cbuf[800]; + static char bigbuf[20000]; + + printf ("Create socket.\n"); + s = socket (AF_INET, SOCK_DGRAM, 0); + if (s < 0) + rtems_panic ("Can't create socket: %s", strerror (errno)); + myAddr.sin_family = AF_INET; + myAddr.sin_port = 1234; + myAddr.sin_addr.s_addr = INADDR_ANY; + printf ("Bind socket.\n"); + if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) + rtems_panic ("Can't bind socket: %s", strerror (errno)); + farAddr.sin_family = AF_INET; + farAddr.sin_port = 9; /* The `discard' port */ + farAddr.sin_addr.s_addr = 0xFFFFFFFF; + for (i = 0 ; i < 5 ; i++) { + if (sendto (s, cbuf, sizeof cbuf, 0, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) + rtems_panic ("Can't broadcast: %s", strerror (errno)); + } + farAddr.sin_addr.s_addr = aton (DATA_SINK_HOST); + for (i = 0 ; i < 500 ; i++) { + if (sendto (s, cbuf, sizeof cbuf, 0, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) + rtems_panic ("Can't send: %s", strerror (errno)); + if (sendto (s, cbuf, sizeof cbuf, 0, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) + rtems_panic ("Can't send: %s", strerror (errno)); + } + for (i = 0 ; i < 2 ; i++) { + if (sendto (s, bigbuf, sizeof bigbuf, 0, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) + rtems_panic ("Can't send: %s", strerror (errno)); + if (sendto (s, bigbuf, sizeof bigbuf, 0, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) + rtems_panic ("Can't send: %s", strerror (errno)); + } + close (s); +} + +/* + * Stress the transmit queue -- send a large number of TCP packets + */ +static void +transmitTcp (void) +{ + int s; + int i; + static struct sockaddr_in myAddr, farAddr; + static char cbuf[800]; + static char bigbuf[20000]; + + printf ("Create socket.\n"); + s = socket (AF_INET, SOCK_STREAM, 0); + if (s < 0) + rtems_panic ("Can't create socket: %s", strerror (errno)); + myAddr.sin_family = AF_INET; + myAddr.sin_port = 1234; + myAddr.sin_addr.s_addr = INADDR_ANY; + printf ("Bind socket.\n"); + if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) + rtems_panic ("Can't bind socket: %s", strerror (errno)); + farAddr.sin_family = AF_INET; + farAddr.sin_port = 9; /* The `discard' port */ + farAddr.sin_addr.s_addr = aton (DATA_SINK_HOST); + if (connect (s, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) { + printf ("Can't connect socket: %s\n", strerror (errno)); + close (s); + return; + } + for (i = 0 ; i < 500 ; i++) { + if (write (s, cbuf, sizeof cbuf) < 0) + rtems_panic ("Can't send: %s", strerror (errno)); + } + for (i = 0 ; i < 2 ; i++) { + if (write (s, bigbuf, sizeof bigbuf) < 0) + rtems_panic ("Can't send: %s", strerror (errno)); + } + close (s); +} + +/* + * Echo characters back to a telnet session + * + * With this running on the test machine you can go to + * another machine on your network and run: + * telnet test_machine the_port_number_with_which_this_function_was_started + * Everything you type should be echoed back. + */ +static void +echoTask (rtems_task_argument fd) +{ + char cbuf[512]; + int n; + rtems_status_code sc; + + for (;;) { +#if 0 + n = read (fd, cbuf, sizeof cbuf); +#else + n = read (fd, cbuf, 1); +#endif + if (n == 0) { + printf ("EOF\n"); + break; + } + else if (n < 0) { + rtems_panic ("Error receiving message: %s", strerror (errno)); + } + printf ("Received: %d\n", n); + if (send (fd, cbuf, n, 0) < 0) + rtems_panic ("Error sending message: %s", strerror (errno)); + if (cbuf[0] == '\007') + show_ka9q_tables (); + if (cbuf[0] == 'Q') + break; + } + if (close (fd) < 0) + rtems_panic ("Can't close connection: %s", strerror (errno)); + sc = rtems_task_delete (RTEMS_SELF); + rtems_panic ("Task deletion failed: %s", rtems_status_text (sc)); +} + +static void +echoServer (unsigned short port) +{ + int s, s1; + struct sockaddr_in myAddr, farAddr; + int addrlen; + rtems_id tid; + rtems_task_priority my_priority; + rtems_status_code sc; + char c = 'a'; + + printf ("Create socket.\n"); + s = socket (AF_INET, SOCK_STREAM, 0); + if (s < 0) + rtems_panic ("Can't create socket: %s", strerror (errno)); + myAddr.sin_family = AF_INET; + myAddr.sin_port = port; + myAddr.sin_addr.s_addr = INADDR_ANY; + memset (myAddr.sin_zero, '\0', sizeof myAddr.sin_zero); + printf ("Bind socket.\n"); + if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) + rtems_panic ("Can't bind socket: %s", strerror (errno)); + printf ("Listen.\n"); + if (listen (s, 2) < 0) + rtems_panic ("Can't listen on socket: %s", strerror (errno)); + for (;;) { + printf ("Accept.\n"); + addrlen = sizeof farAddr; + s1 = accept (s, (struct sockaddr *)&farAddr, &addrlen); + if (s1 < 0) + rtems_panic ("Can't accept connection: %s", strerror (errno)); + else + printf ("ACCEPTED:%lX\n", farAddr.sin_addr.s_addr); + + /* + * Start an echo task + */ + rtems_task_set_priority (RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &my_priority); + sc = rtems_task_create (rtems_build_name ('E', 'C', 'H', c), + my_priority, + 8*1024, + RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), + RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, + &tid); + if (sc != RTEMS_SUCCESSFUL) + rtems_panic ("Can't create echo task; %s\n", rtems_status_text (sc)); + if (c == 'z') + c = 'a'; + else + c++; + sc = rtems_task_start (tid, echoTask, s1); + if (sc != RTEMS_SUCCESSFUL) + rtems_panic ("Can't start echo task; %s\n", rtems_status_text (sc)); + } +} + +/* + * Run an echo server + */ +static void +runEchoServer (rtems_task_argument arg) +{ + echoServer (arg); + rtems_task_delete (RTEMS_SELF); +} + +/* + * Test some socket stuff + */ +void +doSocket (void) +{ + int i; + rtems_status_code sc; + rtems_task_priority my_priority; + + /* + * Spawn other servers + */ + rtems_task_set_priority (RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &my_priority); + for (i = 0 ; i < NSERVER ; i++) { + rtems_id tid; + sc = rtems_task_create (rtems_build_name ('S', 'R', 'V', 'A' + i), + my_priority - 1, + 8*1024, + RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), + RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, + &tid); + if (sc != RTEMS_SUCCESSFUL) { + printf ("Can't create server; %s\n", rtems_status_text (sc)); + return; + } + sc = rtems_task_start (tid, runEchoServer, BASE_PORT + i); + if (sc != RTEMS_SUCCESSFUL) { + printf ("Can't start server; %s\n", rtems_status_text (sc)); + return; + } + } + + /* + * Wait for characters from console terminal + */ + for (;;) { + switch (getchar ()) { + case '\004': + return; + + case 't': + /* + * Test the transmit queues + */ + transmitTcp (); + break; + + case 'u': + /* + * Test the transmit queues + */ + transmitUdp (); + break; + + case 's': + /* + * Show what's been accomplished + */ + show_ka9q_tables (); + break; + } + } +} |