From cbead58ac4450ae5eccb0c1e71e686db9e09fb94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Fri, 5 Aug 2022 08:06:27 +0200 Subject: [PATCH] ci: copy over files from prplOS v1.5 release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to have QA in place. Signed-off-by: Petr Štetiar --- .gitlab-ci.yml | 112 + .gitlab/README.md | 108 + .gitlab/build.yml | 80 + .gitlab/cdrouter.yml | 130 + .gitlab/coverity.yml | 190 ++ .gitlab/docker.yml | 57 + .gitlab/docker/README.md | 15 + .gitlab/docker/builder/Dockerfile | 51 + .gitlab/docker/builder/gitlab.yml | 25 + .gitlab/docker/sdk/Dockerfile | 8 + .gitlab/docker/sdk/gitlab.yml | 58 + .gitlab/docker/testbed/Dockerfile | 69 + .gitlab/docker/testbed/gitlab.yml | 22 + .gitlab/mockups/tr181-mockups.tar.gz | Bin 0 -> 732 bytes .gitlab/scripts/README.md | 17 + .gitlab/scripts/cdrouter-pretty-failures.awk | 18 + .gitlab/scripts/prpl-jira.py | 454 +++ .gitlab/scripts/requirements.txt | 16 + .gitlab/scripts/testbed-cdrouter.py | 433 +++ .gitlab/scripts/testbed-device.py | 140 + .gitlab/sdk.yml | 174 ++ .gitlab/testbed.yml | 130 + .gitlab/testbed/glinet-b1300.yml | 10 + .gitlab/testbed/nec-wx3000hp.yml | 10 + .gitlab/testbed/turris-omnia.yml | 11 + .gitlab/tests/README.md | 12 + .gitlab/tests/cram/README.md | 19 + .../010-firewall-dhcp.t | 41 + .../010-firewall-http-toggle.t | 26 + .../012-firewall-port-trigger.t | 65 + .../013-firewall-mac-filter.t | 43 + .../014-firewall-levels.t | 27 + .../015-nat-portmapping.t | 42 + .../030-usermanagement.t | 56 + .../035-multisettings.t | 69 + .../etc/amx/testing/profile_default.odl | 6 + .../etc/amx/testing/profile_france.odl | 6 + .../etc/amx/testing/profile_usa.odl | 6 + .../etc/amx/testing/testing.odl | 19 + .../035-multisettings/etc/init.d/testing | 22 + .../acceleration-plan-components/040-lcm.t | 73 + .../acceleration-plan-components/045-qos.t | 163 + .../050-rest-api.t | 9 + .gitlab/tests/cram/generic/network.t | 9 + .gitlab/tests/cram/generic/network_security.t | 11 + .gitlab/tests/cram/generic/ubus-cli.t | 12 + .gitlab/tests/cram/generic/ubus.t | 202 ++ .gitlab/tests/cram/glinet-b1300/010-network.t | 26 + .gitlab/tests/cram/glinet-b1300/020-ubus.t | 186 ++ .../tests/cram/glinet-b1300/021-ubus-cli.t | 4 + .gitlab/tests/cram/glinet-b1300/030-wifi.t | 9 + .../tests/cram/glinet-b1300/100-prplmesh.t | 73 + .../010-firewall-dmz.t | 35 + .../020-bridging-guest.t | 41 + .../acceleration-plan-components/030-lcm.t | 96 + .gitlab/tests/cram/nec-wx3000hp/010-network.t | 30 + .gitlab/tests/cram/nec-wx3000hp/020-ubus.t | 10 + .gitlab/tests/cram/nec-wx3000hp/030-wifi.t | 8 + .../tests/cram/nec-wx3000hp/100-prplmesh.t | 76 + .../010-firewall-dmz.t | 35 + .../020-bridging-guest.t | 52 + .../acceleration-plan-components/030-lcm.t | 96 + .gitlab/tests/cram/turris-omnia/010-network.t | 32 + .gitlab/tests/cram/turris-omnia/020-ubus.t | 10 + .gitlab/tests/cram/turris-omnia/030-wifi.t | 9 + .../tests/cram/turris-omnia/100-prplmesh.t | 73 + .../010-firewall-dmz.t | 35 + .../020-bridging-guest.t | 55 + .../acceleration-plan-components/030-lcm.t | 96 + .testbed/README.md | 11 + .testbed/cdrouter/configurations/generic | 2677 +++++++++++++++++ .../packages/CDRouter-IPv6-Top-100.gz | Bin 0 -> 20453 bytes .testbed/cdrouter/packages/CDRouter-TR-069.gz | Bin 0 -> 1191 bytes .../cdrouter/packages/CDRouter-Top-100.gz | Bin 0 -> 20593 bytes .testbed/labgrid/default.yaml | 257 ++ 75 files changed, 7308 insertions(+) create mode 100644 .gitlab-ci.yml create mode 100644 .gitlab/README.md create mode 100644 .gitlab/build.yml create mode 100644 .gitlab/cdrouter.yml create mode 100644 .gitlab/coverity.yml create mode 100644 .gitlab/docker.yml create mode 100644 .gitlab/docker/README.md create mode 100644 .gitlab/docker/builder/Dockerfile create mode 100644 .gitlab/docker/builder/gitlab.yml create mode 100644 .gitlab/docker/sdk/Dockerfile create mode 100644 .gitlab/docker/sdk/gitlab.yml create mode 100644 .gitlab/docker/testbed/Dockerfile create mode 100644 .gitlab/docker/testbed/gitlab.yml create mode 100644 .gitlab/mockups/tr181-mockups.tar.gz create mode 100644 .gitlab/scripts/README.md create mode 100755 .gitlab/scripts/cdrouter-pretty-failures.awk create mode 100755 .gitlab/scripts/prpl-jira.py create mode 100644 .gitlab/scripts/requirements.txt create mode 100755 .gitlab/scripts/testbed-cdrouter.py create mode 100755 .gitlab/scripts/testbed-device.py create mode 100644 .gitlab/sdk.yml create mode 100644 .gitlab/testbed.yml create mode 100644 .gitlab/testbed/glinet-b1300.yml create mode 100644 .gitlab/testbed/nec-wx3000hp.yml create mode 100644 .gitlab/testbed/turris-omnia.yml create mode 100644 .gitlab/tests/README.md create mode 100644 .gitlab/tests/cram/README.md create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/010-firewall-dhcp.t create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/010-firewall-http-toggle.t create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/012-firewall-port-trigger.t create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/013-firewall-mac-filter.t create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/014-firewall-levels.t create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/015-nat-portmapping.t create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/030-usermanagement.t create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings.t create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_default.odl create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_france.odl create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_usa.odl create mode 100755 .gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/testing.odl create mode 100755 .gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/init.d/testing create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/040-lcm.t create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/045-qos.t create mode 100644 .gitlab/tests/cram/generic/acceleration-plan-components/050-rest-api.t create mode 100644 .gitlab/tests/cram/generic/network.t create mode 100644 .gitlab/tests/cram/generic/network_security.t create mode 100644 .gitlab/tests/cram/generic/ubus-cli.t create mode 100644 .gitlab/tests/cram/generic/ubus.t create mode 100644 .gitlab/tests/cram/glinet-b1300/010-network.t create mode 100644 .gitlab/tests/cram/glinet-b1300/020-ubus.t create mode 100644 .gitlab/tests/cram/glinet-b1300/021-ubus-cli.t create mode 100644 .gitlab/tests/cram/glinet-b1300/030-wifi.t create mode 100644 .gitlab/tests/cram/glinet-b1300/100-prplmesh.t create mode 100644 .gitlab/tests/cram/glinet-b1300/acceleration-plan-components/010-firewall-dmz.t create mode 100644 .gitlab/tests/cram/glinet-b1300/acceleration-plan-components/020-bridging-guest.t create mode 100644 .gitlab/tests/cram/glinet-b1300/acceleration-plan-components/030-lcm.t create mode 100644 .gitlab/tests/cram/nec-wx3000hp/010-network.t create mode 100644 .gitlab/tests/cram/nec-wx3000hp/020-ubus.t create mode 100644 .gitlab/tests/cram/nec-wx3000hp/030-wifi.t create mode 100644 .gitlab/tests/cram/nec-wx3000hp/100-prplmesh.t create mode 100644 .gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/010-firewall-dmz.t create mode 100644 .gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/020-bridging-guest.t create mode 100644 .gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/030-lcm.t create mode 100644 .gitlab/tests/cram/turris-omnia/010-network.t create mode 100644 .gitlab/tests/cram/turris-omnia/020-ubus.t create mode 100644 .gitlab/tests/cram/turris-omnia/030-wifi.t create mode 100644 .gitlab/tests/cram/turris-omnia/100-prplmesh.t create mode 100644 .gitlab/tests/cram/turris-omnia/acceleration-plan-components/010-firewall-dmz.t create mode 100644 .gitlab/tests/cram/turris-omnia/acceleration-plan-components/020-bridging-guest.t create mode 100644 .gitlab/tests/cram/turris-omnia/acceleration-plan-components/030-lcm.t create mode 100644 .testbed/README.md create mode 100644 .testbed/cdrouter/configurations/generic create mode 100644 .testbed/cdrouter/packages/CDRouter-IPv6-Top-100.gz create mode 100644 .testbed/cdrouter/packages/CDRouter-TR-069.gz create mode 100644 .testbed/cdrouter/packages/CDRouter-Top-100.gz create mode 100644 .testbed/labgrid/default.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000..1d0a76d95f --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,112 @@ +variables: + CI_DESIGNATED_BRANCH: prplos + +include: + - local: .gitlab/build.yml + - local: .gitlab/cdrouter.yml + - local: .gitlab/coverity.yml + - local: .gitlab/docker.yml + - local: .gitlab/docker/builder/gitlab.yml + - local: .gitlab/docker/testbed/gitlab.yml + - local: .gitlab/docker/sdk/gitlab.yml + - local: .gitlab/testbed.yml + - local: .gitlab/testbed/nec-wx3000hp.yml + - local: .gitlab/testbed/glinet-b1300.yml + - local: .gitlab/testbed/turris-omnia.yml + +stages: + - docker + - docker test + - docker deploy + - build + - docker SDK + - docker SDK test + - docker SDK deploy + - run + - cdrouter + - coverity + +build test intel_mips prpl: + extends: .build test config + +build test ipq40xx prpl: + extends: .build test config + +build test mvebu prpl: + extends: .build test config + +coverity scan ipq40xx prpl: + extends: .coverity scan config + variables: + CI_COVERITY_COMPILER_TEMPLATE_LIST: > + arm-openwrt-linux-gcc + arm-openwrt-linux-muslgnueabi-gcc + +run test NEC WX3000HP with system on NAND: + needs: + - build test intel_mips prpl + extends: .nec-wx3000hp testbed + +run test Gl.iNet B1300 with system on initramfs: + needs: + - build test ipq40xx prpl + extends: .glinet-b1300 testbed + +run test Turris Omnia with system on initramfs: + needs: + - build test mvebu prpl + extends: .turris-omnia testbed + +CDRouter CDRouter-Top-100 package on NEC WX3000HP with system on NAND: + needs: + - build test intel_mips prpl + extends: + - .nec-wx3000hp testbed + - .cdrouter + variables: + LABGRID_TARGET: "$DUT_BOARD-firstboot" + +CDRouter CDRouter-Top-100 package on Gl.iNet B1300 with system on initramfs: + needs: + - build test ipq40xx prpl + extends: + - .glinet-b1300 testbed + - .cdrouter + +CDRouter CDRouter-Top-100 package on Turris Omnia with system on initramfs: + needs: + - build test mvebu prpl + extends: + - .turris-omnia testbed + - .cdrouter + +CDRouter CDRouter-TR-069 package on NEC WX3000HP with system on NAND: + allow_failure: true + needs: + - build test intel_mips prpl + extends: + - .nec-wx3000hp testbed + - .cdrouter + +CDRouter CDRouter-TR-069 package on Gl.iNet B1300 with system on NOR: + allow_failure: true + needs: + - build test ipq40xx prpl + extends: + - .glinet-b1300 testbed + - .cdrouter + variables: + LABGRID_TARGET: glinet-b1300-nor + TFTP_IMAGE_FILENAME: openwrt-ipq40xx-generic-glinet_gl-b1300-squashfs-sysupgrade.bin + +CDRouter CDRouter-TR-069 package on Turris Omnia with system on eMMC: + allow_failure: true + needs: + - build test mvebu prpl + extends: + - .turris-omnia testbed + - .cdrouter + variables: + LABGRID_TARGET: turris-omnia-emmc + TFTP_IMAGE_FILENAME: openwrt-mvebu-cortexa9-cznic_turris-omnia-sysupgrade.img.gz + TFTP_IMAGE_UNPACK_COMMAND: "gunzip --force $TESTBED_TFTP_PATH/$TFTP_IMAGE_FILENAME || true" diff --git a/.gitlab/README.md b/.gitlab/README.md new file mode 100644 index 0000000000..1c0a182d70 --- /dev/null +++ b/.gitlab/README.md @@ -0,0 +1,108 @@ +# Content + +This directory contains stuff used on the GitLab CI. + +## docker + +Contains definitions for Docker images. + +## testbed + +Contains definitions for testbed related tests. + +## scripts + +Contains scripts used on GitLab CI. + +## tests + +Contains tests used on GitLab CI. + +## build.yml + +Contains definition of the GitLab CI build test job templates used during `build` stage. Those templates can then be extended by other GitLab CI jobs in order to keep things DRY. + +### .build test config + +Allows build testing of specific configurations defined in the profiles directory, using `scripts/gen_config.py` under the hood. + +Example usage: + +```yaml +include: + - local: .gitlab/build.yml + +stages: + - build + +build test netgear-rax40 prpl webui: + extends: .build test config +``` + +Which is going to build test prplOS with `netgear-rax40`, `prpl` and `webui` profiles. + +Description of CI variables: + + * CI_BUILD_CONFIG_EXTRA - list of additional config options which should be enabled(prefixed with `+`) or disabled (prefixed with `-`), for example `+BUILD_LOG -SDK` would result in `CONFIG_BUILD_LOG=y` and `CONFIG_SDK=y` config symbols in `.config` file. + +## docker.yml + +Provides support for building, tagging and pushing the Docker images to image registry. + +For example let's build image `foo`. + +Prerequisites: + + * Create directory for new Docker image `mkdir -p .gitlab/docker/foo` + * Docker image description `$EDITOR .gitlab/docker/foo/Dockefile` + +Then just put following into `.gitlab/docker/foo/gitlab.yml` + +```yaml +build Docker image foo: + extends: .build Docker image +``` + +## testbed.yml + +Provides bits needed for runtime testing on real device using [labgrid](https://labgrid.readthedocs.io/en/latest/) Python testing framework. + +Supported devices: + + * Netgear RAX40 + +## sdk.yml + +Provides support for the [OpenWrt SDK](https://openwrt.org/docs/guide-developer/using_the_sdk) utilizing the [Docker SDK container](https://gitlab.com/prpl-foundation/prplOS/prplos/-/tree/prplos/.gitlab/docker/sdk) under the hood. + +### .build feed with SDK + +Allows compile testing of packages using the SDK. + +Example usage, build testing of [safec3](https://gitlab.com/prpl-foundation/intel/feed_opensource_apps/-/tree/ugw-8.4.1/safec3) package from Intel's `feed_opensource_apps` feed. + +```yaml +include: + - remote: https://gitlab.com/prpl-foundation/prplOS/prplos/-/raw/prplos/.gitlab/sdk.yml + +build: + extends: .build feed with SDK + variables: + CI_SDK_INSTALL_FEEDS: feed_target_mips + CI_SDK_BUILD_PACKAGES: safec3 +``` + +Description of CI variables: + + * CI_SDK_INSTALL_FEEDS - list of feeds which should be installed prior to building packages. + * CI_SDK_BUILD_PACKAGES - list of packages which should be compile tested. + * CI_SDK_BUILD_PARALLEL - max number of threads to use for make (defaults to `nproc` if unset). + +### .generate SDK package build jobs + +Generates `sdk-package-jobs.yml` with separate build jobs for every package so the builds of those packages +can run in parallel. It's supposed to be executed by the child pipeline `.execute SDK package build jobs`. + +### .execute SDK package build jobs + +It's supposed to execute jobs generated in `sdk-package-jobs.yml` generated by `.generate SDK package build jobs` job. diff --git a/.gitlab/build.yml b/.gitlab/build.yml new file mode 100644 index 0000000000..c19fe6ccb9 --- /dev/null +++ b/.gitlab/build.yml @@ -0,0 +1,80 @@ +.build test config: + stage: build + image: "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/builder:latest" + tags: + - firmware-builder + variables: + CI_BUILD_CONFIG: > + +DEVEL +BUILD_LOG +SDK + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule"' + when: never + - if: '$CI_COMMIT_BRANCH == $CI_DESIGNATED_BRANCH' + - when: manual + before_script: + - touch .build_failed + + script: + - mkdir logs + - set -o pipefail + + - export CI_BUILD_PROFILE="$(echo $CI_JOB_NAME | sed 's/build test \(.*\)/\1/')" + - scripts/gen_config.py $CI_BUILD_PROFILE 2>&1 | tee logs/build.log + - > + for option in $CI_BUILD_CONFIG $CI_BUILD_CONFIG_EXTRA; do + echo "$option" | sed -E "s/^\+(.*)$/CONFIG_\1=y/;s/^\-(.*)$/CONFIG_\1=n/" >> .config + done + - cat .config + - make defconfig | tee --append logs/build.log + + - make -j $(nproc) tools/tar/compile 2>&1 | tee --append logs/build.log + - make -j $(nproc) download check FIXUP=1 2>&1 | tee --append logs/build.log + + - > + git diff-index --exit-code HEAD || { + ret=$? + echo "Package integrity issues, please check packages-hash-issues.patch from artifacts" + git diff > packages-hash-issues.patch + exit $ret + } + + - > + topdir=$(pwd); + for feed in $(find feeds -name .git); do + pushd $(dirname $feed) > /dev/null; git diff-index --exit-code HEAD || { + ret=$? + echo "Feed $(dirname $feed) packages integrity issues, please check feed-packages-hash-issues.patch from artifacts" + git diff > $topdir/feed-packages-hash-issues.patch + exit $ret + } + popd > /dev/null + done + + - make -j $(nproc) 2>&1 | tee --append logs/build.log + - rm .build_failed + + after_script: + - > + if test -f .build_failed && grep -qr 'make\[[[:digit:]]\].*Error [[:digit:]]$' logs; then + printf "\n====== Showing Make errors found in the log files ======"; + for file in $(grep -lr 'make\[[[:digit:]]\].*Error [[:digit:]]$' logs); do + printf "\n====== Make errors from $CI_JOB_URL/artifacts/file/$file ======\n" ; + grep -r -C5 'make\[[[:digit:]]\].*Error [[:digit:]]$' $file ; + done + fi + - > + [ "$CI_COMMIT_BRANCH" = "$CI_DESIGNATED_BRANCH" ] && { + test -f .build_failed && .gitlab/scripts/prpl-jira.py build_failure || true + } || true + + artifacts: + expire_in: 1 month + when: always + paths: + - bin + - logs + - ./*packages-hash-issues.patch + cache: + key: openwrt-downloads + paths: + - dl/ diff --git a/.gitlab/cdrouter.yml b/.gitlab/cdrouter.yml new file mode 100644 index 0000000000..c91840faaf --- /dev/null +++ b/.gitlab/cdrouter.yml @@ -0,0 +1,130 @@ +.cdrouter: + stage: cdrouter + image: "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/testbed:latest" + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule"' + when: never + - if: '$CI_COMMIT_BRANCH == $CI_DESIGNATED_BRANCH' + - when: manual + variables: + TEST_CONFIG: generic + DUT_SLEEP_AFTER_BOOT: 20 + CDROUTER_LAN_INTERFACE: eth1 + CDROUTER_WAN_INTERFACE: eth2 + CDROUTER_ETH0_MAC_ADDRESS: 00:03:2d:49:2e:d8 + + before_script: + - sudo etherwake -i $TESTBED_MNG_INTERFACE $CDROUTER_ETH0_MAC_ADDRESS 2> /dev/null + - sudo ip link set $TESTBED_LAN_INTERFACE up 2> /dev/null + - sudo ip link set $TESTBED_WAN_INTERFACE up 2> /dev/null + - sleep 10 + + - eval $(ssh-agent -s) + - echo "$TESTBED_SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - + - mkdir -p ~/.ssh; chmod 700 ~/.ssh + - ssh-keyscan $TESTBED_UART_RELAY_HOST > ~/.ssh/known_hosts 2> /dev/null + - chmod 644 ~/.ssh/known_hosts + + - > + if [ -n "$TFTP_IMAGE_DOWNLOAD_URL" ]; then + echo "Downloading firmware image from $TFTP_IMAGE_DOWNLOAD_URL" + curl "$TFTP_IMAGE_DOWNLOAD_URL" > "$TESTBED_TFTP_PATH/$TFTP_IMAGE_FILENAME" + else + echo "Using firmware image $TFTP_IMAGE_PATH/$TFTP_IMAGE_FILENAME" + cp "$TFTP_IMAGE_PATH/$TFTP_IMAGE_FILENAME" "$TESTBED_TFTP_PATH" + fi + - > + if [ -n "$TFTP_IMAGE_UNPACK_COMMAND" ]; then + echo "Running $TFTP_IMAGE_UNPACK_COMMAND" + eval "$TFTP_IMAGE_UNPACK_COMMAND" + fi + - .gitlab/scripts/testbed-device.py --target $LABGRID_TARGET boot_into shell + - sudo ip link set $TESTBED_WAN_INTERFACE down 2> /dev/null + - > + .gitlab/scripts/testbed-device.py + --target $LABGRID_TARGET check_network + --network lan + --remote-host $TARGET_LAN_TEST_HOST + + - > + retry_count=3; + while [ $retry_count -gt 0 ]; do + echo "Waiting for SSH availability on $TARGET_LAN_IP" + ssh-keyscan "$TARGET_LAN_IP" 2>&1 | grep -q "$TARGET_LAN_IP" && break + retry_count="$(( retry_count - 1 ))" + sleep 5 + done + + - ssh-keyscan $TARGET_LAN_IP >> ~/.ssh/known_hosts 2> /dev/null + - ssh root@$TARGET_LAN_IP "cat /var/log/messages" > syslog-$LABGRID_TARGET.txt 2> /dev/null || true + - ssh root@$TARGET_LAN_IP "ubus call system board" | tee system-$LABGRID_TARGET.json + + - scp .gitlab/mockups/tr181-mockups.tar.gz root@${TARGET_LAN_IP}:/tmp/ + - ssh root@$TARGET_LAN_IP "tar xzf /tmp/tr181-mockups.tar.gz -C / && /etc/init.d/tr181-mockups start" + + - .gitlab/scripts/testbed-cdrouter.py package_stop + - .gitlab/scripts/testbed-cdrouter.py wait_for_netif $CDROUTER_LAN_INTERFACE + - .gitlab/scripts/testbed-cdrouter.py wait_for_netif $CDROUTER_WAN_INTERFACE + + - sudo ip link set $TESTBED_LAN_INTERFACE down 2> /dev/null + + script: + - sleep $DUT_SLEEP_AFTER_BOOT + + - export TEST_PACKAGE="$(echo $CI_JOB_NAME | sed 's/CDRouter \(.*\) package on .*/\1/')" + - .gitlab/scripts/testbed-cdrouter.py config_import $TEST_CONFIG + - .gitlab/scripts/testbed-cdrouter.py package_import $TEST_PACKAGE.gz + - > + .gitlab/scripts/testbed-cdrouter.py + package_run $TEST_PACKAGE + --device generic + --configuration $TEST_CONFIG + --system-info system-$LABGRID_TARGET.json + + after_script: + - > + test -f *-logdir.tgz && + mkdir -p cdrouter-results && + tar xf *-logdir.tgz --strip-components=1 --directory=cdrouter-results && + cat cdrouter-results/final.txt && + .gitlab/scripts/cdrouter-pretty-failures.awk cdrouter-results/*.txt + + - eval $(ssh-agent -s) + - echo "$TESTBED_SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - + - mkdir -p ~/.ssh; chmod 700 ~/.ssh + - ssh-keyscan $TESTBED_UART_RELAY_HOST > ~/.ssh/known_hosts 2> /dev/null + - chmod 644 ~/.ssh/known_hosts + + - sudo ip link set $TESTBED_LAN_INTERFACE up 2> /dev/null + - sudo ip link set $TESTBED_WAN_INTERFACE up 2> /dev/null + - sleep 5 + + - ssh-keyscan $TARGET_LAN_IP >> ~/.ssh/known_hosts 2> /dev/null + - > + ssh root@$TARGET_LAN_IP exit && { + ssh root@$TARGET_LAN_IP ps > processes-$LABGRID_TARGET.txt + ssh root@$TARGET_LAN_IP dmesg > dmesg-$LABGRID_TARGET.txt + ssh root@$TARGET_LAN_IP "cat /var/log/messages" > syslog-$LABGRID_TARGET.txt + ssh root@$TARGET_LAN_IP opkg list > opkg_list-$LABGRID_TARGET.txt + scp -r root@${TARGET_LAN_IP}:/etc etc > /dev/null + scp -r root@${TARGET_LAN_IP}:/tmp/beerocks/logs prplmesh_beerocks_logs > /dev/null + } || true + + - .gitlab/scripts/testbed-device.py --target $LABGRID_TARGET power off + - mv console_$LABGRID_TARGET console_$LABGRID_TARGET.txt || true + + - .gitlab/scripts/testbed-cdrouter.py package_stop + + artifacts: + expire_in: 1 month + when: always + paths: + - cdrouter-results + - etc + - prplmesh_beerocks_logs + - processes-$LABGRID_TARGET.txt + - dmesg-$LABGRID_TARGET.txt + - syslog-$LABGRID_TARGET.txt + - system-$LABGRID_TARGET.json + - console_$LABGRID_TARGET.txt + - opkg_list-$LABGRID_TARGET.txt diff --git a/.gitlab/coverity.yml b/.gitlab/coverity.yml new file mode 100644 index 0000000000..1259ae7a76 --- /dev/null +++ b/.gitlab/coverity.yml @@ -0,0 +1,190 @@ +.coverity scan config: + stage: coverity + image: "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/builder:latest" + tags: + - firmware-builder + dependencies: [] + variables: + CI_BUILD_CONFIG: > + +DEVEL +BUILD_LOG +ALL +ALL_KMODS +ALL_NONSHARED + CI_COVERITY_PROJECT_NAME: prplOS + CI_COVERITY_FORCE_COMPILE_PACKAGE_LIST: > + curl + libnl + mbedtls + openssl + CI_COVERITY_OPENWRT_PACKAGE_LIST: > + cgi-io + dropbear + dnsmasq + firewall + fstools + iwinfo + jsonfilter + libnl-tiny + libubox + netifd + odhcp6c + odhcpd + opkg + procd + rpcd + swconfig + ubox + ubus + ucert + uci + uclient + uhttpd + umdns + usign + ustream-ssl + CI_COVERITY_PRPLOS_PACKAGE_LIST: > + acl-manager + amxb-inspect + amx-cli + amx-fcgi + amxo-cg + amxrt + cthulhu + cthulhu-lxc + deviceinfo-manager + dhcpv4-manager + dhcpv6s-manager + ethernet-manager + gmap-mibs-common + gmap-mod-ethernet-dev + gmap-mod-name-selector + gmap-mod-self + gmap-server + ip-manager + libamxa + libamxb + libamxc + libamxd + libamxj + libamxm + libamxo + libamxp + libamxs + libamxt + libdhcpoptions + libfwinterface + libfwrules + libgmap-client + libnetmodel + libsahtrace + libtrace + moca-manager + mod-amxb-ubus + mod-ba-cli + mod-dm-cli + mod-dmext + mod-dmproxy + mod-dmstats + mod-netmodel + mod-pcm-svc + mod-sahtrace + mod-vlan-ioctl + mod-vlan-uci + netdev-plugin + netmodel + netmodel-ip + pcm-manager + prplmesh + rlyeh + routing-manager + time-manager + timingila + timingila-cthulhu + timingila-rlyeh + tr181-bridging + tr181-device + tr181-dhcpv4client + tr181-dhcpv6client + tr181-firewall + tr181-qos + tr181-routeradvertisement + tr181-usermanagement + umdns + uriparser + wan-autosensing + wan-manager + + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" + + script: + - mkdir logs + - set -o pipefail + + - export CI_BUILD_PROFILE="$(echo $CI_JOB_NAME | sed 's/coverity scan \(.*\)/\1/')" + - scripts/gen_config.py $CI_BUILD_PROFILE 2>&1 | tee logs/build.log + - > + for option in $CI_BUILD_CONFIG $CI_BUILD_CONFIG_EXTRA; do + echo "$option" | sed -E "s/^\+(.*)$/CONFIG_\1=y/;s/^\-(.*)$/CONFIG_\1=n/" >> .config + done + - cat .config + - make defconfig | tee --append logs/build.log + + - wget -q https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_PROJECT_TOKEN&project=$CI_COVERITY_PROJECT_NAME" -O coverity.tar.gz + - wget -q https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_PROJECT_TOKEN&project=$CI_COVERITY_PROJECT_NAME&md5=1" -O coverity.tar.gz.md5 + - echo ' coverity.tar.gz' >> coverity.tar.gz.md5 + - md5sum -c coverity.tar.gz.md5 + + - mkdir cov-analysis-linux64 + - tar xzf coverity.tar.gz --strip 1 -C cov-analysis-linux64 + - export PATH=$(pwd)/cov-analysis-linux64/bin:$PATH + - > + for template in $CI_COVERITY_COMPILER_TEMPLATE_LIST; do + cov-configure --template --comptype gcc --compiler $template + done + + - make -j $(nproc) tools/tar/compile || make -j1 V=s tools/tar/compile 2>&1 | tee --append logs/build.log + - make -j $(nproc) download check FIXUP=1 || make -j1 V=s download check FIXUP=1 2>&1 | tee --append logs/build.log + - make -j $(nproc) || make -j1 V=s 2>&1 | tee --append logs/build.log + + - printf -v clean_packages "package/%s/clean " ${CI_COVERITY_OPENWRT_PACKAGE_LIST[@]} ${CI_COVERITY_PRPLOS_PACKAGE_LIST[@]} + - make $clean_packages + + - printf -v force_compile_packages "package/%s/compile " ${CI_COVERITY_FORCE_COMPILE_PACKAGE_LIST[@]} + - make -j $(nproc) $force_compile_packages + + - echo "$COVERITY_PROJECT_TOKEN" > ./coverity-api-token + - > + unset + CI_JOB_JWT + CI_JOB_TOKEN + CI_BUILD_TOKEN + CI_RUNNER_SHORT_TOKEN + CI_DEPENDENCY_PROXY_PASSWORD + CI_REPOSITORY_URL + CI_REGISTRY_PASSWORD + TESTBED_SSH_PRIVATE_KEY + COVERITY_PROJECT_TOKEN + + - printf -v compile_packages "package/%s/compile " ${CI_COVERITY_OPENWRT_PACKAGE_LIST[@]} ${CI_COVERITY_PRPLOS_PACKAGE_LIST[@]} + - cov-build --dir cov-int make -j $(nproc) $compile_packages + + - tar czf cov-int.tar.gz ./cov-int + - > + curl + --form token="$(cat ./coverity-api-token)" + --form email=ynezz@true.cz + --form file=@cov-int.tar.gz + --form version="$CI_COMMIT_SHORT_SHA" + --form description="$CI_COMMIT_REF_SLUG" + "https://scan.coverity.com/builds?project=$CI_COVERITY_PROJECT_NAME" + + artifacts: + expire_in: 1 month + when: always + paths: + - bin + - logs + - cov-int.tar.gz + + cache: + key: openwrt-downloads + paths: + - dl/ diff --git a/.gitlab/docker.yml b/.gitlab/docker.yml new file mode 100644 index 0000000000..d4b639c271 --- /dev/null +++ b/.gitlab/docker.yml @@ -0,0 +1,57 @@ +.docker in docker: + tags: + - gce + image: docker:19.03.7 + services: + - docker:19.03.7-dind + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule"' + when: never + - if: '$CI_COMMIT_BRANCH == $CI_DESIGNATED_BRANCH' + - when: manual + allow_failure: true + variables: + DOCKER_DRIVER: overlay2 + DOCKER_TLS_CERTDIR: "/certs" + +.build Docker image: + stage: docker + extends: .docker in docker + script: + - export IMAGE_NAME="$(echo $CI_JOB_NAME | sed 's/build Docker image \(.*\)/\1/')" + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - docker build -t "$IMAGE_NAME" $DOCKER_BUILD_EXTRA_ARGS $DOCKER_DOCKERFILE_PATH + - docker tag "$IMAGE_NAME" "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:$CI_COMMIT_REF_SLUG" + - docker push "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:$CI_COMMIT_REF_SLUG" + +.test Docker SDK image: + stage: docker SDK test + extends: .docker in docker + script: + - export IMAGE_NAME="$(echo $CI_JOB_NAME | sed 's/test Docker image \(.*\)/\1/')" + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - docker pull "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:$CI_COMMIT_REF_SLUG" + - > + docker run "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:$CI_COMMIT_REF_SLUG" sh -c " + cd /home/builder && + make defconfig && + ./scripts/feeds update base && + ./scripts/feeds install busybox && + sync && sleep 1 && + make -j $(nproc) package/busybox/compile V=s && + sync && sleep 1 && + find ./bin/packages -name busybox*.ipk | grep ^./bin/packages/.*busybox + " + +.deploy Docker image: + extends: .docker in docker + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule"' + when: never + - if: '$CI_COMMIT_BRANCH == $CI_DESIGNATED_BRANCH' + script: + - export IMAGE_NAME="$(echo $CI_JOB_NAME | sed 's/deploy Docker image \(.*\)/\1/')" + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - docker pull "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:$CI_COMMIT_REF_SLUG" + - docker tag "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:$CI_COMMIT_REF_SLUG" "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:latest" + - docker push "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:latest" diff --git a/.gitlab/docker/README.md b/.gitlab/docker/README.md new file mode 100644 index 0000000000..3816ec624c --- /dev/null +++ b/.gitlab/docker/README.md @@ -0,0 +1,15 @@ +# Content + +This directory contains bits for Docker images used on the GitLab CI. + +## builder + +Docker image used for build testing OpenWrt/prplOS. + +## testbed + +Docker image used for runtime testing. + +## sdk + +Docker image with the target SDK. diff --git a/.gitlab/docker/builder/Dockerfile b/.gitlab/docker/builder/Dockerfile new file mode 100644 index 0000000000..e9df295eaa --- /dev/null +++ b/.gitlab/docker/builder/Dockerfile @@ -0,0 +1,51 @@ +FROM debian:buster-slim + +ENV DEBIAN_FRONTEND=noninteractive + +RUN \ + apt-get update && \ + apt-get install --yes --no-install-recommends \ + build-essential \ + curl \ + file \ + gawk \ + git-core \ + gosu \ + iputils-ping \ + iproute2 \ + libncurses5-dev \ + locales \ + nmap \ + openssh-client \ + python-distlib \ + python-yaml \ + python3 \ + python3-pip \ + python3-setuptools \ + pwgen \ + rsync \ + signify-openbsd \ + subversion \ + sudo \ + unzip \ + wget && \ + apt-get -y autoremove && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 +ENV LANG=en_US.utf8 + +RUN pip3 install -U pip +RUN pip3 install \ + jira \ + pyyaml \ + pyjwt + +RUN \ + echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \ + useradd -c "OpenWrt Builder" -m -d /home/builder -G sudo -s /bin/bash builder + +USER builder +ENV HOME /home/builder +WORKDIR /home/builder/ diff --git a/.gitlab/docker/builder/gitlab.yml b/.gitlab/docker/builder/gitlab.yml new file mode 100644 index 0000000000..2269eb4afb --- /dev/null +++ b/.gitlab/docker/builder/gitlab.yml @@ -0,0 +1,25 @@ +build Docker image builder: + extends: .build Docker image + variables: + DOCKER_DOCKERFILE_PATH: .gitlab/docker/builder + +test Docker image builder: + stage: docker test + extends: .docker in docker + needs: ["build Docker image builder"] + script: + - export IMAGE_NAME="$(echo $CI_JOB_NAME | sed 's/test Docker image \(.*\)/\1/')" + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - docker pull "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:$CI_COMMIT_REF_SLUG" + - > + docker run --rm "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:$CI_COMMIT_REF_SLUG" sh -c " + git clone --depth 1 https://gitlab.com/prpl-foundation/prplOS/prplos && + cd prplos && scripts/gen_config.py tplinkC6 prpl && + make -j $(nproc) tools/flock/compile && + python3 -c 'import jira; import jwt' + " + +deploy Docker image builder: + stage: docker deploy + needs: ["test Docker image builder"] + extends: .deploy Docker image diff --git a/.gitlab/docker/sdk/Dockerfile b/.gitlab/docker/sdk/Dockerfile new file mode 100644 index 0000000000..1cca90c217 --- /dev/null +++ b/.gitlab/docker/sdk/Dockerfile @@ -0,0 +1,8 @@ +ARG DESIGNATED_BRANCH=prplos +FROM registry.gitlab.com/prpl-foundation/prplos/prplos/$DESIGNATED_BRANCH/builder:latest + +COPY --chown=builder:builder . /home/builder/ + +WORKDIR /home/builder +RUN mkdir .ssh && ssh-keyscan gitlab.com > .ssh/known_hosts +RUN sed -i 's;\(http[s]\?\)://\(.*@\);\1://;g' feeds.conf.default diff --git a/.gitlab/docker/sdk/gitlab.yml b/.gitlab/docker/sdk/gitlab.yml new file mode 100644 index 0000000000..dd9b1bc467 --- /dev/null +++ b/.gitlab/docker/sdk/gitlab.yml @@ -0,0 +1,58 @@ +build Docker image sdk-intel_mips-xrx500: + stage: docker SDK + needs: ["build test intel_mips prpl"] + variables: + DOCKER_DOCKERFILE_PATH: .gitlab/docker/sdk + DOCKER_BUILD_EXTRA_ARGS: --build-arg DESIGNATED_BRANCH=$CI_DESIGNATED_BRANCH + extends: .build Docker image + before_script: + - tar xf bin/targets/intel_mips/xrx500/openwrt-sdk-intel_mips-xrx500_gcc-*_musl.Linux-x86_64.tar.xz --strip=1 -C .gitlab/docker/sdk + +test Docker image sdk-intel_mips-xrx500: + extends: .test Docker SDK image + needs: ["build Docker image sdk-intel_mips-xrx500"] + +deploy Docker image sdk-intel_mips-xrx500: + stage: docker SDK deploy + extends: .deploy Docker image + needs: ["test Docker image sdk-intel_mips-xrx500"] + + +build Docker image sdk-ipq40xx-generic: + stage: docker SDK + needs: ["build test ipq40xx prpl"] + variables: + DOCKER_DOCKERFILE_PATH: .gitlab/docker/sdk + DOCKER_BUILD_EXTRA_ARGS: --build-arg DESIGNATED_BRANCH=$CI_DESIGNATED_BRANCH + extends: .build Docker image + before_script: + - tar xf bin/targets/ipq40xx/generic/openwrt-sdk-ipq40xx-generic_gcc*.Linux-x86_64.tar.xz --strip=1 -C .gitlab/docker/sdk + +test Docker image sdk-ipq40xx-generic: + extends: .test Docker SDK image + needs: ["build Docker image sdk-ipq40xx-generic"] + +deploy Docker image sdk-ipq40xx-generic: + stage: docker SDK deploy + extends: .deploy Docker image + needs: ["test Docker image sdk-ipq40xx-generic"] + + +build Docker image sdk-mvebu-cortexa9: + stage: docker SDK + needs: ["build test mvebu prpl"] + variables: + DOCKER_DOCKERFILE_PATH: .gitlab/docker/sdk + DOCKER_BUILD_EXTRA_ARGS: --build-arg DESIGNATED_BRANCH=$CI_DESIGNATED_BRANCH + extends: .build Docker image + before_script: + - tar xf bin/targets/mvebu/cortexa9/openwrt-sdk-mvebu-cortexa9_gcc*Linux-x86_64.tar.xz --strip=1 -C .gitlab/docker/sdk + +test Docker image sdk-mvebu-cortexa9: + extends: .test Docker SDK image + needs: ["build Docker image sdk-mvebu-cortexa9"] + +deploy Docker image sdk-mvebu-cortexa9: + stage: docker SDK deploy + extends: .deploy Docker image + needs: ["test Docker image sdk-mvebu-cortexa9"] diff --git a/.gitlab/docker/testbed/Dockerfile b/.gitlab/docker/testbed/Dockerfile new file mode 100644 index 0000000000..f92a27aae4 --- /dev/null +++ b/.gitlab/docker/testbed/Dockerfile @@ -0,0 +1,69 @@ +FROM debian:buster-slim + +ENV DEBIAN_FRONTEND=noninteractive + +RUN \ + apt-get update && \ + apt-get install --yes --no-install-recommends \ + curl \ + etherwake \ + git-core \ + iputils-ping \ + iproute2 \ + locales \ + netcat-openbsd \ + nmap \ + openssh-client \ + python3 \ + python3-pip \ + python3-setuptools \ + sshpass \ + sudo \ + tcpdump \ + xz-utils && \ + apt-get -y autoremove && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 +ENV LANG=en_US.utf8 + +ENV LABGRID_COMMIT=ffa994eca22b +RUN git clone --branch wip/testbed https://gitlab.com/prpl-foundation/prplOS/labgrid +WORKDIR labgrid +RUN git reset --hard $LABGRID_COMMIT + +RUN \ + pip3 install -U pip && \ + pip3 install -r requirements.txt && \ + python3 setup.py install && \ + rm -fr /labgrid + +RUN pip3 install \ + cdrouter \ + cram \ + humanize \ + jira \ + 'marshmallow<3.0.0' \ + pyjwt + +ENV TMATE_VERSION=2.4.0 +ENV TMATE_SHA256SUM=6e503a1a3b0f9117bce6ff7cc30cf61bdc79e9b32d074cf96deb0264e067a60d +ENV TMATE_DL_URL=https://github.com/tmate-io/tmate/releases/download + +RUN \ + curl --location --silent \ + "$TMATE_DL_URL/$TMATE_VERSION/tmate-${TMATE_VERSION}-static-linux-amd64.tar.xz" > tmate.tar.xz && \ + sha256sum tmate.tar.xz | grep -q "$TMATE_SHA256SUM" && \ + tar xf tmate.tar.xz --strip-components=1 -C /usr/local/bin && \ + rm tmate.tar.xz + +RUN \ + echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \ + useradd -c "OpenWrt Testbed" -m -d /home/testbed -G sudo -s /bin/bash testbed + +USER testbed +ENV HOME /home/testbed +WORKDIR /home/testbed/ + +VOLUME [ "/home/testbed" ] diff --git a/.gitlab/docker/testbed/gitlab.yml b/.gitlab/docker/testbed/gitlab.yml new file mode 100644 index 0000000000..dcf94aad51 --- /dev/null +++ b/.gitlab/docker/testbed/gitlab.yml @@ -0,0 +1,22 @@ +build Docker image testbed: + extends: .build Docker image + variables: + DOCKER_DOCKERFILE_PATH: .gitlab/docker/testbed + +test Docker image testbed: + stage: docker test + extends: .docker in docker + needs: ["build Docker image testbed"] + script: + - export IMAGE_NAME="$(echo $CI_JOB_NAME | sed 's/test Docker image \(.*\)/\1/')" + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - docker pull "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:$CI_COMMIT_REF_SLUG" + - > + docker run --rm "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/$IMAGE_NAME:$CI_COMMIT_REF_SLUG" sh -c " + python3 -c 'import labgrid; import yaml; import jira; import jwt; import cdrouter' && tmate -V + " + +deploy Docker image testbed: + stage: docker deploy + extends: .deploy Docker image + needs: ["test Docker image testbed"] diff --git a/.gitlab/mockups/tr181-mockups.tar.gz b/.gitlab/mockups/tr181-mockups.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..858d142ac8811c22c84e37cf2456d1232f6afe99 GIT binary patch literal 732 zcmV<20wet&iwFS4{IOyH1MQbhbJ{QvhB^CJY$#;fP5{do+?L6KNpk2+C(VSkmkb9X z%R!BisU#;Q3IDw^-#CPj38vFl&jpNk-(C5Y&6+Aw$z_bK@w{5{iM*P<_&FtqT&L#R zUJW59XCwW^%|R{e#u8$wumH#nIK8`D6ZhQtzZ9zd$Gu;f?t#tyN2ppw+J985I>!H9 zF!f&v^Z}K65xI{0a?876WB;pO-Kpz1uV5T^ zhNZlXgb#<1&o^eV!?f`6Y3pgJR^0DLLQ(&m60LPH=u?>pHV>MbgVy=?gR_hC1^JZt zQOGD)EA*#yq9}wDjyoaMy7ptCbVCZOc+|o%lS!7pqIjx_78N&CT(;M=F@;1i*QFUG2q7dd<>Oxrs4JW}?B!=6Txu@hUgY_^hvw2r!|kef1Q@ zn6sZTh2k|GOf{Mz!)q?&@X?v!!uB0nfBJUaI?3~2kg}iU0QjQ$fAsuEb!6thoiOvi z_0eAX*WY4|vH#xY{yVngR&(H#%N53%(%og%n(<%zKe@)4)p*hSpMLSTk%Ow9x&L>; zg8!M_W6$|tcb$~~u0AsJ|1Nm5SLrZbkzLE;xJM83OS>R%Sp-W81q6&+<53I?^`PfW z^=>v8UBVue0;t4NjKm7}iPR9hmxG1)9;!>Jqn#k6_P_J9nXGfG$v)E{)6ns z%8zdOyfO=P@uc((78McC^vZqaL%RX0OZn17cg?~O3U3KkD|6<`0ZX?a=xFWpkb*sG zYx!75q!ZuIQz+?1kpCv}6@^bp!sYyWJ|tr8{9-nhnEZPqr@>$_7z_r3!C){L3 fsize: + bufsize = fsize - 1 + + data = [] + while True: + n += 1 + f.seek(fsize - bufsize * n) + data.extend(f.readlines()) + if len(data) >= count or f.tell() == 0: + return "".join(data[-count:]) + + def system_info(self): + path = self.logfile_path("system_info") + if not path: + return + + return OpenWrtSystemInfo(path) + + def failures_jira_string(self): + r = "" + cram_log = self.logfile_content("cram") + console_log = self.logfile_tail_content("console") + system_info = self.system_info() + + if system_info: + r += "Device under test provided following system details:\n" + r += f" * Board: {system_info.board_name}\n" + r += f" * Target: {system_info.target}\n" + r += f" * Version: {system_info.version}\n" + r += f" * Revision: {system_info.revision}\n" + r += f" * Kernel: {system_info.kernel}\n" + + if cram_log: + r += "{code:title=Cram test results}\n" + r += cram_log + r += "{code}\n" + + if console_log: + r += "{code:title=Console log (last 10 lines)}\n" + r += console_log + r += "{code}\n" + + return r + + +class BuildLogAnalyzer: + # make[3]: *** [Makefile:154: /builds/swpal_6x-uci-1.0.0.1.tar.bz2] Error 128 + RE_MAKE_ERROR = re.compile(r"make\[\d+\]: \*\*\* (.*) Error") + + # Makefile:563: recipe for target 'lldpcli' failed + RE_MAKE_RECIPE_FAILED = re.compile( + r"^Makefile:\d+: recipe for target '(.*)' failed" + ) + + def __init__(self, log_dir): + self.log_dir = log_dir + self._failures = [] + self.analyze_logs() + + def get_tail_log(self, path): + tail_log = [] + re_matchers = [self.RE_MAKE_ERROR, self.RE_MAKE_RECIPE_FAILED] + + def add_tail_log(line): + tail_log_goal = 4 + tail_log.append(line) + truncate = len(tail_log) - tail_log_goal + if truncate > 0: + return tail_log[truncate:] + return tail_log + + with open(path, "r", errors="ignore") as fd: + for line in fd: + line = line.rstrip() + if len(line) == 0: + continue + + tail_log = add_tail_log(line) + + for matcher in re_matchers: + if matcher.match(line): + return tail_log + + def process_log_file(self, path): + path = os.path.normpath(path) + filename = os.path.basename(path) + dirname = os.path.dirname(path) + package = dirname.split(os.sep)[-1] + (step, _) = os.path.splitext(filename) + + if step == "check-compile": + return + + tail_log = self.get_tail_log(path) + if not tail_log: + return + + self._failures.append(BuildLogFailure(path, step, package, tail_log)) + + def analyze_logs(self): + glob_pattern = os.path.join(self.log_dir, "**/**.txt") + for item in glob.iglob(glob_pattern, recursive=True): + if os.path.isfile(item): + self.process_log_file(item) + + def failures(self): + return self._failures + + def failures_jira_string(self): + if not self._failures: + return "" + + r = "\nSeems like there are build issues with following items:\n" + for f in self._failures: + r += f" * {f.name} ({f.step}):\n" + for line in f.tail_log: + r += f" ** {line}\n" + r += "\n" + + return r + + +class JiraHelper: + def __init__(self, args): + self.args = args + self.login() + + def login(self): + cert_data = None + args = self.args + + with open(args.private_key, "r", errors="ignore") as cert_file: + cert_data = cert_file.read() + + oauth_dict = { + "access_token": args.access_token, + "access_token_secret": args.access_token_secret, + "consumer_key": args.consumer_key, + "key_cert": cert_data, + } + + self.jira = JIRA({"server": args.instance_url}, oauth=oauth_dict) + + def create_or_update_issue(self, failure_type, failure_details): + args = self.args + job = os.getenv("CI_JOB_NAME", "job") + project = os.getenv("CI_PROJECT_NAME", "project") + project_url = os.getenv("CI_PROJECT_URL", "https://project_url") + branch = os.getenv("CI_COMMIT_BRANCH", "branch") + job_url = os.getenv("CI_JOB_URL", "https://job_url") + commit = os.getenv("CI_COMMIT_SHORT_SHA", "commit_sha") + commit_message = os.getenv("CI_COMMIT_MESSAGE", "foor bar baz") + + summary = f"CI {failure_type} failure in {project}/{branch} during {job}" + + description = ( + f"Just noticed {failure_type} failure during execution of " + f"[{job}|{job_url}] CI job in _{project}/{branch}_ which is now at " + f"[{commit}|{project_url}/-/commit/{commit}] commit:" + "{noformat}" + f"{commit_message}" + "{noformat}" + f"{failure_details}" + ) + + if args.dry_run: + logging.info(description) + + jql = f""" + project={args.project} AND resolution = Unresolved AND summary ~ '{summary}' + """ + existing_issue = self.jira.search_issues(jql, maxResults=1) + if existing_issue: + existing_issue = self.jira.issue(existing_issue[0].key) + logging.info( + f"Updating ({existing_issue.key}) {existing_issue.fields.summary}" + ) + + if not args.dry_run: + self.jira.add_comment(existing_issue, description) + + return existing_issue + + if args.dry_run: + logging.info(f"Would create new issue: '{self.args.project}/{summary}'") + return + + new_issue = self.jira.create_issue( + project=self.args.project, + summary=summary, + description=description, + issuetype={"name": "Bug"}, + fixVersions=[{"name": "1.1"}], + components=[{"name": "CI"}], + ) + + logging.info(f"Created ({new_issue.key}) {new_issue.fields.summary}") + return new_issue + + def build_failure(self): + dry_run = self.args.dry_run + commit = os.getenv("CI_COMMIT_SHORT_SHA", "commit_sha") + log_analyzer = BuildLogAnalyzer(self.args.build_logs_dir) + failures = log_analyzer.failures() + + issue = self.create_or_update_issue( + "build", log_analyzer.failures_jira_string() + ) + + if not failures: + return + + if not dry_run and not issue: + return + + for failure in failures: + filename = f"{failure.name}_{failure.step}_{commit}.log" + + if dry_run: + logging.info(f"Would add attachment {filename} from {failure.path})") + continue + + logging.info(f"Adding attachment {filename} from {failure.path})") + self.jira.add_attachment( + issue=issue, attachment=failure.path, filename=filename + ) + + def run_failure(self): + dry_run = self.args.dry_run + commit = os.getenv("CI_COMMIT_SHORT_SHA", "commit_sha") + log_analyzer = RunLogAnalyzer() + log_files = log_analyzer.log_files() + + issue = self.create_or_update_issue("run", log_analyzer.failures_jira_string()) + + if not log_files: + return + + if not dry_run and not issue: + return + + for kind, path in log_files.items(): + filename = f"{kind}_{commit}.log" + + if dry_run: + logging.info(f"Would add attachment {filename} from {path})") + continue + + logging.info(f"Adding attachment {filename} from {path})") + self.jira.add_attachment(issue=issue, attachment=path, filename=filename) + + +def main(): + logging.basicConfig( + level=logging.INFO, format="%(levelname)7s: %(message)s", stream=sys.stderr + ) + + parser = argparse.ArgumentParser() + parser.add_argument("-d", "--debug", action="store_true", help="enable debug mode") + parser.add_argument( + "--dry-run", + action="store_true", + help="Do not alter Jira content, just printout what would be done", + ) + + parser.add_argument( + "--access-token", + type=str, + default=os.environ.get("JIRA_ACCESS_TOKEN"), + help="Jira access token (default: %(default)s)", + ) + + parser.add_argument( + "--access-token-secret", + type=str, + default=os.environ.get("JIRA_ACCESS_TOKEN_SECRET"), + help="Jira access token secret", + ) + + parser.add_argument( + "--consumer-key", + type=str, + default=os.environ.get("JIRA_CONSUMER_KEY"), + help="Jira consumer key", + ) + + parser.add_argument( + "--instance-url", + type=str, + default=os.environ.get("JIRA_INSTANCE_URL", "https://jira.prplfoundation.org"), + help="Jira instance URL (default: %(default)s)", + ) + + parser.add_argument( + "--private-key", + type=str, + default=os.environ.get("JIRA_PRIVATE_KEY"), + help="Jira private key", + ) + + parser.add_argument( + "--project", + type=str, + default=os.environ.get("JIRA_PROJECT", "PCF"), + help="Jira target project (default: %(default)s)", + ) + + subparsers = parser.add_subparsers(dest="command", title="available subcommands") + subparser = subparsers.add_parser("build_failure", help="report build failure") + subparser.add_argument( + "--build-logs-dir", + type=str, + default=os.path.join(os.getcwd(), "logs"), + help="Path to directory which contains build logs", + ) + subparser.set_defaults(func=JiraHelper.build_failure) + + subparser = subparsers.add_parser("run_failure", help="report run failure") + subparser.add_argument( + "--target", + type=str, + help="Target on which runtime testing happend", + ) + subparser.set_defaults(func=JiraHelper.run_failure) + + args = parser.parse_args() + + if args.debug: + logging.getLogger().setLevel(logging.DEBUG) + + if not args.command: + print("command is missing") + exit(1) + + prpl_jira = JiraHelper(args) + args.func(prpl_jira) + + +if __name__ == "__main__": + main() diff --git a/.gitlab/scripts/requirements.txt b/.gitlab/scripts/requirements.txt new file mode 100644 index 0000000000..95e228bd62 --- /dev/null +++ b/.gitlab/scripts/requirements.txt @@ -0,0 +1,16 @@ +jira +pyyaml + +# labgrid +attrs==19.3.0 +jinja2==2.10.3 +pexpect==4.7 +https://github.com/labgrid-project/pyserial/archive/v3.4.0.1.zip#egg=pyserial +pytest==5.3.1 +pyudev==0.21.0 +requests==2.22.0 +xmodem==0.4.5 +autobahn==19.11.1 +PyYAML==5.1.2 +ansicolors==1.1.8 +pyusb==1.0.2 diff --git a/.gitlab/scripts/testbed-cdrouter.py b/.gitlab/scripts/testbed-cdrouter.py new file mode 100755 index 0000000000..376129e1c9 --- /dev/null +++ b/.gitlab/scripts/testbed-cdrouter.py @@ -0,0 +1,433 @@ +#!/usr/bin/env python3 + +import re +import argparse +import json +import os +import sys +import time +import logging +import humanize + +from types import SimpleNamespace +from http.client import RemoteDisconnected +from requests.exceptions import ConnectionError + +from cdrouter import CDRouter +from cdrouter.jobs import Job, Options +from cdrouter.configs import Config +from cdrouter.cdr_error import CDRouterError + + +class OpenWrtSystemInfo: + def __init__(self, filename): + with open(filename, "r") as read_file: + self.data = json.load(read_file) + + @property + def kernel(self): + return self.data["kernel"] + + @property + def board_name(self): + board_name = self.data["board_name"] + fixup = { + "EASY350 ANYWAN (GRX350) Axepoint Asurada model": "nec-wx3000hp", + "EASY350 ANYWAN (GRX350) Main model": "nec-wx3000hp", + } + board_name = fixup.get(board_name, board_name) + return board_name.replace(",", "-") + + @property + def target(self): + return self.data["release"]["target"] + + @property + def distribution(self): + return self.data["release"]["distribution"] + + @property + def revision(self): + return self.data["release"]["revision"] + + @property + def version(self): + return self.data["release"]["version"] + + def sanitize(self, s): + return s.replace("+", "-").replace("/", "-") + + def as_tags(self): + return self.sanitize( + "kernel_{},board_{},target_{},revision_{},version_{},distro_{}".format( + self.kernel, + self.board_name, + self.target, + self.revision, + self.version, + self.distribution, + ) + ) + + +class TestbedCDRouter: + def __init__(self, args): + self.args = args + self.configs_path = os.path.join(self.args.root_dir, "configurations") + self.packages_path = os.path.join(self.args.root_dir, "packages") + + def connect(self): + api_token = os.getenv("CDROUTER_API_TOKEN") + api_url = os.getenv("CDROUTER_API_URL") + + if not api_token or not api_url: + logging.error("API token or URL is missing") + exit(1) + + logging.debug("Connecting to {}".format(api_url)) + self.cdr = CDRouter(api_url, token=api_token) + + def job_launch(self): + p = self.cdr.packages.get_by_name(self.args.package_name) + logging.info( + "Using test package '{name}' with id {id} and {test_count} tests defined.".format( + name=p.name, id=p.id, test_count=p.test_count + ) + ) + + p = self.cdr.packages.get(p.id) + config = self.cdr.configs.get_by_name(self.args.configuration) + device = self.cdr.devices.get_by_name(self.args.device) + if config: + p.config_id = config.id + if device: + p.device_id = device.id + if config or device: + self.cdr.packages.edit(p) + + a = self.cdr.packages.analyze(p.id) + self.job_total = a.run_count + logging.info( + "Package '{name}' will run {run_count} tests and skip {skipped_count} tests.".format( + name=p.name, run_count=a.run_count, skipped_count=a.skipped_count + ) + ) + + for test in a.skipped_tests: + logging.info( + "Skipping test '{synopsis}' due to '{skip_name}'.".format( + synopsis=test.synopsis, skip_name=test.skip_name + ) + ) + + tags = None + if self.args.system_info: + tags = OpenWrtSystemInfo(self.args.system_info).as_tags().split(",") + + if self.args.tags: + tags += self.args.tags.split(",") + + options = Options(tags=tags) + job = Job(package_id=p.id, options=options) + job = self.cdr.jobs.launch(job) + while job.result_id is None: + time.sleep(1) + job = self.cdr.jobs.get(job.id) + + self.job = job + + def job_progress(self): + current = None + job = self.cdr.jobs.get(self.job.id) + while job.status == "running": + + updates = self.cdr.results.updates(job.result_id) + running = updates.running + progress = updates.progress + + if not running or not progress: + job = self.cdr.jobs.get(self.job.id) + continue + + description = running.description + if current == description: + job = self.cdr.jobs.get(self.job.id) + continue + + current = description + + logging.info( + "Running test {finished}/{total} ({percent}%) '{description}'".format( + description=description, + percent=progress.progress, + finished=progress.finished, + total=self.job_total, + ) + ) + + time.sleep(5) + job = self.cdr.jobs.get(self.job.id) + + def job_result(self, job_id=None): + job_id = job_id or self.job.result_id + r = self.cdr.results.get(job_id) + + buf, filename = self.cdr.results.download_logdir_archive(job_id, format="tgz") + logging.info("Exporting logdir archive {}".format(filename)) + with open(filename, "wb") as f: + f.write(buf.getvalue()) + + logging.info( + "Test job finished as '{}' after {}.".format( + r.status, humanize.naturaldelta(r.duration) + ) + ) + logging.info( + "Run {} tests, which {} failed and {} passed.".format( + r.tests, r.fail, r.passed + ) + ) + + if r.fail == 0 and r.status == "completed": + logging.info("Success!") + exit(0) + + if r.fail == 0: + exit(1) + + logging.error("{:=^50}".format(" [ FAILED TESTS ] ")) + for test in self.cdr.tests.iter_list(r.id, filter=["result=fail"]): + logging.error("{} ({})".format(test.description, test.result)) + + exit(1) + + def package_run(self): + self.connect() + self.job_launch() + self.job_progress() + self.job_result() + + def netif_available(self, name): + for netif in self.cdr.system.interfaces(): + if netif.name == name: + return True + + return False + + def wait_for_netif(self): + self.connect() + + name = self.args.name + timeout = time.time() + self.args.timeout + + while True: + if self.netif_available(name): + logging.info("Interface {} is available.".format(name)) + exit(0) + + if time.time() > timeout: + logging.error( + "Interface {} is not available after {}".format( + name, humanize.naturaldelta(self.args.timeout) + ) + ) + exit(1) + + time.sleep(5) + + def package_stop(self): + self.connect() + + f = ["status~(running|paused)"] + pkg_name = self.args.package_name + if pkg_name: + f.append("package_name={}".format(pkg_name)) + + for r in self.cdr.results.iter_list(filter=f): + self.cdr.results.stop(r.id) + logging.info( + "Stopped '{}' package which was {}".format(r.package_name, r.status) + ) + + def package_export(self): + self.connect() + name = self.args.name + p = self.cdr.packages.get_by_name(name) + buf, filename = self.cdr.packages.export(p.id) + filename = "{}.gz".format(self.args.filename or name) + self.file_save(self.packages_path, buf.getvalue(), filename) + + def package_import(self): + self.connect() + archive = os.path.join(self.packages_path, self.args.filename) + + with open(archive, "rb+") as fd: + si = self.cdr.imports.stage_import_from_file(fd) + + filename = re.sub(r"\.gz$", "", self.args.filename) + name = self.args.name or filename + + req = self.cdr.imports.get_commit_request(si.id) + for id in req.packages: + p = req.packages[id] + p.name = name + logging.debug("Going to import package '{}'".format(name)) + p.should_import = True + + resp = self.cdr.imports.commit(si.id, req) + for id in resp.packages: + r = resp.packages[id].response + if not r.imported: + logging.error("Import of '{}' failed: {}".format(r.name, r.message)) + exit(1) + + logging.info( + "Imported package '{}' from '{}'".format(r.name, self.args.filename) + ) + + def file_save(self, path, content, filename=None): + filename = filename or self.args.filename + os.makedirs(path, exist_ok=True) + dest = os.path.join(path, filename) + with open(dest, "wb") as f: + f.write(content) + + def config_export(self): + self.connect() + c = self.cdr.configs.get_by_name(self.args.name) + content = self.cdr.configs.get_plaintext(c.id) + self.file_save(self.configs_path, content.encode()) + + def file_content(self, path, filename=None): + content = None + filename = filename or self.args.filename + src = os.path.join(path, filename) + with open(src, "rb") as f: + content = f.read() + return content + + def config_check(self): + self.connect() + content = self.file_content(self.configs_path) + check = self.cdr.configs.check_config(content) + if not check.errors: + logging.info("OK, no errors!") + exit(0) + + for error in check.errors: + logging.error( + "{}: {}: {}".format( + self.args.filename, ",".join(error.lines), error.error + ) + ) + + exit(1) + + def config_import(self): + self.connect() + name = self.args.name or self.args.filename + + try: + c = self.cdr.configs.get_by_name(name) + self.cdr.configs.delete(c.id) + logging.debug("Deleted already existing config '{}'".format(c.name)) + except CDRouterError: + pass + + content = self.file_content(self.configs_path) + config = Config(contents=content, name=name) + self.cdr.configs.create(config) + logging.info("Imported config '{}' from '{}'".format(name, self.args.filename)) + + +def main(): + logging.basicConfig( + level=logging.INFO, format="%(levelname)7s: %(message)s", stream=sys.stderr + ) + + parser = argparse.ArgumentParser() + parser.add_argument( + "-r", + "--root-dir", + type=str, + default=os.environ.get("TB_CDROUTER_ROOT", ".testbed/cdrouter"), + help="CDRouter root directory (default: %(default)s)", + ) + parser.add_argument("-d", "--debug", action="store_true", help="enable debug mode") + + subparsers = parser.add_subparsers(dest="command", title="available subcommands") + subparser = subparsers.add_parser("package_run", help="run package") + subparser.add_argument("package_name", help="name of the testing package") + subparser.add_argument("-t", "--tags", help="additional tags for the result") + subparser.add_argument("-d", "--device", help="device used for testing") + subparser.add_argument( + "-c", "--configuration", help="configuration used for testing" + ) + subparser.add_argument( + "-s", + "--system-info", + help="JSON file with system information for additional tags", + ) + subparser.set_defaults(func=TestbedCDRouter.package_run) + + subparser = subparsers.add_parser( + "package_stop", help="stop running/paused package" + ) + subparser.add_argument( + "-p", "--package-name", help="name of the package (default: any)" + ) + subparser.set_defaults(func=TestbedCDRouter.package_stop) + + subparser = subparsers.add_parser("package_export", help="export package") + subparser.add_argument("name", help="package name") + subparser.add_argument( + "-f", "--filename", help="destination filename (default: name)" + ) + subparser.set_defaults(func=TestbedCDRouter.package_export) + + subparser = subparsers.add_parser("package_import", help="package configuration") + subparser.add_argument("filename", help="package filename") + subparser.add_argument("-n", "--name", help="package name, (default: filename)") + subparser.set_defaults(func=TestbedCDRouter.package_import) + + subparser = subparsers.add_parser("config_export", help="export configuration") + subparser.add_argument("name", help="configuration name") + subparser.add_argument("filename", help="destination filename") + subparser.set_defaults(func=TestbedCDRouter.config_export) + + subparser = subparsers.add_parser("config_check", help="check configuration") + subparser.add_argument("filename", help="config filename") + subparser.set_defaults(func=TestbedCDRouter.config_check) + + subparser = subparsers.add_parser("config_import", help="import configuration") + subparser.add_argument("filename", help="config filename") + subparser.add_argument("-n", "--name", help="config name, (default: filename)") + subparser.set_defaults(func=TestbedCDRouter.config_import) + + subparser = subparsers.add_parser( + "wait_for_netif", help="wait for network interface" + ) + subparser.add_argument("name", help="interface name") + subparser.add_argument( + "-t", + "--timeout", + type=int, + default=60, + help="wait duration in seconds (default: %(default)s)", + ) + subparser.set_defaults(func=TestbedCDRouter.wait_for_netif) + + args = parser.parse_args() + if args.debug: + logging.getLogger().setLevel(logging.DEBUG) + + if not args.command: + print("command is missing") + exit(1) + + cdr = TestbedCDRouter(args) + args.func(cdr) + + +if __name__ == "__main__": + main() diff --git a/.gitlab/scripts/testbed-device.py b/.gitlab/scripts/testbed-device.py new file mode 100755 index 0000000000..73643b10a9 --- /dev/null +++ b/.gitlab/scripts/testbed-device.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 + +import argparse +import os +import sys +import logging + +from labgrid import Environment, StepReporter +from labgrid.consoleloggingreporter import ConsoleLoggingReporter + + +class TestbedDevice: + def __init__(self, args): + self.args = args + self.env = Environment(config_file=self.args.config) + ConsoleLoggingReporter.start(args.console_logpath) + self.target = self.env.get_target(args.target) + + def boot_into(self): + strategy = self.target.get_driver("UBootStrategy") + dest = self.args.destination + if dest == "shell": + strategy.transition("shell") + if dest == "bootloader": + strategy.transition("uboot") + + def power(self): + power = self.target.get_driver("PowerProtocol") + action = self.args.action + if action == "on": + power.on() + if action == "off": + power.off() + if action == "cycle": + power.cycle() + + def check_network(self): + host = self.args.remote_host + network = self.args.network + shell = self.target.get_driver("ShellDriver") + shell.wait_for( + 'ifstatus {} | jsonfilter -qe "@.up" || true'.format(network), "true", 60.0 + ) + + shell.wait_for("ping -c1 {} || true".format(host), ", 0% packet loss", 90.0) + + +def main(): + logging.basicConfig( + level=logging.INFO, format="%(levelname)7s: %(message)s", stream=sys.stderr + ) + + parser = argparse.ArgumentParser() + parser.add_argument( + "-c", + "--config", + type=str, + default=os.environ.get("TB_CONFIG", ".testbed/labgrid/default.yaml"), + help="config file (default: %(default)s)", + ) + parser.add_argument( + "-t", + "--target", + type=str, + default=os.environ.get("TB_TARGET", None), + help="target device", + ) + parser.add_argument( + "-o", + "--console-logpath", + type=str, + default=os.environ.get("TB_CONSOLE_LOGPATH", os.getcwd()), + help="path for console logfile (default: %(default)s)", + ) + parser.add_argument( + "-v", + "--verbose", + action="count", + default=int(os.environ.get("TB_VERBOSE", 0)), + help="enable verbose mode", + ) + parser.add_argument( + "-d", + "--debug", + action="store_true", + default=os.environ.get("TB_DEBUG"), + help="enable debug mode", + ) + + subparsers = parser.add_subparsers(dest="command", title="available subcommands") + + subparser = subparsers.add_parser("power", help="control target power") + subparser.add_argument( + "action", choices=["on", "off", "cycle"], help="power on/off/cycle target" + ) + subparser.set_defaults(func=TestbedDevice.power) + + subparser = subparsers.add_parser("boot_into", help="boot target into console") + subparser.add_argument( + "destination", + choices=["shell", "bootloader"], + help="boot target either into system shell or bootloader console", + ) + subparser.set_defaults(func=TestbedDevice.boot_into) + + subparser = subparsers.add_parser( + "check_network", help="ensure that network is usable" + ) + subparser.add_argument( + "-r", + "--remote-host", + default="192.168.1.2", + help="remote host used for ping check (default: %(default)s)", + ) + subparser.add_argument( + "-n", "--network", default="lan", help="target network (default: %(default)s)" + ) + subparser.set_defaults(func=TestbedDevice.check_network) + + args = parser.parse_args() + if args.verbose >= 1: + StepReporter.start() + + if args.debug: + logging.getLogger().setLevel(logging.DEBUG) + + if not args.target: + print("target device name is mandatory") + exit(1) + + if not args.command: + print("command is missing") + exit(1) + + device = TestbedDevice(args) + args.func(device) + + +if __name__ == "__main__": + main() diff --git a/.gitlab/sdk.yml b/.gitlab/sdk.yml new file mode 100644 index 0000000000..156e878ddd --- /dev/null +++ b/.gitlab/sdk.yml @@ -0,0 +1,174 @@ +variables: + CI_DESIGNATED_BRANCH: prplos + +stages: + - generate + - build + +.build feed with SDK: + stage: build + image: $CI_SDK_IMAGE + variables: + CI_SDK_TOPDIR: /home/builder + CI_SDK_INSTALL_FEEDS: base packages luci routing + CI_SDK_BUILD_CONFIG: > + +BUILD_LOG -AUTOREMOVE -ALL -ALL_NONSHARED -ALL_KMODS -SIGNED_PACKAGES + + before_script: + - set -o pipefail + + - cd $CI_SDK_TOPDIR + - mkdir logs + + - sed -i 's;https://git.openwrt.org;https://gitlab.com/openwrt;' feeds.conf.default + - echo "src-include defaults feeds.conf.default" > feeds.conf + - echo "src-link ci $CI_PROJECT_DIR" >> feeds.conf + + - > + for feed in $CI_SDK_INSTALL_FEEDS ci; do + sleep_interval="$(( (RANDOM % 60) + 1 ))" + echo "Waiting for $sleep_interval seconds..." + sleep "${sleep_interval}s" + + ./scripts/feeds update "$feed" ; + ./scripts/feeds install -a -p "$feed" ; + done 2>&1 | tee logs/build.log + + - sync + - sleep 1 + - sync + + - > + for option in $CI_SDK_BUILD_CONFIG $CI_SDK_BUILD_CONFIG_EXTRA; do + echo "$option" | sed -E "s/^\+(.*)$/CONFIG_\1=y/;s/^\-(.*)$/CONFIG_\1=n/" >> .config + done + - cat .config | tee --append logs/build.log + - make defconfig | tee --append logs/build.log + - ./scripts/diffconfig.sh | tee --append logs/build.log + + - sync + - sleep 1 + - sync + + script: + - > + test -n "$CI_SDK_BEFORE_COMPILE_COMMAND" && + echo "Running CI_SDK_BEFORE_COMPILE_COMMAND=$CI_SDK_BEFORE_COMPILE_COMMAND" && + /bin/sh -c "$CI_SDK_BEFORE_COMPILE_COMMAND" + + - > + for package in $CI_SDK_BUILD_PACKAGES; do + make V=sc package/$package/{download,check} FIXUP=1 + done 2>&1 | tee --append logs/build.log + + - > + topdir=$(pwd); + for feed in $(find feeds -follow -name .git); do + pushd $(dirname $feed) > /dev/null; git diff-index --exit-code HEAD || { + ret=$? + echo "Feed $(dirname $feed) packages integrity issues, please check feed-packages-hash-issues.patch from artifacts" + git diff | tee $topdir/feed-packages-hash-issues.patch + exit $ret + } + popd > /dev/null + done + + - > + for package in $CI_SDK_BUILD_PACKAGES; do + make -j ${CI_SDK_BUILD_PARALLEL:-$(nproc)} package/$package/compile + done 2>&1 | tee --append logs/build.log + + after_script: + - cp -R "$CI_SDK_TOPDIR/logs" $CI_PROJECT_DIR + - > + if grep -qr 'make\[[[:digit:]]\].*Error [[:digit:]]$' logs; then + printf "\n====== Showing Make errors found in the log files ======"; + for file in $(grep -lr 'make\[[[:digit:]]\].*Error [[:digit:]]$' logs); do + printf "\n====== Make errors from $CI_JOB_URL/artifacts/file/$file ======\n" ; + grep -r -C5 'make\[[[:digit:]]\].*Error [[:digit:]]$' $file ; + done + fi + + artifacts: + expire_in: 1 month + when: always + paths: + - logs/ + - ./feed-packages-hash-issues.patch + +.generate SDK package build jobs: + stage: generate + image: alpine + + variables: + CI_SDK_BUILD_PACKAGES: | + please-provide + CI_SDK_PACKAGE_JOBS_TEMPLATE: | + include: + - remote: https://gitlab.com/prpl-foundation/prplos/prplos/-/raw/$CI_DESIGNATED_BRANCH/.gitlab/sdk.yml + {% for sdk in env['CI_SDK_TARGETS'].rstrip().split("\n") %} + {% for package in env['CI_SDK_BUILD_PACKAGES'].rstrip().split("\n") %} + build {{ package | trim }} with {{ sdk | trim }} SDK: + extends: .build feed with {{ sdk | trim }} SDK + variables: + CI_SDK_BUILD_PACKAGES: {{ package | trim }} + CI_SDK_BUILD_CONFIG_EXTRA: +PACKAGE_{{ package | trim }} + {% endfor %} + {% endfor %} + + before_script: + - apk add python3 py3-pip + - pip3 install jinja2 + + script: + - | + echo "$CI_SDK_PACKAGE_JOBS_TEMPLATE" | python3 -c ' + import os + import sys + import jinja2 + sys.stdout.write( + jinja2.Template(sys.stdin.read() + ).render(env=os.environ))' > sdk-package-jobs.yml + - cat sdk-package-jobs.yml + + artifacts: + paths: + - sdk-package-jobs.yml + +.execute SDK package build jobs: + stage: build + needs: + - generate + + trigger: + include: + - artifact: sdk-package-jobs.yml + job: generate + strategy: depend + +.build feed with OpenWrt SDK: + extends: .build feed with SDK + variables: + CI_SDK_BEFORE_COMPILE_COMMAND: sudo apt-get update; sudo apt-get install -y python-yaml python3-yaml + CI_SDK_TOPDIR: /home/build/openwrt + +.build feed with intel_mips-xrx500 SDK: + extends: .build feed with SDK + variables: + CI_SDK_IMAGE: registry.gitlab.com/prpl-foundation/prplos/prplos/$CI_DESIGNATED_BRANCH/sdk-intel_mips-xrx500:latest + CI_SDK_INSTALL_FEEDS: base packages luci routing feed_intel + +.build feed with ipq40xx-generic SDK: + extends: .build feed with SDK + variables: + CI_SDK_IMAGE: registry.gitlab.com/prpl-foundation/prplos/prplos/$CI_DESIGNATED_BRANCH/sdk-ipq40xx-generic:latest + +.build feed with mvebu-cortexa9 SDK: + extends: .build feed with SDK + variables: + CI_SDK_IMAGE: registry.gitlab.com/prpl-foundation/prplos/prplos/$CI_DESIGNATED_BRANCH/sdk-mvebu-cortexa9:latest + +.build feed with ath79-generic-19.07.7 SDK: + extends: .build feed with OpenWrt SDK + variables: + CI_SDK_IMAGE: openwrtorg/sdk:ath79-generic-19.07.7 diff --git a/.gitlab/testbed.yml b/.gitlab/testbed.yml new file mode 100644 index 0000000000..7eff15a80a --- /dev/null +++ b/.gitlab/testbed.yml @@ -0,0 +1,130 @@ +.testbed: + stage: run + image: "$CI_REGISTRY_IMAGE/$CI_DESIGNATED_BRANCH/testbed:latest" + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule"' + when: never + - when: always + variables: + DUT_WAN_INTERFACE: eth1 + TESTBED_MNG_INTERFACE: enp1s0 + TESTBED_LAN_INTERFACE: enp2s0 + TESTBED_WAN_INTERFACE: enp3s0 + TESTBED_TFTP_PATH: /var/lib/tftpboot + TFTP_IMAGE_PATH: bin/targets/$DUT_ARCH/$DUT_SUBTARGET + TARGET_LAN_IP: 192.168.1.1 + TARGET_LAN_TEST_HOST: 192.168.1.2 + DUT_SLEEP_AFTER_BOOT: 90 + CRAM_REMOTE_COMMAND: ssh root@$TARGET_LAN_IP + CRAM_TEST_SUITE: | + .gitlab/tests/cram/generic/acceleration-plan-components + .gitlab/tests/cram/$DUT_BOARD/acceleration-plan-components + .gitlab/tests/cram/generic + .gitlab/tests/cram/$DUT_BOARD + + before_script: + - touch .run_failed + + - sudo ip link set $TESTBED_LAN_INTERFACE up 2> /dev/null + - sudo ip link set $TESTBED_WAN_INTERFACE up 2> /dev/null + - sleep 10 + + - eval $(ssh-agent -s) + - echo "$TESTBED_SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - + - mkdir -p ~/.ssh; chmod 700 ~/.ssh + - ssh-keyscan $TESTBED_UART_RELAY_HOST > ~/.ssh/known_hosts 2> /dev/null + - chmod 644 ~/.ssh/known_hosts + + - > + if [ -n "$TFTP_IMAGE_DOWNLOAD_URL" ]; then + echo "Downloading firmware image from $TFTP_IMAGE_DOWNLOAD_URL" + curl --fail "$TFTP_IMAGE_DOWNLOAD_URL" > "$TESTBED_TFTP_PATH/$TFTP_IMAGE_FILENAME" + else + echo "Using firmware image $TFTP_IMAGE_PATH/$TFTP_IMAGE_FILENAME" + cp "$TFTP_IMAGE_PATH/$TFTP_IMAGE_FILENAME" "$TESTBED_TFTP_PATH" + fi + - > + if [ -n "$TFTP_IMAGE_UNPACK_COMMAND" ]; then + echo "Running $TFTP_IMAGE_UNPACK_COMMAND" + eval "$TFTP_IMAGE_UNPACK_COMMAND" + fi + - .gitlab/scripts/testbed-device.py --target $LABGRID_TARGET boot_into shell + - > + .gitlab/scripts/testbed-device.py + --target $LABGRID_TARGET check_network + --network lan + --remote-host $TARGET_LAN_TEST_HOST + + - > + retry_count=3; + while [ $retry_count -gt 0 ]; do + echo "Waiting for SSH availability on $TARGET_LAN_IP" + ssh-keyscan "$TARGET_LAN_IP" 2>&1 | grep -q "$TARGET_LAN_IP" && break + retry_count="$(( retry_count - 1 ))" + sleep 5 + done + + - ssh-keyscan $TARGET_LAN_IP >> ~/.ssh/known_hosts 2> /dev/null + - ssh root@$TARGET_LAN_IP "cat /var/log/messages" > syslog-$LABGRID_TARGET.txt 2> /dev/null || true + - ssh root@$TARGET_LAN_IP "ubus call system board" | tee system-$LABGRID_TARGET.json + + script: + - sleep $DUT_SLEEP_AFTER_BOOT + - set -o pipefail + - python3 -m cram --verbose $CRAM_TEST_SUITE $CRAM_TEST_SUITE_EXTRA | tee cram-result-$LABGRID_TARGET.txt + - rm .run_failed + + after_script: + - > + [ "$TMATE_ENABLE_SHELL" = "YES" ] && { + echo "Starting tmate session..." + tmate -n "${TMATE_SESSION_TOKEN}-$CI_JOB_ID" -k "$TMATE_API_KEY" -F new "ssh root@$TARGET_LAN_IP" > /tmp/tmate-session.log 2>&1 + true + } + + - eval $(ssh-agent -s) + - echo "$TESTBED_SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - + - mkdir -p ~/.ssh; chmod 700 ~/.ssh + - ssh-keyscan $TESTBED_UART_RELAY_HOST > ~/.ssh/known_hosts 2> /dev/null + - chmod 644 ~/.ssh/known_hosts + + - ssh-keyscan $TARGET_LAN_IP >> ~/.ssh/known_hosts 2> /dev/null + - > + ssh root@$TARGET_LAN_IP exit && { + ssh root@$TARGET_LAN_IP ps > processes-$LABGRID_TARGET.txt + ssh root@$TARGET_LAN_IP dmesg > dmesg-$LABGRID_TARGET.txt + ssh root@$TARGET_LAN_IP "cat /var/log/messages" > syslog-$LABGRID_TARGET.txt + ssh root@$TARGET_LAN_IP opkg list > opkg_list-$LABGRID_TARGET.txt + scp -r root@${TARGET_LAN_IP}:/etc etc > /dev/null + scp -r root@${TARGET_LAN_IP}:/tmp/beerocks/logs prplmesh_beerocks_logs > /dev/null + } || true + + - .gitlab/scripts/testbed-device.py --target $LABGRID_TARGET power off + + - mv console_$LABGRID_TARGET console_$LABGRID_TARGET.txt || true + - > + [ "$CI_COMMIT_BRANCH" = "$CI_DESIGNATED_BRANCH" ] && [ "$TMATE_ENABLE_SHELL" != "YES" ] && { + test -f .run_failed && + .gitlab/scripts/prpl-jira.py run_failure --target $LABGRID_TARGET || true + } || true + + + artifacts: + expire_in: 1 month + when: always + paths: + - .gitlab/tests/cram/**/*.t.err + - etc + - prplmesh_beerocks_logs + - processes-$LABGRID_TARGET.txt + - dmesg-$LABGRID_TARGET.txt + - syslog-$LABGRID_TARGET.txt + - system-$LABGRID_TARGET.json + - console_$LABGRID_TARGET.txt + - cram-result-$LABGRID_TARGET.txt + - opkg_list-$LABGRID_TARGET.txt + +.testbed true.cz: + extends: .testbed + variables: + TESTBED_UART_RELAY_HOST: uart-relay.testbed.vpn.true.cz diff --git a/.gitlab/testbed/glinet-b1300.yml b/.gitlab/testbed/glinet-b1300.yml new file mode 100644 index 0000000000..a70d6e8879 --- /dev/null +++ b/.gitlab/testbed/glinet-b1300.yml @@ -0,0 +1,10 @@ +.glinet-b1300 testbed: + extends: .testbed true.cz + variables: + DUT_ARCH: ipq40xx + DUT_SUBTARGET: generic + DUT_BOARD: glinet-b1300 + LABGRID_TARGET: glinet-b1300-initramfs + TFTP_IMAGE_FILENAME: openwrt-ipq40xx-generic-glinet_gl-b1300-initramfs-fit-uImage.itb + tags: + - dut-glinet-b1300 diff --git a/.gitlab/testbed/nec-wx3000hp.yml b/.gitlab/testbed/nec-wx3000hp.yml new file mode 100644 index 0000000000..a3e06f25ba --- /dev/null +++ b/.gitlab/testbed/nec-wx3000hp.yml @@ -0,0 +1,10 @@ +.nec-wx3000hp testbed: + extends: .testbed true.cz + variables: + DUT_ARCH: intel_mips + DUT_SUBTARGET: xrx500 + DUT_BOARD: nec-wx3000hp + LABGRID_TARGET: nec-wx3000hp-nand + TFTP_IMAGE_FILENAME: AX3000_1600_ETH_11AXUCI_ASURADA-squashfs-fullimage.img + tags: + - dut-nec-wx3000hp diff --git a/.gitlab/testbed/turris-omnia.yml b/.gitlab/testbed/turris-omnia.yml new file mode 100644 index 0000000000..db092fb29c --- /dev/null +++ b/.gitlab/testbed/turris-omnia.yml @@ -0,0 +1,11 @@ +.turris-omnia testbed: + extends: .testbed true.cz + variables: + DUT_ARCH: mvebu + DUT_SUBTARGET: cortexa9 + DUT_BOARD: turris-omnia + DUT_WAN_INTERFACE: eth2 + LABGRID_TARGET: turris-omnia-initramfs + TFTP_IMAGE_FILENAME: openwrt-mvebu-cortexa9-cznic_turris-omnia-initramfs-kernel.bin + tags: + - dut-turris-omnia diff --git a/.gitlab/tests/README.md b/.gitlab/tests/README.md new file mode 100644 index 0000000000..973c1ba5c7 --- /dev/null +++ b/.gitlab/tests/README.md @@ -0,0 +1,12 @@ +# Content + +This directory contains tests. + +## cram + +Contains [Cram](https://github.com/brodie/cram/) based tests. [Cram](https://github.com/brodie/cram/) is a functional +testing framework for command line applications. [Cram](https://github.com/brodie/cram/) tests look like snippets of +interactive shell sessions. Cram runs each command and compares the command output in the test with the command's actual +output. + +Tests in this directory should be run against device, usually over network via SSH connection. diff --git a/.gitlab/tests/cram/README.md b/.gitlab/tests/cram/README.md new file mode 100644 index 0000000000..a925b21cb6 --- /dev/null +++ b/.gitlab/tests/cram/README.md @@ -0,0 +1,19 @@ +# Content + +This directory contains Cram based tests. + +## generic + +Contains tests which could be used on all devices. + +## turris-omnia + +Contains tests which could be used against `Turris Omnia` device. + +## glinet-b1300 + +Contains tests which could be used against `Gl.iNet B1300` device. + +## nec-wx3000hp + +Contains tests which could be used against `NEC WX3000HP` device. diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/010-firewall-dhcp.t b/.gitlab/tests/cram/generic/acceleration-plan-components/010-firewall-dhcp.t new file mode 100644 index 0000000000..c03aa72bb8 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/010-firewall-dhcp.t @@ -0,0 +1,41 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check that client is able to get new lease: + + $ sudo nmap --script broadcast-dhcp-discover -e $TESTBED_LAN_INTERFACE 2>&1 | egrep '(Server|Router|Subnet)' | sort + | Domain Name Server: 192.168.1.1 + | Router: 192.168.1.1 + | Server Identifier: 192.168.1.1 + | Subnet Mask: 255.255.255.0 + +Remove dhcp-server rule: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.X_Prpl_Service.dhcp-server-" > /dev/null; sleep .5 + +Check that client is unable to get new lease: + + $ sudo nmap --script broadcast-dhcp-discover -e $TESTBED_LAN_INTERFACE 2>&1 | egrep '(Server|Router|Subnet)' + [1] + +Add back firewall rule for dhcp-server access from LAN: + + $ printf "\ + > ubus-cli Firewall.X_Prpl_Service+{Alias='dhcp-server'} + > ubus-cli Firewall.X_Prpl_Service.dhcp-server.Action=Accept + > ubus-cli Firewall.X_Prpl_Service.dhcp-server.DestinationPort=67 + > ubus-cli Firewall.X_Prpl_Service.dhcp-server.IPVersion=4 + > ubus-cli Firewall.X_Prpl_Service.dhcp-server.Interface=br-lan + > ubus-cli Firewall.X_Prpl_Service.dhcp-server.Protocol=UDP + > ubus-cli Firewall.X_Prpl_Service.dhcp-server.Enable=1 + > " > /tmp/cram + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/cram)'" > /dev/null + +Check that client is able to get new lease again: + + $ sudo nmap --script broadcast-dhcp-discover -e $TESTBED_LAN_INTERFACE 2>&1 | egrep '(Server|Router|Subnet)' | sort + | Domain Name Server: 192.168.1.1 + | Router: 192.168.1.1 + | Server Identifier: 192.168.1.1 + | Subnet Mask: 255.255.255.0 diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/010-firewall-http-toggle.t b/.gitlab/tests/cram/generic/acceleration-plan-components/010-firewall-http-toggle.t new file mode 100644 index 0000000000..e95089a7f8 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/010-firewall-http-toggle.t @@ -0,0 +1,26 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check that HTTP from LAN is allowed by default: + + $ R "iptables -L INPUT_Services -v -n | grep 'br-lan.*dpt:80$'" + * ACCEPT tcp -- br-lan * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 (glob) + +Disable firewall rule for HTTP access from LAN: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.X_Prpl_Service.http.Enable=0" > /dev/null; sleep .5 + +Check that HTTP from LAN is forbidden: + + $ R "iptables -L INPUT_Services -v -n | grep 'br-lan.*dpt:80$'" + [1] + +Enable firewall rule for HTTP access from LAN: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.X_Prpl_Service.http.Enable=1" > /dev/null; sleep .5 + +Check that HTTP from LAN is allowed again: + + $ R "iptables -L INPUT_Services -v -n | grep 'br-lan.*dpt:80$'" + * ACCEPT tcp -- br-lan * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 (glob) diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/012-firewall-port-trigger.t b/.gitlab/tests/cram/generic/acceleration-plan-components/012-firewall-port-trigger.t new file mode 100644 index 0000000000..ea0ad830c9 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/012-firewall-port-trigger.t @@ -0,0 +1,65 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Configure port trigger rule: + + $ printf "\ + > ubus-cli Firewall.X_Prpl_PortTrigger+{Alias='test'} + > ubus-cli Firewall.X_Prpl_PortTrigger.test.Port=6000 + > ubus-cli Firewall.X_Prpl_PortTrigger.test.Protocol="6" + > ubus-cli Firewall.X_Prpl_PortTrigger.test.Timer=7 + > ubus-cli Firewall.X_Prpl_PortTrigger.test.Rule+{Alias='test-rule'} + > ubus-cli Firewall.X_Prpl_PortTrigger.test.Rule.test-rule.Port=8000 + > ubus-cli Firewall.X_Prpl_PortTrigger.test.Rule.test-rule.Protocol="17" + > ubus-cli Firewall.X_Prpl_PortTrigger.test.Enable=1 + > " > /tmp/cram + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/cram)'" > /dev/null; sleep 1 + +Check that there is NFQUEUE rule: + + $ R "iptables -L FORWARD_PortTrigger -n | grep 6000" + NFQUEUE tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:6000[8 bytes of unknown target data] + +Disable port trigger rule: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.X_Prpl_PortTrigger.test.Enable=0" > /dev/null; sleep 1 + +Check that there is no NFQUEUE rule: + + $ R "iptables -L FORWARD_PortTrigger -n | grep 6000" + [1] + +Enable port trigger rule: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.X_Prpl_PortTrigger.test.Enable=1" > /dev/null; sleep 1 + +Add route to 10.10.10.10 via TARGET_LAN_IP: + + $ sudo ip route add 10.10.10.10/32 via $TARGET_LAN_IP dev $TESTBED_LAN_INTERFACE 2> /dev/null + +Trigger port rule: + + $ curl --silent --output /dev/null --max-time 2 http://10.10.10.10:6000 ; sleep 3 + +Check that additional rules has been created: + + $ R "iptables -L FORWARD_PortTrigger -n | grep 8000 | sort" + ACCEPT udp -- 0.0.0.0/0 192.168.1.2 udp dpt:8000 + ACCEPT udp -- 192.168.1.2 0.0.0.0/0 udp spt:8000 + +Check that the owner IPAddress was correctly set: + + $ R "ubus call Firewall.X_Prpl_PortTrigger _get '{\"rel_path\":\"test.Stats.IPAddress\"}' | jsonfilter -e @[*].IPAddress" + 192.168.1.2 + +Wait for expiration of port trigger and check that everything is disabled: + + $ sleep 6 + $ R "iptables -L FORWARD_PortTrigger -n | grep 8000" + [1] + +Remove port trigger rule and route: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.X_Prpl_PortTrigger.test-" > /dev/null + $ sudo ip route del 10.10.10.10/32 via $TARGET_LAN_IP dev $TESTBED_LAN_INTERFACE 2> /dev/null diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/013-firewall-mac-filter.t b/.gitlab/tests/cram/generic/acceleration-plan-components/013-firewall-mac-filter.t new file mode 100644 index 0000000000..fe66f7b035 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/013-firewall-mac-filter.t @@ -0,0 +1,43 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Configure MAC filter rule: + + $ printf "\ + > ubus-cli Firewall.Chain.L_Low.Rule+{Alias='test'} + > ubus-cli Firewall.Chain.L_Low.Rule.test.X_Prpl_SourceMAC='AA:BB:CC:DD:EE:FF' + > ubus-cli Firewall.Chain.L_Low.Rule.test.Target=Accept + > ubus-cli Firewall.Chain.L_Low.Rule.test.IPVersion=4 + > ubus-cli Firewall.Chain.L_Low.Rule.test.Enable=1 + > " > /tmp/cram + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/cram)'" > /dev/null; sleep 1 + +Check that there is correct rule present: + + $ R "iptables -L FORWARD_L_Low -n | grep AA:BB:CC" + ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 MAC AA:BB:CC:DD:EE:FF + +Disable MAC filter rule: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.Chain.L_Low.Rule.test.Enable=0" > /dev/null; sleep 1 + +Check that the rule is missing: + + $ R "iptables -L FORWARD_L_Low -n | grep AA:BB:CC" + [1] + +Enable MAC filter rule: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.Chain.L_Low.Rule.test.Enable=1" > /dev/null; sleep 1 + +Check that the rule is back again: + + $ R "iptables -L FORWARD_L_Low -n | grep AA:BB:CC" + ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 MAC AA:BB:CC:DD:EE:FF + +Remove the rule and check that it is gone: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.Chain.L_Low.Rule.test-" > /dev/null; sleep 1 + $ R "iptables -L FORWARD_L_Low -n | grep AA:BB:CC" + [1] diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/014-firewall-levels.t b/.gitlab/tests/cram/generic/acceleration-plan-components/014-firewall-levels.t new file mode 100644 index 0000000000..d3aed4cb6a --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/014-firewall-levels.t @@ -0,0 +1,27 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Set firewall level to High: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.Config=High" > /dev/null; sleep 1 + +Check that it is set properly: + + $ R "iptables -n -L FORWARD_L_Low | grep references" + Chain FORWARD_L_Low (0 references) + + $ R "iptables -n -L FORWARD_L_High | grep references" + Chain FORWARD_L_High (2 references) + +Set firewall level to Low: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.Config=Low" > /dev/null; sleep 1 + +Check that it is set properly: + + $ R "iptables -n -L FORWARD_L_Low | grep references" + Chain FORWARD_L_Low (2 references) + + $ R "iptables -n -L FORWARD_L_High | grep references" + Chain FORWARD_L_High (0 references) diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/015-nat-portmapping.t b/.gitlab/tests/cram/generic/acceleration-plan-components/015-nat-portmapping.t new file mode 100644 index 0000000000..a55aa24194 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/015-nat-portmapping.t @@ -0,0 +1,42 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Create portmapping: + + $ printf "\ + > ubus-cli NAT.PortMapping+{Alias='testing'} + > ubus-cli NAT.PortMapping.testing.ExternalPort=5000 + > ubus-cli NAT.PortMapping.testing.Interface=wan + > ubus-cli NAT.PortMapping.testing.InternalClient=$TARGET_LAN_TEST_HOST + > ubus-cli NAT.PortMapping.testing.InternalPort=12345 + > ubus-cli NAT.PortMapping.testing.Protocol=TCP + > ubus-cli NAT.PortMapping.testing.Enable=1 + > " > /tmp/cram + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/cram)'" > /dev/null + +Check that portmapping works: + + $ sudo tcpdump -c 1 -l -n -i $TESTBED_LAN_INTERFACE tcp port 12345 > /tmp/tcpdump-works 2> /dev/null & + $ sleep 1 + + $ echo foo | nc -w 1 10.0.0.2 5000 > /dev/null 2>&1 + [1] + + $ grep -c 12345 /tmp/tcpdump-works + 1 + +Remove portmapping: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli NAT.PortMapping.testing-" > /dev/null; sleep .5 + +Check that portmapping doesnt work: + + $ sudo tcpdump -c 1 -l -n -i $TESTBED_LAN_INTERFACE tcp port 12345 > /tmp/tcpdump 2> /dev/null & + $ sleep 1 + + $ echo foo | nc -w 1 10.0.0.2 5000 > /dev/null 2>&1 + [1] + + $ wc -l /tmp/tcpdump + 0 /tmp/tcpdump diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/030-usermanagement.t b/.gitlab/tests/cram/generic/acceleration-plan-components/030-usermanagement.t new file mode 100644 index 0000000000..91d47c22c2 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/030-usermanagement.t @@ -0,0 +1,56 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Create testing user: + + $ printf "\ + > ubus-cli Users.Group.+{GroupID=999,Groupname='testgroup',Alias='testgroup'} + > ubus-cli Users.SupportedShell.+{Name='/bin/ash',Alias='ash',Enable='true'} + > ubus-cli Users.User.+{UserID=666,Username='testuser',Alias='testuser',GroupParticipation='Users.Group.testgroup.',Password='password',Shell='Users.SupportedShell.ash.'} + > sleep 5; passwd -d root + > " > /tmp/cram + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/cram)'" > /dev/null + $ sleep 1 + +Check that user and group exists: + + $ R "grep testgroup /etc/group" + testgroup:x:999:testuser + + $ R "grep testuser /etc/passwd" + testuser:x:666:999:testuser:/var:/bin/ash + + $ R "grep -c testuser /etc/shadow" + 1 + +Check that we are able to login: + + $ sshpass -ppassword ssh testuser@$TARGET_LAN_IP id + uid=666(testuser) gid=999(testgroup) groups=999(testgroup),999(testgroup) + +Delete group and user: + + $ printf "\ + > ubus-cli Users.User.testuser.- + > ubus-cli Users.Group.testgroup.- + > " > /tmp/cram + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/cram)'" > /dev/null + $ sleep 1 + +Check that user and group does not exists: + + $ R "grep testgroup /etc/group" + [1] + + $ R "grep testuser /etc/passwd" + [1] + + $ R "grep testuser /etc/shadow" + [1] + +Check that we are not able to login: + + $ sshpass -ppassword ssh testuser@$TARGET_LAN_IP id + Permission denied, please try again.\r (esc) + [5] diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings.t b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings.t new file mode 100644 index 0000000000..ac4f4135c8 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings.t @@ -0,0 +1,69 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Add testing profiles and triggers: + + $ printf "\ + > ubus-cli X_PRPL-COM_MultiSettings.DetectionAtBoot=1 + > ubus-cli X_PRPL-COM_MultiSettings.Profile.+{Alias='france-profile'} + > ubus-cli X_PRPL-COM_MultiSettings.Profile.france-profile.Name='france' + > ubus-cli X_PRPL-COM_MultiSettings.Profile.france-profile.ImpactedModules='testing' + > ubus-cli X_PRPL-COM_MultiSettings.Profile.france-profile.Trigger.+{Alias='country-france'} + > ubus-cli X_PRPL-COM_MultiSettings.Profile.france-profile.Trigger.country-france.LeftMember='TestingEmitter.CountryCode' + > ubus-cli X_PRPL-COM_MultiSettings.Profile.france-profile.Trigger.country-france.RelationalOperator='Equal' + > ubus-cli X_PRPL-COM_MultiSettings.Profile.france-profile.Trigger.country-france.RightMember='FR' + > ubus-cli X_PRPL-COM_MultiSettings.Profile.+{Alias='usa-profile'} + > ubus-cli X_PRPL-COM_MultiSettings.Profile.usa-profile.Name='usa' + > ubus-cli X_PRPL-COM_MultiSettings.Profile.usa-profile.ImpactedModules='testing' + > ubus-cli X_PRPL-COM_MultiSettings.Profile.usa-profile.Trigger.+{Alias='country-usa'} + > ubus-cli X_PRPL-COM_MultiSettings.Profile.usa-profile.Trigger.country-usa.LeftMember='TestingEmitter.CountryCode' + > ubus-cli X_PRPL-COM_MultiSettings.Profile.usa-profile.Trigger.country-usa.RelationalOperator='Equal' + > ubus-cli X_PRPL-COM_MultiSettings.Profile.usa-profile.Trigger.country-usa.RightMember='US' + > " > /tmp/cram + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/cram)'" > /dev/null + +Add testing service: + + $ scp -r $TESTDIR/035-multisettings/* root@${TARGET_LAN_IP}:/ + +Restart multisettings service and start testing service: + + $ R "/etc/init.d/testing start 2> /dev/null" + $ R "/etc/init.d/multisettings restart 2> /dev/null" + +Check that there is no profile currently selected: + + $ R "cat /var/run/selected_profile" + cat: can't open '/var/run/selected_profile': No such file or directory + [1] + +Check that TestingReceiver and TestingEmitter have correct default settings: + + $ R "ubus call TestingReceiver _get \"{'rel_path':''}\" | jsonfilter -e @[*].NTPServer1 -e @[*].NTPServer2 | sort" + 0.eu.pool.ntp.org + 1.eu.pool.ntp.org + + $ R "ubus call TestingEmitter _get \"{'rel_path':''}\" | jsonfilter -e @[*].CountryCode" + EU + +Change profile to France: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli TestingEmitter.CountryCode='FR'" > /dev/null; sleep 5 + +Check that french profile is correctly applied: + + $ R "ubus list | grep TestingReceiver" + TestingReceiver + + $ R "ubus call TestingReceiver _get \"{'rel_path':''}\" | jsonfilter -e @[*].NTPServer1 -e @[*].NTPServer2 | sort" + 0.fr.pool.ntp.org + 1.fr.pool.ntp.org + +Cleanup: + + $ R "/etc/init.d/testing stop 2> /dev/null" + $ R "/etc/init.d/multisettings stop 2> /dev/null" + $ R "rm -fr /etc/config/multisettings; rm /etc/init.d/testing" + $ R "rm -fr /etc/amx/testing; rm -fr /var/run/selected_profile; rm /usr/bin/testing" + $ R "/etc/init.d/multisettings start 2> /dev/null" diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_default.odl b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_default.odl new file mode 100644 index 0000000000..e740a382de --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_default.odl @@ -0,0 +1,6 @@ +%populate { + object TestingReceiver { + parameter NTPServer1 = "0.eu.pool.ntp.org"; + parameter NTPServer2 = "1.eu.pool.ntp.org"; + } +} diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_france.odl b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_france.odl new file mode 100644 index 0000000000..767b351c12 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_france.odl @@ -0,0 +1,6 @@ +%populate { + object TestingReceiver { + parameter NTPServer1 = "0.fr.pool.ntp.org"; + parameter NTPServer2 = "1.fr.pool.ntp.org"; + } +} diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_usa.odl b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_usa.odl new file mode 100644 index 0000000000..ba02778c05 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/profile_usa.odl @@ -0,0 +1,6 @@ +%populate { + object TestingReceiver { + parameter NTPServer1 = "0.us.pool.ntp.org"; + parameter NTPServer2 = "1.us.pool.ntp.org"; + } +} diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/testing.odl b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/testing.odl new file mode 100755 index 0000000000..43ff50235b --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/amx/testing/testing.odl @@ -0,0 +1,19 @@ +%config {} +%define { + object TestingEmitter { + string CountryCode { + on action validate call check_maximum 2; + } + } + object TestingReceiver { + string NTPServer1; + string NTPServer2; + } +} +%populate { + object TestingEmitter { + parameter CountryCode = "EU"; + } +} +#include "/var/run/selected_profile"; +?include "/etc/amx/testing/profile_${profile}.odl":"/etc/amx/testing/profile_default.odl"; diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/init.d/testing b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/init.d/testing new file mode 100755 index 0000000000..3fbcf73cf8 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/035-multisettings/etc/init.d/testing @@ -0,0 +1,22 @@ +#!/bin/sh + +name="testing" + +case $1 in + start|boot) + [ ! -f /usr/bin/${name} ] && ln -s /usr/bin/amxrt /usr/bin/${name} + $name -D + ;; + stop|shutdown) + if [ -f /var/run/${name}.pid ]; then + kill $(cat /var/run/${name}.pid) + fi + ;; + restart) + $0 stop + $0 start + ;; + *) + echo "Usage : $0 [start|boot|stop]" + ;; +esac diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/040-lcm.t b/.gitlab/tests/cram/generic/acceleration-plan-components/040-lcm.t new file mode 100644 index 0000000000..c61d8dc5c2 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/040-lcm.t @@ -0,0 +1,73 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check that random LXC binaries work: + + $ R /opt/prplos/usr/bin/lxc-info + lxc-info: No container name specified + [1] + + $ R /opt/prplos/usr/bin/lxc-device + lxc-device: No container name specified + [1] + +Check Cthulhu.Config datamodel: + + $ R "ubus -S call Cthulhu.Config _get" + {"Cthulhu.Config.":{"ImageLocation":"/usr/share/rlyeh/images","StorageLocation":"/usr/share/cthulhu","UseOverlayFS":true,"DhcpCommand":"","DefaultBackend":"/usr/lib/cthulhu-lxc/cthulhu-lxc.so","BlobLocation":"/usr/share/rlyeh/blobs"}} + +Check Rlyeh datamodel: + + $ R "ubus -S call Rlyeh _get" + {"Rlyeh.":{"ImageLocation":"/usr/share/rlyeh/images","SignatureVerification":false,"StorageLocation":"/usr/share/rlyeh/blobs"}} + +Check SoftwareModules datamodel: + + $ R "ubus -S call SoftwareModules _get" + {"SoftwareModules.":{"ExecutionUnitNumberOfEntries":0,"ExecEnvNumberOfEntries":1,"DeploymentUnitNumberOfEntries":0}} + +Check Timingila datamodel: + + $ R "ubus -S call Timingila _get" + {"Timingila.":{"RmAfterUninstall":true,"ContainerPluginPath":"/usr/lib/timingila-cthulhu/timingila-cthulhu.so","PackagerPluginPath":"/usr/lib/timingila-rlyeh/timingila-rlyeh.so","version":"alpha"}} + +Check that Rlyeh has no container images: + + $ R "ubus -S call Rlyeh.Images _get" + {"Rlyeh.Images.":{}} + +Check that Rlyeh can download testing container: + + $ R "ubus -S call Rlyeh pull '{\"URI\":\"docker://registry.gitlab.com/prpl-foundation/prplos/prplos/prplos-testing-container-intel_mips-xrx500:v1\",\"UUID\":\"testing\"}'" + {"retval":""} + + $ R "ubus -t 60 wait_for Rlyeh.Images.1" + +Check that Rlyeh has downloaded the testing container: + + $ R "ubus -S call Rlyeh.Images _get | jsonfilter -e @[*].Name -e @[*].Status | sort" + Downloaded + prplos/prplos-testing-container-intel_mips-xrx500 + +Remove testing container: + + $ R "ubus -S call Rlyeh remove '{\"UUID\":\"testing\",\"Version\":\"v1\"}'"; sleep 5 + {"retval":""} + + $ R "ubus -S call Rlyeh.Images.1 _get | jsonfilter -e @[*].MarkForRemoval" + true + + $ R "ubus -S call Rlyeh gc" + {"retval":""} + +Check that Rlyeh has no container images: + + $ R "ubus -S call Rlyeh.Images _get" + {"Rlyeh.Images.":{}} + +Check that testing image is gone from the filesystem as well: + + $ R "ls -al /usr/share/rlyeh/images/prplos/prplos-testing-container-intel_mips-xrx500" + ls: /usr/share/rlyeh/images/prplos/prplos-testing-container-intel_mips-xrx500: No such file or directory + [1] diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/045-qos.t b/.gitlab/tests/cram/generic/acceleration-plan-components/045-qos.t new file mode 100644 index 0000000000..c2a8758641 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/045-qos.t @@ -0,0 +1,163 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check QoS root datamodel: + + $ R "ubus -S call QoS _get" + {"QoS.":{"SupportedControllers":"mod-qos-tc","ShaperNumberOfEntries":1,"QueueNumberOfEntries":5,"MaxClassificationEntries":20,"ClassificationNumberOfEntries":0,"QueueStatsNumberOfEntries":4,"MaxQueueEntries":20,"MaxShaperEntries":20}} + +Check Qos.Node.7 datamodel: + + $ R "ubus call QoS.Node.7 _get | jsonfilter -e @[*].TrafficClasses -e @[*].DropAlgorithm -e @[*].Controller -e @[*].AllInterfaces -e @[*].SchedulerAlgorithm -e @[*].Alias " | sort + 5, 6, 7 + DT + HTB + false + mod-qos-tc + node-queue-home-voip + +Check QoS.Queue datamodel for stats-home-iptv: + + $ R "ubus call QoS.Queue.5 _get | jsonfilter -e @[*].Alias -e @[*].SchedulerAlgorithm -e @[*].Status -e @[*].Controller -e @[*].TrafficClasses" | sort + 3 + Enabled + HTB + mod-qos-tc + queue-home-iptv + +Check QoS.QueueStats datamodel for stats-home-iptv: + + $ R "ubus -S call QoS.QueueStats.4 _get | jsonfilter -e @[*].Status -e @[*].QueueOccupancyPercentage -e @[*].Alias -e @[*].Queue" | sort + 0 + Enabled + QoS.Queue.queue-home-iptv + stats-home-iptv + +Check QoS.Scheduler datamodel: + + $ R "ubus call QoS.Scheduler _get | jsonfilter -e @[*].DefaultQueue -e @[*].SchedulerAlgorithm -e @[*].Status -e @[*].Controller" | sort + Enabled + HTB + QoS.Queue.queue-home-data. + mod-qos-tc + +Check QoS.Shaper.1 datamodel: + + $ R "ubus call QoS.Shaper.1 _get | jsonfilter -e @[*].Controller -e @[*].Enable -e @[*].Status" | sort + Enabled + mod-qos-tc + true + +Add a new classification instance and set the DSCP value for IPv4 ICMP packets: + + $ cat > /tmp/new-classification < ubus-cli QoS.Classification.+{Alias=icmp_dscp_cs6,Flags=\"class_basic\"} + > ubus-cli QoS.Classification.icmp_dscp_cs6.DSCPMark=48 + > ubus-cli QoS.Classification.icmp_dscp_cs6.Interface=\"Postrouting\" + > ubus-cli QoS.Classification.icmp_dscp_cs6.Protocol=1 + > ubus-cli QoS.Classification.icmp_dscp_cs6.IPVersion=4 + > ubus-cli QoS.Classification.icmp_dscp_cs6.Enable=1 + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/new-classification)'" > /dev/null + $ sleep 2 + +Check new classification instance configuration: + + $ R "ubus call QoS.Classification.1 _get | jsonfilter -e @[*].Status -e @[*].DSCPMark -e @[*].Alias -e @[*].Protocol -e @[*].IPVersion" | sort + 1 + 4 + 48 + Enabled + icmp_dscp_cs6 + + $ R "iptables -t mangle -L POSTROUTING_class | grep 'DSCP set'" + DSCP icmp -- anywhere anywhere DSCP set 0x30 + +Alter the previous classification and set the DSCP marking to 52: + + $ script --command "ssh -t root@$TARGET_LAN_IP 'ubus-cli QoS.Classification.icmp_dscp_cs6.DSCPMark=52'" > /dev/null; sleep 2 + +Check altered classification instance configuration: + + $ R "ubus call QoS.Classification.1 _get | jsonfilter -e @[*].Status -e @[*].DSCPMark -e @[*].Alias -e @[*].Protocol -e @[*].IPVersion" | sort + 1 + 4 + 52 + Enabled + icmp_dscp_cs6 + + $ R "iptables -t mangle -L POSTROUTING_class | grep 'DSCP set'" + DSCP icmp -- anywhere anywhere DSCP set 0x34 + +Add a second classification instance. Mark ICMP packets to network 192.168.25.0/24 with value 8 (CS1): + + $ cat > /tmp/new-classification < ubus-cli QoS.Classification.+{Alias=icmp_dscp_cs1,Flags=\"class_basic\"} + > ubus-cli QoS.Classification.icmp_dscp_cs1.DSCPMark=8 + > ubus-cli QoS.Classification.icmp_dscp_cs1.Interface="Postrouting" + > ubus-cli QoS.Classification.icmp_dscp_cs1.Protocol=1 + > ubus-cli QoS.Classification.icmp_dscp_cs1.IPVersion=4 + > ubus-cli QoS.Classification.icmp_dscp_cs1.DestIP=192.168.25.0 + > ubus-cli QoS.Classification.icmp_dscp_cs1.DestMask="255.255.255.0" + > ubus-cli QoS.Classification.icmp_dscp_cs1.Enable=1 + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/new-classification)'" > /dev/null + $ sleep 2 + +The firewall rule to set a DSCP value for ICMP packets to network 192.168.25.0/24 must be the first one, so change the order: + + $ script --command "ssh -t root@$TARGET_LAN_IP 'ubus-cli QoS.Classification.icmp_dscp_cs1.Order=1'" > /dev/null; sleep 2 + +Check correct change of packet classification ordering: + + $ R "ubus call QoS.Classification.1 _get | jsonfilter -e @[*].Order" + 2 + + $ R "ubus call QoS.Classification.2 _get | jsonfilter -e @[*].Order" + 1 + + $ R "iptables -t mangle -L POSTROUTING_class | grep 'DSCP set'" + DSCP icmp -- anywhere 192.168.25.0/24 DSCP set 0x08 + DSCP icmp -- anywhere anywhere DSCP set 0x34 + +Check default QoS configuration: + + $ R "tc qdisc show dev $DUT_WAN_INTERFACE" + qdisc htb 1: root refcnt (2|5|9) r2q 10 default 0x10003 direct_packets_stat [0-9]+ direct_qlen (532|1000) (re) + + $ R "tc class show dev $DUT_WAN_INTERFACE" | sort + class htb 1:1 parent 1:32 prio 5 rate 25Mbit ceil 25Mbit burst *b cburst *b (glob) + class htb 1:2 parent 1:32 rate 300Mbit ceil 300Mbit burst *b cburst *b (glob) + class htb 1:3 parent 1:2 prio 3 rate 250Mbit ceil 250Mbit burst *b cburst *b (glob) + class htb 1:32 root rate 325Mbit ceil 325Mbit burst *b cburst *b (glob) + class htb 1:4 parent 1:2 prio 1 rate 10Mbit ceil 10Mbit burst *b cburst *b (glob) + class htb 1:5 parent 1:2 prio 2 rate 40Mbit ceil 40Mbit burst *b cburst *b (glob) + + $ R "tc filter show dev $DUT_WAN_INTERFACE" | sort + filter parent 1: protocol all pref 1 fw.* (re) + filter parent 1: protocol all pref 1 fw.*handle 0x4/0x1f classid 1:4 (re) + filter parent 1: protocol all pref 2 fw.* (re) + filter parent 1: protocol all pref 2 fw.*handle 0x5/0x1f classid 1:5 (re) + filter parent 1: protocol all pref 5 fw.* (re) + filter parent 1: protocol all pref 5 fw.*handle 0x1/0x1f classid 1:1 (re) + +Let all upstream (LAN -> WAN) UDP packets to network 192.168.55.0/24 go through queue-home-iptv (highest priority): + + $ cat > /tmp/new-classification < ubus-cli QoS.Classification.+{Alias=subnet1_high_prio,Flags=\"class_basic\"} + > ubus-cli QoS.Classification.subnet1_high_prio.Interface=\"Forward\" + > ubus-cli QoS.Classification.subnet1_high_prio.Protocol=17 + > ubus-cli QoS.Classification.subnet1_high_prio.IPVersion=4 + > ubus-cli QoS.Classification.subnet1_high_prio.DestIP=192.168.55.0 + > ubus-cli QoS.Classification.subnet1_high_prio.DestMask="255.255.255.0" + > ubus-cli QoS.Classification.subnet1_high_prio.TrafficClass=5 + > ubus-cli QoS.Classification.subnet1_high_prio.Enable=1 + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/new-classification)'" > /dev/null + $ sleep 2 + +Check that iptables rule is created in the FORWARD_class chain in the mangle table: + + $ R "iptables -t mangle -L FORWARD_class | grep 'MARK xset'" + MARK udp -- anywhere 192.168.55.0/24 udp MARK xset 0x4/0x1f diff --git a/.gitlab/tests/cram/generic/acceleration-plan-components/050-rest-api.t b/.gitlab/tests/cram/generic/acceleration-plan-components/050-rest-api.t new file mode 100644 index 0000000000..d30f2c8989 --- /dev/null +++ b/.gitlab/tests/cram/generic/acceleration-plan-components/050-rest-api.t @@ -0,0 +1,9 @@ +Check that REST API is working as expected: + + $ curl --silent --max-time 3 --user admin:admin 'http://192.168.1.1:8080/serviceElements/DeviceInfo.FriendlyName' + [{"parameters":{"FriendlyName":"prplHGW"},"path":"DeviceInfo."}] (no-eol) + +Check that REST API is not usable with invalid credentials: + + $ curl --silent --max-time 3 --user admin:failure 'http://192.168.1.1:8080/serviceElements/DeviceInfo.FriendlyName' | grep h1 +

