/* * Updates connection stats */ int reporter_handle_packet( ReportHeader *reporthdr ) { ReportStruct *packet = &reporthdr->data[reporthdr->reporterindex]; ReporterData *data = &reporthdr->report; Transfer_Info *stats = &reporthdr->report.info; int finished = 0; double usec_transit; data->packetTime = packet->packetTime; stats->socket = packet->socket; if ( packet->packetID < 0 ) { finished = 1; if ( reporthdr->report.mThreadMode != kMode_Client ) { data->TotalLen += packet->packetLen; } } else { if (!packet->emptyreport) { // update fields common to TCP and UDP, client and server data->TotalLen += packet->packetLen; // update fields common to UDP client and server if ( isUDP( data ) ) { data->cntDatagrams++; stats->IPGsum += TimeDifference(data->packetTime, data->IPGstart ); stats->IPGcnt++; data->IPGstart = data->packetTime; // Finally, update UDP server fields if (stats->mUDP == kMode_Server) { //subsequent packets double transit; double deltaTransit; transit = TimeDifference( packet->packetTime, packet->sentTime ); // packet loss occured if the datagram numbers aren't sequential if ( packet->packetID != data->PacketID + 1 ) { if (packet->packetID < data->PacketID + 1 ) { data->cntOutofOrder++; } else { data->cntError += packet->packetID - data->PacketID - 1; } } // never decrease datagramID (e.g. if we get an out-of-order packet) if ( packet->packetID > data->PacketID ) { data->PacketID = packet->packetID; } if (stats->transit.totcntTransit == 0) { // Very first packet stats->transit.minTransit = transit; stats->transit.maxTransit = transit; stats->transit.sumTransit = transit; stats->transit.cntTransit = 1; stats->transit.totminTransit = transit; stats->transit.totmaxTransit = transit; stats->transit.totsumTransit = transit; stats->transit.totcntTransit = 1; // For variance, working units is microseconds usec_transit = transit * 1e6; stats->transit.vdTransit = usec_transit; stats->transit.meanTransit = usec_transit; stats->transit.m2Transit = usec_transit * usec_transit; stats->transit.totvdTransit = usec_transit; stats->transit.totmeanTransit = usec_transit; stats->transit.totm2Transit = usec_transit * usec_transit; } else { // from RFC 1889, Real Time Protocol (RTP) // J = J + ( | D(i-1,i) | - J ) / // Compute jitter deltaTransit = transit - stats->transit.lastTransit; if ( deltaTransit < 0.0 ) { deltaTransit = -deltaTransit; } stats->jitter += (deltaTransit - stats->jitter) / (16.0); // Compute end/end delay stats stats->transit.sumTransit += transit; stats->transit.cntTransit++; stats->transit.totsumTransit += transit; stats->transit.totcntTransit++; // mean min max tests if (transit < stats->transit.minTransit) { stats->transit.minTransit=transit; } if (transit < stats->transit.totminTransit) { stats->transit.totminTransit=transit; } if (transit > stats->transit.maxTransit) { stats->transit.maxTransit=transit; } if (transit > stats->transit.totmaxTransit) { stats->transit.totmaxTransit=transit; } // For variance, working units is microseconds // variance interval usec_transit = transit * 1e6; stats->transit.vdTransit = usec_transit - stats->transit.meanTransit; stats->transit.meanTransit = stats->transit.meanTransit + (stats->transit.vdTransit / stats->transit.cntTransit); stats->transit.m2Transit = stats->transit.m2Transit + (stats->transit.vdTransit * (usec_transit - stats->transit.meanTransit)); // variance total stats->transit.totvdTransit = usec_transit - stats->transit.totmeanTransit; stats->transit.totmeanTransit = stats->transit.totmeanTransit + (stats->transit.totvdTransit / stats->transit.totcntTransit); stats->transit.totm2Transit = stats->transit.totm2Transit + (stats->transit.totvdTransit * (usec_transit - stats->transit.totmeanTransit)); } stats->transit.lastTransit = transit; } } else if (reporthdr->report.mThreadMode == kMode_Server && (packet->packetLen > 0)) { int bin; // mean min max tests stats->tcp.read.cntRead++; stats->tcp.read.totcntRead++; bin = (int)floor((packet->packetLen -1)/stats->tcp.read.binsize); stats->tcp.read.bins[bin]++; stats->tcp.read.totbins[bin]++; } else if (reporthdr->report.mThreadMode == kMode_Client) { if (packet->errwrite) { stats->tcp.write.WriteErr++; stats->tcp.write.totWriteErr++; } else { stats->tcp.write.WriteCnt++; stats->tcp.write.totWriteCnt++; } } } else if ((stats->mUDP == kMode_Server) && \ (stats->transit.cntTransit == 0)) { // This is the case when empty reports // cross the report interval boundary // Hence, set the per interval min to infinity // and the per interval max and sum to zero stats->transit.minTransit = FLT_MAX; stats->transit.maxTransit = FLT_MIN; stats->transit.sumTransit = 0; stats->transit.vdTransit = 0; stats->transit.meanTransit = 0; stats->transit.m2Transit = 0; } } // Print a report if appropriate return reporter_condprintstats( &reporthdr->report, reporthdr->multireport, finished ); }
/* * Updates connection stats */ int reporter_handle_packet( ReportHeader *reporthdr ) { ReportStruct *packet = &reporthdr->data[reporthdr->reporterindex]; ReporterData *data = &reporthdr->report; Transfer_Info *stats = &reporthdr->report.info; int finished = 0; data->cntDatagrams++; // If this is the last packet set the endTime if ( packet->packetID < 0 ) { data->packetTime = packet->packetTime; finished = 1; if ( reporthdr->report.mThreadMode != kMode_Client ) { data->TotalLen += packet->packetLen; } } else { // update recieved amount and time data->packetTime = packet->packetTime; reporter_condprintstats( &reporthdr->report, reporthdr->multireport, finished ); data->TotalLen += packet->packetLen; if ( packet->packetID != 0 ) { // UDP packet double transit = 0.0; double deltaTransit; // from RFC 1889, Real Time Protocol (RTP) // J = J + ( | D(i-1,i) | - J ) / 16 transit = TimeDifference( packet->packetTime, packet->sentTime ); if ( data->lastTransit != 0.0 ) { deltaTransit = transit - data->lastTransit; if ( deltaTransit < 0.0 ) { deltaTransit = -deltaTransit; } stats->jitter += (deltaTransit - stats->jitter) / (16.0); stats->delay += transit*1000; stats->delay_total += transit*1000; } data->lastTransit = transit; // packet loss occured if the datagram numbers aren't sequential if ( packet->packetID != data->PacketID + 1 ) { if ( packet->packetID < data->PacketID + 1 ) { data->cntOutofOrder++; if (reporthdr->report.mThreadMode != kMode_Client) { struct out_of_order_packet *oop; if (!(oop = (struct out_of_order_packet *) malloc(sizeof(struct out_of_order_packet)))) { fprintf(stderr, "Out of memory"); exit(1); } oop->packetID = packet->packetID; #ifndef WIN32 //printf("Packet %d out of order\n", packet->packetID); LIST_INSERT_HEAD(&(data->out_of_order_packets), oop, list); #endif } } else { data->cntError += packet->packetID - data->PacketID - 1; if (reporthdr->report.mThreadMode != kMode_Client) { struct lost_packet_interval *lpi; if (!(lpi = (struct lost_packet_interval *) malloc(sizeof(struct lost_packet_interval)))) { fprintf(stderr, "Out of memory"); exit(1); } lpi->from = (data->PacketID + 1); lpi->to = (packet->packetID - 1); #ifndef WIN32 LIST_INSERT_HEAD(&data->lost_packets, lpi, list); /* printf("Packet %d revealed a loss gap from %d, " "total loss %d\n", packet->packetID, data->PacketID, data->cntError); */ #endif } } } // never decrease datagramID (e.g. if we get an out-of-order packet) if ( packet->packetID > data->PacketID ) { data->PacketID = packet->packetID; } } } // Print a report if appropriate return reporter_condprintstats( &reporthdr->report, reporthdr->multireport, finished ); }