diff --git a/.github/workflows/ci-ptf-kernels-weekly.yml b/.github/workflows/ci-ptf-kernels-weekly.yml new file mode 100644 index 00000000000..38075296b11 --- /dev/null +++ b/.github/workflows/ci-ptf-kernels-weekly.yml @@ -0,0 +1,90 @@ +# Copyright 2022-present Orange +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: "ptf-ebpf-kernels-weekly" + +on: + schedule: + # Every sunday at 1:17 am UTC + - cron: '17 1 * * 0' + +jobs: + ptf-linux: + # Prevent triggering by a fork because this workflow is resource intensive + if: ${{ github.repository == 'p4lang/p4c' && github.ref == 'refs/heads/main' }} + strategy: + fail-fast: false + matrix: + kernels: [5.8, 5.11, 5.13, 5.15] + include: + - kernels: 5.8 + kernel_version: 5.8.0-63 + os: ubuntu-20.04 + - kernels: 5.11 + kernel_version: 5.11.0-46 + os: ubuntu-20.04 + - kernels: 5.13 + kernel_version: 5.13.0-52 + os: ubuntu-20.04 + - kernels: 5.15 + kernel_version: 5.15.0-48 + os: ubuntu-20.04 + env: + UNIFIED: ON + ENABLE_GMP: ON + # Used by virt-builder and virt-install, for valid values see `virt-builder --list`. + OS_TYPE: ${{ matrix.os }} + # List of kernels to use in a single job + KERNEL_VERSIONS: ${{ matrix.kernel_version }} + VM_NAME: inner + DISK_IMAGE: /tmp/vm_disk_image.qcow2 + WORKING_DISK_IMAGE: /var/lib/libvirt/images/vm_disk.qcow2 + DOCKER_VOLUME_IMAGE: /var/lib/libvirt/images/docker_disk.qcow2 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + + - name: ccache + uses: hendrikmuhs/ccache-action@v1 + with: + key: test-${{ env.UNIFIED }}-${{ runner.os }} + max-size: 1000M + + - name: Cache VM image + uses: actions/cache@v3.0.5 + id: vm_cache + with: + path: ${{ env.DISK_IMAGE }} + key: ${{ env.OS_TYPE }} ${{ env.KERNEL_VERSIONS }} + + - name: Prepare runner + run: sudo -E ./tools/ci-ptf/prepare_runner.sh + + - name: Build VM + if: steps.vm_cache.outputs.cache-hit != 'true' + run: sudo -E ./tools/ci-ptf/build_vm.sh + + - name: Build (Linux) + run: | + docker build --network host -t p4c --build-arg MAKEFLAGS=-j8 --build-arg IMAGE_TYPE=test --build-arg ENABLE_UNIFIED_COMPILATION=$UNIFIED --build-arg ENABLE_GMP=$ENABLE_GMP --build-arg INSTALL_PTF_EBPF_DEPENDENCIES=ON --build-arg KERNEL_VERSIONS="$KERNEL_VERSIONS" . + ./tools/export_ccache.sh + + - name: Install VM + run: sudo -E ./tools/ci-ptf/install_vm.sh + + - name: Run PTF tests for eBPF backend (Linux) + run: | + sudo -E ./tools/ci-ptf/run_for_each_kernel.sh sudo docker run --privileged -v /sys/fs/bpf:/sys/fs/bpf -w /p4c/backends/ebpf/tests p4c ./test.sh diff --git a/Dockerfile b/Dockerfile index 6ed2b799a2c..44bd6d86182 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,6 +24,8 @@ ARG ENABLE_GMP=ON ARG DEBIAN_FRONTEND=noninteractive # Whether to install dependencies required to run PTF-ebpf tests ARG INSTALL_PTF_EBPF_DEPENDENCIES=OFF +# List of kernel versions to install supporting packages for PTF-ebpf tests +ARG KERNEL_VERSIONS # Delegate the build to tools/ci-build. COPY . /p4c/ diff --git a/tools/ci-build.sh b/tools/ci-build.sh index 4aeabeb1a02..66761dd8dfa 100644 --- a/tools/ci-build.sh +++ b/tools/ci-build.sh @@ -71,12 +71,15 @@ backends/ebpf/build_libbpf cd /p4c function install_ptf_ebpf_test_deps() ( + # Install linux-tools for specified kernels and for current one + LINUX_TOOLS="linux-tools-`uname -r`" + for version in $KERNEL_VERSIONS; do + LINUX_TOOLS+=" linux-tools-$version-generic" + done export P4C_PTF_PACKAGES="gcc-multilib \ python3-six \ libjansson-dev \ - linux-tools-`uname -r`" - # Package "linux-tools-generic-hwe-20.04" is not required because - # we test under current kernel, not the newest one + $LINUX_TOOLS" apt-get install -y --no-install-recommends ${P4C_PTF_PACKAGES} git clone --recursive https://github.com/P4-Research/psabpf.git /tmp/psabpf diff --git a/tools/ci-ptf/build_vm.sh b/tools/ci-ptf/build_vm.sh new file mode 100755 index 00000000000..b05c08ea1db --- /dev/null +++ b/tools/ci-ptf/build_vm.sh @@ -0,0 +1,60 @@ +#!/bin/bash -e + +# Copyright 2022-present Orange +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Script to build virtual machine disk image. + +USER_NAME="ubuntu" +USER_PASS=$(mkpasswd ubuntu) +USER_HOME=$(pwd) + +function create_kernel_packages_str() { + KERNEL_PACKAGES="" + while (( "$#" )); do + if [ "x$KERNEL_PACKAGES" != "x" ]; then + KERNEL_PACKAGES+="," + fi + KERNEL_PACKAGES+="linux-image-$1-generic,linux-modules-$1-generic,linux-modules-extra-$1-generic" + shift + done +} + +# $KERNEL_VERSIONS must be passed without quotes to allow split into separate arguments +create_kernel_packages_str $KERNEL_VERSIONS + +# Note: Image with Ubuntu 20.04 is preinstalled on logical volume which virt-builder is unable to resize +virt-builder "$OS_TYPE" \ + --memsize 2048 \ + --hostname "$VM_NAME" \ + --network \ + --timezone "$(cat /etc/timezone)" \ + --format qcow2 -o "$DISK_IMAGE" \ + --update \ + --install "$KERNEL_PACKAGES" \ + --run-command "useradd -p $USER_PASS -s /bin/bash -m -d $USER_HOME -G sudo $USER_NAME" \ + --edit '/etc/sudoers:s/^%sudo.*/%sudo ALL=(ALL) NOPASSWD:ALL/' \ + --edit '/etc/default/grub:s/^GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200n8"/' \ + --run-command update-grub \ + --upload ./tools/ci-ptf/netcfg.yaml:/etc/netplan/netcfg.yaml \ + --run-command "chown root:root /etc/netplan/netcfg.yaml" \ + --append-line "/etc/fstab:runner $USER_HOME 9p defaults,_netdev 0 0" \ + --append-line "/etc/fstab:/dev/vdb1 /mnt/docker ext4 defaults 0 0" \ + --run ./tools/ci-ptf/install_docker.sh \ + --firstboot-command "dpkg-reconfigure openssh-server" + +# Enable compression on disk +mv "$DISK_IMAGE" "$DISK_IMAGE.old" +qemu-img convert -O qcow2 -c "$DISK_IMAGE.old" "$DISK_IMAGE" +rm -f "$DISK_IMAGE.old" diff --git a/tools/ci-ptf/default_network.xml b/tools/ci-ptf/default_network.xml new file mode 100644 index 00000000000..1f69ed52a54 --- /dev/null +++ b/tools/ci-ptf/default_network.xml @@ -0,0 +1,10 @@ + + default + + + + + + + + diff --git a/tools/ci-ptf/install_docker.sh b/tools/ci-ptf/install_docker.sh new file mode 100755 index 00000000000..9555751a678 --- /dev/null +++ b/tools/ci-ptf/install_docker.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +apt install -y \ + ca-certificates \ + curl \ + gnupg \ + lsb-release + +mkdir -p /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg + +echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null + +apt update +apt install -y \ + docker-ce \ + docker-ce-cli \ + containerd.io \ + docker-compose-plugin + +# allow sudo-less docker management +groupadd docker +usermod -aG docker ubuntu + +# change data root directory outside inner VM due to lack of disk space +mkdir /mnt/docker +mkdir -p /etc/docker +cat << EOJSON > /etc/docker/daemon.json +{ + "data-root": "/mnt/docker" +} +EOJSON diff --git a/tools/ci-ptf/install_vm.sh b/tools/ci-ptf/install_vm.sh new file mode 100755 index 00000000000..7cd77829d3f --- /dev/null +++ b/tools/ci-ptf/install_vm.sh @@ -0,0 +1,46 @@ +#!/bin/bash -e + +# Copyright 2022-present Orange +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Script to install virtual machine. + +if [ -e "$WORKING_DISK_IMAGE" ]; then + echo "VM already exist - second invocation of $0, so exiting with an error" + exit 1 +fi + +# Create storage for docker image(s) in VM +qemu-img create -f qcow2 "$DOCKER_VOLUME_IMAGE" 12G +virt-format --format=qcow2 --filesystem=ext4 -a "$DOCKER_VOLUME_IMAGE" + +# Copy boot images for every kernel +mkdir -p /mnt/inner /tmp/vm +guestmount -a "$DISK_IMAGE" -i --ro /mnt/inner/ +for version in $KERNEL_VERSIONS; do + cp "/mnt/inner/boot/initrd.img-$version-generic" /tmp/vm/ + cp "/mnt/inner/boot/vmlinuz-$version-generic" /tmp/vm/ +done +guestunmount /mnt/inner + +# Make working copy of disk image +cp "$DISK_IMAGE" "$WORKING_DISK_IMAGE" + +# Move docker test image into VM, require to boot VM with *any* kernel version +docker save -o p4c.img p4c +chmod +r p4c.img +docker rmi -f p4c +ANY_KERNEL_VERSION="$(echo "$KERNEL_VERSIONS" | awk '{print $1}')" +./tools/ci-ptf/run_test.sh "$ANY_KERNEL_VERSION" docker load -i p4c.img +rm -f p4c.img diff --git a/tools/ci-ptf/netcfg.yaml b/tools/ci-ptf/netcfg.yaml new file mode 100644 index 00000000000..46000196262 --- /dev/null +++ b/tools/ci-ptf/netcfg.yaml @@ -0,0 +1,10 @@ +# guest network configuration + +network: + version: 2 + renderer: networkd + ethernets: + alleths: + match: + name: en* + dhcp4: true diff --git a/tools/ci-ptf/prepare_runner.sh b/tools/ci-ptf/prepare_runner.sh new file mode 100755 index 00000000000..3207edcdc6d --- /dev/null +++ b/tools/ci-ptf/prepare_runner.sh @@ -0,0 +1,36 @@ +#!/bin/bash -e + +# Copyright 2022-present Orange +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Script to prepare runner: install all packages to build and run virtual machine. + +apt update +apt install -y \ + bridge-utils \ + qemu-kvm \ + libvirt-daemon-system \ + libvirt-clients \ + virtinst \ + libguestfs-tools \ + wait-for-it \ + whois \ + sshpass + +# Re-define default network to always assign the same IP address +virsh net-destroy default +virsh net-undefine default +virsh net-define ./tools/ci-ptf/default_network.xml +virsh net-autostart default +virsh net-start default diff --git a/tools/ci-ptf/run_for_each_kernel.sh b/tools/ci-ptf/run_for_each_kernel.sh new file mode 100755 index 00000000000..f4054a0518a --- /dev/null +++ b/tools/ci-ptf/run_for_each_kernel.sh @@ -0,0 +1,28 @@ +#!/bin/bash -e + +# Copyright 2022-present Orange +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Script that starts tests on every kernel + +for version in $KERNEL_VERSIONS; do + ./tools/ci-ptf/run_test.sh "$version" "$@" + exit_code=$? + if [ $exit_code -ne 0 ]; then + echo "************************************************************" + echo "Test failed for kernel $version" + echo "************************************************************" + exit $exit_code + fi +done diff --git a/tools/ci-ptf/run_test.sh b/tools/ci-ptf/run_test.sh new file mode 100755 index 00000000000..cbff735aa35 --- /dev/null +++ b/tools/ci-ptf/run_test.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Copyright 2022-present Orange +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Script to start command under specified kernel + +# Translate OS_TYPE into OS_VARIANT which is required for virt-install, see commands +# `virt-install --osinfo list` or `osinfo-query os` for more information and valid values +OS_VARIANT="" +case "$OS_TYPE" in + "ubuntu-20.04") OS_VARIANT="ubuntu20.04" ;; + *) + echo "Unsupported OS_TYPE=$OS_TYPE; please add it to script $0" + exit 1 + ;; +esac + +IP="192.168.122.2" + +KERNEL_VERSION="$1" +shift + +rm ~/.ssh/known_hosts + +set -e + +virt-install --import \ + --transient \ + --name "$VM_NAME" \ + --vcpu 2 \ + --ram 3072 \ + --disk path="$WORKING_DISK_IMAGE",format=qcow2 \ + --disk path="$DOCKER_VOLUME_IMAGE",format=qcow2 \ + --os-variant "$OS_VARIANT" \ + --network network:default \ + --graphics none \ + --console pty,target_type=serial \ + --noautoconsole \ + --filesystem "$(pwd)",runner \ + --boot kernel=/tmp/vm/vmlinuz-$KERNEL_VERSION-generic,initrd=/tmp/vm/initrd.img-$KERNEL_VERSION-generic,kernel_args="ro console=tty0 console=ttyS0,115200n8 root=/dev/vda5" + +wait-for-it "$IP:22" -t 300 -s -- echo VM ready +sshpass -p ubuntu ssh -o "StrictHostKeyChecking=no" "ubuntu@$IP" uname -a + +# we have to cleanup after tests +set +e +sshpass -p ubuntu ssh "ubuntu@$IP" "$@" +exit_code=$? + +virsh shutdown "$VM_NAME" +# wait for guest to shutdown itself +while virsh domstate "$VM_NAME" 2>/dev/null; do + sleep 5 +done + +exit $exit_code