aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksandermj@chromium.org>2024-02-14 11:49:01 +0000
committerAleksander Morgado <aleksandermj@chromium.org>2024-02-15 21:06:59 +0000
commitb313a603aa0eb9ad2d3315aee2762cbb4eb25651 (patch)
tree38bce22c45b2a02d183ad5ca39f423ff48b141a5 /src
parent2f306e8e7c830d7991b747b127533c7db73754fd (diff)
mtk: remove IP packet filters during connection in FM350 < 29.23.06
Old firmware versions of the FM350 had some internal IP packet filters installed, which prevented proper IPv6 connectivity in certain cases. This workaround ensures that the IP packet filters get removed whenever a data connection is up. Because we don't know when exactly the filters get installed, we do this removal periodically along with the bearer stats query.
Diffstat (limited to 'src')
-rw-r--r--src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.c184
-rw-r--r--src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.h3
-rw-r--r--src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c15
3 files changed, 193 insertions, 9 deletions
diff --git a/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.c b/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.c
index 1effc603..71957a07 100644
--- a/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.c
+++ b/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.c
@@ -19,40 +19,208 @@
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
+#include "mm-log-object.h"
#include "mm-bearer-mbim-mtk-fibocom.h"
G_DEFINE_TYPE (MMBearerMbimMtkFibocom, mm_bearer_mbim_mtk_fibocom, MM_TYPE_BEARER_MBIM)
+struct _MMBearerMbimMtkFibocomPrivate {
+ /* Whether IP packet filters need to be removed */
+ gboolean remove_ip_packet_filters;
+ gboolean reload_stats_unsupported;
+};
+
+/*****************************************************************************/
+/* Stats */
+
+typedef struct {
+ guint64 rx_bytes;
+ guint64 tx_bytes;
+} ReloadStatsResult;
+
+static gboolean
+reload_stats_finish (MMBaseBearer *_self,
+ guint64 *rx_bytes,
+ guint64 *tx_bytes,
+ GAsyncResult *res,
+ GError **error)
+{
+ MMBearerMbimMtkFibocom *self = MM_BEARER_MBIM_MTK_FIBOCOM (_self);
+ g_autofree ReloadStatsResult *stats = NULL;
+ g_autoptr(GError) inner_error = NULL;
+
+ stats = g_task_propagate_pointer (G_TASK (res), &inner_error);
+ if (!stats) {
+ /* If filters need to be removed on every stats query, we must never
+ * return an error, otherwise the upper layers will stop the stats reloading
+ * logic. Only return an error when filters are not being removed. */
+ if (!self->priv->remove_ip_packet_filters) {
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+ /* Flag as stats reloading being unsupported, we will avoid querying. */
+ self->priv->reload_stats_unsupported = TRUE;
+ }
+
+ if (rx_bytes)
+ *rx_bytes = stats ? stats->rx_bytes : 0;
+ if (tx_bytes)
+ *tx_bytes = stats ? stats->tx_bytes : 0;
+ return TRUE;
+}
+
+static void
+parent_reload_stats_ready (MMBaseBearer *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ g_autofree ReloadStatsResult *stats = NULL;
+ GError *error = NULL;
+
+ stats = g_new0 (ReloadStatsResult, 1);
+
+ if (!MM_BASE_BEARER_CLASS (mm_bearer_mbim_mtk_fibocom_parent_class)->reload_stats_finish (
+ self,
+ &stats->rx_bytes,
+ &stats->tx_bytes,
+ res,
+ &error))
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_pointer (task, g_steal_pointer (&stats), g_free);
+ g_object_unref (task);
+}
+
+static void
+packet_statistics_query (GTask *task)
+{
+ MMBearerMbimMtkFibocom *self;
+
+ self = g_task_get_source_object (task);
+ if (self->priv->reload_stats_unsupported) {
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Skipping stats reloading");
+ g_object_unref (task);
+ return;
+ }
+
+ /* Chain up parent's stats query */
+ MM_BASE_BEARER_CLASS (mm_bearer_mbim_mtk_fibocom_parent_class)->reload_stats (
+ MM_BASE_BEARER (self),
+ (GAsyncReadyCallback) parent_reload_stats_ready,
+ task);
+}
+
+static void
+packet_filters_set_ready (MbimDevice *device,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMBearerMbim *self;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(MbimMessage) response = NULL;
+
+ self = g_task_get_source_object (task);
+
+ response = mbim_device_command_finish (device, res, &error);
+ if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error))
+ mm_obj_dbg (self, "Couldn't reset IP packet filters: %s", error->message);
+
+ packet_statistics_query (task);
+}
+
+static void
+ensure_removed_filters (GTask *task)
+{
+ MMBearerMbimMtkFibocom *self;
+ MMPortMbim *port;
+ g_autoptr(MbimMessage) message = NULL;
+ g_autoptr(MMBaseModem) modem = NULL;
+ guint32 session_id;
+
+ self = g_task_get_source_object (task);
+
+ g_object_get (self,
+ MM_BASE_BEARER_MODEM, &modem,
+ NULL);
+ port = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (modem));
+ if (!port) {
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Couldn't peek MBIM port");
+ g_object_unref (task);
+ return;
+ }
+
+ mm_obj_dbg (self, "Resetting IP packet filters...");
+
+ session_id = mm_bearer_mbim_get_session_id (MM_BEARER_MBIM (self));
+ message = mbim_message_ip_packet_filters_set_new (session_id, 0, NULL, NULL);
+ mbim_device_command (mm_port_mbim_peek_device (port),
+ message,
+ 5,
+ NULL,
+ (GAsyncReadyCallback)packet_filters_set_ready,
+ task);
+}
+
+static void
+reload_stats (MMBaseBearer *_self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBearerMbimMtkFibocom *self = MM_BEARER_MBIM_MTK_FIBOCOM (_self);
+ GTask *task;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ if (self->priv->remove_ip_packet_filters)
+ ensure_removed_filters (task);
+ else
+ packet_statistics_query (task);
+}
+
/*****************************************************************************/
MMBaseBearer *
mm_bearer_mbim_mtk_fibocom_new (MMBroadbandModemMbim *modem,
gboolean is_async_slaac_supported,
+ gboolean remove_ip_packet_filters,
MMBearerProperties *config)
{
- MMBaseBearer *bearer;
+ MMBearerMbimMtkFibocom *self;
/* The Mbim bearer inherits from MMBaseBearer (so it's not a MMBroadbandBearer)
* and that means that the object is not async-initable, so we just use
* g_object_new() here */
- bearer = g_object_new (MM_TYPE_BEARER_MBIM_MTK_FIBOCOM,
- MM_BASE_BEARER_MODEM, modem,
- MM_BASE_BEARER_CONFIG, config,
- MM_BEARER_MBIM_ASYNC_SLAAC, is_async_slaac_supported,
- NULL);
+ self = g_object_new (MM_TYPE_BEARER_MBIM_MTK_FIBOCOM,
+ MM_BASE_BEARER_MODEM, modem,
+ MM_BASE_BEARER_CONFIG, config,
+ MM_BEARER_MBIM_ASYNC_SLAAC, is_async_slaac_supported,
+ NULL);
+
+ self->priv->remove_ip_packet_filters = remove_ip_packet_filters;
/* Only export valid bearers */
- mm_base_bearer_export (bearer);
+ mm_base_bearer_export (MM_BASE_BEARER (self));
- return bearer;
+ return MM_BASE_BEARER (self);
}
static void
mm_bearer_mbim_mtk_fibocom_init (MMBearerMbimMtkFibocom *self)
{
+ /* Initialize private data */
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_BEARER_MBIM_MTK_FIBOCOM, MMBearerMbimMtkFibocomPrivate);
}
static void
mm_bearer_mbim_mtk_fibocom_class_init (MMBearerMbimMtkFibocomClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMBearerMbimMtkFibocomPrivate));
+
+ base_bearer_class->reload_stats = reload_stats;
+ base_bearer_class->reload_stats_finish = reload_stats_finish;
}
diff --git a/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.h b/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.h
index 736d3fc9..7e093a52 100644
--- a/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.h
+++ b/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.h
@@ -33,9 +33,11 @@
typedef struct _MMBearerMbimMtkFibocom MMBearerMbimMtkFibocom;
typedef struct _MMBearerMbimMtkFibocomClass MMBearerMbimMtkFibocomClass;
+typedef struct _MMBearerMbimMtkFibocomPrivate MMBearerMbimMtkFibocomPrivate;
struct _MMBearerMbimMtkFibocom {
MMBearerMbim parent;
+ MMBearerMbimMtkFibocomPrivate *priv;
};
struct _MMBearerMbimMtkFibocomClass {
@@ -48,6 +50,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBearerMbimMtkFibocom, g_object_unref)
/* MBIM bearer creation implementation */
MMBaseBearer *mm_bearer_mbim_mtk_fibocom_new (MMBroadbandModemMbim *modem,
gboolean is_async_slaac_supported,
+ gboolean remove_ip_packet_filters,
MMBearerProperties *config);
#endif /* MM_BEARER_MBIM_MTK_FIBOCOM_H */
diff --git a/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c b/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c
index cfcd3616..7ef97b64 100644
--- a/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c
+++ b/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c
@@ -42,9 +42,10 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimMtkFibocom, mm_broadband_modem_mbim_
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_FIBOCOM, shared_fibocom_init))
struct _MMBroadbandModemMbimMtkFibocomPrivate {
- /* Supported features */
+ /* Custom MTK/Fibocom bearer behavior */
gboolean is_multiplex_supported;
gboolean is_async_slaac_supported;
+ gboolean remove_ip_packet_filters;
};
/*****************************************************************************/
@@ -58,6 +59,9 @@ struct _MMBroadbandModemMbimMtkFibocomPrivate {
* versions. */
#define MULTIPLEX_SUPPORTED_VERSION 29, 23, 6
+/* Explicit IP packet filter removal required in old firmware versions. */
+#define IP_PACKET_FILTER_REMOVAL_UNNEEDED_VERSION 29, 23, 6
+
static inline gboolean
fm350_check_version (guint A1, guint A2, guint A3,
guint B1, guint B2, guint B3)
@@ -102,6 +106,11 @@ process_fm350_version_features (MMBroadbandModemMbimMtkFibocom *self,
self->priv->is_multiplex_supported = fm350_check_version (major, minor, micro, MULTIPLEX_SUPPORTED_VERSION);
mm_obj_info (self, "FM350 multiplexing is %ssupported",
self->priv->is_multiplex_supported ? "" : "not ");
+
+ /* Check if we need to remove IP packet filters */
+ self->priv->remove_ip_packet_filters = !fm350_check_version (major, minor, micro, IP_PACKET_FILTER_REMOVAL_UNNEEDED_VERSION);
+ mm_obj_info (self, "FM350 %s IP packet filter removal",
+ self->priv->remove_ip_packet_filters ? "requires" : "does not require");
}
/*****************************************************************************/
@@ -171,6 +180,7 @@ create_bearer (MMIfaceModem *_self,
self->priv->is_async_slaac_supported ? "supported" : "unsupported");
bearer = mm_bearer_mbim_mtk_fibocom_new (MM_BROADBAND_MODEM_MBIM (self),
self->priv->is_async_slaac_supported,
+ self->priv->remove_ip_packet_filters,
properties);
g_task_return_pointer (task, bearer, g_object_unref);
g_object_unref (task);
@@ -230,6 +240,9 @@ mm_broadband_modem_mbim_mtk_fibocom_init (MMBroadbandModemMbimMtkFibocom *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
MM_TYPE_BROADBAND_MODEM_MBIM_MTK_FIBOCOM,
MMBroadbandModemMbimMtkFibocomPrivate);
+
+ /* By default remove, unless we have a new enough version */
+ self->priv->remove_ip_packet_filters = TRUE;
}
static void