summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-09-05 15:57:40 -0500
committerDan Williams <dcbw@redhat.com>2014-09-11 12:50:15 -0500
commit0bc1b5138ad8f7a64c74c374c866d615c69887bb (patch)
treec0f8e059eb06b25a94233e18c21ea7a219baedc6
parent38b076de8fc0e531ff80e9c9237960e0b2126467 (diff)
downloadNetworkManager-0bc1b5138ad8f7a64c74c374c866d615c69887bb.tar.gz
core: add support for internal device factories
-rw-r--r--src/devices/nm-device-factory.c15
-rw-r--r--src/devices/nm-device-factory.h57
-rw-r--r--src/nm-manager.c48
-rw-r--r--src/tests/Makefile.am16
4 files changed, 121 insertions, 15 deletions
diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c
index dc229bd5c8..80488aec37 100644
--- a/src/devices/nm-device-factory.c
+++ b/src/devices/nm-device-factory.c
@@ -27,6 +27,21 @@ enum {
};
static guint signals[LAST_SIGNAL] = { 0 };
+static GSList *internal_types = NULL;
+
+void
+_nm_device_factory_internal_register_type (GType factory_type)
+{
+ g_return_if_fail (g_slist_find (internal_types, GUINT_TO_POINTER (factory_type)) == NULL);
+ internal_types = g_slist_prepend (internal_types, GUINT_TO_POINTER (factory_type));
+}
+
+const GSList *
+nm_device_factory_get_internal_factory_types (void)
+{
+ return internal_types;
+}
+
gboolean
nm_device_factory_emit_component_added (NMDeviceFactory *factory, GObject *component)
{
diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h
index dd8a907961..ce672b8bfb 100644
--- a/src/devices/nm-device-factory.h
+++ b/src/devices/nm-device-factory.h
@@ -168,5 +168,60 @@ NMDevice * nm_device_factory_create_virtual_device_for_connection (NMDeviceFacto
gboolean nm_device_factory_emit_component_added (NMDeviceFactory *factory,
GObject *component);
-#endif /* __NETWORKMANAGER_DEVICE_FACTORY_H__ */
+/**************************************************************************
+ * INTERNAL DEVICE FACTORY FUNCTIONS - devices provided by plugins should
+ * not use these functions.
+ **************************************************************************/
+
+#define DEFINE_DEVICE_FACTORY_INTERNAL(upper, mixed, lower, dfi_code) \
+ DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(upper, mixed, lower, upper, dfi_code)
+
+#define DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(upper, mixed, lower, devtype, dfi_code) \
+ typedef GObject NM##mixed##Factory; \
+ typedef GObjectClass NM##mixed##FactoryClass; \
+ \
+ static GType nm_##lower##_factory_get_type (void); \
+ static void device_factory_interface_init (NMDeviceFactory *factory_iface); \
+ \
+ G_DEFINE_TYPE_EXTENDED (NM##mixed##Factory, nm_##lower##_factory, G_TYPE_OBJECT, 0, \
+ G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init) \
+ _nm_device_factory_internal_register_type (g_define_type_id);) \
+ \
+ /* Use a module constructor to register the factory's GType at load \
+ * time, which then calls _nm_device_factory_internal_register_type() \
+ * to register the factory's GType with the Manager. \
+ */ \
+ static void __attribute__((constructor)) \
+ register_device_factory_internal_##lower (void) \
+ { \
+ g_type_init (); \
+ g_type_ensure (NM_TYPE_##upper##_FACTORY); \
+ } \
+ \
+ static NMDeviceType \
+ get_device_type (NMDeviceFactory *factory) \
+ { \
+ return NM_DEVICE_TYPE_##devtype; \
+ } \
+ \
+ static void \
+ device_factory_interface_init (NMDeviceFactory *factory_iface) \
+ { \
+ factory_iface->get_device_type = get_device_type; \
+ dfi_code \
+ } \
+ \
+ static void \
+ nm_##lower##_factory_init (NM##mixed##Factory *self) \
+ { \
+ } \
+ \
+ static void \
+ nm_##lower##_factory_class_init (NM##mixed##FactoryClass *lower##_class) \
+ { \
+ }
+
+void _nm_device_factory_internal_register_type (GType factory_type);
+const GSList *nm_device_factory_get_internal_factory_types (void);
+#endif /* __NETWORKMANAGER_DEVICE_FACTORY_H__ */
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 6dd70eea93..cf7d2f5a9b 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -1968,6 +1968,7 @@ NEXT:
static gboolean
_register_device_factory (NMManager *self,
NMDeviceFactory *factory,
+ gboolean duplicate_check,
const char *path,
GError **error)
{
@@ -1975,15 +1976,17 @@ _register_device_factory (NMManager *self,
NMDeviceType ftype;
GSList *iter;
- /* Make sure we don't double-register factories */
- ftype = nm_device_factory_get_device_type (factory);
- for (iter = priv->factories; iter; iter = iter->next) {
- if (ftype == nm_device_factory_get_device_type (iter->data)) {
- g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_INTERNAL,
- "multiple plugins for same type (using '%s' instead of '%s')",
- (char *) g_object_get_data (G_OBJECT (iter->data), PLUGIN_PATH_TAG),
- path);
- return FALSE;
+ if (duplicate_check) {
+ /* Make sure we don't double-register factories */
+ ftype = nm_device_factory_get_device_type (factory);
+ for (iter = priv->factories; iter; iter = iter->next) {
+ if (ftype == nm_device_factory_get_device_type (iter->data)) {
+ g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_INTERNAL,
+ "multiple plugins for same type (using '%s' instead of '%s')",
+ (char *) g_object_get_data (G_OBJECT (iter->data), PLUGIN_PATH_TAG),
+ path);
+ return FALSE;
+ }
}
}
@@ -2005,17 +2008,32 @@ _register_device_factory (NMManager *self,
static void
load_device_factories (NMManager *self)
{
- char **path;
- char **paths;
+ NMDeviceFactory *factory;
+ const GSList *iter;
+ GError *error = NULL;
+ char **path, **paths;
+
+ /* Register internal factories first */
+ for (iter = nm_device_factory_get_internal_factory_types (); iter; iter = iter->next) {
+ GType ftype = GPOINTER_TO_UINT (iter->data);
+
+ factory = (NMDeviceFactory *) g_object_new (ftype, NULL);
+ g_assert (factory);
+ if (_register_device_factory (self, factory, FALSE, "internal", &error)) {
+ nm_log_dbg (LOGD_HW, "Loaded device plugin: %s", g_type_name (ftype));
+ } else {
+ nm_log_warn (LOGD_HW, "Loading device plugin failed: %s", error->message);
+ g_object_unref (factory);
+ g_clear_error (&error);
+ }
+ }
paths = read_device_factory_paths ();
if (!paths)
return;
for (path = paths; *path; path++) {
- GError *error = NULL;
GModule *plugin;
- NMDeviceFactory *factory;
NMDeviceFactoryCreateFunc create_func;
const char *item;
@@ -2045,7 +2063,7 @@ load_device_factories (NMManager *self)
}
g_clear_error (&error);
- if (_register_device_factory (self, factory, g_module_name (plugin), &error)) {
+ if (_register_device_factory (self, factory, TRUE, g_module_name (plugin), &error)) {
nm_log_info (LOGD_HW, "Loaded device plugin: %s", g_module_name (plugin));
g_module_make_resident (plugin);
} else {
@@ -2058,6 +2076,8 @@ load_device_factories (NMManager *self)
g_strfreev (paths);
}
+/*******************************************************************/
+
static void
platform_link_added (NMManager *self,
int ifindex,
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index a5824c96a3..221d3f5704 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -95,3 +95,19 @@ TESTS = \
test-general-with-expect \
test-wired-defname
+
+if ENABLE_TESTS
+
+check-local:
+ @for t in ; do \
+ # Ensure the device subclass factory registration constructors exist \
+ # which could inadvertently break if src/Makefile.am gets changed \
+ if ! LC_ALL=C nm $(top_builddir)/src/NetworkManager | LC_ALL=C grep -q "register_device_factory_internal_$$t" ; then \
+ echo "Testing device factory symbols... FAILED" ; \
+ exit 1 ; \
+ fi \
+ done
+ @echo -n "Testing device factory symbols... PASSED"
+
+endif
+