1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* This program benchmarks a QEMUD pipe to exchange data with a test 18 * server. 19 * 20 * See test_host_1.c for the corresponding server code, which simply 21 * sends back anything it receives from the client. 22 */ 23 #include <stddef.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <errno.h> 27 #include <string.h> 28 #include "test_util.h" 29 30 #define PIPE_NAME "pingpong" 31 32 char* progname; 33 34 static void usage(int code) 35 { 36 printf("Usage: %s [options]\n\n", progname); 37 printf( 38 "Valid options are:\n\n" 39 " -? -h --help Print this message\n" 40 " -pipe <name> Use pipe name (default: " PIPE_NAME ")\n" 41 " -tcp <port> Use local tcp port\n" 42 " -size <size> Specify packet size\n" 43 "\n" 44 ); 45 exit(code); 46 } 47 48 int main(int argc, char** argv) 49 { 50 Pipe pipe[1]; 51 const char* tcpPort = NULL; 52 int localPort = 0; 53 const char* pipeName = NULL; 54 const char* packetSize = NULL; 55 int port = 8012; 56 int maxCount = 1000; 57 int bufferSize = 16384; 58 uint8_t* buffer; 59 uint8_t* buffer2; 60 int nn, count; 61 double time0, time1; 62 63 /* Extract program name */ 64 { 65 char* p = strrchr(argv[0], '/'); 66 if (p == NULL) 67 progname = argv[0]; 68 else 69 progname = p+1; 70 } 71 72 /* Parse options */ 73 while (argc > 1 && argv[1][0] == '-') { 74 char* arg = argv[1]; 75 if (!strcmp(arg, "-?") || !strcmp(arg, "-h") || !strcmp(arg, "--help")) { 76 usage(0); 77 } else if (!strcmp(arg, "-pipe")) { 78 if (argc < 3) { 79 fprintf(stderr, "-pipe option needs an argument! See --help for details.\n"); 80 exit(1); 81 } 82 argc--; 83 argv++; 84 pipeName = argv[1]; 85 } else if (!strcmp(arg, "-tcp")) { 86 if (argc < 3) { 87 fprintf(stderr, "-tcp option needs an argument! See --help for details.\n"); 88 exit(1); 89 } 90 argc--; 91 argv++; 92 tcpPort = argv[1]; 93 } else if (!strcmp(arg, "-size")) { 94 if (argc < 3) { 95 fprintf(stderr, "-tcp option needs an argument! See --help for details.\n"); 96 exit(1); 97 } 98 argc--; 99 argv++; 100 packetSize = argv[1]; 101 } else { 102 fprintf(stderr, "UNKNOWN OPTION: %s\n\n", arg); 103 usage(1); 104 } 105 argc--; 106 argv++; 107 } 108 109 /* Check arguments */ 110 if (tcpPort && pipeName) { 111 fprintf(stderr, "You can't use both -pipe and -tcp at the same time\n"); 112 exit(2); 113 } 114 115 if (tcpPort != NULL) { 116 localPort = atoi(tcpPort); 117 if (localPort <= 0 || localPort > 65535) { 118 fprintf(stderr, "Invalid port number: %s\n", tcpPort); 119 exit(2); 120 } 121 } else if (pipeName == NULL) { 122 /* Use default pipe name */ 123 pipeName = PIPE_NAME; 124 } 125 126 if (packetSize != NULL) { 127 int size = atoi(packetSize); 128 if (size <= 0) { 129 fprintf(stderr, "Invalid byte size: %s\n", packetSize); 130 exit(3); 131 } 132 bufferSize = size; 133 } 134 135 /* Open the pipe */ 136 if (tcpPort != NULL) { 137 if (pipe_openSocket(pipe, localPort) < 0) { 138 fprintf(stderr, "Could not open tcp socket!\n"); 139 return 1; 140 } 141 printf("Connected to tcp:localhost:%d\n", port); 142 } 143 else { 144 if (pipe_openQemuPipe(pipe, pipeName) < 0) { 145 fprintf(stderr, "Could not open '%s' pipe: %s\n", pipeName, strerror(errno)); 146 return 1; 147 } 148 printf("Connected to '%s' pipe\n", pipeName); 149 } 150 151 /* Allocate buffers, setup their data */ 152 buffer = malloc(bufferSize); 153 buffer2 = malloc(bufferSize); 154 155 for (nn = 0; nn < bufferSize; nn++) { 156 buffer[nn] = (uint8_t)nn; 157 } 158 159 /* Do the work! */ 160 time0 = now_secs(); 161 162 for (count = 0; count < maxCount; count++) { 163 int ret = pipe_send(pipe, buffer, bufferSize); 164 int pos, len; 165 166 if (ret < 0) { 167 fprintf(stderr,"%d: Sending %d bytes failed: %s\n", count, bufferSize, strerror(errno)); 168 return 1; 169 } 170 171 #if 1 172 /* The server is supposed to send the message back */ 173 pos = 0; 174 len = bufferSize; 175 while (len > 0) { 176 ret = pipe_recv(pipe, buffer2 + pos, len); 177 if (ret < 0) { 178 fprintf(stderr, "Receiving failed (ret=%d): %s\n", ret, strerror(errno)); 179 return 3; 180 } 181 if (ret == 0) { 182 fprintf(stderr, "Disconnection while receiving!\n"); 183 return 4; 184 } 185 pos += ret; 186 len -= ret; 187 } 188 189 if (memcmp(buffer, buffer2, bufferSize) != 0) { 190 fprintf(stderr, "Message content mismatch!\n"); 191 const int maxAvail = 16; 192 const int maxLines = 12; 193 int numLines = 0; 194 for (nn = 0; nn < bufferSize; ) { 195 int avail = bufferSize - nn; 196 int mm; 197 if (avail > maxAvail) 198 avail = maxAvail; 199 200 if (memcmp(buffer+nn, buffer2+nn, avail) != 0) { 201 if (++numLines >= maxLines) { 202 printf(".... to be continued ...\n"); 203 break; 204 } 205 printf("%04x:", nn); 206 207 for (mm = 0; mm < avail; mm++) 208 printf(" %02x", buffer[nn+mm]); 209 for ( ; mm < maxAvail; mm++ ) 210 printf(" "); 211 212 printf( " -- " ); 213 214 for (mm = 0; mm < avail; mm++) 215 printf(" %02x", buffer2[nn+mm]); 216 217 printf ("\n"); 218 } 219 nn += avail; 220 } 221 return 6; 222 } 223 224 #endif 225 226 if (count > 0 && (count % 200) == 0) { 227 printf("... %d\n", count); 228 } 229 } 230 231 time1 = now_secs(); 232 233 printf("Closing pipe\n"); 234 pipe_close(pipe); 235 236 printf("Total time: %g seconds\n", time1 - time0); 237 printf("Total bytes: %g bytes\n", 1.0*maxCount*bufferSize); 238 printf("Bandwidth: %g MB/s\n", (maxCount*bufferSize/(1024.0*1024.0))/(time1 - time0) ); 239 return 0; 240 } 241