policy: track autoconnect retries per Device x Connection

Autoconnect retries are not being tracked by connection anymore. Now it
is tracked per Device x Connection. In addition, autoconnect might be
blocked for the connection due to no secrets or user requested.

All the properties tracking the retries and blocked time were move to
DevConData and the functions to manipulate them aswell. In NMPolicy the
logic didn't change very much. Instead of looking into the connection
when the device failed activation it looks for DevConData.
This commit is contained in:
Fernando Fernandez Mancera 2023-02-15 10:35:08 +01:00
parent 51fe418cab
commit cee5959b7e
7 changed files with 413 additions and 194 deletions

View file

@ -240,7 +240,9 @@ ovsdb_interface_failed(NMOvsdb *ovsdb,
return;
if (connection) {
nm_settings_connection_autoconnect_blocked_reason_set(
nm_manager_devcon_autoconnect_blocked_reason_set(
nm_device_get_manager(device),
device,
connection,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
TRUE);

View file

@ -2302,9 +2302,10 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
* to reset the retry count so we set no timeout.
*/
if (priv->iwd_autoconnect) {
NMSettingsConnection *sett_conn = nm_act_request_get_settings_connection(req);
nm_settings_connection_autoconnect_retries_set(sett_conn, 0);
nm_manager_devcon_autoconnect_retries_set(nm_device_get_manager(device),
device,
nm_act_request_get_settings_connection(req),
0);
}
/* With priv->iwd_autoconnect, if we're assuming a connection because

View file

@ -69,11 +69,24 @@ typedef struct {
bool os_owner : 1;
} RfkillRadioState;
#define AUTOCONNECT_RESET_RETRIES_TIMER_SEC 300
typedef struct {
NMDevice *device;
NMSettingsConnection *sett_conn;
CList dev_lst;
CList con_lst;
/* Autoconnet retries needs to be tracked for each (device, connection)
* tuple because when a connection is a multiconnect one, each valid device
* must try to autoconnect the retries defined in the connection. */
struct {
guint32 retries;
gint32 blocked_until_sec;
NMSettingsAutoconnectBlockedReason blocked_reason;
bool initialized : 1;
} autoconnect;
} DevConData;
typedef enum {
@ -1226,6 +1239,228 @@ active_connection_get_by_path(NMManager *self, const char *path)
/*****************************************************************************/
static guint32
_autoconnect_retries_initial(NMSettingsConnection *sett_conn)
{
NMSettingConnection *s_con;
int retries = -1;
s_con = nm_connection_get_setting_connection(nm_settings_connection_get_connection(sett_conn));
if (s_con)
retries = nm_setting_connection_get_autoconnect_retries(s_con);
/* -1 means 'default' */
if (retries == -1)
retries = nm_config_data_get_autoconnect_retries_default(NM_CONFIG_GET_DATA);
nm_assert(retries >= 0 && ((guint) retries) <= ((guint) G_MAXINT32));
/* 0 means 'forever', which is translated to a retry count of -1 */
if (retries == 0)
return NM_AUTOCONNECT_RETRIES_FOREVER;
return (guint32) retries;
}
static void
_autoconnect_retries_set(NMManager *self, DevConData *data, guint32 retries, gboolean is_reset)
{
nm_assert(data);
if (data->autoconnect.retries != retries || !data->autoconnect.initialized) {
_LOGT(LOGD_SETTINGS,
"autoconnect: retries set %d%s for device %s",
retries,
is_reset ? " (reset)" : "",
nm_device_get_ip_iface(data->device));
data->autoconnect.initialized = TRUE;
data->autoconnect.retries = retries;
}
if (retries != 0) {
_LOGT(LOGD_SETTINGS,
"autoconnect: blocked time set to 0 for device %s%s",
nm_device_get_ip_iface(data->device),
is_reset ? " (reset)" : "");
data->autoconnect.blocked_until_sec = 0;
} else {
/* NOTE: the blocked time must be identical for all connections, otherwise
* the tracking of resetting the retry count in NMPolicy needs adjustment
* in _connection_autoconnect_retries_set() (as it would need to re-evaluate
* the next-timeout every time a connection gets blocked). */
data->autoconnect.blocked_until_sec =
nm_utils_get_monotonic_timestamp_sec() + AUTOCONNECT_RESET_RETRIES_TIMER_SEC;
_LOGT(LOGD_SETTINGS,
"autoconnect: blocked time set to %d for device %s%s",
data->autoconnect.blocked_until_sec,
nm_device_get_ip_iface(data->device),
is_reset ? " (reset)" : "");
}
}
/**
* nm_manager_devcon_autoconnect_retries_get:
* @self: the settings connection
*
* Returns the number of autoconnect retries left. If the value is
* not yet set, initialize it with the value from the connection or
* with the global default.
*/
guint32
nm_manager_devcon_autoconnect_retries_get(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn)
{
DevConData *data;
nm_assert(NM_IS_MANAGER(self));
nm_assert(NM_IS_DEVICE(device));
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
nm_assert(self == nm_device_get_manager(device));
nm_assert(self == nm_settings_connection_get_manager(sett_conn));
data = _devcon_lookup_data(self, device, sett_conn, TRUE);
if (G_UNLIKELY(!data->autoconnect.initialized)) {
_autoconnect_retries_set(self, data, _autoconnect_retries_initial(sett_conn), FALSE);
}
return data->autoconnect.retries;
}
void
nm_manager_devcon_autoconnect_retries_set(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn,
guint32 retries)
{
_autoconnect_retries_set(self,
_devcon_lookup_data(self, device, sett_conn, TRUE),
retries,
FALSE);
}
void
nm_manager_devcon_autoconnect_retries_reset(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn)
{
DevConData *data;
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
if (device)
_autoconnect_retries_set(self,
_devcon_lookup_data(self, device, sett_conn, TRUE),
_autoconnect_retries_initial(sett_conn),
TRUE);
else {
c_list_for_each_entry (data, &sett_conn->devcon_con_lst_head, con_lst)
_autoconnect_retries_set(self, data, _autoconnect_retries_initial(sett_conn), TRUE);
}
}
gint32
nm_manager_devcon_autoconnect_retries_blocked_until(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn)
{
DevConData *data;
gint32 min_stamp;
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
if (device) {
data = _devcon_lookup_data(self, device, sett_conn, TRUE);
return data->autoconnect.blocked_until_sec;
} else {
min_stamp = 0;
c_list_for_each_entry (data, &sett_conn->devcon_con_lst_head, con_lst) {
gint32 condev_stamp = data->autoconnect.blocked_until_sec;
if (condev_stamp == 0)
continue;
if (min_stamp == 0 || min_stamp > condev_stamp)
min_stamp = condev_stamp;
}
}
return min_stamp;
}
gboolean
nm_manager_devcon_autoconnect_is_blocked(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn)
{
DevConData *data;
nm_assert(NM_IS_DEVICE(device));
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
if (nm_settings_connection_autoconnect_is_blocked(sett_conn))
return TRUE;
data = _devcon_lookup_data(self, device, sett_conn, TRUE);
if (data->autoconnect.blocked_reason != NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE)
return TRUE;
if (data->autoconnect.retries == 0 && data->autoconnect.initialized)
return TRUE;
return FALSE;
}
gboolean
nm_manager_devcon_autoconnect_blocked_reason_set_full(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn,
NMSettingsAutoconnectBlockedReason mask,
NMSettingsAutoconnectBlockedReason value)
{
NMSettingsAutoconnectBlockedReason v;
DevConData *data;
gboolean changed = FALSE;
char buf[100];
nm_assert(mask);
nm_assert(sett_conn);
nm_assert(!NM_FLAGS_ANY(value, ~mask));
if (device) {
data = _devcon_lookup_data(self, device, sett_conn, TRUE);
v = data->autoconnect.blocked_reason;
v = (v & ~mask) | (value & mask);
if (data->autoconnect.blocked_reason == v)
return FALSE;
_LOGT(LOGD_SETTINGS,
"autoconnect: blocked reason: %s for device %s",
nm_settings_autoconnect_blocked_reason_to_string(v, buf, sizeof(buf)),
nm_device_get_ip_iface(device));
data->autoconnect.blocked_reason = v;
return TRUE;
} else {
c_list_for_each_entry (data, &sett_conn->devcon_con_lst_head, con_lst) {
v = data->autoconnect.blocked_reason;
v = (v & ~mask) | (value & mask);
if (data->autoconnect.blocked_reason == v)
continue;
_LOGT(LOGD_SETTINGS,
"autoconnect: blocked reason: %s for device %s",
nm_settings_autoconnect_blocked_reason_to_string(v, buf, sizeof(buf)),
nm_device_get_ip_iface(data->device));
data->autoconnect.blocked_reason = v;
changed = TRUE;
}
}
return changed;
}
/*****************************************************************************/
static guint
_devcon_data_hash(gconstpointer ptr)
{
@ -1280,6 +1515,10 @@ _devcon_lookup_data(NMManager *self,
*data = (DevConData){
.device = device,
.sett_conn = sett_conn,
.autoconnect =
{
.initialized = FALSE,
},
};
c_list_link_tail(&device->devcon_dev_lst_head, &data->dev_lst);
c_list_link_tail(&sett_conn->devcon_con_lst_head, &data->con_lst);

View file

@ -224,4 +224,51 @@ void nm_manager_device_auth_request(NMManager *self,
void nm_manager_unblock_failed_ovs_interfaces(NMManager *self);
/*****************************************************************************/
#define NM_AUTOCONNECT_RETRIES_FOREVER G_MAXUINT32
guint32 nm_manager_devcon_autoconnect_retries_get(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn);
void nm_manager_devcon_autoconnect_retries_set(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn,
guint32 retries);
void nm_manager_devcon_autoconnect_retries_reset(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn);
gint32 nm_manager_devcon_autoconnect_retries_blocked_until(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn);
gboolean nm_manager_devcon_autoconnect_is_blocked(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn);
gboolean
nm_manager_devcon_autoconnect_blocked_reason_set_full(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn,
NMSettingsAutoconnectBlockedReason mask,
NMSettingsAutoconnectBlockedReason value);
static inline gboolean
nm_manager_devcon_autoconnect_blocked_reason_set(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn,
NMSettingsAutoconnectBlockedReason mask,
gboolean set)
{
return nm_manager_devcon_autoconnect_blocked_reason_set_full(
self,
device,
sett_conn,
mask,
set ? mask : NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE);
}
#endif /* __NETWORKMANAGER_MANAGER_H__ */

View file

@ -1328,7 +1328,9 @@ pending_ac_state_changed(NMActiveConnection *ac, guint state, guint reason, NMPo
*/
if (reason != NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED) {
con = nm_active_connection_get_settings_connection(ac);
nm_settings_connection_autoconnect_blocked_reason_set(
nm_manager_devcon_autoconnect_blocked_reason_set(
priv->manager,
nm_active_connection_get_device(ac),
con,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
TRUE);
@ -1391,7 +1393,7 @@ auto_activate_device(NMPolicy *self, NMDevice *device)
NMSettingConnection *s_con;
const char *permission;
if (nm_settings_connection_autoconnect_is_blocked(candidate))
if (nm_manager_devcon_autoconnect_is_blocked(priv->manager, device, candidate))
continue;
cand_conn = nm_settings_connection_get_connection(candidate);
@ -1435,7 +1437,9 @@ auto_activate_device(NMPolicy *self, NMDevice *device)
"connection '%s' auto-activation failed: %s",
nm_settings_connection_get_id(best_connection),
error->message);
nm_settings_connection_autoconnect_blocked_reason_set(
nm_manager_devcon_autoconnect_blocked_reason_set(
priv->manager,
device,
best_connection,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
TRUE);
@ -1600,8 +1604,10 @@ nm_policy_unblock_failed_ovs_interfaces(NMPolicy *self)
NMConnection *connection = nm_settings_connection_get_connection(sett_conn);
if (nm_connection_get_setting_ovs_interface(connection)) {
nm_settings_connection_autoconnect_retries_reset(sett_conn);
nm_settings_connection_autoconnect_blocked_reason_set(
nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn);
nm_manager_devcon_autoconnect_blocked_reason_set(
priv->manager,
NULL,
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
FALSE);
@ -1646,21 +1652,36 @@ reset_autoconnect_all(
/* maybe the connection is still blocked afterwards for other reasons
* and in the larger picture nothing changed. But it's too complicated
* to find out exactly. Just assume, something changed to be sure. */
if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
if (device) {
if (!nm_manager_devcon_autoconnect_is_blocked(priv->manager, device, sett_conn))
changed = TRUE;
} else if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
changed = TRUE;
}
} else {
/* we reset the tries-count and any blocked-reason */
if (nm_settings_connection_autoconnect_retries_get(sett_conn) == 0)
if (device
&& nm_manager_devcon_autoconnect_retries_get(priv->manager, device, sett_conn) == 0)
changed = TRUE;
nm_settings_connection_autoconnect_retries_reset(sett_conn);
nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn);
if (nm_settings_connection_autoconnect_blocked_reason_set(
if ((device
&& nm_manager_devcon_autoconnect_blocked_reason_set(
priv->manager,
device,
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED
| NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
FALSE))
|| nm_settings_connection_autoconnect_blocked_reason_set(
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_ALL
& ~NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS
| NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
FALSE)) {
if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
if (device) {
if (!nm_manager_devcon_autoconnect_is_blocked(priv->manager, device, sett_conn))
changed = TRUE;
} else if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
changed = TRUE;
}
}
@ -1737,12 +1758,13 @@ reset_connections_retries(gpointer user_data)
for (i = 0; connections[i]; i++) {
NMSettingsConnection *connection = connections[i];
con_stamp = nm_settings_connection_autoconnect_retries_blocked_until(connection);
con_stamp =
nm_manager_devcon_autoconnect_retries_blocked_until(priv->manager, NULL, connection);
if (con_stamp == 0)
continue;
if (con_stamp <= now) {
nm_settings_connection_autoconnect_retries_reset(connection);
nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, connection);
changed = TRUE;
} else if (min_stamp == 0 || min_stamp > con_stamp)
min_stamp = con_stamp;
@ -1761,20 +1783,23 @@ reset_connections_retries(gpointer user_data)
}
static void
_connection_autoconnect_retries_set(NMPolicy *self, NMSettingsConnection *connection, int tries)
_connection_autoconnect_retries_set(NMPolicy *self,
NMDevice *device,
NMSettingsConnection *connection,
guint32 tries)
{
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
nm_assert(NM_IS_SETTINGS_CONNECTION(connection));
nm_assert(tries >= 0);
nm_settings_connection_autoconnect_retries_set(connection, tries);
nm_manager_devcon_autoconnect_retries_set(priv->manager, device, connection, tries);
if (tries == 0) {
/* Schedule a handler to reset retries count */
if (!priv->reset_retries_id) {
gint32 retry_time =
nm_settings_connection_autoconnect_retries_blocked_until(connection);
gint32 retry_time = nm_manager_devcon_autoconnect_retries_blocked_until(priv->manager,
device,
connection);
g_warn_if_fail(retry_time != 0);
priv->reset_retries_id =
@ -1839,11 +1864,14 @@ activate_slave_connections(NMPolicy *self, NMDevice *device)
continue;
if (!internal_activation) {
if (nm_settings_connection_autoconnect_retries_get(sett_conn) == 0)
changed = TRUE;
nm_settings_connection_autoconnect_retries_reset(sett_conn);
nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn);
/* we cannot know if they changed or not, so considering we did a reset, let's consider they changed. */
changed = TRUE;
}
if (nm_settings_connection_autoconnect_blocked_reason_set(
/* unblock the devices associated with that connection */
if (nm_manager_devcon_autoconnect_blocked_reason_set(
priv->manager,
NULL,
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
FALSE)) {
@ -1968,7 +1996,9 @@ device_state_changed(NMDevice *device,
* a missing SIM or wrong modem initialization).
*/
if (sett_conn) {
nm_settings_connection_autoconnect_blocked_reason_set(
nm_manager_devcon_autoconnect_blocked_reason_set(
priv->manager,
device,
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
TRUE);
@ -1988,7 +2018,6 @@ device_state_changed(NMDevice *device,
if (sett_conn && old_state >= NM_DEVICE_STATE_PREPARE
&& old_state <= NM_DEVICE_STATE_ACTIVATED) {
gboolean blocked = FALSE;
int tries;
guint64 con_v;
if (nm_device_state_reason_check(reason) == NM_DEVICE_STATE_REASON_NO_SECRETS) {
@ -2029,7 +2058,9 @@ device_state_changed(NMDevice *device,
_LOGD(LOGD_DEVICE,
"connection '%s' now blocked from autoconnect due to failed dependency",
nm_settings_connection_get_id(sett_conn));
nm_settings_connection_autoconnect_blocked_reason_set(
nm_manager_devcon_autoconnect_blocked_reason_set(
priv->manager,
device,
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
TRUE);
@ -2037,14 +2068,18 @@ device_state_changed(NMDevice *device,
}
if (!blocked) {
tries = nm_settings_connection_autoconnect_retries_get(sett_conn);
if (tries > 0) {
guint32 tries;
tries = nm_manager_devcon_autoconnect_retries_get(priv->manager, device, sett_conn);
if (tries == 0) {
/* blocked */
} else if (tries != NM_AUTOCONNECT_RETRIES_FOREVER) {
_LOGD(LOGD_DEVICE,
"connection '%s' failed to autoconnect; %d tries left",
"connection '%s' failed to autoconnect; %u tries left",
nm_settings_connection_get_id(sett_conn),
tries - 1);
_connection_autoconnect_retries_set(self, sett_conn, tries - 1);
} else if (tries != 0) {
tries - 1u);
_connection_autoconnect_retries_set(self, device, sett_conn, tries - 1u);
} else {
_LOGD(LOGD_DEVICE,
"connection '%s' failed to autoconnect; infinite tries left",
nm_settings_connection_get_id(sett_conn));
@ -2055,7 +2090,7 @@ device_state_changed(NMDevice *device,
case NM_DEVICE_STATE_ACTIVATED:
if (sett_conn) {
/* Reset auto retries back to default since connection was successful */
nm_settings_connection_autoconnect_retries_reset(sett_conn);
nm_manager_devcon_autoconnect_retries_reset(priv->manager, device, sett_conn);
}
/* Since there is no guarantee that device_l3cd_changed() is called
@ -2105,9 +2140,16 @@ device_state_changed(NMDevice *device,
nm_settings_connection_get_id(sett_conn),
NM_UTILS_LOOKUP_STR_A(nm_device_state_reason_to_string,
nm_device_state_reason_check(reason)));
nm_settings_connection_autoconnect_blocked_reason_set(sett_conn,
blocked_reason,
TRUE);
if (blocked_reason == NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED)
nm_manager_devcon_autoconnect_blocked_reason_set(priv->manager,
device,
sett_conn,
blocked_reason,
TRUE);
else
nm_settings_connection_autoconnect_blocked_reason_set(sett_conn,
blocked_reason,
TRUE);
}
}
ip6_remove_device_prefix_delegations(self, device);
@ -2146,7 +2188,9 @@ device_state_changed(NMDevice *device,
case NM_DEVICE_STATE_IP_CONFIG:
/* We must have secrets if we got here. */
if (sett_conn)
nm_settings_connection_autoconnect_blocked_reason_set(
nm_manager_devcon_autoconnect_blocked_reason_set(
priv->manager,
device,
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_ALL,
FALSE);

View file

@ -24,13 +24,10 @@
#include "libnm-core-intern/nm-core-internal.h"
#include "nm-audit-manager.h"
#include "nm-settings.h"
#include "nm-manager.h"
#include "nm-dbus-manager.h"
#include "settings/plugins/keyfile/nms-keyfile-storage.h"
#define AUTOCONNECT_RETRIES_UNSET -2
#define AUTOCONNECT_RETRIES_FOREVER -1
#define AUTOCONNECT_RESET_RETRIES_TIMER 300
#define SEEN_BSSIDS_MAX 30
#define _NM_SETTINGS_UPDATE2_FLAG_ALL_PERSIST_MODES \
@ -159,16 +156,12 @@ typedef struct _NMSettingsConnectionPrivate {
guint64 last_secret_agent_version_id;
int autoconnect_retries;
gint32 autoconnect_retries_blocked_until;
bool timestamp_set : 1;
NMSettingsAutoconnectBlockedReason autoconnect_blocked_reason : 4;
NMSettingsConnectionIntFlags flags : 5;
NMSettingsAutoconnectBlockedReason autoconnect_blocked_reason : 4;
} NMSettingsConnectionPrivate;
struct _NMSettingsConnectionClass {
@ -1461,52 +1454,6 @@ update_complete(NMSettingsConnection *self, UpdateInfo *info, GError *error)
g_slice_free(UpdateInfo, info);
}
static int
_autoconnect_retries_initial(NMSettingsConnection *self)
{
NMSettingConnection *s_con;
int retries = -1;
s_con = nm_connection_get_setting_connection(nm_settings_connection_get_connection(self));
if (s_con)
retries = nm_setting_connection_get_autoconnect_retries(s_con);
/* -1 means 'default' */
if (retries == -1)
retries = nm_config_data_get_autoconnect_retries_default(NM_CONFIG_GET_DATA);
/* 0 means 'forever', which is translated to a retry count of -1 */
if (retries == 0)
retries = AUTOCONNECT_RETRIES_FOREVER;
nm_assert(retries == AUTOCONNECT_RETRIES_FOREVER || retries >= 0);
return retries;
}
static void
_autoconnect_retries_set(NMSettingsConnection *self, int retries, gboolean is_reset)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
g_return_if_fail(retries == AUTOCONNECT_RETRIES_FOREVER || retries >= 0);
if (priv->autoconnect_retries != retries) {
_LOGT("autoconnect: retries set %d%s", retries, is_reset ? " (reset)" : "");
priv->autoconnect_retries = retries;
}
if (retries)
priv->autoconnect_retries_blocked_until = 0;
else {
/* NOTE: the blocked time must be identical for all connections, otherwise
* the tracking of resetting the retry count in NMPolicy needs adjustment
* in _connection_autoconnect_retries_set() (as it would need to re-evaluate
* the next-timeout every time a connection gets blocked). */
priv->autoconnect_retries_blocked_until =
nm_utils_get_monotonic_timestamp_sec() + AUTOCONNECT_RESET_RETRIES_TIMER;
}
}
static void
update_auth_cb(NMSettingsConnection *self,
GDBusMethodInvocation *context,
@ -1557,8 +1504,11 @@ update_auth_cb(NMSettingsConnection *self,
self,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS,
FALSE)
&& !nm_settings_connection_autoconnect_blocked_reason_get(self))
nm_settings_connection_autoconnect_retries_reset(self);
&& !nm_settings_connection_autoconnect_is_blocked(self))
nm_manager_devcon_autoconnect_retries_reset(
nm_settings_connection_get_manager(self),
NULL,
self);
}
}
@ -1631,7 +1581,9 @@ update_auth_cb(NMSettingsConnection *self,
}
/* Reset auto retries back to default since connection was updated */
nm_settings_connection_autoconnect_retries_reset(self);
nm_manager_devcon_autoconnect_retries_reset(nm_settings_connection_get_manager(self),
NULL,
self);
update_complete(self, info, local);
}
@ -2550,46 +2502,27 @@ nm_settings_connection_add_seen_bssid(NMSettingsConnection *self, const char *se
/*****************************************************************************/
/**
* nm_settings_connection_autoconnect_retries_get:
* @self: the settings connection
*
* Returns the number of autoconnect retries left. If the value is
* not yet set, initialize it with the value from the connection or
* with the global default.
*/
int
nm_settings_connection_autoconnect_retries_get(NMSettingsConnection *self)
gboolean
nm_settings_connection_autoconnect_blocked_reason_set(NMSettingsConnection *self,
NMSettingsAutoconnectBlockedReason reason,
gboolean set)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
NMSettingsAutoconnectBlockedReason v;
char buf[100];
if (G_UNLIKELY(priv->autoconnect_retries == AUTOCONNECT_RETRIES_UNSET)) {
_autoconnect_retries_set(self, _autoconnect_retries_initial(self), TRUE);
v = priv->autoconnect_blocked_reason;
if (set) {
priv->autoconnect_blocked_reason = priv->autoconnect_blocked_reason | reason;
_LOGD("autoconnect: blocked reason: %s",
nm_settings_autoconnect_blocked_reason_to_string(reason, buf, sizeof(buf)));
return v != priv->autoconnect_blocked_reason;
} else {
priv->autoconnect_blocked_reason = priv->autoconnect_blocked_reason & ~reason;
_LOGD("autoconnect: unblocked reason: %s",
nm_settings_autoconnect_blocked_reason_to_string(reason, buf, sizeof(buf)));
return v != priv->autoconnect_blocked_reason;
}
return priv->autoconnect_retries;
}
void
nm_settings_connection_autoconnect_retries_set(NMSettingsConnection *self, int retries)
{
g_return_if_fail(NM_IS_SETTINGS_CONNECTION(self));
g_return_if_fail(retries >= 0);
_autoconnect_retries_set(self, retries, FALSE);
}
void
nm_settings_connection_autoconnect_retries_reset(NMSettingsConnection *self)
{
g_return_if_fail(NM_IS_SETTINGS_CONNECTION(self));
_autoconnect_retries_set(self, _autoconnect_retries_initial(self), TRUE);
}
gint32
nm_settings_connection_autoconnect_retries_blocked_until(NMSettingsConnection *self)
{
return NM_SETTINGS_CONNECTION_GET_PRIVATE(self)->autoconnect_retries_blocked_until;
}
NMSettingsAutoconnectBlockedReason
@ -2598,30 +2531,6 @@ nm_settings_connection_autoconnect_blocked_reason_get(NMSettingsConnection *self
return NM_SETTINGS_CONNECTION_GET_PRIVATE(self)->autoconnect_blocked_reason;
}
gboolean
nm_settings_connection_autoconnect_blocked_reason_set_full(NMSettingsConnection *self,
NMSettingsAutoconnectBlockedReason mask,
NMSettingsAutoconnectBlockedReason value)
{
NMSettingsAutoconnectBlockedReason v;
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
char buf[100];
nm_assert(mask);
nm_assert(!NM_FLAGS_ANY(value, ~mask));
v = priv->autoconnect_blocked_reason;
v = (v & ~mask) | (value & mask);
if (priv->autoconnect_blocked_reason == v)
return FALSE;
_LOGT("autoconnect: blocked reason: %s",
nm_settings_autoconnect_blocked_reason_to_string(v, buf, sizeof(buf)));
priv->autoconnect_blocked_reason = v;
return TRUE;
}
gboolean
nm_settings_connection_autoconnect_is_blocked(NMSettingsConnection *self)
{
@ -2630,22 +2539,17 @@ nm_settings_connection_autoconnect_is_blocked(NMSettingsConnection *self)
g_return_val_if_fail(NM_IS_SETTINGS_CONNECTION(self), TRUE);
priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
if (priv->autoconnect_blocked_reason != NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE)
return TRUE;
if (priv->autoconnect_retries == 0)
return TRUE;
flags = priv->flags;
priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
flags = nm_settings_connection_get_flags(self);
if (NM_FLAGS_ANY(flags,
NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE
| NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL))
return TRUE;
if (!NM_FLAGS_HAS(flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE))
return TRUE;
return FALSE;
return priv->autoconnect_blocked_reason != NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE;
}
/*****************************************************************************/
@ -2755,8 +2659,6 @@ nm_settings_connection_init(NMSettingsConnection *self)
priv->agent_mgr = g_object_ref(nm_agent_manager_get());
priv->settings = g_object_ref(nm_settings_get());
priv->autoconnect_retries = AUTOCONNECT_RETRIES_UNSET;
}
NMSettingsConnection *

View file

@ -338,31 +338,15 @@ gboolean nm_settings_connection_has_seen_bssid(NMSettingsConnection *self, const
void nm_settings_connection_add_seen_bssid(NMSettingsConnection *self, const char *seen_bssid);
int nm_settings_connection_autoconnect_retries_get(NMSettingsConnection *self);
void nm_settings_connection_autoconnect_retries_set(NMSettingsConnection *self, int retries);
void nm_settings_connection_autoconnect_retries_reset(NMSettingsConnection *self);
gboolean nm_settings_connection_autoconnect_is_blocked(NMSettingsConnection *self);
gint32 nm_settings_connection_autoconnect_retries_blocked_until(NMSettingsConnection *self);
gboolean
nm_settings_connection_autoconnect_blocked_reason_set(NMSettingsConnection *self,
NMSettingsAutoconnectBlockedReason reason,
gboolean set);
NMSettingsAutoconnectBlockedReason
nm_settings_connection_autoconnect_blocked_reason_get(NMSettingsConnection *self);
gboolean nm_settings_connection_autoconnect_blocked_reason_set_full(
NMSettingsConnection *self,
NMSettingsAutoconnectBlockedReason mask,
NMSettingsAutoconnectBlockedReason value);
static inline gboolean
nm_settings_connection_autoconnect_blocked_reason_set(NMSettingsConnection *self,
NMSettingsAutoconnectBlockedReason mask,
gboolean set)
{
return nm_settings_connection_autoconnect_blocked_reason_set_full(
self,
mask,
set ? mask : NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE);
}
gboolean nm_settings_connection_autoconnect_is_blocked(NMSettingsConnection *self);
nm_settings_connection_autoconnect_blocked_reason_get(NMSettingsConnection *self);
const char *nm_settings_connection_get_id(NMSettingsConnection *connection);
const char *nm_settings_connection_get_uuid(NMSettingsConnection *connection);