mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-16 07:40:41 +01:00
netlink: consolidate netlink monitor error handling and initialization
The fact that any of this code was in main.c was a hangover from a long time ago and it should really go with the rest of the netlink monitor code.
This commit is contained in:
parent
33ae7cf518
commit
2ade420479
4 changed files with 88 additions and 131 deletions
83
src/main.c
83
src/main.c
|
|
@ -67,80 +67,6 @@ static NMManager *manager = NULL;
|
|||
static GMainLoop *main_loop = NULL;
|
||||
static int quit_pipe[2] = { -1, -1 };
|
||||
|
||||
typedef struct {
|
||||
time_t time;
|
||||
GQuark domain;
|
||||
guint32 code;
|
||||
guint32 count;
|
||||
} MonitorInfo;
|
||||
|
||||
static gboolean
|
||||
detach_monitor (gpointer data)
|
||||
{
|
||||
nm_log_warn (LOGD_HW, "detaching netlink event monitor");
|
||||
nm_netlink_monitor_detach (NM_NETLINK_MONITOR (data));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_error_monitoring_device_link_state (NMNetlinkMonitor *monitor,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
MonitorInfo *info = (MonitorInfo *) user_data;
|
||||
time_t now;
|
||||
|
||||
now = time (NULL);
|
||||
|
||||
if ( (info->domain != error->domain)
|
||||
|| (info->code != error->code)
|
||||
|| (info->time && now > info->time + 10)) {
|
||||
/* FIXME: Try to handle the error instead of just printing it. */
|
||||
nm_log_warn (LOGD_HW, "error monitoring device for netlink events: %s\n", error->message);
|
||||
|
||||
info->time = now;
|
||||
info->domain = error->domain;
|
||||
info->code = error->code;
|
||||
info->count = 0;
|
||||
}
|
||||
|
||||
info->count++;
|
||||
if (info->count > 100) {
|
||||
/* Broken drivers will sometimes cause a flood of netlink errors.
|
||||
* rh #459205, novell #443429, lp #284507
|
||||
*/
|
||||
nm_log_warn (LOGD_HW, "excessive netlink errors ocurred, disabling netlink monitor.");
|
||||
nm_log_warn (LOGD_HW, "link change events will not be processed.");
|
||||
g_idle_add_full (G_PRIORITY_HIGH, detach_monitor, monitor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nm_monitor_setup (GError **error)
|
||||
{
|
||||
NMNetlinkMonitor *monitor;
|
||||
MonitorInfo *info;
|
||||
|
||||
monitor = nm_netlink_monitor_get ();
|
||||
if (!nm_netlink_monitor_open_connection (monitor, error)) {
|
||||
g_object_unref (monitor);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
info = g_new0 (MonitorInfo, 1);
|
||||
g_signal_connect_data (G_OBJECT (monitor), "error",
|
||||
G_CALLBACK (nm_error_monitoring_device_link_state),
|
||||
info,
|
||||
(GClosureNotify) g_free,
|
||||
0);
|
||||
nm_netlink_monitor_attach (monitor);
|
||||
|
||||
/* Request initial status of cards */
|
||||
nm_netlink_monitor_request_status (monitor, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean quit_early = FALSE;
|
||||
|
||||
static void
|
||||
|
|
@ -431,6 +357,7 @@ main (int argc, char *argv[])
|
|||
NMFirewallManager *fw_mgr = NULL;
|
||||
NMSettings *settings = NULL;
|
||||
NMConfig *config;
|
||||
NMNetlinkMonitor *monitor = NULL;
|
||||
GError *error = NULL;
|
||||
gboolean wrote_pidfile = FALSE;
|
||||
|
||||
|
|
@ -600,12 +527,8 @@ main (int argc, char *argv[])
|
|||
|
||||
main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
/* Create watch functions that monitor cards for link status. */
|
||||
if (!nm_monitor_setup (&error)) {
|
||||
nm_log_err (LOGD_CORE, "failed to start monitoring devices: %s.",
|
||||
error && error->message ? error->message : "(unknown)");
|
||||
goto done;
|
||||
}
|
||||
/* Create netlink monitor object */
|
||||
monitor = nm_netlink_monitor_get ();
|
||||
|
||||
/* Initialize our DBus service & connection */
|
||||
dbus_mgr = nm_dbus_manager_get ();
|
||||
|
|
|
|||
|
|
@ -243,14 +243,7 @@ constructor (GType type,
|
|||
/* Request link state again just in case an error occurred getting the
|
||||
* initial link state.
|
||||
*/
|
||||
if (!nm_netlink_monitor_request_status (priv->monitor, &error)) {
|
||||
nm_log_warn (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
|
||||
"(%s): couldn't request carrier state: (%d) %s",
|
||||
nm_device_get_iface (NM_DEVICE (self)),
|
||||
error ? error->code : -1,
|
||||
(error && error->message) ? error->message : "unknown");
|
||||
g_clear_error (&error);
|
||||
}
|
||||
nm_netlink_monitor_request_status (priv->monitor);
|
||||
} else {
|
||||
nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
|
||||
"(%s): driver '%s' does not support carrier detection.",
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ enum {
|
|||
NOTIFICATION = 0,
|
||||
CARRIER_ON,
|
||||
CARRIER_OFF,
|
||||
ERROR,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
|
@ -84,11 +83,60 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
|||
|
||||
G_DEFINE_TYPE (NMNetlinkMonitor, nm_netlink_monitor, G_TYPE_OBJECT);
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
static gboolean
|
||||
detach_monitor (gpointer data)
|
||||
{
|
||||
nm_log_warn (LOGD_HW, "detaching netlink event monitor");
|
||||
nm_netlink_monitor_detach (NM_NETLINK_MONITOR (data));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
log_error_limited (NMNetlinkMonitor *monitor, guint32 code, const char *fmt, ...)
|
||||
{
|
||||
static time_t rl_time = 0;
|
||||
static guint32 rl_code = 0;
|
||||
static guint32 rl_count = 0;
|
||||
va_list args;
|
||||
char *msg;
|
||||
time_t now;
|
||||
|
||||
g_return_if_fail (monitor != NULL);
|
||||
|
||||
now = time (NULL);
|
||||
|
||||
if ((code != rl_code) || (now > rl_time + 10)) {
|
||||
va_start (args, fmt);
|
||||
msg = g_strdup_vprintf (fmt, args);
|
||||
va_end (args);
|
||||
|
||||
nm_log_warn (LOGD_HW, "error monitoring device for netlink events: %s\n", msg);
|
||||
g_free (msg);
|
||||
|
||||
rl_time = now;
|
||||
rl_code = code;
|
||||
rl_count = 0;
|
||||
}
|
||||
|
||||
rl_count++;
|
||||
if (rl_count > 100) {
|
||||
/* Broken drivers will sometimes cause a flood of netlink errors.
|
||||
* rh #459205, novell #443429, lp #284507
|
||||
*/
|
||||
nm_log_warn (LOGD_HW, "excessive netlink errors ocurred, disabling netlink monitor.");
|
||||
nm_log_warn (LOGD_HW, "link change events will not be processed.");
|
||||
g_idle_add_full (G_PRIORITY_HIGH, detach_monitor, monitor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
static void
|
||||
link_msg_handler (struct nl_object *obj, void *arg)
|
||||
{
|
||||
NMNetlinkMonitor *self = NM_NETLINK_MONITOR (arg);
|
||||
GError *error;
|
||||
struct rtnl_link *filter;
|
||||
struct rtnl_link *link_obj;
|
||||
guint flags;
|
||||
|
|
@ -96,12 +144,9 @@ link_msg_handler (struct nl_object *obj, void *arg)
|
|||
|
||||
filter = rtnl_link_alloc ();
|
||||
if (!filter) {
|
||||
error = g_error_new (NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_BAD_ALLOC,
|
||||
_("error processing netlink message: %s"),
|
||||
nl_geterror (ENOMEM));
|
||||
g_signal_emit (self, signals[ERROR], 0, error);
|
||||
g_error_free (error);
|
||||
log_error_limited (self, NM_NETLINK_MONITOR_ERROR_BAD_ALLOC,
|
||||
_("error processing netlink message: %s"),
|
||||
nl_geterror (ENOMEM));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +240,6 @@ event_handler (GIOChannel *channel,
|
|||
{
|
||||
NMNetlinkMonitor *self = (NMNetlinkMonitor *) user_data;
|
||||
NMNetlinkMonitorPrivate *priv;
|
||||
GError *error = NULL;
|
||||
int err;
|
||||
|
||||
g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), TRUE);
|
||||
|
|
@ -204,22 +248,17 @@ event_handler (GIOChannel *channel,
|
|||
g_return_val_if_fail (priv->event_id > 0, TRUE);
|
||||
|
||||
if (io_condition & ERROR_CONDITIONS) {
|
||||
const char *err_msg;
|
||||
const char *err_msg = _("error occurred while waiting for data on socket");
|
||||
int err_code = 0;
|
||||
socklen_t err_len = sizeof (err_code);
|
||||
|
||||
/* Grab error information */
|
||||
if (getsockopt (g_io_channel_unix_get_fd (channel),
|
||||
SOL_SOCKET, SO_ERROR, (void *) &err_code, &err_len))
|
||||
SOL_SOCKET, SO_ERROR,
|
||||
(void *) &err_code, &err_len) == 0)
|
||||
err_msg = strerror (err_code);
|
||||
else
|
||||
err_msg = _("error occurred while waiting for data on socket");
|
||||
|
||||
error = g_error_new (NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_WAITING_FOR_SOCKET_DATA,
|
||||
"%s", err_msg);
|
||||
g_signal_emit (self, signals[ERROR], 0, error);
|
||||
g_error_free (error);
|
||||
log_error_limited (self, NM_NETLINK_MONITOR_ERROR_WAITING_FOR_SOCKET_DATA, "%s", err_msg);
|
||||
return TRUE;
|
||||
} else if (io_condition & DISCONNECT_CONDITIONS)
|
||||
return FALSE;
|
||||
|
|
@ -229,12 +268,9 @@ event_handler (GIOChannel *channel,
|
|||
/* Process the netlink messages */
|
||||
err = nl_recvmsgs_default (priv->nlh_event);
|
||||
if (err < 0) {
|
||||
error = g_error_new (NM_NETLINK_MONITOR_ERROR,
|
||||
NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE,
|
||||
_("error processing netlink message: %s"),
|
||||
nl_geterror (err));
|
||||
g_signal_emit (self, signals[ERROR], 0, error);
|
||||
g_error_free (error);
|
||||
log_error_limited (self, NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE,
|
||||
_("error processing netlink message: %s"),
|
||||
nl_geterror (err));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -578,20 +614,18 @@ deferred_emit_carrier_state (gpointer user_data)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_netlink_monitor_request_status (NMNetlinkMonitor *self, GError **error)
|
||||
void
|
||||
nm_netlink_monitor_request_status (NMNetlinkMonitor *self)
|
||||
{
|
||||
NMNetlinkMonitorPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE);
|
||||
g_return_if_fail (NM_IS_NETLINK_MONITOR (self));
|
||||
|
||||
priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
|
||||
|
||||
/* Schedule the carrier state emission */
|
||||
if (!priv->request_status_id)
|
||||
priv->request_status_id = g_idle_add (deferred_emit_carrier_state, self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -778,10 +812,26 @@ NMNetlinkMonitor *
|
|||
nm_netlink_monitor_get (void)
|
||||
{
|
||||
static NMNetlinkMonitor *singleton = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!singleton)
|
||||
singleton = NM_NETLINK_MONITOR (g_object_new (NM_TYPE_NETLINK_MONITOR, NULL));
|
||||
else
|
||||
if (!singleton) {
|
||||
singleton = (NMNetlinkMonitor *) g_object_new (NM_TYPE_NETLINK_MONITOR, NULL);
|
||||
g_return_val_if_fail (singleton != NULL, NULL);
|
||||
|
||||
if (nm_netlink_monitor_open_connection (singleton, &error)) {
|
||||
nm_netlink_monitor_attach (singleton);
|
||||
/* Request initial status of cards */
|
||||
nm_netlink_monitor_request_status (singleton);
|
||||
} else {
|
||||
nm_log_warn (LOGD_HW, "Failed to connect to netlink: (%d) %s",
|
||||
error ? error->code : 0,
|
||||
(error && error->message) ? error->message : "(unknown)");
|
||||
g_clear_error (&error);
|
||||
|
||||
g_object_unref (singleton);
|
||||
singleton = NULL;
|
||||
}
|
||||
} else
|
||||
g_object_ref (singleton);
|
||||
|
||||
return singleton;
|
||||
|
|
@ -860,14 +910,6 @@ nm_netlink_monitor_class_init (NMNetlinkMonitorClass *monitor_class)
|
|||
G_STRUCT_OFFSET (NMNetlinkMonitorClass, carrier_off),
|
||||
NULL, NULL, g_cclosure_marshal_VOID__INT,
|
||||
G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
|
||||
signals[ERROR] =
|
||||
g_signal_new ("error",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (NMNetlinkMonitorClass, error),
|
||||
NULL, NULL, g_cclosure_marshal_VOID__POINTER,
|
||||
G_TYPE_NONE, 1, G_TYPE_POINTER);
|
||||
}
|
||||
|
||||
GQuark
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ typedef struct {
|
|||
void (*notification) (NMNetlinkMonitor *monitor, struct nl_msg *msg);
|
||||
void (*carrier_on) (NMNetlinkMonitor *monitor, int index);
|
||||
void (*carrier_off) (NMNetlinkMonitor *monitor, int index);
|
||||
void (*error) (NMNetlinkMonitor *monitor, GError *error);
|
||||
} NMNetlinkMonitorClass;
|
||||
|
||||
|
||||
|
|
@ -83,8 +82,8 @@ void nm_netlink_monitor_unsubscribe (NMNetlinkMonitor *monitor
|
|||
gboolean nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *monitor,
|
||||
GError **error);
|
||||
|
||||
gboolean nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor,
|
||||
GError **error);
|
||||
void nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor);
|
||||
|
||||
gboolean nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *monitor,
|
||||
guint32 ifindex,
|
||||
guint32 *ifflags,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue