Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

perf-flow.c

Go to the documentation of this file.
00001 /*
00002 ** $Id$
00003 **
00004 ** perf-flow.c
00005 **
00006 **
00007 ** Copyright (C) 2002 Sourcefire,Inc
00008 ** Marc Norton <mnorton@sourcefire.com>
00009 ** Dan Roelker <droelker@sourcefire.com>
00010 **
00011 ** NOTES
00012 **   4.10.02 - Initial Checkin.  Norton
00013 **   5.5.02  - Changed output format and added output structure for
00014 **             easy stat printing. Roelker
00015 **   5.29.02 - Added ICMP traffic stats and overall protocol flow 
00016 **             stats. Roelker
00017 **
00018 ** This program is free software; you can redistribute it and/or modify
00019 ** it under the terms of the GNU General Public License as published by
00020 ** the Free Software Foundation; either version 2 of the License, or
00021 ** (at your option) any later version.
00022 **
00023 ** This program is distributed in the hope that it will be useful,
00024 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00025 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00026 ** GNU General Public License for more details.
00027 **
00028 ** You should have received a copy of the GNU General Public License
00029 ** along with this program; if not, write to the Free Software
00030 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00031 **
00032 **  DESCRIPTION
00033 **    The following subroutines track eand analyze the traffic flow
00034 **  statistics.
00035 **
00036 **   PacketLen vs Packet Count
00037 **   TCP-Port vs Packet Count
00038 **   UDP-Port vs Packet Count
00039 **   TCP High<->High Port Count 
00040 **   UDP High<->High Port Count
00041 **
00042 **
00043 */
00044 
00045 #include <time.h>
00046 #ifndef WIN32
00047 #include <sys/time.h>
00048 #include <sys/resource.h>
00049 #endif
00050 #include <stdlib.h>
00051 #include <stdio.h>
00052 #include <string.h>
00053 
00054 #include "snort.h"
00055 #include "util.h" 
00056 
00057 int DisplayFlowStats(SFFLOW_STATS *sfFlowStats);
00058 
00059 /*
00060 **  Quick function to return the correct
00061 **  FlowStats ptr for us
00062 */
00063 SFFLOW *sfGetFlowPtr() { return &sfPerf.sfFlow; }
00064 
00065 /*
00066 *  Allocate Memory, initialize arrays, etc...
00067 */
00068 int InitFlowStats(SFFLOW *sfFlow)
00069 {
00070     sfFlow->pktLenCnt = (UINT64*)malloc(sizeof(UINT64) * (SF_MAX_PKT_LEN+1) );
00071     if( sfFlow->pktLenCnt )
00072         memset(sfFlow->pktLenCnt,0,sizeof(UINT64)*(SF_MAX_PKT_LEN+1));
00073     else
00074         FatalError("PERFMONITOR ERROR: Error allocating pktLenCnt.");
00075     
00076     sfFlow->pktTotal = 0;
00077     sfFlow->byteTotal = 0;
00078 
00079     sfFlow->portTcpSrc = (UINT64*)malloc(sizeof(UINT64) * SF_MAX_PORT);
00080     if( sfFlow->portTcpSrc )
00081         memset( sfFlow->portTcpSrc, 0, sizeof(UINT64)*SF_MAX_PORT );
00082     else
00083         FatalError("PERFMONITOR ERROR: Error allocating portTcpSrc.");
00084 
00085     sfFlow->portTcpDst = (UINT64*)malloc(sizeof(UINT64) * SF_MAX_PORT );
00086     if( sfFlow->portTcpDst )
00087         memset( sfFlow->portTcpDst, 0, sizeof(UINT64)*SF_MAX_PORT );
00088     else
00089         FatalError("PERFMONITOR ERROR: Error allocating portTcpDst.");
00090     
00091     sfFlow->portTcpHigh=0;
00092     sfFlow->portTcpTotal=0;
00093 
00094     sfFlow->portUdpSrc = (UINT64*)malloc(sizeof(UINT64) * SF_MAX_PORT );
00095     if( sfFlow->portUdpSrc )
00096         memset( sfFlow->portUdpSrc, 0, sizeof(UINT64)*SF_MAX_PORT );
00097     else
00098         FatalError("PERFMONITOR ERROR: Error allocating portUdpSrc.");
00099 
00100     sfFlow->portUdpDst = (UINT64*)malloc(sizeof(UINT64) * SF_MAX_PORT );
00101     if( sfFlow->portUdpDst )
00102         memset( sfFlow->portUdpDst, 0, sizeof(UINT64)*SF_MAX_PORT );
00103     else
00104         FatalError("PERFMONITOR ERROR: Error allocating portUdpDst.");
00105     
00106     sfFlow->portUdpHigh=0;
00107     sfFlow->portUdpTotal=0;
00108 
00109     sfFlow->typeIcmp = (UINT64 *)calloc(256, sizeof(UINT64));
00110     if(!sfFlow->typeIcmp)
00111         FatalError("PERFMONITOR ERROR: Error allocating typeIcmp.");
00112 
00113     sfFlow->typeIcmpTotal = 0;
00114     
00115     return 0;
00116 }
00117 
00118 int UpdateTCPFlowStats(SFFLOW *sfFlow, int sport, int dport, int len )
00119 {
00120     /*
00121     ** Track how much data on each port, and hihg<-> high port data
00122     */
00123     if( sport < SF_MAX_PORT )
00124     {
00125         sfFlow->portTcpSrc  [ sport ]+= len;
00126    
00127     }else if( dport < SF_MAX_PORT ){
00128     
00129         sfFlow->portTcpDst  [ dport ]+= len;
00130     
00131     }else{
00132 
00133         sfFlow->portTcpHigh += len;
00134     }
00135 
00136     sfFlow->portTcpTotal += len;
00137 
00138     return 0;
00139 }
00140 
00141 int UpdateTCPFlowStatsEx(int sport, int dport, int len )
00142 {
00143     if(!(sfPerf.iPerfFlags & SFPERF_FLOW))
00144        return 1;
00145 
00146     return UpdateTCPFlowStats( sfGetFlowPtr(), sport, dport, len );
00147 }
00148 
00149 int UpdateUDPFlowStats(SFFLOW *sfFlow, int sport, int dport, int len )
00150 {
00151     /*
00152      * Track how much data on each port, and hihg<-> high port data
00153      */
00154     if( sport < SF_MAX_PORT )
00155     {
00156         sfFlow->portUdpSrc  [ sport ]+= len;
00157    
00158     }else if( dport < SF_MAX_PORT ){
00159     
00160         sfFlow->portUdpDst  [ dport ]+= len;
00161     
00162     }else{
00163 
00164         sfFlow->portUdpHigh += len;
00165     }
00166 
00167     sfFlow->portUdpTotal += len;
00168 
00169     return 0;
00170 }
00171 
00172 int UpdateUDPFlowStatsEx(int sport, int dport, int len )
00173 {
00174     if(!(sfPerf.iPerfFlags & SFPERF_FLOW))
00175        return 1;
00176 
00177     return UpdateUDPFlowStats( sfGetFlowPtr(), sport, dport, len );
00178 }
00179 
00180 int UpdateICMPFlowStats(SFFLOW *sfFlow, int type, int len)
00181 {
00182     if(type < 256)
00183     {
00184         sfFlow->typeIcmp[type] += len;
00185     }
00186 
00187     sfFlow->typeIcmpTotal += len;
00188 
00189     return 0;
00190 }
00191 
00192 int UpdateICMPFlowStatsEx(int type, int len)
00193 {
00194     if(!(sfPerf.iPerfFlags & SFPERF_FLOW))
00195         return 1;
00196 
00197     return UpdateICMPFlowStats(sfGetFlowPtr(), type, len);
00198 }
00199 
00200 /*
00201 *   Add in stats for this packet
00202 *
00203 *   Packet lengths
00204 */
00205 int UpdateFlowStats(SFFLOW *sfFlow, unsigned char *pucPacket, int len,
00206         int iRebuiltPkt)
00207 {
00208     /*
00209     * Track how many packets of each length
00210     */
00211     if( len <= SF_MAX_PKT_LEN )
00212     {
00213         sfFlow->pktLenCnt[ len ]++;
00214         sfFlow->pktTotal++;
00215         sfFlow->byteTotal += len;
00216     }
00217 
00218     return 0;
00219 }
00220 
00221 /*
00222 *   Analyze/Calc Stats and Display them.
00223 */
00224 int ProcessFlowStats(SFFLOW *sfFlow)
00225 {
00226     SFFLOW_STATS sfFlowStats;
00227     int i;
00228     double rate, srate, drate, totperc;
00229     UINT64 tot;
00230 
00231     memset(&sfFlowStats, 0x00, sizeof(sfFlowStats));
00232 
00233     /*
00234     **  Calculate the percentage of TCP, UDP and ICMP
00235     **  and other traffic that consisted in the stream.
00236     */
00237     sfFlowStats.trafficTCP = 100.0 * (double)(sfFlow->portTcpTotal) /
00238                  (double)(sfFlow->byteTotal);
00239     sfFlowStats.trafficUDP = 100.0 * (double)(sfFlow->portUdpTotal) /
00240                  (double)(sfFlow->byteTotal);
00241     sfFlowStats.trafficICMP = 100.0 * (double)(sfFlow->typeIcmpTotal) /
00242                  (double)(sfFlow->byteTotal);
00243     sfFlowStats.trafficOTHER = 100.0 *
00244                    (double)((double)sfFlow->byteTotal -
00245                    ((double)sfFlow->portTcpTotal +
00246                    (double)sfFlow->portUdpTotal +
00247                    (double)sfFlow->typeIcmpTotal)) /
00248                    (double)sfFlow->byteTotal;
00249     
00250     /*
00251     **  Calculate Packet percent of total pkt length
00252     **  distribution.
00253     */
00254     for(i=1;i<SF_MAX_PKT_LEN;i++)
00255     {
00256         if( !sfFlow->pktLenCnt[i]  ) continue;
00257      
00258         rate =  100.0 * (double)(sfFlow->pktLenCnt[i]) / 
00259                 (double)(sfFlow->pktTotal);
00260 
00261         if( rate > .10 )
00262         {
00263             sfFlowStats.pktLenPercent[i] = rate;
00264         }
00265         else
00266         {
00267             sfFlowStats.pktLenPercent[i] = 0;
00268         }  
00269       
00270         sfFlow->pktLenCnt[i]=0;
00271     }
00272 
00273     /*
00274     **  Calculate TCP port distribution by src, dst and
00275     **  total percentage.
00276     */
00277     for(i=0;i<SF_MAX_PORT;i++)
00278     {
00279         tot = sfFlow->portTcpSrc[i]+sfFlow->portTcpDst[i];
00280         if(!tot)
00281         {
00282             sfFlowStats.portflowTCP.totperc[i] = 0;
00283             continue;
00284         }
00285 
00286         totperc = 100.0 * tot / sfFlow->portTcpTotal;
00287         
00288         if(totperc > .1)
00289         {
00290             srate =  100.0 * (double)(sfFlow->portTcpSrc[i]) / tot ;
00291             drate =  100.0 * (double)(sfFlow->portTcpDst[i]) / tot ;
00292         
00293             sfFlowStats.portflowTCP.totperc[i]    = totperc;
00294             sfFlowStats.portflowTCP.sport_rate[i] = srate;
00295             sfFlowStats.portflowTCP.dport_rate[i] = drate;
00296         }
00297         else
00298         {
00299             sfFlowStats.portflowTCP.totperc[i] = 0;
00300         }
00301         
00302         sfFlow->portTcpSrc[i] = sfFlow->portTcpDst[i] = 0;
00303     }
00304 
00305     sfFlowStats.portflowHighTCP = 100.0 * sfFlow->portTcpHigh /
00306                                   sfFlow->portTcpTotal;
00307 
00308     /*
00309     **  Reset counters for next go round.
00310     */
00311     sfFlow->portTcpHigh=0;
00312     sfFlow->portTcpTotal=0;
00313     
00314     /*
00315     **  Calculate UDP port processing based on src, dst and
00316     **  total distributions.
00317     */
00318     for(i=0;i<SF_MAX_PORT;i++)
00319     {
00320         tot = sfFlow->portUdpSrc[i]+sfFlow->portUdpDst[i];
00321         if(!tot)
00322         {
00323             sfFlowStats.portflowUDP.totperc[i] = 0;
00324             continue;
00325         }
00326 
00327         totperc= 100.0 * tot / sfFlow->portUdpTotal;
00328         
00329         if(totperc > .1)
00330         {
00331             srate =  100.0 * (double)(sfFlow->portUdpSrc[i]) / tot ;
00332             drate =  100.0 * (double)(sfFlow->portUdpDst[i]) / tot ;
00333 
00334             sfFlowStats.portflowUDP.totperc[i]    = totperc;
00335             sfFlowStats.portflowUDP.sport_rate[i] = srate;
00336             sfFlowStats.portflowUDP.dport_rate[i] = drate;
00337         }
00338         else
00339         {
00340             sfFlowStats.portflowUDP.totperc[i] = 0;
00341         }
00342         
00343         sfFlow->portUdpSrc[i] = sfFlow->portUdpDst[i] = 0;
00344     }
00345 
00346     sfFlowStats.portflowHighUDP = 100.0 * sfFlow->portUdpHigh /
00347                                   sfFlow->portUdpTotal;
00348 
00349     /*
00350     **  Reset counters for next go round
00351     */
00352     sfFlow->portUdpHigh=0;
00353     sfFlow->portUdpTotal=0;
00354 
00355     /*
00356     **  Calculate ICMP statistics
00357     */
00358     for(i=0;i<256;i++)
00359     {
00360         tot = sfFlow->typeIcmp[i];
00361         if(!tot)
00362         {
00363             sfFlowStats.flowICMP.totperc[i] = 0;
00364             continue;
00365         }
00366 
00367         totperc= 100.0 * tot / sfFlow->typeIcmpTotal;
00368         
00369         if(totperc > .1)
00370         {
00371             sfFlowStats.flowICMP.totperc[i]  = totperc;
00372         }
00373         else
00374         {
00375             sfFlowStats.flowICMP.totperc[i] = 0;
00376         }
00377 
00378         sfFlow->typeIcmp[i] = 0;
00379     }
00380 
00381     sfFlow->typeIcmpTotal = 0;
00382 
00383     sfFlow->byteTotal = 0;
00384    
00385     sfFlow->pktTotal  = 0; 
00386  
00387     DisplayFlowStats(&sfFlowStats);
00388 
00389     return 0;
00390 }
00391                                                 
00392 int DisplayFlowStats(SFFLOW_STATS *sfFlowStats)
00393 {
00394     int i;
00395   
00396     LogMessage("\n\nProtocol Byte Flows - %%Total Flow\n");
00397     LogMessage(    "--------------------------------------\n");
00398     LogMessage("TCP:   %.2f%%\n", sfFlowStats->trafficTCP);
00399     LogMessage("UDP:   %.2f%%\n", sfFlowStats->trafficUDP);
00400     LogMessage("ICMP:  %.2f%%\n", sfFlowStats->trafficICMP);
00401     LogMessage("OTHER: %.2f%%\n", sfFlowStats->trafficOTHER);
00402 
00403     LogMessage("\n\nPacketLen - %%TotalPackets\n");
00404     LogMessage(    "-------------------------\n"); 
00405     for(i=1;i<SF_MAX_PKT_LEN;i++)
00406     {
00407         if( sfFlowStats->pktLenPercent[i] < .1 ) continue;
00408      
00409         LogMessage("Bytes[%d] %.2f%%\n", i, sfFlowStats->pktLenPercent[i]);
00410     }
00411 
00412     LogMessage("\n\nTCP Port Flows\n");
00413     LogMessage(    "--------------\n"); 
00414     for(i=0;i<SF_MAX_PORT;i++)
00415     {
00416         if(sfFlowStats->portflowTCP.totperc[i])
00417         {
00418             LogMessage("Port[%d] %.2f%% of Total, Src: %6.2f%% Dst: %6.2f%%\n",
00419                         i, sfFlowStats->portflowTCP.totperc[i],
00420                         sfFlowStats->portflowTCP.sport_rate[i],
00421                         sfFlowStats->portflowTCP.dport_rate[i]);
00422         }
00423     }
00424 
00425     if(sfFlowStats->portflowHighTCP > .1)
00426     {
00427         LogMessage("Ports[High<->High]: %.2f%%\n", 
00428                 sfFlowStats->portflowHighTCP);
00429     }
00430 
00431     LogMessage("\n\nUDP Port Flows\n");
00432     LogMessage(    "--------------\n"); 
00433     for(i=0;i<SF_MAX_PORT;i++)
00434     {
00435         if(sfFlowStats->portflowUDP.totperc[i])
00436         {
00437             LogMessage("Port[%d] %.2f%% of Total, Src: %6.2f%% Dst: %6.2f%%\n",
00438                         i, sfFlowStats->portflowUDP.totperc[i],
00439                         sfFlowStats->portflowUDP.sport_rate[i],
00440                         sfFlowStats->portflowUDP.dport_rate[i]);
00441         }
00442     }
00443 
00444     if(sfFlowStats->portflowHighUDP > .1)
00445     {
00446         LogMessage("Ports[High<->High]: %.2f%%\n", 
00447                 sfFlowStats->portflowHighUDP);
00448     }
00449 
00450     LogMessage("\n\nICMP Type Flows\n");
00451     LogMessage(    "---------------\n");
00452     for(i=0;i<256;i++)
00453     {
00454         if(sfFlowStats->flowICMP.totperc[i])
00455         {
00456             LogMessage("Type[%d] %.2f%% of Total\n",
00457                         i, sfFlowStats->flowICMP.totperc[i]);
00458         }
00459     }
00460 
00461          
00462     return 0;
00463 }
00464 

Generated on Sun May 14 14:51:15 2006 by  doxygen 1.4.2