From 3d4267f4da442a53e1725d2e4a7174629efbf2af 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 aac4e7581f7988507460caeab72d858e85232aee 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 3d613f1ffa2d65c00f20f045536ef7ace375bceb 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 58ab88fe6317daac18bb549b862b608396a1279e 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 98707504581d22ea35cf21ca88522a80863b048a 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 5d3a1e9d967a286cb3321dcf60b983e63232d23e 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 ddffee5bef74b2005cd2f239386cf75e877d7d15 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 3b99ebfa3ee1b23616850ce3103b17e9d6e5bde1 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 b29a9242cae0aeca8aec7573dbc31a3cc2361c1f 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 66b5e6703e0e34cd0129875d92380f73310fa370 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 18 Aug 2025 07:30:38 -0700 Subject: [PATCH 10/13] netdev: check connected in channel switch event In an ideal world userspace should never be getting a channel switch event unless connected to an AP, but alas this has been seen at least with ath10k hardware. This causes IWD to crash since the logic assumes netdev->handshake is set. --- src/netdev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/netdev.c b/src/netdev.c index c5ab9105a..8a9dac84a 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -5417,6 +5417,9 @@ static void netdev_channel_switch_event(struct l_genl_msg *msg, if (netdev->type != NL80211_IFTYPE_STATION) return; + if (L_WARN_ON(!netdev->connected)) + return; + chandef = l_new(struct band_chandef, 1); if (nl80211_parse_chandef(msg, chandef) < 0) { From 767a3dc9fcc5903943b1f700a61a3ee50e6905e9 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 18 Aug 2025 07:30:39 -0700 Subject: [PATCH 11/13] netdev: disconnect rather than deauth in FT association failure After CSA IE parsing was added to the kernel this opened up the possibility that associations could be rejected locally based on the contents of this CSA IE in the AP's beacons. Overall, it was always possible for a local rejection but this case was never considered by IWD. The CSA-based rejection is something that can and does happen out in the wild. When this association rejection happens it desync's IWD and the kernel's state: 1. IWD begins an FT roam. Authenticates successfully, then proceeds to calling netdev_ft_reassociate(). 2. Immediately IWD transitions to a ft-roaming state and waits for an association response. 3. CMD_ASSOCIATE is rejected by the kernel in the ACK which IWD handles by sending a deauthenticate command to the kernel (since we have a valid authentication to the new BSS). 4. Due to a bug IWD uses the target BSSID to deauthenticate which the kernel rejects since it has no knowledge of this auth. This error is not handled or logged. 5. IWD proceeds, assuming its deauthenticated, and transitions to a disconnected state. The kernel remains "connected" which of course prevents any future connections. A simple fix for this is to address the bug (4) in IWD that deauths using the current BSS roam target. This is actually legacy behavior from back when IWD used CMD_AUTHENTICATE. Today the kernel is unaware that IWD authenticated so a deauth is not going to be effective. Instead we can issue a CMD_DISCONNECT. This is somewhat of a large hammer, but since the handshake and internal state has already been modified to use the new target BSS we cannot go back and maintain the existing connect (though it is _possible_, see the TODO in the patch). --- src/netdev.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/netdev.c b/src/netdev.c index 8a9dac84a..cdb3f1d78 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -3008,13 +3008,26 @@ static void netdev_cmd_ft_reassociate_cb(struct l_genl_msg *msg, void *user_data) { struct netdev *netdev = user_data; + int err = l_genl_msg_get_error(msg); netdev->connect_cmd_id = 0; - if (l_genl_msg_get_error(msg) >= 0) + l_debug("%d", err); + + if (err >= 0) return; - netdev_deauth_and_fail_connection(netdev, + /* + * TODO: It is possible to not trigger a disconnect here and maintain + * the current connection. The issue is that IWD has already + * modified the handshake and we've lost all reference to the old + * BSS keys. + * + * This could be remedied in the future by creating an entirely + * new handshake_state object for the association and only when + * the ack indicates success do we clear out the old object. + */ + netdev_disconnect_and_fail_connection(netdev, NETDEV_RESULT_ASSOCIATION_FAILED, MMPDU_STATUS_CODE_UNSPECIFIED); } From 93084b98ac30dd11454be0f951ab7be0b8cb728c Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 18 Aug 2025 07:30:40 -0700 Subject: [PATCH 12/13] auto-t: make waiting for channel switch configurable --- autotests/util/hostapd.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/autotests/util/hostapd.py b/autotests/util/hostapd.py index 611d8a632..5db5ef214 100644 --- a/autotests/util/hostapd.py +++ b/autotests/util/hostapd.py @@ -288,13 +288,15 @@ def resend_m3(self, address): cmd = 'RESEND_M3 %s' % address self.ctrl_sock.sendall(cmd.encode('utf-8')) - def chan_switch(self, channel): + def chan_switch(self, channel, wait=True): if channel > len(chan_freq_map): raise Exception("Only 2.4GHz channels supported for chan_switch") cmd = self.cmdline + ['chan_switch', '50', str(chan_freq_map[channel])] ctx.start_process(cmd).wait() - self.wait_for_event('AP-CSA-FINISHED') + + if wait: + self.wait_for_event('AP-CSA-FINISHED') def _get_status(self): ret = {} From 7faf43d3e84fc8bad8c9d3e254d9be92f99f873b Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 18 Aug 2025 07:30:41 -0700 Subject: [PATCH 13/13] auto-t: add test for channel switch during roam In kernel 6.8 a new CMD_ASSOCIATE failure path was added which checks if the AP has a channel switch in progress. Eariler patches update IWD into handling this case better, and this new test exercises that. --- autotests/testPSK-roam/chan_switch_test.py | 114 +++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 autotests/testPSK-roam/chan_switch_test.py diff --git a/autotests/testPSK-roam/chan_switch_test.py b/autotests/testPSK-roam/chan_switch_test.py new file mode 100644 index 000000000..2e2154cfa --- /dev/null +++ b/autotests/testPSK-roam/chan_switch_test.py @@ -0,0 +1,114 @@ +#! /usr/bin/python3 + +import unittest +import sys, os + +sys.path.append('../util') +from iwd import IWD +from iwd import NetworkType +from hostapd import HostapdCLI +from packaging import version +from subprocess import run +import re +import testutil + +# +# The CSA handling was added in kernel 6.8, so for any earlier kernel this test +# won't pass. +# +def kernel_is_newer(min_version="6.8"): + proc = run(["uname", "-r"], capture_output=True) + + version_str = proc.stdout.decode("utf-8") + match = re.match(r"(\d+\.\d+)", version_str) + if not match: + return False + + return version.parse(match.group(1)) >= version.parse(min_version) + +class Test(unittest.TestCase): + def test_channel_switch_during_roam(self): + wd = self.wd + + device = wd.list_devices(1)[0] + + ordered_network = device.get_ordered_network('TestFT', full_scan=True) + + self.assertEqual(ordered_network.type, NetworkType.psk) + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.assertFalse(self.bss_hostapd[0].list_sta()) + self.assertFalse(self.bss_hostapd[1].list_sta()) + + device.connect_bssid(self.bss_hostapd[0].bssid) + + condition = 'obj.state == DeviceState.connected' + wd.wait_for_object_condition(device, condition) + + self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % device.address) + + testutil.test_iface_operstate(device.name) + testutil.test_ifaces_connected(self.bss_hostapd[0].ifname, device.name) + self.assertRaises(Exception, testutil.test_ifaces_connected, + (self.bss_hostapd[1].ifname, device.name, True, True)) + + # Start a channel switch and wait for it to begin + self.bss_hostapd[1].chan_switch(6, wait=False) + self.bss_hostapd[1].wait_for_event("CTRL-EVENT-STARTED-CHANNEL-SWITCH") + # Initiate a roam immediately which should get rejected by the kernel + device.roam(self.bss_hostapd[1].bssid) + + # IWD should authenticate, then proceed to association + device.wait_for_event("ft-authenticating") + device.wait_for_event("ft-roaming") + + # The kernel should reject the association, which should trigger a + # disconnect + condition = 'obj.state == DeviceState.disconnected' + wd.wait_for_object_condition(device, condition) + + condition = 'obj.state == DeviceState.connected' + wd.wait_for_object_condition(device, condition) + + + def tearDown(self): + os.system('ip link set "' + self.bss_hostapd[0].ifname + '" down') + os.system('ip link set "' + self.bss_hostapd[1].ifname + '" down') + os.system('ip link set "' + self.bss_hostapd[0].ifname + '" up') + os.system('ip link set "' + self.bss_hostapd[1].ifname + '" up') + + for hapd in self.bss_hostapd: + hapd.default() + + self.wd.stop() + self.wd = None + + def setUp(self): + self.wd = IWD(True) + + @classmethod + def setUpClass(cls): + if not kernel_is_newer(): + raise unittest.SkipTest() + + IWD.copy_to_storage('TestFT.psk') + + cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'), + HostapdCLI(config='ft-psk-ccmp-2.conf'), + HostapdCLI(config='ft-psk-ccmp-3.conf') ] + + unused = HostapdCLI(config='ft-psk-ccmp-3.conf') + unused.disable() + + cls.bss_hostapd[0].set_address('12:00:00:00:00:01') + cls.bss_hostapd[1].set_address('12:00:00:00:00:02') + cls.bss_hostapd[2].set_address('12:00:00:00:00:03') + + HostapdCLI.group_neighbors(*cls.bss_hostapd) + + @classmethod + def tearDownClass(cls): + IWD.clear_storage() + cls.bss_hostapd = None