base-bearer: setup periodic stats loading
If the bearer implementation supports it, load stats periodically. By default every 30s for now.
This commit is contained in:
@@ -13,7 +13,8 @@
|
|||||||
* Copyright (C) 2008 - 2009 Novell, Inc.
|
* Copyright (C) 2008 - 2009 Novell, Inc.
|
||||||
* Copyright (C) 2009 - 2011 Red Hat, Inc.
|
* Copyright (C) 2009 - 2011 Red Hat, Inc.
|
||||||
* Copyright (C) 2011 Google, Inc.
|
* Copyright (C) 2011 Google, Inc.
|
||||||
* Copyright (C) 2011 - 2014 Aleksander Morgado <aleksander@aleksander.es>
|
* Copyright (C) 2015 Azimut Electronics
|
||||||
|
* Copyright (C) 2011 - 2015 Aleksander Morgado <aleksander@aleksander.es>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@@ -36,13 +37,16 @@
|
|||||||
#include "mm-base-modem.h"
|
#include "mm-base-modem.h"
|
||||||
#include "mm-log.h"
|
#include "mm-log.h"
|
||||||
#include "mm-modem-helpers.h"
|
#include "mm-modem-helpers.h"
|
||||||
|
#include "mm-bearer-stats.h"
|
||||||
|
|
||||||
/* We require up to 20s to get a proper IP when using PPP */
|
/* We require up to 20s to get a proper IP when using PPP */
|
||||||
#define BEARER_IP_TIMEOUT_DEFAULT 20
|
#define BEARER_IP_TIMEOUT_DEFAULT 20
|
||||||
|
|
||||||
#define BEARER_DEFERRED_UNREGISTRATION_TIMEOUT 15
|
#define BEARER_DEFERRED_UNREGISTRATION_TIMEOUT 15
|
||||||
|
|
||||||
G_DEFINE_TYPE (MMBaseBearer, mm_base_bearer, MM_GDBUS_TYPE_BEARER_SKELETON);
|
#define BEARER_STATS_UPDATE_TIMEOUT 30
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MMBaseBearer, mm_base_bearer, MM_GDBUS_TYPE_BEARER_SKELETON)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CONNECTION_FORBIDDEN_REASON_NONE,
|
CONNECTION_FORBIDDEN_REASON_NONE,
|
||||||
@@ -97,6 +101,13 @@ struct _MMBaseBearerPrivate {
|
|||||||
/* Handler IDs for the registration state change signals */
|
/* Handler IDs for the registration state change signals */
|
||||||
guint id_cdma1x_registration_change;
|
guint id_cdma1x_registration_change;
|
||||||
guint id_evdo_registration_change;
|
guint id_evdo_registration_change;
|
||||||
|
|
||||||
|
/* The stats object to expose */
|
||||||
|
MMBearerStats *stats;
|
||||||
|
/* Handler id for the stats update timeout */
|
||||||
|
guint stats_update_id;
|
||||||
|
/* Timer to measure the duration of the connection */
|
||||||
|
GTimer *duration_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -124,6 +135,102 @@ mm_base_bearer_export (MMBaseBearer *self)
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
bearer_update_interface_stats (MMBaseBearer *self)
|
||||||
|
{
|
||||||
|
mm_gdbus_bearer_set_stats (
|
||||||
|
MM_GDBUS_BEARER (self),
|
||||||
|
mm_bearer_stats_get_dictionary (self->priv->stats));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bearer_reset_interface_stats (MMBaseBearer *self)
|
||||||
|
{
|
||||||
|
g_clear_object (&self->priv->stats);
|
||||||
|
mm_gdbus_bearer_set_stats (MM_GDBUS_BEARER (self), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bearer_stats_stop (MMBaseBearer *self)
|
||||||
|
{
|
||||||
|
if (self->priv->duration_timer) {
|
||||||
|
if (self->priv->stats)
|
||||||
|
mm_bearer_stats_set_duration (self->priv->stats, (guint64) g_timer_elapsed (self->priv->duration_timer, NULL));
|
||||||
|
g_timer_destroy (self->priv->duration_timer);
|
||||||
|
self->priv->duration_timer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->priv->stats_update_id) {
|
||||||
|
g_source_remove (self->priv->stats_update_id);
|
||||||
|
self->priv->stats_update_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reload_stats_ready (MMBaseBearer *self,
|
||||||
|
GAsyncResult *res)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
guint64 rx_bytes = 0;
|
||||||
|
guint64 tx_bytes = 0;
|
||||||
|
|
||||||
|
if (!MM_BASE_BEARER_GET_CLASS (self)->reload_stats_finish (self, &rx_bytes, &tx_bytes, res, &error)) {
|
||||||
|
g_warning ("Reloading stats failed: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We only update stats if they were retrieved properly */
|
||||||
|
mm_bearer_stats_set_duration (self->priv->stats, (guint32) g_timer_elapsed (self->priv->duration_timer, NULL));
|
||||||
|
mm_bearer_stats_set_tx_bytes (self->priv->stats, rx_bytes);
|
||||||
|
mm_bearer_stats_set_rx_bytes (self->priv->stats, tx_bytes);
|
||||||
|
bearer_update_interface_stats (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
stats_update_cb (MMBaseBearer *self)
|
||||||
|
{
|
||||||
|
/* If the implementation knows how to update stat values, run it */
|
||||||
|
if (MM_BASE_BEARER_GET_CLASS (self)->reload_stats &&
|
||||||
|
MM_BASE_BEARER_GET_CLASS (self)->reload_stats_finish) {
|
||||||
|
MM_BASE_BEARER_GET_CLASS (self)->reload_stats (
|
||||||
|
self,
|
||||||
|
(GAsyncReadyCallback)reload_stats_ready,
|
||||||
|
NULL);
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, just update duration and we're done */
|
||||||
|
mm_bearer_stats_set_duration (self->priv->stats, (guint32) g_timer_elapsed (self->priv->duration_timer, NULL));
|
||||||
|
mm_bearer_stats_set_tx_bytes (self->priv->stats, 0);
|
||||||
|
mm_bearer_stats_set_rx_bytes (self->priv->stats, 0);
|
||||||
|
bearer_update_interface_stats (self);
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bearer_stats_start (MMBaseBearer *self)
|
||||||
|
{
|
||||||
|
/* Allocate new stats object. If there was one already created from a
|
||||||
|
* previous run, deallocate it */
|
||||||
|
g_assert (!self->priv->stats);
|
||||||
|
self->priv->stats = mm_bearer_stats_new ();
|
||||||
|
|
||||||
|
/* Start duration timer */
|
||||||
|
g_assert (!self->priv->duration_timer);
|
||||||
|
self->priv->duration_timer = g_timer_new ();
|
||||||
|
|
||||||
|
/* Schedule */
|
||||||
|
g_assert (!self->priv->stats_update_id);
|
||||||
|
self->priv->stats_update_id = g_timeout_add_seconds (BEARER_STATS_UPDATE_TIMEOUT,
|
||||||
|
(GSourceFunc) stats_update_cb,
|
||||||
|
self);
|
||||||
|
/* Load initial values */
|
||||||
|
stats_update_cb (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bearer_reset_interface_status (MMBaseBearer *self)
|
bearer_reset_interface_status (MMBaseBearer *self)
|
||||||
{
|
{
|
||||||
@@ -151,8 +258,11 @@ bearer_update_status (MMBaseBearer *self,
|
|||||||
|
|
||||||
/* Ensure that we don't expose any connection related data in the
|
/* Ensure that we don't expose any connection related data in the
|
||||||
* interface when going into disconnected state. */
|
* interface when going into disconnected state. */
|
||||||
if (self->priv->status == MM_BEARER_STATUS_DISCONNECTED)
|
if (self->priv->status == MM_BEARER_STATUS_DISCONNECTED) {
|
||||||
bearer_reset_interface_status (self);
|
bearer_reset_interface_status (self);
|
||||||
|
/* Stop statistics */
|
||||||
|
bearer_stats_stop (self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -171,6 +281,9 @@ bearer_update_status_connected (MMBaseBearer *self,
|
|||||||
MM_GDBUS_BEARER (self),
|
MM_GDBUS_BEARER (self),
|
||||||
mm_bearer_ip_config_get_dictionary (ipv6_config));
|
mm_bearer_ip_config_get_dictionary (ipv6_config));
|
||||||
|
|
||||||
|
/* Start statistics */
|
||||||
|
bearer_stats_start (self);
|
||||||
|
|
||||||
/* Update the property value */
|
/* Update the property value */
|
||||||
self->priv->status = MM_BEARER_STATUS_CONNECTED;
|
self->priv->status = MM_BEARER_STATUS_CONNECTED;
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATUS]);
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATUS]);
|
||||||
@@ -590,6 +703,7 @@ mm_base_bearer_connect (MMBaseBearer *self,
|
|||||||
mm_dbg ("Connecting bearer '%s'", self->priv->path);
|
mm_dbg ("Connecting bearer '%s'", self->priv->path);
|
||||||
self->priv->connect_cancellable = g_cancellable_new ();
|
self->priv->connect_cancellable = g_cancellable_new ();
|
||||||
bearer_update_status (self, MM_BEARER_STATUS_CONNECTING);
|
bearer_update_status (self, MM_BEARER_STATUS_CONNECTING);
|
||||||
|
bearer_reset_interface_stats (self);
|
||||||
MM_BASE_BEARER_GET_CLASS (self)->connect (
|
MM_BASE_BEARER_GET_CLASS (self)->connect (
|
||||||
self,
|
self,
|
||||||
self->priv->connect_cancellable,
|
self->priv->connect_cancellable,
|
||||||
@@ -1150,6 +1264,9 @@ dispose (GObject *object)
|
|||||||
{
|
{
|
||||||
MMBaseBearer *self = MM_BASE_BEARER (object);
|
MMBaseBearer *self = MM_BASE_BEARER (object);
|
||||||
|
|
||||||
|
bearer_stats_stop (self);
|
||||||
|
g_clear_object (&self->priv->stats);
|
||||||
|
|
||||||
if (self->priv->connection) {
|
if (self->priv->connection) {
|
||||||
base_bearer_dbus_unexport (self);
|
base_bearer_dbus_unexport (self);
|
||||||
g_clear_object (&self->priv->connection);
|
g_clear_object (&self->priv->connection);
|
||||||
|
@@ -10,10 +10,10 @@
|
|||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details:
|
* GNU General Public License for more details:
|
||||||
*
|
*
|
||||||
* Author: Aleksander Morgado <aleksander@lanedo.com>
|
|
||||||
*
|
|
||||||
* Copyright (C) 2011 Google, Inc.
|
* Copyright (C) 2011 Google, Inc.
|
||||||
* Copyright (C) 2011 - 2013 Aleksander Morgado <aleksander@gnu.org>
|
* Copyright (C) 2015 Azimut Electronics
|
||||||
|
* Copyright (C) 2011 - 2015 Aleksander Morgado <aleksander@aleksander.es>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MM_BASE_BEARER_H
|
#ifndef MM_BASE_BEARER_H
|
||||||
@@ -101,6 +101,16 @@ struct _MMBaseBearerClass {
|
|||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
/* Reload statistics */
|
||||||
|
void (* reload_stats) (MMBaseBearer *bearer,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
gboolean (* reload_stats_finish) (MMBaseBearer *bearer,
|
||||||
|
guint64 *bytes_rx,
|
||||||
|
guint64 *bytes_tx,
|
||||||
|
GAsyncResult *res,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
/* Report connection status of this bearer */
|
/* Report connection status of this bearer */
|
||||||
void (* report_connection_status) (MMBaseBearer *bearer,
|
void (* report_connection_status) (MMBaseBearer *bearer,
|
||||||
MMBearerConnectionStatus status);
|
MMBearerConnectionStatus status);
|
||||||
|
Reference in New Issue
Block a user