| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* This program benchmarks a QEMUD pipe to exchange data with a test |
| * server. |
| * |
| * See test_host_1.c for the corresponding server code, which simply |
| * sends back anything it receives from the client. |
| */ |
| #include <stddef.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <errno.h> |
| #include <string.h> |
| #include "test_util.h" |
| |
| #define PIPE_NAME "pingpong" |
| |
| char* progname; |
| |
| static void usage(int code) |
| { |
| printf("Usage: %s [options]\n\n", progname); |
| printf( |
| "Valid options are:\n\n" |
| " -? -h --help Print this message\n" |
| " -pipe <name> Use pipe name (default: " PIPE_NAME ")\n" |
| " -tcp <port> Use local tcp port\n" |
| " -size <size> Specify packet size\n" |
| "\n" |
| ); |
| exit(code); |
| } |
| |
| int main(int argc, char** argv) |
| { |
| Pipe pipe[1]; |
| const char* tcpPort = NULL; |
| int localPort = 0; |
| const char* pipeName = NULL; |
| const char* packetSize = NULL; |
| int port = 8012; |
| int maxCount = 1000; |
| int bufferSize = 16384; |
| uint8_t* buffer; |
| uint8_t* buffer2; |
| int nn, count; |
| double time0, time1; |
| |
| /* Extract program name */ |
| { |
| char* p = strrchr(argv[0], '/'); |
| if (p == NULL) |
| progname = argv[0]; |
| else |
| progname = p+1; |
| } |
| |
| /* Parse options */ |
| while (argc > 1 && argv[1][0] == '-') { |
| char* arg = argv[1]; |
| if (!strcmp(arg, "-?") || !strcmp(arg, "-h") || !strcmp(arg, "--help")) { |
| usage(0); |
| } else if (!strcmp(arg, "-pipe")) { |
| if (argc < 3) { |
| fprintf(stderr, "-pipe option needs an argument! See --help for details.\n"); |
| exit(1); |
| } |
| argc--; |
| argv++; |
| pipeName = argv[1]; |
| } else if (!strcmp(arg, "-tcp")) { |
| if (argc < 3) { |
| fprintf(stderr, "-tcp option needs an argument! See --help for details.\n"); |
| exit(1); |
| } |
| argc--; |
| argv++; |
| tcpPort = argv[1]; |
| } else if (!strcmp(arg, "-size")) { |
| if (argc < 3) { |
| fprintf(stderr, "-tcp option needs an argument! See --help for details.\n"); |
| exit(1); |
| } |
| argc--; |
| argv++; |
| packetSize = argv[1]; |
| } else { |
| fprintf(stderr, "UNKNOWN OPTION: %s\n\n", arg); |
| usage(1); |
| } |
| argc--; |
| argv++; |
| } |
| |
| /* Check arguments */ |
| if (tcpPort && pipeName) { |
| fprintf(stderr, "You can't use both -pipe and -tcp at the same time\n"); |
| exit(2); |
| } |
| |
| if (tcpPort != NULL) { |
| localPort = atoi(tcpPort); |
| if (localPort <= 0 || localPort > 65535) { |
| fprintf(stderr, "Invalid port number: %s\n", tcpPort); |
| exit(2); |
| } |
| } else if (pipeName == NULL) { |
| /* Use default pipe name */ |
| pipeName = PIPE_NAME; |
| } |
| |
| if (packetSize != NULL) { |
| int size = atoi(packetSize); |
| if (size <= 0) { |
| fprintf(stderr, "Invalid byte size: %s\n", packetSize); |
| exit(3); |
| } |
| bufferSize = size; |
| } |
| |
| /* Open the pipe */ |
| if (tcpPort != NULL) { |
| if (pipe_openSocket(pipe, localPort) < 0) { |
| fprintf(stderr, "Could not open tcp socket!\n"); |
| return 1; |
| } |
| printf("Connected to tcp:localhost:%d\n", port); |
| } |
| else { |
| if (pipe_openQemuPipe(pipe, pipeName) < 0) { |
| fprintf(stderr, "Could not open '%s' pipe: %s\n", pipeName, strerror(errno)); |
| return 1; |
| } |
| printf("Connected to '%s' pipe\n", pipeName); |
| } |
| |
| /* Allocate buffers, setup their data */ |
| buffer = malloc(bufferSize); |
| buffer2 = malloc(bufferSize); |
| |
| for (nn = 0; nn < bufferSize; nn++) { |
| buffer[nn] = (uint8_t)nn; |
| } |
| |
| /* Do the work! */ |
| time0 = now_secs(); |
| |
| for (count = 0; count < maxCount; count++) { |
| int ret = pipe_send(pipe, buffer, bufferSize); |
| int pos, len; |
| |
| if (ret < 0) { |
| fprintf(stderr,"%d: Sending %d bytes failed: %s\n", count, bufferSize, strerror(errno)); |
| return 1; |
| } |
| |
| #if 1 |
| /* The server is supposed to send the message back */ |
| pos = 0; |
| len = bufferSize; |
| while (len > 0) { |
| ret = pipe_recv(pipe, buffer2 + pos, len); |
| if (ret < 0) { |
| fprintf(stderr, "Receiving failed (ret=%d): %s\n", ret, strerror(errno)); |
| return 3; |
| } |
| if (ret == 0) { |
| fprintf(stderr, "Disconnection while receiving!\n"); |
| return 4; |
| } |
| pos += ret; |
| len -= ret; |
| } |
| |
| if (memcmp(buffer, buffer2, bufferSize) != 0) { |
| fprintf(stderr, "Message content mismatch!\n"); |
| const int maxAvail = 16; |
| const int maxLines = 12; |
| int numLines = 0; |
| for (nn = 0; nn < bufferSize; ) { |
| int avail = bufferSize - nn; |
| int mm; |
| if (avail > maxAvail) |
| avail = maxAvail; |
| |
| if (memcmp(buffer+nn, buffer2+nn, avail) != 0) { |
| if (++numLines >= maxLines) { |
| printf(".... to be continued ...\n"); |
| break; |
| } |
| printf("%04x:", nn); |
| |
| for (mm = 0; mm < avail; mm++) |
| printf(" %02x", buffer[nn+mm]); |
| for ( ; mm < maxAvail; mm++ ) |
| printf(" "); |
| |
| printf( " -- " ); |
| |
| for (mm = 0; mm < avail; mm++) |
| printf(" %02x", buffer2[nn+mm]); |
| |
| printf ("\n"); |
| } |
| nn += avail; |
| } |
| return 6; |
| } |
| |
| #endif |
| |
| if (count > 0 && (count % 200) == 0) { |
| printf("... %d\n", count); |
| } |
| } |
| |
| time1 = now_secs(); |
| |
| printf("Closing pipe\n"); |
| pipe_close(pipe); |
| |
| printf("Total time: %g seconds\n", time1 - time0); |
| printf("Total bytes: %g bytes\n", 1.0*maxCount*bufferSize); |
| printf("Bandwidth: %g MB/s\n", (maxCount*bufferSize/(1024.0*1024.0))/(time1 - time0) ); |
| return 0; |
| } |