[gnome-remote-desktop] rdp/nw-auto: Add API to allow lowering or increasing the ping interval



commit 45a47f2c0dfc682ee5b097ff94c977195b29ab07
Author: Pascal Nowack <Pascal Nowack gmx de>
Date:   Sun Jul 18 20:31:17 2021 +0200

    rdp/nw-auto: Add API to allow lowering or increasing the ping interval
    
    When no frame updates happen for some time, but the client window is
    not minimized, gnome-remote-desktop will currently happily still emit
    a lot of RTTRequests, producing unnecessary network activity.
    This usually results in a bandwidth usage of ~2.5KiB/s.
    
    When the graphics pipeline detects that the global encoding rate
    stalled at zero, it should be able to notify the network autodetection
    class about it, so that the network autodetection class can lower the
    ping interval.
    Lowering the ping interval, instead of stopping the detection mechanism
    completely, still allows gnome-remote-desktop to track the current
    round trip time to ensure that the throttling mechanism still has an up
    to date value of the round trip time, when gnome-remote-desktop
    continues to encode frame content.
    When any encoding activity happens again, the graphics pipeline will
    notify the network autodetection class again about the behaviour, to
    increase the ping interval again for a more accurate round trip time.

 src/grd-rdp-network-autodetection.c | 138 ++++++++++++++++++++++++++++++------
 src/grd-rdp-network-autodetection.h |  10 +++
 2 files changed, 126 insertions(+), 22 deletions(-)
---
diff --git a/src/grd-rdp-network-autodetection.c b/src/grd-rdp-network-autodetection.c
index d79dcff..63fa44f 100644
--- a/src/grd-rdp-network-autodetection.c
+++ b/src/grd-rdp-network-autodetection.c
@@ -25,9 +25,16 @@
 #include "grd-rdp-private.h"
 
 #define BW_MEASURE_SEQUENCE_NUMBER 0
-#define PING_INTERVAL_MS 70
+#define PING_INTERVAL_HIGH_MS 70
+#define PING_INTERVAL_LOW_MS 700
 #define RTT_AVG_PERIOD_US (500 * 1000)
 
+typedef enum _PingInterval
+{
+  PING_INTERVAL_HIGH,
+  PING_INTERVAL_LOW,
+} PingInterval;
+
 typedef struct _PingInfo
 {
   uint16_t sequence_number;
@@ -51,6 +58,7 @@ struct _GrdRdpNetworkAutodetection
 
   GMutex consumer_mutex;
   GrdRdpNwAutodetectRTTConsumer rtt_consumers;
+  GrdRdpNwAutodetectRTTConsumer rtt_high_nec_consumers;
 
   GMutex sequence_mutex;
   GHashTable *sequences;
@@ -58,6 +66,7 @@ struct _GrdRdpNetworkAutodetection
   GSource *ping_source;
   GQueue *pings;
   GQueue *round_trip_times;
+  PingInterval ping_interval;
 
   uint16_t next_sequence_number;
 };
@@ -72,6 +81,27 @@ grd_rdp_network_autodetection_invoke_shutdown (GrdRdpNetworkAutodetection *netwo
   g_mutex_unlock (&network_autodetection->shutdown_mutex);
 }
 
+static gboolean
+has_rtt_consumer (GrdRdpNetworkAutodetection    *network_autodetection,
+                  GrdRdpNwAutodetectRTTConsumer  rtt_consumer)
+{
+  g_assert (!g_mutex_trylock (&network_autodetection->consumer_mutex));
+
+  return !!(network_autodetection->rtt_consumers & rtt_consumer);
+}
+
+static gboolean
+is_active_high_nec_rtt_consumer (GrdRdpNetworkAutodetection    *network_autodetection,
+                                 GrdRdpNwAutodetectRTTConsumer  rtt_consumer)
+{
+  if (!has_rtt_consumer (network_autodetection, rtt_consumer))
+    return FALSE;
+  if (network_autodetection->rtt_high_nec_consumers & rtt_consumer)
+    return TRUE;
+
+  return FALSE;
+}
+
 static uint16_t
 get_next_free_sequence_number (GrdRdpNetworkAutodetection *network_autodetection)
 {
@@ -111,6 +141,53 @@ emit_ping (gpointer user_data)
   return G_SOURCE_CONTINUE;
 }
 
