bonding: kernel bonding device creation

Creates virtual kernel devices as needed. Since the manager is
initialized after the connections have been loaded no
CONNECTIONS_ADDED notification is received for connections parsed
at startup.

Therefore walks the loaded connections looking for bonding
connections.

Connections added on the fly are handled via the notifications.

Connection renaming and deleting is not supported yet.

Signed-off-by: Thomas Graf <tgraf@redhat.com>
This commit is contained in:
Thomas Graf
2011-10-18 13:48:44 +02:00
committed by Dan Williams
parent a2a0d78818
commit 095aff0c21
4 changed files with 130 additions and 7 deletions

View File

@@ -924,12 +924,80 @@ get_active_connections (NMManager *manager, NMConnection *filter)
/* Settings stuff via NMSettings */ /* Settings stuff via NMSettings */
/*******************************************************************/ /*******************************************************************/
static gboolean
connection_needs_virtual_device (NMConnection *connection)
{
if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
return TRUE;
return FALSE;
}
static gboolean
system_update_virtual_device (NMConnection *connection)
{
if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) {
NMSettingBond *s_bond;
s_bond = nm_connection_get_setting_bond (connection);
g_assert (s_bond);
return nm_system_add_bonding_master (s_bond);
}
return TRUE;
}
static void static void
connections_changed (NMSettings *settings, system_create_virtual_devices (NMSettings *settings)
{
GSList *iter, *connections;
nm_log_info (LOGD_CORE, "Creating virtual devices");
connections = nm_settings_get_connections (settings);
for (iter = connections; iter; iter = g_slist_next (iter)) {
NMConnection *connection = NM_CONNECTION (iter->data);
if (connection_needs_virtual_device (connection))
system_update_virtual_device (connection);
}
g_slist_free (connections);
}
static void
connection_added (NMSettings *settings,
NMSettingsConnection *connection, NMSettingsConnection *connection,
NMManager *manager) NMManager *manager)
{ {
bluez_manager_resync_devices (manager); bluez_manager_resync_devices (manager);
if (connection_needs_virtual_device (NM_CONNECTION (connection)))
system_update_virtual_device (NM_CONNECTION (connection));
}
static void
connection_changed (NMSettings *settings,
NMSettingsConnection *connection,
NMManager *manager)
{
bluez_manager_resync_devices (manager);
/* FIXME: Some virtual devices may need to be updated in the future. */
}
static void
connection_removed (NMSettings *settings,
NMSettingsConnection *connection,
NMManager *manager)
{
bluez_manager_resync_devices (manager);
/*
* Do not delete existing virtual devices to keep connectivity up.
* Virtual devices are reused when NetworkManager is restarted.
*/
} }
static void static void
@@ -2823,6 +2891,12 @@ nm_manager_start (NMManager *self)
nm_udev_manager_query_devices (priv->udev_mgr); nm_udev_manager_query_devices (priv->udev_mgr);
bluez_manager_resync_devices (self); bluez_manager_resync_devices (self);
/*
* Connections added before the manager is started do not emit
* connection-added signals thus devices have to be created manually.
*/
system_create_virtual_devices (priv->settings);
} }
static gboolean static gboolean
@@ -3099,13 +3173,13 @@ nm_manager_new (NMSettings *settings,
g_signal_connect (priv->settings, "notify::" NM_SETTINGS_HOSTNAME, g_signal_connect (priv->settings, "notify::" NM_SETTINGS_HOSTNAME,
G_CALLBACK (system_hostname_changed_cb), singleton); G_CALLBACK (system_hostname_changed_cb), singleton);
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED,
G_CALLBACK (connections_changed), singleton); G_CALLBACK (connection_added), singleton);
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED,
G_CALLBACK (connections_changed), singleton); G_CALLBACK (connection_changed), singleton);
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED,
G_CALLBACK (connections_changed), singleton); G_CALLBACK (connection_removed), singleton);
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED,
G_CALLBACK (connections_changed), singleton); G_CALLBACK (connection_changed), singleton);
dbus_g_connection_register_g_object (bus, NM_DBUS_PATH, G_OBJECT (singleton)); dbus_g_connection_register_g_object (bus, NM_DBUS_PATH, G_OBJECT (singleton));

View File

@@ -68,7 +68,14 @@ __rtnl_link_alloc_cache (struct nl_sock *h, struct nl_cache **cache)
/* functions with similar prototypes */ /* functions with similar prototypes */
#define nlmsg_datalen nlmsg_len #define nlmsg_datalen nlmsg_len
#endif
static inline int
rtnl_link_bond_add (struct nl_sock *h, const char *name, void *data)
{
/* Bonding only in libnl3 */
return -NLE_OPNOTSUPP;
}
#endif /* HAVE_LIBNL2 */
/* libnl-1.0 compat functions */ /* libnl-1.0 compat functions */
@@ -214,6 +221,14 @@ static inline int __genl_ctrl_alloc_cache(struct nl_sock *h, struct nl_cache **c
#define NLE_NOACCESS 27 #define NLE_NOACCESS 27
#define NLE_PERM 28 #define NLE_PERM 28
#define NLE_PKTLOC_FILE 29 #define NLE_PKTLOC_FILE 29
#endif
static inline int
rtnl_link_bond_add (struct nl_sock *h, const char *name, void *data)
{
/* Bonding only in libnl3 */
return -NLE_OPNOTSUPP;
}
#endif /* HAVE_LIBNL1 */
#endif /* NM_NETLINK_COMPAT_H */ #endif /* NM_NETLINK_COMPAT_H */

View File

@@ -1202,3 +1202,34 @@ nm_system_device_set_priority (int ifindex,
rtnl_route_put (found); rtnl_route_put (found);
} }
} }
/**
* nm_system_add_bonding_master:
* @setting: bonding setting
*
* Adds a virtual bonding device if it does not exist yet.
*
* Returns: %TRUE on success, %FALSE on failure
*/
gboolean
nm_system_add_bonding_master(NMSettingBond *setting)
{
struct nl_sock *sock;
const char *name;
int err;
sock = nm_netlink_get_default_handle ();
name = nm_setting_bond_get_interface_name (setting);
g_assert (name);
/* Existing bonding devices with matching name will be reused */
err = rtnl_link_bond_add (sock, name, NULL);
if (err < 0) {
nm_log_err (LOGD_DEVICE, "(%s): error %d returned from "
"rtnl_link_bond_add(): %s",
name, err, nl_geterror (err));
return FALSE;
}
return TRUE;
}

View File

@@ -30,6 +30,7 @@
#include <glib.h> #include <glib.h>
#include "nm-device.h" #include "nm-device.h"
#include "nm-ip4-config.h" #include "nm-ip4-config.h"
#include "nm-setting-bond.h"
/* Prototypes for system/distribution dependent functions, /* Prototypes for system/distribution dependent functions,
* implemented in the backend files in backends/ directory * implemented in the backend files in backends/ directory
@@ -89,4 +90,6 @@ gboolean nm_system_iface_set_mtu (int ifindex, guint32 mtu);
gboolean nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac); gboolean nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac);
gboolean nm_system_add_bonding_master (NMSettingBond *setting);
#endif #endif