/**************************************************************************** * * * Copyright 2004-2011 NetApp Inc. All rights reserved. This file is * * confidential and a trade secret of NetApp Inc. The receipt or * * possession of this file does not convey any rights to reproduce or * * disclose its contents or to manufacture, use, or sell anything it may * * describe, in whole, or in part, without the specific written consent of * * LSI Corporation. * * * ****************************************************************************/ /**************************************************************************** * * * NAME nicClnt.c * * SUMMARY * * VERSION %version: % * * UPDATE DATE %date_modified: % * * PROGRAMMER %created_by: Merck Hung % * * * * Copyright 2002-2011 NetApp Inc. All Rights Reserved. * * * * DESCRIPTION: * * * ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "nicStress.h" static volatile unsigned char threadStop = FALSE; void usage( void ) { fprintf( stderr, "\n" ); fprintf( stderr, NIC_CLNT_NAME "\n" ); fprintf( stderr, "Usage: " NIC_CLNT_NAME " -i IPADDR | [-h] | [-v] | [-s SIZE]\n" ); fprintf( stderr, "\t-h\tprint this message\n" ); fprintf( stderr, "\t-i\tIPv4 address\n" ); fprintf( stderr, "\t-s\tsize of buffer in MB, default 1\n" ); fprintf( stderr, "\t-v\tverbose\n" ); fprintf( stderr, "\n" ); } void errorNicStressInit( void ) { system( "echo ERROR NicStressInit >> /tmp/ethStressStopOnError.log" ); } void errorNicStressSend( void ) { system( "echo ERROR NicStressSend >> /tmp/ethStressStopOnError.log" ); } void errorNicStressRecv( void ) { system( "echo ERROR NicStressRecv >> /tmp/ethStressStopOnError.log" ); } void errorNicStressCompare( void ) { system( "echo ERROR NicStressCompare >> /tmp/ethStressStopOnError.log" ); } void signalHandler( int num ) { threadStop = TRUE; } unsigned char isIPv4Format( const char *str ) { int i, j, pos[ 3 ], len; char buf[ IP_STR_BUF ]; unsigned int addr[ 4 ]; unsigned char valid = TRUE; // Length check len = strlen( str ); if( len > IP_STR_LEN || len < IP_STR_LEN_MIN ) return FALSE; strncpy( buf, str, IP_STR_BUF ); // Look for positions of delimiters for( i = 0, j = 0 ; i < len ; i++ ) { if( buf[ i ] == '.' ) { // Exceed the limit if( j >= 3 ) return FALSE; // Record & Terminate string pos[ j ] = i; buf[ i ] = 0; j++; } } // Must have 3 dots at least or at most if( j != 3 ) return FALSE; // Convert strings addr[ 0 ] = strtol( (const char *)&buf[ 0 ], NULL, 10 ); addr[ 1 ] = strtol( (const char *)&buf[ pos[ 0 ] + 1 ], NULL, 10 ); addr[ 2 ] = strtol( (const char *)&buf[ pos[ 1 ] + 1 ], NULL, 10 ); addr[ 3 ] = strtol( (const char *)&buf[ pos[ 2 ] + 1 ], NULL, 10 ); // Check range for( i = 0 ; i < 4 ; i++ ) if( addr[ i ] > 255 ) { valid = FALSE; break; } // Not ZERO snprintf( buf, IP_STR_BUF, "%d.%d.%d.%d", addr[ 0 ], addr[ 1 ], addr[ 2 ], addr[ 3 ] ); if( strcmp( buf, str ) ) valid = FALSE; return valid; } int main( int argc, char **argv ) { int ret = 0, rbytes, wbytes, sfd, i; struct sockaddr_in servaddr; unsigned int size = DEFAULT_BUFSIZE; char *sbuf = NULL, *rbuf = NULL; int c; char *ipaddr = NULL, ipbuf[ IP_STR_BUF + 1 ]; int verbose = 0; // Handle arguments while( (c = getopt( argc, argv, "i:s:vh" )) != EOF ) { switch( c ) { case 'i': strncpy( ipbuf, optarg, sizeof( ipbuf ) ); if( isIPv4Format( ipbuf ) == TRUE ) ipaddr = ipbuf; break; case 's': size = strtol( optarg, NULL, 10 ); size *= (1024 * 1024); break; case 'v': verbose = 1; break; case 'h': default: usage(); return -1; } } // Sanity check if( !size ) { fprintf( stderr, NIC_CLNT_NAME ": Invalid size(%d)\n", size ); return -1; } if( !ipaddr ) { fprintf( stderr, NIC_CLNT_NAME ": Invalid ip addr\n" ); return -1; } // Allocate buffers sbuf = malloc( size ); rbuf = malloc( size ); if( !sbuf || !rbuf ) { ret = -1; fprintf( stderr, NIC_CLNT_NAME ": Out of memory\n" ); goto errexit; } // Handle signal signal( SIGTERM, signalHandler ); // Print Start printf( "NIC Stress Start (IP: %s)\n", ipaddr ); // Main loop while( threadStop != TRUE ) { // Main procedure sfd = socket( PF_INET, SOCK_STREAM, 0 ); if( sfd < 0 ) { fprintf( stderr, NIC_CLNT_NAME ": Cannot open socket\n" ); errorNicStressInit(); break; } // Set address memset( &servaddr, 0, sizeof( struct sockaddr_in ) ); servaddr.sin_family = PF_INET; servaddr.sin_port = htons( PORT_NUM ); ret = inet_aton( ipaddr, &servaddr.sin_addr ); if( ret < 0 ) { fprintf( stderr, NIC_CLNT_NAME ": Cannot set IP address %s\n", ipaddr ); errorNicStressInit(); goto stopTest; } // Connect to server ret = connect( sfd, (struct sockaddr *)&servaddr, sizeof( struct sockaddr_in ) ); if( ret < 0 ) { fprintf( stderr, NIC_CLNT_NAME ": Cannot connect to server %s\n", ipaddr ); errorNicStressInit(); goto stopTest; } // Initialize buffers for( i = 0 ; i < size ; i++ ) sbuf[ i ] = (char)(time( NULL ) * rand()); // Clear buffers memset( rbuf, 0x00, size ); // Send Pattern wbytes = send( sfd, sbuf, size, 0 ); if( wbytes < 0 ) { errorNicStressSend(); goto stopTest; } if( (wbytes != size) && verbose ) fprintf( stderr, NIC_CLNT_NAME ": Incompletely send %d of %d bytes\n", wbytes, size ); // Recv Response rbytes = recv( sfd, rbuf, wbytes, MSG_WAITALL ); if( rbytes < 0 ) { errorNicStressRecv(); goto stopTest; } if( (rbytes != wbytes) && verbose ) fprintf( stderr, NIC_CLNT_NAME ": Incompletely recv %d of %d bytes\n", wbytes, size ); // Compare memory if( (threadStop != TRUE) && bcmp( sbuf, rbuf, size ) ) { if( verbose ) fprintf( stderr, NIC_CLNT_NAME ": Inconsistent content -- NIC Stress Failed\n" ); errorNicStressCompare(); goto stopTest; } // if(threadStop != TRUE) // printf("Pattern send done\n"); // Next round close( sfd ); usleep( 100 ); continue; stopTest: // Error close( sfd ); break; } // Print STOP printf( "NIC Stress Stop (IP: %s)\n", ipaddr ); errexit: // Free buffer if( sbuf ) free( sbuf ); if( rbuf ) free( rbuf ); return 0; }