#include #include #include #include #include #include #include #include #define BLOCK_SIZE 200 #define AX_DEVICE "bcp0" #define MAX_RETRIES 100 #define NUMBER_OF_PACKETS 20 #define BPS 400 // Bytes per second struct timeval start; long byteCount; double throughput; // Initializes AX25 int initAX25() { if (ax25_config_load_ports() == 0) { fprintf(stderr, "ERROR: no AX.25 ports defined\n"); return 1; } return 0; } // Creates a datagram socket for AX25. The port is bound to a source // address and connected to a destination address. int connectPortTx( char *port, char *destCall ) { char *portcall; int s, dlen, len; struct full_sockaddr_ax25 dest; struct full_sockaddr_ax25 src; if ((portcall = ax25_config_get_addr(port)) == NULL) { fprintf(stderr, "beacon: invalid AX.25 port setting - %s\n", port); return 1; } fprintf(stderr, "Loaded port: %s\n", portcall); if ((dlen = ax25_aton(destCall, &dest)) == -1) { fprintf(stderr, "beacon: unable to convert callsign '%s'\n", destCall); return 1; } if ((len = ax25_aton(portcall, &src)) == -1) { fprintf(stderr, "beacon: unable to convert callsign '%s'\n", portcall); return 1; } fprintf(stderr, "Converted call sign\n"); fflush(stderr); if ((s = socket(AF_AX25, SOCK_DGRAM, 0xbb)) < 0) { fprintf( stderr, "Failed to open socket\n" ); perror("Socket open failed"); return 1; } fprintf(stderr, "Opened socket\n"); if (bind(s, (struct sockaddr *)&src, len) == -1) { fprintf( stderr, "Failed to bind socket\n" ); return 1; } if ( connect( s, (struct sockaddr *)&dest, dlen ) != 0 ) perror("connect failed"); return( s ); } // ---------------------------------------------------------------------------- // Calculates open loop throughput. Used to limit overflowing in transmit // buffer and dropping packets. // ---------------------------------------------------------------------------- double calcThroughput() { struct timeval now; double uDiff, sNow, usNow, sStart, usStart; if ( gettimeofday( &now, NULL) == -1 ) perror("Error in get time of day"); sNow = (double)now.tv_sec; usNow = (double)now.tv_usec; sStart = (double)start.tv_sec; usStart = (double)start.tv_usec; uDiff = ( sNow - sStart ) * 1000000; uDiff = uDiff + ( usNow - usStart ); throughput = ( byteCount * 1000000 ) / uDiff; throughput = ( (double)byteCount * 1000000 ) / uDiff; fprintf(stderr, "\t\tthroughput %d\n", (int)throughput ); return (throughput); } // ---------------------------------------------------------------------------- // Inititializes variables used in throughput calculations. // ---------------------------------------------------------------------------- void initThroughputVars() { byteCount = throughput = 0; if ( gettimeofday( &start, NULL) == -1 ) perror("Error in start get time of day"); } // ---------------------------------------------------------------------------- // Sends packets // ---------------------------------------------------------------------------- void sendPackets( int s, int blockSize, int nop, int bps ) { int i, total, count; double uTime; struct timeval now; char data[1000]; char str[1000]; fprintf(stderr, "Sending %d packets of size %d\n", nop, blockSize ); initThroughputVars(); // Build packet to send str[0] = '\0'; while ( strlen(str) < blockSize ) sprintf( str, "0%s", str ); count = 0; while( count < nop ) { // Append count to data sprintf( data, "%s:%d", str, count ); fprintf(stderr, "\tsending packet %d:%s\n", count, data ); // Pause to throttle back throughput if needed. Have to do this // in an open loop fashion. i = 0; while ( (calcThroughput() > bps ) && ( i <= MAX_RETRIES ) ) { i++; usleep(100); } // Send the packet. if( send( s, data, strlen(data), 0 ) < strlen(data) ) { perror("The write failed(1)"); exit(-1); } byteCount+=strlen(data); count++; printf ("\tTotal data sent: %d\n", byteCount ); } printf ("\nTotal data sent: %d\n", byteCount ); } // ---------------------------------------------------------------------------- // Print proper usage // ---------------------------------------------------------------------------- void printUsage() { fprintf(stderr, "usage: throughput [-p ] [-s ]\n"); fprintf(stderr, " [-n ] [-b ] \n" ); } int main( int argc, char** argv) { int bps,c,numberOfPackets, blockSize, id, txSocket; char port[11]; blockSize = BLOCK_SIZE; strcpy( port, AX_DEVICE ); numberOfPackets = NUMBER_OF_PACKETS; bps = BPS; // Parse arguments while ((c = getopt(argc, argv, "p:s:b:n:")) != -1) { switch (c) { case 'p': strncpy( port, optarg, 10 ); if ( strlen(optarg) >= 10 ) port[11] = '\0'; break; case 's': if ( ( blockSize = atoi(optarg) ) <= 0 ) { fprintf( stderr, "throughput: invalid block size - %s\n", optarg); return 1; } break; case 'n': if ( ( numberOfPackets = atoi(optarg) ) <= 0 ) { fprintf( stderr, "throughput: invalid number - %s\n", optarg); return 1; } break; case 'b': if ( ( bps = atoi(optarg) ) <= 0 ) { fprintf( stderr, "throughput: invalid number - %s\n", optarg); return 1; } break; case ':': case '?': default: printUsage(); return 1; } } initAX25(); txSocket = connectPortTx( port, "QST" ); sendPackets( txSocket, blockSize, numberOfPackets, bps ); close ( txSocket ); }