/* * 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 * * $Id$ */ #include #include #include #include #include #include #include #include #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; } } }