diff options
author | Gerald Combs <gerald@wireshark.org> | 2013-09-08 01:25:27 +0000 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2013-09-08 01:25:27 +0000 |
commit | abdac5bfac5f330de14c545d8d5f503393801d1f (patch) | |
tree | 8f40df8d4876d6f439e85b98170d7aa27472d4b1 | |
parent | cc26962f96217d834e1dcf11312f9521bde9841c (diff) | |
download | wireshark-abdac5bfac5f330de14c545d8d5f503393801d1f.tar.gz wireshark-abdac5bfac5f330de14c545d8d5f503393801d1f.tar.bz2 wireshark-abdac5bfac5f330de14c545d8d5f503393801d1f.zip |
Add the TCP RTT graph.
Show the time values in ms instead of s. Add a button and keyboard
shortcut to switch the connection direction. Move more code to
tap-tcp-stream.c. Update our axis labels.
svn path=/trunk/; revision=51832
-rw-r--r-- | ui/gtk/tcp_graph.c | 70 | ||||
-rw-r--r-- | ui/qt/main_window.h | 1 | ||||
-rw-r--r-- | ui/qt/main_window.ui | 9 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 5 | ||||
-rw-r--r-- | ui/qt/tcp_stream_dialog.cpp | 115 | ||||
-rw-r--r-- | ui/qt/tcp_stream_dialog.h | 5 | ||||
-rw-r--r-- | ui/qt/tcp_stream_dialog.ui | 11 | ||||
-rw-r--r-- | ui/tap-tcp-stream.c | 57 | ||||
-rw-r--r-- | ui/tap-tcp-stream.h | 12 |
9 files changed, 201 insertions, 84 deletions
diff --git a/ui/gtk/tcp_graph.c b/ui/gtk/tcp_graph.c index 157075accc..06e1656f8d 100644 --- a/ui/gtk/tcp_graph.c +++ b/ui/gtk/tcp_graph.c @@ -194,13 +194,6 @@ struct style_wscale { #define TIME_ORIGIN_CAP 0x10 #define TIME_ORIGIN_CONN 0x0 -/* this is used by rtt module only */ -struct unack { - struct unack *next; - double time; - unsigned int seqno; -}; - struct cross { int x, y; int draw; /* indicates whether we should draw cross at all */ @@ -462,10 +455,6 @@ static void tput_make_elmtlist(struct gtk_graph * ); static void tput_toggle_time_origin(struct gtk_graph * ); static void rtt_read_config(struct gtk_graph * ); static void rtt_initialize(struct gtk_graph * ); -static int rtt_is_retrans(struct unack * , unsigned int ); -static struct unack *rtt_get_new_unack(double , unsigned int ); -static void rtt_put_unack_on_list(struct unack ** , struct unack * ); -static void rtt_delete_unack_from_list(struct unack ** , struct unack * ); static void rtt_make_elmtlist(struct gtk_graph * ); static void rtt_toggle_seq_origin(struct gtk_graph * ); static void wscale_initialize(struct gtk_graph *); @@ -4291,65 +4280,6 @@ static void rtt_initialize(struct gtk_graph *g) g->zoom.y = g->geom.height / g->bounds.height; } -static int rtt_is_retrans(struct unack *list, unsigned int seqno) -{ - struct unack *u; - - for (u=list; u; u=u->next) { - if (u->seqno == seqno) - return TRUE; - } - return FALSE; -} - -static struct unack *rtt_get_new_unack(double time_val, unsigned int seqno) -{ - struct unack *u; - - u = (struct unack * )g_malloc(sizeof(struct unack)); - if (!u) - return NULL; - u->next = NULL; - u->time = time_val; - u->seqno = seqno; - return u; -} - -static void rtt_put_unack_on_list(struct unack **l, struct unack *new_unack) -{ - struct unack *u, *list = *l; - - for (u=list; u; u=u->next) { - if (!u->next) - break; - } - if (u) - u->next = new_unack; - else - *l = new_unack; -} - -static void rtt_delete_unack_from_list(struct unack **l, struct unack *dead) -{ - struct unack *u, *list = *l; - - if (!dead || !list) - return; - - if (dead == list) { - *l = list->next; - g_free(list); - } else { - for (u=list; u; u=u->next) { - if (u->next == dead) { - u->next = u->next->next; - g_free(dead); - break; - } - } - } -} - static void rtt_make_elmtlist(struct gtk_graph *g) { struct segment *tmp; diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index fb121413dc..d8c3938005 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -302,6 +302,7 @@ private slots: void openTcpStreamDialog(int graph_type); void on_actionStatisticsTcpStreamStevens_triggered(); void on_actionStatisticsTcpStreamThroughput_triggered(); + void on_actionStatisticsTcpStreamRoundTripTime_triggered(); }; diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index fdbeb811b9..366203bca9 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -321,6 +321,7 @@ </property> <addaction name="actionStatisticsTcpStreamStevens"/> <addaction name="actionStatisticsTcpStreamThroughput"/> + <addaction name="actionStatisticsTcpStreamRoundTripTime"/> </widget> <addaction name="actionSummary"/> <addaction name="actionProtocol_Hierarchy"/> @@ -1265,6 +1266,14 @@ <string>TCP througput</string> </property> </action> + <action name="actionStatisticsTcpStreamRoundTripTime"> + <property name="text"> + <string>Round Trip Time</string> + </property> + <property name="toolTip"> + <string>TCP round trip time</string> + </property> + </action> </widget> <layoutdefault spacing="6" margin="11"/> <customwidgets> diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index d52efe1704..9ed79afb63 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -1712,6 +1712,11 @@ void MainWindow::on_actionStatisticsTcpStreamThroughput_triggered() openTcpStreamDialog(GRAPH_THROUGHPUT); } +void MainWindow::on_actionStatisticsTcpStreamRoundTripTime_triggered() +{ + openTcpStreamDialog(GRAPH_RTT); +} + // Help Menu void MainWindow::on_actionHelpContents_triggered() { diff --git a/ui/qt/tcp_stream_dialog.cpp b/ui/qt/tcp_stream_dialog.cpp index 76b7a17064..3aeb51060f 100644 --- a/ui/qt/tcp_stream_dialog.cpp +++ b/ui/qt/tcp_stream_dialog.cpp @@ -47,6 +47,12 @@ const int moving_avg_period_ = 20; const QRgb graph_color_1 = tango_sky_blue_5; const QRgb graph_color_2 = tango_butter_6; +const QString average_throughput_label_ = QObject::tr("Avgerage Througput (bits/s)"); +const QString round_trip_time_ms_label_ = QObject::tr("Round Trip Time (ms)"); +const QString segment_length_label_ = QObject::tr("Segment Length (B)"); +const QString sequence_number_label_ = QObject::tr("Relative Sequence Number (B)"); +const QString time_s_label_ = QObject::tr("Time (s)"); + Q_DECLARE_METATYPE(tcp_graph_type) TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_type graph_type) : @@ -73,11 +79,16 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty ui->graphTypeComboBox->setUpdatesEnabled(false); ui->graphTypeComboBox->addItem(tr("Time / Sequence (Stevens)"), qVariantFromValue(GRAPH_TSEQ_STEVENS)); ui->graphTypeComboBox->addItem(tr("Throughput"), qVariantFromValue(GRAPH_THROUGHPUT)); + ui->graphTypeComboBox->addItem(tr("Round Trip Time"), qVariantFromValue(GRAPH_RTT)); ui->graphTypeComboBox->setCurrentIndex(-1); ui->graphTypeComboBox->setUpdatesEnabled(true); memset (&graph_, 0, sizeof(graph_)); graph_.type = graph_type; + COPY_ADDRESS(&graph_.src_address, ¤t.ip_src); + graph_.src_port = current.th_sport; + COPY_ADDRESS(&graph_.dst_address, ¤t.ip_dst); + graph_.dst_port = current.th_dport; QCustomPlot *sp = ui->streamPlot; QCPPlotTitle *file_title = new QCPPlotTitle(sp, cf_get_display_name(cap_file_)); @@ -103,7 +114,6 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty sp->graph(0)->setPen(QPen(QBrush(graph_color_1), 0.25)); sp->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 5)); - sp->xAxis->setLabel(tr("Time (s)")); sp->yAxis->setLabelColor(QColor(graph_color_1)); sp->yAxis->setTickLabelColor(QColor(graph_color_1)); @@ -189,6 +199,9 @@ void TCPStreamDialog::keyPressEvent(QKeyEvent *event) case Qt::Key_Home: resetAxes(); break; + case Qt::Key_S: + on_otherDirectionButton_clicked(); + break; // Alas, there is no Blade Runner-style Qt::Key_Ehance } @@ -218,7 +231,8 @@ void TCPStreamDialog::fillGraph() if (sp->graphCount() < 1) return; - segment_map_.clear(); + rel_time_map_.clear(); + sequence_num_map_.clear(); graph_segment_list_free(&graph_); tracer_->setGraph(NULL); // We need at least one graph, so don't bother deleting the first one. @@ -226,11 +240,15 @@ void TCPStreamDialog::fillGraph() sp->graph(i)->clearData(); sp->graph(i)->setVisible(i == 0 ? true : false); } + + sp->xAxis->setLabel(time_s_label_); + sp->xAxis->setNumberFormat("gb"); + sp->xAxis->setNumberPrecision(6); sp->yAxis2->setVisible(false); sp->yAxis2->setLabel(QString()); if (!cap_file_) { - QString dlg_title = QString(tr("No capture file")); + QString dlg_title = QString(tr("No Capture Data")); setWindowTitle(dlg_title); title_->setText(dlg_title); sp->setEnabled(false); @@ -242,14 +260,14 @@ void TCPStreamDialog::fillGraph() // XXX graph_segment_list_get returns a different list for throughput // graphs. If the throughput list used the same list we could call this // above in our ctor. - graph_segment_list_get(cap_file_, &graph_, FALSE); + graph_segment_list_get(cap_file_, &graph_, TRUE); for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { if (!compareHeaders(seg)) { continue; } double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0; - segment_map_.insertMulti(rt_val, seg); + rel_time_map_.insertMulti(rt_val, seg); } switch (graph_.type) { @@ -259,6 +277,9 @@ void TCPStreamDialog::fillGraph() case GRAPH_THROUGHPUT: initializeThroughput(); break; + case GRAPH_RTT: + initializeRoundTripTime(); + break; default: break; } @@ -300,7 +321,7 @@ void TCPStreamDialog::resetAxes() void TCPStreamDialog::initializeStevens() { - QString dlg_title = QString(tr("Sequence numbers")) + streamDescription(); + QString dlg_title = QString(tr("Sequence Numbers")) + streamDescription(); setWindowTitle(dlg_title); title_->setText(dlg_title); @@ -319,7 +340,7 @@ void TCPStreamDialog::initializeStevens() seq.append(seg->th_seq); } sp->graph(0)->setData(rel_time, seq); - sp->yAxis->setLabel(tr("Sequence number (B)")); + sp->yAxis->setLabel(sequence_number_label_); } void TCPStreamDialog::initializeThroughput() @@ -328,7 +349,7 @@ void TCPStreamDialog::initializeThroughput() #ifdef MA_1_SECOND dlg_title.append(tr(" (1s MA)")); #else - dlg_title.append(QString(tr(" (%1 segment MA)")).arg(moving_avg_period_)); + dlg_title.append(QString(tr(" (%1 Segment MA)")).arg(moving_avg_period_)); #endif setWindowTitle(dlg_title); title_->setText(dlg_title); @@ -395,14 +416,58 @@ void TCPStreamDialog::initializeThroughput() sp->graph(0)->setData(rel_time, seg_len); sp->graph(1)->setData(tput_time, tput); - sp->yAxis->setLabel(tr("Segment length (B)")); + sp->yAxis->setLabel(segment_length_label_); - sp->yAxis2->setLabel(tr("Avg througput (bits/s)")); + sp->yAxis2->setLabel(average_throughput_label_); sp->yAxis2->setLabelColor(QColor(graph_color_2)); sp->yAxis2->setTickLabelColor(QColor(graph_color_2)); sp->yAxis2->setVisible(true); } +void TCPStreamDialog::initializeRoundTripTime() +{ + QString dlg_title = QString(tr("Round Trip Time")) + streamDescription(); + setWindowTitle(dlg_title); + title_->setText(dlg_title); + + QCustomPlot *sp = ui->streamPlot; + sp->graph(0)->setLineStyle(QCPGraph::lsLine); + + QVector<double> seq_no, rtt; + guint32 seq_base; + struct unack *unack = NULL, *u; + for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { + if (seg == graph_.segments) { + seq_base = seg->th_seq; + } + if (compareHeaders(seg)) { + if (seg->th_seglen && !rtt_is_retrans(unack, seg->th_seq)) { + double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0; + rtt_put_unack_on_list(&unack, rtt_get_new_unack(rt_val, seg->th_seq)); + } + } 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); + rtt_delete_unack_from_list(&unack, u); + } + v = u->next; + } + } + } + sp->graph(0)->setData(seq_no, rtt); + sp->xAxis->setLabel(sequence_number_label_); + sp->xAxis->setNumberFormat("f"); + sp->xAxis->setNumberPrecision(0); + sp->yAxis->setLabel(round_trip_time_ms_label_); +} + QString TCPStreamDialog::streamDescription() { return QString(tr(" for %1:%2 %3 %4:%5")) @@ -461,12 +526,21 @@ void TCPStreamDialog::graphClicked(QMouseEvent *event) // using a QTimer instead. void TCPStreamDialog::mouseMoved(QMouseEvent *event) { - double ts = tracer_->position->key(); + double tr_key = tracer_->position->key(); struct segment *packet_seg = NULL; packet_num_ = 0; if (event && tracer_->graph() && tracer_->position->axisRect()->rect().contains(event->pos())) { - packet_seg = segment_map_.value(ts, NULL); + switch (graph_.type) { + case GRAPH_TSEQ_STEVENS: + case GRAPH_THROUGHPUT: + packet_seg = rel_time_map_.value(tr_key, NULL); + break; + case GRAPH_RTT: + packet_seg = sequence_num_map_.value(tr_key, NULL); + default: + break; + } } if (!packet_seg) { @@ -481,7 +555,7 @@ void TCPStreamDialog::mouseMoved(QMouseEvent *event) QString hint = QString(tr("<small><i>%1 %2 (%3s len %4 seq %5 ack %6 win %7)</i></small>")) .arg(cap_file_ ? tr("Click to select packet") : tr("Packet")) .arg(packet_num_) - .arg(QString::number(ts, 'g', 4)) + .arg(QString::number(packet_seg->rel_secs + packet_seg->rel_usecs / 1000000.0, 'g', 4)) .arg(packet_seg->th_seglen) .arg(packet_seg->th_seq) .arg(packet_seg->th_ack) @@ -559,6 +633,21 @@ void TCPStreamDialog::setCaptureFile(capture_file *cf) } } +void TCPStreamDialog::on_otherDirectionButton_clicked() +{ + address tmp_addr; + guint16 tmp_port; + + COPY_ADDRESS(&tmp_addr, &graph_.src_address); + tmp_port = graph_.src_port; + COPY_ADDRESS(&graph_.src_address, &graph_.dst_address); + graph_.src_port = graph_.dst_port; + COPY_ADDRESS(&graph_.dst_address, &tmp_addr); + graph_.dst_port = tmp_port; + + fillGraph(); +} + /* * Editor modelines * diff --git a/ui/qt/tcp_stream_dialog.h b/ui/qt/tcp_stream_dialog.h index 45ee68bc25..087aba9d42 100644 --- a/ui/qt/tcp_stream_dialog.h +++ b/ui/qt/tcp_stream_dialog.h @@ -62,7 +62,8 @@ protected: private: Ui::TCPStreamDialog *ui; capture_file *cap_file_; - QMap<double, struct segment *> segment_map_; + QMap<double, struct segment *> rel_time_map_; + QMap<double, struct segment *> sequence_num_map_; struct tcp_graph graph_; QCPPlotTitle *title_; QCPItemTracer *tracer_; @@ -77,6 +78,7 @@ private: void resetAxes(); void initializeStevens(); void initializeThroughput(); + void initializeRoundTripTime(); QString streamDescription(); bool compareHeaders(struct segment *seg); void toggleTracerStyle(bool force_default = false); @@ -88,6 +90,7 @@ private slots: void on_buttonBox_accepted(); void on_graphTypeComboBox_currentIndexChanged(int index); void on_resetButton_clicked(); + void on_otherDirectionButton_clicked(); }; #endif // TCP_STREAM_DIALOG_H diff --git a/ui/qt/tcp_stream_dialog.ui b/ui/qt/tcp_stream_dialog.ui index ac78761918..d19d5ed04d 100644 --- a/ui/qt/tcp_stream_dialog.ui +++ b/ui/qt/tcp_stream_dialog.ui @@ -45,6 +45,7 @@ <tr><th><i>Shift+</i>↑</th><td>Move up 10%</td></th> <tr><th><i>Shift+</i>↓</th><td>Move down 10%</td></th> <tr><th>0</th><td>Reset graph to its initial state</td></th> +<tr><th>s</th><td>Switch direction (swap TCP endpoints)</td></th> <tr><th>Space</th><td>Toggle crosshairs</td></th> </tbody></table> </body></html></string> @@ -89,6 +90,16 @@ </property> </widget> </item> + <item> + <widget class="QPushButton" name="otherDirectionButton"> + <property name="toolTip"> + <string><html><head/><body><p>Switch the direction of the connection (swap the TCP endpoints).</p></body></html></string> + </property> + <property name="text"> + <string>Switch Direction</string> + </property> + </widget> + </item> </layout> </item> <item> diff --git a/ui/tap-tcp-stream.c b/ui/tap-tcp-stream.c index e2359dacf1..6bbf3c1d3a 100644 --- a/ui/tap-tcp-stream.c +++ b/ui/tap-tcp-stream.c @@ -343,6 +343,63 @@ select_tcpip_session(capture_file *cf, struct segment *hdrs) } +int rtt_is_retrans(struct unack *list, unsigned int seqno) +{ + struct unack *u; + + for (u=list; u; u=u->next) { + if (u->seqno == seqno) + return TRUE; + } + return FALSE; +} + +struct unack *rtt_get_new_unack(double time_val, unsigned int seqno) +{ + struct unack *u; + + u = (struct unack * )g_malloc(sizeof(struct unack)); + u->next = NULL; + u->time = time_val; + u->seqno = seqno; + return u; +} + +void rtt_put_unack_on_list(struct unack **l, struct unack *new_unack) +{ + struct unack *u, *list = *l; + + for (u=list; u; u=u->next) { + if (!u->next) + break; + } + if (u) + u->next = new_unack; + else + *l = new_unack; +} + +void rtt_delete_unack_from_list(struct unack **l, struct unack *dead) +{ + struct unack *u, *list = *l; + + if (!dead || !list) + return; + + if (dead == list) { + *l = list->next; + g_free(list); + } else { + for (u=list; u; u=u->next) { + if (u->next == dead) { + u->next = u->next->next; + g_free(dead); + break; + } + } + } +} + /* * Editor modelines * diff --git a/ui/tap-tcp-stream.h b/ui/tap-tcp-stream.h index 551b09af15..56953adc4e 100644 --- a/ui/tap-tcp-stream.h +++ b/ui/tap-tcp-stream.h @@ -89,6 +89,18 @@ int get_num_acks(struct tcp_graph *, int * ); struct tcpheader *select_tcpip_session(capture_file *, struct segment * ); +/* This is used by rtt module only */ +struct unack { + struct unack *next; + double time; + unsigned int seqno; +}; + +int rtt_is_retrans(struct unack * , unsigned int ); +struct unack *rtt_get_new_unack(double , unsigned int ); +void rtt_put_unack_on_list(struct unack ** , struct unack * ); +void rtt_delete_unack_from_list(struct unack ** , struct unack * ); + #ifdef __cplusplus } |