void TCPStreamDialog::fillRoundTripTime() { QString dlg_title = QString(tr("Round Trip Time")) + streamDescription(); setWindowTitle(dlg_title); title_->setText(dlg_title); sequence_num_map_.clear(); QCustomPlot *sp = ui->streamPlot; sp->xAxis->setLabel(sequence_number_label_); sp->xAxis->setNumberFormat("f"); sp->xAxis->setNumberPrecision(0); sp->yAxis->setLabel(round_trip_time_ms_label_); base_graph_->setLineStyle(QCPGraph::lsLine); QVector<double> seq_no, rtt; guint32 seq_base = 0; struct unack *unack = NULL, *u = NULL; for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { if (compareHeaders(seg)) { seq_base = seg->th_seq; break; } } for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { if (compareHeaders(seg)) { guint32 seqno = seg->th_seq - seq_base; if (seg->th_seglen && !rtt_is_retrans(unack, seqno)) { double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0; u = rtt_get_new_unack(rt_val, seqno); if (!u) return; rtt_put_unack_on_list(&unack, u); } } else { guint32 ack_no = seg->th_ack - seq_base; double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0; struct unack *v; for (u = unack; u; u = v) { if (ack_no > u->seqno) { seq_no.append(u->seqno); rtt.append((rt_val - u->time) * 1000.0); sequence_num_map_.insert(u->seqno, seg); v = u->next; rtt_delete_unack_from_list(&unack, u); } else { v = u->next; } } } } base_graph_->setData(seq_no, rtt); }
void TCPStreamDialog::fillWindowScale() { QString dlg_title = QString(tr("Window Scaling")) + streamDescription(); setWindowTitle(dlg_title); title_->setText(dlg_title); QCustomPlot *sp = ui->streamPlot; base_graph_->setLineStyle(QCPGraph::lsLine); QVector<double> rel_time, win_size; for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { if (!compareHeaders(seg)) { continue; } double ts = seg->rel_secs + seg->rel_usecs / 1000000.0; guint16 flags = seg->th_flags; if ((flags & (TH_SYN|TH_RST)) == 0) { rel_time.append(ts - ts_offset_); win_size.append(seg->th_win); } } base_graph_->setData(rel_time, win_size); sp->yAxis->setLabel(window_size_label_); }
void TCPStreamDialog::fillTcptrace() { QString dlg_title = QString(tr("Sequence Numbers (tcptrace)")) + streamDescription(); setWindowTitle(dlg_title); title_->setText(dlg_title); QCustomPlot *sp = ui->streamPlot; sp->yAxis->setLabel(sequence_number_label_); base_graph_->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDot)); seg_graph_->setVisible(true); ack_graph_->setVisible(true); rwin_graph_->setVisible(true); QVector<double> seq_time, seq, sb_time, sb_center, sb_span, ackrwin_time, ack, rwin; for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { double ts = (seg->rel_secs + seg->rel_usecs / 1000000.0) - ts_offset_; if (compareHeaders(seg)) { // Forward direction: seq + data seq_time.append(ts); seq.append(seg->th_seq - seq_offset_); // QCP doesn't have a segment graph type. For now, fake // it with error bars. if (seg->th_seglen > 0) { double half = seg->th_seglen / 2.0; sb_time.append(ts); sb_center.append(seg->th_seq - seq_offset_ + half); sb_span.append(half); } } else { // Reverse direction: ACK + RWIN if (! (seg->th_flags & TH_ACK)) { // SYNs and RSTs do not necessarily have ACKs continue; } double ackno = seg->th_ack - seq_offset_; ackrwin_time.append(ts); ack.append(ackno); rwin.append(ackno + seg->th_win); } } base_graph_->setData(seq_time, seq); seg_graph_->setDataValueError(sb_time, sb_center, sb_span); ack_graph_->setData(ackrwin_time, ack); rwin_graph_->setData(ackrwin_time, rwin); }
void TCPStreamDialog::fillStevens() { QString dlg_title = QString(tr("Sequence Numbers (Stevens)")) + streamDescription(); setWindowTitle(dlg_title); title_->setText(dlg_title); QCustomPlot *sp = ui->streamPlot; sp->yAxis->setLabel(sequence_number_label_); // True Stevens-style graphs don't have lines but I like them - gcc base_graph_->setLineStyle(QCPGraph::lsStepLeft); QVector<double> rel_time, seq; for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { if (!compareHeaders(seg)) { continue; } double ts = seg->rel_secs + seg->rel_usecs / 1000000.0; rel_time.append(ts - ts_offset_); seq.append(seg->th_seq - seq_offset_); } base_graph_->setData(rel_time, seq); }
// Fill in graph data based upon what was read into the rlc_graph struct. void LteRlcGraphDialog::fillGraph() { QCustomPlot *sp = ui->rlcPlot; // We should always have 4 graphs, but cover case if no channel was chosen. if (sp->graphCount() < 1) { return; } tracer_->setGraph(NULL); base_graph_->setLineStyle(QCPGraph::lsNone); // dot reseg_graph_->setLineStyle(QCPGraph::lsNone); // dot acks_graph_->setLineStyle(QCPGraph::lsStepLeft); // to get step effect... nacks_graph_->setLineStyle(QCPGraph::lsNone); // dot, but bigger. // Will show all graphs with data we find. for (int i = 0; i < sp->graphCount(); i++) { sp->graph(i)->clearData(); sp->graph(i)->setVisible(true); } // N.B. ssDisc is really too slow. TODO: work out how to turn off aliasing, or experiment // with ssCustom. Other styles tried didn't look right. // GTK version was speeded up noticibly by turning down aliasing level... base_graph_->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, pkt_point_size_)); reseg_graph_->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, pkt_point_size_)); acks_graph_->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, pkt_point_size_)); // NACKs are shown bigger than others. nacks_graph_->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, pkt_point_size_*2)); // Map timestamps -> segments in first pass. time_stamp_map_.clear(); for (struct rlc_segment *seg = graph_.segments; seg != NULL; seg = seg->next) { if (!compareHeaders(seg)) { continue; } double ts = seg->rel_secs + seg->rel_usecs / 1000000.0; time_stamp_map_.insertMulti(ts, seg); } // Now sequence numbers. QVector<double> seq_time, seq, reseg_seq_time, reseg_seq, acks_time, acks, nacks_time, nacks; for (struct rlc_segment *seg = graph_.segments; seg != NULL; seg = seg->next) { double ts = seg->rel_secs + seg->rel_usecs / 1000000.0; if (compareHeaders(seg)) { if (!seg->isControlPDU) { // Data if (seg->isResegmented) { reseg_seq_time.append(ts); reseg_seq.append(seg->SN); } else { seq_time.append(ts); seq.append(seg->SN); } } else { // Status (ACKs/NACKs) acks_time.append(ts); acks.append(seg->ACKNo-1); for (int n=0; n < seg->noOfNACKs; n++) { nacks_time.append(ts); nacks.append(seg->NACKs[n]); } } } } // Add the data from the graphs. base_graph_->setData(seq_time, seq); reseg_graph_->setData(reseg_seq_time, reseg_seq); acks_graph_->setData(acks_time, acks); nacks_graph_->setData(nacks_time, nacks); sp->setEnabled(true); // Auto-size... mouseMoved(NULL); resetAxes(); tracer_->setGraph(base_graph_); // XXX QCustomPlot doesn't seem to draw any sort of focus indicator. sp->setFocus(); }
void TCPStreamDialog::fillThroughput() { QString dlg_title = QString(tr("Throughput")) + streamDescription(); #ifdef MA_1_SECOND dlg_title.append(tr(" (1s MA)")); #else dlg_title.append(QString(tr(" (%1 Segment MA)")).arg(moving_avg_period_)); #endif setWindowTitle(dlg_title); title_->setText(dlg_title); QCustomPlot *sp = ui->streamPlot; sp->yAxis->setLabel(segment_length_label_); sp->yAxis2->setLabel(average_throughput_label_); sp->yAxis2->setLabelColor(QColor(graph_color_2)); sp->yAxis2->setTickLabelColor(QColor(graph_color_2)); sp->yAxis2->setVisible(true); tput_graph_->setVisible(true); if (!graph_.segments || !graph_.segments->next) { dlg_title.append(tr(" [not enough data]")); return; } QVector<double> rel_time, seg_len, tput_time, tput; int oldest = 0; guint64 sum = 0; // Financial charts don't show MA data until a full period has elapsed. // The Rosetta Code MA examples start spitting out values immediately. // For now use not-really-correct initial values just to keep our vector // lengths the same. for (struct segment *seg = graph_.segments->next; seg != NULL; seg = seg->next) { if (!compareHeaders(seg)) { continue; } double ts = (seg->rel_secs + seg->rel_usecs / 1000000.0) - ts_offset_; rel_time.append(ts); seg_len.append(seg->th_seglen); #ifdef MA_1_SECOND while (ts - rel_time[oldest] > 1.0 && oldest < rel_time.size()) { sum -= seg_len[oldest]; oldest++; } #else if (seg_len.size() > moving_avg_period_) { sum -= seg_len[oldest]; oldest++; } #endif double dtime = ts - rel_time[oldest]; double av_tput; sum += seg->th_seglen; if (dtime > 0.0) { av_tput = sum * 8.0 / dtime; } else { av_tput = 0.0; } // Add a data point only if our time window has advanced. Otherwise // update the most recent point. (We might want to show a warning // for out-of-order packets.) if (tput_time.size() > 0 && ts <= tput_time.last()) { tput[tput.size() - 1] = av_tput; } else { tput.append(av_tput); tput_time.append(ts); } } base_graph_->setData(rel_time, seg_len); tput_graph_->setData(tput_time, tput); }
void TCPStreamDialog::fillGraph() { QCustomPlot *sp = ui->streamPlot; if (sp->graphCount() < 1) return; base_graph_->setLineStyle(QCPGraph::lsNone); tracer_->setGraph(NULL); // base_graph_ is always visible. for (int i = 0; i < sp->graphCount(); i++) { sp->graph(i)->clearData(); sp->graph(i)->setVisible(i == 0 ? true : false); } base_graph_->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, pkt_point_size_)); sp->xAxis->setLabel(time_s_label_); sp->xAxis->setNumberFormat("gb"); sp->xAxis->setNumberPrecision(6); sp->yAxis->setNumberFormat("f"); sp->yAxis->setNumberPrecision(0); sp->yAxis2->setVisible(false); sp->yAxis2->setLabel(QString()); if (!cap_file_) { QString dlg_title = QString(tr("No Capture Data")); setWindowTitle(dlg_title); title_->setText(dlg_title); sp->setEnabled(false); sp->yAxis->setLabel(QString()); sp->replot(); return; } ts_offset_ = 0; seq_offset_ = 0; bool first = true; guint64 bytes_fwd = 0; guint64 bytes_rev = 0; int pkts_fwd = 0; int pkts_rev = 0; time_stamp_map_.clear(); for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { if (!compareHeaders(seg)) { bytes_rev += seg->th_seglen; pkts_rev++; continue; } bytes_fwd += seg->th_seglen; pkts_fwd++; double ts = seg->rel_secs + seg->rel_usecs / 1000000.0; if (first) { if (ts_origin_conn_) ts_offset_ = ts; if (seq_origin_zero_) seq_offset_ = seg->th_seq; first = false; } time_stamp_map_.insertMulti(ts - ts_offset_, seg); } switch (graph_.type) { case GRAPH_TSEQ_STEVENS: fillStevens(); break; case GRAPH_TSEQ_TCPTRACE: fillTcptrace(); break; case GRAPH_THROUGHPUT: fillThroughput(); break; case GRAPH_RTT: fillRoundTripTime(); break; case GRAPH_WSCALE: fillWindowScale(); break; default: break; } sp->setEnabled(true); stream_desc_ = tr("%1 %2 pkts, %3 %4 %5 pkts, %6 ") .arg(UTF8_RIGHTWARDS_ARROW) .arg(gchar_free_to_qstring(format_size(pkts_fwd, format_size_unit_none|format_size_prefix_si))) .arg(gchar_free_to_qstring(format_size(bytes_fwd, format_size_unit_bytes|format_size_prefix_si))) .arg(UTF8_LEFTWARDS_ARROW) .arg(gchar_free_to_qstring(format_size(pkts_rev, format_size_unit_none|format_size_prefix_si))) .arg(gchar_free_to_qstring(format_size(bytes_rev, format_size_unit_bytes|format_size_prefix_si))); mouseMoved(NULL); resetAxes(); tracer_->setGraph(base_graph_); // XXX QCustomPlot doesn't seem to draw any sort of focus indicator. sp->setFocus(); }