📄 trpr.cpp
字号:
friend class FlowList; public: Flow(bool presetFlow = false); ~Flow(); bool InitFromDescription(char* flowInfo); void PrintDescription(FILE* f); const char* Type() {return type;} bool SetType(const char* theType); const Address& SrcAddr() const {return src_addr;} void SetSrcAddr(const Address& value) {src_addr = value;} unsigned short SrcPort() const {return src_port;} void SetSrcPort(unsigned short value) {src_port = value;} const Address& DstAddr() const {return dst_addr;} void SetDstAddr(const Address& value) {dst_addr = value;} unsigned short DstPort() const {return dst_port;} void SetDstPort(unsigned short value) {dst_port = value;} void SetFlowId(unsigned long value) {flow_id = value;} unsigned long FlowId() {return flow_id.Value();} bool IsPreset() {return preset;} bool TypeMatch(const char* theType) const { if (theType && type) return (0 == strncmp(theType, type, type_len)); else return (theType == type); } bool Match(const char* theType, const Address& srcAddr, unsigned short srcPort, const Address& dstAddr, unsigned short dstPort, unsigned long flowId) const; unsigned long Bytes() const {return byte_count;} void AddBytes(unsigned long pktSize) {byte_count += pktSize;} void ResetByteCount() {byte_count = 0;} double Accumulator() {return accumulator;} unsigned long AccumulatorCount() {return accumulator_count;} void ResetAccumulator() {accumulator = 0.0; accumulator_count = 0;} void Accumulate(double value) {accumulator += value; accumulator_count++;} void InitLossTracker(unsigned long seqMax = 0xffffffff) {loss_tracker.Init(seqMax);} void ResetLossTracker() {loss_tracker.Reset();} bool UpdateLossTracker(double theTime, unsigned long seq, unsigned long theFlow = 0) {return loss_tracker.Update(theTime, seq, theFlow);} double LossFraction() {return loss_tracker.LossFraction();} void InitLossTracker2(double windowSize, unsigned long seqMax = 0xffffffff) { loss_tracker2.Init(windowSize, seqMax); } void ResetLossTracker2() {loss_tracker2.Reset();} bool UpdateLossTracker2(double theTime, unsigned long seq, unsigned long theFlow = 0) {return loss_tracker2.Update(theTime, seq, theFlow);} double LossFraction2() {return loss_tracker2.LossFraction();} double LossWindowStart2() {return loss_tracker2.LossWindowStart();} double LossWindowEnd2() {return loss_tracker2.LossWindowEnd();} Flow* Next() {return next;} bool AppendData(double x, double y); void PruneData(double xMin) {point_list.PruneData(xMin);} bool PrintData(FILE* filePtr) {return point_list.PrintData(filePtr);} double MarkReception(double theTime) { double currentDelay = ((last_time < 0.0) ? -1.0 : (theTime - last_time)); last_time = theTime; return currentDelay; } void UpdateSummary(double value, double weight = 1.0) { if (sum_init) { sum_total = value * weight; sum_min = sum_max = value; sum_var = value*value*weight; sum_weight = weight; sum_init = false; } else { sum_weight += weight; sum_total += (value * weight); sum_var += (value*value*weight); if (value < sum_min) sum_min = value; if (value > sum_max) sum_max = value; } histogram.Tally(value); } double SummaryAverage() {return (sum_total / sum_weight);} double SummaryVariance() { double mean = SummaryAverage(); double variance = sum_var/((double)sum_weight) - (mean*mean); return variance; } double SummaryMin() {return sum_min;} double SummaryMax() {return sum_max;} double PosX() {return pos_x;} double PosY() {return pos_y;} bool PositionIsValid() { bool xvalid = ((pos_x <= 180.0) && (pos_x >= -180.0)); bool yvalid = ((pos_y <= 90.0) && (pos_y >= -90.0)); return (xvalid && yvalid); } double UpdatePosition(double theTime, double x, double y); void PrintHistogram(FILE* file) {histogram.Print(file);} double Percentile(double p) {return histogram.Percentile(p);} private: bool preset; // used to mark preset flows from "flow" command char* type; unsigned int type_len; Address src_addr; int src_port; Address dst_addr; int dst_port; ::FlowId flow_id; // if applicable // Byte count accumulator double last_time; // used for inter-arrival delay plot unsigned long byte_count; double accumulator; // for interarrival or latency accumulation unsigned long accumulator_count; PointList point_list; LossTracker loss_tracker; LossTracker2 loss_tracker2; // GPS Position double pos_x; double pos_y; // Summary data bool sum_init; double sum_total; double sum_var; double sum_min; double sum_max; double sum_weight; // histogram Histogram histogram; Flow* prev; Flow* next; }; // end class Flowclass FlowList{ public: FlowList(); ~FlowList(); void Destroy(); void Append(Flow* theFlow); void Remove(Flow* theFlow); Flow* Head() {return head;} unsigned long Count() {return count;} private: Flow* head; Flow* tail; unsigned long count; }; // end class FlowListvoid UpdateWindowPlot(PlotMode plotMode, FlowList& flowList, FILE* outfile, double theTime, double windowStart, double windowEnd, bool realTime, bool stairStep);void UpdateGnuplot(PlotMode plotMode, FlowList* flowList, double xMin, double xMax, const char* pngFile, const char* postFile, bool scatter);void UpdateMultiGnuplot(PlotMode plotMode, FlowList* flowList, double xMin, double xMax, const char* pngFile, const char* postFile, bool scatter);Point::Point(double x, double y) : xval(x), yval(y), kval(0), prev(NULL), next(NULL){}Point::Point(double x, unsigned long k) : xval(x), yval(0), kval(k), prev(NULL), next(NULL){}PointList::PointList() : head(NULL), tail(NULL){}PointList::~PointList(){ Destroy();}Point* PointList::FindPointByK(unsigned long k){ Point* next = head; while (next) { if (k == next->K()) return next; else next = next->Next(); } return NULL;} // end PointList::FindPointByK()// This tries to leave only one point with X < xMin// This assumes X data is in order min -> maxvoid PointList::PruneData(double xMin){ Point* next = head; while ((next = head)) { if (next->X() < xMin) { Remove(next); delete next; } else { break; } }} // end PointList::PruneData()bool PointList::PrintData(FILE* filePtr){ Point* next = head; while (next) { fprintf(filePtr, "%f, %f\n", next->X(), next->Y()); next = next->Next(); } if (head) return true; else return false;} // end PointList::PrintData() void PointList::Append(Point* thePoint){ if ((thePoint->prev = tail)) tail->next = thePoint; else head = thePoint; thePoint->next = NULL; tail = thePoint; } // end PointList::Append()void PointList::Remove(Point* thePoint){ if (thePoint->prev) thePoint->prev->next = thePoint->next; else head = thePoint->next; if (thePoint->next) thePoint->next->prev = thePoint->prev; else tail = thePoint->prev;} // end PointList::Remove()void PointList::Destroy(){ Point* next; while ((next = head)) { Remove(next); delete next; }} // end PointList::Destroy()LossTracker::LossTracker() : last_time(0.0), loss_fraction(1.0), loss_max(16536), first_packet(true), packet_count(0), loss_count(0), resync_count(0), duplicate_count(0), late_count(0), seq_last(0), flow_id(0){ SetSeqMax(0xffffffff);}bool LossTracker::Update(double theTime, unsigned long theSequence, unsigned long theFlow){ if (theTime < last_time) { fprintf(stderr, "trpr: LossTracker::Update() time out of order (thisTime:%f lastTime:%f)!\n", theTime, last_time); return false; } if (first_packet) { first_packet = false; seq_last = theSequence; packet_count = 1; loss_fraction = 0.0; flow_id = theFlow; return true; } // Process incoming sequence number // 1) Calc delta, handling wrap conditions long delta; if ((theSequence < seq_qtr) && (seq_last > (seq_hlf+seq_qtr))) delta = seq_max - seq_last + theSequence + 1; else if ((theSequence > (seq_hlf+seq_qtr)) && (seq_last < seq_qtr)) delta = theSequence - seq_last - seq_max - 1; else delta = theSequence - seq_last; // 2) Use "delta" to determine sync state, loss, etc if ((labs(delta) > loss_max) || (theFlow != flow_id)) { // lost sync? resync_count++; fprintf(stderr, "trpr: LossTracker::Update() resync! (seq:%lu lseq:%lu delta:%ld max:%lu " "flow:%lu oldFlow:%lu)\n", theSequence, seq_last, delta, loss_max, theFlow, flow_id); seq_last = theSequence; Update(theTime, theSequence, theFlow); return false; } else if (delta > 0) { if (delta > 1) { // possible loss while(seq_last++ != theSequence) { if (seq_last > seq_max) seq_last = 0; Point* lost = new Point(theTime, seq_last); if (!lost) { perror("trpr: LossTracker::Update() Error adding point"); return false; } loss_list.Append(lost); loss_count++; } } else { // No loss } seq_last = theSequence; packet_count++; } else if (delta < 0) { // Late arriving packet packet_count++; Point* oldLost = loss_list.FindPointByK(theSequence); if (oldLost) { loss_list.Remove(oldLost); loss_count--; } else { // Late packet (from previous window?) late_count++; } } else { // duplicate packet? duplicate_count++; packet_count++; } // 4) Compute current loss fraction value // (TBD) Fudge with late_count?? //fprintf(stderr, "losses:%lu pkts:%lu\n", loss_count, packet_count); loss_fraction = ((double)loss_count) / ((double)(packet_count+loss_count)); last_time = theTime; return true;} // end LossTracker::Update()LossTracker2::LossTracker2() : first_packet(true), wrap(false), wrap_count(0), time_first(-1.0), time_last(-1.0), window_size(1.0), window_end(-1.0), packet_count(0), seq_first(0), seq_last(0), duplicate_count(0), resync_count(0), seq_max(0xffffffff), flow_id(0) { }int LossTracker2::Update(double theTime, unsigned long theSequence, unsigned long theFlow){ if (theTime < time_last) { fprintf(stderr, "trpr: LossTracker::Update() time out of order (thisTime:%f lastTime:%f)!\n", theTime, time_last); //exit(-1); } if (first_packet) { first_packet = false; seq_first = seq_last = theSequence; time_first = time_last = theTime; if (window_size > 0.0) window_end = theTime + window_size; packet_count = 1; wrap = false; wrap_count = 0; flow_id = theFlow; return 0; } // Process incoming sequence number // 1) Check for sequence wrap & sync loss long delta; if ((theSequence < seq_qtr) && (seq_last > (seq_hlf+seq_qtr))) { delta = seq_max - seq_last + theSequence + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -