bonding: detect virtual bonding devices and create an ethernet device
A bonding device is like a virtual ethernet device. We therefore reuse nm-device-ethernet and add some special handling to detect bonding connections. Changes v2: - Fixed memory leak Signed-off-by: Thomas Graf <tgraf@redhat.com>
This commit is contained in:

committed by
Dan Williams

parent
095aff0c21
commit
8d5af59812
@@ -55,6 +55,7 @@
|
|||||||
#include "nm-setting-wired.h"
|
#include "nm-setting-wired.h"
|
||||||
#include "nm-setting-8021x.h"
|
#include "nm-setting-8021x.h"
|
||||||
#include "nm-setting-pppoe.h"
|
#include "nm-setting-pppoe.h"
|
||||||
|
#include "nm-setting-bond.h"
|
||||||
#include "ppp-manager/nm-ppp-manager.h"
|
#include "ppp-manager/nm-ppp-manager.h"
|
||||||
#include "nm-logging.h"
|
#include "nm-logging.h"
|
||||||
#include "nm-properties-changed-signal.h"
|
#include "nm-properties-changed-signal.h"
|
||||||
@@ -599,6 +600,22 @@ nm_device_ethernet_get_address (NMDeviceEthernet *self, struct ether_addr *addr)
|
|||||||
memcpy (addr, &priv->hw_addr, sizeof (priv->hw_addr));
|
memcpy (addr, &priv->hw_addr, sizeof (priv->hw_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_device_bond_connection_matches (NMDevice *device, NMConnection *connection)
|
||||||
|
{
|
||||||
|
NMSettingBond *s_bond;
|
||||||
|
const char *devname;
|
||||||
|
|
||||||
|
devname = nm_device_get_iface (device);
|
||||||
|
g_assert(devname);
|
||||||
|
|
||||||
|
s_bond = nm_connection_get_setting_bond (connection);
|
||||||
|
if (s_bond && !strcmp (devname, nm_setting_bond_get_interface_name (s_bond)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns speed in Mb/s */
|
/* Returns speed in Mb/s */
|
||||||
static guint32
|
static guint32
|
||||||
nm_device_ethernet_get_speed (NMDeviceEthernet *self)
|
nm_device_ethernet_get_speed (NMDeviceEthernet *self)
|
||||||
@@ -890,6 +907,14 @@ real_get_best_auto_connection (NMDevice *dev,
|
|||||||
g_assert (s_con);
|
g_assert (s_con);
|
||||||
|
|
||||||
connection_type = nm_setting_connection_get_connection_type (s_con);
|
connection_type = nm_setting_connection_get_connection_type (s_con);
|
||||||
|
|
||||||
|
if (!strcmp (connection_type, NM_SETTING_BOND_SETTING_NAME)) {
|
||||||
|
if (nm_device_bond_connection_matches (dev, connection))
|
||||||
|
return connection;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME))
|
if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME))
|
||||||
is_pppoe = TRUE;
|
is_pppoe = TRUE;
|
||||||
|
|
||||||
@@ -1593,7 +1618,7 @@ real_check_connection_compatible (NMDevice *device,
|
|||||||
NMSettingConnection *s_con;
|
NMSettingConnection *s_con;
|
||||||
NMSettingWired *s_wired;
|
NMSettingWired *s_wired;
|
||||||
const char *connection_type;
|
const char *connection_type;
|
||||||
gboolean is_pppoe = FALSE;
|
gboolean is_pppoe = FALSE, is_bond = FALSE;
|
||||||
const GByteArray *mac;
|
const GByteArray *mac;
|
||||||
gboolean try_mac = TRUE;
|
gboolean try_mac = TRUE;
|
||||||
const GSList *mac_blacklist, *mac_blacklist_iter;
|
const GSList *mac_blacklist, *mac_blacklist_iter;
|
||||||
@@ -1603,19 +1628,23 @@ real_check_connection_compatible (NMDevice *device,
|
|||||||
|
|
||||||
connection_type = nm_setting_connection_get_connection_type (s_con);
|
connection_type = nm_setting_connection_get_connection_type (s_con);
|
||||||
if ( strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)
|
if ( strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)
|
||||||
|
&& strcmp (connection_type, NM_SETTING_BOND_SETTING_NAME)
|
||||||
&& strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
|
&& strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED,
|
NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED,
|
||||||
"The connection was not a wired or PPPoE connection.");
|
"The connection was not a wired, bond, or PPPoE connection.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME))
|
if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME))
|
||||||
is_pppoe = TRUE;
|
is_pppoe = TRUE;
|
||||||
|
|
||||||
|
if (!strcmp (connection_type, NM_SETTING_BOND_SETTING_NAME))
|
||||||
|
is_bond = TRUE;
|
||||||
|
|
||||||
s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
|
s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
|
||||||
/* Wired setting is optional for PPPoE */
|
/* Wired setting is optional for PPPoE */
|
||||||
if (!is_pppoe && !s_wired) {
|
if (!is_pppoe && !s_wired && !is_bond) {
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INVALID,
|
NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INVALID,
|
||||||
"The connection was not a valid wired connection.");
|
"The connection was not a valid wired connection.");
|
||||||
|
@@ -63,6 +63,8 @@ NMDevice *nm_device_ethernet_new (const char *udi,
|
|||||||
void nm_device_ethernet_get_address (NMDeviceEthernet *dev,
|
void nm_device_ethernet_get_address (NMDeviceEthernet *dev,
|
||||||
struct ether_addr *addr);
|
struct ether_addr *addr);
|
||||||
|
|
||||||
|
gboolean nm_device_bond_connection_matches (NMDevice *device, NMConnection *connection);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* NM_DEVICE_ETHERNET_H */
|
#endif /* NM_DEVICE_ETHERNET_H */
|
||||||
|
@@ -68,13 +68,6 @@ __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
|
||||||
|
|
||||||
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 */
|
#endif /* HAVE_LIBNL2 */
|
||||||
|
|
||||||
|
|
||||||
@@ -222,6 +215,11 @@ static inline int __genl_ctrl_alloc_cache(struct nl_sock *h, struct nl_cache **c
|
|||||||
#define NLE_PERM 28
|
#define NLE_PERM 28
|
||||||
#define NLE_PKTLOC_FILE 29
|
#define NLE_PKTLOC_FILE 29
|
||||||
|
|
||||||
|
#endif /* HAVE_LIBNL1 */
|
||||||
|
|
||||||
|
/* Stuff that only libnl3 has */
|
||||||
|
#if HAVE_LIBNL1 || HAVE_LIBNL2
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
rtnl_link_bond_add (struct nl_sock *h, const char *name, void *data)
|
rtnl_link_bond_add (struct nl_sock *h, const char *name, void *data)
|
||||||
{
|
{
|
||||||
@@ -229,6 +227,20 @@ rtnl_link_bond_add (struct nl_sock *h, const char *name, void *data)
|
|||||||
return -NLE_OPNOTSUPP;
|
return -NLE_OPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_LIBNL1 */
|
static inline int
|
||||||
|
rtnl_link_get_kernel (struct nl_sock *h, int f, const char *name, struct rtnl_link **out_link)
|
||||||
|
{
|
||||||
|
/* Bonding only in libnl3 */
|
||||||
|
return -NLE_OPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
rtnl_link_get_type (struct rtnl_link *rtnl_link)
|
||||||
|
{
|
||||||
|
/* Bonding only in libnl3 */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_LIBNL1 || HAVE_LIBNL2 */
|
||||||
|
|
||||||
#endif /* NM_NETLINK_COMPAT_H */
|
#endif /* NM_NETLINK_COMPAT_H */
|
||||||
|
@@ -1233,3 +1233,35 @@ nm_system_add_bonding_master(NMSettingBond *setting)
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_system_get_link_type:
|
||||||
|
* @name: name of link
|
||||||
|
*
|
||||||
|
* Lookup virtual link type. The returned string is allocated and needs
|
||||||
|
* to be freed after usage.
|
||||||
|
*
|
||||||
|
* Returns: Name of virtual link type or NULL if not a virtual link.
|
||||||
|
**/
|
||||||
|
char *
|
||||||
|
nm_system_get_link_type (const char *name)
|
||||||
|
{
|
||||||
|
struct rtnl_link *result;
|
||||||
|
struct nl_sock *nlh;
|
||||||
|
char *type;
|
||||||
|
|
||||||
|
nlh = nm_netlink_get_default_handle ();
|
||||||
|
if (!nlh)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (rtnl_link_get_kernel (nlh, 0, name, &result) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((type = rtnl_link_get_type (result)))
|
||||||
|
type = g_strdup (type);
|
||||||
|
|
||||||
|
rtnl_link_put (result);
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -92,4 +92,6 @@ gboolean nm_system_iface_set_mac (int ifindex, const struct eth
|
|||||||
|
|
||||||
gboolean nm_system_add_bonding_master (NMSettingBond *setting);
|
gboolean nm_system_add_bonding_master (NMSettingBond *setting);
|
||||||
|
|
||||||
|
char * nm_system_get_link_type (const char *name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
#if WITH_WIMAX
|
#if WITH_WIMAX
|
||||||
#include "nm-device-wimax.h"
|
#include "nm-device-wimax.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "nm-system.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GUdevClient *client;
|
GUdevClient *client;
|
||||||
@@ -422,9 +423,18 @@ device_creator (NMUdevManager *manager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!driver) {
|
if (!driver) {
|
||||||
if (g_str_has_prefix (ifname, "easytether")) {
|
char *type;
|
||||||
|
|
||||||
|
type = nm_system_get_link_type (ifname);
|
||||||
|
if (type) {
|
||||||
|
if (g_strcmp0 (type, "bond") == 0)
|
||||||
|
driver = "bonding";
|
||||||
|
g_free (type);
|
||||||
|
} else if (g_str_has_prefix (ifname, "easytether")) {
|
||||||
driver = "easytether";
|
driver = "easytether";
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (!driver) {
|
||||||
nm_log_warn (LOGD_HW, "%s: couldn't determine device driver; ignoring...", path);
|
nm_log_warn (LOGD_HW, "%s: couldn't determine device driver; ignoring...", path);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@@ -52,6 +52,7 @@
|
|||||||
#include <nm-setting-wired.h>
|
#include <nm-setting-wired.h>
|
||||||
#include <nm-setting-wireless.h>
|
#include <nm-setting-wireless.h>
|
||||||
#include <nm-setting-wireless-security.h>
|
#include <nm-setting-wireless-security.h>
|
||||||
|
#include <nm-setting-bond.h>
|
||||||
|
|
||||||
#include "../nm-device-ethernet.h"
|
#include "../nm-device-ethernet.h"
|
||||||
#include "nm-dbus-glib-types.h"
|
#include "nm-dbus-glib-types.h"
|
||||||
@@ -1172,7 +1173,7 @@ impl_settings_save_hostname (NMSettings *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
have_connection_for_device (NMSettings *self, GByteArray *mac)
|
have_connection_for_device (NMSettings *self, GByteArray *mac, NMDevice *device)
|
||||||
{
|
{
|
||||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
@@ -1194,6 +1195,14 @@ have_connection_for_device (NMSettings *self, GByteArray *mac)
|
|||||||
s_con = nm_connection_get_setting_connection (connection);
|
s_con = nm_connection_get_setting_connection (connection);
|
||||||
ctype = nm_setting_connection_get_connection_type (s_con);
|
ctype = nm_setting_connection_get_connection_type (s_con);
|
||||||
|
|
||||||
|
if (!strcmp (ctype, NM_SETTING_BOND_SETTING_NAME)) {
|
||||||
|
if (nm_device_bond_connection_matches (device, connection)) {
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME)
|
if ( strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME)
|
||||||
&& strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME))
|
&& strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME))
|
||||||
continue;
|
continue;
|
||||||
@@ -1445,7 +1454,7 @@ nm_settings_device_added (NMSettings *self, NMDevice *device)
|
|||||||
mac = g_byte_array_sized_new (ETH_ALEN);
|
mac = g_byte_array_sized_new (ETH_ALEN);
|
||||||
g_byte_array_append (mac, tmp.ether_addr_octet, ETH_ALEN);
|
g_byte_array_append (mac, tmp.ether_addr_octet, ETH_ALEN);
|
||||||
|
|
||||||
if ( have_connection_for_device (self, mac)
|
if ( have_connection_for_device (self, mac, device)
|
||||||
|| is_mac_auto_wired_blacklisted (self, mac))
|
|| is_mac_auto_wired_blacklisted (self, mac))
|
||||||
goto ignore;
|
goto ignore;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user