mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-06 10:18:03 +02:00
rdisc: backport rate-limiting failures to send router solicitations
https://bugzilla.gnome.org/show_bug.cgi?id=759596
This commit is contained in:
commit
645bf63e0b
6 changed files with 62 additions and 12 deletions
|
|
@ -59,6 +59,8 @@
|
|||
#define CLOCK_BOOTTIME 7
|
||||
#endif
|
||||
|
||||
G_DEFINE_QUARK (nm-utils-error-quark, nm_utils_error)
|
||||
|
||||
G_STATIC_ASSERT (sizeof (NMUtilsTestFlags) <= sizeof (int));
|
||||
int _nm_utils_testing = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -232,4 +232,25 @@ gboolean nm_utils_get_testing_initialized (void);
|
|||
NMUtilsTestFlags nm_utils_get_testing (void);
|
||||
void _nm_utils_set_testing (NMUtilsTestFlags flags);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* NMUtilsError:
|
||||
* @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
|
||||
* @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has
|
||||
* pending aynchronous operations, the operation is cancelled with this
|
||||
* error reason. Depending on the usage, this might indicate a bug because
|
||||
* usually the target object should stay alive as long as there are pending
|
||||
* operations.
|
||||
*/
|
||||
typedef enum {
|
||||
NM_UTILS_ERROR_UNKNOWN = 0, /*< nick=Unknown >*/
|
||||
NM_UTILS_ERROR_CANCELLED_DISPOSING, /*< nick=CancelledDisposing >*/
|
||||
} NMUtilsError;
|
||||
|
||||
#define NM_UTILS_ERROR (nm_utils_error_quark ())
|
||||
GQuark nm_utils_error_quark (void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NETWORKMANAGER_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ nm_fake_rdisc_done (NMFakeRDisc *self)
|
|||
/******************************************************************/
|
||||
|
||||
static gboolean
|
||||
send_rs (NMRDisc *rdisc)
|
||||
send_rs (NMRDisc *rdisc, GError **error)
|
||||
{
|
||||
g_signal_emit (rdisc, signals[RS_SENT], 0);
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -52,20 +52,28 @@ G_DEFINE_TYPE (NMLNDPRDisc, nm_lndp_rdisc, NM_TYPE_RDISC)
|
|||
/******************************************************************/
|
||||
|
||||
static gboolean
|
||||
send_rs (NMRDisc *rdisc)
|
||||
send_rs (NMRDisc *rdisc, GError **error)
|
||||
{
|
||||
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
|
||||
struct ndp_msg *msg;
|
||||
int error;
|
||||
int errsv;
|
||||
|
||||
error = ndp_msg_new (&msg, NDP_MSG_RS);
|
||||
g_assert (!error);
|
||||
errsv = ndp_msg_new (&msg, NDP_MSG_RS);
|
||||
if (errsv) {
|
||||
errsv = errsv > 0 ? errsv : -errsv;
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"cannot create router solicitation");
|
||||
return FALSE;
|
||||
}
|
||||
ndp_msg_ifindex_set (msg, rdisc->ifindex);
|
||||
|
||||
error = ndp_msg_send (priv->ndp, msg);
|
||||
errsv = ndp_msg_send (priv->ndp, msg);
|
||||
ndp_msg_destroy (msg);
|
||||
if (error) {
|
||||
error ("(%s): cannot send router solicitation: %d.", rdisc->ifname, error);
|
||||
if (errsv) {
|
||||
errsv = errsv > 0 ? errsv : -errsv;
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"%s (%d)",
|
||||
g_strerror (errsv), errsv);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ typedef struct {
|
|||
gint64 last_rs;
|
||||
guint ra_timeout_id; /* first RA timeout */
|
||||
guint timeout_id; /* prefix/dns/etc lifetime timeout */
|
||||
char *last_send_rs_error;
|
||||
} NMRDiscPrivate;
|
||||
|
||||
#define NM_RDISC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_RDISC, NMRDiscPrivate))
|
||||
|
|
@ -280,11 +281,25 @@ send_rs (NMRDisc *rdisc)
|
|||
{
|
||||
NMRDiscClass *klass = NM_RDISC_GET_CLASS (rdisc);
|
||||
NMRDiscPrivate *priv = NM_RDISC_GET_PRIVATE (rdisc);
|
||||
GError *error = NULL;
|
||||
|
||||
debug ("(%s): sending router solicitation", rdisc->ifname);
|
||||
|
||||
if (klass->send_rs (rdisc))
|
||||
if (klass->send_rs (rdisc, &error)) {
|
||||
debug ("(%s): router solicitation sent", rdisc->ifname);
|
||||
priv->solicitations_left--;
|
||||
g_clear_pointer (&priv->last_send_rs_error, g_free);
|
||||
} else {
|
||||
gboolean different_message;
|
||||
|
||||
different_message = g_strcmp0 (priv->last_send_rs_error, error->message) != 0;
|
||||
nm_log (different_message ? LOGL_WARN : LOGL_DEBUG, LOGD_IP6,
|
||||
"(%s): failure sending router solicitation: %s",
|
||||
rdisc->ifname, error->message);
|
||||
if (different_message) {
|
||||
g_clear_pointer (&priv->last_send_rs_error, g_free);
|
||||
priv->last_send_rs_error = g_strdup (error->message);
|
||||
}
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
priv->last_rs = nm_utils_get_monotonic_timestamp_s ();
|
||||
if (priv->solicitations_left > 0) {
|
||||
|
|
@ -581,8 +596,11 @@ timeout_cb (gpointer user_data)
|
|||
void
|
||||
nm_rdisc_ra_received (NMRDisc *rdisc, guint32 now, NMRDiscConfigMap changed)
|
||||
{
|
||||
NMRDiscPrivate *priv = NM_RDISC_GET_PRIVATE (rdisc);
|
||||
|
||||
clear_ra_timeout (rdisc);
|
||||
clear_rs_timeout (rdisc);
|
||||
g_clear_pointer (&priv->last_send_rs_error, g_free);
|
||||
check_timestamps (rdisc, now, changed);
|
||||
}
|
||||
|
||||
|
|
@ -621,6 +639,7 @@ dispose (GObject *object)
|
|||
|
||||
clear_ra_timeout (rdisc);
|
||||
clear_rs_timeout (rdisc);
|
||||
g_clear_pointer (&priv->last_send_rs_error, g_free);
|
||||
|
||||
if (priv->timeout_id) {
|
||||
g_source_remove (priv->timeout_id);
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ typedef struct {
|
|||
GObjectClass parent;
|
||||
|
||||
void (*start) (NMRDisc *rdisc);
|
||||
gboolean (*send_rs) (NMRDisc *rdisc);
|
||||
gboolean (*send_rs) (NMRDisc *rdisc, GError **error);
|
||||
void (*config_changed) (NMRDisc *rdisc, NMRDiscConfigMap changed);
|
||||
void (*ra_process) (NMRDisc *rdisc);
|
||||
void (*ra_timeout) (NMRDisc *rdisc);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue