nettimeprovider: Add possibility to set QoS DSCP value
authorRobert Rosengren <robertr@axis.com>
Thu, 1 Jun 2017 13:48:16 +0000 (15:48 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Thu, 19 Oct 2017 14:14:17 +0000 (16:14 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=784737

libs/gst/net/gstnettimeprovider.c

index f8e0308..824e43d 100644 (file)
 #include "config.h"
 #endif
 
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifndef G_OS_WIN32
+#include <netinet/in.h>
+#endif
+
 #include "gstnettimeprovider.h"
 #include "gstnettimepacket.h"
 
@@ -46,6 +54,7 @@ GST_DEBUG_CATEGORY_STATIC (ntp_debug);
 
 #define DEFAULT_ADDRESS         "0.0.0.0"
 #define DEFAULT_PORT            5637
+#define DEFAULT_QOS_DSCP        -1
 
 #define IS_ACTIVE(self) (g_atomic_int_get (&((self)->priv->active)))
 
@@ -55,7 +64,8 @@ enum
   PROP_PORT,
   PROP_ADDRESS,
   PROP_CLOCK,
-  PROP_ACTIVE
+  PROP_ACTIVE,
+  PROP_QOS_DSCP
 };
 
 #define GST_NET_TIME_PROVIDER_GET_PRIVATE(obj)  \
@@ -65,6 +75,7 @@ struct _GstNetTimeProviderPrivate
 {
   gchar *address;
   int port;
+  gint qos_dscp;                /* ATOMIC */
 
   GThread *thread;
 
@@ -131,6 +142,11 @@ gst_net_time_provider_class_init (GstNetTimeProviderClass * klass)
       g_param_spec_boolean ("active", "Active",
           "TRUE if the clock will respond to queries over the network", TRUE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_QOS_DSCP,
+      g_param_spec_int ("qos-dscp", "QoS diff srv code point",
+          "Quality of Service, differentiated services code point (-1 default)",
+          -1, 63, DEFAULT_QOS_DSCP,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -140,6 +156,7 @@ gst_net_time_provider_init (GstNetTimeProvider * self)
 
   self->priv->port = DEFAULT_PORT;
   self->priv->address = g_strdup (DEFAULT_ADDRESS);
+  self->priv->qos_dscp = DEFAULT_QOS_DSCP;
   self->priv->thread = NULL;
   self->priv->active = TRUE;
 }
@@ -172,12 +189,15 @@ gst_net_time_provider_thread (gpointer data)
   GSocket *socket = self->priv->socket;
   GstNetTimePacket *packet;
   GError *err = NULL;
+  gint cur_qos_dscp = DEFAULT_QOS_DSCP;
+  gint new_qos_dscp;
 
   GST_INFO_OBJECT (self, "time provider thread is running");
 
   while (TRUE) {
     GSocketAddress *sender_addr = NULL;
 
+
     GST_LOG_OBJECT (self, "waiting on socket");
     if (!g_socket_condition_wait (socket, G_IO_IN, cancel, &err)) {
       GST_INFO_OBJECT (self, "socket error: %s", err->message);
@@ -203,6 +223,23 @@ gst_net_time_provider_thread (gpointer data)
       continue;
     }
 
+    /* before next sending check if need to change QoS */
+    new_qos_dscp = self->priv->qos_dscp;
+    if (cur_qos_dscp != new_qos_dscp) {
+      gint tos, fd;
+      fd = g_socket_get_fd (socket);
+
+      /* Extract and shift 6 bits of DSFIELD */
+      tos = (new_qos_dscp & 0x3f) << 2;
+
+      if (setsockopt (fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) {
+        GST_ERROR_OBJECT (self, "could not set TOS: %s", g_strerror (errno));
+      }
+
+      GST_DEBUG_OBJECT (self, "changed QoS DSCP to: %d", new_qos_dscp);
+      cur_qos_dscp = new_qos_dscp;
+    }
+
     if (IS_ACTIVE (self)) {
       /* do what we were asked to and send the packet back */
       packet->remote_time = gst_clock_get_time (self->priv->clock);
@@ -245,6 +282,9 @@ gst_net_time_provider_set_property (GObject * object, guint prop_id,
     case PROP_ACTIVE:
       g_atomic_int_set (&self->priv->active, g_value_get_boolean (value));
       break;
+    case PROP_QOS_DSCP:
+      g_atomic_int_set (&self->priv->qos_dscp, g_value_get_int (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -270,6 +310,9 @@ gst_net_time_provider_get_property (GObject * object, guint prop_id,
     case PROP_ACTIVE:
       g_value_set_boolean (value, IS_ACTIVE (self));
       break;
+    case PROP_QOS_DSCP:
+      g_value_set_int (value, self->priv->qos_dscp);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;