Re: [PATCH v1] gdbus: Skip BLE random-address devices and remove broad match rule
Xiuzhuo Shang <[email protected]> Mon, 13 Jul 2026 14:03:26 +0800
| Newsgroups | dev.linux.lists.ofono,org.kernel.vger.linux-bluetooth |
|---|---|
| Message-ID | <[email protected]> |
On 7/10/2026 10:12 PM, Luiz Augusto von Dentz wrote: > Hi Xiuzhuo, > > On Fri, Jul 10, 2026 at 3:55 AM Xiuzhuo Shang > <[email protected]> wrote: >> >> Two related changes to reduce dbus-daemon load caused by high-rate >> BLE advertising signals: >> >> 1. In parse_properties(), skip creating a GDBusProxy for Device1 >> objects whose AddressType is 'random' (BLE-only devices). Each >> proxy registers a per-device PropertiesChanged watch via >> g_dbus_add_properties_watch(); with hundreds of BLE peripherals >> advertising simultaneously, this results in hundreds of match rules >> and dbus-daemon routing thousands of RSSI PropertiesChanged signals >> per second to ofono, none of which ofono processes. The >> AddressType property is available in the InterfacesAdded dict at >> the time parse_properties() is called, so the check is reliable >> and race-free. >> >> BR/EDR devices (AddressType='public') are unaffected: their proxies >> are created as before, and the property_changed callback continues >> to receive Paired and ServicesResolved updates needed for HFP/HSP. >> >> 2. In g_dbus_client_new_full(), remove the broad >> type='signal',sender=<service>,path_namespace=<path> match rule. >> This rule was the sole feeder for the signal_func path in >> message_filter(). ofono never calls g_dbus_client_set_signal_watch() >> so signal_func is always NULL; the broad rule therefore served no >> purpose and caused dbus-daemon to route every bluetoothd signal >> (including all BLE PropertiesChanged) to ofono. >> >> InterfacesAdded and InterfacesRemoved are already covered by the >> precise watches registered via g_dbus_add_signal_watch() earlier in >> g_dbus_client_new_full(), so no functionality is lost. > > Looks like this is on ofono though, why are you chaning the BlueZ side? Regarding your suggestion to move the BLE filter to hfp_hf_bluez5.c: filtering in proxy_added() would only prevent ofono from processing BLE devices at the application level. The per-device PropertiesChanged watch is registered inside proxy_new(), which is called before proxy_added(). So dbus-daemon would still route all RSSI signals to the process — the D-Bus pressure problem would remain unchanged. I will drop the change from the gdbus patch per your feedback > >> Together these two changes prevent dbus-daemon from routing BLE >> advertising PropertiesChanged signals to ofono entirely, eliminating >> the dbus-daemon memory growth and bluetoothd socket backpressure seen >> after hours of BLE scanning. >> >> Signed-off-by: Xiuzhuo Shang <[email protected]> >> --- >> gdbus/client.c | 46 ++++++++++++++++++++++++++++++++++++++-------- >> 1 file changed, 38 insertions(+), 8 deletions(-) >> >> diff --git a/gdbus/client.c b/gdbus/client.c >> index 48711ae8..dd3c17f9 100644 >> --- a/gdbus/client.c >> +++ b/gdbus/client.c >> @@ -937,6 +937,44 @@ static void parse_properties(GDBusClient *client, const char *path, >> if (g_str_equal(interface, DBUS_INTERFACE_PROPERTIES) == TRUE) >> return; >> >> + /* >> + * Skip BLE devices (AddressType='random') to avoid registering a >> + * per-device PropertiesChanged watch for every advertising BLE >> + * peripheral. ofono only needs BR/EDR devices for HFP/HSP; the >> + * high-rate RSSI PropertiesChanged signals from BLE scanners cause >> + * dbus-daemon memory bloat and socket backpressure in bluetoothd. >> + * >> + * The AddressType property is present in the InterfacesAdded dict >> + * (iter) at this point, so it can be checked before proxy_new(). >> + */ >> + if (g_str_equal(interface, "org.bluez.Device1") == TRUE) { >> + DBusMessageIter props, entry; >> + DBusMessageIter copy = *iter; >> + >> + if (dbus_message_iter_get_arg_type(©) == DBUS_TYPE_ARRAY) { >> + dbus_message_iter_recurse(©, &props); >> + while (dbus_message_iter_get_arg_type(&props) == >> + DBUS_TYPE_DICT_ENTRY) { >> + const char *key; >> + dbus_message_iter_recurse(&props, &entry); >> + dbus_message_iter_get_basic(&entry, &key); >> + if (g_str_equal(key, "AddressType") == TRUE) { >> + DBusMessageIter var; >> + const char *addr_type; >> + dbus_message_iter_next(&entry); >> + dbus_message_iter_recurse(&entry, &var); >> + dbus_message_iter_get_basic(&var, >> + &addr_type); >> + if (g_str_equal(addr_type, >> + "random") == TRUE) >> + return; >> + break; >> + } >> + dbus_message_iter_next(&props); >> + } >> + } >> + } > > Nack, not going to introduce BlueZ specific logic into gdbus like > this. If we need to rate limit the RSSI notification then it means > it's not suitable to be a property, but I believe we have a threshold > logic in the likes of device_set_rssi_with_delta so perhaps we shall > check why it is not working in your case. I investigated why device_set_rssi_with_delta is not working in our case. Root cause in BlueZ The customer scans with the following bluetoothctl sequence: menu scan → transport le → duplicate-data off → back → scan le scan le calls SetDiscoveryFilter({'Transport': 'le'}) — a transport-only filter with no RSSI or pathloss condition. In btd_adapter_device_found() (src/adapter.c): if (adapter->filtered_discovery) device_set_rssi_with_delta(dev, rssi, 0); /* delta forced to 0 */ else device_set_rssi(dev, rssi); /* delta = RSSI_THRESHOLD = 8 */ filtered_discovery is set true whenever current_discovery_filter is non-NULL (adapter.c:1872), which happens for any SetDiscoveryFilter() call — including a transport-only filter. With delta_threshold=0, the condition delta < 0 is never true, so g_dbus_emit_property_changed("RSSI") fires on every BLE advertisement regardless of whether the RSSI value changed. With 280+ BLE devices advertising continuously, this produces ~95 PropertiesChanged(RSSI) signals per second that flood dbus-daemon. The delta=0 path was presumably intended for clients that set RSSI/pathloss proximity filters, so that is_filter_match() gets precise RSSI tracking. A transport-only filter does not involve any proximity condition, so forcing delta=0 is unnecessary in that case. Proposed BlueZ fix direction Only apply delta=0 when at least one active client filter has a real proximity condition (RSSI or pathloss): static bool discovery_filter_has_proximity(struct btd_adapter *adapter) { GSList *l; for (l = adapter->discovery_list; l; l = g_slist_next(l)) { struct discovery_client *client = l->data; struct discovery_filter *item = client->discovery_filter; if (item && (item->rssi != DISTANCE_VAL_INVALID || item->pathloss != DISTANCE_VAL_INVALID)) return true; } return false; } /* in btd_adapter_device_found() */ if (adapter->filtered_discovery && discovery_filter_has_proximity(adapter)) device_set_rssi_with_delta(dev, rssi, 0); else device_set_rssi(dev, rssi); Could you advise whether this is the right approach, or if there is a better place to fix this? then I will Submit a separate BlueZ patch for the delta=0 fix once we agree on the approach. > >> proxy = proxy_lookup(client, path, interface); >> if (proxy) { >> update_properties(proxy, iter, FALSE); >> @@ -1255,14 +1293,6 @@ GDBusClient *g_dbus_client_new_full(DBusConnection *connection, >> "InterfacesRemoved", >> interfaces_removed, >> client, NULL); >> - g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal'," >> - "sender='%s',path_namespace='%s'", >> - client->service_name, client->base_path)); >> - >> - for (i = 0; i < client->match_rules->len; i++) { >> - modify_match(client->dbus_conn, "AddMatch", >> - g_ptr_array_index(client->match_rules, i)); >> - } > > This perhaps has a merit, but I can't recall what this watch was for. > Is it matching every signal from the sender? It seems it was introduce > before the watch infra existed, so if we can safely remove it we can > perhaps remove the whole client-->match_rules. > >> return g_dbus_client_ref(client); >> } >> -- >> 2.43.0 >> > >