summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-02-17 03:31:58 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-02-17 03:31:58 +0000
commitddf5326273325822c74424b50b79d8f741cd9bf8 (patch)
treeeb5702cf7807f0469279ed974d3849009ecf3cf9
parentdbe77443e4e0baf7207dee699ac596d04b3f89de (diff)
parentfa13e575d13f51ec9bf4ea8ec241f3d4b1c24fa5 (diff)
downloadtests-ddf5326273325822c74424b50b79d8f741cd9bf8.tar.gz
Snap for 8192848 from fa13e575d13f51ec9bf4ea8ec241f3d4b1c24fa5 to tm-frc-os-statsd-release
Change-Id: Ie8fc84543e525b4433a931b0914b56db3b44dc61
-rw-r--r--Android.bp27
-rw-r--r--devicetree/early_mount/Android.bp6
-rw-r--r--net/test/Android.bp9
-rw-r--r--net/test/OWNERS3
-rwxr-xr-xnet/test/all_tests.py6
-rwxr-xr-xnet/test/build_all_rootfs.sh26
-rwxr-xr-xnet/test/build_rootfs.sh330
-rwxr-xr-xnet/test/net_test.sh2
-rwxr-xr-xnet/test/policy_crash_test.py2
-rw-r--r--net/test/rootfs/OWNERS3
-rw-r--r--net/test/rootfs/bullseye-common.sh130
-rw-r--r--net/test/rootfs/bullseye-cuttlefish.list13
-rwxr-xr-xnet/test/rootfs/bullseye-cuttlefish.sh50
-rw-r--r--net/test/rootfs/bullseye-rockpi.list7
-rwxr-xr-xnet/test/rootfs/bullseye-rockpi.sh390
-rw-r--r--net/test/rootfs/bullseye.list8
-rwxr-xr-xnet/test/rootfs/bullseye.sh116
-rw-r--r--net/test/rootfs/common.sh159
-rwxr-xr-xnet/test/rootfs/stage1.sh51
-rwxr-xr-xnet/test/rootfs/stage2.sh69
-rwxr-xr-xnet/test/run_net_test.sh20
-rwxr-xr-xnet/test/tcp_fastopen_test.py14
22 files changed, 1168 insertions, 273 deletions
diff --git a/Android.bp b/Android.bp
index 5c20661..e6b4444 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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)