+static void
+update_ping_source (GrdRdpNetworkAutodetection *network_autodetection)
+{
+  GrdRdpNwAutodetectRTTConsumer active_high_nec_rtt_consumers;
+  PingInterval new_ping_interval_type;
+  uint32_t ping_interval_ms;
+
+  active_high_nec_rtt_consumers = GRD_RDP_NW_AUTODETECT_RTT_CONSUMER_NONE;
+  if (is_active_high_nec_rtt_consumer (
+        network_autodetection, GRD_RDP_NW_AUTODETECT_RTT_CONSUMER_RDPGFX))
+    active_high_nec_rtt_consumers |= GRD_RDP_NW_AUTODETECT_RTT_CONSUMER_RDPGFX;
+
+  if (active_high_nec_rtt_consumers)
+    new_ping_interval_type = PING_INTERVAL_HIGH;
+  else
+    new_ping_interval_type = PING_INTERVAL_LOW;
+
+  if ((network_autodetection->rtt_consumers == GRD_RDP_NW_AUTODETECT_RTT_CONSUMER_NONE ||
+       network_autodetection->ping_interval != new_ping_interval_type) &&
+      network_autodetection->ping_source)
+    {
+      g_source_destroy (network_autodetection->ping_source);
+      g_clear_pointer (&network_autodetection->ping_source, g_source_unref);
+    }
+
+  if (network_autodetection->rtt_consumers == GRD_RDP_NW_AUTODETECT_RTT_CONSUMER_NONE)
+    return;
+
+  emit_ping (network_autodetection);
+
+  switch (new_ping_interval_type)
+    {
+    case PING_INTERVAL_HIGH:
+      ping_interval_ms = PING_INTERVAL_HIGH_MS;
+      break;
+    case PING_INTERVAL_LOW:
+      ping_interval_ms = PING_INTERVAL_LOW_MS;
+      break;
+    }
+
+  network_autodetection->ping_source = g_timeout_source_new (ping_interval_ms);
+  g_source_set_callback (network_autodetection->ping_source, emit_ping,
+                         network_autodetection, NULL);
+  g_source_attach (network_autodetection->ping_source, NULL);
+  network_autodetection->ping_interval = new_ping_interval_type;
+}
+
 void
 grd_rdp_network_autodetection_ensure_rtt_consumer (GrdRdpNetworkAutodetection    *network_autodetection,
                                                    GrdRdpNwAutodetectRTTConsumer  rtt_consumer)
@@ -118,17 +195,10 @@ grd_rdp_network_autodetection_ensure_rtt_consumer (GrdRdpNetworkAutodetection
   g_assert (rtt_consumer != GRD_RDP_NW_AUTODETECT_RTT_CONSUMER_NONE);
 
   g_mutex_lock (&network_autodetection->consumer_mutex);
-  network_autodetection->rtt_consumers |= rtt_consumer;
+  if (!has_rtt_consumer (network_autodetection, rtt_consumer))
+    network_autodetection->rtt_consumers |= rtt_consumer;
 
-  if (!network_autodetection->ping_source)
-    {
-      emit_ping (network_autodetection);
-
-      network_autodetection->ping_source = g_timeout_source_new (PING_INTERVAL_MS);
-      g_source_set_callback (network_autodetection->ping_source, emit_ping,
-                             network_autodetection, NULL);
-      g_source_attach (network_autodetection->ping_source, NULL);
-    }
+  update_ping_source (network_autodetection);
   g_mutex_unlock (&network_autodetection->consumer_mutex);
 }
 
@@ -139,22 +209,46 @@ grd_rdp_network_autodetection_remove_rtt_consumer (GrdRdpNetworkAutodetection
   g_mutex_lock (&network_autodetection->consumer_mutex);
   network_autodetection->rtt_consumers &= ~rtt_consumer;
 
-  if (network_autodetection->rtt_consumers == GRD_RDP_NW_AUTODETECT_RTT_CONSUMER_NONE &&
-      network_autodetection->ping_source)
-    {
-      g_source_destroy (network_autodetection->ping_source);
-      g_clear_pointer (&network_autodetection->ping_source, g_source_unref);
-    }
+  update_ping_source (network_autodetection);
   g_mutex_unlock (&network_autodetection->consumer_mutex);
 }
 
