mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-05 15:00:25 +01:00
core: add device factory infrastructure and make WiMAX a plugin
This allows us to package WiMAX separately so you can choose to install WiMAX or not. For package-based distros you can now install libnm-device-plugin-wimax.so in a separate package that links to/requires the Intel WiMAX service instead of having the main NM package require it and pull it in by default. This plugin infrastructure will be extended to other device types as well.
This commit is contained in:
parent
21fab21ec0
commit
2099459794
5 changed files with 316 additions and 40 deletions
|
|
@ -36,10 +36,6 @@ INCLUDES = -I${top_srcdir} \
|
|||
-I${top_srcdir}/libnm-util \
|
||||
-I${top_srcdir}/callouts
|
||||
|
||||
if WITH_WIMAX
|
||||
INCLUDES += -I$(top_srcdir)/src/wimax
|
||||
endif
|
||||
|
||||
###########################################
|
||||
# Test libraries
|
||||
###########################################
|
||||
|
|
@ -146,6 +142,7 @@ NetworkManager_SOURCES = \
|
|||
nm-dbus-manager.c \
|
||||
nm-udev-manager.c \
|
||||
nm-udev-manager.h \
|
||||
nm-device-factory.h \
|
||||
nm-hostname-provider.c \
|
||||
nm-hostname-provider.h \
|
||||
nm-ip4-config.c \
|
||||
|
|
@ -265,14 +262,9 @@ NetworkManager_CPPFLAGS = \
|
|||
-DLOCALSTATEDIR=\"$(localstatedir)\" \
|
||||
-DNM_RUN_DIR=\"$(rundir)\" \
|
||||
-DNMLOCALEDIR=\"$(datadir)/locale\" \
|
||||
-DNMPLUGINDIR=\"$(pkglibdir)\"
|
||||
-DARP_DEBUG
|
||||
|
||||
|
||||
WIMAX_LIBS=
|
||||
if WITH_WIMAX
|
||||
WIMAX_LIBS += ./wimax/libwimax.la
|
||||
endif
|
||||
|
||||
NetworkManager_LDADD = \
|
||||
$(top_builddir)/marshallers/libmarshallers.la \
|
||||
./logging/libnm-logging.la \
|
||||
|
|
@ -287,7 +279,6 @@ NetworkManager_LDADD = \
|
|||
./bluez-manager/libbluez-manager.la \
|
||||
./firewall-manager/libfirewall-manager.la \
|
||||
./settings/libsettings.la \
|
||||
$(WIMAX_LIBS) \
|
||||
./backends/libnmbackend.la \
|
||||
$(top_builddir)/libnm-util/libnm-util.la \
|
||||
$(DBUS_LIBS) \
|
||||
|
|
|
|||
91
src/nm-device-factory.h
Normal file
91
src/nm-device-factory.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2007 - 2011 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef NM_DEVICE_FACTORY_H
|
||||
#define NM_DEVICE_FACTORY_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
#include "NetworkManager.h"
|
||||
|
||||
/* WARNING: this file is private API between NetworkManager and its internal
|
||||
* device plugins. Its API can change at any time and is not guaranteed to be
|
||||
* stable. NM and device plugins are distributed together and this API is
|
||||
* not meant to enable third-party plugins.
|
||||
*/
|
||||
|
||||
/**
|
||||
* nm_device_factory_create_device:
|
||||
* @device: GUdev device object representing the device
|
||||
* @devpath: sysfs path of the device
|
||||
* @ifname: interface name of the device
|
||||
* @driver: driver of the device
|
||||
* @error: error for failure information
|
||||
*
|
||||
* Creates a #NMDevice subclass if the given information represents a device
|
||||
* the factory is capable of creating. If the information does represent a
|
||||
* device the factory is capable of creating, but the device could not be
|
||||
* created, %NULL should be returned and @error should be set. If the
|
||||
* factory is not capable of creating a device with the given information
|
||||
* (ie, the factory creates Ethernet devices but the information represents
|
||||
* a WiFi device) it should return %NULL and leave @error untouched.
|
||||
*
|
||||
* Returns: the device object (a subclass of #NMDevice) or %NULL
|
||||
*/
|
||||
GObject *nm_device_factory_create_device (GUdevDevice *device,
|
||||
const char *devpath,
|
||||
const char *ifname,
|
||||
const char *driver,
|
||||
GError **error);
|
||||
|
||||
/* Should match nm_device_factory() */
|
||||
typedef GObject * (*NMDeviceFactoryCreateFunc) (GUdevDevice *device,
|
||||
const char *devpath,
|
||||
const char *ifname,
|
||||
const char *driver,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* nm_device_factory_get_priority:
|
||||
*
|
||||
* Returns the priority of this plugin. Higher numbers mean a higher priority.
|
||||
*
|
||||
* Returns: plugin priority
|
||||
*/
|
||||
guint32 nm_device_factory_get_priority (void);
|
||||
|
||||
typedef guint32 (*NMDeviceFactoryPriorityFunc) (void);
|
||||
|
||||
/**
|
||||
* nm_device_factory_get_type:
|
||||
*
|
||||
* Returns the type of device this factory can create. Only one factory for
|
||||
* each type of device is allowed.
|
||||
*
|
||||
* Returns: the %NMDeviceType
|
||||
*/
|
||||
NMDeviceType nm_device_factory_get_type (void);
|
||||
|
||||
typedef NMDeviceType (*NMDeviceFactoryTypeFunc) (void);
|
||||
|
||||
#endif /* NM_DEVICE_FACTORY_H */
|
||||
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#include <unistd.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#include <gmodule.h>
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
#include "nm-udev-manager.h"
|
||||
|
|
@ -38,15 +39,16 @@
|
|||
#include "nm-device-olpc-mesh.h"
|
||||
#include "nm-device-infiniband.h"
|
||||
#include "nm-device-ethernet.h"
|
||||
#include "nm-device-factory.h"
|
||||
#include "wifi-utils.h"
|
||||
#if WITH_WIMAX
|
||||
#include "nm-device-wimax.h"
|
||||
#endif
|
||||
#include "nm-system.h"
|
||||
|
||||
typedef struct {
|
||||
GUdevClient *client;
|
||||
|
||||
/* List of NMDeviceFactoryFunc pointers sorted in priority order */
|
||||
GSList *factories;
|
||||
|
||||
/* Authoritative rfkill state (RFKILL_* enum) */
|
||||
RfKillState rfkill_states[RFKILL_TYPE_MAX];
|
||||
GSList *killswitches;
|
||||
|
|
@ -374,15 +376,6 @@ is_olpc_mesh (GUdevDevice *device)
|
|||
return (prop != NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_wimax (const char *driver)
|
||||
{
|
||||
/* FIXME: check 'DEVTYPE' instead; but since we only support Intel
|
||||
* WiMAX devices for now this is appropriate.
|
||||
*/
|
||||
return g_strcmp0 (driver, "i2400m_usb") == 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_infiniband (GUdevDevice *device)
|
||||
{
|
||||
|
|
@ -395,10 +388,13 @@ device_creator (NMUdevManager *manager,
|
|||
GUdevDevice *udev_device,
|
||||
gboolean sleeping)
|
||||
{
|
||||
NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (manager);
|
||||
GObject *device = NULL;
|
||||
const char *ifname, *driver, *path, *subsys;
|
||||
GUdevDevice *parent = NULL, *grandparent = NULL;
|
||||
gint ifindex;
|
||||
GError *error = NULL;
|
||||
GSList *iter;
|
||||
|
||||
ifname = g_udev_device_get_name (udev_device);
|
||||
g_assert (ifname);
|
||||
|
|
@ -455,18 +451,35 @@ device_creator (NMUdevManager *manager,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (is_olpc_mesh (udev_device)) /* must be before is_wireless */
|
||||
device = (GObject *) nm_device_olpc_mesh_new (path, ifname, driver);
|
||||
else if (is_wireless (udev_device))
|
||||
device = (GObject *) nm_device_wifi_new (path, ifname, driver);
|
||||
else if (is_wimax (driver)) {
|
||||
#if WITH_WIMAX
|
||||
device = (GObject *) nm_device_wimax_new (path, ifname, driver);
|
||||
#endif
|
||||
} else if (is_infiniband (udev_device))
|
||||
device = (GObject *) nm_device_infiniband_new (path, ifname, driver);
|
||||
else
|
||||
device = (GObject *) nm_device_ethernet_new (path, ifname, driver);
|
||||
/* Try registered device factories */
|
||||
for (iter = priv->factories; iter; iter = g_slist_next (iter)) {
|
||||
NMDeviceFactoryCreateFunc create_func = iter->data;
|
||||
|
||||
g_clear_error (&error);
|
||||
device = create_func (udev_device, path, ifname, driver, &error);
|
||||
if (device) {
|
||||
g_assert_no_error (error);
|
||||
break; /* success! */
|
||||
}
|
||||
|
||||
if (error) {
|
||||
nm_log_warn (LOGD_HW, "%s: factory failed to create device: (%d) %s",
|
||||
path, error->code, error->message);
|
||||
g_clear_error (&error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (device == NULL) {
|
||||
if (is_olpc_mesh (udev_device)) /* must be before is_wireless */
|
||||
device = (GObject *) nm_device_olpc_mesh_new (path, ifname, driver);
|
||||
else if (is_wireless (udev_device))
|
||||
device = (GObject *) nm_device_wifi_new (path, ifname, driver);
|
||||
else if (is_infiniband (udev_device))
|
||||
device = (GObject *) nm_device_infiniband_new (path, ifname, driver);
|
||||
else
|
||||
device = (GObject *) nm_device_ethernet_new (path, ifname, driver);
|
||||
}
|
||||
|
||||
out:
|
||||
if (grandparent)
|
||||
|
|
@ -555,6 +568,121 @@ nm_udev_manager_query_devices (NMUdevManager *self)
|
|||
g_list_free (devices);
|
||||
}
|
||||
|
||||
#define PLUGIN_PREFIX "libnm-device-plugin-"
|
||||
|
||||
typedef struct {
|
||||
NMDeviceType t;
|
||||
guint priority;
|
||||
NMDeviceFactoryCreateFunc create_func;
|
||||
} PluginInfo;
|
||||
|
||||
static gint
|
||||
plugin_sort (PluginInfo *a, PluginInfo *b)
|
||||
{
|
||||
/* Higher priority means sort earlier in the list (ie, return -1) */
|
||||
if (a->priority > b->priority)
|
||||
return -1;
|
||||
else if (a->priority < b->priority)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
load_device_factories (NMUdevManager *self)
|
||||
{
|
||||
NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self);
|
||||
GDir *dir;
|
||||
GError *error = NULL;
|
||||
const char *item;
|
||||
char *path;
|
||||
GSList *list = NULL, *iter;
|
||||
|
||||
dir = g_dir_open (NMPLUGINDIR, 0, &error);
|
||||
if (!dir) {
|
||||
nm_log_warn (LOGD_HW, "Failed to open plugin directory %s: %s",
|
||||
NMPLUGINDIR,
|
||||
(error && error->message) ? error->message : "(unknown)");
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((item = g_dir_read_name (dir))) {
|
||||
GModule *plugin;
|
||||
NMDeviceFactoryCreateFunc create_func;
|
||||
NMDeviceFactoryPriorityFunc priority_func;
|
||||
NMDeviceFactoryTypeFunc type_func;
|
||||
PluginInfo *info = NULL;
|
||||
NMDeviceType plugin_type;
|
||||
|
||||
if (!g_str_has_prefix (item, PLUGIN_PREFIX))
|
||||
continue;
|
||||
|
||||
path = g_module_build_path (NMPLUGINDIR, item);
|
||||
g_assert (path);
|
||||
plugin = g_module_open (path, G_MODULE_BIND_LOCAL);
|
||||
g_free (path);
|
||||
|
||||
if (!plugin) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to load plugin: %s", item, g_module_error ());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!g_module_symbol (plugin, "nm_device_factory_get_type", (gpointer) (&type_func))) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to find device factory: %s", item, g_module_error ());
|
||||
g_module_close (plugin);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Make sure we don't double-load plugins */
|
||||
plugin_type = type_func ();
|
||||
for (iter = list; iter; iter = g_slist_next (iter)) {
|
||||
PluginInfo *candidate = iter->data;
|
||||
|
||||
if (plugin_type == candidate->t) {
|
||||
info = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (info) {
|
||||
g_module_close (plugin);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!g_module_symbol (plugin, "nm_device_factory_create_device", (gpointer) (&create_func))) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to find device creator: %s", item, g_module_error ());
|
||||
g_module_close (plugin);
|
||||
continue;
|
||||
}
|
||||
|
||||
info = g_malloc0 (sizeof (*info));
|
||||
info->create_func = create_func;
|
||||
info->t = plugin_type;
|
||||
|
||||
/* Grab priority; higher number equals higher priority */
|
||||
if (g_module_symbol (plugin, "nm_device_factory_get_priority", (gpointer) (&priority_func)))
|
||||
info->priority = priority_func ();
|
||||
else {
|
||||
nm_log_dbg (LOGD_HW, "(%s): failed to find device factory priority func: %s",
|
||||
item, g_module_error ());
|
||||
}
|
||||
|
||||
g_module_make_resident (plugin);
|
||||
list = g_slist_insert_sorted (list, info, (GCompareFunc) plugin_sort);
|
||||
|
||||
nm_log_info (LOGD_HW, "Loaded device factory: %s", g_module_name (plugin));
|
||||
};
|
||||
g_dir_close (dir);
|
||||
|
||||
/* Ditch the priority info and copy the factory functions to our private data */
|
||||
for (iter = list; iter; iter = g_slist_next (iter)) {
|
||||
PluginInfo *info = iter->data;
|
||||
|
||||
priv->factories = g_slist_append (priv->factories, info->create_func);
|
||||
g_free (info);
|
||||
}
|
||||
g_slist_free (list);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_uevent (GUdevClient *client,
|
||||
const char *action,
|
||||
|
|
@ -612,6 +740,8 @@ nm_udev_manager_init (NMUdevManager *self)
|
|||
g_list_free (switches);
|
||||
|
||||
recheck_killswitches (self);
|
||||
|
||||
load_device_factories (self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -631,6 +761,8 @@ dispose (GObject *object)
|
|||
g_slist_foreach (priv->killswitches, (GFunc) killswitch_destroy, NULL);
|
||||
g_slist_free (priv->killswitches);
|
||||
|
||||
g_slist_free (priv->factories);
|
||||
|
||||
G_OBJECT_CLASS (nm_udev_manager_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ INCLUDES = \
|
|||
-I${top_srcdir}/libnm-util \
|
||||
-I${top_builddir}/marshallers
|
||||
|
||||
noinst_LTLIBRARIES = libwimax.la
|
||||
pkglib_LTLIBRARIES = libnm-device-plugin-wimax.la
|
||||
|
||||
libwimax_la_SOURCES = \
|
||||
libnm_device_plugin_wimax_la_SOURCES = \
|
||||
nm-wimax-factory.c \
|
||||
nm-device-wimax.c \
|
||||
nm-device-wimax.h \
|
||||
nm-wimax-nsp.c \
|
||||
|
|
@ -18,14 +19,17 @@ libwimax_la_SOURCES = \
|
|||
iwmxsdk.c \
|
||||
iwmxsdk.h
|
||||
|
||||
libwimax_la_CPPFLAGS = \
|
||||
libnm_device_plugin_wimax_la_CPPFLAGS = \
|
||||
$(DBUS_CFLAGS) \
|
||||
$(IWMX_SDK_CFLAGS) \
|
||||
$(LIBNL_CFLAGS)
|
||||
$(LIBNL_CFLAGS) \
|
||||
$(GUDEV_CFLAGS)
|
||||
|
||||
libwimax_la_LIBADD = \
|
||||
libnm_device_plugin_wimax_la_LDFLAGS = -module -avoid-version
|
||||
libnm_device_plugin_wimax_la_LIBADD = \
|
||||
$(DBUS_LIBS) \
|
||||
$(IWMX_SDK_LIBS) \
|
||||
$(GUDEV_LIBS) \
|
||||
$(top_builddir)/marshallers/libmarshallers.la
|
||||
|
||||
nm-wimax-nsp-glue.h: $(top_srcdir)/introspection/nm-wimax-nsp.xml
|
||||
|
|
|
|||
58
src/wimax/nm-wimax-factory.c
Normal file
58
src/wimax/nm-wimax-factory.c
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
#include "nm-device-factory.h"
|
||||
#include "nm-device-wimax.h"
|
||||
|
||||
G_MODULE_EXPORT GObject *
|
||||
nm_device_factory_create_device (GUdevDevice *device,
|
||||
const char *devpath,
|
||||
const char *ifname,
|
||||
const char *driver,
|
||||
GError **error)
|
||||
{
|
||||
GObject *dev;
|
||||
|
||||
/* FIXME: check 'DEVTYPE' instead; but since we only support Intel
|
||||
* WiMAX devices for now this is appropriate.
|
||||
*/
|
||||
if (g_strcmp0 (driver, "i2400m_usb") != 0)
|
||||
return NULL; /* unsupported */
|
||||
|
||||
dev = (GObject *) nm_device_wimax_new (devpath, ifname, driver);
|
||||
if (dev == NULL)
|
||||
g_set_error_literal (error, 0, 0, "Failed to create WiMAX device.");
|
||||
return dev;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT guint32
|
||||
nm_device_factory_get_priority (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT NMDeviceType
|
||||
nm_device_factory_get_type (void)
|
||||
{
|
||||
return NM_DEVICE_TYPE_WIMAX;
|
||||
}
|
||||
|
||||
Loading…
Add table
Reference in a new issue