diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-02-17 03:31:58 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-02-17 03:31:58 +0000 |
commit | ddf5326273325822c74424b50b79d8f741cd9bf8 (patch) | |
tree | eb5702cf7807f0469279ed974d3849009ecf3cf9 | |
parent | dbe77443e4e0baf7207dee699ac596d04b3f89de (diff) | |
parent | fa13e575d13f51ec9bf4ea8ec241f3d4b1c24fa5 (diff) | |
download | tests-ddf5326273325822c74424b50b79d8f741cd9bf8.tar.gz |
Snap for 8192848 from fa13e575d13f51ec9bf4ea8ec241f3d4b1c24fa5 to tm-frc-os-statsd-release
Change-Id: Ie8fc84543e525b4433a931b0914b56db3b44dc61
-rw-r--r-- | Android.bp | 27 | ||||
-rw-r--r-- | devicetree/early_mount/Android.bp | 6 | ||||
-rw-r--r-- | net/test/Android.bp | 9 | ||||
-rw-r--r-- | net/test/OWNERS | 3 | ||||
-rwxr-xr-x | net/test/all_tests.py | 6 | ||||
-rwxr-xr-x | net/test/build_all_rootfs.sh | 26 | ||||
-rwxr-xr-x | net/test/build_rootfs.sh | 330 | ||||
-rwxr-xr-x | net/test/net_test.sh | 2 | ||||
-rwxr-xr-x | net/test/policy_crash_test.py | 2 | ||||
-rw-r--r-- | net/test/rootfs/OWNERS | 3 | ||||
-rw-r--r-- | net/test/rootfs/bullseye-common.sh | 130 | ||||
-rw-r--r-- | net/test/rootfs/bullseye-cuttlefish.list | 13 | ||||
-rwxr-xr-x | net/test/rootfs/bullseye-cuttlefish.sh | 50 | ||||
-rw-r--r-- | net/test/rootfs/bullseye-rockpi.list | 7 | ||||
-rwxr-xr-x | net/test/rootfs/bullseye-rockpi.sh | 390 | ||||
-rw-r--r-- | net/test/rootfs/bullseye.list | 8 | ||||
-rwxr-xr-x | net/test/rootfs/bullseye.sh | 116 | ||||
-rw-r--r-- | net/test/rootfs/common.sh | 159 | ||||
-rwxr-xr-x | net/test/rootfs/stage1.sh | 51 | ||||
-rwxr-xr-x | net/test/rootfs/stage2.sh | 69 | ||||
-rwxr-xr-x | net/test/run_net_test.sh | 20 | ||||
-rwxr-xr-x | net/test/tcp_fastopen_test.py | 14 |
22 files changed, 1168 insertions, 273 deletions
@@ -1,29 +1,6 @@ package { - default_applicable_licenses: ["kernel_tests_license"], -} - -// Added automatically by a large-scale-change that took the approach of -// 'apply every license found to every target'. While this makes sure we respect -// every license restriction, it may not be entirely correct. -// -// e.g. GPL in an MIT project might only apply to the contrib/ directory. -// -// Please consider splitting the single license below into multiple licenses, -// taking care not to lose any license_kind information, and overriding the -// default license using the 'licenses: [...]' property on targets as needed. -// -// For unused files, consider creating a 'fileGroup' with "//visibility:private" -// to attach the license to, and including a comment whether the files may be -// used in the current project. -// See: http://go/android-license-faq -license { - name: "kernel_tests_license", - visibility: [":__subpackages__"], - license_kinds: [ - "SPDX-license-identifier-Apache-2.0", - "SPDX-license-identifier-OpenSSL", - ], - // large-scale-change unable to identify any license_text files + // See: http://go/android-license-faq + default_applicable_licenses: ["Android-Apache-2.0"], } python_defaults { diff --git a/devicetree/early_mount/Android.bp b/devicetree/early_mount/Android.bp index 6c60e91..01d149e 100644 --- a/devicetree/early_mount/Android.bp +++ b/devicetree/early_mount/Android.bp @@ -14,11 +14,7 @@ package { // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "kernel_tests_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["kernel_tests_license"], + default_applicable_licenses: ["Android-Apache-2.0"], } python_test { diff --git a/net/test/Android.bp b/net/test/Android.bp index 2ecef87..2d789a2 100644 --- a/net/test/Android.bp +++ b/net/test/Android.bp @@ -1,11 +1,6 @@ package { // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "kernel_tests_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - // SPDX-license-identifier-OpenSSL - default_applicable_licenses: ["kernel_tests_license"], + default_applicable_licenses: ["Android-Apache-2.0"], } python_defaults { @@ -34,6 +29,6 @@ python_test { stem: "kernel_net_tests_bin", main: "all_tests.py", defaults: ["kernel_net_tests_defaults",], - test_suites: ["vts",], + test_suites: ["vts", "general-tests"], test_config: "vts_kernel_net_tests.xml", } diff --git a/net/test/OWNERS b/net/test/OWNERS index cbbfa70..2108f19 100644 --- a/net/test/OWNERS +++ b/net/test/OWNERS @@ -1,2 +1,5 @@ +# Bug component: 31808 lorenzo@google.com maze@google.com + +per-file build_rootfs.sh = rammuthiah@google.com, adelva@google.com, muntsinger@google.com diff --git a/net/test/all_tests.py b/net/test/all_tests.py index 17d9701..2305354 100755 --- a/net/test/all_tests.py +++ b/net/test/all_tests.py @@ -15,6 +15,7 @@ # limitations under the License. import importlib +import os import sys import unittest @@ -48,8 +49,9 @@ test_modules = [ ] if __name__ == '__main__': - # Check whether ADB over TCP is occupying TCP port 5555. - if namespace.HasEstablishedTcpSessionOnPort(5555): + # Check whether ADB over TCP is occupying TCP port 5555, + # or if we're on a real Android device + if os.path.isdir('/system') or namespace.HasEstablishedTcpSessionOnPort(5555): namespace.IfPossibleEnterNewNetworkNamespace() # First, run InjectTests on all modules, to ensure that any parameterized # tests in those modules are injected. diff --git a/net/test/build_all_rootfs.sh b/net/test/build_all_rootfs.sh deleted file mode 100755 index 6e4fdd6..0000000 --- a/net/test/build_all_rootfs.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2019 The Android Open Source Project -# -# 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. -# - -set -e - -for s in bullseye; do - for a in i386 amd64 armhf arm64; do - ./build_rootfs.sh -s "${s}" -a "${a}" - done -done - -echo 'All rootfs builds completed.' diff --git a/net/test/build_rootfs.sh b/net/test/build_rootfs.sh index 5563d8a..994985e 100755 --- a/net/test/build_rootfs.sh +++ b/net/test/build_rootfs.sh @@ -16,87 +16,155 @@ # set -e +set -u SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) -# Make sure we're in C locale so build inside chroot does not complain -# about missing files -unset LANG LANGUAGE \ - LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION LC_MEASUREMENT \ - LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME -export LC_ALL=C - usage() { - echo -n "usage: $0 [-h] [-s bullseye] [-a i386|amd64|armhf|arm64] " - echo "[-m http://mirror/debian] [-n net_test.rootfs.`date +%Y%m%d`]" + echo -n "usage: $0 [-h] [-s bullseye|bullseye-cuttlefish|bullseye-rockpi] " + echo -n "[-a i386|amd64|armhf|arm64] -k /path/to/kernel " + echo -n "-i /path/to/initramfs.gz [-d /path/to/dtb:subdir] " + echo "[-m http://mirror/debian] [-n rootfs] [-r initrd] [-e]" exit 1 } mirror=http://ftp.debian.org/debian -debootstrap=debootstrap suite=bullseye arch=amd64 -while getopts ":hs:a:m:n:" opt; do - case $opt in +embed_kernel_initrd_dtb= +dtb_subdir= +ramdisk= +rootfs= +dtb= + +while getopts ":hs:a:m:n:r:k:i:d:e" opt; do + case "${opt}" in h) usage ;; s) - if [[ "$OPTARG" != "bullseye" ]]; then - echo "Invalid suite: $OPTARG" >&2 + if [[ "${OPTARG%-*}" != "bullseye" ]]; then + echo "Invalid suite: ${OPTARG}" >&2 usage fi suite="${OPTARG}" ;; a) - case "${OPTARG}" in - i386|amd64|armhf|arm64) - arch="${OPTARG}" - ;; - *) - echo "Invalid arch: ${OPTARG}" >&2 - usage - ;; - esac + arch="${OPTARG}" ;; m) - mirror=$OPTARG + mirror="${OPTARG}" ;; n) - name=$OPTARG + rootfs="${OPTARG}" + ;; + r) + ramdisk="${OPTARG}" + ;; + k) + kernel="${OPTARG}" + ;; + i) + initramfs="${OPTARG}" + ;; + d) + dtb="${OPTARG%:*}" + if [ "${OPTARG#*:}" != "${dtb}" ]; then + dtb_subdir="${OPTARG#*:}/" + fi + ;; + e) + embed_kernel_initrd_dtb=1 ;; \?) - echo "Invalid option: $OPTARG" >&2 + echo "Invalid option: ${OPTARG}" >&2 usage ;; :) - echo "Invalid option: $OPTARG requires an argument" >&2 + echo "Invalid option: ${OPTARG} requires an argument" >&2 usage ;; esac done -if [[ -z "${name}" ]]; then - name=net_test.rootfs.${arch}.${suite}.`date +%Y%m%d` +# Disable Debian's "persistent" network device renaming +cmdline="net.ifnames=0 rw PATH=/usr/sbin:/usr/bin" + +# Pass down embedding option, if specified +if [ -n "${embed_kernel_initrd_dtb}" ]; then + cmdline="${cmdline} embed_kernel_initrd_dtb=${embed_kernel_initrd_dtb}" +fi + +case "${arch}" in + i386) + cmdline="${cmdline} console=ttyS0 exitcode=/dev/ttyS1" + machine="pc-i440fx-2.8,accel=kvm" + qemu="qemu-system-i386" + cpu="max" + ;; + amd64) + cmdline="${cmdline} console=ttyS0 exitcode=/dev/ttyS1" + machine="pc-i440fx-2.8,accel=kvm" + qemu="qemu-system-x86_64" + cpu="max" + ;; + armhf) + cmdline="${cmdline} console=ttyAMA0 exitcode=/dev/ttyS0" + machine="virt,gic-version=2" + qemu="qemu-system-arm" + cpu="cortex-a15" + ;; + arm64) + cmdline="${cmdline} console=ttyAMA0 exitcode=/dev/ttyS0" + machine="virt,gic-version=2" + qemu="qemu-system-aarch64" + cpu="cortex-a53" # "max" is too slow + ;; + *) + echo "Invalid arch: ${OPTARG}" >&2 + usage + ;; +esac + +if [[ -z "${rootfs}" ]]; then + rootfs="rootfs.${arch}.${suite}.$(date +%Y%m%d)" +fi +rootfs=$(realpath "${rootfs}") + +if [[ -z "${ramdisk}" ]]; then + ramdisk="initrd.${arch}.${suite}.$(date +%Y%m%d)" fi +ramdisk=$(realpath "${ramdisk}") -# Switch to qemu-debootstrap for incompatible architectures -if [ "$arch" = "arm64" ]; then - debootstrap=qemu-debootstrap +if [[ -z "${kernel}" ]]; then + echo "$0: Path to kernel image must be specified (with '-k')" + usage +elif [[ ! -e "${kernel}" ]]; then + echo "$0: Kernel image not found at '${kernel}'" + exit 2 +fi + +if [[ -z "${initramfs}" ]]; then + echo "Path to initial ramdisk image must be specified (with '-i')" + usage +elif [[ ! -e "${initramfs}" ]]; then + echo "Initial ramdisk image not found at '${initramfs}'" + exit 3 fi # Sometimes it isn't obvious when the script fails failure() { echo "Filesystem generation process failed." >&2 + rm -f "${rootfs}" "${ramdisk}" } trap failure ERR # Import the package list for this release -packages=`cat $SCRIPT_DIR/rootfs/$suite.list | xargs | tr -s ' ' ','` +packages=$(cpp "${SCRIPT_DIR}/rootfs/${suite}.list" | grep -v "^#" | xargs | tr -s ' ' ',') # For the debootstrap intermediates -tmpdir=`mktemp -d` +tmpdir=$(mktemp -d) tmpdir_remove() { echo "Removing temporary files.." >&2 sudo rm -rf "${tmpdir}" @@ -104,55 +172,191 @@ tmpdir_remove() { trap tmpdir_remove EXIT workdir="${tmpdir}/_" - mkdir "${workdir}" chmod 0755 "${workdir}" sudo chown root:root "${workdir}" # Run the debootstrap first -cd $workdir -sudo $debootstrap --arch=$arch --variant=minbase --include=$packages \ - $suite . $mirror -# Workarounds for bugs in the debootstrap suite scripts -for mount in `cat /proc/mounts | cut -d' ' -f2 | grep -e ^$workdir`; do - echo "Unmounting mountpoint $mount.." >&2 - sudo umount $mount -done -# Copy the chroot preparation scripts, and enter the chroot -for file in $suite.sh common.sh net_test.sh; do - sudo cp -a $SCRIPT_DIR/rootfs/$file root/$file - sudo chown root:root root/$file -done -sudo chroot . /root/$suite.sh +cd "${workdir}" +sudo debootstrap --arch="${arch}" --variant=minbase --include="${packages}" \ + --foreign "${suite%-*}" . "${mirror}" + +# Copy some bootstrapping scripts into the rootfs +sudo cp -a "${SCRIPT_DIR}"/rootfs/*.sh root/ +sudo cp -a "${SCRIPT_DIR}"/rootfs/net_test.sh sbin/net_test.sh +sudo chown root:root sbin/net_test.sh + +# Extract the ramdisk to bootstrap with to / +lz4 -lcd "${initramfs}" | sudo cpio -idum lib/modules/* + +# Create /host, for the pivot_root and 9p mount use cases +sudo mkdir host # Leave the workdir, to build the filesystem cd - -# For the final image mount -mount=`mktemp -d` +# For the initial ramdisk, and later for the final rootfs +mount=$(mktemp -d) mount_remove() { - rmdir $mount - tmpdir_remove + rmdir "${mount}" + tmpdir_remove } trap mount_remove EXIT -# Create a 1G empty ext3 filesystem -truncate -s 1G $name -mke2fs -F -t ext3 -L ROOT $name +# The initial ramdisk filesystem must be <=512M, or QEMU's -initrd +# option won't touch it +initrd=$(mktemp) +initrd_remove() { + rm -f "${initrd}" + mount_remove +} +trap initrd_remove EXIT +truncate -s 512M "${initrd}" +mke2fs -F -t ext3 -L ROOT "${initrd}" # Mount the new filesystem locally -sudo mount -o loop -t ext3 $name $mount +sudo mount -o loop -t ext3 "${initrd}" "${mount}" image_unmount() { - sudo umount $mount - mount_remove + sudo umount "${mount}" + initrd_remove } trap image_unmount EXIT # Copy the patched debootstrap results into the new filesystem -sudo cp -a $workdir/* $mount +sudo cp -a "${workdir}"/* "${mount}" +sudo rm -rf "${workdir}" + +# Unmount the initial ramdisk +sudo umount "${mount}" +trap initrd_remove EXIT + +# Copy the initial ramdisk to the final rootfs name and extend it +sudo cp -a "${initrd}" "${rootfs}" +truncate -s 2G "${rootfs}" +e2fsck -p -f "${rootfs}" || true +resize2fs "${rootfs}" + +# Create another fake block device for initrd.img writeout +raw_initrd=$(mktemp) +raw_initrd_remove() { + rm -f "${raw_initrd}" + initrd_remove +} +trap raw_initrd_remove EXIT +truncate -s 64M "${raw_initrd}" + +# Complete the bootstrap process using QEMU and the specified kernel +${qemu} -machine "${machine}" -cpu "${cpu}" -m 2048 >&2 \ + -kernel "${kernel}" -initrd "${initrd}" -no-user-config -nodefaults \ + -no-reboot -display none -nographic -serial stdio -parallel none \ + -smp 8,sockets=8,cores=1,threads=1 \ + -object rng-random,id=objrng0,filename=/dev/urandom \ + -device virtio-rng-pci-non-transitional,rng=objrng0,id=rng0,max-bytes=1024,period=2000 \ + -drive file="${rootfs}",format=raw,if=none,aio=threads,id=drive-virtio-disk0 \ + -device virtio-blk-pci-non-transitional,scsi=off,drive=drive-virtio-disk0 \ + -drive file="${raw_initrd}",format=raw,if=none,aio=threads,id=drive-virtio-disk1 \ + -device virtio-blk-pci-non-transitional,scsi=off,drive=drive-virtio-disk1 \ + -chardev file,id=exitcode,path=exitcode \ + -device pci-serial,chardev=exitcode \ + -append "root=/dev/ram0 ramdisk_size=524288 init=/root/stage1.sh ${cmdline}" +[[ -s exitcode ]] && exitcode=$(cat exitcode | tr -d '\r') || exitcode=2 +rm -f exitcode +if [ "${exitcode}" != "0" ]; then + echo "Second stage debootstrap failed (err=${exitcode})" + exit "${exitcode}" +fi + +# Fix up any issues from the unclean shutdown +e2fsck -p -f "${rootfs}" || true + +# New workdir for the initrd extraction +workdir="${tmpdir}/initrd" +mkdir "${workdir}" +chmod 0755 "${workdir}" +sudo chown root:root "${workdir}" + +# Change into workdir to repack initramfs +cd "${workdir}" + +# Process the initrd to remove kernel-specific metadata +kernel_version=$(basename $(lz4 -lcd "${raw_initrd}" | sudo cpio -idumv 2>&1 | grep usr/lib/modules/ - | head -n1)) +sudo rm -rf usr/lib/modules +sudo mkdir -p usr/lib/modules + +# Debian symlinks /usr/lib to /lib, but we'd prefer the other way around +# so that it more closely matches what happens in Android initramfs images. +# This enables 'cat ramdiskA.img ramdiskB.img >ramdiskC.img' to "just work". +sudo rm -f lib +sudo mv usr/lib lib +sudo ln -s /lib usr/lib + +# Repack the ramdisk to the final output +find * | sudo cpio -H newc -o --quiet | lz4 -lc9 >"${ramdisk}" + +# Pack another ramdisk with the combined artifacts, for boot testing +cat "${ramdisk}" "${initramfs}" >"${initrd}" + +# Leave workdir to boot-test combined initrd +cd - + +# Mount the new filesystem locally +sudo mount -o loop -t ext3 "${rootfs}" "${mount}" +image_unmount2() { + sudo umount "${mount}" + raw_initrd_remove +} +trap image_unmount2 EXIT + +# Embed the kernel and dtb images now, if requested +if [ -n "${embed_kernel_initrd_dtb}" ]; then + if [ -n "${dtb}" ]; then + sudo mkdir -p "${mount}/boot/dtb/${dtb_subdir}" + sudo cp -a "${dtb}" "${mount}/boot/dtb/${dtb_subdir}" + sudo chown -R root:root "${mount}/boot/dtb/${dtb_subdir}" + fi + sudo cp -a "${kernel}" "${mount}/boot/vmlinuz-${kernel_version}" + sudo chown root:root "${mount}/boot/vmlinuz-${kernel_version}" +fi + +# Unmount the initial ramdisk +sudo umount "${mount}" +trap raw_initrd_remove EXIT + +# Boot test the new system and run stage 3 +${qemu} -machine "${machine}" -cpu "${cpu}" -m 2048 >&2 \ + -kernel "${kernel}" -initrd "${initrd}" -no-user-config -nodefaults \ + -no-reboot -display none -nographic -serial stdio -parallel none \ + -smp 8,sockets=8,cores=1,threads=1 \ + -object rng-random,id=objrng0,filename=/dev/urandom \ + -device virtio-rng-pci-non-transitional,rng=objrng0,id=rng0,max-bytes=1024,period=2000 \ + -drive file="${rootfs}",format=raw,if=none,aio=threads,id=drive-virtio-disk0 \ + -device virtio-blk-pci-non-transitional,scsi=off,drive=drive-virtio-disk0 \ + -chardev file,id=exitcode,path=exitcode \ + -device pci-serial,chardev=exitcode \ + -netdev user,id=usernet0,ipv6=off \ + -device virtio-net-pci-non-transitional,netdev=usernet0,id=net0 \ + -append "root=LABEL=ROOT init=/root/${suite}.sh ${cmdline}" +[[ -s exitcode ]] && exitcode=$(cat exitcode | tr -d '\r') || exitcode=2 +rm -f exitcode +if [ "${exitcode}" != "0" ]; then + echo "Root filesystem finalization failed (err=${exitcode})" + exit "${exitcode}" +fi + +# Fix up any issues from the unclean shutdown +e2fsck -p -f "${rootfs}" || true + +# Mount the final rootfs locally +sudo mount -o loop -t ext3 "${rootfs}" "${mount}" +image_unmount3() { + sudo umount "${mount}" + raw_initrd_remove +} +trap image_unmount3 EXIT # Fill the rest of the space with zeroes, to optimize compression -sudo dd if=/dev/zero of=$mount/sparse bs=1M 2>/dev/null || true -sudo rm -f $mount/sparse +sudo dd if=/dev/zero of="${mount}/sparse" bs=1M 2>/dev/null || true +sudo rm -f "${mount}/sparse" -echo "Debian $suite for $arch filesystem generated at '$name'." +echo "Debian ${suite} for ${arch} filesystem generated at '${rootfs}'." +echo "Initial ramdisk generated at '${ramdisk}'." diff --git a/net/test/net_test.sh b/net/test/net_test.sh index 52b168d..e62120c 100755 --- a/net/test/net_test.sh +++ b/net/test/net_test.sh @@ -165,7 +165,7 @@ rv="$?" # Write exit code of net_test to a file so that the builder can use it # to signal failure if any tests fail. -echo "${rv}" > "${net_test_exitcode}" +echo "${rv}" > "${exitcode}" # Additionally on UML make it the exit code of UML kernel binary itself. if [[ -e '/proc/exitcode' ]]; then diff --git a/net/test/policy_crash_test.py b/net/test/policy_crash_test.py index 536f96d..ad1b92a 100755 --- a/net/test/policy_crash_test.py +++ b/net/test/policy_crash_test.py @@ -107,7 +107,7 @@ class RemovedFeatureTest(net_test.NetworkTest): dst = ip6loopback # 8 byte IPv6 fragmentation header - frag_nexthdr = '00' + frag_nexthdr = '3b' frag_reserved = '00' # 13-bit offset, 2-bit reserved, 1-bit M[ore] flag pkt1_frag_offset = '0001' diff --git a/net/test/rootfs/OWNERS b/net/test/rootfs/OWNERS new file mode 100644 index 0000000..9ee1527 --- /dev/null +++ b/net/test/rootfs/OWNERS @@ -0,0 +1,3 @@ +adelva@google.com +muntsinger@google.com +rammuthiah@google.com diff --git a/net/test/rootfs/bullseye-common.sh b/net/test/rootfs/bullseye-common.sh new file mode 100644 index 0000000..f7a0660 --- /dev/null +++ b/net/test/rootfs/bullseye-common.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# +# Copyright (C) 2021 The Android Open Source Project +# +# 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_DIR/common.sh + +iptables=iptables-1.8.7 +debian_iptables=1.8.7-1 +cuttlefish=android-cuttlefish + +setup_and_build_iptables() { + # Install everything needed from bullseye to build iptables + apt-get install -y \ + build-essential \ + autoconf \ + automake \ + bison \ + debhelper \ + devscripts \ + fakeroot \ + flex \ + libmnl-dev \ + libnetfilter-conntrack-dev \ + libnfnetlink-dev \ + libnftnl-dev \ + libtool + + # Construct the iptables source package to build + mkdir -p /usr/src/$iptables + + cd /usr/src/$iptables + # Download a specific revision of iptables from AOSP + wget -qO - \ + https://android.googlesource.com/platform/external/iptables/+archive/master.tar.gz | \ + tar -zxf - + # Download a compatible 'debian' overlay from Debian salsa + # We don't want all of the sources, just the Debian modifications + # NOTE: This will only work if Android always uses a version of iptables + # that exists for Debian as well. + debian_iptables_dir=pkg-iptables-debian-$debian_iptables + wget -qO - \ + https://salsa.debian.org/pkg-netfilter-team/pkg-iptables/-/archive/debian/$debian_iptables/$debian_iptables_dir.tar.gz | \ + tar --strip-components 1 -zxf - \ + $debian_iptables_dir/debian + cd - + + cd /usr/src + # Generate a source package to leave in the filesystem. This is done for + # license compliance and build reproducibility. + tar --exclude=debian -cf - $iptables | \ + xz -9 >$(echo $iptables | tr -s '-' '_').orig.tar.xz + cd - + + cd /usr/src/$iptables + # Build debian packages from the integrated iptables source + dpkg-buildpackage -F -d -us -uc + cd - +} + +install_and_cleanup_iptables() { + cd /usr/src + # Find any packages generated, resolve to the debian package name, then + # exclude any compat, header or symbol packages + packages=$(find -maxdepth 1 -name '*.deb' | colrm 1 2 | cut -d'_' -f1 | + grep -ve '-compat$\|-dbg$\|-dbgsym$\|-dev$' | xargs) + # Install the patched iptables packages, and 'hold' then so + # "apt-get dist-upgrade" doesn't replace them + apt-get install --allow-downgrades -y -f \ + $(for package in $packages; do echo ./${package}_*.deb; done | xargs) + for package in $packages; do + echo "$package hold" | LANG=C dpkg --set-selections + done + update-alternatives --set iptables /usr/sbin/iptables-legacy + + # Tidy up the mess we left behind, leaving just the source tarballs + rm -rf $iptables *.{buildinfo,changes,deb,dsc} + cd - +} + +setup_and_build_cuttlefish() { + # Install everything needed from bullseye to build cuttlefish-common + apt-get install -y \ + cdbs \ + config-package-dev \ + debhelper \ + dpkg-dev \ + git + + # Fetch cuttlefish and build it for cuttlefish-common + git clone https://github.com/google/android-cuttlefish.git /usr/src/$cuttlefish + cd /usr/src/$cuttlefish + dpkg-buildpackage -d -uc -us + cd - +} + +install_and_cleanup_cuttlefish() { + # Install and clean up cuttlefish-common + cd /usr/src + apt-get install -y -f ./cuttlefish-common_*.deb + rm -rf $cuttlefish cuttlefish*.{buildinfo,changes,deb,dsc} + cd - +} + +bullseye_cleanup() { + # SELinux is supported by our kernels, but we don't install the policy files + # which causes an error to be printed by systemd. Disable selinux. + echo "SELINUX=disabled" >/etc/selinux/config + + # Switch binfmt misc over to a static mount, to avoid an autofs4 dependency + systemctl mask proc-sys-fs-binfmt_misc.automount + systemctl enable proc-sys-fs-binfmt_misc.mount + + # This package gets pulled in as a phantom dependency. Remove it + apt-get purge -y gcc-9-base + + cleanup +} diff --git a/net/test/rootfs/bullseye-cuttlefish.list b/net/test/rootfs/bullseye-cuttlefish.list new file mode 100644 index 0000000..c5ff165 --- /dev/null +++ b/net/test/rootfs/bullseye-cuttlefish.list @@ -0,0 +1,13 @@ +#include "bullseye.list" +libegl1-mesa +libgles1 +libgles2 +libpam-systemd +locales +lsof +lzop +ntpdate +openssh-server +resolvconf +sudo +vim diff --git a/net/test/rootfs/bullseye-cuttlefish.sh b/net/test/rootfs/bullseye-cuttlefish.sh new file mode 100755 index 0000000..0f572bc --- /dev/null +++ b/net/test/rootfs/bullseye-cuttlefish.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# +# Copyright (C) 2021 The Android Open Source Project +# +# 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. +# + +set -e +set -u + +SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) + +. $SCRIPT_DIR/bullseye-common.sh + +setup_dynamic_networking "eth1" "br0" + +update_apt_sources bullseye + +setup_cuttlefish_user + +get_installed_packages >/root/originally-installed + +setup_and_build_cuttlefish +setup_and_build_iptables + +get_installed_packages >/root/installed + +remove_installed_packages /root/originally-installed /root/installed + +install_and_cleanup_cuttlefish +sed -i "s,^#\(bridge_interface=\),\1br0," /etc/default/cuttlefish-common + +install_and_cleanup_iptables + +create_systemd_getty_symlinks ttyS0 hvc1 + +setup_grub "net.ifnames=0" + +apt-get purge -y vim-tiny +bullseye_cleanup diff --git a/net/test/rootfs/bullseye-rockpi.list b/net/test/rootfs/bullseye-rockpi.list new file mode 100644 index 0000000..dea4196 --- /dev/null +++ b/net/test/rootfs/bullseye-rockpi.list @@ -0,0 +1,7 @@ +#include "bullseye-cuttlefish.list" +binfmt-support +eject +gdisk +network-manager +qemu-user-static +u-boot-tools diff --git a/net/test/rootfs/bullseye-rockpi.sh b/net/test/rootfs/bullseye-rockpi.sh new file mode 100755 index 0000000..e8188c3 --- /dev/null +++ b/net/test/rootfs/bullseye-rockpi.sh @@ -0,0 +1,390 @@ +#!/bin/bash +# +# Copyright (C) 2021 The Android Open Source Project +# +# 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. +# + +set -e +set -u + +SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) + +. $SCRIPT_DIR/bullseye-common.sh + +sed -i "s,debian,rockpi," /etc/hosts +sed -i "s,debian,rockpi," /etc/hostname + +# Build U-Boot FIT based on the Debian initrd +if [ -n "${embed_kernel_initrd_dtb}" ]; then + mkimage -f auto -A arm64 -O linux -T kernel -C none -a 0x02080000 \ + -d /boot/vmlinuz-$(uname -r) -i /boot/initrd.img-$(uname -r) \ + -b /boot/dtb/rockchip/rk3399-rock-pi-4b.dtb /boot/boot.fit +fi + +# Write U-Boot script to /boot +cat >/boot/boot.cmd <<"EOF" +setenv start_poe 'gpio set 150; gpio clear 146' +run start_poe +setenv bootcmd_dhcp ' +mw.b ${scriptaddr} 0 0x8000 +mmc dev 0 0 +mmc read ${scriptaddr} 0x1fc0 0x40 +env import -b ${scriptaddr} 0x8000 +mw.b ${scriptaddr} 0 0x8000 +if dhcp ${scriptaddr} manifest.txt; then + setenv OldSha ${Sha} + setenv Sha + env import -t ${scriptaddr} 0x8000 ManifestVersion + echo "Manifest version $ManifestVersion"; + if test "$ManifestVersion" = "1"; then + run manifest1 + elif test "$ManifestVersion" = "2"; then + run manifest2 + else + run manifestX + fi +fi' +setenv manifestX 'echo "***** ERROR: Unknown manifest version! *****";' +setenv manifest1 ' +env import -t ${scriptaddr} 0x8000 +if test "$Sha" != "$OldSha"; then + setenv serverip ${TftpServer} + setenv loadaddr 0x00200000 + mmc dev 0 0; + setenv file $TplSplImg; offset=0x40; size=0x1f80; run tftpget1; setenv TplSplImg + setenv file $UbootItb; offset=0x4000; size=0x2000; run tftpget1; setenv UbootItb + setenv file $TrustImg; offset=0x6000; size=0x2000; run tftpget1; setenv TrustImg + setenv file $RootfsImg; offset=0x8000; size=0; run tftpget1; setenv RootfsImg + setenv file $UbootEnv; offset=0x1fc0; size=0x40; run tftpget1; setenv UbootEnv + mw.b ${scriptaddr} 0 0x8000 + env export -b ${scriptaddr} 0x8000 + mmc write ${scriptaddr} 0x1fc0 0x40 +else + echo "Already have ${Sha}. Booting..." +fi' +setenv manifest2 ' +env import -t ${scriptaddr} 0x8000 +if test "$DFUethaddr" = "$ethaddr" || test "$DFUethaddr" = ""; then + if test "$Sha" != "$OldSha"; then + setenv serverip ${TftpServer} + setenv loadaddr 0x00200000 + mmc dev 0 0; + setenv file $TplSplImg; offset=0x40; size=0x1f80; run tftpget1; setenv TplSplImg + setenv file $UbootItb; offset=0x4000; size=0x2000; run tftpget1; setenv UbootItb + setenv file $TrustImg; offset=0x6000; size=0x2000; run tftpget1; setenv TrustImg + setenv file $RootfsImg; offset=0x8000; size=0; run tftpget1; setenv RootfsImg + setenv file $UbootEnv; offset=0x1fc0; size=0x40; run tftpget1; setenv UbootEnv + mw.b ${scriptaddr} 0 0x8000 + env export -b ${scriptaddr} 0x8000 + mmc write ${scriptaddr} 0x1fc0 0x40 + else + echo "Already have ${Sha}. Booting..." + fi +else + echo "Update ${Sha} is not for me. Booting..." +fi' +setenv tftpget1 ' +if test "$file" != ""; then + mw.b ${loadaddr} 0 0x400000 + tftp ${file} + if test $? = 0; then + setenv isGz 0 && setexpr isGz sub .*\\.gz\$ 1 ${file} + if test $isGz = 1; then + if test ${file} = ${UbootEnv}; then + echo "** gzipped env unsupported **" + else + setexpr boffset ${offset} * 0x200 + gzwrite mmc 0 ${loadaddr} 0x${filesize} 100000 ${boffset} && echo Updated: ${file} + fi + elif test ${file} = ${UbootEnv}; then + env import -b ${loadaddr} && echo Updated: ${file} + else + if test $size = 0; then + setexpr x $filesize - 1 + setexpr x $x / 0x1000 + setexpr x $x + 1 + setexpr x $x * 0x1000 + setexpr x $x / 0x200 + size=0x${x} + fi + mmc write ${loadaddr} ${offset} ${size} && echo Updated: ${file} + fi + fi + if test $? != 0; then + echo ** UPDATE FAILED: ${file} ** + fi +fi' +if mmc dev 1 0; then; else + run bootcmd_dhcp; +fi +if test -e mmc ${devnum}:${distro_bootpart} /boot/rootfs.gz; then + setenv loadaddr 0x00200000 + mw.b ${loadaddr} 0 0x400000 + load mmc ${devnum}:${distro_bootpart} ${loadaddr} /boot/rootfs.gz + gzwrite mmc ${devnum} ${loadaddr} 0x${filesize} 100000 0x1000000 +fi +load mmc ${devnum}:${distro_bootpart} 0x06080000 /boot/boot.fit +setenv bootargs "earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 loglevel=7 sdhci.debug_quirks=0x20000000 root=LABEL=ROOT" +bootm 0x06080000 +EOF +mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr + +# Write control script for PoE hat +cat >/usr/local/bin/poe <<"EOF" +#!/bin/bash + +if [ "$1" == "--start" ]; then + echo 146 > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio146/direction + echo 0 > /sys/class/gpio/gpio146/value + echo 150 > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio150/direction + echo 1 > /sys/class/gpio/gpio150/value + exit 0 +fi + +if [ "$1" == "--stop" ]; then + echo 0 > /sys/class/gpio/gpio146/value + echo 146 > /sys/class/gpio/unexport + echo 0 > /sys/class/gpio/gpio150/value + echo 150 > /sys/class/gpio/unexport + exit 0 +fi + +if [ ! -e /sys/class/gpio/gpio146/value ] || [ ! -e /sys/class/gpio/gpio150/value ]; then + echo "error: PoE service not initialized" + exit 1 +fi + +if [ "$1" == "0" ] || [ "$1" == "off" ] || [ "$1" == "OFF" ]; then + echo 0 > /sys/class/gpio/gpio150/value + exit 0 +fi + +if [ "$1" == "1" ] || [ "$1" == "on" ] || [ "$1" == "ON" ]; then + echo 1 > /sys/class/gpio/gpio150/value + exit 0 +fi + +echo "usage: poe <0|1>" +exit 1 +EOF +chmod a+x /usr/local/bin/poe + +# Write service to start PoE control script +cat >/etc/systemd/system/poe.service <<EOF +[Unit] +Description=PoE service +ConditionPathExists=/usr/local/bin/poe + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/poe --start +ExecStop=/usr/local/bin/poe --stop +RemainAfterExit=true +StandardOutput=journal + +[Install] +WantedBy=multi-user.target +EOF + +# Write control script for status LEDs +cat >/usr/local/bin/led <<"EOF" +#!/bin/bash + +if [ "$1" == "--start" ]; then + echo 125 > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio125/direction + chmod 666 /sys/class/gpio/gpio125/value + echo 0 > /sys/class/gpio/gpio125/value + exit 0 +fi + +if [ "$1" == "--stop" ]; then + echo 0 > /sys/class/gpio/gpio125/value + echo 125 > /sys/class/gpio/unexport + exit 0 +fi + +if [ ! -e /sys/class/gpio/gpio125/value ]; then + echo "error: led service not initialized" + exit 1 +fi + +if [ "$1" == "0" ] || [ "$1" == "off" ] || [ "$1" == "OFF" ]; then + echo 0 > /sys/class/gpio/gpio125/value + exit 0 +fi + +if [ "$1" == "1" ] || [ "$1" == "on" ] || [ "$1" == "ON" ]; then + echo 1 > /sys/class/gpio/gpio125/value + exit 0 +fi + +echo "usage: led <0|1>" +exit 1 +EOF +chmod a+x /usr/local/bin/led + +# Write service to start LED control script +cat >/etc/systemd/system/led.service <<EOF +[Unit] +Description=led service +ConditionPathExists=/usr/local/bin/led + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/led --start +ExecStop=/usr/local/bin/led --stop +RemainAfterExit=true +StandardOutput=journal + +[Install] +WantedBy=multi-user.target +EOF + +# Write control script for one-time SD-Card->eMMC duplication +cat >/usr/local/bin/sd-dupe <<"EOF" +#!/bin/bash +led 0 + +src_dev=mmcblk0 +dest_dev=mmcblk1 +part_num=p5 + +if [ -e /dev/mmcblk0p5 ] && [ -e /dev/mmcblk1p5 ]; then + led 1 + + sgdisk -Z -a1 /dev/${dest_dev} + sgdisk -a1 -n:1:64:8127 -t:1:8301 -c:1:loader1 /dev/${dest_dev} + sgdisk -a1 -n:2:8128:8191 -t:2:8301 -c:2:env /dev/${dest_dev} + sgdisk -a1 -n:3:16384:24575 -t:3:8301 -c:3:loader2 /dev/${dest_dev} + sgdisk -a1 -n:4:24576:32767 -t:4:8301 -c:4:trust /dev/${dest_dev} + sgdisk -a1 -n:5:32768:- -A:5:set:2 -t:5:8305 -c:5:rootfs /dev/${dest_dev} + + src_block_count=$(tune2fs -l /dev/${src_dev}${part_num} | grep "Block count:" | sed 's/.*: *//') + src_block_size=$(tune2fs -l /dev/${src_dev}${part_num} | grep "Block size:" | sed 's/.*: *//') + src_fs_size=$(( src_block_count*src_block_size )) + src_fs_size_m=$(( src_fs_size / 1024 / 1024 + 1 )) + + dd if=/dev/${src_dev}p1 of=/dev/${dest_dev}p1 conv=sync,noerror status=progress + dd if=/dev/${src_dev}p2 of=/dev/${dest_dev}p2 conv=sync,noerror status=progress + dd if=/dev/${src_dev}p3 of=/dev/${dest_dev}p3 conv=sync,noerror status=progress + dd if=/dev/${src_dev}p4 of=/dev/${dest_dev}p4 conv=sync,noerror status=progress + + echo "Writing ${src_fs_size_m} MB: /dev/${src_dev} -> /dev/${dest_dev}..." + dd if=/dev/${src_dev}${part_num} of=/dev/${dest_dev}${part_num} bs=1M conv=sync,noerror status=progress + + echo "Expanding /dev/${dest_dev}${part_num} filesystem..." + e2fsck -fy /dev/${dest_dev}${part_num} + resize2fs /dev/${dest_dev}${part_num} + tune2fs -O has_journal /dev/${dest_dev}${part_num} + e2fsck -fy /dev/${dest_dev}${part_num} + sync /dev/${dest_dev} + + echo "Cleaning up..." + mount /dev/${dest_dev}${part_num} /media + chroot /media /usr/local/bin/install-cleanup + + if [ $? == 0 ]; then + echo "Successfully copied Rock Pi image!" + while true; do + led 1; sleep 0.5 + led 0; sleep 0.5 + done + else + echo "Error while copying Rock Pi image" + while true; do + led 1; sleep 0.1 + led 0; sleep 0.1 + done + fi +else + echo "Expanding /dev/${dest_dev}${part_num} filesystem..." + e2fsck -fy /dev/${dest_dev}${part_num} + resize2fs /dev/${dest_dev}${part_num} + tune2fs -O has_journal /dev/${dest_dev}${part_num} + e2fsck -fy /dev/${dest_dev}${part_num} + sync /dev/${dest_dev} + + echo "Cleaning up..." + /usr/local/bin/install-cleanup +fi +EOF +chmod a+x /usr/local/bin/sd-dupe + +# Write one-shot service for SDCard->eMMC duplication +cat >/etc/systemd/system/sd-dupe.service <<EOF +[Unit] +Description=Duplicate SD card rootfs to eMMC on Rock Pi +ConditionPathExists=/usr/local/bin/sd-dupe +After=led.service + +[Service] +Type=simple +ExecStart=/usr/local/bin/sd-dupe +TimeoutSec=0 +StandardOutput=tty + +[Install] +WantedBy=multi-user.target +EOF + +# Write cleanup script for eMMC (after duplication) +cat >/usr/local/bin/install-cleanup <<"EOF" +#!/bin/bash +MAC=$(ip link | grep eth0 -A1 | grep ether | sed 's/.*\(..:..:..:..:..:..\) .*/\1/' | tr -d :) +sed -i "s,rockpi,rockpi-${MAC}," /etc/hosts +sudo hostnamectl set-hostname "rockpi-${MAC}" + +rm -f /etc/machine-id +rm -f /var/lib/dbus/machine-id +dbus-uuidgen --ensure +systemd-machine-id-setup + +systemctl disable sd-dupe +rm -f /etc/systemd/system/sd-dupe.service +rm -f /usr/local/bin/sd-dupe +rm -f /usr/local/bin/install-cleanup +EOF +chmod a+x /usr/local/bin/install-cleanup + +systemctl enable poe +systemctl enable led +systemctl enable sd-dupe + +setup_dynamic_networking "en*" "" + +update_apt_sources bullseye + +setup_cuttlefish_user + +get_installed_packages >/root/originally-installed + +apt-get install -y libc6-dev:amd64 + +setup_and_build_cuttlefish +setup_and_build_iptables + +get_installed_packages >/root/installed + +remove_installed_packages /root/originally-installed /root/installed + +install_and_cleanup_cuttlefish +install_and_cleanup_iptables + +create_systemd_getty_symlinks ttyS0 hvc1 + +apt-get purge -y vim-tiny +bullseye_cleanup diff --git a/net/test/rootfs/bullseye.list b/net/test/rootfs/bullseye.list index b749472..e908a11 100644 --- a/net/test/rootfs/bullseye.list +++ b/net/test/rootfs/bullseye.list @@ -3,15 +3,19 @@ apt-utils bash-completion bsdmainutils ca-certificates +e2fsprogs file gpgv ifupdown +initramfs-tools insserv iputils-ping iptables +isc-dhcp-client less libnetfilter-conntrack3 libnfnetlink0 +lz4 mime-support netbase netcat-openbsd @@ -21,14 +25,12 @@ openssl pciutils procps psmisc -python +python2 python3-scapy strace systemd-sysv tcpdump traceroute udev -udhcpc -usbutils vim-tiny wget diff --git a/net/test/rootfs/bullseye.sh b/net/test/rootfs/bullseye.sh index d198aac..d959fca 100755 --- a/net/test/rootfs/bullseye.sh +++ b/net/test/rootfs/bullseye.sh @@ -16,115 +16,25 @@ # set -e +set -u SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) -. $SCRIPT_DIR/common.sh +. $SCRIPT_DIR/bullseye-common.sh -chroot_sanity_check +setup_static_networking -cd /root +update_apt_sources bullseye -# Add the needed debian sources -cat >/etc/apt/sources.list <<EOF -deb http://ftp.debian.org/debian bullseye main -deb-src http://ftp.debian.org/debian bullseye main -EOF +# Disable the root password +passwd -d root -# Disable the automatic installation of recommended packages -cat >/etc/apt/apt.conf.d/90recommends <<EOF -APT::Install-Recommends "0"; -EOF +get_installed_packages >/root/originally-installed +setup_and_build_iptables +get_installed_packages >/root/installed +remove_installed_packages /root/originally-installed /root/installed +install_and_cleanup_iptables -# Update for the above changes -apt-get update +create_systemd_getty_symlinks ttyS0 -# Note what we have installed; we will go back to this -LANG=C dpkg --get-selections | sort >originally-installed - -# Install everything needed from bullseye to build iptables -apt-get install -y \ - build-essential \ - autoconf \ - automake \ - bison \ - debhelper \ - devscripts \ - fakeroot \ - flex \ - libmnl-dev \ - libnetfilter-conntrack-dev \ - libnfnetlink-dev \ - libnftnl-dev \ - libtool - -# We are done with apt; reclaim the disk space -apt-get clean - -# Construct the iptables source package to build -iptables=iptables-1.8.4 -mkdir -p /usr/src/$iptables - -cd /usr/src/$iptables -# Download a specific revision of iptables from AOSP -wget -qO - \ - https://android.googlesource.com/platform/external/iptables/+archive/master.tar.gz | \ - tar -zxf - -# Download a compatible 'debian' overlay from Debian salsa -# We don't want all of the sources, just the Debian modifications -# NOTE: This will only work if Android always uses a version of iptables that exists -# for Debian as well. -debian_iptables=1.8.4-3 -debian_iptables_dir=pkg-iptables-debian-$debian_iptables -wget -qO - \ - https://salsa.debian.org/pkg-netfilter-team/pkg-iptables/-/archive/debian/$debian_iptables/$debian_iptables_dir.tar.gz | \ - tar --strip-components 1 -zxf - \ - $debian_iptables_dir/debian -cd - - -cd /usr/src -# Generate a source package to leave in the filesystem. This is done for license -# compliance and build reproducibility. -tar --exclude=debian -cf - $iptables | \ - xz -9 >`echo $iptables | tr -s '-' '_'`.orig.tar.xz -cd - - -cd /usr/src/$iptables -# Build debian packages from the integrated iptables source -dpkg-buildpackage -F -us -uc -cd - - -# Record the list of packages we have installed now -LANG=C dpkg --get-selections | sort >installed - -# Compute the difference, and remove anything installed between the snapshots -dpkg -P `comm -3 originally-installed installed | sed -e 's,install,,' -e 's,\t,,' | xargs` - -cd /usr/src -# Find any packages generated, resolve to the debian package name, then -# exclude any compat, header or symbol packages -packages=`find -maxdepth 1 -name '*.deb' | colrm 1 2 | cut -d'_' -f1 | - grep -ve '-compat$\|-dbg$\|-dbgsym$\|-dev$' | xargs` -# Install the patched iptables packages, and 'hold' then so -# "apt-get dist-upgrade" doesn't replace them -dpkg -i ` -for package in $packages; do - echo ${package}_*.deb -done | xargs` -for package in $packages; do - echo "$package hold" | dpkg --set-selections -done -# Tidy up the mess we left behind, leaving just the source tarballs -rm -rf $iptables *.buildinfo *.changes *.deb *.dsc -cd - - -# Ensure a getty is spawned on ttyS0, if booting the image manually -ln -s /lib/systemd/system/serial-getty\@.service \ - /etc/systemd/system/getty.target.wants/serial-getty\@ttyS0.service - -# systemd needs some directories to be created -mkdir -p /var/lib/systemd/coredump /var/lib/systemd/rfkill \ - /var/lib/systemd/timesync - -# Finalize and tidy up the created image -chroot_cleanup +bullseye_cleanup diff --git a/net/test/rootfs/common.sh b/net/test/rootfs/common.sh index 172d9b6..c86c39c 100644 --- a/net/test/rootfs/common.sh +++ b/net/test/rootfs/common.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (C) 2018 The Android Open Source Project +# Copyright (C) 2021 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,43 +15,140 @@ # limitations under the License. # -chroot_sanity_check() { - if [ ! -f /var/log/bootstrap.log ]; then - echo "Do not run this script directly!" - echo "This is supposed to be run from inside a debootstrap chroot!" - echo "Aborting." - exit 1 - fi +trap "echo 3 >${exitcode}" ERR + +# $1 - Suite name for apt sources +update_apt_sources() { + # Add the needed debian sources + cat >/etc/apt/sources.list <<EOF +deb http://ftp.debian.org/debian bullseye main +deb-src http://ftp.debian.org/debian bullseye main +EOF + + # Disable the automatic installation of recommended packages + cat >/etc/apt/apt.conf.d/90recommends <<EOF +APT::Install-Recommends "0"; +EOF + + # On the ARM64, allow packages from AMD64 to be installed + dpkg --add-architecture amd64 + + # Update for the above changes + apt-get update +} + +# $1 - Output file for currently installed packages +get_installed_packages() { + LANG=C dpkg --get-selections | sort +} + +# $1 - File containing package selections to restore to +# $2 - File containing currently installed packages list +remove_installed_packages() { + apt-get purge --allow-remove-essential -y \ + $(comm -3 "$1" "$2" | sed -e 's,install,,' -e 's,\t,,' | xargs) + rm -f "$1" "$2" +} + +setup_static_networking() { + # Temporarily bring up static QEMU SLIRP networking (no DHCP) + ip link set dev eth0 up + ip addr add 10.0.2.15/24 broadcast 10.0.2.255 dev eth0 + ip route add default via 10.0.2.2 dev eth0 + + # Permanently update the resolv.conf with the Google DNS servers + echo "nameserver 8.8.8.8" >/etc/resolv.conf + echo "nameserver 8.8.4.4" >>/etc/resolv.conf } -chroot_cleanup() { - # Read-only root breaks booting via init - cat >/etc/fstab << EOF -tmpfs /tmp tmpfs defaults 0 0 -tmpfs /var/log tmpfs defaults 0 0 -tmpfs /var/tmp tmpfs defaults 0 0 +# $1 - Network interface for bridge (or NetworkManager DHCP) +# $2 - Bridge name. If set to the empty string, NetworkManager is used +setup_dynamic_networking() { + # So isc-dhcp-client can work with a read-only rootfs.. + cat >>/etc/fstab <<EOF +tmpfs /var/lib/dhcp tmpfs defaults 0 0 EOF - # systemd will attempt to re-create this symlink if it does not exist, - # which fails if it is booting from a read-only root filesystem (which - # is normally the case). The syslink must be relative, not absolute, - # and it must point to /proc/self/mounts, not /proc/mounts. - ln -sf ../proc/self/mounts /etc/mtab + # Bring up networking one time with dhclient + mount /var/lib/dhcp + dhclient eth0 + echo "nameserver 8.8.8.8" >/run/resolvconf/resolv.conf + echo "nameserver 8.8.4.4" >>/run/resolvconf/resolv.conf - # Remove contaminants coming from the debootstrap process - echo vm >/etc/hostname - echo "nameserver 127.0.0.1" >/etc/resolv.conf + # Set up automatic DHCP for *future* boots + if [ -z "$2" ]; then + cat >/etc/systemd/network/dhcp.network <<EOF +[Match] +Name=$1 - # Put the helper net_test.sh script into place - mv /root/net_test.sh /sbin/net_test.sh +[Network] +DHCP=yes +EOF + # Mask the NetworkManager-wait-online service to prevent hangs + systemctl mask NetworkManager-wait-online.service + else + cat >/etc/network/interfaces.d/$2.conf <<EOF +auto $2 +iface $2 inet dhcp + bridge_ports $1 + bridge_stp off + bridge_fd 0 +EOF + fi +} + +setup_cuttlefish_user() { + # Add a default user and put them in the right group + addgroup --system cvdnetwork + useradd -m -G cvdnetwork,kvm,render,sudo,video \ + -d /home/vsoc-01 --shell /bin/bash vsoc-01 + echo -e "cuttlefish\ncuttlefish" | passwd vsoc-01 +} + +# $* - One or more device names for getty spawns +create_systemd_getty_symlinks() { + for device in $*; do + ln -s /lib/systemd/system/serial-getty\@.service \ + /etc/systemd/system/getty.target.wants/serial-getty\@"${device}".service + done +} - # Make sure the /host mountpoint exists for net_test.sh - mkdir /host +# $1 - Additional default command line +setup_grub() { + if [ -n "${embed_kernel_initrd_dtb}" ]; then + # For testing the image with a virtual device + apt-get install -y grub2-common + cat >/etc/default/grub <<EOF +GRUB_DEFAULT=0 +GRUB_TIMEOUT=5 +GRUB_DISTRIBUTOR=Debian +GRUB_CMDLINE_LINUX_DEFAULT="quiet" +GRUB_CMDLINE_LINUX="\\\$cmdline $1" +EOF + mkdir /boot/grub + update-grub + fi +} + +cleanup() { + # Prevents systemd boot issues with read-only rootfs + mkdir -p /var/lib/systemd/{coredump,linger,rfkill,timesync} + chown systemd-timesync:systemd-timesync /var/lib/systemd/timesync + + # If embedding isn't enabled, remove the embedded modules and initrd and + # uninstall the tools to regenerate the initrd, as they're unlikely to + # ever be used + if [ -z "${embed_kernel_initrd_dtb}" ]; then + apt-get purge -y initramfs-tools initramfs-tools-core klibc-utils kmod + rm -f "/boot/initrd.img-$(uname -r)" + rm -rf "/lib/modules/$(uname -r)" + fi - # Disable the root password - passwd -d root + # Miscellaneous cleanup + rm -rf /var/lib/apt/lists/* || true + rm -f /root/* || true + apt-get clean - # Clean up any junk created by the imaging process - rm -rf /var/lib/apt/lists/* /var/log/bootstrap.log /root/* /tmp/* - find /var/log -type f -exec rm -f '{}' ';' + echo 0 >"${exitcode}" + sync && poweroff -f } diff --git a/net/test/rootfs/stage1.sh b/net/test/rootfs/stage1.sh new file mode 100755 index 0000000..ccf54f1 --- /dev/null +++ b/net/test/rootfs/stage1.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# Copyright (C) 2021 The Android Open Source Project +# +# 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. +# + +set -e +set -u + +trap "echo 1 >${exitcode}" ERR + +# So we have a rw location to extract kmod +mount -t tmpfs tmpfs /tmp + +# Extract kmod utility to /tmp +dpkg-deb -x /var/cache/apt/archives/kmod*.deb /tmp +ln -s /tmp/bin/kmod /tmp/insmod + +# Load just enough to get the rootfs from virtio_blk +module_dir=/lib/modules/$(uname -r)/kernel +# virtio_pci_modern_dev was split out in 5.12 +/tmp/insmod ${module_dir}/drivers/virtio/virtio_pci_modern_dev.ko || true +/tmp/insmod ${module_dir}/drivers/virtio/virtio_pci.ko +/tmp/insmod ${module_dir}/drivers/block/virtio_blk.ko +/tmp/insmod ${module_dir}/drivers/char/hw_random/virtio-rng.ko + +# Mount devtmpfs so we can see /dev/vda +mount -t devtmpfs devtmpfs /dev + +# Mount /dev/vda over the top of /root +mount /dev/vda /root + +# Switch to the new root and start stage 2 +mount -n --move /dev /root/dev +mount -n --move /tmp /root/tmp +mount -n -t proc none /root/proc +mount -n -t sysfs none /root/sys +mount -n -t tmpfs tmpfs /root/run +pivot_root /root /root/host +exec chroot / /root/stage2.sh ${exitcode} </dev/console >/dev/console 2>&1 diff --git a/net/test/rootfs/stage2.sh b/net/test/rootfs/stage2.sh new file mode 100755 index 0000000..84fc8ea --- /dev/null +++ b/net/test/rootfs/stage2.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# +# Copyright (C) 2021 The Android Open Source Project +# +# 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. +# + +set -e +set -u + +trap "echo 2 >${exitcode}" ERR + +# Remove the old ramdisk root; we don't need it any more +umount -l /host + +# Complete the debootstrap process +/debootstrap/debootstrap --second-stage + +# We are done with apt; clean up apt and debootstrap intermediaries +apt-get clean +rm -rf /debootstrap /var/lib/apt/lists/* + +# Read-only root breaks booting via init +cat >/etc/fstab << EOF +LABEL=ROOT / ext4 defaults,discard 0 1 +tmpfs /tmp tmpfs defaults 0 0 +tmpfs /var/log tmpfs defaults 0 0 +tmpfs /var/tmp tmpfs defaults 0 0 +EOF + +# systemd will attempt to re-create this symlink if it does not exist, +# which fails if it is booting from a read-only root filesystem (which +# is normally the case). The syslink must be relative, not absolute, +# and it must point to /proc/self/mounts, not /proc/mounts. +ln -sf ../proc/self/mounts /etc/mtab + +# Set up the virtual device image hostname +echo "127.0.1.1 debian" >>/etc/hosts +echo debian >/etc/hostname + +# Support chroot jailing with minijail +cat >/etc/sysctl.d/80-nsjail.conf <<EOF +kernel.unprivileged_userns_clone=1 +EOF +mkdir -p /var/empty + +# Clean up any other junk created by the imaging process +rm -rf /root/stage1.sh /root/stage2.sh /root/lib /tmp/* +find /var/log -type f -exec rm -f '{}' ';' +find /var/tmp -type f -exec rm -f '{}' ';' + +# Create an empty initramfs to be combined with modules later +sed -i 's,^COMPRESS=gzip,COMPRESS=lz4,' /etc/initramfs-tools/initramfs.conf +depmod -a $(uname -r) +update-initramfs -c -k $(uname -r) +dd if=/boot/initrd.img-$(uname -r) of=/dev/vdb conv=fsync + +echo 0 >"${exitcode}" +sync && poweroff -f diff --git a/net/test/run_net_test.sh b/net/test/run_net_test.sh index 6f32f81..9dca4fe 100755 --- a/net/test/run_net_test.sh +++ b/net/test/run_net_test.sh @@ -108,7 +108,7 @@ nowrite=1 nobuild=0 norun=0 -if [[ -z "${DEFCONFIG}" ]]; then +if [[ -z "${DEFCONFIG:-}" ]]; then case "${ARCH}" in um) export DEFCONFIG=defconfig @@ -245,7 +245,7 @@ if (( $NUMTAPINTERFACES > 0 )); then done fi -if [ -n "$KERNEL_BINARY" ]; then +if [[ -n "${KERNEL_BINARY:-}" ]]; then nobuild=1 else # Set default KERNEL_BINARY location if it was not provided. @@ -265,7 +265,7 @@ if ((nobuild == 0)); then # "sometimes" (?) results in a 32-bit kernel. make_flags="$make_flags ARCH=$ARCH SUBARCH=${SUBARCH:-x86_64} CROSS_COMPILE= " fi - if [ -n "$CC" ]; then + if [[ -n "${CC:-}" ]]; then # The CC flag is *not* inherited from the environment, so it must be # passed in on the command line. make_flags="$make_flags CC=$CC" @@ -280,12 +280,15 @@ if ((nobuild == 0)); then # Disable the kernel config options listed in $DISABLE_OPTIONS. $CONFIG_SCRIPT --file $CONFIG_FILE ${DISABLE_OPTIONS// / -d } + echo "Running: $MAKE $make_flags olddefconfig" $MAKE $make_flags olddefconfig # Compile the kernel. if [ "$ARCH" == "um" ]; then + echo "Running: $MAKE -j$J $make_flags linux" $MAKE -j$J $make_flags linux else + echo "Running: $MAKE -j$J $make_flags" $MAKE -j$J $make_flags fi fi @@ -327,7 +330,7 @@ if [ "$ARCH" == "um" ]; then # We'd use UML's /proc/exitcode feature to communicate errors on test failure, # if not for UML having a tendency to crash during shutdown, # so instead use an extra serial line we'll redirect to an open fd... - cmdline="$cmdline net_test_exitcode=/dev/ttyS3" + cmdline="$cmdline exitcode=/dev/ttyS3" # Map the --readonly flag to UML block device names if ((nowrite == 0)); then @@ -344,6 +347,11 @@ if [ "$ARCH" == "um" ]; then $blockdevice=$ROOTFS $netconfig $consolemode ssl3=null,fd:3 $cmdline \ || exitcode=$? + # Return to beginning of line (via carriage return) after the above newline moved us down. + echo -en '\r' + # re-enable: 'postprocess output' and 'translate newline to carriage return-newline' + stty opost onlcr || : + if [[ "${exitcode}" == 134 && -s "${SSL3}" && "$(tr -d '\r' < "${SSL3}")" == 0 ]]; then # Sometimes the tests all pass, but UML crashes during the shutdown process itself. # As such we can't actually rely on the /proc/exitcode returned value. @@ -422,7 +430,7 @@ else # The assignment of 'ttyS1' here is magical; we know ttyS0 was used up # by '-serial mon:stdio', and so this second serial port will be 'ttyS1' - cmdline="$cmdline net_test_exitcode=/dev/ttyS1" + cmdline="$cmdline exitcode=/dev/ttyS1" elif [ "$ARCH" == "arm64" ]; then # This uses a software model CPU, based on cortex-a57 qemu="qemu-system-aarch64 -machine virt -cpu cortex-a57" @@ -434,7 +442,7 @@ else # The kernel will print messages via a virtual ARM serial port (ttyAMA0), # but for command line consistency with x86, we put the exitcode serial # port on the PCI bus, and it will be the only one. - cmdline="$cmdline net_test_exitcode=/dev/ttyS0" + cmdline="$cmdline exitcode=/dev/ttyS0" fi $qemu >&2 -name net_test -m 512 \ diff --git a/net/test/tcp_fastopen_test.py b/net/test/tcp_fastopen_test.py index eadae79..9c777c6 100755 --- a/net/test/tcp_fastopen_test.py +++ b/net/test/tcp_fastopen_test.py @@ -22,12 +22,14 @@ from scapy import all as scapy import multinetwork_base import net_test +import os import packets import tcp_metrics TCPOPT_FASTOPEN = 34 TCP_FASTOPEN_CONNECT = 30 +BH_TIMEOUT_SYSCTL = "/proc/sys/net/ipv4/tcp_fastopen_blackhole_timeout_sec" class TcpFastOpenTest(multinetwork_base.MultiNetworkBaseTest): @@ -63,12 +65,24 @@ class TcpFastOpenTest(multinetwork_base.MultiNetworkBaseTest): with self.assertRaisesErrno(ENOENT): self.tcp_metrics.GetMetrics(saddr, daddr) + def clearBlackhole(self): + if net_test.LINUX_VERSION < (4, 14, 0): + return + # Prior to 4.15 this sysctl is not namespace aware. + if net_test.LINUX_VERSION < (4, 15, 0) and not os.path.exists(BH_TIMEOUT_SYSCTL): + return + timeout = self.GetSysctl(BH_TIMEOUT_SYSCTL) + + # Write to timeout to clear any pre-existing blackhole condition + self.SetSysctl(BH_TIMEOUT_SYSCTL, timeout) + def CheckConnectOption(self, version): ip_layer = {4: scapy.IP, 6: scapy.IPv6}[version] netid = self.RandomNetid() s = self.TFOClientSocket(version, netid) self.clearTcpMetrics(version, netid) + self.clearBlackhole() # Connect the first time. remoteaddr = self.GetRemoteAddress(version) |