Hi Pau,

> If for whatever reason a network interface belonging to a modem is
> renamed after ofono startup, ofono then keeps advertising the old
> non-existing interface name instead of the new one.
> To catch the changes we use udev's "move" action together with
> DEVPATH_OLD variable, which points to the old devpath of the device.
> 
> Unfortunately current debian9 systemd version contains systemd bug which
> prevents this feature to work fine if the iface is renamed more than
> once, see [1] for more information.
> 
> [1] https://github.com/systemd/systemd/issues/9426
> ---
> plugins/udevng.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 83 insertions(+), 1 deletion(-)
> 
> diff --git a/plugins/udevng.c b/plugins/udevng.c
> index c518553a..8338927b 100644
> --- a/plugins/udevng.c
> +++ b/plugins/udevng.c
> @@ -56,6 +56,7 @@ struct modem_info {
>       };
>       struct ofono_modem *modem;
>       const char *sysattr;
> +     gboolean needs_update;
> };
> 
> struct device_info {
> @@ -1630,6 +1631,7 @@ static void add_device(const char *syspath, const char 
> *devname,
> 
>       modem->devices = g_slist_insert_sorted(modem->devices, info,
>                                                       compare_device);
> +     modem->needs_update = TRUE;
> }
> 
> static struct {
> @@ -1822,6 +1824,8 @@ static gboolean create_modem(gpointer key, gpointer 
> value, gpointer user_data)
>       const char *syspath = key;
>       unsigned int i;
> 
> +     modem->needs_update = FALSE;
> +
>       if (modem->modem != NULL)
>               return FALSE;
> 
> @@ -1909,6 +1913,81 @@ static gboolean check_modem_list(gpointer user_data)
>       return FALSE;
> }
> 
> +static void drop_old_device(gpointer key, gpointer value, gpointer user_data)
> +{
> +     const char *syspath = key;
> +     struct modem_info *modem = value;
> +     struct udev_device *device = user_data;
> +     const char *devpath_old;
> +     GSList *list;
> +
> +     devpath_old = udev_device_get_property_value(device, "DEVPATH_OLD");
> +     if (!devpath_old)
> +             return;
> +
> +     for (list = modem->devices; list; list = list->next) {
> +             struct device_info *info = list->data;
> +             struct udev_device *dev;
> +
> +             if (g_strcmp0(info->subsystem, "net") != 0)
> +                     continue;
> +
> +             if (g_strcmp0(info->devpath, devpath_old) != 0)
> +                     continue;
> +
> +             /* Drop no longer existing net iface device */
> +             DBG("Dropping lost device %s", info->devpath);

I really prefer that DBG is surrounded by empty lines.

> +             modem->devices = g_slist_remove_link(modem->devices, list);
> +             g_slist_free_1 (list);

No space between 1 and ( here.

> +             device_info_free(info);
> +             udev_device_unref(dev);
> +             modem->needs_update = TRUE;
> +     }
> +}
> +
> +
> +static void update_modem(gpointer key, gpointer value, gpointer user_data)
> +{
> +     const char *syspath = key;
> +     struct modem_info *modem = value;
> +     unsigned int i;
> +
> +     if (!modem->needs_update)
> +             return;
> +
> +     DBG("Updating modem %s", syspath);
> +
> +     for (i = 0; driver_list[i].name; i++) {
> +             if (g_str_equal(driver_list[i].name, modem->driver) == FALSE)
> +                     continue;
> +             if (driver_list[i].setup(modem) == FALSE)
> +                     continue;
> +     }
> +}
> +static void update_device(struct udev_device *device)
> +{
> +     const char *syspath;
> +
> +     syspath = udev_device_get_syspath(device);
> +     if (syspath == NULL)
> +             return;
> +
> +     DBG("%s", syspath);
> +
> +     /* We only care about net iface renames for now */
> +     if (g_strcmp0(udev_device_get_subsystem(device), "net") != 0)
> +             return;
> +
> +     /* Drop old device from modem */
> +     g_hash_table_foreach(modem_list, drop_old_device, device);
> +
> +     /* Add new device to modem */
> +     check_device(device);
> +
> +     /* Update modified modems */
> +     g_hash_table_foreach(modem_list, update_modem, NULL);
> +}
> +
> static gboolean udev_event(GIOChannel *channel, GIOCondition cond,
>                                                       gpointer user_data)
> {
> @@ -1936,8 +2015,11 @@ static gboolean udev_event(GIOChannel *channel, 
> GIOCondition cond,
>               check_device(device);
> 
>               udev_delay = g_timeout_add_seconds(1, check_modem_list, NULL);
> -     } else if (g_str_equal(action, "remove") == TRUE)
> +     } else if (g_str_equal(action, "remove") == TRUE) {
>               remove_device(device);
> +     } else if (g_str_equal(action, "move") == TRUE) {
> +             update_device(device);
> +     }
> 
>       udev_device_unref(device);

Wouldn’t it generally be better for reading the name after oFono has brought up 
the interface. In case we need this for the D-Bus API somehow. And for sake of 
matching we start and handing this to the plugins and drivers we should start 
using the ifindex.

Regards

Marcel

_______________________________________________
ofono mailing list
[email protected]
https://lists.ofono.org/mailman/listinfo/ofono

Reply via email to