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 10c38eabb9
commit b73b34c3ee
7 changed files with 442 additions and 196 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,292 @@ 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);
if (retries == -1)
retries = nm_config_data_get_autoconnect_retries_default(NM_CONFIG_GET_DATA);
nm_assert(retries >= 0 && ((guint) retries) <= ((guint) G_MAXINT32));
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: device[%p] (%s): retries set %d%s",
data->device,
nm_device_get_ip_iface(data->device),
retries,
is_reset ? " (reset)" : "");
data->autoconnect.initialized = TRUE;
data->autoconnect.retries = retries;
}
if (retries != 0) {
_LOGT(LOGD_SETTINGS,
"autoconnect: device[%p] (%s): no longer block autoconnect (due to retry count) %s",
data->device,
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: device[%p] (%s): block autoconnect due to retry count for %d seconds",
data->device,
nm_device_get_ip_iface(data->device),
AUTOCONNECT_RESET_RETRIES_TIMER_SEC);
}
}
/**
* nm_manager_devcon_autoconnect_retries_get:
* @self: the #NMManager
* @device: the #NMDevice
* @sett_conn: the #NMSettingsConnection
*
* Returns the number of autoconnect retries left for the (device, connection)
* tuple. 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);
}
}
/**
* nm_manager_devcon_autoconnect_reset_reconnect_all:
* @self: the #NMManager
* @device: the #NMDevice
* @sett_conn: the #NMSettingsConnection
* @only_no_secrets: boolean to reset all reasons or only no secrets.
*
* Returns a boolean indicating if something changed or not when resetting the
* blocked reasons. If a #NMDevice is present then we also reset the reasons
* for the (device, connection) tuple.
*/
gboolean
nm_manager_devcon_autoconnect_reset_reconnect_all(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn,
gboolean only_no_secrets)
{
gboolean changed = FALSE;
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
if (only_no_secrets) {
/* we only reset the no-secrets blocked flag. */
if (nm_settings_connection_autoconnect_blocked_reason_set(
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS,
FALSE)) {
/* maybe the connection is still blocked afterwards for other reasons
* and in the larger picture nothing changed. Check if the connection
* is still blocked or not. */
if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
changed = TRUE;
}
return changed;
}
/* we reset the tries-count and any blocked-reason */
nm_manager_devcon_autoconnect_retries_reset(self, NULL, sett_conn);
/* if there is a device and we changed the state, then something changed. */
if (device
&& nm_manager_devcon_autoconnect_blocked_reason_set(
self,
device,
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED
| NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
FALSE))
changed = TRUE;
/* we remove all the blocked reason from the connection, if something
* happened, then it means the status changed */
if (nm_settings_connection_autoconnect_blocked_reason_set(
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS
| NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
FALSE))
changed = TRUE;
return changed;
}
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(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn,
NMSettingsAutoconnectBlockedReason value,
gboolean set)
{
NMSettingsAutoconnectBlockedReason v;
DevConData *data;
gboolean changed = FALSE;
char buf[100];
nm_assert(value);
nm_assert(sett_conn);
if (device) {
data = _devcon_lookup_data(self, device, sett_conn, TRUE);
v = data->autoconnect.blocked_reason;
v = NM_FLAGS_ASSIGN(v, value, set);
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;
}
c_list_for_each_entry (data, &sett_conn->devcon_con_lst_head, con_lst) {
v = data->autoconnect.blocked_reason;
v = NM_FLAGS_ASSIGN(v, value, set);
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 +1579,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);
@ -1325,7 +1628,7 @@ static gboolean
_devcon_remove_sett_conn_all(NMManager *self, NMSettingsConnection *sett_conn)
{
DevConData *data;
gboolean changed;
gboolean changed = FALSE;
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));

View file

