name: hostap and wpa-supplicant Tests # START OF COMMON SECTION on: push: branches: [ 'master', 'main', 'release/**' ] pull_request: branches: [ '*' ] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # END OF COMMON SECTION env: LINUX_REF: v6.12 jobs: build_wolfssl: strategy: matrix: include: - build_id: hostap-vm-build1 wolf_extra_config: --disable-tls13 - build_id: hostap-vm-build2 wolf_extra_config: >- --enable-wpas-dpp --enable-brainpool --with-eccminsz=192 --enable-tlsv10 --enable-oldtls name: Build wolfSSL if: github.repository_owner == 'wolfssl' runs-on: ubuntu-22.04 # This should be a safe limit for the tests to run. timeout-minutes: 10 steps: # No way to view the full strategy in the browser (really weird) - name: Print strategy run: | cat <> $GITHUB_ENV - name: Build wolfSSL uses: wolfSSL/actions-build-autotools-project@v1 with: path: wolfssl configure: >- --enable-wpas CPPFLAGS=-DWOLFSSL_STATIC_RSA ${{ env.wolf_debug_flags }} ${{ matrix.wolf_extra_config }} install: true - name: tar build-dir run: tar -zcf build-dir.tgz build-dir - name: Upload built lib uses: actions/upload-artifact@v4 with: name: ${{ matrix.build_id }} path: build-dir.tgz retention-days: 5 checkout_hostap: name: Checkout hostap repo if: github.repository_owner == 'wolfssl' runs-on: ubuntu-22.04 # This should be a safe limit for the tests to run. timeout-minutes: 10 steps: - name: Checking if we have hostap in cache uses: actions/cache@v4 id: cache with: path: hostap key: hostap-repo - name: Checkout hostap if: steps.cache.outputs.cache-hit != 'true' run: git clone https://w1.fi/hostap.git hostap - name: tar hostap run: tar -zcf hostap.tgz hostap - name: Upload hostap repo uses: actions/upload-artifact@v4 with: name: hostap-repo path: hostap.tgz retention-days: 1 build_uml_linux: name: Build UML (UserMode Linux) if: github.repository_owner == 'wolfssl' runs-on: ubuntu-22.04 # This should be a safe limit for the tests to run. timeout-minutes: 10 needs: checkout_hostap steps: - name: Checking if we have kernel in cache uses: actions/cache@v4 id: cache with: path: linux/linux key: hostap-linux-${{ env.LINUX_REF }} - name: Download hostap repo if: steps.cache.outputs.cache-hit != 'true' uses: actions/download-artifact@v4 with: name: hostap-repo - name: untar hostap if: steps.cache.outputs.cache-hit != 'true' run: tar -xf hostap.tgz - name: Checkout linux if: steps.cache.outputs.cache-hit != 'true' uses: actions/checkout@v4 with: repository: torvalds/linux path: linux ref: ${{ env.LINUX_REF }} fetch-depth: 1 - name: Compile linux if: steps.cache.outputs.cache-hit != 'true' run: | cp hostap/tests/hwsim/vm/kernel-config.uml linux/.config cd linux yes "" | ARCH=um make -j $(nproc) - name: Upload kernel binary uses: actions/upload-artifact@v4 with: name: uml-linux-kernel path: linux/linux retention-days: 1 hostap_test: strategy: fail-fast: false matrix: # should hostapd be compiled with wolfssl hostapd: [true, false] # should wpa_supplicant be compiled with wolfssl wpa_supplicant: [true, false] # Fix the versions of hostap and osp to not break testing when a new # patch is added in to osp. Tests are read from the corresponding # configs/hostap_ref/tests file. config: [ { hostap_ref: hostap_2_10, remove_teap: true, # TLS 1.3 does not work for this version build_id: hostap-vm-build1, }, # Test the dpp patch { hostap_ref: b607d2723e927a3446d89aed813f1aa6068186bb, osp_ref: ad5b52a49b3cc2a5bfb47ccc1d6a5137132e9446, build_id: hostap-vm-build2 }, { hostap_ref: 07c9f183ea744ac04585fb6dd10220c75a5e2e74, osp_ref: e1876fbbf298ee442bc7ab8561331ebc7de17528, build_id: hostap-vm-build2 }, ] exclude: # don't test openssl on both sides - hostapd: false wpa_supplicant: false # no hostapd support for dpp yet - hostapd: true config: { hostap_ref: b607d2723e927a3446d89aed813f1aa6068186bb, osp_ref: ad5b52a49b3cc2a5bfb47ccc1d6a5137132e9446, build_id: hostap-vm-build2 } name: hwsim test if: github.repository_owner == 'wolfssl' runs-on: ubuntu-22.04 # This should be a safe limit for the tests to run. timeout-minutes: 45 needs: [build_wolfssl, build_uml_linux, checkout_hostap] steps: - name: Download kernel binary uses: actions/download-artifact@v4 with: name: uml-linux-kernel path: linux - name: Restore kernel binary executable bit run: chmod +x linux/linux # No way to view the full strategy in the browser (really weird) - name: Print strategy run: | cat <> $GITHUB_ENV echo Our job run ID is $SHA_SUM - name: Checkout wolfSSL uses: actions/checkout@v4 with: path: wolfssl - name: Download lib uses: actions/download-artifact@v4 with: name: ${{ matrix.config.build_id }} - name: untar build-dir run: tar -xf build-dir.tgz - name: Install dependencies uses: ./wolfssl/.github/actions/install-apt-deps with: packages: libpcap0.8 libpcap-dev curl libcurl4-openssl-dev libnl-3-dev binutils-dev libssl-dev libiberty-dev libnl-genl-3-dev libnl-route-3-dev libdbus-1-dev bridge-utils tshark python3-pycryptodome - name: Install pip dependencies run: sudo pip install pycryptodome - name: Download hostap repo uses: actions/download-artifact@v4 with: name: hostap-repo - name: untar hostap run: tar -xf hostap.tgz - name: Checkout correct ref working-directory: hostap run: git checkout ${{ matrix.config.hostap_ref }} - if: ${{ matrix.config.osp_ref }} name: Checkout OSP uses: actions/checkout@v4 with: repository: wolfssl/osp path: osp ref: ${{ matrix.config.osp_ref }} fetch-depth: 1 - if: ${{ matrix.config.osp_ref }} name: Apply patch files working-directory: hostap run: | for f in $GITHUB_WORKSPACE/osp/hostap-patches/pending/* do patch -p1 < $f done - name: Update certs working-directory: hostap/tests/hwsim/auth_serv run: | mkdir -p rootCA/newcerts ./update.sh ./ec-generate.sh ./ec2-generate.sh ./sha512-generate.sh # Force regeneration of rsa3072-ca.key to get rsa3072-generate.sh to # correctly update all the certs rm rsa3072-ca.key ./rsa3072-generate.sh ./ica-generate.sh - name: Apply extra patches working-directory: hostap run: | FILE=$GITHUB_WORKSPACE/wolfssl/.github/workflows/hostap-files/configs/${{ matrix.config.hostap_ref }}/extra.patch if [ -f "$FILE" ]; then patch -p1 < $FILE fi - if: ${{ matrix.hostapd }} name: Setup hostapd config file run: | cp wolfssl/.github/workflows/hostap-files/configs/${{ matrix.config.hostap_ref }}/hostapd.config \ hostap/hostapd/.config cat <> hostap/hostapd/.config CFLAGS += -I$GITHUB_WORKSPACE/build-dir/include -Wl,-rpath=$GITHUB_WORKSPACE/build-dir/lib LIBS += -L$GITHUB_WORKSPACE/build-dir/lib -Wl,-rpath=$GITHUB_WORKSPACE/build-dir/lib EOF - if: ${{ matrix.wpa_supplicant }} name: Setup wpa_supplicant config file run: | cp wolfssl/.github/workflows/hostap-files/configs/${{ matrix.config.hostap_ref }}/wpa_supplicant.config \ hostap/wpa_supplicant/.config cat <> hostap/wpa_supplicant/.config CFLAGS += -I$GITHUB_WORKSPACE/build-dir/include -Wl,-rpath=$GITHUB_WORKSPACE/build-dir/lib LIBS += -L$GITHUB_WORKSPACE/build-dir/lib -Wl,-rpath=$GITHUB_WORKSPACE/build-dir/lib EOF - name: Build hostap and wpa_supplicant working-directory: hostap/tests/hwsim/ run: ./build.sh - if: ${{ matrix.hostapd }} name: Confirm hostapd linking with wolfSSL run: ldd hostap/hostapd/hostapd | grep wolfssl - if: ${{ matrix.wpa_supplicant }} name: Confirm wpa_supplicant linking with wolfSSL run: ldd hostap/wpa_supplicant/wpa_supplicant | grep wolfssl - if: ${{ matrix.config.remove_teap }} name: Remove EAP-TEAP from test configuration working-directory: hostap/tests/hwsim/auth_serv run: | sed -e 's/"erp-teap@example.com"\tTEAP//' -i eap_user.conf sed -e 's/"erp-teap@example.com"\tMSCHAPV2\t"password"\t\[2\]//' -i eap_user.conf sed -e 's/"TEAP"\t\tTEAP//' -i eap_user.conf sed -e 's/TEAP,//' -i eap_user.conf - if: ${{ runner.debug }} name: Enable hostap debug logging run: | echo "hostap_debug_flags=--debug" >> $GITHUB_ENV - name: Run tests id: testing working-directory: hostap/tests/hwsim/ run: | cat <> vm/vm-config KERNELDIR=$GITHUB_WORKSPACE/linux KVMARGS="-cpu host" EOF git config --global --add safe.directory $GITHUB_WORKSPACE/hostap # parallel-vm.py exits non-zero whenever any test failed on its first # attempt, even if hostap's own internal retry recovered. Treat # "All failed cases passed on retry" as success so we don't churn the # whole VM batch over a flaky test that already passed on retry. run_hwsim() { local log rc=0 log=$(mktemp) ./vm/parallel-vm.py ${{ env.hostap_debug_flags }} --nocurses "$@" 2>&1 | tee "$log" rc=${PIPESTATUS[0]} if [ "$rc" -ne 0 ] && grep -q "All failed cases passed on retry" "$log"; then echo "Treating run as success: hostap's internal retry recovered all failures" rc=0 fi rm -f "$log" return $rc } # Run tests in increments of 200 to not stall out the parallel-vm script while mapfile -t -n 200 ary && ((${#ary[@]})); do TESTS=$(printf '%s\n' "${ary[@]}" | tr '\n' ' ') HWSIM_RES=0 # Not set when command succeeds run_hwsim $(nproc) $TESTS || HWSIM_RES=$? # Retry failing tests up to 2 times to mitigate flakiness in the # upstream hostap tests themselves. for i in 1 2; do if [ "$HWSIM_RES" -ne "0" ]; then # Let's re-run the failing tests. We gather the failed tests from the log file. # `|| true` keeps the step alive under `-eo pipefail` if grep finds no matches. FAILED_TESTS=$(grep 'failed tests' /tmp/hwsim-test-logs/*-parallel.log 2>/dev/null | sed 's/failed tests: //' | tr ' ' '\n' | sort | uniq | tr '\n' ' ' || true) if [ -z "$FAILED_TESTS" ]; then echo "Could not determine failed tests from logs, skipping retry" break fi printf 'failed tests (retry %d): %s\n' "$i" "$FAILED_TESTS" rm -rf /tmp/hwsim-test-logs HWSIM_RES=0 run_hwsim $(nproc) $FAILED_TESTS || HWSIM_RES=$? fi done if [ "$HWSIM_RES" -ne "0" ]; then echo "Tests still failing after retries" exit 1 fi rm -rf /tmp/hwsim-test-logs done < $GITHUB_WORKSPACE/wolfssl/.github/workflows/hostap-files/configs/${{ matrix.config.hostap_ref }}/tests - name: show errors if: ${{ failure() && steps.testing.outcome == 'failure' }} run: grep -riP 'fail|error' /tmp/hwsim-test-logs/latest # The logs are quite big. It hasn't been useful so far so let's not waste # precious gh space. #- name: zip logs # if: ${{ failure() && steps.testing.outcome == 'failure' }} # working-directory: hostap/tests/hwsim/ # run: | # rm /tmp/hwsim-test-logs/latest # zip -9 -r logs.zip /tmp/hwsim-test-logs # #- name: Upload failure logs # if: ${{ failure() && steps.testing.outcome == 'failure' }} # uses: actions/upload-artifact@v4 # with: # name: hostap-logs-${{ env.our_job_run_id }} # path: hostap/tests/hwsim/logs.zip # retention-days: 5