From patchwork Mon Mar 10 21:40:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 14010752 Received: from mail-qt1-f170.google.com (mail-qt1-f170.google.com [209.85.160.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A2851DFFD for ; Mon, 10 Mar 2025 21:41:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642876; cv=none; b=SAeKH8wSqzpBsrTtoKdFG3rHMV6bUCo7pByP9HLJcAnL60eWegauiGFwN2EHXa0oHmLULkcrnMz3KF2a6UYy+Duu1pqf5zCCEmQJlLY3m0/BP8a6erjPKfb+wQxPhYzn4t0bouJE+nA2EnIv5HuP2AQ3xAxz0f74My0LuOMgPhg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642876; c=relaxed/simple; bh=oXxroYoZTSblSWJSbtqjTRVXqV50TGF+rEHQGvWwN4M=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=GZuT8dxZeRw0Hu4JLR+9Z3p86g5WFqc3BcDV42bKJ821kMVMHXXNKmmlyg96clmQdfzLmkDpRFjPkm8prdfeMnF26/mcMZW+TkVWiDyLRPEiHRX11OQwIJIGedGz8HafR0n+83VCVverLZTdEDCX51HTN3f2KSdNIrKZInpoaBI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=eL6vX3re; arc=none smtp.client-ip=209.85.160.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eL6vX3re" Received: by mail-qt1-f170.google.com with SMTP id d75a77b69052e-4750c3b0097so41513941cf.0 for ; Mon, 10 Mar 2025 14:41:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741642873; x=1742247673; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=0mFpTsqLKYS9MlkJ8LTsWza+e49TdZbiyZl2/VHb7rk=; b=eL6vX3rePDbw7Sx9BgOqVf/I/8nx+YSxCA24JjItbZSVF2yL738C5yI5VZLcGeHOVX zulFGeVWbe41TyucUfaut80LRz/ZIM1EEjGR3A4jps8pF0S5SNdfjagT/mpFU4p1+oeY stx/RKLzYYW4SvoLsPjk2oZrMx9PgRFPos5G0W4KlChHSYXBrtNX3WDRjFBpTpNCQSRP Sq/tfmNjO0XgBlGZgifMhcquGHVl/c+7shZX4sqgtz2XHJJ5skXd5/0n54vb1AT4LP3A H1Y8MVUZum2giAugJKwnFz71ok12IE/w1u9M8Sm+rCMNOvy0Jyg8nFZalWpv5iGLztaO zgrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741642873; x=1742247673; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=0mFpTsqLKYS9MlkJ8LTsWza+e49TdZbiyZl2/VHb7rk=; b=gq6Xi++YUbSWhaYoBgv6A8rztbzxhBkekUumfjtKA2F78vBbYG0+q7PYPm8LyOc9+F CsiwwIneYa00gyjTnGvqcaEz40W4NNI4dyUnfdxVM3uKlZs9iGC7RvRVup5cGWv4vGya m3kcZrDAlEAiRXhlLp2oEdtaolX29uOuXPBrQqsCBgmGENtGEhMc02ouuQcDngbkiS/N VlpjFM2jDuCrl/r3lDAbos61fU+qpO11+P11riM6WGUiirwhD61Mj1Dvem3PZ4JEmOsz x0jfaXt+YmyagL4ZdKKul4zMlTxKTxPfksLl2QwlaSspjfFCo+dApJKkBn4WCuqz+tT7 Jr0w== X-Gm-Message-State: AOJu0YwyM4gakWl6lqpMKkrtnOl2i5VON2xLvJ6jjTmp8F2PZMKsxXwi v2ICiu9oeNriBj+CY5P5GW4pqWZWLnAibtpqSO/O1ZE9E3Cxitk1KzWaFQ== X-Gm-Gg: ASbGncuvapDwGbnB9FqElezsZjXPE2VVuzWxqV2zsgMKjreKq0XQf9iX0I8iyzd64Fp FCE+QdzNZjj3BOw2fwk1ZJeombxfjkol/58BQlXZD0P0w1c5aVMZ6MQYxOx9vAptL8AauxMpZ8Q 8glm1ZHi46lta5cH01hL3LqkLRSBrBV7PEyDywMFELlgNQbd2tvVXPIzopy6dYle8Ixv5p0I6bq nImh5OWzo73zoky/igq6X/LQePsDkrD0J7EPoOgvpGlMSw0PV8GXjAp0B55NCyd+EVBqE/jOYIT 8Z4Vz4E1ZemoKaVagoyY3WNmyQ75PVn4fqhbj3a5QdzTAxKKbc6/NyLLqJSPZ20JyTd78r5NGGs XNy/lRZvRLNZi3w== X-Google-Smtp-Source: AGHT+IESQx6ek1dfAq9/pbjypcFSBJ8ryc4i1hKnrKC8Grgntp9HURBoN89ygSdn8mqcAgKITMUTjQ== X-Received: by 2002:a05:622a:164c:b0:476:9296:80c1 with SMTP id d75a77b69052e-4769950dc42mr25163451cf.31.1741642873019; Mon, 10 Mar 2025 14:41:13 -0700 (PDT) Received: from LOCLAP699.locus-rst-dev-locuspark.locus ([152.193.78.90]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-476772de5absm30487841cf.66.2025.03.10.14.41.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Mar 2025 14:41:12 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 1/8] blacklist: include a blacklist reason when adding/finding Date: Mon, 10 Mar 2025 14:40:52 -0700 Message-Id: <20250310214059.20809-1-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To both prepare for some new blacklisting behavior and allow for easier consolidation of the network-specific blacklist include a reason enum for each entry. This allows IWD to differentiate between multiple blacklist types. For now only the existing "permanent" type is being added which prevents connections to that BSS via autoconnect until it expires. By including a type into each entry we now have additional search criteria and can have multiple entires of the same BSS with different reasons. This was done versus a bitmask because each blacklist reason may have a different expiration time. We want to maintain individual expirations to have the best "memory" of past events rather than overwriting them. Future patches will lump in the temporary network blacklist as well as a new roaming blacklist type. --- src/blacklist.c | 81 +++++++++++++++++++++++++++++++++++++------------ src/blacklist.h | 14 +++++++-- src/network.c | 3 +- src/station.c | 12 +++++--- 4 files changed, 83 insertions(+), 27 deletions(-) diff --git a/src/blacklist.c b/src/blacklist.c index 21f85a75..b6583fdf 100644 --- a/src/blacklist.c +++ b/src/blacklist.c @@ -51,10 +51,46 @@ struct blacklist_entry { uint8_t addr[6]; uint64_t added_time; uint64_t expire_time; + enum blacklist_reason reason; +}; + +struct blacklist_search { + const uint8_t *addr; + enum blacklist_reason reason; }; static struct l_queue *blacklist; +static struct blacklist_entry *blacklist_entry_new(const uint8_t *addr, + enum blacklist_reason reason) +{ + struct blacklist_entry *entry; + uint64_t added; + uint64_t expires; + + switch (reason) { + case BLACKLIST_REASON_PERMANENT: + if (!blacklist_initial_timeout) + return NULL; + + added = l_time_now(); + expires = l_time_offset(added, blacklist_initial_timeout); + break; + default: + l_warn("Unhandled blacklist reason: %u", reason); + return NULL; + } + + entry = l_new(struct blacklist_entry, 1); + + entry->added_time = added; + entry->expire_time = expires; + entry->reason = reason; + memcpy(entry->addr, addr, 6); + + return entry; +} + static bool check_if_expired(void *data, void *user_data) { struct blacklist_entry *entry = data; @@ -79,24 +115,28 @@ static void blacklist_prune(void) static bool match_addr(const void *a, const void *b) { const struct blacklist_entry *entry = a; - const uint8_t *addr = b; + const struct blacklist_search *search = b; + + if (entry->reason != search->reason) + return false; - if (!memcmp(entry->addr, addr, 6)) + if (!memcmp(entry->addr, search->addr, 6)) return true; return false; } -void blacklist_add_bss(const uint8_t *addr) +void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason) { struct blacklist_entry *entry; - - if (!blacklist_initial_timeout) - return; + struct blacklist_search search = { + .addr = addr, + .reason = reason + }; blacklist_prune(); - entry = l_queue_find(blacklist, match_addr, addr); + entry = l_queue_find(blacklist, match_addr, &search); if (entry) { uint64_t offset = l_time_diff(entry->added_time, @@ -112,25 +152,24 @@ void blacklist_add_bss(const uint8_t *addr) return; } - entry = l_new(struct blacklist_entry, 1); - - entry->added_time = l_time_now(); - entry->expire_time = l_time_offset(entry->added_time, - blacklist_initial_timeout); - memcpy(entry->addr, addr, 6); - - l_queue_push_tail(blacklist, entry); + entry = blacklist_entry_new(addr, reason); + if (entry) + l_queue_push_tail(blacklist, entry); } -bool blacklist_contains_bss(const uint8_t *addr) +bool blacklist_contains_bss(const uint8_t *addr, enum blacklist_reason reason) { bool ret; uint64_t time_now; struct blacklist_entry *entry; + struct blacklist_search search = { + .addr = addr, + .reason = reason + }; blacklist_prune(); - entry = l_queue_find(blacklist, match_addr, addr); + entry = l_queue_find(blacklist, match_addr, &search); if (!entry) return false; @@ -142,13 +181,17 @@ bool blacklist_contains_bss(const uint8_t *addr) return ret; } -void blacklist_remove_bss(const uint8_t *addr) +void blacklist_remove_bss(const uint8_t *addr, enum blacklist_reason reason) { struct blacklist_entry *entry; + struct blacklist_search search = { + .addr = addr, + .reason = reason + }; blacklist_prune(); - entry = l_queue_remove_if(blacklist, match_addr, addr); + entry = l_queue_remove_if(blacklist, match_addr, &search); if (!entry) return; diff --git a/src/blacklist.h b/src/blacklist.h index 56260e20..d4da4478 100644 --- a/src/blacklist.h +++ b/src/blacklist.h @@ -20,6 +20,14 @@ * */ -void blacklist_add_bss(const uint8_t *addr); -bool blacklist_contains_bss(const uint8_t *addr); -void blacklist_remove_bss(const uint8_t *addr); +enum blacklist_reason { + /* + * When a BSS is blacklisted using this reason IWD will refuse to + * connect to it via autoconnect + */ + BLACKLIST_REASON_PERMANENT, +}; + +void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason); +bool blacklist_contains_bss(const uint8_t *addr, enum blacklist_reason reason); +void blacklist_remove_bss(const uint8_t *addr, enum blacklist_reason reason); diff --git a/src/network.c b/src/network.c index 0a40a6c5..92b44ed3 100644 --- a/src/network.c +++ b/src/network.c @@ -1280,7 +1280,8 @@ struct scan_bss *network_bss_select(struct network *network, if (l_queue_find(network->blacklist, match_bss, bss)) continue; - if (blacklist_contains_bss(bss->addr)) + if (blacklist_contains_bss(bss->addr, + BLACKLIST_REASON_PERMANENT)) continue; /* OWE Transition BSS */ diff --git a/src/station.c b/src/station.c index 5403c332..fab37478 100644 --- a/src/station.c +++ b/src/station.c @@ -2880,7 +2880,8 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list, if (network_can_connect_bss(network, bss) < 0) goto next; - if (blacklist_contains_bss(bss->addr)) + if (blacklist_contains_bss(bss->addr, + BLACKLIST_REASON_PERMANENT)) goto next; rank = bss->rank; @@ -3400,7 +3401,8 @@ static bool station_retry_with_reason(struct station *station, break; } - blacklist_add_bss(station->connected_bss->addr); + blacklist_add_bss(station->connected_bss->addr, + BLACKLIST_REASON_PERMANENT); try_next: return station_try_next_bss(station); @@ -3463,7 +3465,8 @@ static bool station_retry_with_status(struct station *station, network_blacklist_add(station->connected_network, station->connected_bss); else if (!station_pmksa_fallback(station, status_code)) - blacklist_add_bss(station->connected_bss->addr); + blacklist_add_bss(station->connected_bss->addr, + BLACKLIST_REASON_PERMANENT); iwd_notice(IWD_NOTICE_CONNECT_FAILED, "status: %u", status_code); @@ -3549,7 +3552,8 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result, switch (result) { case NETDEV_RESULT_OK: - blacklist_remove_bss(station->connected_bss->addr); + blacklist_remove_bss(station->connected_bss->addr, + BLACKLIST_REASON_PERMANENT); station_connect_ok(station); return; case NETDEV_RESULT_DISCONNECTED: From patchwork Mon Mar 10 21:40:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 14010753 Received: from mail-qt1-f174.google.com (mail-qt1-f174.google.com [209.85.160.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 933F41E0DFE for ; Mon, 10 Mar 2025 21:41:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642877; cv=none; b=rC5mlmt4fYcRVsXzb7W0tZHss7a0hxr8wXbMeNz38ASdel19cPFYYQ9jXFTiAXH/9OQ/r63kTEJo2lIcW5fMNApeXpsaT8ltzma4rTHFsZm148ZXKyi+Aut6M8wVbWT+t0ON4i9Qo8TssBCHGGyQBD5NRUYSyHG0bfuyS+f8PYY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642877; c=relaxed/simple; bh=lggmDBdi7Qo4rHQUc5Vt3rVXhSZLhE0e1B4BuRcazaY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=o7Z4cjvAr4tarw5LJsYgXjQllK3Y1GG7NvGAg/82XGg/XTV8gJmJpM3oBYdOuiOkbzxMIwEorZkN4KCtK7F8XftBWSq8hpqSL9jSfF69d1WiPPEePAibqPOf1BUPH/ApwlMawTe/14tQ9U/s8OQBz6Rc6Vfu2RzszwBWBwHblgA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kSibmADQ; arc=none smtp.client-ip=209.85.160.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kSibmADQ" Received: by mail-qt1-f174.google.com with SMTP id d75a77b69052e-475a77bbd8cso46042511cf.3 for ; Mon, 10 Mar 2025 14:41:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741642874; x=1742247674; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3B+uJuu6c4TBgixutemxV73ZyO1KyZzSW4bjfnd4OZI=; b=kSibmADQv+n6vH/PikigK8Yt/5iEcRGKp1nBikRXb6GNpIkMZfytZCzLSP7Ln6RME0 xha8x5kqBcQo275ArXgOZwiqfEl9uzJl+MXb6qveLyE6/GQeewVS9AwgHSGJvdArKqrl Sj8s8jCQKkazCI1g52at4yih/X4fE0tpZ0TNyCzCWa3Q7vkXZGLZrDHIRkQTdRO8Uc2l /KVURg4QXWppIwnwM05WMteRaRH4xiGywFOXEBphfJA5qHBuFpWu2fVb22Fnv02FCD6j C/9ef9ye6kpmcWj58PYyiKrdmKNSj5d0UfIlGNWtlzK86udHlD4kfUB2V4DeHCCT81iR g5rA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741642874; x=1742247674; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3B+uJuu6c4TBgixutemxV73ZyO1KyZzSW4bjfnd4OZI=; b=IDvKSpaI4AFDoijZgiGKfu74CNfp8IijOa0NgO331cFmEftcihHNK+uFKQ2Bfg3e76 Y4o+dzWR7M8wMcSWRRFm5Wjyt+zj0B7TA6ziZ3wbylnrhbl3cx/B9ZiYeKJkn+5SfaLr Ixrxy23J2k0Nj+R/8Cqlm19qEGD3We2wjFFfO2jEPoRN5wfyab7ldbPxrguFQVwoQMp8 E3RRuDTyrECO8z5KvACsnyYdxab7WfEYZQtNkPDUR0EhC+IlJYjFEX/uzBapRJ42i0hd RuNuTdRawaBPq96IxVIZXlxUIYsATvTGwqSBEdUm74JGlnMnqmEaAzTtx95CFMrK5QYJ YAYQ== X-Gm-Message-State: AOJu0YwE1S+umlJ6KVarPF2lDtM+mgR5Um48P9NaUzDhGxFgUZYIh9+z 8vCljWOoFKk3dx4I/DHr6rwV1kHeAwFUlO63aCw2D7pl2lmm7IdGkNlIaw== X-Gm-Gg: ASbGncvV4V85eS+4qWsblSS3e03nfR/z3C61MZobhrMV98rY/DhqD7YFlacpRXtbynz M8m7ybOJy/0EXt8RJNa7PzI2BD1KAf0TESXWq9EQFeW/XrxccYjzYrP8PcUsOY5u0xFFuFNmYiQ Gv8DWaywumH5BMpJjYY9VdvPx77U09t5MODMHKCHmQY6oZAI1nW4g3byN6m5Uc79VK+oWehmOg/ /WxQH9PJIHoeC3sBQvF5MgAvrITqwzuW0J+iXb2LObVdRGqbxrvJ4JDRt0WuCbPHak18V8SXrSS x2u8TEk3K3gIAmhU+AOVbZi5loWB5aOeo/bZ4zVQNCx9t5dB4zihyTi+6CzdyRZ+op+jFvnHGQV AWa4= X-Google-Smtp-Source: AGHT+IHVt8mT/KP70GolfsL5bLRdAOS+ruf7sXf9Btli1RGSBuTzMWcjH9DYxOkXsydv4Oa+pUNmyA== X-Received: by 2002:ac8:7d4a:0:b0:476:8f9e:44af with SMTP id d75a77b69052e-4768f9e4583mr52366461cf.29.1741642874195; Mon, 10 Mar 2025 14:41:14 -0700 (PDT) Received: from LOCLAP699.locus-rst-dev-locuspark.locus ([152.193.78.90]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-476772de5absm30487841cf.66.2025.03.10.14.41.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Mar 2025 14:41:13 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 2/8] blacklist: fix pruning to remove the entry if its expired Date: Mon, 10 Mar 2025 14:40:53 -0700 Message-Id: <20250310214059.20809-2-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250310214059.20809-1-prestwoj@gmail.com> References: <20250310214059.20809-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When pruning the list check_if_expired was comparing to the maximum amount of time a BSS can be blacklisted, not if the current time had exceeded the expirationt time. This results in blacklist entries hanging around longer than they should, which would result in them poentially being blacklisted even longer if there was another reason to blacklist in the future. Instead on prune check the actual expiration and remove the entry if its expired. Doing this removes the need to check any of the times in blacklist_contains_bss since prune will remove any expired entries correctly. --- src/blacklist.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/blacklist.c b/src/blacklist.c index b6583fdf..12100a07 100644 --- a/src/blacklist.c +++ b/src/blacklist.c @@ -96,7 +96,7 @@ static bool check_if_expired(void *data, void *user_data) struct blacklist_entry *entry = data; uint64_t now = l_get_u64(user_data); - if (l_time_diff(now, entry->added_time) > blacklist_max_timeout) { + if (l_time_after(now, entry->expire_time)) { l_debug("Removing entry "MAC" on prune", MAC_STR(entry->addr)); l_free(entry); return true; @@ -159,9 +159,6 @@ void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason) bool blacklist_contains_bss(const uint8_t *addr, enum blacklist_reason reason) { - bool ret; - uint64_t time_now; - struct blacklist_entry *entry; struct blacklist_search search = { .addr = addr, .reason = reason @@ -169,16 +166,7 @@ bool blacklist_contains_bss(const uint8_t *addr, enum blacklist_reason reason) blacklist_prune(); - entry = l_queue_find(blacklist, match_addr, &search); - - if (!entry) - return false; - - time_now = l_time_now(); - - ret = l_time_after(time_now, entry->expire_time) ? false : true; - - return ret; + return l_queue_find(blacklist, match_addr, &search) != NULL; } void blacklist_remove_bss(const uint8_t *addr, enum blacklist_reason reason) From patchwork Mon Mar 10 21:40:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 14010754 Received: from mail-qt1-f180.google.com (mail-qt1-f180.google.com [209.85.160.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DBA4C1E0DFE for ; Mon, 10 Mar 2025 21:41:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642879; cv=none; b=g253mrRG76XU23Fk+UZvssa1gFBDx2oxmdDn3eEc1Rah2BQ+ko/nR6mhezy0FCnYd3gGQ01rOKpwP1NRdRbqOU/9TXA5SeVdBZRZiF2VWBJVPu04XZuKbXuS6Fcu3oiXuZYMQjJcKJA3+vqoA6CNm2Fdbt+A/ZeHGAi+04SMN/k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642879; c=relaxed/simple; bh=eKO1Gyqh2jCy9GAmlM36eeeVwtbj13gPZh5jSMvGdbE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=k5tQGWphloW7GC6IAIGNc2mDFScqjKz/Wx+QyucPOLWmqUIXHKsZiYDQ7RV7hNI1u0oNW3Mk3KDEsJU2MxsDmGS2HMV/KN42DXxfxO06htjWytui/3DM/cdkQe7Yzk1bq3dPghrxxSpj+J9RmsAUIPGi+eIc5kytMNNsqiz7l9g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=dqjHy65s; arc=none smtp.client-ip=209.85.160.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dqjHy65s" Received: by mail-qt1-f180.google.com with SMTP id d75a77b69052e-47698757053so6795851cf.0 for ; Mon, 10 Mar 2025 14:41:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741642875; x=1742247675; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=aMsJptddDXeOL+An9Tsw0CzZvPobOuoRxUqKqWF7bgs=; b=dqjHy65smFa5mtQhQoLCuctCrGIJSWIqiOLRLNt69HDdr4OZlhf84nmaR8+/yEPWTw 0+DkQ9qmxQnqN3YgI2o0sgMKM3lQ2outhj5tr2lzHCxxwZ7B/HNKr/mozy/AAa38tW6v IUhLRcncghbLw5E2uTewDlC7zADGK79tg9HF1/avuob3ByWcS0SVOz8eYkm/HUWMhFW4 SC9oe06Dh/FTgKUNvNiaICaotJPdPfuhqifcx/Ap+HjqC7CvLz0nCKvV/ymBcCQ8cOvd lt5bteMhuNkCkPIrvY3JmjVBdF264BnDtfQbXXmrNa4t9q9yGvlyBHMf3Jd1Lu2L5BB4 QZNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741642875; x=1742247675; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aMsJptddDXeOL+An9Tsw0CzZvPobOuoRxUqKqWF7bgs=; b=QIfBRunmzCLxP9GRiDchSMSESRcWCiwXapkG94ZV/F5GasGlHsLkXvFMR84O9X1Co/ TU7WpSVfvm3r9JfxvyA6uYuEix3IoLxTgDFXpLZGZ6M8akR5h3Wjbdig73mH8UFwxTA6 B7BwPT1a6IThDhMFuo/1Pn+cuPtZ40p2aNFKYQNWJ5MFSYqbdQfKZ57tbBq8lNDouS3b jFwMgcBnUtWhKhrbzanvLJMr9OytvTkus00PI9GvQGxIEELB6JytzYDmhUoYObf/p6SV wIz1qM/JrAt1/xQdIR1X/3oGoZJ0EEmo3/030t+z74JsOhIZhmLDsmEyUbWW7r2Wj+RW BLvA== X-Gm-Message-State: AOJu0YznGSlHoj6J/ropXe3OaM1aKoircJpRuySASCTHqReCKkakATAP 8+b3q7hlS6Cg3sP53+sTb3EuExJtpy1v28hZUJTt3Lee6souPJOPfx/Xug== X-Gm-Gg: ASbGncttzo4/QHhrnXGmoTallDznohCUUQHS3RMIFore+PxUFvX8z8qDWSDnotsAfDs QlxCAGEyOawKdgi8H65ZuNqVzNWu25GfxZ+t2rgAerqe5Obb619PKz+OiyxdpUIH0wL6LGb0vGv /tPWxWKS8vOC0Rlw4cqNMiXWYF6L4/EhoGpAisBpg3Yfde+z4Whn1/SuhnuD1rWMA4i6IQPypZH LkapIoK21ok2VTa+UC7YOn6wINCxwyiznHd7khWY0tLhqoLmRccIQt6Ms9iUtmfwFgGbLSB8R2y 2vFQcSsaiE7i1v9xP5JJNoK26Kib2q3zCNIffdRPZio/05E2ZVJ1jV3fpW9bJBEGoLdES5zgusy TuMXeVM9XnUCXWQ== X-Google-Smtp-Source: AGHT+IEOkvAD8PD3I3Myzd+xEZOmJ6/BXn3hnrlaswIlTCTsDHcw5oddunhvYYFtF0T8KA3clD21Hw== X-Received: by 2002:a05:622a:144c:b0:476:85d9:5ec0 with SMTP id d75a77b69052e-47685d9665dmr64789091cf.0.1741642875495; Mon, 10 Mar 2025 14:41:15 -0700 (PDT) Received: from LOCLAP699.locus-rst-dev-locuspark.locus ([152.193.78.90]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-476772de5absm30487841cf.66.2025.03.10.14.41.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Mar 2025 14:41:15 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 3/8] blacklist: add BLACKLIST_REASON_TEMPORARY Date: Mon, 10 Mar 2025 14:40:54 -0700 Message-Id: <20250310214059.20809-3-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250310214059.20809-1-prestwoj@gmail.com> References: <20250310214059.20809-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This is meant to replace the blacklist held in network objects, known as the temporary blacklist. For these entires there is no expiration as it will be up to network.c to remove them as it does now internally. --- src/blacklist.c | 13 +++++++++++++ src/blacklist.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/src/blacklist.c b/src/blacklist.c index 12100a07..eef3f730 100644 --- a/src/blacklist.c +++ b/src/blacklist.c @@ -76,6 +76,16 @@ static struct blacklist_entry *blacklist_entry_new(const uint8_t *addr, added = l_time_now(); expires = l_time_offset(added, blacklist_initial_timeout); break; + case BLACKLIST_REASON_TEMPORARY: + /* + * The temporary blacklist is a special case where entries are + * required to be removed manually. This type of blacklist is + * only used for an ongoing connection attempt to iterate BSS's + * and not retry until all have been exhausted. + */ + added = 0; + expires = 0; + break; default: l_warn("Unhandled blacklist reason: %u", reason); return NULL; @@ -96,6 +106,9 @@ static bool check_if_expired(void *data, void *user_data) struct blacklist_entry *entry = data; uint64_t now = l_get_u64(user_data); + if (entry->reason == BLACKLIST_REASON_TEMPORARY) + return false; + if (l_time_after(now, entry->expire_time)) { l_debug("Removing entry "MAC" on prune", MAC_STR(entry->addr)); l_free(entry); diff --git a/src/blacklist.h b/src/blacklist.h index d4da4478..6ce26aba 100644 --- a/src/blacklist.h +++ b/src/blacklist.h @@ -26,6 +26,13 @@ enum blacklist_reason { * connect to it via autoconnect */ BLACKLIST_REASON_PERMANENT, + /* + * When a BSS is blacklisted due to a specific subset of error codes. + * This reason is somewhat of a special case and has no expiration. It + * is assumed that the calling module will remove these entries when + * appropriate (after a connection/disconnection) + */ + BLACKLIST_REASON_TEMPORARY, }; void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason); From patchwork Mon Mar 10 21:40:55 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 14010755 Received: from mail-qt1-f171.google.com (mail-qt1-f171.google.com [209.85.160.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 31FEE1E25F9 for ; Mon, 10 Mar 2025 21:41:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642880; cv=none; b=f/NiJvJetaBDKGpYi+qtgRiMW1ep5bYIGS4oAodrJWLV9Uai5Hh7DWCVKjE1Msy2cbQYo7eTmpPL0L+dLEJwxoZPgzeLVfJ8un3hP769Ozi5WXFTyiefoM4G8iA6tHOrzzL2PGFS4LizMfpx3QCCFhdko9s3WEhoMFUWJh5K/Zk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642880; c=relaxed/simple; bh=6Fp8R4Qw0nOtNEgD63cJHCtZcpKImAfVM8JPMBCUgTg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=NkkKgFDIoC6kfOPIOGllmZgVtUlQMmyCFDW0gOasoTv1tcigqdxbZZsB+2qYfRTpCbUiDtglKNGd2QSkvAVqEOX+etcPQkoQnZfWFf10gRwUnQtL32xWLk/WFjOzvca4JG/ryi4GgkxrOGbuLXZU5ZAAcB+O/ux/t5TapLzHsV8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=UI0UJXR1; arc=none smtp.client-ip=209.85.160.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UI0UJXR1" Received: by mail-qt1-f171.google.com with SMTP id d75a77b69052e-46c8474d8f6so38241011cf.3 for ; Mon, 10 Mar 2025 14:41:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741642877; x=1742247677; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2A1lLqRFKn/6XH8pCFXenZs6pITaQh0n3lF9tO6nvOU=; b=UI0UJXR1y/B84fflf693PcFr3QFucxDfFRC4g30pJPxD0awDt3HtJSNaIk9IbHJ4S8 KSxGXbxVzF1BHZ4dG2x6X66BMkDpbEzsdUdzwkNfV0cCzttQ3cE5TrNuCjp+4U9k7emb iMTaH8PuZRD9W39uhkWlfocir6/adWyOR6sk+s/aojh5Sw83b9/GVhhhJIAX1vI4H+8y 2pARp5DEZNk6PzN+brpRpghOnvyaWh2Syqey/F0SPLX08IpUFmMGF1z/DEc/AiAqyHNs pc9ce1dYmMQ+6m6JF9tkeUXoZWqAoM7KWXipp7foJl1Di5GQHyoSUKyWv9TBwCsgqd3p MSKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741642877; x=1742247677; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2A1lLqRFKn/6XH8pCFXenZs6pITaQh0n3lF9tO6nvOU=; b=psad4F26uwrtCzStAEfxe2pQtfErOyPqk+IugyYl4Bg0x+FaoKEdnBRazaF2HRgpSH vzVYE+Py4yreIGEbtXLjKNTKJKbxs32vdZNwmYL5NRmbHhuQNRYG29jhwutxX3nfWr8o HVTfHt/jjBW+ffTabWcM1S2Bt58R8nWTwV2kTQBPMHS01GYQu2Fw9kN0x8d5cVuZYPLg P878/uKFC0CJfJQM9tJSUSIsUt6bgpkjkHkp/RfPiTQTjdtUmbkyP16Ca7s6uEeFmwFs 23/YiuGVfDKhw15O6tkmA756Pkt2m7KQUw10t2GRIOkZIogpSNJ/L0hfIgaymBAEo9JY E/9Q== X-Gm-Message-State: AOJu0Ywn7UfsfGc5VnqYPVI8tZ8viP+dYQRwt47w0oHNeDv512E/hg5U z5w3VPXrl5RPtzLbx083z/uzOWpAtqscB76wQr54eu5zKKXx3/zIuRTfXw== X-Gm-Gg: ASbGnctTu4KSUFTgkkkkhR3mBmae4P+tvyqnfdiWFtQLELR+ZhNgyUua5lO38uPCyJI NwdKqxBSyJC7yjyPAmNav1qVSkJMq6QVFuub/7JEfova8z7XyPuhLiwZpZfKDSYxd3qMLl59lVd 6zINR5N+YSwTyPF4BVOpzQf9dnZVphIi2c81Kl9nDOgmW9dWVZcchcwdnCp2MZ8w/1bEqMBFGei wCOZR5GUX+fdkbq3kASFzAnWa/Ki2WBMuCbrmjUWD2BviqrEucvwagAgQWX0CXvyNfgBt7Nd0KZ kUMxoVhkynqwYNgsTCV7S3RAvvtieSHHldwCjJEMdQJWEPQrL1AlqLHTwf1QE7uLHikIz/7ox+n 5C1k= X-Google-Smtp-Source: AGHT+IFT/14+yvSwIjXHlEvFDsXexacsboGf7oIx6LPzvhqJ5wsHmOKWsjK5L9Kgv49OSM2G/PgJAQ== X-Received: by 2002:ac8:7d16:0:b0:476:671e:deb6 with SMTP id d75a77b69052e-476994c5f5fmr15957041cf.12.1741642876770; Mon, 10 Mar 2025 14:41:16 -0700 (PDT) Received: from LOCLAP699.locus-rst-dev-locuspark.locus ([152.193.78.90]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-476772de5absm30487841cf.66.2025.03.10.14.41.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Mar 2025 14:41:16 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 4/8] network: update to use blacklist's new temporary type Date: Mon, 10 Mar 2025 14:40:55 -0700 Message-Id: <20250310214059.20809-4-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250310214059.20809-1-prestwoj@gmail.com> References: <20250310214059.20809-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Remove the temporary blacklist from network.c and use the new BLACKLIST_REASON_TEMPORARY type. --- src/network.c | 34 +++++++++++++++++----------------- src/network.h | 2 -- src/station.c | 8 ++++---- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/network.c b/src/network.c index 92b44ed3..b48eaa51 100644 --- a/src/network.c +++ b/src/network.c @@ -78,7 +78,6 @@ struct network { struct l_queue *bss_list; struct l_settings *settings; struct l_queue *secrets; - struct l_queue *blacklist; /* temporary blacklist for BSS's */ uint8_t hessid[6]; char **nai_realms; uint8_t *rc_ie; @@ -168,6 +167,18 @@ static bool network_secret_check_cacheable(void *data, void *user_data) return false; } +static void remove_temporary_blacklist(void *user_data) +{ + struct scan_bss *bss = user_data; + + blacklist_remove_bss(bss->addr, BLACKLIST_REASON_TEMPORARY); +} + +static void remove_blacklist_foreach(void *data, void *user_data) +{ + remove_temporary_blacklist(data); +} + void network_connected(struct network *network) { enum security security = network_get_security(network); @@ -198,7 +209,7 @@ void network_connected(struct network *network) l_queue_foreach_remove(network->secrets, network_secret_check_cacheable, network); - l_queue_clear(network->blacklist, NULL); + l_queue_foreach(network->bss_list, remove_blacklist_foreach, NULL); network->provisioning_hidden = false; } @@ -207,7 +218,7 @@ void network_disconnected(struct network *network) { network_settings_close(network); - l_queue_clear(network->blacklist, NULL); + l_queue_foreach(network->bss_list, remove_blacklist_foreach, NULL); if (network->provisioning_hidden) station_hide_network(network->station, network); @@ -254,7 +265,6 @@ struct network *network_create(struct station *station, const char *ssid, } network->bss_list = l_queue_new(); - network->blacklist = l_queue_new(); return network; } @@ -1197,11 +1207,6 @@ struct scan_bss *network_bss_find_by_addr(struct network *network, return l_queue_find(network->bss_list, match_addr, addr); } -static bool match_bss(const void *a, const void *b) -{ - return a == b; -} - struct erp_cache_entry *network_get_erp_cache(struct network *network) { struct erp_cache_entry *cache; @@ -1277,7 +1282,8 @@ struct scan_bss *network_bss_select(struct network *network, candidate = bss; /* check if temporarily blacklisted */ - if (l_queue_find(network->blacklist, match_bss, bss)) + if (blacklist_contains_bss(bss->addr, + BLACKLIST_REASON_TEMPORARY)) continue; if (blacklist_contains_bss(bss->addr, @@ -1784,11 +1790,6 @@ struct l_dbus_message *network_connect_new_hidden_network( return dbus_error_not_supported(message); } -void network_blacklist_add(struct network *network, struct scan_bss *bss) -{ - l_queue_push_head(network->blacklist, bss); -} - static bool network_property_get_name(struct l_dbus *dbus, struct l_dbus_message *message, struct l_dbus_message_builder *builder, @@ -1934,8 +1935,7 @@ void network_remove(struct network *network, int reason) if (network->info) network->info->seen_count -= 1; - l_queue_destroy(network->bss_list, NULL); - l_queue_destroy(network->blacklist, NULL); + l_queue_destroy(network->bss_list, remove_temporary_blacklist); if (network->nai_realms) l_strv_free(network->nai_realms); diff --git a/src/network.h b/src/network.h index 849051dd..1e01de88 100644 --- a/src/network.h +++ b/src/network.h @@ -95,8 +95,6 @@ struct l_dbus_message *network_connect_new_hidden_network( struct network *network, struct l_dbus_message *message); -void network_blacklist_add(struct network *network, struct scan_bss *bss); - struct erp_cache_entry *network_get_erp_cache(struct network *network); const struct l_queue_entry *network_bss_list_get_entries( diff --git a/src/station.c b/src/station.c index fab37478..d16e82af 100644 --- a/src/station.c +++ b/src/station.c @@ -3462,8 +3462,8 @@ static bool station_retry_with_status(struct station *station, * obtain that IE, but this should be done in the future. */ if (IS_TEMPORARY_STATUS(status_code)) - network_blacklist_add(station->connected_network, - station->connected_bss); + blacklist_add_bss(station->connected_bss->addr, + BLACKLIST_REASON_TEMPORARY); else if (!station_pmksa_fallback(station, status_code)) blacklist_add_bss(station->connected_bss->addr, BLACKLIST_REASON_PERMANENT); @@ -3562,8 +3562,8 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result, iwd_notice(IWD_NOTICE_DISCONNECT_INFO, "reason: %u", reason); /* Disconnected while connecting */ - network_blacklist_add(station->connected_network, - station->connected_bss); + blacklist_add_bss(station->connected_bss->addr, + BLACKLIST_REASON_TEMPORARY); if (station_try_next_bss(station)) return; From patchwork Mon Mar 10 21:40:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 14010756 Received: from mail-qt1-f176.google.com (mail-qt1-f176.google.com [209.85.160.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7E6991E32A2 for ; Mon, 10 Mar 2025 21:41:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642881; cv=none; b=PxFuGFB7Z513Lpf/FiCQgmEFuMwyS5ZBNV2NKao4iXjnEUeSj85MdyZ+F6eX2ou7PRgM6zCZEX9zNERVe6IxFvhK0Vhub6pNPqkAui5KzW/LTIF5EgpBlap3Ics8yAtkyrQoxsrnu6uaq/1RTjD6n+H/rWRUu8QgN3AX71bvAzQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642881; c=relaxed/simple; bh=o2x0Ur23K6ROQ9Ffza91iYrSRrhVZcbPnX3Xljp+LA0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=THlHs9xJSHTUML9qVnP1IXZrgQ7j0DqaaslAW58MQqljnvbTfoJNQrarH7tBQmTmJQKk0lXTvUPygOn2O5FdB2sk1hx3Ark5T8gOfSqt+VfaDUhDP9GsNALWwKPRzwIGmY299xo64/vwSMJyHZCXgboGysQh1HgFdtGt7r7CAoc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=N8Km8xLk; arc=none smtp.client-ip=209.85.160.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="N8Km8xLk" Received: by mail-qt1-f176.google.com with SMTP id d75a77b69052e-47690a4ec97so11388531cf.2 for ; Mon, 10 Mar 2025 14:41:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741642878; x=1742247678; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fvVT/A/3zKMBlutOB57nnV1meZrYFUQH+dqnTWyCI6g=; b=N8Km8xLkvm8MmQKvQS8rkT3OyguCbn5m0JpvXe3jqLKqlTSDXJdSkFToGeTliTXyNf gR1wka0dZwyh/sp69Fau/R53ZaIuKmWsj+Z6p1zM2rIVlNFrpSt0GY+Iwt8Jo4Ia14tZ Pe5xkJevTNSOBzSLlRdhnJEwOZvYzzW6pNKWIl3jhdxvQhmJhE0NX0u2qiAOjMu7R+l8 jpLLR40Okj4vSmg43FhiKpffL6iFR0XK2xHZUTpEr6Wmc6Vbq9hj10eVlh7Yigh6nGF5 nByq4dBUe5rWvpxe5cP+BTasrjb6dV9yEcz2iFUozWsNchCgNEgvIt1C1R+YijLBZfLj soAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741642878; x=1742247678; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fvVT/A/3zKMBlutOB57nnV1meZrYFUQH+dqnTWyCI6g=; b=NvtUptNbKMXq/vktoYNa1PUc2Q83EO6DKgoRPdN/fR0lWf9xYTmHTzmEU8OSerYRkF Le/XiK3nU9wX/herCEtQ6TZyKeyPxnDK0N7AqFAJzN6Pi0nOUGqI/vpqzC1JHhr/O3WF 22lXKkzkcXPRDNzGC6rYBYFPl1rXMk2HSo7tOld6noSj2vK06ifiRs41OeaVhX2LBwZM 30XYrZImTvZh5MHb2I+ZpinaB1OQ90zJekKcE5LojsEGGxE3Iy6k5OJOyJbR8e9I3M/w NrJswKSDPKElLP2pGRvjsxe4RO2am/Ttc9/U6WoRncuyespBdn3a8+Du0lFbFH4TpX8W sUGA== X-Gm-Message-State: AOJu0YzmZdob8gSb/PlS0tF2j/SZtzFjRcdx/vPJBWv0sJs7uYkwYPaU rCvJqIMX/FNiiSBFl9dR70fT6VnT6UqqY3lBeTrT/Us+7w++QSOv15p1/A== X-Gm-Gg: ASbGnctd6R2SnvSneoaLACrCd5+krZTzwIRm0n2ufVKRRLJwOEnX2K44PiJefG95oY+ Wuza7qFnymzYgVjPVkuHpj4hWMN3CERRRGoTtLUwzYKh+5WakebUoixAhNlDjQRsoe662XdUp49 ItklIzQmMzs8uiTbAenuc8ivPZWCYQnkQmJzNPzZdqsr/xn1oKJChAsjOE8NCmjdxASY0bFb25s YecJg6SEd6y93m6qI3QkpDgEVoP27xdve3qSvTXeL/YgNtVE99SYCyeKhRYTylf69q2Nxk7BksF npfB3zvQdk0hsDhkou6PtwKXOfnVtm8nADZVchNS54kDtRl5JbcKCiUHt5ky/AHzWmasTOqFCs0 3KUA= X-Google-Smtp-Source: AGHT+IFaEYJLxlso9jEsUmS2pzPavpJtAdxdJ5x3LmYl+x+JZxJojNC3xnbtL8CD/phgJj53W+qLAA== X-Received: by 2002:a05:622a:111:b0:476:8ee8:d8a1 with SMTP id d75a77b69052e-4769964b5d5mr16111591cf.45.1741642878097; Mon, 10 Mar 2025 14:41:18 -0700 (PDT) Received: from LOCLAP699.locus-rst-dev-locuspark.locus ([152.193.78.90]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-476772de5absm30487841cf.66.2025.03.10.14.41.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Mar 2025 14:41:17 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 5/8] blacklist: add new blacklist reason, ROAM_REQUESTED Date: Mon, 10 Mar 2025 14:40:56 -0700 Message-Id: <20250310214059.20809-5-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250310214059.20809-1-prestwoj@gmail.com> References: <20250310214059.20809-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This adds a new blacklist reason as well as an option to configure the timeout. This blacklist reason will be used in cases where a BSS has requested IWD roam elsewhere. At that time a new blacklist entry will be added which will be used along with some other criteria to determine if IWD should connect/roam to that BSS again. --- src/blacklist.c | 16 ++++++++++++++++ src/blacklist.h | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/src/blacklist.c b/src/blacklist.c index eef3f730..178cb41c 100644 --- a/src/blacklist.c +++ b/src/blacklist.c @@ -45,6 +45,7 @@ static uint64_t blacklist_multiplier; static uint64_t blacklist_initial_timeout; +static uint64_t blacklist_roam_initial_timeout; static uint64_t blacklist_max_timeout; struct blacklist_entry { @@ -86,6 +87,13 @@ static struct blacklist_entry *blacklist_entry_new(const uint8_t *addr, added = 0; expires = 0; break; + case BLACKLIST_REASON_ROAM_REQUESTED: + if (!blacklist_roam_initial_timeout) + return NULL; + + added = l_time_now(); + expires = l_time_offset(added, blacklist_roam_initial_timeout); + break; default: l_warn("Unhandled blacklist reason: %u", reason); return NULL; @@ -211,6 +219,14 @@ static int blacklist_init(void) /* For easier user configuration the timeout values are in seconds */ blacklist_initial_timeout *= L_USEC_PER_SEC; + if (!l_settings_get_uint64(config, "Blacklist", + "InitialRoamRequestedTimeout", + &blacklist_roam_initial_timeout)) + blacklist_roam_initial_timeout = BLACKLIST_DEFAULT_TIMEOUT; + + /* For easier user configuration the timeout values are in seconds */ + blacklist_roam_initial_timeout *= L_USEC_PER_SEC; + if (!l_settings_get_uint64(config, "Blacklist", "Multiplier", &blacklist_multiplier)) diff --git a/src/blacklist.h b/src/blacklist.h index 6ce26aba..ec4c6de3 100644 --- a/src/blacklist.h +++ b/src/blacklist.h @@ -33,6 +33,13 @@ enum blacklist_reason { * appropriate (after a connection/disconnection) */ BLACKLIST_REASON_TEMPORARY, + /* + * This type of blacklist is added when a BSS requests IWD roams + * elsewhere. This is to aid in preventing IWD from roaming/connecting + * back to that BSS in the future unless there are no other "good" + * candidates to connect to. + */ + BLACKLIST_REASON_ROAM_REQUESTED, }; void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason); From patchwork Mon Mar 10 21:40:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 14010757 Received: from mail-qt1-f172.google.com (mail-qt1-f172.google.com [209.85.160.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F37DA1E378C for ; Mon, 10 Mar 2025 21:41:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642882; cv=none; b=EZwlXrlqRmEEgJN79PH9wbm/2ifupAvg6k3SyEdbs13BalYUXWuCMWBwX/1A0PaUg/XZ/qSomA17H7nyRgYviH/nDSyDfNpXFgGZhD/3DBRIkDBQmkmXSsGhQtLRBPQ8s3+RxnHiAmLdkSyzHzTIWiL7+x6NXYR+SJkKv0hN4tA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642882; c=relaxed/simple; bh=qP4Pn+/RcHhTltFTDAx0815WcMG9CbxDW03yuCc0fGQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=F4DSltWKrXi9dQ/eLk20s6iVpnFz/MguqHPpqlQS+/1nzcsc1YunKTrTsmU+8sxu7PWdV5LgsJy5b6Q02yUW5yMDm1ujfNYy28uwJGXpjEcQRaMjJuPWes7aobeQlLVB++xwl2gQiLURmulDGwNUZv1wxf1//2CLfxNJjDhBgqE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=lUeQMF4u; arc=none smtp.client-ip=209.85.160.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lUeQMF4u" Received: by mail-qt1-f172.google.com with SMTP id d75a77b69052e-474f0c1e1c6so55079721cf.1 for ; Mon, 10 Mar 2025 14:41:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741642880; x=1742247680; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bIc8rPcrNtR6O/5fFmMP+J568N4+MXOB1YbviJJpRkM=; b=lUeQMF4u7vlB7ACs3iAf6DGQFu9KySm3Z3gQNYs24UsnMxBvhpeDf7lJknAAVz02tZ pWwOQDePnPQ2cbG3KqWHhBvMCXd1Ub75RP/fu/CzgRgN58FyoIv241ybCpgAJ3KOhdKV 5l3z31/KLd07URS0UxzrqW6mTOURpgzV0q/svjVEuJOLHe66Z0YJURVZJJepXHT7kVVN j/J2qmljP8WPZzClQjDSEH07jiKI3sFKrYnTKhToS2SUeTHgj7Xaa/9wiP9h23clNCCp iApCmahJJe2pOUkw92VPoQxBLBfWEOkOXJY3rwXvzIe8LWWHolusWR6j693V9/L+0wzx LDxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741642880; x=1742247680; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bIc8rPcrNtR6O/5fFmMP+J568N4+MXOB1YbviJJpRkM=; b=tOMFHB8SFbe1bXsv1JWo7O8nZ7cEPW/1mnoufeZTcWeOxbpQ54i37DoqvTjdyuQq2X KkvxZpPbiB6D632m6bITbuRifQTSoBuQazkb55PAXHfD1s2hdM/vJ1U0m+YWS3cCT4Ia edgYWD0puFoLT3+Oh8oeyBl/NOCpo2oC4BhbBdfPQmhnjCI3Dh05Lf9RW2dE8+vVfH4t +G+iqF5qHAZY2vhs9njHlwT/frbotJWRDWkZUFZLxoBIP8iMeljLEuGBO54QT7vkHRIB OUifQMavmvmv2YeHMtgly7b822Vz0e9Iqs9q/LjHJ1L+yHdcCx/3kkWlEW+m5X1kyi4w N8RQ== X-Gm-Message-State: AOJu0Yw8QhR9HbSTGpwbcIYYlHQMsYfSq1U5YTBovz8Td/A3KJXIG+N2 WFy0yKmEQCtRSw7jnjjkaDKXSiXqai5H2SqP25FdmfQ3UzzrudqUle4fSg== X-Gm-Gg: ASbGncvjsdkhnu2xnFrCQUwoZDNw/eEkt4rnf/3w9pcTdQKvGdvc19AgGnpyckhMQGe emRxDWj/YX02bw4wN1m1DFMfXI6XBVy/a+KjBHdOoZ1XZBqccXHEuLkhFA5t9XpRTcEFPwb+xzp gPj6lrVCWOpC9vC+f5n87pCeGDK3Fs60MxJlC0MueCjYH+x4HTsVtAzUK12JgpQJxujy0tZurUe u7O2axhlVlnnAkJpHM8CN5kMjZL8N0/TroCNL57Z+Kqy0bpqM96+q04tyoPVXMW0+JBL9hDhTM5 XsP7kJX2sVKNx1YaG77w1HyH24I3EN0XajtfwvrjeyEI1LyGOEcTY2z5U0F3cmfWIU2QTK9bWXQ iSUA= X-Google-Smtp-Source: AGHT+IG6BTR5hFUgU3JYHDejT/cUbhsN3Vk9LzUkdZcPNxE+GLjrAEFPv9HQEQ51ZrIn6HTThjO7+A== X-Received: by 2002:ac8:5714:0:b0:476:8c58:4f68 with SMTP id d75a77b69052e-4768c585117mr70444391cf.2.1741642879612; Mon, 10 Mar 2025 14:41:19 -0700 (PDT) Received: from LOCLAP699.locus-rst-dev-locuspark.locus ([152.193.78.90]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-476772de5absm30487841cf.66.2025.03.10.14.41.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Mar 2025 14:41:19 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 6/8] scan: Introduce higher level scan BSS groups Date: Mon, 10 Mar 2025 14:40:57 -0700 Message-Id: <20250310214059.20809-6-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250310214059.20809-1-prestwoj@gmail.com> References: <20250310214059.20809-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This introduces a higher level grouping to BSS's to improve sorting as opposed to purely rank based sorting. The reason for this is to handle roam request-based blacklisting where we want to encourage IWD to avoid BSS's that have requested we roam elsewhere, but also not fully ban these BSS's (i.e. BLACKLIST_REASON_PERMANENT). This new concept introduces 4 group types, in order of worse to best: - Blacklisted - the BSS has a permanent timeout blacklist - Under threshold - the BSS is under the set RSSI threshold - Above threshold - the BSS is above the set RSSI threshold - Optimal - The BSS is not "roam blacklisted" and is above the set RSSI threshold. When sorting the BSS group will be considered before rank. This means we will still prefer roam blacklisted BSS's above those that are under the set RSSI threshold. BSS's within the same group are still compared by their rank/signal. The new group sorting logic was added via a macro __scan_bss_rank_compare. This was done since station uses a separate roam_bss structure to sort roam candidates which can also take advantage of this new sorting. The macro is agnostic to the type as long as the structure member names match. --- src/scan.c | 42 +++++++++++++++++++++++++++++++++++++----- src/scan.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/scan.c b/src/scan.c index aeab6516..2787028d 100644 --- a/src/scan.c +++ b/src/scan.c @@ -51,6 +51,7 @@ #include "src/mpdu.h" #include "src/band.h" #include "src/scan.h" +#include "src/blacklist.h" /* User configurable options */ static double RANK_2G_FACTOR; @@ -58,6 +59,7 @@ static double RANK_5G_FACTOR; static double RANK_6G_FACTOR; static uint32_t RANK_HIGH_UTILIZATION; static uint32_t RANK_HIGH_STATION_COUNT; +static int RANK_OPTIMAL_SIGNAL_THRESHOLD; static uint32_t SCAN_MAX_INTERVAL; static uint32_t SCAN_INIT_INTERVAL; @@ -1910,15 +1912,41 @@ int scan_bss_get_security(const struct scan_bss *bss, enum security *security) return 0; } +/* + * Evaluate the BSS's grouping based on its signal strength and blacklist + * status. From best to worst the groupings are: + * + * Optimal: Not blacklisted in any form, and above the RSSI threshold + * Above Threshold: Above the RSSI threshold (may be roam blacklisted) + * Below Threshold: Below the RSSI threshold (may be roam blacklisted) + * Blacklisted: Permanently blacklisted + */ +enum scan_bss_group scan_bss_evaluate_group(const uint8_t *addr, + int16_t signal_strength) +{ + int rssi = signal_strength / 100; + + if (RANK_OPTIMAL_SIGNAL_THRESHOLD == 0) + return SCAN_BSS_GROUP_OPTIMAL; + + if (blacklist_contains_bss(addr, BLACKLIST_REASON_PERMANENT)) + return SCAN_BSS_GROUP_BLACKLISTED; + + if (!blacklist_contains_bss(addr, BLACKLIST_REASON_ROAM_REQUESTED) && + rssi >= RANK_OPTIMAL_SIGNAL_THRESHOLD) + return SCAN_BSS_GROUP_OPTIMAL; + + if (rssi >= RANK_OPTIMAL_SIGNAL_THRESHOLD) + return SCAN_BSS_GROUP_ABOVE_THRESHOLD; + + return SCAN_BSS_GROUP_UNDER_THRESHOLD; +} + int scan_bss_rank_compare(const void *a, const void *b, void *user_data) { const struct scan_bss *new_bss = a, *bss = b; - if (bss->rank == new_bss->rank) - return (bss->signal_strength > - new_bss->signal_strength) ? 1 : -1; - - return (bss->rank > new_bss->rank) ? 1 : -1; + return __scan_bss_rank_compare(new_bss, bss); } static bool scan_survey_get_snr(struct scan_results *results, @@ -2678,6 +2706,10 @@ static int scan_init(void) if (L_WARN_ON(RANK_HIGH_STATION_COUNT > 255)) RANK_HIGH_STATION_COUNT = 255; + if (!l_settings_get_int(config, "Rank", "OptimalSignalThreshold", + &RANK_OPTIMAL_SIGNAL_THRESHOLD)) + RANK_OPTIMAL_SIGNAL_THRESHOLD = 0; + return 0; } diff --git a/src/scan.h b/src/scan.h index 4c1ebc21..4d06f29d 100644 --- a/src/scan.h +++ b/src/scan.h @@ -45,6 +45,17 @@ enum scan_bss_frame_type { SCAN_BSS_BEACON, }; +/* + * Groupings for BSS's. These are assumed to be in order of preference where + * the last enum is the most preferred group to connect to. + */ +enum scan_bss_group { + SCAN_BSS_GROUP_BLACKLISTED, + SCAN_BSS_GROUP_UNDER_THRESHOLD, + SCAN_BSS_GROUP_ABOVE_THRESHOLD, + SCAN_BSS_GROUP_OPTIMAL, +}; + struct scan_bss { uint8_t addr[6]; uint32_t frequency; @@ -168,6 +179,36 @@ bool scan_get_firmware_scan(uint64_t wdev_id, scan_notify_func_t notify, void *userdata, scan_destroy_func_t destroy); void scan_bss_free(struct scan_bss *bss); + +enum scan_bss_group scan_bss_evaluate_group(const uint8_t *addr, + int16_t signal_strength); + +/* + * Macro to compare two scan_bss-like objects. This is to share code between + * station.c and scan.c since station uses "roam_bss" objects which is a subset + * of a scan_bss. + * - If the groups differ this is used as the comparison. + * - If the groups match, the BSS rank is used as the comparison + * - If the BSS ranks match, the signal strength is used as the comparison + */ +#define __scan_bss_rank_compare(a, b) ({ \ + int ret; \ + enum scan_bss_group a_group = scan_bss_evaluate_group( \ + (a)->addr, (a)->signal_strength); \ + enum scan_bss_group b_group = scan_bss_evaluate_group( \ + (b)->addr, (b)->signal_strength); \ + if (b_group > a_group) \ + ret = 1; \ + else if (b_group < a_group) \ + ret = -1; \ + else if ((b)->rank == (a)->rank) \ + ret = ((b)->signal_strength > \ + (a)->signal_strength) ? 1 : -1; \ + else \ + ret = ((b)->rank > (a)->rank) ? 1 : -1; \ + ret; \ +}) + int scan_bss_rank_compare(const void *a, const void *b, void *user); int scan_bss_get_rsn_info(const struct scan_bss *bss, struct ie_rsn_info *info); From patchwork Mon Mar 10 21:40:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 14010758 Received: from mail-qt1-f173.google.com (mail-qt1-f173.google.com [209.85.160.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 302701E1C22 for ; Mon, 10 Mar 2025 21:41:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642883; cv=none; b=bWoNiRCCwnn92jshqMnxvrcl/yQ08plbJ37Ew16cJuVI2XL6/n5GCO484gNVaetsc1Fte6tpLmGdzP3UHLFAjrLuxgaUC4E/3SQ4oBpQ1iZJ69mHYNRR5hsXUHRlwGFt+1je9QG2/sv12cgkqQwB9HID47gWFDzZywIg1xMvR1g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642883; c=relaxed/simple; bh=4TBFHLx0v9So0GhoPkfflUk012Gl9dxE7gC31FrKIxE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=a8ALeO2zflhUSqy5P018WUEd4nlNv4+ezSiNZBM5z0FuazpE2QQpZMuw6R9JucaIaFLiG9sPbajaWZTdBnSvaE5HcwHtSbaEYWK7SXmVogz3Asu/ckrNoEmpOhkWpGjI835APyz+hFiF9H+pZKZRMFROaQEubtsjRWbvNom+Lvc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OsGYtbz+; arc=none smtp.client-ip=209.85.160.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OsGYtbz+" Received: by mail-qt1-f173.google.com with SMTP id d75a77b69052e-476805acddaso18674161cf.1 for ; Mon, 10 Mar 2025 14:41:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741642881; x=1742247681; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7Rs7qaDSYgYJxxnp510WgMdJS5hCD84nfpzE8QkJJCU=; b=OsGYtbz+d/amPxtwi01xo1QeIvJOrNx41JEb2aISJ7KYlUT5CCKPNlA17BWbTfj7Eq oriejvVkpo+fKVEWwlGfqm1d2X2JQOHDegXTVp2xugrMGaSTcfmhbi98djOeaRcNK1hE MathlGKDLviiXL5seMVneOMDdwXqNGQJ21VpXGJMjhsQ8uPBOi8DVi5xTtGPhZflyNu5 H+2jicIpVeU9YSBN8FPFUvbLphtHGFZROl3yNG1myYqpC0RKfBG0qF7bNCKcZejVOkwa 0EimH25dHuw6kYZjpolRPdEtGSOlVXaPLfSM1nfSoQuUuXVjhCS8HJ8NkH7n0axED47e Iv6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741642881; x=1742247681; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7Rs7qaDSYgYJxxnp510WgMdJS5hCD84nfpzE8QkJJCU=; b=thFdNh1kcMdevi4/+neRhe3eDguibgbVONGifh8bOt/21zA8eF1CrF/Nx8Sc1hZunO kdkj0YHNPav/FbsjKuo8eX9WEzcMHZl/bLaAdO/fvV4uy7EeecVySZ/R3Bjzfol/aCxC m8xIeWL3ZhQeTKrvUezh55zYCVR2vgQ6FeAcDxxFx7WamY6j9+1vSmKw+54BYWzDTA5M pN3kTgTeUpak/JuAMDATHks48ilRJhbyfhHpzoKLpmY8GKvq6y30GqQwE3frEMazF/GY +xQsADBdDJUtr18ICOXWmLkW0XLrfZg4OLptOFnLZMyZ2p0dW9GR6wKAIoDlEB/l1hl0 Y5EA== X-Gm-Message-State: AOJu0YzY5SS71OwN84jnngmn+Gt24o+B124RhCiuS6aL7IpWWIqRrGlt 2VEutKGpib5Wihjl444rEctyb8xoxcVzAtdkXZCUDOGGDDmFkDGfZ4wtmw== X-Gm-Gg: ASbGnctMvkWH0ZygbQn6kxRC+NoVCND75yG9H7yjhufZdZNEI0zZ+j3dKxHnVeN7hsh 7JZsgTMlzErXSU3F7lu/f2Fjc4j53t9yBwUb7x5SnCmSleje3exCPe/vA73cx4Ukt6vugfLKCa+ kC8zXmHOZmWk8UNjCfaPBlyBjYi72EY4cO8ocXbihCP6XWZgjg0v5SB0OaB/jDNvsaBJWa4i+1u LDkYQ6V4Q7m1tklIKQz0ZgWviL+d+PPNmZNqBOZlbmYEl8kzrp80xmC9AWWXQ+VnEGvX5IOC5B7 iobtI27Lg+ta1Put9fb3OIRktUtihJUw+bB27OrHiNmsusiZKD6mA26p7HdU/ea9CmYHRoaU0nF sosI= X-Google-Smtp-Source: AGHT+IErWfCdyWJzznKNqyfiyo9BhMFI/d++hueh9xDLKCra6rAHpjGaNu82gOQ/K9EeMcUYj8D5CQ== X-Received: by 2002:ac8:7f4f:0:b0:476:8f75:b885 with SMTP id d75a77b69052e-4768f75d1efmr70761181cf.44.1741642880816; Mon, 10 Mar 2025 14:41:20 -0700 (PDT) Received: from LOCLAP699.locus-rst-dev-locuspark.locus ([152.193.78.90]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-476772de5absm30487841cf.66.2025.03.10.14.41.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Mar 2025 14:41:20 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 7/8] station: roam blacklist BSS when a roam is requested Date: Mon, 10 Mar 2025 14:40:58 -0700 Message-Id: <20250310214059.20809-7-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250310214059.20809-1-prestwoj@gmail.com> References: <20250310214059.20809-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 If the BSS is requesting IWD roam elsewhere add this BSS to the blacklist using BLACKLIST_REASON_ROAM_REQUESTED. This will lower the chances of IWD roaming/connecting back to this BSS in the future. In addition we also needed to update the roam_bss sorting to use __scan_bss_rank_compare so we sort based on the new groupings rather than only rank/rssi. --- src/station.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/station.c b/src/station.c index d16e82af..148f628d 100644 --- a/src/station.c +++ b/src/station.c @@ -184,11 +184,7 @@ static int roam_bss_rank_compare(const void *a, const void *b, void *user_data) { const struct roam_bss *new_bss = a, *bss = b; - if (bss->rank == new_bss->rank) - return (bss->signal_strength > - new_bss->signal_strength) ? 1 : -1; - - return (bss->rank > new_bss->rank) ? 1 : -1; + return __scan_bss_rank_compare(new_bss, bss); } struct wiphy *station_get_wiphy(struct station *station) @@ -3268,6 +3264,10 @@ static void station_ap_directed_roam(struct station *station, l_timeout_remove(station->roam_trigger_timeout); station->roam_trigger_timeout = NULL; + blacklist_add_bss(station->connected_bss->addr, + BLACKLIST_REASON_ROAM_REQUESTED); + station_debug_event(station, "ap-roam-blacklist-added"); + if (req_mode & WNM_REQUEST_MODE_PREFERRED_CANDIDATE_LIST) { l_debug("roam: AP sent a preferred candidate list"); station_neighbor_report_cb(station->netdev, 0, body + pos, From patchwork Mon Mar 10 21:40:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 14010759 Received: from mail-qt1-f182.google.com (mail-qt1-f182.google.com [209.85.160.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D48D1E25E1 for ; Mon, 10 Mar 2025 21:41:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642885; cv=none; b=cpo3y4LYj6U7fkCLg1TTMVLLMkYS3CZ570ZntmdEKk85u2H2Xut78VQoYuVdC9qgReXTzSsAiZOOloiC2n1fVznb/DB6c9Sc0CQciORL359KNy1ODSqBBk3NHvO+u1NgbYcjgFKka7/tl0DlHYVMRglIPgDMKqow3tq+ZZmUMZE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741642885; c=relaxed/simple; bh=DgQz+47eb6MRzQ7XuoYC13sW2oZDH0N7tu4Ow/4BwwQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=EYA+R2/KtVGX4uTpPj+o+JIQb5JBlxnGmKcb2WYLHWImTsSRdzVHj9ZA/pYEdvwekHj9h72fLII+XGVCc8DwtfjKogmosk322GU5V6m4jiQ4z3Zb+90tx8EmmBLMRjFD2/Bc9+0mqNZ/IwOlvuTZhKqGietsjqOLCH3LDbqlDqw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=F1Cu1Dtn; arc=none smtp.client-ip=209.85.160.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="F1Cu1Dtn" Received: by mail-qt1-f182.google.com with SMTP id d75a77b69052e-474f836eb4cso36401811cf.3 for ; Mon, 10 Mar 2025 14:41:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741642882; x=1742247682; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fYoe+3H8/5yAERsOoYL6MzUOf1VoKgTy+zK3fCZIX1M=; b=F1Cu1DtnVFCDlO5KpekVjuWthS8VMxkDV4oXDV4Yer3RKasOeJqCrBNU/LNczUR94e azAmnNxjii/9ZkQMN+ltTtjBGAPPPy2T93QoFxWcb+6KCKpumNyoO25AeNC7OP7nEYoW 7uOsHfDAWvw+JtgN2tprY+Jm5vTbFwSwLChE5F+hVjz7mAJTGDdifAOij77s3GULF3IE FwUyGw8e85IQkhX/a1JQOtqxpElIzIkXmAhisyfzczgLQH3Ay+4re+tQ9exctwo0a5gX uxa3vLhF1l5gsl1zhBa9UbGh9FWlxpUxYVcmiYYf37xFYD23T+D9Bx2FxAZk7EUhxBR5 roAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741642882; x=1742247682; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fYoe+3H8/5yAERsOoYL6MzUOf1VoKgTy+zK3fCZIX1M=; b=LktTAxWDM08iO0fcy2S4d1WvwQCa1cpYZlb0o2ViSDAOxSrkhOtJa7RtOrUeaYCpvH 0Ep3qjnzNuiZZEAPbHMHwRu1fwwGllBgSu4sIjp6t+AXKNmn6V1Z/yRnL7qMqEHlNuvN kUM/3VD4oetWZKC+uHGqUGnIrRPWVdsphmZ+1zemuAfbMmoaB8EXAmUiIAL7Tqwboz22 zrBET2FdyDi0pveL7ykP/LiB7TO750JZgF2Wzc2ouJvA2wzb3Zl7aiiy4qz1Q0w0HG2u HlQyztqMUswmG84EujUbi7nl1B+5j9xxdqyS1mQIbDmKh6NHEscDfJ/iANtAi8xk5Bb9 BxTw== X-Gm-Message-State: AOJu0Yw1gx5028770QVZgHAeji7tsF+kJDavyliitLBiA62yiOHONWA2 jUfKqHmSWHAKvKYv1CFQ1+SpMzbI2n812YAGtZ+ncM42k4JjmXdmgdjQjA== X-Gm-Gg: ASbGncsohRw2a915LWRTrxJnBfmKlH3PKPNBLY7Z9gpTZHXigjqW1olgP2v5niu9sN7 482xtadYJpm9+j88VmJeLmX/IW3k0dOmBudrojCTIzEXQ6nzr5G3Q3MIO6S1z4daJDpNZVWvB31 SByK+ogHqM52THfIyQrnWZRYyGv8p1pAHiDlBzL0GMZJVjdCv2/59fLDGtPLWLBxMLRTLhfGSwY pBrgrTbmqTF88rJ4Gk2F9rBN0sqb6I5TO9bi2M8H1Uzqs6aiuAKlcoQbegCwDvUvzvxti3nuwCn vYJ0pFL+t9QhndlOsgGlDZAHfmpRnPd75IoYa5LAbnQV4xYUq80f13743GJL+xeWOFBdgNdOw0z 42Ro= X-Google-Smtp-Source: AGHT+IFuJ3cK49a0/GQSi5nIz7UK9aUK1Jk9p+sPZBmnfD1tbB96jo8GqNfDDkJDINNn67Io3uj1VA== X-Received: by 2002:a05:622a:1993:b0:472:12f1:ba4a with SMTP id d75a77b69052e-4761095065emr249644531cf.4.1741642882209; Mon, 10 Mar 2025 14:41:22 -0700 (PDT) Received: from LOCLAP699.locus-rst-dev-locuspark.locus ([152.193.78.90]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-476772de5absm30487841cf.66.2025.03.10.14.41.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Mar 2025 14:41:21 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 8/8] auto-t: add test for AP roam blacklisting Date: Mon, 10 Mar 2025 14:40:59 -0700 Message-Id: <20250310214059.20809-8-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250310214059.20809-1-prestwoj@gmail.com> References: <20250310214059.20809-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- autotests/testAPRoam/connection_test.py | 2 +- autotests/testAPRoam/hw.conf | 2 + autotests/testAPRoam/main.conf | 5 + autotests/testAPRoam/roam_blacklist_test.py | 154 ++++++++++++++++++++ 4 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 autotests/testAPRoam/main.conf create mode 100644 autotests/testAPRoam/roam_blacklist_test.py diff --git a/autotests/testAPRoam/connection_test.py b/autotests/testAPRoam/connection_test.py index a419f4aa..9d17ca87 100644 --- a/autotests/testAPRoam/connection_test.py +++ b/autotests/testAPRoam/connection_test.py @@ -13,7 +13,7 @@ from hostapd import HostapdCLI class Test(unittest.TestCase): def validate(self, expect_roam=True): - wd = IWD() + wd = IWD(True) devices = wd.list_devices(1) device = devices[0] diff --git a/autotests/testAPRoam/hw.conf b/autotests/testAPRoam/hw.conf index 00a31063..46b1d4a8 100644 --- a/autotests/testAPRoam/hw.conf +++ b/autotests/testAPRoam/hw.conf @@ -1,5 +1,7 @@ [SETUP] num_radios=4 +hwsim_medium=true +start_iwd=false [HOSTAPD] rad0=ssid1.conf diff --git a/autotests/testAPRoam/main.conf b/autotests/testAPRoam/main.conf new file mode 100644 index 00000000..9c9fb994 --- /dev/null +++ b/autotests/testAPRoam/main.conf @@ -0,0 +1,5 @@ +[Rank] +OptimalSignalThreshold=-72 + +[Blacklist] +InitialRoamRequestedTimeout=20 diff --git a/autotests/testAPRoam/roam_blacklist_test.py b/autotests/testAPRoam/roam_blacklist_test.py new file mode 100644 index 00000000..259f6aa5 --- /dev/null +++ b/autotests/testAPRoam/roam_blacklist_test.py @@ -0,0 +1,154 @@ +#!/usr/bin/python3 + +import unittest +import sys + +sys.path.append('../util') +import iwd +from iwd import IWD +from iwd import NetworkType + +from hostapd import HostapdCLI +from hwsim import Hwsim + +class Test(unittest.TestCase): + def validate_connected(self, hostapd): + ordered_network = self.device.get_ordered_network('TestAPRoam') + + self.assertEqual(ordered_network.type, NetworkType.psk) + + condition = 'not obj.connected' + self.wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.device.connect_bssid(hostapd.bssid) + + condition = 'obj.state == DeviceState.connected' + self.wd.wait_for_object_condition(self.device, condition) + + hostapd.wait_for_event('AP-STA-CONNECTED') + + def validate_ap_roamed(self, from_hostapd, to_hostapd): + from_hostapd.send_bss_transition( + self.device.address, self.neighbor_list, disassoc_imminent=True + ) + + from_condition = 'obj.state == DeviceState.roaming' + to_condition = 'obj.state == DeviceState.connected' + self.wd.wait_for_object_change(self.device, from_condition, to_condition) + + to_hostapd.wait_for_event('AP-STA-CONNECTED %s' % self.device.address) + + self.device.wait_for_event("ap-roam-blacklist-added") + + def test_roam_to_optimal_candidates(self): + # In this test IWD will naturally transition down the list after each + # BSS gets roam blacklisted. All BSS's are above the RSSI thresholds. + self.rule_ssid1.signal = -5000 + self.rule_ssid2.signal = -6500 + self.rule_ssid3.signal = -6900 + + # Connect to BSS0 + self.validate_connected(self.bss_hostapd[0]) + + # AP directed roam to BSS1 + self.validate_ap_roamed(self.bss_hostapd[0], self.bss_hostapd[1]) + + # AP directed roam to BSS2 + self.validate_ap_roamed(self.bss_hostapd[1], self.bss_hostapd[2]) + + def test_avoiding_under_threshold_bss(self): + # In this test IWD will blacklist BSS0, then roam the BSS1. BSS1 will + # then tell IWD to roam, but it should go back to BSS0 since the only + # non-blacklisted BSS is under the roam threshold. + self.rule_ssid1.signal = -5000 + self.rule_ssid2.signal = -6500 + self.rule_ssid3.signal = -7300 + + # Connect to BSS0 + self.validate_connected(self.bss_hostapd[0]) + + # AP directed roam to BSS1 + self.validate_ap_roamed(self.bss_hostapd[0], self.bss_hostapd[1]) + + # AP directed roam, but IWD should choose BSS0 since BSS2 is -73dB + self.validate_ap_roamed(self.bss_hostapd[1], self.bss_hostapd[0]) + + def test_connect_to_roam_blacklisted_bss(self): + # In this test a BSS will be roam blacklisted, but all other options are + # below the RSSI threshold so IWD should roam back to the blacklisted + # BSS. + self.rule_ssid1.signal = -5000 + self.rule_ssid2.signal = -8000 + self.rule_ssid3.signal = -8500 + + # Connect to BSS0 + self.validate_connected(self.bss_hostapd[0]) + + # AP directed roam, should connect to BSS1 as its the next best + self.validate_ap_roamed(self.bss_hostapd[0], self.bss_hostapd[1]) + + # Connected to BSS1, but the signal is bad, so IWD should try to roam + # again. BSS0 is still blacklisted, but its the only reasonable option + # since both BSS1 and BSS2 are below the set RSSI threshold (-72dB) + + from_condition = 'obj.state == DeviceState.roaming' + to_condition = 'obj.state == DeviceState.connected' + self.wd.wait_for_object_change(self.device, from_condition, to_condition) + + # IWD should have connected to BSS0, even though its roam blacklisted + self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % self.device.address) + + def setUp(self): + self.wd = IWD(True) + + devices = self.wd.list_devices(1) + self.device = devices[0] + + + def tearDown(self): + self.wd = None + self.device = None + + + @classmethod + def setUpClass(cls): + IWD.copy_to_storage('TestAPRoam.psk') + hwsim = Hwsim() + + cls.bss_hostapd = [ HostapdCLI(config='ssid1.conf'), + HostapdCLI(config='ssid2.conf'), + HostapdCLI(config='ssid3.conf') ] + HostapdCLI.group_neighbors(*cls.bss_hostapd) + + rad0 = hwsim.get_radio('rad0') + rad1 = hwsim.get_radio('rad1') + rad2 = hwsim.get_radio('rad2') + + cls.neighbor_list = [ + (cls.bss_hostapd[0].bssid, "8f0000005101060603000000"), + (cls.bss_hostapd[1].bssid, "8f0000005102060603000000"), + (cls.bss_hostapd[2].bssid, "8f0000005103060603000000"), + ] + + + cls.rule_ssid1 = hwsim.rules.create() + cls.rule_ssid1.source = rad0.addresses[0] + cls.rule_ssid1.bidirectional = True + cls.rule_ssid1.enabled = True + + cls.rule_ssid2 = hwsim.rules.create() + cls.rule_ssid2.source = rad1.addresses[0] + cls.rule_ssid2.bidirectional = True + cls.rule_ssid2.enabled = True + + cls.rule_ssid3 = hwsim.rules.create() + cls.rule_ssid3.source = rad2.addresses[0] + cls.rule_ssid3.bidirectional = True + cls.rule_ssid3.enabled = True + + @classmethod + def tearDownClass(cls): + IWD.clear_storage() + +if __name__ == '__main__': + unittest.main(exit=True)