401 Unauthorized

diff --git a/.gitlab/tests/cram/generic/network.t b/.gitlab/tests/cram/generic/network.t new file mode 100644 index 0000000000..1ec72e1f81 --- /dev/null +++ b/.gitlab/tests/cram/generic/network.t @@ -0,0 +1,9 @@ +Check DUT is reachable over LAN: + + $ ping -c3 -W1 192.168.1.2 | grep '3 packets' | cut -d, -f1-3 + 3 packets transmitted, 3 received, 0% packet loss + +Check DUT is reachable over WAN: + + $ ping -c3 -W1 10.0.0.2 | grep '3 packets' | cut -d, -f1-3 + 3 packets transmitted, 3 received, 0% packet loss diff --git a/.gitlab/tests/cram/generic/network_security.t b/.gitlab/tests/cram/generic/network_security.t new file mode 100644 index 0000000000..385d8bd680 --- /dev/null +++ b/.gitlab/tests/cram/generic/network_security.t @@ -0,0 +1,11 @@ +Check that NO port is open from WAN: + + $ nmap --open 10.0.0.2 | grep open + [1] + +Check that only certain ports are open from LAN: + + $ nmap --open 192.168.1.1 | grep open + 22/tcp open ssh + 53/tcp open domain + 8080/tcp open http-proxy diff --git a/.gitlab/tests/cram/generic/ubus-cli.t b/.gitlab/tests/cram/generic/ubus-cli.t new file mode 100644 index 0000000000..6651f8cbbf --- /dev/null +++ b/.gitlab/tests/cram/generic/ubus-cli.t @@ -0,0 +1,12 @@ +Check that we've correct DHCPv4 pools: + + $ script --command "ssh -t root@$TARGET_LAN_IP 'ubus-cli DHCPv4.Server.Pool.*.Alias?'" | grep Alias= | sort + \x1b[32;1mDHCPv4.Server.Pool.1.\x1b[0mAlias="lan"\r (esc) + \x1b[32;1mDHCPv4.Server.Pool.1.Client.1.\x1b[0mAlias="client-??:??:??:??:??:??"\r (esc) (glob) + \x1b[32;1mDHCPv4.Server.Pool.2.\x1b[0mAlias="guest"\r (esc) + +Check that we've correct DHCPv6 pools: + + $ script --command "ssh -t root@$TARGET_LAN_IP 'ubus-cli DHCPv6.Server.Pool.*.Alias?'" | grep Alias= | sort + \x1b[32;1mDHCPv6.Server.Pool.1.\x1b[0mAlias="lan"\r (esc) + \x1b[32;1mDHCPv6.Server.Pool.2.\x1b[0mAlias="guest"\r (esc) diff --git a/.gitlab/tests/cram/generic/ubus.t b/.gitlab/tests/cram/generic/ubus.t new file mode 100644 index 0000000000..b7bd019db0 --- /dev/null +++ b/.gitlab/tests/cram/generic/ubus.t @@ -0,0 +1,202 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check that ubus has all expected services available: + + $ R "ubus list | grep -v '^[[:upper:]]'" + dhcp + dnsmasq + luci-rpc + network + network.device + network.interface + network.interface.guest + network.interface.lan + network.interface.loopback + network.interface.wan + network.interface.wan6 + network.wireless + service + session + system + uci + umdns + +Check that ubus has expected datamodels available: + + $ R "ubus list | grep '[[:upper:]]' | grep -v '\.[[:digit:]]'" + ACLManager + ACLManager.Role + Bridging + Bridging.Bridge + Cthulhu + Cthulhu.Config + Cthulhu.Container + Cthulhu.Container.Instances + Cthulhu.Information + Cthulhu.Sandbox + Cthulhu.Sandbox.Instances + DHCPv4 + DHCPv4.Client + DHCPv4.Server + DHCPv4.Server.Pool + DHCPv6 + DHCPv6.Client + DHCPv6.Server + DHCPv6.Server.Pool + Device + Device.InterfaceStack + DeviceInfo + DeviceInfo.DeviceImageFile + DeviceInfo.FirmwareImage + DeviceInfo.Location + DeviceInfo.MemoryStatus + DeviceInfo.Processor + DeviceInfo.VendorConfigFile + DeviceInfo.VendorLogFile + Ethernet + Ethernet.Interface + Ethernet.Link + Ethernet.VLANTermination + Firewall + Firewall.Chain + Firewall.Level + Firewall.X_Prpl_DMZ + Firewall.X_Prpl_Pinhole + Firewall.X_Prpl_Policy + Firewall.X_Prpl_PortTrigger + Firewall.X_Prpl_Service + IP + IP.ActivePort + IP.Interface + ManagementServer + ManagementServer.ConnRequest + ManagementServer.InternalSettings + ManagementServer.State + ManagementServer.Stats + ManagementServer.Subscription + NAT + NAT.InterfaceSetting + NAT.PortMapping + NetDev + NetDev.ConversionTable + NetDev.ConversionTable.Protocol + NetDev.ConversionTable.Scope + NetDev.ConversionTable.Table + NetDev.Link + NetModel + NetModel.Intf + QoS + QoS.Classification + QoS.Node + QoS.Queue + QoS.QueueStats + QoS.Scheduler + QoS.Shaper + Rlyeh + Rlyeh.Images + Routing + Routing.RIP + Routing.RIP.InterfaceSetting + Routing.RouteInformation + Routing.RouteInformation.InterfaceSetting + Routing.Router + SoftwareModules + SoftwareModules.DeploymentUnit + SoftwareModules.ExecEnv + SoftwareModules.ExecutionUnit + Time + Time.X_PRPL_TimeServer + Time.X_PRPL_TimeServer.Intf + Timingila + Users + Users.Group + Users.Role + Users.SupportedShell + Users.User + X_PRPL-COM_MultiSettings + X_PRPL-COM_MultiSettings.Profile + X_PRPL-COM_PersistentConfiguration + X_PRPL-COM_PersistentConfiguration.Config + X_PRPL-COM_PersistentConfiguration.Config.Security + X_PRPL-COM_PersistentConfiguration.Service + X_PRPL_WANManager + X_PRPL_WANManager.WAN + +Check that we've correct bridge aliases: + + $ R "ubus call Bridging _get \"{'rel_path':'Bridge.*.Alias'}\" | jsonfilter -e @[*].Alias | sort" + guest + lan + +Check that we've correct DHCP pool settings: + + $ R "ubus call DHCPv4.Server.Pool _get \"{'rel_path':'*'}\" | grep -E '(Alias|MinAddres|MaxAddress|Enable|Servers|Status)' | sort" + \t\t"Alias": "guest", (esc) + \t\t"Alias": "lan", (esc) + \t\t"DNSServers": "192.168.1.1", (esc) + \t\t"DNSServers": "192.168.2.1", (esc) + \t\t"Enable": true, (esc) + \t\t"Enable": true, (esc) + \t\t"MaxAddress": "192.168.1.249", (esc) + \t\t"MaxAddress": "192.168.2.249", (esc) + \t\t"MinAddress": "192.168.1.100", (esc) + \t\t"MinAddress": "192.168.2.100", (esc) + \t\t"Status": "Enabled", (esc) + \t\t"Status": "Enabled", (esc) + + $ R "ubus call DHCPv6.Server.Pool _get \"{'rel_path':'*'}\" | grep -E '(Alias|Enable|Status)' | sort" + \t\t"Alias": "guest", (esc) + \t\t"Alias": "lan", (esc) + \t\t"Enable": true, (esc) + \t\t"Enable": true, (esc) + \t\t"IANAEnable": false, (esc) + \t\t"IANAEnable": false, (esc) + \t\t"IAPDEnable": false, (esc) + \t\t"IAPDEnable": false, (esc) + \t\t"Status": "Enabled", (esc) + \t\t"Status": "Enabled", (esc) + +Check that we've correct Time.CurrentLocalTime: + + $ time=$(R "ubus call Time _get '{\"rel_path\":\"CurrentLocalTime\"}' | jsonfilter -e @[*].CurrentLocalTime") + $ time=$(echo $time | sed -E 's/([0-9\-]+)T([0-9]+:[0-9]+:[0-9]+).*/\1 \2/') + $ time=$(date -d "$time" +'%s') + $ sys=$(R date +"%s") + $ diff=$(( (sys - time) )) + $ tolerance=5 + $ R logger -t cram "Time.CurrentLocalTime=$(date -d @$time +'%c') SystemTime=$(date -d @$sys +'%c') diff=${diff}s tolerance=${tolerance}s" + $ test "$diff" -le "$tolerance" && echo "Time is OK" + Time is OK + +Check that aclmanager has expected setup: + + $ R "ubus call ACLManager.Role _get '{\"rel_path\":\"*\"}' | jsonfilter -e @[*].Name -e @[*].Alias | sort" + admin + cpe-Role-1 + cpe-Role-2 + cpe-Role-3 + guest + operator + +Check that Users.Role component has expected setup: + + $ R "ubus call Users.Role _get '{\"rel_path\":\"\"}' | jsonfilter -e @[*].Alias -e @[*].RoleName | sort" + acl + acl-role + admin + admin-role + guest + guest-role + +Check that we've correct hostname and release info: + + $ R "ubus -S call system board | jsonfilter -e '@.hostname' -e '@.release.distribution'" + prplOS + OpenWrt + +Check that netifd service is running: + + $ R "ubus -S call service list | jsonfilter -e '@.network.instances.instance1.running'" + true diff --git a/.gitlab/tests/cram/glinet-b1300/010-network.t b/.gitlab/tests/cram/glinet-b1300/010-network.t new file mode 100644 index 0000000000..d3c88d6fb4 --- /dev/null +++ b/.gitlab/tests/cram/glinet-b1300/010-network.t @@ -0,0 +1,26 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check correct routing table: + + $ R ip route + default via 10.0.0.1 dev eth1 proto static src 10.0.0.2 + 10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.2 + 192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.1 + 192.168.2.0/24 dev br-guest proto kernel scope link src 192.168.2.1 linkdown + +Check correct interface setup: + + $ R "ip link | grep ^\\\\d | cut -d: -f2-" | LC_ALL=C sort + br-guest: mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000 + br-lan: mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 + eth0: mtu 1500 qdisc mq master br-lan state UP mode DEFAULT group default qlen 1000 + eth1: mtu 1500 qdisc htb state UP mode DEFAULT group default qlen 1000 + ifb0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 32 + ifb1: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 32 + lo: mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 + teql0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 100 + veth_gene_0@if2: mtu 1500 qdisc noqueue master br-lan state UP mode DEFAULT group default qlen 1000 + wlan0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 + wlan1: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 diff --git a/.gitlab/tests/cram/glinet-b1300/020-ubus.t b/.gitlab/tests/cram/glinet-b1300/020-ubus.t new file mode 100644 index 0000000000..fc473496ed --- /dev/null +++ b/.gitlab/tests/cram/glinet-b1300/020-ubus.t @@ -0,0 +1,186 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check that we've correct system info: + + $ R "ubus call system board | jsonfilter -e @.system -e @.model -e @.board_name" + ARMv7 Processor rev 5 (v7l) + GL.iNet GL-B1300 + glinet,gl-b1300 + + $ R "ubus call DeviceInfo _get | jsonfilter -e '@[\"DeviceInfo.\"].ProductClass'" + GL.iNet GL-B1300 + +Check that we've correct bridge port aliases: + + $ R "ubus call Bridging _get \"{'rel_path':'Bridge.*.Port.*.Alias'}\" | jsonfilter -e @[*].Alias | sort" + ETH0 + GUEST + bridge + default_radio0 + default_radio1 + guest_radio0 + guest_radio1 + +Check that we've correct ethernet interface details: + + $ R "ubus call Ethernet _get \"{'rel_path':'Interface.'}\" | grep -E '(Alias|Enable|Name)' | sort" + \t\t"Alias": "ETH0", (esc) + \t\t"Alias": "ETH1", (esc) + \t\t"EEEEnable": false, (esc) + \t\t"EEEEnable": false, (esc) + \t\t"Enable": true, (esc) + \t\t"Enable": true, (esc) + \t\t"Name": "eth0", (esc) + \t\t"Name": "eth1", (esc) + +Check that we've correct ethernet link details: + + $ R "ubus call Ethernet _get \"{'rel_path':'Link.'}\" | grep -E '(Alias|Enable|Name)' | sort" + \t\t"Alias": "ETH1", (esc) + \t\t"Alias": "GUEST", (esc) + \t\t"Alias": "LAN", (esc) + \t\t"Alias": "LO", (esc) + \t\t"Enable": true, (esc) + \t\t"Enable": true, (esc) + \t\t"Enable": true, (esc) + \t\t"Enable": true, (esc) + \t\t"Name": "br-guest", (esc) + \t\t"Name": "br-lan", (esc) + \t\t"Name": "eth1", (esc) + \t\t"Name": "lo", (esc) + +Check that IP.Interface provides expected output: + + $ R "ubus call IP _get '{\"rel_path\":\"Interface.\",\"depth\":100}' | jsonfilter -e @[*].Alias -e @[*].Name -e @[*].IPAddress -e @[*].SubnetMask | sort" | egrep -v '(^f[0-9a-z:]+|^$)' + 10.0.0.2 + 127.0.0.1 + 192.168.1.1 + 192.168.2.1 + 255.0.0.0 + 255.255.255.0 + 255.255.255.0 + 255.255.255.0 + ::1 + GUA + GUA + GUA_IAPD + GUA_IAPD + GUA_RA + GUA_RA + ULA + ULA64 + br-guest + br-lan + eth1 + guest + guest + lan + lan + lo + loopback + loopback_ipv4 + loopbackipv6 + wan + wan + +Check that NAT.Interface provides expected output: + + $ R "ubus call NAT _get '{\"rel_path\":\"InterfaceSetting.\",\"depth\":100}' | jsonfilter -e @[*].Alias -e @[*].Interface" + lan + guest + wan + br-lan + br-guest + eth1 + +Check that NetDev.Link provides expected output: + + $ R "ubus call NetDev _get '{\"rel_path\":\"Link.\",\"depth\":100}' | jsonfilter -e @[*].Name | sort" + br-guest + br-lan + eth0 + eth1 + ifb0 + ifb1 + lo + teql0 + veth_gene_0 + wlan0 + wlan1 + +Check that NetModel.Intf provides expected output: + + $ R "ubus call NetModel _get '{\"rel_path\":\"Intf.\",\"depth\":100}' | jsonfilter -e @[*].Alias -e @[*].Flags -e @[*].Name -e @[*].Status | sed '/^$/d' | sort" + bridge + bridge + bridge-GUEST + bridge-GUEST + bridge-bridge + bridge-bridge + bridgeport-ETH0 + bridgeport-ETH0 + bridgeport-default_radio0 + bridgeport-default_radio0 + bridgeport-default_radio1 + bridgeport-default_radio1 + bridgeport-guest_radio0 + bridgeport-guest_radio0 + bridgeport-guest_radio1 + bridgeport-guest_radio1 + ethIntf-ETH0 + ethIntf-ETH0 + ethIntf-ETH1 + ethIntf-ETH1 + ethLink-ETH1 + ethLink-ETH1 + ethLink-GUEST + ethLink-GUEST + ethLink-LAN + ethLink-LAN + ethLink-LO + ethLink-LO + eth_intf netdev + eth_intf netdev + eth_link + eth_link + eth_link + eth_link + false + false + false + false + false + false + false + false + false + false + false + false + false + false + false + false + false + false + inbridge + inbridge + inbridge + inbridge + inbridge + ip netdev + ip netdev + ip netdev + ip netdev dhcpv[46] dhcpv[46] (re) + ip-guest + ip-guest + ip-lan + ip-lan + ip-loopback + ip-loopback + ip-wan + ip-wan + resolver + resolver diff --git a/.gitlab/tests/cram/glinet-b1300/021-ubus-cli.t b/.gitlab/tests/cram/glinet-b1300/021-ubus-cli.t new file mode 100644 index 0000000000..bf72d28a8c --- /dev/null +++ b/.gitlab/tests/cram/glinet-b1300/021-ubus-cli.t @@ -0,0 +1,4 @@ +Check that we've correct system info: + + $ script --command "ssh -t root@$TARGET_LAN_IP 'ubus-cli DeviceInfo.?'" | grep ProductClass + \x1b[32;1mDeviceInfo.\x1b[0mProductClass="GL.iNet GL-B1300"\r (esc) diff --git a/.gitlab/tests/cram/glinet-b1300/030-wifi.t b/.gitlab/tests/cram/glinet-b1300/030-wifi.t new file mode 100644 index 0000000000..35975a1b7d --- /dev/null +++ b/.gitlab/tests/cram/glinet-b1300/030-wifi.t @@ -0,0 +1,9 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check for correct SSID setup: + + $ R "iwinfo | grep ESSID" + wlan0 ESSID: unknown + wlan1 ESSID: unknown diff --git a/.gitlab/tests/cram/glinet-b1300/100-prplmesh.t b/.gitlab/tests/cram/glinet-b1300/100-prplmesh.t new file mode 100644 index 0000000000..205979f50d --- /dev/null +++ b/.gitlab/tests/cram/glinet-b1300/100-prplmesh.t @@ -0,0 +1,73 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Start wireless: + + $ R logger -t cram "Start wireless" + $ R "uci set wireless.radio0.disabled='0'; uci set wireless.radio1.disabled='0'; uci commit; wifi up" + $ sleep 30 + +Check that hostapd is operating after reboot: + + $ R logger -t cram "Check that hostapd is operating after reboot" + $ R "ps w" | sed -nE 's/.*(\/usr\/sbin\/hostapd.*)/\1/p' | LC_ALL=C sort + /usr/sbin/hostapd -s -P /var/run/wifi-phy0.pid -B /var/run/hostapd-phy0.conf + /usr/sbin/hostapd -s -P /var/run/wifi-phy1.pid -B /var/run/hostapd-phy1.conf + +Restart prplmesh: + + $ R logger -t cram "Restart prplmesh" + $ R "/etc/init.d/prplmesh gateway_mode && sleep 5" > /dev/null 2>&1 + $ sleep 60 + +Check VAP setup after restart: + + $ R logger -t cram "Check VAP setup after restart" + $ R "iwinfo | grep ESSID" + wlan0 ESSID: "prplOS" + wlan0-1 ESSID: "prplOS-guest" + wlan1 ESSID: "prplOS" + wlan1-1 ESSID: "prplOS-guest" + +Check that prplmesh processes are running: + + $ R logger -t cram "Check that prplmesh processes are running" + $ R "ps w" | sed -nE 's/.*(\/opt\/prplmesh\/bin.*)/\1/p' | LC_ALL=C sort + /opt/prplmesh/bin/beerocks_agent + /opt/prplmesh/bin/beerocks_controller + /opt/prplmesh/bin/beerocks_fronthaul -i wlan0 + /opt/prplmesh/bin/beerocks_fronthaul -i wlan1 + /opt/prplmesh/bin/ieee1905_transport + +Check that prplmesh is operational: + + $ R logger -t cram "Check that prplmesh is operational" + $ R "/opt/prplmesh/scripts/prplmesh_utils.sh status" | sed -E 's/.*(\/opt\/prplmesh.*)/\1/' | LC_ALL=C sort + \x1b[0m (esc) + \x1b[0m\x1b[1;32mOK Main radio agent operational (esc) + \x1b[1;32moperational test success! (esc) + /opt/prplmesh/bin/beerocks_agent + /opt/prplmesh/bin/beerocks_controller + /opt/prplmesh/bin/beerocks_controller + /opt/prplmesh/bin/beerocks_fronthaul + /opt/prplmesh/bin/beerocks_fronthaul + /opt/prplmesh/bin/ieee1905_transport + /opt/prplmesh/scripts/prplmesh_utils.sh: status + OK wlan0 radio agent operational + OK wlan1 radio agent operational + executing operational test using bml + +Check that prplmesh is in operational state: + + $ R logger -t cram "Check that prplmesh is in operational state" + $ R "/opt/prplmesh/bin/beerocks_cli -c bml_conn_map" | egrep '(wlan|OK)' | sed -E "s/.*: (wlan[0-9.]+) .*/\1/" | LC_ALL=C sort + bml_connect: return value is: BML_RET_OK, Success status + bml_disconnect: return value is: BML_RET_OK, Success status + bml_nw_map_query: return value is: BML_RET_OK, Success status + wlan0 + wlan0.0 + wlan0.1 + wlan1 + wlan1.0 + wlan1.1 diff --git a/.gitlab/tests/cram/glinet-b1300/acceleration-plan-components/010-firewall-dmz.t b/.gitlab/tests/cram/glinet-b1300/acceleration-plan-components/010-firewall-dmz.t new file mode 100644 index 0000000000..b8e5327aae --- /dev/null +++ b/.gitlab/tests/cram/glinet-b1300/acceleration-plan-components/010-firewall-dmz.t @@ -0,0 +1,35 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Add DMZ host: + + $ printf "\ + > ubus-cli Firewall.X_Prpl_DMZ+{Alias='test'} + > ubus-cli Firewall.X_Prpl_DMZ.test.SourceInterface=eth1 + > ubus-cli Firewall.X_Prpl_DMZ.test.DestinationIPAddress=192.168.1.186 + > ubus-cli Firewall.X_Prpl_DMZ.test.Enable=1 + > " > /tmp/cram + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/cram)'" > /dev/null; sleep 1 + +Check that correct firewall rules were created: + + $ R "iptables -t nat -L POSTROUTING_DMZ | grep 186 | sort" + SNAT all -- prplOS.lan 192.168.1.186 to:10.0.0.2 + + $ R "iptables -t nat -L PREROUTING_DMZ | grep 186 | sort" + DNAT all -- anywhere 10.0.0.2 to:192.168.1.186 + + $ R "iptables -L FORWARD_DMZ | grep 186 | sort" + ACCEPT all -- 192.168.1.186 anywhere + ACCEPT all -- anywhere 192.168.1.186 + +Remove DMZ host: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.X_Prpl_DMZ.test-" > /dev/null; sleep 1 + +Check that firewall rules are gone: + + $ R "iptables -t nat -L POSTROUTING_DMZ | grep 186 | sort" + $ R "iptables -t nat -L PREROUTING_DMZ | grep 186 | sort" + $ R "iptables -L FORWARD_DMZ | grep 186 | sort" diff --git a/.gitlab/tests/cram/glinet-b1300/acceleration-plan-components/020-bridging-guest.t b/.gitlab/tests/cram/glinet-b1300/acceleration-plan-components/020-bridging-guest.t new file mode 100644 index 0000000000..3540267aa8 --- /dev/null +++ b/.gitlab/tests/cram/glinet-b1300/acceleration-plan-components/020-bridging-guest.t @@ -0,0 +1,41 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Get initial state of bridges: + + $ R "brctl show | sort | cut -d$'\t' -f1,4-" + br-guest\tno (esc) + br-lan\tno\t\teth0 (esc) + bridge name\tSTP enabled\tinterfaces (esc) + +Add eth1 to the Guest bridge: + + $ printf ' \ + > ubus-cli Bridging.Bridge.guest.Port.+{Name="eth1", Alias="ETH1"}\n + > ubus-cli Bridging.Bridge.guest.Port.ETH1.Enable=1\n + > ' > /tmp/run + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run)'" > /dev/null + $ sleep 5 + +Check that eth1 is added to br-guest bridge: + + $ R "brctl show | sort | cut -d$'\t' -f1,4-" + br-guest\tno\t\teth1 (esc) + br-lan\tno\t\teth0 (esc) + bridge name\tSTP enabled\tinterfaces (esc) + +Remove eth1 from the Guest bridge: + + $ printf '\ + > ubus-cli Bridging.Bridge.guest.Port.ETH1-\n + > ' > /tmp/run + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run)'" > /dev/null + $ sleep 5 + +Check for initial state of bridges again: + + $ R "brctl show | sort | cut -d$'\t' -f1,4-" + br-guest\tno (esc) + br-lan\tno\t\teth0 (esc) + bridge name\tSTP enabled\tinterfaces (esc) diff --git a/.gitlab/tests/cram/glinet-b1300/acceleration-plan-components/030-lcm.t b/.gitlab/tests/cram/glinet-b1300/acceleration-plan-components/030-lcm.t new file mode 100644 index 0000000000..3ce8a92b56 --- /dev/null +++ b/.gitlab/tests/cram/glinet-b1300/acceleration-plan-components/030-lcm.t @@ -0,0 +1,96 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check that Sandbox is not configured properly: + + $ R "ubus -S call Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1 _get" + [4] + + $ R "ubus -S call Cthulhu.Config _get | jsonfilter -e @[*].DhcpCommand" + + +Configure Sandbox: + + $ cat > /tmp/run-sandbox < ubus-cli Cthulhu.Config.DhcpCommand=\"udhcpc -r 192.168.1.200 -i\" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Type="Veth" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.+ + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.Bridge="br-lan" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.Interface="eth0" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.EnableDhcp=1 + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Enable=1 + > ubus-cli "Cthulhu.Sandbox.start(SandboxId=\"generic\")" + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run-sandbox)'" > /dev/null + $ sleep 10 + +Check that Sandbox was configured properly: + + $ R "ubus -S call Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1 _get" + {"Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.":{"EnableDhcp":true,"Interface":"eth0","Bridge":"br-lan"}} + + $ R "ubus -S call Cthulhu.Config _get | jsonfilter -e @[*].DhcpCommand" + udhcpc -r 192.168.1.200 -i + +Install testing prplOS container v1: + + $ cat > /tmp/run-container < ubus-cli "SoftwareModules.InstallDU(URL=\"docker://registry.gitlab.com/prpl-foundation/prplos/prplos/prplos-testing-container-ipq40xx-generic:v1\", UUID=\"prplos-testing\", ExecutionEnvRef=\"generic\")" + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run-container)'" > /dev/null + +Check that prplOS container v1 is running: + + $ sleep 30 + + $ R "ubus -S call Cthulhu.Container.Instances.1 _get | jsonfilter -e @[*].Status -e @[*].Bundle -e @[*].BundleVersion -e @[*].ContainerId -e @[*].Alias | sort" + Running + cpe-prplos-testing + prplos-testing + prplos/prplos-testing-container-ipq40xx-generic + v1 + + $ R "ssh -y root@192.168.1.200 'cat /etc/container-version' 2> /dev/null" + 1 + +Update to prplOS container v2: + + $ cat > /tmp/run-container < ubus-cli "SoftwareModules.DeploymentUnit.cpe-prplos-testing.Update(URL=\"docker://registry.gitlab.com/prpl-foundation/prplos/prplos/prplos-testing-container-ipq40xx-generic:v2\")" + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run-container)'" > /dev/null + +Check that prplOS container v2 is running: + + $ sleep 30 + + $ R "ubus -S call Cthulhu.Container.Instances.2 _get | jsonfilter -e @[*].Status -e @[*].Bundle -e @[*].BundleVersion -e @[*].ContainerId -e @[*].Alias | sort" + Running + cpe-prplos-testing + prplos-testing + prplos/prplos-testing-container-ipq40xx-generic + v2 + + $ R "ssh -y root@192.168.1.200 'cat /etc/container-version' 2> /dev/null" + 2 + +Uninstall prplOS testing container: + + $ script --command "ssh -t root@$TARGET_LAN_IP 'ubus-cli SoftwareModules.DeploymentUnit.cpe-prplos-testing.Uninstall\(\)'" > /dev/null; sleep 5 + +Check that prplOS container is not running: + + $ R "ubus -S call Cthulhu.Container.Instances.2 _get" + [4] + +Check that Rlyeh has no container images: + + $ R "ubus -S call Rlyeh.Images _get" + {"Rlyeh.Images.":{}} + +Check that container image is gone from the filesystem as well: + + $ R "ls -al /usr/share/rlyeh/images/prplos" + ls: /usr/share/rlyeh/images/prplos: No such file or directory + [1] diff --git a/.gitlab/tests/cram/nec-wx3000hp/010-network.t b/.gitlab/tests/cram/nec-wx3000hp/010-network.t new file mode 100644 index 0000000000..48eb052876 --- /dev/null +++ b/.gitlab/tests/cram/nec-wx3000hp/010-network.t @@ -0,0 +1,30 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check correct routing table: + + $ R ip route + default via 10.0.0.1 dev eth1 proto static src 10.0.0.2 + 10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.2 + 192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.1 + 192.168.2.0/24 dev br-guest proto kernel scope link src 192.168.2.1 linkdown + +Check correct interface setup: + + $ R "ip link" | awk '/^[0-9]+:/ { printf $0; next } { print ";"$2 }' | awk '/lo:/{print} !/00:00:00:00:00:00/{print}' | cut -d\; -f1 | cut -d: -f2- | LC_ALL=C sort + br-guest: mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000 + br-lan: mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 + eth0_0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 + eth0_1: mtu 1500 qdisc pfifo_fast master br-lan state DOWN mode DEFAULT group default qlen 1000 + eth0_2: mtu 1500 qdisc pfifo_fast master br-lan state DOWN mode DEFAULT group default qlen 1000 + eth0_3: mtu 1500 qdisc pfifo_fast master br-lan state DOWN mode DEFAULT group default qlen 1000 + eth0_4: mtu 1500 qdisc pfifo_fast master br-lan state UP mode DEFAULT group default qlen 1000 + eth1: mtu 1500 qdisc htb state UNKNOWN mode DEFAULT group default qlen 1000 + ifb0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 32 + ifb1: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 32 + lite0: mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000 + lo: mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1 + loopdev0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 + teql0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 100 + veth_gene_0@if2: mtu 1500 qdisc noqueue master br-lan state UP mode DEFAULT group default qlen 1000 diff --git a/.gitlab/tests/cram/nec-wx3000hp/020-ubus.t b/.gitlab/tests/cram/nec-wx3000hp/020-ubus.t new file mode 100644 index 0000000000..0f8d8adee5 --- /dev/null +++ b/.gitlab/tests/cram/nec-wx3000hp/020-ubus.t @@ -0,0 +1,10 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check that we've correct system info: + + $ R "ubus call system board | jsonfilter -e @.system -e @.model -e @.board_name" + GRX500 rev 1.2 + EASY350 ANYWAN (GRX350) Axepoint Asurada model + EASY350 ANYWAN (GRX350) Axepoint Asurada model diff --git a/.gitlab/tests/cram/nec-wx3000hp/030-wifi.t b/.gitlab/tests/cram/nec-wx3000hp/030-wifi.t new file mode 100644 index 0000000000..f623605582 --- /dev/null +++ b/.gitlab/tests/cram/nec-wx3000hp/030-wifi.t @@ -0,0 +1,8 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check for correct SSID setup: + + $ R "iwinfo" | awk '/wlan[0-9.]+/{printf("%s %s ",$1,$3)};/Point:/{print $3}' | grep -v 00:00:00:00:00:00 + [1] diff --git a/.gitlab/tests/cram/nec-wx3000hp/100-prplmesh.t b/.gitlab/tests/cram/nec-wx3000hp/100-prplmesh.t new file mode 100644 index 0000000000..213edc9c76 --- /dev/null +++ b/.gitlab/tests/cram/nec-wx3000hp/100-prplmesh.t @@ -0,0 +1,76 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Start wireless: + + $ R logger -t cram "Start wireless" + $ R "uci set wireless.radio0.disabled='0'; uci set wireless.radio2.disabled='0'; uci commit; wifi up" + $ sleep 120 + +Check that hostapd & supplicant proccess are up after wireless startup: + + $ R logger -t cram "Check that hostapd \& supplicant proccess are up after wireless startup" + + $ R "ps w" | sed -nE 's/.*(\/usr\/sbin\/hostapd.*)/\1/p' | LC_ALL=C sort + /usr/sbin/hostapd -s -g /var/run/hostapd/global-hostapd -P /var/run/wifi-global-hostapd.pid -B /var/run/h + +Restart prplmesh: + + $ R logger -t cram "Restart prplmesh" + $ R "/etc/init.d/prplmesh gateway_mode > /dev/null 2>&1 && sleep 120" + +Check VAP setup: + + $ R logger -t cram "Check VAP setup" + + $ R "iwinfo | grep ESSID" + wlan0 ESSID: "dummy_ssid_0" + wlan0.0 ESSID: "prplOS" + wlan0.1 ESSID: "prplOS-guest" + wlan2 ESSID: "dummy_ssid_2" + wlan2.0 ESSID: "prplOS" + wlan2.1 ESSID: "prplOS-guest" + +Check that prplmesh processes are running: + + $ R logger -t cram "Check that prplmesh processes are running" + + $ R "ps w" | sed -nE 's/.*(\/opt\/prplmesh\/bin.*)/\1/p' | LC_ALL=C sort + /opt/prplmesh/bin/beerocks_agent + /opt/prplmesh/bin/beerocks_controller + /opt/prplmesh/bin/beerocks_fronthaul -i wlan0 + /opt/prplmesh/bin/beerocks_fronthaul -i wlan2 + /opt/prplmesh/bin/ieee1905_transport + +Check that prplmesh is operational: + + $ R logger -t cram "Check that prplmesh is operational" + $ R "/opt/prplmesh/scripts/prplmesh_utils.sh status" | sed -E 's/.*(\/opt\/prplmesh.*)/\1/' | LC_ALL=C sort + \x1b[0m (esc) + \x1b[0m\x1b[1;32mOK Main radio agent operational (esc) + \x1b[1;32moperational test success! (esc) + /opt/prplmesh/bin/beerocks_agent + /opt/prplmesh/bin/beerocks_controller + /opt/prplmesh/bin/beerocks_controller + /opt/prplmesh/bin/beerocks_fronthaul + /opt/prplmesh/bin/beerocks_fronthaul + /opt/prplmesh/bin/ieee1905_transport + /opt/prplmesh/scripts/prplmesh_utils.sh: status + OK wlan0 radio agent operational + OK wlan2 radio agent operational + executing operational test using bml + +Check that prplmesh is in operational state: + + $ R logger -t cram "Check that prplmesh is in operational state" + $ R "/opt/prplmesh/bin/beerocks_cli -c bml_conn_map" | egrep '(wlan|OK)' | sed -E "s/.*: (wlan[0-9.]+) .*/\1/" | LC_ALL=C sort + bml_connect: return value is: BML_RET_OK, Success status + bml_disconnect: return value is: BML_RET_OK, Success status + bml_nw_map_query: return value is: BML_RET_OK, Success status + wlan0 + wlan0.0 + wlan0.1 + wlan2 + wlan2.0 + wlan2.1 diff --git a/.gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/010-firewall-dmz.t b/.gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/010-firewall-dmz.t new file mode 100644 index 0000000000..b8e5327aae --- /dev/null +++ b/.gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/010-firewall-dmz.t @@ -0,0 +1,35 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Add DMZ host: + + $ printf "\ + > ubus-cli Firewall.X_Prpl_DMZ+{Alias='test'} + > ubus-cli Firewall.X_Prpl_DMZ.test.SourceInterface=eth1 + > ubus-cli Firewall.X_Prpl_DMZ.test.DestinationIPAddress=192.168.1.186 + > ubus-cli Firewall.X_Prpl_DMZ.test.Enable=1 + > " > /tmp/cram + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/cram)'" > /dev/null; sleep 1 + +Check that correct firewall rules were created: + + $ R "iptables -t nat -L POSTROUTING_DMZ | grep 186 | sort" + SNAT all -- prplOS.lan 192.168.1.186 to:10.0.0.2 + + $ R "iptables -t nat -L PREROUTING_DMZ | grep 186 | sort" + DNAT all -- anywhere 10.0.0.2 to:192.168.1.186 + + $ R "iptables -L FORWARD_DMZ | grep 186 | sort" + ACCEPT all -- 192.168.1.186 anywhere + ACCEPT all -- anywhere 192.168.1.186 + +Remove DMZ host: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.X_Prpl_DMZ.test-" > /dev/null; sleep 1 + +Check that firewall rules are gone: + + $ R "iptables -t nat -L POSTROUTING_DMZ | grep 186 | sort" + $ R "iptables -t nat -L PREROUTING_DMZ | grep 186 | sort" + $ R "iptables -L FORWARD_DMZ | grep 186 | sort" diff --git a/.gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/020-bridging-guest.t b/.gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/020-bridging-guest.t new file mode 100644 index 0000000000..30c4eb79ab --- /dev/null +++ b/.gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/020-bridging-guest.t @@ -0,0 +1,52 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Get initial state of bridges: + + $ R "brctl show | cut -d$'\t' -f1,4-" + bridge name\tSTP enabled\tinterfaces (esc) + br-guest\tno\t\t (esc) + br-lan\tno\t\teth0_1 (esc) + \t\t\t\t\teth0_2 (esc) + \t\t\t\t\teth0_3 (esc) + \t\t\t\t\teth0_4 (esc) + +Remove eth0_1 from LAN bridge and add it to the Guest bridge: + + $ printf ' \ + > ubus-cli Bridging.Bridge.lan.Port.ETH0_1-\n + > ubus-cli Bridging.Bridge.guest.Port.+{Name="eth0_1", Alias="ETH0_1"}\n + > ubus-cli Bridging.Bridge.guest.Port.ETH0_1.Enable=1\n + > ' > /tmp/run + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run)'" > /dev/null + $ sleep 10 + +Check that eth0_1 is added to Guest bridge: + + $ R "brctl show | cut -d$'\t' -f1,4-" + bridge name\tSTP enabled\tinterfaces (esc) + br-guest\tno\t\teth0_1 (esc) + br-lan\tno\t\teth0_2 (esc) + \t\t\t\t\teth0_3 (esc) + \t\t\t\t\teth0_4 (esc) + +Remove eth0_1 from the Guest bridge and add it back to the LAN bridge: + + $ printf '\ + > ubus-cli Bridging.Bridge.guest.Port.ETH0_1-\n + > ubus-cli Bridging.Bridge.lan.Port.+{Name="eth0_1", Alias="ETH0_1"}\n + > ubus-cli Bridging.Bridge.lan.Port.ETH0_1.Enable=1\n + > ' > /tmp/run + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run)'" > /dev/null + $ sleep 10 + +Check for initial state of bridges again: + + $ R "brctl show | cut -d$'\t' -f1,4-" + bridge name\tSTP enabled\tinterfaces (esc) + br-guest\tno\t\t (esc) + br-lan\tno\t\teth0_1 (esc) + \t\t\t\t\teth0_2 (esc) + \t\t\t\t\teth0_3 (esc) + \t\t\t\t\teth0_4 (esc) diff --git a/.gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/030-lcm.t b/.gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/030-lcm.t new file mode 100644 index 0000000000..f833112719 --- /dev/null +++ b/.gitlab/tests/cram/nec-wx3000hp/acceleration-plan-components/030-lcm.t @@ -0,0 +1,96 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check that Sandbox is not configured properly: + + $ R "ubus -S call Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1 _get" + [4] + + $ R "ubus -S call Cthulhu.Config _get | jsonfilter -e @[*].DhcpCommand" + + +Configure Sandbox: + + $ cat > /tmp/run-sandbox < ubus-cli Cthulhu.Config.DhcpCommand=\"udhcpc -r 192.168.1.200 -i\" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Type="Veth" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.+ + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.Bridge="br-lan" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.Interface="eth0" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.EnableDhcp=1 + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Enable=1 + > ubus-cli "Cthulhu.Sandbox.start(SandboxId=\"generic\")" + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run-sandbox)'" > /dev/null + $ sleep 10 + +Check that Sandbox was configured properly: + + $ R "ubus -S call Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1 _get" + {"Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.":{"EnableDhcp":true,"Interface":"eth0","Bridge":"br-lan"}} + + $ R "ubus -S call Cthulhu.Config _get | jsonfilter -e @[*].DhcpCommand" + udhcpc -r 192.168.1.200 -i + +Install testing prplOS container v1: + + $ cat > /tmp/run-container < ubus-cli "SoftwareModules.InstallDU(URL=\"docker://registry.gitlab.com/prpl-foundation/prplos/prplos/prplos-testing-container-intel_mips-xrx500:v1\", UUID=\"prplos-testing\", ExecutionEnvRef=\"generic\")" + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run-container)'" > /dev/null + +Check that prplOS container v1 is running: + + $ sleep 50 + + $ R "ubus -S call Cthulhu.Container.Instances.1 _get | jsonfilter -e @[*].Status -e @[*].Bundle -e @[*].BundleVersion -e @[*].ContainerId -e @[*].Alias | sort" + Running + cpe-prplos-testing + prplos-testing + prplos/prplos-testing-container-intel_mips-xrx500 + v1 + + $ R "ssh -y root@192.168.1.200 'cat /etc/container-version' 2> /dev/null" + 1 + +Update to prplOS container v2: + + $ cat > /tmp/run-container < ubus-cli "SoftwareModules.DeploymentUnit.cpe-prplos-testing.Update(URL=\"docker://registry.gitlab.com/prpl-foundation/prplos/prplos/prplos-testing-container-intel_mips-xrx500:v2\")" + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run-container)'" > /dev/null + +Check that prplOS container v2 is running: + + $ sleep 40 + + $ R "ubus -S call Cthulhu.Container.Instances.2 _get | jsonfilter -e @[*].Status -e @[*].Bundle -e @[*].BundleVersion -e @[*].ContainerId -e @[*].Alias | sort" + Running + cpe-prplos-testing + prplos-testing + prplos/prplos-testing-container-intel_mips-xrx500 + v2 + + $ R "ssh -y root@192.168.1.200 'cat /etc/container-version' 2> /dev/null" + 2 + +Uninstall prplOS testing container: + + $ script --command "ssh -t root@$TARGET_LAN_IP 'ubus-cli SoftwareModules.DeploymentUnit.cpe-prplos-testing.Uninstall\(\)'" > /dev/null; sleep 5 + +Check that prplOS container is not running: + + $ R "ubus -S call Cthulhu.Container.Instances.2 _get" + [4] + +Check that Rlyeh has no container images: + + $ R "ubus -S call Rlyeh.Images _get" + {"Rlyeh.Images.":{}} + +Check that container image is gone from the filesystem as well: + + $ R "ls -al /usr/share/rlyeh/images/prplos" + ls: /usr/share/rlyeh/images/prplos: No such file or directory + [1] diff --git a/.gitlab/tests/cram/turris-omnia/010-network.t b/.gitlab/tests/cram/turris-omnia/010-network.t new file mode 100644 index 0000000000..5918e047a0 --- /dev/null +++ b/.gitlab/tests/cram/turris-omnia/010-network.t @@ -0,0 +1,32 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check correct routing table: + + $ R ip route + default via 10.0.0.1 dev eth2 proto static src 10.0.0.2 + 10.0.0.0/24 dev eth2 proto kernel scope link src 10.0.0.2 + 192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.1 + 192.168.2.0/24 dev br-guest proto kernel scope link src 192.168.2.1 linkdown + +Check correct interface setup: + + $ R "ip link | grep ^\\\\d | cut -d: -f2-" | LC_ALL=C sort + br-guest: mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000 + br-lan: mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 + eth0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 532 + eth1: mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 532 + eth2: mtu 1500 qdisc htb state UP mode DEFAULT group default qlen 532 + ifb0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 32 + ifb1: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 32 + lan0@eth1: mtu 1500 qdisc noqueue master br-lan state LOWERLAYERDOWN mode DEFAULT group default qlen 1000 + lan1@eth1: mtu 1500 qdisc noqueue master br-lan state LOWERLAYERDOWN mode DEFAULT group default qlen 1000 + lan2@eth1: mtu 1500 qdisc noqueue master br-lan state LOWERLAYERDOWN mode DEFAULT group default qlen 1000 + lan3@eth1: mtu 1500 qdisc noqueue master br-lan state UP mode DEFAULT group default qlen 1000 + lan4@eth1: mtu 1500 qdisc noqueue master br-lan state LOWERLAYERDOWN mode DEFAULT group default qlen 1000 + lo: mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 + teql0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 100 + veth_gene_0@if2: mtu 1500 qdisc noqueue master br-lan state UP mode DEFAULT group default qlen 1000 + wlan0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 + wlan1: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 diff --git a/.gitlab/tests/cram/turris-omnia/020-ubus.t b/.gitlab/tests/cram/turris-omnia/020-ubus.t new file mode 100644 index 0000000000..fd975d4d75 --- /dev/null +++ b/.gitlab/tests/cram/turris-omnia/020-ubus.t @@ -0,0 +1,10 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check that we've correct system info: + + $ R "ubus call system board | jsonfilter -e @.system -e @.model -e @.board_name" + ARMv7 Processor rev 1 (v7l) + Turris Omnia + cznic,turris-omnia diff --git a/.gitlab/tests/cram/turris-omnia/030-wifi.t b/.gitlab/tests/cram/turris-omnia/030-wifi.t new file mode 100644 index 0000000000..35975a1b7d --- /dev/null +++ b/.gitlab/tests/cram/turris-omnia/030-wifi.t @@ -0,0 +1,9 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check for correct SSID setup: + + $ R "iwinfo | grep ESSID" + wlan0 ESSID: unknown + wlan1 ESSID: unknown diff --git a/.gitlab/tests/cram/turris-omnia/100-prplmesh.t b/.gitlab/tests/cram/turris-omnia/100-prplmesh.t new file mode 100644 index 0000000000..205979f50d --- /dev/null +++ b/.gitlab/tests/cram/turris-omnia/100-prplmesh.t @@ -0,0 +1,73 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Start wireless: + + $ R logger -t cram "Start wireless" + $ R "uci set wireless.radio0.disabled='0'; uci set wireless.radio1.disabled='0'; uci commit; wifi up" + $ sleep 30 + +Check that hostapd is operating after reboot: + + $ R logger -t cram "Check that hostapd is operating after reboot" + $ R "ps w" | sed -nE 's/.*(\/usr\/sbin\/hostapd.*)/\1/p' | LC_ALL=C sort + /usr/sbin/hostapd -s -P /var/run/wifi-phy0.pid -B /var/run/hostapd-phy0.conf + /usr/sbin/hostapd -s -P /var/run/wifi-phy1.pid -B /var/run/hostapd-phy1.conf + +Restart prplmesh: + + $ R logger -t cram "Restart prplmesh" + $ R "/etc/init.d/prplmesh gateway_mode && sleep 5" > /dev/null 2>&1 + $ sleep 60 + +Check VAP setup after restart: + + $ R logger -t cram "Check VAP setup after restart" + $ R "iwinfo | grep ESSID" + wlan0 ESSID: "prplOS" + wlan0-1 ESSID: "prplOS-guest" + wlan1 ESSID: "prplOS" + wlan1-1 ESSID: "prplOS-guest" + +Check that prplmesh processes are running: + + $ R logger -t cram "Check that prplmesh processes are running" + $ R "ps w" | sed -nE 's/.*(\/opt\/prplmesh\/bin.*)/\1/p' | LC_ALL=C sort + /opt/prplmesh/bin/beerocks_agent + /opt/prplmesh/bin/beerocks_controller + /opt/prplmesh/bin/beerocks_fronthaul -i wlan0 + /opt/prplmesh/bin/beerocks_fronthaul -i wlan1 + /opt/prplmesh/bin/ieee1905_transport + +Check that prplmesh is operational: + + $ R logger -t cram "Check that prplmesh is operational" + $ R "/opt/prplmesh/scripts/prplmesh_utils.sh status" | sed -E 's/.*(\/opt\/prplmesh.*)/\1/' | LC_ALL=C sort + \x1b[0m (esc) + \x1b[0m\x1b[1;32mOK Main radio agent operational (esc) + \x1b[1;32moperational test success! (esc) + /opt/prplmesh/bin/beerocks_agent + /opt/prplmesh/bin/beerocks_controller + /opt/prplmesh/bin/beerocks_controller + /opt/prplmesh/bin/beerocks_fronthaul + /opt/prplmesh/bin/beerocks_fronthaul + /opt/prplmesh/bin/ieee1905_transport + /opt/prplmesh/scripts/prplmesh_utils.sh: status + OK wlan0 radio agent operational + OK wlan1 radio agent operational + executing operational test using bml + +Check that prplmesh is in operational state: + + $ R logger -t cram "Check that prplmesh is in operational state" + $ R "/opt/prplmesh/bin/beerocks_cli -c bml_conn_map" | egrep '(wlan|OK)' | sed -E "s/.*: (wlan[0-9.]+) .*/\1/" | LC_ALL=C sort + bml_connect: return value is: BML_RET_OK, Success status + bml_disconnect: return value is: BML_RET_OK, Success status + bml_nw_map_query: return value is: BML_RET_OK, Success status + wlan0 + wlan0.0 + wlan0.1 + wlan1 + wlan1.0 + wlan1.1 diff --git a/.gitlab/tests/cram/turris-omnia/acceleration-plan-components/010-firewall-dmz.t b/.gitlab/tests/cram/turris-omnia/acceleration-plan-components/010-firewall-dmz.t new file mode 100644 index 0000000000..ed1fb5f714 --- /dev/null +++ b/.gitlab/tests/cram/turris-omnia/acceleration-plan-components/010-firewall-dmz.t @@ -0,0 +1,35 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Add DMZ host: + + $ printf "\ + > ubus-cli Firewall.X_Prpl_DMZ+{Alias='test'} + > ubus-cli Firewall.X_Prpl_DMZ.test.SourceInterface=eth2 + > ubus-cli Firewall.X_Prpl_DMZ.test.DestinationIPAddress=192.168.1.186 + > ubus-cli Firewall.X_Prpl_DMZ.test.Enable=1 + > " > /tmp/cram + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/cram)'" > /dev/null; sleep 1 + +Check that correct firewall rules were created: + + $ R "iptables -t nat -L POSTROUTING_DMZ | grep 186 | sort" + SNAT all -- prplOS.lan 192.168.1.186 to:10.0.0.2 + + $ R "iptables -t nat -L PREROUTING_DMZ | grep 186 | sort" + DNAT all -- anywhere 10.0.0.2 to:192.168.1.186 + + $ R "iptables -L FORWARD_DMZ | grep 186 | sort" + ACCEPT all -- 192.168.1.186 anywhere + ACCEPT all -- anywhere 192.168.1.186 + +Remove DMZ host: + + $ script --command "ssh -t root@$TARGET_LAN_IP ubus-cli Firewall.X_Prpl_DMZ.test-" > /dev/null; sleep 1 + +Check that firewall rules are gone: + + $ R "iptables -t nat -L POSTROUTING_DMZ | grep 186 | sort" + $ R "iptables -t nat -L PREROUTING_DMZ | grep 186 | sort" + $ R "iptables -L FORWARD_DMZ | grep 186 | sort" diff --git a/.gitlab/tests/cram/turris-omnia/acceleration-plan-components/020-bridging-guest.t b/.gitlab/tests/cram/turris-omnia/acceleration-plan-components/020-bridging-guest.t new file mode 100644 index 0000000000..16d2351318 --- /dev/null +++ b/.gitlab/tests/cram/turris-omnia/acceleration-plan-components/020-bridging-guest.t @@ -0,0 +1,55 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Get initial state of bridges: + + $ R "brctl show | cut -d$'\t' -f1,4-" + bridge name\tSTP enabled\tinterfaces (esc) + br-guest\tno (esc) + br-lan\tno\t\tlan0 (esc) + \t\t\t\t\tlan1 (esc) + \t\t\t\t\tlan2 (esc) + \t\t\t\t\tlan3 (esc) + \t\t\t\t\tlan4 (esc) + +Remove lan4 from LAN bridge and add it to the Guest bridge: + + $ printf ' \ + > ubus-cli Bridging.Bridge.lan.Port.LAN4-\n + > ubus-cli Bridging.Bridge.guest.Port.+{Name="lan4", Alias="LAN4"}\n + > ubus-cli Bridging.Bridge.guest.Port.LAN4.Enable=1\n + > ' > /tmp/run + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run)'" > /dev/null + $ sleep 5 + +Check that lan4 is added to Guest bridge: + + $ R "brctl show | cut -d$'\t' -f1,4-" + bridge name\tSTP enabled\tinterfaces (esc) + br-guest\tno\t\tlan4 (esc) + br-lan\tno\t\tlan0 (esc) + \t\t\t\t\tlan1 (esc) + \t\t\t\t\tlan2 (esc) + \t\t\t\t\tlan3 (esc) + +Remove lan4 from the Guest bridge and add it back to the LAN bridge: + + $ printf '\ + > ubus-cli Bridging.Bridge.guest.Port.LAN4-\n + > ubus-cli Bridging.Bridge.lan.Port.+{Name="lan4", Alias="LAN4"}\n + > ubus-cli Bridging.Bridge.lan.Port.LAN4.Enable=1\n + > ' > /tmp/run + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run)'" > /dev/null + $ sleep 5 + +Check for initial state of bridges again: + + $ R "brctl show | cut -d$'\t' -f1,4-" + bridge name\tSTP enabled\tinterfaces (esc) + br-guest\tno (esc) + br-lan\tno\t\tlan0 (esc) + \t\t\t\t\tlan1 (esc) + \t\t\t\t\tlan2 (esc) + \t\t\t\t\tlan3 (esc) + \t\t\t\t\tlan4 (esc) diff --git a/.gitlab/tests/cram/turris-omnia/acceleration-plan-components/030-lcm.t b/.gitlab/tests/cram/turris-omnia/acceleration-plan-components/030-lcm.t new file mode 100644 index 0000000000..cdc4987ab0 --- /dev/null +++ b/.gitlab/tests/cram/turris-omnia/acceleration-plan-components/030-lcm.t @@ -0,0 +1,96 @@ +Create R alias: + + $ alias R="${CRAM_REMOTE_COMMAND:-}" + +Check that Sandbox is not configured properly: + + $ R "ubus -S call Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1 _get" + [4] + + $ R "ubus -S call Cthulhu.Config _get | jsonfilter -e @[*].DhcpCommand" + + +Configure Sandbox: + + $ cat > /tmp/run-sandbox < ubus-cli Cthulhu.Config.DhcpCommand=\"udhcpc -r 192.168.1.200 -i\" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Type="Veth" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.+ + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.Bridge="br-lan" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.Interface="eth0" + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.EnableDhcp=1 + > ubus-cli Cthulhu.Sandbox.Instances.1.NetworkNS.Enable=1 + > ubus-cli "Cthulhu.Sandbox.start(SandboxId=\"generic\")" + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run-sandbox)'" > /dev/null + $ sleep 10 + +Check that Sandbox was configured properly: + + $ R "ubus -S call Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1 _get" + {"Cthulhu.Sandbox.Instances.1.NetworkNS.Interfaces.1.":{"EnableDhcp":true,"Interface":"eth0","Bridge":"br-lan"}} + + $ R "ubus -S call Cthulhu.Config _get | jsonfilter -e @[*].DhcpCommand" + udhcpc -r 192.168.1.200 -i + +Install testing prplOS container v1: + + $ cat > /tmp/run-container < ubus-cli "SoftwareModules.InstallDU(URL=\"docker://registry.gitlab.com/prpl-foundation/prplos/prplos/prplos-testing-container-mvebu-cortexa9:v1\", UUID=\"prplos-testing\", ExecutionEnvRef=\"generic\")" + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run-container)'" > /dev/null + +Check that prplOS container v1 is running: + + $ sleep 30 + + $ R "ubus -S call Cthulhu.Container.Instances.1 _get | jsonfilter -e @[*].Status -e @[*].Bundle -e @[*].BundleVersion -e @[*].ContainerId -e @[*].Alias | sort" + Running + cpe-prplos-testing + prplos-testing + prplos/prplos-testing-container-mvebu-cortexa9 + v1 + + $ R "ssh -y root@192.168.1.200 'cat /etc/container-version' 2> /dev/null" + 1 + +Update to prplOS container v2: + + $ cat > /tmp/run-container < ubus-cli "SoftwareModules.DeploymentUnit.cpe-prplos-testing.Update(URL=\"docker://registry.gitlab.com/prpl-foundation/prplos/prplos/prplos-testing-container-mvebu-cortexa9:v2\")" + > EOF + $ script --command "ssh -t root@$TARGET_LAN_IP '$(cat /tmp/run-container)'" > /dev/null + +Check that prplOS container v2 is running: + + $ sleep 30 + + $ R "ubus -S call Cthulhu.Container.Instances.2 _get | jsonfilter -e @[*].Status -e @[*].Bundle -e @[*].BundleVersion -e @[*].ContainerId -e @[*].Alias | sort" + Running + cpe-prplos-testing + prplos-testing + prplos/prplos-testing-container-mvebu-cortexa9 + v2 + + $ R "ssh -y root@192.168.1.200 'cat /etc/container-version' 2> /dev/null" + 2 + +Uninstall prplOS testing container: + + $ script --command "ssh -t root@$TARGET_LAN_IP 'ubus-cli SoftwareModules.DeploymentUnit.cpe-prplos-testing.Uninstall\(\)'" > /dev/null; sleep 5 + +Check that prplOS container is not running: + + $ R "ubus -S call Cthulhu.Container.Instances.2 _get" + [4] + +Check that Rlyeh has no container images: + + $ R "ubus -S call Rlyeh.Images _get" + {"Rlyeh.Images.":{}} + +Check that container image is gone from the filesystem as well: + + $ R "ls -al /usr/share/rlyeh/images/prplos" + ls: /usr/share/rlyeh/images/prplos: No such file or directory + [1] diff --git a/.testbed/README.md b/.testbed/README.md new file mode 100644 index 0000000000..ff85a65e55 --- /dev/null +++ b/.testbed/README.md @@ -0,0 +1,11 @@ +# Content + +This directory contains bits needed for testbed. + +## cdrouter + +Contains CDRouter configurations and test packages definitions for runtime testing on real devices using [CDRouter](https://www.qacafe.com/test-solutions/cdrouter-benefits/cdrouter-technology/). + +## labgrid + +Provides content used during runtime testing on real device using [labgrid](https://labgrid.readthedocs.io/en/latest/) Python testing framework. diff --git a/.testbed/cdrouter/configurations/generic b/.testbed/cdrouter/configurations/generic new file mode 100644 index 0000000000..cf27b643ed --- /dev/null +++ b/.testbed/cdrouter/configurations/generic @@ -0,0 +1,2677 @@ +SECTION "About" { + + # Cable/DSL Router Test Suite + # + # Auto-generated by cdrouter-cli -upgrade-config on 2022-06-03 12:25:19 + # Version: Version 13.1.1 (cf9d6b1), built 2022-04-05 17:19:59 by build@cdr-forge7.corp.qacafe.com (x86_64) + # + # Local.conf + # + # This is the main configuration file for CDRouter. This file defines the + # configuration of the router under test and controls various aspects of + # CDRouter's behavior. This file consists of a number of unique test variables + # called 'testvars' which are grouped by interface, protocol, or functionality. + # The basic syntax for all testvars is: + # + # testvar NAME VALUE + +} + +SECTION "Base Configuration" { + + SECTION "WAN" { + + SECTION "WAN Interface" { + + # testvar wanInterface eth2 + # testvar wanMode DHCP + # testvar wanIspIp 202.254.1.1 + # testvar wanIspAssignIp 202.254.1.2 + # testvar wanIspMask 255.255.255.0 + # testvar wanDomainName qacafe.com + # testvar forwardingMode route + # testvar wanDutMac none + # testvar wanDutClientID 01000000000001 + # testvar wanAuthenticator no + # testvar wanNatIp 202.254.1.2 + # testvar wanIspNextIp 202.254.1.3 + + } + + SECTION "WAN Gateway and DHCP Relay" { + + # testvar wanIspGateway 10.0.0.2 + # testvar wanIspAssignGateway 4.0.0.1 + # testvar wanIspAssignMask 255.255.255.0 + # testvar IPv4HopCount 1 + # testvar dhcpRelayServer 10.0.0.2 + + } + + SECTION "DHCP Server" { + + # testvar dhcpLeaseTime 300 + # testvar dhcpServerBroadcast no + # testvar dhcpServerRapidCommit yes + # testvar dhcpServerClientIDBehavior rfc6842 + # testvar dhcpServerResponseDelay 4500 + # testvar dhcpConnectOnDemand no + + # testvar dhcpServerOptionCode1 69 + # testvar dhcpServerOptionData1 04040404 + + # testvar wanDhcpClientOptionCode1 60 + # testvar wanDhcpClientOptionData1 04040404 + + # testvar dhcpClientMac auto + + } + + SECTION "DHCP Authentication" { + + # testvar supportsDhcpAuth no + + } + + SECTION "PPPoE Server" { + + # testvar pppoeConnectOnDemand no + # testvar pppoeIdleTimeout 60 + # testvar pppoeUser qacafe + # testvar pppoePassword qacafe123 + # testvar pppoeAcName qacafe-ac + # testvar pppoeServiceName any + # testvar pppoeAcCookie auto + # testvar pppoeMaxPayload none + + } + + SECTION "PPTP Server" { + + # testvar pptpUser qacafe + # testvar pptpPassword qacafe123 + # testvar pptpConnectOnDemand yes + # testvar pptpServerIp 202.254.201.1 + # testvar pptpClientIp 202.254.201.2 + # testvar pptpUseDHCP no + + } + + SECTION "L2TP Server" { + + # testvar l2tpUser qacafe + # testvar l2tpPassword qacafe123 + # testvar l2tpConnectOnDemand yes + # testvar l2tpServerIp 202.254.201.1 + # testvar l2tpClientIp 202.254.201.2 + # testvar l2tpUseDHCP no + + } + + SECTION "DS-Lite" { + + # testvar ipv6DsliteAftr 3001:aaaa::1 + # testvar dhcpv6WanAftrName aftr.qacafe.com + # testvar dsliteFirewallMode address-restricted + + } + + SECTION "MAP / LW4o6" { + + # testvar mapBmrRuleIpv6Prefix 5002:db8:0:2ff:: + # testvar mapBmrRuleIpv6PrefixLen 48 + # testvar mapBmrRuleIpv4Prefix 5.0.0.0 + # testvar mapBmrRuleIpv4PrefixLen 24 + # testvar mapBmrRuleEABitLen 16 + + # testvar mapSharingRatio 256 + # testvar mapStartPort 4096 + # testvar mapPsid 255 + + # testvar mapEnableDhcpv6Options yes + + SECTION "MAP-E / LW4o6" { + + # testvar mapTunnelFlowLabel 0 + # testvar mapTunnelHopLimit 64 + # testvar mapTunnelTrafficClass 0 + + } + + SECTION "MAP-T" { + + # testvar mapDmrIpv6Prefix 5001:db8:: + # testvar mapDmrIpv6PrefixLen 48 + + # testvar mapTosTranslate yes + + } + + } + + SECTION "PPP Options" { + + # testvar pppAuthType PAP + # testvar pppForceLcpMRU 1500 + # testvar pppMagicNumber yes + # testvar pppConnectionDelay 10 + # testvar pppRestartTimeout 300000 + # testvar pppFailUsesICMP no + + } + + SECTION "WAN 802.1q VLAN" { + + # testvar wanVlanId 100 + # testvar wanVlanPriority 0 + + } + + SECTION "WAN 802.1ad VLAN" { + + # testvar enableVlanStacking no + + # testvar wanInnerVlanId 100 + # testvar wanInnerVlanPriority 0 + + # testvar wanOuterVlanId 100 + # testvar wanOuterVlanPriority 0 + # testvar wanOuterVlanQinQ no + + } + + SECTION "Wireless Access Point (AP)" { + + # testvar wanApBand 2.4GHz + # testvar wanApSSID qa-net + # testvar wanApChannel auto + + SECTION "WPA Authenticator" { + + # testvar wanApWpaMode RSN + # testvar wanApWpaKeyMgmt PSK + # testvar wanApWpaCipher CCMP-128 + # testvar wanApWpaGroupCipher auto + # testvar wanApWpaPMF auto + # testvar wanApWpaPsk qacafe123 + # testvar wanApWpaSaePassword "sae secret" + + } + } + + SECTION "WAN 802.1X and RADIUS" { + + SECTION "WAN RADIUS" { + + # testvar wanRadiusEnable no + # testvar wanRadiusInterface wan + # testvar wanRadiusIp 3.3.3.44 + # testvar wanRadiusSecret qacafe123 + # testvar wanRadiusServerAttrType1 200 + # testvar wanRadiusServerAttrData1 04040404 + + } + + SECTION "WAN EAP Settings" { + + # testvar wanEapType eap-md5 + + SECTION "WAN Supplicant Credentials" { + + # testvar wanEapIdentity1 user1 + # testvar wanEapPassword1 qacafe123 + + } + + SECTION "WAN Authentication Options" { + + # testvar wanEapRootCert /usr/cdrouter/tests/root.pem + # testvar wanEapServerCertPath /usr/cdrouter/tests/server.pem + # testvar wanEapServerCertPassword qacafe123 + # testvar wanEapFragmentSize 1024 + + } + + } + + } + + SECTION "WAN DNS" { + + # testvar wanDnsServer 202.254.101.1 + # testvar wanBackupDnsServer 202.254.101.2 + # testvar wanBackupDnsServer2 0.0.0.0 + # testvar wanBackupDnsServer3 0.0.0.0 + # testvar DNStoDHCP no + # testvar supportsDnsProxy yes + # testvar supportsDnsCaching yes + # testvar dnsCacheSize 150 + # testvar dnsLookupTimeout 5 + # testvar dnsFailoverAuth "2 4 5" + # testvar dnsFailoverNonAuth "2 4 5" + # testvar dnsFailoverDelay 10 + # testvar dnsFailoverAttempts 20 + # testvar dnsRelayFailover 120 + # testvar dnsForwardServerStatus no + # testvar dnsUsageProfile opportunistic-privacy + # testvar dnsCaptive no + + SECTION "User Configurable DNS Entries" { + + # testvar dnsHostname1 test.qacafe.com + # testvar dnsIp1 5.5.5.5 + + } + + } + + SECTION "HTTP" { + + # testvar supportsHttpProxy yes + # testvar httpProxyIdleTimeout 30 + # testvar httpMaxHeaderCount 200 + + } + + SECTION "NTP" { + + # testvar ntpServer1 3.3.3.6 + # testvar ntpServerName1 time.nist.gov + # testvar ntpServer2 3.3.3.7 + # testvar ntpServerName2 time.foo.com + # testvar ntpStartDate "6/2/2007 11:00 am UTC" + # testvar ntpOffset 0 + # testvar enableRFC868TimeProtocol no + + } + + SECTION "Dynamic DNS" { + + # testvar supportsDynDns no + # testvar dynDnsServerIp 66.37.215.49 + # testvar dynDnsTransport http + # testvar dynDnsHostname test.domain.com + # testvar dynDnsUsername qacafe + # testvar dynDnsPassword qacafe123 + # testvar dynDnsSystem dyndns + # testvar dynDnsMx mail.domain.com + # testvar dynDnsBackMx no + # testvar dynDnsWildcard off + # testvar dynDnsAgent RAS/1.1 + # testvar dynDnsWait 30 + # testvar testDynDnsErrorCode no + # testvar dynDnsServerReturn !yours + + } + + SECTION "WINS Servers" { + + # testvar winsServer1 3.3.3.4 + # testvar winsServer2 3.3.3.5 + + } + + SECTION "WAN Static Routes" { + + # testvar staticRouteWanNetwork1 7.1.1.0/255.255.255.0 + # testvar staticRouteWanNextHop1 wan + + } + + } + + SECTION "LAN" { + + SECTION "LAN Interface" { + + # testvar lanInterface eth1 + # testvar lanMode DHCP + # testvar lanClients 1 + # testvar lanSecurity NONE + # testvar lanIp 192.168.1.1 + # testvar lanMask 255.255.255.0 + # testvar lanDomainName qacafe.com + # testvar lanMtu default + # testvar lanHostname mydut + # testvar lanGuestMode no + + SECTION "ARP Settings" { + + # testvar arpMode strict + # testvar arpSupportGratuitous yes + + } + + } + + SECTION "LAN DNS" { + + # testvar lanDnsServer 192.168.1.1 + # testvar lanStaticDns no + # testvar supportsDnsHostnameCreate no + + } + + SECTION "DHCP Client" { + + # testvar dhcpClientTimeout 5 + # testvar dhcpInform no + # testvar dhcpClientStart 192.168.1.2 + # testvar dhcpClientEnd 192.168.1.254 + # testvar dhcpClientLeaseTime 86400 + # testvar dhcpRapidCommit no + # testvar ipv4MaxLanClients auto + # testvar dhcpClientExclude "192.168.1.47 192.168.1.48" + # testvar dhcpCreateDelay 0 + # testvar dhcpReleaseDelay 300 + # testvar dhcpServerMac auto + # testvar dhcpClientVendorClass myIpDevice + # testvar useDHCPpadding yes + # testvar dhcpClientTrackSeconds no + # testvar dhcpClientRequestNtp no + + # testvar lanDhcpClientOptionCode1 60 + # testvar lanDhcpClientOptionData1 04040404 + + SECTION "DHCP Client Reservations" { + + # testvar dhcpClientReservedIp1 192.168.1.10 + # testvar dhcpClientReservedMac1 b0:75:0c:00:00:00 + + } + + SECTION "DHCP Client Extra Parameters" { + + # testvar dhcpExtraClientParams "69 70" + + } + + SECTION "DHCP Client Extra Options" { + + # testvar dhcpClientOptionCode1 124 + # testvar dhcpClientOptionData1 000000000401020304 + + } + + } + + SECTION "802.11 Wireless" { + + # testvar lanSSID qa-net + # testvar lanChannel auto + # testvar lan80211Phy auto + # testvar lanBSSID auto + # testvar lan80211BandSteering none + + SECTION "WPA Configuration Options" { + + # testvar wpaMode auto + # testvar wpaKey qacafe123 + # testvar wpaSaePassword "sae secret" + # testvar wpaKeyMgmt PSK + # testvar wpaCipher auto + # testvar wpaGroupCipher auto + # testvar wpaPMF auto + + } + + SECTION "WEP Encryption Options" { + + # testvar lanWEPKey off + # testvar lanWEPKeyIndex 0 + + } + + SECTION "Hotspot Router Settings" { + + # testvar browserLoginUrl1 https://192.168.1.1/login?user=%USERNAME%&passwd=%PASSWORD% + # testvar browserLogoutUrl1 http://192.168.1.1/logout?username=%USERNAME% + + SECTION "Hotspot Clients" { + + # testvar clientLoginName1 client1 + # testvar clientLoginPassword1 admin1 + + } + + SECTION "Advanced Hotspot Settings" { + + # testvar browserLoginProc example_login + # testvar browserLogoutProc example_logout + # testvar browserScriptsPath /usr/cdrouter/tests/helper-scripts/hotspot-login.tcl + + } + + } + + SECTION "Expected Beacon Information" { + + # testvar wifiBeaconWpaMode none + # testvar wifiBeaconWpaKeyMgmt PSK + # testvar wifiBeaconWpaCipher CCMP-128 + # testvar wifiBeaconRsnCipher CCMP-128 + # testvar wifiBeaconWpaGroupCipher CCMP-128 + # testvar wifiBeaconPhy "n a ac" + + } + + } + + SECTION "LAN 802.1X and RADIUS" { + + SECTION "LAN RADIUS" { + + # testvar enableRADIUSserver yes + # testvar radiusHost remoteHost + # testvar radiusSecret qacafe123 + # testvar radiusServerAttrType1 200 + # testvar radiusServerAttrData1 04040404 + + } + + SECTION "LAN EAP Settings" { + + # testvar eapType eap-tls + + SECTION "LAN Supplicant Credentials" { + + # testvar eapIdentity1 user1 + # testvar eapPassword1 qacafe123 + # testvar eapUserCertPath1 /usr/cdrouter/tests/user1.pem + # testvar eapUserCertPassword1 qacafe123 + # testvar eapUserPrivateKey1 "" + + } + + SECTION "LAN Authentication Options" { + + # testvar eapRootCert /usr/cdrouter/tests/root.pem + # testvar eapServerCertPath /usr/cdrouter/tests/server.pem + # testvar eapServerCertPassword qacafe123 + # testvar eapFragmentSize 1024 + # testvar eapTxWhen 60 + # testvar eapQuietPeriod 60 + # testvar eapReAuthMax 2 + # testvar eapSendLogoffFailure yes + # testvar eapReAuthPeriod 0 + + } + + } + + } + + SECTION "LAN 802.1q VLAN" { + + # testvar lanVlanId 100 + # testvar lanVlanPriority 0 + + } + + SECTION "LAN Static Routes" { + + # testvar staticRouteLanNetwork1 2.0.0.0/255.255.255.0 + # testvar staticRouteLanNextHop1 192.168.1.18 + + } + + } + + SECTION "Firewall and NAT" { + + SECTION "NAT Options" { + + # testvar natSimultaneousTcp no + # testvar natSrcPort0 yes + # testvar natSupportsP2P yes + # testvar natPortParity yes + # testvar natMode port-restricted + # testvar natVerifyIpId yes + # testvar defaultTcpEchoPort 50000 + # testvar defaultUdpEchoPort 50000 + # testvar natRefreshBehavior both + + SECTION "NAT Timers" { + + # testvar natFinTimeout disabled + # testvar natRstTimeout disabled + # testvar natTcpTimeout disabled + # testvar natSynTimeout disabled + # testvar natUdpTimeout disabled + # testvar natDnsTimeout disabled + # testvar natIcmpTimeout disabled + # testvar natRtspTimeout disabled + # testvar natLagTime 0 + + } + + } + + SECTION "Protocol Pass Through" { + + SECTION "IPSEC Pass Through" { + + # testvar supportsIPSECpass yes + # testvar ipsecMaxTunnels 20 + # testvar ipsecScaleSameServer no + # testvar alwaysUseIke no + # testvar ipsecPassRetransmit no + # testvar unknownPassthrough yes + + } + + SECTION "PPTP Pass Through" { + + # testvar supportsPPTPpass yes + # testvar pptpMaxTunnels 20 + + } + + SECTION "L2TP Pass Through" { + + # testvar supportsL2TPpass yes + # testvar l2tpMaxTunnels 20 + + } + + SECTION "PPPoE Pass Through" { + + # testvar supportsPPPoEpass no + + } + + } + + SECTION "Port Triggers" { + + # testvar portTriggers no + # testvar portTriggerTimeout 0 + # testvar portTriggerDelay 0 + # testvar portTriggerOpenDelay 0 + + # testvar triggerName1 net2phone-1 + # testvar triggerAddrType1 ipv4 + # testvar triggerPort1 6801 + # testvar triggerType1 udp + # testvar triggerPublic1 30000 + # testvar triggerPublicType1 both + + } + + SECTION "Application Layer Gateways (ALGs)" { + + SECTION "MSN Messenger" { + + # testvar supportsMsnAlg no + # testvar msnNotificationServerPort 1863 + # testvar msnSwitchBoardServerPort 1863 + + } + + SECTION "RTSP" { + + # testvar supportsRtspAlg no + # testvar rtspTeardownDelay 5 + # testvar rtspGetParameterInterval 5 + + } + + SECTION "SIP" { + + # testvar supportsSipAlg yes + # testvar sipInterface wan + # testvar sipServerIp 3.3.3.8 + # testvar ipv6SipServerIp 3001:051a:cafe::4 + # testvar sipCallTeardownDelay 5 + # testvar sipMaxOutboundCalls 10 + # testvar sipMaxInboundCalls 10 + # testvar sipCallPacing 0 + # testvar sipScaleRunTime 30 + # testvar sipScaleServerPort 5060 + # testvar sipScaleClientPort 5060 + # testvar sipMaxUserNames -1 + # testvar rtpSendInterval 5000 + + } + + SECTION "FTP" { + + # testvar ftpPortTimeout 120 + + } + + } + + SECTION "Virtual Services (Port Mappings)" { + + # testvar virtualWANTransType none + # testvar virtualLANTransType public + + SECTION "TCP Virtual Services" { + + # testvar virtualTcpServices no + + # testvar virtualTcpServicePort1 21 + # testvar virtualTcpServiceHost1 192.168.1.200 + # testvar virtualTcpServiceName1 ftp + # testvar virtualTcpServiceLanPort1 21 + + } + + SECTION "UDP Virtual Services" { + + # testvar virtualUdpServices no + + # testvar virtualUdpServicePort1 53 + # testvar virtualUdpServiceHost1 192.168.1.203 + # testvar virtualUdpServiceName1 dns + # testvar virtualUdpServiceLanPort1 53 + + } + + } + + SECTION "Port Scanning, Firewall and DoS Options" { + + # testvar portScanStart 0 + # testvar portScanStop 65535 + # testvar portScanDelay 1 + # testvar firewallTcpOpenPorts "22 443" + # testvar firewallTcpClosedPorts 2323 + # testvar firewallUdpOpenPorts 1234 + # testvar firewallUdpClosedPorts 113 + # testvar firewallOutBlockedTcpPorts 1234 + # testvar firewallOutBlockedUdpPorts 1234 + # testvar firewallOutBlockedIpProtos 0 + # testvar wanPingRespond no + + SECTION "Denial of Service Options" { + + # testvar dosRecoveryTime 5 + # testvar dosAttackAttempts 100 + # testvar dutMgmtPort 80 + # testvar dutSecureMgmtPort disabled + # testvar dosSynAttackPort 80 + # testvar dosSynAttackAttempts 100 + + } + + SECTION "Deprecated SSL Protocols and Ciphers" { + + # testvar sslDeprecatedProtocols "sslv2 sslv3" + # testvar sslDeprecatedCiphers "DES-CBC-SHA ECDH-ECDSA-RC4-SHA ECDH-RSA-RC4-SHA ECDHE-ECDSA-RC4-SHA ECDHE-RSA-RC4-SHA EDH-DSS-DES-CBC-SHA EDH-RSA-DES-CBC-SHA EXP-DES-CBC-SHA EXP-EDH-DSS-DES-CBC-SHA EXP-EDH-RSA-DES-CBC-SHA EXP-RC2-CBC-MD5 EXP-RC4-MD5 RC4-MD5" + + } + + } + + SECTION "DMZ" { + + # testvar lanDmzHost 192.168.1.253 + # testvar lanDmzTcpPortExceptions 113 + # testvar lanDmzUdpPortExceptions 1234 + # testvar lanDmzIpProtoExceptions 2,47 + # testvar lanDmzSupportsIcmp no + + } + + SECTION "URL Filtering" { + + # testvar urlFilterSupported no + # testvar filtered-urls "http://abc.com/yahoo.htm http://www.foo.com/home.htm" + # testvar non-filtered-urls http://qacafe.com + # testvar urlFilterBlockedText "This website is blocked" + + } + + SECTION "XBox Live Options" { + + # testvar xboxNatMinType open + # testvar xboxPort 3074 + # testvar xboxMtu 1364 + + } + + } + + SECTION "Advanced Protocols" { + + SECTION "RIP v1/v2" { + + # testvar ripSupported no + # testvar ripVersion 1 + # testvar ripV2mode multicast + # testvar ripAuthMode none + # testvar ripPassword qacafe123 + # testvar ripMaxRoutes 96 + # testvar ripRouteTimeout 180 + # testvar ripGarbageTimeout 120 + # testvar ripRouteDelay 5000 + # testvar ripAcceptWanUpdate no + + } + + SECTION "UPnP" { + + # testvar upnpSupported yes + # testvar upnpVersion 1.1 + # testvar upnpDevice InternetGatewayDevice:2 + # testvar upnpWANPPPConnection no + # testvar upnpLANDevice no + # testvar upnpMaxTcpMappings 10 + # testvar upnpMaxSubClients 10 + # testvar upnpMinSubTimeout 40 + # testvar upnpMaxSubTimeout 3600 + # testvar upnpWANFailureTimeout 120 + # testvar upnpPortStart 40000 + # testvar upnpPortStop 50000 + + } + + SECTION "LLDP" { + + # testvar supportsLLDP no + # testvar lldpLanMac none + # testvar lldpLanChassisMac auto + # testvar lldpMsgFastTx 1 + # testvar lldpMsgTxInterval 30 + # testvar lldpTxFastInit 4 + + } + + SECTION "IGMP (Multicast)" { + + # testvar supportsMulticast yes + # testvar multicastType proxy + # testvar supportsMulticastOut no + # testvar igmpVersion 2 + # testvar igmpFastLeave no + # testvar igmpRouterOption yes + # testvar igmpMaxGroups 64 + # testvar multicastCacheTimeout 10 + # testvar multicastPoolStart 224.0.1.0 + # testvar multicastPoolStop 239.255.255.255 + # testvar SSMulticastPoolStart 232.0.1.1 + # testvar SSMulticastPoolStop 232.0.1.255 + # testvar multicastJoinDelay 2 + # testvar multicastScaleDelay 1 + # testvar multicastInterface wan + # testvar multicastBypassPPPoE no + + SECTION "IGMP Timers" { + + # testvar igmpQueryInterval 125 + # testvar igmpRobustnessVariable 2 + # testvar igmpQueryResponseInterval 10 + + } + + SECTION "IPTV Options" { + + # testvar iptvChannelRange 200 + # testvar iptvChannelChangeDelay 200 + # testvar iptvMaxFailures 10 + + } + + } + + SECTION "GRE Tunnels" { + + # testvar greDFflag on + + IGNORE testvar_group greTunnel1 { + + SECTION "Generic IPv4 GRE Tunnel Endpoints" { + + # testvar greType IPv4 + # testvar greEndpoint 5.5.5.5 + # testvar greLocalNet 192.168.1.0 + # testvar greLocalMask 255.255.255.0 + + } + + SECTION "L2GRE Options" { + + # testvar greWanGroup wan2 + + } + + SECTION "L3GRE Remote IPv4 Network" { + + # testvar greHost 3.0.0.1 + # testvar greRemoteNet 3.0.0.0 + # testvar greRemoteMask 255.0.0.0 + + } + + } + + } + + } + + SECTION "Additional Features" { + + # testvar supportsIPv4 yes + # testvar internalSmtpServer 5.5.5.5 + # testvar remoteHostIp 3.3.3.3 + # testvar startOtherLanFirst no + # testvar cdrouterOui B0750C + # testvar forwardingMaxFailures 20 + # testvar forwardingPort 5001 + # testvar jumboMtu disabled + # testvar tcpUdpPortStart 10000 + + SECTION "General Purpose HTTP Server" { + + # testvar httpServerIp 3.3.3.16 + # testvar httpServerPort 80 + # testvar httpServerRoot /tmp + + } + + SECTION "Free Network Range" { + + # testvar FreeNetworkStart 200.0.0.0 + # testvar FreeNetworkMask 255.255.255.0 + # testvar FreeNetworkStop 201.0.0.0 + + } + + SECTION "TCP MSS Clamping" { + + # testvar mssClampingValue default + # testvar mssClampingInValue default + + } + + SECTION "TCP/UDP Scaling Options" { + + # testvar scaleTcpConnsPerHost 5 + # testvar natMaxTcpConns 200 + # testvar natMaxUdpConns 100 + + } + + SECTION "Global Wireless Options" { + + # testvar wirelessRetry 3 + # testvar lanWirelessMaxClients auto + # testvar wifiCapture off + # testvar wifiCaptureFilter {} + + } + + } + + SECTION "Test Execution Options and Auto-Reboot" { + + # testvar startDelay 3 + # testvar lanStartDelay 3 + # testvar startTimeout 90 + # testvar wanCloseOnExit yes + # testvar RestartDut none + # testvar RestartDutDelay disabled + # testvar ShutdownDut "echo -n" + # testvar cpeRebootMode skip + # testvar healthCheckEnable no + + } + +} + +SECTION "CDRouter DOCSIS Add-On" { + + # testvar supportsDocsis no + + SECTION "Basic Configuration" { + + # testvar docsisIpProvisioningMode ipv4-only + # testvar docsisBootDelay 30 + + # testvar docsisClientMac auto + + } + + SECTION "IPv4 Provisioning" { + + SECTION "Default Gateway and Network" { + + # testvar docsisIp 10.10.10.1 + # testvar docsisMask 255.255.255.0 + + } + + SECTION "DHCPv4 Server" { + + # testvar docsisDhcpServer 10.10.10.3 + # testvar docsisAssignIp 10.10.10.2 + # testvar docsisDomain docsis.qacafe.com + # testvar docsisDhcpLeaseTime 300 + # testvar docsisDhcpRapidCommit no + + # testvar docsisDhcpServerOptionCode1 69 + # testvar docsisDhcpServerOptionData1 04040404 + + # testvar docsisDhcpClientOptionCode1 60 + # testvar docsisDhcpClientOptionData1 04040404 + + SECTION "DHCPv4 Relay" { + + # testvar docsisGateway 6.6.6.7 + # testvar docsisAssignGateway 6.6.6.6 + # testvar docsisAssignMask 255.255.255.0 + # testvar docsisDhcpRelayServer 6.6.6.7 + + } + + } + + SECTION "Log, Time, and TFTP Servers" { + + # testvar docsisLogServer 10.10.10.5 + # testvar docsisTimeServer 10.10.10.6 + # testvar docsisTftpServer 10.10.10.4 + + } + + } + + SECTION "IPv6 Provisioning" { + + SECTION "Default Gateway and Network" { + + # testvar docsisIpv6 8001::1 + # testvar docsisIpv6PrefixLen 64 + + } + + SECTION "DHCPv6 Server" { + + # testvar docsisDhcpIpv6Server 8001::3 + # testvar docsisAssignIpv6 8001::2 + # testvar docsisDHCPv6PreferredLifetime 300 + # testvar docsisDHCPv6ValidLifetime 300 + # testvar docsisDhcpv6RapidCommit no + + # testvar docsisDhcpv6ServerOptionCode1 69 + # testvar docsisDhcpv6ServerOptionData1 04040404 + + # testvar docsisDhcpv6ClientOptionCode1 60 + # testvar docsisDhcpv6ClientOptionData1 04040404 + + } + + SECTION "DHCPv6 Relay" { + + # testvar docsisIpv6Gateway 9001::1 + # testvar docsisAssignIpv6PrefixLen 64 + # testvar docsisDhcpv6RelayServer 9001::1 + + } + + SECTION "Log, Time, and TFTP Servers" { + + # testvar docsisLogIpv6Server 8001::5 + # testvar docsisTimeIpv6Server 8001::6 + # testvar docsisTftpIpv6Server 8001::4 + + } + + } + + SECTION "CM Config File" { + + SECTION "Global TFTP Settings" { + + # testvar docsisTftpServerDirectory /usr/cdrouter-data/temp + # testvar docsisTftpBootFile auto-docsis.bin + + } + + SECTION "Embedded Config File" { + + # testvar docsisConfig { + # Main + # { + # NetworkAccess 1; + # BaselinePrivacy + # { + # AuthTimeout 10; + # ReAuthTimeout 10; + # AuthGraceTime 600; + # OperTimeout 1; + # ReKeyTimeout 1; + # TEKGraceTime 600; + # AuthRejectTimeout 60; + # SAMapWaitTimeout 1; + # SAMapMaxRetries 4; + # } + # MaxCPE 3; + # UsServiceFlow + # { + # UsServiceFlowRef 2; + # QosParamSetType 7; + # } + # DsServiceFlow + # { + # DsServiceFlowRef 1; + # QosParamSetType 7; + # } + # SNMPv1v2cCoexistenceConfig + # { + # SNMPv1v2cCommunityName "public"; + # SNMPv1v2cTransportAddressAccess + # { + # SNMPv1v2cTransportAddress 0.0.0.0/0; + # SNMPv1v2cTransportAddressMask 0.0.0.0/0; + # } + # SNMPv1v2cAccessViewType 2; + # SNMPv1v2cAccessViewName "docsisManagerView"; + # } + # /* CmMic e07f5ace4d2b69cfd8d65cdeb30f739c; */ + # /* CmtsMic 08187b8a159f0fa6021fa95be0be5a59; */ + # /*EndOfDataMkr*/ + # } + # } + + } + + SECTION "Vendor Defined Config File" { + + # testvar docsisConfigFile none + + } + + } + + SECTION "CM Firewall Configuration" { + + SECTION "IPv4" { + + # testvar docsisTcpOpenPorts "22 443" + # testvar docsisTcpClosedPorts all + # testvar docsisUdpOpenPorts 1234 + # testvar docsisUdpClosedPorts all + + } + + SECTION "IPv6" { + + # testvar docsisIpv6TcpOpenPorts "22 443 3000-3009" + # testvar docsisIpv6TcpClosedPorts "2323 80" + # testvar docsisIpv6UdpOpenPorts 1234 + # testvar docsisIpv6UdpClosedPorts 113 + + } + + } + +} + +SECTION "CDRouter HomeKit Add-On" { + + # testvar supportsHomeKit no + + # testvar homeKitRouterName "HomeKit Router" + # testvar homeKitHATHostname hat.local + # testvar homeKitHATRulesPath /Users/hat/TestcasesJSON/ + # testvar homeKitRouterSetupCode + + # testvar homeKitManualEnabled yes + +} + +SECTION "CDRouter IKE Add-On" { + + SECTION "Global IKE Options" { + + # testvar ikeMaxPhase2SA 20 + # testvar ikeDeadPeerDetection no + # testvar ikeNewQuickModeDelay 1000 + # testvar ikeKeepAlive 20 + # testvar ikeMinimumLifetime 20 + # testvar ipsecMinimumLifetime 20 + # testvar ikePhase2DeleteDelay 100 + # testvar ikeMaxTransforms 21 + # testvar ikeInitialContact yes + # testvar ikeBringUpTunnels yes + # testvar ikeAlwaysInitiate no + # testvar useSameIpsecTunnel no + # testvar ikeNatTraversal no + # testvar ike_FQDN fqdn-test.cdrouter.com + # testvar ike_USER_FQDN cdrouter@fqdn-test.cdrouter.com + + } + + SECTION "IPsec Tunnel Configurations" { + + SECTION "IPsec Tunnel Configuration 1" { + + # testvar ipsecTunnelKeyType1 manual + # testvar ipsecTunnelEndpoint1 5.0.0.1 + # testvar ipsecTunnelRemoteNetwork1 5.0.0.0 + # testvar ipsecTunnelRemoteMask1 255.255.255.0 + # testvar ipsecTunnelHost1 5.0.0.2 + + SECTION "Manual IPsec Tunnel Configuration" { + + # testvar ipsecTunnelOutboundSpi1 1000 + # testvar ipsecTunnelOutEncrypt1 des + # testvar ipsecTunnelOutEncryptKey1 0102030405060708 + # testvar ipsecTunnelOutAuth1 md5-hmac + # testvar ipsecTunnelOutAuthKey1 6262626262626262 + # testvar ipsecTunnelInboundSpi1 1001 + # testvar ipsecTunnelInEncrypt1 des + # testvar ipsecTunnelInEncryptKey1 0102030405060708 + # testvar ipsecTunnelInAuth1 md5-hmac + # testvar ipsecTunnelInAuthKey1 6262626262626262 + + } + + SECTION "IKE IPsec Tunnel Configuration" { + + # testvar ipsecTunnelIkeEncrypt1 des + # testvar ipsecTunnelIkeAuth1 md5-hmac + # testvar ipsecTunnelIkeGroup1 1 + # testvar ipsecTunnelIkeLifetime1 300 + # testvar ipsecTunnelEncrypt1 3des + # testvar ipsecTunnelAuth1 sha1-hmac + # testvar ipsecTunnelPfsGroup1 1 + # testvar ipsecTunnelLifetime1 120 + # testvar ipsecTunnelPsk1 qacafe123 + # testvar ipsecTunnelIkeMode1 main + # testvar ipsecTunnelUsesNat1 no + + } + + } + + } + +} + +SECTION "CDRouter IPv6 Add-On" { + + # testvar supportsIPv6 no + + SECTION "IPv6 WAN" { + + # testvar ipv6WanMode DHCP + # testvar ipv6PPPoEAddressMode DHCP + # testvar ipv6WanIspIp 3001::1 + # testvar ipv6WanIspAssignIp 3001::2 + # testvar ipv6WanIspNextIp 3001::3 + # testvar ipv6WanIspPrefixLen 64 + # testvar ipv6WanDutDuid 00000000 + # testvar ipv6RelayServer 192.88.99.1 + # testvar ipv6RelayServerGlobal 3001:051a:cafe::6 + # testvar ipv6rdPrefix 2001:1234:: + # testvar ipv6rdPrefixLen 32 + # testvar ipv6rdIPv4MaskLen 0 + # testvar ipv6rdDHCPv4Option yes + # testvar ipv6TunnelMtuType static + # testvar ipv6WanMtu 1500 + # testvar ipv6WanMtuOption no + # testvar ipv6RASendInterval 10 + # testvar ipv6ExpectRAonWan no + + SECTION "WAN IPv6 Gateway and DHCPv6 Relay" { + + # testvar ipv6WanIspGateway 3001::9 + # testvar ipv6WanAssignPrefixLen 64 + # testvar IPv6HopCount 1 + # testvar dhcpv6RelayServer 3001::9 + + } + + SECTION "WAN IPv6 DNS" { + + # testvar ipv6WanDnsServer 3001:51a:cafe::2 + # testvar ipv6WanBackupDnsServer 3001:51a:cafe::3 + # testvar ipv6WanBackupDnsServer2 :: + # testvar ipv6WanBackupDnsServer3 :: + # testvar ipv6WanRDNSS no + # testvar ipv6WanDNSSL no + + } + + SECTION "DHCPv6 Server" { + + # testvar dhcpv6IAValidLifetime 300 + # testvar dhcpv6IAPreferredLifetime 300 + # testvar dhcpv6DuidType 1 + # testvar dhcpv6RestartLatency 10 + # testvar dhcpv6ServerRapidCommit yes + + # testvar dhcpv6ServerOptionCode1 69 + # testvar dhcpv6ServerOptionData1 04040404 + + # testvar wanDhcpv6ClientOptionCode1 60 + # testvar wanDhcpv6ClientOptionData1 04040404 + + } + + SECTION "DHCPv6 Authentication" { + + # testvar supportsDhcpv6Auth no + + } + + SECTION "DHCPv6 Prefix Delegation" { + + # testvar dhcpv6WanEnablePD yes + # testvar dhcpv6WanEnablePDExclude no + # testvar dhcpv6WanAssignPrefix 3001:dddd:: + # testvar dhcpv6WanAssignNextPrefix 3001:ddde:: + # testvar dhcpv6WanAssignPrefixLen 48 + # testvar dhcpv6PDLatency 30 + + } + + SECTION "IPv6 NTP" { + + # testvar ipv6NtpServer1 4321::23 + # testvar ipv6NtpServerName1 time.nist.gov + + # testvar ipv6NtpServer2 4321::24 + # testvar ipv6NtpServerName2 time.foo.com + + } + + SECTION "WAN IPv6 Static Routes" { + + # testvar staticIpv6RouteWanNetwork1 3001::/64 + # testvar staticIpv6RouteWanNextHop1 wan + + } + + } + + SECTION "IPv6 LAN" { + + # testvar ipv6LanMode autoconf + # testvar ipv6LanIp 3001:dddd::%eui64% + # testvar ipv6LanPrivacyAddresses no + # testvar ipv6LanPrefixLen 64 + # testvar ipv6MaxLanClients 32 + # testvar ipv6RAInterval 300 + # testvar ipv6LanSubnetId 1 + + SECTION "DHCPv6 Client" { + + # testvar dhcpv6ClientTimeout 5 + # testvar ipv6DhcpClientStart ::2 + # testvar ipv6DhcpClientEnd ::1f + # testvar ipv6DhcpClientExclude "::3 ::7" + # testvar ipv6DhcpClientValidLifetime 86400 + # testvar dhcpv6RapidCommit yes + # testvar dhcpv6ClientOptionRequest "21 22" + + # testvar dhcpv6ClientOptionCode1 39 + # testvar dhcpv6ClientOptionData1 000671616361666503636f6d00 + + } + + SECTION "IPv6 LAN DNS" { + + # testvar ipv6DNStoLAN yes + # testvar ipv6RdnssSupport yes + # testvar ipv6DnsslSupport yes + # testvar ipv6LanStaticDns no + + } + + SECTION "Unique Local Address (ULA) Options" { + + # testvar supportsULA no + # testvar ipv6LanULAPrefix fd00:: + # testvar ipv6LanULAIp ::%eui64% + # testvar ipv6LanULAMode autoconf + + } + + SECTION "LAN IPv6 Static Routes" { + + # testvar staticIpv6RouteLanNetwork1 2001::/64 + # testvar staticIpv6RouteLanNextHop1 3001:dddd::1a + + } + } + + SECTION "IPv6 Firewall" { + + # testvar ipv6FirewallTcpOpenPorts "22 443 3000-3009" + # testvar ipv6FirewallTcpClosedPorts "2323 80" + # testvar ipv6FirewallUdpOpenPorts 1234 + # testvar ipv6FirewallUdpClosedPorts 113 + # testvar ipv6FirewallOutBlockedTcpPorts 1234 + # testvar ipv6FirewallOutBlockedUdpPorts 1234 + # testvar ipv6FirewallOutBlockedIpProtos 0 + # testvar ipv6WanPingRespond no + + SECTION "IPv6 TCP MSS Clamping" { + + # testvar ipv6MssClampingValue default + # testvar ipv6MssClampingInValue default + # testvar ipv6MssClampingTestPort 8096 + + } + + } + + SECTION "IPv6 Advanced Protocols" { + + SECTION "RIPng" { + + # testvar supportsRIPng no + + } + + SECTION "MLD (IPv6 Multicast)" { + + # testvar supportsIPv6Multicast yes + # testvar supportsIPv6MulticastOut no + # testvar mldVersion 2 + # testvar mldMaxGroups 64 + # testvar mldFastLeave no + # testvar ipv6MulticastCacheTimeout 10 + # testvar ipv6MulticastJoinDelay 2 + # testvar ipv6MulticastScaleDelay 1 + + SECTION "MLD Timers" { + + # testvar mldQueryInterval 125 + # testvar mldRobustnessVariable 2 + # testvar mldQueryResponseInterval 10 + + } + + SECTION "IPv6 IPTV Options" { + + # testvar ipv6IptvChannelRange 200 + # testvar ipv6IptvChannelChangeDelay 200 + # testvar ipv6IptvMaxFailures 10 + + } + + } + + } + + SECTION "IPv6 Additional Features" { + + SECTION "IPv6 Free Network Range" { + + # testvar ipv6RemoteHost 3001:051a:cafe::1 + # testvar ipv6FreeNetworkStart 3001:cafe:1:: + # testvar ipv6FreeNetworkPrefixLen 64 + # testvar ipv6FreeNetworkStop 3001:cafe:ffff:: + + } + + SECTION "IPv6 Multicast Pool Ranges" { + + # testvar ipv6MulticastPoolStart ff0e::1 + # testvar ipv6MulticastPoolStop ff0e:ffff:: + # testvar ipv6SSMulticastPoolStart ff3e::8000:1 + # testvar ipv6SSMulticastPoolStop ff3e::ffff:ffff + + } + + } + +} + +SECTION "CDRouter Multiport Add-On" { + + SECTION "Additional WAN Interface Setup" { + + # testvar wanFailoverTimeout 300 + + IGNORE testvar_group wan2 { + + SECTION "IPv4 WAN" { + + SECTION "WAN Interface" { + + # testvar wanInterface eth2 + # testvar wanMode DHCP + # testvar wanIspIp 202.254.2.1 + # testvar wanIspAssignIp 202.254.2.2 + # testvar wanIspMask 255.255.255.0 + # testvar wanDomainName qacafe.com + # testvar forwardingMode route + # testvar wanDutMac none + # testvar wanDutClientID 01000000000001 + # testvar wanAuthenticator no + # testvar wanNatIp 202.254.2.2 + # testvar wanIspNextIp 202.254.2.3 + # testvar wanAlwaysOn yes + + } + + SECTION "WAN Gateway and DHCP Relay" { + + # testvar wanIspGateway 10.0.0.2 + # testvar wanIspAssignGateway 4.0.0.1 + # testvar dhcpRelayServer 10.0.0.2 + + } + + SECTION "DHCP Server" { + + # testvar dhcpLeaseTime 300 + # testvar dhcpServerBroadcast no + + # testvar dhcpServerOptionCode1 69 + # testvar dhcpServerOptionData1 04040404 + + # testvar dhcpClientMac auto + + } + + SECTION "PPPoE Server" { + + # testvar pppoeUser qacafe + # testvar pppoePassword qacafe123 + # testvar pppoeAcName qacafe-ac + # testvar pppoeServiceName any + + } + + SECTION "PPTP Server" { + + # testvar pptpUser qacafe + # testvar pptpPassword qacafe123 + # testvar pptpServerIp 202.254.202.1 + # testvar pptpClientIp 202.254.202.2 + + } + + SECTION "L2TP Server" { + + # testvar l2tpUser qacafe + # testvar l2tpPassword qacafe123 + # testvar l2tpServerIp 202.254.202.1 + # testvar l2tpClientIp 202.254.202.2 + + } + + SECTION "PPP Options" { + + # testvar pppAuthType PAP + # testvar pppForceLcpMRU 1500 + # testvar pppMagicNumber yes + + } + + SECTION "WAN 802.1q VLAN" { + + # testvar wanVlanId 100 + # testvar wanVlanPriority 0 + + } + + SECTION "WAN 802.1ad VLAN" { + + # testvar enableVlanStacking no + + # testvar wanInnerVlanId 100 + # testvar wanInnerVlanPriority 0 + + # testvar wanOuterVlanId 100 + # testvar wanOuterVlanPriority 0 + # testvar wanOuterVlanQinQ no + + } + + SECTION "WAN DNS" { + + # testvar wanDnsServer 202.254.102.1 + # testvar wanBackupDnsServer 202.254.102.2 + + } + SECTION "WAN Static Routes" { + + # testvar staticRouteWanNetwork1 7.1.1.0/255.255.255.0 + # testvar staticRouteWanNextHop1 wan + + } + + } + + SECTION "IPv6 WAN" { + + # testvar ipv6WanMode DHCP + # testvar ipv6PPPoEAddressMode DHCP + # testvar ipv6WanIspIp 3001:0:0:2::1 + # testvar ipv6WanIspAssignIp 3001:0:0:2::2 + # testvar ipv6WanIspNextIp 3001:0:0:2::3 + # testvar ipv6WanIspPrefixLen 64 + + SECTION "WAN IPv6 DNS" { + + # testvar ipv6WanDnsServer 3001:51a:cafe:2::2 + # testvar ipv6WanBackupDnsServer 3001:51a:cafe:2::3 + # testvar ipv6WanBackupDnsServer2 :: + # testvar ipv6WanBackupDnsServer3 :: + + } + + SECTION "DHCPv6 Prefix Delegation" { + + # testvar dhcpv6WanEnablePD yes + # testvar dhcpv6WanEnablePDExclude no + # testvar dhcpv6WanAssignPrefix 3001:dddd:2:: + # testvar dhcpv6WanAssignNextPrefix 3001:ddde:2:: + # testvar dhcpv6WanAssignPrefixLen 48 + + } + + SECTION "WAN IPv6 Static Routes" { + + # testvar staticIpv6RouteWanNetwork1 3001::/64 + # testvar staticIpv6RouteWanNextHop1 wan + + } + + } + + } + + IGNORE testvar_group wan3 { + + SECTION "IPv4 WAN" { + + SECTION "WAN Interface" { + + # testvar wanInterface eth2 + # testvar wanMode DHCP + # testvar wanIspIp 202.254.3.1 + # testvar wanIspAssignIp 202.254.3.2 + # testvar wanIspMask 255.255.255.0 + # testvar wanDomainName qacafe.com + # testvar forwardingMode route + # testvar wanDutMac none + # testvar wanDutClientID 01000000000001 + # testvar wanAuthenticator no + # testvar wanNatIp 202.254.3.2 + # testvar wanIspNextIp 202.254.3.3 + # testvar wanAlwaysOn yes + + } + + SECTION "WAN Gateway and DHCP Relay" { + + # testvar wanIspGateway 10.0.0.2 + # testvar wanIspAssignGateway 4.0.0.1 + # testvar dhcpRelayServer 10.0.0.2 + + } + + SECTION "DHCP Server" { + + # testvar dhcpLeaseTime 300 + # testvar dhcpServerBroadcast no + + # testvar dhcpServerOptionCode1 69 + # testvar dhcpServerOptionData1 04040404 + + # testvar dhcpClientMac auto + + } + + SECTION "PPPoE Server" { + + # testvar pppoeUser qacafe + # testvar pppoePassword qacafe123 + # testvar pppoeAcName qacafe-ac + # testvar pppoeServiceName any + + } + + SECTION "PPTP Server" { + + # testvar pptpUser qacafe + # testvar pptpPassword qacafe123 + # testvar pptpServerIp 202.254.203.1 + # testvar pptpClientIp 202.254.203.2 + + } + + SECTION "L2TP Server" { + + # testvar l2tpUser qacafe + # testvar l2tpPassword qacafe123 + # testvar l2tpServerIp 202.254.203.1 + # testvar l2tpClientIp 202.254.203.2 + + } + + SECTION "PPP Options" { + + # testvar pppAuthType PAP + # testvar pppForceLcpMRU 1500 + # testvar pppMagicNumber yes + + } + + SECTION "WAN 802.1q VLAN" { + + # testvar wanVlanId 100 + # testvar wanVlanPriority 0 + + } + + SECTION "WAN 802.1ad VLAN" { + + # testvar enableVlanStacking no + + # testvar wanInnerVlanId 100 + # testvar wanInnerVlanPriority 0 + + # testvar wanOuterVlanId 100 + # testvar wanOuterVlanPriority 0 + # testvar wanOuterVlanQinQ no + + } + + SECTION "WAN DNS" { + + # testvar wanDnsServer 202.254.103.1 + # testvar wanBackupDnsServer 202.254.103.2 + + } + SECTION "WAN Static Routes" { + + # testvar staticRouteWanNetwork1 7.1.1.0/255.255.255.0 + # testvar staticRouteWanNextHop1 wan + + } + + } + + SECTION "IPv6 WAN" { + + # testvar ipv6WanMode DHCP + # testvar ipv6PPPoEAddressMode DHCP + # testvar ipv6WanIspIp 3001:0:0:3::1 + # testvar ipv6WanIspAssignIp 3001:0:0:3::2 + # testvar ipv6WanIspNextIp 3001:0:0:3::3 + # testvar ipv6WanIspPrefixLen 64 + + SECTION "WAN IPv6 DNS" { + + # testvar ipv6WanDnsServer 3001:51a:cafe:3::2 + # testvar ipv6WanBackupDnsServer 3001:51a:cafe:3::3 + # testvar ipv6WanBackupDnsServer2 :: + # testvar ipv6WanBackupDnsServer3 :: + + } + + SECTION "DHCPv6 Prefix Delegation" { + + # testvar dhcpv6WanEnablePD yes + # testvar dhcpv6WanEnablePDExclude no + # testvar dhcpv6WanAssignPrefix 3001:dddd:3:: + # testvar dhcpv6WanAssignNextPrefix 3001:ddde:3:: + # testvar dhcpv6WanAssignPrefixLen 48 + + } + + SECTION "WAN IPv6 Static Routes" { + + # testvar staticIpv6RouteWanNetwork1 3001::/64 + # testvar staticIpv6RouteWanNextHop1 wan + + } + + } + + } + + } + + SECTION "Additional LAN Interface Setup" { + + # testvar useSameLanInterface no + + IGNORE testvar_group lan2 { + + SECTION "IPv4 LAN" { + + SECTION "LAN Interface" { + + # testvar lanInterface eth1 + # testvar lanMode DHCP + # testvar lanClients 1 + # testvar lanSecurity NONE + # testvar lanIp 192.168.1.1 + # testvar lanMask 255.255.255.0 + # testvar lanGuestMode no + + SECTION "LAN Host IP" { + + # testvar hostIp 192.168.1.0 + # testvar hostMask 255.255.255.0 + # testvar hostGateway 192.168.1.1 + + } + + } + + SECTION "LAN DNS" { + + # testvar lanDnsServer 192.168.1.1 + # testvar lanStaticDns no + + } + + SECTION "LAN 802.1q VLAN" { + + # testvar lanVlanId 100 + # testvar lanVlanPriority 0 + + } + + SECTION "DHCP Client Configuration" { + + # testvar dhcpClientStart 192.168.1.2 + # testvar dhcpClientEnd 192.168.1.254 + # testvar dhcpClientLeaseTime 86400 + # testvar dhcpClientExclude "192.168.1.47 192.168.1.48" + # testvar dhcpClientVendorClass myIpDevice + # testvar useDHCPpadding yes + + # testvar lanDhcpClientOptionCode1 60 + # testvar lanDhcpClientOptionData1 04040404 + + # testvar dhcpClientOptionCode1 124 + # testvar dhcpClientOptionData1 000000000401020304 + + # testvar dhcpExtraClientParams "69 70" + + SECTION "DHCP Client Reservations" { + + # testvar dhcpClientReservedIp1 192.168.1.10 + # testvar dhcpClientReservedMac1 b0:75:0c:00:00:00 + + } + + } + + SECTION "802.11 Wireless" { + + # testvar lanSSID qa-net + # testvar lanChannel auto + # testvar lan80211Phy auto + # testvar lanBSSID auto + # testvar lan80211BandSteering none + + SECTION "WPA Configuration Options" { + + # testvar wpaMode auto + # testvar wpaKey qacafe123 + # testvar wpaSaePassword "sae secret" + # testvar wpaKeyMgmt PSK + # testvar wpaCipher auto + # testvar wpaGroupCipher auto + # testvar wpaPMF auto + + } + + SECTION "WEP Encryption Configuration Options" { + + # testvar lanWEPKey off + # testvar lanWEPKeyIndex 0 + + } + + SECTION "Expected Beacon Information" { + + # testvar wifiBeaconWpaMode none + # testvar wifiBeaconWpaKeyMgmt PSK + # testvar wifiBeaconWpaCipher CCMP-128 + # testvar wifiBeaconWpaGroupCipher CCMP-128 + # testvar wifiBeaconPhy "n a ac" + + } + + } + + SECTION "LAN 802.1X" { + + # testvar eapType eap-tls + + SECTION "LAN Supplicant Credentials" { + + # testvar eapIdentity1 user1 + # testvar eapPassword1 qacafe123 + # testvar eapUserCertPath1 /usr/cdrouter/tests/user1.pem + # testvar eapUserCertPassword1 qacafe123 + # testvar eapUserPrivateKey1 "" + + } + + } + + SECTION "IPv4 Firewall and NAT" { + + SECTION "Static NAT" { + + # testvar staticNatIp 202.254.1.2 + # testvar staticNatFirewall yes + # testvar natMode port-restricted + + } + + SECTION "Special Application Port Triggers" { + + # testvar portTriggers no + + # testvar triggerName1 net2phone-1 + # testvar triggerAddrType1 ipv4 + # testvar triggerPort1 6801 + # testvar triggerType1 udp + # testvar triggerPublic1 30000 + # testvar triggerPublicType1 both + + } + + SECTION "TCP and UDP Virtual Services (Port Mappings)" { + + # testvar virtualWANTransType none + # testvar virtualLANTransType public + + SECTION "TCP Virtual Services" { + + # testvar virtualTcpServices no + + # testvar virtualTcpServicePort1 21 + # testvar virtualTcpServiceHost1 192.168.1.200 + # testvar virtualTcpServiceName1 ftp + # testvar virtualTcpServiceLanPort1 21 + + } + + SECTION "UDP Virtual Services" { + + # testvar virtualUdpServices no + + # testvar virtualUdpServicePort1 53 + # testvar virtualUdpServiceHost1 192.168.1.203 + # testvar virtualUdpServiceName1 dns + # testvar virtualUdpServiceLanPort1 53 + + } + + } + + } + + SECTION "LAN Static Routes" { + + # testvar staticRouteLanNetwork1 2.0.0.0/255.255.255.0 + # testvar staticRouteLanNextHop1 192.168.1.18 + + } + + } + + SECTION "IPv6 LAN" { + + # testvar ipv6LanMode autoconf + # testvar ipv6LanPrivacyAddresses no + # testvar ipv6LanStaticDns no + + SECTION "LAN IPv6 Static Routes" { + + # testvar staticIpv6RouteLanNetwork1 2001::/64 + # testvar staticIpv6RouteLanNextHop1 3001:dddd::1a + + } + + SECTION "LAN IPv6 DHCP Client" { + + # testvar dhcpv6ClientOptionRequest "21 22" + + # testvar dhcpv6ClientOptionCode1 39 + # testvar dhcpv6ClientOptionData1 000671616361666503636f6d00 + + } + + } + + SECTION "Parental Controls" { + + # testvar internetScheduleSundayMode none + # testvar internetScheduleSundayTimes "9:00am - 5:00pm" + + # testvar internetScheduleMondayMode none + # testvar internetScheduleMondayTimes "9:00am - 5:00pm" + + # testvar internetScheduleTuesdayMode none + # testvar internetScheduleTuesdayTimes "9:00am - 5:00pm" + + # testvar internetScheduleWednesdayMode none + # testvar internetScheduleWednesdayTimes "9:00am - 5:00pm" + + # testvar internetScheduleThursdayMode none + # testvar internetScheduleThursdayTimes "9:00am - 5:00pm" + + # testvar internetScheduleFridayMode none + # testvar internetScheduleFridayTimes "9:00am - 5:00pm" + + # testvar internetScheduleSaturdayMode none + # testvar internetScheduleSaturdayTimes "9:00am - 5:00pm" + + } + + } + + } + +} + +SECTION "CDRouter Performance Add-On" { + + # testvar supportsPerformance no + + SECTION "Basic Configuration" { + + # testvar perfWanIp 202.254.1.4 + # testvar perfWanIpv6 3001::4 + # testvar perfPort 19750 + # testvar perfPort2 19751 + + } + + SECTION "Performance Settings" { + + # testvar perfDuration 10 + # testvar perfDownloadBandwidth 0.0 + # testvar perfInterval auto + # testvar perfIncrement 5 + # testvar perfStreams 1 + # testvar perfStreamIncr 0 + # testvar perfUdpLen auto + # testvar perfUploadBandwidth 0.0 + # testvar perfLantoLanBandwidth 0.0 + # testvar perfOmit 0 + # testvar perfDSCP 0 + # testvar perfFairness no + + } + + SECTION "WAN Download Thresholds" { + + # testvar perfDownloadMaxLatency 10000 + # testvar perfDownloadTcpRetr any + # testvar perfDownloadTcpLowThreshold 10.0 + # testvar perfDownloadTcpHighThreshold 0.0 + # testvar perfDownloadUdpLossPercentage 1.0 + # testvar perfDownloadUdpLowThreshold 10.0 + # testvar perfDownloadUdpHighThreshold 0.0 + + } + + SECTION "WAN Upload Thresholds" { + + # testvar perfUploadMaxLatency 10000 + # testvar perfUploadTcpRetr any + # testvar perfUploadTcpLowThreshold 10.0 + # testvar perfUploadTcpHighThreshold 0.0 + # testvar perfUploadUdpLossPercentage 1.0 + # testvar perfUploadUdpLowThreshold 10.0 + # testvar perfUploadUdpHighThreshold 0.0 + + } + + SECTION "LAN to LAN Thresholds" { + + # testvar perfLantoLanMaxLatency 10000 + # testvar perfLantoLanTcpRetr any + # testvar perfLantoLanTcpLowThreshold 10.0 + # testvar perfLantoLanTcpHighThreshold 0.0 + # testvar perfLantoLanUdpLossPercentage 1.0 + # testvar perfLantoLanUdpLowThreshold 10.0 + # testvar perfLantoLanUdpHighThreshold 0.0 + + } + + SECTION "Application Thresholds" { + + # testvar perfDHCPRenewMaxLatency 1000000 + # testvar perfDHCPRestartMaxLatency 2000000 + # testvar perfDNSMaxLatency 50000 + + } + + SECTION "Advanced Options" { + + # testvar perfPingEnable no + # testvar perfEnableCapture no + # testvar perfLatencyAttempts 25 + # testvar perfApplicationAttempts 4 + # testvar perfApplicationDelay 100 + + } + + SECTION "Wireless" { + + IGNORE testvar_group wireless-performance { + + SECTION "Performance Settings" { + + # testvar perfDownloadBandwidth 0.0 + # testvar perfUploadBandwidth 0.0 + # testvar perfLantoLanBandwidth 0.0 + + } + + SECTION "WAN Download Thresholds" { + + # testvar perfDownloadMaxLatency 10000 + # testvar perfDownloadTcpRetr any + # testvar perfDownloadTcpLowThreshold 10.0 + # testvar perfDownloadTcpHighThreshold 0.0 + # testvar perfDownloadUdpLossPercentage 1.0 + # testvar perfDownloadUdpLowThreshold 10.0 + # testvar perfDownloadUdpHighThreshold 0.0 + + } + + SECTION "WAN Upload Thresholds" { + + # testvar perfUploadMaxLatency 10000 + # testvar perfUploadTcpRetr any + # testvar perfUploadTcpLowThreshold 10.0 + # testvar perfUploadTcpHighThreshold 0.0 + # testvar perfUploadUdpLossPercentage 1.0 + # testvar perfUploadUdpLowThreshold 10.0 + # testvar perfUploadUdpHighThreshold 0.0 + + } + + SECTION "LAN to LAN Thresholds" { + + # testvar perfLantoLanMaxLatency 10000 + # testvar perfLantoLanTcpRetr any + # testvar perfLantoLanTcpLowThreshold 10.0 + # testvar perfLantoLanTcpHighThreshold 0.0 + # testvar perfLantoLanUdpLossPercentage 1.0 + # testvar perfLantoLanUdpLowThreshold 10.0 + # testvar perfLantoLanUdpHighThreshold 0.0 + + } + + SECTION "Application Thresolds" { + + # testvar perfDHCPRenewMaxLatency 1000000 + # testvar perfDHCPRestartMaxLatency 2000000 + # testvar perfDNSMaxLatency 50000 + + } + + } + + } + +} + +SECTION "CDRouter Security Add-On" { + + SECTION "Internet Connection Sharing (ICS)" { + + # testvar enableICS no + # testvar icsInterface eth0 + # testvar icsShareIPv4 yes + # testvar icsShareIPv6 yes + + } + + SECTION "Traffic Analysis" { + + # testvar enableSuricata no + + } + + SECTION "Nmap Scans" { + + # testvar enableNmap no + # testvar nmapPorts 0-65535 + # testvar nmapScanTimeout 600 + # testvar nmapTimingTemplate 5 + + } + + SECTION "Parental Controls" { + + # testvar internetScheduleBase auto + # testvar internetScheduleTimeZone auto + # testvar internetScheduleBlockedText "This website is blocked" + + # testvar internetScheduleSundayMode none + # testvar internetScheduleSundayTimes "9:00am - 5:00pm" + + # testvar internetScheduleMondayMode none + # testvar internetScheduleMondayTimes "9:00am - 5:00pm" + + # testvar internetScheduleTuesdayMode none + # testvar internetScheduleTuesdayTimes "9:00am - 5:00pm" + + # testvar internetScheduleWednesdayMode none + # testvar internetScheduleWednesdayTimes "9:00am - 5:00pm" + + # testvar internetScheduleThursdayMode none + # testvar internetScheduleThursdayTimes "9:00am - 5:00pm" + + # testvar internetScheduleFridayMode none + # testvar internetScheduleFridayTimes "9:00am - 5:00pm" + + # testvar internetScheduleSaturdayMode none + # testvar internetScheduleSaturdayTimes "9:00am - 5:00pm" + + } + +} + +SECTION "CDRouter SNMP Add-On" { + + # testvar supportsSnmp no + + # testvar snmpPort 161 + # testvar snmpDefaultUser auto + # testvar snmpMibDirs "/var/lib/mibs /var/lib/my-mibs" + # testvar snmpUpdateDelay 15 + + SECTION "SNMP Options and Users" { + + # testvar snmpManagerIp 3.3.3.33 + # testvar snmpManagerIpv6 3001:051a:cafe::33 + + IGNORE testvar_group snmpuser1 { + + # testvar snmpVersion 2c + + # testvar snmpAccess read-only + # testvar snmpTransport udp + # testvar snmpRetries 5 + # testvar snmpTimeout 5 + + SECTION "SNMP v1/2c Configuration" { + + # testvar snmpCommunity public + + } + + SECTION "SNMP v3 Configuration" { + + # testvar snmpSecurityLevel noAuthNoPriv + + # testvar snmpAuthProtocol MD5 + # testvar snmpAuthUsername qacafe + # testvar snmpAuthPassword qacafe123 + + # testvar snmpPrivacyProtocol DES + # testvar snmpPrivacyPassword qacafe123 + + # testvar snmpContextName bridge1 + # testvar snmpSecurityEngineId 800000020109840301 + # testvar snmpContextEngineId 800000020109840301 + + } + + } + + } + + SECTION "SNMP Scenarios" { + + # testvar snmpScenarioPath /usr/cdrouter-data/custom/myVendorScenario.snmp + # testvar snmpScenarioSingleMode no + # testvar snmpScenarioInterface lan + # testvar snmpScenarioIpVersion IPv4 + + } + +} + +SECTION "CDRouter Storage Add-On" { + + # testvar supportsStorage no + + # testvar storageFileSize 10 + # testvar storageUserFilePath none + # testvar useMulticastDNS no + + SECTION "SMB Options and Users" { + + # testvar supportsStorageSmb yes + # testvar storageSmbMaxSessions 20 + # testvar storageSmbTimeout 120 + # testvar storageSmbPacing 0 + + IGNORE testvar_group smbuser1 { + + # testvar server MyNAS + # testvar share data + # testvar folder /home/qacafe + # testvar guest no + # testvar user qacafe + # testvar password qacafe123 + # testvar permission ReadWrite + + } + + } + + SECTION "FTP Options and Users" { + + # testvar supportsStorageFtp yes + # testvar supportsStorageFtps yes + # testvar storageFtpMaxSessions 20 + # testvar storageFtpTimeout 120 + # testvar storageFtpPacing 0 + + IGNORE testvar_group ftpuser1 { + + # testvar server MyNAS + # testvar path /home/qacafe + # testvar user qacafe + # testvar password qacafe123 + # testvar permission ReadWrite + + } + + } + +} + +SECTION "CDRouter TR-069 Add-On" { + + testvar supportsCWMP yes + + SECTION "Basic ACS Configuration" { + + # testvar acsIp 6.0.0.1 + # testvar acsPort 80 + testvar acsDomain acs-download.qacafe.com + # testvar acsTransport http + # testvar acsAuth digest + # testvar acsDigestQopAuth yes + # testvar acsInterface wan + testvar acsDiscoveryUrl http://acs-download.qacafe.com:80/ + # testvar acsWaitForInform 120 + # testvar acsSkipInitialInform no + # testvar acsCpeConnReqURL http://192.168.200.2:80/cwmp + # testvar cwmpProtocolVersion 1.0 + # testvar acsDeviceDiscovery no + # testvar acsConfigurePeriodicInform yes + # testvar tr69InitiateConnection yes + testvar acsDefaultUser cdrouter + testvar acsDefaultPassword cdrouter + testvar acsCpeDefaultUser acs + testvar acsCpeDefaultPassword acs + # testvar acsFileServerUser file_server_user + # testvar acsFileServerPassword file_server_password + + } + + SECTION "XMPP Connection Request Configuration" { + + # testvar acsSupportsXmppConnReq no + + # testvar acsXmppServerConnectAlgorithm DNS-SRV + # testvar acsXmppConnReqUsername qacafe + # testvar acsXmppConnReqResource cdrouter + # testvar acsXmppConnReqPassword qacafe123 + # testvar acsXmppConnReqUseTls no + + } + + SECTION "Advanced ACS Configuration" { + + # testvar acsCpeKeepAlive yes + # testvar acsChunkedEncoding no + # testvar acsChunkSize 64 + # testvar acsAuthOncePerSession no + # testvar acsCookieMode rfc6265 + # testvar acsCpeConnReqURLMapped http://5.5.5.5:5678/cwmp + # testvar acsNumberCpeAttempts 2 + # testvar acsDelayCpeAttempts 10 + # testvar acsWaitForConnectionRequest yes + # testvar acsUseTcpOffload yes + # testvar acsTargetDevice tr069_device2 + # testvar acsDualStackIp 6000::1 + # testvar acsStrictSyntaxChecking on + + } + + SECTION "SSL Configuration" { + + # testvar acsSslVersion tls + # testvar acsCertPath /usr/cdrouter/tests/acs.cdroutertest.com.pem + # testvar acsCaCertPath /usr/cdrouter/tests/acs.cdroutertest.com-ca.pem + # testvar acsDownloadCertPath /usr/cdrouter/tests/acs-download.cdroutertest.com.pem + # testvar acsDownloadCaCertPath /usr/cdrouter/tests/acs.cdroutertest.com-ca.pem + # testvar acsCipherSuite auto + # testvar acsClientCaCertPath /path/to/client/ca/file + + } + + SECTION "Profiles" { + + # testvar cwmpSupportedDataModel auto + # testvar cwmpDataValidation yes + # testvar cwmpSkipParameters empty + # testvar cwmpModifyParameters empty + # testvar cwmpVendorSpecificParams none + + SECTION "Custom CWMP Profiles" { + + IGNORE testvar_group cwmp_profile1 { + + # testvar cwmpProfileName myVendorParameters + # testvar cwmpProfilePath /usr/cdrouter-data/custom/myVendorParameters.cwmp + # testvar cwmpProfileObject InternetGatewayDevice:1 + + } + + } + + } + + SECTION "CWMP Scenarios" { + + # testvar cwmpScenarioPath /usr/cdrouter-data/custom/myVendorScenario.cwmp + # testvar cwmpScenarioSingleMode no + # testvar cwmpScenarioBootstrap /usr/cdrouter-data/custom/myBootstrapScenario.cwmp + + } + + SECTION "Additional TR-069 Options" { + + # testvar tr69DeviceType IGD + # testvar tr69DeviceOui e09153 + # testvar tr69DeviceSn 2673964 + # testvar tr69InformTimeout 120 + # testvar tr69MinPeriodicInform 60 + # testvar tr69ScheduleInformRPC yes + # testvar tr69UploadRPC no + # testvar tr69UploadPath /tmp + # testvar tr69ConfigUploadFilename vendor_configuration_file + # testvar tr69LogUploadFilename vendor_log_file + # testvar tr69FactoryResetRPC no + # testvar tr69CpeGetRPCs no + # testvar tr69ForceBoolean no + # testvar tr69XMLCapturePath /tmp/tr69-xml + # testvar tr69DownloadTimeout 600 + # testvar tr69DownloadImage /path/to/image + # testvar tr69DownloadImageVersion 1.0 + # testvar tr69DownloadOriginalImage /path/to/original_image + # testvar tr69RebootTimeout 300 + # testvar tr69RpcTimeout 180 + # testvar tr69DownloadConfig /path/to/config + # testvar tr69MaxUserNameLen 256 + # testvar tr69MaxPasswordLen 256 + # testvar tr69MaxCpeUserNameLen 256 + # testvar tr69MaxCpePasswordLen 256 + # testvar tr69DUInstallImage /path/to/du.image + # testvar tr69DUInstallImageVersion 1.0 + # testvar tr69DUInstallImageAlternate /path/to/alternate/du.image + # testvar tr69DUInstallImageAlternateVersion 1.0 + # testvar tr69DUInstallUUID b1fbaaa4-44f0-11e0-94cb-001cc09333fb + # testvar tr69DUChangeExecEnvRef openwrt + # testvar tr69DUChangeTimeout 600 + # testvar tr69WildcardPortMappingOnly no + # testvar tr69PortMapDeletionDelay 15 + # testvar tr69PortMapCreationDelay 0 + # testvar tr69PortMapDisableDelay 15 + # testvar tr69TraceRouteTimeout 120 + + } + + SECTION "TR-111 Parts 1 and 2" { + + # testvar supportsTr111Part1 yes + # testvar supportsTr111Part2 no + # testvar STUNMaximumKeepAlivePeriod 60 + # testvar STUNMinimumKeepAlivePeriod 60 + # testvar STUNAuth no + # testvar STUNUsername qacafe + # testvar STUNPassword qacafe123 + # testvar acsUdpConnectionDelay 0 + + } + + SECTION "TR-143 Performance Tests" { + + # testvar tr143HttpDownloadSize 1000000 + # testvar tr143HttpUploadSize 1000000 + + # testvar tr143HttpDownloadHighThreshold 0.0 + # testvar tr143HttpDownloadLowThreshold 5.0 + # testvar tr143HttpDownloadResponseMax 60 + + # testvar tr143HttpUploadHighThreshold 0.0 + # testvar tr143HttpUploadLowThreshold 5.0 + # testvar tr143HttpUploadResponseMax 60 + + } + + SECTION "TR-069 LAN Side Devices" { + + IGNORE testvar_group tr069_device2 { + + # testvar acsDefaultUser qacafe + # testvar acsDefaultPassword qacafe123 + # testvar acsCpeDefaultUser qacafe + # testvar acsCpeDefaultPassword qacafe123 + # testvar acsCreatePortMapOnIGD no + # testvar acsPortMapPublicPort 20000 + # testvar tr69DeviceOui e09153 + # testvar tr69DeviceSn 2673964 + # testvar tr69DeviceType IGD + # testvar tr69DownloadImage /path/to/image + # testvar tr69DownloadOriginalImage /path/to/original_image + # testvar tr69DUInstallImage /path/to/du.image + # testvar tr69DownloadConfig /path/to/config + # testvar acsCpeConnReqURL http://192.168.200.2:80/cwmp + # testvar acsCpeConnReqURLMapped http://5.5.5.5:5678/cwmp + + } + + } + +} + +SECTION "CDRouter USP Add-On" { + + # testvar supportsUSP no + + SECTION "Basic Controller Configuration" { + + # testvar uspControllerID proto::controller-id + # testvar uspControllerInterface wan + + # testvar uspControllerIpMode ipv4-only + # testvar uspControllerIpv4 6.0.0.2 + # testvar uspControllerIpv6 6000::2 + # testvar uspControllerPort auto + # testvar uspControllerPath /controller-path + + # testvar uspControllerUseNonPayloadProtection no + # testvar uspControllerUseSessionContext no + # testvar uspControllerMTP websocket + # testvar uspControllerMTPEncryption no + # testvar uspControllerUSPEncryption no + # testvar uspControllerDomain controller.cdroutertest.com + + # testvar uspSegmentationEnable no + # testvar uspSegmentationSize auto + + # testvar uspControllerMTPCertPath /usr/cdrouter/tests/wildcard.cdroutertest.com.pem + # testvar uspControllerMTPCaCertPath /usr/cdrouter/tests/wildcard.cdroutertest.com-ca.pem + + # testvar uspControllerUSPCaCertPath /usr/cdrouter/tests/wildcard.cdroutertest.com-ca.pem + # testvar uspControllerUSPCertPath /usr/cdrouter/tests/wildcard.cdroutertest.com.pem + + # testvar uspControllerSenderCertPath /usr/cdrouter/tests/wildcard.cdroutertest.com.pem + # testvar uspControllerVerifyRecordIntegrity no + + # testvar uspControllerExpiredCertPath /usr/cdrouter/tests/expired-wilcard.cdroutertest.com.pem + + # testvar uspControllerHost any + # testvar uspControllerUsername qacafe + # testvar uspControllerPassword qacafe123 + + } + + SECTION "Basic Agent Configuration" { + + # testvar uspAgentID proto::agent-id + + # testvar uspAgentIpv4 auto + # testvar uspAgentIpv6 auto + # testvar uspAgentPort auto + # testvar uspAgentPath /agent-path + + # testvar uspMessageTimeout 30 + # testvar uspNotificationTimeout 30 + # testvar uspRebootTimeout 120 + + } + + SECTION "USP Scenarios" { + + # testvar uspScenarioPath /usr/cdrouter-data/custom/myUSPScenario.usp + # testvar uspScenarioSingleMode no + # testvar uspScenarioBootstrap /usr/cdrouter-data/custom/myBootstrapScenario.usp + + } + + SECTION "Data Model" { + + # testvar uspSkipParameters empty + # testvar uspModifyParameters empty + # testvar uspSupportedDataModel all + + SECTION "Custom USP Data Model" { + + IGNORE testvar_group usp_profile_1 { + + # testvar uspProfileName myVendorParameters + # testvar uspProfilePath /usr/cdrouter-data/custom/myVendorParameters.xml + + } + + } + + } + + SECTION "USP Agent Data Model Configuration" { + + # testvar uspNestedMultiInstancePath Device.LocalAgent.Controller.{i}.BootParameter.{i}. + # testvar uspMultiInstancePath Device.LocalAgent.Controller.{i}.BootParameter.{i}. + + # testvar uspParameterPath1 Device.DeviceInfo.ModelName + # testvar uspParameterPath2 Device.IP.Interface.3.Enable + # testvar uspMissingParameterPath Device.DeviceInfo.DeviceCatagory + # testvar uspExternallyChangeableParam Device.DeviceInfo.ProvisioningCode + + # testvar uspNotificationParamNewValue myCustomParameterValue + + # testvar uspObject1 Device.IP.Interface. + # testvar uspObject2 Device.WiFi.AccessPoint. + + # testvar uspValidSearchPath {Device.LocalAgent.Controller.[Enable==true].} + # testvar uspValidSearchPathResultParam PeriodicNotifInterval + # testvar uspValidSearchPathResultValue 5000 + + # testvar uspFirmwareImage /path/to/firmware.bin + # testvar uspOriginalFirmwareImage /path/to/firmwareOriginal.bin + # testvar uspInactiveFirmwareSlot Device.DeviceInfo.FirmwareImage.1 + + } + +} + +SECTION "CDRouter BBF.069 Add-On" { + + # testvar supportsBBF069 yes + + SECTION "General" { + + SECTION "ACS URL" { + + # testvar bbf069ACSURL http://acs1.broadband-forum.org + # testvar bbf069AlternateACSURL http://acs2.broadband-forum.org + + } + + SECTION "Security Certificates" { + + # testvar bbf069AlternateAcsCertPath /usr/cdrouter/tests/bbf.069/Security_Certificate/acs2/CDRouter_acsCert.pem + # testvar bbf069AlternateAcsCaCertPath /usr/cdrouter/tests/bbf.069/Security_Certificate/acs2/CDRouter_acsCaCert.pem + # testvar bbf069InvalidCertPath /usr/cdrouter/tests/bbf.069/Security_Certificate/acs1invalid/CDRouter_acsCert.pem + # testvar bbf069InvalidCACertPath /usr/cdrouter/tests/bbf.069/Security_Certificate/acs1invalid/CDRouter_acsCaCert.pem + # testvar bbf069AncientCertPath /usr/cdrouter/tests/bbf.069/Security_Certificate/acs1expired/CDRouter_acsCert.pem + # testvar bbf069AncientCACertPath /usr/cdrouter/tests/bbf.069/Security_Certificate/acs1expired/CDRouter_acsCaCert.pem + + } + + SECTION "HTTP Verification" { + + # testvar bbf069HTTPVerification no + + } + + } + + SECTION "Device Specific" { + + SECTION "General" { + + # testvar bbf069RootDataModel InternetGatewayDevice + # testvar bbf069UnsupportedRPC ChangeDUState + # testvar bbf069UploadType "1 Vendor Configuration File" + # testvar bbf069ExpectedUpgradeTime 100 + + } + + SECTION "Data Model" { + + # testvar bbf069AddDeleteObject InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.PortMapping. + + # testvar bbf069ActiveParam InternetGatewayDevice.ManagementServer.PeriodicInformInterval + # testvar bbf069ActiveParamType unsignedInt + # testvar bbf069ActiveParamValue 60 + + # testvar bbf069CompletePath1 InternetGatewayDevice.ManagementServer.PeriodicInformInterval + # testvar bbf069CompletePath1Type unsignedInt + # testvar bbf069CompletePath1Value 73 + + # testvar bbf069CompletePath2 InternetGatewayDevice.ManagementServer.PeriodicInformEnable + # testvar bbf069CompletePath2Type boolean + # testvar bbf069CompletePath2Value true + + # testvar bbf069PartialPath InternetGatewayDevice.ManagementServer. + # testvar bbf069PartialMultiPath InternetGatewayDevice.LANDevice. + # testvar bbf069PartialMultiPathEmpty InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.PortMapping. + # testvar bbf069PartialPathEmpty InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.PortMapping. + + # testvar bbf069InvalidPath InternetGatewayDevice.ManagementServer.PeriodicInformInterv + # testvar bbf069InvalidPathType unsignedInt + + # testvar bbf069UnwritablePath InternetGatewayDevice.DeviceInfo.Manufacturer + # testvar bbf069UnwritableType string + # testvar bbf069WritableString InternetGatewayDevice.Time.NTPServer1 + + } + + } + +} diff --git a/.testbed/cdrouter/packages/CDRouter-IPv6-Top-100.gz b/.testbed/cdrouter/packages/CDRouter-IPv6-Top-100.gz new file mode 100644 index 0000000000000000000000000000000000000000..52aa396105b58389f25df6a292473ebb23e965b9 GIT binary patch literal 20453 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ônz$hx&)+EVdo%CbP#odX16PF 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

P$flC-;ZV5NM0mEq!C}I=R%1@?bV72AZRcdi0+W z0p-HMb>wgtA7`JH`&%EhjY>lORqo7M;&e4gQG!V2-+0QdgIwmP^fU9dbzFo=)cRVKaI>@ zuRmY(`-AcLfJv9nq+9QsdxC5zYGYiDj1&VL* z29f&4*kQZNU_ZkIYjEvg*;D_{1oG`{wh)+1RG(gU-?S8&uB-t8GFHYwAJ3 z;aix}Abe{(I$hK&3UG}RYgjs6T5C?c8Mo6s`)bz?~22|;`B zE&F;N+K`;CC@8f8QC%Qi=hr^sBi7EcJX(LXe?)PN;*ba^W|OH}Vy^PLKDqx(Q)dCq zA#IuBlHsDw>8`688&YmwwuVtgn7Ko-)eM9r_OxHCJ~>?O0k(7BGK+ zxPfcO7Xw?smpjDX4+UpIX(;c%(<1edmIZv7F0a685W_vo!ipnwon+4;Y(dQyO={Tg z&;|^HjSH|}vy$aPSRo#j^gaj`WP0{P`O&aZe%f{759DWcyI4LAo`%shLoc`_D2)&| zTHoDS3hMp7N-=r8g?j|Pbn1KConSABzH6{FZ&FU;xIkse&0L5|fufaaiOSyg#ADbe z?Z)Rpd~6MQ9L}I-S`Bgmea7gSDSf-4(y%X~>s}K(eJR|cf_{IX1B1k#{0&U^3mgH| zf4@105ju;9kE6?I6JNxm^C(7-r~S?Q)63}Jz~4?neasM%lA`Kg3@+Y3UckZm<)*)Z zqyBKPftTlxsQ-x0;rZpifxn%63D~ofzg?yArww(A7vBnhvrfh|zd`#TJtO`)5}2V4 zPT%TEIJ_CLE$?t;9n0bALf-LiUX>;|)Apa)K+yI@UHdeqv*W!>4Zz{s)V0&*yGsoK zOcGNO^i62*RqF7aX5O&(Ds|nkL%5cZMs0*dopFz#gpgPksP1XMf2kgL&|*rwM&`N% z{-rZK9iD;<_Qa8b!imEpy3kc{E;dSlM|A8uq(f{>C)t0bhBYT5AG1CB1(Q}sBBHKU z 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 Q0RRC1{{R30000000D)IJ7XSbN literal 0 HcmV?d00001 diff --git a/.testbed/labgrid/default.yaml b/.testbed/labgrid/default.yaml new file mode 100644 index 0000000000..7c15395700 --- /dev/null +++ b/.testbed/labgrid/default.yaml @@ -0,0 +1,257 @@ +targets: + + nec-wx3000hp-nand: + resources: + RawSerialPort: + port: "/dev/nec-wx3000hp" + drivers: + ExternalPowerDriver: + cmd_on: ssh root@uart-relay.testbed.vpn.true.cz power_on 2 + cmd_off: ssh root@uart-relay.testbed.vpn.true.cz power_off 2 + SerialDriver: {} + ShellDriver: + console_ready: Please press Enter to activate this console. + prompt: 'root@[\w()]+:[^ ]+ ' + login_prompt: built-in shell (ash) + username: kingbanik + SmallUBootDriver: + prompt: 'GRX500 #' + boot_secret: '' + boot_expression: 'Hit any key to stop autoboot' + init_command_timeout: 60 + init_commands: + - setenv bootdelay 5 + - setenv serverip 192.168.1.2 + - setenv ipaddr 192.168.1.1 + - setenv bootargs debug earlyprintk console=ttyLTQ0,115200 + - setenv fullimage AX3000_1600_ETH_11AXUCI_ASURADA-squashfs-fullimage.img + - ubi part system_sw + - ubi remove rootfs_data + - ubi create rootfs_data 0x2000000 dynamic + - run update_fullimage + - run run_bootcore + - ubi read $loadaddr $kernel_vol + - run flashargs addmisc + UBootStrategy: {} + + nec-wx3000hp-firstboot: + resources: + RawSerialPort: + port: "/dev/nec-wx3000hp" + drivers: + ExternalPowerDriver: + cmd_on: ssh root@uart-relay.testbed.vpn.true.cz power_on 2 + cmd_off: ssh root@uart-relay.testbed.vpn.true.cz power_off 2 + SerialDriver: {} + ShellDriver: + console_ready: Please press Enter to activate this console. + prompt: 'root@[\w()]+:[^ ]+ ' + login_prompt: built-in shell (ash) + username: kingbanik + SmallUBootDriver: + prompt: 'GRX500 #' + boot_secret: '' + boot_expression: 'Hit any key to stop autoboot' + init_command_timeout: 60 + init_commands: + - setenv bootargs debug earlyprintk console=ttyLTQ0,115200 + - ubi part system_sw + - ubi remove rootfs_data + - ubi create rootfs_data 0x2000000 dynamic + - ubi read $loadaddr $kernel_vol + - run flashargs addmisc + UBootStrategy: {} + + netgear-rax40-nand: + resources: + RawSerialPort: + port: "/dev/netgear-rax40" + drivers: + ExternalPowerDriver: + cmd_on: ssh root@uart-relay.testbed.vpn.true.cz power_on 1 + cmd_off: ssh root@uart-relay.testbed.vpn.true.cz power_off 1 + SerialDriver: {} + ShellDriver: + console_ready: Please press Enter to activate this console. + prompt: 'root@[\w()]+:[^ ]+ ' + login_prompt: built-in shell (ash) + username: kingbanik + SmallUBootDriver: + prompt: 'GRX500 #' + boot_secret: '' + boot_expression: 'Hit any key to stop autoboot' + init_command_timeout: 60 + init_commands: + - setenv bootdelay 0 + - setenv serverip 192.168.1.2 + - setenv ipaddr 192.168.1.1 + - setenv bootargs debug earlyprintk console=ttyLTQ0,115200 + - setenv fullimage NETGEAR_RAX40-squashfs-fullimage.img + - ubi part system_sw + - ubi remove rootfs_data + - ubi create rootfs_data 0x2000000 dynamic 5 + - run update_fullimage + - run run_bootcore + - ubi read $(loadaddr) $(kernel_vol) + - run flashargs addmisc + UBootStrategy: {} + + netgear-rax40-initramfs: + resources: + RawSerialPort: + port: "/dev/ttyS1" + drivers: + ExternalPowerDriver: + cmd_on: ssh root@uart-relay.testbed.vpn.true.cz power_on 1 + cmd_off: ssh root@uart-relay.testbed.vpn.true.cz power_off 1 + SerialDriver: {} + ShellDriver: + console_ready: Please press Enter to activate this console. + prompt: 'root@[\w()]+:[^ ]+ ' + login_prompt: built-in shell (ash) + username: kingbanik + SmallUBootDriver: + prompt: 'GRX500 #' + boot_secret: '' + boot_expression: 'Hit any key to stop autoboot' + init_command_timeout: 60 + init_commands: + - setenv bootdelay 0 + - setenv serverip 192.168.1.2 + - setenv ipaddr 192.168.1.1 + - setenv bootargs debug earlyprintk console=ttyLTQ0,115200 + - tftpboot 0x8f500000 NETGEAR_RAX40-initramfs-kernel.bin + UBootStrategy: {} + + tplink-c6v2-initramfs: + resources: + RawSerialPort: + port: "/dev/tplink-c6v2" + drivers: + ExternalPowerDriver: + cmd_on: ssh root@uart-relay.testbed.vpn.true.cz power_on 0 + cmd_off: ssh root@uart-relay.testbed.vpn.true.cz power_off 0 + SerialDriver: {} + ShellDriver: + console_ready: Please press Enter to activate this console. + prompt: 'root@[\w()]+:[^ ]+ ' + login_prompt: built-in shell (ash) + await_login_timeout: 15 + username: kingbanik + SmallUBootDriver: + prompt: 'ath> ' + boot_expression: 'Hit any key to stop autoboot' + init_commands: + - setenv bootdelay 0 + - setenv serverip 192.168.1.2 + - setenv ipaddr 192.168.1.1 + - setenv bootargs debug earlyprintk console=ttyS0,115200 + - ping 192.168.1.2; ping 192.168.1.2; ping 192.168.1.2 + - tftpboot 0x81000000 openwrt-ath79-generic-tplink_archer-c6-v2-initramfs-kernel.bin + UBootStrategy: {} + + glinet-b1300-initramfs: + resources: + RawSerialPort: + port: "/dev/glinet-b1300" + drivers: + ExternalPowerDriver: + cmd_on: ssh root@uart-relay.testbed.vpn.true.cz power_on 1 + cmd_off: ssh root@uart-relay.testbed.vpn.true.cz power_off 1 + SerialDriver: {} + ShellDriver: + console_ready: Please press Enter to activate this console. + prompt: 'root@[\w()]+:[^ ]+ ' + login_prompt: built-in shell (ash) + await_login_timeout: 15 + username: kingbanik + UBootDriver: + prompt: '\(IPQ40xx\) # ' + password: 'gl' + password_prompt: 'Hit "gl" key to stop booting' + init_commands: + - setenv bootdelay 0 + - setenv serverip 192.168.1.2 + - setenv ipaddr 192.168.1.1 + boot_command_delay: 5 + boot_timeout: 90 + boot_command: tftpboot 0x88000000 openwrt-ipq40xx-generic-glinet_gl-b1300-initramfs-fit-uImage.itb && bootm 0x88000000 + UBootStrategy: {} + + glinet-b1300-nor: + resources: + RawSerialPort: + port: "/dev/glinet-b1300" + drivers: + ExternalPowerDriver: + cmd_on: ssh root@uart-relay.testbed.vpn.true.cz power_on 1 + cmd_off: ssh root@uart-relay.testbed.vpn.true.cz power_off 1 + SerialDriver: {} + ShellDriver: + console_ready: Please press Enter to activate this console. + prompt: 'root@[\w()]+:[^ ]+ ' + login_prompt: built-in shell (ash) + await_login_timeout: 15 + username: kingbanik + UBootDriver: + prompt: '\(IPQ40xx\) # ' + password: 'gl' + password_prompt: 'Hit "gl" key to stop booting' + init_commands: + - setenv bootdelay 0 + - setenv serverip 192.168.1.2 + - setenv ipaddr 192.168.1.1 + boot_command_delay: 5 + boot_timeout: 180 + boot_command: tftpboot 0x84000000 openwrt-ipq40xx-generic-glinet_gl-b1300-squashfs-sysupgrade.bin && sf probe && sf erase 0x180000 0x1e80000 && sf write 0x84000000 0x180000 $filesize && bootipq + UBootStrategy: {} + + # needs patched u-boot for emmc r/w https://lists.denx.de/pipermail/u-boot/2021-February/441964.html + turris-omnia-emmc: + resources: + RawSerialPort: + port: "/dev/turris-omnia" + drivers: + ExternalPowerDriver: + cmd_on: ssh root@uart-relay.testbed.vpn.true.cz power_on 0 + cmd_off: ssh root@uart-relay.testbed.vpn.true.cz power_off 0 + SerialDriver: + txdelay: 0.01 + ShellDriver: + console_ready: Please press Enter to activate this console. + prompt: 'root@[\w()]+:[^ ]+ ' + login_prompt: built-in shell (ash) + await_login_timeout: 15 + username: kingbanik + UBootDriver: + prompt: '=> ' + init_commands: + - setenv bootargs earlyprintk console=ttyS0,115200 + - setenv set_blkcnt 'setexpr blkcnt ${filesize} + 0x7ffff && setexpr blkcnt ${blkcnt} / 0x80000 && setexpr blkcnt ${blkcnt} * 0x400' + - dhcp ${kernel_addr_r} openwrt-mvebu-cortexa9-cznic_turris-omnia-sysupgrade.img + boot_command: run set_blkcnt && mmc dev 0 0 && mmc erase 0 ${blkcnt} && mmc write ${kernel_addr_r} 0 ${blkcnt} && run bootcmd + UBootStrategy: {} + + turris-omnia-initramfs: + resources: + RawSerialPort: + port: "/dev/turris-omnia" + drivers: + ExternalPowerDriver: + cmd_on: ssh root@uart-relay.testbed.vpn.true.cz power_on 0 + cmd_off: ssh root@uart-relay.testbed.vpn.true.cz power_off 0 + SerialDriver: + txdelay: 0.01 + ShellDriver: + console_ready: Please press Enter to activate this console. + prompt: 'root@[\w()]+:[^ ]+ ' + login_prompt: built-in shell (ash) + await_login_timeout: 15 + username: kingbanik + UBootDriver: + prompt: '=> ' + init_commands: + - setenv bootargs earlyprintk console=ttyS0,115200 + - dhcp ${kernel_addr_r} openwrt-mvebu-cortexa9-cznic_turris-omnia-initramfs-kernel.bin + boot_command: bootm ${kernel_addr_r} + UBootStrategy: {}