aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ui/gtk/tcp_graph.c70
-rw-r--r--ui/qt/main_window.h1
-rw-r--r--ui/qt/main_window.ui9
-rw-r--r--ui/qt/main_window_slots.cpp5
-rw-r--r--ui/qt/tcp_stream_dialog.cpp115
-rw-r--r--ui/qt/tcp_stream_dialog.h5
-rw-r--r--ui/qt/tcp_stream_dialog.ui11
-rw-r--r--ui/tap-tcp-stream.c57
-rw-r--r--ui/tap-tcp-stream.h12
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, &current.ip_src);
+ graph_.src_port = current.th_sport;
+ COPY_ADDRESS(&graph_.dst_address, &current.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 @@
&lt;tr&gt;&lt;th&gt;&lt;i&gt;Shift+&lt;/i&gt;↑&lt;/th&gt;&lt;td&gt;Move up 10%&lt;/td&gt;&lt;/th&gt;
&lt;tr&gt;&lt;th&gt;&lt;i&gt;Shift+&lt;/i&gt;↓&lt;/th&gt;&lt;td&gt;Move down 10%&lt;/td&gt;&lt;/th&gt;
&lt;tr&gt;&lt;th&gt;0&lt;/th&gt;&lt;td&gt;Reset graph to its initial state&lt;/td&gt;&lt;/th&gt;
+&lt;tr&gt;&lt;th&gt;s&lt;/th&gt;&lt;td&gt;Switch direction (swap TCP endpoints)&lt;/td&gt;&lt;/th&gt;
&lt;tr&gt;&lt;th&gt;Space&lt;/th&gt;&lt;td&gt;Toggle crosshairs&lt;/td&gt;&lt;/th&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/body&gt;&lt;/html&gt;</string>
@@ -89,6 +90,16 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QPushButton" name="otherDirectionButton">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Switch the direction of the connection (swap the TCP endpoints).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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
}