From c07babbdf667ec7c3b4b47460aba56ac629c15db Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Wed, 16 Mar 2022 10:39:08 -0700 Subject: [PATCH 01/13] Workflow's for syncing with upstream, build, unit test, and test-runner --- .github/workflows/ci.yml | 236 +++++++++++++++++++++++++++ .github/workflows/pw-to-pr-email.txt | 16 ++ .github/workflows/pw-to-pr.json | 14 ++ .github/workflows/schedule_work.yml | 43 +++++ 4 files changed, 309 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/pw-to-pr-email.txt create mode 100644 .github/workflows/pw-to-pr.json create mode 100644 .github/workflows/schedule_work.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..8e140ad8c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,236 @@ +name: IWD CI + +# +# The basic flow of the CI is as follows: +# +# 1. Get all inputs, or default values, and set as 'setup' job output +# 2. Find any cached binaries (hostapd, wpa_supplicant, kernel etc) +# 3. Checkout all dependent repositories +# 4. Tar all local files. This is an unfortunate requirement since github jobs +# cannot share local files. Since there are multiple CI's acting on the same +# set of repositories it makes more sense to retain these and re-download +# them for each CI job. +# 5. Run each CI, currently 'main' and 'musl'. +# * 'main' is the default IWD CI which runs all the build steps as well +# as test-runner +# * 'musl' uses an alpine docker image to test the build on musl-libc +# +# Both CI's use the 'iwd-ci-v2' repo which calls into 'ci-docker'. The +# 'ci-docker' action essentially re-implements the native Github docker +# action but allows arbitrary options to be passed in (e.g. privileged or +# mounting non-standard directories) +# + +on: + pull_request: + workflow_dispatch: + inputs: + tests: + description: Tests to run (comma separated, no spaces) + default: all + kernel: + description: Kernel version + default: '5.16' + hostapd_version: + description: Hostapd and wpa_supplicant version + default: '2_10' + ell_ref: + description: ELL reference + default: refs/heads/workflow + + repository_dispatch: + types: [ell-dispatch] + +jobs: + setup: + runs-on: ubuntu-22.04 + outputs: + tests: ${{ steps.inputs.outputs.tests }} + kernel: ${{ steps.inputs.outputs.kernel }} + hostapd_version: ${{ steps.inputs.outputs.hostapd_version }} + ell_ref: ${{ steps.inputs.outputs.ell_ref }} + repository: ${{ steps.inputs.outputs.repository }} + ref_branch: ${{ steps.inputs.outputs.ref_branch }} + steps: + # + # This makes CI inputs consistent depending on how the CI was invoked: + # * pull_request trigger won't have any inputs, so these need to be set + # to default values. + # * workflow_dispatch sets all inputs from the user input + # * repository_dispatch sets all inputs based on the JSON payload of + # the request. + # + - name: Setup Inputs + id: inputs + run: | + if [ ${{ github.event_name }} == 'workflow_dispatch' ] + then + TESTS=${{ github.event.inputs.tests }} + KERNEL=${{ github.event.inputs.kernel }} + HOSTAPD_VERSION=${{ github.event.inputs.hostapd_version }} + ELL_REF=${{ github.event.inputs.ell_ref }} + REF="$GITHUB_REF" + REPO="$GITHUB_REPOSITORY" + elif [ ${{ github.event_name }} == 'repository_dispatch' ] + then + TESTS=all + KERNEL=5.16 + HOSTAPD_VERSION=2_10 + ELL_REF=${{ github.event.client_payload.ref }} + REF=$ELL_REF + REPO=${{ github.event.client_payload.repo }} + else + TESTS=all + KERNEL=5.16 + HOSTAPD_VERSION=2_10 + ELL_REF="refs/heads/workflow" + REF="$GITHUB_REF" + REPO="$GITHUB_REPOSITORY" + fi + + # + # Now that the inputs are sorted, set the output of this step to these + # values so future jobs can refer to them. + # + echo ::set-output name=tests::$TESTS + echo ::set-output name=kernel::$KERNEL + echo ::set-output name=hostapd_version::$HOSTAPD_VERSION + echo ::set-output name=ell_ref::$ELL_REF + echo ::set-output name=repository::$REPO + echo ::set-output name=ref_branch::$REF + + - name: Cache UML Kernel + id: cache-uml-kernel + uses: actions/cache@v3 + with: + path: ${{ github.workspace }}/cache/um-linux-${{ steps.inputs.outputs.kernel }} + key: um-linux-${{ steps.inputs.outputs.kernel }}_ubuntu22 + + - name: Cache Hostapd + id: cache-hostapd + uses: actions/cache@v3 + with: + path: | + ${{ github.workspace }}/cache/hostapd_${{ steps.inputs.outputs.hostapd_version }} + ${{ github.workspace }}/cache/hostapd_cli_${{ steps.inputs.outputs.hostapd_version }} + key: hostapd_${{ steps.inputs.outputs.hostapd_version }}_ssl3 + + - name: Cache WpaSupplicant + id: cache-wpas + uses: actions/cache@v3 + with: + path: | + ${{ github.workspace }}/cache/wpa_supplicant_${{ steps.inputs.outputs.hostapd_version }} + ${{ github.workspace }}/cache/wpa_cli_${{ steps.inputs.outputs.hostapd_version }} + key: wpa_supplicant_${{ steps.inputs.outputs.hostapd_version }}_ssl3 + + - name: Checkout IWD + uses: actions/checkout@v3 + with: + path: iwd + repository: IWDTestBot/iwd + token: ${{ secrets.ACTION_TOKEN }} + + - name: Checkout ELL + uses: actions/checkout@v3 + with: + path: ell + repository: IWDTestBot/ell + ref: ${{ steps.inputs.outputs.ell_ref }} + + - name: Checkout CiBase + uses: actions/checkout@v3 + with: + repository: IWDTestBot/cibase + path: cibase + + - name: Checkout CI + uses: actions/checkout@v3 + with: + repository: IWDTestBot/iwd-ci-v2 + path: iwd-ci + + - name: Tar files + run: | + tar -cvf archive.tar \ + ${{ github.workspace }}/cache/um-linux-${{ steps.inputs.outputs.kernel }} \ + ${{ github.workspace }}/cache/hostapd_${{ steps.inputs.outputs.hostapd_version }} \ + ${{ github.workspace }}/cache/hostapd_cli_${{ steps.inputs.outputs.hostapd_version }} \ + ${{ github.workspace }}/cache/wpa_supplicant_${{ steps.inputs.outputs.hostapd_version }} \ + ${{ github.workspace }}/cache/wpa_cli_${{ steps.inputs.outputs.hostapd_version }} \ + iwd \ + ell \ + cibase \ + iwd-ci \ + cache + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: iwd-artifacts + path: | + archive.tar + + iwd-alpine-ci: + runs-on: ubuntu-22.04 + needs: setup + steps: + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + name: iwd-artifacts + + - name: Untar + run: tar -xf archive.tar + + - name: Modprobe pkcs8_key_parser + run: | + sudo modprobe pkcs8_key_parser + + - name: Alpine CI + uses: IWDTestBot/iwd-ci-v2@master + with: + ref_branch: ${{ needs.setup.outputs.ref_branch }} + repository: ${{ needs.setup.outputs.repository }} + github_token: ${{ secrets.ACTION_TOKEN }} + email_token: ${{ secrets.EMAIL_TOKEN }} + patchwork_token: ${{ secrets.PATCHWORK_TOKEN }} + ci: musl + + iwd-ci: + runs-on: ubuntu-22.04 + needs: setup + steps: + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + name: iwd-artifacts + + - name: Untar + run: tar -xf archive.tar + + - name: Modprobe pkcs8_key_parser + run: | + sudo modprobe pkcs8_key_parser + echo ${{ needs.setup.outputs.ref_branch }} + echo ${{ needs.setup.outputs.repository }} + + - name: Run CI + uses: IWDTestBot/iwd-ci-v2@master + with: + ref_branch: ${{ needs.setup.outputs.ref_branch }} + repository: ${{ needs.setup.outputs.repository }} + tests: ${{ needs.setup.outputs.tests }} + kernel: ${{ needs.setup.outputs.kernel }} + hostapd_version: ${{ needs.setup.outputs.hostapd_version }} + github_token: ${{ secrets.ACTION_TOKEN }} + email_token: ${{ secrets.EMAIL_TOKEN }} + patchwork_token: ${{ secrets.PATCHWORK_TOKEN }} + ci: main + + - name: Upload Logs + if: always() + uses: actions/upload-artifact@v3 + with: + name: test-runner-logs + path: ${{ github.workspace }}/log diff --git a/.github/workflows/pw-to-pr-email.txt b/.github/workflows/pw-to-pr-email.txt new file mode 100644 index 000000000..0ad6d7659 --- /dev/null +++ b/.github/workflows/pw-to-pr-email.txt @@ -0,0 +1,16 @@ +This is an automated email and please do not reply to this email. + +Dear Submitter, + +Thank you for submitting the patches to the IWD mailing list. +While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository. + +----- Output ----- +{} + +Please resolve the issue and submit the patches again. + + +--- +Regards, +IWDTestBot diff --git a/.github/workflows/pw-to-pr.json b/.github/workflows/pw-to-pr.json new file mode 100644 index 000000000..b4491413c --- /dev/null +++ b/.github/workflows/pw-to-pr.json @@ -0,0 +1,14 @@ +{ + "email": { + "enable": true, + "server": "smtp.gmail.com", + "port": 587, + "user": "iwd.ci.bot@gmail.com", + "starttls": true, + "default-to": "prestwoj@gmail.com", + "only-maintainers": false, + "maintainers": [ + "prestwoj@gmail.com" + ] + } +} diff --git a/.github/workflows/schedule_work.yml b/.github/workflows/schedule_work.yml new file mode 100644 index 000000000..cfc14fba9 --- /dev/null +++ b/.github/workflows/schedule_work.yml @@ -0,0 +1,43 @@ +name: Sync Upstream +on: + schedule: + - cron: "*/15 * * * *" + workflow_dispatch: + +jobs: + repo-sync: + runs-on: ubuntu-latest + steps: + + - uses: actions/checkout@v2 + with: + persist-credentials: false + fetch-depth: 0 + + - name: Manage Repo + uses: IWDTestBot/action-manage-repo@master + with: + src_repo: "https://git.kernel.org/pub/scm/network/wireless/iwd.git" + src_branch: "master" + dest_branch: "master" + workflow_branch: "workflow" + github_token: ${{ secrets.GITHUB_TOKEN }} + + create_pr: + needs: repo-sync + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Patchwork to PR + uses: IWDTestBot/action-patchwork-to-pr@master + with: + pw_key_str: "user" + github_token: ${{ secrets.ACTION_TOKEN }} + email_token: ${{ secrets.EMAIL_TOKEN }} + patchwork_token: ${{ secrets.PATCHWORK_TOKEN }} + config: https://raw.githubusercontent.com/IWDTestBot/iwd/workflow/.github/workflows/pw-to-pr.json + patchwork_id: "408" + email_message: https://raw.githubusercontent.com/IWDTestBot/iwd/workflow/.github/workflows/pw-to-pr-email.txt From 1d8e26a275a11094a7064594f921f3bfdabcc314 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Fri, 24 Jun 2022 15:27:03 -0700 Subject: [PATCH 02/13] workflow: use newer commit for hostapd --- .github/workflows/ci.yml | 61 +++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e140ad8c..4bf5b1347 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ on: default: '5.16' hostapd_version: description: Hostapd and wpa_supplicant version - default: '2_10' + default: '09a281e52a25b5461c4b08d261f093181266a554' ell_ref: description: ELL reference default: refs/heads/workflow @@ -75,14 +75,14 @@ jobs: then TESTS=all KERNEL=5.16 - HOSTAPD_VERSION=2_10 + HOSTAPD_VERSION=09a281e52a25b5461c4b08d261f093181266a554 ELL_REF=${{ github.event.client_payload.ref }} REF=$ELL_REF REPO=${{ github.event.client_payload.repo }} else TESTS=all KERNEL=5.16 - HOSTAPD_VERSION=2_10 + HOSTAPD_VERSION=09a281e52a25b5461c4b08d261f093181266a554 ELL_REF="refs/heads/workflow" REF="$GITHUB_REF" REPO="$GITHUB_REPOSITORY" @@ -152,17 +152,25 @@ jobs: - name: Tar files run: | - tar -cvf archive.tar \ - ${{ github.workspace }}/cache/um-linux-${{ steps.inputs.outputs.kernel }} \ - ${{ github.workspace }}/cache/hostapd_${{ steps.inputs.outputs.hostapd_version }} \ - ${{ github.workspace }}/cache/hostapd_cli_${{ steps.inputs.outputs.hostapd_version }} \ - ${{ github.workspace }}/cache/wpa_supplicant_${{ steps.inputs.outputs.hostapd_version }} \ - ${{ github.workspace }}/cache/wpa_cli_${{ steps.inputs.outputs.hostapd_version }} \ - iwd \ - ell \ - cibase \ - iwd-ci \ - cache + FILES="iwd ell cibase iwd-ci cache" + + if [ "${{ steps.cache-uml-kernel.outputs.cache-hit }}" == 'true' ] + then + FILES+=" ${{ github.workspace }}/cache/um-linux-${{ steps.inputs.outputs.kernel }}" + fi + + if [ "${{ steps.cache-hostapd.outputs.cache-hit }}" == 'true' ] + then + FILES+=" ${{ github.workspace }}/cache/hostapd_${{ steps.inputs.outputs.hostapd_version }}" + FILES+=" ${{ github.workspace }}/cache/hostapd_cli_${{ steps.inputs.outputs.hostapd_version }}" + fi + if [ "${{ steps.cache-wpas.outputs.cache-hit }}" == 'true' ] + then + FILES+=" ${{ github.workspace }}/cache/wpa_supplicant_${{ steps.inputs.outputs.hostapd_version }}" + FILES+=" ${{ github.workspace }}/cache/wpa_cli_${{ steps.inputs.outputs.hostapd_version }}" + fi + + tar -cvf archive.tar $FILES - name: Upload artifacts uses: actions/upload-artifact@v3 @@ -209,6 +217,31 @@ jobs: - name: Untar run: tar -xf archive.tar + - name: Cache UML Kernel + id: cache-uml-kernel + uses: actions/cache@v3 + with: + path: ${{ github.workspace }}/cache/um-linux-${{ needs.setup.outputs.kernel }} + key: um-linux-${{ needs.setup.outputs.kernel }}_ubuntu22 + + - name: Cache Hostapd + id: cache-hostapd + uses: actions/cache@v3 + with: + path: | + ${{ github.workspace }}/cache/hostapd_${{ needs.setup.outputs.hostapd_version }} + ${{ github.workspace }}/cache/hostapd_cli_${{ needs.setup.outputs.hostapd_version }} + key: hostapd_${{ needs.setup.outputs.hostapd_version }}_ssl3 + + - name: Cache WpaSupplicant + id: cache-wpas + uses: actions/cache@v3 + with: + path: | + ${{ github.workspace }}/cache/wpa_supplicant_${{ needs.setup.outputs.hostapd_version }} + ${{ github.workspace }}/cache/wpa_cli_${{ needs.setup.outputs.hostapd_version }} + key: wpa_supplicant_${{ needs.setup.outputs.hostapd_version }}_ssl3 + - name: Modprobe pkcs8_key_parser run: | sudo modprobe pkcs8_key_parser From 0c51e5ecaf22ade5475161c9e165c33596e35257 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Wed, 7 Sep 2022 14:51:41 -0700 Subject: [PATCH 03/13] ci: remove cache/ from tar file list This is taken care of by the individual cache items and if none exist, tar fails. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4bf5b1347..09bbb2961 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,7 +152,7 @@ jobs: - name: Tar files run: | - FILES="iwd ell cibase iwd-ci cache" + FILES="iwd ell cibase iwd-ci" if [ "${{ steps.cache-uml-kernel.outputs.cache-hit }}" == 'true' ] then From c7491d8c6daa180478b58f80c573794e097d7e0a Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Wed, 14 Sep 2022 15:35:30 -0700 Subject: [PATCH 04/13] ci: use kernel 5.19 --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 09bbb2961..20b2e8419 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ on: default: all kernel: description: Kernel version - default: '5.16' + default: '5.19' hostapd_version: description: Hostapd and wpa_supplicant version default: '09a281e52a25b5461c4b08d261f093181266a554' @@ -74,14 +74,14 @@ jobs: elif [ ${{ github.event_name }} == 'repository_dispatch' ] then TESTS=all - KERNEL=5.16 + KERNEL=5.19 HOSTAPD_VERSION=09a281e52a25b5461c4b08d261f093181266a554 ELL_REF=${{ github.event.client_payload.ref }} REF=$ELL_REF REPO=${{ github.event.client_payload.repo }} else TESTS=all - KERNEL=5.16 + KERNEL=5.19 HOSTAPD_VERSION=09a281e52a25b5461c4b08d261f093181266a554 ELL_REF="refs/heads/workflow" REF="$GITHUB_REF" From 78ad7643e5a6fb4be2692944cd1eed8b9779addd Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Fri, 14 Oct 2022 08:58:15 -0700 Subject: [PATCH 05/13] ci: use iwd-ci after renaming to remove -v2 --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20b2e8419..3f9d6981a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ name: IWD CI # as test-runner # * 'musl' uses an alpine docker image to test the build on musl-libc # -# Both CI's use the 'iwd-ci-v2' repo which calls into 'ci-docker'. The +# Both CI's use the 'iwd-ci' repo which calls into 'ci-docker'. The # 'ci-docker' action essentially re-implements the native Github docker # action but allows arbitrary options to be passed in (e.g. privileged or # mounting non-standard directories) @@ -147,7 +147,7 @@ jobs: - name: Checkout CI uses: actions/checkout@v3 with: - repository: IWDTestBot/iwd-ci-v2 + repository: IWDTestBot/iwd-ci path: iwd-ci - name: Tar files @@ -196,7 +196,7 @@ jobs: sudo modprobe pkcs8_key_parser - name: Alpine CI - uses: IWDTestBot/iwd-ci-v2@master + uses: IWDTestBot/iwd-ci@master with: ref_branch: ${{ needs.setup.outputs.ref_branch }} repository: ${{ needs.setup.outputs.repository }} @@ -249,7 +249,7 @@ jobs: echo ${{ needs.setup.outputs.repository }} - name: Run CI - uses: IWDTestBot/iwd-ci-v2@master + uses: IWDTestBot/iwd-ci@master with: ref_branch: ${{ needs.setup.outputs.ref_branch }} repository: ${{ needs.setup.outputs.repository }} From 11b2b74152f2132d83de281de9f2dbdb09ac7d69 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Fri, 14 Oct 2022 10:18:25 -0700 Subject: [PATCH 06/13] ci: remove set-output use, now deprecated --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f9d6981a..393341c27 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,12 +92,12 @@ jobs: # Now that the inputs are sorted, set the output of this step to these # values so future jobs can refer to them. # - echo ::set-output name=tests::$TESTS - echo ::set-output name=kernel::$KERNEL - echo ::set-output name=hostapd_version::$HOSTAPD_VERSION - echo ::set-output name=ell_ref::$ELL_REF - echo ::set-output name=repository::$REPO - echo ::set-output name=ref_branch::$REF + echo "tests=$TESTS" >> $GITHUB_OUTPUT + echo "kernel=$KERNEL" >> $GITHUB_OUTPUT + echo "hostapd_version=$HOSTAPD_VERSION" >> $GITHUB_OUTPUT + echo "ell_ref=$ELL_REF" >> $GITHUB_OUTPUT + echo "repository=$REPO" >> $GITHUB_OUTPUT + echo "ref_branch=$REF" >> $GITHUB_OUTPUT - name: Cache UML Kernel id: cache-uml-kernel From 37c319d9399d94cb0c896d299f2a630e64d65a9f Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Thu, 7 Nov 2024 06:12:51 -0800 Subject: [PATCH 07/13] Update kernel to 6.2 and hostapd/wpa_s to 2.11 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 393341c27..993ce662d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,10 +30,10 @@ on: default: all kernel: description: Kernel version - default: '5.19' + default: '6.2' hostapd_version: description: Hostapd and wpa_supplicant version - default: '09a281e52a25b5461c4b08d261f093181266a554' + default: 'hostapd_2_11' ell_ref: description: ELL reference default: refs/heads/workflow From 26fedda44ac330e01d8c5877f0151288f455065e Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Thu, 13 Feb 2025 08:18:29 -0800 Subject: [PATCH 08/13] Update upload/download-artifact to v4 --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 993ce662d..a9582eb14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -173,7 +173,7 @@ jobs: tar -cvf archive.tar $FILES - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: iwd-artifacts path: | @@ -184,7 +184,7 @@ jobs: needs: setup steps: - name: Download artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: iwd-artifacts @@ -210,7 +210,7 @@ jobs: needs: setup steps: - name: Download artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: iwd-artifacts @@ -263,7 +263,7 @@ jobs: - name: Upload Logs if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-runner-logs path: ${{ github.workspace }}/log From e84d9233b4c073552653f269e3200a748f3fb150 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Fri, 18 Apr 2025 12:03:43 -0700 Subject: [PATCH 09/13] Add coverity Github action --- .github/workflows/coverity.yml | 86 ++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 .github/workflows/coverity.yml diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml new file mode 100644 index 000000000..91f9073d3 --- /dev/null +++ b/.github/workflows/coverity.yml @@ -0,0 +1,86 @@ +name: Coverity Scan and Submit +description: Runs a coverity scan, then sends results to the cloud +on: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + scan-and-submit: + runs-on: ubuntu-22.04 + steps: + - name: Lookup latest tool + id: cache-lookup + run: | + hash=$(curl https://scan.coverity.com/download/cxx/linux64 \ + --data "token=${{ secrets.COVERITY_IWD_TOKEN }}&project=IWD&md5=1"); + echo "hash=${hash}" >> $GITHUB_OUTPUT + + - name: Get cached coverity tool + id: build-cache + uses: actions/cache@v4 + with: + path: ${{ github.workspace }}/cov-analysis + key: cov-build-cxx-linux64-${{ steps.cache-lookup.outputs.hash }} + + - name: Download Coverity Build Tool + if: steps.build-cache.outputs.cache-hit != 'true' + run: | + curl https://scan.coverity.com/download/cxx/linux64 \ + --no-progress-meter \ + --output cov-analysis.tar.gz \ + --data "token=${{ secrets.COVERITY_IWD_TOKEN }}&project=IWD" + shell: bash + working-directory: ${{ github.workspace }} + + - if: steps.build-cache.outputs.cache-hit != 'true' + run: mkdir cov-analysis + shell: bash + working-directory: ${{ github.workspace }} + + - if: steps.build-cache.outputs.cache-hit != 'true' + run: tar -xzf cov-analysis.tar.gz --strip 1 -C cov-analysis + shell: bash + working-directory: ${{ github.workspace }} + + - name: Checkout IWD + uses: actions/checkout@v3 + with: + path: ${{ github.workspace }}/iwd + repository: IWDTestBot/iwd + token: ${{ secrets.ACTION_TOKEN }} + + - name: Checkout ELL + uses: actions/checkout@v3 + with: + path: ${{ github.workspace }}/ell + repository: IWDTestBot/ell + token: ${{ secrets.ACTION_TOKEN }} + + - name: Configure IWD + run: | + cd ${{ github.workspace }}/iwd + ./bootstrap-configure --disable-manual-pages + + - name: Build with cov-build + run: | + export PATH="${{ github.workspace }}/cov-analysis/bin:${PATH}" + cov-build --dir cov-int make -j4 + shell: bash + working-directory: ${{ github.workspace }}/iwd + + - name: Tar results + run: tar -czvf cov-int.tgz cov-int + shell: bash + working-directory: ${{ github.workspace }}/iwd + + - name: Submit results to Coverity Scan + if: ${{ ! inputs.dry_run }} + run: | + curl \ + --form token="${{ secrets.COVERITY_IWD_TOKEN }}" \ + --form email="iwd.ci.bot@gmail.com" \ + --form file=@cov-int.tgz \ + "https://scan.coverity.com/builds?project=IWD" + shell: bash + working-directory: ${{ github.workspace }}/iwd From d035ebb7fcfe735c57c7b954150464c2c6c23c9d Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 18 Aug 2025 07:55:14 -0700 Subject: [PATCH 10/13] Fix hostap branch name --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9582eb14..51153d6dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ on: default: '6.2' hostapd_version: description: Hostapd and wpa_supplicant version - default: 'hostapd_2_11' + default: 'hostap_2_11' ell_ref: description: ELL reference default: refs/heads/workflow From 0588f2bd05a3aaa44e3ef75252e9d6156e199a85 Mon Sep 17 00:00:00 2001 From: Alexander Ganslandt Date: Fri, 29 Aug 2025 09:43:39 +0200 Subject: [PATCH 11/13] util: add scan_freq_set_size function Return the number of freqs in a scan_freq_set, useful for knowing how big the set is. --- src/util.c | 11 +++++++++++ src/util.h | 1 + 2 files changed, 12 insertions(+) diff --git a/src/util.c b/src/util.c index 65b97c8eb..1e1dfc150 100644 --- a/src/util.c +++ b/src/util.c @@ -637,6 +637,17 @@ struct scan_freq_set *scan_freq_set_clone(const struct scan_freq_set *set, return new; } +uint32_t scan_freq_set_size(struct scan_freq_set *freqs) +{ + uint32_t size = 0; + + size += __builtin_popcount(freqs->channels_2ghz); + size += l_uintset_size(freqs->channels_5ghz); + size += l_uintset_size(freqs->channels_6ghz); + + return size; +} + /* First 64 entries calculated by 1 / pow(n, 0.3) for n >= 1 */ static const double rankmod_table[] = { 1.0000000000, 0.8122523964, 0.7192230933, 0.6597539554, diff --git a/src/util.h b/src/util.h index 8aef2985b..7c024c791 100644 --- a/src/util.h +++ b/src/util.h @@ -138,6 +138,7 @@ uint32_t *scan_freq_set_to_fixed_array(const struct scan_freq_set *set, size_t *len_out); struct scan_freq_set *scan_freq_set_clone(const struct scan_freq_set *set, uint32_t band_mask); +uint32_t scan_freq_set_size(struct scan_freq_set *freqs); DEFINE_CLEANUP_FUNC(scan_freq_set_free); From 80faf5d9551023c614d271a2787de8517ead888e Mon Sep 17 00:00:00 2001 From: Alexander Ganslandt Date: Fri, 29 Aug 2025 09:43:40 +0200 Subject: [PATCH 12/13] station: improve scan_freqs_order channel subsets Splits the scan frequencies into more subsets that have been ordered such that the more common frequencies appear first, and the more uncommon frequencies last. Non-DFS channels are also added to the earlier subsets to prioritize fast-scanning frequencies. This approach allows iwd to scan the frequencies with the statistically highest chance for BSSes first, resulting in shorter scan times until a good BSS is found. In future patches this will also be used when roaming. --- src/station.c | 122 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 33 deletions(-) diff --git a/src/station.c b/src/station.c index f8069d897..c2e18fc9a 100644 --- a/src/station.c +++ b/src/station.c @@ -125,7 +125,7 @@ struct station { struct l_queue *roam_bss_list; /* Frequencies split into subsets by priority */ - struct scan_freq_set *scan_freqs_order[3]; + struct scan_freq_set *scan_freqs_order[5]; unsigned int dbus_scan_subset_idx; uint32_t wiphy_watch; @@ -4500,8 +4500,7 @@ static bool station_dbus_scan_results(int err, struct l_queue *bss_list, return false; } - last_subset = next_idx >= L_ARRAY_SIZE(station->scan_freqs_order) || - station->scan_freqs_order[next_idx] == NULL; + last_subset = next_idx >= L_ARRAY_SIZE(station->scan_freqs_order); station->dbus_scan_subset_idx = next_idx; station_set_scan_results(station, bss_list, freqs, false); @@ -4516,6 +4515,15 @@ static bool station_dbus_scan_subset(struct station *station) { unsigned int idx = station->dbus_scan_subset_idx; + /* Find the next non-empty subset */ + while (idx < L_ARRAY_SIZE(station->scan_freqs_order) && + scan_freq_set_isempty(station->scan_freqs_order[idx])) + idx++; + station->dbus_scan_subset_idx = idx; + + if (idx >= L_ARRAY_SIZE(station->scan_freqs_order)) + return false; + station->dbus_scan_id = station_scan_trigger(station, station->scan_freqs_order[idx], station_dbus_scan_triggered, @@ -5061,40 +5069,91 @@ static void station_fill_scan_freq_subsets(struct station *station) wiphy_get_supported_freqs(station->wiphy); unsigned int subset_idx = 0; - /* - * Scan the 2.4GHz "social channels" first, 5GHz second, if supported, - * all other 2.4GHz channels last. To be refined as needed. - */ + station->scan_freqs_order[subset_idx] = scan_freq_set_new(); + + /* Subset 0: 2.4GHz "social channels" and low 5GHz non-DFS channels */ if (allowed_bands & BAND_FREQ_2_4_GHZ) { - station->scan_freqs_order[subset_idx] = scan_freq_set_new(); + /* Channels 1, 6, 11 */ scan_freq_set_add(station->scan_freqs_order[subset_idx], 2412); scan_freq_set_add(station->scan_freqs_order[subset_idx], 2437); scan_freq_set_add(station->scan_freqs_order[subset_idx], 2462); - subset_idx++; } - /* - * TODO: It may might sense to split up 5 and 6ghz into separate subsets - * since the channel set is so large. - */ - if (allowed_bands & (BAND_FREQ_5_GHZ | BAND_FREQ_6_GHZ)) { - uint32_t mask = allowed_bands & - (BAND_FREQ_5_GHZ | BAND_FREQ_6_GHZ); - struct scan_freq_set *set = scan_freq_set_clone(supported, - mask); - - /* 5/6ghz didn't add any frequencies */ - if (scan_freq_set_isempty(set)) { - scan_freq_set_free(set); - } else - station->scan_freqs_order[subset_idx++] = set; + if (allowed_bands & BAND_FREQ_5_GHZ) { + /* Channels 32 - 48 */ + for (int i = 5160; i <= 5240; i+=20) { + scan_freq_set_add(station->scan_freqs_order[subset_idx], i); + } } - /* Add remaining 2.4ghz channels to subset */ + scan_freq_set_constrain(station->scan_freqs_order[subset_idx], supported); + station->scan_freqs_order[++subset_idx] = scan_freq_set_new(); + + /* Subset 1: Remaining common 2.4GHz channels and high 5GHz non-DFS channels */ if (allowed_bands & BAND_FREQ_2_4_GHZ) { - station->scan_freqs_order[subset_idx] = scan_freq_set_new(); - scan_freq_set_foreach(supported, station_add_2_4ghz_freq, - station->scan_freqs_order[subset_idx]); + /* Channels 2 - 10, except 6 */ + for (int i = 2417; i < 2462; i+=5) { + if (i != 2437) + scan_freq_set_add(station->scan_freqs_order[subset_idx], i); + } + } + + if (allowed_bands & BAND_FREQ_5_GHZ) { + /* Channels 149 - 177 */ + for (int i = 5745; i <= 5885; i+=20) { + scan_freq_set_add(station->scan_freqs_order[subset_idx], i); + } + } + + scan_freq_set_constrain(station->scan_freqs_order[subset_idx], supported); + station->scan_freqs_order[++subset_idx] = scan_freq_set_new(); + + /* Subset 2: Uncommon 2.4GHz channels and 5GHz DFS channels */ + if (allowed_bands & BAND_FREQ_2_4_GHZ) { + /* Channels 12 - 14 */ + scan_freq_set_add(station->scan_freqs_order[subset_idx], 2467); + scan_freq_set_add(station->scan_freqs_order[subset_idx], 2472); + scan_freq_set_add(station->scan_freqs_order[subset_idx], 2484); + } + + if (allowed_bands & BAND_FREQ_5_GHZ) { + /* Channels 52 - 68 */ + for (int i = 5260; i <= 5340; i+=20) { + scan_freq_set_add(station->scan_freqs_order[subset_idx], i); + } + + /* Channels 96 - 144 */ + for (int i = 5480; i <= 5720; i+=20) { + scan_freq_set_add(station->scan_freqs_order[subset_idx], i); + } + } + + scan_freq_set_constrain(station->scan_freqs_order[subset_idx], supported); + station->scan_freqs_order[++subset_idx] = scan_freq_set_new(); + + /* Subset 3: 6GHz channels */ + if (allowed_bands & BAND_FREQ_6_GHZ) { + struct scan_freq_set *set = scan_freq_set_clone(supported, BAND_FREQ_6_GHZ); + + if (scan_freq_set_isempty(set)) + scan_freq_set_free(set); + else + scan_freq_set_merge(station->scan_freqs_order[subset_idx], set); + } + + scan_freq_set_constrain(station->scan_freqs_order[subset_idx], supported); + station->scan_freqs_order[++subset_idx] = scan_freq_set_clone(supported, allowed_bands); + + /* All channels that are both supported and allowed should be in the subsets, + * if this is not the case then some new channel has been added that we are + * not tracking, put it in the last subset to make sure it's scanned */ + for (int i = 0; i < 4; i++) { + scan_freq_set_subtract(station->scan_freqs_order[subset_idx], + station->scan_freqs_order[i]); + } + + if (!scan_freq_set_isempty(station->scan_freqs_order[subset_idx])) { + l_warn("Final subset is not empty"); } /* @@ -5273,11 +5332,8 @@ static void station_free(struct station *station) l_queue_destroy(station->anqp_pending, remove_anqp); - scan_freq_set_free(station->scan_freqs_order[0]); - scan_freq_set_free(station->scan_freqs_order[1]); - - if (station->scan_freqs_order[2]) - scan_freq_set_free(station->scan_freqs_order[2]); + for (uint8_t i = 0; i < L_ARRAY_SIZE(station->scan_freqs_order); i++) + scan_freq_set_free(station->scan_freqs_order[i]); wiphy_state_watch_remove(station->wiphy, station->wiphy_watch); From 8d537a63f937060fe49ff8875b428df7bebd2776 Mon Sep 17 00:00:00 2001 From: Alexander Ganslandt Date: Fri, 29 Aug 2025 09:43:41 +0200 Subject: [PATCH 13/13] station: improve roam scan strategy When iwd decides to roam, it scans either neighbor freqs or known freqs (if neighbors are not available). If it fails to roam after getting the scan results, it scans ALL freqs. There's a high chance that both neighbor and/or known scans fail to roam and we end up scanning all freqs. This is very slow and if you're already moving away from the current BSS, there's a high chance you will lose connection completely before the scan is finished. Instead of scanning all freqs at once, use the already-defined subsets to optimize the scans. The subsets contain a handful of freqs each and are ordered to increase the chance of finding a good BSS early. In order to not scan the same freq multiple times, use a list (scanned_freqs) to keep track of which freqs have been scanned in the current roam attempt. When a roam scan is triggered, add the most prioritized freqs to the list of freqs that should be scanned. The order of priority is: 1. Neighbor freqs 2. Known freqs 3. Subsets, starting with index 0 and incrementing if the subset is exhausted A freq is only added to the scan if it has not yet been scanned in the current roam attempt. An exception to this are neighbor freqs. They have a higher chance of containing good BSSes, so they're scanned every 3rd scan (defined by STATION_SCANS_BEFORE_NEIGHBOR_SCAN). This approach results in more scans, but fewer freqs per scan, leading to shorter delays between scan results. It also avoids scanning the same freqs back-to-back, which is generally not very useful. In combination with the subset ordering, this increases the chance of finding a good BSS early and results in better roaming performance. --- src/station.c | 228 ++++++++++++++++++++++++-------------------------- 1 file changed, 108 insertions(+), 120 deletions(-) diff --git a/src/station.c b/src/station.c index c2e18fc9a..0aef46ec2 100644 --- a/src/station.c +++ b/src/station.c @@ -68,6 +68,8 @@ #define STATION_RECENT_NETWORK_LIMIT 5 #define STATION_RECENT_FREQS_LIMIT 5 +#define STATION_MAX_SCAN_FREQS 10 +#define STATION_SCANS_BEFORE_NEIGHBOR_SCAN 2 static struct l_queue *station_list; static uint32_t netdev_watch; @@ -123,6 +125,9 @@ struct station { /* Set of frequencies to scan first when attempting a roam */ struct scan_freq_set *roam_freqs; struct l_queue *roam_bss_list; + struct scan_freq_set *scan_freqs; + struct scan_freq_set *scanned_freqs; + uint8_t roam_scans_since_neighbor_scan; /* Frequencies split into subsets by priority */ struct scan_freq_set *scan_freqs_order[5]; @@ -141,7 +146,6 @@ struct station { struct handshake_state *hs; bool preparing_roam : 1; - bool roam_scan_full : 1; bool signal_low : 1; bool ap_directed_roaming : 1; bool scanning : 1; @@ -1940,7 +1944,6 @@ static void station_roam_state_clear(struct station *station) l_timeout_remove(station->roam_trigger_timeout); station->roam_trigger_timeout = NULL; station->preparing_roam = false; - station->roam_scan_full = false; station->signal_low = false; station->netconfig_after_roam = false; station->last_roam_scan = 0; @@ -2205,27 +2208,6 @@ static void parse_neighbor_report(struct station *station, } } -static void station_early_neighbor_report_cb(struct netdev *netdev, int err, - const uint8_t *reports, - size_t reports_len, - void *user_data) -{ - struct station *station = user_data; - - if (err == -ENODEV) - return; - - l_debug("ifindex: %u, error: %d(%s)", - netdev_get_ifindex(station->netdev), - err, err < 0 ? strerror(-err) : ""); - - if (!reports || err) - return; - - parse_neighbor_report(station, reports, reports_len, - &station->roam_freqs); -} - static bool station_try_next_bss(struct station *station) { struct scan_bss *next; @@ -2360,9 +2342,32 @@ static bool netconfig_after_roam(struct station *station) return true; } +static void station_neighbor_report_cb(struct netdev *netdev, int err, + const uint8_t *reports, + size_t reports_len, void *user_data) +{ + struct station *station = user_data; + + if (err == -ENODEV) + return; + + l_debug("ifindex: %u, error: %d(%s)", + netdev_get_ifindex(station->netdev), + err, err < 0 ? strerror(-err) : ""); + + if (!reports || err) { + l_debug("no neighbor report results"); + return; + } + + parse_neighbor_report(station, reports, reports_len, &station->roam_freqs); +} + static void station_roamed(struct station *station) { - station->roam_scan_full = false; + scan_freq_set_free(station->scanned_freqs); + station->scanned_freqs = scan_freq_set_new(); + station->roam_scans_since_neighbor_scan = STATION_SCANS_BEFORE_NEIGHBOR_SCAN; /* * Schedule another roaming attempt in case the signal continues to @@ -2382,7 +2387,7 @@ static void station_roamed(struct station *station) if (station->connected_bss->cap_rm_neighbor_report) { if (netdev_neighbor_report_req(station->netdev, - station_early_neighbor_report_cb) < 0) + station_neighbor_report_cb) < 0) l_warn("Could not request neighbor report"); } @@ -2404,8 +2409,10 @@ static void station_roam_retry(struct station *station) * time. */ station->preparing_roam = false; - station->roam_scan_full = false; station->ap_directed_roaming = false; + scan_freq_set_free(station->scanned_freqs); + station->scanned_freqs = scan_freq_set_new(); + station->roam_scans_since_neighbor_scan = STATION_SCANS_BEFORE_NEIGHBOR_SCAN; if (station->roam_freqs) { scan_freq_set_free(station->roam_freqs); @@ -2416,6 +2423,8 @@ static void station_roam_retry(struct station *station) station_roam_timeout_rearm(station, roam_retry_interval); } +static void station_start_roam(struct station *station); + static void station_roam_failed(struct station *station) { l_debug("%u", netdev_get_ifindex(station->netdev)); @@ -2438,39 +2447,22 @@ static void station_roam_failed(struct station *station) } /* - * We were told by the AP to roam, but failed. Try ourselves or - * wait for the AP to tell us to roam again + * Keep trying to roam if the signal is still low, or we were told by the AP + * to roam but failed. */ - if (station->ap_directed_roaming) { - /* - * The candidate list from the AP (or neighbor report) found - * no BSS's. Force a full scan - */ - if (!station->roam_scan_full) - goto full_scan; - - goto delayed_retry; - } - - /* - * If we tried a limited scan, failed and the signal is still low, - * repeat with a full scan right away - */ - if (station->signal_low && !station->roam_scan_full) { + if (station->signal_low || station->ap_directed_roaming) { /* * Since we're re-using roam_scan_id, explicitly cancel * the scan here, so that the destroy callback is not called * after the return of this function */ -full_scan: scan_cancel(netdev_get_wdev_id(station->netdev), station->roam_scan_id); - if (!station_roam_scan(station, NULL)) - return; + station_start_roam(station); + return; } -delayed_retry: station_roam_retry(station); } @@ -3057,7 +3049,6 @@ static int station_roam_scan(struct station *station, } if (!freq_set) { - station->roam_scan_full = true; params.freqs = allowed; station_debug_event(station, "full-roam-scan"); } else @@ -3080,71 +3071,68 @@ static int station_roam_scan(struct station *station, return 0; } -static int station_roam_scan_known_freqs(struct station *station) +static void station_filter_roam_scan_freq(uint32_t freq, void *user_data) { - const struct network_info *info = network_get_info( - station->connected_network); - struct scan_freq_set *freqs = network_info_get_roam_frequencies(info, - station->connected_bss->frequency, - STATION_RECENT_FREQS_LIMIT); - int r = -ENODATA; - - if (!freqs) - return r; + struct station *station = user_data; - if (!wiphy_constrain_freq_set(station->wiphy, freqs)) - goto free_set; + if (scan_freq_set_size(station->scan_freqs) >= STATION_MAX_SCAN_FREQS) + return; - r = station_roam_scan(station, freqs); + /* Skip freq if already scanned */ + if (scan_freq_set_contains(station->scanned_freqs, freq)) + return; -free_set: - scan_freq_set_free(freqs); - return r; + scan_freq_set_add(station->scan_freqs, freq); + scan_freq_set_add(station->scanned_freqs, freq); } -static void station_neighbor_report_cb(struct netdev *netdev, int err, - const uint8_t *reports, - size_t reports_len, void *user_data) +static void station_populate_roam_scan_freqs(struct station *station) { - struct station *station = user_data; - struct scan_freq_set *freq_set; - int r; + struct scan_freq_set *tmp; - if (err == -ENODEV) - return; + station->scan_freqs = scan_freq_set_new(); - l_debug("ifindex: %u, error: %d(%s)", - netdev_get_ifindex(station->netdev), - err, err < 0 ? strerror(-err) : ""); + /* Add current frequency, always scan this to get updated data for the + * current BSS */ + scan_freq_set_add(station->scan_freqs, station->connected_bss->frequency); + scan_freq_set_add(station->scanned_freqs, station->connected_bss->frequency); - /* - * Check if we're still attempting to roam -- if dbus Disconnect - * had been called in the meantime we just abort the attempt. - */ - if (!station->preparing_roam || err == -ENODEV) + /* Add neighbor frequencies */ + if (station->roam_scans_since_neighbor_scan >= + STATION_SCANS_BEFORE_NEIGHBOR_SCAN && station->roam_freqs) { + station->roam_scans_since_neighbor_scan = 0; + scan_freq_set_merge(station->scan_freqs, station->roam_freqs); + scan_freq_set_merge(station->scanned_freqs, station->roam_freqs); return; + } + station->roam_scans_since_neighbor_scan++; - if (!reports || err) { - r = station_roam_scan_known_freqs(station); - - if (r == -ENODATA) - l_debug("no neighbor report results or known freqs"); - - if (r < 0) - station_roam_failed(station); - + /* Add known frequencies */ + const struct network_info *info = network_get_info( + station->connected_network); + tmp = network_info_get_roam_frequencies(info, + station->connected_bss->frequency, + STATION_RECENT_FREQS_LIMIT); + scan_freq_set_foreach(tmp, station_filter_roam_scan_freq, station); + scan_freq_set_free(tmp); + if (scan_freq_set_size(station->scan_freqs) >= STATION_MAX_SCAN_FREQS) { return; } - parse_neighbor_report(station, reports, reports_len, &freq_set); - - r = station_roam_scan(station, freq_set); - - if (freq_set) - scan_freq_set_free(freq_set); + /* Add frequencies based on the prioritized subsets */ + for (uint8_t i = 0; i < L_ARRAY_SIZE(station->scan_freqs_order); i++) { + scan_freq_set_foreach(station->scan_freqs_order[i], station_filter_roam_scan_freq, station); + if (scan_freq_set_size(station->scan_freqs) >= STATION_MAX_SCAN_FREQS) { + return; + } + } - if (r < 0) - station_roam_failed(station); + if (scan_freq_set_size(station->scan_freqs) <= STATION_MAX_SCAN_FREQS) { + /* All freqs have been scanned after this, so empty the list of scanned + * freqs to restart */ + scan_freq_set_free(station->scanned_freqs); + station->scanned_freqs = scan_freq_set_new(); + } } static void station_start_roam(struct station *station) @@ -3154,34 +3142,26 @@ static void station_start_roam(struct station *station) station->preparing_roam = true; /* - * If current BSS supports Neighbor Reports, narrow the scan down - * to channels occupied by known neighbors in the ESS. If no neighbor - * report was obtained upon connection, request one now. This isn't - * 100% reliable as the neighbor lists are not required to be - * complete or current. It is likely still better than doing a - * full scan. 10.11.10.1: "A neighbor report may not be exhaustive - * either by choice, or due to the fact that there may be neighbor - * APs not known to the AP." + * If no neighbor report was obtained upon connection, request one now if BSS + * supports it. This isn't 100% reliable as the neighbor lists are not + * required to be complete or current. + * 10.11.10.1: "A neighbor report may not be exhaustive either by choice, or + * due to the fact that there may be neighbor APs not known to the AP." + * + * Continue roaming while waiting for the neighbor report, the neighbors will + * be added to the roam scan when/if they're available. */ - if (station->roam_freqs) { - if (station_roam_scan(station, station->roam_freqs) == 0) { - l_debug("Using cached neighbor report for roam"); - return; - } - } else if (station->connected_bss->cap_rm_neighbor_report) { + if (!station->roam_freqs && station->connected_bss->cap_rm_neighbor_report) { if (netdev_neighbor_report_req(station->netdev, station_neighbor_report_cb) == 0) { l_debug("Requesting neighbor report for roam"); - return; } } - r = station_roam_scan_known_freqs(station); - if (r == -ENODATA) - l_debug("No neighbor report or known frequencies, roam failed"); - - if (r < 0) - station_roam_failed(station); + station_populate_roam_scan_freqs(station); + station_roam_scan(station, station->scan_freqs); + scan_freq_set_free(station->scan_freqs); + station->scan_freqs = NULL; } static bool station_cannot_roam(struct station *station) @@ -3624,7 +3604,7 @@ static void station_connect_ok(struct station *station) */ if (station->connected_bss->cap_rm_neighbor_report) { if (netdev_neighbor_report_req(station->netdev, - station_early_neighbor_report_cb) < 0) + station_neighbor_report_cb) < 0) l_warn("Could not request neighbor report"); } @@ -5246,6 +5226,9 @@ static struct station *station_create(struct netdev *netdev) station->roam_bss_list = l_queue_new(); station->affinities = l_queue_new(); + station->scanned_freqs = scan_freq_set_new(); + station->roam_scans_since_neighbor_scan = STATION_SCANS_BEFORE_NEIGHBOR_SCAN; + return station; } @@ -5344,6 +5327,11 @@ static void station_free(struct station *station) l_queue_destroy(station->affinities, l_free); + scan_freq_set_free(station->scanned_freqs); + + if (station->scan_freqs) + scan_freq_set_free(station->scan_freqs); + l_free(station); }