summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2016-02-25 09:09:27 +0000
committerFrediano Ziglio <freddy77@gmail.com>2023-11-22 07:39:16 +0000
commit4683eaf98096a220e89e1154ddc153bce94293a7 (patch)
tree059f5baaf513e5b51deeef6b7ff0139074dc46d4
parentdbfebc419780f43e00a18f82cde6359abccb35f8 (diff)
try do detect bandwidthstream_bug_francois
-rw-r--r--server/Makefile.am2
-rw-r--r--server/bw-stats.c82
-rw-r--r--server/bw-stats.h38
-rw-r--r--server/meson.build2
-rw-r--r--server/red-stream.cpp16
5 files changed, 139 insertions, 1 deletions
diff --git a/server/Makefile.am b/server/Makefile.am
index 5260051b..57c30f4d 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -88,6 +88,8 @@ libserver_la_SOURCES = \
$(spice_built_sources) \
agent-msg-filter.c \
agent-msg-filter.h \
+ bw-stats.c \
+ bw-stats.h \
cache-item.h \
char-device.cpp \
char-device.h \
diff --git a/server/bw-stats.c b/server/bw-stats.c
new file mode 100644
index 00000000..f72a3287
--- /dev/null
+++ b/server/bw-stats.c
@@ -0,0 +1,82 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2016 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_LINUX_SOCKIOS_H
+#include <linux/sockios.h> /* SIOCOUTQ */
+#endif
+
+#include "bw-stats.h"
+
+void bandwidth_stats_init(BandwidthStatistics *stat)
+{
+ stat->first_time_valid = stat->last_time_valid = 0;
+}
+
+void bandwidth_stats_destroy(BandwidthStatistics *stat)
+{
+}
+
+void bandwidth_stats_update(BandwidthStatistics *stat, int socket, size_t size)
+{
+ /* try to understand if we buffer was full */
+#ifdef HAVE_LINUX_SOCKIOS_H /* SIOCOUTQ is a Linux only ioctl on sockets. */
+ int so_unsent_size = 0;
+
+/*
+sent queued unsent total sent
+0 0 0 0
+100 100 0 0
+100 200 100 0
+-100 300 200 0
+100 150 50 150 = prev total + prev queued + bytes - queued
+100 150 50 = 150 + 150 + 100 - 150
+*/
+
+ /* retrieving the occupied size of the socket's tcp snd buffer (unacked + unsent) */
+ if (ioctl(socket, SIOCOUTQ, &so_unsent_size) == -1 || so_unsent_size <= size) {
+ /* TODO see if data was enough */
+ stat->first_time_valid = stat->last_time_valid = 0;
+ return;
+ }
+
+ red_time_t curr_time = spice_get_monotonic_time_ns();
+
+ /* if this the first valid data ? */
+ if (!stat->first_time_valid) {
+ stat->first_time_valid = stat->last_time_valid = curr_time;
+ stat->total_bytes = 0;
+ stat->prev_unsent = so_unsent_size;
+ return;
+ }
+
+ /* add this reading */
+ stat->last_time_valid = curr_time;
+ stat->total_bytes += stat->prev_unsent + size - so_unsent_size;
+ stat->prev_unsent = so_unsent_size;
+return;
+ printf("%zu / %" PRIu64 " %g\n",
+ stat->total_bytes, stat->last_time_valid - stat->first_time_valid,
+ stat->total_bytes * 1000000000.0 / (stat->last_time_valid - stat->first_time_valid));
+#endif
+}
diff --git a/server/bw-stats.h b/server/bw-stats.h
new file mode 100644
index 00000000..8be690fc
--- /dev/null
+++ b/server/bw-stats.h
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 2016 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BW_STATS_H_
+#define BW_STATS_H_
+
+#include "utils.h"
+
+SPICE_BEGIN_DECLS
+
+typedef struct BandwidthStatistics {
+ red_time_t first_time_valid, last_time_valid;
+ size_t prev_unsent, total_bytes;
+} BandwidthStatistics;
+
+/* initialize structure to hold bandwidth computation */
+void bandwidth_stats_init(BandwidthStatistics *stat);
+void bandwidth_stats_destroy(BandwidthStatistics *stat);
+/* update bandwidth statistics */
+void bandwidth_stats_update(BandwidthStatistics *stat, int socket, size_t size);
+
+SPICE_END_DECLS
+
+#endif /* BW_STATS_H_ */
diff --git a/server/meson.build b/server/meson.build
index a8da777f..3f1c67f7 100644
--- a/server/meson.build
+++ b/server/meson.build
@@ -69,6 +69,8 @@ spice_server_sources = [
spice_server_enums,
'agent-msg-filter.c',
'agent-msg-filter.h',
+ 'bw-stats.c',
+ 'bw-stats.h',
'cache-item.h',
'char-device.cpp',
'char-device.h',
diff --git a/server/red-stream.cpp b/server/red-stream.cpp
index 89222702..ede3dd48 100644
--- a/server/red-stream.cpp
+++ b/server/red-stream.cpp
@@ -42,6 +42,7 @@
#include "red-stream.h"
#include "reds.h"
#include "websocket.h"
+#include "bw-stats.h"
// compatibility for *BSD systems
#if !defined(TCP_CORK) && !defined(_WIN32)
@@ -102,6 +103,8 @@ struct RedStreamPrivate {
ssize_t (*write)(RedStream *s, const void *buf, size_t nbyte);
ssize_t (*writev)(RedStream *s, const struct iovec *iov, int iovcnt);
+ BandwidthStatistics bw_stat;
+
RedsState *reds;
SpiceCoreInterfaceInternal *core;
};
@@ -123,9 +126,19 @@ static inline int socket_set_cork(int socket, int enabled)
}
#endif
+/* update bandwidth statistics
+ */
+static void stream_bandwidth_compute_update(RedStream *s, ssize_t size)
+{
+ if (size > 0)
+ bandwidth_stats_update(&s->priv->bw_stat, s->socket, size);
+}
+
static ssize_t stream_write_cb(RedStream *s, const void *buf, size_t size)
{
- return socket_write(s->socket, buf, size);
+ ssize_t ret = socket_write(s->socket, buf, size);
+ stream_bandwidth_compute_update(s, ret);
+ return ret;
}
static ssize_t stream_writev_cb(RedStream *s, const struct iovec *iov, int iovcnt)
@@ -144,6 +157,7 @@ static ssize_t stream_writev_cb(RedStream *s, const struct iovec *iov, int iovcn
expected += iov[i].iov_len;
}
n = socket_writev(s->socket, iov, tosend);
+ stream_bandwidth_compute_update(s, n);
if (n <= expected) {
if (n > 0)
ret += n;