-static gboolean
-has_rtt_consumer (GrdRdpNetworkAutodetection    *network_autodetection,
-                  GrdRdpNwAutodetectRTTConsumer  rtt_consumer)
+void
+grd_rdp_network_autodetection_set_rtt_consumer_necessity (GrdRdpNetworkAutodetection     
*network_autodetection,
+                                                          GrdRdpNwAutodetectRTTConsumer   rtt_consumer,
+                                                          GrdRdpNwAutodetectRTTNecessity  rtt_necessity)
 {
-  g_assert (!g_mutex_trylock (&network_autodetection->consumer_mutex));
+  GrdRdpNwAutodetectRTTNecessity current_rtt_necessity;
 
-  return !!(network_autodetection->rtt_consumers & rtt_consumer);
+  g_assert (rtt_consumer != GRD_RDP_NW_AUTODETECT_RTT_CONSUMER_NONE);
+  g_assert (rtt_necessity == GRD_RDP_NW_AUTODETECT_RTT_NEC_HIGH ||
+            rtt_necessity == GRD_RDP_NW_AUTODETECT_RTT_NEC_LOW);
+
+  g_mutex_lock (&network_autodetection->consumer_mutex);
+  if (network_autodetection->rtt_high_nec_consumers & rtt_consumer)
+    current_rtt_necessity = GRD_RDP_NW_AUTODETECT_RTT_NEC_HIGH;
+  else
+    current_rtt_necessity = GRD_RDP_NW_AUTODETECT_RTT_NEC_LOW;
+
+  if (current_rtt_necessity == rtt_necessity)
+    {
+      g_mutex_unlock (&network_autodetection->consumer_mutex);
+      return;
+    }
+
+  switch (rtt_necessity)
+    {
+    case GRD_RDP_NW_AUTODETECT_RTT_NEC_HIGH:
+      network_autodetection->rtt_high_nec_consumers |= rtt_consumer;
+      break;
+    case GRD_RDP_NW_AUTODETECT_RTT_NEC_LOW:
+      network_autodetection->rtt_high_nec_consumers &= ~rtt_consumer;
+      break;
+    }
+
+  if (has_rtt_consumer (network_autodetection, rtt_consumer))
+    update_ping_source (network_autodetection);
+  g_mutex_unlock (&network_autodetection->consumer_mutex);
 }
 
 static void
diff --git a/src/grd-rdp-network-autodetection.h b/src/grd-rdp-network-autodetection.h
index 73d1ad8..8d34963 100644
--- a/src/grd-rdp-network-autodetection.h
+++ b/src/grd-rdp-network-autodetection.h
@@ -33,6 +33,12 @@ typedef enum _GrdRdpNwAutodetectRTTConsumer
   GRD_RDP_NW_AUTODETECT_RTT_CONSUMER_RDPGFX = 1 << 0,
 } GrdRdpNwAutodetectRTTConsumer;
 
+typedef enum _GrdRdpNwAutodetectRTTNecessity
+{
+  GRD_RDP_NW_AUTODETECT_RTT_NEC_HIGH,
+  GRD_RDP_NW_AUTODETECT_RTT_NEC_LOW,
+} GrdRdpNwAutodetectRTTNecessity;
+
 GrdRdpNetworkAutodetection *grd_rdp_network_autodetection_new (rdpContext *rdp_context);
 
 void grd_rdp_network_autodetection_invoke_shutdown (GrdRdpNetworkAutodetection *network_autodetection);
@@ -43,4 +49,8 @@ void grd_rdp_network_autodetection_ensure_rtt_consumer (GrdRdpNetworkAutodetecti
 void grd_rdp_network_autodetection_remove_rtt_consumer (GrdRdpNetworkAutodetection    *network_autodetection,
                                                         GrdRdpNwAutodetectRTTConsumer  rtt_consumer);
 
+void grd_rdp_network_autodetection_set_rtt_consumer_necessity (GrdRdpNetworkAutodetection     
*network_autodetection,
+                                                               GrdRdpNwAutodetectRTTConsumer   rtt_consumer,
+                                                               GrdRdpNwAutodetectRTTNecessity  
rtt_necessity);
+
 #endif /* GRD_RDP_NETWORK_AUTODETECTION_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]