From 8f7e295cbf98ca220fbd13336bb0cdd4d477bd27 Mon Sep 17 00:00:00 2001 From: "Francisco Blas Izquierdo Riera (klondike)" Date: Tue, 5 Apr 2022 22:41:51 +0200 Subject: [PATCH] bridge: fix reentrant call for bluetooth NAP bridge Currently NetworkManager fails to establish a NAP bridge because it never gets out of the stage2. This is caused because when making the BlueZ callback reentrant we return NM_ACT_STAGE_RETURN_POSTPONE even after registration has succeeded. This patch changes registration to a three state automaton instead of a boolean. This allows distinguishing when we are waiting for registration to finish and when it is done and therefore ensures that when the stage2 is called again by the callback the result is success so NetworkManager can proceed to the IP configuration. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1181 --- src/core/devices/nm-device-bridge.c | 31 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index 466f075691..f11c172abb 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -22,11 +22,17 @@ /*****************************************************************************/ +enum _NMBtCbState { + _NM_BT_CB_STATE_NONE = 0, /* Registration not done */ + _NM_BT_CB_STATE_WAIT = 1, /* Waiting for the callback */ + _NM_BT_CB_STATE_SUCCESS = 2, /* Callback succeeded */ +}; + struct _NMDeviceBridge { NMDevice parent; GCancellable *bt_cancellable; bool vlan_configured : 1; - bool bt_registered : 1; + unsigned bt_cb_state : 2; }; struct _NMDeviceBridgeClass { @@ -76,7 +82,8 @@ check_connection_available(NMDevice *device, if (!nm_bt_vtable_network_server->is_available( nm_bt_vtable_network_server, bdaddr, - (self->bt_cancellable || self->bt_registered) ? device : NULL)) { + (self->bt_cancellable || self->bt_cb_state != _NM_BT_CB_STATE_NONE) ? device + : NULL)) { if (bdaddr) nm_utils_error_set(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, @@ -880,6 +887,7 @@ _bt_register_bridge_cb(GError *error, gpointer user_data) return; } + self->bt_cb_state = _NM_BT_CB_STATE_SUCCESS; nm_device_activate_schedule_stage2_device_config(NM_DEVICE(self), FALSE); } @@ -891,12 +899,12 @@ _nm_device_bridge_notify_unregister_bt_nap(NMDevice *device, const char *reason) _LOGD(LOGD_DEVICE, "bluetooth NAP server unregistered from bridge: %s%s", reason, - self->bt_registered ? "" : " (was no longer registered)"); + self->bt_cb_state != _NM_BT_CB_STATE_NONE ? "" : " (was no longer registered)"); nm_clear_g_cancellable(&self->bt_cancellable); - if (self->bt_registered) { - self->bt_registered = FALSE; + if (self->bt_cb_state != _NM_BT_CB_STATE_NONE) { + self->bt_cb_state = _NM_BT_CB_STATE_NONE; nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BT_FAILED); } } @@ -924,9 +932,12 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) if (self->bt_cancellable) return NM_ACT_STAGE_RETURN_POSTPONE; - if (self->bt_registered) + if (self->bt_cb_state == _NM_BT_CB_STATE_WAIT) return NM_ACT_STAGE_RETURN_POSTPONE; + if (self->bt_cb_state == _NM_BT_CB_STATE_SUCCESS) + return NM_ACT_STAGE_RETURN_SUCCESS; + self->bt_cancellable = g_cancellable_new(); if (!nm_bt_vtable_network_server->register_bridge(nm_bt_vtable_network_server, nm_setting_bluetooth_get_bdaddr(s_bt), @@ -940,7 +951,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) return NM_ACT_STAGE_RETURN_FAILURE; } - self->bt_registered = TRUE; + self->bt_cb_state = _NM_BT_CB_STATE_WAIT; return NM_ACT_STAGE_RETURN_POSTPONE; } @@ -951,14 +962,14 @@ deactivate(NMDevice *device) _LOGD(LOGD_DEVICE, "deactivate bridge%s", - self->bt_registered ? " (registered as NAP bluetooth device)" : ""); + self->bt_cb_state != _NM_BT_CB_STATE_NONE ? " (registered as NAP bluetooth device)" : ""); self->vlan_configured = FALSE; nm_clear_g_cancellable(&self->bt_cancellable); - if (self->bt_registered) { - self->bt_registered = FALSE; + if (self->bt_cb_state != _NM_BT_CB_STATE_NONE) { + self->bt_cb_state = _NM_BT_CB_STATE_NONE; nm_bt_vtable_network_server->unregister_bridge(nm_bt_vtable_network_server, device); } }