@ -224,4 +224,40 @@ 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);
gboolean nm_manager_devcon_autoconnect_reset_reconnect_all(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn,
gboolean only_no_secrets);
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(NMManager *self,
NMDevice *device,
NMSettingsConnection *sett_conn,
NMSettingsAutoconnectBlockedReason value,
gboolean set);
#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);
@ -1637,33 +1643,11 @@ reset_autoconnect_all(
NULL))
continue;
if (only_no_secrets) {
/* we only reset the no-secrets blocked flag. */
if (nm_settings_connection_autoconnect_blocked_reason_set(
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS,
FALSE)) {
/* 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))
changed = TRUE;
}
} else {
/* we reset the tries-count and any blocked-reason */
if (nm_settings_connection_autoconnect_retries_get(sett_conn) == 0)
changed = TRUE;
nm_settings_connection_autoconnect_retries_reset(sett_conn);
if (nm_settings_connection_autoconnect_blocked_reason_set(
sett_conn,
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_ALL
& ~NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
FALSE)) {
if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
changed = TRUE;
}
}
if (nm_manager_devcon_autoconnect_reset_reconnect_all(priv->manager,
device,
sett_conn,
only_no_secrets))
changed = TRUE;
}
return changed;
}
@ -1737,12 +1721,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 +1746,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 +1827,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 +1959,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 +1981,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) {
@ -2027,9 +2019,13 @@ device_state_changed(NMDevice *device,
* dependency-failed.
*/
_LOGD(LOGD_DEVICE,
"connection '%s' now blocked from autoconnect due to failed dependency",
"autoconnect: connection[%p] (%s) now blocked from autoconnect due to failed "
"dependency",
sett_conn,
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,16 +2033,23 @@ 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",
"autoconnect: connection[%p] (%s): failed to autoconnect; %u tries left",
sett_conn,
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",
"autoconnect: connection[%p] (%s) failed to autoconnect; infinite tries "
"left",
sett_conn,
nm_settings_connection_get_id(sett_conn));
}
}
@ -2055,7 +2058,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 +2108,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_AUTO_CONNECT_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 +2156,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,10 +156,6 @@ 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;
@ -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,
@ -1558,7 +1505,10 @@ update_auth_cb(NMSettingsConnection *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_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,48 +2502,6 @@ 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)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
if (G_UNLIKELY(priv->autoconnect_retries == AUTOCONNECT_RETRIES_UNSET)) {
_autoconnect_retries_set(self, _autoconnect_retries_initial(self), TRUE);
}
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
nm_settings_connection_autoconnect_blocked_reason_get(NMSettingsConnection *self)
{
@ -2599,25 +2509,27 @@ nm_settings_connection_autoconnect_blocked_reason_get(NMSettingsConnection *self
}
gboolean
nm_settings_connection_autoconnect_blocked_reason_set_full(NMSettingsConnection *self,
NMSettingsAutoconnectBlockedReason mask,
NMSettingsAutoconnectBlockedReason value)
nm_settings_connection_autoconnect_blocked_reason_set(NMSettingsConnection *self,
NMSettingsAutoconnectBlockedReason reason,
gboolean set)
{
NMSettingsAutoconnectBlockedReason v;
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
char buf[100];
char buf1[100];
char buf2[100];
nm_assert(mask);
nm_assert(!NM_FLAGS_ANY(value, ~mask));
nm_assert(reason);
v = priv->autoconnect_blocked_reason;
v = (v & ~mask) | (value & mask);
v = NM_FLAGS_ASSIGN(v, reason, set);
if (priv->autoconnect_blocked_reason == v)
return FALSE;
_LOGT("autoconnect: blocked reason: %s",
nm_settings_autoconnect_blocked_reason_to_string(v, buf, sizeof(buf)));
_LOGD("autoconnect: %s blocked reason: %s (now %s)",
set ? "set" : "unset",
nm_settings_autoconnect_blocked_reason_to_string(reason, buf1, sizeof(buf1)),
nm_settings_autoconnect_blocked_reason_to_string(v, buf2, sizeof(buf2)));
priv->autoconnect_blocked_reason = v;
return TRUE;
}
@ -2634,8 +2546,6 @@ nm_settings_connection_autoconnect_is_blocked(NMSettingsConnection *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;
if (NM_FLAGS_ANY(flags,
@ -2755,8 +2665,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);
gint32 nm_settings_connection_autoconnect_retries_blocked_until(NMSettingsConnection *self);
gboolean nm_settings_connection_autoconnect_is_blocked(NMSettingsConnection *self);
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);
nm_settings_connection_autoconnect_blocked_reason_get(NMSettingsConnection *self);
static inline gboolean
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);
NMSettingsAutoconnectBlockedReason reason,
gboolean set);
const char *nm_settings_connection_get_id(NMSettingsConnection *connection);
const char *nm_settings_connection_get_uuid(NMSettingsConnection *connection);