[c87143a] | 1 | /* |
---|
| 2 | * Test KA9Q networking |
---|
| 3 | * |
---|
| 4 | * This program may be distributed and used for any purpose. |
---|
| 5 | * I ask only that you: |
---|
| 6 | * 1. Leave this author information intact. |
---|
| 7 | * 2. Document any changes you make. |
---|
| 8 | * |
---|
| 9 | * W. Eric Norum |
---|
| 10 | * Saskatchewan Accelerator Laboratory |
---|
| 11 | * University of Saskatchewan |
---|
| 12 | * Saskatoon, Saskatchewan, CANADA |
---|
| 13 | * eric@skatter.usask.ca |
---|
[481950e] | 14 | * |
---|
| 15 | * $Id$ |
---|
[c87143a] | 16 | */ |
---|
[481950e] | 17 | |
---|
[c87143a] | 18 | #include <stdio.h> |
---|
| 19 | #include <unistd.h> |
---|
| 20 | #include <rtems.h> |
---|
| 21 | #include <rtems/error.h> |
---|
| 22 | #include <socket.h> |
---|
| 23 | #include <sockaddr.h> |
---|
| 24 | #include <netuser.h> |
---|
| 25 | #include <rtems_ka9q.h> |
---|
| 26 | |
---|
| 27 | #define NSERVER 2 |
---|
| 28 | #define BASE_PORT 24742 |
---|
| 29 | |
---|
| 30 | #define DATA_SINK_HOST "128.233.14.1" |
---|
| 31 | |
---|
| 32 | /* |
---|
| 33 | * Display the contents of several KA9Q tables |
---|
| 34 | */ |
---|
| 35 | static void |
---|
| 36 | show_ka9q_tables (void) |
---|
| 37 | { |
---|
| 38 | printf ("\n****************** MALLOC Statistics ***************\n"); |
---|
| 39 | malloc_dump (); |
---|
| 40 | printf ("\n****************** MBUF Statistics ***************\n"); |
---|
| 41 | mbufstat (); |
---|
| 42 | mbufsizes (); |
---|
| 43 | printf ("\n****************** Routing Table ***************\n"); |
---|
| 44 | rtems_ka9q_execute_command ("route"); |
---|
| 45 | printf ("\n****************** ARP Table ***************\n"); |
---|
| 46 | rtems_ka9q_execute_command ("arp"); |
---|
| 47 | printf ("\n****************** Driver Statistics ***************\n"); |
---|
| 48 | rtems_ka9q_execute_command ("ifconfig rtems"); |
---|
| 49 | printf ("\n****************** Ip Statistics ***************\n"); |
---|
| 50 | rtems_ka9q_execute_command ("ip status"); |
---|
| 51 | printf ("\n****************** ICMP Statistics ***************\n"); |
---|
| 52 | rtems_ka9q_execute_command ("icmp status"); |
---|
| 53 | printf ("\n****************** UDP Statistics ***************\n"); |
---|
| 54 | rtems_ka9q_execute_command ("udp status"); |
---|
| 55 | printf ("\n****************** TCP Statistics ***************\n"); |
---|
| 56 | rtems_ka9q_execute_command ("tcp status"); |
---|
| 57 | } |
---|
| 58 | |
---|
| 59 | /* |
---|
| 60 | * Stress the transmit queue -- send a large number of UDP packets |
---|
| 61 | */ |
---|
| 62 | static void |
---|
| 63 | transmitUdp (void) |
---|
| 64 | { |
---|
| 65 | int s; |
---|
| 66 | int i; |
---|
| 67 | static struct sockaddr_in myAddr, farAddr; |
---|
| 68 | static char cbuf[800]; |
---|
| 69 | static char bigbuf[20000]; |
---|
| 70 | |
---|
| 71 | printf ("Create socket.\n"); |
---|
| 72 | s = socket (AF_INET, SOCK_DGRAM, 0); |
---|
| 73 | if (s < 0) |
---|
| 74 | rtems_panic ("Can't create socket: %s", strerror (errno)); |
---|
| 75 | myAddr.sin_family = AF_INET; |
---|
| 76 | myAddr.sin_port = 1234; |
---|
| 77 | myAddr.sin_addr.s_addr = INADDR_ANY; |
---|
| 78 | printf ("Bind socket.\n"); |
---|
| 79 | if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) |
---|
| 80 | rtems_panic ("Can't bind socket: %s", strerror (errno)); |
---|
| 81 | farAddr.sin_family = AF_INET; |
---|
| 82 | farAddr.sin_port = 9; /* The `discard' port */ |
---|
| 83 | farAddr.sin_addr.s_addr = 0xFFFFFFFF; |
---|
| 84 | for (i = 0 ; i < 5 ; i++) { |
---|
| 85 | if (sendto (s, cbuf, sizeof cbuf, 0, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) |
---|
| 86 | rtems_panic ("Can't broadcast: %s", strerror (errno)); |
---|
| 87 | } |
---|
| 88 | farAddr.sin_addr.s_addr = aton (DATA_SINK_HOST); |
---|
| 89 | for (i = 0 ; i < 500 ; i++) { |
---|
| 90 | if (sendto (s, cbuf, sizeof cbuf, 0, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) |
---|
| 91 | rtems_panic ("Can't send: %s", strerror (errno)); |
---|
| 92 | if (sendto (s, cbuf, sizeof cbuf, 0, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) |
---|
| 93 | rtems_panic ("Can't send: %s", strerror (errno)); |
---|
| 94 | } |
---|
| 95 | for (i = 0 ; i < 2 ; i++) { |
---|
| 96 | if (sendto (s, bigbuf, sizeof bigbuf, 0, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) |
---|
| 97 | rtems_panic ("Can't send: %s", strerror (errno)); |
---|
| 98 | if (sendto (s, bigbuf, sizeof bigbuf, 0, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) |
---|
| 99 | rtems_panic ("Can't send: %s", strerror (errno)); |
---|
| 100 | } |
---|
| 101 | close (s); |
---|
| 102 | } |
---|
| 103 | |
---|
| 104 | /* |
---|
| 105 | * Stress the transmit queue -- send a large number of TCP packets |
---|
| 106 | */ |
---|
| 107 | static void |
---|
| 108 | transmitTcp (void) |
---|
| 109 | { |
---|
| 110 | int s; |
---|
| 111 | int i; |
---|
| 112 | static struct sockaddr_in myAddr, farAddr; |
---|
| 113 | static char cbuf[800]; |
---|
| 114 | static char bigbuf[20000]; |
---|
| 115 | |
---|
| 116 | printf ("Create socket.\n"); |
---|
| 117 | s = socket (AF_INET, SOCK_STREAM, 0); |
---|
| 118 | if (s < 0) |
---|
| 119 | rtems_panic ("Can't create socket: %s", strerror (errno)); |
---|
| 120 | myAddr.sin_family = AF_INET; |
---|
| 121 | myAddr.sin_port = 1234; |
---|
| 122 | myAddr.sin_addr.s_addr = INADDR_ANY; |
---|
| 123 | printf ("Bind socket.\n"); |
---|
| 124 | if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) |
---|
| 125 | rtems_panic ("Can't bind socket: %s", strerror (errno)); |
---|
| 126 | farAddr.sin_family = AF_INET; |
---|
| 127 | farAddr.sin_port = 9; /* The `discard' port */ |
---|
| 128 | farAddr.sin_addr.s_addr = aton (DATA_SINK_HOST); |
---|
| 129 | if (connect (s, (struct sockaddr *)&farAddr, sizeof farAddr) < 0) { |
---|
| 130 | printf ("Can't connect socket: %s\n", strerror (errno)); |
---|
| 131 | close (s); |
---|
| 132 | return; |
---|
| 133 | } |
---|
| 134 | for (i = 0 ; i < 500 ; i++) { |
---|
| 135 | if (write (s, cbuf, sizeof cbuf) < 0) |
---|
| 136 | rtems_panic ("Can't send: %s", strerror (errno)); |
---|
| 137 | } |
---|
| 138 | for (i = 0 ; i < 2 ; i++) { |
---|
| 139 | if (write (s, bigbuf, sizeof bigbuf) < 0) |
---|
| 140 | rtems_panic ("Can't send: %s", strerror (errno)); |
---|
| 141 | } |
---|
| 142 | close (s); |
---|
| 143 | } |
---|
| 144 | |
---|
| 145 | /* |
---|
| 146 | * Echo characters back to a telnet session |
---|
| 147 | * |
---|
| 148 | * With this running on the test machine you can go to |
---|
| 149 | * another machine on your network and run: |
---|
| 150 | * telnet test_machine the_port_number_with_which_this_function_was_started |
---|
| 151 | * Everything you type should be echoed back. |
---|
| 152 | */ |
---|
| 153 | static void |
---|
| 154 | echoTask (rtems_task_argument fd) |
---|
| 155 | { |
---|
| 156 | char cbuf[512]; |
---|
| 157 | int n; |
---|
| 158 | rtems_status_code sc; |
---|
| 159 | |
---|
| 160 | for (;;) { |
---|
| 161 | #if 0 |
---|
| 162 | n = read (fd, cbuf, sizeof cbuf); |
---|
| 163 | #else |
---|
| 164 | n = read (fd, cbuf, 1); |
---|
| 165 | #endif |
---|
| 166 | if (n == 0) { |
---|
| 167 | printf ("EOF\n"); |
---|
| 168 | break; |
---|
| 169 | } |
---|
| 170 | else if (n < 0) { |
---|
| 171 | rtems_panic ("Error receiving message: %s", strerror (errno)); |
---|
| 172 | } |
---|
| 173 | printf ("Received: %d\n", n); |
---|
| 174 | if (send (fd, cbuf, n, 0) < 0) |
---|
| 175 | rtems_panic ("Error sending message: %s", strerror (errno)); |
---|
| 176 | if (cbuf[0] == '\007') |
---|
| 177 | show_ka9q_tables (); |
---|
| 178 | if (cbuf[0] == 'Q') |
---|
| 179 | break; |
---|
| 180 | } |
---|
| 181 | if (close (fd) < 0) |
---|
| 182 | rtems_panic ("Can't close connection: %s", strerror (errno)); |
---|
| 183 | sc = rtems_task_delete (RTEMS_SELF); |
---|
| 184 | rtems_panic ("Task deletion failed: %s", rtems_status_text (sc)); |
---|
| 185 | } |
---|
| 186 | |
---|
| 187 | static void |
---|
| 188 | echoServer (unsigned short port) |
---|
| 189 | { |
---|
| 190 | int s, s1; |
---|
| 191 | struct sockaddr_in myAddr, farAddr; |
---|
| 192 | int addrlen; |
---|
| 193 | rtems_id tid; |
---|
| 194 | rtems_task_priority my_priority; |
---|
| 195 | rtems_status_code sc; |
---|
| 196 | char c = 'a'; |
---|
| 197 | |
---|
| 198 | printf ("Create socket.\n"); |
---|
| 199 | s = socket (AF_INET, SOCK_STREAM, 0); |
---|
| 200 | if (s < 0) |
---|
| 201 | rtems_panic ("Can't create socket: %s", strerror (errno)); |
---|
| 202 | myAddr.sin_family = AF_INET; |
---|
| 203 | myAddr.sin_port = port; |
---|
| 204 | myAddr.sin_addr.s_addr = INADDR_ANY; |
---|
| 205 | memset (myAddr.sin_zero, '\0', sizeof myAddr.sin_zero); |
---|
| 206 | printf ("Bind socket.\n"); |
---|
| 207 | if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) |
---|
| 208 | rtems_panic ("Can't bind socket: %s", strerror (errno)); |
---|
| 209 | printf ("Listen.\n"); |
---|
| 210 | if (listen (s, 2) < 0) |
---|
| 211 | rtems_panic ("Can't listen on socket: %s", strerror (errno)); |
---|
| 212 | for (;;) { |
---|
| 213 | printf ("Accept.\n"); |
---|
| 214 | addrlen = sizeof farAddr; |
---|
| 215 | s1 = accept (s, (struct sockaddr *)&farAddr, &addrlen); |
---|
| 216 | if (s1 < 0) |
---|
| 217 | rtems_panic ("Can't accept connection: %s", strerror (errno)); |
---|
| 218 | else |
---|
| 219 | printf ("ACCEPTED:%lX\n", farAddr.sin_addr.s_addr); |
---|
| 220 | |
---|
| 221 | /* |
---|
| 222 | * Start an echo task |
---|
| 223 | */ |
---|
| 224 | rtems_task_set_priority (RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &my_priority); |
---|
| 225 | sc = rtems_task_create (rtems_build_name ('E', 'C', 'H', c), |
---|
| 226 | my_priority, |
---|
| 227 | 8*1024, |
---|
| 228 | RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), |
---|
| 229 | RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, |
---|
| 230 | &tid); |
---|
| 231 | if (sc != RTEMS_SUCCESSFUL) |
---|
| 232 | rtems_panic ("Can't create echo task; %s\n", rtems_status_text (sc)); |
---|
| 233 | if (c == 'z') |
---|
| 234 | c = 'a'; |
---|
| 235 | else |
---|
| 236 | c++; |
---|
| 237 | sc = rtems_task_start (tid, echoTask, s1); |
---|
| 238 | if (sc != RTEMS_SUCCESSFUL) |
---|
| 239 | rtems_panic ("Can't start echo task; %s\n", rtems_status_text (sc)); |
---|
| 240 | } |
---|
| 241 | } |
---|
| 242 | |
---|
| 243 | /* |
---|
| 244 | * Run an echo server |
---|
| 245 | */ |
---|
| 246 | static void |
---|
| 247 | runEchoServer (rtems_task_argument arg) |
---|
| 248 | { |
---|
| 249 | echoServer (arg); |
---|
| 250 | rtems_task_delete (RTEMS_SELF); |
---|
| 251 | } |
---|
| 252 | |
---|
| 253 | /* |
---|
| 254 | * Test some socket stuff |
---|
| 255 | */ |
---|
| 256 | void |
---|
| 257 | doSocket (void) |
---|
| 258 | { |
---|
| 259 | int i; |
---|
| 260 | rtems_status_code sc; |
---|
| 261 | rtems_task_priority my_priority; |
---|
| 262 | |
---|
| 263 | /* |
---|
| 264 | * Spawn other servers |
---|
| 265 | */ |
---|
| 266 | rtems_task_set_priority (RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &my_priority); |
---|
| 267 | for (i = 0 ; i < NSERVER ; i++) { |
---|
| 268 | rtems_id tid; |
---|
| 269 | sc = rtems_task_create (rtems_build_name ('S', 'R', 'V', 'A' + i), |
---|
| 270 | my_priority - 1, |
---|
| 271 | 8*1024, |
---|
| 272 | RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), |
---|
| 273 | RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, |
---|
| 274 | &tid); |
---|
| 275 | if (sc != RTEMS_SUCCESSFUL) { |
---|
| 276 | printf ("Can't create server; %s\n", rtems_status_text (sc)); |
---|
| 277 | return; |
---|
| 278 | } |
---|
| 279 | sc = rtems_task_start (tid, runEchoServer, BASE_PORT + i); |
---|
| 280 | if (sc != RTEMS_SUCCESSFUL) { |
---|
| 281 | printf ("Can't start server; %s\n", rtems_status_text (sc)); |
---|
| 282 | return; |
---|
| 283 | } |
---|
| 284 | } |
---|
| 285 | |
---|
| 286 | /* |
---|
| 287 | * Wait for characters from console terminal |
---|
| 288 | */ |
---|
| 289 | for (;;) { |
---|
| 290 | switch (getchar ()) { |
---|
| 291 | case '\004': |
---|
| 292 | return; |
---|
| 293 | |
---|
| 294 | case 't': |
---|
| 295 | /* |
---|
| 296 | * Test the transmit queues |
---|
| 297 | */ |
---|
| 298 | transmitTcp (); |
---|
| 299 | break; |
---|
| 300 | |
---|
| 301 | case 'u': |
---|
| 302 | /* |
---|
| 303 | * Test the transmit queues |
---|
| 304 | */ |
---|
| 305 | transmitUdp (); |
---|
| 306 | break; |
---|
| 307 | |
---|
| 308 | case 's': |
---|
| 309 | /* |
---|
| 310 | * Show what's been accomplished |
---|
| 311 | */ |
---|
| 312 | show_ka9q_tables (); |
---|
| 313 | break; |
---|
| 314 | } |
---|
| 315 | } |
---|
| 316 | } |
---|